Files
agent-loop/async-agent-lab/shared/types.ts
2026-11-12 15:29:12 +08:00

112 lines
3.3 KiB
TypeScript

// Agent 内核、本地服务和网页共用的类型。只有类型,没有运行时代码。
export type ToolCall = {
id: string;
type: 'function';
function: { name: string; arguments: string };
};
export type Message =
| { role: 'system'; content: string }
| { role: 'user'; content: string }
| { role: 'assistant'; content: string; tool_calls?: ToolCall[] }
| { role: 'tool'; tool_call_id: string; content: string };
export type AssistantMessage = Extract<Message, { role: 'assistant' }>;
export type ToolSpec = {
type: 'function';
function: { name: string; description: string; parameters: Record<string, unknown> };
};
export type Usage = {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
cached_tokens?: number;
reasoning_tokens?: number;
};
// 收件箱里的一条:用户消息、后台命令完成通知、问题答复,三种来源走同一个入口。
export type InboxKind = 'user' | 'job_done' | 'question_reply';
export type InboxItem = {
id: string;
kind: InboxKind;
content: string; // 进入历史时作为 user 消息的正文
ref?: string; // 关联的 job_id 或 question_id
};
export type QuestionMode = 'blocking' | 'async';
export type LevelInfo = {
id: number;
name: string;
title: string;
adds: string;
watch: string;
tools: string[];
defaultTask: string;
source: { file: string; anchor: string }[];
};
// 一次运行的完整记录就是这些事件。网页的实时视图、逐步查看和导出的回放都从它还原。
export type TraceEvent = { seq: number; t: number } & TraceBody;
export type TraceBody =
| {
type: 'run.start';
runId: string;
level: number;
model: string;
baseURL: string;
tools: ToolSpec[];
startedAt: number;
}
| {
type: 'history.append';
index: number;
message: Message;
origin?: { inboxId: string; kind: InboxKind; ref?: string };
}
| { type: 'inbox.push'; item: InboxItem }
| { type: 'inbox.deliver'; ids: string[] }
| { type: 'model.start'; n: number; messageCount: number }
| { type: 'model.delta'; n: number; content?: string; reasoning?: string }
| {
type: 'model.end';
n: number;
message: AssistantMessage;
reasoning: string;
usage: Usage | null;
finishReason: string | null;
ttftMs: number | null;
}
| { type: 'model.error'; n: number; error: string }
| { type: 'tool.start'; callId: string; name: string; args: unknown; n: number }
| { type: 'tool.output'; callId: string; chunk: string }
| { type: 'tool.end'; callId: string; result: string }
| { type: 'job.start'; jobId: string; callId: string; command: string }
| { type: 'job.output'; jobId: string; chunk: string }
| { type: 'job.end'; jobId: string; exitCode: number | null; durationMs: number }
| {
type: 'question.ask';
questionId: string;
callId: string;
mode: QuestionMode;
question: string;
options: string[];
}
| { type: 'question.answer'; questionId: string; answer: string }
| { type: 'workspace.diff'; diff: string }
| { type: 'guard.forged'; n: number; tag: string }
| { type: 'run.stop'; reason: 'stopped' | 'error'; error?: string };
export type RunRecording = {
runId: string;
level: number;
task: string;
startedAt: number;
events: TraceEvent[];
};