@blade-hq/agent-client 2610.0.0-beta.5 → 2610.0.0-beta.51

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.
Files changed (36) hide show
  1. package/README.md +180 -6
  2. package/dist/auth.d.ts +0 -1
  3. package/dist/blade-client.d.ts +4 -2
  4. package/dist/index.d.ts +25 -4
  5. package/dist/index.js +1592 -227
  6. package/dist/index.js.map +1 -1
  7. package/dist/platform-endpoints.d.ts +14 -0
  8. package/dist/polling-backoff.d.ts +11 -0
  9. package/dist/resources/chat-projects.d.ts +26 -0
  10. package/dist/resources/computers.d.ts +85 -0
  11. package/dist/resources/models.d.ts +2 -0
  12. package/dist/resources/sessions.d.ts +146 -1
  13. package/dist/schemas/context.d.ts +49 -0
  14. package/dist/schemas/event.d.ts +9 -0
  15. package/dist/schemas/mcp-app.d.ts +30 -0
  16. package/dist/schemas/message-utils.d.ts +5 -1
  17. package/dist/schemas/message.d.ts +5 -0
  18. package/dist/schemas/projection.d.ts +22 -1
  19. package/dist/schemas/session.d.ts +9 -1
  20. package/dist/session/agent-session.d.ts +53 -16
  21. package/dist/session/events.d.ts +4 -0
  22. package/dist/session/history-page.d.ts +9 -0
  23. package/dist/session/hub.d.ts +9 -1
  24. package/dist/session/state.d.ts +11 -2
  25. package/dist/shared/auth-busy.d.ts +9 -0
  26. package/dist/shared/projection/builder.d.ts +9 -0
  27. package/dist/shared/projection/context.d.ts +3 -0
  28. package/dist/shared/projection/helpers.d.ts +1 -1
  29. package/dist/shared/projection/history.d.ts +1 -0
  30. package/dist/shared/projection/index.d.ts +2 -1
  31. package/dist/shared/projection/state.d.ts +3 -0
  32. package/dist/shared/tool-ui-card.d.ts +58 -0
  33. package/dist/shared/type-guards.d.ts +2 -0
  34. package/dist/types/socket-events.d.ts +41 -4
  35. package/package.json +1 -1
  36. package/public-api.md +574 -10
package/README.md CHANGED
@@ -2,16 +2,21 @@
2
2
 
3
3
  Blade Agent 的框架无关客户端。浏览器和 Node.js 都能用;用 Vue、Svelte 或自建 UI 的团队直接用这个包,React 团队一般用上层的 `@blade-hq/agent-react`。
4
4
 
5
- 它做三件事:
5
+ 它做四件事:
6
6
 
7
7
  1. **实时会话**(`AgentSession`):把 Socket.IO 协议、历史加载、流式合流、断线重连全部封装掉,你只面对"状态快照 + 动作 + 事件"。
8
8
  2. **登录**:`client.auth.login()` 弹窗授权,用户点一下"许可授权"就拿到访问令牌,不用手工复制粘贴。
9
9
  3. **REST**:类型化会话和模型目录(`client.sessions.*`、`client.models.list()`)。其他长尾接口对照 Swagger 用原生 `fetch` + `client.token` 调用。
10
+ 4. **部署端点**:从同源 `config.json` 读取其他 Blade 服务的公开地址,不根据主机名和固定端口猜测拓扑。
10
11
 
11
12
  ```bash
12
13
  npm install @blade-hq/agent-client
13
14
  ```
14
15
 
16
+ 默认装到的是当前长期支持版(LTS),厂内离线交付按它开发。要跟两周一发的公网版本,改用 `@next`。
17
+
18
+ 最稳妥的做法是先读目标 Server 的 `GET /api/version`,按返回的版本号在 `package.json` 里钉死——NPM 的 `latest` 不一定和目标环境跑的版本一致。
19
+
15
20
  ## 快速开始
16
21
 
17
22
  ```html
@@ -47,6 +52,27 @@ const client = new BladeClient({
47
52
  })
48
53
  ```
49
54
 
55
+ ## 部署端点
56
+
57
+ Blade 平台前端需要跳转其他服务时,读取当前 origin 的公开配置:
58
+
59
+ ```ts
60
+ import { loadPlatformEndpoints, resolveServiceUrl } from "@blade-hq/agent-client"
61
+
62
+ const endpoints = await loadPlatformEndpoints()
63
+ const hubUrl = resolveServiceUrl(endpoints, "hub", "/skills/42")
64
+ if (hubUrl) window.open(hubUrl)
65
+ ```
66
+
67
+ `loadPlatformEndpoints()` 请求 `config.json`,超过 3 秒、网络失败或配置非法时返回空配置;
68
+ 调用方应隐藏对应入口。文件只能放浏览器可访问的公开地址,不能写 Docker 服务名、令牌或
69
+ 其他内部配置。应用部署在子路径时,通过 `baseUrl` 显式传入部署根路径。
70
+ `resolveServiceUrl()` 的 `path` 只接受服务内相对路径;绝对 URL、反斜杠和越出服务
71
+ base path 的路径返回 `null`。
72
+
73
+ 公开类型为 `PlatformEndpoints`、`PlatformServiceName`、`LoadPlatformEndpointsOptions`;
74
+ 需要同步初始化时可直接使用 `EMPTY_PLATFORM_ENDPOINTS`。
75
+
50
76
  ## BladeClient
51
77
 
52
78
  ### 构造
@@ -56,10 +82,12 @@ new BladeClient({
56
82
  baseUrl: "https://blade.example.com", // 后端地址;同域部署可传 ""
57
83
  token: "sk-blade-xxx", // 可选:PAT。不传则用 cookie 或 login()
58
84
  tokenStorage: "local", // 可选:login() 的令牌存哪("local" 默认 / "memory")
59
- streamTokens: false, // 可选:只接收完成态内容,不订阅逐 token 增量
60
85
  })
61
86
  ```
62
87
 
88
+ SDK 会固定订阅普通聊天所需的完整实时事件。产品内置 Web 的精简/开发者展示模式不属于
89
+ 公共 SDK 契约,也没有对应的构造参数或 Socket.IO 字段。
90
+
63
91
  > **`baseUrl` 填哪个地址?** 必须是 Blade Agent 后端的地址(形如 `http://<主机>:8020`),只要域名和端口、不带路径。
64
92
  > 注意别填成你平时打开的 Blade OS 地址(同主机的 `:80`)—— 那是另一套接口,SDK 连不上。
65
93
 
@@ -139,8 +167,48 @@ await client.sessions.getSession(id) // 会话详情
139
167
  await client.sessions.updateSession(id, { intent: "新标题" })
140
168
  await client.sessions.deleteSession(id)
141
169
  await client.sessions.getSessionTurns(id) // 历史消息(投影格式,与实时流同构)
170
+ const page = await client.sessions.getSessionTurnsPage(id) // 聊天首屏 recent page
171
+ await client.sessions.getSessionTurnsPage(id, { before: page.nextBefore! })
142
172
  ```
143
173
 
174
+ 会话插件可通过 `client.sessions.listSessionPlugins(id)` 查询,并用
175
+ `client.sessions.setSessionPluginActivation(id, name, active)` 切换当前会话。列表项为 `SessionPlugin`;修改结果为 `SessionPluginActivation`,只返回选择和准备状态,安装事实需从列表获取。
176
+
177
+ 插件可以在包内 `cn.com.bladeai.agent/config.schema.json` 用标准 JSON Schema
178
+ (Draft 2020-12)声明账号、token 或任意业务配置。声明了配置的插件用
179
+ `client.sessions.getSessionPluginConfig(id, name)` 读取声明与当前值,用
180
+ `client.sessions.updateSessionPluginConfig(id, name, { expected_revision, set, remove })`
181
+ 保存;两者都要等到插件包已准备(即已激活过)才有内容,没有声明的插件返回
182
+ `state: "not_required"`。
183
+
184
+ ```ts
185
+ const { config } = await client.sessions.getSessionPluginConfig(id, "crm")
186
+ // config: SessionPluginConfigState
187
+ // state "not_required" | "required" | "configured" | "error"
188
+ // schema 包内声明的 JSON Schema(Draft 2020-12)
189
+ // values 已存值,writeOnly 字段已被平台剔除
190
+ // write_only 当前有值的秘密字段 JSON Pointer
191
+ // revision 乐观并发用的版本号
192
+ // errors SessionPluginConfigError[],逐条 { path, message },不含用户输入
193
+ // 列表项 SessionPlugin.config 是 SessionPluginConfigSummary
194
+ // (SessionPluginConfigStateName 之外多一个 "unchecked":列表只报本地已知事实,
195
+ // 不伪报已配置)
196
+
197
+ await client.sessions.updateSessionPluginConfig(id, "crm", {
198
+ expected_revision: config.revision,
199
+ set: [{ path: "/login/password", value: password }], // SessionPluginConfigSet[]
200
+ remove: [],
201
+ } satisfies SessionPluginConfigUpdate)
202
+ ```
203
+
204
+ 图标用 `client.sessions.fetchSessionPluginIcon(id, name)` 取 `Blob`(自带凭据),
205
+ 或 `client.sessions.sessionPluginIconUrl(id, name)` 取已鉴权 URL。
206
+
207
+ `set`/`remove` 只表达显式改动:没出现的字段保持原值,因此表单不需要回传秘密;
208
+ `null` 是一个合法值,不是删除。校验不通过或版本过期时请求被拒绝,磁盘上的旧
209
+ 配置保持不变。平台只写用户 Home 下的 `~/.plugin/<plugin_id>/config.json`,不会
210
+ 重启 MCP、清缓存或刷新 token。
211
+
144
212
  ### 会话回放(演示 / 彩排)
145
213
 
146
214
  拿一个已经聊完的会话当素材,重现当时的回复和工具调用,**完全不调用模型**。
@@ -261,6 +329,57 @@ const body = { model: defaultServiceModel, messages, stream: true }
261
329
  没问题,直接交给浏览器就指向用户自己的机器了。默认形态是后端透传(密钥本来也不该进浏览器),
262
330
  浏览器直连只适合这个地址对浏览器同样可达的场景。
263
331
 
332
+ ### 远程电脑:client.computers
333
+
334
+ 一个会话除了自己的运行时,还可以操作用户接入的其他电脑(`blade daemon connect` 接进来的机器)。
335
+ **默认一台都不能用**,要先为这次会话启动它。
336
+
337
+ ```ts
338
+ const { computers } = await client.computers.list(sessionId)
339
+ // SessionComputerList → { computers: SessionComputer[] }
340
+ // SessionComputer: { id, label, os, arch, home, workspace, allowed_paths,
341
+ // online, enabled, is_primary, last_seen_at, ... }
342
+
343
+ await client.computers.setEnabled(sessionId, computer.id, true) // 启动
344
+ await client.computers.setEnabled(sessionId, computer.id, false) // 停用
345
+ ```
346
+
347
+ `online` 和 `enabled` 是**两件独立的事**:前者指那台电脑此刻连着后端,后者指这次会话已经启动了它。
348
+ 离线的电脑也能先启动,等它连上就直接可用。`online` 由服务端读心跳时间判定,不做实时探测,
349
+ 所以电脑离线时列表照样返回它——你拿得到「它离线了」这个结论。
350
+
351
+ `is_primary` 表示这次会话本身就跑在这台电脑上。这种电脑恒为可用,也不能停用——
352
+ 那是会话自己的工作目录所在。
353
+
354
+ 做电脑选择器时用这几个纯函数,别自己重算状态:
355
+
356
+ ```ts
357
+ import {
358
+ canToggleComputer, computerState, sortComputers,
359
+ computerOS, computerPlatformLabel, computerDaemonVersion,
360
+ } from "@blade-hq/agent-client"
361
+
362
+ sortComputers(computers) // 按接入时间,顺序稳定不随状态变化
363
+ computerState(computer) // ComputerState: "primary" | "enabled" | "offline" | "idle"
364
+ canToggleComputer(computer) // 主运行时返回 false
365
+
366
+ computerOS(computer) // ComputerOS: "macos" | "windows" | "linux" | "unknown"
367
+ computerPlatformLabel(computer) // "darwin/arm64"
368
+ computerDaemonVersion(computer) // "dev (bc3ad71d1)",未知时是空串
369
+ ```
370
+
371
+ `sortComputers` **刻意不按在线/可用排序**:那样排看着"手边的在前面",代价是电脑
372
+ 上下线、勾选状态一变整个列表就重排,用户正要点的那一项会在手指底下跑掉。改名也
373
+ 不会挪位置,新接入的稳定排在末尾。
374
+
375
+ `computerOS` 判定的是 daemon 上报的 `runtime.GOOS`,各处自己 `startsWith` 一遍必然会分叉;
376
+ 图标怎么画交给界面,这里只回答"是哪一类系统"。
377
+
378
+ `computerDaemonVersion` 返回的是服务端存的完整串——dev 构建带 commit,
379
+ 因为 dev 的版本号全都是 `dev`,光看它分不出是哪次构建的二进制。**不要在前端另拼一套格式。**
380
+
381
+ `ComputersResource` 是 `client.computers` 的类型。
382
+
264
383
  ## AgentSession
265
384
 
266
385
  一个会话的实时状态机。**状态归属实例**:同一页面建多个会话互不干扰。
@@ -279,6 +398,7 @@ chat.getState()
279
398
  // errorMessage, 最近一次运行错误
280
399
  // replay, 回放状态:{ isReplay, speed, sourceSessionId } | null
281
400
  // viewerRole, "owner" | "viewer" | null(只读身份改不动会话)
401
+ // nextBefore, loadingOlder, 历史分页游标与加载状态
282
402
  // turns, askAnswers, agentLoops, activeCompaction 进阶字段
283
403
  // }
284
404
 
@@ -295,6 +415,7 @@ await chat.send("换个方案", { mode: "planning" }) // 指定模式/模型等
295
415
  chat.append("补充:预算不超过 5 万") // 智能体运行中追加说明
296
416
  await chat.stop() // 停止当前回复
297
417
  await chat.compact() // 手动压缩上下文
418
+ if (chat.hasOlderHistory) await chat.loadOlderHistory()
298
419
  chat.dispose() // 彻底释放(什么时候该调见下方说明)
299
420
  ```
300
421
 
@@ -369,7 +490,9 @@ chat.on("chatEnd", (e) => console.log("回复结束", e.status))
369
490
  chat.on("error", (e) => console.error(e.message))
370
491
  ```
371
492
 
372
- 完整事件表见 `AgentSessionEvents` 类型定义(含 `modeChange` / `workspaceChanged` / `artifact` / `notification` / `backgroundTask` / `taskListUpdated` / `rewind` / `replayMismatch` 等)。`on()` 返回取消函数;handler 抛异常只告警,不影响会话。
493
+ 完整事件表见 `AgentSessionEvents` 类型定义(含 `modeChange` / `workspaceChanged` / `artifact` / `notification` / `backgroundTask` / `taskListUpdated` / `rewind` / `replayMismatch` 等)。`toolResult.source` 区分实时结果、首次连接回放和断线重连回放;`on()` 返回取消函数,handler 抛异常只告警、不影响会话。
494
+
495
+ 分页响应是 `SessionTurnsPage`,其中 `nextBefore: string | null` 是唯一的“还有更早历史”真值。历史页面指令通过独立的 `HistoricalCommand` 日志恢复,不混进展示页。自定义状态容器可复用 `prependOlder`、`replaceWindow` 与 `LiveRevisionState`,但一般直接使用 `AgentSession` 即可。
373
496
 
374
497
  ## iframe 嵌入形态:connectEmbedded
375
498
 
@@ -414,6 +537,15 @@ PATCH / query / FormData / AbortSignal 等完整 HTTP 语义(否则不够用
414
537
  > **安全约束**:`client.token` 只应发往 `baseUrl` 同源的接口。不要把它附加到
415
538
  > 第三方域名的请求上——那等于把用户的访问凭据交给别人。
416
539
 
540
+ ### 只读轮询退避
541
+
542
+ `new PollingBackoff(3000)` 为轮询维护独立退避状态,参数为正常间隔(大于 0、不超过 60 秒)。
543
+ 请求成功后调用 `reset()`,失败后调用 `failed(error)`;`waitMs()` 返回剩余等待毫秒数,
544
+ `0` 表示可以请求,`false` 表示停止。HTTP 错误应传入保留响应头的 `BladeApiError`。
545
+ 401/403 等确定性错误停止,网络/5xx 指数退避带抖动且最高 60 秒;`Retry-After`
546
+ 可以要求更长等待,超出浏览器定时器范围时停止。策略自身不发送请求,调度器须传递
547
+ AbortSignal、在卸载时停止,并避免将它用于自动重放 POST 等有副作用的操作。
548
+
417
549
  ## headless:一次性问答
418
550
 
419
551
  ```ts
@@ -456,6 +588,9 @@ groupMessagesByLoop(messages) // 按主/子智能体分组(智能体
456
588
  contentPreview(message.content, 80) // 截断预览
457
589
  ```
458
590
 
591
+ 错误消息在普通聊天界面展示前用 `chatErrorForDisplay(message)` 转成稳定的业务文案,
592
+ 避免把内部路径或传输诊断暴露给用户;仅开发者界面显式传入第二个参数 `true` 保留原文。
593
+
459
594
  一个完整的渲染示例:
460
595
 
461
596
  ```tsx
@@ -496,6 +631,38 @@ transformSlashCommand(skillId, prompt, { local: false, installed: false })
496
631
 
497
632
  不传第三个参数时按本地已有处理,和不带这个参数的老用法结果一致。
498
633
 
634
+ ### MCP App 卡片
635
+
636
+ MCP 工具可以通过 `_meta.ui` 在消息流里产出交互卡片(`tool_ui` block)。卡片的
637
+ 实例、守卫、可见性、身份和终态规则全部收敛在这一份共享判定里——内置 Web 与
638
+ SDK 渲染的是同一批卡片,不要自己再写一份判断:
639
+
640
+ ```ts
641
+ import {
642
+ collectInlineToolUiCards,
643
+ collectPreviewToolUiCards,
644
+ resolveToolUiCardContent,
645
+ buildToolUiCardKey,
646
+ isToolUiCard,
647
+ } from "@blade-hq/agent-client"
648
+
649
+ // 按可见性分类:inline 进消息流,preview 交给你的侧栏/面板(也随 toolPreview 事件推送)
650
+ const inlineCards = collectInlineToolUiCards(messages) // [{ key, toolCallId, card }]
651
+ const previewCards = collectPreviewToolUiCards(messages) // [{ key, toolCall, card, blocks }]
652
+
653
+ // 渲染前解析实际内容;archived 留档卡片只用留档 HTML,绝不回退 resourceUri
654
+ // (历史恢复/刷新不会因此重放一次 MCP 资源读取)
655
+ const resolved = resolveToolUiCardContent(card) // { type: "resource-html" | "resource-uri", content } | null
656
+
657
+ // 实例去重键:uri 卡片按内容、html 卡片按 toolCallId,与 toolPreview 事件、内置侧栏一致
658
+ const key = buildToolUiCardKey(toolCallId, resolved.type, resolved.content)
659
+ ```
660
+
661
+ 单个 block 判有效用 `isToolUiCard`(严格守卫:`target`/`height` 缺失、archived 无留档
662
+ HTML 一律判无效);`isInternalStatusToolUiCard` 识别内部「阶段进度」卡片(不对用户展示),
663
+ `isAppDevToolUiCard` 识别应用开发会话的预览卡。相关类型:`ToolUiCard`、
664
+ `ToolUiCardContentType`、`InlineToolUiCardEntry`、`PreviewToolUiCardEntry`。
665
+
499
666
  ## 常见问题
500
667
 
501
668
  | 现象 | 原因与解法 |
@@ -516,11 +683,18 @@ transformSlashCommand(skillId, prompt, { local: false, installed: false })
516
683
  - **SDK 身份**:`SDK_NAME`、`SDK_VERSION`
517
684
  - **声明式会话**:`SessionDefinition`、`SolutionDefinition`、`SkillDefinition`、`SessionConfig`、`TextFile`、`SessionSetupError`、`SessionSetupStage`
518
685
  - **模型目录**:`ModelsResource`、`ModelCatalog`、`ModelOption`
686
+ - **聊天项目资源(REST)**:`ChatProjectsResource`、`ChatProject`(含 `delete` 永久删除)
519
687
  - **会话资源(REST)**:`SessionsResource`、`CreateSessionRequest`、`ImportSessionOptions`、`AppCliDefinition`、`AppCliAttachment`、`AttachAppOptions`、`PaginatedSessionsResult`、`GlobalSearchResult`、`GlobalSearchResultItem`、`GlobalSearchConversationResult`、`GlobalSearchFileResult`、`SessionHistory`、`SessionContextStats`、`ResultFeedback`、`ResultFeedbackReason`、`ShareLinkResult`、`FileEntry`、`UploadFileEntry`、`UploadFilesOptions`、`SessionProfile`、`SessionDetail`、`SessionInfo`、`SessionStatus`、`SessionPortMapping`、`ModeId`、`TemplateId`、`PrimarySkillSnapshot`、`PrimarySkillParallelMode`
520
688
  - **会话回放**:`ReplayState`、`ReplaySpeed`、`ReplayPreview`、`ReplaySnapshot`、`toReplaySnapshot`、`DEFAULT_REPLAY_SPEED`
521
- - **会话状态机**:`SessionHub`、`SessionState`、`SendOptions`、`ConnectionStatus`、`AskUserAnswerData`、`AgentLoopInfo`、`ActiveCompactionState`、`createInitialSessionState`、`AgentSessionEventName`
689
+ - **会话状态机**:`SessionHub`、`SessionConnectOptions`、`SessionState`、`SendOptions`、`ConnectionStatus`、`AskUserAnswerData`、`AgentLoopInfo`、`ActiveCompactionState`、`createInitialSessionState`、`AgentSessionEventName`
522
690
  - **页面协作**:`EmbeddedChat`、`EmbeddedChatOptions`、`CommandHandler`、`CommandEnvelope`、`InboundAction`、`InboundEnvelope`、`isCommandEnvelope`、`isInboundEnvelope`
523
- - **消息与投影协议**:`MessageContent`、`MessageContentPart`、`TextContentPart`、`ImageUrlContentPart`、`FileContentPart`、`ToolCallInfo`、`ToolBridgeContent`、`CompactionInfo`、`MemoryRefInfo`、`ArchivedFileInfo`、`ArchivedToolCallInfo`、`TurnProjection`、`ContentBlock`、`PatchEnvelope`、`MemoryRef`、`PostChatFollowup`、`FinalArtifact`、`latestPostChatFollowup`、`buildMessageContent`、`normalizeMessageContent`、`isHiddenInternalMessage`、`transformSlashCommand`、`SkillMentionAvailability`、`extractTextAttachments`、`ParsedTextAttachment`、`ParsedTextContext`
691
+ - **消息与投影协议**:`MessageContent`、`MessageContentPart`、`TextContentPart`、`ImageUrlContentPart`、`FileContentPart`、`ToolCallInfo`、`ToolBridgeContent`、`CompactionInfo`、`ContextProjectionData`、`ContextProjectionFields`、`ContextDisplayState`、`ContextGroupDisplayState`、`ContextAction`、`ContextSourceInfo`、`MemoryRefInfo`、`ArchivedFileInfo`、`ArchivedToolCallInfo`、`TurnProjection`、`ContentBlock`、`PatchEnvelope`、`MemoryRef`、`PostChatFollowup`、`FinalArtifact`、`contextProjectionData`、`getContextDisplayState`、`getContextGroupDisplayState`、`groupAdjacentContextRuns`、`latestPostChatFollowup`、`buildMessageContent`、`normalizeMessageContent`、`isHiddenInternalMessage`、`transformSlashCommand`、`SkillMentionAvailability`、`extractTextAttachments`、`ParsedTextAttachment`、`ParsedTextContext`
692
+ - **MCP Apps 留档与卡片判定**:`McpAppData`、`isMcpAppData`、`McpAppContextState`、`McpAppContextUpdate`、`ToolUiCard`、`ToolUiCardContentType`、`InlineToolUiCardEntry`、`PreviewToolUiCardEntry`、`isToolUiCard`、`resolveToolUiCardContent`、`buildToolUiCardKey`、`isInternalStatusToolUiCard`、`isAppDevToolUiCard`、`collectInlineToolUiCards`、`collectPreviewToolUiCards`(`McpAppContextState` / `McpAppContextUpdate` 配合 `sessions.getMcpAppContext` / `sessions.updateMcpAppContext`:App 保存的状态在下一个新运行才进入模型上下文)
524
693
  - **Solution / 任务协议**:`Solution`、`SolutionAppField`、`SolutionAppState`、`SolutionAppUiConfig`、`SolutionRef`、`PublishedSolutionRef`、`ExistingSolutionRef`、`PreparedSolution`、`PreparedSolutionAsset`、`LayoutType`、`BizRole`、`TaskStatus`、`BackgroundTask`、`BackgroundTaskStopResult`
525
694
  - **Headless**:`HeadlessResource`、`RunOptions`、`RunResult`、`RunTrace`
526
- - **低层通道(apps/web 等高级集成)**:`createSocket`、`CreateSocketOptions`、`TypedSocket`、`AsrAudioPayload`、`ClientProjectionBuilder`、`RawEvent`、`acceptedPostChatFollowupCompletesLatestRun`
695
+ - **低层通道(apps/web 等高级集成)**:`createSocket`、`CreateSocketOptions`、`TypedSocket`、`AsrAudioPayload`、`AuthBusyReconnect`、`authBusyRetryDelayMs`、`ClientProjectionBuilder`、`RawEvent`、`acknowledgeTurnEvents`、`hasChatRunEvent`、`acceptedPostChatFollowupCompletesLatestRun`、`reconcileOptimisticUserTurns`、`reconcileHistoricalUserTurns`
696
+ ### MCP App 留档
697
+
698
+ `McpAppArchive` 是 `client.sessions.getMcpApp(sessionId, sourceId)` 经鉴权返回的归档,包含保存的 HTML 与最新留档输入/结果。`callMcpApp` 在会话 sandbox 内调用该卡片的归档能力;`onMcpAppChanged` 订阅结果变化,返回取消订阅函数。
699
+
700
+ 最新调用失败或完成状态未知时,归档同时提供 `previousToolInput` / `previousToolResult`,用于先恢复最后成功的界面再展示错误。读取这些留档不会重新执行工具。
package/dist/auth.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export interface AuthOptions {
2
2
  token?: string | (() => string | null | undefined);
3
3
  }
4
- export declare function buildAuthHeaders(options: AuthOptions): Record<string, string>;
5
4
  export declare function buildSocketAuth(options: AuthOptions): {
6
5
  token: string;
7
6
  } | undefined;
@@ -2,8 +2,10 @@ import { type LoginOptions, type LoginResult, type TokenStorageMode } from "./au
2
2
  import { type BladeFetchInit, type HttpMethod } from "./rest";
3
3
  import { AuthResource } from "./resources/auth";
4
4
  import { HeadlessResource } from "./resources/headless";
5
+ import { ComputersResource } from "./resources/computers";
5
6
  import { ModelsResource } from "./resources/models";
6
7
  import { SessionsResource } from "./resources/sessions";
8
+ import { ChatProjectsResource } from "./resources/chat-projects";
7
9
  import { SessionHub } from "./session/hub";
8
10
  import { type TypedSocket } from "./socket";
9
11
  export interface BladeClientOptions {
@@ -23,8 +25,6 @@ export interface BladeClientOptions {
23
25
  tokenStorage?: TokenStorageMode;
24
26
  fetchImpl?: typeof fetch;
25
27
  onRefreshSuccess?: () => void | Promise<void>;
26
- /** 是否订阅逐 token 增量,默认 true。关闭后仍接收完整消息和语义事件。 */
27
- streamTokens?: boolean;
28
28
  }
29
29
  export declare class BladeClient {
30
30
  private refreshPromise;
@@ -35,8 +35,10 @@ export declare class BladeClient {
35
35
  readonly options: BladeClientOptions;
36
36
  readonly auth: AuthResource;
37
37
  readonly headless: HeadlessResource;
38
+ readonly computers: ComputersResource;
38
39
  readonly models: ModelsResource;
39
40
  readonly sessions: SessionsResource;
41
+ readonly chatProjects: ChatProjectsResource;
40
42
  /** 实时会话中枢:client.sessions.connect() 内部使用,一般不直接访问。 */
41
43
  readonly hub: SessionHub;
42
44
  constructor(options: BladeClientOptions);
package/dist/index.d.ts CHANGED
@@ -1,15 +1,21 @@
1
1
  export { BladeClient } from "./blade-client";
2
2
  export type { BladeClientOptions, UploadProgress } from "./blade-client";
3
3
  export { BladeApiError } from "./rest";
4
+ export { PollingBackoff } from "./polling-backoff";
4
5
  export type { LoginOptions, LoginResult, TokenStorageMode } from "./auth-login";
6
+ export { EMPTY_PLATFORM_ENDPOINTS, loadPlatformEndpoints, resolveServiceUrl, } from "./platform-endpoints";
7
+ export type { LoadPlatformEndpointsOptions, PlatformEndpoints, PlatformServiceName, } from "./platform-endpoints";
5
8
  export { SDK_NAME, SDK_VERSION } from "./version";
6
9
  export { AgentSession } from "./session/agent-session";
7
10
  export type { AttachAppOptions, SendOptions } from "./session/agent-session";
8
11
  export { SessionHub } from "./session/hub";
12
+ export type { SessionConnectOptions } from "./session/hub";
9
13
  export type { AgentSessionEvents, AgentSessionEventName } from "./session/events";
14
+ export { isMcpAppData } from "./schemas/mcp-app";
15
+ export type { McpAppArchive, McpAppContextState, McpAppContextUpdate, McpAppData, } from "./schemas/mcp-app";
10
16
  export { SessionSetupError } from "./session/definition";
11
17
  export type { SessionConfig, SessionDefinition, SessionSetupStage, SkillDefinition, TextFile, SolutionDefinition, } from "./session/definition";
12
- export { createInitialSessionState, toReplaySnapshot } from "./session/state";
18
+ export { createInitialSessionState, reconcileHistoricalUserTurns, reconcileOptimisticUserTurns, toReplaySnapshot, } from "./session/state";
13
19
  export type { AskUserAnswerData, AgentLoopInfo, ActiveCompactionState, ConnectionStatus, ReplaySnapshot, SessionState, } from "./session/state";
14
20
  export { connectEmbedded } from "./commands/embedded";
15
21
  export type { EmbeddedChat, EmbeddedChatOptions } from "./commands/embedded";
@@ -18,15 +24,29 @@ export type { CommandEnvelope, InboundAction, InboundEnvelope } from "./commands
18
24
  export { isCommandEnvelope, isInboundEnvelope } from "./commands/protocol";
19
25
  export type { AuthResource, ExchangeCodeParams, ExchangeCodeResult, ProvidersResponse, UserInfo, } from "./resources/auth";
20
26
  export type { HeadlessResource } from "./resources/headless";
27
+ export { ComputersResource } from "./resources/computers";
28
+ export { canToggleComputer, computerDaemonVersion, computerOS, computerPlatformLabel, computerState, sortComputers, } from "./resources/computers";
29
+ export type { ComputerOS, ComputerState, SessionComputer, SessionComputerList, } from "./resources/computers";
21
30
  export { ModelsResource } from "./resources/models";
22
31
  export type { ModelCatalog, ModelOption } from "./resources/models";
23
32
  export type { SessionsResource } from "./resources/sessions";
24
- export type { CreateSessionRequest, AppCliAttachment, AppCliDefinition, FileEntry, ImportSessionOptions, PaginatedSessionsResult, GlobalSearchConversationResult, GlobalSearchFileResult, GlobalSearchResult, GlobalSearchResultItem, ResultFeedback, ResultFeedbackReason, SessionContextStats, SessionHistory, ShareLinkResult, UploadFileEntry, UploadFilesOptions, } from "./resources/sessions";
33
+ export type { SessionPlugin, SessionPluginActivation } from "./resources/sessions";
34
+ export type { SessionPluginConfigError, SessionPluginConfigSet, SessionPluginConfigState, SessionPluginConfigStateName, SessionPluginConfigSummary, SessionPluginConfigUpdate, } from "./resources/sessions";
35
+ export { ChatProjectsResource } from "./resources/chat-projects";
36
+ export type { ChatProject } from "./resources/chat-projects";
37
+ export { hasChatRunEvent } from "./shared/projection";
38
+ export type { CreateSessionRequest, AppCliAttachment, AppCliDefinition, FileEntry, ImportSessionOptions, PaginatedSessionsResult, GlobalSearchConversationResult, GlobalSearchFileResult, GlobalSearchResult, GlobalSearchResultItem, ResultFeedback, ResultFeedbackReason, HistoricalCommand, SessionContextStats, SessionHistory, SessionTurnsPage, ShareLinkResult, UploadFileEntry, UploadFilesOptions, } from "./resources/sessions";
25
39
  export type { ArchivedFileInfo, ArchivedToolCallInfo, ChatMessage, CompactionInfo, FileContentPart, ImageUrlContentPart, MemoryRefInfo, MessageContent, MessageContentPart, TextContentPart, ToolBridgeContent, ToolCallInfo, } from "./schemas/message";
26
- export { buildMessageContent, contentPreview, extractTextAttachments, getFileParts, getImageParts, getTextContent, groupMessagesByLoop, isHiddenInternalMessage, normalizeMessageContent, transformSlashCommand, } from "./schemas/message-utils";
40
+ export { buildMessageContent, chatErrorForDisplay, contentPreview, extractTextAttachments, getFileParts, getImageParts, getTextContent, groupMessagesByLoop, isHiddenInternalMessage, normalizeMessageContent, transformSlashCommand, } from "./schemas/message-utils";
41
+ export { contextProjectionData, getContextDisplayState, getContextGroupDisplayState, groupAdjacentContextRuns, } from "./schemas/context";
42
+ export type { ContextAction, ContextDisplayState, ContextGroupDisplayState, ContextProjectionData, ContextProjectionFields, ContextSourceInfo, } from "./schemas/context";
27
43
  export type { ParsedTextAttachment, ParsedTextContext, SkillMentionAvailability, } from "./schemas/message-utils";
28
44
  export type { ContentBlock, FinalArtifact, MemoryRef, PatchEnvelope, PostChatFollowup, TurnProjection, } from "./schemas/projection";
29
45
  export { latestPostChatFollowup } from "./schemas/projection-utils";
46
+ export { buildToolUiCardKey, collectInlineToolUiCards, collectPreviewToolUiCards, isAppDevToolUiCard, isInternalStatusToolUiCard, isToolUiCard, resolveToolUiCardContent, } from "./shared/tool-ui-card";
47
+ export type { InlineToolUiCardEntry, PreviewToolUiCardEntry, ToolUiCard, ToolUiCardContentType, } from "./shared/tool-ui-card";
48
+ export { prependOlder, replaceWindow } from "./session/history-page";
49
+ export type { LiveRevisionState } from "./session/history-page";
30
50
  export { DEFAULT_REPLAY_SPEED } from "./schemas/session";
31
51
  export { SessionInfo, SessionStatus } from "./schemas/session";
32
52
  export type { ModeId, PrimarySkillParallelMode, PrimarySkillSnapshot, ReplayPreview, ReplaySpeed, ReplayState, SessionDetail, SessionPortMapping, PublishedSolutionRef, TemplateId, } from "./schemas/session";
@@ -34,8 +54,9 @@ export { LayoutType } from "./schemas/solution";
34
54
  export type { BizRole, Solution, SolutionAppField, SolutionAppState, SolutionAppUiConfig, } from "./schemas/solution";
35
55
  export { Task, TaskStatus } from "./schemas/task";
36
56
  export type { BackgroundTask, BackgroundTaskStopResult } from "./schemas/background";
37
- export { acceptedPostChatFollowupCompletesLatestRun, ClientProjectionBuilder } from "./shared/projection";
57
+ export { acceptedPostChatFollowupCompletesLatestRun, acknowledgeTurnEvents, ClientProjectionBuilder, } from "./shared/projection";
38
58
  export type { RawEvent } from "./shared/projection";
59
+ export { AuthBusyReconnect, authBusyRetryDelayMs } from "./shared/auth-busy";
39
60
  export { createSocket } from "./socket";
40
61
  export type { CreateSocketOptions, TypedSocket } from "./socket";
41
62
  export type { AsrAudioPayload } from "./types/socket-events";