/** * A1 阶段的占位引擎:把用户输入回显成一条助手消息,用来打通 HTTP / SSE 链路。 * * 它刻意不做任何「理解」,也不调用 Provider——避免把假能力写进真实链路。 * A3.1 定义正式 AgentRuntime、A3.2 写 FakeRuntime 之后,本文件整体替换。 */ import type { EventBus } from './events.js'; export interface EchoRunInput { sessionId: string; runId: string; messageId: string; text: string; bus: EventBus; signal: AbortSignal; } export interface EchoRunResult { text: string; finishReason: 'stop' | 'cancelled'; } const CHUNK_SIZE = 6; const CHUNK_DELAY_MS = 25; const sleep = (ms: number): Promise => new Promise((resolve) => setTimeout(resolve, ms)); export async function runEcho(input: EchoRunInput): Promise { const { bus, signal, sessionId, runId, messageId } = input; const replyMessageId = `${messageId}-reply`; const reply = `(A1 占位引擎)收到:${input.text}`; let emitted = ''; bus.publish({ sessionId, runId, type: 'run.state', data: { state: 'running' } }); for (let index = 0; index < reply.length; index += CHUNK_SIZE) { if (signal.aborted) return finish(true); const piece = reply.slice(index, index + CHUNK_SIZE); emitted += piece; bus.publish({ sessionId, runId, type: 'message.delta', data: { messageId: replyMessageId, text: piece } }); await sleep(CHUNK_DELAY_MS); } if (signal.aborted) return finish(true); bus.publish({ sessionId, runId, type: 'message.completed', data: { messageId: replyMessageId, finishReason: 'stop' } }); bus.publish({ sessionId, runId, type: 'run.state', data: { state: 'idle' } }); return { text: emitted, finishReason: 'stop' }; function finish(cancelled: boolean): EchoRunResult { // 取消路径:cancelling → 一条带 cancelled 结束原因的消息 → 回到 idle。 // 'cancelled' 这个运行状态当前不使用(A3.1 定稿再确认语义)。 bus.publish({ sessionId, runId, type: 'run.state', data: { state: 'cancelling' } }); bus.publish({ sessionId, runId, type: 'message.completed', data: { messageId: replyMessageId, finishReason: cancelled ? 'cancelled' : 'stop' }, }); bus.publish({ sessionId, runId, type: 'run.state', data: { state: 'idle' } }); return { text: emitted, finishReason: 'cancelled' }; } }