@blade-hq/agent-client 2612.0.0-beta.64 → 2612.0.0-beta.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resources/sandbox.ts","../src/rest.ts","../src/tool-provider.ts","../src/version.ts","../src/auth-login.ts","../src/resources/auth.ts","../src/shared/type-guards.ts","../src/session/log-cursor.ts","../src/schemas/context-attachments.ts","../src/schemas/plugin-refs.ts","../src/schemas/topic-assets.ts","../src/shared/projection/helpers.ts","../src/schemas/message.ts","../src/shared/projection/state.ts","../src/schemas/context.ts","../src/shared/projection/context.ts","../src/shared/projection/builder.ts","../src/schemas/mcp-app.ts","../src/shared/tool-ui-card.ts","../src/shared/projection/history.ts","../src/shared/projection/workflow.ts","../src/resources/headless.ts","../src/resources/computers.ts","../src/resources/phones.ts","../src/resources/llm.ts","../src/resources/models.ts","../src/resources/connectors.ts","../src/schemas/session.ts","../src/session/definition.ts","../src/resources/sessions.ts","../src/resources/plugins.ts","../src/resources/chat-groups.ts","../src/resources/site-visits.ts","../src/server-clock.ts","../src/session/background.ts","../src/shared/auth-busy.ts","../src/commands/registry.ts","../src/session/events.ts","../src/session/history-page.ts","../src/session/queue.ts","../src/shared/oom.ts","../src/schemas/message-utils.ts","../src/session/workflow.ts","../src/session/state.ts","../src/session/errors.ts","../src/session/agent-session.ts","../src/session/hub.ts","../src/socket.ts","../src/auth.ts","../src/blade-client.ts","../src/application-client.ts","../src/schemas/ask-user-question.ts"],"sourcesContent":["import type { BladeClient } from \"../blade-client\"\n\nexport interface SandboxScriptRequest {\n script: string\n cwd: string\n /** Seconds, up to 120; defaults to 120. */\n timeout?: number\n}\nexport interface SandboxScriptResult {\n /** Combined stdout and stderr for diagnostics. */\n output: string\n stdout: string\n stdout_truncated: boolean\n exit_code: number | null\n timed_out: boolean\n error: string | null\n}\n\n/** Model-free execution in the authenticated user's sandbox. */\nexport class SandboxResource {\n constructor(private client: BladeClient) {}\n execute(input: SandboxScriptRequest): Promise<SandboxScriptResult> {\n return this.client.json(\"POST\", \"/api/sandbox/execute\", input)\n }\n}\n","const DOCS_URL = \"https://blade-hq.github.io/public-skills/\"\n\nexport class BladeApiError extends Error {\n readonly response: Response\n readonly status: number\n readonly statusText: string\n\n constructor(response: Response, message?: string) {\n super(message ?? `请求失败(${response.status} ${response.statusText})`)\n this.name = \"BladeApiError\"\n this.response = response\n this.status = response.status\n this.statusText = response.statusText\n }\n}\n\n/**\n * 从 FastAPI 风格的错误响应中提取 detail 字段,作为用户可读的中文错误文案。\n * 失败时返回 undefined,调用方会回退到默认提示。\n */\nexport async function extractErrorDetail(response: Response): Promise<string | undefined> {\n try {\n const cloned = response.clone()\n const contentType = cloned.headers.get(\"content-type\") ?? \"\"\n if (contentType.includes(\"application/json\")) {\n const data = (await cloned.json()) as { detail?: unknown }\n const detail = data?.detail\n if (typeof detail === \"string\" && detail.trim()) return detail\n if (Array.isArray(detail) && detail.length > 0) {\n const first = detail[0] as { msg?: unknown }\n if (first && typeof first.msg === \"string\") return first.msg\n }\n } else {\n const text = (await cloned.text()).trim()\n if (text) return text\n }\n } catch {\n }\n return undefined\n}\n\n/** 401/403 补充\"怎么办\"的指引,避免初级开发者对着裸状态码发呆。 */\nexport function decorateAuthError(error: unknown): unknown {\n if (!(error instanceof BladeApiError)) return error\n if (error.status === 401) {\n error.message =\n `${error.message}(未登录或凭证已失效。浏览器场景调用 client.auth.login() 弹窗登录,` +\n `自动化场景在 new BladeClient({ token }) 传入 PAT。接入指南:${DOCS_URL})`\n } else if (error.status === 403) {\n error.message = `${error.message}(当前账号无权访问该资源。接入指南:${DOCS_URL})`\n }\n return error\n}\n\nexport type HttpMethod = \"DELETE\" | \"GET\" | \"PATCH\" | \"POST\" | \"PUT\" | (string & {})\n\nexport interface BladeFetchInit {\n body?: BodyInit | null\n credentials?: RequestCredentials\n expectOk?: boolean\n headers?: HeadersInit\n signal?: AbortSignal | null\n}\n\n/**\n * 按客户端规则把后端路径拼成绝对 URL:`baseUrl` 自带路径前缀时保留前缀,\n * 路径里的前导 `/` 只表示\"从后端根开始\",不会被解释成站点根目录。\n *\n * 单独放在传输层,是为了让不走 `fetch()` 鉴权通道的资源(例如匿名的站点统计)\n * 落到同一个后端地址上,不必各自再写一份 URL 规则。\n */\nexport function buildBackendUrl(baseUrl: string, path: string): URL {\n const base = baseUrl.endsWith(\"/\") ? baseUrl : `${baseUrl}/`\n return new URL(path.startsWith(\"/\") ? path.slice(1) : path, base)\n}\n","import { buildBackendUrl } from \"./rest\"\nimport type { BladeClient } from \"./blade-client\"\n\nexport interface ProviderTool {\n name: string\n description?: string\n inputSchema: Record<string, unknown>\n outputSchema?: Record<string, unknown>\n handler: (arguments_: Record<string, unknown>, context: { sessionId: string; signal: AbortSignal; executionId?: string; requestId?: string; toolCallId?: string }) => Promise<ProviderToolResult>\n}\nexport interface ProviderToolResult {\n content: Array<{ type: \"text\"; text: string }>\n structuredContent?: Record<string, unknown>\n isError?: boolean\n}\nexport interface ToolProviderOptions {\n /** Stable application-owned ID, preserved across reconnects. */\n providerId: string\n /** Secret bound to the session's mcp_sources bearer_token. */\n capability: string\n tools: ProviderTool[]\n onError?: (error: Error) => void\n}\ninterface Wire {\n jsonrpc: \"2.0\"\n id?: string\n method?: string\n params?: Record<string, unknown>\n result?: unknown\n error?: { code: number; message: string }\n}\n\n/** Backend-only outbound connection. Reconnects registrations, never tool calls. */\nexport class ToolProvider {\n readonly url: string\n private socket?: WebSocket\n private timer?: ReturnType<typeof setTimeout>\n private registrationTimer?: ReturnType<typeof setTimeout>\n private disposed = false\n private registered = false\n private attempts = 0\n private calls = new Map<string, AbortController>()\n private waiters = new Set<{ resolve: () => void; reject: (error: Error) => void }>()\n constructor(private client: BladeClient, private options: ToolProviderOptions, private onDispose: () => void) {\n if (!/^[a-zA-Z0-9_-]{1,128}$/.test(options.providerId) || options.capability.length < 16 || options.capability.length > 4096) throw new Error(\"Invalid tool provider identity\")\n if (new Set(options.tools.map(t => t.name)).size !== options.tools.length || options.tools.length > 256) throw new Error(\"Duplicate or excessive provider tools\")\n this.url = `blade-rpc://${options.providerId}`\n this.open()\n }\n /** Resolves only after BA has authenticated and registered this connection. */\n ready(): Promise<void> {\n if (this.disposed) return Promise.reject(new Error(\"Tool provider disposed\"))\n if (this.registered) return Promise.resolve()\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => { this.waiters.delete(waiter); reject(new Error(\"Tool provider registration timed out\")) }, 25_000)\n const waiter = { resolve: () => { clearTimeout(timer); resolve() }, reject: (e: Error) => { clearTimeout(timer); reject(e) } }\n this.waiters.add(waiter)\n })\n }\n reconnect(): void {\n if (this.disposed) return\n clearTimeout(this.timer)\n this.reset()\n this.open()\n }\n private reset(): void {\n clearTimeout(this.registrationTimer)\n this.registered = false\n const socket = this.socket\n this.socket = undefined\n socket?.close()\n for (const controller of this.calls.values()) controller.abort()\n this.calls.clear()\n }\n private fail(error: Error): void {\n for (const waiter of this.waiters) waiter.reject(error)\n this.waiters.clear()\n try { this.options.onError?.(error) } catch {}\n }\n private open(): void {\n if (this.disposed) return\n const endpoint = buildBackendUrl(this.client.options.baseUrl, \"/api/app-tools/connect\")\n endpoint.protocol = endpoint.protocol === \"https:\" ? \"wss:\" : \"ws:\"\n let socket: WebSocket\n try {\n const token = this.client.token\n if (!token) throw new Error(\"Tool provider requires a token\")\n const encoded = btoa(Array.from(new TextEncoder().encode(token), byte => String.fromCharCode(byte)).join(\"\")).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\")\n socket = this.client.options.applicationTransport?.provider() ?? new WebSocket(endpoint, [\"blade-rpc\", `blade-bearer.${encoded}`])\n }\n catch { this.fail(new Error(\"Tool provider WebSocket unavailable\")); this.schedule(); return }\n this.socket = socket\n this.registrationTimer = setTimeout(() => { if (this.socket === socket) { this.fail(new Error(\"Tool provider registration timed out\")); socket.close() } }, 15_000)\n socket.addEventListener(\"open\", () => {\n if (this.socket !== socket) return\n socket.send(JSON.stringify({ jsonrpc: \"2.0\", id: \"register\", method: \"provider/register\", params: { providerId: this.options.providerId, capability: this.options.capability } }))\n })\n socket.addEventListener(\"message\", event => {\n if (this.socket !== socket || typeof event.data !== \"string\") return\n void this.receive(socket, event.data).catch(() => { this.fail(new Error(\"Invalid application tool RPC message\")); socket.close() })\n })\n socket.addEventListener(\"error\", () => { if (this.socket === socket) this.fail(new Error(\"Application tool connection failed\")) })\n socket.addEventListener(\"close\", () => {\n if (this.socket !== socket) return\n this.reset()\n this.fail(new Error(\"Application tool connection closed; unfinished calls will not be replayed\"))\n this.schedule()\n })\n }\n private schedule(): void {\n if (this.disposed) return\n this.timer = setTimeout(() => this.open(), Math.min(10_000, 500 * 2 ** Math.min(this.attempts++, 5)))\n }\n private async receive(socket: WebSocket, text: string): Promise<void> {\n const message = JSON.parse(text) as Wire\n if (message.jsonrpc !== \"2.0\") throw new Error(\"Invalid JSON-RPC envelope\")\n if (message.id === \"register\" && !message.method) {\n clearTimeout(this.registrationTimer)\n if (message.error || !(message.result as { registered?: boolean })?.registered) {\n this.fail(new Error(message.error?.message ?? \"Tool provider registration rejected\")); socket.close(); return\n }\n this.registered = true; this.attempts = 0\n for (const waiter of this.waiters) waiter.resolve()\n this.waiters.clear(); return\n }\n if (!this.registered) throw new Error(\"Provider not registered\")\n if (message.method === \"notifications/cancelled\") {\n this.calls.get(String(message.params?.requestId))?.abort(); return\n }\n if (!message.id || typeof message.id !== \"string\" || this.calls.has(message.id)) throw new Error(\"Invalid RPC request ID\")\n const controller = new AbortController()\n this.calls.set(message.id, controller)\n let response: Wire = { jsonrpc: \"2.0\", id: message.id }\n try {\n if (message.method === \"tools/list\") {\n response.result = { tools: this.options.tools.map(({ name, description, inputSchema, outputSchema }) => ({ name, description, inputSchema, ...(outputSchema ? { outputSchema } : {}) })) }\n } else if (message.method === \"tools/call\") {\n const params = message.params\n const tool = this.options.tools.find(t => t.name === params?.name)\n if (!tool || typeof params?.sessionId !== \"string\" || !params.sessionId || !params.arguments || typeof params.arguments !== \"object\" || Array.isArray(params.arguments)) throw new Error(\"Invalid or unauthorized tool call\")\n response.result = await tool.handler(params.arguments as Record<string, unknown>, { sessionId: params.sessionId, signal: controller.signal, ...Object.fromEntries([\"executionId\", \"requestId\", \"toolCallId\"].flatMap(key => typeof params[key] === \"string\" && params[key] ? [[key, params[key]]] : [])) })\n } else {\n response.error = { code: -32601, message: \"Method not found\" }\n }\n } catch {\n response = { jsonrpc: \"2.0\", id: message.id, error: { code: -32000, message: \"Application tool execution failed\" } }\n } finally { this.calls.delete(message.id) }\n if (this.socket === socket && socket.readyState === WebSocket.OPEN && !controller.signal.aborted) socket.send(JSON.stringify(response))\n }\n dispose(): void {\n if (this.disposed) return\n this.disposed = true\n clearTimeout(this.timer); this.reset()\n this.fail(new Error(\"Tool provider disposed\")); this.onDispose()\n }\n}\n","\ndeclare const __BLADE_SDK_VERSION__: string | undefined\n\n/**\n * 本 SDK 的 npm 包版本,随 Socket.IO 握手一并声明。\n * Release 构建由 Git Tag 注入;本地开发回退到当前源码版本。\n */\nexport const SDK_NAME = \"agent-client\"\nexport const SDK_VERSION =\n typeof __BLADE_SDK_VERSION__ === \"string\" ? __BLADE_SDK_VERSION__ : \"1.1.1\"\n","import type { BladeClient } from \"./blade-client\"\n\n/**\n * 弹窗授权登录,与 Chrome 扩展共用同一套后端授权内核(见 server/routes/sdk_auth.py):\n *\n * 1. 弹窗打开 `GET /api/auth/sdk/authorize?client_origin=<本页 origin>&state=<随机值>`\n * 2. 用户点击「许可授权」→ 回调页把 `{ type: \"blade-agent:sdk-auth\", state, code }`\n * postMessage 定向发回本页(code 一次性、5 分钟有效)\n * 3. SDK 用 `POST /api/auth/sdk/token`(code + state + client_origin)换取 PAT,\n * 存储并热挂载(REST 与 Socket.IO 同时生效)\n */\n\nexport interface LoginOptions {\n /** 弹窗尺寸,默认 480x640。 */\n width?: number\n height?: number\n /** 超时毫秒数,默认 5 分钟(与后端授权码有效期一致)。 */\n timeoutMs?: number\n}\n\nexport interface LoginResult {\n token: string\n user?: { id?: string; username?: string; display_name?: string }\n}\n\ninterface AuthCallbackMessage {\n type: \"blade-agent:sdk-auth\"\n version: number\n status: \"success\" | \"denied\" | \"error\"\n state: string\n code?: string\n error?: string\n}\n\nfunction isAuthCallbackMessage(value: unknown): value is AuthCallbackMessage {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as Record<string, unknown>).type === \"blade-agent:sdk-auth\"\n )\n}\n\nconst AUTH_ERROR_HINTS: Record<string, string> = {\n pat_unavailable: \"没能为你准备访问凭据。请退出后重新登录 Blade 再试一次;若仍然失败,请联系管理员。\",\n}\n\nfunction randomState(): string {\n const bytes = new Uint8Array(24)\n crypto.getRandomValues(bytes)\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\")\n}\n\nexport type TokenStorageMode = \"local\" | \"memory\"\n\nconst storageKeyFor = (baseUrl: string) => `blade-sdk-token:${baseUrl}`\n\nexport function readStoredToken(baseUrl: string): string | null {\n if (typeof localStorage === \"undefined\") return null\n try {\n return localStorage.getItem(storageKeyFor(baseUrl))\n } catch {\n return null\n }\n}\n\nexport function writeStoredToken(baseUrl: string, token: string | null, mode: TokenStorageMode): void {\n if (mode !== \"local\" || typeof localStorage === \"undefined\") return\n try {\n if (token) {\n localStorage.setItem(storageKeyFor(baseUrl), token)\n } else {\n localStorage.removeItem(storageKeyFor(baseUrl))\n }\n } catch {\n }\n}\n\nexport async function loginWithPopup(\n client: BladeClient,\n options: LoginOptions = {},\n): Promise<LoginResult> {\n if (typeof window === \"undefined\") {\n throw new Error(\"client.auth.login() 只能在浏览器中调用;Node.js 场景请直接传入 token。\")\n }\n // file:// 打开的本地 HTML(智能体生成的交付物被双击打开)没有可声明的\n // origin,按 opaque(\"null\")走:授权页会向用户展示「本地文件页面」,\n // 回传的一次性 code 由 \"*\" 投递给本窗口,state 校验不变。\n const rawOrigin = window.location.origin\n const clientOrigin = /^https?:\\/\\//.test(rawOrigin) ? rawOrigin : \"null\"\n\n const width = options.width ?? 480\n const height = options.height ?? 640\n const left = Math.max(0, (window.screen.width - width) / 2)\n const top = Math.max(0, (window.screen.height - height) / 2)\n const state = randomState()\n const authorizeUrl = new URL(\n \"/api/auth/sdk/authorize\",\n client.options.baseUrl || window.location.origin,\n )\n authorizeUrl.searchParams.set(\"client_origin\", clientOrigin)\n authorizeUrl.searchParams.set(\"state\", state)\n\n const popup = window.open(\n \"about:blank\",\n `blade-sdk-login-${state}`,\n `popup=yes,width=${width},height=${height},left=${left},top=${top}`,\n )\n if (!popup) {\n throw new Error(\"登录弹窗被浏览器拦截了。请允许本站打开弹窗后重试。\")\n }\n\n const expectedOrigin = new URL(client.options.baseUrl || window.location.origin).origin\n\n return new Promise<LoginResult>((resolve, reject) => {\n const timeoutMs = options.timeoutMs ?? 5 * 60 * 1000\n let settled = false\n let closeTimer: ReturnType<typeof globalThis.setTimeout> | undefined\n\n const stopCloseWatch = () => {\n globalThis.clearInterval(closeWatcher)\n if (closeTimer !== undefined) globalThis.clearTimeout(closeTimer)\n }\n\n const cleanup = () => {\n window.removeEventListener(\"message\", onMessage)\n stopCloseWatch()\n globalThis.clearTimeout(timeoutHandle)\n }\n const settle = (fn: () => void) => {\n if (settled) return\n settled = true\n cleanup()\n fn()\n }\n\n const onMessage = (event: MessageEvent) => {\n if (event.origin !== expectedOrigin) return\n if (event.source !== popup) return\n if (!isAuthCallbackMessage(event.data)) return\n if (event.data.state !== state) return\n const message = event.data\n stopCloseWatch()\n const closePopup = () => {\n try {\n popup.close()\n } catch {\n }\n }\n if (message.status === \"denied\") {\n closePopup()\n settle(() => reject(new Error(\"你取消了授权,未完成登录。\")))\n return\n }\n if (message.status !== \"success\" || !message.code) {\n settle(() => reject(new Error(AUTH_ERROR_HINTS[message.error ?? \"\"] ?? message.error ?? \"登录失败,未取得授权码。\")))\n return\n }\n closePopup()\n client\n .json<{\n access_token: string\n user?: LoginResult[\"user\"]\n }>(\"POST\", \"/api/auth/sdk/token\", {\n code: message.code,\n state,\n client_origin: clientOrigin,\n })\n .then((response) => {\n settle(() => resolve({ token: response.access_token, user: response.user }))\n })\n .catch((error) => {\n settle(() =>\n reject(error instanceof Error ? error : new Error(\"授权码换取令牌失败,请重试。\")),\n )\n })\n }\n\n const closeWatcher = globalThis.setInterval(() => {\n if (!popup.closed || settled || closeTimer !== undefined) return\n closeTimer = globalThis.setTimeout(() => {\n settle(() => reject(new Error(\"登录窗口已关闭,未完成授权。\")))\n }, 400)\n }, 500)\n\n const timeoutHandle = globalThis.setTimeout(() => {\n settle(() => reject(new Error(\"登录超时,请重试。\")))\n }, timeoutMs)\n\n window.addEventListener(\"message\", onMessage)\n popup.location.replace(authorizeUrl.toString())\n })\n}\n","import type { BladeClient } from \"../blade-client\"\nimport type { LoginOptions, LoginResult } from \"../auth-login\"\n\nexport interface UserInfo {\n id: string\n username: string\n display_name?: string | null\n avatar_url: string | null\n token: string\n auth_type: \"casdoor\"\n is_admin?: boolean\n}\n\nexport interface ProvidersResponse {\n providers: Array<{\n name: string\n authorize_url: string\n }>\n password_enabled: boolean\n}\n\nexport interface ExchangeCodeParams {\n /** 原生客户端浏览器回传使用的 S256 PKCE 校验。 */\n codeVerifier?: string\n androidApp?: \"ba\" | \"pa\"\n desktopApp?: \"ba\" | \"pa\"\n /** 桌面主进程监听的完整回环 URI,必须与授权时一致。 */\n callbackUri?: string\n /** 授权回调页 postMessage 回来的一次性 code。 */\n code: string\n /** 发起授权时用的 state,必须原样传回。 */\n state: string\n /** 发起授权的页面 origin,要和 authorize 时传的 `client_origin` 完全一致。 */\n clientOrigin: string\n}\n\nexport interface ExchangeCodeResult {\n access_token: string\n token_type: string\n user: {\n id: string\n username: string\n display_name: string\n avatar_url: string | null\n }\n}\n\nexport class AuthResource {\n constructor(private client: BladeClient) {}\n\n /**\n * 弹窗授权登录(浏览器专用):弹出后端授权页,用户点击\"许可授权\"后\n * 自动取得 PAT 并热挂载到当前 client。等价于 client.login()。\n */\n login(options?: LoginOptions): Promise<LoginResult> {\n return this.client.login(options)\n }\n\n /**\n * 用一次性 code 换 PAT。给**服务端**用:浏览器把 code 交给你自己的后端,\n * 后端换到的 PAT 不进浏览器。浏览器里直接用 `login()` 就够了。\n *\n * 服务端调用时会自己补上 `Origin` 头(浏览器会自动带,服务端不会,缺了\n * 后端报 `missing_request_origin`)。\n */\n exchangeCode(params: ExchangeCodeParams): Promise<ExchangeCodeResult> {\n return this.client.jsonFromInit(\"/api/auth/sdk/token\", {\n method: \"POST\",\n headers: { Origin: params.clientOrigin },\n body: JSON.stringify({\n code: params.code,\n ...(params.codeVerifier ? { code_verifier: params.codeVerifier, android_app: params.androidApp, desktop_app: params.desktopApp, callback_uri: params.callbackUri } : {}),\n state: params.state,\n client_origin: params.clientOrigin,\n }),\n })\n }\n\n /** 清除 login() 存储的令牌。 */\n logoutToken(): void {\n this.client.logoutToken()\n }\n\n getProviders(): Promise<ProvidersResponse> {\n return this.client.json(\"GET\", \"/api/auth/providers\")\n }\n\n getMe(options: { signal?: AbortSignal } = {}): Promise<UserInfo> {\n return this.client.jsonFromInit(\"/api/auth/me\", { signal: options.signal })\n }\n\n logout(): Promise<{ logout_url: string }> {\n return this.client.json(\"POST\", \"/api/auth/logout\")\n }\n}\n","/** Return true for non-null, non-array objects. */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n","import type { RawEvent } from \"../shared/projection\"\n\nfunction positive(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value > 0\n}\n\n/** Shared by full and status subscriptions. UI sequence and run_id are unrelated. */\nexport class LogCursor {\n private sequence = 0\n private epoch = 0\n private readonly deltas = new Map<number, number>()\n\n subscription(): { after_log_seq?: number } {\n return this.sequence > 0 ? { after_log_seq: this.sequence } : {}\n }\n\n consume(events: RawEvent[]): { events: RawEvent[]; reload: boolean } {\n const accepted: RawEvent[] = []\n let reload = false\n for (const event of events) {\n if (event.type === \"log:retract\") {\n this.deltas.clear()\n reload = true\n continue\n }\n if (event.type === \"log:record\") {\n if (!positive(event.log_seq) || event.log_seq <= this.sequence) continue\n const nested = event.payload.events\n if (!Array.isArray(nested)) continue\n if (positive(event.payload.epoch) && event.payload.epoch !== this.epoch) {\n this.epoch = event.payload.epoch\n this.deltas.clear()\n reload = true\n }\n accepted.push(...nested as RawEvent[])\n if ([\"step_end\", \"run_end\", \"truncate\"].includes(String(event.payload.kind))) {\n for (const step of this.deltas.keys()) if (step <= event.log_seq) this.deltas.delete(step)\n }\n this.sequence = event.log_seq\n continue\n }\n if (event.type === \"llm:stream:reset\" && positive(event.step_log_seq)) {\n this.deltas.delete(event.step_log_seq)\n }\n if (positive(event.step_log_seq) && positive(event.delta_seq)) {\n if (event.delta_seq <= (this.deltas.get(event.step_log_seq) ?? 0)) continue\n this.deltas.set(event.step_log_seq, event.delta_seq)\n }\n if (event.type === \"log:delta\" && Array.isArray(event.payload.events)) {\n accepted.push(...event.payload.events as RawEvent[])\n } else {\n accepted.push(event)\n }\n }\n return { events: accepted, reload }\n }\n}\n","/** Frozen application data belonging to one message. The server does not interpret business types. */\nexport interface ContextAttachment {\n id: string\n label: string\n content: string\n /** Project plain text as a named session Context; the producer supplies full state. */\n update_format?: \"snapshot\" | \"diff\"\n data?: Record<string, unknown> | null\n files?: Array<{ name: string; session_id?: string; path?: string }>\n}\n\n/** Validate before persisting a reliable request. JSON cloning also rejects cycles. */\nexport function snapshotContextAttachments(value: ContextAttachment[]): ContextAttachment[] {\n const snapshot = JSON.parse(JSON.stringify(value)) as ContextAttachment[]\n if (!Array.isArray(snapshot) || snapshot.length > 20) throw new Error(\"每条消息最多提供 20 份资料\")\n const ids = new Set<string>()\n const validText = (text: unknown, limit: number): text is string => typeof text === \"string\" && [...text].length > 0 && [...text].length <= limit\n for (const item of snapshot) {\n if (!item || !validText(item.id, 128) || !validText(item.label, 512) || !validText(item.content, 64000) || ids.has(item.id)) throw new Error(\"附加资料格式错误或 ID 重复\")\n ids.add(item.id)\n if (item.update_format !== undefined && item.update_format !== \"snapshot\" && item.update_format !== \"diff\") throw new Error(\"资料更新格式无效\")\n if (item.data != null && (typeof item.data !== \"object\" || Array.isArray(item.data))) throw new Error(\"资料数据必须是 JSON 对象\")\n if (item.files != null && (!Array.isArray(item.files) || item.files.length > 20)) throw new Error(\"资料文件格式错误\")\n for (const file of item.files ?? []) {\n if (!validText(file.name, 512)) throw new Error(\"资料文件名格式错误\")\n if (file.session_id == null && file.path == null) continue\n if (!validText(file.session_id, 128) || !validText(file.path, 2048) || /[\\\\:]/.test(file.path) || file.path.replace(/^\\//, \"\").split(\"/\").some(part => !part || part === \".\" || part === \"..\")) throw new Error(\"资料文件必须使用有效的会话文件路径\")\n }\n }\n if (new TextEncoder().encode(JSON.stringify(snapshot)).length > 256 * 1024) throw new Error(\"消息附加资料不能超过 256 KiB\")\n return snapshot\n}\n\n/** Server-owned snapshots travel unchanged through stream and history projections. */\nexport function normalizeContextAttachments(value: unknown): ContextAttachment[] {\n return Array.isArray(value) ? value as ContextAttachment[] : []\n}\n","export interface PluginRef {\n provider: \"plugin\"\n plugin: string\n server: string\n id: string\n label: string\n}\nexport function normalizePluginRefs(value: unknown): PluginRef[] {\n if (!Array.isArray(value)) return []\n const seen = new Set<string>()\n return value.flatMap((item) => {\n if (!item || typeof item !== \"object\" || item.provider !== \"plugin\" ||\n ![item.plugin, item.server, item.id, item.label].every((part) => typeof part === \"string\" && part)) return []\n const key = JSON.stringify([item.plugin, item.server, item.id])\n if (seen.has(key)) return []\n seen.add(key)\n return [{ provider: \"plugin\" as const, plugin: item.plugin, server: item.server, id: item.id, label: item.label }]\n })\n}\n\n\nexport interface SkillRef {\n provider: \"skill\"\n id: string\n label: string\n}\n\nexport type MessageRef = PluginRef | SkillRef\n\nexport function normalizeMessageRefs(value: unknown): MessageRef[] {\n if (!Array.isArray(value)) return []\n const seen = new Set<string>()\n return value.flatMap((item): MessageRef[] => {\n if (!item || typeof item !== \"object\") return []\n const ref = item.provider === \"skill\" && typeof item.id === \"string\" && item.id &&\n typeof item.label === \"string\" && item.label\n ? { provider: \"skill\" as const, id: item.id, label: item.label }\n : normalizePluginRefs([item])[0]\n if (!ref) return []\n const key = ref.provider === \"skill\" ? JSON.stringify([ref.provider, ref.id]) : JSON.stringify([ref.provider, ref.plugin, ref.server, ref.id])\n if (seen.has(key)) return []\n seen.add(key)\n return [ref]\n })\n}\n","/** An explicit asset selection for one user message, never a persistent session choice. */\nexport interface TopicAssetRef {\n topic_id: string\n path: string\n}\n\n/** Read display identities only. The server rechecks access and resolves current metadata. */\nexport function normalizeTopicAssetRefs(value: unknown): TopicAssetRef[] {\n if (!Array.isArray(value)) return []\n const seen = new Set<string>()\n return value.flatMap((item) => {\n if (!item || typeof item !== \"object\" || typeof item.topic_id !== \"string\" || !item.topic_id || typeof item.path !== \"string\" || !item.path) return []\n const key = JSON.stringify([item.topic_id, item.path])\n if (seen.has(key)) return []\n seen.add(key)\n return [{ topic_id: item.topic_id, path: item.path }]\n })\n}\n","import type {\n ContentBlock,\n PendingQuestionRef,\n ToolCallProjection,\n ToolEvidence,\n TurnProjection,\n} from \"../../schemas/projection\"\nimport type { TurnState } from \"./state\"\n\n\nexport function upsertToolCall(\n state: TurnState,\n toolCallId: string,\n toolName: string,\n displayName: string,\n args: string,\n): void {\n if (!toolCallId) return\n\n let found = false\n for (let i = 0; i < state.toolCalls.length; i++) {\n if (state.toolCalls[i].id !== toolCallId) continue\n const tc = state.toolCalls[i]\n state.toolCalls[i] = {\n ...tc,\n tool_name: toolName || tc.tool_name,\n display_name: displayName || tc.display_name,\n arguments: args || tc.arguments,\n }\n found = true\n break\n }\n if (!found) {\n state.toolCalls.push({\n id: toolCallId,\n tool_name: toolName,\n display_name: displayName,\n arguments: args,\n status: \"pending\",\n })\n }\n\n let blockFound = false\n for (let i = 0; i < state.blocks.length; i++) {\n const b = state.blocks[i]\n if (b.type !== \"tool_use\" || b.tool_call_id !== toolCallId) continue\n state.blocks[i] = {\n ...b,\n content: args || b.content,\n tool_name: toolName || b.tool_name,\n display_name: displayName || b.display_name,\n }\n blockFound = true\n break\n }\n if (!blockFound) {\n state.blocks.push({\n type: \"tool_use\",\n content: args,\n tool_call_id: toolCallId,\n tool_name: toolName || null,\n display_name: displayName || null,\n })\n }\n}\n\n\nexport function applyToolResult(\n state: TurnState,\n toolCallId: string,\n result: unknown,\n status: ToolCallProjection[\"status\"],\n durationMs: number | null,\n ranInParallel: boolean | null,\n sourceLoop: { loop_name: string; description: string } | null,\n startedAt: string | null = null,\n): void {\n let toolName = \"\"\n let displayName = \"\"\n let finalResult = result\n\n for (let i = 0; i < state.toolCalls.length; i++) {\n const tc = state.toolCalls[i]\n if (tc.id !== toolCallId) continue\n\n if (typeof result === \"string\") {\n finalResult = maybeEnrichAskUserResult(tc.tool_name, result, sourceLoop)\n }\n\n const update: Partial<ToolCallProjection> = { status, result: finalResult }\n if (durationMs != null) update.duration_ms = durationMs\n if (ranInParallel != null) update.ran_in_parallel = ranInParallel\n if (startedAt != null) update.started_at = startedAt\n state.toolCalls[i] = { ...tc, ...update }\n toolName = tc.tool_name\n displayName = tc.display_name\n break\n }\n\n upsertToolResultBlock(state, toolCallId, finalResult, toolName, displayName)\n}\n\nexport function appendToolResultDelta(\n state: TurnState,\n toolCallId: string,\n delta: string,\n reset = false,\n): void {\n if (!toolCallId || !delta) return\n\n let toolName = \"\"\n let displayName = \"\"\n let currentResult = \"\"\n\n for (let i = 0; i < state.toolCalls.length; i++) {\n const tc = state.toolCalls[i]\n if (tc.id !== toolCallId) continue\n toolName = tc.tool_name\n displayName = tc.display_name\n if (!reset && typeof tc.result === \"string\") currentResult = tc.result\n state.toolCalls[i] = { ...tc, result: currentResult + delta }\n break\n }\n\n for (const block of state.blocks) {\n if (block.type !== \"tool_result\" || block.tool_call_id !== toolCallId) continue\n if (!reset && typeof block.content === \"string\") currentResult = block.content\n break\n }\n\n upsertToolResultBlock(state, toolCallId, currentResult + delta, toolName, displayName)\n}\n\nfunction upsertToolResultBlock(\n state: TurnState,\n toolCallId: string,\n content: unknown,\n toolName: string,\n displayName: string,\n): void {\n for (let i = 0; i < state.blocks.length; i++) {\n const block = state.blocks[i]\n if (block.type !== \"tool_result\" || block.tool_call_id !== toolCallId) continue\n state.blocks[i] = {\n ...block,\n content,\n tool_name: toolName || block.tool_name,\n display_name: displayName || block.display_name,\n }\n return\n }\n\n state.blocks.push({\n type: \"tool_result\",\n content,\n tool_call_id: toolCallId,\n tool_name: toolName || null,\n display_name: displayName || null,\n })\n}\n\n\nexport function appendTextBlock(\n state: TurnState,\n blockType: ContentBlock[\"type\"],\n content: unknown,\n): void {\n if (content == null || content === \"\") return\n const text = String(content)\n const lastBlock = state.blocks[state.blocks.length - 1]\n if (lastBlock && lastBlock.type === blockType && typeof lastBlock.content === \"string\") {\n state.blocks[state.blocks.length - 1] = {\n ...lastBlock,\n content: lastBlock.content + text,\n }\n return\n }\n state.blocks.push({ type: blockType, content: text })\n}\n\n\nexport function appendToolCallArguments(\n state: TurnState,\n toolCallId: string,\n delta: string,\n): void {\n let newArgs = \"\"\n for (let i = 0; i < state.toolCalls.length; i++) {\n const tc = state.toolCalls[i]\n if (tc.id === toolCallId) {\n newArgs = tc.arguments + delta\n state.toolCalls[i] = { ...tc, arguments: newArgs }\n break\n }\n }\n if (!newArgs) return\n\n for (let i = 0; i < state.blocks.length; i++) {\n const b = state.blocks[i]\n if (b.type === \"tool_use\" && b.tool_call_id === toolCallId) {\n state.blocks[i] = { ...b, content: newArgs }\n break\n }\n }\n}\n\n\nfunction maybeEnrichAskUserResult(\n toolName: string,\n result: string,\n sourceLoop: { loop_name: string; description: string } | null,\n): string {\n if (!sourceLoop) return result\n const normalized = toolName.includes(\":\") ? toolName.split(\":\").pop()! : toolName\n if (normalized !== \"AskUserQuestion\") return result\n try {\n const payload = JSON.parse(result)\n if (typeof payload !== \"object\" || payload === null) return result\n payload.source_loop = sourceLoop\n return JSON.stringify(payload)\n } catch {\n return result\n }\n}\n\n\nexport function buildSystemNotificationTurn(\n sequence: number,\n turnId: string,\n loopId: string,\n notificationType: string,\n status: string,\n title: string,\n detail: string | null,\n metadata: Record<string, unknown>,\n): TurnProjection {\n return {\n id: turnId,\n sequence,\n turn_id: turnId,\n loop_id: loopId,\n kind: \"message\",\n role: \"system\",\n status: \"completed\",\n blocks: [\n {\n type: \"system_notification\",\n content: {\n notification_type: notificationType,\n status,\n title,\n detail,\n metadata,\n },\n },\n ],\n tool_calls: [],\n model: null,\n usage: null,\n duration_ms: 0,\n }\n}\n\nexport function buildSystemNotificationBlock(\n notificationType: string,\n status: string,\n title: string,\n detail: string | null,\n metadata: Record<string, unknown>,\n): ContentBlock {\n return {\n type: \"system_notification\",\n content: {\n notification_type: notificationType,\n status,\n title,\n detail,\n metadata,\n },\n }\n}\n\n\nexport function buildMarkerTurn(\n sequence: number,\n turnId: string,\n loopId: string,\n blockType: ContentBlock[\"type\"],\n content: unknown,\n): TurnProjection {\n return {\n id: turnId,\n sequence,\n turn_id: turnId,\n loop_id: loopId,\n kind: \"message\",\n role: \"assistant\",\n status: \"completed\",\n blocks: [{ type: blockType, content }],\n tool_calls: [],\n model: null,\n usage: null,\n duration_ms: 0,\n }\n}\n\n\nexport function buildCompactionTurn(\n sequence: number,\n compactionId: string,\n loopId: string,\n status: TurnProjection[\"status\"],\n data: Record<string, unknown>,\n): TurnProjection {\n const tokensBefore = asInt(data.tokens_before)\n const tokensAfter = asInt(data.tokens_after)\n let savedRatio: number | null = null\n if (tokensBefore && tokensBefore > 0 && tokensAfter != null) {\n savedRatio = 1 - tokensAfter / tokensBefore\n } else {\n savedRatio = asFloat(data.saved_ratio)\n }\n let archivedCount = asInt(data.archived_count)\n if (archivedCount == null && Array.isArray(data.archived_files)) {\n archivedCount = data.archived_files.length\n }\n\n const content = data.content\n const summaryFull = compactionSummaryFull(content)\n const summaryPreview = summaryFull\n ? summaryFull\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean)\n .join(\" \")\n .slice(0, 200)\n : null\n\n return {\n id: `compaction:${compactionId}`,\n sequence,\n turn_id: `compaction:${compactionId}`,\n loop_id: loopId,\n kind: \"compaction\",\n role: \"system\",\n status,\n blocks: [],\n tool_calls: [],\n model: null,\n usage: null,\n duration_ms: 0,\n compaction_id: compactionId,\n summary_preview: summaryPreview,\n summary_full: summaryFull,\n archived_count: archivedCount,\n archived_files: Array.isArray(data.archived_files)\n ? data.archived_files.filter(\n (item): item is Record<string, unknown> =>\n typeof item === \"object\" && item !== null && !Array.isArray(item),\n )\n : null,\n archived_tool_calls: Array.isArray(data.archived_tool_calls)\n ? data.archived_tool_calls.filter(\n (item): item is Record<string, unknown> =>\n typeof item === \"object\" && item !== null && !Array.isArray(item),\n )\n : null,\n tokens_before: tokensBefore,\n tokens_after: tokensAfter,\n saved_ratio: savedRatio,\n trigger: asTrigger(data.trigger),\n failure_reason: [data.failure_reason, data.fallback_reason, data.reason]\n .find((value): value is string => typeof value === \"string\" && value.length > 0) ?? null,\n fallback_applied: typeof data.fallback_applied === \"boolean\" ? data.fallback_applied : null,\n }\n}\n\nfunction compactionSummaryFull(content: unknown): string | null {\n const text = String(content ?? \"\")\n if (!text) return null\n const cleaned = text\n .replace(\"<compaction-summary>\", \"\")\n .replace(\"</compaction-summary>\", \"\")\n .replace(/\\r\\n/g, \"\\n\")\n .replace(/\\r/g, \"\\n\")\n .trim()\n return cleaned || null\n}\n\nfunction asInt(value: unknown): number | null {\n if (typeof value === \"boolean\") return null\n if (typeof value === \"number\") return Math.trunc(value)\n return null\n}\n\nfunction asFloat(value: unknown): number | null {\n if (typeof value === \"boolean\") return null\n if (typeof value === \"number\") return value\n return null\n}\n\nfunction asTrigger(value: unknown): \"auto\" | \"manual\" | \"forced_retry\" | null {\n if (value === \"auto\" || value === \"manual\" || value === \"forced_retry\") return value\n return null\n}\n\n// --- Child pause helpers ---\n\nexport interface ChildPauseInfo {\n parentLoopName: string\n parentToolCallId: string\n childLoopName: string\n childToolCallId: string\n description: string\n}\n\nexport function setToolCallStatus(\n turn: TurnState | TurnProjection | null | undefined,\n toolCallId: string,\n status: ToolCallProjection[\"status\"],\n result: unknown,\n pendingQuestionRef: PendingQuestionRef | null,\n): void {\n if (!turn || !toolCallId) return\n const toolCalls = \"toolCalls\" in turn ? turn.toolCalls : turn.tool_calls\n for (let i = 0; i < toolCalls.length; i++) {\n if (toolCalls[i].id !== toolCallId) continue\n toolCalls[i] = {\n ...toolCalls[i],\n status,\n result,\n pending_question_ref: pendingQuestionRef,\n }\n return\n }\n}\n\nexport function applyAskUserPauseToTurn(\n turn: TurnState | TurnProjection | null | undefined,\n pauseToolData: Record<string, unknown>,\n toolCallId: string,\n childLoopName: string,\n description: string,\n displayNameResolver: (name: string) => string,\n): void {\n if (!turn || !toolCallId) return\n\n const sourceLoop = childLoopName\n ? { loop_name: childLoopName, description }\n : null\n const pauseName = String(pauseToolData.name ?? \"AskUserQuestion\")\n const result = spacedJson(askUserResultFromPausePayload(pauseToolData, sourceLoop))\n\n const isTurnState = \"toolCalls\" in turn\n const toolCalls = isTurnState ? turn.toolCalls : turn.tool_calls\n const blocks = turn.blocks\n\n const existingCall = toolCalls.find((call) => call.id === toolCallId)\n const toolName = existingCall?.tool_name || pauseName.split(\":\").pop() || pauseName\n const displayName = existingCall?.display_name || displayNameResolver(toolName)\n const rawArgs = existingCall?.arguments || JSON.stringify(pauseToolData.arguments ?? {})\n const args = spacedJson(rawArgs)\n let found = false\n for (let i = 0; i < toolCalls.length; i++) {\n if (toolCalls[i].id !== toolCallId) continue\n toolCalls[i] = {\n ...toolCalls[i],\n tool_name: toolName,\n display_name: displayName,\n arguments: args,\n }\n found = true\n break\n }\n if (!found) {\n toolCalls.push({\n id: toolCallId,\n tool_name: toolName,\n display_name: displayName,\n arguments: args,\n status: \"pending\",\n })\n }\n\n let blockFound = false\n for (let i = 0; i < blocks.length; i++) {\n if (blocks[i].type !== \"tool_use\" || blocks[i].tool_call_id !== toolCallId) continue\n blocks[i] = { ...blocks[i], content: args, tool_name: toolName, display_name: displayName }\n blockFound = true\n break\n }\n if (!blockFound) {\n blocks.push({\n type: \"tool_use\",\n content: args,\n tool_call_id: toolCallId,\n tool_name: toolName,\n display_name: displayName,\n })\n }\n\n setToolCallStatus(turn, toolCallId, \"awaiting_answer\", result, null)\n\n let resultBlockFound = false\n for (let i = 0; i < blocks.length; i++) {\n if (blocks[i].type !== \"tool_result\" || blocks[i].tool_call_id !== toolCallId) continue\n blocks[i] = { ...blocks[i], content: result }\n resultBlockFound = true\n break\n }\n if (!resultBlockFound) {\n blocks.push({\n type: \"tool_result\",\n content: result,\n tool_call_id: toolCallId,\n tool_name: toolName,\n display_name: displayName,\n })\n }\n}\n\nfunction spacedJson(value: string): string {\n try {\n const encode = (item: unknown): string => {\n if (Array.isArray(item)) return `[${item.map(encode).join(\", \")}]`\n if (item && typeof item === \"object\") {\n return `{${Object.entries(item).map(([key, part]) => `${JSON.stringify(key)}: ${encode(part)}`).join(\", \")}}`\n }\n return JSON.stringify(item) ?? \"null\"\n }\n return encode(JSON.parse(value))\n } catch {\n return value\n }\n}\n\n/** Answered questions use the model's compact JSON again in persisted history. */\nexport function restoreAnsweredAskUserJson(\n turn: TurnState | TurnProjection | null | undefined,\n toolCallId: string,\n): void {\n if (!turn || !toolCallId) return\n const compact = (value: unknown): unknown => {\n if (typeof value !== \"string\") return value\n try { return JSON.stringify(JSON.parse(value)) } catch { return value }\n }\n const calls = \"toolCalls\" in turn ? turn.toolCalls : turn.tool_calls\n for (const call of calls) {\n if (call.id === toolCallId) call.arguments = compact(call.arguments) as string\n }\n for (const block of turn.blocks) {\n if (block.tool_call_id === toolCallId && (block.type === \"tool_use\" || block.type === \"tool_result\")) {\n block.content = compact(block.content)\n }\n }\n}\n\nexport function applyChildPauseToParent(\n parentTurn: TurnState | TurnProjection | null | undefined,\n parentToolCallId: string,\n childLoopName: string,\n childToolCallId: string,\n description: string,\n displayNameResolver: (name: string) => string,\n): void {\n if (!parentTurn || !parentToolCallId) return\n\n const toolCalls = \"toolCalls\" in parentTurn ? parentTurn.toolCalls : parentTurn.tool_calls\n const blocks = parentTurn.blocks\n\n const displayName =\n toolCalls.find((call) => call.id === parentToolCallId)?.display_name ||\n displayNameResolver(\"Agent\")\n let found = false\n for (let i = 0; i < toolCalls.length; i++) {\n if (toolCalls[i].id !== parentToolCallId) continue\n toolCalls[i] = {\n ...toolCalls[i],\n tool_name: \"Agent\",\n display_name: displayName || toolCalls[i].display_name,\n }\n found = true\n break\n }\n if (!found) {\n toolCalls.push({\n id: parentToolCallId,\n tool_name: \"Agent\",\n display_name: displayName,\n arguments: \"\",\n status: \"pending\",\n })\n }\n\n let blockFound = false\n for (let i = 0; i < blocks.length; i++) {\n if (blocks[i].type !== \"tool_use\" || blocks[i].tool_call_id !== parentToolCallId) continue\n blockFound = true\n break\n }\n if (!blockFound) {\n blocks.push({\n type: \"tool_use\",\n content: \"\",\n tool_call_id: parentToolCallId,\n tool_name: \"Agent\",\n display_name: displayName,\n })\n }\n\n setToolCallStatus(parentTurn, parentToolCallId, \"awaiting_answer\", null, {\n child_loop_name: childLoopName,\n child_tool_call_id: childToolCallId,\n description: description || null,\n })\n}\n\nexport function applyChildResultToParent(\n parentTurn: TurnState | TurnProjection | null | undefined,\n parentToolCallId: string,\n result: string,\n): void {\n if (!parentTurn || !parentToolCallId) return\n const toolCalls = \"toolCalls\" in parentTurn ? parentTurn.toolCalls : parentTurn.tool_calls\n const call = toolCalls.find((item) => item.id === parentToolCallId)\n if (!call) return\n setToolCallStatus(parentTurn, parentToolCallId, \"done\", result, null)\n const block = parentTurn.blocks.find(\n (item) => item.type === \"tool_result\" && item.tool_call_id === parentToolCallId,\n )\n if (block) {\n block.content = result\n } else {\n parentTurn.blocks.push({\n type: \"tool_result\",\n content: result,\n tool_call_id: parentToolCallId,\n tool_name: call.tool_name,\n display_name: call.display_name,\n })\n }\n}\n\nfunction askUserResultFromPausePayload(\n pauseToolData: Record<string, unknown>,\n sourceLoop: { loop_name: string; description: string } | null,\n): string {\n const args =\n typeof pauseToolData.arguments === \"object\" && pauseToolData.arguments !== null\n ? (pauseToolData.arguments as Record<string, unknown>)\n : {}\n const payload: Record<string, unknown> = { questions: args.questions ?? [] }\n if (sourceLoop) payload.source_loop = sourceLoop\n return JSON.stringify(payload)\n}\n\nexport function sourceLoopFor(\n loopId: string,\n loopDescriptions: Map<string, string>,\n): { loop_name: string; description: string } | null {\n if (loopId === \"root\") return null\n const description = loopDescriptions.get(loopId)\n if (!description) return null\n return { loop_name: loopId, description }\n}\n\n/** 本轮交付给用户的成果:工作区里的文件,或可以打开的网址。 */\nexport interface FinalArtifact {\n kind: \"file\" | \"link\"\n /** file 是文件路径(相对工作目录或容器内绝对路径);link 是 http/https 网址。 */\n target: string\n label: string\n}\n\nconst MAX_FINAL_ARTIFACTS = 20\n\nfunction normalizeFinalArtifacts(raw: unknown): FinalArtifact[] {\n if (!Array.isArray(raw)) return []\n const artifacts: FinalArtifact[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (typeof item !== \"object\" || item === null) continue\n const record = item as Record<string, unknown>\n const target = String(record.target ?? \"\").trim()\n if (!target || seen.has(target)) continue\n const isLink = /^https?:\\/\\//i.test(target)\n if (!isLink && target.split(\"/\").includes(\"..\")) continue\n seen.add(target)\n artifacts.push({\n kind: isLink ? \"link\" : \"file\",\n target,\n label: String(record.label ?? \"\").trim(),\n })\n if (artifacts.length === MAX_FINAL_ARTIFACTS) break\n }\n return artifacts\n}\n\n/**\n * Shared by the streaming and history channels — both must decide \"is this\n * follow-up showable\" identically. Returns null when there is nothing to show.\n */\nexport function normalizePostChatFollowup(\n data: Record<string, unknown>,\n assistantEntryId: string,\n): {\n assistant_entry_id: string\n recaption: string\n suggestions: string[]\n final_artifacts: FinalArtifact[]\n feedback_eligible: boolean\n feedback_scope: \"latest_result\"\n} | null {\n const raw = data.suggestions\n const suggestions: string[] = []\n if (Array.isArray(raw)) {\n for (const value of raw) {\n if (typeof value !== \"string\") continue\n const text = value.trim()\n if (text && !suggestions.includes(text)) suggestions.push(text)\n }\n }\n const recaption = String(data.recaption ?? \"\")\n const finalArtifacts = normalizeFinalArtifacts(data.final_artifacts)\n const feedbackEligible = data.feedback_eligible === true\n if (suggestions.length === 0 && !recaption && finalArtifacts.length === 0 && !feedbackEligible)\n return null\n return {\n assistant_entry_id: assistantEntryId,\n recaption,\n suggestions: suggestions.slice(0, 3),\n final_artifacts: finalArtifacts,\n feedback_eligible: feedbackEligible,\n feedback_scope: \"latest_result\",\n }\n}\n\nexport function normalizeChildPause(\n pausePayload: Record<string, unknown>,\n): {\n pauseToolData: Record<string, unknown>\n childLoopName: string\n childToolCallId: string\n description: string\n} {\n const rawPtd = pausePayload.pause_tool_data\n const pauseToolData: Record<string, unknown> =\n typeof rawPtd === \"object\" && rawPtd !== null\n ? { ...(rawPtd as Record<string, unknown>) }\n : { ...pausePayload }\n\n let sourceLoop = pauseToolData.source_loop as Record<string, unknown> | undefined\n if (typeof sourceLoop !== \"object\" || sourceLoop === null) {\n sourceLoop = pausePayload.source_loop as Record<string, unknown> | undefined\n }\n\n const childLoopName =\n String(pausePayload.child_loop_name ?? \"\") ||\n (typeof sourceLoop === \"object\" && sourceLoop ? String(sourceLoop.name ?? \"\") : \"\")\n\n const childToolCallId =\n String(\n pausePayload.child_pause_tool_call_id ?? pauseToolData.tool_call_id ?? \"\",\n )\n\n const description =\n typeof sourceLoop === \"object\" && sourceLoop ? String(sourceLoop.description ?? \"\") : \"\"\n\n if (childLoopName && description) {\n pauseToolData.source_loop = { name: childLoopName, description }\n }\n\n return { pauseToolData, childLoopName, childToolCallId, description }\n}\n\n/** Copy only the trusted protocol field, never evidence embedded in output. */\nexport function attachToolEvidence(call: ToolCallProjection | undefined, evidence: unknown): void {\n if (!call) return\n call.evidence = (call.status === \"done\" || call.status === \"error\") && Array.isArray(evidence) ? evidence as ToolEvidence[] : undefined\n}\n","import type { ToolEvidence, ContentBlock, PendingQuestionRef, ToolBridgeContent } from \"./projection\"\nimport type { ContextProjectionData } from \"./context\"\n\nexport interface TextContentPart {\n type: \"text\"\n text: string\n}\n\nexport interface ImageUrlContentPart {\n type: \"image_url\"\n image_url: {\n url: string\n source_path?: string\n width?: number\n height?: number\n }\n}\n\nexport interface FileContentPart {\n type: \"file\"\n name: string\n data: string\n}\n\nexport type MessageContentPart = TextContentPart | ImageUrlContentPart | FileContentPart\nexport type MessageContent = string | MessageContentPart[]\n\n/** 固定流程解释执行落史的一步(workflow:run 专用):刷新后时间线从这里重建。 */\nexport interface WorkflowStepInfo {\n step_id: string\n desc?: string\n step_kind?: string // agent | step | parallel | choice | end\n status?: string // done | error | cancelled\n output?: string\n /** 直播时的先后:步骤宣告与它的输出/失败行(条目按终态落盘,重建按这两个值排回去) */\n seq?: number\n log_seq?: number\n}\n\nexport interface ToolCallInfo {\n evidence?: ToolEvidence[]\n id: string\n name: string\n display_name?: string | null\n arguments: string\n result?: unknown\n status?: \"pending\" | \"done\" | \"error\" | \"cancelled\" | \"awaiting_answer\"\n duration_ms?: number | null\n pending_question_ref?: PendingQuestionRef | null\n workflow_steps?: WorkflowStepInfo[] | null\n}\n\nexport type { ToolBridgeContent }\n\n/** Derive tool status from the result content string. */\nexport function inferToolStatus(\n resultStr: string,\n): \"done\" | \"error\" | \"cancelled\" {\n if (resultStr.includes('\"Cancelled by user\"')) return \"cancelled\"\n try {\n const parsed = JSON.parse(resultStr)\n if (typeof parsed === \"object\" && parsed !== null) {\n if (\"error\" in parsed && parsed.error) return \"error\"\n const nested = parsed.result\n if (typeof nested === \"object\" && nested !== null && \"error\" in nested && nested.error) {\n return \"error\"\n }\n }\n } catch {\n }\n return \"done\"\n}\n\nexport interface MemoryRefInfo {\n id: number\n content_preview: string\n skill_name?: string | null\n}\n\nexport interface CompactionInfo {\n compaction_id: string\n summary_preview?: string | null\n summary_full?: string | null\n archived_count?: number | null\n archived_files?: ArchivedFileInfo[] | null\n archived_tool_calls?: ArchivedToolCallInfo[] | null\n tokens_before?: number | null\n tokens_after?: number | null\n saved_ratio?: number | null\n trigger?: \"auto\" | \"manual\" | \"forced_retry\" | null\n failure_reason?: string | null\n fallback_applied?: boolean | null\n}\n\nexport interface ArchivedFileInfo {\n tool_name?: string | null\n filename?: string | null\n relative_path?: string | null\n size_bytes?: number | null\n}\n\nexport interface ArchivedToolCallInfo {\n tool_call_id?: string | null\n tool_name?: string | null\n archive_path?: string | null\n replacement_content?: string | null\n entry_id?: string | null\n}\n\nexport interface ChatMessage {\n role: \"user\" | \"assistant\" | \"tool\" | \"error\"\n content: MessageContent\n reasoning?: string\n tool_calls?: ToolCallInfo[]\n status?: \"streaming\" | \"completed\" | \"paused\" | \"failed\" | \"interrupted\"\n duration_ms?: number\n timestamp?: string\n entry_id?: string\n client_request_id?: string\n /** Stable React key retained when an optimistic user message is confirmed. */\n render_id?: string\n parent_id?: string | null\n loop_name?: string\n /** Entry kind from backend -- present for non-message entries like mode changes. */\n kind?: string\n /** Memory references injected into this turn's context */\n refs?: import(\"./plugin-refs\").MessageRef[]\n context_attachments?: import(\"./context-attachments\").ContextAttachment[]\n topic_asset_refs?: import(\"./topic-assets\").TopicAssetRef[]\n memory_refs?: MemoryRefInfo[]\n /** Raw projection blocks for block-level UI rendering. */\n blocks?: ContentBlock[]\n /** Compaction metadata for compaction turns. */\n compaction?: CompactionInfo\n /** Sourced Context metadata for rendering or headless consumers. */\n context?: ContextProjectionData\n}\n","import { inferToolStatus } from \"../../schemas/message\"\nimport type {\n ContentBlock,\n MemoryRef,\n ToolCallProjection,\n TurnProjection,\n} from \"../../schemas/projection\"\n\nexport interface TurnState {\n turnId: string\n loopId: string\n role: \"user\" | \"assistant\" | \"system\"\n model: string | null\n startedAt: number\n contextWindow: number\n blocks: ContentBlock[]\n toolCalls: ToolCallProjection[]\n usage: Record<string, unknown> | null\n responseDone: boolean\n firstTokenMs: number | null\n streamDurationMs: number | null\n firstTokenDeliveryMs: number | null\n /** 生产者上报的模型请求时序;缺失时保持 null,不用浏览器时间补(#2581 A1/I1)。 */\n modelStartedAt: string | null\n modelDurationMs: number | null\n modelStartedAtReported: boolean\n memoryRefs: MemoryRef[] | null\n parentForkToolCallId: string | null\n}\n\nexport function createTurnState(\n turnId: string,\n loopId: string,\n opts: {\n model?: string | null\n contextWindow?: number\n memoryRefs?: MemoryRef[] | null\n } = {},\n): TurnState {\n return {\n turnId,\n loopId,\n role: \"assistant\",\n model: opts.model ?? null,\n startedAt: Date.now(),\n contextWindow: opts.contextWindow ?? 0,\n blocks: [],\n toolCalls: [],\n usage: null,\n responseDone: false,\n firstTokenMs: null,\n streamDurationMs: null,\n firstTokenDeliveryMs: null,\n modelStartedAt: null,\n modelDurationMs: null,\n modelStartedAtReported: false,\n memoryRefs: opts.memoryRefs ?? null,\n parentForkToolCallId: null,\n }\n}\n\nexport function snapshot(\n state: TurnState,\n sequence: number,\n status: TurnProjection[\"status\"],\n): TurnProjection {\n return {\n id: state.turnId,\n sequence,\n turn_id: state.turnId,\n loop_id: state.loopId,\n kind: \"message\",\n role: state.role,\n status,\n blocks: [...state.blocks],\n tool_calls: [...state.toolCalls],\n model: state.model,\n usage: state.usage ? { ...state.usage } : null,\n duration_ms: state.modelDurationMs,\n first_token_ms: state.firstTokenMs,\n stream_duration_ms: state.streamDurationMs,\n first_token_delivery_ms: state.firstTokenDeliveryMs,\n started_at: state.modelStartedAt,\n // 未上报时不伪造服务器起点;浏览器时钟不能与服务器时钟混用。\n has_reported_timing: state.modelStartedAtReported,\n context_window: state.contextWindow,\n memory_refs: state.memoryRefs,\n parent_fork_tool_call_id: state.parentForkToolCallId,\n }\n}\n\nexport const PAUSE_TOOL_NAMES = new Set([\"AskUserQuestion\", \"ExitPlanMode\"])\n\nexport function toolStatusFromResult(result: unknown): ToolCallProjection[\"status\"] {\n const text =\n typeof result === \"string\"\n ? result\n : Array.isArray(result)\n ? result\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" && p !== null && p.type === \"text\",\n )\n .map((p) => p.text ?? \"\")\n .join(\"\\n\")\n : String(result ?? \"\")\n return inferToolStatus(text)\n}\n","export type ContextAction = \"published\" | \"retained\" | \"removed\"\n\n/** Safe display-source metadata retained for headless consumers. */\nexport type ContextSourceInfo = Record<string, unknown>\n\nexport interface ContextProjectionData {\n context_kind: string\n context_key: string\n context_name: string\n context_order: number\n context_action: ContextAction\n context_revision: string\n display_title?: string | null\n display_summary?: string | null\n sources: ContextSourceInfo[]\n}\n\nexport interface ContextProjectionFields {\n context_kind?: string | null\n context_key?: string | null\n context_name?: string | null\n context_order?: number | null\n context_action?: ContextAction | null\n context_revision?: string | null\n display_title?: string | null\n display_summary?: string | null\n sources?: ContextSourceInfo[] | null\n}\n\nexport interface ContextDisplayState {\n title: string\n summary: string\n detail: string\n isRemoved: boolean\n}\n\nexport interface ContextGroupDisplayState {\n title: string\n summary: string\n count: number\n}\n\nconst BUILTIN_CONTEXT_TITLES: Record<string, string> = {\n \"agent-instructions\": \"项目说明\",\n \"skill-catalog\": \"可用能力\",\n \"runtime-context\": \"当前工作环境\",\n \"workspace-context\": \"当前工作区环境\",\n}\n\nconst BUILTIN_CONTEXT_DETAILS: Record<string, string> = {\n \"agent-instructions\": \"这些说明会帮助智能体理解当前项目和工作要求。\",\n \"skill-catalog\": \"这些能力会帮助智能体选择合适的方式完成任务。\",\n \"runtime-context\": \"这些信息会帮助智能体了解当前文件夹和运行条件。\",\n \"workspace-context\": \"这些信息会帮助智能体了解当前工作目录、文件和运行环境。\",\n}\n\nfunction nonEmptyString(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() ? value.trim() : null\n}\n\nexport function contextProjectionData(\n fields: ContextProjectionFields,\n): ContextProjectionData | null {\n const contextKind = nonEmptyString(fields.context_kind)\n const contextKey = nonEmptyString(fields.context_key)\n const contextName = nonEmptyString(fields.context_name)\n const contextRevision = nonEmptyString(fields.context_revision)\n if (\n !contextKind ||\n !contextKey ||\n !contextName ||\n !contextRevision ||\n typeof fields.context_order !== \"number\" ||\n !Number.isFinite(fields.context_order) ||\n !fields.context_action\n ) {\n return null\n }\n return {\n context_kind: contextKind,\n context_key: contextKey,\n context_name: contextName,\n context_order: fields.context_order,\n context_action: fields.context_action,\n context_revision: contextRevision,\n display_title: nonEmptyString(fields.display_title),\n display_summary: nonEmptyString(fields.display_summary),\n sources: Array.isArray(fields.sources) ? fields.sources : [],\n }\n}\n\n/** The single status-to-display mapping used by both React chat surfaces. */\nexport function getContextDisplayState(\n context: ContextProjectionData,\n): ContextDisplayState {\n const title =\n nonEmptyString(context.display_title) ??\n BUILTIN_CONTEXT_TITLES[context.context_kind] ??\n \"对话背景\"\n const isRemoved = context.context_action === \"removed\"\n const summary =\n nonEmptyString(context.display_summary) ??\n (isRemoved\n ? \"已停止用于后续对话\"\n : context.context_action === \"retained\"\n ? \"继续用于后续对话\"\n : context.context_kind === \"agent-instructions\"\n ? \"已更新本次对话使用的项目说明\"\n : context.context_kind === \"skill-catalog\"\n ? \"已更新本次可用能力\"\n : context.context_kind === \"runtime-context\"\n ? \"已更新本次工作环境\"\n : context.context_kind === \"workspace-context\"\n ? \"已更新本次工作区环境\"\n : \"已更新本次对话背景\")\n const detail = isRemoved\n ? `${title}已不再用于后续对话。`\n : (BUILTIN_CONTEXT_DETAILS[context.context_kind] ??\n \"这些信息会帮助智能体理解当前任务。\")\n return { title, summary, detail, isRemoved }\n}\n\n/**\n * 把一段渲染序列里连续的 Context 归成组。\n *\n * 入参是序列里每一项的 context kind,非 Context 项传 null;返回每一段连续\n * Context 的下标数组。纯下标运算,不认识任何 UI 类型,所以调试日志、Lite 视图\n * 和 SDK 卡片可以共用同一份分组判定,各自只管排版。\n */\nexport function groupAdjacentContextRuns(\n kinds: readonly (string | null)[],\n): readonly (readonly number[])[] {\n const runs: number[][] = []\n let current: number[] | null = null\n kinds.forEach((kind, index) => {\n if (kind === null) {\n current = null\n return\n }\n if (current === null) {\n current = []\n runs.push(current)\n }\n current.push(index)\n })\n return runs\n}\n\n/** 折叠行的文案。展开后才逐条显示各自的标题与状态。 */\nexport function getContextGroupDisplayState(\n contexts: readonly ContextProjectionData[],\n): ContextGroupDisplayState {\n const count = contexts.length\n if (count === 1) {\n const single = getContextDisplayState(contexts[0])\n return { title: single.title, summary: single.summary, count }\n }\n const removed = contexts.filter(\n (context) => context.context_action === \"removed\",\n ).length\n const updated = count - removed\n const parts: string[] = []\n if (updated > 0) parts.push(`${updated} 项已更新`)\n if (removed > 0) parts.push(`${removed} 项已停用`)\n return {\n title: \"对话背景\",\n summary: parts.join(\" · \") || `${count} 项`,\n count,\n }\n}\n","import { contextProjectionData } from \"../../schemas/context\"\nimport type { TurnProjection } from \"../../schemas/projection\"\nimport { isRecord } from \"../type-guards\"\n\n/** Build one Context turn from the canonical entry used by live and history paths. */\nexport function buildContextTurn(\n entry: Record<string, unknown>,\n sequence: number,\n): TurnProjection | null {\n if (entry.kind !== \"context\" || !isRecord(entry.source) || !isRecord(entry.data)) {\n return null\n }\n const display = isRecord(entry.data.display) ? entry.data.display : {}\n const message = isRecord(entry.message) ? entry.message : {}\n const context = contextProjectionData({\n context_kind: typeof entry.source.kind === \"string\" ? entry.source.kind : null,\n context_key: typeof entry.source.key === \"string\" ? entry.source.key : null,\n context_name: typeof entry.data.contribution_name === \"string\" ? entry.data.contribution_name : null,\n context_order: typeof entry.data.order === \"number\" ? entry.data.order : null,\n context_action:\n entry.data.action === \"published\" || entry.data.action === \"retained\" || entry.data.action === \"removed\"\n ? entry.data.action\n : null,\n context_revision: typeof entry.data.revision === \"string\" ? entry.data.revision : null,\n display_title: typeof display.title === \"string\" ? display.title : null,\n display_summary: typeof display.summary === \"string\" ? display.summary : null,\n sources: Array.isArray(display.sources) ? display.sources.filter(isRecord) : [],\n })\n if (!context) return null\n const turnId = typeof entry.id === \"string\" && entry.id ? entry.id : `context-${sequence}`\n return {\n id: turnId,\n sequence,\n turn_id: turnId,\n loop_id: typeof entry.loop_name === \"string\" && entry.loop_name ? entry.loop_name : \"root\",\n kind: \"context\",\n role: \"system\",\n status: \"completed\",\n blocks: [],\n tool_calls: [],\n model: null,\n usage: null,\n duration_ms: 0,\n context_content: Object.hasOwn(message, \"content\") ? message.content : null,\n ...context,\n }\n}\n","import { normalizeContextAttachments } from \"../../schemas/context-attachments\"\nimport { normalizeMessageRefs } from \"../../schemas/plugin-refs\"\nimport { normalizeTopicAssetRefs } from \"../../schemas/topic-assets\"\nimport type { MemoryRef, RunTiming, TurnProjection } from \"../../schemas/projection\"\nimport {\n attachToolEvidence,\n applyAskUserPauseToTurn,\n applyChildPauseToParent,\n applyChildResultToParent,\n appendTextBlock,\n appendToolCallArguments,\n appendToolResultDelta,\n applyToolResult,\n buildCompactionTurn,\n buildMarkerTurn,\n buildSystemNotificationBlock,\n buildSystemNotificationTurn,\n type ChildPauseInfo,\n normalizeChildPause,\n normalizePostChatFollowup,\n restoreAnsweredAskUserJson,\n setToolCallStatus,\n sourceLoopFor,\n upsertToolCall,\n} from \"./helpers\"\nimport { isRecord } from \"../type-guards\"\nimport { createTurnState, PAUSE_TOOL_NAMES, snapshot, toolStatusFromResult, type TurnState } from \"./state\"\nimport { buildContextTurn } from \"./context\"\n\nfunction backgroundTaskStatus(payload: Record<string, unknown>): \"done\" | \"error\" {\n const tasks = Array.isArray(payload.tasks) ? payload.tasks : []\n return tasks.some((task) => isRecord(task) && (\n [\"failed\", \"cancelled\", \"lost\"].includes(String(task.status)) ||\n (typeof task.exit_code === \"number\" && task.exit_code !== 0)\n )) ? \"error\" : \"done\"\n}\n\nexport interface RawEvent {\n log_seq?: number\n step_log_seq?: number\n delta_seq?: number\n type: string\n payload: Record<string, unknown>\n}\n\n/** 在任何事件处理前确认 Socket.IO 批次已到达客户端。 */\nexport function acknowledgeTurnEvents(acknowledge?: () => void): void {\n acknowledge?.()\n}\n\nexport type ProjectionUpdate =\n | { kind: \"upsert\"; turn: TurnProjection }\n | {\n kind: \"workspace_changed\"\n loopId: string\n toolCallId?: string\n toolName?: string\n workspacePath?: string\n /** 本次工具改动的文件(相对工作区)。缺省表示不知道具体文件,按整体变化处理。 */\n paths?: string[]\n }\n\n/** 是否包含会改变聊天运行生命周期的事件。纯观测/整理事件不启动新一轮。 */\nexport function hasChatRunEvent(events: RawEvent[]): boolean {\n return events.some(\n (event) =>\n event.type !== \"llm:first_token:delivered\" &&\n event.type !== \"session:post_chat_followup\" &&\n event.type !== \"loop:tool_bridge\" &&\n !event.type.startsWith(\"compaction:\"),\n )\n}\n\n/**\n * 缺失 chat:end 时的终态兜底。只有被投影接受到当前 assistant turn 的 followup\n * 才能结束流式态;陈旧 followup 或其后已有新轮事件时均返回 false。\n */\nexport function acceptedPostChatFollowupCompletesLatestRun(\n events: RawEvent[],\n updates: ProjectionUpdate[],\n): boolean {\n const acceptedAssistantEntryIds = new Set(\n updates.flatMap((update) => {\n if (update.kind !== \"upsert\") return []\n const followup = update.turn.post_chat_followup\n return followup?.assistant_entry_id ? [followup.assistant_entry_id] : []\n }),\n )\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index]\n if (event?.type !== \"session:post_chat_followup\") continue\n const assistantEntryId = String(event.payload.assistant_entry_id ?? \"\")\n return (\n acceptedAssistantEntryIds.has(assistantEntryId) &&\n !hasChatRunEvent(events.slice(index + 1))\n )\n }\n return false\n}\n\ntype FollowupTurn = TurnProjection\n\nfunction isConversationTurn(turn: TurnProjection): boolean {\n return (\n (turn.role === \"user\" || turn.role === \"assistant\") &&\n (turn.kind ?? \"message\") === \"message\" &&\n !turn.blocks.some(\n (block) =>\n block.type === \"mode_change\" ||\n block.type === \"plan_status\" ||\n block.type === \"ask_user_answer\",\n )\n )\n}\n\nfunction completedResponseText(content: unknown): string {\n if (typeof content === \"string\") return content\n if (!Array.isArray(content)) return content == null ? \"\" : String(content)\n return content\n .filter(\n (part): part is Record<string, unknown> =>\n typeof part === \"object\" && part !== null && !Array.isArray(part),\n )\n .filter((part) => part.type === \"text\")\n .map((part) => String(part.text ?? \"\"))\n .join(\"\")\n}\n\nfunction replaceTextContent(state: TurnState, content: string): void {\n const currentContent = state.blocks\n .filter((block) => block.type === \"text\")\n .map((block) => String(block.content ?? \"\"))\n .join(\"\")\n if (currentContent === content) return\n const replacement = { type: \"text\" as const, content }\n const blocks: TurnState[\"blocks\"] = []\n let inserted = false\n for (const block of state.blocks) {\n if (block.type === \"text\") {\n if (content && !inserted) {\n blocks.push(replacement)\n inserted = true\n }\n continue\n }\n blocks.push(block)\n }\n if (content && !inserted) {\n const toolIndex = blocks.findIndex((block) => block.type === \"tool_use\")\n blocks.splice(toolIndex < 0 ? blocks.length : toolIndex, 0, replacement)\n }\n state.blocks = blocks\n}\n\nfunction applyResponseBlockOrder(state: TurnState, value: unknown): boolean {\n if (!Array.isArray(value)) return false\n const ordered: TurnState[\"blocks\"] = []\n for (const item of value) {\n if (typeof item !== \"object\" || item === null || Array.isArray(item)) continue\n const block = item as Record<string, unknown>\n if (block.type === \"text\" || block.type === \"thinking\") {\n const content = String(block[block.type] ?? \"\")\n if (content) ordered.push({ type: block.type, content })\n continue\n }\n if (block.type !== \"tool_call\") continue\n const toolCallId = String(block.id ?? \"\")\n const toolBlock = state.blocks.find(\n (candidate) =>\n candidate.type === \"tool_use\" && candidate.tool_call_id === toolCallId,\n )\n if (toolBlock) ordered.push(toolBlock)\n }\n if (ordered.length === 0 && value.length > 0) return false\n const unrelatedBlocks = state.blocks.filter(\n (block) =>\n block.type !== \"text\" && block.type !== \"thinking\" && block.type !== \"tool_use\",\n )\n state.blocks = [...ordered, ...unrelatedBlocks]\n return true\n}\n\nexport class ClientProjectionBuilder {\n private activeTurns = new Map<string, TurnState>()\n private lastTurnIds = new Map<string, string>()\n private latestTurns = new Map<string, TurnProjection>()\n private turnsById = new Map<string, TurnProjection>()\n private loopDescriptions = new Map<string, string>()\n private activeSubagentRuns = new Map<string, { runId: string; startedAt: string }>()\n private pendingChildPauses = new Map<string, ChildPauseInfo>()\n private answeredChildParents = new Map<string, { parentLoopName: string; parentToolCallId: string }>()\n private pendingMemoryRefs = new Map<string, { turnId: string; refs: MemoryRef[] }>()\n private activeCompactions = new Map<string, Record<string, unknown>>()\n private failedCompactions = new Map<string, Record<string, unknown>>()\n private seq = 0\n private syntheticCounter = 0\n private displayNameResolver: (name: string) => string\n\n constructor(displayNameResolver?: (name: string) => string) {\n this.displayNameResolver = displayNameResolver ?? ((n) => n)\n }\n\n processBatch(events: RawEvent[]): ProjectionUpdate[] {\n const lastUpsertByTurn = new Map<string, ProjectionUpdate & { kind: \"upsert\" }>()\n const nonUpserts: ProjectionUpdate[] = []\n for (const event of events) {\n const updates = this.processEvent(event)\n if (!updates) continue\n for (const u of updates) {\n if (u.kind === \"upsert\") {\n lastUpsertByTurn.set(u.turn.turn_id, u)\n } else {\n nonUpserts.push(u)\n }\n }\n }\n return [...nonUpserts, ...lastUpsertByTurn.values()]\n }\n\n processEvent(event: RawEvent): ProjectionUpdate[] | null {\n const payload = event.payload\n const loopId = String(payload.loop_name ?? \"root\")\n\n switch (event.type) {\n case \"memory:inject:done\":\n return this.onMemoryInject(loopId, payload)\n case \"memory:inject:none\":\n return null\n case \"context:entry\":\n return this.onContextEntry(payload)\n case \"loop:turn\":\n return this.onLoopTurn(loopId, payload)\n case \"mode:change\":\n return this.onModeChange(loopId, payload)\n case \"plan:status:update\":\n return this.onPlanStatusUpdate(loopId, payload)\n case \"workspace:changed\":\n return this.onWorkspaceChanged(loopId, payload)\n case \"agent:start\":\n return this.onAgentStart(loopId, payload)\n case \"bg:started\":\n return this.onBgStarted(loopId, payload)\n case \"bg:tasks_completed\":\n return this.onBgTasksCompleted(loopId, payload)\n case \"loop:ask_user_answer\":\n return this.onAskUserAnswer(loopId, payload)\n case \"user:message\":\n return this.onUserMessage(loopId, payload)\n case \"session:post_chat_followup\":\n return this.onPostChatFollowup(payload)\n }\n\n if (event.type.startsWith(\"compaction:\"))\n return this.onCompaction(event.type, loopId, payload)\n\n if (event.type === \"llm:first_token:delivered\") {\n const targetTurnId = String(payload.turn_id ?? \"\")\n const active = this.activeTurns.get(loopId)\n if (active && (!targetTurnId || active.turnId === targetTurnId)) {\n this.applyFirstTokenDelivery(active, payload)\n return this.syncPatch(active)\n }\n const latest = targetTurnId\n ? this.turnsById.get(targetTurnId)\n : this.latestTurns.get(loopId)\n const duration = payload.first_token_delivery_ms\n if (!latest || latest.role !== \"assistant\" || typeof duration !== \"number\" || duration < 0) {\n return null\n }\n const turn = { ...latest, first_token_delivery_ms: duration }\n this.turnsById.set(turn.turn_id, turn)\n if (this.latestTurns.get(loopId)?.turn_id === turn.turn_id) {\n this.latestTurns.set(loopId, turn)\n }\n return [{ kind: \"upsert\", turn }]\n }\n\n const state = this.activeTurns.get(loopId)\n if (!state) {\n if (event.type === \"chat:end\") {\n this.pendingMemoryRefs.delete(loopId)\n return null\n }\n if (event.type === \"agent:end\") return this.onAgentEnd(null, loopId, payload)\n return null\n }\n\n switch (event.type) {\n case \"llm:stream:reset\":\n state.blocks = []\n state.toolCalls = []\n state.usage = null\n state.responseDone = false\n state.firstTokenMs = null\n state.streamDurationMs = null\n state.firstTokenDeliveryMs = null\n return this.syncPatch(state)\n case \"llm:thinking:delta\":\n this.applyFirstTokenDelivery(state, payload)\n return this.onDelta(state, \"thinking\", \"\", String(payload.content ?? \"\"))\n case \"llm:content:delta\":\n this.applyFirstTokenDelivery(state, payload)\n return this.onDelta(state, \"text\", \"\", String(payload.content ?? \"\"))\n case \"llm:content:complete\":\n replaceTextContent(state, String(payload.content ?? \"\"))\n return this.syncPatch(state)\n case \"llm:content:done\":\n this.applyStreamTiming(state, payload)\n return this.syncPatch(state)\n case \"llm:tool_call:created\":\n this.applyFirstTokenDelivery(state, payload)\n return this.onToolCallCreated(state, payload)\n case \"llm:tool_call:arguments:delta\":\n this.applyFirstTokenDelivery(state, payload)\n return this.onToolCallArgumentsDelta(state, payload)\n case \"llm:response:done\":\n return this.onResponseDone(state, loopId, payload)\n case \"tool:result:delta\":\n return this.onToolResultDelta(state, payload)\n case \"tool:result:done\":\n return this.onToolResultDone(state, loopId, payload)\n case \"loop:tool_ui\":\n return this.onToolUi(state, payload)\n case \"loop:tool_bridge\":\n return this.onToolBridge(state, payload)\n case \"tool:approval:required\":\n return this.onToolApprovalRequired(state, payload)\n case \"loop:child_pause\":\n return this.onChildPause(state, loopId, payload)\n case \"chat:end\":\n return this.onChatEnd(state, loopId, payload)\n case \"agent:end\":\n return this.onAgentEnd(state, loopId, payload)\n default:\n return null\n }\n }\n\n reset(): void {\n this.activeTurns.clear()\n this.lastTurnIds.clear()\n this.latestTurns.clear()\n this.turnsById.clear()\n this.loopDescriptions.clear()\n this.activeSubagentRuns.clear()\n this.pendingChildPauses.clear()\n this.answeredChildParents.clear()\n this.pendingMemoryRefs.clear()\n this.activeCompactions.clear()\n this.failedCompactions.clear()\n this.seq = 0\n this.syntheticCounter = 0\n }\n\n /** A durable snapshot supersedes only this turn's temporary overlay. */\n acceptDurableTurn(turn: TurnProjection): void {\n this.seedSequence(turn.sequence)\n if (turn.kind === \"compaction\") {\n this.turnsById.set(turn.turn_id, turn)\n if (turn.status !== \"streaming\") this.activeCompactions.delete(turn.compaction_id ?? \"\")\n return\n }\n if (!isConversationTurn(turn)) return\n const active = this.activeTurns.get(turn.loop_id)\n if (active?.turnId === turn.turn_id) this.activeTurns.delete(turn.loop_id)\n this.turnsById.set(turn.turn_id, turn)\n const latest = this.latestTurns.get(turn.loop_id)\n if ((!active || active.turnId === turn.turn_id) &&\n (!latest || latest.turn_id === turn.turn_id || turn.sequence >= latest.sequence)) {\n this.latestTurns.set(turn.loop_id, turn)\n this.lastTurnIds.set(turn.loop_id, turn.turn_id)\n }\n }\n\n seedSequence(maxSeq: number): void {\n if (maxSeq > this.seq) {\n this.seq = maxSeq\n }\n }\n\n _seedTurns(turns: TurnProjection[]): void {\n const latestTurns = new Map<string, TurnProjection>()\n const turnsById = new Map<string, TurnProjection>()\n for (const turn of turns) {\n this.seedSequence(turn.sequence)\n if (turn.kind === \"compaction\") turnsById.set(turn.turn_id, turn)\n if (!isConversationTurn(turn)) continue\n turnsById.set(turn.turn_id, turn)\n const current = latestTurns.get(turn.loop_id)\n if (!current || turn.sequence >= current.sequence) {\n latestTurns.set(turn.loop_id, turn)\n }\n }\n this.latestTurns = latestTurns\n this.turnsById = turnsById\n }\n\n\n private onMemoryInject(\n loopId: string,\n payload: Record<string, unknown>,\n ): null {\n const refs = payload.memory_refs\n const turnId = String(payload.turn_id ?? \"\")\n if (Array.isArray(refs) && refs.length > 0) {\n this.pendingMemoryRefs.set(loopId, {\n turnId,\n refs: refs.map((r: Record<string, unknown>) => ({\n id: Number(r.id),\n content_preview: String(r.content_preview ?? \"\"),\n skill_name: r.skill_name != null ? String(r.skill_name) : null,\n })),\n })\n }\n return null\n }\n\n private onContextEntry(\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n if (!isRecord(payload.entry)) return null\n const turn = buildContextTurn(payload.entry, this.nextSeq())\n return turn ? [{ kind: \"upsert\", turn }] : null\n }\n\n private onLoopTurn(\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] {\n let turnId = String(payload.turn_id ?? this.nextTurnId(`turn:${loopId}`))\n let memoryRefs: MemoryRef[] | null = null\n\n const pending = this.pendingMemoryRefs.get(loopId)\n if (pending && (!pending.turnId || pending.turnId === turnId)) {\n this.pendingMemoryRefs.delete(loopId)\n if (pending.turnId) turnId = pending.turnId\n memoryRefs = pending.refs\n }\n\n const rawCw = payload.context_window\n const contextWindow =\n typeof rawCw === \"number\" && rawCw > 0 ? Math.trunc(rawCw) : 0\n\n const state = createTurnState(turnId, loopId, {\n model: optStr(payload.model),\n contextWindow,\n memoryRefs,\n })\n\n this.activeTurns.set(loopId, state)\n this.lastTurnIds.set(loopId, turnId)\n\n const turn = snapshot(state, this.nextSeq(), \"streaming\")\n this.latestTurns.set(loopId, turn)\n this.turnsById.set(turn.turn_id, turn)\n return [{ kind: \"upsert\", turn }]\n }\n\n private onModeChange(\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] {\n const content: Record<string, string> = {}\n if (payload.from != null && payload.from !== \"\") content.from = String(payload.from)\n if (payload.to != null && payload.to !== \"\") content.to = String(payload.to)\n const turn = buildMarkerTurn(\n this.nextSeq(),\n optStr(payload.entry_id) ?? this.nextTurnId(\"mode_change\"),\n loopId,\n \"mode_change\",\n content,\n )\n return [{ kind: \"upsert\", turn }]\n }\n\n private onPlanStatusUpdate(\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] {\n let statuses = payload.statuses\n if (typeof statuses !== \"object\" || statuses === null) {\n statuses = payload._statuses ?? {}\n }\n const turn = buildMarkerTurn(\n this.nextSeq(),\n this.nextTurnId(\"plan_status\"),\n loopId,\n \"plan_status\",\n { plan_yaml: payload.plan_yaml ?? \"\", statuses },\n )\n return [{ kind: \"upsert\", turn }]\n }\n\n private onWorkspaceChanged(\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] {\n const updates: ProjectionUpdate[] = [\n {\n kind: \"workspace_changed\",\n loopId,\n toolCallId: optStr(payload.tool_call_id) ?? undefined,\n toolName: toolNameFromPayload(payload) ?? undefined,\n workspacePath: isRecord(payload.workspace_change)\n ? optStr(payload.workspace_change.to) ?? undefined\n : undefined,\n ...changedPaths(payload.paths),\n },\n ]\n const change = payload.workspace_change\n if (isRecord(change)) {\n const source = optStr(change.source) ?? \"\"\n const projectName = optStr(change.project_name) ?? \"\"\n const fromPath = optStr(change.from) ?? \"\"\n const toPath = optStr(change.to) ?? \"\"\n const filesCopied =\n typeof change.files_copied === \"number\" ? change.files_copied : 0\n updates.unshift({\n kind: \"upsert\",\n turn: buildSystemNotificationTurn(\n this.nextSeq(),\n this.nextTurnId(\"workspace_change\"),\n loopId,\n \"workspace_change\",\n \"done\",\n source === \"cli:blade\" && projectName\n ? `项目「${projectName}」已创建`\n : \"工作目录已切换\",\n source === \"cli:blade\" && projectName\n ? `${filesCopied > 0 ? `已复制 ${filesCopied} 项当前文件。` : \"已原地使用当前文件夹。\"} 后续工作将在 ${toPath} 进行。`\n : `工作目录已从 ${fromPath} 切换到 ${toPath}。后续工作将在新目录进行。`,\n { ...change },\n ),\n })\n }\n const state = this.activeTurns.get(loopId)\n if (state) {\n const turn = snapshot(state, this.nextSeq(), \"streaming\")\n this.latestTurns.set(loopId, turn)\n this.lastTurnIds.set(loopId, turn.turn_id)\n updates.push({ kind: \"upsert\", turn })\n }\n return updates\n }\n\n private onAgentStart(\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] {\n const description = optStr(payload.description)\n if (description) this.loopDescriptions.set(loopId, description)\n const subagentStartedAt = optStr(payload.started_at)\n if (subagentStartedAt) {\n this.activeSubagentRuns.set(loopId, {\n runId: optStr(payload.run_id) ?? loopId,\n startedAt: subagentStartedAt,\n })\n }\n const turn = buildSystemNotificationTurn(\n this.nextSeq(),\n this.nextTurnId(\"agent:start\"),\n loopId,\n \"agent:start\",\n \"running\",\n `Agent: ${payload.description ?? payload.skill_id ?? \"agent\"}`,\n optStr(payload.prompt),\n {\n skill_id: optStr(payload.skill_id),\n description: optStr(payload.description),\n parent_fork_tool_call_id: optStr(payload.parent_fork_tool_call_id),\n },\n )\n return [{ kind: \"upsert\", turn }]\n }\n\n private onBgStarted(\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] {\n const taskId = optStr(payload.task_id) ?? \"\"\n const command = optStr(payload.command)\n const description = optStr(payload.description)\n const turn = buildSystemNotificationTurn(\n this.nextSeq(),\n this.nextTurnId(\"bg:started\"),\n loopId,\n \"bg:started\",\n \"running\",\n description ?? `Background: ${taskId || \"task\"}`,\n command,\n { task_id: taskId, command, description },\n )\n return [{ kind: \"upsert\", turn }]\n }\n\n private onBgTasksCompleted(\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] {\n const taskIds = Array.isArray(payload.task_ids) ? payload.task_ids : []\n const count = typeof payload.count === \"number\" ? payload.count : taskIds.length\n const detail = taskIds.map(String).join(\", \")\n const turn = buildSystemNotificationTurn(\n this.nextSeq(),\n this.nextTurnId(\"bg:tasks_completed\"),\n loopId,\n \"bg:tasks_completed\",\n backgroundTaskStatus(payload),\n `Background tasks completed (${count})`,\n detail || null,\n { task_ids: taskIds, count },\n )\n return [{ kind: \"upsert\", turn }]\n }\n\n private onAskUserAnswer(\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] {\n const toolCallId = String(payload.tool_call_id ?? \"\")\n const pending = this.pendingChildPauses.get(toolCallId)\n const parent = pending ?? [...this.latestTurns.values()].flatMap((turn) =>\n turn.tool_calls\n .filter((call) => call.pending_question_ref?.child_tool_call_id === toolCallId)\n .map((call) => ({ parentLoopName: turn.loop_id, parentToolCallId: call.id })),\n )[0]\n if (parent) {\n this.answeredChildParents.set(loopId, {\n parentLoopName: parent.parentLoopName,\n parentToolCallId: parent.parentToolCallId,\n })\n }\n const parentLoopId = parent?.parentLoopName\n\n if (pending) {\n this.pendingChildPauses.delete(toolCallId)\n const childTurn =\n this.activeTurns.get(pending.childLoopName) ??\n this.latestTurns.get(pending.childLoopName)\n restoreAnsweredAskUserJson(childTurn, pending.childToolCallId)\n setToolCallStatus(childTurn, pending.childToolCallId, \"done\", null, null)\n }\n if (parent) {\n const parentTurn =\n this.activeTurns.get(parent.parentLoopName) ??\n this.latestTurns.get(parent.parentLoopName)\n setToolCallStatus(parentTurn, parent.parentToolCallId, \"done\", null, null)\n }\n\n const directTurn = this.activeTurns.get(loopId) ?? this.latestTurns.get(loopId)\n restoreAnsweredAskUserJson(directTurn, toolCallId)\n setToolCallStatus(directTurn, toolCallId, \"done\", null, null)\n\n const updates = this.collectLoopUpdates(loopId, parentLoopId)\n const entryId = typeof payload.entry_id === \"string\" ? payload.entry_id : \"\"\n if (!entryId) return updates\n const answerData = isRecord(payload.answer_data) ? payload.answer_data : {}\n const answerTurn: TurnProjection = {\n id: entryId,\n sequence: this.nextSeq(),\n turn_id: entryId,\n loop_id: loopId,\n kind: \"message\",\n role: \"assistant\",\n status: \"completed\",\n blocks: [\n {\n type: \"ask_user_answer\",\n content: answerData,\n tool_call_id: toolCallId || null,\n },\n ],\n tool_calls: [],\n model: null,\n usage: null,\n duration_ms: 0,\n client_request_id:\n typeof payload.client_request_id === \"string\" ? payload.client_request_id : null,\n }\n return [...updates, { kind: \"upsert\", turn: answerTurn }]\n }\n\n private onUserMessage(\n _loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] {\n const entryId = String(payload.entry_id ?? this.nextTurnId(\"user\"))\n const displayContent = payload.display_content ?? payload.content ?? \"\"\n const refs = normalizeMessageRefs(payload.refs)\n const turn: TurnProjection = {\n id: entryId,\n sequence: this.nextSeq(),\n turn_id: entryId,\n loop_id: \"root\",\n kind: \"message\",\n role: \"user\",\n status: \"completed\",\n blocks: [{ type: \"text\", content: displayContent }],\n ...(refs.length ? { refs } : {}),\n context_attachments: normalizeContextAttachments(payload.context_attachments),\n topic_asset_refs: normalizeTopicAssetRefs(payload.topic_asset_refs),\n tool_calls: [],\n model: null,\n usage: null,\n duration_ms: 0,\n client_request_id:\n typeof payload.client_request_id === \"string\" ? payload.client_request_id : null,\n }\n if (payload.start_reason === \"background-completion\") {\n turn.blocks.push({ type: \"system_notification\", content: { notification_type: \"bg:wakeup\" } })\n }\n this.latestTurns.set(\"root\", turn)\n return [{ kind: \"upsert\", turn }]\n }\n\n private onPostChatFollowup(\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n const assistantEntryId = String(payload.assistant_entry_id ?? \"\")\n const latest = this.latestTurns.get(\"root\") as FollowupTurn | undefined\n if (\n !latest ||\n latest.role !== \"assistant\" ||\n latest.turn_id !== assistantEntryId\n ) {\n return null\n }\n\n const postChatFollowup = normalizePostChatFollowup(payload, assistantEntryId)\n if (!postChatFollowup) return null\n const turn: FollowupTurn = {\n ...latest,\n post_chat_followup: postChatFollowup,\n }\n this.latestTurns.set(\"root\", turn)\n return [{ kind: \"upsert\", turn }]\n }\n\n\n private onDelta(\n state: TurnState,\n blockType: \"thinking\" | \"text\",\n _toolCallId: string,\n content: string,\n ): ProjectionUpdate[] | null {\n if (!content) return null\n appendTextBlock(state, blockType, content)\n return this.syncPatch(state)\n }\n\n private onToolCallCreated(\n state: TurnState,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n if (\"arguments_delta\" in payload) {\n return this.onToolCallArgumentsDelta(state, payload)\n }\n const toolCallId = String(payload.id ?? \"\")\n const toolName = toolNameFromPayload(payload)\n const displayName = String(payload.display_name ?? \"\") || this.displayNameResolver(toolName)\n const args = toolArgsFromPayload(payload)\n upsertToolCall(state, toolCallId, toolName, displayName, args)\n return this.syncPatch(state)\n }\n\n private onToolCallArgumentsDelta(\n state: TurnState,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n const delta = String(payload.arguments_delta ?? \"\")\n const toolCallId = String(payload.id ?? \"\")\n if (!delta || !toolCallId) return null\n appendToolCallArguments(state, toolCallId, delta)\n return this.syncPatch(state)\n }\n\n private onResponseDone(\n state: TurnState,\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n state.responseDone = true\n this.applyStreamTiming(state, payload)\n const model = optStr(payload.model)\n if (model) state.model = model\n if (typeof payload.usage === \"object\" && payload.usage !== null) {\n state.usage = { ...(payload.usage as Record<string, unknown>) }\n }\n const toolCalls = payload.tool_calls\n if (Array.isArray(toolCalls)) {\n for (const raw of toolCalls) {\n if (typeof raw !== \"object\" || raw === null) continue\n const tc = raw as Record<string, unknown>\n const fn = (tc.function ?? {}) as Record<string, unknown>\n const toolName = String(fn.name ?? \"\")\n const displayName =\n String(tc.display_name ?? \"\") || this.displayNameResolver(toolName)\n upsertToolCall(\n state,\n String(tc.id ?? \"\"),\n toolName,\n displayName,\n String(fn.arguments ?? \"\"),\n )\n }\n }\n\n if (!applyResponseBlockOrder(state, payload.response_blocks) && \"content\" in payload) {\n replaceTextContent(state, completedResponseText(payload.content))\n }\n\n if (state.toolCalls.length === 0) {\n const childParent = this.answeredChildParents.get(loopId)\n if (childParent) {\n this.answeredChildParents.delete(loopId)\n const parentTurn =\n this.activeTurns.get(childParent.parentLoopName) ??\n this.latestTurns.get(childParent.parentLoopName)\n applyChildResultToParent(\n parentTurn,\n childParent.parentToolCallId,\n completedResponseText(payload.content),\n )\n }\n const updates = this.finalize(loopId, \"completed\") ?? []\n return childParent\n ? [...updates, ...this.collectLoopUpdates(childParent.parentLoopName)]\n : updates\n }\n return this.syncPatch(state)\n }\n\n private applyFirstTokenDelivery(\n state: TurnState,\n payload: Record<string, unknown>,\n ): void {\n this.applyStreamTiming(state, payload)\n const firstTokenMs = payload.first_token_ms\n if (state.firstTokenMs === null && typeof firstTokenMs === \"number\" && firstTokenMs >= 0) {\n state.firstTokenMs = Math.round(firstTokenMs)\n }\n const duration = payload.first_token_delivery_ms\n if (state.firstTokenDeliveryMs === null && typeof duration === \"number\" && duration >= 0) {\n state.firstTokenDeliveryMs = duration\n }\n }\n\n private applyStreamTiming(\n state: TurnState,\n payload: Record<string, unknown>,\n ): void {\n if (typeof payload.first_token_ms === \"number\" && payload.first_token_ms >= 0) {\n state.firstTokenMs = Math.round(payload.first_token_ms)\n }\n if (\n typeof payload.stream_duration_ms === \"number\" &&\n payload.stream_duration_ms >= 0\n ) {\n state.streamDurationMs = Math.round(payload.stream_duration_ms)\n }\n if (typeof payload.started_at === \"string\" && payload.started_at) {\n state.modelStartedAt = payload.started_at\n state.modelStartedAtReported = true\n }\n if (typeof payload.duration_ms === \"number\" && payload.duration_ms >= 0) {\n state.modelDurationMs = Math.round(payload.duration_ms)\n }\n }\n\n private onToolResultDone(\n state: TurnState,\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n const toolCallId = String(payload.tool_call_id ?? \"\")\n const streamedResult = state.toolCalls.find((toolCall) => toolCall.id === toolCallId)?.result\n const content =\n payload.content_from_deltas === true ? (streamedResult ?? \"\") : payload.content ?? \"\"\n const status = payload.is_error === true ? \"error\" : payload._tool_pending === true ? \"pending\" : toolStatusFromResult(content)\n const rawDuration = payload.duration_ms\n const durationMs =\n typeof rawDuration === \"number\" && rawDuration >= 0\n ? Math.round(rawDuration)\n : null\n const ranInParallel =\n typeof payload.ran_in_parallel === \"boolean\" ? payload.ran_in_parallel : null\n\n const sl = sourceLoopFor(state.loopId, this.loopDescriptions)\n const startedAt = typeof payload.started_at === \"string\" && payload.started_at ? payload.started_at : null\n applyToolResult(state, toolCallId, content, status, durationMs, ranInParallel, sl, startedAt)\n attachToolEvidence(state.toolCalls.find((call) => call.id === toolCallId), payload.evidence)\n const pendingChild = [...this.pendingChildPauses.values()].find(\n (pause) => pause.parentLoopName === loopId && pause.parentToolCallId === toolCallId,\n )\n if (pendingChild) {\n applyChildPauseToParent(\n state,\n toolCallId,\n pendingChild.childLoopName,\n pendingChild.childToolCallId,\n pendingChild.description,\n this.displayNameResolver,\n )\n }\n\n if (this.shouldFinalizeAfterToolResults(state)) {\n return this.finalize(loopId, \"completed\")\n }\n return this.syncPatch(state)\n }\n\n private onToolResultDelta(\n state: TurnState,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n appendToolResultDelta(\n state,\n String(payload.tool_call_id ?? \"\"),\n String(payload.content ?? \"\"),\n payload.content_reset === true,\n )\n return this.syncPatch(state)\n }\n\n private onToolUi(\n state: TurnState,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n const toolCallId = String(payload.tool_call_id ?? \"\")\n const ui = payload.ui\n if (toolCallId && typeof ui === \"object\" && ui !== null) {\n state.blocks.push({\n type: \"tool_ui\",\n content: ui,\n tool_call_id: toolCallId,\n })\n }\n return this.syncPatch(state)\n }\n\n private onToolBridge(\n state: TurnState,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n const bridge = payload.bridge\n if (typeof bridge !== \"object\" || bridge === null) return null\n const toolCallId = String(payload.tool_call_id ?? \"\")\n if (!toolCallId || !state.toolCalls.some((toolCall) => toolCall.id === toolCallId)) return null\n state.blocks.push({\n type: \"tool_bridge\",\n content: bridge,\n delivery_id: String(payload.delivery_id ?? \"\") || null,\n tool_call_id: toolCallId,\n })\n return this.syncPatch(state)\n }\n\n private onToolApprovalRequired(\n state: TurnState,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n const toolCallId = String(payload.tool_call_id ?? \"\")\n const toolName = String(payload.tool_name ?? \"\")\n const displayName = this.displayNameResolver(toolName)\n upsertToolCall(state, toolCallId, toolName, displayName, \"\")\n const relatedToolCallId = String(payload.related_tool_call_id ?? \"\")\n if (relatedToolCallId && relatedToolCallId !== toolCallId) {\n const related = state.toolCalls.find((toolCall) => toolCall.id === relatedToolCallId)\n if (related) related.status = \"awaiting_answer\"\n }\n return this.syncPatch(state)\n }\n\n private onChildPause(\n state: TurnState,\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n const pauseToolData = payload.pause_tool_data\n if (typeof pauseToolData !== \"object\" || pauseToolData === null)\n return this.syncPatch(state)\n\n const ptd = pauseToolData as Record<string, unknown>\n const sourceLoop = ptd.source_loop as Record<string, unknown> | undefined\n if (typeof sourceLoop === \"object\" && sourceLoop) {\n const slName = String(sourceLoop.name ?? \"\")\n const slDesc = optStr(sourceLoop.description)\n if (slName && slDesc) this.loopDescriptions.set(slName, slDesc)\n }\n\n const { childLoopName, childToolCallId, description } =\n normalizeChildPause(payload as Record<string, unknown>)\n\n if (!childToolCallId) return this.syncPatch(state)\n\n const existing = this.pendingChildPauses.get(childToolCallId)\n const parentLoopName = String(\n payload.parent_loop_name ?? existing?.parentLoopName ?? \"root\",\n )\n const parentToolCallId = String(\n payload.parent_fork_tool_call_id ?? existing?.parentToolCallId ?? \"\",\n )\n const resolvedChildLoopName =\n String(payload.child_loop_name ?? \"\") || existing?.childLoopName || childLoopName || loopId\n\n this.pendingChildPauses.set(childToolCallId, {\n parentLoopName,\n parentToolCallId,\n childLoopName: resolvedChildLoopName,\n childToolCallId,\n description: description || existing?.description || \"\",\n })\n\n applyAskUserPauseToTurn(\n state,\n ptd,\n childToolCallId,\n resolvedChildLoopName,\n this.pendingChildPauses.get(childToolCallId)!.description,\n this.displayNameResolver,\n )\n\n const parentTurn =\n this.activeTurns.get(parentLoopName) ?? this.latestTurns.get(parentLoopName)\n if (parentTurn) {\n applyChildPauseToParent(\n parentTurn,\n parentToolCallId,\n resolvedChildLoopName,\n childToolCallId,\n this.pendingChildPauses.get(childToolCallId)!.description,\n this.displayNameResolver,\n )\n }\n\n return this.collectLoopUpdates(loopId, parentLoopName)\n }\n\n private onChatEnd(\n state: TurnState,\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n const status = String(payload.status ?? \"completed\")\n let askPause = false\n\n const pauseToolData = payload.pause_tool_data\n if (typeof pauseToolData === \"object\" && pauseToolData !== null) {\n const ptd = pauseToolData as Record<string, unknown>\n const pauseToolName = String(ptd.name ?? \"\")\n const normalized = pauseToolName.includes(\":\")\n ? pauseToolName.split(\":\").pop()!\n : pauseToolName\n const sourceLoop = ptd.source_loop as Record<string, unknown> | undefined\n\n if (typeof sourceLoop === \"object\" && sourceLoop) {\n const slName = String(sourceLoop.name ?? \"\")\n const slDesc = optStr(sourceLoop.description)\n if (slName && slDesc) this.loopDescriptions.set(slName, slDesc)\n\n if (status === \"paused\" && slName) {\n askPause = true\n applyChildPauseToParent(\n state,\n String(ptd.parent_fork_tool_call_id ?? \"\"),\n slName,\n String(ptd.tool_call_id ?? \"\"),\n slDesc ?? \"\",\n this.displayNameResolver,\n )\n\n const childTurn = this.activeTurns.get(slName)\n if (childTurn) {\n applyAskUserPauseToTurn(\n childTurn,\n ptd,\n String(ptd.tool_call_id ?? \"\"),\n slName,\n slDesc ?? \"\",\n this.displayNameResolver,\n )\n }\n }\n } else if (status === \"paused\" && normalized === \"AskUserQuestion\") {\n askPause = true\n applyAskUserPauseToTurn(\n state,\n ptd,\n String(ptd.tool_call_id ?? \"\"),\n \"\",\n \"\",\n this.displayNameResolver,\n )\n }\n }\n\n const finalStatus = (\n { completed: \"completed\", paused: \"paused\", failed: \"failed\", interrupted: \"interrupted\" } as Record<string, TurnProjection[\"status\"]>\n )[status]\n\n if (!finalStatus) return null\n if (finalStatus === \"failed\") this.dropIncompleteToolCalls(state)\n if (!this.activeTurns.has(loopId)) {\n this.pendingMemoryRefs.delete(loopId)\n }\n return this.finalize(loopId, askPause ? \"completed\" : finalStatus)\n }\n\n private onAgentEnd(\n state: TurnState | null,\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n const ok = payload.ok !== false\n this.settleSubagentRun(loopId, payload)\n if (payload.run_status === \"paused\") {\n return state ? this.finalize(loopId, \"completed\") : null\n }\n const status = ok ? \"done\" : \"error\"\n const title = `Agent: ${payload.description ?? payload.skill_id ?? \"agent\"}`\n const detail = optStr(payload.error)\n const metadata = {\n skill_id: optStr(payload.skill_id),\n description: optStr(payload.description),\n parent_fork_tool_call_id: optStr(payload.parent_fork_tool_call_id),\n ...(typeof payload.run_status === \"string\" ? { run_status: payload.run_status } : {}),\n ok,\n }\n if (state) {\n if (!ok) this.dropIncompleteToolCalls(state)\n state.blocks.push(buildSystemNotificationBlock(\"agent:end\", status, title, detail, metadata))\n return this.finalize(loopId, ok ? \"completed\" : \"failed\")\n }\n const turn = buildSystemNotificationTurn(\n this.nextSeq(), this.nextTurnId(\"agent:end\"), loopId, \"agent:end\", status, title, detail, metadata,\n )\n return [{ kind: \"upsert\", turn }]\n }\n\n private settleSubagentRun(\n loopId: string,\n payload: Record<string, unknown>,\n ): void {\n const active = this.activeSubagentRuns.get(loopId)\n this.activeSubagentRuns.delete(loopId)\n const parentToolCallId = optStr(payload.parent_fork_tool_call_id)\n if (!parentToolCallId) return\n const rawDuration = payload.run_duration_ms\n const durationMs =\n typeof rawDuration === \"number\" && rawDuration >= 0 ? Math.round(rawDuration) : null\n const rawStatus = optStr(payload.run_status)\n const status: RunTiming[\"status\"] =\n rawStatus === \"failed\" ||\n rawStatus === \"cancelled\" ||\n rawStatus === \"paused\" ||\n rawStatus === \"incomplete\"\n ? rawStatus\n : payload.ok === false\n ? \"failed\"\n : \"completed\"\n const run: RunTiming = {\n run_id: active?.runId ?? optStr(payload.run_id) ?? loopId,\n scope: \"subagent\",\n loop_id: loopId,\n started_at: active?.startedAt ?? optStr(payload.run_started_at),\n duration_ms: durationMs,\n status,\n }\n const seen = new Set<TurnProjection>()\n for (const turn of [...this.latestTurns.values(), ...this.turnsById.values()]) {\n if (seen.has(turn)) continue\n seen.add(turn)\n const toolCall = turn.tool_calls.find((item) => item.id === parentToolCallId)\n if (!toolCall) continue\n toolCall.subagent_runs = [...(toolCall.subagent_runs ?? []), run]\n }\n }\n\n private dropIncompleteToolCalls(state: TurnState): void {\n if (state.responseDone) return\n state.toolCalls = []\n state.blocks = state.blocks.filter((block) => block.type !== \"tool_use\")\n }\n\n private onCompaction(\n eventType: string,\n loopId: string,\n payload: Record<string, unknown>,\n ): ProjectionUpdate[] | null {\n const compactionId = String(payload.compaction_id ?? \"\")\n if (!compactionId) return null\n // Temporary delivery can lag behind the durable terminal snapshot.\n const previous = this.turnsById.get(`compaction:${compactionId}`)\n if (eventType === \"compaction:start\" && previous && previous.status !== \"streaming\") return null\n\n let current = {\n ...(this.activeCompactions.get(compactionId) ?? {}),\n ...payload,\n loop_id: loopId,\n }\n\n let status: TurnProjection[\"status\"]\n switch (eventType) {\n case \"compaction:start\":\n status = \"streaming\"\n this.activeCompactions.set(compactionId, current)\n this.failedCompactions.delete(compactionId)\n break\n case \"compaction:end\":\n status = \"completed\"\n this.activeCompactions.delete(compactionId)\n break\n case \"compaction:abort\":\n status = \"interrupted\"\n this.activeCompactions.delete(compactionId)\n break\n case \"compaction:error\":\n status = \"failed\"\n this.activeCompactions.delete(compactionId)\n this.failedCompactions.set(compactionId, { ...current })\n break\n default:\n status = \"streaming\"\n this.activeCompactions.set(compactionId, current)\n }\n\n const failed = this.failedCompactions.get(compactionId)\n if (failed && status !== \"failed\") {\n current = { ...failed, ...current }\n status = \"failed\"\n }\n\n const turn = buildCompactionTurn(this.nextSeq(), compactionId, loopId, status, current)\n return [{ kind: \"upsert\", turn }]\n }\n\n\n private syncPatch(state: TurnState): ProjectionUpdate[] {\n const turn = snapshot(state, this.nextSeq(), \"streaming\")\n this.latestTurns.set(state.loopId, turn)\n this.turnsById.set(turn.turn_id, turn)\n this.lastTurnIds.set(state.loopId, turn.turn_id)\n return [{ kind: \"upsert\", turn }]\n }\n\n private finalize(\n loopId: string,\n status: TurnProjection[\"status\"],\n ): ProjectionUpdate[] | null {\n const state = this.activeTurns.get(loopId)\n if (!state) return null\n this.activeTurns.delete(loopId)\n const turn = snapshot(state, this.nextSeq(), status)\n this.lastTurnIds.set(loopId, turn.turn_id)\n this.latestTurns.set(loopId, turn)\n this.turnsById.set(turn.turn_id, turn)\n return [{ kind: \"upsert\", turn }]\n }\n\n private shouldFinalizeAfterToolResults(state: TurnState): boolean {\n if (state.toolCalls.length === 0) return true\n if (state.toolCalls.some((tc) => tc.status === \"pending\")) return false\n return !state.toolCalls.some((tc) => {\n const normalized = tc.tool_name.includes(\":\")\n ? tc.tool_name.split(\":\").pop()!\n : tc.tool_name\n return PAUSE_TOOL_NAMES.has(normalized)\n })\n }\n\n private collectLoopUpdates(\n ...loopIds: (string | undefined | null)[]\n ): ProjectionUpdate[] {\n const updates: ProjectionUpdate[] = []\n for (const loopId of loopIds) {\n if (!loopId) continue\n const state = this.activeTurns.get(loopId)\n if (state) {\n updates.push(...this.syncPatch(state))\n continue\n }\n const proj = this.latestTurns.get(loopId)\n if (proj) {\n const updated = { ...proj, sequence: this.nextSeq() }\n this.latestTurns.set(loopId, updated)\n updates.push({ kind: \"upsert\", turn: updated })\n }\n }\n return updates\n }\n\n private nextSeq(): number {\n return ++this.seq\n }\n\n private nextTurnId(prefix: string): string {\n this.syntheticCounter++\n const hex = Math.random().toString(16).slice(2, 10)\n return `${prefix}:${this.syntheticCounter}:${hex}`\n }\n}\n\n\nfunction optStr(value: unknown): string | null {\n if (value == null || value === \"\") return null\n return String(value)\n}\n\nfunction toolNameFromPayload(payload: Record<string, unknown>): string {\n const fn = payload.function\n if (typeof fn === \"object\" && fn !== null) {\n return String((fn as Record<string, unknown>).name ?? \"\")\n }\n return String(payload.tool_name ?? \"\")\n}\n\nfunction toolArgsFromPayload(payload: Record<string, unknown>): string {\n const fn = payload.function\n if (typeof fn === \"object\" && fn !== null) {\n return String((fn as Record<string, unknown>).arguments ?? \"\")\n }\n return \"\"\n}\n\nfunction changedPaths(value: unknown): { paths?: string[] } {\n if (!Array.isArray(value)) return {}\n const paths = value.filter((item): item is string => typeof item === \"string\" && item !== \"\")\n return paths.length ? { paths } : {}\n}\n","import { isRecord } from \"../shared/type-guards\"\n\n/** Archived MCP App data. Credentials and executable server configuration are excluded. */\nexport interface McpAppData {\n sourceId: string\n resourceUri: string\n mimeType: string\n resourceMeta: Record<string, unknown>\n toolInput: Record<string, unknown>\n toolResult: Record<string, unknown>\n}\n\nexport interface McpAppArchive extends McpAppData {\n html: string\n plugin: string\n /** Restore the last successful view before delivering a saved failure. */\n previousToolInput?: Record<string, unknown>\n previousToolResult?: Record<string, unknown>\n}\n\nexport function isMcpAppData(value: unknown): value is McpAppData {\n return (\n isRecord(value) &&\n typeof value.sourceId === \"string\" && value.sourceId.length > 0 &&\n typeof value.resourceUri === \"string\" && value.resourceUri.startsWith(\"ui://\") &&\n typeof value.mimeType === \"string\" &&\n isRecord(value.resourceMeta) && isRecord(value.toolInput) && isRecord(value.toolResult)\n )\n}\n\n\n/** Latest model-context state one MCP App saved for its own card. */\nexport interface McpAppContextState {\n revision: string\n content: string\n plugin: string | null\n server_alias: string | null\n}\n\nexport interface McpAppContextUpdate {\n request_id: string\n /** null on the first save; the server rejects a stale revision. */\n expected_revision: string | null\n content: string\n}\n","import type { ChatMessage, ToolCallInfo } from \"../schemas/message\"\nimport type { ContentBlock } from \"../schemas/projection\"\nimport { isMcpAppData, type McpAppData } from \"../schemas/mcp-app\"\n\n/**\n * MCP App 卡片(`_meta.ui` → `tool_ui` block)的共享判定层。\n *\n * 判定逻辑不许各写一份(仓库 CLAUDE.md):agent-react 与 apps/web 都从这里消费卡片的\n * 实例、可见性、身份和终态规则;样式与状态容器(侧栏页签栈等)两侧各自实现。\n */\n\nexport interface ToolUiCard {\n resourceUri?: string\n resourceURI?: string\n resourceHTML?: string\n /** Local HTML source file; hosts can normalize it against the session workspace. */\n sourcePath?: string\n /** 历史投影标记:绝不重新解析 resourceUri(刷新不重放 MCP/资源读取)。 */\n archived?: boolean\n target: \"inline\" | \"preview\"\n height: number\n title?: string\n /** 留档的 MCP App 来源身份与调用数据(来源 server、ui:// 资源、CSP 元数据)。 */\n mcpApp?: McpAppData\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.trim().length > 0\n}\n\nfunction isPositiveNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0\n}\n\n/** 严格守卫:target/height 缺失、archived 无留档 HTML、或 mcpApp 来源身份残缺的\n * 卡片一律判无效,消息流、侧栏、toolPreview 事件三处一致降级(不渲染、不发事件、\n * 不推送)。后端 `_tool_ui_meta.py` 总会补齐 target/height 默认值,判无效即数据畸形。 */\nexport function isToolUiCard(value: unknown): value is ToolUiCard {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false\n }\n const raw = value as Record<string, unknown>\n if (raw.target !== \"inline\" && raw.target !== \"preview\") {\n return false\n }\n if (!isPositiveNumber(raw.height)) {\n return false\n }\n if (raw.archived === true && !isNonEmptyString(raw.resourceHTML)) {\n return false\n }\n if (\n !isNonEmptyString(raw.resourceHTML) &&\n !isNonEmptyString(raw.resourceUri) &&\n !isNonEmptyString(raw.resourceURI) &&\n !(raw.target === \"preview\" && isNonEmptyString(raw.sourcePath))\n ) {\n return false\n }\n if (raw.title != null && !isNonEmptyString(raw.title)) {\n return false\n }\n if (raw.sourcePath != null && !isNonEmptyString(raw.sourcePath)) return false\n if (raw.mcpApp !== undefined && !isMcpAppData(raw.mcpApp)) {\n return false\n }\n return true\n}\n\nexport type ToolUiCardContentType = \"resource-html\" | \"resource-uri\" | \"resource-file\"\n\n/** 解析卡片实际要渲染的内容。archived 卡片只认留档 HTML,绝不回退到\n * resourceUri——历史恢复/浏览器刷新不得因此重新发起 MCP 资源读取。 */\nexport function resolveToolUiCardContent(\n card: ToolUiCard,\n): { type: ToolUiCardContentType; content: string } | null {\n if (isNonEmptyString(card.resourceHTML)) {\n return { type: \"resource-html\", content: card.resourceHTML }\n }\n if (card.archived) return null\n const uri = isNonEmptyString(card.resourceUri) ? card.resourceUri : card.resourceURI\n if (isNonEmptyString(uri)) return { type: \"resource-uri\", content: uri }\n return card.target === \"preview\" && isNonEmptyString(card.sourcePath)\n ? { type: \"resource-file\", content: card.sourcePath }\n : null\n}\n\n/** 卡片实例身份/去重键:uri 卡片按内容去重(同一 URI 多次产出只留一份),\n * 文件 HTML 按来源路径,无来源的 HTML 按 toolCallId 去重。 */\nexport function buildToolUiCardKey(\n toolCallId: string,\n type: ToolUiCardContentType,\n content: string,\n sourcePath?: string,\n): string {\n if (type === \"resource-uri\") {\n return `tool-preview-uri:${content}`\n }\n if (sourcePath?.trim()) return sourcePath.trim()\n if (type === \"resource-file\") return content\n return `tool-preview:${toolCallId}`\n}\n\n/** 内部「阶段进度」卡片不对用户展示入口。 */\nexport function isInternalStatusToolUiCard(card: { title?: string | null } | null): boolean {\n return card?.title?.trim() === \"阶段进度\"\n}\n\n/** app-dev 会话里的应用预览卡片:走专门的预览页签,不开普通侧栏 artifact。 */\nexport function isAppDevToolUiCard(card: ToolUiCard, isAppDev: boolean): boolean {\n return (\n isAppDev &&\n card.target === \"preview\" &&\n !card.resourceHTML &&\n Boolean(card.resourceUri || card.resourceURI)\n )\n}\n\nexport interface InlineToolUiCardEntry {\n key: string\n toolCallId: string\n card: ToolUiCard\n}\n\n/** 从一轮消息里收集 target=inline 的卡片(渲染进消息流)。 */\nexport function collectInlineToolUiCards(messages: ChatMessage[]): InlineToolUiCardEntry[] {\n return messages.flatMap((message) =>\n (message.blocks ?? []).flatMap((block, index) =>\n block.type === \"tool_ui\" &&\n block.tool_call_id &&\n isToolUiCard(block.content) &&\n block.content.target === \"inline\"\n ? [\n {\n key: `${message.entry_id ?? message.timestamp ?? \"message\"}-${block.tool_call_id}-${index}`,\n toolCallId: block.tool_call_id,\n card: block.content,\n },\n ]\n : [],\n ),\n )\n}\n\nexport interface PreviewToolUiCardEntry {\n key: string\n toolCall: ToolCallInfo\n card: ToolUiCard\n /** 所属消息的 blocks;调用方需要还原卡片所在 block 上下文时用。 */\n blocks: ContentBlock[]\n}\n\n/** 从一轮消息里收集 target=preview 的卡片(进侧栏/面板,不进消息流),\n * 并绑定回所属的 toolCall。 */\nexport function collectPreviewToolUiCards(messages: ChatMessage[]): PreviewToolUiCardEntry[] {\n return messages.flatMap((message) =>\n (message.blocks ?? []).flatMap((block, index) => {\n if (\n block.type !== \"tool_ui\" ||\n !block.tool_call_id ||\n !isToolUiCard(block.content) ||\n block.content.target !== \"preview\"\n ) {\n return []\n }\n const toolCall = (message.tool_calls ?? []).find(\n (candidate) => candidate.id === block.tool_call_id,\n )\n return toolCall\n ? [\n {\n key: `${message.entry_id ?? message.timestamp ?? \"message\"}-${block.tool_call_id}-${index}`,\n toolCall,\n card: block.content,\n blocks: message.blocks ?? [],\n },\n ]\n : []\n }),\n )\n}\n","import { normalizeContextAttachments } from \"../../schemas/context-attachments\"\nimport { normalizeMessageRefs } from \"../../schemas/plugin-refs\"\nimport type {\n ContentBlock,\n RunTiming,\n ToolCallProjection,\n TurnProjection,\n} from \"../../schemas/projection\"\nimport { inferToolStatus } from \"../../schemas/message\"\nimport { buildContextTurn } from \"./context\"\nimport { isRecord } from \"../type-guards\"\nimport { isToolUiCard, resolveToolUiCardContent } from \"../tool-ui-card\"\nimport {\n attachToolEvidence,\n applyAskUserPauseToTurn,\n applyChildPauseToParent,\n buildCompactionTurn,\n buildSystemNotificationTurn,\n normalizePostChatFollowup,\n restoreAnsweredAskUserJson,\n setToolCallStatus,\n} from \"./helpers\"\n\nexport interface RawHistoryEntry {\n id?: string\n kind?: string\n loop_name?: string\n message?: Record<string, unknown>\n source?: Record<string, unknown>\n data?: Record<string, unknown>\n timestamp?: string\n [key: string]: unknown\n}\n\ntype FollowupTurn = TurnProjection\n\n/** Rebuild completed UI turns from raw persisted history entries. */\nexport function projectHistory(entries: RawHistoryEntry[]): TurnProjection[] {\n const turns: TurnProjection[] = []\n const toolOwners = new Map<string, TurnProjection>()\n const latestAssistantByLoop = new Map<string, TurnProjection>()\n const pendingChildPauses = new Map<\n string,\n { childLoopId: string; parentLoopId: string; parentToolCallId: string }\n >()\n const childPauseEntries: Array<{\n childToolCallId: string\n pauseToolData: Record<string, unknown>\n description: string\n }> = []\n const answeredToolCallIds = new Set<string>()\n const turnEntryAliases = new Map<string, TurnProjection>()\n let latestRootMessage: FollowupTurn | null = null\n let latestRootAssistant: TurnProjection | null = null\n let sequence = 0\n\n for (const entry of entries) {\n const kind = String(entry.kind ?? \"\")\n const loopId = String(entry.loop_name ?? \"root\")\n const id = String(entry.id ?? `history-${sequence + 1}`)\n if (kind === \"turn_timing\" && isRecord(entry.data)) {\n const turnId = typeof entry.data.turn_id === \"string\" ? entry.data.turn_id : \"\"\n const duration = numberOrNull(entry.data.first_token_delivery_ms)\n const target = turnEntryAliases.get(turnId)\n if (target && duration !== null) target.first_token_delivery_ms = duration\n continue\n }\n if (kind === \"run_timing\" && isRecord(entry.data)) {\n const data = entry.data\n if (data.scope === \"subagent\") {\n const parentToolCallId = String(data.parent_fork_tool_call_id ?? \"\")\n const duration = numberOrNull(data.duration_ms)\n const rawStatus = String(data.status ?? \"completed\")\n const status: RunTiming[\"status\"] =\n rawStatus === \"failed\" ||\n rawStatus === \"cancelled\" ||\n rawStatus === \"paused\" ||\n rawStatus === \"incomplete\"\n ? rawStatus\n : \"completed\"\n for (const turn of turns) {\n const toolCall = turn.tool_calls.find((item) => item.id === parentToolCallId)\n if (!toolCall) continue\n toolCall.subagent_runs = [\n ...(toolCall.subagent_runs ?? []),\n {\n run_id: String(data.run_id ?? \"\"),\n scope: \"subagent\",\n loop_id: loopId,\n started_at:\n typeof data.started_at === \"string\" ? data.started_at : null,\n duration_ms: duration,\n status,\n },\n ]\n break\n }\n }\n continue\n }\n if (kind === \"post_chat_followup\" && isRecord(entry.data)) {\n const assistantEntryId = String(entry.data.assistant_entry_id ?? \"\")\n if (\n latestRootMessage?.role === \"assistant\" &&\n latestRootMessage.turn_id === assistantEntryId\n ) {\n const followup = normalizePostChatFollowup(entry.data, assistantEntryId)\n if (followup) latestRootMessage.post_chat_followup = followup\n }\n continue\n }\n if (kind === \"context\") {\n const turn = buildContextTurn(entry, sequence + 1)\n if (turn) {\n sequence += 1\n turns.push(turn)\n }\n continue\n }\n if (kind === \"message\" && isRecord(entry.message)) {\n const message = entry.message\n const role = String(message.role ?? \"\")\n if (role === \"tool\") {\n const toolCallId = String(message.tool_call_id ?? \"\")\n const owner = toolOwners.get(toolCallId)\n const toolCall = owner?.tool_calls.find((item) => item.id === toolCallId)\n if (owner && toolCall) {\n toolCall.status = message._error\n ? \"error\"\n : message._tool_pending === true ? \"pending\" : inferToolStatus(String(message.content ?? \"\"))\n toolCall.result = message.content ?? \"\"\n attachToolEvidence(toolCall, message._evidence)\n const duration = numberOrNull(message._duration_ms)\n if (duration !== null) toolCall.duration_ms = duration\n if (typeof message._started_at === \"string\") {\n toolCall.started_at = message._started_at\n }\n if (message._ran_in_parallel === true) toolCall.ran_in_parallel = true\n const existing = owner.blocks.find(block => block.type === \"tool_result\" && block.tool_call_id === toolCallId)\n if (existing) existing.content = message.content ?? \"\"\n else owner.blocks.push({ type: \"tool_result\", content: message.content ?? \"\", tool_call_id: toolCallId })\n }\n continue\n }\n if (role !== \"user\" && role !== \"assistant\" && role !== \"system\") continue\n\n const toolCalls = role === \"assistant\" && !message._error\n ? buildToolCalls(message.tool_calls)\n : []\n const blocks = buildBlocks(message, toolCalls)\n if (role === \"user\" && message._start_reason === \"background-completion\") {\n blocks.push({ type: \"system_notification\", content: { notification_type: \"bg:wakeup\" } })\n }\n const turn: FollowupTurn = {\n id,\n sequence: ++sequence,\n turn_id: id,\n loop_id: loopId,\n kind: \"message\",\n role,\n client_request_id: stringOrNull(entry.client_request_id),\n status: message._error\n ? \"failed\"\n : message._interrupted\n ? \"interrupted\"\n : \"completed\",\n blocks,\n tool_calls: toolCalls,\n model: stringOrNull(message.model),\n usage: isRecord(message._usage) ? { ...message._usage } : null,\n duration_ms: numberOrNull(message._duration_ms),\n first_token_ms: numberOrNull(message._first_token_ms),\n stream_duration_ms: numberOrNull(message._stream_duration_ms),\n started_at:\n typeof message._started_at === \"string\"\n ? message._started_at\n : typeof entry.timestamp === \"string\"\n ? entry.timestamp\n : undefined,\n has_reported_timing: typeof message._started_at === \"string\",\n parent_fork_tool_call_id: stringOrNull(message._parent_fork_tool_call_id),\n }\n\n if (role === \"user\") {\n const refs = normalizeMessageRefs(message.refs)\n if (refs.length) turn.refs = refs\n turn.context_attachments = normalizeContextAttachments(message.context_attachments)\n }\n\n if (\n loopId === \"root\" &&\n (role === \"user\" || role === \"assistant\")\n ) {\n latestRootMessage = turn\n }\n turns.push(turn)\n turnEntryAliases.set(id, turn)\n if (role === \"assistant\") latestAssistantByLoop.set(loopId, turn)\n if (loopId === \"root\") {\n if (role === \"assistant\") latestRootAssistant = turn\n else if (role === \"user\") latestRootAssistant = null\n }\n for (const toolCall of toolCalls) toolOwners.set(toolCall.id, turn)\n continue\n }\n\n if (kind === \"tool_result\") {\n const data = entry.data ?? {}\n const toolCallId = String(data.tool_call_id ?? \"\")\n const owner = toolOwners.get(toolCallId) ?? findLatestAssistant(turns, loopId)\n if (owner && toolCallId) {\n const rawContent = data.content\n const content =\n typeof rawContent === \"string\"\n ? rawContent\n : Array.isArray(rawContent)\n ? rawContent\n : String(rawContent ?? \"\")\n const status = data.is_error === true\n ? \"error\"\n : data._tool_pending === true ? \"pending\" : inferToolStatus(typeof content === \"string\" ? content : JSON.stringify(content))\n setToolCallStatus(owner, toolCallId, status, content, null)\n if (!owner.blocks.some((block) => block.type === \"tool_result\" && block.tool_call_id === toolCallId)) {\n owner.blocks.push({ type: \"tool_result\", content, tool_call_id: toolCallId })\n }\n }\n continue\n }\n\n if (kind === \"workflow_step\") {\n const data = entry.data ?? {}\n const toolCallId = String(data.tool_call_id ?? \"\")\n const owner = toolOwners.get(toolCallId) ?? findLatestAssistant(turns, loopId)\n if (owner && toolCallId) {\n const index = owner.tool_calls.findIndex((call) => call.id === toolCallId)\n if (index >= 0) {\n const call = owner.tool_calls[index]\n owner.tool_calls[index] = {\n ...call,\n workflow_steps: [\n ...(call.workflow_steps ?? []),\n {\n step_id: String(data.step_id ?? \"\"),\n desc: String(data.desc ?? \"\"),\n step_kind: String(data.step_kind ?? \"step\"),\n status: String(data.status ?? \"done\"),\n output: String(data.output ?? \"\"),\n ...(typeof data.seq === \"number\" ? { seq: data.seq } : {}),\n ...(typeof data.log_seq === \"number\" ? { log_seq: data.log_seq } : {}),\n },\n ],\n }\n }\n }\n continue\n }\n\n if (kind === \"mode_change\") {\n turns.push(markerTurn(id, ++sequence, loopId, \"mode_change\", entry.data ?? {}))\n } else if (kind === \"workspace_change\") {\n const change = isRecord(entry.data) ? entry.data : {}\n const source = stringOrNull(change.source) ?? \"\"\n const projectName = stringOrNull(change.project_name) ?? \"\"\n const fromPath = stringOrNull(change.from) ?? \"\"\n const toPath = stringOrNull(change.to) ?? \"\"\n const filesCopied =\n typeof change.files_copied === \"number\" ? change.files_copied : 0\n turns.push(\n buildSystemNotificationTurn(\n ++sequence,\n id,\n loopId,\n \"workspace_change\",\n \"done\",\n source === \"cli:blade\" && projectName\n ? `项目「${projectName}」已创建`\n : \"工作目录已切换\",\n source === \"cli:blade\" && projectName\n ? `${filesCopied > 0 ? `已复制 ${filesCopied} 项当前文件。` : \"已原地使用当前文件夹。\"} 后续工作将在 ${toPath} 进行。`\n : `工作目录已从 ${fromPath} 切换到 ${toPath}。后续工作将在新目录进行。`,\n { ...change },\n ),\n )\n } else if (kind === \"plan_status\") {\n const data = entry.data ?? {}\n turns.push(\n markerTurn(id, ++sequence, loopId, \"plan_status\", {\n plan_yaml: data.plan_yaml ?? \"\",\n statuses: data.statuses ?? data._statuses ?? {},\n }),\n )\n } else if (kind === \"tool_ui\" || kind === \"tool_bridge\") {\n const data = entry.data ?? {}\n const toolCallId = String(data.tool_call_id ?? \"\")\n const owner = kind === \"tool_bridge\"\n ? (toolCallId ? toolOwners.get(toolCallId) : undefined)\n : toolOwners.get(toolCallId) ?? findLatestAssistant(turns, loopId)\n const rawContent = kind === \"tool_ui\" ? data.ui : data.bridge\n // History is a pure replay: archived HTML may be rendered again, but a\n // resource URI must never trigger a fresh MCP/resource fetch on refresh.\n // Explicit local file references instead point to the current file.\n const fileReference = isToolUiCard(rawContent)\n && resolveToolUiCardContent(rawContent)?.type === \"resource-file\"\n const content = kind === \"tool_ui\" && isRecord(rawContent)\n ? { ...rawContent, ...(!fileReference ? { archived: true } : {}) }\n : rawContent\n if (owner && content !== undefined) {\n owner.blocks.push({\n type: kind,\n content,\n ...(kind === \"tool_bridge\" ? { delivery_id: id } : {}),\n tool_call_id: toolCallId || null,\n })\n }\n } else if (kind === \"compaction\" || kind === \"tool_result_archive\") {\n const data = entry.data ?? {}\n const compactionId = String(data.compaction_id ?? entry.id ?? `history-${sequence + 1}`)\n let content = isRecord(entry.message) ? entry.message.content : undefined\n if (kind === \"tool_result_archive\") {\n const archivedCount = Array.isArray(data.archived_files) ? data.archived_files.length : 0\n content = typeof data.summary === \"string\" && data.summary\n ? data.summary\n : `<compaction-summary>\\n已归档 ${archivedCount} 个大型工具结果。\\n</compaction-summary>`\n }\n turns.push(\n buildCompactionTurn(++sequence, compactionId, loopId,\n data.status === \"interrupted\" ? \"interrupted\" : data.status === \"failed\" ? \"failed\" : \"completed\", {\n ...data,\n content,\n }),\n )\n } else if (kind === \"child_pause\") {\n const data = entry.data ?? {}\n const sourceLoop = isRecord(data.source_loop) ? data.source_loop : {}\n const childLoopId = String(data.child_loop_name ?? sourceLoop.name ?? \"\")\n const childToolCallId = String(data.child_pause_tool_call_id ?? \"\")\n const parentToolCallId = String(data.parent_fork_tool_call_id ?? \"\")\n const pauseToolData = isRecord(data.pause_tool_data) ? data.pause_tool_data : {}\n const description = String(sourceLoop.description ?? \"\")\n applyAskUserPauseToTurn(\n latestAssistantByLoop.get(childLoopId),\n pauseToolData,\n childToolCallId,\n childLoopId,\n description,\n (name) => name,\n )\n applyChildPauseToParent(\n latestAssistantByLoop.get(loopId),\n parentToolCallId,\n childLoopId,\n childToolCallId,\n description,\n (name) => name,\n )\n if (childToolCallId) {\n pendingChildPauses.set(childToolCallId, {\n childLoopId,\n parentLoopId: loopId,\n parentToolCallId,\n })\n childPauseEntries.push({ childToolCallId, pauseToolData, description })\n }\n } else if (kind === \"ask_user_answer\") {\n const data = entry.data ?? {}\n const toolCallId = String(data.tool_call_id ?? \"\")\n if (toolCallId) answeredToolCallIds.add(toolCallId)\n const pending = pendingChildPauses.get(toolCallId)\n if (pending) {\n restoreAnsweredAskUserJson(latestAssistantByLoop.get(pending.childLoopId), toolCallId)\n setToolCallStatus(latestAssistantByLoop.get(pending.childLoopId), toolCallId, \"done\", null, null)\n setToolCallStatus(\n latestAssistantByLoop.get(pending.parentLoopId),\n pending.parentToolCallId,\n \"done\",\n null,\n null,\n )\n pendingChildPauses.delete(toolCallId)\n } else {\n setToolCallStatus(latestAssistantByLoop.get(loopId), toolCallId, \"done\", null, null)\n }\n turns.push(\n markerTurn(\n id,\n ++sequence,\n loopId,\n \"ask_user_answer\",\n data,\n toolCallId || null,\n ),\n )\n }\n }\n\n for (const { childToolCallId, pauseToolData, description } of childPauseEntries) {\n const pending = pendingChildPauses.get(childToolCallId)\n if (!pending) continue\n applyAskUserPauseToTurn(\n latestAssistantByLoop.get(pending.childLoopId),\n pauseToolData,\n childToolCallId,\n pending.childLoopId,\n description,\n (name) => name,\n )\n applyChildPauseToParent(\n latestAssistantByLoop.get(pending.parentLoopId),\n pending.parentToolCallId,\n pending.childLoopId,\n childToolCallId,\n description,\n (name) => name,\n )\n }\n\n const rootAssistant = latestRootAssistant\n if (rootAssistant) {\n for (const toolCall of rootAssistant.tool_calls) {\n if (answeredToolCallIds.has(toolCall.id)) continue\n if (toolCall.tool_name.split(\":\").pop() !== \"AskUserQuestion\") continue\n if (toolCall.status === \"error\" || toolCall.status === \"cancelled\") continue\n const pauseArguments = parseToolArguments(toolCall.arguments)\n if (typeof toolCall.result === \"string\") {\n const resultArguments = parseToolArguments(toolCall.result)\n if (Array.isArray(resultArguments.questions)) {\n pauseArguments.questions = resultArguments.questions\n }\n }\n applyAskUserPauseToTurn(\n rootAssistant,\n {\n name: toolCall.tool_name,\n tool_call_id: toolCall.id,\n arguments: pauseArguments,\n },\n toolCall.id,\n \"\",\n \"\",\n (name) => name,\n )\n }\n }\n\n return turns\n}\n\nfunction parseToolArguments(value: string): Record<string, unknown> {\n if (!value) return {}\n try {\n const parsed = JSON.parse(value)\n return isRecord(parsed) ? parsed : {}\n } catch {\n return {}\n }\n}\n\nfunction buildToolCalls(value: unknown): ToolCallProjection[] {\n if (!Array.isArray(value)) return []\n return value.filter(isRecord).map((raw) => {\n const fn = isRecord(raw.function) ? raw.function : {}\n const name = String(fn.name ?? \"\")\n return {\n id: String(raw.id ?? \"\"),\n tool_name: name,\n display_name: String(raw.display_name ?? name),\n arguments: typeof fn.arguments === \"string\" ? fn.arguments : JSON.stringify(fn.arguments ?? {}),\n status: \"running\",\n result: null,\n }\n })\n}\n\nfunction buildBlocks(\n message: Record<string, unknown>,\n toolCalls: ToolCallProjection[],\n): ContentBlock[] {\n const displayContent = message.role === \"user\" ? message._display_content : undefined\n const stored = message._blocks\n const blocks: ContentBlock[] = []\n const storedToolCallIds = new Set<string>()\n if (displayContent !== undefined) {\n blocks.push({ type: \"text\", content: displayContent })\n } else if (Array.isArray(stored)) {\n for (const raw of stored) {\n if (!isRecord(raw)) continue\n const type = String(raw.type ?? \"\")\n if (type === \"thinking\") blocks.push({ type, content: raw.thinking ?? raw.content ?? \"\" })\n if (type === \"text\") blocks.push({ type, content: raw.text ?? raw.content ?? \"\" })\n if (type === \"tool_call\") {\n const toolCallId = String(raw.id ?? \"\")\n const toolCall = toolCalls.find((candidate) => candidate.id === toolCallId)\n if (!toolCall) continue\n storedToolCallIds.add(toolCallId)\n blocks.push({\n type: \"tool_use\",\n content: toolCall.arguments,\n tool_call_id: toolCall.id,\n tool_name: toolCall.tool_name,\n display_name: toolCall.display_name,\n })\n }\n }\n } else if (message.content !== undefined && message.content !== \"\") {\n blocks.push({ type: \"text\", content: message.content })\n }\n for (const toolCall of toolCalls) {\n if (storedToolCallIds.has(toolCall.id)) continue\n blocks.push({\n type: \"tool_use\",\n content: toolCall.arguments,\n tool_call_id: toolCall.id,\n tool_name: toolCall.tool_name,\n display_name: toolCall.display_name,\n })\n }\n return blocks\n}\n\nfunction markerTurn(\n id: string,\n sequence: number,\n loopId: string,\n type: \"mode_change\" | \"plan_status\" | \"ask_user_answer\",\n content: Record<string, unknown>,\n toolCallId: string | null = null,\n): TurnProjection {\n return {\n id,\n sequence,\n turn_id: id,\n loop_id: loopId,\n kind: type as TurnProjection[\"kind\"],\n role: \"system\",\n status: \"completed\",\n blocks: [{ type, content, tool_call_id: toolCallId }],\n tool_calls: [],\n model: null,\n usage: null,\n duration_ms: 0,\n }\n}\n\nfunction stringOrNull(value: unknown): string | null {\n return typeof value === \"string\" ? value : null\n}\n\nfunction numberOrNull(value: unknown): number | null {\n return typeof value === \"number\" && value >= 0 ? value : null\n}\n\nfunction findLatestAssistant(\n turns: TurnProjection[],\n loopId: string,\n): TurnProjection | undefined {\n for (let index = turns.length - 1; index >= 0; index -= 1) {\n const turn = turns[index]\n if (turn?.role === \"assistant\" && turn.loop_id === loopId) return turn\n }\n return undefined\n}\n","import type { WorkflowStepProjection } from \"../../schemas/projection\"\n\n/** 固定流程时间线的一条事件:step 开一张步骤卡,log 归并进上一张卡。\n * 形状与 session/workflow.ts 的 WorkflowRunEntry 一致(结构化兼容,直接互喂)。 */\nexport type WorkflowTimelineEntry =\n | { kind: \"step\"; stepId: string; desc: string; stepKind: string; status?: string }\n | { kind: \"log\"; text: string; stepId?: string }\n\nconst STEP_KINDS = new Set([\"agent\", \"step\", \"parallel\", \"choice\", \"end\"])\n\n/** 解释执行落史的结构化步骤 → 时间线事件流:与 host live 事件逐行同文案、同顺序。\n * 命令步骤的「└ 输出」行从同一 4KiB 截断串推导(含 …(共N字) 记号),叶子步骤的\n * 「失败:」行还原 error 条目里存的失败说明(容器步骤的 error 条目不带说明)。\n * 条目按终态落盘(容器晚于子步骤、并行分支按完成先后),带 seq / log_seq 时按它们\n * 排回直播时的顺序;旧记录没有序号就按落盘顺序。流式与刷新重建必须渲染出相同结果。 */\nexport function workflowEntriesFromSteps(\n steps: readonly WorkflowStepProjection[],\n): WorkflowTimelineEntry[] {\n const items: { key: number; entry: WorkflowTimelineEntry }[] = []\n const ordered = steps.every((step) => typeof step.seq === \"number\")\n steps.forEach((step, index) => {\n const base = ordered ? (step.seq as number) : index * 2\n const stepKind = step.step_kind && STEP_KINDS.has(step.step_kind) ? step.step_kind : \"step\"\n items.push({\n key: base,\n entry: { kind: \"step\", stepId: step.step_id, desc: step.desc ?? \"\", stepKind, status: step.status },\n })\n const logKey = ordered && typeof step.log_seq === \"number\" ? step.log_seq : base + 0.5\n const output = step.output ?? \"\"\n if (step.status === \"done\" && stepKind === \"step\") {\n // 按码点计数,与 Go shownOutput 的 rune 截断一致(emoji 不算两个字)\n const chars = Array.from(output)\n const shown = chars.length <= 300 ? output : `${chars.slice(0, 300).join(\"\")}…(共${chars.length}字)`\n items.push({ key: logKey, entry: { kind: \"log\", text: ` └ 输出: ${shown || \"(空)\"}`, stepId: step.step_id } })\n }\n if (step.status === \"error\" && output) {\n items.push({ key: logKey, entry: { kind: \"log\", text: `失败: ${output}`, stepId: step.step_id } })\n }\n })\n return items.sort((a, b) => a.key - b.key).map((item) => item.entry)\n}\n\n/** 取消的运行在工具层留档是通用错误串(status=error),真相在步骤条目里:有步骤标记\n * cancelled 且没有步骤失败,整次运行按「已取消」呈现。并行分支失败时兄弟分支也会被\n * 取消,那是失败不是取消。 */\nexport function workflowRunCancelled(steps: readonly WorkflowStepProjection[]): boolean {\n return (\n steps.some((step) => step.status === \"cancelled\") &&\n !steps.some((step) => step.status === \"error\")\n )\n}\n","import type { TopicAssetRef } from \"../schemas/topic-assets\"\nimport type { BladeClient } from \"../blade-client\"\nimport type { ChatEndPayload, ChatSendPayload, ChatStartPayload, SystemErrorPayload, TurnEventsPayload } from \"../types/socket-events\"\nimport { isRecord } from \"../shared/type-guards\"\nimport { LogCursor } from \"../session/log-cursor\"\nimport { acknowledgeTurnEvents, type RawEvent } from \"../shared/projection\"\n\nexport type JsonSchemaObject = Record<string, unknown>\n\nexport interface HeadlessRunOptions {\n schema?: JsonSchemaObject | null\n model?: string | null\n timeoutMs?: number\n /** Assets explicitly selected for this message in a topic-linked session. */\n refs?: import(\"../schemas/plugin-refs\").MessageRef[]\n topicAssetRefs?: TopicAssetRef[]\n}\n\nexport interface HeadlessRunInSessionResult<T = unknown> {\n session_id: string\n chat_run_id: string | null\n result: T | string\n}\n\nexport class HeadlessError extends Error {\n constructor(\n message: string,\n readonly detail?: unknown,\n ) {\n super(message)\n this.name = \"HeadlessError\"\n }\n}\n\nconst SYSTEM_ERROR_CHAT_END_GRACE_MS = 1_000\nconst CLEANUP_ACK_TIMEOUT_MS = 35_000\n\ntype AckOutcome<T = unknown> = { status: \"received\"; ack: T }\n | { status: \"unconfirmed\"; reason: \"ack_timeout\" | \"disconnected\" | \"emit_failed\"; error?: unknown }\n\ntype StopDelivery = {\n status: \"confirmed\" | \"unconfirmed\"\n phase: \"send_ack\" | \"stop_ack\"\n chat_run_id: string | null\n reason?: string\n late?: boolean\n ack?: unknown\n error?: unknown\n}\n\nexport class HeadlessResource {\n private readonly subscriptions = new Map<string, Set<LogCursor>>()\n\n constructor(private client: BladeClient) {}\n\n async run<T = unknown>(prompt: string, options: HeadlessRunOptions & { schema: JsonSchemaObject }): Promise<T>\n async run(prompt: string, options?: HeadlessRunOptions): Promise<string>\n async run<T = unknown>(prompt: string, options: HeadlessRunOptions = {}): Promise<T | string> {\n const { session_id } = await this.client.sessions.createSessionWithRequest({\n intent: prompt,\n model: options.model ?? null,\n })\n return this.runTracked<T>(session_id, prompt, options, false) as Promise<T | string>\n }\n\n async runInSession<T = unknown>(\n sessionId: string,\n prompt: string,\n options: HeadlessRunOptions & { schema: JsonSchemaObject },\n ): Promise<T>\n async runInSession(sessionId: string, prompt: string, options?: HeadlessRunOptions): Promise<string>\n async runInSession<T = unknown>(\n sessionId: string,\n prompt: string,\n options: HeadlessRunOptions = {},\n ): Promise<T | string> {\n return this.runTracked<T>(sessionId, prompt, options, false) as Promise<T | string>\n }\n\n async runWithSession<T = unknown>(\n prompt: string,\n options: HeadlessRunOptions & { schema: JsonSchemaObject },\n ): Promise<HeadlessRunInSessionResult<T>>\n async runWithSession(prompt: string, options?: HeadlessRunOptions): Promise<HeadlessRunInSessionResult<string>>\n async runWithSession<T = unknown>(\n prompt: string,\n options: HeadlessRunOptions = {},\n ): Promise<HeadlessRunInSessionResult<T>> {\n const { session_id } = await this.client.sessions.createSessionWithRequest({\n intent: prompt,\n model: options.model ?? null,\n })\n return this.runTracked<T>(session_id, prompt, options, true) as Promise<HeadlessRunInSessionResult<T>>\n }\n\n private async runTracked<T = unknown>(\n sessionId: string,\n prompt: string,\n options: HeadlessRunOptions,\n returnEnvelope: boolean,\n ): Promise<T | string | HeadlessRunInSessionResult<T>> {\n if ((options.refs?.length ?? 0) > 20) throw new HeadlessError(\"每条消息最多选择 20 个引用\")\n if ((options.topicAssetRefs?.length ?? 0) > 20) throw new HeadlessError(\"每条消息最多引用 20 个主题资产\")\n const timeoutMs = options.timeoutMs ?? 300_000\n const session_id = sessionId\n const socket = this.client.socket()\n await ensureSocketConnected(socket, timeoutMs, { session_id })\n const cursor = new LogCursor()\n const subscriptions = this.subscriptions.get(session_id) ?? new Set<LogCursor>()\n subscriptions.add(cursor)\n this.subscriptions.set(session_id, subscriptions)\n\n return new Promise<T | string | HeadlessRunInSessionResult<T>>((resolve, reject) => {\n let settled = false\n let cleanupPromise: Promise<void> | undefined\n let stopAttempt: Promise<StopDelivery> | undefined\n let handleLateAck: ((response: unknown) => void) | undefined\n let acknowledgeSend: (response: unknown) => void = () => undefined\n const sendAck = new Promise<unknown>((resolveAck) => { acknowledgeSend = resolveAck })\n let started = false\n let chatRunId: string | null = null\n let systemErrorTimeout: ReturnType<typeof setTimeout> | null = null\n const beforeAck = new Map<string, RawEvent[]>()\n const timeout = setTimeout(() => {\n fail(new HeadlessError(`headless run timed out after ${timeoutMs}ms`, { session_id, chat_run_id: chatRunId }))\n }, timeoutMs)\n\n const stopOwnedRun = (runId: string, deadline: number): Promise<StopDelivery> => {\n stopAttempt ??= (async (): Promise<StopDelivery> => {\n const stopped = await waitForCleanupAck(socket, deadline, (ack) => {\n socket.emit(\"chat:stop\", { session_id, chat_run_id: runId }, ack)\n })\n if (stopped.status !== \"received\") return { ...stopped, phase: \"stop_ack\", chat_run_id: runId }\n const ack = stopped.ack\n const confirmed = isRecord(ack)\n && ack.ok !== false\n && ack.chat_run_id === runId\n && typeof ack.status === \"string\"\n && [\"stopping\", \"stopped\", \"idle\", \"done\", \"interrupted\"].includes(ack.status)\n return {\n status: confirmed ? \"confirmed\" : \"unconfirmed\", phase: \"stop_ack\", chat_run_id: runId,\n ...(confirmed ? {} : { reason: \"invalid_stop_ack\" }), ack,\n }\n })().finally(releaseSubscription).catch((error): StopDelivery => ({\n status: \"unconfirmed\", phase: \"stop_ack\", chat_run_id: runId, reason: \"cleanup_failed\", error,\n }))\n return stopAttempt\n }\n const cancelRun = async (deadline: number): Promise<StopDelivery> => {\n if (chatRunId === null) {\n const sent = await waitForCleanupAck(socket, deadline, (ack) => { void sendAck.then(ack) })\n if (sent.status !== \"received\") return { ...sent, phase: \"send_ack\", chat_run_id: null }\n const runId = acceptedRunId(sent.ack)\n if (runId === null) {\n return { status: \"unconfirmed\", phase: \"send_ack\", chat_run_id: null, reason: \"no_accepted_run\", ack: sent.ack }\n }\n chatRunId = runId\n }\n const attempt = stopOwnedRun(chatRunId, deadline)\n const stopped = await waitForCleanupAck<StopDelivery>(socket, deadline, (ack) => { void attempt.then(ack) })\n return stopped.status === \"received\" ? stopped.ack : { ...stopped, phase: \"stop_ack\", chat_run_id: chatRunId }\n }\n const releaseSubscription = () => {\n const current = this.subscriptions.get(session_id)\n current?.delete(cursor)\n if (current?.size === 0) {\n this.subscriptions.delete(session_id)\n socket.emit(\"session:unsubscribe\", { session_id })\n }\n }\n const reportDelivery = (error: unknown, delivery: StopDelivery) => {\n let detailUpdated = true\n try {\n if (error instanceof HeadlessError && isRecord(error.detail)) error.detail.stop_delivery = delivery\n } catch {\n detailUpdated = false\n }\n if (delivery.status !== \"confirmed\" || !detailUpdated) {\n console.warn(delivery.status !== \"confirmed\"\n ? \"[agent-client] headless stop delivery unconfirmed; the run may still be active\"\n : \"[agent-client] late headless stop delivery confirmed; error detail is read-only\", { session_id, ...delivery })\n }\n }\n const cleanup = (error?: unknown): Promise<void> => {\n cleanupPromise ??= (async () => {\n clearTimeout(timeout)\n if (systemErrorTimeout) clearTimeout(systemErrorTimeout)\n systemErrorTimeout = null\n socket.off(\"chat:start\", onChatStart)\n socket.off(\"chat:end\", onChatEnd)\n socket.off(\"system:error\", onSystemError)\n socket.off(\"turn:events\", onTurnEvents)\n socket.off(\"connect\", subscribe)\n beforeAck.clear()\n if (error !== undefined) {\n const deadline = Date.now() + CLEANUP_ACK_TIMEOUT_MS\n handleLateAck = (ack) => {\n const runId = acceptedRunId(ack)\n if (runId === null || !socket.connected || stopAttempt) return\n const late = Date.now() >= deadline\n const current = this.subscriptions.get(session_id) ?? new Set<LogCursor>()\n current.add(cursor)\n this.subscriptions.set(session_id, current)\n void stopOwnedRun(runId, late ? Date.now() + CLEANUP_ACK_TIMEOUT_MS : deadline).then((delivery) => {\n if (late) reportDelivery(error, { ...delivery, late: true })\n }).catch((error) => {\n console.warn(\"[agent-client] late headless stop cleanup failed\", { session_id, chat_run_id: runId, error })\n })\n }\n reportDelivery(error, await cancelRun(deadline))\n }\n if (!stopAttempt) releaseSubscription()\n })()\n return cleanupPromise\n }\n\n const finish = (value: T | string) => {\n if (settled) return\n settled = true\n void cleanup().then(() => resolve(returnEnvelope ? { session_id, chat_run_id: chatRunId, result: value } : value), reject)\n }\n const rejectRun = (error: unknown, sendStop = false) => {\n if (settled) return\n settled = true\n void cleanup(sendStop ? error : undefined).then(() => reject(error), () => reject(error))\n }\n const fail = (error: unknown) => rejectRun(error, true)\n\n const accept = (event: RawEvent) => {\n if (settled) return\n const payload = event.payload\n if (event.type === \"chat:start\") {\n started = true\n return\n }\n if (event.type === \"system:error\") {\n const error = new HeadlessError(String(payload.message || \"headless run failed\"), {\n session_id, chat_run_id: chatRunId, event: payload,\n })\n if (!started) {\n rejectRun(error)\n } else {\n if (systemErrorTimeout) clearTimeout(systemErrorTimeout)\n systemErrorTimeout = setTimeout(() => fail(error), SYSTEM_ERROR_CHAT_END_GRACE_MS)\n }\n return\n }\n if (event.type !== \"chat:end\") return\n if (payload.status !== \"completed\") {\n rejectRun(new HeadlessError(errorMessageFromResult(payload.result) ?? `headless run ${String(payload.status || \"failed\")}`, {\n session_id, chat_run_id: chatRunId, event: payload,\n }))\n return\n }\n try {\n finish(normalizeResult<T>(payload.result, Boolean(options.schema)))\n } catch (error) {\n rejectRun(error)\n }\n }\n const observe = (type: string, payload: Record<string, unknown>) => {\n if (settled || (payload.session_id && payload.session_id !== session_id)) return\n const runId = payload.chat_run_id\n const event = { type, payload }\n if (typeof runId !== \"string\" || !runId) {\n if (!runId && chatRunId === null && type === \"system:error\"\n && payload.session_id === session_id && !beforeAck.has(\"\")) {\n beforeAck.set(\"\", [event])\n }\n return\n }\n if (chatRunId === null) {\n const pending = beforeAck.get(runId) ?? []\n pending.push(event)\n beforeAck.set(runId, pending)\n } else if (runId === chatRunId) {\n accept(event)\n }\n }\n function onChatStart(payload: ChatStartPayload) { observe(\"chat:start\", payload) }\n function onChatEnd(payload: ChatEndPayload) { observe(\"chat:end\", payload) }\n function onSystemError(payload: SystemErrorPayload) { observe(\"system:error\", payload) }\n function onTurnEvents(data: TurnEventsPayload, acknowledge?: () => void) {\n acknowledgeTurnEvents(acknowledge)\n if (data.session_id !== session_id) return\n for (const event of cursor.consume(data.events.map((event) => ({\n ...event, log_seq: event.log_seq ?? undefined,\n step_log_seq: event.step_log_seq ?? undefined, delta_seq: event.delta_seq ?? undefined,\n }))).events) {\n if ([\"chat:start\", \"chat:end\", \"system:error\"].includes(event.type)) observe(event.type, event.payload)\n }\n }\n function subscribe() {\n if (settled) return\n const after = Math.min(...[...subscriptions].map((item) => item.subscription().after_log_seq ?? 0))\n socket.emit(\"session:subscribe\", {\n session_id, event_format: \"raw\", ...(after > 0 ? { after_log_seq: after } : {}),\n })\n }\n\n socket.on(\"chat:start\", onChatStart)\n socket.on(\"chat:end\", onChatEnd)\n socket.on(\"system:error\", onSystemError)\n socket.on(\"turn:events\", onTurnEvents)\n socket.on(\"connect\", subscribe)\n subscribe()\n socket.emit(\n \"chat:send\",\n {\n session_id,\n message: prompt as unknown as ChatSendPayload[\"message\"],\n headless: true,\n output_schema: options.schema ?? null,\n model: options.model ?? null,\n refs: options.refs as ChatSendPayload[\"refs\"],\n topic_asset_refs: options.topicAssetRefs as ChatSendPayload[\"topic_asset_refs\"],\n },\n (response) => {\n acknowledgeSend(response)\n if (settled) {\n handleLateAck?.(response)\n return\n }\n if (response?.status !== \"accepted\") {\n const validationError = beforeAck.get(\"\")?.[0]\n if ((response == null || (isRecord(response) && Object.keys(response).length === 0)) && validationError) {\n accept(validationError)\n return\n }\n rejectRun(new HeadlessError(response?.message ?? \"headless run was not accepted\", response))\n return\n }\n if (typeof response.chat_run_id !== \"string\" || !response.chat_run_id) {\n rejectRun(new HeadlessError(\"headless run acknowledgement has no run ID\", response))\n return\n }\n chatRunId = response.chat_run_id\n const pending = beforeAck.get(chatRunId) ?? []\n beforeAck.clear()\n for (const event of pending) accept(event)\n },\n )\n })\n }\n}\n\nfunction normalizeResult<T>(result: unknown, hasSchema: boolean): T | string {\n if (!isRecord(result)) {\n throw new HeadlessError(\"headless run finished without a result\", result)\n }\n const errMsg = typeof result.err_msg === \"string\" ? result.err_msg : \"\"\n if (errMsg) {\n throw new HeadlessError(errMsg, result)\n }\n if (!hasSchema) {\n const text = result.result\n return typeof text === \"string\" ? text : String(text ?? \"\")\n }\n const { err_msg: _errMsg, ...businessResult } = result\n return businessResult as T\n}\n\nfunction errorMessageFromResult(result: unknown): string | null {\n if (isRecord(result) && typeof result.err_msg === \"string\" && result.err_msg) {\n return result.err_msg\n }\n return null\n}\n\nfunction ensureSocketConnected(\n socket: ReturnType<BladeClient[\"socket\"]>,\n timeoutMs: number,\n detail: Record<string, unknown>,\n): Promise<void> {\n if (socket.connected) {\n return Promise.resolve()\n }\n return new Promise((resolve, reject) => {\n let settled = false\n const timeout = setTimeout(() => {\n finish(() => reject(new HeadlessError(`socket connection timed out after ${timeoutMs}ms`, detail)))\n }, timeoutMs)\n const onConnect = () => finish(resolve)\n const onConnectError = (error: unknown) => {\n finish(() => reject(new HeadlessError(\"socket connection failed\", { ...detail, event: error })))\n }\n const finish = (callback: () => void) => {\n if (settled) return\n settled = true\n clearTimeout(timeout)\n socket.off(\"connect\", onConnect)\n socket.off(\"connect_error\", onConnectError)\n callback()\n }\n socket.on(\"connect\", onConnect)\n socket.on(\"connect_error\", onConnectError)\n socket.connect()\n })\n}\n\nfunction acceptedRunId(ack: unknown): string | null {\n return isRecord(ack) && ack.status === \"accepted\" && typeof ack.chat_run_id === \"string\" && ack.chat_run_id\n ? ack.chat_run_id : null\n}\n\nfunction waitForCleanupAck<T = unknown>(\n socket: ReturnType<BladeClient[\"socket\"]>,\n deadline: number,\n request: (acknowledge: (response: T) => void) => void,\n): Promise<AckOutcome<T>> {\n if (!socket.connected) return Promise.resolve({ status: \"unconfirmed\", reason: \"disconnected\" })\n if (Date.now() >= deadline) return Promise.resolve({ status: \"unconfirmed\", reason: \"ack_timeout\" })\n return new Promise((resolve) => {\n const timer = setTimeout(() => finish({ status: \"unconfirmed\", reason: \"ack_timeout\" }), Math.max(0, deadline - Date.now()))\n let finished = false\n const finish = (outcome: AckOutcome<T>) => {\n if (finished) return\n finished = true\n clearTimeout(timer)\n socket.off(\"disconnect\", onDisconnect)\n resolve(outcome)\n }\n const onDisconnect = () => finish({ status: \"unconfirmed\", reason: \"disconnected\" })\n socket.on(\"disconnect\", onDisconnect)\n try {\n request((ack) => finish({ status: \"received\", ack }))\n } catch (error) {\n finish({ status: \"unconfirmed\", reason: \"emit_failed\", error })\n }\n })\n}\n","import type { BladeClient } from \"../blade-client\"\n\n/** 一台远程电脑在某个会话眼里的样子。 */\nexport interface SessionComputer {\n id: string\n label: string\n hostname?: string | null\n os?: string | null\n arch?: string | null\n /** 那台机器的用户主目录,命令默认在这里执行。 */\n home?: string | null\n /** daemon 启动时所在的目录。 */\n workspace?: string | null\n blade_home?: string | null\n allowed_paths?: string[]\n agent_runtimes?: unknown[]\n daemon_version?: string | null\n created_at: string\n last_seen_at?: string | null\n /** 这台电脑此刻连着后端。由服务端读心跳时间判定,不做实时探测。 */\n online: boolean\n /** 本次会话可用,默认启用,明确停用后为 false。和 `online` 互相独立。 */\n enabled: boolean\n}\n\nexport interface SessionComputerList {\n computers: SessionComputer[]\n}\n\n/**\n * 账号级电脑目录里的一台机器。\n *\n * 只有「这台机器登记过、此刻在不在线」这类账号事实,**没有**会话授权状态——\n * 「本次会话能不能用它」是另一件事,由会话接口回答。两者混在一起说,用户就会\n * 把「在线」当成「已授权」,或者反过来。\n */\nexport interface AccountComputer {\n id: string\n label: string\n hostname?: string | null\n os?: string | null\n arch?: string | null\n blade_home?: string | null\n workspace?: string | null\n daemon_version?: string | null\n created_at: string\n last_seen_at?: string | null\n online: boolean\n}\n\nexport interface AccountComputerList {\n computers: AccountComputer[]\n}\n\n/**\n * 一台电脑在界面上该显示成什么状态。\n *\n * - `enabled` 本次会话已启动\n * - `offline` 没启动且当前离线\n * - `idle` 没启动,在线\n *\n * 判定只写这一份,界面只管样式和排版——两边各写一份必然会分叉,\n * 然后其中一边的兜底会把另一边的错误盖住。\n */\nexport type ComputerState = \"enabled\" | \"offline\" | \"idle\"\n\nexport function computerState(computer: SessionComputer): ComputerState {\n if (computer.enabled) return \"enabled\"\n return computer.online ? \"idle\" : \"offline\"\n}\n\n/**\n * 这台电脑跑的是哪一类系统。\n *\n * 判定放这里、图标映射留给界面:`os` 是 daemon 上报的 `runtime.GOOS`,\n * 各处自己 `startsWith` 一遍必然会分叉。\n */\nexport type ComputerOS = \"macos\" | \"windows\" | \"linux\" | \"unknown\"\n\nexport function computerOS(computer: SessionComputer): ComputerOS {\n const os = (computer.os ?? \"\").toLowerCase()\n if (os.startsWith(\"darwin\") || os.startsWith(\"mac\")) return \"macos\"\n if (os.startsWith(\"windows\")) return \"windows\"\n if (os.startsWith(\"linux\")) return \"linux\"\n return \"unknown\"\n}\n\n/** 系统与架构,例如 `darwin/arm64`。信息不全时尽量给出已知的那部分。 */\nexport function computerPlatformLabel(computer: SessionComputer): string {\n const os = (computer.os ?? \"\").trim()\n const arch = (computer.arch ?? \"\").trim()\n if (os && arch) return `${os}/${arch}`\n return os || arch || \"\"\n}\n\n/**\n * 那台电脑上 blade daemon 的版本。\n *\n * 服务端存的就是 daemon 上报的完整串(dev 构建带 commit),这里原样用,\n * 不在前端另拼一套格式——拼两份迟早对不上。\n */\nexport function computerDaemonVersion(computer: SessionComputer): string {\n return (computer.daemon_version ?? \"\").trim()\n}\n\n/**\n * 列表顺序:按接入时间,稳定不变。\n *\n * **刻意不按在线/可用排序。** 那样排看着\"手边的在前面\",代价是电脑上下线、\n * 勾选状态一变,整个列表就重排——用户正要点的那一项会在手指底下跑掉。\n * 一个会自己动的列表比一个排序不那么聪明的列表难用得多。\n *\n * 用 `created_at` 而不是名字:改名不会让位置变,新接入的稳定排在末尾。\n */\nexport function sortComputers(computers: SessionComputer[]): SessionComputer[] {\n return [...computers].sort((a, b) => {\n const byCreated = (a.created_at ?? \"\").localeCompare(b.created_at ?? \"\")\n if (byCreated !== 0) return byCreated\n return a.label.localeCompare(b.label)\n })\n}\n\n/** 会话可以操作哪些远程电脑。 */\nexport class ComputersResource {\n constructor(private client: BladeClient) {}\n\n /**\n * 列出当前账号登记过的全部电脑及其在线状态。\n *\n * 首页还没有会话,也要能看到同一份清单——判定各写一份必然分叉,一边的兜底会把\n * 另一边的错误盖住(#1597)。所以账号事实只从这一个接口读。\n */\n async listAccount(): Promise<AccountComputerList> {\n const data = await this.client.json<{\n instances: Array<Omit<AccountComputer, \"online\"> & { online?: boolean }>\n }>(\"GET\", \"/api/daemon/instances\")\n return {\n computers: (data.instances ?? []).map((instance) => ({\n ...instance,\n online: Boolean(instance.online),\n })),\n }\n }\n\n /**\n * 列出当前用户的全部电脑,带上\"在不在线\"和\"这次会话能不能用\"。\n * 服务端只查库,电脑离线时同样返回,所以拿得到\"它离线了\"这个结论。\n */\n list(sessionId: string): Promise<SessionComputerList> {\n return this.client.json(\n \"GET\",\n `/api/sessions/${encodeURIComponent(sessionId)}/computers`,\n )\n }\n\n /**\n * 启动或停止一台电脑。只改这次会话的可用范围,不会碰远程机器,\n * 电脑离线时同样能登记,等它上线就直接可用。\n */\n setEnabled(\n sessionId: string,\n computer: string,\n enabled: boolean,\n ): Promise<SessionComputer> {\n return this.client.json(\n \"PUT\",\n `/api/sessions/${encodeURIComponent(sessionId)}/computers/${encodeURIComponent(computer)}/enabled`,\n { enabled },\n )\n }\n}\n","import type { BladeClient } from \"../blade-client\"\n\n/** 用户接进来的一台手机。 */\nexport interface PhoneDevice {\n id: string\n /** 展示名,重名时后台会追加序号;用户可以认这个。 */\n label: string\n /** `ro.serialno`,设备身份。智能体用它指定 `adb -s`。 */\n serial: string\n model?: string | null\n android_version?: string | null\n created_at: string\n last_seen_at?: string | null\n /** 此刻隧道连着后台。由隧道服务实时判定,不读心跳时间。 */\n online: boolean\n /**\n * 沙盒里的 adb 此刻能不能对这台手机执行命令。\n *\n * 与 `online` 分开:手机连着但沙盒里没装 adb、或者 adb 认证没过,用户执行\n * `adb shell` 照样失败,而 `online` 仍然是 true。\n */\n adb_online: boolean\n /** 本次会话已启用它。与 `online` 互相独立。 */\n enabled: boolean\n /** 当前绑定到哪个会话;`null` 表示没有被任何会话使用。 */\n session_id?: string | null\n}\n\nexport interface PhoneList {\n phones: PhoneDevice[]\n}\n\n/** 用户级接入密钥。设置页只展示它,手机把它填进 App 就能连。 */\nexport interface PhoneAccessKey {\n key: string\n /**\n * **服务器地址本身**(协议+主机+端口),不带隧道路径。\n *\n * 由服务端从请求来源推导,不接受手填;手机 App 自己补 `/api/mobile/hub`。\n * 用户看到的应该是 `http://agent.ba.test` 这样能一眼认出的地址,而不是一个\n * 他不需要理解、还容易抄错的路径。\n */\n hub_url: string\n /**\n * 手机连接器的下载地址。\n *\n * 默认是服务端的相对路径(`/api/phone/connector.apk`,由后端读构建产物发出去);\n * 管理员可以配成自己的静态文件地址。相对路径由前端按当前 origin 展开。\n */\n connector_url: string\n}\n\nexport interface PhonePipeline {\n running: boolean\n /** 最后一帧距今多久;-1 表示还没出过帧。静止画面不出帧是正常的。 */\n last_frame_ago_ms: number\n viewers: number\n width: number\n height: number\n codec: string\n start_error: string\n}\n\nexport interface PhoneHealth {\n online: boolean\n reason: string\n /** 沙盒已休眠(不是\"手机坏了\"),前端据此给\"打开会话唤醒\"而不是\"重试\"。 */\n dormant: boolean\n pipeline: PhonePipeline | null\n}\n\n/**\n * 一台手机在界面上该显示成什么状态。\n *\n * 与 `computerState` 同形同语义:判定只写这一份,界面只管样式和排版。\n * 两边各写一份必然会分叉,然后其中一边的兜底会把另一边的错误盖住。\n */\nexport type PhoneState = \"enabled\" | \"offline\" | \"idle\"\n\nexport function phoneState(phone: PhoneDevice): PhoneState {\n if (phone.enabled) return \"enabled\"\n return phone.online ? \"idle\" : \"offline\"\n}\n\n/** 列表顺序:按接入时间,稳定不变;不按在线状态重排。 */\nexport function sortPhones(phones: PhoneDevice[]): PhoneDevice[] {\n return [...phones].sort((a, b) => {\n const byCreated = (a.created_at ?? \"\").localeCompare(b.created_at ?? \"\")\n if (byCreated !== 0) return byCreated\n return a.label.localeCompare(b.label)\n })\n}\n\n/** 手机的 adb 序列号,展示时用不会太长的那一截。 */\nexport function phoneSerialLabel(phone: PhoneDevice): string {\n return phone.serial.trim()\n}\n\nexport class PhonesResource {\n constructor(private client: BladeClient) {}\n\n /** 账号下的全部手机(不含\"本次会话是否可用\")。 */\n async listAccount(): Promise<PhoneList> {\n return this.client.json<PhoneList>(\"GET\", \"/api/phone/devices\")\n }\n\n /**\n * 当前接入密钥;没有就补一个。\n *\n * **取的时候不轮换**:每次打开设置页都换钥匙会让已配好的手机集体掉线。\n */\n getKey(): Promise<PhoneAccessKey> {\n return this.client.json<PhoneAccessKey>(\"GET\", \"/api/phone/key\")\n }\n\n /** 换一把新密钥(旧的立即失效)。 */\n resetKey(): Promise<{ key: string }> {\n return this.client.json<{ key: string }>(\"POST\", \"/api/phone/key/reset\")\n }\n\n /** 作废密钥;设备记录保留,用户下次取密钥会得到一把新的。 */\n async revokeKey(): Promise<void> {\n await this.client.fetch(\"DELETE\", \"/api/phone/key\")\n }\n\n async remove(phoneId: string): Promise<void> {\n await this.client.fetch(\"DELETE\", `/api/phone/devices/${encodeURIComponent(phoneId)}`)\n }\n\n /** 本次会话能用的手机 + 账号下的其他手机。 */\n listForSession(sessionId: string): Promise<PhoneList> {\n return this.client.json<PhoneList>(\n \"GET\",\n `/api/sessions/${encodeURIComponent(sessionId)}/phones`,\n )\n }\n\n setEnabled(sessionId: string, phoneId: string, enabled: boolean): Promise<PhoneDevice> {\n return this.client.json<PhoneDevice>(\n \"PUT\",\n `/api/sessions/${encodeURIComponent(sessionId)}/phones/${encodeURIComponent(phoneId)}/enabled`,\n { enabled },\n )\n }\n\n health(sessionId: string, phoneId: string): Promise<PhoneHealth> {\n return this.client.json<PhoneHealth>(\n \"GET\",\n `/api/sessions/${encodeURIComponent(sessionId)}/phones/${encodeURIComponent(phoneId)}/health`,\n )\n }\n\n /**\n * WHEP 信令:POST 一个 SDP offer,拿到 answer。\n *\n * 走 `textFromInit` 而不是 `json()`:SDP 是纯文本,`json()` 会强制序列化成\n * JSON;也不能用裸 `fetch`,那会丢掉 bearer token。\n */\n async whep(sessionId: string, phoneId: string, offerSdp: string): Promise<string> {\n return this.client.textFromInit(\n `/api/sessions/${encodeURIComponent(sessionId)}/phones/${encodeURIComponent(phoneId)}/whep`,\n {\n method: \"POST\",\n body: offerSdp,\n headers: { \"content-type\": \"application/sdp\" },\n },\n )\n }\n\n /** 用户点「刷新画面」:让后台重新确认隧道服务并忘掉记住的 token。 */\n async wake(sessionId: string, phoneId: string): Promise<void> {\n await this.client.json(\n \"POST\",\n `/api/sessions/${encodeURIComponent(sessionId)}/phones/${encodeURIComponent(phoneId)}/wake`,\n )\n }\n}\n","import type { BladeClient } from \"../blade-client\"\n\nexport interface ChatCompletionRequest {\n model: string\n messages: { role: string; content?: unknown; [key: string]: unknown }[]\n tools?: { type: \"function\"; function: { name: string; description?: string; parameters: Record<string, unknown> } }[]\n tool_choice?: \"auto\" | \"none\" | \"required\" | { type: \"function\"; function: { name: string } }\n stream?: false\n [key: string]: unknown\n}\nexport interface ChatCompletion {\n id: string\n object: \"chat.completion\"\n created: number\n model: string\n choices: { index: number; finish_reason: string; message: { role: \"assistant\"; content: string | null; tool_calls?: { id: string; type: \"function\"; function: { name: string; arguments: string } }[] } }[]\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number }\n}\n\n/** One model call. Returned tool calls are data; BA does not execute them. */\nexport class LlmResource {\n constructor(private client: BladeClient) {}\n readonly chat = { completions: { create: (body: ChatCompletionRequest, options: { signal?: AbortSignal } = {}): Promise<ChatCompletion> =>\n this.client.jsonFromInit(\"/api/llm/chat/completions\", { method: \"POST\", body: JSON.stringify(body), signal: options.signal }) } }\n}\n","import type { BladeClient } from \"../blade-client\"\n\nexport interface ModelOption {\n id: string\n label: string\n thinkingAvailable?: boolean\n reasoningLevels?: string[]\n defaultReasoningLevel?: string\n /**\n * 把这个模型发给 `baseUrl` 时该用的名字。`id` 是平台内部标识,接了多个模型服务时\n * 形如 `provider-xxx::name`,直接发过去会被拒。不在 `baseUrl` 那个服务上的模型\n * 这里是空串——自己做模型选择器时据此过滤。\n */\n serviceModelId?: string\n}\n\nexport interface ModelCatalog {\n default: string\n models: ModelOption[]\n unavailableProviderIds?: string[]\n unavailableModelIds?: string[]\n /**\n * 平台默认模型服务的 OpenAI 兼容地址(Server ≥ 提供 `baseUrl` 的版本才有,否则为空)。\n * 自建应用可以带用户的 PAT 直接调它,不必让用户自己填地址——网关端口各部署不同,\n * 推算不出来。\n *\n * 这是**服务端视角**的地址:平台可能配的是 `http://127.0.0.1:30000/v1`,从自己后端\n * 转发没问题,直接丢给浏览器就指向用户自己的机器了。默认形态是后端透传(密钥也不该\n * 进浏览器),浏览器直连只适合这个地址对浏览器同样可达的场景。\n */\n baseUrl?: string\n /**\n * 直接调 `baseUrl` 时该用的默认模型名。**不要用 `default`**——那是平台内部标识,\n * 平台默认模型来自额外接的模型服务时它带 `provider-xxx::` 前缀,发过去只会得到\n * 「模型不存在」。没有可直调的模型时为空串。\n */\n defaultServiceModel?: string\n}\n\n/** Server 可供当前用户选择的模型目录。 */\nexport class ModelsResource {\n constructor(private client: BladeClient) {}\n\n list(options: { signal?: AbortSignal } = {}): Promise<ModelCatalog> {\n return this.client.jsonFromInit(\"/api/config/models\", { signal: options.signal })\n }\n}\n","export function isLocalConnectorName(name: string): boolean {\n return name.startsWith(\"connector.personal.\") || name.startsWith(\"connector.builtin.\")\n}\n\nimport type { BladeClient } from \"../blade-client\"\nimport type { SessionPluginConfigState, SessionPluginConfigUpdate } from \"./sessions\"\n\nexport interface ConnectorConnection {\n status: \"disconnected\" | \"connected\" | \"auth_required\"\n revision: number\n account_label: string\n verified_at: string\n}\n\nexport interface AccountConnector {\n available?: boolean\n\t authorization?: { type: \"browser\" | \"device\"; url: string } | null\n name: string\n display_name: string\n operations: number\n connection: ConnectorConnection\n description: string\n source: \"personal\" | \"builtin\"\n active: boolean\n}\n\nexport interface ConnectorDraft {\n display_name: string\n description: string\n url?: string\n bearer_token?: string\n}\n\nexport interface ConnectorConnectionView {\n url?: string | null\n description?: string\n\n display_name?: string\n\t authorization?: { type: \"browser\" | \"device\"; url: string } | null\n name: string\n config: SessionPluginConfigState\n connection: ConnectorConnection\n}\n\n/** Platform approval classification with a verifiable source; unknown is not exemption. */\nexport type ConnectorApprovalStatus = \"exempt\" | \"review_required\" | \"unknown\"\n\nexport interface ConnectorDomain {\n id: string\n name: string\n description?: string\n}\n\n/** SW reports each capability independently; BA controls only its local binding. */\nexport interface ConnectorCapability {\n category?: string\n category_name?: string\n tool_name?: string\n /** The local selection key; operation id may instead be its MCP tool name. */\n capability_id?: string\n approval?: ConnectorApprovalStatus\n approval_evidence?: string\n effect?: string\n /** SW implements this operation; current permission availability is reported by status. */\n executable?: boolean\n id: string\n name: string\n identity: \"bot\" | \"user\"\n status: \"available\" | \"not_selected\" | \"permission_required\" | \"user_auth_required\" | \"app_required\" | \"unsupported\" | \"unknown\" | \"temporarily_unavailable\"\n scopes: string[]\n /** Alternative grants accepted by SW for this capability. */\n scope_alternatives?: string[]\n /** Grants that remain required alongside the resolved alternative. */\n required_scopes?: string[]\n description: string\n limitations: string[]\n default?: boolean\n reason?: string\n next_action?: string\n actor?: string\n evidence?: string\n verified_at?: number\n}\n\nexport interface ConnectorPermission {\n /** Application activation and personal consent are independent. */\n app_status?: \"granted\" | \"missing\" | \"unknown\"\n user_status?: \"granted\" | \"not_granted\" | \"unknown\"\n category_name?: string\n template?: boolean\n scope: string\n name: string\n identity: \"bot\" | \"user\"\n description?: string\n approval?: string\n approval_status?: ConnectorApprovalStatus\n approval_evidence?: string\n status?: string\n evidence?: string\n}\n\nexport interface ConnectorAuthorizationFailure {\n code: string\n message: string\n retryable: boolean\n next_action?: string\n platform_code?: string\n platform_request_id?: string\n trace_id: string\n}\n\nexport interface ConnectorAuthorizationStep {\n action?: string\n id: string\n state: string\n message: string\n capabilities?: string[]\n /** Unix milliseconds. */\n at: number\n}\n\nexport interface ConnectorAuthorization {\n authorization_result?: {status:\"waiting\"|\"complete\"|\"partial\"|\"incomplete\";mode:\"automatic\"|\"manual\";capabilities:string[];missing_permissions:{scope:string;identity:\"bot\"|\"user\";status:string}[];next_action:string;manual_url?:string}\n permission_template?: { id: string; name: string; source: string }\n catalog_revision?: string\n domains?: ConnectorDomain[]\n operations?: ConnectorCapability[]\n current_step?: ConnectorAuthorizationStep\n /** The old binding is gone; the initial capability directory can be retried. */\n catalog_unavailable?: boolean\n connected?: boolean\n /** Local BA binding. Disabling it leaves the SW account and PA subscription intact. */\n enabled?: boolean\n /** A new binding is waiting for its first finish; explicit disablement clears this intent. */\n activation_pending?: boolean\n connection_id?: string\n revision?: number\n phase: \"disconnected\" | \"app\" | \"app_ready\" | \"permissions\" | \"user\" | \"expired\" | \"ready\"\n authorization_url?: string\n /** Unix seconds. */\n expires_at?: number\n app_id?: string\n label?: string\n user_authorized: boolean\n delivery_bound: boolean\n subscription_state?: \"not_bound\" | \"enabled\" | \"paused\" | \"missing\"\n capabilities?: ConnectorCapability[]\n permissions?: ConnectorPermission[]\n selected_capabilities?: string[]\n steps?: ConnectorAuthorizationStep[]\n attempt_id?: string\n trace_id?: string\n error?: ConnectorAuthorizationFailure\n}\n\nexport interface ConnectorAuthorizationOptions {\n /** Bind an authorization step to the expected connection; required for remove. Never MCP authority. */\n expected_connection_id?: string\n capabilities?: string[]\n attempt_id?: string\n /** Applied by BA only on explicit finish; false preserves a disabled binding. */\n enable?: boolean\n}\n\nexport interface ConnectorAuthorizationPlan {\n recovery_requirements?: Array<{ connection_id: string; app_id: string; capabilities: string[]; identity: \"bot\" | \"user\"; mode: \"automatic\" | \"manual\" | \"enable\"; required_scopes: string[]; scopes: string[]; next_action: string; manual_url?: string }>\n capabilities: ConnectorCapability[]\n requested_scopes: string[]\n blocked_capabilities: string[]\n permissions_url?: string\n ready_capabilities?: string[]\n user_authorization_capabilities?: string[]\n admin_review_capabilities?: string[]\n unknown_capabilities?: string[]\n unsupported_capabilities?: string[]\n}\n\nexport interface ConnectorAuditEvent {\n type?: string\n at_ms?: number\n platform_code?: string\n platform_request_id?: string\n id?: string | number\n trace_id?: string\n action?: string\n capability?: string\n outcome?: string\n code?: string\n message?: string\n at?: number\n [key: string]: unknown\n}\n\nexport interface ConnectorRuntimeDiagnostics {\n account_id: string\n /** Last recorded channel event; it is not an independent live health check. */\n channel_state: string\n last_event_at_ms: number\n channel_events: Array<{ trace_id: string; at_ms: number; type: string }>\n deliveries: Array<{ delivery_id: string; status: string; attempt: number; next_at_ms: number; created_at_ms: number }>\n delivery_attempts: Array<{ id: string | number; delivery_id: string; attempt: number; started_at_ms: number; finished_at_ms: number; status: string }>\n}\n\nexport interface ConnectorDiagnostics {\n connection: ConnectorAuthorization\n audit_events: ConnectorAuditEvent[]\n runtime?: ConnectorRuntimeDiagnostics\n}\n\nexport type ConnectorAuthorizationAction = \"authorize\" | \"permissions\" | \"pause\" | \"resume\" | \"app\" | \"user\" | \"poll\" | \"finish\" | \"bind\" | \"cancel\" | \"check\" | \"remove\"\n\nexport interface ConnectorArtifact {\n artifact_id: string\n name: string\n size: number\n sha256: string\n content_type: string\n expires_at?: number\n reference_scope: { connection_id: string; app_id: string }\n /** Authenticated same-origin path; use downloadFile rather than a public URL. */\n download_path: string\n}\n\nexport class ConnectorsResource {\n constructor(private client: BladeClient) {}\n\n /** Stage an explicit attachment in the current user's SW connection. Reuse requestId on retry. */\n async uploadFile(name: string, file: Blob, fileName: string, requestId: string): Promise<ConnectorArtifact> {\n const form = new FormData()\n form.append(\"file\", file, fileName)\n form.append(\"request_id\", requestId)\n const response = await this.client.formData(\"POST\", `/api/connectors/${encodeURIComponent(name)}/files`, form)\n return response.json()\n }\n\n /** Fetch a private artifact through BA authentication; no SW PAT or public URL is exposed. */\n downloadFile(name: string, artifactId: string): Promise<Blob> {\n return this.client.blob(\"GET\", `/api/connectors/${encodeURIComponent(name)}/files/${encodeURIComponent(artifactId)}`)\n }\n\n authorization(name: string, init?: RequestInit): Promise<ConnectorAuthorization> {\n return this.client.jsonFromInit(`/api/connectors/${encodeURIComponent(name)}/authorization`, init)\n }\n\n authorize(name: string, action: ConnectorAuthorizationAction, pushUrl?: string, options?: ConnectorAuthorizationOptions): Promise<ConnectorAuthorization> {\n return this.client.json(\"POST\", `/api/connectors/${encodeURIComponent(name)}/authorization`, {\n action, ...options, ...(pushUrl ? { push_url: pushUrl } : {}),\n })\n }\n\n authorizationPlan(name: string, capabilities: string[]): Promise<ConnectorAuthorizationPlan> {\n return this.client.json(\"POST\", `/api/connectors/${encodeURIComponent(name)}/authorization`, { action: \"plan\", capabilities })\n }\n\n diagnostics(name: string, init?: RequestInit): Promise<ConnectorDiagnostics> {\n return this.client.jsonFromInit(`/api/connectors/${encodeURIComponent(name)}/diagnostics`, init)\n }\n\n create(draft: ConnectorDraft & { url: string }): Promise<{ name: string }> {\n return this.client.json(\"POST\", \"/api/connectors\", draft)\n }\n\n update(name: string, draft: ConnectorDraft): Promise<{ name: string }> {\n return this.client.json(\"PATCH\", `/api/connectors/${encodeURIComponent(name)}`, draft)\n }\n\n delete(name: string): Promise<{ name: string }> {\n return this.client.json(\"DELETE\", `/api/connectors/${encodeURIComponent(name)}`)\n }\n\n /** Create a generation conversation and send its visible Skill request.\n * Hosts use onCreated only to register caches and navigate before sending. */\n async startGeneration({ connector, onCreated, initiator = \"sdk\" }: {\n connector?: Pick<AccountConnector, \"name\" | \"display_name\">\n onCreated?: (created: { session_id: string; intent: string }) => void | Promise<void>\n initiator?: \"ui\" | \"sdk\"\n } = {}): Promise<{ session_id: string; sent: boolean }> {\n const intent = connector ? \"修改连接器\" : \"创建连接器\"\n const request = connector ? \"修改选定的连接器\" : \"创建连接器\"\n const { session_id } = await this.client.sessions.createSessionWithRequest({ intent, solution_id: \"connector_generate\", initiator })\n await onCreated?.({ session_id, intent })\n const session = await this.client.sessions.connect(session_id)\n try {\n const sent = await session.send(`请使用连接器生成器,帮我${request}。先确认我希望连接的系统和需要的功能,再按技能引导我完成。`, {\n mode: \"executing\", refs: [{ provider: \"skill\", id: \"generate-connector\", label: \"连接器生成器\" }],\n ...(connector ? { contextAttachments: [{\n id: \"connector-generation-target\", label: \"选定的连接器\",\n content: JSON.stringify({ name: connector.name, display_name: connector.display_name }),\n update_format: \"snapshot\" as const,\n }] } : {}),\n })\n return { session_id, sent }\n } finally { session.dispose() }\n }\n\n list(init?: RequestInit): Promise<{ connectors: AccountConnector[] }> {\n return this.client.jsonFromInit(\"/api/connectors\", init)\n }\n\n listForSession(sessionId: string, init?: RequestInit): Promise<{ connectors: AccountConnector[] }> {\n return this.client.jsonFromInit(`/api/connectors?session_id=${encodeURIComponent(sessionId)}`, init)\n }\n\n read(name: string, init?: RequestInit): Promise<ConnectorConnectionView> {\n return this.client.jsonFromInit(`/api/connectors/${encodeURIComponent(name)}/connection`, init)\n }\n\n connect(name: string, update: SessionPluginConfigUpdate & { session_id?: string }, init?: RequestInit): Promise<ConnectorConnectionView> {\n return this.client.jsonFromInit(`/api/connectors/${encodeURIComponent(name)}/connection`, {\n method: \"PUT\", body: JSON.stringify(update), ...init,\n })\n }\n\n browserAuthorizationUrl(name: string): string {\n return new URL(`connector-auth/${encodeURIComponent(name)}`, `${this.client.options.baseUrl.replace(/\\/$/, \"\")}/`).toString()\n }\n\n /** One-use, one-minute identity handoff to this client's trusted Blade origin.\n * Tokens travel only through a source/origin-bound message, never a URL/storage. */\n bindBrowserAuthorizationFrame(frame: HTMLIFrameElement, name: string): () => void {\n const nonce = Array.from(crypto.getRandomValues(new Uint8Array(32)), (value) => value.toString(16).padStart(2, \"0\")).join(\"\")\n const url = new URL(this.browserAuthorizationUrl(name), window.location.href)\n url.searchParams.set(\"embedded\", \"1\")\n url.searchParams.set(\"handoff\", nonce)\n url.searchParams.set(\"parent_origin\", window.location.origin)\n const receive = (event: MessageEvent) => {\n if (event.origin !== url.origin || event.source !== frame.contentWindow || event.data?.type !== \"blade:connector-auth-ready\" || event.data?.nonce !== nonce) return\n cleanup()\n frame.contentWindow?.postMessage({ type: \"blade:connector-auth-identity\", nonce, token: this.client.token }, url.origin)\n }\n const timeout = window.setTimeout(() => cleanup(), 60_000)\n const cleanup = () => { window.clearTimeout(timeout); window.removeEventListener(\"message\", receive) }\n window.addEventListener(\"message\", receive)\n frame.src = url.toString()\n return cleanup\n }\n\n async startBrowserAuthorization(name: string, sessionId?: string): Promise<{ session_id: string; view: ConnectorConnectionView }> {\n const view = await this.read(name)\n if (view.authorization?.type !== \"browser\") throw new Error(\"该连接器没有网页登录入口\")\n const id = sessionId ?? (await this.client.sessions.createSessionWithRequest({\n intent: `连接 ${view.display_name || \"业务系统\"}`, memory_enabled: false,\n })).session_id\n // Existing browser endpoints enforce ownership for both fresh and reused sessions.\n await this.client.json(\"POST\", `/api/sessions/${encodeURIComponent(id)}/browser/wake`, {})\n const tabs = await this.client.json<{ data?: Array<{ url: string }> }>(\"GET\", `/api/sessions/${encodeURIComponent(id)}/browser/tabs`)\n const hasBusinessTab = tabs.data?.some(({ url }) => url && url !== \"about:blank\" && !/^http:\\/\\/(?:127\\.0\\.0\\.1|localhost):9223\\/home(?:[/?#]|$)/.test(url))\n if (!sessionId || !hasBusinessTab) await this.client.json(\"POST\", `/api/sessions/${encodeURIComponent(id)}/browser/tabs`, { url: view.authorization.url })\n return { session_id: id, view }\n }\n\n verify(name: string): Promise<ConnectorConnectionView> {\n return this.client.json(\"POST\", `/api/connectors/${encodeURIComponent(name)}/connection:verify`)\n }\n\n disconnect(name: string): Promise<ConnectorConnectionView> {\n return this.client.json(\"DELETE\", `/api/connectors/${encodeURIComponent(name)}/connection`)\n }\n}\n","import { type } from \"arktype\"\nimport type { Solution } from \"./solution\"\n\nexport const SessionStatus = type(\n \"'created' | 'running' | 'completed' | 'failed' | 'interrupted' | 'waiting_for_input'\",\n)\nexport type SessionStatus = typeof SessionStatus.infer\n\nexport type ModeId = \"planning\" | \"executing\"\n\nexport type PublishedSolutionRef =\n | { source: \"builtin\"; name: string }\n | { source: \"hub\"; org: string; name: string }\n\n/** 回放时录制内容的播放倍速。 */\nexport type ReplaySpeed = 1 | 2 | 5\n\n/**\n * 新建回放会话时的默认倍速。\n *\n * 所有创建入口都用它——曾经侧栏走 API 默认 5x、设置菜单初始化成 1x,\n * 同一个源对话从不同入口开出来速度不一样。\n */\nexport const DEFAULT_REPLAY_SPEED: ReplaySpeed = 5\n\nexport interface ReplayState {\n source_session_id?: string\n status?: \"replay\" | \"autonomous\"\n speed?: ReplaySpeed\n next_source_entry_id?: string | null\n ended_at?: string | null\n autonomous_reason?: string | null\n}\n\n/** 某个会话能否作为回放来源。 */\nexport interface ReplayPreview {\n session_id: string\n intent?: string | null\n supported: boolean\n /** supported 为 false 时给出的原因,可直接展示给用户。 */\n reason?: string | null\n}\n\nexport interface SessionPortMapping {\n container_port: number\n host_port: number\n}\n\n/**\n * 列表搜索时单条会话的命中信息。\n * - field='title':关键词出现在 intent 里,snippet 为 null(标题本身就在 UI 上)\n * - field='content':关键词出现在历史消息里,snippet 含截窗预览与角色\n */\nexport interface SessionSearchMatch {\n field: \"title\" | \"content\"\n snippet: { role: string; text: string } | null\n}\n\nexport const SessionInfo = type({\n id: \"string\",\n intent: \"string\",\n status: SessionStatus,\n created_at: \"string\",\n updated_at: \"string\",\n \"shared?\": \"boolean\",\n \"anonymous?\": \"boolean\",\n \"memory_enabled?\": \"boolean\",\n \"is_persistent?\": \"boolean\",\n \"initiator?\": \"'ui' | 'sdk' | 'unknown' | null\",\n \"is_headless?\": \"boolean\",\n \"viewer_role?\": \"'owner' | 'viewer'\",\n \"model?\": \"string | null\",\n \"enable_thinking?\": \"boolean | null\",\n \"solution_id?\": \"string | null\",\n \"solution_ref?\": \"unknown\",\n \"biz_role_id?\": \"string | null\",\n \"solution?\": \"unknown\",\n \"plan_summary?\": \"string | null\",\n \"replay_state?\": \"unknown\",\n \"is_pinned?\": \"boolean\",\n \"pinned_at?\": \"string | null\",\n \"is_example?\": \"boolean\",\n \"ports?\": \"unknown\",\n \"disable_tools?\": \"string[]\",\n \"workspace_path?\": \"string | null\",\n \"ba_version?\": \"string | null\",\n \"sandbox_version?\": \"string | null\",\n \"chat_group_id?\": \"string | null\",\n \"match?\": \"unknown\",\n})\nexport type SessionInfo = Omit<\n typeof SessionInfo.infer,\n \"solution\" | \"ports\" | \"match\"\n> & {\n shared?: boolean\n memory_enabled?: boolean\n is_persistent?: boolean\n is_headless?: boolean\n viewer_role?: \"owner\" | \"viewer\"\n model?: string | null\n enable_thinking?: boolean | null\n solution_id?: string | null\n solution_ref?: PublishedSolutionRef | null\n biz_role_id?: string | null\n solution?: Solution | null\n replay_state?: ReplayState | null\n is_pinned?: boolean\n pinned_at?: string | null\n is_example?: boolean\n ports?: SessionPortMapping[]\n disable_tools?: string[]\n workspace_path?: string | null\n ba_version?: string | null\n sandbox_version?: string | null\n chat_group_id?: string | null\n /** 仅在带 q 搜索的列表响应中出现;普通列表里此字段缺省。 */\n match?: SessionSearchMatch | null\n}\n\nexport interface SessionDetail extends SessionInfo {\n preview_url?: string | null\n /**\n * 会话级环境变量(owner-only)。后端仅在 GET detail 和 PUT /env 响应中返回,\n * 列表/搜索响应不带此字段。调用 setSessionEnv 后可类型安全地读回。\n */\n env?: Record<string, string>\n}\n","import type { McpSourceConfig } from \"../resources/sessions\"\n\nexport type TextFile = {\n path: string\n content: string\n}\n\nexport type SolutionDefinition =\n | { id: string; role?: string }\n /** 自定义 Solution:文本文件路径均相对于 Solution 根目录。 */\n | { files: TextFile[]; role?: string }\n\nexport type SkillFile = TextFile & {\n /** 二进制内容使用 base64;省略时为 UTF-8 文本。 */\n encoding?: \"utf-8\" | \"base64\"\n executable?: boolean\n}\n\nexport interface SkillDefinition {\n /** 会话内安装名,格式为 `组织/名称`。 */\n name: string\n /** 必须包含根目录的 SKILL.md。 */\n files: SkillFile[]\n}\n\nexport interface SessionConfig {\n /** Application tools bound at session creation, before any execution. */\n mcpSources?: McpSourceConfig[]\n /** Server 模型目录中的 model ID。 */\n model?: string\n enableThinking?: boolean\n memoryEnabled?: boolean\n compactionRatio?: number\n env?: Record<string, string>\n disableTools?: string[]\n}\n\n/**\n * 声明一个待创建的会话。传给 `client.sessions.create(...)` 后,SDK 会先准备\n * Solution,再创建会话并安装 Skill;Promise resolve 时会话已经可以使用。\n */\nexport interface SessionDefinition {\n intent?: string\n solution?: SolutionDefinition\n skills?: SkillDefinition[]\n config?: SessionConfig\n}\n\nexport type SessionSetupStage = \"solution\" | \"session\" | \"skill\" | \"connection\"\n\n/** 声明式会话准备失败;stage 和 sessionId 可直接用于界面提示或日志。 */\nexport class SessionSetupError extends Error {\n readonly name = \"SessionSetupError\"\n readonly cause?: unknown\n\n constructor(\n message: string,\n readonly stage: SessionSetupStage,\n readonly sessionId?: string,\n options?: { cause?: unknown },\n ) {\n super(message)\n this.cause = options?.cause\n }\n}\n","import { isLocalConnectorName } from \"./connectors\"\nimport type { BackgroundTask, BackgroundTaskStopResult } from \"../schemas/background\"\nimport type { TurnProjection } from \"../schemas/projection\"\nimport type { McpAppArchive } from \"../schemas/mcp-app\"\nimport { DEFAULT_REPLAY_SPEED } from \"../schemas/session\"\nimport type {\n PublishedSolutionRef,\n ReplayPreview,\n ReplaySpeed,\n SessionDetail,\n SessionInfo,\n} from \"../schemas/session\"\nimport type {\n McpAppContextState,\n McpAppContextUpdate,\n} from \"../schemas/mcp-app\"\nimport type { Task } from \"../schemas/task\"\nimport type { BladeClient, UploadProgress } from \"../blade-client\"\nimport type { AgentSession } from \"../session/agent-session\"\nimport {\n SessionSetupError,\n type SessionDefinition,\n type SkillDefinition,\n type SolutionDefinition,\n} from \"../session/definition\"\nimport type { SessionProfile } from \"../types/sdk-profile\"\nimport { projectHistory, type RawHistoryEntry } from \"../shared/projection\"\n\nexport interface SessionPlugin {\n /** Technical ID: always used for paths, authorization, caching and calls. */\n name: string\n /** Business name declared by the package; null falls back to `name`. */\n display_name?: string | null\n /**\n * Opaque content token for the package-local icon, or null when the plugin\n * ships none. Pass it to `fetchSessionPluginIcon`; never used as a path.\n */\n icon?: string | null\n /** Whether BH lists this plugin for the current user; null means BH was unavailable. */\n installed: boolean | null\n /**\n * Configuration standing as the list could determine it without reading the\n * user's Home: `unchecked` means nobody has looked yet, never \"configured\".\n */\n config?: SessionPluginConfigSummary\n /** Persisted session choice, independent of preparation success. */\n active: boolean\n /** Previously prepared skills may remain after deselection. */\n projected: boolean\n projection_source?: string | null\n status: string\n reason?: string | null\n}\n\n/** Selection/preparation result; installed facts are obtained from the BH-backed list. */\nexport type SessionPluginActivation = Pick<SessionPlugin, \"name\" | \"active\" | \"status\" | \"reason\">\n\n/**\n * How a plugin's user configuration stands.\n *\n * `not_required` — the package ships no config schema, the plugin keeps its old\n * behaviour. `required` — a schema exists but the stored configuration is\n * missing or does not validate. `configured` — stored configuration validates.\n * `error` — the declaration itself is unusable.\n */\nexport type SessionPluginConfigStateName = \"not_required\" | \"required\" | \"configured\" | \"error\"\n\n/** List-level view: `unchecked` means nobody has read this user's file yet. */\nexport type SessionPluginConfigSummary =\n | SessionPluginConfigStateName\n | \"unchecked\"\n\nexport interface SessionPluginConfigError {\n /** JSON Pointer of the offending field. */\n path: string\n /** Value-free message; the platform never echoes submitted secrets. */\n message: string\n}\n\nexport interface SessionPluginHostState {\n digest: string\n revision: string\n state: string\n reason: string\n restarts: number\n recent?: string[]\n}\n\nexport interface SessionPluginConfigState {\n state: SessionPluginConfigStateName\n reason: string | null\n /** The package-declared JSON Schema (Draft 2020-12), or null. */\n schema: Record<string, unknown> | null\n /** Stored values with `writeOnly` properties removed. */\n values: Record<string, unknown>\n /** JSON Pointers of `writeOnly` properties that currently hold a value. */\n write_only: string[]\n /** Opaque revision for optimistic concurrency; null when nothing is stored. */\n revision: string | null\n errors: SessionPluginConfigError[]\n auth_status?: \"login_required\" | \"ready\" | \"expired\"\n global_ready?: boolean\n}\n\nexport interface SessionPluginConfigSet {\n /** JSON Pointer; arrays are replaced as a whole. */\n path: string\n value: unknown\n}\n\nexport interface SessionPluginConfigUpdate {\n /** Omit (or pass null) to publish unconditionally. */\n expected_revision?: string | null\n set?: SessionPluginConfigSet[]\n remove?: string[]\n}\n\nexport interface CreateSessionRequest {\n /** Notification owner. Built-in Web declares ui; external applications default to sdk. */\n initiator?: \"ui\" | \"sdk\"\n /** 认证创建独立匿名沙盒;链接持有者可继续聊天,不继承个人资源。 */\n anonymous?: boolean\n intent?: string\n /** 正式 Solution 来源。Hub 使用 { source: \"hub\", org, name }。 */\n solution_ref?: PublishedSolutionRef\n /** @deprecated 请使用结构化的 solution_ref;继续支持以保证现有 SDK 调用无感升级。 */\n solution_id?: string\n /** 从已有会话复制其不可变 Solution 与 Skill 运行快照。 */\n solution_snapshot_session_id?: string\n biz_role_id?: string | null\n model?: string | null\n enable_thinking?: boolean | null\n memory_enabled?: boolean | null\n env?: Record<string, string>\n disable_tools?: string[] | null\n mcp_sources?: McpSourceConfig[]\n /** 此会话的所有普通轮次直接执行工具,不弹审批。 */\n skip_confirmations?: boolean\n session_solution_files?: { path: string; content: string }[]\n session_solution_asset_id?: string | null\n compaction_ratio?: number | null\n chat_group_id?: string | null\n}\n\nexport interface McpSourceConfig {\n /** Source summary shown before lazy tool discovery. */\n description?: string\n id: string\n url: string\n bearer_token?: string | null\n exposure?: \"lazy\" | \"eager\"\n include_tools?: string[] | null\n eager_tools?: string[]\n}\n\n/** Sandbox only. Omitted fields are retained; lists/maps replace their previous value. */\nexport interface UpdateSessionConfigurationRequest {\n version: string\n expected_revision?: number\n solution_ref?: PublishedSolutionRef\n solution_id?: string\n session_solution_files?: { path: string; content: string }[]\n session_solution_asset_id?: string\n biz_role_id?: string\n model?: string\n enable_thinking?: boolean | null\n memory_enabled?: boolean\n env?: Record<string, string>\n disable_tools?: string[]\n mcp_sources?: McpSourceConfig[]\n skip_confirmations?: boolean\n compaction_ratio?: number | null\n}\n\nexport interface SessionConfiguration {\n session_id: string\n version: string | null\n revision: number\n configuration: {\n solution_identity: Record<string, unknown> | null\n solution_version: string | null\n biz_role_id: string | null\n biz_role_version: string | null\n model: string | null\n enable_thinking: boolean | null\n memory_enabled: boolean\n env: Record<string, string>\n disable_tools: string[]\n mcp_sources: Omit<McpSourceConfig, \"bearer_token\">[]\n skip_confirmations: boolean\n compaction_ratio: number | null\n }\n}\n\nexport interface CheckpointNode {\n id: string\n parent_id: string | null\n content_preview: string\n content: string\n timestamp: string\n}\n\nexport type ContentPart =\n | { type: \"text\"; text: string }\n | { type: \"image_url\"; image_url: { url: string; detail?: string } }\n\nexport interface HistoryNode {\n id: string\n parent_id: string | null\n kind: string\n role: string\n timestamp: string\n preview: string\n content: string | ContentPart[]\n tool_calls: Array<{\n id?: string\n type?: string\n function?: { name?: string; arguments?: string }\n }> | null\n usage: { prompt_tokens?: number; completion_tokens?: number; total_tokens?: number } | null\n total_tokens: number\n token_diff: number\n is_deprecated: boolean\n loop_name: string\n}\n\nexport interface SessionHistory {\n nodes: HistoryNode[]\n active_branch: string | null\n branches: string[]\n system_prompt_tokens?: number | null\n tools_tokens?: number | null\n tokenizer_model?: string | null\n}\n\nexport interface TokenizeResult {\n model: string\n prompt_tokens: number\n prompt: string\n}\n\nexport interface PaginatedSessionsResult {\n items: SessionInfo[]\n total: number\n limit: number\n offset: number\n content_match_truncated?: boolean\n}\n\nexport interface GlobalSearchConversationResult {\n type: \"conversation\"\n session: SessionInfo\n snippet: string\n matched: \"title\" | \"content\"\n}\n\nexport interface GlobalSearchFileResult {\n type: \"file\"\n session: SessionInfo\n path: string\n name: string\n snippet: string\n matched: \"name\" | \"path\"\n}\n\nexport type GlobalSearchResultItem =\n | GlobalSearchConversationResult\n | GlobalSearchFileResult\n\nexport interface GlobalSearchResult {\n items: GlobalSearchResultItem[]\n truncated: boolean\n indexing: boolean\n}\n\ninterface ListSessionsPageParams {\n limit: number\n offset: number\n solution_id?: string\n solution_registry_id?: string\n q?: string\n chat_group_id?: string\n}\n\nexport interface SkillDevSession {\n session: SessionInfo\n skill_id: string\n display_name: string\n skill_description: string\n}\n\nexport interface ShareLinkResult {\n token: string\n url: string\n expires_at: string | null\n}\n\nexport interface SessionContextStats {\n tokens_used: number\n context_window: number\n compaction_ratio: number\n}\n\nexport interface SessionTurnsPage {\n turns: TurnProjection[]\n nextBefore: string | null\n currentMode: \"planning\" | \"executing\"\n}\n\n/** `getSessionTurnsPage` 的取数参数:向后翻页(before)或从某条发言定位(fromEntryId)。 */\nexport interface SessionTurnsQuery {\n limit?: number\n before?: string\n /**\n * 从这条用户发言开始、一直到最新。服务端按当前分支校验它,命中不了不会回空页\n * (`entry_not_found` / `entry_not_in_branch`),窗口首条就是这条发言,它的\n * `nextBefore` 可以继续当 `before` 往上翻。\n */\n fromEntryId?: string\n}\n\n/**\n * 服务端明确说这条发言不在当前分支上(`entry_not_found` / `entry_not_in_branch`),\n * 和\"这次没取到\"(网络 / 5xx / 鉴权)分开:前者说明这个定位目标已经没了,后者只说明这次失败。\n */\nexport function isEntryGoneError(error: unknown): boolean {\n const status = (error as { status?: unknown } | null)?.status\n return status === 404 || status === 409\n}\n\n/** 侧栏「消息历史」的一条:只有 id、标题和时间,没有消息体。 */\nexport interface SessionTurnIndexItem {\n entryId: string\n preview: string\n createdAt: string | null\n}\n\nexport interface SessionTurnIndex {\n sessionId: string\n items: SessionTurnIndexItem[]\n}\n\nexport interface HistoricalCommand {\n deliveryId: string\n toolCallId?: string\n action: string\n payload?: unknown\n}\n\nexport type ResultFeedbackReason =\n | \"not_solved\"\n | \"inaccurate\"\n | \"incomplete\"\n | \"needs_major_changes\"\n | \"too_slow\"\n | \"other\"\n\nexport interface ResultFeedback {\n session_id: string\n assistant_entry_id: string\n surface: \"chat\" | \"software_factory\" | \"unknown\"\n project_id: string | null\n helpful: boolean\n reason: ResultFeedbackReason | null\n created_at: string\n updated_at: string\n}\n\nexport interface FileEntry {\n name: string\n path: string\n is_dir: boolean\n created_at: number\n tags?: string[]\n}\n\nexport type UploadFileEntry = File | { file: File; name: string }\n\nexport interface UploadFilesOptions {\n onProgress?: (progress: UploadProgress) => void\n}\n\nexport interface AppCliDefinition {\n /** 智能体在 Bash 中直接执行的业务命令名,例如 `library`。 */\n command: string\n /** Python 脚本由沙盒系统 Python 执行;executable 必须是 Linux 可执行文件。 */\n runtime: \"python\" | \"executable\"\n /** CLI 文件本身,或浏览器可以读取的 URL。 */\n source: Blob | string | URL\n /** source 是普通 Blob 时使用的上传文件名。 */\n filename?: string\n}\n\nexport interface AppCliAttachment {\n command: string\n runtime: \"python\" | \"executable\"\n digest: string\n}\n\nexport interface ImportPreviewSkill {\n name: string\n description: string\n path: string\n}\n\n/** Legacy archive decode shape only; custom scenario scripts are never executed. */\nexport interface ImportPreviewScenario {\n scenario?: { name?: string }\n skills?: string[]\n preview_urls?: string[]\n init_script?: string\n generated_at?: string\n}\n\nexport interface ImportPreview {\n user_messages: string[]\n turn_count: number\n skills: ImportPreviewSkill[]\n /** Retained for older responses. Current servers always return null. */\n scenario: ImportPreviewScenario | null\n}\n\nexport interface ImportSessionOptions {\n /** 导入后改用这个正式 Solution 的最新版。 */\n solution_ref?: PublishedSolutionRef\n /** 导入后改用已有会话的完整运行快照。 */\n solution_snapshot_session_id?: string\n}\n\nfunction toCreateSessionPayload(request: CreateSessionRequest) {\n const solutionRef = request.solution_ref ?? externalSolutionRef(request.solution_id)\n return {\n intent: request.intent ?? \"\",\n // The server defaults to sdk; older APIs reject even this redundant field.\n initiator: request.initiator === \"sdk\" ? undefined : request.initiator,\n anonymous: request.anonymous,\n solution_id: solutionRef ? undefined : request.solution_id,\n solution_ref: solutionRef,\n biz_role_id: request.biz_role_id ?? null,\n model: request.model ?? null,\n enable_thinking: request.enable_thinking ?? null,\n memory_enabled: request.memory_enabled ?? null,\n env: request.env,\n disable_tools: request.disable_tools ?? null,\n mcp_sources: request.mcp_sources,\n skip_confirmations: request.skip_confirmations,\n session_solution_asset_id: request.session_solution_asset_id ?? null,\n session_solution_files: request.session_solution_files,\n solution_snapshot_session_id: request.solution_snapshot_session_id ?? null,\n compaction_ratio: request.compaction_ratio ?? null,\n ...(request.chat_group_id ? { chat_group_id: request.chat_group_id } : {}),\n }\n}\n\nconst builtinSolutionIds = new Set([\n \"app-dev\",\n \"general_chat\",\n \"night_build\",\n \"skill_editor\",\n \"smart_bid\",\n \"solution_generate\",\n])\n\nfunction externalSolutionRef(\n solutionId: string | undefined,\n): PublishedSolutionRef | undefined {\n if (!solutionId) return undefined\n const normalized = solutionId === \"default\" ? \"general_chat\" : solutionId.trim()\n if (builtinSolutionIds.has(normalized)) {\n return { source: \"builtin\", name: normalized }\n }\n const parts = normalized.split(\"/\")\n if (parts.length === 2 && parts.every(Boolean)) {\n return { source: \"hub\", org: parts[0], name: parts[1] }\n }\n return undefined\n}\n\nexport class SessionsResource {\n private readonly pendingImages = new Map<string, Promise<Blob>>()\n\n /** Fetch an immutable message image using this client's authenticated identity. */\n fetchImage(sessionId: string, assetId: string, preview = true): Promise<Blob> {\n return this.fetchImagePath(`/api/sessions/${encodeURIComponent(sessionId)}/media/${encodeURIComponent(assetId)}`, preview)\n }\n\n /** Fetch a public-share image; the server validates the share token on every request. */\n fetchSharedImage(token: string, assetId: string, preview = true): Promise<Blob> {\n return this.fetchImagePath(`/api/share/${encodeURIComponent(token)}/media/${encodeURIComponent(assetId)}`, preview)\n }\n\n private fetchImagePath(resource: string, preview: boolean): Promise<Blob> {\n const path = `${resource}${preview ? \"?variant=preview\" : \"\"}`\n const identity = this.client.buildAuthedUrl(path)\n const existing = this.pendingImages.get(identity)\n if (existing) return existing\n const pending = this.client.blob(\"GET\", path).finally(() => this.pendingImages.delete(identity))\n this.pendingImages.set(identity, pending)\n return pending\n }\n\n constructor(private client: BladeClient) {}\n\n getMcpApp(sessionId: string, sourceId: string, init?: RequestInit): Promise<McpAppArchive> {\n return this.client.jsonFromInit(`/api/sessions/${encodeURIComponent(sessionId)}/mcp-apps/${encodeURIComponent(sourceId)}`, init)\n }\n\n onMcpAppChanged(sessionId: string, sourceId: string, listener: () => void): () => void {\n let socket = this.client.socket()\n const changed = (payload: { session_id: string; source_id: string }) => {\n if (payload.session_id === sessionId && payload.source_id === sourceId) listener()\n }\n socket.on(\"mcp-app:changed\", changed)\n socket.on(\"connect\", listener)\n const off = this.client.onSocketReplaced(() => {\n socket.off(\"mcp-app:changed\", changed)\n socket.off(\"connect\", listener)\n socket = this.client.socket()\n socket.on(\"mcp-app:changed\", changed)\n socket.on(\"connect\", listener)\n })\n return () => {\n off()\n socket.off(\"mcp-app:changed\", changed)\n socket.off(\"connect\", listener)\n }\n }\n\n callMcpApp(sessionId: string, sourceId: string, request: {\n request_id: string; name: string; arguments: Record<string, unknown>\n }, init?: RequestInit): Promise<{ response: Record<string, unknown>; replayed: boolean }> {\n return this.client.jsonFromInit(`/api/sessions/${encodeURIComponent(sessionId)}/mcp-apps/${encodeURIComponent(sourceId)}/calls`, {\n ...init, method: \"POST\", body: JSON.stringify(request),\n })\n }\n\n /**\n * 连接一个已存在的会话,返回实时会话对象 AgentSession\n * (自动完成历史加载、Socket.IO 订阅、断线重连补数)。\n */\n connect(sessionId: string): Promise<AgentSession> {\n return this.client.hub.connect(sessionId)\n }\n\n listSessionPlugins(sessionId: string, init?: RequestInit): Promise<{ plugins: SessionPlugin[]; sync_version: number; sync_pending: boolean }> {\n return this.client.jsonFromInit(`/api/sessions/${encodeURIComponent(sessionId)}/plugins`, init)\n }\n\n setSessionPluginActivation(sessionId: string, name: string, active: boolean, init?: RequestInit): Promise<{ plugin: SessionPluginActivation; sync_version: number }> {\n const kind = isLocalConnectorName(name) ? \"connectors\" : \"plugins\"\n return this.client.jsonFromInit(`/api/sessions/${encodeURIComponent(sessionId)}/${kind}/${encodeURIComponent(name)}:activation`, { method: \"POST\", body: JSON.stringify({ active }), ...init })\n }\n\n /**\n * Fetch a plugin's package-local icon as bytes.\n *\n * The request carries the client's own bearer credentials, so callers turn\n * the blob into an object URL instead of pointing `<img>` at an API path and\n * hoping the request is authenticated.\n */\n fetchSessionPluginIcon(sessionId: string, name: string): Promise<Blob> {\n return this.client.blob(\"GET\", `/api/sessions/${encodeURIComponent(sessionId)}/plugins/${encodeURIComponent(name)}/icon`)\n }\n\n /** Authenticated URL for the icon; useful where a blob URL cannot be used. */\n sessionPluginIconUrl(sessionId: string, name: string): string {\n return this.client.buildAuthedUrl(`/api/sessions/${encodeURIComponent(sessionId)}/plugins/${encodeURIComponent(name)}/icon`)\n }\n\n /**\n * 准备一个插件的配置:把包准备好并读出用户的配置契约,**不启用**它。\n *\n * 开启插件前必须先走这一步:缺配置时用户只会看到配置表单,服务端不会先把\n * active 持久化成 true 再靠补偿关掉。它不修改会话的插件选择、不连接 MCP。\n */\n prepareSessionPluginConfig(sessionId: string, name: string, init?: RequestInit): Promise<{ plugin: string; config: SessionPluginConfigState }> {\n return this.client.jsonFromInit(\n `/api/sessions/${encodeURIComponent(sessionId)}/plugins/${encodeURIComponent(name)}:prepare-config`,\n { method: \"POST\", ...init },\n )\n }\n\n /**\n * Read a plugin's configuration contract and the user's stored values.\n *\n * Secrets are never returned: `write_only` lists the pointers that hold one.\n */\n getSessionPluginConfig(sessionId: string, name: string, init?: RequestInit, scope: \"personal\" | \"global\" = \"personal\"): Promise<{ plugin: string; config: SessionPluginConfigState; can_configure_global?: boolean; host?: SessionPluginHostState | null }> {\n return this.client.jsonFromInit(`/api/sessions/${encodeURIComponent(sessionId)}/plugins/${encodeURIComponent(name)}/config?scope=${scope}`, init)\n }\n\n /**\n * Save explicit set/remove operations to encrypted server storage.\n *\n * Fields absent from both lists keep their stored value, so a form never has\n * to round-trip a secret. Rejections preserve the previous values; the\n * shared settings restart only the affected hosted plugin.\n */\n updateSessionPluginConfig(sessionId: string, name: string, update: SessionPluginConfigUpdate, init?: RequestInit, scope: \"personal\" | \"global\" = \"personal\"): Promise<{ plugin: string; config: SessionPluginConfigState }> {\n return this.client.jsonFromInit(`/api/sessions/${encodeURIComponent(sessionId)}/plugins/${encodeURIComponent(name)}/config?scope=${scope}`, { method: \"PUT\", body: JSON.stringify(update), ...init })\n }\n\n restartSessionPluginHost(sessionId: string, name: string): Promise<{ host: SessionPluginHostState | null }> {\n return this.client.jsonFromInit(`/api/sessions/${encodeURIComponent(sessionId)}/plugins/${encodeURIComponent(name)}/host`, { method: \"POST\" })\n }\n\n /** 创建新会话并直接连接,返回可收发消息的 AgentSession。 */\n async create(request: CreateSessionRequest | SessionDefinition = {}): Promise<AgentSession> {\n if (isSessionDefinition(request)) {\n return this.createDeclared(request)\n }\n const { session_id } = await this.createSessionWithRequest(request)\n return request.anonymous ? this.client.forAnonymousSession(session_id).sessions.connect(session_id) : this.connect(session_id)\n }\n\n private async createDeclared(definition: SessionDefinition): Promise<AgentSession> {\n const { intent, solution, skills = [], config } = definition\n validateDefinition(definition)\n let solutionRequest: Pick<CreateSessionRequest, \"solution_id\" | \"session_solution_asset_id\" | \"biz_role_id\"> = {}\n try {\n solutionRequest = solution ? await this.prepareSolution(solution) : {}\n } catch (error) {\n throw setupError(\"solution\", \"Solution 准备失败\", error)\n }\n\n let session_id: string\n try {\n const created = await this.createSessionWithRequest({\n intent,\n ...solutionRequest,\n model: config?.model,\n enable_thinking: config?.enableThinking,\n memory_enabled: config?.memoryEnabled,\n compaction_ratio: config?.compactionRatio,\n env: config?.env,\n disable_tools: config?.disableTools,\n mcp_sources: config?.mcpSources,\n })\n session_id = created.session_id\n } catch (error) {\n const assetId = solutionRequest.session_solution_asset_id\n const assetCleaned = await this.cleanupSolutionAsset(assetId)\n const cleanupMessage = assetId\n ? assetCleaned\n ? \";临时 Solution 已清理\"\n : `;临时 Solution ${assetId} 清理失败`\n : \"\"\n throw setupError(\"session\", `会话创建失败${cleanupMessage}`, error)\n }\n\n let installingSkill = \"\"\n try {\n for (const skill of skills) {\n installingSkill = skill.name\n await this.client.json(\"POST\", `/api/sessions/${encodeURIComponent(session_id)}/skills:upload`, {\n name: skill.name,\n files: skill.files,\n })\n }\n } catch (error) {\n const sessionCleaned = await this.deleteSession(session_id).then(\n () => true,\n () => false,\n )\n const assetCleaned = await this.cleanupSolutionAsset(solutionRequest.session_solution_asset_id)\n const cleanupMessage = sessionCleaned ? \"未完成的会话已清理\" : `请手动删除会话 ${session_id}`\n const assetCleanupMessage = assetCleaned ? \"\" : \";临时 Solution 清理失败\"\n throw setupError(\n \"skill\",\n `Skill \"${installingSkill}\" 安装失败;${cleanupMessage}${assetCleanupMessage}`,\n error,\n session_id,\n )\n }\n\n await this.cleanupSolutionAsset(solutionRequest.session_solution_asset_id)\n\n try {\n return await this.connect(session_id)\n } catch (error) {\n throw setupError(\"connection\", `会话连接失败;可使用 sessionId ${session_id} 重试`, error, session_id)\n }\n }\n\n private async prepareSolution(\n solution: SolutionDefinition,\n ): Promise<Pick<CreateSessionRequest, \"solution_id\" | \"session_solution_asset_id\" | \"biz_role_id\">> {\n if (\"id\" in solution) {\n return { solution_id: solution.id, biz_role_id: solution.role ?? null }\n }\n\n const prepared = await this.client.json<{ asset_id: string }>(\n \"POST\",\n \"/api/session-assets/solutions\",\n { files: solution.files },\n )\n return {\n session_solution_asset_id: prepared.asset_id,\n biz_role_id: solution.role ?? null,\n }\n }\n\n private async cleanupSolutionAsset(assetId?: string | null): Promise<boolean> {\n if (!assetId) return true\n try {\n await this.client.json(\"DELETE\", `/api/session-assets/solutions/${encodeURIComponent(assetId)}`)\n return true\n } catch {\n return false\n }\n }\n\n private fetchSessionsPage({\n limit,\n offset,\n solution_id,\n solution_registry_id,\n q,\n chat_group_id,\n }: ListSessionsPageParams): Promise<PaginatedSessionsResult> {\n const searchParams = new URLSearchParams()\n searchParams.set(\"limit\", String(limit))\n searchParams.set(\"offset\", String(offset))\n if (solution_registry_id) {\n searchParams.set(\"solution_registry_id\", solution_registry_id)\n } else if (solution_id) {\n searchParams.set(\"solution_id\", solution_id)\n }\n const trimmedQuery = q?.trim()\n if (trimmedQuery) searchParams.set(\"q\", trimmedQuery)\n if (chat_group_id) searchParams.set(\"chat_group_id\", chat_group_id)\n return this.client.json(\"GET\", `/api/sessions?${searchParams.toString()}`)\n }\n\n async listSessions(solution_id?: string): Promise<SessionInfo[]> {\n const pageSize = 100\n const sessions: SessionInfo[] = []\n let offset = 0\n while (true) {\n const page = await this.fetchSessionsPage({ limit: pageSize, offset, solution_id })\n sessions.push(...page.items)\n if (sessions.length >= page.total || page.items.length === 0) return sessions\n offset += page.items.length\n }\n }\n\n listSessionsPaginated(params: {\n limit: number\n offset: number\n solution_id?: string\n solution_registry_id?: string\n q?: string\n chat_group_id?: string\n }): Promise<PaginatedSessionsResult> {\n return this.fetchSessionsPage(params)\n }\n\n listSessionsWithSkillData(): Promise<SkillDevSession[]> {\n return this.client.json(\"GET\", \"/api/sessions/with-skill-data\")\n }\n\n searchOwnedContent(params: { q: string; limit?: number }): Promise<GlobalSearchResult> {\n const searchParams = new URLSearchParams({ q: params.q.trim() })\n if (params.limit !== undefined) searchParams.set(\"limit\", String(params.limit))\n return this.client.json(\"GET\", `/api/search?${searchParams.toString()}`)\n }\n\n createSession(\n intent?: string,\n ): Promise<{ session_id: string }> {\n return this.createSessionWithRequest({ intent })\n }\n\n createSessionWithRequest(request: CreateSessionRequest): Promise<{ session_id: string }> {\n return this.client.json(\"POST\", \"/api/sessions\", toCreateSessionPayload(request))\n }\n\n createWithProfile(params: {\n intent: string\n profile: SessionProfile\n }): Promise<{ session_id: string }> {\n const { intent, profile } = params\n return this.createSessionWithRequest({\n intent,\n ...profileToCreateSessionRequest(profile),\n })\n }\n\n getSession(sessionId: string, init?: RequestInit): Promise<SessionDetail> {\n return this.client.jsonFromInit(`/api/sessions/${sessionId}`, init)\n }\n\n updateSession(sessionId: string, payload: { intent?: string; chat_group_id?: string | null }): Promise<SessionDetail> {\n return this.client.json(\"PATCH\", `/api/sessions/${sessionId}`, payload)\n }\n\n getSessionConfiguration(sessionId: string, init?: RequestInit): Promise<SessionConfiguration> {\n return this.client.jsonFromInit(`/api/sessions/${encodeURIComponent(sessionId)}/configuration`, init)\n }\n\n /** Updates atomically between turns. A running/handoff session returns HTTP 409. */\n updateSessionConfiguration(sessionId: string, request: UpdateSessionConfigurationRequest): Promise<SessionConfiguration> {\n return this.client.json(\"PATCH\", `/api/sessions/${encodeURIComponent(sessionId)}/configuration`, request)\n }\n\n setSessionEnv(sessionId: string, env: Record<string, string>): Promise<SessionDetail> {\n return this.client.json(\"PUT\", `/api/sessions/${sessionId}/env`, { env })\n }\n\n pinSession(sessionId: string, pinned: boolean): Promise<SessionInfo> {\n return this.client.json(\"PATCH\", `/api/sessions/${sessionId}/pin`, { pinned })\n }\n\n startReplaySession(\n sourceSessionId: string,\n speed: ReplaySpeed = DEFAULT_REPLAY_SPEED,\n ): Promise<{ session_id: string }> {\n return this.client.json(\"POST\", `/api/sessions/${sourceSessionId}/replay`, { speed })\n }\n\n updateReplaySession(\n sessionId: string,\n payload: { speed?: ReplaySpeed; status?: \"autonomous\" },\n ): Promise<{ replay_state: SessionInfo[\"replay_state\"] }> {\n return this.client.json(\"PATCH\", `/api/sessions/${sessionId}/replay`, payload)\n }\n\n /** 查询会话能否作为回放来源;不支持时 reason 可直接展示,用来提前禁用入口。 */\n getReplayPreview(sessionId: string): Promise<ReplayPreview> {\n return this.client.json(\"GET\", `/api/sessions/${sessionId}/replay/preview`)\n }\n\n updateSharing(sessionId: string, shared: boolean): Promise<{ shared: boolean }> {\n return this.client.json(\"PATCH\", `/api/sessions/${sessionId}/sharing`, { shared })\n }\n\n updateSessionMemory(sessionId: string, memoryEnabled: boolean): Promise<{ memory_enabled: boolean }> {\n return this.client.json(\"PATCH\", `/api/sessions/${sessionId}/memory`, {\n memory_enabled: memoryEnabled,\n })\n }\n\n createShare(sessionId: string): Promise<ShareLinkResult> {\n return this.client.json(\"POST\", `/api/sessions/${sessionId}/share`, {})\n }\n\n revokeShare(sessionId: string, token: string): Promise<{ revoked: boolean }> {\n return this.client.json(\"DELETE\", `/api/sessions/${sessionId}/share/${encodeURIComponent(token)}`)\n }\n\n async getSharedSession(token: string): Promise<TurnProjection[]> {\n const entries = await this.client.jsonFromInit<RawHistoryEntry[]>(`/api/share/${encodeURIComponent(token)}`, {\n credentials: \"omit\",\n headers: { Accept: \"application/json\" },\n })\n return projectHistory(entries)\n }\n\n getSessionTasks(sessionId: string): Promise<Task[]> {\n return this.client.json(\"GET\", `/api/sessions/${sessionId}/tasks`)\n }\n\n /** Durable result for this execution; null until its run_end is committed. Owner only. */\n getRunResult<T = unknown>(sessionId: string, runId: string): Promise<SessionRunResult<T> | null> {\n return this.client.json(\"GET\", `/api/sessions/${encodeURIComponent(sessionId)}/runs/${encodeURIComponent(runId)}`)\n }\n\n async getSessionTurns(sessionId: string): Promise<TurnProjection[]> {\n const entries = await this.client.json<RawHistoryEntry[]>(\n \"GET\",\n `/api/sessions/${sessionId}/messages`,\n )\n return projectHistory(entries)\n }\n\n async getSessionTurnsPage(\n sessionId: string,\n options: SessionTurnsQuery = {},\n init: RequestInit = {},\n ): Promise<SessionTurnsPage> {\n const query = new URLSearchParams()\n if (options.limit !== undefined) query.set(\"limit\", String(options.limit))\n if (options.before !== undefined) query.set(\"before\", options.before)\n if (options.fromEntryId !== undefined) query.set(\"from_entry_id\", options.fromEntryId)\n const suffix = query.size ? `?${query}` : \"\"\n const page = await this.client.jsonFromInit<{\n turns: TurnProjection[]\n next_before: string | null\n current_mode: \"planning\" | \"executing\"\n }>(`/api/sessions/${encodeURIComponent(sessionId)}/turns${suffix}`, init)\n return {\n turns: page.turns,\n nextBefore: page.next_before,\n currentMode: page.current_mode,\n }\n }\n\n /**\n * 当前分支上可导航的用户发言目录(消息导航侧栏)。\n *\n * 只回 id、标题和时间:侧栏要列的是**整条会话**的发言,而窗口外的发言 id 只能\n * 从服务端拿;消息体仍然走 `/turns`。\n */\n async getSessionTurnIndex(sessionId: string): Promise<SessionTurnIndex> {\n const index = await this.client.json<{\n session_id: string\n items: Array<{ entry_id: string; preview: string; created_at: string | null }>\n }>(\"GET\", `/api/sessions/${encodeURIComponent(sessionId)}/turn-index`)\n return {\n sessionId: index.session_id,\n items: index.items.map((item) => ({\n entryId: item.entry_id,\n preview: item.preview,\n createdAt: item.created_at,\n })),\n }\n }\n\n getMcpAppContext(sessionId: string, sourceId: string, init?: RequestInit): Promise<McpAppContextState> {\n return this.client.jsonFromInit(`/api/sessions/${encodeURIComponent(sessionId)}/mcp-apps/${encodeURIComponent(sourceId)}/context`, init)\n }\n\n updateMcpAppContext(sessionId: string, sourceId: string, body: McpAppContextUpdate, init?: RequestInit): Promise<{ status: \"accepted\"; revision: string }> {\n return this.client.jsonFromInit(`/api/sessions/${encodeURIComponent(sessionId)}/mcp-apps/${encodeURIComponent(sourceId)}/context`, {\n ...init, method: \"POST\", body: JSON.stringify(body),\n })\n }\n\n async getSessionTurnCommands(sessionId: string): Promise<HistoricalCommand[]> {\n const commands = await this.client.json<Array<{\n delivery_id: string\n tool_call_id?: string | null\n action: string\n payload?: unknown\n }>>(\"GET\", `/api/sessions/${encodeURIComponent(sessionId)}/turn-commands`)\n return commands.map((command) => ({\n deliveryId: command.delivery_id,\n toolCallId: command.tool_call_id ?? undefined,\n action: command.action,\n payload: command.payload,\n }))\n }\n\n listResultFeedback(sessionId: string): Promise<ResultFeedback[]> {\n return this.client.json(\"GET\", `/api/sessions/${encodeURIComponent(sessionId)}/feedback`)\n }\n\n putResultFeedback(\n sessionId: string,\n assistantEntryId: string,\n feedback: { helpful: boolean; reason?: ResultFeedbackReason | null },\n ): Promise<ResultFeedback> {\n return this.client.json(\n \"PUT\",\n `/api/sessions/${encodeURIComponent(sessionId)}/turns/${encodeURIComponent(assistantEntryId)}/feedback`,\n feedback,\n )\n }\n\n getSessionContextStats(sessionId: string, init?: RequestInit): Promise<SessionContextStats> {\n return this.client.jsonFromInit(`/api/sessions/${sessionId}/context-stats`, init)\n }\n\n getSessionHistory(sessionId: string, init?: RequestInit): Promise<SessionHistory> {\n return this.client.jsonFromInit(`/api/sessions/${sessionId}/history`, init)\n }\n\n tokenizePrompt(prompt: string, model?: string): Promise<TokenizeResult> {\n return this.client.json(\"POST\", \"/api/sessions/tokenize/prompt\", { prompt, model })\n }\n\n tokenizeMessages(\n messages: Array<Record<string, unknown>>,\n options?: {\n model?: string\n add_generation_prompt?: boolean\n enable_thinking?: boolean | null\n tools?: Array<Record<string, unknown>>\n },\n ): Promise<TokenizeResult> {\n return this.client.json(\"POST\", \"/api/sessions/tokenize/messages\", {\n messages,\n model: options?.model,\n add_generation_prompt: options?.add_generation_prompt ?? true,\n enable_thinking: options?.enable_thinking ?? null,\n tools: options?.tools ?? null,\n })\n }\n\n getSessionCheckpoints(\n sessionId: string,\n init?: RequestInit,\n ): Promise<{ nodes: CheckpointNode[]; leaf_id: string | null }> {\n return this.client.jsonFromInit(`/api/sessions/${sessionId}/checkpoints`, init)\n }\n\n checkoutSession(\n sessionId: string,\n checkpointId: string,\n position: \"before\" | \"turn_end\",\n mode?: \"both\" | \"conversation\" | \"code\",\n linear?: boolean,\n ): Promise<{\n id: string\n content: string\n position: string\n mode?: string\n files_restored?: boolean\n linear?: boolean\n history_committed?: boolean\n file_checkpoint_cleanup_failed?: boolean\n warning?: string\n }> {\n return this.client.json(\"POST\", `/api/sessions/${sessionId}/checkout`, {\n checkpoint_id: checkpointId,\n position,\n ...(mode ? { mode } : {}),\n ...(linear ? { linear } : {}),\n })\n }\n\n async rewindSession(sessionId: string, checkpointId: string): Promise<{\n id: string\n content: string\n history_committed?: boolean\n file_checkpoint_cleanup_failed?: boolean\n warning?: string\n }> {\n const result = await this.checkoutSession(sessionId, checkpointId, \"before\")\n return {\n id: result.id,\n content: result.content,\n ...(result.history_committed !== undefined ? { history_committed: result.history_committed } : {}),\n ...(result.file_checkpoint_cleanup_failed !== undefined\n ? { file_checkpoint_cleanup_failed: result.file_checkpoint_cleanup_failed }\n : {}),\n ...(result.warning !== undefined ? { warning: result.warning } : {}),\n }\n }\n\n switchBranch(sessionId: string, checkpointId: string): Promise<{ id: string; leaf_id: string }> {\n return this.client.json(\"POST\", `/api/sessions/${sessionId}/switch-branch`, {\n checkpoint_id: checkpointId,\n })\n }\n\n listAnonymousSessions(): Promise<Array<{ id: string; intent: string; created_at: string; status: string }>> {\n return this.client.json(\"GET\", \"/api/anonymous-sessions\")\n }\n\n deleteAnonymousSession(sessionId: string): Promise<{ deleted: boolean }> {\n return this.client.json(\"DELETE\", `/api/anonymous-sessions/${encodeURIComponent(sessionId)}`)\n }\n\n deleteSession(\n sessionId: string,\n options?: { deleteWorkspace?: boolean },\n ): Promise<{ deleted: boolean; workspace_deleted?: boolean }> {\n const query = options?.deleteWorkspace ? \"?delete_workspace=true\" : \"\"\n return this.client.json(\"DELETE\", `/api/sessions/${sessionId}${query}`)\n }\n\n listBackgroundTasks(sessionId: string, init?: RequestInit): Promise<BackgroundTask[]> {\n return this.client.jsonFromInit(`/api/sessions/${sessionId}/background-tasks`, init)\n }\n\n getBackgroundTask(\n sessionId: string,\n taskId: string,\n tail = 100,\n init?: RequestInit,\n ): Promise<BackgroundTask> {\n return this.client.jsonFromInit(`/api/sessions/${sessionId}/background-tasks/${taskId}?tail=${tail}`, init)\n }\n\n stopBackgroundTask(\n sessionId: string,\n taskId: string,\n ): Promise<BackgroundTaskStopResult> {\n return this.client.json(\"POST\", `/api/sessions/${sessionId}/background-tasks/${taskId}/stop`)\n }\n\n\n probeSessionUrl(\n sessionId: string,\n url: string,\n ): Promise<{ reachable: boolean; requires_proxy: boolean }> {\n return this.client.json(\n \"GET\",\n `/api/sessions/${sessionId}/probe-url?url=${encodeURIComponent(url)}`,\n )\n }\n\n listDir(sessionId: string, dirPath: string, showHidden = false): Promise<FileEntry[]> {\n const query = showHidden ? \"?show_hidden=true\" : \"\"\n return this.client.json(\"GET\", `/api/sessions/${sessionId}/ls/${encodeURIComponent(dirPath)}${query}`)\n }\n\n async countFiles(sessionId: string, dirPath = \"\"): Promise<number> {\n const entries = await this.listDir(sessionId, dirPath)\n let count = 0\n for (const entry of entries) {\n count += entry.is_dir ? await this.countFiles(sessionId, entry.path) : 1\n }\n return count\n }\n\n /** 在浏览器中下载一个会话文件。 */\n async downloadFile(sessionId: string, filePath: string, downloadName?: string): Promise<void> {\n if (typeof document === \"undefined\") {\n throw new Error(\"downloadFile 只能在浏览器中使用\")\n }\n const response = await this.client.fetch(\n \"GET\",\n `/api/sessions/${encodeURIComponent(sessionId)}/files/${encodeURIComponent(filePath)}`,\n )\n const objectUrl = URL.createObjectURL(await response.blob())\n const anchor = document.createElement(\"a\")\n anchor.href = objectUrl\n anchor.download = downloadName || filePath.split(\"/\").pop() || \"download\"\n anchor.style.display = \"none\"\n document.body.appendChild(anchor)\n anchor.click()\n anchor.remove()\n globalThis.setTimeout(() => URL.revokeObjectURL(objectUrl), 1_000)\n }\n\n async uploadFiles(\n sessionId: string,\n dirPath: string,\n files: FileList | File[] | UploadFileEntry[],\n options: UploadFilesOptions = {},\n ): Promise<{\n uploaded: string[]\n failed: string[]\n results: Array<{ index: number; path?: string; error?: string }>\n }> {\n const formData = new FormData()\n const entries = Array.from(files).map((f) =>\n f instanceof File ? { file: f, name: f.name } : (f as { file: File; name: string }),\n )\n for (const entry of entries) {\n formData.append(\"files\", entry.file, entry.name)\n }\n const relativePaths = entries.map((e) => e.file.webkitRelativePath || e.name)\n if (relativePaths.some((p) => p.includes(\"/\"))) {\n formData.append(\"paths\", JSON.stringify(relativePaths))\n }\n const response = await this.client.formData(\n \"POST\",\n `/api/sessions/${sessionId}/upload/${encodeURIComponent(dirPath)}`,\n formData,\n { expectOk: false, onUploadProgress: options.onProgress },\n )\n return response.json()\n }\n\n /** 把应用自己的业务 CLI 安装到会话沙盒,并保留开发者声明的命令名。 */\n async attachAppCli(\n sessionId: string,\n definition: AppCliDefinition,\n ): Promise<AppCliAttachment> {\n let source: Blob\n if (definition.source instanceof Blob) {\n source = definition.source\n } else {\n const response = await globalThis.fetch(definition.source.toString())\n if (!response.ok) {\n throw new Error(`读取应用 CLI 失败:HTTP ${response.status}`)\n }\n source = await response.blob()\n }\n const filename =\n definition.filename ??\n (typeof File !== \"undefined\" && definition.source instanceof File\n ? definition.source.name\n : undefined) ??\n (definition.runtime === \"python\" ? \"app-cli.py\" : \"app-cli\")\n const form = new FormData()\n form.append(\"command\", definition.command)\n form.append(\"runtime\", definition.runtime)\n form.append(\"file\", source, filename)\n const response = await this.client.formData(\n \"POST\",\n `/api/sessions/${sessionId}/app-cli`,\n form,\n )\n return response.json()\n }\n\n async deleteFile(sessionId: string, filePath: string): Promise<void> {\n await this.client.json(\"DELETE\", `/api/sessions/${sessionId}/files/${encodeURIComponent(filePath)}`)\n }\n\n writeFile(sessionId: string, filePath: string, content: string): Promise<{ success: boolean }> {\n return this.client.json(\"PUT\", `/api/sessions/${sessionId}/files/${encodeURIComponent(filePath)}`, {\n content,\n })\n }\n\n renameFile(sessionId: string, filePath: string, newName: string): Promise<{ path: string }> {\n return this.client.json(\"POST\", `/api/sessions/${sessionId}/files/${encodeURIComponent(filePath)}/rename`, {\n new_name: newName,\n })\n }\n\n copyFile(sessionId: string, filePath: string): Promise<{ path: string }> {\n return this.client.json(\"POST\", `/api/sessions/${sessionId}/files/${encodeURIComponent(filePath)}/copy`)\n }\n\n shareFile(\n sessionId: string,\n sourcePath: string,\n linkName?: string,\n shareFolder?: string,\n ): Promise<{ path: string; target: string }> {\n return this.client.json(\"POST\", `/api/sessions/${sessionId}/share-file`, {\n source_path: sourcePath,\n link_name: linkName ?? \"\",\n share_folder: shareFolder ?? \"\",\n })\n }\n\n getDownloadDirUrl(sessionId: string, dirPath: string): string {\n return this.client.buildAuthedUrl(`/api/sessions/${sessionId}/download-dir/${encodeURIComponent(dirPath)}`)\n }\n\n async exportSession(sessionId: string): Promise<void> {\n await this.getSession(sessionId)\n const a = document.createElement(\"a\")\n a.href = this.client.buildAuthedUrl(`/api/sessions/${sessionId}/export`)\n a.download = `${sessionId}.zip`\n document.body.appendChild(a)\n a.click()\n a.remove()\n }\n\n async previewImport(file: File): Promise<ImportPreview> {\n const form = new FormData()\n form.append(\"file\", file)\n const res = await this.client.formData(\"POST\", \"/api/sessions/preview-import\", form)\n return res.json()\n }\n\n async importSession(\n file: File,\n name?: string,\n solutionOverride?: string | null | ImportSessionOptions,\n ): Promise<{ session_id: string }> {\n const form = new FormData()\n form.append(\"file\", file)\n if (name) form.append(\"name\", name)\n if (typeof solutionOverride === \"string\") {\n if (solutionOverride) form.append(\"solution_id\", solutionOverride)\n } else if (solutionOverride) {\n if (solutionOverride.solution_ref) {\n form.append(\"solution_ref\", JSON.stringify(solutionOverride.solution_ref))\n }\n if (solutionOverride.solution_snapshot_session_id) {\n form.append(\n \"solution_snapshot_session_id\",\n solutionOverride.solution_snapshot_session_id,\n )\n }\n }\n const res = await this.client.formData(\"POST\", \"/api/sessions/import\", form)\n return res.json()\n }\n}\n\nfunction isSessionDefinition(request: CreateSessionRequest | SessionDefinition): request is SessionDefinition {\n return \"solution\" in request || \"skills\" in request || \"config\" in request\n}\n\nfunction validateDefinition(definition: SessionDefinition): void {\n if (definition.solution) {\n if (\"id\" in definition.solution) {\n if (!definition.solution.id.trim()) {\n throw new SessionSetupError(\"Solution id 不能为空\", \"solution\")\n }\n } else {\n validateTextFiles(definition.solution.files, \"solution\", \"Solution\")\n if (!definition.solution.files.some((file) => file.path === \"solution.yaml\")) {\n throw new SessionSetupError(\"Solution 缺少根目录 solution.yaml\", \"solution\")\n }\n }\n }\n for (const skill of definition.skills ?? []) validateSkill(skill)\n}\n\nfunction validateSkill(skill: SkillDefinition): void {\n if (!/^[a-z0-9-]+\\/[a-z0-9-]+$/.test(skill.name)) {\n throw new SessionSetupError(`Skill name \"${skill.name}\" 必须是小写的 组织/名称`, \"skill\")\n }\n validateTextFiles(skill.files, \"skill\", `Skill \"${skill.name}\"`)\n if (!skill.files.some((file) => file.path === \"SKILL.md\")) {\n throw new SessionSetupError(`Skill \"${skill.name}\" 缺少根目录 SKILL.md`, \"skill\")\n }\n}\n\nfunction validateTextFiles(\n files: Array<{ path: string; content: string }>,\n stage: ConstructorParameters<typeof SessionSetupError>[1],\n label: string,\n): void {\n if (files.length === 0) throw new SessionSetupError(`${label} files 不能为空`, stage)\n const paths = new Set<string>()\n for (const file of files) {\n const path = file.path\n if (\n !path\n || path !== path.trim()\n || path.startsWith(\"/\")\n || path.includes(\"\\\\\")\n || path.split(\"/\").some((part) => !part || part === \".\" || part === \"..\")\n || /^[a-zA-Z]:/.test(path)\n ) {\n throw new SessionSetupError(`${label} 文件路径不安全:\"${path}\"`, stage)\n }\n if (paths.has(path)) {\n throw new SessionSetupError(`${label} 文件路径重复:\"${path}\"`, stage)\n }\n paths.add(path)\n }\n}\n\nfunction setupError(\n stage: ConstructorParameters<typeof SessionSetupError>[1],\n message: string,\n cause: unknown,\n sessionId?: string,\n): SessionSetupError {\n const detail = cause instanceof Error ? cause.message : String(cause)\n return new SessionSetupError(`${message}:${detail}`, stage, sessionId, { cause })\n}\n\nfunction profileToCreateSessionRequest(profile: SessionProfile): CreateSessionRequest {\n const solution = profile.solution\n return {\n solution_id: solution?.kind === \"existing\" ? solution.solutionId : undefined,\n session_solution_asset_id: solution?.kind === \"prepared\" ? solution.assetId : undefined,\n biz_role_id: solution?.bizRoleId ?? null,\n model: profile.model ?? null,\n compaction_ratio: profile.compactionRatio ?? null,\n enable_thinking: profile.enableThinking ?? null,\n memory_enabled: profile.memoryEnabled ?? null,\n disable_tools: profile.disableTools ?? null,\n env: profile.env,\n }\n}\n\n\nexport interface SessionRunResult<T = unknown> {\n kind: \"run_end\"\n run_id: string\n status: \"completed\" | \"failed\" | \"interrupted\" | \"waiting_for_input\"\n output?: string\n error?: string\n structured_result?: T\n}\n","import type { BladeClient } from \"../blade-client\"\n\n/**\n * 一个插件在当前用户眼里的展示信息,**与会话无关**。\n *\n * 连接器面板在首页(还没有 sessionId)也要显示插件名称和图标,所以这份目录\n * 只能依赖用户身份:它不激活任何插件、不启动沙盒、不读用户配置。\n */\nexport interface PluginCatalogEntry {\n /** 技术 ID:路径、授权、缓存与调用一律用它。 */\n name: string\n /** 包声明的业务名称;null 时界面回退到 `name`。 */\n display_name: string | null\n /**\n * 包内图标的 opaque token,没有可用图标时为 null。\n * 交给 `fetchPluginIcon`,**不是**路径,也不能直接当 URL 用。\n */\n icon: string | null\n /** 当前用户是否安装了它。 */\n auth_status?: \"login_required\" | \"ready\" | \"expired\" | \"unavailable\"\n installed: boolean\n connector?: boolean\n}\n\n/**\n * 按用户读取的插件目录(无会话)。\n *\n * 图标只能通过带凭据的请求取字节,再转成 object URL——把 `<img>` 指向 API\n * 路径要靠 cookie,token 用户会拿到 401/403。\n */\nexport class PluginsResource {\n constructor(private client: BladeClient) {}\n\n /**\n * 列出当前用户安装的插件及其展示信息。\n *\n * 服务端可能为了补齐名称/图标惰性获取包内容,但绝不激活插件、不连 MCP;\n * 单个插件的展示信息读不出来只会降级成占位,不会让整份目录失败。\n */\n catalog(init?: RequestInit): Promise<{ plugins: PluginCatalogEntry[] }> {\n return this.client.jsonFromInit(\"/api/plugins/catalog\", init)\n }\n\n /** 取一个插件的包内图标字节(用户级,不需要会话)。 */\n fetchIcon(name: string): Promise<Blob> {\n return this.client.blob(\"GET\", `/api/plugins/${encodeURIComponent(name)}/icon`)\n }\n\n /** 带凭据的图标地址;能直接用 blob URL 的地方优先用 `fetchIcon`。 */\n iconUrl(name: string): string {\n return this.client.buildAuthedUrl(`/api/plugins/${encodeURIComponent(name)}/icon`)\n }\n}\n","import type { BladeClient } from \"../blade-client\"\nimport { BladeApiError } from \"../rest\"\n\nexport type ChatGroupRole = \"owner\" | \"editor\" | \"viewer\"\n\nexport interface ChatGroup {\n id: string\n name: string\n instructions: string\n created_at: string\n updated_at: string\n session_count: number\n member_count: number\n role: ChatGroupRole\n initiator: \"ui\" | \"sdk\" | null\n workspace_path: string\n}\n\nexport interface ChatGroupMember {\n user_id: string\n display_name: string | null\n username: string\n role: ChatGroupRole\n added_by: string\n added_at: string\n}\n\nexport interface ChatGroupTask {\n id: string\n group_id: string\n number: number\n title: string\n description: string\n owner_user_id: string\n owner_display_name: string\n owner_left: boolean\n due_date: string | null\n status: \"todo\" | \"doing\" | \"done\"\n /** Only returned to the owner of this private session. */\n session_id: string | null\n can_open_session: boolean\n agent_started: boolean\n created_by: string\n created_at: string\n updated_at: string\n}\n\nexport interface CreateChatGroupTask {\n title: string\n description?: string\n owner_user_id: string\n due_date?: string | null\n start_agent?: boolean\n}\n\nexport interface UpdateChatGroupTask extends Partial<Omit<CreateChatGroupTask, \"start_agent\">> {\n status?: ChatGroupTask[\"status\"]\n}\n\nexport interface ChatGroupAsset {\n path: string\n is_dir: boolean\n size: number\n sha256: string\n submitted_by: string\n submitted_by_name: string\n session_id: string | null\n message: string\n updated_at: string\n}\n\nexport interface ChatGroupAssetList {\n group_id: string\n items: ChatGroupAsset[]\n}\n\nexport class ChatGroupsResource {\n constructor(private readonly client: BladeClient) {}\n\n private path(groupId: string): string {\n return `/api/chat-groups/${encodeURIComponent(groupId)}`\n }\n\n list(): Promise<ChatGroup[]> {\n return this.client.json(\"GET\", \"/api/chat-groups\")\n }\n\n create(payload: { name: string; instructions?: string; initiator?: \"ui\" | \"sdk\" }): Promise<ChatGroup> {\n return this.client.json(\"POST\", \"/api/chat-groups\", payload)\n }\n\n update(groupId: string, payload: { name?: string; instructions?: string }): Promise<ChatGroup> {\n return this.client.json(\"PATCH\", this.path(groupId), payload)\n }\n\n delete(\n groupId: string,\n options?: { deleteWorkspace?: boolean },\n ): Promise<{ deleted: boolean; deleted_sessions: number }> {\n const query = options?.deleteWorkspace ? \"?delete_workspace=true\" : \"\"\n return this.client.json(\"DELETE\", `${this.path(groupId)}${query}`)\n }\n\n listMembers(groupId: string): Promise<ChatGroupMember[]> {\n return this.client.json(\"GET\", `${this.path(groupId)}/members`)\n }\n\n addMembers(groupId: string, userIds: string[], role: \"editor\" | \"viewer\"): Promise<ChatGroupMember[]> {\n return this.client.json(\"POST\", `${this.path(groupId)}/members`, { user_ids: userIds, role })\n }\n\n updateMember(groupId: string, userId: string, role: \"editor\" | \"viewer\"): Promise<ChatGroupMember> {\n return this.client.json(\"PATCH\", `${this.path(groupId)}/members/${encodeURIComponent(userId)}`, { role })\n }\n\n removeMember(groupId: string, userId: string): Promise<{ deleted: boolean }> {\n return this.client.json(\"DELETE\", `${this.path(groupId)}/members/${encodeURIComponent(userId)}`)\n }\n\n listTasks(groupId: string): Promise<ChatGroupTask[]> {\n return this.client.json(\"GET\", `${this.path(groupId)}/tasks`)\n }\n\n async createTask(groupId: string, payload: CreateChatGroupTask): Promise<ChatGroupTask> {\n try {\n return await this.client.json(\"POST\", `${this.path(groupId)}/tasks`, payload)\n } catch (error) {\n if (error instanceof BladeApiError && error.status === 502) {\n const data = await error.response\n .clone()\n .json()\n .catch(() => null)\n if (typeof data?.detail?.message === \"string\") error.message = data.detail.message\n }\n throw error\n }\n }\n\n updateTask(groupId: string, taskId: string, payload: UpdateChatGroupTask): Promise<ChatGroupTask> {\n return this.client.json(\"PATCH\", `${this.path(groupId)}/tasks/${encodeURIComponent(taskId)}`, payload)\n }\n\n deleteTask(groupId: string, taskId: string): Promise<{ deleted: boolean }> {\n return this.client.json(\"DELETE\", `${this.path(groupId)}/tasks/${encodeURIComponent(taskId)}`)\n }\n\n listAssets(groupId: string): Promise<ChatGroupAssetList> {\n return this.client.json(\"GET\", `${this.path(groupId)}/assets`)\n }\n\n async readAsset(groupId: string, path: string, signal?: AbortSignal): Promise<Blob> {\n const response = await this.client.fetch(\n \"GET\",\n `${this.path(groupId)}/assets/file?${new URLSearchParams({ path })}`,\n { signal },\n )\n return response.blob()\n }\n\n /** Read at most the first 1 MiB. Full downloads continue to use readAsset. */\n async readAssetPreview(\n groupId: string,\n path: string,\n signal?: AbortSignal,\n ): Promise<{ blob: Blob; truncated: boolean }> {\n const limit = 1024 * 1024\n let response: Response\n try {\n response = await this.client.fetch(\n \"GET\",\n `${this.path(groupId)}/assets/file?${new URLSearchParams({ path })}`,\n { signal, headers: { Range: `bytes=0-${limit - 1}` } },\n )\n } catch (error) {\n if (\n error instanceof BladeApiError && error.status === 416 &&\n error.response.headers.get(\"content-range\") === \"bytes */0\"\n ) {\n await error.response.body?.cancel()\n return { blob: new Blob(), truncated: false }\n }\n throw error\n }\n const reader = response.body?.getReader()\n if (!reader) return { blob: new Blob(), truncated: false }\n const chunks: Uint8Array<ArrayBuffer>[] = []\n let bytes = 0\n let ended = false\n let overflow = false\n try {\n while (bytes < limit) {\n signal?.throwIfAborted()\n const { done, value } = await reader.read()\n if (done) {\n ended = true\n break\n }\n const remaining = limit - bytes\n overflow = value.byteLength > remaining\n const chunk = value.slice(0, remaining)\n chunks.push(chunk)\n bytes += chunk.byteLength\n }\n signal?.throwIfAborted()\n } finally {\n if (!ended) await reader.cancel().catch(() => undefined)\n reader.releaseLock()\n }\n const range = response.headers.get(\"content-range\")?.match(/^bytes 0-\\d+\\/(\\d+)$/)\n const length = response.headers.get(\"content-length\")\n const total = range\n ? Number(range[1])\n : response.status === 200 && length && !response.headers.has(\"content-encoding\") ? Number(length) : null\n return {\n blob: new Blob(chunks, { type: response.headers.get(\"content-type\") ?? \"\" }),\n truncated: overflow || (total !== null && Number.isFinite(total) ? total > bytes : !ended),\n }\n }\n\n async uploadAsset(\n groupId: string,\n file: File,\n path: string,\n message = \"\",\n ): Promise<{ file: ChatGroupAsset }> {\n const form = new FormData()\n form.append(\"file\", file)\n form.append(\"message\", message)\n const response = await this.client.formData(\n \"POST\",\n `${this.path(groupId)}/assets/upload?${new URLSearchParams({ path })}`,\n form,\n )\n return response.json()\n }\n\n createAssetFolder(groupId: string, path: string): Promise<{ file: ChatGroupAsset }> {\n return this.client.json(\"POST\", `${this.path(groupId)}/assets/folders`, { path })\n }\n\n deleteAsset(groupId: string, path: string): Promise<{ deleted: boolean }> {\n return this.client.json(\"DELETE\", `${this.path(groupId)}/assets/file?${new URLSearchParams({ path })}`)\n }\n\n submitSessionAsset(payload: {\n session_id: string\n path: string\n target_path: string\n message?: string\n }): Promise<{ file: ChatGroupAsset }> {\n return this.client.json(\"POST\", \"/api/topic-agent/files/submit\", payload)\n }\n}\n","import { BladeApiError, buildBackendUrl, extractErrorDetail } from \"../rest\"\nimport type { BladeClient } from \"../blade-client\"\n\nconst SITE_VISITS_PATH = \"/api/site-visits\"\nconst REQUEST_TIMEOUT_MS = 5_000\n\n/** 全站访问统计快照。每个数字都来自真实请求,没有基数、系数或回填。 */\nexport interface SiteVisitsSummary {\n /** 统计日期,按北京时间切日(`YYYY-MM-DD`)。 */\n date: string\n /** 统计时区,固定为 `Asia/Shanghai`。 */\n timezone: string\n /** 当天出现过的匿名访客数:按天去重,不是实时在线人数。 */\n today_uv: number\n /** 当天的页面访问次数。 */\n today_pv: number\n /** 功能上线以来累计的页面访问次数。 */\n total_pv: number\n /** 快照生成时间(RFC3339 UTC)。并发响应可能倒序到达,用它丢弃旧快照。 */\n as_of: string\n}\n\n/**\n * 全站访问统计(内置 Web 的匿名计数)。\n *\n * 这两个操作刻意走独立传输:不带 bearer、不触发 401 登录刷新,也不读登录\n * Cookie——计数只依赖匿名访客 Cookie,因此登录态失效时统计依然可用。它们\n * 只在同源的内置 Web 里使用,不是给第三方宿主页面用的。\n */\nexport class SiteVisitsResource {\n constructor(private readonly client: BladeClient) {}\n\n /** 上报一次页面访问,返回当前快照;不承诺本次已计入或已落盘。 */\n record(): Promise<SiteVisitsSummary> {\n return this.request(\"POST\")\n }\n\n /** 只读快照:不设置访客 Cookie,也不增加任何计数。 */\n summary(): Promise<SiteVisitsSummary> {\n return this.request(\"GET\")\n }\n\n private async request(method: \"GET\" | \"POST\"): Promise<SiteVisitsSummary> {\n const url = buildBackendUrl(this.client.options.baseUrl, SITE_VISITS_PATH)\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)\n try {\n const response = await (this.client.options.fetchImpl ?? fetch)(url.toString(), {\n method,\n credentials: \"include\",\n signal: controller.signal,\n })\n if (!response.ok) {\n throw new BladeApiError(response, await extractErrorDetail(response))\n }\n return (await response.json()) as SiteVisitsSummary\n } finally {\n clearTimeout(timeout)\n }\n }\n}\n","const clocks = new WeakMap<object, { serverTime: number; receivedAt: number }>()\n\nexport function syncServerTime(client: object, timestamp: unknown, receivedAt = performance.now()) {\n if (typeof timestamp !== \"string\") return\n const serverTime = Date.parse(timestamp)\n if (!Number.isFinite(serverTime)) return\n const current = getServerTime(client, receivedAt)\n clocks.set(client, { serverTime: Math.max(serverTime, current ?? serverTime), receivedAt })\n}\n\nexport function getServerTime(client: object | null, now = performance.now()): number | null {\n const clock = client ? clocks.get(client) : undefined\n return clock ? clock.serverTime + Math.max(0, now - clock.receivedAt) : null\n}\n","import type { AgentSessionEvents } from \"./events\"\n\nconst BACKGROUND_STATUSES = [\n \"starting\",\n \"running\",\n \"cancelling\",\n \"succeeded\",\n \"failed\",\n \"cancelled\",\n \"lost\",\n] as const\n\ntype BackgroundStatus = (typeof BACKGROUND_STATUSES)[number]\n\nfunction normalizeBackgroundStatus(value: unknown): BackgroundStatus {\n return (BACKGROUND_STATUSES as readonly string[]).includes(value as string)\n ? (value as BackgroundStatus)\n : \"running\"\n}\n\nexport type BackgroundTaskEvent = {\n id?: string\n task_id?: string\n command?: string\n description?: string\n status?: string\n failure_reason?: string | null\n exit_code?: number | null\n elapsed_seconds?: number\n output_lines_count?: number\n output_preview?: string[]\n}\n\nexport function completedBackgroundTask(task: BackgroundTaskEvent): AgentSessionEvents[\"backgroundTask\"] | null {\n const taskId = typeof task.id === \"string\" ? task.id : typeof task.task_id === \"string\" ? task.task_id : \"\"\n if (!taskId) return null\n return {\n id: taskId,\n command: typeof task.command === \"string\" ? task.command : \"\",\n description: typeof task.description === \"string\" ? task.description : undefined,\n status: normalizeBackgroundStatus(task.status),\n failureReason: typeof task.failure_reason === \"string\" ? task.failure_reason : undefined,\n exitCode: typeof task.exit_code === \"number\" || task.exit_code === null ? task.exit_code : undefined,\n elapsedSeconds: typeof task.elapsed_seconds === \"number\" ? task.elapsed_seconds : 0,\n output: Array.isArray(task.output_preview) && task.output_preview.length > 0 ? task.output_preview.join(\"\\n\") : undefined,\n }\n}\n","const DEFAULT_RETRY_AFTER_SECONDS = 1\nconst MAX_TIMER_DELAY_MS = 2_147_483_647\n\ntype AuthBusyData = {\n code?: unknown\n status?: unknown\n retry_after?: unknown\n}\n\nfunction errorData(error: unknown): AuthBusyData | null {\n if (typeof error !== \"object\" || error === null || !(\"data\" in error)) return null\n const data = error.data\n return typeof data === \"object\" && data !== null ? (data as AuthBusyData) : null\n}\n\n/** Return the server-requested delay for a typed temporary auth rejection. */\nexport function authBusyRetryDelayMs(error: unknown): number | null {\n const data = errorData(error)\n if (data?.code !== \"auth_busy\" || Number(data.status) !== 429) return null\n const rawRetryAfter = data.retry_after\n const seconds = rawRetryAfter == null || String(rawRetryAfter).trim() === \"\"\n ? Number.NaN\n : Number(rawRetryAfter)\n const delaySeconds = Number.isFinite(seconds) && seconds >= 0\n ? seconds\n : DEFAULT_RETRY_AFTER_SECONDS\n return Math.min(delaySeconds * 1000, MAX_TIMER_DELAY_MS)\n}\n\n/** One pending manual reconnect for Socket.IO CONNECT_ERROR auth overloads. */\nexport class AuthBusyReconnect {\n private timer: ReturnType<typeof globalThis.setTimeout> | null = null\n\n get pending(): boolean {\n return this.timer !== null\n }\n\n schedule(error: unknown, reconnect: () => void): boolean {\n const delay = authBusyRetryDelayMs(error)\n if (delay === null) {\n this.cancel()\n return false\n }\n this.cancel()\n this.timer = globalThis.setTimeout(() => {\n this.timer = null\n reconnect()\n }, delay)\n return true\n }\n\n cancel(): void {\n if (this.timer === null) return\n globalThis.clearTimeout(this.timer)\n this.timer = null\n }\n}\n","export type CommandHandler = (payload: unknown, meta: { toolCallId?: string }) => void\n\ninterface BufferedCommand {\n payload: unknown\n meta: { toolCallId?: string }\n}\n\nconst BUFFER_LIMIT_PER_ACTION = 20\n\n/**\n * 指令注册表:onCommand 事后注册 + 注册前缓冲补投。\n *\n * action 的来源见 ./protocol.ts 顶部说明——它由技能作者在工具返回值的\n * `_meta.bridge` 字段里写入,是技能作者与宿主页面开发者的业务契约。\n * 缓冲的意义:指令可能在页面还没来得及调用 onCommand 时就到达(比如\n * 历史回放),先存起来、注册时立刻补投,消除\"注册晚了漏事件\"的坑。\n */\nexport class CommandRegistry {\n private handlers = new Map<string, Set<CommandHandler>>()\n private buffered = new Map<string, BufferedCommand[]>()\n\n onCommand(action: string, handler: CommandHandler): () => void {\n let set = this.handlers.get(action)\n if (!set) {\n set = new Set()\n this.handlers.set(action, set)\n }\n set.add(handler)\n\n const pending = this.buffered.get(action)\n if (pending?.length) {\n this.buffered.delete(action)\n for (const command of pending) {\n this.invoke(handler, action, command)\n }\n }\n return () => {\n this.handlers.get(action)?.delete(handler)\n }\n }\n\n dispatch(action: string, payload: unknown, meta: { toolCallId?: string } = {}): void {\n const set = this.handlers.get(action)\n if (set && set.size > 0) {\n for (const handler of [...set]) {\n this.invoke(handler, action, { payload, meta })\n }\n return\n }\n let pending = this.buffered.get(action)\n if (!pending) {\n pending = []\n this.buffered.set(action, pending)\n }\n pending.push({ payload, meta })\n if (pending.length > BUFFER_LIMIT_PER_ACTION) {\n pending.shift()\n console.warn(\n `[agent-client] 指令 \"${action}\" 无人处理且缓冲已满,最旧的一条已丢弃。` +\n `请调用 onCommand(\"${action}\", handler) 注册处理函数。`,\n )\n }\n }\n\n private invoke(handler: CommandHandler, action: string, command: BufferedCommand): void {\n try {\n handler(command.payload, command.meta)\n } catch (error) {\n console.warn(`[agent-client] 指令 \"${action}\" 的处理函数抛出异常:`, error)\n }\n }\n\n clear(): void {\n this.handlers.clear()\n this.buffered.clear()\n }\n}\n","import type { ChatMessage, ToolCallInfo } from \"../schemas/message\"\nimport type { McpAppData } from \"../schemas/mcp-app\"\nimport type { TurnProjection } from \"../schemas/projection\"\nimport type { SessionStatus } from \"../schemas/session\"\n\n/**\n * AgentSession 的语义事件表。\n *\n * 这是\"底层逃生舱\"(L1):React 使用者优先用 useChat() 的响应式状态(L2)\n * 或 <ChatView onToolCall/commands> 的声明式入口(L3),一般不需要直接监听。\n * Vue / 无框架集成者用 session.on(...) 精确订阅。\n */\nexport interface AgentSessionEvents {\n /** 一条消息物化完成(turn 离开 streaming 状态)。 */\n message: { message: ChatMessage; turn: TurnProjection }\n /** 智能体发起了一次工具调用(首次出现)。 */\n toolCall: { toolCall: ToolCallInfo; turn: TurnProjection }\n /** 一次工具调用出结果(done / error / cancelled)。 */\n toolResult: {\n toolCall: ToolCallInfo\n turn: TurnProjection\n /** 实时到达,或首次连接/断线重连时由服务端回放。 */\n source: \"live\" | \"bootstrap_replay\" | \"reconnect_replay\"\n }\n /** 一轮回复结束。status: completed / paused / interrupted / failed。 */\n chatEnd: { status: string }\n /**\n * 运行错误(system:error、发送失败等)。\n *\n * `code` 是服务端给的机器可读原因(如 `owner_timeout` / `route_broken`),\n * 供调用方决定要不要重试;`message` 是可以直接展示的业务文案。\n */\n error: { message: string; code?: string }\n /** planning / executing 模式切换。 */\n modeChange: { mode: \"planning\" | \"executing\" }\n /**\n * 智能体给宿主页面下发指令。\n *\n * action 的来源:技能作者在工具实现的返回值 JSON 里写 `_meta.bridge:\n * { action, payload }`,后端剥离后经事件流送达前端。action 是技能作者与\n * 宿主页面开发者约定的业务契约字符串(如 \"map.highlight\"),LLM 不参与、\n * SDK 不做枚举。一般用 session.onCommand(action, fn) 消费,而不是监听本事件。\n */\n command: { action: string; payload: unknown; toolCallId?: string }\n /** 系统通知(技能阶段提示、后台任务启动等)。 */\n notification: {\n type: string\n title: string\n detail?: string\n status: \"info\" | \"running\" | \"done\" | \"error\"\n loopId?: string\n metadata?: Record<string, unknown>\n }\n /**\n * 工作区文件发生变化(写文件、重命名等)。`paths` 是已知的变化路径(相对工作区,\n * 目录以 `/` 结尾);没有 `filePath` 也没有 `paths` 时表示不知道具体变了什么。\n */\n workspaceChanged: {\n filePath?: string\n paths?: string[]\n /** 工具切换了会话工作目录时的新目录(例如绑定到分组工作区)。 */\n workspacePath?: string\n }\n /**\n * 一条回合在实时通道上落地(新出现或内容更新),供宿主做自己的副作用(打开预览、标记面板未读等)。\n * 历史加载(REST)不触发;`source` 区分真正的实时更新与订阅时服务端重发的缓冲。\n */\n turnUpdated: {\n turn: TurnProjection\n source: \"live\" | \"bootstrap_replay\" | \"reconnect_replay\"\n }\n /** 智能体产出了文件成果(artifact:created / artifact:updated)。 */\n artifact: {\n filePath: string\n contentType: string\n title: string\n content: string\n oldString?: string\n newString?: string\n kind: \"created\" | \"updated\"\n }\n /** 工具返回值带 _meta.ui 的可视化预览(resource HTML / URI)。 */\n toolPreview: {\n /** Source file identity when the preview comes from a local HTML file. */\n sourcePath?: string\n toolCallId: string\n type: \"resource-html\" | \"resource-uri\" | \"resource-file\"\n content: string\n title: string\n mcpApp?: McpAppData\n }\n /** 任务清单(TaskCreate 等)更新。 */\n taskListUpdated: { tasks: unknown[] }\n /** 沙盒后台命令状态更新。 */\n backgroundTask: {\n id: string\n command: string\n description?: string\n /**\n * 与 REST 一致的真实状态。不要在客户端合并这些值:把 cancelled / lost\n * 显示成\"完成\"会让订阅方拿到与 REST 相反的结论。\n * lost 表示平台跟丢了这个进程,不代表它失败,也可能仍在运行。\n */\n status:\n | \"starting\"\n | \"running\"\n | \"cancelling\"\n | \"succeeded\"\n | \"failed\"\n | \"cancelled\"\n | \"lost\"\n /** failed 时说明原因,如 start_failed、log_budget_exceeded。 */\n failureReason?: string | null\n exitCode?: number | null\n elapsedSeconds: number\n output?: string\n }\n /** 会话被回溯到某个检查点。 */\n rewind: { checkpointId: string }\n /** 会话属性(名称、状态、绑定技能等)被服务端更新。 */\n sessionUpdated: {\n workspacePath?: string\n chatGroupId?: string | null\n intent?: string\n status?: SessionStatus\n model?: string | null\n replayState?: Record<string, unknown> | null\n }\n /** 回放输入不匹配,需要决定保持回放还是转自主模式。 */\n replayMismatch: {\n actualMessage?: string\n expectedMessage?: string\n respond: (decision: \"keep_replay\" | \"continue_replay\") => void\n }\n /** 沙盒内存超限自动重启。 */\n sandboxOom: { toolCallId: string }\n /** session.attach() 被调用,渲染层(ChatView/useChat)应把它显示为输入框附件。 */\n attachRequested: { label: string; content: string }\n /** session.insertText() 被调用,渲染层应把文字追加到输入框。 */\n insertTextRequested: { text: string }\n}\n\nexport type AgentSessionEventName = keyof AgentSessionEvents\n\ntype Handler<E> = (event: E) => void\n\nexport class Emitter<Events> {\n private handlers = new Map<keyof Events, Set<Handler<never>>>()\n\n on<K extends keyof Events>(name: K, handler: Handler<Events[K]>): () => void {\n let set = this.handlers.get(name)\n if (!set) {\n set = new Set()\n this.handlers.set(name, set)\n }\n set.add(handler as Handler<never>)\n return () => this.off(name, handler)\n }\n\n off<K extends keyof Events>(name: K, handler: Handler<Events[K]>): void {\n this.handlers.get(name)?.delete(handler as Handler<never>)\n }\n\n emit<K extends keyof Events>(name: K, event: Events[K]): void {\n const set = this.handlers.get(name)\n if (!set) return\n for (const handler of [...set]) {\n try {\n ;(handler as Handler<Events[K]>)(event)\n } catch (error) {\n console.warn(`[agent-client] \"${String(name)}\" 事件处理器抛出异常:`, error)\n }\n }\n }\n\n /**\n * 只把事件交给最先注册的处理器。用于必须由单一交互入口作答的事件,\n * 避免多个 UI 同时弹窗并提交相互冲突的决定。\n */\n emitFirst<K extends keyof Events>(name: K, event: Events[K]): boolean {\n const handler = this.handlers.get(name)?.values().next().value\n if (!handler) return false\n try {\n ;(handler as Handler<Events[K]>)(event)\n } catch (error) {\n console.warn(`[agent-client] \"${String(name)}\" 事件处理器抛出异常:`, error)\n return false\n }\n return true\n }\n\n listenerCount(name: keyof Events): number {\n return this.handlers.get(name)?.size ?? 0\n }\n\n clear(): void {\n this.handlers.clear()\n }\n}\n","import type { TurnProjection } from \"../schemas/projection\"\n\nexport interface LiveRevisionState {\n current: number\n byTurnId: ReadonlyMap<string, number>\n}\n\nfunction sortedUnique(turns: TurnProjection[]): TurnProjection[] {\n const byId = new Map<string, TurnProjection>()\n for (const turn of turns) byId.set(turn.turn_id, turn)\n return [...byId.values()].sort((left, right) => left.sequence - right.sequence)\n}\n\n/** Add an older authoritative slice without allowing it to roll back live content. */\nexport function prependOlder(\n current: TurnProjection[],\n page: TurnProjection[],\n): TurnProjection[] {\n const currentById = new Map(current.map((turn) => [turn.turn_id, turn]))\n return sortedUnique([\n ...current,\n ...page.map((turn) => {\n const live = currentById.get(turn.turn_id)\n return live ? { ...live, sequence: turn.sequence } : turn\n }),\n ])\n}\n\n/** Install a new authoritative window, retaining only live writes newer than the request. */\nexport function replaceWindow(\n current: TurnProjection[],\n page: TurnProjection[],\n liveRevisionAtStart: number,\n liveRevisions: LiveRevisionState,\n): TurnProjection[] {\n const pageById = new Map(page.map((turn) => [turn.turn_id, turn]))\n const newerLive = current.filter(\n (turn) =>\n turn.turn_id.startsWith(\"local-user-\") ||\n (liveRevisions.byTurnId.get(turn.turn_id) ?? 0) > liveRevisionAtStart,\n )\n return sortedUnique([\n ...page,\n ...newerLive.map((turn) => {\n const snapshot = pageById.get(turn.turn_id)\n return snapshot ? { ...turn, sequence: snapshot.sequence } : turn\n }),\n ])\n}\n","import { isRecord } from \"../shared/type-guards\"\n\n/**\n * 会话消息队列的共享领域模型:类型、快照合并规则与中文文案。\n *\n * 这里是**单一定义处**:AgentSession 的状态机、agent-react 与内置 Web 的队列 UI\n * 都只用这一份判定,避免\"能不能编辑 / 旧快照要不要覆盖\"各写一遍后各自演进。\n * 服务端语义见 issue #2529 与 local://frontend-queue-contract.md。\n */\n\n/** 等待消息的服务端生命周期状态。 */\nexport type QueuedMessageStatus = \"pending\" | \"delivering\" | \"claimed\" | \"consumed\" | \"cancelled\"\n\n/** 队列里的一条等待消息;权威快照只包含 pending(等待执行)与 delivering(等待接收)。 */\nexport interface QueuedMessage {\n id: string\n content: string\n position: number\n version: number\n status: QueuedMessageStatus\n created_at: string\n updated_at: string\n /** 立即补充指向的当前运行 id;普通等待条目没有。 */\n target_run_id?: string\n /** 领取或投递失败的原因。 */\n error?: string\n}\n\n/** 服务端权威队列快照。`revision` 单调递增,客户端据此丢弃过期快照。 */\nexport interface SessionQueueSnapshot {\n session_id: string\n revision: number\n paused: boolean\n pause_reason: string | null\n items: QueuedMessage[]\n}\n\n/**\n * 还没有拿到服务端快照时的占位。\n *\n * `session_id` 为空表示\"身份未知\":`shouldApplySnapshot` 会跳过会话身份校验、\n * 只比较 revision,这样第一份快照(哪怕 revision 为 0 的暂停态)也能装进来。\n */\nexport const EMPTY_SESSION_QUEUE: SessionQueueSnapshot = {\n session_id: \"\",\n revision: 0,\n paused: false,\n pause_reason: null,\n items: [],\n}\n\n/**\n * 队列命令的 ack 线格式。\n *\n * `conflict` 表示乐观并发或状态校验失败,此时快照字段是服务端最新值,客户端必须\n * 据此刷新本地并保留用户草稿;`error` 时快照字段可能缺失(如鉴权失败),此时只报错、\n * 不改动本地队列。\n */\nexport interface QueueAck {\n /** `queued` 只出现在 `chat:send` 的运行中改道:消息已进等待队列,不是失败。 */\n status: \"ok\" | \"conflict\" | \"error\" | \"queued\"\n /**\n * 只有 `queued` 会带:服务端判定这次改道时该会话是否有运行。\n * 客户端据此对齐流式标记,不用自己的猜测。\n */\n running?: boolean\n message?: string | null\n session_id?: string\n revision?: number\n paused?: boolean\n pause_reason?: string | null\n items?: QueuedMessage[]\n}\n\n/** 解析后的队列操作结果;UI 只看这一个结构。 */\nexport interface QueueOperationResult {\n ok: boolean\n conflict: boolean\n /** 服务端快照;缺失时为 null,调用方不得据此清空本地队列。 */\n snapshot: SessionQueueSnapshot | null\n message: string | null\n /**\n * 服务端给的机器可读失败原因(如 `owner_timeout` / `route_broken` / `owner_busy`),\n * 供调用方决定要不要重试;`message` 是可以直接展示的业务文案。\n */\n code?: string\n}\n\nconst QUEUE_FAILURE_MESSAGE = \"队列操作失败\"\n\nconst QUEUED_MESSAGE_STATUSES: readonly string[] = [\n \"pending\",\n \"delivering\",\n \"claimed\",\n \"consumed\",\n \"cancelled\",\n]\n\nfunction toQueuedMessage(value: unknown): QueuedMessage | null {\n if (!isRecord(value)) return null\n const status =\n typeof value.status === \"string\" && QUEUED_MESSAGE_STATUSES.includes(value.status)\n ? (value.status as QueuedMessageStatus)\n : null\n if (\n typeof value.id !== \"string\" ||\n typeof value.content !== \"string\" ||\n typeof value.position !== \"number\" ||\n typeof value.version !== \"number\" ||\n typeof value.created_at !== \"string\" ||\n typeof value.updated_at !== \"string\" ||\n status === null\n ) {\n return null\n }\n const item: QueuedMessage = {\n id: value.id,\n content: value.content,\n position: value.position,\n version: value.version,\n status,\n created_at: value.created_at,\n updated_at: value.updated_at,\n }\n if (typeof value.target_run_id === \"string\") item.target_run_id = value.target_run_id\n if (typeof value.error === \"string\") item.error = value.error\n return item\n}\n\nfunction toQueueSnapshot(value: unknown, fallbackSessionId: string): SessionQueueSnapshot | null {\n if (!isRecord(value)) return null\n if (\n typeof value.revision !== \"number\" ||\n !Number.isInteger(value.revision) ||\n value.revision < 0\n ) {\n return null\n }\n if (typeof value.paused !== \"boolean\") return null\n if (!Array.isArray(value.items)) return null\n const pauseReason = value.pause_reason\n if (pauseReason !== null && pauseReason !== undefined && typeof pauseReason !== \"string\") {\n return null\n }\n const items: QueuedMessage[] = []\n for (const raw of value.items) {\n const item = toQueuedMessage(raw)\n if (!item) return null\n items.push(item)\n }\n return {\n session_id:\n typeof value.session_id === \"string\" && value.session_id\n ? value.session_id\n : fallbackSessionId,\n revision: value.revision,\n paused: value.paused,\n pause_reason: typeof pauseReason === \"string\" ? pauseReason : null,\n items,\n }\n}\n\n/** 判定一份载荷是不是完整的权威队列快照(广播事件用)。 */\nexport function isSessionQueueSnapshot(value: unknown): value is SessionQueueSnapshot {\n if (!isRecord(value) || typeof value.session_id !== \"string\") return false\n return toQueueSnapshot(value, value.session_id) !== null\n}\n\n/**\n * 是否用 `next` 覆盖 `current`。\n *\n * 规则只有两条:会话身份必须一致(还没拿到过快照时不校验),且 revision 必须严格\n * 更新——相等或更旧一律不采纳,乱序到达的旧快照不会把新状态顶回去。\n */\nexport function shouldApplySnapshot(\n current: SessionQueueSnapshot | undefined,\n next: SessionQueueSnapshot,\n): boolean {\n if (!isSessionQueueSnapshot(next)) return false\n if (current?.session_id && next.session_id !== current.session_id) return false\n return next.revision > (current?.revision ?? -1)\n}\n\n/**\n * 解析 `emitWithAck` 的返回值。\n *\n * - `ok` / `queued` / `conflict` 且能解析成快照 → `snapshot` 有值;\n * - `queued` → `ok=true`:`chat:send` 在运行中改道进了等待队列,调用方要撤掉乐观消息;\n * - `conflict` → `ok=false, conflict=true`(快照可能仍缺失,调用方按 null 处理);\n * - `error` 或结构不合法 → `ok=false, conflict=false`,`message` 为服务端文案或兜底。\n */\nexport function parseQueueAck(response: unknown, fallbackSessionId: string): QueueOperationResult {\n if (!isRecord(response)) {\n return { ok: false, conflict: false, snapshot: null, message: QUEUE_FAILURE_MESSAGE }\n }\n const message =\n typeof response.message === \"string\" && response.message ? response.message : null\n const code = typeof response.code === \"string\" && response.code ? response.code : undefined\n const status = response.status\n if (status !== \"ok\" && status !== \"conflict\" && status !== \"queued\") {\n return {\n ok: false,\n conflict: false,\n snapshot: null,\n message: message ?? QUEUE_FAILURE_MESSAGE,\n ...(code ? { code } : {}),\n }\n }\n const snapshot = toQueueSnapshot(response, fallbackSessionId)\n if (status === \"conflict\") {\n return {\n ok: false,\n conflict: true,\n snapshot,\n message: message ?? QUEUE_FAILURE_MESSAGE,\n ...(code ? { code } : {}),\n }\n }\n if (!snapshot) {\n return {\n ok: false,\n conflict: false,\n snapshot: null,\n message: message ?? QUEUE_FAILURE_MESSAGE,\n ...(code ? { code } : {}),\n }\n }\n return { ok: true, conflict: false, snapshot, message, ...(code ? { code } : {}) }\n}\n\n/** 等待中的条目才能改正文;已经交给运行或开始执行的条目不再可编辑。 */\nexport function canEditQueuedMessage(item: QueuedMessage): boolean {\n return item.status === \"pending\"\n}\n\n/** 等待中的条目才能删除。 */\nexport function canCancelQueuedMessage(item: QueuedMessage): boolean {\n return item.status === \"pending\"\n}\n\n/**\n * 能否立即补充。条目本身必须是等待中的;\"会话是否正在运行\"由调用方判断——\n * 服务端会在没有可接收补充的任务时返回冲突。\n */\nexport function canDeliverQueuedMessage(item: QueuedMessage): boolean {\n return item.status === \"pending\"\n}\n\nconst QUEUED_MESSAGE_STATUS_LABELS: Record<QueuedMessageStatus, string> = {\n pending: \"待执行\",\n delivering: \"等待接收\",\n claimed: \"\",\n consumed: \"\",\n cancelled: \"\",\n}\n\n/** 面向前端展示的状态文案;已离开队列视图的状态没有文案。 */\nexport function queuedMessageStatusLabel(status: QueuedMessageStatus): string {\n return QUEUED_MESSAGE_STATUS_LABELS[status] ?? \"\"\n}\n\nconst QUEUE_PAUSE_REASON_LABELS: Record<string, string> = {\n user_stop: \"已暂停\",\n run_failed: \"任务异常已暂停\",\n run_unknown: \"任务结束状态未知,已暂停\",\n server_restart: \"服务重启已暂停\",\n}\n\n/** 暂停原因文案;未知原因原样透出,没有原因返回 null。 */\nexport function queuePauseReasonLabel(reason: string | null | undefined): string | null {\n if (!reason) return null\n return QUEUE_PAUSE_REASON_LABELS[reason] ?? reason\n}\n","/** 沙盒因内存超限被杀(退出码 137)时展示给用户的说明。实时 system:error 与历史恢复共用。 */\nexport const OOM_MESSAGE = \"沙盒内存使用超出限制,已自动重启。如果经常触发,可以联系管理员调整额度。\"\n\nconst OOM_KEYWORDS_RE = /(?:\\b(?:exit_code|ExitedWith|exited with)|退出码)\\D*(?<!\\d)137(?!\\d)/i\n\nexport function isOomText(value: unknown): boolean {\n return typeof value === \"string\" && OOM_KEYWORDS_RE.test(value)\n}\n\n/** 错误说明的展示文案:内存超限换成友好说明,其余原样。实时与历史两条路径都要经过它,才能对得上。 */\nexport function userFacingErrorText(message: string): string {\n return isOomText(message) ? OOM_MESSAGE : message\n}\n","import type {\n ChatMessage,\n FileContentPart,\n ImageUrlContentPart,\n MessageContent,\n MessageContentPart,\n} from \"./message\"\n\nconst SYSTEM_REMINDER_PATTERN = /^<system-reminder>\\s*[\\s\\S]*?\\s*<\\/system-reminder>$/i\nconst SYSTEM_NOTIFICATION_PATTERN =\n /^<system-notification>\\s*[\\s\\S]*?\\s*<\\/system-notification>$/i\nconst LEGACY_FORK_CONTEXT_MARKERS = [\n \"父智能体在派生你之前已经完成了一些操作。\",\n \"可通过 `read_file` 读取。\",\n \"# 你的任务\",\n]\nconst INTERNAL_CHAT_ERROR_PATTERNS = [\n /\\b(?:ENOENT|EACCES|EPERM)\\b/i,\n /\\[(?:Errno -?\\d+|WinError \\d+)\\]/i,\n /\\b(?:ECONNRESET|ECONNREFUSED|ETIMEDOUT|EHOSTUNREACH|ENETUNREACH|ENOTFOUND|EAI_AGAIN)\\b/i,\n /\\b(?:Connection refused|Connection reset by peer|All connection attempts failed|getaddrinfo failed)\\b/i,\n /(?:^|[\\s(\"'`])\\/(?:root|home|Users|tmp|var|opt|etc)\\//,\n /[A-Za-z]:\\\\(?:Users|Windows|Program Files|AppData)\\\\/i,\n /(?:^|\\n)Traceback \\(most recent call last\\):/,\n /(?:^|\\n)\\s*at\\s+\\S+(?:\\s+\\(|:\\d+:\\d+)/,\n /(?:^|\\n)File \"[^\"]+\", line \\d+/,\n]\nconst SAFE_CHAT_ERROR_PREFIXES = [\n \"沙盒运行环境暂时不可用,请稍后重试。\",\n \"模型服务暂时不可用,请检查模型配置后重试。\",\n]\nconst GENERIC_CHAT_ERROR = \"消息发送失败,请重试。\"\n\n/** Ordinary chat uses business copy; developer mode may retain diagnostics. */\nexport function chatErrorForDisplay(message: string, developer = false): string {\n const normalized = message.trim()\n if (!developer) {\n const safePrefix = SAFE_CHAT_ERROR_PREFIXES.find((prefix) => normalized.startsWith(prefix))\n if (safePrefix) return safePrefix\n }\n if (!developer && /no source matches this model/i.test(normalized)) {\n return \"当前模型暂时不可用,请稍后重试或重新选择模型。\"\n }\n if (!developer && INTERNAL_CHAT_ERROR_PATTERNS.some((pattern) => pattern.test(normalized))) {\n return GENERIC_CHAT_ERROR\n }\n return normalized || GENERIC_CHAT_ERROR\n}\n\nexport function normalizeMessageContent(content: unknown): MessageContent {\n if (typeof content === \"string\") return content\n if (Array.isArray(content)) return content as MessageContentPart[]\n return String(content ?? \"\")\n}\n\nexport function getTextContent(content: MessageContent): string {\n if (typeof content === \"string\") return content\n return content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\")\n}\n\nexport function isSystemReminderText(text: string): boolean {\n return SYSTEM_REMINDER_PATTERN.test(text.trim())\n}\n\nfunction isSystemNotificationText(text: string): boolean {\n return SYSTEM_NOTIFICATION_PATTERN.test(text.trim())\n}\n\nexport function isLegacyForkContextText(text: string): boolean {\n const normalized = text.trim()\n return LEGACY_FORK_CONTEXT_MARKERS.every((marker) => normalized.includes(marker))\n}\n\n/**\n * 平台自己写进去、不该露给用户的内部提示。\n *\n * 服务端的消息导航目录有一份同名同语义的 Python 实现\n * (`server/.../routes/sessions.py` 的 `_is_hidden_internal_message`):客户端靠它决定\n * 渲染不渲染,服务端靠它决定进不进目录。改这里必须同时改那边,否则目录会列出没有对应\n * 行的死条目,或者把内部提示原文当标题露出去。\n */\nexport function isHiddenInternalMessage(\n message: Pick<ChatMessage, \"role\" | \"content\">,\n options: { includeLegacyForkContext?: boolean } = {},\n): boolean {\n if (message.role !== \"user\") return false\n const text = getTextContent(normalizeMessageContent(message.content))\n return (\n isSystemReminderText(text) ||\n isSystemNotificationText(text) ||\n ((options.includeLegacyForkContext ?? true) && isLegacyForkContextText(text))\n )\n}\n\nexport function buildMessageContent(\n text: string,\n attachments: Array<{\n kind: \"file\"\n name: string\n uploadedPath?: string\n textContent?: string | null\n mimeType?: string\n }>,\n): MessageContent {\n if (attachments.length === 0) return text\n const textSegments: string[] = []\n\n if (text.trim()) {\n textSegments.push(text)\n }\n\n for (const attachment of attachments) {\n let fileText: string\n if (attachment.uploadedPath) {\n const displayName = attachment.uploadedPath.split(\"/\").pop() || attachment.name\n fileText = `[附件: ${displayName}] 已上传到工作区路径: ${attachment.uploadedPath}`\n } else if (attachment.textContent) {\n const MAX_TEXT_CHARS = 100_000\n const content =\n attachment.textContent.length > MAX_TEXT_CHARS\n ? `${attachment.textContent.slice(0, MAX_TEXT_CHARS)}\\n\\n[内容已截断,原始共 ${attachment.textContent.length} 字符]`\n : attachment.textContent\n fileText = `[附件: ${attachment.name}]\\n${content}`\n } else {\n fileText = `[附件: ${attachment.name}]`\n }\n textSegments.push(fileText)\n }\n\n return textSegments.join(\"\\n\\n\")\n}\n\nexport function contentPreview(content: MessageContent, maxLen = 80): string {\n const text = getTextContent(content).trim()\n return text.length > maxLen ? `${text.slice(0, maxLen)}…` : text\n}\n\n/** @deprecated 技能可用状态由运行时解析,发送身份请使用 SkillRef。 */\nexport interface SkillMentionAvailability {\n /** 本地已有(内置 / 技能目录 / 会话已加载),直接可用。 */\n local?: boolean\n /** Blade Hub 上该账号是否已安装。本地技能恒为 true。 */\n installed?: boolean\n}\n\n/** Serialize a skill marker as user text. Send its identity separately in refs. */\nexport function transformSlashCommand(\n skillName: string,\n rawInput: string,\n _availability: SkillMentionAvailability = {},\n): string {\n return rawInput.replace(`<skill>${skillName}</skill>`, `@${skillName}`).trim()\n}\n\nconst ATTACHMENT_TAG_RE = /\\[附件:\\s*([^\\]]+)\\](?:[ \\t]*已上传到工作区路径:[ \\t]*([^\\r\\n]+))?/g\nconst CONTEXT_PART_RE = /^\\[上下文:\\s*([^\\]]+)\\]\\n([\\s\\S]*)$/\n\nexport interface ParsedTextAttachment {\n name: string\n uploadedPath?: string\n}\n\nexport interface ParsedTextContext {\n label: string\n content: string\n}\n\n/**\n * Extract `[附件: name]` and `[上下文: label]` tags from text parts and return\n * the cleaned text plus the collected attachment / context metadata. 每个 text\n * part 独立匹配,以避免跨 part 拼接打乱正则。\n */\nexport function extractTextAttachments(content: MessageContent): {\n cleanText: string\n attachments: ParsedTextAttachment[]\n contexts: ParsedTextContext[]\n} {\n if (typeof content === \"string\") {\n const attachments: ParsedTextAttachment[] = []\n const contexts: ParsedTextContext[] = []\n const ctxMatch = CONTEXT_PART_RE.exec(content)\n let working = content\n if (ctxMatch) {\n contexts.push({ label: ctxMatch[1].trim(), content: ctxMatch[2].trim() })\n working = \"\"\n }\n for (const match of working.matchAll(ATTACHMENT_TAG_RE)) {\n attachments.push({\n name: match[1].trim(),\n uploadedPath: match[2]?.trim() || undefined,\n })\n }\n return {\n cleanText: working.replace(ATTACHMENT_TAG_RE, \"\"),\n attachments,\n contexts,\n }\n }\n\n const attachments: ParsedTextAttachment[] = []\n const contexts: ParsedTextContext[] = []\n const cleanParts: string[] = []\n\n for (const part of content) {\n if (part.type !== \"text\") continue\n\n const ctxMatch = CONTEXT_PART_RE.exec(part.text)\n if (ctxMatch) {\n contexts.push({ label: ctxMatch[1].trim(), content: ctxMatch[2].trim() })\n continue\n }\n\n let hasAttachment = false\n for (const match of part.text.matchAll(ATTACHMENT_TAG_RE)) {\n attachments.push({\n name: match[1].trim(),\n uploadedPath: match[2]?.trim() || undefined,\n })\n hasAttachment = true\n }\n if (hasAttachment) {\n const remaining = part.text.replace(ATTACHMENT_TAG_RE, \"\")\n if (remaining.trim()) cleanParts.push(remaining)\n } else {\n cleanParts.push(part.text)\n }\n }\n\n return { cleanText: cleanParts.join(\"\\n\"), attachments, contexts }\n}\n\nexport function getImageParts(content: MessageContent): ImageUrlContentPart[] {\n if (typeof content === \"string\") return []\n return content.filter((part): part is ImageUrlContentPart => part.type === \"image_url\")\n}\n\nexport function getFileParts(content: MessageContent): FileContentPart[] {\n if (typeof content === \"string\") return []\n return content.filter((part): part is FileContentPart => part.type === \"file\")\n}\n\ninterface MessageGroup {\n root: ChatMessage | null\n childLoops: { loopName: string; messages: ChatMessage[] }[]\n}\n\nexport function groupMessagesByLoop(messages: ChatMessage[]): MessageGroup[] {\n const groups: MessageGroup[] = []\n let currentGroup: MessageGroup | null = null\n\n for (const msg of messages) {\n const loop = msg.loop_name ?? \"root\"\n\n if (loop === \"root\") {\n currentGroup = { root: msg, childLoops: [] }\n groups.push(currentGroup)\n } else {\n if (!currentGroup) {\n currentGroup = { root: null, childLoops: [] }\n groups.push(currentGroup)\n }\n const existingLoop = currentGroup.childLoops.find((l) => l.loopName === loop)\n if (existingLoop) {\n existingLoop.messages.push(msg)\n } else {\n currentGroup.childLoops.push({ loopName: loop, messages: [msg] })\n }\n }\n }\n\n return groups\n}\n\n/** A typed wake input stays internal for navigation, but has a visible notice. */\nexport function isBackgroundWakeMessage(message: Pick<ChatMessage, \"blocks\">): boolean {\n return message.blocks?.some((block) => {\n const content = block.content\n return block.type === \"system_notification\" && content !== null &&\n typeof content === \"object\" && \"notification_type\" in content &&\n content.notification_type === \"bg:wakeup\"\n }) ?? false\n}\n","import type { TurnProjection } from \"../schemas/projection\"\nimport { workflowEntriesFromSteps, workflowRunCancelled } from \"../shared/projection/workflow\"\n\n/**\n * 「工作流运行」的时间线:一次 workflow:run 工具调用执行过程中的步骤与日志。\n *\n * 两个来源,规则固定:\n * - 运行中:服务端流式解析工作流 stdout 后推送的 `workflow:run:start` / `workflow:step` /\n * `workflow:log` / `workflow:run:end` 原始事件(不落盘);\n * - 工具调用结束后:一律用工具结果里留存的 `[workflow] …` 行重建(落盘,历史也只有这一份)。\n * 这样实时、历史、重连、回放在运行结束后得到同一份时间线。\n */\nexport type WorkflowRunEntry =\n /** status:步骤终态(done / error / cancelled);落史与直播的终态更新都会带上。 */\n | { kind: \"step\"; stepId: string; desc: string; stepKind: string; status?: string }\n /** stepId:这行属于哪一步。并行分支的输出不按宣告顺序到达,不能按位置归到上一步。 */\n | { kind: \"log\"; text: string; stepId?: string }\n\nexport interface WorkflowRunState {\n /** 触发它的 workflow:run 工具调用 id。 */\n toolCallId: string\n /** 工作流名(工具参数里的 name);拿不到时为空串,由界面兜底。 */\n name: string\n status: \"running\" | \"done\" | \"error\" | \"cancelled\"\n entries: WorkflowRunEntry[]\n}\n\n/**\n * workflow:run 工具在 LLM 线上的名字是 `workflow__run`(provider 名与工具名过 LLM 层时用双下划线\n * 拼接),内部锚点是 `workflow:run`。两种都认;不要先归一化工具名,归一化会把两种都变成 `run`。\n */\nexport function isWorkflowRunToolName(name: string): boolean {\n return name === \"workflow:run\" || name === \"workflow__run\"\n}\n\nconst LOG_PREFIX = \"[workflow] \"\nconst STEP_LINE_RE = /^步骤 (\\S+?):([\\s\\S]*)$/\nconst PARALLEL_SUFFIX_RE = /\\(并行 \\d+ 分支\\)$/\nconst CHOICE_SUFFIX = \"(条件判断)\"\nconst AGENT_SUFFIX = \"(子智能体)\"\n\n/**\n * 从工具结果里的 `[workflow] …` 行重建步骤时间线,与后端 parse_workflow_log_line 同词表。\n * 非前缀行(最终输出 / traceback)不参与,由界面在外层展示。\n */\nexport function workflowEntriesFromOutput(output: string): WorkflowRunEntry[] {\n const entries: WorkflowRunEntry[] = []\n for (const line of output.split(\"\\n\")) {\n if (!line.startsWith(LOG_PREFIX)) continue\n const body = line.slice(LOG_PREFIX.length)\n const match = STEP_LINE_RE.exec(body)\n if (!match) {\n entries.push({ kind: \"log\", text: body })\n continue\n }\n let desc = match[2]\n let stepKind = \"step\"\n if (desc.endsWith(AGENT_SUFFIX)) {\n stepKind = \"agent\"\n desc = desc.slice(0, -AGENT_SUFFIX.length)\n } else if (desc.endsWith(CHOICE_SUFFIX)) {\n stepKind = \"choice\"\n desc = desc.slice(0, -CHOICE_SUFFIX.length)\n } else if (PARALLEL_SUFFIX_RE.test(desc)) {\n stepKind = \"parallel\"\n desc = desc.replace(PARALLEL_SUFFIX_RE, \"\")\n }\n entries.push({ kind: \"step\", stepId: match[1], desc: desc.trimEnd(), stepKind })\n }\n return entries\n}\n\n/** 运行的标题只从工具参数取:历史没有实时事件,两条路径都用这一个来源。\n * 与 host 起跑时发的 label 同款:「技能「org/x」」,非 main 流程再带「 · 流程 x」。 */\nexport function workflowNameFromArguments(argumentsJson: string): string {\n try {\n const args = JSON.parse(argumentsJson)\n const skillId = typeof args?.skill_id === \"string\" ? args.skill_id.trim() : \"\"\n if (skillId) {\n const flow = typeof args?.flow === \"string\" ? args.flow.trim() : \"\"\n return `技能「${skillId}」${flow && flow !== \"main\" ? ` · 流程 ${flow}` : \"\"}`\n }\n const name = args?.name\n return typeof name === \"string\" ? name : \"\"\n } catch {\n return \"\"\n }\n}\n\nconst WORKFLOW_EVENT_TYPES = new Set([\n \"workflow:run:start\",\n \"workflow:step\",\n \"workflow:log\",\n \"workflow:run:end\",\n])\n\nexport function isWorkflowEvent(type: string): boolean {\n return WORKFLOW_EVENT_TYPES.has(type)\n}\n\nfunction asText(value: unknown): string {\n return typeof value === \"string\" ? value : \"\"\n}\n\n/**\n * 把一条实时 workflow 事件叠加到这次运行的时间线上。`current` 为 undefined 表示还没有这次运行。\n * 返回 null 表示事件不改变时间线。\n *\n * `workflow:run:start` 到达 = 事件流从头开始:重连回放会把整个缓冲(含 start 与全部 step/log)\n * 原样重发,保留旧条目再逐条追加会让时间线每次重连翻一倍;清空重建天然幂等。\n */\nexport function applyWorkflowEvent(\n current: WorkflowRunState | undefined,\n toolCallId: string,\n type: string,\n payload: Record<string, unknown>,\n): WorkflowRunState | null {\n if (type === \"workflow:run:start\") {\n return { toolCallId, name: current?.name ?? \"\", status: \"running\", entries: [] }\n }\n const base: WorkflowRunState = current ?? { toolCallId, name: \"\", status: \"running\", entries: [] }\n if (type === \"workflow:step\") {\n const settled = asText(payload.status)\n const stepId = asText(payload.step_id)\n if (stepId && isFinished(settled)) {\n const index = base.entries.findIndex((entry) => entry.kind === \"step\" && entry.stepId === stepId)\n if (index === -1) return null\n const entries = [...base.entries]\n entries[index] = { ...(entries[index] as Extract<WorkflowRunEntry, { kind: \"step\" }>), status: settled }\n return { ...base, entries }\n }\n return {\n ...base,\n entries: [\n ...base.entries,\n {\n kind: \"step\",\n stepId: asText(payload.step_id),\n desc: asText(payload.desc),\n stepKind: asText(payload.kind) || \"step\",\n },\n ],\n }\n }\n if (type === \"workflow:log\") {\n const stepId = asText(payload.step_id)\n const entry: WorkflowRunEntry = stepId\n ? { kind: \"log\", text: asText(payload.text), stepId }\n : { kind: \"log\", text: asText(payload.text) }\n return { ...base, entries: [...base.entries, entry] }\n }\n if (type === \"workflow:run:end\") {\n const status = asText(payload.status)\n return {\n ...base,\n status: status === \"done\" || status === \"error\" || status === \"cancelled\" ? status : \"done\",\n }\n }\n return null\n}\n\nfunction isFinished(status: string): status is \"done\" | \"error\" | \"cancelled\" {\n return status === \"done\" || status === \"error\" || status === \"cancelled\"\n}\n\n/**\n * 按当前 turn 列表重建全部工作流运行。\n * - 工具调用已结束:时间线取工具结果,状态取工具状态(与历史同源);\n * - 仍在运行:保留实时事件累积的时间线(没有时为空)。\n * 只保留当前 turn 列表里还存在的工具调用(rewind 之后旧运行随之消失)。\n */\nexport function rebuildWorkflowRuns(\n turns: readonly TurnProjection[],\n previous: Readonly<Record<string, WorkflowRunState>>,\n): Record<string, WorkflowRunState> {\n const runs: Record<string, WorkflowRunState> = {}\n for (const turn of turns) {\n for (const toolCall of turn.tool_calls) {\n if (!isWorkflowRunToolName(toolCall.tool_name)) continue\n const name = workflowNameFromArguments(toolCall.arguments)\n const prior = previous[toolCall.id]\n if (isFinished(toolCall.status)) {\n const steps = toolCall.workflow_steps ?? []\n const entries =\n steps.length > 0\n ? workflowEntriesFromSteps(steps)\n : workflowEntriesFromOutput(typeof toolCall.result === \"string\" ? toolCall.result.trim() : \"\")\n const status: WorkflowRunState[\"status\"] =\n toolCall.status === \"error\" && workflowRunCancelled(steps) ? \"cancelled\" : toolCall.status\n runs[toolCall.id] =\n prior &&\n prior.status === status &&\n prior.name === name &&\n JSON.stringify(prior.entries) === JSON.stringify(entries)\n ? prior\n : { toolCallId: toolCall.id, name, status, entries }\n continue\n }\n runs[toolCall.id] =\n prior && prior.name === name\n ? prior\n : { toolCallId: toolCall.id, name, status: prior?.status ?? \"running\", entries: prior?.entries ?? [] }\n }\n }\n return runs\n}\n\n/** 同一次运行里第 n 个子智能体步骤的描述(历史没有 agent:start 通知时给子回路起标题)。 */\nexport function workflowAgentStepDescription(\n run: WorkflowRunState | undefined,\n index: number,\n): string | null {\n if (!run) return null\n const steps = run.entries.filter(\n (entry): entry is Extract<WorkflowRunEntry, { kind: \"step\" }> =>\n entry.kind === \"step\" && entry.stepKind === \"agent\",\n )\n const desc = steps[index]?.desc.trim()\n return desc ? desc : null\n}\n","import type { TopicAssetRef } from \"../schemas/topic-assets\"\nimport type { ChatMessage, CompactionInfo, MessageContent, ToolCallInfo } from \"../schemas/message\"\nimport { normalizeMessageContent } from \"../schemas/message-utils\"\nimport type { ContentBlock, PatchEnvelope, TurnProjection } from \"../schemas/projection\"\nimport { contextProjectionData } from \"../schemas/context\"\nimport type { ReplaySpeed, ReplayState, SessionStatus } from \"../schemas/session\"\nimport { isRecord } from \"../shared/type-guards\"\nimport { userFacingErrorText } from \"../shared/oom\"\nimport { EMPTY_SESSION_QUEUE, shouldApplySnapshot, type SessionQueueSnapshot } from \"./queue\"\nimport {\n applyWorkflowEvent,\n isWorkflowRunToolName,\n rebuildWorkflowRuns,\n workflowAgentStepDescription,\n workflowNameFromArguments,\n type WorkflowRunState,\n} from \"./workflow\"\n\n/** 一次 AskUserQuestion 的用户作答(选项选择 + 自定义输入 + 可选补充)。 */\nexport interface AskUserAnswerData {\n selections: Record<number, number[]>\n custom: Record<number, string>\n /** 选完选项后的自由补充,空着就是没有。 */\n note?: string\n}\n\nexport interface AgentLoopInfo {\n toolCallId: string\n description: string\n status: \"running\" | \"done\" | \"error\" | \"cancelled\" | \"awaiting_answer\"\n /**\n * 工作流步骤 fork 出来的子回路:触发它的 workflow:run 工具调用 id。这类回路没有可解析参数的\n * 父 Agent 工具调用,toolCallId 用回路名合成。普通子智能体没有此字段。\n */\n workflowRunId?: string\n}\n\nexport interface ActiveCompactionState extends CompactionInfo {\n turn_id: string\n status: \"streaming\" | \"completed\" | \"paused\" | \"failed\" | \"interrupted\"\n}\n\nexport type ConnectionStatus = \"connecting\" | \"connected\" | \"reconnecting\" | \"disconnected\"\n\n/**\n * 一个会话的完整快照。引用不可变:任何变更都会产生新对象,\n * 满足 React `useSyncExternalStore` / Vue `shallowRef` 的订阅契约。\n */\nexport interface SessionState {\n sessionId: string\n /** 服务端投影的原始 turn 列表(按 sequence 有序)。 */\n turns: TurnProjection[]\n /** 由 turns 物化出的聊天消息列表,UI 直接渲染。 */\n messages: ChatMessage[]\n /** 智能体是否正在流式回复。 */\n isStreaming: boolean\n /** 会话状态(running / completed / failed / waiting_for_input / interrupted …)。 */\n status: SessionStatus | null\n /** Latest BA execution terminal, restored from durable lifecycle events independently of message paging. */\n lastRun: { runId: string; status: string; result: unknown } | null\n /** 当前模式(planning / executing),来自 mode_change 事件。 */\n mode: \"planning\" | \"executing\" | null\n /** Socket.IO 连接状态(同一 client 下所有会话共享)。 */\n connection: ConnectionStatus\n /** 最近一次运行错误消息(system:error 等)。 */\n errorMessage: string | null\n askAnswers: Record<string, AskUserAnswerData>\n agentLoops: Record<string, AgentLoopInfo>\n activeCompaction: ActiveCompactionState | null\n /**\n * 手动整理已被服务端接受、还没收到结束事件。接受应答与真正的开始事件之间有一段准备时间,\n * 这期间输入框也要保持「正在整理」。\n */\n compactionPending: boolean\n /** 回放(演示 / 彩排)状态;不是回放会话时为 null。 */\n replay: ReplaySnapshot | null\n /** 服务端持久化的等待消息队列快照;只在 revision 更新时替换。 */\n queue: SessionQueueSnapshot\n /** 当前身份对这个会话的权限;\"viewer\" 表示只读(分享链接打开的)。 */\n viewerRole: \"owner\" | \"viewer\" | null\n /** 工作流运行时间线,按触发它的 workflow:run 工具调用 id 索引(见 workflow.ts)。 */\n workflowRuns: Record<string, WorkflowRunState>\n /** Stable anchor for the next older projected page. */\n nextBefore: string | null\n loadingOlder: boolean\n /** 权威历史窗口每提交一次加一(首屏、运行结束 / 重连对账、定位)。向上翻页不算。 */\n historyRevision: number\n /**\n * timeline 被外部整体改写的次数(rewind、游标失效后的整窗修复、显式重载)。消息导航目录据此\n * 当场作废:旧条目的 entry id 可能已经不在新的 timeline 上。定位换窗口不算改写。\n */\n timelineRevision: number\n}\n\n/** 回放会话的快照视图,由服务端的 replay_state 归一化而来。 */\nexport interface ReplaySnapshot {\n /** 仍在按录制内容走;转自主运行后为 false。 */\n isReplay: boolean\n speed: ReplaySpeed\n sourceSessionId: string | null\n}\n\n/** 把服务端的 replay_state 归一化成快照;不是回放会话时返回 null。 */\nexport function toReplaySnapshot(raw: ReplayState | null | undefined): ReplaySnapshot | null {\n if (!raw || !raw.status) return null\n return {\n isReplay: raw.status === \"replay\",\n speed: raw.speed ?? 1,\n sourceSessionId: raw.source_session_id ?? null,\n }\n}\n\nexport function createInitialSessionState(sessionId: string): SessionState {\n return {\n sessionId,\n turns: [],\n messages: [],\n isStreaming: false,\n status: null,\n mode: null,\n connection: \"disconnected\",\n errorMessage: null,\n lastRun: null,\n askAnswers: {},\n agentLoops: {},\n activeCompaction: null,\n compactionPending: false,\n replay: null,\n queue: EMPTY_SESSION_QUEUE,\n viewerRole: null,\n workflowRuns: {},\n nextBefore: null,\n loadingOlder: false,\n historyRevision: 0,\n timelineRevision: 0,\n }\n}\n\nfunction parseAgentDescription(argumentsJson: string): string {\n try {\n return JSON.parse(argumentsJson)?.description ?? \"子智能体\"\n } catch {\n return \"子智能体\"\n }\n}\n\nfunction normalizedToolName(name: string): string {\n const separatorIndex = name.lastIndexOf(\":\")\n return separatorIndex >= 0 ? name.slice(separatorIndex + 1) : name\n}\n\nfunction inferLoopStatusFromMessages(messages: ChatMessage[]): AgentLoopInfo[\"status\"] {\n const toolCalls = messages.flatMap((message) => message.tool_calls ?? [])\n if (messages.some((message) => message.status === \"streaming\")) return \"running\"\n if (messages.some((message) => message.status === \"failed\")) return \"error\"\n if (toolCalls.some((toolCall) => toolCall.status === \"awaiting_answer\")) return \"awaiting_answer\"\n if (toolCalls.some((toolCall) => toolCall.status === \"error\")) return \"error\"\n if (toolCalls.some((toolCall) => toolCall.status === \"cancelled\")) return \"cancelled\"\n if (toolCalls.some((toolCall) => toolCall.status === \"pending\")) return \"running\"\n return \"done\"\n}\n\nfunction inferLoopStatusFromTurns(\n turns: TurnProjection[],\n messages: ChatMessage[],\n): AgentLoopInfo[\"status\"] {\n const messageStatus = inferLoopStatusFromMessages(messages)\n if (messageStatus === \"awaiting_answer\") return messageStatus\n const latestAgentNotification = [...turns]\n .reverse()\n .flatMap((turn) => turn.blocks)\n .find((block) => {\n if (block.type !== \"system_notification\" || !isRecord(block.content)) return false\n return (\n block.content.notification_type === \"agent:start\" ||\n block.content.notification_type === \"agent:end\"\n )\n })\n if (\n latestAgentNotification?.type === \"system_notification\" &&\n isRecord(latestAgentNotification.content)\n ) {\n const notificationType = latestAgentNotification.content.notification_type\n const status = latestAgentNotification.content.status\n if (notificationType === \"agent:start\" || status === \"running\") return \"running\"\n if (status === \"error\") return \"error\"\n if (status === \"cancelled\") return \"cancelled\"\n }\n return messageStatus\n}\n\nfunction toSelectionMap(value: unknown): Record<number, number[]> {\n if (!isRecord(value)) return {}\n const entries = Object.entries(value)\n .map(([questionKey, optionIndexes]) => {\n if (!Array.isArray(optionIndexes)) return null\n const parsedIndexes = optionIndexes\n .map((item) => (typeof item === \"number\" ? item : Number(item)))\n .filter((item) => Number.isInteger(item))\n return [Number(questionKey), parsedIndexes] as const\n })\n .filter((entry): entry is readonly [number, number[]] => entry !== null)\n return Object.fromEntries(entries) as Record<number, number[]>\n}\n\nfunction toCustomMap(value: unknown): Record<number, string> {\n if (!isRecord(value)) return {}\n const entries = Object.entries(value)\n .filter(([, text]) => typeof text === \"string\")\n .map(([questionKey, text]) => [Number(questionKey), text] as const)\n return Object.fromEntries(entries) as Record<number, string>\n}\n\nfunction extractAskAnswers(turns: TurnProjection[]): Record<string, AskUserAnswerData> {\n const answers: Record<string, AskUserAnswerData> = {}\n for (const turn of turns) {\n for (const block of turn.blocks) {\n if (block.type !== \"ask_user_answer\" || typeof block.tool_call_id !== \"string\") continue\n if (!isRecord(block.content)) continue\n const note = typeof block.content.note === \"string\" ? block.content.note.trim() : \"\"\n answers[block.tool_call_id] = {\n selections: toSelectionMap(block.content.selections),\n custom: toCustomMap(block.content.custom),\n ...(note ? { note } : {}),\n }\n }\n }\n return answers\n}\n\nexport function parentForkToolCallIdFromTurn(turn: TurnProjection): string | null {\n if (\n typeof turn.parent_fork_tool_call_id === \"string\" &&\n turn.parent_fork_tool_call_id.length > 0\n ) {\n return turn.parent_fork_tool_call_id\n }\n for (const block of turn.blocks) {\n if (block.type !== \"system_notification\" || !isRecord(block.content)) continue\n const metadata = block.content.metadata\n if (!isRecord(metadata)) continue\n const parentId = metadata.parent_fork_tool_call_id\n if (typeof parentId === \"string\" && parentId.length > 0) return parentId\n }\n return null\n}\n\nfunction buildMessageContent(turn: TurnProjection): MessageContent {\n const textBlocks = turn.blocks.filter((block) => block.type === \"text\")\n if (textBlocks.length === 0) return \"\"\n if (textBlocks.length === 1) return normalizeMessageContent(textBlocks[0].content)\n return textBlocks\n .map((block) => {\n if (typeof block.content === \"string\") return block.content\n return JSON.stringify(block.content)\n })\n .join(\"\")\n}\n\nfunction workspaceNotificationContent(turn: TurnProjection): string {\n const block = turn.blocks.find(\n (candidate) =>\n candidate.type === \"system_notification\" &&\n isRecord(candidate.content) &&\n candidate.content.notification_type === \"workspace_change\",\n )\n if (!block || !isRecord(block.content)) return \"\"\n const title = typeof block.content.title === \"string\" ? block.content.title.trim() : \"\"\n const detail = typeof block.content.detail === \"string\" ? block.content.detail.trim() : \"\"\n return [title ? `**${title}**` : \"\", detail].filter(Boolean).join(\"\\n\\n\")\n}\n\nfunction askUserAnswerContent(turn: TurnProjection): string | null {\n const answerBlock = turn.blocks.find((block) => block.type === \"ask_user_answer\")\n if (!answerBlock || !isRecord(answerBlock.content)) return null\n const answer = answerBlock.content.answer\n return typeof answer === \"string\" && answer.trim().length > 0 ? answer : null\n}\n\nfunction buildReasoning(turn: TurnProjection): string | undefined {\n const thinking = turn.blocks\n .filter((block) => block.type === \"thinking\")\n .map((block) => (typeof block.content === \"string\" ? block.content : JSON.stringify(block.content)))\n .filter(Boolean)\n if (thinking.length === 0) return undefined\n return thinking.join(\"\\n\\n\")\n}\n\nfunction isModeChangeContent(value: unknown): value is { from: string; to: string } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { from?: unknown }).from === \"string\" &&\n typeof (value as { to?: unknown }).to === \"string\"\n )\n}\n\nexport function extractModeFromBlocks(blocks: ContentBlock[]): \"planning\" | \"executing\" | null {\n const modeBlock = blocks.find((block) => block.type === \"mode_change\")\n if (modeBlock && isModeChangeContent(modeBlock.content)) {\n return modeBlock.content.to === \"planning\" || modeBlock.content.to === \"executing\"\n ? modeBlock.content.to\n : null\n }\n return null\n}\n\nfunction projectionToMessage(turn: TurnProjection): ChatMessage | null {\n if (turn.kind === \"context\") {\n const context = contextProjectionData(turn)\n if (!context) return null\n return {\n role: \"assistant\",\n content: \"\",\n kind: \"context\",\n context,\n loop_name: turn.loop_id,\n entry_id: turn.turn_id,\n status: turn.status,\n }\n }\n if (turn.kind === \"compaction\" && turn.compaction_id) {\n return {\n role: \"assistant\",\n content: turn.summary_preview ?? \"\",\n kind: \"compaction\",\n loop_name: turn.loop_id,\n entry_id: turn.turn_id,\n status: turn.status,\n compaction: {\n compaction_id: turn.compaction_id,\n summary_preview: turn.summary_preview,\n summary_full: turn.summary_full,\n archived_count: turn.archived_count,\n archived_files: turn.archived_files,\n archived_tool_calls: turn.archived_tool_calls,\n tokens_before: turn.tokens_before,\n tokens_after: turn.tokens_after,\n saved_ratio: turn.saved_ratio,\n trigger: turn.trigger,\n failure_reason: turn.failure_reason,\n fallback_applied: turn.fallback_applied,\n },\n }\n }\n\n const planningBlock = turn.blocks.find(\n (block) => block.type === \"mode_change\" || block.type === \"plan_status\",\n )\n if (planningBlock) {\n if (planningBlock.type === \"plan_status\") {\n return {\n role: \"tool\",\n content:\n typeof planningBlock.content === \"string\"\n ? planningBlock.content\n : JSON.stringify(planningBlock.content ?? {}, null, 2),\n kind: \"plan_status\",\n loop_name: turn.loop_id,\n entry_id: turn.turn_id,\n status: turn.status,\n }\n }\n return {\n role: \"assistant\",\n content:\n typeof planningBlock.content === \"string\"\n ? planningBlock.content\n : JSON.stringify(planningBlock.content ?? {}),\n kind: planningBlock.type,\n loop_name: turn.loop_id,\n entry_id: turn.turn_id,\n status: turn.status,\n }\n }\n\n const askAnswer = askUserAnswerContent(turn)\n if (askAnswer !== null) {\n return {\n role: \"user\",\n content: askAnswer,\n blocks: turn.blocks,\n loop_name: turn.loop_id,\n entry_id: turn.turn_id,\n status: turn.status,\n ...(typeof turn.duration_ms === \"number\" ? { duration_ms: turn.duration_ms } : {}),\n ...(turn.started_at ? { timestamp: turn.started_at } : {}),\n }\n }\n\n const content = buildMessageContent(turn) || workspaceNotificationContent(turn)\n const reasoning = buildReasoning(turn)\n const toolCalls: ToolCallInfo[] | undefined =\n turn.tool_calls.length > 0\n ? turn.tool_calls.map((toolCall) => ({\n id: toolCall.id,\n name: toolCall.tool_name,\n display_name: toolCall.display_name,\n arguments: toolCall.arguments,\n result: toolCall.result ?? undefined,\n ...(toolCall.evidence ? { evidence: toolCall.evidence } : {}),\n pending_question_ref: toolCall.pending_question_ref ?? undefined,\n workflow_steps: toolCall.workflow_steps ?? undefined,\n status:\n toolCall.status === \"pending\" ||\n toolCall.status === \"awaiting_answer\" ||\n toolCall.status === \"done\" ||\n toolCall.status === \"error\" ||\n toolCall.status === \"cancelled\"\n ? toolCall.status\n : \"pending\",\n ...(typeof toolCall.duration_ms === \"number\" ? { duration_ms: toolCall.duration_ms } : {}),\n }))\n : undefined\n\n if (turn.role === \"system\" && !content && !toolCalls?.length) {\n return null\n }\n\n return {\n role: turn.role === \"system\" ? \"assistant\" : turn.role,\n content,\n blocks: turn.blocks,\n ...(reasoning ? { reasoning } : {}),\n ...(toolCalls ? { tool_calls: toolCalls } : {}),\n loop_name: turn.loop_id,\n entry_id: turn.turn_id,\n ...(turn.client_request_id ? { client_request_id: turn.client_request_id } : {}),\n status: turn.status,\n ...(typeof turn.duration_ms === \"number\" ? { duration_ms: turn.duration_ms } : {}),\n ...(turn.started_at ? { timestamp: turn.started_at } : {}),\n ...(turn.memory_refs?.length ? { memory_refs: turn.memory_refs } : {}),\n ...(turn.refs?.length ? { refs: turn.refs } : {}),\n ...(turn.context_attachments?.length ? { context_attachments: turn.context_attachments } : {}),\n ...(turn.topic_asset_refs?.length ? { topic_asset_refs: turn.topic_asset_refs } : {}),\n }\n}\n\nconst messageProjectionCache = new WeakMap<TurnProjection, ChatMessage | null>()\n\nfunction cachedProjectionToMessage(turn: TurnProjection): ChatMessage | null {\n if (messageProjectionCache.has(turn)) {\n return messageProjectionCache.get(turn) ?? null\n }\n const message = projectionToMessage(turn)\n messageProjectionCache.set(turn, message)\n return message\n}\n\nfunction workflowLoopNotificationDescription(loopTurns: TurnProjection[]): string | null {\n for (const turn of loopTurns) {\n for (const block of turn.blocks) {\n if (block.type !== \"system_notification\" || !isRecord(block.content)) continue\n if (block.content.notification_type !== \"agent:start\") continue\n const metadata = block.content.metadata\n const fromMetadata =\n isRecord(metadata) && typeof metadata.description === \"string\" ? metadata.description : \"\"\n const direct = typeof block.content.description === \"string\" ? block.content.description : \"\"\n const description = (fromMetadata || direct).trim()\n if (description) return description\n }\n }\n return null\n}\n\nconst WORKFLOW_STEP_FALLBACK_DESCRIPTION = \"工作流步骤\"\n\nfunction rebuildAgentLoops(\n turns: TurnProjection[],\n messages: ChatMessage[],\n workflowRuns: Record<string, WorkflowRunState>,\n): Record<string, AgentLoopInfo> {\n const childLoopNames = [\n ...new Set(turns.map((turn) => turn.loop_id).filter((name) => name !== \"root\")),\n ]\n if (childLoopNames.length === 0) return {}\n\n const rootToolCalls = messages\n .filter((message) => message.role === \"assistant\" && (message.loop_name ?? \"root\") === \"root\")\n .flatMap((message) => message.tool_calls ?? [])\n const agentToolCalls = rootToolCalls.filter((toolCall) => normalizedToolName(toolCall.name) === \"Agent\")\n const workflowRunToolCallIds = new Set(\n rootToolCalls.filter((toolCall) => isWorkflowRunToolName(toolCall.name)).map((toolCall) => toolCall.id),\n )\n const workflowLoopCounts = new Map<string, number>()\n\n const loops: Record<string, AgentLoopInfo> = {}\n const agentToolCallsById = new Map(agentToolCalls.map((toolCall) => [toolCall.id, toolCall]))\n const explicitParentToolCallIds = new Set(\n turns.map(parentForkToolCallIdFromTurn).filter((id): id is string => id !== null),\n )\n const usedToolCallIds = new Set<string>()\n for (const loopName of childLoopNames) {\n const loopMessages = messages.filter((message) => (message.loop_name ?? \"root\") === loopName)\n const loopTurns = turns.filter((turn) => turn.loop_id === loopName)\n const parentToolCallId = loopTurns.map(parentForkToolCallIdFromTurn).find(Boolean)\n if (parentToolCallId && workflowRunToolCallIds.has(parentToolCallId)) {\n const index = workflowLoopCounts.get(parentToolCallId) ?? 0\n workflowLoopCounts.set(parentToolCallId, index + 1)\n loops[loopName] = {\n toolCallId: loopName,\n description:\n workflowLoopNotificationDescription(loopTurns) ??\n workflowAgentStepDescription(workflowRuns[parentToolCallId], index) ??\n WORKFLOW_STEP_FALLBACK_DESCRIPTION,\n status: inferLoopStatusFromTurns(loopTurns, loopMessages),\n workflowRunId: parentToolCallId,\n }\n continue\n }\n const explicitToolCall =\n parentToolCallId && !usedToolCallIds.has(parentToolCallId)\n ? (agentToolCallsById.get(parentToolCallId) ?? null)\n : null\n const fallbackToolCall =\n explicitToolCall === null\n ? agentToolCalls.find(\n (toolCall) =>\n !usedToolCallIds.has(toolCall.id) && !explicitParentToolCallIds.has(toolCall.id),\n )\n : null\n const toolCall = explicitToolCall ?? fallbackToolCall\n if (!toolCall) continue\n usedToolCallIds.add(toolCall.id)\n loops[loopName] = {\n toolCallId: toolCall.id,\n description: parseAgentDescription(toolCall.arguments),\n status: inferLoopStatusFromTurns(loopTurns, loopMessages),\n }\n }\n return loops\n}\n\nfunction materialize(turns: TurnProjection[], workflowRuns: Record<string, WorkflowRunState>) {\n const projectedMessages = turns\n .map(cachedProjectionToMessage)\n .filter((message): message is ChatMessage => message !== null)\n const messages = projectedMessages.filter((message, index, allMessages) => {\n if (!message.blocks?.some((block) => block.type === \"ask_user_answer\")) return true\n const next = allMessages[index + 1]\n return !(next?.role === \"user\" && next.content === message.content)\n })\n const activeCompaction = [...turns]\n .reverse()\n .find(\n (turn): turn is TurnProjection =>\n turn.kind === \"compaction\" &&\n turn.status === \"streaming\" &&\n typeof turn.compaction_id === \"string\",\n )\n return {\n messages,\n agentLoops: rebuildAgentLoops(turns, projectedMessages, workflowRuns),\n activeCompaction: activeCompaction\n ? {\n turn_id: activeCompaction.turn_id,\n status: activeCompaction.status,\n compaction_id: activeCompaction.compaction_id!,\n summary_preview: activeCompaction.summary_preview,\n summary_full: activeCompaction.summary_full,\n archived_count: activeCompaction.archived_count,\n archived_files: activeCompaction.archived_files,\n archived_tool_calls: activeCompaction.archived_tool_calls,\n tokens_before: activeCompaction.tokens_before,\n tokens_after: activeCompaction.tokens_after,\n saved_ratio: activeCompaction.saved_ratio,\n trigger: activeCompaction.trigger,\n failure_reason: activeCompaction.failure_reason,\n fallback_applied: activeCompaction.fallback_applied,\n }\n : null,\n }\n}\n\nconst ERROR_ANCHOR_PREFIX = \"error-anchor:\"\n\nfunction orderTurns(turns: TurnProjection[]) {\n for (let index = 1; index < turns.length; index += 1) {\n if (turns[index - 1].sequence > turns[index].sequence) {\n return [...turns].sort((left, right) => left.sequence - right.sequence)\n }\n }\n return turns\n}\n\nexport function reconcileOptimisticUserTurns(\n currentTurns: TurnProjection[],\n incomingTurns: TurnProjection[],\n): TurnProjection[] {\n return reconcileUserTurns(currentTurns, incomingTurns, true, false)\n}\n\n/** Reconcile a bulk authoritative window only by an echoed request identity.\n * Positional fallback is reserved for a single live turn from an older server. */\nexport function reconcileHistoricalUserTurns(\n currentTurns: TurnProjection[],\n incomingTurns: TurnProjection[],\n): TurnProjection[] {\n return reconcileUserTurns(currentTurns, incomingTurns, false, true)\n}\n\nfunction reconcileUserTurns(\n currentTurns: TurnProjection[],\n incomingTurns: TurnProjection[],\n allowLiveFallback: boolean,\n keepUnclaimedOptimistic: boolean,\n): TurnProjection[] {\n const preservedTurns = preserveClientRenderIds(currentTurns, incomingTurns)\n const optimisticUserTurns = currentTurns.filter(\n (turn) =>\n turn.role === \"user\" &&\n (turn.kind ?? \"message\") === \"message\" &&\n turn.turn_id.startsWith(\"local-user-\"),\n )\n const optimisticByRequestId = new Map(\n optimisticUserTurns.map((turn) => [\n turn.turn_id.slice(\"local-user-\".length),\n turn,\n ]),\n )\n const currentTurnIds = new Set(currentTurns.map((turn) => turn.turn_id))\n const claimedOptimisticIds = new Set<string>()\n const reconciled = preservedTurns.map((turn) => {\n const exactOptimistic =\n typeof turn.client_request_id === \"string\"\n ? optimisticByRequestId.get(turn.client_request_id)\n : undefined\n if (\n exactOptimistic &&\n !claimedOptimisticIds.has(exactOptimistic.turn_id) &&\n isUserConfirmation(turn)\n ) {\n claimedOptimisticIds.add(exactOptimistic.turn_id)\n return { ...turn, client_render_id: exactOptimistic.turn_id }\n }\n const fallbackOptimistic = optimisticUserTurns.find(\n (candidate) => !claimedOptimisticIds.has(candidate.turn_id),\n )\n if (\n allowLiveFallback &&\n typeof turn.client_request_id !== \"string\" &&\n fallbackOptimistic &&\n isUserConfirmation(turn) &&\n !turn.turn_id.startsWith(\"local-user-\") &&\n !currentTurnIds.has(turn.turn_id)\n ) {\n claimedOptimisticIds.add(fallbackOptimistic.turn_id)\n return { ...turn, client_render_id: fallbackOptimistic.turn_id }\n }\n return turn\n })\n const result =\n claimedOptimisticIds.size === 0\n ? reconciled\n : reconciled.filter((turn) => !claimedOptimisticIds.has(turn.turn_id))\n if (!keepUnclaimedOptimistic) return result\n // 只补回真正从结果里缺席的乐观 turn——claimedOptimisticIds 只覆盖\"这次调用\n // 里用 client_request_id/位置兜底重新认领过\"的情况,reconcile 一个已经\n // 包含这条乐观 turn 本身的列表(比如 upsertTurn 认领替换完之后,\n // withTurns 内部拿最终列表对自己再 reconcile 一遍)时,它既没被这次调用\n // 认领、也已经原样出现在 result 里,不能再重复拼一份。\n const resultIds = new Set(result.map((turn) => turn.turn_id))\n const unclaimedOptimisticTurns = optimisticUserTurns.filter(\n (turn) => !claimedOptimisticIds.has(turn.turn_id) && !resultIds.has(turn.turn_id),\n )\n return unclaimedOptimisticTurns.length === 0\n ? result\n : orderTurns([...result, ...unclaimedOptimisticTurns])\n}\n\nfunction isUserConfirmation(turn: TurnProjection): boolean {\n return (\n (turn.role === \"user\" && (turn.kind ?? \"message\") === \"message\") ||\n turn.blocks.some((block) => block.type === \"ask_user_answer\")\n )\n}\n\n/**\n * 同一条回合换成新版本时保留本地已知、新版本却缺失的字段:\n * - client_render_id:乐观发言确认后的稳定渲染标识;\n * - memory_refs:完成投影与历史同步有时不带经验引用(引用只在流式过程中下发一次)。\n */\nexport function preserveLocalTurnMetadata(\n next: TurnProjection,\n previous: TurnProjection | undefined,\n): TurnProjection {\n if (!previous) return next\n const memoryRefs = next.memory_refs?.length ? next.memory_refs : previous.memory_refs\n const clientRenderId = next.client_render_id || previous.client_render_id\n if (memoryRefs === next.memory_refs && clientRenderId === next.client_render_id) return next\n return {\n ...next,\n ...(memoryRefs?.length ? { memory_refs: memoryRefs } : {}),\n ...(clientRenderId ? { client_render_id: clientRenderId } : {}),\n }\n}\n\nfunction preserveClientRenderIds(\n currentTurns: TurnProjection[],\n incomingTurns: TurnProjection[],\n): TurnProjection[] {\n const currentById = new Map(currentTurns.map((turn) => [turn.turn_id, turn]))\n return incomingTurns.map((turn) => preserveLocalTurnMetadata(turn, currentById.get(turn.turn_id)))\n}\n\nfunction areAgentLoopsEqual(\n left: Record<string, AgentLoopInfo> | undefined,\n right: Record<string, AgentLoopInfo>,\n) {\n if (!left) return Object.keys(right).length === 0\n const leftEntries = Object.entries(left)\n const rightKeys = Object.keys(right)\n if (leftEntries.length !== rightKeys.length) return false\n return leftEntries.every(([key, value]) => {\n const next = right[key]\n return (\n next !== undefined &&\n value.toolCallId === next.toolCallId &&\n value.description === next.description &&\n value.status === next.status &&\n value.workflowRunId === next.workflowRunId\n )\n })\n}\n\n/**\n * 用一份新的 turn 列表重建会话状态。\n * addErrorMessage 注入的 role===\"error\" 消息不在 turns 里,默认会被物化过程抹掉;\n * 这里沿用锚点策略:只保留锚定在\"当前最后一个 turn\"上的错误气泡,\n * turn 推进(新消息 / rewind / 重连)时旧错误自动消失。\n */\nexport function withTurns(state: SessionState, turns: TurnProjection[]): SessionState {\n const orderedTurns = orderTurns(reconcileHistoricalUserTurns(state.turns, turns))\n const workflowRuns = rebuildWorkflowRuns(orderedTurns, state.workflowRuns)\n const { messages, agentLoops, activeCompaction } = materialize(orderedTurns, workflowRuns)\n const isWaitingForInput = orderedTurns.some((turn) =>\n turn.tool_calls.some((toolCall) => toolCall.status === \"awaiting_answer\"),\n )\n const stableAgentLoops = areAgentLoopsEqual(state.agentLoops, agentLoops)\n ? state.agentLoops\n : agentLoops\n const lastTurnId = orderedTurns[orderedTurns.length - 1]?.turn_id ?? null\n const preservedErrors = lastTurnId\n ? state.messages.filter(\n (m) =>\n m.role === \"error\" &&\n typeof m.entry_id === \"string\" &&\n m.entry_id.startsWith(`${ERROR_ANCHOR_PREFIX}${lastTurnId}:`),\n )\n : []\n const turnById = new Map(orderedTurns.map((turn) => [turn.turn_id, turn]))\n const messagesWithRenderIds = messages.map((message) => {\n if (!message.entry_id) return message\n const renderId = turnById.get(message.entry_id)?.client_render_id\n return renderId ? { ...message, render_id: renderId } : message\n })\n const latestTurn = orderedTurns[orderedTurns.length - 1]\n const historyError =\n latestTurn?.status === \"failed\" && latestTurn.error_message ? userFacingErrorText(latestTurn.error_message) : null\n const errorMessages = historyError\n ? preservedErrors.some((message) => message.content === historyError)\n ? preservedErrors\n : [{ role: \"error\" as const, content: historyError, loop_name: \"root\", entry_id: `${ERROR_ANCHOR_PREFIX}${lastTurnId}:0` }]\n : preservedErrors\n const mergedMessages = [...messagesWithRenderIds, ...errorMessages]\n const latestMode = [...orderedTurns]\n .reverse()\n .map((turn) => extractModeFromBlocks(turn.blocks))\n .find((mode): mode is \"planning\" | \"executing\" => mode !== null)\n const askAnswersFromHistory = extractAskAnswers(orderedTurns)\n const presentToolCallIds = new Set(\n orderedTurns.flatMap((turn) => turn.tool_calls.map((toolCall) => toolCall.id)),\n )\n const askAnswers: Record<string, AskUserAnswerData> = { ...askAnswersFromHistory }\n for (const [toolCallId, answer] of Object.entries(state.askAnswers)) {\n if (!(toolCallId in askAnswers) && presentToolCallIds.has(toolCallId)) {\n askAnswers[toolCallId] = answer\n }\n }\n return {\n ...state,\n turns: orderedTurns,\n messages: mergedMessages,\n errorMessage: historyError ?? (\n lastTurnId === (state.turns[state.turns.length - 1]?.turn_id ?? null)\n ? state.errorMessage\n : null\n ),\n agentLoops: stableAgentLoops,\n workflowRuns: sameWorkflowRuns(state.workflowRuns, workflowRuns) ? state.workflowRuns : workflowRuns,\n activeCompaction,\n askAnswers,\n mode: latestMode ?? state.mode,\n status: isWaitingForInput ? \"waiting_for_input\" : state.status,\n }\n}\n\n/**\n * 安装一份服务端权威队列快照。旧 revision、别的会话或结构不合法的快照一律不采纳,\n * 直接返回原 state——引用不变,订阅者不会收到多余通知。\n */\nexport function withQueue(state: SessionState, snapshot: SessionQueueSnapshot): SessionState {\n if (!shouldApplySnapshot(state.queue, snapshot)) return state\n return { ...state, queue: snapshot }\n}\n\nlet localTurnCounter = 0\n\nexport function addUserMessage(\n state: SessionState,\n content: MessageContent,\n clientRequestId?: string,\n topicAssetRefs?: TopicAssetRef[],\n refs?: import(\"../schemas/plugin-refs\").MessageRef[],\n contextAttachments?: import(\"../schemas/context-attachments\").ContextAttachment[],\n): SessionState {\n localTurnCounter += 1\n const turnId = `local-user-${clientRequestId ?? `${Date.now()}-${localTurnCounter}`}`\n const optimisticTurn: TurnProjection = {\n id: turnId,\n sequence: Math.max(0, ...state.turns.map((turn) => turn.sequence)) + 1,\n turn_id: turnId,\n client_render_id: turnId,\n ...(refs ? { refs } : {}),\n ...(contextAttachments?.length ? { context_attachments: contextAttachments } : {}),\n ...(topicAssetRefs?.length ? { topic_asset_refs: topicAssetRefs } : {}),\n loop_id: \"root\",\n role: \"user\",\n status: \"streaming\",\n blocks: [{ type: \"text\", content }],\n tool_calls: [],\n model: null,\n usage: null,\n duration_ms: 0,\n }\n return withTurns(state, [...state.turns, optimisticTurn])\n}\n\nexport function upsertTurn(state: SessionState, turn: TurnProjection): SessionState {\n let existing = [...state.turns]\n const [nextTurn] = reconcileOptimisticUserTurns(existing, [turn])\n const claimedOptimisticId = nextTurn.client_render_id\n if (claimedOptimisticId?.startsWith(\"local-user-\")) {\n existing = existing.filter((item) => item.turn_id !== claimedOptimisticId)\n }\n const index = existing.findIndex((item) => item.turn_id === nextTurn.turn_id)\n if (index >= 0) {\n existing[index] = preserveLocalTurnMetadata(nextTurn, existing[index])\n } else {\n existing.push(nextTurn)\n }\n return withTurns({ ...state, turns: existing }, existing)\n}\n\nexport function applyTurnPatch(state: SessionState, patch: PatchEnvelope): SessionState {\n const turn = patch.data.turn\n if (!turn) return state\n\n const existing = [...state.turns]\n const index = existing.findIndex((item) => item.turn_id === turn.turn_id)\n const lastSequence = index >= 0 ? existing[index].sequence : null\n if (lastSequence !== null && patch.sequence <= lastSequence) {\n return state\n }\n\n return upsertTurn(state, { ...turn, sequence: patch.sequence })\n}\n\nexport function addErrorMessage(state: SessionState, content: string): SessionState {\n const anchorTurnId = state.turns[state.turns.length - 1]?.turn_id ?? null\n const entry_id = anchorTurnId\n ? `${ERROR_ANCHOR_PREFIX}${anchorTurnId}:0`\n : undefined\n if (state.messages.some((message) =>\n message.role === \"error\" && message.entry_id === entry_id && message.content === content\n )) return state\n const others = entry_id\n ? state.messages.filter((message) => !(message.role === \"error\" && message.entry_id === entry_id))\n : state.messages\n return {\n ...state,\n messages: [...others, { role: \"error\", content, loop_name: \"root\", entry_id }],\n }\n}\n\nexport function markInterrupted(state: SessionState): SessionState {\n return markStreamingTurns(state, \"interrupted\", \"cancelled\")\n}\n\nexport function markFailed(state: SessionState): SessionState {\n return markStreamingTurns(state, \"failed\", \"error\")\n}\n\nfunction markStreamingTurns(\n state: SessionState,\n turnStatus: \"interrupted\" | \"failed\",\n toolCallStatus: \"cancelled\" | \"error\",\n): SessionState {\n const turns = state.turns.map((turn) => {\n if (turn.status !== \"streaming\") return turn\n return {\n ...turn,\n status: turnStatus,\n tool_calls: turn.tool_calls.map((toolCall) =>\n toolCall.status === \"pending\" || toolCall.status === \"awaiting_answer\"\n ? { ...toolCall, status: toolCallStatus }\n : toolCall,\n ),\n }\n })\n return withTurns(state, turns)\n}\n\nfunction sameWorkflowRuns(\n left: Record<string, WorkflowRunState>,\n right: Record<string, WorkflowRunState>,\n): boolean {\n const leftKeys = Object.keys(left)\n if (leftKeys.length !== Object.keys(right).length) return false\n return leftKeys.every((key) => left[key] === right[key])\n}\n\n/**\n * 叠加一条实时 workflow 事件。工具调用已经结束(时间线以工具结果为准)或不在当前 turn 列表里时\n * 忽略;工作流名固定取工具参数,与历史同源。\n */\nexport function withWorkflowEvent(\n state: SessionState,\n toolCallId: string,\n type: string,\n payload: Record<string, unknown>,\n): SessionState {\n const toolCall = state.turns.flatMap((turn) => turn.tool_calls).find((call) => call.id === toolCallId)\n if (!toolCall || !isWorkflowRunToolName(toolCall.tool_name)) return state\n if (toolCall.status === \"done\" || toolCall.status === \"error\" || toolCall.status === \"cancelled\") {\n return state\n }\n const next = applyWorkflowEvent(state.workflowRuns[toolCallId], toolCallId, type, payload)\n if (!next) return state\n const run = { ...next, name: workflowNameFromArguments(toolCall.arguments) }\n const workflowRuns = { ...state.workflowRuns, [toolCallId]: run }\n const { agentLoops } = materialize(state.turns, workflowRuns)\n return {\n ...state,\n workflowRuns,\n agentLoops: areAgentLoopsEqual(state.agentLoops, agentLoops) ? state.agentLoops : agentLoops,\n }\n}\n\n/**\n * 撤回还没被服务端确认的乐观发言:`clientRequestIds` 给出时只撤回这些请求,否则撤回全部。\n * 用于排队中断的 chat:end(服务端取消了排队中的发送)。\n */\nexport function withoutOptimisticUserTurns(\n state: SessionState,\n clientRequestIds?: readonly string[],\n): SessionState {\n const cancelled = clientRequestIds?.length\n ? new Set(clientRequestIds.map((requestId) => `local-user-${requestId}`))\n : null\n const retained = state.turns.filter(\n (turn) =>\n turn.role !== \"user\" ||\n !turn.turn_id.startsWith(\"local-user-\") ||\n (cancelled !== null && !cancelled.has(turn.turn_id)),\n )\n if (retained.length === state.turns.length) return state\n return withTurns({ ...state, turns: retained }, retained)\n}\n","/**\n * 一次会话操作的失败。\n *\n * `code` 是服务端给的机器可读原因(如 `owner_timeout` / `route_broken`),\n * 调用方据此决定要不要重试;`message` 是可以直接展示的业务文案,不要当协议解析。\n */\nexport class AgentSessionError extends Error {\n readonly name = \"AgentSessionError\"\n readonly code?: string\n\n constructor(message: string, code?: string) {\n super(message)\n this.code = code\n }\n}\n","import { snapshotContextAttachments, type ContextAttachment } from \"../schemas/context-attachments\"\nimport { completedBackgroundTask, type BackgroundTaskEvent } from \"./background\"\nimport { LogCursor } from \"./log-cursor\"\nimport type { TopicAssetRef } from \"../schemas/topic-assets\"\nimport {\n acceptedPostChatFollowupCompletesLatestRun,\n ClientProjectionBuilder,\n hasChatRunEvent,\n type RawEvent,\n} from \"../shared/projection\"\nimport type { MessageContent, ToolBridgeContent, ToolCallInfo } from \"../schemas/message\"\nimport type { ContentBlock, PatchEnvelope, TurnProjection } from \"../schemas/projection\"\nimport type { ReplaySpeed, ReplayState, SessionStatus } from \"../schemas/session\"\nimport { CommandRegistry, type CommandHandler } from \"../commands/registry\"\nimport { Emitter, type AgentSessionEvents } from \"./events\"\nimport type {\n AppCliAttachment,\n AppCliDefinition,\n FileEntry,\n HistoricalCommand,\n SessionTurnIndex,\n SessionTurnIndexItem,\n SessionTurnsPage,\n SessionTurnsQuery,\n} from \"../resources/sessions\"\nimport { prependOlder, replaceWindow } from \"./history-page\"\nimport {\n canEditQueuedMessage,\n isSessionQueueSnapshot,\n parseQueueAck,\n type QueueOperationResult,\n} from \"./queue\"\nimport { isEntryGoneError } from \"../resources/sessions\"\nimport { isOomText, OOM_MESSAGE, userFacingErrorText } from \"../shared/oom\"\nimport { isRecord } from \"../shared/type-guards\"\nimport {\n buildToolUiCardKey,\n isToolUiCard,\n resolveToolUiCardContent,\n} from \"../shared/tool-ui-card\"\nimport {\n addErrorMessage,\n addUserMessage,\n applyTurnPatch,\n createInitialSessionState,\n withoutOptimisticUserTurns,\n withWorkflowEvent,\n extractModeFromBlocks,\n markFailed,\n markInterrupted,\n toReplaySnapshot,\n upsertTurn,\n withQueue,\n withTurns,\n type AskUserAnswerData,\n type ConnectionStatus,\n type SessionState,\n} from \"./state\"\nimport { AgentSessionError } from \"./errors\"\nimport { isWorkflowEvent } from \"./workflow\"\n\n/** SessionHub 注入给 AgentSession 的运行时依赖(socket 收发 + REST 补数)。 */\nexport interface SessionRuntime {\n emitEvent(event: string, data: unknown): void\n emitWithAck(\n event: string,\n data: unknown,\n timeoutMs: number,\n ): Promise<Record<string, unknown> | undefined>\n ensureConnected(): void\n fetchTurnsPage(\n sessionId: string,\n query?: SessionTurnsQuery,\n init?: RequestInit,\n ): Promise<SessionTurnsPage>\n fetchTurnIndex(sessionId: string): Promise<SessionTurnIndex>\n fetchCommands(sessionId: string): Promise<HistoricalCommand[]>\n /**\n * 会话详情包含会话状态、回放状态、查看权限和运行时类型。`fresh` 为 true 时必须取最新值\n * (重连补数);为 false 时宿主可以复用刚取过的一份(进入会话)。\n */\n fetchSessionInfo(\n sessionId: string,\n options?: { fresh?: boolean },\n ): Promise<SessionDetailSnapshot>\n updateReplay(\n sessionId: string,\n payload: { speed?: ReplaySpeed; status?: \"autonomous\" },\n ): Promise<ReplayState | null>\n listDir(sessionId: string, dirPath: string): Promise<FileEntry[]>\n countFiles(sessionId: string, dirPath?: string): Promise<number>\n downloadFile(sessionId: string, filePath: string, downloadName?: string): Promise<void>\n attachAppCli(sessionId: string, definition: AppCliDefinition): Promise<AppCliAttachment>\n /**\n * 归还一份持有。返回 true 表示这是最后一份、实例可以真正释放;\n * 返回 false 表示还有别的持有者,实例必须继续工作。\n */\n onDispose(session: AgentSession): boolean\n}\n\nexport interface SessionDetailSnapshot {\n status?: SessionStatus\n replay_state?: ReplayState | null\n viewer_role?: \"owner\" | \"viewer\"\n}\n\n/** 服务端 chat:end 载荷里 AgentSession 关心的字段。 */\nexport interface ChatEndPayload {\n chat_run_id?: string\n result?: unknown\n status?: string\n /** 排队中断:服务端取消了排队中的发送,`cancelled_client_request_ids` 是被取消的请求。 */\n queued?: boolean\n cancelled_client_request_ids?: unknown\n pause_tool_data?: Record<string, unknown>\n}\n\nexport interface AttachAppOptions {\n /** 可选;只需要页面上下文时无需提供 CLI。 */\n cli?: AppCliDefinition\n /** 每次发送前执行一次;返回当前页面状态的 JSON 对象快照。 */\n getContext: () => Record<string, unknown> | Promise<Record<string, unknown>>\n}\n\nexport interface SendOptions {\n contextAttachments?: ContextAttachment[]\n /** planning / executing 模式。 */\n mode?: string\n /** AskUserQuestion 的作答(tool_call_id + 选项)。 */\n askUserAnswer?: Record<string, unknown>\n /** 本次运行的模型覆盖。 */\n model?: string\n /** 本次运行是否强制开/关思考。 */\n thinkingOverride?: boolean\n /** 本次运行的推理强度(模型支持时生效)。 */\n reasoningLevel?: string\n whatif?: {\n from_step: number\n quotes: Array<Record<string, unknown>>\n deprecate_entry_ids: string[]\n }\n replayDecision?: \"keep_replay\" | \"continue_replay\"\n /** 用户显式选择的知识库 id;后端将元信息作为 once Context 提供给模型。 */\n /** Explicit topic assets for this message only. */\n refs?: import(\"../schemas/plugin-refs\").MessageRef[]\n topicAssetRefs?: TopicAssetRef[]\n /**\n * 默认发送引导消息;显式为 true 时等待当前运行结束(等待回答时发送仍作答)。\n */\n queueWhenRunning?: boolean\n}\n\n/** Durable text input with message-scoped application data. Persist this JSON value before calling sendPrepared. */\nexport interface PreparedSend {\n sessionId: string\n requestId: string\n content: string\n options: PreparedSendOptions\n}\n\nexport interface PreparedSendOptions {\n /** Require BA submit_result for this execution. */\n headless?: boolean\n /** false 时补充当前运行;省略或 true 时等待下一轮。 */\n queueWhenRunning?: boolean\n contextAttachments?: ContextAttachment[]\n mode?: \"planning\" | \"executing\"\n model?: string\n thinkingOverride?: boolean\n reasoningLevel?: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\"\n}\n\nexport interface DeliveryReceipt {\n requestId: string\n status: \"accepted\" | \"not_found\" | \"rejected\" | \"unknown\"\n itemId?: string\n queueStatus?: string\n executionId?: string | null\n message?: string\n}\n\nconst COMMAND_RESTORE_RETRY_BASE_MS = 1_000\nconst COMMAND_RESTORE_RETRY_MAX_MS = 30_000\nconst QUEUE_ACK_TIMEOUT_MS = 10_000\nlet fallbackRequestCounter = 0\n\nfunction createClientRequestId(): string {\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID()\n }\n fallbackRequestCounter += 1\n return `${Date.now()}-${Math.random().toString(36).slice(2)}-${fallbackRequestCounter}`\n}\n\n\nfunction describeSessionError(\n error: unknown,\n fallback: string,\n): { message: string; code?: string } {\n if (error instanceof AgentSessionError) {\n return {\n message: error.message || fallback,\n ...(error.code ? { code: error.code } : {}),\n }\n }\n if (error instanceof Error && error.message) return { message: error.message }\n return { message: fallback }\n}\n\nfunction parseJsonRecord(value: unknown): Record<string, unknown> | null {\n if (isRecord(value)) return value\n if (typeof value !== \"string\") return null\n try {\n const parsed = JSON.parse(value)\n return isRecord(parsed) ? parsed : null\n } catch {\n return null\n }\n}\n\nfunction isOomResult(value: unknown): boolean {\n if (Array.isArray(value)) {\n return value.some((part) => isOomResult(part))\n }\n if (typeof value === \"object\" && value !== null) {\n const record = value as Record<string, unknown>\n if (record.exit_code === 137) return true\n if (typeof record.text === \"string\" && isOomText(record.text)) return true\n if (typeof record.content === \"string\" && isOomText(record.content)) return true\n return false\n }\n if (typeof value === \"string\") {\n const parsed = parseJsonRecord(value)\n if (parsed?.exit_code === 137) return true\n return isOomText(value)\n }\n return false\n}\n\nfunction isToolBridgeContent(value: unknown): value is ToolBridgeContent {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n typeof (value as { action?: unknown }).action === \"string\"\n )\n}\n\nfunction isCursorInvalidError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n (error as { status?: unknown }).status === 409\n )\n}\n\nfunction queueRequestFailure(error: unknown): QueueOperationResult {\n const failure =\n error instanceof AgentSessionError\n ? { message: error.message, ...(error.code ? { code: error.code } : {}) }\n : { message: error instanceof Error && error.message ? error.message : \"队列操作失败\" }\n return {\n ok: false,\n conflict: false,\n snapshot: null,\n ...failure,\n }\n}\n\nfunction commandDeliveryKey(deliveryId: string): string {\n return `tool-command:${deliveryId}`\n}\n\ninterface PendingCommandDelivery {\n deliveryKey: string\n action: string\n payload: unknown\n toolCallId: string | undefined\n}\n\nexport function sessionStatusFromChatEnd(status: string | undefined): SessionStatus {\n if (status === \"paused\") return \"waiting_for_input\"\n if (status === \"interrupted\") return \"interrupted\"\n if (status === \"failed\") return \"failed\"\n return \"completed\"\n}\n\ninterface ManualCompactionRequest {\n runId: string | null\n finishedBeforeAck: Set<string>\n ack: Promise<Record<string, unknown>>\n}\n\nfunction isCompactionFinished(type: string): boolean {\n return type === \"compaction:end\" || type === \"compaction:error\" || type === \"compaction:abort\"\n}\n\nfunction extractTerminalChatEndStatus(events: RawEvent[]): string | null {\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i]\n if (event?.type !== \"chat:end\") continue\n const status = event.payload?.status\n return typeof status === \"string\" ? status : \"completed\"\n }\n return null\n}\n\n/**\n * 一个会话的实时状态机:封装 Socket.IO 订阅、历史 + 流式合流、断线补数,\n * 对外只有三样东西——状态快照(getState/subscribe)、动作(send/stop/…)、\n * 语义事件(on/onCommand)。\n *\n * 状态完全归属实例:同一页面创建多个 AgentSession 互不干扰。\n */\nexport class AgentSession {\n private readonly logCursor = new LogCursor()\n readonly sessionId: string\n\n private state: SessionState\n private statusRevision = 0\n\n private noteLiveStatus(): void {\n this.statusRevision += 1\n }\n private readonly listeners = new Set<() => void>()\n private readonly emitter = new Emitter<AgentSessionEvents>()\n private readonly commands = new CommandRegistry()\n private readonly runtime: SessionRuntime\n private activeReplayPlaybackId: string | null = null\n private readonly projectionBuilder = new ClientProjectionBuilder()\n\n private readonly pendingTurnPatches = new Map<string, PatchEnvelope>()\n private patchFlushHandle: number | ReturnType<typeof globalThis.setTimeout> | null = null\n private patchFlushCancel: (() => void) | null = null\n\n private joined = false\n private joinPending: Promise<void> | null = null\n private subscriptionQueue: Promise<unknown> = Promise.resolve()\n private replaceQueue: Promise<unknown> = Promise.resolve()\n private timelineEpoch = 0\n private locateToken = 0\n private locateAbort: AbortController | null = null\n private pagingGeneration = 0\n private liveRevision = 0\n private modeRevision = 0\n private readonly liveRevisions = new Map<string, number>()\n private readonly pendingOptimisticTurnIds = new Set<string>()\n private olderPending: Promise<void> | null = null\n private replaceInFlight = 0\n private replayQueue: Promise<unknown> = Promise.resolve()\n private commandRestoreQueue: Promise<unknown> = Promise.resolve()\n private commandRecoveryGeneration = 0\n private commandRestoreRetryAttempt = 0\n private commandRestoreRetryHandle: ReturnType<typeof globalThis.setTimeout> | null = null\n private bufferedCommandDeliveries: PendingCommandDelivery[] | null = null\n private pendingReplayMessage: MessageContent | null = null\n private pendingReplayMode: string | undefined\n private pendingReplayRequestId: string | undefined\n private pendingReplayAttachments: ContextAttachment[] | undefined\n private pendingReplayRefs: import(\"../schemas/plugin-refs\").MessageRef[] | undefined\n private pendingReplayTopicAssetRefs: TopicAssetRef[] | undefined\n private recentChatEndAt = 0\n private lastDeliveredSystemError: { message: string; code?: string; generation: number } | null =\n null\n private systemErrorGeneration = 0\n private subscriptionReplaySource: \"bootstrap_replay\" | \"reconnect_replay\" | null = null\n private disposed = false\n private getAppContext: AttachAppOptions[\"getContext\"] | null = null\n private sendPending = false\n private manualCompactionRequest: ManualCompactionRequest | null = null\n private epochReloadRequested = 0\n private epochReloadDone = 0\n private epochReloadRunning = false\n\n private setManualCompactionRequest(request: ManualCompactionRequest | null): void {\n this.manualCompactionRequest = request\n const pending = request !== null\n if (this.state.compactionPending !== pending) this.update((s) => ({ ...s, compactionPending: pending }))\n }\n\n private handleManualCompactionFinished(event: RawEvent): void {\n const request = this.manualCompactionRequest\n const runId = event.payload.run_id\n if (!request || !isCompactionFinished(event.type) || typeof runId !== \"string\" || !runId) return\n if (request.runId === null) request.finishedBeforeAck.add(runId)\n else if (request.runId === runId) this.setManualCompactionRequest(null)\n }\n private pendingChatRequestId: string | null = null\n private readonly workflowRunToolCalls = new Map<string, string>()\n private desiredStreamTokens: boolean | null = null\n private joinedStreamTokens: boolean | null = null\n\n private readonly deliveredCommandKeys = new Set<string>()\n private readonly deliveredToolPreviews = new Map<string, string>()\n private readonly oomNotifiedKeys = new Set<string>()\n private readonly seenToolCallIds = new Set<string>()\n private readonly finishedToolCallIds = new Set<string>()\n private readonly emittedMessageTurnIds = new Set<string>()\n\n constructor(\n sessionId: string,\n runtime: SessionRuntime,\n connection: ConnectionStatus,\n options: { staticHistory?: boolean; streamTokens?: boolean | null } = {},\n ) {\n this.sessionId = sessionId\n this.runtime = runtime\n this.state = { ...createInitialSessionState(sessionId), connection }\n this.isStatic = options.staticHistory === true\n this.desiredStreamTokens = options.streamTokens ?? null\n }\n\n /**\n * 静态历史(分享页 / `fromTurns`):没有目录接口,也**没有**\"目录还没到位\"这个中间态。\n *\n * 宿主据此决定要不要拿已加载窗口当兜底条目——真实会话在 timeline 被重写后,窗口里还是\n * 旧分支的发言,拿它兜底会把已经失效的 entry id 重新摆到轨道上,点了必然找不到。\n */\n readonly isStatic: boolean\n\n /**\n * 从一份静态 turn 快照构造只展示历史的会话(例如公开分享页)。`overrides` 覆盖展示相关的少数字段\n * (只读身份、开发调试页模拟的流式状态)。\n */\n static fromTurns(\n sessionId: string,\n turns: TurnProjection[],\n overrides: Partial<Pick<SessionState, \"isStreaming\" | \"status\" | \"viewerRole\">> = {},\n ): AgentSession {\n const readonlyError = () => {\n throw new Error(\"静态会话只用于展示历史,不能执行会话操作\")\n }\n const session = new AgentSession(\n sessionId,\n {\n emitEvent: readonlyError,\n emitWithAck: async () => readonlyError(),\n ensureConnected: readonlyError,\n fetchTurnsPage: async () => ({ turns, nextBefore: null, currentMode: \"executing\" }),\n fetchTurnIndex: async () => ({ sessionId, items: [] }),\n fetchCommands: async () => [],\n fetchSessionInfo: async () => ({ replay_state: null }),\n updateReplay: async () => readonlyError(),\n listDir: async () => readonlyError(),\n countFiles: async () => readonlyError(),\n downloadFile: async () => readonlyError(),\n attachAppCli: async () => readonlyError(),\n onDispose: () => true,\n },\n \"connected\",\n { staticHistory: true },\n )\n session.state = {\n ...withTurns(session.state, turns),\n status: \"completed\",\n ...overrides,\n }\n return session\n }\n\n\n /** 返回当前会话快照。引用稳定:状态未变化时返回同一对象。 */\n getState(): SessionState {\n return this.state\n }\n\n get hasOlderHistory(): boolean {\n return this.state.nextBefore !== null\n }\n\n /** Load the page immediately preceding the current display window. */\n loadOlderHistory(options: { beforeCommit?: () => void } = {}): Promise<void> {\n if (this.disposed) return Promise.resolve()\n if (this.olderPending) return this.olderPending\n if (this.replaceInFlight > 0) {\n return this.replaceQueue.then(() => this.loadOlderHistory(options))\n }\n const before = this.state.nextBefore\n if (!before) return Promise.resolve()\n const epoch = this.timelineEpoch\n const generation = this.pagingGeneration\n this.update((state) => ({ ...state, loadingOlder: true }))\n const request = this.runtime\n .fetchTurnsPage(this.sessionId, { before })\n .then((page) => {\n if (\n epoch !== this.timelineEpoch ||\n generation !== this.pagingGeneration ||\n this.state.nextBefore !== before\n ) return\n options.beforeCommit?.()\n this.update((state) => ({\n ...withTurns(state, prependOlder(state.turns, page.turns)),\n nextBefore: page.nextBefore,\n loadingOlder: false,\n }))\n })\n .catch(async (error) => {\n if (\n isCursorInvalidError(error) &&\n epoch === this.timelineEpoch &&\n generation === this.pagingGeneration &&\n this.state.nextBefore === before\n ) {\n this.invalidateTimeline()\n this.update((state) => ({ ...state, timelineRevision: state.timelineRevision + 1 }))\n await this.replaceFromHistory()\n return\n }\n })\n .finally(() => {\n if (this.olderPending !== request) return\n this.olderPending = null\n this.update((state) => ({ ...state, loadingOlder: false }))\n })\n this.olderPending = request\n return request\n }\n\n /**\n * 定位到一条窗口外的历史发言:请服务端返回\"从这条发言到最新\"的窗口并整窗替换。\n *\n * 返回 false 表示这次定位没有落地(请求失败,或期间 timeline 被重写、会话已释放),\n * 当前窗口保持不变,调用方可以原样重试。已加载的发言不要走这里——宿主直接滚动,\n * 一次网络请求都不该发。\n */\n async locateEntry(entryId: string): Promise<boolean> {\n const token = ++this.locateToken\n const controller = new AbortController()\n this.locateAbort?.abort()\n this.locateAbort = controller\n try {\n return await this.replaceFromHistory({\n suppressErrors: false,\n fromEntryId: entryId,\n signal: controller.signal,\n isStale: () => this.locateToken !== token,\n })\n } catch {\n return false\n } finally {\n if (this.locateAbort === controller) this.locateAbort = null\n }\n }\n\n /**\n * 取消在途定位:用户改选了另一条发言(哪怕那条已经加载、不需要请求),\n * 先前那次定位既不该再落地,也不该继续占着替换队列——排队中的下一次定位\n * 不然要等它跑完(用户看到的是\"点了新目标一直转圈\")。\n *\n * **只**中止定位自己的请求:权威刷新(运行结束 / 重连补数)不共用这个 controller,\n * 否则\"运行刚结束时点一下侧栏\"就会把终态对账一起中止,流式与历史对不上。\n */\n cancelPendingLocate(): void {\n this.locateToken += 1\n this.locateAbort?.abort()\n this.locateAbort = null\n }\n\n /**\n * 历史被外部改写后(rewind / checkout 分支等由宿主发起的操作)整窗重新加载最新一页:\n * 作废在途的旧结果,递增 `timelineRevision`;同时向服务端确认一次运行状态(改写期间错过的\n * chat:end 会让界面停在「运行中」)。\n */\n async reloadHistory(): Promise<boolean> {\n const replaced = await this.reloadHistoryWindow()\n await this.refreshRunningState().catch(() => undefined)\n return replaced\n }\n\n private async reloadHistoryWindow(): Promise<boolean> {\n if (this.disposed) return false\n this.invalidateTimeline()\n this.invalidateOlderPaging()\n this.update((state) => ({\n ...state,\n nextBefore: null,\n loadingOlder: false,\n timelineRevision: state.timelineRevision + 1,\n }))\n return this.replaceFromHistory()\n }\n\n /**\n * 向服务端确认会话此刻是否在运行,校准流式状态(残留的「运行中」会被清掉)。只在已加入房间时\n * 生效;不带 resume,服务端不会重发上一轮的终态事件(否则会被当成一次新的结束)。\n */\n async refreshRunningState(): Promise<void> {\n if (this.disposed || !this.joined) return\n const liveRevision = this.liveRevision\n const response = await this.runtime.emitWithAck(\n \"session:subscribe\",\n {\n session_id: this.sessionId,\n event_format: \"raw\",\n ...(this.joinedStreamTokens === null ? {} : { internal_stream_tokens: this.joinedStreamTokens }),\n },\n 5_000,\n )\n if (this.disposed || !response || response.ok === false || typeof response.is_running !== \"boolean\") return\n this._applyRunningState(response.is_running, liveRevision)\n }\n\n private invalidateTimeline(): void {\n this.timelineEpoch += 1\n this.locateAbort?.abort()\n this.locateAbort = null\n }\n\n /**\n * 拉取当前分支的用户发言目录(消息导航侧栏用)。\n *\n * 不在这里缓存:什么时候该刷新只有调用方知道(会话切换、历史被替换、新发言),\n * 缓存只会让旧条目在 rewind 之后继续可点。\n */\n async loadTurnIndex(): Promise<SessionTurnIndexItem[]> {\n const index = await this.runtime.fetchTurnIndex(this.sessionId)\n return index.items\n }\n\n /** 订阅状态变化。返回取消订阅函数。 */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n private setState(next: SessionState): void {\n if (next === this.state) return\n if (next.status !== this.state.status) this.statusRevision += 1\n this.state = next\n for (const listener of [...this.listeners]) {\n try {\n listener()\n } catch (error) {\n console.warn(\"[agent-client] 状态订阅回调抛出异常:\", error)\n }\n }\n }\n\n private update(fn: (state: SessionState) => SessionState): void {\n this.setState(fn(this.state))\n }\n\n\n /** 监听语义事件(底层逃生舱,见 events.ts)。返回取消函数。 */\n on<K extends keyof AgentSessionEvents>(\n name: K,\n handler: (event: AgentSessionEvents[K]) => void,\n ): () => void {\n return this.emitter.on(name, handler)\n }\n\n off<K extends keyof AgentSessionEvents>(\n name: K,\n handler: (event: AgentSessionEvents[K]) => void,\n ): void {\n this.emitter.off(name, handler)\n }\n\n /**\n * 监听智能体下发给宿主页面的指令。\n *\n * action 是技能作者在工具返回值 `_meta.bridge` 里写的契约字符串(如\n * \"map.highlight\"),由你和技能作者约定;注册前到达的指令会被缓冲补投。\n */\n onCommand(action: string, handler: CommandHandler): () => void {\n return this.commands.onCommand(action, handler)\n }\n\n\n /**\n * 声明当前应用提供的页面上下文和业务 CLI。\n *\n * CLI 安装成功后才保存 getContext;之后每次 send 前恰好读取一次。\n */\n async attachApp(options: AttachAppOptions): Promise<AppCliAttachment | null> {\n const attachment = options.cli\n ? await this.runtime.attachAppCli(this.sessionId, options.cli)\n : null\n this.getAppContext = options.getContext\n return attachment\n }\n\n /** 立即为整个会话切换模型,并接续因模型故障停下的任务。 */\n async selectModel(model: string): Promise<boolean> {\n try {\n await this.ensureJoined()\n const response = await this.runtime.emitWithAck(\"chat:model\", { session_id: this.sessionId, model }, 30_000)\n if (response?.status !== \"ok\") throw new Error(typeof response?.message === \"string\" ? response.message : \"模型切换失败\")\n return true\n } catch (error) {\n const failure = describeSessionError(error, \"模型切换失败,请重试\")\n this.update((state) => addErrorMessage(state, failure.message))\n this.emitter.emit(\"error\", { message: failure.message })\n return false\n }\n }\n\n /** Prepare a durable text input without sending any network request. */\n prepareSend(content: string, options: PreparedSendOptions = {}): PreparedSend {\n if (!content.trim()) throw new Error(\"消息不能为空\")\n if (Object.keys(options).some(key => ![\"mode\", \"model\", \"thinkingOverride\", \"reasoningLevel\", \"contextAttachments\", \"queueWhenRunning\", \"headless\"].includes(key))) {\n throw new Error(\"可靠文本发送不支持这些参数,请使用 send()\")\n }\n const snapshot = JSON.parse(JSON.stringify(options)) as PreparedSendOptions\n if (snapshot.contextAttachments) snapshot.contextAttachments = snapshotContextAttachments(snapshot.contextAttachments)\n return { sessionId: this.sessionId, requestId: createClientRequestId(), content, options: snapshot }\n }\n\n /** Durably send a text input with its saved delivery intent. Retries must reuse the saved request. */\n async sendPrepared(request: PreparedSend): Promise<DeliveryReceipt> {\n if (request.sessionId !== this.sessionId) throw new Error(\"发送请求不属于当前会话\")\n try {\n this.runtime.ensureConnected()\n const response = await this.runtime.emitWithAck(\"chat:append\", {\n session_id: this.sessionId, client_request_id: request.requestId, message: request.content,\n prepared_options: {\n mode: request.options.mode, model: request.options.model,\n ...(request.options.headless !== undefined ? { headless: request.options.headless } : {}),\n ...(request.options.queueWhenRunning !== undefined ? { queue_when_running: request.options.queueWhenRunning } : {}),\n thinking_override: request.options.thinkingOverride, reasoning_level: request.options.reasoningLevel,\n ...(request.options.contextAttachments ? { context_attachments: request.options.contextAttachments } : {}),\n },\n }, QUEUE_ACK_TIMEOUT_MS)\n const result = parseQueueAck(response, this.sessionId)\n if (result.snapshot) this.update((state) => withQueue(state, result.snapshot!))\n if (!result.ok) return {\n requestId: request.requestId,\n status: response?.status === \"conflict\" ? \"rejected\" : \"unknown\",\n message: result.message ?? undefined,\n }\n const delivery = response?.delivery\n if (!isRecord(delivery) || delivery.status !== \"accepted\") return { requestId: request.requestId, status: \"unknown\" }\n return {\n requestId: request.requestId, status: \"accepted\",\n itemId: typeof delivery.item_id === \"string\" ? delivery.item_id : undefined,\n queueStatus: typeof delivery.queue_status === \"string\" ? delivery.queue_status : undefined,\n executionId: typeof delivery.execution_id === \"string\" ? delivery.execution_id : null,\n }\n } catch {\n return { requestId: request.requestId, status: \"unknown\" }\n }\n }\n\n /** Owner-authorized lookup; receipts remain until the session is deleted. */\n async getDelivery(requestId: string): Promise<DeliveryReceipt> {\n try {\n this.runtime.ensureConnected()\n const response = await this.runtime.emitWithAck(\"chat:queue:request\", {\n session_id: this.sessionId, client_request_id: requestId,\n }, QUEUE_ACK_TIMEOUT_MS)\n if (response?.status === \"accepted\") return {\n requestId, status: \"accepted\",\n itemId: typeof response.item_id === \"string\" ? response.item_id : undefined,\n queueStatus: typeof response.queue_status === \"string\" ? response.queue_status : undefined,\n executionId: typeof response.execution_id === \"string\" ? response.execution_id : null,\n }\n if (response?.status === \"not_found\") return { requestId, status: \"not_found\" }\n return { requestId, status: \"unknown\", message: typeof response?.message === \"string\" ? response.message : undefined }\n } catch {\n return { requestId, status: \"unknown\" }\n }\n }\n\n /** 发送一条消息。字符串或多模态内容均可。 */\n async send(content: MessageContent, options: SendOptions = {}): Promise<boolean> {\n this.runtime.ensureConnected()\n if (\n this.state.activeCompaction ||\n this.sendPending ||\n this.manualCompactionRequest\n ) {\n this.update((s) =>\n addErrorMessage(s, \"当前回复尚未结束或对话正在整理,请稍后再发送。\"),\n )\n return false\n }\n this.sendPending = true\n try {\n return await this.sendUnlocked(content, options)\n } finally {\n this.sendPending = false\n }\n }\n\n /**\n * 入队一条等待消息(运行中排队 / 暂停期间照常入队)。\n *\n * ack 超时或传输失败时结果未知:用**同一个** `client_request_id` 重试一次,\n * 服务端按 `(session_id, client_request_id)` 幂等,不会制造第二条。\n */\n async queueMessage(content: string): Promise<QueueOperationResult> {\n const text = content.trim()\n if (!text) {\n return { ok: false, conflict: false, snapshot: null, message: \"消息不能为空\" }\n }\n const payload = {\n session_id: this.sessionId,\n message: text,\n client_request_id: createClientRequestId(),\n }\n try {\n return await this.requestQueueAck(\"chat:append\", payload)\n } catch {\n try {\n return await this.requestQueueAck(\"chat:append\", payload)\n } catch (error) {\n return queueRequestFailure(error)\n }\n }\n }\n\n /** 修改一条等待消息的正文;`expectedVersion` 是客户端看到的条目版本。 */\n async updateQueuedMessage(\n itemId: string,\n expectedVersion: number,\n content: string,\n ): Promise<QueueOperationResult> {\n return this.runQueueCommand(\"chat:queue:update\", {\n session_id: this.sessionId,\n item_id: itemId,\n expected_version: expectedVersion,\n message: content,\n })\n }\n\n /**\n * 重排等待消息。`orderedIds` 必须是当前 pending 条目 id 的**完整集合**(顺序任意),\n * 服务端按 `expectedRevision` 校验后整体替换顺序。\n *\n * 拖动排序就该像本地操作一样落地:版本冲突(运行中的任务刚领走一条 / 另一个端也在\n * 动队列)不甩给用户「刷新后重试」,而是拿冲突响应里那份**最新快照**重算一次再提交\n * ——掉队的条目(已经被领取执行的)从顺序里剔除,剩下的保持用户拖出来的相对次序。\n * 最多补两次;仍旧冲突才把结果交回调用方。\n */\n async reorderQueuedMessages(\n expectedRevision: number,\n orderedIds: string[],\n ): Promise<QueueOperationResult> {\n let revision = expectedRevision\n let ids = orderedIds\n let result = await this.runQueueCommand(\"chat:queue:reorder\", {\n session_id: this.sessionId,\n expected_revision: revision,\n ordered_ids: ids,\n })\n for (let attempt = 0; attempt < 2 && !result.ok && result.conflict; attempt++) {\n const snapshot = result.snapshot\n if (!snapshot) break\n const pending = snapshot.items.filter(canEditQueuedMessage)\n const live = new Set(pending.map((item) => item.id))\n const next = ids.filter((id) => live.has(id))\n for (const item of pending) if (!next.includes(item.id)) next.push(item.id)\n if (next.length === 0) {\n return { ok: true, conflict: false, snapshot, message: null }\n }\n revision = snapshot.revision\n ids = next\n result = await this.runQueueCommand(\"chat:queue:reorder\", {\n session_id: this.sessionId,\n expected_revision: revision,\n ordered_ids: ids,\n })\n }\n return result\n }\n\n /** 删除一条等待消息;不传版本时由服务端自行判定。 */\n async cancelQueuedMessage(\n itemId: string,\n expectedVersion?: number,\n ): Promise<QueueOperationResult> {\n return this.runQueueCommand(\"chat:queue:cancel\", {\n session_id: this.sessionId,\n item_id: itemId,\n expected_version: expectedVersion,\n })\n }\n\n /** 立即补充:把等待消息交给当前运行,在下一个接收点消费,不停止也不另起一轮。 */\n async deliverQueuedMessage(\n itemId: string,\n expectedVersion: number,\n ): Promise<QueueOperationResult> {\n return this.runQueueCommand(\"chat:queue:deliver\", {\n session_id: this.sessionId,\n item_id: itemId,\n expected_version: expectedVersion,\n })\n }\n\n /** 继续执行:清除暂停,并按当前顺序恢复逐条接续。 */\n async resumeQueue(): Promise<QueueOperationResult> {\n return this.runQueueCommand(\"chat:queue:resume\", { session_id: this.sessionId })\n }\n\n /** 拉取一份权威队列快照。首次连接与每次重连后由实例自动调用,也可以手动刷新。 */\n async refreshQueue(): Promise<QueueOperationResult> {\n return this.runQueueCommand(\"chat:queue:list\", { session_id: this.sessionId })\n }\n\n private async requestQueueAck(\n event: string,\n payload: Record<string, unknown>,\n ): Promise<QueueOperationResult> {\n this.runtime.ensureConnected()\n const response = await this.runtime.emitWithAck(event, payload, QUEUE_ACK_TIMEOUT_MS)\n const result = parseQueueAck(response, this.sessionId)\n const snapshot = result.snapshot\n if (snapshot) this.update((state) => withQueue(state, snapshot))\n return result\n }\n\n private async runQueueCommand(\n event: string,\n payload: Record<string, unknown>,\n ): Promise<QueueOperationResult> {\n try {\n return await this.requestQueueAck(event, payload)\n } catch (error) {\n return queueRequestFailure(error)\n }\n }\n\n private async sendUnlocked(content: MessageContent, options: SendOptions): Promise<boolean> {\n const contextAttachments = options.contextAttachments ? snapshotContextAttachments(options.contextAttachments) : undefined\n await this.ensureIdleBeforeSend()\n if (\n this.state.activeCompaction ||\n this.manualCompactionRequest\n ) {\n this.update((s) =>\n addErrorMessage(s, \"当前回复尚未结束或对话正在整理,请稍后再发送。\"),\n )\n return false\n }\n let appContext: Record<string, unknown> | undefined\n // Active-run input inherits the admitted application snapshot.\n if (this.getAppContext && !this.state.isStreaming) {\n try {\n const rawContext = await this.getAppContext()\n if (!isRecord(rawContext)) {\n throw new Error(\"getContext 必须返回 JSON 对象\")\n }\n const serialized = JSON.stringify(rawContext)\n if (serialized === undefined) {\n throw new Error(\"getContext 必须返回可序列化的 JSON 对象\")\n }\n const normalized = JSON.parse(serialized)\n if (!isRecord(normalized)) {\n throw new Error(\"getContext 必须返回 JSON 对象\")\n }\n appContext = normalized\n } catch (error) {\n const message =\n error instanceof Error && error.message\n ? `读取应用上下文失败:${error.message}`\n : \"读取应用上下文失败,消息未发送\"\n this.update((s) => addErrorMessage(s, message))\n return false\n }\n }\n const wasStreaming = this.state.isStreaming\n const askUserAnswer = options.askUserAnswer\n let optimisticTurnId: string | null = null\n const clientRequestId = createClientRequestId()\n let optimisticAskAnswer: AskUserAnswerData | undefined\n let previousAskAnswer: AskUserAnswerData | undefined\n this.update((state) => {\n const next = addUserMessage(state, content, clientRequestId, options.topicAssetRefs, options.refs, contextAttachments)\n optimisticTurnId = next.turns.at(-1)?.turn_id ?? null\n return next\n })\n if (optimisticTurnId) this.markOptimisticTurnPending(optimisticTurnId)\n this.update((s) => ({ ...s, isStreaming: true }))\n if (askUserAnswer && typeof askUserAnswer.tool_call_id === \"string\") {\n const { tool_call_id, ...rest } = askUserAnswer\n previousAskAnswer = this.state.askAnswers[tool_call_id]\n optimisticAskAnswer = rest as unknown as AskUserAnswerData\n this.update((s) => ({\n ...s,\n askAnswers: { ...s.askAnswers, [tool_call_id as string]: optimisticAskAnswer! },\n }))\n }\n if (!options.replayDecision) {\n this.pendingReplayMessage = content\n this.pendingReplayMode = options.mode\n this.pendingReplayRequestId = clientRequestId\n this.pendingReplayAttachments = contextAttachments\n this.pendingReplayRefs = options.refs\n this.pendingReplayTopicAssetRefs = options.topicAssetRefs\n }\n this.pendingChatRequestId = clientRequestId\n const payload = {\n session_id: this.sessionId,\n message: content,\n client_request_id: clientRequestId,\n mode: options.mode,\n askuser_answer: askUserAnswer,\n model: options.model,\n thinking_override: options.thinkingOverride,\n reasoning_level: options.reasoningLevel,\n whatif: options.whatif,\n replay_decision: options.replayDecision,\n app_context: appContext,\n context_attachments: contextAttachments,\n refs: options.refs,\n topic_asset_refs: options.topicAssetRefs,\n queue_when_running: options.queueWhenRunning === true,\n }\n try {\n await this.ensureJoined()\n } catch (error) {\n const failure = describeSessionError(error, \"会话订阅失败,消息未发送\")\n this.rollbackOptimisticSend(\n optimisticTurnId,\n askUserAnswer,\n optimisticAskAnswer,\n previousAskAnswer,\n wasStreaming,\n failure.message,\n failure.code,\n )\n return false\n }\n const waitStartedAt = this.systemErrorGeneration\n try {\n const response = await this.runtime.emitWithAck(\"chat:send\", payload, 30_000)\n if (response?.status === \"queued\") {\n this.discardOptimisticSend(\n optimisticTurnId,\n askUserAnswer,\n optimisticAskAnswer,\n previousAskAnswer,\n )\n const snapshot = parseQueueAck(response, this.sessionId).snapshot\n const running = response.running === true\n this.update((current) => {\n const next = running ? current : { ...current, isStreaming: false }\n return snapshot ? withQueue(next, snapshot) : next\n })\n return true\n }\n if (response?.status !== \"accepted\") {\n throw new AgentSessionError(\n typeof response?.message === \"string\"\n ? response.message\n : \"消息未被服务端接受\",\n typeof response?.code === \"string\" ? response.code : undefined,\n )\n }\n if (optimisticTurnId) {\n this.update((state) => {\n const next = withTurns(state, state.turns.map((turn) =>\n turn.turn_id === optimisticTurnId ? { ...turn, status: \"completed\" } : turn,\n ))\n return { ...next, askAnswers: state.askAnswers }\n })\n }\n return true\n } catch (error) {\n const failure = describeSessionError(error, \"消息发送失败,请重试\")\n this.rollbackOptimisticSend(\n optimisticTurnId,\n askUserAnswer,\n optimisticAskAnswer,\n previousAskAnswer,\n wasStreaming,\n failure.message,\n failure.code,\n waitStartedAt,\n )\n return false\n }\n }\n\n private rollbackOptimisticSend(\n optimisticTurnId: string | null,\n askUserAnswer: Record<string, unknown> | undefined,\n optimisticAskAnswer: AskUserAnswerData | undefined,\n previousAskAnswer: AskUserAnswerData | undefined,\n wasStreaming: boolean,\n message: string,\n code?: string,\n waitStartedAt?: number,\n ): void {\n this.discardOptimisticSend(\n optimisticTurnId,\n askUserAnswer,\n optimisticAskAnswer,\n previousAskAnswer,\n )\n this.update((current) =>\n addErrorMessage(wasStreaming ? current : { ...current, isStreaming: false }, message),\n )\n if (!wasStreaming) this.applyDesiredStreamTokens()\n const delivered = this.lastDeliveredSystemError\n if (\n waitStartedAt !== undefined &&\n delivered &&\n delivered.generation > waitStartedAt &&\n delivered.message === message &&\n delivered.code === code\n ) {\n this.lastDeliveredSystemError = null\n return\n }\n this.emitter.emit(\"error\", { message, ...(code ? { code } : {}) })\n }\n\n private discardOptimisticSend(\n optimisticTurnId: string | null,\n askUserAnswer: Record<string, unknown> | undefined,\n optimisticAskAnswer: AskUserAnswerData | undefined,\n previousAskAnswer: AskUserAnswerData | undefined,\n ): void {\n if (optimisticTurnId && this.pendingChatRequestId && optimisticTurnId === `local-user-${this.pendingChatRequestId}`) {\n this.pendingChatRequestId = null\n }\n this.pendingReplayMessage = null\n this.pendingReplayMode = undefined\n this.pendingReplayRequestId = undefined\n this.pendingReplayAttachments = undefined\n this.pendingReplayRefs = undefined\n this.pendingReplayTopicAssetRefs = undefined\n this.update((current) => {\n const filtered = optimisticTurnId\n ? current.turns.filter((turn) => turn.turn_id !== optimisticTurnId)\n : current.turns\n let next = optimisticTurnId\n ? withTurns({ ...current, turns: filtered }, filtered)\n : current\n const toolCallId =\n askUserAnswer && typeof askUserAnswer.tool_call_id === \"string\"\n ? askUserAnswer.tool_call_id\n : null\n if (toolCallId && next.askAnswers[toolCallId] === optimisticAskAnswer) {\n const askAnswers = { ...next.askAnswers }\n if (previousAskAnswer === undefined) {\n delete askAnswers[toolCallId]\n } else {\n askAnswers[toolCallId] = previousAskAnswer\n }\n next = { ...next, askAnswers }\n }\n return next\n })\n if (optimisticTurnId) {\n this.pendingOptimisticTurnIds.delete(optimisticTurnId)\n this.liveRevisions.delete(optimisticTurnId)\n }\n }\n\n /** 停止当前回复。 */\n async stop(executionId?: string): Promise<Record<string, unknown>> {\n const request = this.manualCompactionRequest\n if (request && !executionId) {\n const ack = await request.ack\n if (ack.status !== \"accepted\") return ack\n if (this.manualCompactionRequest !== request) return { status: \"idle\" }\n return await this.runtime.emitWithAck(\"chat:stop\", {\n session_id: this.sessionId,\n chat_run_id: request.runId,\n }, 35_000) ?? {}\n }\n const response = await this.runtime.emitWithAck(\"chat:stop\", { session_id: this.sessionId, ...(executionId ? { chat_run_id: executionId } : {}) }, 35_000) ?? {}\n const cancelled = response.cancelled_client_request_ids\n if (response.status === \"stopped\" && Array.isArray(cancelled) &&\n this.pendingChatRequestId !== null && cancelled.includes(this.pendingChatRequestId)) {\n this.pendingChatRequestId = null\n this.update((state) => ({ ...withoutOptimisticUserTurns(state, cancelled), isStreaming: false }))\n this.applyDesiredStreamTokens()\n }\n return response\n }\n\n /** 手动触发上下文压缩。 */\n compact(): Promise<Record<string, unknown>> {\n if (this.state.isStreaming || this.state.activeCompaction || this.manualCompactionRequest) {\n return Promise.resolve({\n status: \"error\",\n message: \"当前回复尚未结束或对话正在整理,请稍后再试。\",\n })\n }\n const request: ManualCompactionRequest = {\n runId: null,\n finishedBeforeAck: new Set(),\n ack: Promise.resolve()\n .then(() => this.runtime.emitWithAck(\"chat:compact\", { session_id: this.sessionId }, 30_000))\n .then((response) => {\n const result = response ?? {}\n if (result.status !== \"accepted\") {\n if (this.manualCompactionRequest === request) this.setManualCompactionRequest(null)\n return result\n }\n if (typeof result.run_id !== \"string\" || !result.run_id) {\n throw new AgentSessionError(\"整理请求确认缺少 run_id,无法确认运行状态\")\n }\n request.runId = result.run_id\n if (request.finishedBeforeAck.has(request.runId) && this.manualCompactionRequest === request) {\n this.setManualCompactionRequest(null)\n }\n request.finishedBeforeAck.clear()\n return result\n })\n .catch((error) => {\n if (this.manualCompactionRequest === request) this.setManualCompactionRequest(null)\n throw error\n })\n .finally(() => {\n if ((!this.manualCompactionRequest || this.manualCompactionRequest === request) &&\n this.state.activeCompaction?.compaction_id === \"pending-manual-compaction\") {\n this.update((state) => ({ ...state, activeCompaction: null }))\n }\n }),\n }\n this.setManualCompactionRequest(request)\n this.update((state) => ({\n ...state,\n activeCompaction: {\n turn_id: \"pending-manual-compaction\",\n compaction_id: \"pending-manual-compaction\",\n status: \"streaming\",\n trigger: \"manual\",\n },\n }))\n return request.ack\n }\n\n /**\n * 把一段业务数据作为附件放进聊天输入框(比如地图上选中的点位)。\n * 附件随下一条消息一起发给智能体。需要 ChatView / useChat 渲染层配合展示;\n * 无 UI 场景可直接用 send()。\n */\n attach(label: string, data: unknown): void {\n const content = typeof data === \"string\" ? data : JSON.stringify(data, null, 2)\n this.emitter.emit(\"attachRequested\", { label, content })\n }\n\n /** 往聊天输入框追加一段文字(不发送)。 */\n insertText(text: string): void {\n this.emitter.emit(\"insertTextRequested\", { text })\n }\n\n /** 列出工作区的一层目录。 */\n listDir(dirPath = \"\"): Promise<FileEntry[]> {\n return this.runtime.listDir(this.sessionId, dirPath)\n }\n\n /** 递归统计工作区文件数(不含目录)。 */\n countFiles(dirPath = \"\"): Promise<number> {\n return this.runtime.countFiles(this.sessionId, dirPath)\n }\n\n /** 在浏览器中下载一个工作区文件。 */\n downloadFile(filePath: string, downloadName?: string): Promise<void> {\n return this.runtime.downloadFile(this.sessionId, filePath, downloadName)\n }\n\n /**\n * 归还一份持有。同一个会话被多处 connect 时按引用计数释放:只有最后\n * 一份归还才真正断开订阅与监听器,之前的归还不影响仍在使用的一方。\n */\n dispose(): void {\n if (this.disposed) return\n if (!this.runtime.onDispose(this)) return\n this.disposed = true\n this.invalidateTimeline()\n this.invalidateOlderPaging()\n this.state = { ...this.state, nextBefore: null, loadingOlder: false }\n this.cancelPatchFlush()\n this.listeners.clear()\n this.emitter.clear()\n this.commands.clear()\n this.commandRecoveryGeneration += 1\n this.commandRestoreRetryAttempt = 0\n this.bufferedCommandDeliveries = null\n if (this.commandRestoreRetryHandle !== null) {\n globalThis.clearTimeout(this.commandRestoreRetryHandle)\n this.commandRestoreRetryHandle = null\n }\n }\n\n get isDisposed(): boolean {\n return this.disposed\n }\n\n\n _setConnection(connection: ConnectionStatus): void {\n if (this.state.connection === connection) return\n this.update((s) => ({ ...s, connection }))\n }\n\n _handleQueueUpdated(payload: unknown): void {\n if (!isSessionQueueSnapshot(payload)) return\n const snapshot = payload\n this.update((state) => withQueue(state, snapshot))\n }\n\n _rejoinAfterReconnect(): Promise<void> {\n // 边界快照必须在收到 connect 时同步取得。队列实际开始前到达的 live turn\n // 也属于本次重连后的新变化,历史补数不能把它清掉。\n //\n // **不推进 timeline 纪元**:重连不是 timeline 被改写(分支没变,只是补一次数),推进了\n // 在途定位的结果就会被丢掉——用户点了没反应。补数本来就按它落地后的窗口取窗口。\n this.invalidateOlderPaging()\n this.update((state) => ({ ...state, nextBefore: null, loadingOlder: false }))\n const reconnectLiveRevision = this.liveRevision\n const reconnectModeRevision = this.modeRevision\n const commandRecoveryGeneration = this.beginCommandRecovery()\n return this.enqueueSubscription(async () => {\n this.joined = false\n this.joinPending = null\n try {\n this.subscriptionReplaySource = \"reconnect_replay\"\n try {\n await this.ensureJoined(reconnectLiveRevision)\n } finally {\n this.subscriptionReplaySource = null\n this.scheduleHistoricalCommandRestore(commandRecoveryGeneration)\n }\n await Promise.all([\n this.refreshAuthoritativeHistory({\n liveRevisionAtStart: reconnectLiveRevision,\n modeRevisionAtStart: reconnectModeRevision,\n }),\n this.syncSessionFromDetail({ fresh: true }),\n ])\n } catch {\n }\n })\n }\n\n _bootstrap(): Promise<void> {\n const commandRecoveryGeneration = this.beginCommandRecovery()\n return this.enqueueSubscription(async () => {\n const statusRevisionAtDetail = this.statusRevision\n const fetchDetail = () => this.runtime.fetchSessionInfo(this.sessionId, { fresh: false })\n const [, detail] = await Promise.all([\n this.replaceFromHistory({ suppressErrors: false }),\n Promise.resolve()\n .then(fetchDetail)\n .catch(() => fetchDetail())\n .catch(() => null),\n ])\n if (this.disposed) return\n this.subscriptionReplaySource = \"bootstrap_replay\"\n try {\n await this.ensureJoined()\n } finally {\n this.subscriptionReplaySource = null\n }\n this.scheduleHistoricalCommandRestore(commandRecoveryGeneration)\n await Promise.all([\n detail && !detail.replay_state\n ? Promise.resolve(this.applySessionDetail(detail, statusRevisionAtDetail))\n : this.syncSessionFromDetail({ fresh: true }),\n this.refreshQueue(),\n ])\n })\n }\n\n private enqueueSubscription(operation: () => Promise<void>): Promise<void> {\n const run = this.subscriptionQueue.then(operation)\n this.subscriptionQueue = run.catch(() => undefined)\n return run\n }\n\n private get canControlReplay(): boolean {\n return this.state.viewerRole !== \"viewer\"\n }\n\n private async syncSessionFromDetail(options: { fresh: boolean }): Promise<void> {\n const statusRevisionAtRequest = this.statusRevision\n try {\n const info = await this.runtime.fetchSessionInfo(this.sessionId, options)\n this.applySessionDetail(info, statusRevisionAtRequest)\n } catch {\n }\n }\n\n private applySessionDetail(info: SessionDetailSnapshot, statusRevisionAtRequest: number): void {\n if (this.disposed) return\n const replay = toReplaySnapshot(info.replay_state)\n const viewerRole = info.viewer_role ?? null\n this.update((s) => ({\n ...s,\n replay,\n viewerRole,\n status: this.statusRevision === statusRevisionAtRequest &&\n !(s.status === \"waiting_for_input\" && info.status === \"running\" &&\n s.turns.some((turn) => turn.tool_calls.some((call) => call.status === \"awaiting_answer\")))\n ? (info.status ?? s.status)\n : s.status,\n }))\n }\n\n /** 调整回放倍速;不是回放会话、或只读身份时什么都不做。 */\n async setReplaySpeed(speed: ReplaySpeed): Promise<void> {\n if (!this.state.replay?.isReplay || !this.canControlReplay) return\n await this.applyReplayControl({ speed })\n }\n\n /** 退出回放,之后的对话交给真实模型运行;不是回放会话、或只读身份时什么都不做。 */\n async exitReplay(): Promise<void> {\n if (!this.state.replay?.isReplay || !this.canControlReplay) return\n await this.applyReplayControl({ status: \"autonomous\" })\n }\n\n private applyReplayControl(\n payload: { speed?: ReplaySpeed; status?: \"autonomous\" },\n ): Promise<void> {\n const run = this.replayQueue.then(async () => {\n const result = await this.runtime.updateReplay(this.sessionId, payload)\n this.update((s) => ({ ...s, replay: toReplaySnapshot(result) }))\n })\n this.replayQueue = run.catch(() => undefined)\n return run\n }\n\n _handleTurnStart(turn: TurnProjection): void {\n this.markRunningIfIdle()\n this.applyTurn(turn)\n }\n\n _handleTurnPatch(patch: PatchEnvelope): void {\n this.markRunningIfIdle()\n if (patch.data.workspace_changed) {\n const { paths, workspace_path: workspacePath } = patch.data.workspace_changed\n this.emitter.emit(\"workspaceChanged\", {\n ...(paths?.length ? { paths } : {}),\n ...(workspacePath ? { workspacePath } : {}),\n })\n }\n const current = this.pendingTurnPatches.get(patch.turn_id)\n if (!current || patch.sequence >= current.sequence) {\n this.pendingTurnPatches.set(patch.turn_id, patch)\n }\n this.schedulePatchFlush()\n }\n\n _handleTurnEnd(turn: TurnProjection): void {\n this.applyTurn(turn)\n }\n\n private runEpochReload(): void {\n if (this.disposed || this.epochReloadRunning || this.epochReloadDone >= this.epochReloadRequested) return\n const target = this.epochReloadRequested\n this.epochReloadRunning = true\n void this.reloadHistoryWindow()\n .then((replaced) => { if (replaced) this.epochReloadDone = Math.max(this.epochReloadDone, target) })\n .catch(() => undefined)\n .finally(() => {\n this.epochReloadRunning = false\n if (this.epochReloadRequested > target) this.runEpochReload()\n })\n }\n\n _handleTurnEvents(incoming: RawEvent[], replayed = false): void {\n const delivery = this.logCursor.consume(incoming)\n let events = delivery.events\n if (delivery.reload) {\n this.activeReplayPlaybackId = null\n this.projectionBuilder.reset()\n this.update((state) => ({ ...state, lastRun: null }))\n this.pendingTurnPatches.clear()\n this.epochReloadRequested += 1\n }\n this.runEpochReload()\n for (const event of events) {\n if (event.type === \"chat:end\") this.recordRunResult(event.payload)\n const playbackId = typeof event.payload.playback_id === \"string\" ? event.payload.playback_id : null\n if (event.type === \"chat:start\") this.activeReplayPlaybackId = null\n if (event.type === \"replay:start\" && playbackId) {\n this.activeReplayPlaybackId = playbackId\n this._handleChatStart()\n } else if (event.type === \"replay:state\") {\n const status = event.payload.status\n if (event.payload.reconciled === true && typeof status === \"string\") {\n if (status === \"running\") this._handleChatStart()\n else { this.activeReplayPlaybackId = null; this.finishStreaming(status) }\n }\n this._handleSessionUpdated(event.payload)\n } else if (event.type === \"replay:end\" && playbackId &&\n (!this.activeReplayPlaybackId || this.activeReplayPlaybackId === playbackId)) {\n this.activeReplayPlaybackId = null\n const status = event.payload.status === \"interrupted\" ? \"interrupted\" :\n event.payload.status === \"failed\" ? \"failed\" : \"completed\"\n this._handleChatEnd({ status })\n }\n if (event.type === \"log:notification\") {\n const notification = event.payload.event as RawEvent\n if (isCompactionFinished(notification.type)) {\n this.handleManualCompactionFinished(notification)\n } else if (notification.type === \"artifact:created\" || notification.type === \"artifact:updated\") {\n this._handleArtifact(notification.payload, notification.type === \"artifact:created\" ? \"created\" : \"updated\", replayed)\n } else if (notification.type === \"workspace:changed\") {\n const change = notification.payload.workspace_change as { to?: unknown } | undefined\n const paths = Array.isArray(notification.payload.paths)\n ? notification.payload.paths.filter((path): path is string => typeof path === \"string\")\n : []\n this.emitter.emit(\"workspaceChanged\", {\n ...(paths.length ? { paths } : {}),\n ...(typeof change?.to === \"string\" && change.to ? { workspacePath: change.to } : {}),\n })\n } else if (notification.type === \"task:updated\" && Array.isArray(notification.payload.tasks)) {\n this._handleTaskUpdated(notification.payload.tasks)\n } else if (notification.type === \"bg:tasks_completed\" && Array.isArray(notification.payload.tasks)) {\n for (const task of notification.payload.tasks as BackgroundTaskEvent[]) {\n const completed = completedBackgroundTask(task)\n if (completed) this._handleBackgroundTask(completed)\n }\n } else {\n this.applyWorkflowEvents([notification])\n }\n }\n if (event.type === \"turn:snapshot\") {\n const turn = event.payload.turn as unknown as TurnProjection\n this.projectionBuilder.acceptDurableTurn(turn)\n this.pendingTurnPatches.delete(turn.turn_id)\n this.applyTurn(turn,\n replayed ? (this.subscriptionReplaySource ?? \"bootstrap_replay\") : \"live\")\n }\n }\n events = events.filter((event) => event.type !== \"turn:snapshot\" && event.type !== \"log:notification\" && !event.type.startsWith(\"replay:\"))\n if (!events.length) return\n for (const event of events) this.handleManualCompactionFinished(event)\n this.dispatchRawCommands(events)\n const terminalChatEndStatus = extractTerminalChatEndStatus(events)\n if (\n !terminalChatEndStatus &&\n hasChatRunEvent(events) &&\n this.state.status !== \"waiting_for_input\"\n ) {\n this.markRunningIfIdle()\n }\n if (this.state.turns.length) {\n this.projectionBuilder._seedTurns(this.state.turns)\n }\n const updates = this.projectionBuilder.processBatch(events)\n for (const update of updates) {\n if (update.kind === \"upsert\") {\n this.applyTurn(\n update.turn,\n replayed ? (this.subscriptionReplaySource ?? \"bootstrap_replay\") : \"live\",\n )\n } else if (update.kind === \"workspace_changed\") {\n this.emitter.emit(\"workspaceChanged\", {\n ...(update.paths ? { paths: update.paths } : {}),\n ...(update.workspacePath ? { workspacePath: update.workspacePath } : {}),\n })\n }\n }\n this.applyWorkflowEvents(events)\n if (events.some((event) => event.type === \"loop:child_pause\")) {\n this.noteLiveStatus()\n this.finishStreaming(\"paused\")\n } else if (events.some((event) => event.type === \"loop:ask_user_answer\")) {\n this.markRunningIfIdle()\n }\n if (\n terminalChatEndStatus ||\n acceptedPostChatFollowupCompletesLatestRun(events, updates)\n ) {\n this.completeChat(terminalChatEndStatus ?? \"completed\")\n }\n }\n\n _handleChatStart(): void {\n this.noteLiveStatus()\n this.update((s) => ({\n ...s,\n status: \"running\",\n errorMessage: null,\n isStreaming: true,\n }))\n }\n\n private recordRunResult(payload: ChatEndPayload): void {\n const runId = payload.chat_run_id\n if (payload.queued || typeof runId !== \"string\" || !runId) return\n this.update((state) => ({\n ...state,\n lastRun: { runId, status: payload.status ?? \"completed\", result: payload.result },\n }))\n }\n\n _handleChatEnd(payload: ChatEndPayload = {}): boolean {\n const status = payload.status ?? \"completed\"\n if (payload.queued === true) {\n const cancelled = Array.isArray(payload.cancelled_client_request_ids)\n ? payload.cancelled_client_request_ids.filter((id): id is string => typeof id === \"string\")\n : []\n this.update((state) => withoutOptimisticUserTurns(state, cancelled.length > 0 ? cancelled : undefined))\n if (\n cancelled.length > 0 &&\n this.pendingChatRequestId !== null &&\n !cancelled.includes(this.pendingChatRequestId)\n ) {\n return false\n }\n }\n this.recordRunResult(payload)\n this.pendingChatRequestId = null\n this.noteLiveStatus()\n this.flushPatches()\n if (payload.queued === true) {\n this.finishStreaming(status)\n this.recentChatEndAt = Date.now()\n this.emitter.emit(\"chatEnd\", { status })\n return true\n }\n this.completeChat(status)\n return true\n }\n\n _handleSystemError(message: string, code?: string): void {\n this.pendingChatRequestId = null\n this.noteLiveStatus()\n this.flushPatches()\n const finalMessage = userFacingErrorText(message)\n this.update((s) =>\n addErrorMessage(\n markFailed({\n ...s,\n status: \"failed\",\n errorMessage: finalMessage,\n isStreaming: false,\n }),\n finalMessage,\n ),\n )\n this.recentChatEndAt = Date.now()\n this.applyDesiredStreamTokens()\n this.systemErrorGeneration += 1\n this.lastDeliveredSystemError = {\n message: finalMessage,\n ...(code ? { code } : {}),\n generation: this.systemErrorGeneration,\n }\n this.emitter.emit(\"error\", {\n message: finalMessage,\n ...(code ? { code } : {}),\n })\n }\n\n _handleTaskUpdated(tasks: unknown[]): void {\n this.emitter.emit(\"taskListUpdated\", { tasks })\n }\n\n _handleWorkspaceFilesChanged(filePath?: string, paths?: string[] | null): void {\n this.emitter.emit(\"workspaceChanged\", paths?.length ? { filePath, paths } : { filePath })\n }\n\n _handleSessionUpdated(data: {\n workspace_path?: string\n chat_group_id?: string | null\n intent?: string\n status?: SessionStatus\n model?: string | null\n replay_state?: Record<string, unknown> | null\n }): void {\n if (data.status) {\n this.noteLiveStatus()\n this.update((s) => ({ ...s, status: data.status ?? s.status }))\n }\n if (data.replay_state !== undefined) {\n const replay = toReplaySnapshot(data.replay_state as ReplayState | null)\n this.update((s) => ({ ...s, replay }))\n }\n this.emitter.emit(\"sessionUpdated\", {\n workspacePath: data.workspace_path,\n chatGroupId: data.chat_group_id,\n intent: data.intent,\n status: data.status,\n model: data.model,\n replayState: data.replay_state,\n })\n }\n\n _handleRewind(checkpointId: string): void {\n this.invalidateTimeline()\n this.invalidateOlderPaging()\n this.update((s) => ({\n ...s,\n mode: null,\n errorMessage: null,\n nextBefore: null,\n loadingOlder: false,\n timelineRevision: s.timelineRevision + 1,\n }))\n void this.replaceFromHistory()\n this.emitter.emit(\"rewind\", { checkpointId })\n }\n\n _handleReplayMismatch(data: { actual_message?: string; expected_message?: string }): void {\n const message = this.pendingReplayMessage ?? data.actual_message ?? \"\"\n const mode = this.pendingReplayMode\n const requestId = this.pendingReplayRequestId ?? createClientRequestId()\n const contextAttachments = this.pendingReplayAttachments\n const refs = this.pendingReplayRefs\n const topicAssetRefs = this.pendingReplayTopicAssetRefs\n this.pendingReplayMessage = null\n this.pendingReplayMode = undefined\n this.pendingReplayRequestId = undefined\n this.pendingReplayAttachments = undefined\n this.pendingReplayRefs = undefined\n this.pendingReplayTopicAssetRefs = undefined\n const respond = (decision: \"keep_replay\" | \"continue_replay\") => {\n void this.runtime\n .emitWithAck(\n \"chat:send\",\n {\n session_id: this.sessionId,\n message,\n mode,\n replay_decision: decision,\n client_request_id: requestId,\n refs,\n topic_asset_refs: topicAssetRefs,\n context_attachments: contextAttachments,\n },\n 30_000,\n )\n .then((response) => {\n if (response?.status === \"accepted\") return\n this.update((state) =>\n addErrorMessage(\n { ...state, isStreaming: false },\n typeof response?.message === \"string\"\n ? response.message\n : \"消息未被服务端接受\",\n ),\n )\n })\n .catch((error) => {\n this.update((state) =>\n addErrorMessage(\n { ...state, isStreaming: false },\n error instanceof Error && error.message ? error.message : \"消息发送失败,请重试\",\n ),\n )\n })\n }\n const handled = this.emitter.emitFirst(\"replayMismatch\", {\n actualMessage: data.actual_message,\n expectedMessage: data.expected_message,\n respond,\n })\n if (!handled) {\n respond(\"continue_replay\")\n }\n }\n\n _handleSystemNotification(loopId: string, notification: Record<string, unknown>): void {\n const notificationType =\n typeof notification.notification_type === \"string\"\n ? notification.notification_type\n : \"system_notification\"\n const title = typeof notification.title === \"string\" ? notification.title : notificationType\n const detail =\n typeof notification.detail === \"string\"\n ? notification.detail\n : notification.detail == null\n ? undefined\n : JSON.stringify(notification.detail)\n const status =\n notification.status === \"running\" || notification.status === \"done\" || notification.status === \"error\"\n ? notification.status\n : \"info\"\n this.emitter.emit(\"notification\", {\n type: notificationType,\n title,\n detail,\n status,\n loopId,\n metadata: isRecord(notification.metadata) ? notification.metadata : undefined,\n })\n if (notificationType === \"bg:started\" && isRecord(notification.metadata)) {\n const taskId =\n typeof notification.metadata.task_id === \"string\" ? notification.metadata.task_id : \"\"\n if (taskId) {\n this.emitter.emit(\"backgroundTask\", {\n id: taskId,\n command:\n typeof notification.metadata.command === \"string\" ? notification.metadata.command : \"\",\n description:\n typeof notification.metadata.description === \"string\"\n ? notification.metadata.description\n : undefined,\n status: \"running\",\n elapsedSeconds: 0,\n })\n }\n }\n }\n\n _handleBackgroundTask(task: AgentSessionEvents[\"backgroundTask\"]): void {\n this.emitter.emit(\"backgroundTask\", task)\n }\n\n _handleArtifact(data: Record<string, unknown>, kind: \"created\" | \"updated\", replayed = false): void {\n const filePath = typeof data.file_path === \"string\" ? data.file_path : \"\"\n if (!filePath) return\n this._handleWorkspaceFilesChanged(filePath)\n if (replayed) return\n this.emitter.emit(\"artifact\", {\n filePath,\n contentType: typeof data.content_type === \"string\" ? data.content_type : \"\",\n title: typeof data.title === \"string\" ? data.title : filePath,\n content: typeof data.content === \"string\" ? data.content : \"\",\n oldString: typeof data.old_string === \"string\" ? data.old_string : undefined,\n newString: typeof data.new_string === \"string\" ? data.new_string : undefined,\n kind,\n })\n }\n\n _applyRunningState(isRunning: boolean, liveRevisionAtJoin = this.liveRevision): void {\n const hasPendingQuestion = this.state.turns.some((turn) =>\n turn.tool_calls.some((call) => call.status === \"awaiting_answer\"),\n )\n if (isRunning && !hasPendingQuestion) {\n this.noteLiveStatus()\n this.update((s) => ({ ...s, status: \"running\", isStreaming: true }))\n } else if (this.state.isStreaming) {\n this.update((s) => ({ ...s, isStreaming: false }))\n void this.refreshAuthoritativeHistory({ liveRevisionAtStart: liveRevisionAtJoin })\n }\n }\n\n\n private markRunningIfIdle(): void {\n if (!this.state.isStreaming) {\n this.noteLiveStatus()\n this.update((s) => ({ ...s, status: \"running\", isStreaming: true }))\n }\n }\n\n private finishStreaming(status: string): void {\n const sessionStatus = sessionStatusFromChatEnd(status)\n this.update((s) => {\n let next: SessionState = { ...s, status: sessionStatus, isStreaming: false }\n if (status === \"interrupted\") next = markInterrupted(next)\n else if (status === \"failed\") next = markFailed(next)\n return next\n })\n this.applyDesiredStreamTokens()\n }\n\n private applyWorkflowEvents(events: RawEvent[]): void {\n for (const event of events) {\n if (!isWorkflowEvent(event.type)) continue\n const payload = (event.payload ?? {}) as Record<string, unknown>\n const runId = typeof payload.workflow_run_id === \"string\" ? payload.workflow_run_id.trim() : \"\"\n if (!runId) continue\n if (event.type === \"workflow:run:start\" && typeof payload.tool_call_id === \"string\") {\n this.workflowRunToolCalls.set(runId, payload.tool_call_id)\n }\n const toolCallId = this.workflowRunToolCalls.get(runId)\n if (!toolCallId) continue\n this.update((state) => withWorkflowEvent(state, toolCallId, event.type, payload))\n }\n }\n\n _setStreamTokens(enabled: boolean): void {\n this.desiredStreamTokens = enabled\n if (!this.state.isStreaming) this.applyDesiredStreamTokens()\n }\n\n private applyDesiredStreamTokens(): void {\n if (this.disposed || !this.joined) return\n if (this.desiredStreamTokens === null || this.desiredStreamTokens === this.joinedStreamTokens) return\n void this.enqueueSubscription(async () => {\n if (this.disposed || this.desiredStreamTokens === this.joinedStreamTokens) return\n this.joined = false\n this.joinPending = null\n await this.ensureJoined()\n }).catch(() => undefined)\n }\n\n private completeChat(status: string): void {\n this.finishStreaming(status)\n this.recentChatEndAt = Date.now()\n void this.refreshAuthoritativeHistory()\n this.emitter.emit(\"chatEnd\", { status })\n }\n\n private markTurnFresh(turnId: string): void {\n this.liveRevision += 1\n this.liveRevisions.set(turnId, this.liveRevision)\n }\n\n private markOptimisticTurnPending(turnId: string): void {\n this.pendingOptimisticTurnIds.add(turnId)\n this.markTurnFresh(turnId)\n }\n\n private pruneOptimisticLiveRevisions(): void {\n const retained = new Set(\n this.state.turns\n .map((turn) => turn.turn_id)\n .filter((turnId) => turnId.startsWith(\"local-user-\")),\n )\n for (const turnId of this.liveRevisions.keys()) {\n if (turnId.startsWith(\"local-user-\") && !retained.has(turnId)) {\n this.pendingOptimisticTurnIds.delete(turnId)\n this.liveRevisions.delete(turnId)\n }\n }\n }\n\n private applyTurn(\n turn: TurnProjection,\n source: AgentSessionEvents[\"toolResult\"][\"source\"] = \"live\",\n ): void {\n this.flushPatches()\n this.markTurnFresh(turn.turn_id)\n if (extractModeFromBlocks(turn.blocks)) this.modeRevision += 1\n const previous = this.state\n this.update((s) => upsertTurn(s, turn))\n this.pruneOptimisticLiveRevisions()\n this.emitTurnDerivedEvents(previous, turn, source)\n }\n\n private schedulePatchFlush(): void {\n if (this.patchFlushHandle != null) return\n const flush = () => {\n this.patchFlushHandle = null\n this.patchFlushCancel = null\n this.flushPatches()\n }\n if (typeof window !== \"undefined\" && typeof window.requestAnimationFrame === \"function\") {\n const handle = window.requestAnimationFrame(flush)\n this.patchFlushHandle = handle\n this.patchFlushCancel = () => window.cancelAnimationFrame(handle)\n return\n }\n const handle = globalThis.setTimeout(flush, 33)\n this.patchFlushHandle = handle\n this.patchFlushCancel = () => globalThis.clearTimeout(handle)\n }\n\n private cancelPatchFlush(): void {\n this.patchFlushCancel?.()\n this.patchFlushHandle = null\n this.patchFlushCancel = null\n this.pendingTurnPatches.clear()\n }\n\n private flushPatches(): void {\n if (this.pendingTurnPatches.size === 0) return\n const patches = [...this.pendingTurnPatches.values()].sort(\n (left, right) => left.sequence - right.sequence,\n )\n this.pendingTurnPatches.clear()\n for (const patch of patches) {\n const previous = this.state\n const next = applyTurnPatch(previous, patch)\n if (next === previous) continue\n this.liveRevision += 1\n this.liveRevisions.set(patch.turn_id, this.liveRevision)\n const turn = patch.data.turn\n if (turn && extractModeFromBlocks(turn.blocks)) this.modeRevision += 1\n this.setState(next)\n this.pruneOptimisticLiveRevisions()\n if (turn) this.emitTurnDerivedEvents(previous, turn)\n }\n if (this.patchFlushCancel) {\n this.patchFlushCancel()\n this.patchFlushHandle = null\n this.patchFlushCancel = null\n }\n }\n\n private emitTurnDerivedEvents(\n previous: SessionState,\n turn: TurnProjection,\n source: AgentSessionEvents[\"toolResult\"][\"source\"] = \"live\",\n ): void {\n this.emitter.emit(\"turnUpdated\", { turn, source })\n const mode = extractModeFromBlocks(turn.blocks)\n if (mode && previous.mode !== mode) {\n this.emitter.emit(\"modeChange\", { mode })\n }\n\n for (const block of turn.blocks) {\n if (block.type === \"tool_result\" && isOomResult(block.content)) {\n this.notifySandboxOom(block.tool_call_id ?? turn.id)\n }\n if (block.type === \"tool_bridge\" && isToolBridgeContent(block.content)) {\n this.dispatchCommand(turn, block)\n continue\n }\n if (block.type === \"tool_ui\" && block.tool_call_id && isToolUiCard(block.content)) {\n const ui = block.content\n if (ui.target !== \"preview\") continue\n const resolved = resolveToolUiCardContent(ui)\n if (!resolved) continue\n const key = buildToolUiCardKey(block.tool_call_id, resolved.type, resolved.content, ui.sourcePath)\n const fingerprint = JSON.stringify([\n resolved.content, ui.mcpApp?.sourceId,\n resolved.type === \"resource-file\" ? block.tool_call_id : undefined,\n ])\n if (this.deliveredToolPreviews.get(key) === fingerprint) continue\n this.deliveredToolPreviews.set(key, fingerprint)\n this.emitter.emit(\"toolPreview\", {\n toolCallId: block.tool_call_id,\n type: resolved.type,\n content: resolved.content,\n title: ui.title ?? \"工具预览\",\n ...(ui.sourcePath ? { sourcePath: ui.sourcePath } : {}),\n ...(ui.mcpApp ? { mcpApp: ui.mcpApp } : {}),\n })\n }\n if (block.type === \"system_notification\" && isRecord(block.content)) {\n this._handleSystemNotification(turn.loop_id, block.content)\n }\n }\n\n for (const toolCall of turn.tool_calls) {\n const info: ToolCallInfo = {\n id: toolCall.id,\n name: toolCall.tool_name,\n display_name: toolCall.display_name,\n arguments: toolCall.arguments,\n result: toolCall.result ?? undefined,\n ...(toolCall.evidence ? { evidence: toolCall.evidence } : {}),\n status:\n toolCall.status === \"pending\" ||\n toolCall.status === \"awaiting_answer\" ||\n toolCall.status === \"done\" ||\n toolCall.status === \"error\" ||\n toolCall.status === \"cancelled\"\n ? toolCall.status\n : (\"pending\" as const),\n }\n if (!this.seenToolCallIds.has(toolCall.id)) {\n this.seenToolCallIds.add(toolCall.id)\n this.emitter.emit(\"toolCall\", { toolCall: info, turn })\n }\n const finished =\n toolCall.status === \"done\" || toolCall.status === \"error\" || toolCall.status === \"cancelled\"\n if (finished && !this.finishedToolCallIds.has(toolCall.id)) {\n this.finishedToolCallIds.add(toolCall.id)\n this.emitter.emit(\"toolResult\", { toolCall: info, turn, source })\n if (isOomResult(toolCall.result)) {\n this.notifySandboxOom(toolCall.id)\n }\n }\n }\n\n if (turn.status !== \"streaming\" && !this.emittedMessageTurnIds.has(turn.turn_id)) {\n const message = this.state.messages.find((m) => m.entry_id === turn.turn_id)\n if (message) {\n this.emittedMessageTurnIds.add(turn.turn_id)\n this.emitter.emit(\"message\", { message, turn })\n }\n }\n }\n\n private dispatchCommand(\n turn: TurnProjection,\n block: ContentBlock,\n ): void {\n if (!isToolBridgeContent(block.content)) return\n const { action, payload } = block.content\n const deliveryKey = block.delivery_id\n ? commandDeliveryKey(block.delivery_id)\n : `legacy-tool-command:${turn.turn_id}:${block.tool_call_id ?? \"\"}:${action}:${JSON.stringify(payload)}`\n this.deliverCommand(deliveryKey, action, payload, block.tool_call_id ?? undefined)\n }\n\n private dispatchRawCommands(events: RawEvent[]): void {\n for (const event of events) {\n if (event.type !== \"loop:tool_bridge\") continue\n const deliveryId = String(event.payload.delivery_id ?? \"\")\n const bridge = event.payload.bridge\n if (!deliveryId || !isToolBridgeContent(bridge)) continue\n this.deliverCommand(\n commandDeliveryKey(deliveryId),\n bridge.action,\n bridge.payload,\n String(event.payload.tool_call_id ?? \"\") || undefined,\n )\n }\n }\n\n private deliverCommand(\n deliveryKey: string,\n action: string,\n payload: unknown,\n toolCallId: string | undefined,\n ): void {\n if (this.bufferedCommandDeliveries) {\n this.bufferedCommandDeliveries.push({ deliveryKey, action, payload, toolCallId })\n return\n }\n this.deliverCommandNow({ deliveryKey, action, payload, toolCallId })\n }\n\n private deliverCommandNow(command: PendingCommandDelivery): void {\n const { deliveryKey, action, payload, toolCallId } = command\n if (this.deliveredCommandKeys.has(deliveryKey)) return\n this.deliveredCommandKeys.add(deliveryKey)\n const meta = { toolCallId }\n this.emitter.emit(\"command\", { action, payload, toolCallId })\n this.commands.dispatch(action, payload, meta)\n }\n\n private notifySandboxOom(key: string): void {\n if (this.oomNotifiedKeys.has(key)) return\n this.oomNotifiedKeys.add(key)\n this.update((s) => addErrorMessage(s, OOM_MESSAGE))\n this.emitter.emit(\"sandboxOom\", { toolCallId: key })\n }\n\n private refreshAuthoritativeHistory(options: {\n liveRevisionAtStart?: number\n modeRevisionAtStart?: number\n } = {}): Promise<boolean> {\n let entryGone = false\n const locateTokenAtStart = this.locateToken\n return this.replaceFromHistory({\n ...options,\n fromEntryId: () => {\n const anchor = this.state.turns[0]?.turn_id\n return anchor?.startsWith(\"local-user-\") ? undefined : anchor\n },\n onError: (error) => {\n entryGone = isEntryGoneError(error)\n },\n }).then((located) => {\n if (located || !entryGone) return located\n if (this.locateToken !== locateTokenAtStart) return false\n return this.replaceFromHistory(options)\n })\n }\n\n private replaceFromHistory(options: {\n suppressErrors?: boolean\n liveRevisionAtStart?: number\n modeRevisionAtStart?: number\n /** 按这条发言定位:服务端返回\"从它到最新\"的窗口,而不是最新一页。传函数则在实际取数时求值。 */\n fromEntryId?: string | (() => string | undefined)\n /** 这次替换是否已被取代(用户改选了别的发言);返回 true 时整条丢弃。 */\n isStale?: () => boolean\n /** 中止在途请求(用户改选下一条时用);中止后同样整条丢弃。 */\n signal?: AbortSignal\n /** 取数失败时上报原始错误(调用方要区分\"目标没了\"和\"这次没取到\")。 */\n onError?: (error: unknown) => void\n } = {}): Promise<boolean> {\n if (this.disposed) return Promise.resolve(false)\n const operationEpoch = this.timelineEpoch\n const liveRevisionAtStart = options.liveRevisionAtStart ?? this.liveRevision\n const modeRevisionAtStart = options.modeRevisionAtStart ?? this.modeRevision\n this.invalidateOlderPaging()\n this.replaceInFlight += 1\n const operation = async (): Promise<boolean> => {\n let previousNextBefore: string | null = null\n // 这次替换被作废(会话已释放 / timeline 被重写 / 被更新的定位取代)时,游标在下面\n // 已经被清成 null:还回去,否则窗口还在、向上翻页却没了锚点。\n const restoreCursor = () => {\n if (this.disposed || previousNextBefore === null) return\n this.update((state) => ({\n ...state,\n nextBefore: previousNextBefore,\n loadingOlder: false,\n }))\n }\n try {\n if (this.disposed || operationEpoch !== this.timelineEpoch) return false\n if (options.isStale?.()) return false\n this.invalidateOlderPaging()\n previousNextBefore = this.state.nextBefore\n this.update((state) => ({ ...state, nextBefore: null, loadingOlder: false }))\n const signal = options.signal\n const fromEntryId =\n typeof options.fromEntryId === \"function\" ? options.fromEntryId() : options.fromEntryId\n const page = await this.runtime.fetchTurnsPage(\n this.sessionId,\n fromEntryId ? { fromEntryId } : undefined,\n signal ? { signal } : undefined,\n )\n if (this.disposed || operationEpoch !== this.timelineEpoch) {\n restoreCursor()\n return false\n }\n if (options.isStale?.()) {\n restoreCursor()\n return false\n }\n if (!this.joined) this.seedToolCallDeliveryBaseline(page.turns)\n this.update((state) => {\n const next = withTurns(\n state,\n replaceWindow(state.turns, page.turns, liveRevisionAtStart, {\n current: this.liveRevision,\n byTurnId: this.liveRevisions,\n }),\n )\n return {\n ...next,\n mode:\n this.modeRevision === modeRevisionAtStart\n ? page.currentMode\n : state.mode,\n nextBefore: page.nextBefore,\n loadingOlder: false,\n }\n })\n this.pruneOptimisticLiveRevisions()\n this.projectionBuilder._seedTurns(this.state.turns)\n this.update((state) => ({ ...state, historyRevision: state.historyRevision + 1 }))\n return true\n } catch (error) {\n options.onError?.(error)\n if (!this.disposed && operationEpoch === this.timelineEpoch) {\n this.update((state) => ({\n ...state,\n nextBefore: previousNextBefore,\n loadingOlder: false,\n }))\n }\n if (options.suppressErrors === false) throw error\n return false\n } finally {\n this.replaceInFlight -= 1\n }\n }\n const run = this.replaceQueue.then(operation)\n this.replaceQueue = run.catch(() => undefined)\n return run\n }\n\n private invalidateOlderPaging(): void {\n this.pagingGeneration += 1\n this.olderPending = null\n }\n\n private beginCommandRecovery(): number {\n this.commandRecoveryGeneration += 1\n this.commandRestoreRetryAttempt = 0\n this.bufferedCommandDeliveries ??= []\n if (this.commandRestoreRetryHandle !== null) {\n globalThis.clearTimeout(this.commandRestoreRetryHandle)\n this.commandRestoreRetryHandle = null\n }\n return this.commandRecoveryGeneration\n }\n\n private scheduleHistoricalCommandRestore(generation: number): void {\n const restore = async () => {\n if (this.disposed || generation !== this.commandRecoveryGeneration) return\n try {\n const commands = await this.runtime.fetchCommands(this.sessionId)\n if (this.disposed) return\n for (const command of commands) {\n if (this.disposed) return\n this.deliverCommandNow({\n deliveryKey: commandDeliveryKey(command.deliveryId),\n action: command.action,\n payload: command.payload,\n toolCallId: command.toolCallId,\n })\n }\n if (generation !== this.commandRecoveryGeneration) return\n this.commandRestoreRetryAttempt = 0\n this.flushBufferedCommands(generation)\n } catch {\n if (\n !this.disposed &&\n generation === this.commandRecoveryGeneration &&\n this.commandRestoreRetryHandle === null\n ) {\n const retryDelay = Math.min(\n COMMAND_RESTORE_RETRY_BASE_MS * 2 ** this.commandRestoreRetryAttempt,\n COMMAND_RESTORE_RETRY_MAX_MS,\n )\n this.commandRestoreRetryAttempt += 1\n this.commandRestoreRetryHandle = globalThis.setTimeout(() => {\n this.commandRestoreRetryHandle = null\n if (!this.disposed && generation === this.commandRecoveryGeneration) {\n this.scheduleHistoricalCommandRestore(generation)\n }\n }, retryDelay)\n }\n }\n }\n const run = this.commandRestoreQueue.then(restore)\n this.commandRestoreQueue = run.catch(() => undefined)\n }\n\n private flushBufferedCommands(generation: number): void {\n const pending = [...(this.bufferedCommandDeliveries ?? [])]\n this.bufferedCommandDeliveries = []\n let index = 0\n while (index < pending.length) {\n if (this.disposed) return\n if (generation !== this.commandRecoveryGeneration) {\n const currentGenerationBuffer = this.bufferedCommandDeliveries ?? []\n this.bufferedCommandDeliveries = [\n ...pending.slice(index),\n ...currentGenerationBuffer,\n ]\n return\n }\n this.deliverCommandNow(pending[index]!)\n index += 1\n const reentrantBuffer = this.bufferedCommandDeliveries\n if (index === pending.length && reentrantBuffer && reentrantBuffer.length > 0) {\n pending.push(...reentrantBuffer)\n this.bufferedCommandDeliveries = []\n }\n }\n if (!this.disposed && generation === this.commandRecoveryGeneration) {\n this.bufferedCommandDeliveries = null\n }\n }\n\n private seedToolCallDeliveryBaseline(turns: TurnProjection[]): void {\n for (const turn of turns) {\n for (const toolCall of turn.tool_calls) {\n this.seenToolCallIds.add(toolCall.id)\n if (\n toolCall.status === \"done\" ||\n toolCall.status === \"error\" ||\n toolCall.status === \"cancelled\"\n ) {\n this.finishedToolCallIds.add(toolCall.id)\n }\n }\n }\n }\n\n private ensureJoined(liveRevisionBoundary = this.liveRevision): Promise<void> {\n if (this.joined) return Promise.resolve()\n if (this.joinPending) return this.joinPending\n\n const streamTokens = this.desiredStreamTokens\n const join = this.runtime\n .emitWithAck(\n \"session:subscribe\",\n {\n session_id: this.sessionId,\n event_format: \"raw\",\n resume: true,\n ...this.logCursor.subscription(),\n ...(streamTokens === null ? {} : { internal_stream_tokens: streamTokens }),\n },\n 5_000,\n )\n .then((response) => {\n if (response && response.ok === false) {\n throw new AgentSessionError(\n typeof response.message === \"string\" && response.message\n ? response.message\n : \"Session subscription failed\",\n typeof response.code === \"string\" ? response.code : undefined,\n )\n }\n this.joined = true\n this.joinedStreamTokens = streamTokens\n this._applyRunningState(Boolean(response?.is_running), liveRevisionBoundary)\n })\n .finally(() => {\n this.joinPending = null\n })\n\n this.joinPending = join\n return join\n }\n\n private async ensureIdleBeforeSend(): Promise<void> {\n if (this.state.isStreaming) return\n if (Date.now() - this.recentChatEndAt > 3000) return\n const deadline = Date.now() + 3000\n while (Date.now() < deadline) {\n const response = await this.stop()\n const status = String(response.status ?? \"\")\n if (status !== \"stopping\") return\n await new Promise((resolve) => globalThis.setTimeout(resolve, 150))\n }\n }\n}\n","import { syncServerTime } from \"../server-clock\"\nimport { completedBackgroundTask, type BackgroundTaskEvent } from \"./background\"\nimport { LogCursor } from \"./log-cursor\"\nimport type { BladeClient } from \"../blade-client\"\nimport type { PatchEnvelope, TurnProjection } from \"../schemas/projection\"\nimport { AuthBusyReconnect } from \"../shared/auth-busy\"\nimport { acknowledgeTurnEvents, type RawEvent } from \"../shared/projection\"\nimport { AgentSession, type ChatEndPayload, type SessionDetailSnapshot, type SessionRuntime } from \"./agent-session\"\nimport { Emitter } from \"./events\"\nimport type { ConnectionStatus } from \"./state\"\n\n/**\n * Hub 级事件:服务端推送的会话运行状态,**不论这个会话有没有 AgentSession 实例**都会触发\n * (完整订阅的会话,以及 `watchStatus` 登记的状态订阅会话)。适合维护会话列表、发任务通知;\n * 会话内部的状态请用 AgentSession。\n */\nexport interface SessionHubEvents {\n /** 一轮运行开始(chat:start)。 */\n runStarted: { sessionId: string }\n /** 一轮运行结束(chat:end)。`replayed` 为 true 表示订阅时服务端重发的旧终态,不是新完成。 */\n runEnded: {\n sessionId: string\n /** 服务端给的终态原文;缺省时按 completed 处理会话状态,但不要当作「新完成」。 */\n status?: string\n queued: boolean\n replayed: boolean\n chatRunId?: string\n }\n /** 运行错误(system:error)。 */\n runError: { sessionId: string; message: string; code?: string }\n /** 会话属性被服务端更新(session:updated),`data` 是载荷原文。 */\n sessionUpdated: { sessionId: string; data: Record<string, unknown> }\n}\n\nexport interface SessionHubOptions {\n /**\n * 进入会话 / 重连时是否拉取历史指令(`GET /turns/commands`)补投给 onCommand。默认 true。\n * 不消费历史指令的宿主可以关掉,省一次请求。\n */\n restoreHistoricalCommands: boolean\n /** 覆盖会话详情的取数(宿主用自己的缓存去重)。缺省调 `client.sessions.getSession`。 */\n fetchSessionInfo?: (sessionId: string, options: { fresh: boolean }) => Promise<SessionDetailSnapshot>\n}\n\nexport interface SessionConnectOptions {\n /**\n * 在会话进入事件路由后、历史加载与房间订阅开始前同步执行。\n * 适合安装不能漏掉 bootstrap 回放事件的监听器。\n */\n setup?: (session: AgentSession) => void\n}\n\n/**\n * 每个 BladeClient 一个:管理一条 Socket.IO 连接,按 session_id 把事件\n * 路由给各 AgentSession 实例。多会话共享连接、状态互不干扰。\n */\nexport class SessionHub {\n private readonly client: BladeClient\n private readonly sessions = new Map<string, AgentSession>()\n private readonly bootstrapPending = new Map<string, Promise<AgentSession>>()\n private readonly holdCounts = new Map<string, number>()\n private connection: ConnectionStatus = \"disconnected\"\n private readonly connectionListeners = new Set<(status: ConnectionStatus) => void>()\n private bound = false\n private hasConnected = false\n private readonly authBusyReconnect = new AuthBusyReconnect()\n private readonly hubEmitter = new Emitter<SessionHubEvents>()\n private options: SessionHubOptions = { restoreHistoricalCommands: true }\n private streamTokens: boolean | null = null\n private readonly statusWatchCounts = new Map<string, number>()\n private readonly statusLogCursors = new Map<string, LogCursor>()\n private readonly replayPlaybackIds = new Map<string, string>()\n private connectionHeld = false\n private connectDeferred = false\n private connectionDemanded = false\n\n\n constructor(client: BladeClient) {\n this.client = client\n }\n\n /** 调整 Hub 行为(见 SessionHubOptions)。只影响之后创建的会话实例。 */\n configure(options: Partial<SessionHubOptions>): void {\n this.options = { ...this.options, ...options }\n }\n\n /** 监听 Hub 级事件(见 SessionHubEvents)。返回取消函数。 */\n on<K extends keyof SessionHubEvents>(\n name: K,\n handler: (event: SessionHubEvents[K]) => void,\n ): () => void {\n return this.hubEmitter.on(name, handler)\n }\n\n setStreamTokens(enabled: boolean): void {\n if (this.streamTokens === enabled) return\n this.streamTokens = enabled\n for (const session of this.sessions.values()) session._setStreamTokens(enabled)\n }\n\n /**\n * 只订阅一个会话的运行状态(chat:start / chat:end / session:updated / system:error),\n * 不加载历史、不收回合内容。用于后台会话的列表状态与完成通知。引用计数:返回的函数归还一份。\n * 事件经 Hub 级事件(`on(\"runEnded\")` 等)送达。\n */\n watchStatus(sessionId: string): () => void {\n const count = this.statusWatchCounts.get(sessionId) ?? 0\n this.statusWatchCounts.set(sessionId, count + 1)\n if (count === 0) {\n this.ensureBound()\n this.ensureConnected()\n if (!this.sessions.has(sessionId)) this.emitStatusSubscribe([sessionId])\n }\n let released = false\n return () => {\n if (released) return\n released = true\n const remaining = (this.statusWatchCounts.get(sessionId) ?? 0) - 1\n if (remaining > 0) {\n this.statusWatchCounts.set(sessionId, remaining)\n return\n }\n this.statusWatchCounts.delete(sessionId)\n this.statusLogCursors.delete(sessionId)\n if (!this.sessions.has(sessionId)) {\n // biome-ignore lint/suspicious/noExplicitAny: session:unsubscribe 是后端自定义事件\n ;(this.client.socket() as any).emit(\"session:unsubscribe\", { session_id: sessionId })\n }\n }\n }\n\n /**\n * 启动连接门控:身份确认前扣住连接,`ensureConnected` 只登记需求;`releaseConnection` 后连一次。\n * 避免用旧凭证连一次、身份确认后又重连一次。不调用则不受影响。\n */\n holdConnection(): void {\n this.connectionHeld = true\n }\n\n /**\n * 放开门控。扣住期间登记过连接需求时连一次;`connect: false`(例如身份确认后发现没有登录)只放开、\n * 丢掉登记的需求,之后的 ensureConnected / reconnect 照常生效。\n */\n releaseConnection(options: { connect?: boolean } = {}): void {\n if (!this.connectionHeld) return\n this.connectionHeld = false\n const deferred = this.connectDeferred\n this.connectDeferred = false\n if (deferred && options.connect !== false) this.ensureConnected()\n }\n\n /** 需要实时连接(例如只订阅产品事件、还没有会话时)。已连接或连接中时什么都不做。 */\n ensureConnected(): void {\n this.connectionDemanded = true\n this.ensureBound()\n if (this.connectionHeld) {\n this.connectDeferred = true\n return\n }\n const socket = this.client.socket()\n if (socket.connected || socket.active || this.authBusyReconnect.pending) return\n this.setConnection(\"connecting\")\n socket.connect()\n }\n\n /** 当前 Socket.IO 连接状态。 */\n getConnection(): ConnectionStatus {\n return this.connection\n }\n\n /** 订阅连接状态变化。 */\n onConnectionChange(listener: (status: ConnectionStatus) => void): () => void {\n this.connectionListeners.add(listener)\n return () => {\n this.connectionListeners.delete(listener)\n }\n }\n\n /**\n * 取得(或复用)一个会话的 AgentSession,并完成历史加载 + 房间订阅。\n *\n * 每次调用都算一份持有,调用方用完必须 `dispose()` 归还。复用同一实例时\n * 只有最后一份归还才退订房间——否则 StrictMode 双跑、路由抖动这类\"连两次\n * 只释放一次\"的场景会把仍在用的会话退订掉,之后所有 turn/chat 事件静默丢失。\n */\n async connect(sessionId: string, options: SessionConnectOptions = {}): Promise<AgentSession> {\n const existing = this.sessions.get(sessionId)\n if (existing && !existing.isDisposed) {\n this.hold(sessionId)\n try {\n options.setup?.(existing)\n } catch (error) {\n existing.dispose()\n throw error\n }\n return this.bootstrapPending.get(sessionId) ?? existing\n }\n this.ensureBound()\n const session = new AgentSession(sessionId, this.runtimeFor(), this.connection, {\n streamTokens: this.streamTokens,\n })\n this.sessions.set(sessionId, session)\n this.hold(sessionId)\n try {\n options.setup?.(session)\n } catch (error) {\n session.dispose()\n throw error\n }\n this.ensureConnected()\n const bootstrap = session._bootstrap().then(() => session)\n this.bootstrapPending.set(sessionId, bootstrap)\n try {\n return await bootstrap\n } catch (error) {\n this.forceRelease(session)\n throw error\n } finally {\n if (this.bootstrapPending.get(sessionId) === bootstrap) {\n this.bootstrapPending.delete(sessionId)\n }\n }\n }\n\n /** 已有实例则返回,不触发网络请求。 */\n peek(sessionId: string): AgentSession | undefined {\n if (this.bootstrapPending.has(sessionId)) return undefined\n const session = this.sessions.get(sessionId)\n return session && !session.isDisposed ? session : undefined\n }\n\n /** 手动重连(例如登录态变化后)。 */\n reconnect(): void {\n this.ensureBound()\n this.connectionDemanded = true\n this.authBusyReconnect.cancel()\n const socket = this.client.socket()\n socket.disconnect()\n if (this.connectionHeld) {\n this.connectDeferred = true\n this.setConnection(\"disconnected\")\n return\n }\n this.setConnection(\"connecting\")\n socket.connect()\n }\n\n /** 断开连接(不清理 session 实例)。 */\n disconnect(): void {\n this.connectionDemanded = false\n this.authBusyReconnect.cancel()\n this.client.socket().disconnect()\n this.setConnection(\"disconnected\")\n }\n\n /** 清理当前身份下缓存的全部会话,避免切换登录身份后复用旧快照。 */\n disposeAll(): void {\n this.authBusyReconnect.cancel()\n this.bootstrapPending.clear()\n this.statusWatchCounts.clear()\n this.statusLogCursors.clear()\n for (const session of [...this.sessions.values()]) {\n this.forceRelease(session)\n }\n }\n\n _handleSocketReplaced(): void {\n this.authBusyReconnect.cancel()\n this.bound = false\n this.setConnection(\"disconnected\")\n if (!this.needsConnection()) return\n this.ensureBound()\n this.ensureConnected()\n }\n\n private runtimeFor(): SessionRuntime {\n return {\n emitEvent: (event, data) => {\n // biome-ignore lint/suspicious/noExplicitAny: 泛化 emit,事件名由调用方保证\n ;(this.client.socket() as any).emit(event, data)\n },\n emitWithAck: (event, data, timeoutMs) => this.client.requestCommand(event, data as Record<string, unknown>, timeoutMs),\n ensureConnected: () => this.ensureConnected(),\n fetchTurnsPage: (sessionId, query, init) =>\n this.client.sessions.getSessionTurnsPage(sessionId, query, init),\n fetchTurnIndex: (sessionId) => this.client.sessions.getSessionTurnIndex(sessionId),\n fetchCommands: (sessionId) =>\n this.options.restoreHistoricalCommands\n ? this.client.sessions.getSessionTurnCommands(sessionId)\n : Promise.resolve([]),\n fetchSessionInfo: (sessionId, options) =>\n this.options.fetchSessionInfo\n ? this.options.fetchSessionInfo(sessionId, { fresh: options?.fresh ?? true })\n : this.client.sessions.getSession(sessionId),\n updateReplay: (sessionId, payload) =>\n this.client.sessions\n .updateReplaySession(sessionId, payload)\n .then((result) => result.replay_state ?? null),\n listDir: (sessionId, dirPath) => this.client.sessions.listDir(sessionId, dirPath),\n countFiles: (sessionId, dirPath) => this.client.sessions.countFiles(sessionId, dirPath),\n downloadFile: (sessionId, filePath, downloadName) =>\n this.client.sessions.downloadFile(sessionId, filePath, downloadName),\n attachAppCli: (sessionId, definition) =>\n this.client.sessions.attachAppCli(sessionId, definition),\n onDispose: (session) => this.release(session),\n }\n }\n\n private hold(sessionId: string): void {\n this.holdCounts.set(sessionId, (this.holdCounts.get(sessionId) ?? 0) + 1)\n }\n\n private release(session: AgentSession): boolean {\n const remaining = (this.holdCounts.get(session.sessionId) ?? 0) - 1\n if (remaining > 0) {\n this.holdCounts.set(session.sessionId, remaining)\n return false\n }\n this.holdCounts.delete(session.sessionId)\n if (this.sessions.get(session.sessionId) === session) {\n this.sessions.delete(session.sessionId)\n }\n if (!this.needsConnection()) {\n this.authBusyReconnect.cancel()\n }\n // biome-ignore lint/suspicious/noExplicitAny: session:unsubscribe 是后端自定义事件\n ;(this.client.socket() as any).emit(\"session:unsubscribe\", { session_id: session.sessionId })\n if (this.statusWatchCounts.has(session.sessionId)) this.emitStatusSubscribe([session.sessionId])\n else this.statusLogCursors.delete(session.sessionId)\n if (this.client.options.anonymousSessionId && !this.needsConnection()) this.disconnect()\n return true\n }\n\n private statusCursor(sessionId: string): LogCursor {\n let cursor = this.statusLogCursors.get(sessionId)\n if (!cursor) {\n cursor = new LogCursor()\n this.statusLogCursors.set(sessionId, cursor)\n }\n return cursor\n }\n\n private emitStatusSubscribe(sessionIds: string[]): void {\n if (sessionIds.length === 0) return\n // biome-ignore lint/suspicious/noExplicitAny: 后端自定义事件\n const socket = this.client.socket() as any\n const payload = (sessionId: string) => ({\n session_id: sessionId,\n mode: \"status\",\n ...this.statusCursor(sessionId).subscription(),\n })\n if (sessionIds.length === 1) {\n socket.emit(\"session:subscribe\", payload(sessionIds[0]!))\n return\n }\n socket.emit(\"session:subscribe_batch\", {\n sessions: sessionIds.map(payload),\n })\n }\n\n private forceRelease(session: AgentSession): void {\n this.holdCounts.delete(session.sessionId)\n session.dispose()\n if (!this.needsConnection()) {\n this.authBusyReconnect.cancel()\n }\n }\n\n private needsConnection(): boolean {\n return this.connectionDemanded || this.sessions.size > 0 || this.statusWatchCounts.size > 0\n }\n\n private setConnection(status: ConnectionStatus): void {\n if (this.connection === status) return\n this.connection = status\n for (const session of this.sessions.values()) {\n session._setConnection(status)\n }\n for (const listener of [...this.connectionListeners]) {\n try {\n listener(status)\n } catch (error) {\n console.warn(\"[agent-client] 连接状态回调抛出异常:\", error)\n }\n }\n }\n\n private route(sessionId: string | null | undefined): AgentSession[] {\n if (sessionId) {\n const session = this.sessions.get(sessionId)\n return session && !session.isDisposed ? [session] : []\n }\n const active = [...this.sessions.values()].filter((session) => !session.isDisposed)\n return active.length === 1 ? active : []\n }\n\n private ensureBound(): void {\n if (this.bound) return\n this.bound = true\n // biome-ignore lint/suspicious/noExplicitAny: 事件桥接层统一收敛混合 payload\n const socket = this.client.socket() as any\n\n socket.on(\"connect\", () => {\n this.authBusyReconnect.cancel()\n const isReconnect = this.hasConnected\n this.hasConnected = true\n this.setConnection(\"connected\")\n if (isReconnect) {\n for (const session of this.sessions.values()) {\n void session._rejoinAfterReconnect()\n void session.refreshQueue()\n }\n }\n this.emitStatusSubscribe(\n [...this.statusWatchCounts.keys()].filter((sessionId) => !this.sessions.has(sessionId)),\n )\n })\n socket.on(\"connect_error\", (error: unknown) => {\n this.setConnection(\"disconnected\")\n if (!this.needsConnection()) {\n this.authBusyReconnect.cancel()\n return\n }\n if (this.authBusyReconnect.schedule(error, () => {\n const current = this.client.socket()\n if (current !== socket || current.connected || current.active) return\n this.setConnection(\"connecting\")\n current.connect()\n })) return\n this.authBusyReconnect.cancel()\n })\n socket.on(\"disconnect\", () => {\n this.authBusyReconnect.cancel()\n this.setConnection(\"disconnected\")\n })\n socket.io.on(\"reconnect_attempt\", () => this.setConnection(\"reconnecting\"))\n\n socket.on(\"turn:start\", (data: TurnProjection & { session_id?: string }) => {\n for (const session of this.route(data.session_id)) session._handleTurnStart(data)\n })\n socket.on(\"turn:patch\", (data: PatchEnvelope & { session_id?: string }) => {\n for (const session of this.route(data.session_id)) session._handleTurnPatch(data)\n })\n socket.on(\"turn:end\", (data: TurnProjection & { session_id?: string }) => {\n for (const session of this.route(data.session_id)) session._handleTurnEnd(data)\n })\n socket.on(\n \"turn:timing\",\n (data: {\n session_id?: string\n loop_name?: string\n turn_id?: string\n first_token_delivery_ms?: number\n }) => {\n for (const session of this.route(data.session_id)) {\n session._handleTurnEvents([\n { type: \"llm:first_token:delivered\", payload: data },\n ])\n }\n },\n )\n socket.on(\n \"turn:events\",\n (\n data: { session_id?: string; events: RawEvent[]; replayed?: boolean; server_time?: string },\n acknowledge?: () => void,\n ) => {\n syncServerTime(this.client, data.server_time)\n acknowledgeTurnEvents(acknowledge)\n if (data.session_id && (this.statusWatchCounts.has(data.session_id) || this.sessions.has(data.session_id)) &&\n data.events?.some((event) => event.type === \"log:record\")) {\n const delivery = this.statusCursor(data.session_id).consume(data.events ?? [])\n for (const event of delivery.events) {\n if (event.type === \"chat:start\") {\n this.replayPlaybackIds.delete(data.session_id)\n this.hubEmitter.emit(\"runStarted\", { sessionId: data.session_id })\n } else if (event.type === \"chat:end\") {\n this.hubEmitter.emit(\"runEnded\", {\n sessionId: data.session_id,\n status: typeof event.payload.status === \"string\" ? event.payload.status : undefined,\n queued: false,\n replayed: data.replayed === true,\n ...(typeof event.payload.chat_run_id === \"string\" ? { chatRunId: event.payload.chat_run_id } : {}),\n })\n }\n }\n }\n if (data.session_id) {\n for (const event of data.events ?? []) {\n if (event.type === \"log:retract\") this.replayPlaybackIds.delete(data.session_id)\n if (event.type === \"replay:state\") {\n this.hubEmitter.emit(\"sessionUpdated\", { sessionId: data.session_id, data: event.payload })\n }\n const playbackId = event.payload.playback_id\n if (typeof playbackId !== \"string\") continue\n if (event.type === \"replay:start\") {\n if (this.replayPlaybackIds.get(data.session_id) !== playbackId) {\n this.replayPlaybackIds.set(data.session_id, playbackId)\n this.hubEmitter.emit(\"runStarted\", { sessionId: data.session_id })\n }\n } else if (event.type === \"replay:end\") {\n const current = this.replayPlaybackIds.get(data.session_id)\n if (current && current !== playbackId) continue\n this.replayPlaybackIds.delete(data.session_id)\n this.hubEmitter.emit(\"runEnded\", { sessionId: data.session_id,\n status: typeof event.payload.status === \"string\" ? event.payload.status : \"completed\",\n queued: false, replayed: true })\n }\n }\n }\n for (const session of this.route(data.session_id)) {\n session._handleTurnEvents(data.events ?? [], data.replayed === true)\n }\n },\n )\n socket.on(\"chat:start\", (data?: { session_id?: string }) => {\n for (const session of this.route(data?.session_id)) session._handleChatStart()\n if (data?.session_id) this.hubEmitter.emit(\"runStarted\", { sessionId: data.session_id })\n })\n socket.on(\n \"chat:end\",\n (data?: ChatEndPayload & { session_id?: string; replayed?: boolean; chat_run_id?: string }) => {\n let stale = false\n for (const session of this.route(data?.session_id)) {\n if (!session._handleChatEnd(data ?? {})) stale = true\n }\n if (data?.session_id && !stale) {\n this.hubEmitter.emit(\"runEnded\", {\n sessionId: data.session_id,\n ...(typeof data.status === \"string\" ? { status: data.status } : {}),\n queued: data.queued === true,\n replayed: data.replayed === true,\n ...(typeof data.chat_run_id === \"string\" ? { chatRunId: data.chat_run_id } : {}),\n })\n }\n },\n )\n socket.on(\n \"system:error\",\n (data: {\n message: string\n code?: string | number | null\n session_id?: string\n }) => {\n const code = data.code == null ? undefined : String(data.code)\n for (const session of this.route(data.session_id)) {\n session._handleSystemError(data.message, code)\n }\n if (data.session_id) {\n this.hubEmitter.emit(\"runError\", {\n sessionId: data.session_id,\n message: data.message,\n ...(code ? { code } : {}),\n })\n }\n },\n )\n socket.on(\"chat:queue:updated\", (data: Record<string, unknown> & { session_id?: string }) => {\n for (const session of this.route(data?.session_id)) session._handleQueueUpdated(data)\n })\n socket.on(\n \"system:notification\",\n (data: { session_id?: string } & Record<string, unknown>) => {\n for (const session of this.route(data.session_id)) {\n session._handleSystemNotification(\"root\", data)\n }\n },\n )\n socket.on(\"task:updated\", (data: { tasks: unknown[]; session_id?: string }) => {\n for (const session of this.route(data.session_id)) session._handleTaskUpdated(data.tasks)\n })\n socket.on(\"task:synced\", (data: { tasks: unknown[]; session_id?: string }) => {\n for (const session of this.route(data.session_id)) session._handleTaskUpdated(data.tasks)\n })\n socket.on(\n \"workspace:files_changed\",\n (data: { session_id?: string; file_path?: string; file_paths?: string[] | null }) => {\n for (const session of this.route(data.session_id)) {\n session._handleWorkspaceFilesChanged(data.file_path, data.file_paths)\n }\n },\n )\n socket.on(\n \"session:updated\",\n (data: {\n session_id?: string\n workspace_path?: string\n chat_group_id?: string | null\n intent?: string\n status?: import(\"../schemas/session\").SessionStatus\n model?: string | null\n replay_state?: Record<string, unknown> | null\n }) => {\n for (const session of this.route(data.session_id)) {\n session._handleSessionUpdated(data)\n }\n if (data.session_id) {\n this.hubEmitter.emit(\"sessionUpdated\", {\n sessionId: data.session_id,\n data: data as Record<string, unknown>,\n })\n }\n },\n )\n socket.on(\"session:rewind\", (data: { checkpoint_id: string; session_id?: string }) => {\n for (const session of this.route(data.session_id)) {\n session._handleRewind(data.checkpoint_id)\n }\n })\n socket.on(\n \"replay:input_mismatch\",\n (data: { session_id?: string; actual_message?: string; expected_message?: string }) => {\n for (const session of this.route(data.session_id)) session._handleReplayMismatch(data)\n },\n )\n socket.on(\"artifact:created\", (data: Record<string, unknown> & { session_id?: string }) => {\n this.routeArtifact(data, \"created\")\n })\n socket.on(\"artifact:updated\", (data: Record<string, unknown> & { session_id?: string }) => {\n this.routeArtifact(data, \"updated\")\n })\n socket.on(\"bg:started\", (data: BackgroundTaskEvent & { session_id?: string }) => {\n const taskId =\n typeof data.task_id === \"string\" ? data.task_id : typeof data.id === \"string\" ? data.id : \"\"\n if (!taskId) return\n for (const session of this.route(data.session_id)) {\n session._handleBackgroundTask({\n id: taskId,\n command: typeof data.command === \"string\" ? data.command : \"\",\n description: typeof data.description === \"string\" ? data.description : undefined,\n status: \"running\",\n elapsedSeconds: typeof data.elapsed_seconds === \"number\" ? data.elapsed_seconds : 0,\n })\n }\n })\n socket.on(\n \"bg:tasks_completed\",\n (data: { tasks?: BackgroundTaskEvent[]; session_id?: string }) => {\n for (const session of this.route(data.session_id)) {\n for (const task of data.tasks ?? []) {\n const completed = completedBackgroundTask(task)\n if (completed) session._handleBackgroundTask(completed)\n }\n }\n },\n )\n }\n\n private routeArtifact(\n data: Record<string, unknown> & { session_id?: string },\n kind: \"created\" | \"updated\",\n ): void {\n for (const session of this.route(data.session_id)) {\n session._handleArtifact(data, kind)\n }\n }\n}\n","import { io, type Socket } from \"socket.io-client\"\nimport { buildSocketAuth, type AuthOptions } from \"./auth\"\nimport type { ClientToServerEvents, ServerToClientEvents } from \"./types/socket-events\"\n\nexport type TypedSocket = Socket<ServerToClientEvents, ClientToServerEvents>\n\nexport interface CreateSocketOptions extends AuthOptions {\n baseUrl: string\n /** MV3 service workers have WebSocket but no XMLHttpRequest. */\n transports?: (\"polling\" | \"websocket\")[]\n path?: string\n}\n\nexport function createSocket(options: CreateSocketOptions): TypedSocket {\n return io(options.baseUrl, {\n path: options.path ?? \"/socket.io\",\n withCredentials: true,\n ...(options.transports ? { transports: options.transports } : {}),\n auth:\n typeof options.token === \"function\"\n ? (cb) => cb(buildSocketAuth(options) ?? {})\n : (buildSocketAuth(options) ?? {}),\n autoConnect: false,\n })\n}\n","export interface AuthOptions {\n token?: string | (() => string | null | undefined)\n}\n\nexport function buildSocketAuth(options: AuthOptions): { token: string } | undefined {\n const token = resolveAuthToken(options)\n return token ? { token } : undefined\n}\n\nexport function resolveAuthToken(options: AuthOptions): string | null {\n const token = typeof options.token === \"function\" ? options.token() : options.token\n return token ? token : null\n}\n","import type { ApplicationUserTransport } from \"./application-client\"\nimport { SandboxResource } from \"./resources/sandbox\"\nimport { ToolProvider, type ToolProviderOptions } from \"./tool-provider\"\nimport { SDK_NAME, SDK_VERSION } from \"./version\"\nimport {\n loginWithPopup,\n readStoredToken,\n writeStoredToken,\n type LoginOptions,\n type LoginResult,\n type TokenStorageMode,\n} from \"./auth-login\"\nimport {\n BladeApiError,\n type BladeFetchInit,\n type HttpMethod,\n buildBackendUrl,\n decorateAuthError,\n extractErrorDetail,\n} from \"./rest\"\nimport { AuthResource } from \"./resources/auth\"\nimport { HeadlessResource } from \"./resources/headless\"\nimport { ComputersResource } from \"./resources/computers\"\nimport { PhonesResource } from \"./resources/phones\"\nimport { LlmResource } from \"./resources/llm\"\nimport { ModelsResource } from \"./resources/models\"\nimport { SessionsResource } from \"./resources/sessions\"\nimport { PluginsResource } from \"./resources/plugins\"\nimport { ConnectorsResource } from \"./resources/connectors\"\nimport { ChatGroupsResource } from \"./resources/chat-groups\"\nimport { SiteVisitsResource } from \"./resources/site-visits\"\nimport { SessionHub } from \"./session/hub\"\nimport { createSocket, type TypedSocket } from \"./socket\"\n\nexport interface BladeClientOptions {\n /** 后端地址,如 \"https://blade.example.com\"。浏览器里传空字符串则使用当前域名。 */\n baseUrl: string\n /**\n * 访问令牌(PAT)。不传时按 cookie 会话模式工作;\n * 浏览器场景也可以不传,改用 client.auth.login() 弹窗登录。\n */\n token?: string | (() => string | null | undefined)\n /** 只访问此匿名会话;UUID 链接本身是访问凭证,不使用账号令牌。 */\n anonymousSessionId?: string\n /**\n * Socket.IO 专用令牌。第一方应用可在 REST 继续使用 cookie 刷新的同时,\n * 把 cookie 换得的短期令牌只用于实时连接;不传时复用 token。\n */\n socketToken?: string | (() => string | null | undefined)\n /** login() 取得的令牌存放位置,默认 \"local\"(localStorage,刷新页面不掉登录)。 */\n tokenStorage?: TokenStorageMode\n /** Host-owned command transport; event subscriptions stay on the normal socket. */\n commandTransport?: (event: string, payload: Record<string, unknown>, send: () => Promise<Record<string, unknown>>, scope?: { anonymousSessionId: string }) => Promise<Record<string, unknown>>\n /** Backend shared application transport, installed by BladeApplicationClient. */\n applicationTransport?: ApplicationUserTransport\n fetchImpl?: typeof fetch\n onRefreshSuccess?: () => void | Promise<void>\n}\n\nconst REFRESH_PATH = \"/api/auth/refresh\"\n\nexport class BladeClient {\n private readonly anonymousClients = new Map<string, BladeClient>()\n private readonly toolProviders = new Set<ToolProvider>()\n private refreshPromise: Promise<boolean> | null = null\n private cookieLogoutPending = 0\n private socketInstance: TypedSocket | null = null\n private readonly socketReplacementListeners = new Set<() => void>()\n private runtimeToken: string | null | undefined = undefined\n readonly options: BladeClientOptions\n readonly sandbox: SandboxResource\n readonly auth: AuthResource\n readonly headless: HeadlessResource\n readonly computers: ComputersResource\n /** 用户接进来的手机:账号级清单、会话启用、画面信令。 */\n readonly phones: PhonesResource\n readonly llm: LlmResource\n readonly models: ModelsResource\n readonly sessions: SessionsResource\n /** 按用户读取的插件目录与图标;没有会话时也能用。 */\n readonly plugins: PluginsResource\n readonly connectors: ConnectorsResource\n readonly chatGroups: ChatGroupsResource\n /**\n * 全站访问统计:匿名读写,不带 bearer 也不触发登录刷新。\n * 只有内置 Web 的同源页面使用,第三方宿主页面不会被自动统计。\n */\n readonly siteVisits: SiteVisitsResource\n /** 实时会话中枢:client.sessions.connect() 内部使用,一般不直接访问。 */\n readonly hub: SessionHub\n\n constructor(options: BladeClientOptions) {\n if (options.anonymousSessionId !== undefined && !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(options.anonymousSessionId)) {\n throw new Error(\"匿名会话 ID 必须是 UUID v4\")\n }\n this.options = {\n ...options,\n baseUrl: normalizeBaseUrl(options.baseUrl),\n }\n this.sandbox = new SandboxResource(this)\n this.auth = new AuthResource(this)\n this.headless = new HeadlessResource(this)\n this.computers = new ComputersResource(this)\n this.phones = new PhonesResource(this)\n this.llm = new LlmResource(this)\n this.models = new ModelsResource(this)\n this.sessions = new SessionsResource(this)\n this.plugins = new PluginsResource(this)\n this.connectors = new ConnectorsResource(this)\n this.chatGroups = new ChatGroupsResource(this)\n this.siteVisits = new SiteVisitsResource(this)\n this.hub = new SessionHub(this)\n if (this.options.token === undefined && !this.options.anonymousSessionId) {\n this.runtimeToken = readStoredToken(this.options.baseUrl) ?? undefined\n }\n }\n\n /** Backend application tools, callable over an outbound WebSocket. */\n connectToolProvider(options: ToolProviderOptions): ToolProvider {\n const provider = new ToolProvider(this, options, () => this.toolProviders.delete(provider))\n this.toolProviders.add(provider)\n return provider\n }\n\n /**\n * 弹窗授权登录:用户在弹出的授权页点击\"许可授权\"后自动取得 PAT,\n * REST 与 Socket.IO 立即生效。只在浏览器可用。\n */\n async login(options?: LoginOptions): Promise<LoginResult> {\n const result = await loginWithPopup(this, options)\n this.setToken(result.token)\n return result\n }\n\n /** 退出登录:清除 login() 存储的令牌并断开实时连接。 */\n logoutToken(): void {\n this.setToken(null)\n this.hub.disconnect()\n }\n\n /** 热挂载访问令牌(null 表示清除)。会重建 Socket.IO 连接以携带新凭证。 */\n setToken(token: string | null): void {\n const previousToken = this.resolveToken()\n this.runtimeToken = token\n const nextToken = this.resolveToken()\n if (token === null) for (const provider of this.toolProviders) provider.dispose()\n if (previousToken !== nextToken) {\n this.options.applicationTransport?.invalidate()\n for (const provider of this.toolProviders) {\n if (nextToken) provider.reconnect()\n else provider.dispose()\n }\n this.hub.disposeAll()\n }\n writeStoredToken(this.options.baseUrl, token, this.options.tokenStorage ?? \"local\")\n if (this.socketInstance) {\n const wasConnected = this.socketInstance.connected || this.socketInstance.active\n this.socketInstance.disconnect()\n if (wasConnected || token) {\n this.socketInstance.connect()\n }\n }\n }\n\n /** 当前是否持有访问令牌(不代表令牌一定有效)。 */\n hasToken(): boolean {\n return Boolean(this.resolveRestToken())\n }\n\n /**\n * 当前访问令牌(PAT),未登录时为 null。\n *\n * SDK 只封装会话相关接口;其余长尾接口对照后端 Swagger(`<baseUrl>/docs`)\n * 用原生 fetch 自行调用,把本令牌填入 Authorization 头即可:\n *\n * ```ts\n * fetch(`${baseUrl}/api/memories/search?q=xxx`, {\n * headers: { Authorization: `Bearer ${client.token}` },\n * })\n * ```\n *\n * 安全约束:该令牌只应发往 baseUrl 同源接口,不要附加到第三方域名的请求上。\n */\n get token(): string | null {\n return this.resolveRestToken()\n }\n\n /** 获取只访问指定匿名会话的客户端;创建仍由已认证的原客户端完成。 */\n forAnonymousSession(sessionId: string): BladeClient {\n let client = this.anonymousClients.get(sessionId)\n if (!client) {\n client = new BladeClient({ baseUrl: this.options.baseUrl, anonymousSessionId: sessionId, fetchImpl: this.options.fetchImpl, commandTransport: this.options.commandTransport })\n this.anonymousClients.set(sessionId, client)\n }\n return client\n }\n\n setBaseUrl(baseUrl: string): void {\n const nextBaseUrl = normalizeBaseUrl(baseUrl)\n if (nextBaseUrl === this.options.baseUrl) {\n return\n }\n for (const provider of this.toolProviders) provider.dispose()\n this.hub.disposeAll()\n for (const client of this.anonymousClients.values()) {\n client.hub.disposeAll()\n client.hub.disconnect()\n }\n this.anonymousClients.clear()\n this.options.baseUrl = nextBaseUrl\n if (this.socketInstance) {\n this.socketInstance.removeAllListeners()\n this.socketInstance.disconnect()\n this.socketInstance = null\n this.hub._handleSocketReplaced()\n for (const listener of [...this.socketReplacementListeners]) {\n try {\n listener()\n } catch (error) {\n console.warn(\"[agent-client] socket 替换回调抛出异常:\", error)\n }\n }\n }\n }\n\n /** 底层 Socket.IO 实例因后端地址变化而被替换时通知高级集成层。 */\n onSocketReplaced(listener: () => void): () => void {\n this.socketReplacementListeners.add(listener)\n return () => {\n this.socketReplacementListeners.delete(listener)\n }\n }\n\n socket(): TypedSocket {\n if (!this.socketInstance) {\n this.socketInstance = this.options.applicationTransport?.socket() ?? createSocket({\n baseUrl: this.options.baseUrl,\n token: () => this.resolveSocketToken(),\n })\n }\n return this.socketInstance\n }\n\n requestCommand(event: string, payload: Record<string, unknown>, timeoutMs: number): Promise<Record<string, unknown>> {\n const send = () => new Promise<Record<string, unknown>>((resolve, reject) => {\n // biome-ignore lint/suspicious/noExplicitAny: event names are supplied by the typed session API\n ;(this.socket() as any).timeout(timeoutMs).emit(event, payload, (error: Error | null, ack?: Record<string, unknown>) => {\n if (error) reject(error)\n else resolve(ack ?? {})\n })\n })\n const transport = this.options.commandTransport\n if (!transport) return send()\n const handled = this.options.anonymousSessionId\n ? transport(event, payload, send, { anonymousSessionId: this.options.anonymousSessionId })\n : transport(event, payload, send)\n return handled ?? send()\n }\n\n async json<T>(method: HttpMethod, path: string, body?: unknown): Promise<T> {\n const response = await this.fetch(method, path, {\n body: body === undefined ? undefined : JSON.stringify(body),\n headers: body === undefined ? undefined : { \"content-type\": \"application/json\" },\n })\n return readJsonResponse(response)\n }\n\n async jsonFromInit<T>(path: string, init: RequestInit = {}): Promise<T> {\n const method = (init.method ?? \"GET\").toUpperCase() as HttpMethod\n const headers = new Headers(init.headers)\n if (init.body != null && !isFormData(init.body) && !headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\")\n }\n const response = await this.fetch(method, path, {\n body: init.body,\n credentials: init.credentials,\n headers,\n signal: init.signal,\n })\n return readJsonResponse(response)\n }\n\n async text(method: HttpMethod, path: string): Promise<string> {\n const response = await this.fetch(method, path)\n return response.text()\n }\n\n async textFromInit(path: string, init: RequestInit = {}): Promise<string> {\n const method = (init.method ?? \"GET\").toUpperCase() as HttpMethod\n const response = await this.fetch(method, path, {\n body: init.body,\n credentials: init.credentials,\n headers: init.headers,\n signal: init.signal,\n })\n return response.text()\n }\n\n async responseFromInit(path: string, init: RequestInit = {}): Promise<Response> {\n const method = (init.method ?? \"GET\").toUpperCase() as HttpMethod\n return this.fetch(method, path, {\n body: init.body,\n credentials: init.credentials,\n headers: init.headers,\n signal: init.signal,\n })\n }\n\n async blob(method: HttpMethod, path: string): Promise<Blob> {\n const response = await this.fetch(method, path)\n return response.blob()\n }\n\n async formData(\n method: HttpMethod,\n path: string,\n form: FormData,\n options: { expectOk?: boolean; onUploadProgress?: (progress: UploadProgress) => void } = {},\n ): Promise<Response> {\n if (options.onUploadProgress && !this.options.fetchImpl && typeof XMLHttpRequest !== \"undefined\") {\n return this.formDataWithUploadProgress(method, path, form, options)\n }\n return this.fetch(method, path, { body: form, expectOk: options.expectOk })\n }\n\n async fetch(\n method: HttpMethod,\n path: string,\n init: BladeFetchInit = {},\n isRetry = false,\n ): Promise<Response> {\n const url = this.buildUrl(path)\n const isLogout = method === \"POST\" && url.pathname === this.buildUrl(\"/api/auth/logout\").pathname\n && this.isSameBackendUrl(url)\n if (isLogout) this.cookieLogoutPending += 1\n try {\n if (isLogout) await this.refreshPromise\n const response = await (this.options.fetchImpl ?? fetch)(url.toString(), {\n method,\n body: init.body,\n credentials: init.credentials ?? \"include\",\n headers: this.buildHeaders(url, init.headers),\n signal: init.signal,\n })\n\n if (response.status === 401 && !isRetry && this.shouldRefreshFor401(url)) {\n const refreshed = await this.tryRefreshUnlessAborted(init.signal)\n if (refreshed) {\n return this.fetch(method, path, init, true)\n }\n }\n\n if (init.expectOk !== false && !response.ok) {\n const detail = await extractErrorDetail(response)\n throw decorateAuthError(new BladeApiError(response, detail))\n }\n return response\n } finally {\n if (isLogout) this.cookieLogoutPending -= 1\n }\n }\n\n buildAuthedUrl(path: string): string {\n const url = buildBackendUrl(this.options.baseUrl, path)\n const token = this.resolveTokenForUrl(url)\n if (token) {\n url.searchParams.set(\"token\", token)\n }\n return url.toString()\n }\n\n private buildHeaders(url: URL, headers?: HeadersInit): Headers {\n const result = new Headers(headers)\n if (!this.isSameBackendUrl(url)) {\n return result\n }\n result.set(\"X-Blade-Client\", `${SDK_NAME}/${SDK_VERSION}`)\n const token = this.resolveRestToken()\n if (token) {\n result.set(\"Authorization\", `Bearer ${token}`)\n }\n return result\n }\n\n private buildUrl(path: string): URL {\n return buildBackendUrl(this.options.baseUrl, path)\n }\n\n private baseUrlWithTrailingSlash(): string {\n return this.options.baseUrl.endsWith(\"/\") ? this.options.baseUrl : `${this.options.baseUrl}/`\n }\n\n private isSameBackendUrl(url: URL): boolean {\n const base = new URL(this.baseUrlWithTrailingSlash())\n if (url.origin !== base.origin) {\n return false\n }\n const basePath = base.pathname.replace(/\\/+$/, \"\")\n if (basePath === \"\") {\n return true\n }\n return url.pathname === basePath || url.pathname.startsWith(`${basePath}/`)\n }\n\n private shouldRefreshFor401(url: URL): boolean {\n const refreshUrl = this.buildUrl(REFRESH_PATH)\n return (\n this.isSameBackendUrl(url) &&\n url.pathname !== refreshUrl.pathname &&\n !this.hasExplicitBearerToken()\n )\n }\n\n private hasExplicitBearerToken(): boolean {\n return Boolean(this.resolveRestToken())\n }\n\n private async tryRefreshUnlessAborted(signal?: AbortSignal | null): Promise<boolean> {\n if (!signal) return this.tryRefresh()\n if (signal.aborted) throw new DOMException(\"The operation was aborted.\", \"AbortError\")\n let onAbort: (() => void) | undefined\n const aborted = new Promise<never>((_resolve, reject) => {\n onAbort = () => reject(new DOMException(\"The operation was aborted.\", \"AbortError\"))\n signal.addEventListener(\"abort\", onAbort, { once: true })\n })\n try {\n return await Promise.race([this.tryRefresh(), aborted])\n } finally {\n if (onAbort) signal.removeEventListener(\"abort\", onAbort)\n }\n }\n\n private async tryRefresh(): Promise<boolean> {\n if (this.options.anonymousSessionId || this.cookieLogoutPending > 0) return false\n if (this.refreshPromise) {\n return this.refreshPromise\n }\n\n this.refreshPromise = (async () => {\n try {\n const response = await (this.options.fetchImpl ?? fetch)(\n this.buildUrl(REFRESH_PATH).toString(),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: { \"X-Blade-Client\": `${SDK_NAME}/${SDK_VERSION}` },\n },\n )\n if (!response.ok) {\n return false\n }\n await this.options.onRefreshSuccess?.()\n return true\n } catch {\n return false\n } finally {\n this.refreshPromise = null\n }\n })()\n\n return this.refreshPromise\n }\n\n private resolveTokenForUrl(url: URL): string | null {\n if (!this.isSameBackendUrl(url)) {\n return null\n }\n return this.resolveRestToken()\n }\n\n private resolveRestToken(): string | null {\n if (this.options.anonymousSessionId) return `ba-anonymous-${this.options.anonymousSessionId}`\n return this.resolveToken()\n }\n\n private resolveSocketToken(): string | null {\n if (this.options.anonymousSessionId) return `ba-anonymous-${this.options.anonymousSessionId}`\n if (this.runtimeToken !== undefined) return this.runtimeToken\n return resolveTokenOption(this.options.socketToken ?? this.options.token)\n }\n\n private resolveToken(): string | null {\n if (this.runtimeToken !== undefined) return this.runtimeToken\n return resolveTokenOption(this.options.token)\n }\n\n private formDataWithUploadProgress(\n method: HttpMethod,\n path: string,\n form: FormData,\n options: { expectOk?: boolean; onUploadProgress?: (progress: UploadProgress) => void },\n isRetry = false,\n ): Promise<Response> {\n const url = this.buildUrl(path)\n const headers = this.buildHeaders(url)\n\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest()\n xhr.open(method, url.toString(), true)\n xhr.withCredentials = true\n\n headers.forEach((value, key) => {\n xhr.setRequestHeader(key, value)\n })\n\n xhr.upload.onprogress = (event) => {\n options.onUploadProgress?.({\n loaded: event.loaded,\n total: event.lengthComputable ? event.total : undefined,\n percent: event.lengthComputable && event.total > 0 ? event.loaded / event.total : undefined,\n })\n }\n\n xhr.onerror = () => reject(new TypeError(\"Network request failed\"))\n xhr.ontimeout = () => reject(new TypeError(\"Network request timed out\"))\n xhr.onabort = () => reject(new DOMException(\"Request aborted\", \"AbortError\"))\n xhr.onload = async () => {\n if (xhr.status === 401 && !isRetry && this.shouldRefreshFor401(url)) {\n const refreshed = await this.tryRefresh()\n if (refreshed) {\n resolve(this.formDataWithUploadProgress(method, path, form, options, true))\n return\n }\n }\n\n const response = new Response(xhr.responseText, {\n status: xhr.status,\n statusText: xhr.statusText,\n headers: parseXhrHeaders(xhr.getAllResponseHeaders()),\n })\n if (options.expectOk !== false && !response.ok) {\n const detail = await extractErrorDetail(response.clone())\n reject(new BladeApiError(response, detail))\n return\n }\n options.onUploadProgress?.({ loaded: 1, total: 1, percent: 1 })\n resolve(response)\n }\n\n xhr.send(form)\n })\n }\n}\n\nfunction resolveTokenOption(\n tokenOption: string | (() => string | null | undefined) | undefined,\n): string | null {\n const token = typeof tokenOption === \"function\" ? tokenOption() : tokenOption\n return token ? token : null\n}\n\nexport interface UploadProgress {\n loaded: number\n total?: number\n percent?: number\n}\n\n/** Docker 给容器用的宿主机别名。浏览器里没有这条 DNS,怎么都解析不到。 */\nconst SANDBOX_ONLY_HOST = \"host.docker.internal\"\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n const normalized = baseUrl.trim().replace(/\\/+$/, \"\")\n if (typeof window === \"undefined\") {\n return normalized\n }\n if (!normalized) {\n return window.location.origin\n }\n assertBrowserReachable(normalized)\n return normalized\n}\n\n/**\n * 浏览器里拿到 `host.docker.internal` 就当场报错,不猜、不改、不静默降级。\n *\n * 智能体在沙盒里开发应用时,手边的后端地址是 `BLADE_API_URL`\n * (`http://host.docker.internal:8020`),很容易被原样写进前端配置。这个地址只有\n * 容器里解析得到,用户浏览器打不开——登录授权页会直接白屏,而 `client_origin` 却是\n * 真实 IP,故障看起来毫无头绪。与其替换主机名去猜一个\"可能对\"的地址,不如立刻把\n * 原因说清楚:这类配置错误必须在开发阶段就暴露出来。\n */\nfunction assertBrowserReachable(baseUrl: string): void {\n let hostname: string\n try {\n hostname = new URL(baseUrl, window.location.href).hostname\n } catch {\n return\n }\n if (hostname !== SANDBOX_ONLY_HOST) {\n return\n }\n throw new Error(\n `Blade Agent 地址 ${baseUrl} 只有沙盒内部解析得到,浏览器打不开。请把它改成用户浏览器能访问的地址(通常是访问这个应用时用的主机名 + Blade Server 端口)。`,\n )\n}\n\nfunction isFormData(value: BodyInit): boolean {\n return typeof FormData !== \"undefined\" && value instanceof FormData\n}\n\nfunction readJsonResponse<T>(response: Response): Promise<T> {\n if (response.status === 204 || response.headers.get(\"content-length\") === \"0\") {\n return Promise.resolve(undefined as T)\n }\n return response.json() as Promise<T>\n}\n\nfunction parseXhrHeaders(rawHeaders: string): Headers {\n const headers = new Headers()\n for (const line of rawHeaders.trim().split(/[\\r\\n]+/)) {\n const separatorIndex = line.indexOf(\":\")\n if (separatorIndex <= 0) continue\n headers.append(line.slice(0, separatorIndex).trim(), line.slice(separatorIndex + 1).trim())\n }\n return headers\n}\n","import { BladeClient, type BladeClientOptions } from \"./blade-client\"\nimport { buildBackendUrl } from \"./rest\"\nimport type { TypedSocket } from \"./socket\"\n\ninterface WireValue {\n value: unknown\n attachments: string[]\n}\ninterface Frame {\n id?: string\n method?: string\n user?: string\n params?: unknown\n result?: unknown\n error?: { code: string; message: string }\n event?: string\n args?: WireValue\n ack_id?: string\n handle?: string\n message?: unknown\n}\ntype Listener = (...args: unknown[]) => void\n\nclass Events {\n private listeners = new Map<string, Set<Listener>>()\n on(name: string, listener: Listener) {\n let set = this.listeners.get(name)\n if (!set) {\n set = new Set()\n this.listeners.set(name, set)\n }\n set.add(listener)\n return this\n }\n off(name: string, listener?: Listener) {\n if (listener) this.listeners.get(name)?.delete(listener)\n else this.listeners.delete(name)\n return this\n }\n once(name: string, listener: Listener) {\n const wrapped = (...args: unknown[]) => {\n this.off(name, wrapped)\n listener(...args)\n }\n return this.on(name, wrapped)\n }\n fire(name: string, ...args: unknown[]) {\n for (const listener of [...(this.listeners.get(name) ?? [])]) {\n try {\n listener(...args)\n } catch (error) {\n console.warn(\n `[agent-client] \"${name}\" application handler failed:`,\n error,\n )\n }\n }\n }\n removeAllListeners() {\n this.listeners.clear()\n return this\n }\n}\n\nfunction encode(input: unknown): WireValue {\n const attachments: string[] = []\n const walk = (value: unknown): unknown => {\n if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {\n const bytes =\n value instanceof ArrayBuffer\n ? new Uint8Array(value)\n : new Uint8Array(value.buffer, value.byteOffset, value.byteLength)\n let text = \"\"\n for (let offset = 0; offset < bytes.length; offset += 8192)\n text += String.fromCharCode(...bytes.subarray(offset, offset + 8192))\n attachments.push(btoa(text))\n return [\"bytes\", attachments.length - 1]\n }\n if (Array.isArray(value)) return [\"list\", value.map(walk)]\n if (value && typeof value === \"object\")\n return [\n \"dict\",\n Object.entries(value)\n .filter(([, item]) => item !== undefined)\n .map(([key, item]) => [key, walk(item)]),\n ]\n return [\"value\", value ?? null]\n }\n return { value: walk(input), attachments }\n}\nfunction decode(wire: WireValue): unknown[] {\n const walk = (node: unknown): unknown => {\n if (!Array.isArray(node) || node.length !== 2)\n throw new Error(\"Invalid application value\")\n if (node[0] === \"value\") return node[1]\n if (node[0] === \"bytes\")\n return Uint8Array.from(atob(wire.attachments[node[1]]), (c) =>\n c.charCodeAt(0),\n )\n if (node[0] === \"list\") return node[1].map(walk)\n if (node[0] === \"dict\")\n return Object.fromEntries(\n node[1].map(([key, value]: [string, unknown]) => [key, walk(value)]),\n )\n throw new Error(\"Invalid application value\")\n }\n const value = walk(wire.value)\n if (!Array.isArray(value)) throw new Error(\"Invalid application event\")\n return value\n}\n\n/** Transport selected by BladeApplicationClient; ordinary clients use Socket.IO. */\nexport interface ApplicationUserTransport {\n socket(): TypedSocket\n provider(): WebSocket\n invalidate(): void\n}\n\n/** Backend application: all users share two lazy WebSockets; REST keeps user credentials. */\nexport class BladeApplicationClient {\n private readonly channels: ApplicationChannel[]\n private readonly clients = new Map<string, BladeClient>()\n private readonly applicationId = crypto.randomUUID()\n constructor(\n private readonly options: Pick<BladeClientOptions, \"baseUrl\" | \"fetchImpl\">,\n ) {\n this.channels = [\n new ApplicationChannel(this.options.baseUrl, this.applicationId),\n new ApplicationChannel(this.options.baseUrl, this.applicationId),\n ]\n }\n forUser(\n userId: string,\n options: Omit<\n BladeClientOptions,\n \"baseUrl\" | \"applicationTransport\" | \"anonymousSessionId\"\n >,\n ): BladeClient {\n const saved = this.clients.get(userId)\n if (saved) return saved\n let hash = 0\n for (const character of userId)\n hash = (hash * 31 + character.charCodeAt(0)) | 0\n const channel = this.channels[(hash >>> 0) % this.channels.length]!\n const user = new ApplicationUser(channel, userId, (): BladeClient => client)\n const client: BladeClient = new BladeClient({\n ...this.options,\n ...options,\n tokenStorage: options.tokenStorage ?? \"memory\",\n applicationTransport: user,\n })\n this.clients.set(userId, client)\n return client\n }\n get connectionCount(): number {\n return this.channels.filter((channel) => channel.isConnected).length\n }\n dispose(): void {\n for (const client of this.clients.values()) {\n client.hub.disposeAll()\n client.logoutToken()\n }\n for (const channel of this.channels) channel.dispose()\n this.clients.clear()\n }\n}\n\nclass ApplicationChannel {\n private socket?: WebSocket\n private opening?: Promise<void>\n private timer?: ReturnType<typeof setTimeout>\n private stopped = false\n private attempts = 0\n private controlCount = 0\n private readonly controlWaiters: (() => void)[] = []\n private async controlSlot(): Promise<() => void> {\n if (this.controlCount >= 16)\n await new Promise<void>((resolve) => this.controlWaiters.push(resolve))\n else this.controlCount++\n return () => {\n const next = this.controlWaiters.shift()\n if (next) next()\n else this.controlCount--\n }\n }\n private readonly pending = new Map<\n string,\n {\n user: string\n resolve: (result: unknown) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n }\n >()\n readonly users = new Map<string, ApplicationUser>()\n constructor(\n private readonly baseUrl: string,\n private readonly applicationId: string,\n ) {}\n get isConnected() {\n return this.socket?.readyState === WebSocket.OPEN\n }\n ensure(): Promise<void> {\n if (this.stopped)\n return Promise.reject(new Error(\"Application client disposed\"))\n if (this.isConnected) return Promise.resolve()\n if (!this.opening) {\n const work = this.open()\n this.opening = work\n void work\n .finally(() => {\n if (this.opening === work) this.opening = undefined\n })\n .catch(() => {})\n }\n return this.opening\n }\n private async open(): Promise<void> {\n clearTimeout(this.timer)\n this.timer = undefined\n const candidates = [...this.users.values()].filter(\n (user) => user.demanded && user.client().token,\n )\n const user = candidates[this.attempts % candidates.length]\n let ticket: { token: string }\n try {\n if (!user)\n throw new Error(\n \"Application channel requires a demanded user credential\",\n )\n // One credential per channel attempt; backoff also rotates past expired credentials.\n ticket = await user\n .client()\n .jsonFromInit<{ token: string }>(\"/api/app-channels\", {\n method: \"POST\",\n body: JSON.stringify({ application_id: this.applicationId }),\n signal: AbortSignal.timeout(10000),\n })\n } catch (error) {\n this.schedule()\n throw error\n }\n if (this.stopped) throw new Error(\"Application client disposed\")\n const endpoint = buildBackendUrl(this.baseUrl, \"/api/app-channels/connect\")\n endpoint.protocol = endpoint.protocol === \"https:\" ? \"wss:\" : \"ws:\"\n const socket = new WebSocket(endpoint, [\n \"blade-application\",\n `blade-channel.${ticket.token}`,\n ])\n this.socket = socket\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"Application connection timed out\"))\n socket.close()\n }, 15000)\n socket.addEventListener(\"open\", () => {\n if (this.socket !== socket || this.stopped) return\n clearTimeout(timeout)\n this.attempts = 0\n resolve()\n for (const user of this.users.values()) user.restore()\n })\n socket.addEventListener(\"message\", (event) => {\n if (this.socket !== socket || typeof event.data !== \"string\") return\n try {\n this.receive(JSON.parse(event.data) as Frame)\n } catch {\n socket.close()\n }\n })\n socket.addEventListener(\"error\", () => {\n clearTimeout(timeout)\n reject(new Error(\"Application connection failed\"))\n })\n socket.addEventListener(\"close\", () => {\n clearTimeout(timeout)\n reject(new Error(\"Application connection closed\"))\n if (this.socket !== socket) return\n this.socket = undefined\n for (const request of this.pending.values()) {\n clearTimeout(request.timer)\n request.reject(new Error(\"Application connection closed\"))\n }\n this.pending.clear()\n for (const user of this.users.values()) user.lost()\n this.schedule()\n })\n })\n }\n private schedule() {\n if (\n this.stopped ||\n this.timer ||\n ![...this.users.values()].some((user) => user.demanded)\n )\n return\n this.timer = setTimeout(\n () => {\n this.timer = undefined\n void this.ensure().catch(() => this.schedule())\n },\n Math.min(10000, 500 * 2 ** Math.min(this.attempts++, 5)),\n )\n }\n private receive(frame: Frame) {\n if (frame.id) {\n const request = this.pending.get(frame.id)\n if (!request || request.user !== frame.user) return\n this.pending.delete(frame.id)\n clearTimeout(request.timer)\n if (frame.error)\n request.reject(\n Object.assign(new Error(frame.error.message), {\n code: frame.error.code,\n data: {\n code: frame.error.code,\n status: frame.error.code === \"auth_busy\" ? 429 : 401,\n retry_after: 1,\n },\n }),\n )\n else request.resolve(frame.result)\n return\n }\n const user = frame.user && this.users.get(frame.user)\n if (user) user.receive(frame)\n }\n async request(\n user: string,\n method: string,\n params: unknown,\n timeoutMs = 30000,\n ): Promise<unknown> {\n const release =\n method === \"socket/event\" ? () => {} : await this.controlSlot()\n try {\n return await new Promise((resolve, reject) => {\n const id = crypto.randomUUID()\n const timer = setTimeout(() => {\n this.pending.delete(id)\n reject(new Error(\"Application request timed out\"))\n }, timeoutMs)\n this.pending.set(id, { user, resolve, reject, timer })\n try {\n this.send({ id, user, method, params })\n } catch (error) {\n clearTimeout(timer)\n this.pending.delete(id)\n reject(error)\n }\n })\n } finally {\n release()\n }\n }\n send(frame: Frame): void {\n if (!this.isConnected || !this.socket)\n throw new Error(\"Application connection unavailable\")\n this.socket.send(JSON.stringify(frame))\n }\n dispose() {\n this.stopped = true\n clearTimeout(this.timer)\n this.timer = undefined\n for (const user of this.users.values()) user.lost()\n this.socket?.close()\n for (const request of this.pending.values()) {\n clearTimeout(request.timer)\n request.reject(new Error(\"Application client disposed\"))\n }\n this.pending.clear()\n this.users.clear()\n }\n}\n\nclass ApplicationUser implements ApplicationUserTransport {\n readonly key = crypto.randomUUID()\n readonly events: ApplicationSocket\n readonly providers = new Map<string, ApplicationProviderSocket>()\n private binding?: Promise<void>\n private bindingToken?: string\n constructor(\n readonly channel: ApplicationChannel,\n private readonly userId: string,\n readonly client: () => BladeClient,\n ) {\n this.events = new ApplicationSocket(this)\n channel.users.set(this.key, this)\n }\n get demanded() {\n return this.events.active || this.providers.size > 0\n }\n async bind(): Promise<void> {\n await this.channel.ensure()\n if (!this.demanded) throw new Error(\"Application user no longer needed\")\n const token = this.client().token\n if (!token) throw new Error(\"Application user requires a token\")\n if (!this.binding || this.bindingToken !== token) {\n this.bindingToken = token\n const work = this.channel\n .request(this.key, \"user/bind\", { user_id: this.userId, token })\n .then((result) => {\n if ((result as { user_id: string }).user_id !== this.userId)\n throw new Error(\"Application user identity mismatch\")\n if (!this.demanded) {\n this.binding = undefined\n this.bindingToken = undefined\n void this.channel\n .request(this.key, \"user/unbind\", {})\n .catch(() => {})\n throw new Error(\"Application user no longer needed\")\n }\n })\n this.binding = work\n void work.catch(() => {\n if (this.binding === work) this.binding = undefined\n })\n }\n return this.binding\n }\n socket(): TypedSocket {\n return this.events as unknown as TypedSocket\n }\n provider(): WebSocket {\n const provider = new ApplicationProviderSocket(this)\n this.providers.set(provider.handle, provider)\n provider.open()\n return provider as unknown as WebSocket\n }\n invalidate() {\n this.binding = undefined\n this.bindingToken = undefined\n if (!this.client().token && this.channel.isConnected)\n void this.channel.request(this.key, \"user/unbind\", {}).catch(() => {})\n }\n restore() {\n if (this.events.active) this.events.connect()\n }\n lost() {\n this.invalidate()\n this.events.lost()\n for (const provider of [...this.providers.values()]) provider.closeLocal()\n }\n receive(frame: Frame) {\n if (frame.method === \"socket/closed\") {\n this.events.lost()\n if (this.events.active) this.events.connect()\n return\n }\n if (frame.method === \"tool/closed\") {\n this.providers.get(frame.handle ?? \"\")?.closeLocal()\n return\n }\n if (frame.method === \"tool/message\") {\n this.providers.get(frame.handle ?? \"\")?.message(frame.message)\n return\n }\n if (frame.event && frame.args) {\n const args = decode(frame.args)\n if (frame.ack_id)\n args.push((...values: unknown[]) =>\n this.channel.send({\n method: \"event/ack\",\n user: this.key,\n ack_id: frame.ack_id,\n params: encode(values),\n }),\n )\n this.events.fire(frame.event, ...args)\n }\n }\n}\n\nclass ApplicationSocket extends Events {\n connected = false\n active = false\n readonly io = new Events()\n private connecting?: Promise<void>\n private generation = 0\n constructor(private readonly user: ApplicationUser) {\n super()\n }\n connect(): this {\n this.active = true\n if (this.connected || this.connecting) return this\n const generation = ++this.generation\n const work = this.user\n .bind()\n .then(() => {\n if (generation !== this.generation || !this.active) return\n return this.user.channel.request(this.user.key, \"socket/connect\", {})\n })\n .then(() => {\n if (generation !== this.generation || !this.active) return\n this.connected = true\n this.fire(\"connect\")\n })\n .catch((error) => {\n if (generation === this.generation && this.active) {\n // Logical auth failures use SessionHub's existing retry; physical startup keeps demand.\n if (error?.code === \"auth_busy\" || error?.code === \"unauthorized\")\n this.active = false\n this.fire(\"connect_error\", error)\n }\n })\n .finally(() => {\n if (this.connecting === work) this.connecting = undefined\n })\n this.connecting = work\n return this\n }\n disconnect(): this {\n this.active = false\n this.lost()\n if (this.user.channel.isConnected)\n void this.user.channel\n .request(this.user.key, \"socket/disconnect\", {})\n .catch(() => {})\n return this\n }\n lost() {\n const wasConnected = this.connected\n this.connected = false\n this.connecting = undefined\n this.generation++\n if (wasConnected) this.fire(\"disconnect\", \"transport close\")\n }\n emit(event: string, ...args: unknown[]): this {\n this.send(event, args)\n return this\n }\n timeout(timeoutMs: number) {\n return {\n emit: (event: string, ...args: unknown[]) => {\n this.send(event, args, timeoutMs)\n return this\n },\n }\n }\n private send(event: string, values: unknown[], timeoutMs?: number) {\n const args = [...values]\n const callback =\n typeof args.at(-1) === \"function\" ? (args.pop() as Listener) : undefined\n const generation = this.generation\n const deadline = Date.now() + (timeoutMs ?? 30000)\n const work = (async () => {\n if (!this.active) throw new Error(\"Application user disconnected\")\n if (!this.connected) await this.connecting\n if (!this.connected || this.generation !== generation)\n throw new Error(\"Application user disconnected\")\n const remaining = deadline - Date.now()\n if (remaining <= 0) throw new Error(\"Application request timed out\")\n const params = { event, args: encode(args) }\n if (!callback) {\n this.user.channel.send({\n user: this.user.key,\n method: \"socket/event\",\n params,\n })\n return\n }\n return this.user.channel.request(\n this.user.key,\n \"socket/event\",\n params,\n remaining,\n )\n })()\n void work.then(\n (result) => {\n if (!callback) return\n const values = decode(result as WireValue)\n if (timeoutMs !== undefined) callback?.(null, ...values)\n else callback?.(...values)\n },\n (error) => {\n if (timeoutMs !== undefined) callback?.(error)\n else if (callback) callback(error)\n },\n )\n }\n}\n\nclass ApplicationProviderSocket extends Events {\n readonly handle = crypto.randomUUID()\n readyState: number = WebSocket.CONNECTING\n constructor(private readonly user: ApplicationUser) {\n super()\n }\n addEventListener(name: string, listener: Listener) {\n this.on(name, listener)\n }\n open() {\n void this.user.bind().then(\n () => {\n if (this.readyState !== WebSocket.CONNECTING) return\n this.readyState = WebSocket.OPEN\n this.fire(\"open\", new Event(\"open\"))\n },\n () => {\n if (this.readyState !== WebSocket.CLOSED) {\n this.fire(\"error\", new Event(\"error\"))\n this.closeLocal()\n }\n },\n )\n }\n send(text: string) {\n if (this.readyState !== WebSocket.OPEN)\n throw new Error(\"Application provider closed\")\n const message = JSON.parse(text) as {\n id?: string\n method?: string\n params?: Record<string, unknown>\n }\n if (message.method === \"provider/register\") {\n void this.user.channel\n .request(this.user.key, \"tool/register\", {\n ...message.params,\n handle: this.handle,\n })\n .then(\n (result) => this.message({ jsonrpc: \"2.0\", id: message.id, result }),\n (error) =>\n this.message({\n jsonrpc: \"2.0\",\n id: message.id,\n error: { code: -32001, message: error.message },\n }),\n )\n } else\n this.user.channel.send({\n method: \"tool/result\",\n user: this.user.key,\n handle: this.handle,\n message,\n })\n }\n message(message: unknown) {\n if (this.readyState === WebSocket.OPEN)\n this.fire(\n \"message\",\n new MessageEvent(\"message\", { data: JSON.stringify(message) }),\n )\n }\n close() {\n if (this.readyState === WebSocket.CLOSED) return\n if (this.user.channel.isConnected)\n void this.user.channel\n .request(this.user.key, \"tool/unregister\", { handle: this.handle })\n .catch(() => {})\n this.closeLocal()\n }\n closeLocal() {\n if (this.readyState === WebSocket.CLOSED) return\n this.readyState = WebSocket.CLOSED\n this.user.providers.delete(this.handle)\n this.fire(\"close\", new Event(\"close\"))\n this.removeAllListeners()\n }\n}\n","import type { AskUserAnswerData } from \"../session/state\"\n\nexport interface AskUserQuestionOption {\n label: string\n description: string\n}\n\nexport interface AskUserQuestionItem {\n question: string\n options: AskUserQuestionOption[]\n multiSelect?: boolean\n}\n\nexport interface AskUserQuestionData {\n questions: AskUserQuestionItem[]\n source_loop?: { loop_name: string; description: string } | null\n}\n\n/** Normalize the question payload returned by AskUserQuestion or stored in its arguments. */\nexport function parseAskUserQuestion(\n toolResult: string | null | undefined,\n): AskUserQuestionData | null {\n if (!toolResult) return null\n try {\n const parsed = JSON.parse(toolResult)\n let questions = parsed?.questions\n if (typeof questions === \"string\") {\n try {\n questions = JSON.parse(questions)\n } catch {\n return null\n }\n }\n if (Array.isArray(questions) && questions.length > 0) {\n const normalized = questions.map(normalizeQuestionItem)\n if (normalized.every((question): question is AskUserQuestionItem => question !== null)) {\n return { ...parsed, questions: normalized } as AskUserQuestionData\n }\n }\n } catch {\n }\n return null\n}\n\n/** Build the user message accompanying a structured AskUserQuestion answer. */\nexport function formatAskUserAnswer(data: AskUserQuestionData, answer: AskUserAnswerData): string {\n const parts = data.questions.map((question, index) => {\n const text = typeof answer.custom[index] === \"string\"\n ? answer.custom[index].trim()\n : [...(answer.selections[index] ?? [])]\n .sort((a, b) => a - b)\n .map(optionIndex => question.options[optionIndex].label)\n .join(\", \")\n return `- ${question.question} -> ${indentAnswerContinuationLines(text)}`\n })\n const note = answer.note?.trim() ?? \"\"\n return [\n `关于需要确认的问题,用户的回答如下:\\n${parts.join(\"\\n\")}`,\n note ? `补充说明:${indentAnswerContinuationLines(note)}` : \"\",\n ].filter(Boolean).join(\"\\n\")\n}\n\nfunction indentAnswerContinuationLines(answer: string) {\n return answer.replaceAll(\"\\n\", \"\\n \")\n}\n\nfunction normalizeQuestionItem(value: unknown): AskUserQuestionItem | null {\n if (!value || typeof value !== \"object\") return null\n const item = value as {\n question?: unknown\n options?: unknown\n multiSelect?: unknown\n multi_select?: unknown\n }\n if (typeof item.question !== \"string\" || !Array.isArray(item.options)) return null\n const options = item.options.map(normalizeOptionItem)\n if (!options.every((option): option is AskUserQuestionOption => option !== null)) return null\n return {\n question: item.question,\n options,\n multiSelect: item.multiSelect === true || item.multi_select === true,\n }\n}\n\nfunction normalizeOptionItem(value: unknown): AskUserQuestionOption | null {\n if (typeof value === \"string\") return { label: value, description: \"\" }\n if (!value || typeof value !== \"object\") return null\n const option = value as { label?: unknown; description?: unknown }\n if (typeof option.label !== \"string\") return null\n return {\n label: option.label,\n description: typeof option.description === \"string\" ? option.description : \"\",\n }\n}\n"],"mappings":"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","names":["snapshot","encode","type","type","ack","error","type","event","response","snapshot","snapshot","attachments","contexts","type","buildMessageContent","toolCall","snapshot","type","type","snapshot","handle","value","user","values"]}
|