8dad52f040
新增画布Agent会话契约、领域规则、SpacetimeDB元数据表和生成绑定。 新增api-server画布Agent会话CRUD、OSS消息文档读写、SSE消息流和生成工具编排。 新增前端右侧Agent对话面板、会话状态hook、SSE客户端、BFF客户端和相关测试。 调整画布侧栏、任务栏、小地图默认状态和面板互斥交互。 补齐画布Agent、OSS消息存储、SSE收口、后端契约和项目记忆文档。
71 lines
1.8 KiB
TypeScript
71 lines
1.8 KiB
TypeScript
import type { EditorAgentSseEvent } from '../../../packages/shared/src/contracts/editorAgent';
|
|
import { readSseJsonStream } from '../sseStream';
|
|
|
|
const EDITOR_AGENT_SSE_EVENT_NAMES = new Set<EditorAgentSseEvent['event']>([
|
|
'stage',
|
|
'message_delta',
|
|
'tool_started',
|
|
'tool_completed',
|
|
'generation_result',
|
|
'error',
|
|
'done',
|
|
]);
|
|
|
|
function isEditorAgentSseEventName(
|
|
value: unknown,
|
|
): value is EditorAgentSseEvent['event'] {
|
|
return (
|
|
typeof value === 'string' &&
|
|
EDITOR_AGENT_SSE_EVENT_NAMES.has(value as EditorAgentSseEvent['event'])
|
|
);
|
|
}
|
|
|
|
function readEventNameFromPayload(parsed: Record<string, unknown>) {
|
|
return isEditorAgentSseEventName(parsed.event) ? parsed.event : null;
|
|
}
|
|
|
|
function readEventDataFromPayload(parsed: Record<string, unknown>) {
|
|
const data = parsed.data;
|
|
return typeof data === 'object' && data !== null
|
|
? (data as Record<string, unknown>)
|
|
: null;
|
|
}
|
|
|
|
export function normalizeEditorAgentSseEvent(
|
|
eventName: string,
|
|
parsed: Record<string, unknown>,
|
|
): EditorAgentSseEvent | null {
|
|
const payloadEventName = readEventNameFromPayload(parsed);
|
|
if (payloadEventName) {
|
|
const payloadData = readEventDataFromPayload(parsed);
|
|
if (!payloadData) {
|
|
return null;
|
|
}
|
|
return {
|
|
event: payloadEventName,
|
|
data: payloadData,
|
|
} as unknown as EditorAgentSseEvent;
|
|
}
|
|
|
|
if (!isEditorAgentSseEventName(eventName)) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
event: eventName,
|
|
data: parsed,
|
|
} as unknown as EditorAgentSseEvent;
|
|
}
|
|
|
|
export async function readEditorAgentSseEvents(
|
|
response: Response,
|
|
onEvent: (event: EditorAgentSseEvent) => void,
|
|
) {
|
|
await readSseJsonStream(response, ({ eventName, parsed }) => {
|
|
const event = normalizeEditorAgentSseEvent(eventName, parsed);
|
|
if (event) {
|
|
onEvent(event);
|
|
}
|
|
});
|
|
}
|