62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
/**
|
||
* A1 阶段的占位引擎:把用户输入回显成一条助手消息,用来打通 HTTP / SSE 链路。
|
||
*
|
||
* 它刻意不做任何「理解」,也不调用 Provider——避免把假能力写进真实链路。
|
||
* A3.1 定义正式 AgentRuntime、A3.2 写 FakeRuntime 之后,本文件整体替换。
|
||
*/
|
||
import { 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' };
|
||
}
|
||
} |