fix(agents): initialize ExtensionRunner in embedded mode (#2027)
In pi-coding-agent, ExtensionRunner defaults ctx.model to undefined until extensionRunner.initialize() is called. Moltbot uses the SDK in embedded mode (no interactive UI), so compaction hooks that rely on ctx.model (e.g. compaction-safeguard) would fall back to "Summary unavailable..." and history would be truncated without a real summary.
This commit is contained in:
parent
eda601c46a
commit
902e3f56d1
@ -40,6 +40,7 @@ Status: beta.
|
||||
- **BREAKING:** Gateway auth mode "none" is removed; gateway now requires token/password (Tailscale Serve identity still allowed).
|
||||
|
||||
### Fixes
|
||||
- Agents: initialize ExtensionRunner in embedded mode so compaction hooks produce real summaries instead of "Summary unavailable...". (#2027)
|
||||
- Security: harden SSH tunnel target parsing to prevent option injection/DoS. (#4001) Thanks @YLChen-007.
|
||||
- Security: prevent PATH injection in exec sandbox; harden file serving; pin DNS in URL fetches; verify Twilio webhooks; fix LINE webhook timing-attack edge case; validate Tailscale Serve identity; flag loopback Control UI with auth disabled as critical. (#1616, #1795)
|
||||
- Gateway: prevent crashes on transient network errors, suppress AbortError/unhandled rejections, sanitize error responses, clean session locks on exit, and harden reverse proxy handling for unauthenticated proxied connects. (#2980, #2451, #2483, #1795)
|
||||
|
||||
@ -4,7 +4,12 @@ import os from "node:os";
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import type { AssistantMessage, ImageContent } from "@mariozechner/pi-ai";
|
||||
import { streamSimple } from "@mariozechner/pi-ai";
|
||||
import { createAgentSession, SessionManager, SettingsManager } from "@mariozechner/pi-coding-agent";
|
||||
import {
|
||||
createAgentSession,
|
||||
SessionManager,
|
||||
SettingsManager,
|
||||
type CompactOptions,
|
||||
} from "@mariozechner/pi-coding-agent";
|
||||
|
||||
import { resolveHeartbeatPrompt } from "../../../auto-reply/heartbeat.js";
|
||||
import {
|
||||
@ -492,6 +497,74 @@ export async function runEmbeddedAttempt(
|
||||
// Force a stable streamFn reference so vitest can reliably mock @mariozechner/pi-ai.
|
||||
activeSession.agent.streamFn = streamSimple;
|
||||
|
||||
// IMPORTANT (embedded mode): initialize the pi extension runner.
|
||||
//
|
||||
// In pi-coding-agent, ExtensionRunner defaults `ctx.model` to `undefined` until
|
||||
// `extensionRunner.initialize(...)` is called. Moltbot uses the SDK in embedded
|
||||
// mode (no interactive UI), so without this initialization compaction hooks that
|
||||
// rely on `ctx.model` (e.g. `compaction-safeguard`) will always fall back to
|
||||
// "Summary unavailable..." and history will be truncated without a summary.
|
||||
const extensionRunner = activeSession.extensionRunner;
|
||||
if (extensionRunner) {
|
||||
extensionRunner.initialize(
|
||||
{
|
||||
// Embedded runs don't have a UI; keep UI-dependent actions as safe no-ops.
|
||||
sendMessage: async () => {},
|
||||
sendUserMessage: async () => {},
|
||||
appendEntry: () => {},
|
||||
setSessionName: () => {},
|
||||
getSessionName: () => undefined,
|
||||
setLabel: () => {},
|
||||
getActiveTools: () =>
|
||||
(activeSession.agent.state.tools ?? [])
|
||||
.map((tool) => {
|
||||
if (!tool) return undefined;
|
||||
if (typeof tool === "string") return tool;
|
||||
if (typeof tool === "object" && "name" in tool) {
|
||||
const name = (tool as { name?: unknown }).name;
|
||||
return typeof name === "string" ? name : undefined;
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
.filter((name): name is string => typeof name === "string"),
|
||||
getAllTools: () => [],
|
||||
setActiveTools: () => {},
|
||||
setModel: async (model) => {
|
||||
const key = await activeSession.modelRegistry.getApiKey(model);
|
||||
if (!key) return false;
|
||||
await activeSession.setModel(model);
|
||||
return true;
|
||||
},
|
||||
getThinkingLevel: () => activeSession.thinkingLevel,
|
||||
setThinkingLevel: (level) => {
|
||||
activeSession.setThinkingLevel(level);
|
||||
},
|
||||
},
|
||||
{
|
||||
// Provide live model + context access for extensions.
|
||||
getModel: () => activeSession.agent.state.model,
|
||||
isIdle: () => true,
|
||||
abort: () => {
|
||||
void activeSession.abort();
|
||||
},
|
||||
hasPendingMessages: () => false,
|
||||
shutdown: () => {},
|
||||
getContextUsage: () => activeSession.getContextUsage(),
|
||||
compact: (options?: CompactOptions) => {
|
||||
void (async () => {
|
||||
try {
|
||||
const result = await activeSession.compact(options?.customInstructions);
|
||||
options?.onComplete?.(result);
|
||||
} catch (error) {
|
||||
const err = error instanceof Error ? error : new Error(String(error));
|
||||
options?.onError?.(err);
|
||||
}
|
||||
})();
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
applyExtraParamsToAgent(
|
||||
activeSession.agent,
|
||||
params.config,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user