aps-agent/server/app/echo-runtime.ts

62 lines
2.3 KiB
TypeScript
Raw Normal View History

/**
* 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<void> => new Promise((resolve) => setTimeout(resolve, ms));
export async function runEcho(input: EchoRunInput): Promise<EchoRunResult> {
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' };
}
}