mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 16:00:58 +00:00
refactor(ai): improve error handling and stop reason types
- Add 'aborted' as a distinct stop reason separate from 'error'
- Change AssistantMessage.error to errorMessage for clarity
- Update error event to include reason field ('error' | 'aborted')
- Map provider-specific safety/refusal reasons to 'error' stop reason
- Reorganize utility functions into utils/ directory
- Rename agent.ts to agent-loop.ts for better clarity
- Fix error handling in all providers to properly distinguish abort from error
This commit is contained in:
parent
293a6e878d
commit
2296dc4052
22 changed files with 703 additions and 139 deletions
|
|
@ -1,11 +1,11 @@
|
|||
import { EventStream } from "../event-stream.js";
|
||||
import { streamSimple } from "../stream.js";
|
||||
import type { AssistantMessage, Context, Message, ToolResultMessage, UserMessage } from "../types.js";
|
||||
import { validateToolArguments } from "../validation.js";
|
||||
import { EventStream } from "../utils/event-stream.js";
|
||||
import { validateToolArguments } from "../utils/validation.js";
|
||||
import type { AgentContext, AgentEvent, AgentTool, AgentToolResult, PromptConfig } from "./types.js";
|
||||
|
||||
// Main prompt function - returns a stream of events
|
||||
export function prompt(
|
||||
export function agentLoop(
|
||||
prompt: UserMessage,
|
||||
context: AgentContext,
|
||||
config: PromptConfig,
|
||||
|
|
@ -46,21 +46,29 @@ export function prompt(
|
|||
firstTurn = false;
|
||||
}
|
||||
// Stream assistant response
|
||||
const assistantMessage = await streamAssistantResponse(currentContext, config, signal, stream, streamFn);
|
||||
newMessages.push(assistantMessage);
|
||||
const message = await streamAssistantResponse(currentContext, config, signal, stream, streamFn);
|
||||
newMessages.push(message);
|
||||
|
||||
if (message.stopReason === "error" || message.stopReason === "aborted") {
|
||||
// Stop the loop on error or abort
|
||||
stream.push({ type: "turn_end", message, toolResults: [] });
|
||||
stream.push({ type: "agent_end", messages: newMessages });
|
||||
stream.end(newMessages);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for tool calls
|
||||
const toolCalls = assistantMessage.content.filter((c) => c.type === "toolCall");
|
||||
const toolCalls = message.content.filter((c) => c.type === "toolCall");
|
||||
hasMoreToolCalls = toolCalls.length > 0;
|
||||
|
||||
const toolResults: ToolResultMessage[] = [];
|
||||
if (hasMoreToolCalls) {
|
||||
// Execute tool calls
|
||||
toolResults.push(...(await executeToolCalls(currentContext.tools, assistantMessage, signal, stream)));
|
||||
toolResults.push(...(await executeToolCalls(currentContext.tools, message, signal, stream)));
|
||||
currentContext.messages.push(...toolResults);
|
||||
newMessages.push(...toolResults);
|
||||
}
|
||||
stream.push({ type: "turn_end", assistantMessage, toolResults: toolResults });
|
||||
stream.push({ type: "turn_end", message, toolResults: toolResults });
|
||||
}
|
||||
stream.push({ type: "agent_end", messages: newMessages });
|
||||
stream.end(newMessages);
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
export { prompt } from "./agent.js";
|
||||
export { agentLoop } from "./agent-loop.js";
|
||||
export * from "./tools/index.js";
|
||||
export type { AgentContext, AgentEvent, AgentTool, PromptConfig } from "./types.js";
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export type AgentEvent =
|
|||
isError: boolean;
|
||||
}
|
||||
// Emitted when a full turn completes
|
||||
| { type: "turn_end"; assistantMessage: AssistantMessage; toolResults: ToolResultMessage[] }
|
||||
| { type: "turn_end"; message: AssistantMessage; toolResults: ToolResultMessage[] }
|
||||
// Emitted when the agent has completed all its turns. All messages from every turn are
|
||||
// contained in messages, which can be appended to the context
|
||||
| { type: "agent_end"; messages: AgentContext["messages"] };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue