fix(agent): always provide getApiKey callback and emit error events
PiAgentCore was created with an empty object when no API key was initially configured. This broke dynamic provider switching because setProvider() updated currentApiKey but PiAgentCore had no getApiKey callback to read it. Always provide the callback so it dynamically reads the current key. Also adds AgentErrorEvent to MulticaEvent and emits it from AsyncAgent.write() catch handlers so errors flow through the subscriber mechanism to IPC listeners. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
dacf8894e9
commit
9fe6b920c4
3 changed files with 29 additions and 11 deletions
|
|
@ -51,11 +51,14 @@ export class AsyncAgent {
|
|||
// Normal text is delivered via message_end event; only handle errors here
|
||||
if (result.error) {
|
||||
this.channel.send({ id: uuidv7(), content: `[error] ${result.error}` });
|
||||
this.agent.emitError(result.error);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
this.channel.send({ id: uuidv7(), content: `[error] ${message}` });
|
||||
// Also emit through subscriber mechanism so IPC listeners receive the error
|
||||
this.agent.emitError(message);
|
||||
})
|
||||
.finally(() => {
|
||||
this.pendingWrites = Math.max(0, this.pendingWrites - 1);
|
||||
|
|
|
|||
|
|
@ -21,10 +21,16 @@ export type CompactionEndEvent = {
|
|||
type: "compaction_end";
|
||||
removed: number;
|
||||
kept: number;
|
||||
tokensRemoved?: number;
|
||||
tokensKept?: number;
|
||||
tokensRemoved?: number | undefined;
|
||||
tokensKept?: number | undefined;
|
||||
reason: "count" | "tokens" | "summary" | "pruning";
|
||||
};
|
||||
|
||||
/** Emitted when an agent encounters an error during execution */
|
||||
export type AgentErrorEvent = {
|
||||
type: "agent_error";
|
||||
message: string;
|
||||
};
|
||||
|
||||
/** Union of all Multica-specific events */
|
||||
export type MulticaEvent = CompactionStartEvent | CompactionEndEvent;
|
||||
export type MulticaEvent = CompactionStartEvent | CompactionEndEvent | AgentErrorEvent;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Agent as PiAgentCore, type AgentEvent, type AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import { v7 as uuidv7 } from "uuid";
|
||||
import type { AgentOptions, AgentRunResult, ReasoningMode } from "./types.js";
|
||||
import type { MulticaEvent } from "./events.js";
|
||||
import type { MulticaEvent, CompactionEndEvent } from "./events.js";
|
||||
import { createAgentOutput } from "./cli/output.js";
|
||||
import { resolveModel, resolveTools, type ResolveToolsOptions } from "./tools.js";
|
||||
import {
|
||||
|
|
@ -159,11 +159,14 @@ export class Agent {
|
|||
: 0;
|
||||
}
|
||||
|
||||
this.agent = new PiAgentCore(
|
||||
this.currentApiKey
|
||||
? { getApiKey: (_provider: string) => this.currentApiKey! }
|
||||
: {},
|
||||
);
|
||||
this.agent = new PiAgentCore({
|
||||
getApiKey: (_provider: string) => {
|
||||
if (!this.currentApiKey) {
|
||||
throw new Error(`No API key configured for provider: ${this.resolvedProvider}`);
|
||||
}
|
||||
return this.currentApiKey;
|
||||
},
|
||||
});
|
||||
|
||||
// Load Agent Profile (if profileId is specified)
|
||||
// Every Agent should have a Profile for memory, tools config, and other settings
|
||||
|
|
@ -352,6 +355,11 @@ export class Agent {
|
|||
}
|
||||
}
|
||||
|
||||
/** Emit an error event through the subscriber mechanism */
|
||||
emitError(message: string): void {
|
||||
this.emitMulticaEvent({ type: "agent_error", message });
|
||||
}
|
||||
|
||||
async run(prompt: string): Promise<AgentRunResult> {
|
||||
await this.ensureInitialized();
|
||||
this.output.state.lastAssistantText = "";
|
||||
|
|
@ -461,14 +469,15 @@ export class Agent {
|
|||
if (result?.kept) {
|
||||
this.agent.replaceMessages(result.kept);
|
||||
}
|
||||
this.emitMulticaEvent({
|
||||
const endEvent: CompactionEndEvent = {
|
||||
type: "compaction_end",
|
||||
removed: result?.removedCount ?? 0,
|
||||
kept: result?.kept.length ?? messages.length,
|
||||
tokensRemoved: result?.tokensRemoved,
|
||||
tokensKept: result?.tokensKept,
|
||||
reason: result?.reason ?? "tokens",
|
||||
});
|
||||
};
|
||||
this.emitMulticaEvent(endEvent);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue