@blade-hq/agent-client 2612.0.0-beta.2 → 2612.0.0-beta.21

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 (92) hide show
  1. package/README.md +203 -19
  2. package/dist/blade-client.d.ts +13 -1
  3. package/dist/{chunk-PWJJJATA.js → chunk-J3XXTHHK.js} +1723 -701
  4. package/dist/chunk-J3XXTHHK.js.map +1 -0
  5. package/dist/index.d.ts +12 -3
  6. package/dist/index.js +9 -1
  7. package/dist/internal.d.ts +9 -3
  8. package/dist/internal.js +13 -1
  9. package/dist/internal.js.map +1 -1
  10. package/dist/resources/auth.d.ts +3 -1
  11. package/dist/resources/chat-groups.d.ts +92 -0
  12. package/dist/resources/headless.d.ts +5 -0
  13. package/dist/resources/models.d.ts +6 -1
  14. package/dist/resources/plugins.d.ts +1 -0
  15. package/dist/resources/sessions.d.ts +96 -11
  16. package/dist/schemas/context-attachments.d.ts +16 -0
  17. package/dist/schemas/event.d.ts +2 -0
  18. package/dist/schemas/message-utils.d.ts +3 -9
  19. package/dist/schemas/message.d.ts +18 -1
  20. package/dist/schemas/plugin-refs.d.ts +15 -0
  21. package/dist/schemas/projection.d.ts +31 -0
  22. package/dist/schemas/session.d.ts +2 -42
  23. package/dist/schemas/topic-assets.d.ts +7 -0
  24. package/dist/server-clock.d.ts +2 -0
  25. package/dist/session/agent-session.d.ts +51 -7
  26. package/dist/session/background.d.ts +14 -0
  27. package/dist/session/events.d.ts +0 -1
  28. package/dist/session/hub.d.ts +3 -0
  29. package/dist/session/log-cursor.d.ts +14 -0
  30. package/dist/session/state.d.ts +2 -1
  31. package/dist/session/workflow.d.ts +10 -3
  32. package/dist/shared/projection/builder.d.ts +5 -0
  33. package/dist/shared/projection/helpers.d.ts +2 -0
  34. package/dist/shared/projection/index.d.ts +1 -0
  35. package/dist/shared/projection/workflow.d.ts +24 -0
  36. package/dist/tool-provider.d.ts +51 -0
  37. package/dist/types/socket-events.d.ts +179 -6
  38. package/node_modules/engine.io-client/build/cjs/globals.node.d.ts +2 -3
  39. package/node_modules/engine.io-client/build/cjs/index.d.ts +3 -3
  40. package/node_modules/engine.io-client/build/cjs/index.js +1 -4
  41. package/node_modules/engine.io-client/build/cjs/socket.d.ts +39 -82
  42. package/node_modules/engine.io-client/build/cjs/socket.js +151 -218
  43. package/node_modules/engine.io-client/build/cjs/transport.d.ts +1 -1
  44. package/node_modules/engine.io-client/build/cjs/transports/polling-xhr.d.ts +4 -4
  45. package/node_modules/engine.io-client/build/cjs/transports/polling-xhr.js +2 -2
  46. package/node_modules/engine.io-client/build/cjs/transports/polling-xhr.node.js +17 -7
  47. package/node_modules/engine.io-client/build/cjs/transports/websocket.node.js +17 -7
  48. package/node_modules/engine.io-client/build/esm/globals.node.d.ts +2 -3
  49. package/node_modules/engine.io-client/build/esm/index.d.ts +3 -3
  50. package/node_modules/engine.io-client/build/esm/index.js +1 -2
  51. package/node_modules/engine.io-client/build/esm/socket.d.ts +39 -82
  52. package/node_modules/engine.io-client/build/esm/socket.js +141 -206
  53. package/node_modules/engine.io-client/build/esm/transport.d.ts +1 -1
  54. package/node_modules/engine.io-client/build/esm/transports/polling-xhr.d.ts +4 -4
  55. package/node_modules/engine.io-client/build/esm/transports/polling-xhr.js +2 -2
  56. package/node_modules/engine.io-client/build/esm-debug/globals.node.d.ts +2 -3
  57. package/node_modules/engine.io-client/build/esm-debug/index.d.ts +3 -3
  58. package/node_modules/engine.io-client/build/esm-debug/index.js +1 -2
  59. package/node_modules/engine.io-client/build/esm-debug/socket.d.ts +39 -82
  60. package/node_modules/engine.io-client/build/esm-debug/socket.js +150 -215
  61. package/node_modules/engine.io-client/build/esm-debug/transport.d.ts +1 -1
  62. package/node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.d.ts +4 -4
  63. package/node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.js +2 -2
  64. package/node_modules/engine.io-client/dist/engine.io.esm.min.js +3 -3
  65. package/node_modules/engine.io-client/dist/engine.io.esm.min.js.map +1 -1
  66. package/node_modules/engine.io-client/dist/engine.io.js +164 -239
  67. package/node_modules/engine.io-client/dist/engine.io.js.map +1 -1
  68. package/node_modules/engine.io-client/dist/engine.io.min.js +3 -3
  69. package/node_modules/engine.io-client/dist/engine.io.min.js.map +1 -1
  70. package/node_modules/engine.io-client/package.json +2 -2
  71. package/node_modules/socket.io-parser/build/cjs/binary.js +4 -1
  72. package/node_modules/socket.io-parser/build/cjs/index.d.ts +14 -4
  73. package/node_modules/socket.io-parser/build/cjs/index.js +18 -11
  74. package/node_modules/socket.io-parser/build/esm/binary.js +4 -1
  75. package/node_modules/socket.io-parser/build/esm/index.d.ts +14 -4
  76. package/node_modules/socket.io-parser/build/esm/index.js +14 -10
  77. package/node_modules/socket.io-parser/build/esm-debug/binary.js +4 -1
  78. package/node_modules/socket.io-parser/build/esm-debug/index.d.ts +14 -4
  79. package/node_modules/socket.io-parser/build/esm-debug/index.js +14 -10
  80. package/node_modules/socket.io-parser/package.json +1 -1
  81. package/node_modules/ws/index.js +15 -6
  82. package/node_modules/ws/lib/constants.js +1 -0
  83. package/node_modules/ws/lib/permessage-deflate.js +9 -7
  84. package/node_modules/ws/lib/receiver.js +37 -0
  85. package/node_modules/ws/lib/sender.js +6 -1
  86. package/node_modules/ws/lib/websocket-server.js +18 -6
  87. package/node_modules/ws/lib/websocket.js +50 -17
  88. package/node_modules/ws/package.json +8 -3
  89. package/node_modules/ws/wrapper.mjs +14 -1
  90. package/package.json +4 -4
  91. package/public-api.md +335 -28
  92. package/dist/chunk-PWJJJATA.js.map +0 -1
@@ -0,0 +1,16 @@
1
+ /** Frozen application data belonging to one message. The server does not interpret business types. */
2
+ export interface ContextAttachment {
3
+ id: string;
4
+ label: string;
5
+ content: string;
6
+ data?: Record<string, unknown> | null;
7
+ files?: Array<{
8
+ name: string;
9
+ session_id?: string;
10
+ path?: string;
11
+ }>;
12
+ }
13
+ /** Validate before persisting a reliable request. JSON cloning also rejects cycles. */
14
+ export declare function snapshotContextAttachments(value: ContextAttachment[]): ContextAttachment[];
15
+ /** Server-owned snapshots travel unchanged through stream and history projections. */
16
+ export declare function normalizeContextAttachments(value: unknown): ContextAttachment[];
@@ -1,3 +1,4 @@
1
+ import type { ToolEvidence } from "./projection";
1
2
  export interface ContentDelta {
2
3
  content: string;
3
4
  loop_name?: string;
@@ -21,6 +22,7 @@ export interface ToolCallArgumentsDelta {
21
22
  arguments_delta: string;
22
23
  }
23
24
  export interface ToolResultDone {
25
+ evidence?: ToolEvidence[];
24
26
  tool_call_id: string;
25
27
  loop_name?: string;
26
28
  function: {
@@ -24,21 +24,15 @@ export declare function buildMessageContent(text: string, attachments: Array<{
24
24
  mimeType?: string;
25
25
  }>): MessageContent;
26
26
  export declare function contentPreview(content: MessageContent, maxLen?: number): string;
27
- /** `/` 选中的技能当前处于什么状态,决定智能体要不要先装、先加载。 */
27
+ /** @deprecated 技能可用状态由运行时解析,发送身份请使用 SkillRef。 */
28
28
  export interface SkillMentionAvailability {
29
29
  /** 本地已有(内置 / 技能目录 / 会话已加载),直接可用。 */
30
30
  local?: boolean;
31
31
  /** Blade Hub 上该账号是否已安装。本地技能恒为 true。 */
32
32
  installed?: boolean;
33
33
  }
34
- /**
35
- * Transform a skill mention into a natural language skill invocation.
36
- * Strips the `<skill>name</skill>` tag from the raw input and prepends the instruction.
37
- *
38
- * Hub 技能装没装、加载没加载,用户不需要知道,但智能体需要——所以把状态翻译
39
- * 成它能直接照做的 CLI 步骤。不传 availability 时按本地技能处理,与旧行为一致。
40
- */
41
- export declare function transformSlashCommand(skillName: string, rawInput: string, { local, installed }?: SkillMentionAvailability): string;
34
+ /** Serialize a skill marker as user text. Send its identity separately in refs. */
35
+ export declare function transformSlashCommand(skillName: string, rawInput: string, _availability?: SkillMentionAvailability): string;
42
36
  export interface ParsedTextAttachment {
43
37
  name: string;
44
38
  uploadedPath?: string;
@@ -1,4 +1,4 @@
1
- import type { ContentBlock, PendingQuestionRef, ToolBridgeContent } from "./projection";
1
+ import type { ToolEvidence, ContentBlock, PendingQuestionRef, ToolBridgeContent } from "./projection";
2
2
  import type { ContextProjectionData } from "./context";
3
3
  export interface TextContentPart {
4
4
  type: "text";
@@ -20,7 +20,19 @@ export interface FileContentPart {
20
20
  }
21
21
  export type MessageContentPart = TextContentPart | ImageUrlContentPart | FileContentPart;
22
22
  export type MessageContent = string | MessageContentPart[];
23
+ /** 固定流程解释执行落史的一步(workflow:run 专用):刷新后时间线从这里重建。 */
24
+ export interface WorkflowStepInfo {
25
+ step_id: string;
26
+ desc?: string;
27
+ step_kind?: string;
28
+ status?: string;
29
+ output?: string;
30
+ /** 直播时的先后:步骤宣告与它的输出/失败行(条目按终态落盘,重建按这两个值排回去) */
31
+ seq?: number;
32
+ log_seq?: number;
33
+ }
23
34
  export interface ToolCallInfo {
35
+ evidence?: ToolEvidence[];
24
36
  id: string;
25
37
  name: string;
26
38
  display_name?: string | null;
@@ -29,6 +41,7 @@ export interface ToolCallInfo {
29
41
  status?: "pending" | "done" | "error" | "cancelled" | "awaiting_answer";
30
42
  duration_ms?: number | null;
31
43
  pending_question_ref?: PendingQuestionRef | null;
44
+ workflow_steps?: WorkflowStepInfo[] | null;
32
45
  }
33
46
  export type { ToolBridgeContent };
34
47
  /** Derive tool status from the result content string. */
@@ -74,6 +87,7 @@ export interface ChatMessage {
74
87
  duration_ms?: number;
75
88
  timestamp?: string;
76
89
  entry_id?: string;
90
+ client_request_id?: string;
77
91
  /** Stable React key retained when an optimistic user message is confirmed. */
78
92
  render_id?: string;
79
93
  parent_id?: string | null;
@@ -81,6 +95,9 @@ export interface ChatMessage {
81
95
  /** Entry kind from backend -- present for non-message entries like mode changes. */
82
96
  kind?: string;
83
97
  /** Memory references injected into this turn's context */
98
+ refs?: import("./plugin-refs").MessageRef[];
99
+ context_attachments?: import("./context-attachments").ContextAttachment[];
100
+ topic_asset_refs?: import("./topic-assets").TopicAssetRef[];
84
101
  memory_refs?: MemoryRefInfo[];
85
102
  /** Raw projection blocks for block-level UI rendering. */
86
103
  blocks?: ContentBlock[];
@@ -0,0 +1,15 @@
1
+ export interface PluginRef {
2
+ provider: "plugin";
3
+ plugin: string;
4
+ server: string;
5
+ id: string;
6
+ label: string;
7
+ }
8
+ export declare function normalizePluginRefs(value: unknown): PluginRef[];
9
+ export interface SkillRef {
10
+ provider: "skill";
11
+ id: string;
12
+ label: string;
13
+ }
14
+ export type MessageRef = PluginRef | SkillRef;
15
+ export declare function normalizeMessageRefs(value: unknown): MessageRef[];
@@ -25,7 +25,34 @@ export interface RunTiming {
25
25
  duration_ms?: number | null;
26
26
  status: "completed" | "failed" | "cancelled" | "paused" | "incomplete";
27
27
  }
28
+ /** 固定流程解释执行时落史的一步:刷新/重启后时间线的真相源。 */
29
+ export interface WorkflowStepProjection {
30
+ step_id: string;
31
+ desc?: string;
32
+ step_kind?: string;
33
+ status?: string;
34
+ output?: string;
35
+ /** 直播时的先后:步骤宣告与它的输出/失败行(条目按终态落盘,重建按这两个值排回去) */
36
+ seq?: number;
37
+ log_seq?: number;
38
+ }
39
+ export interface ToolEvidence {
40
+ n: number;
41
+ id: string;
42
+ title: string;
43
+ text: string;
44
+ url?: string;
45
+ plugin: string;
46
+ server: string;
47
+ source: string;
48
+ digest: string;
49
+ tool_call_id: string;
50
+ parent_tool_call_id?: string;
51
+ loop: string;
52
+ branch: string;
53
+ }
28
54
  export interface ToolCallProjection {
55
+ evidence?: ToolEvidence[];
29
56
  id: string;
30
57
  tool_name: string;
31
58
  display_name: string;
@@ -39,6 +66,7 @@ export interface ToolCallProjection {
39
66
  /** 该工具派生的子智能体运行区间,仅作外层展示。 */
40
67
  subagent_runs?: RunTiming[];
41
68
  pending_question_ref?: PendingQuestionRef | null;
69
+ workflow_steps?: WorkflowStepProjection[] | null;
42
70
  }
43
71
  export interface MemoryRef {
44
72
  id: number;
@@ -80,6 +108,9 @@ export interface TurnProjection {
80
108
  /** started_at 是否来自生产者上报(而非旧会话的落盘回落)。瀑布只承认前者。 */
81
109
  has_reported_timing?: boolean;
82
110
  context_window?: number;
111
+ refs?: import("./plugin-refs").MessageRef[] | null;
112
+ context_attachments?: import("./context-attachments").ContextAttachment[];
113
+ topic_asset_refs?: import("./topic-assets").TopicAssetRef[] | null;
83
114
  memory_refs?: MemoryRef[] | null;
84
115
  parent_fork_tool_call_id?: string | null;
85
116
  context_kind?: string | null;
@@ -1,8 +1,6 @@
1
1
  import type { Solution } from "./solution";
2
2
  export declare const SessionStatus: import("arktype/internal/variants/string.ts").StringType<"completed" | "created" | "failed" | "interrupted" | "running" | "waiting_for_input", {}>;
3
3
  export type SessionStatus = typeof SessionStatus.infer;
4
- export type TemplateId = "default" | "skill_editor" | "ship_attack";
5
- export type SkillEditorTemplateId = "skill_editor";
6
4
  export type ModeId = "planning" | "executing";
7
5
  export type PublishedSolutionRef = {
8
6
  source: "builtin";
@@ -60,12 +58,12 @@ export declare const SessionInfo: import("arktype/internal/variants/object.ts").
60
58
  created_at: string;
61
59
  updated_at: string;
62
60
  shared?: boolean | undefined;
61
+ anonymous?: boolean | undefined;
63
62
  memory_enabled?: boolean | undefined;
64
63
  is_persistent?: boolean | undefined;
65
64
  initiator?: "sdk" | "ui" | "unknown" | null | undefined;
66
65
  is_headless?: boolean | undefined;
67
66
  viewer_role?: "owner" | "viewer" | undefined;
68
- template_id?: string | null | undefined;
69
67
  model?: string | null | undefined;
70
68
  enable_thinking?: boolean | null | undefined;
71
69
  solution_id?: string | null | undefined;
@@ -73,8 +71,6 @@ export declare const SessionInfo: import("arktype/internal/variants/object.ts").
73
71
  biz_role_id?: string | null | undefined;
74
72
  solution?: unknown;
75
73
  plan_summary?: string | null | undefined;
76
- primary_skill_id?: string | null | undefined;
77
- bound_skill_id?: string | null | undefined;
78
74
  replay_state?: unknown;
79
75
  is_pinned?: boolean | undefined;
80
76
  pinned_at?: string | null | undefined;
@@ -90,21 +86,18 @@ export declare const SessionInfo: import("arktype/internal/variants/object.ts").
90
86
  chat_group_id?: string | null | undefined;
91
87
  match?: unknown;
92
88
  }, {}>;
93
- export type SessionInfo = Omit<typeof SessionInfo.infer, "template_id" | "solution" | "ports" | "match"> & {
89
+ export type SessionInfo = Omit<typeof SessionInfo.infer, "solution" | "ports" | "match"> & {
94
90
  shared?: boolean;
95
91
  memory_enabled?: boolean;
96
92
  is_persistent?: boolean;
97
93
  is_headless?: boolean;
98
94
  viewer_role?: "owner" | "viewer";
99
- template_id?: TemplateId | null;
100
95
  model?: string | null;
101
96
  enable_thinking?: boolean | null;
102
97
  solution_id?: string | null;
103
98
  solution_ref?: PublishedSolutionRef | null;
104
99
  biz_role_id?: string | null;
105
100
  solution?: Solution | null;
106
- primary_skill_id?: string | null;
107
- bound_skill_id?: string | null;
108
101
  replay_state?: ReplayState | null;
109
102
  is_pinned?: boolean;
110
103
  pinned_at?: string | null;
@@ -121,40 +114,7 @@ export type SessionInfo = Omit<typeof SessionInfo.infer, "template_id" | "soluti
121
114
  /** 仅在带 q 搜索的列表响应中出现;普通列表里此字段缺省。 */
122
115
  match?: SessionSearchMatch | null;
123
116
  };
124
- /**
125
- * 主 skill 配置快照(v2)。创建 session 时从 SKILL.md frontmatter 抽出并
126
- * 固化到 session_root/.blade/primary-skill.json;ship-attack 页面骨架的唯
127
- * 一数据源。
128
- */
129
- export interface PrimarySkillStepSpec {
130
- n: number;
131
- label: string;
132
- }
133
- export interface PrimarySkillStageSpec {
134
- id: string;
135
- name: string;
136
- steps: PrimarySkillStepSpec[];
137
- }
138
- export interface PrimarySkillParallelMode {
139
- id: string;
140
- name: string;
141
- prompt_hint: string;
142
- }
143
- export interface PrimarySkillSnapshot {
144
- version: number;
145
- skill_id: string;
146
- title: string;
147
- description: string;
148
- stages: PrimarySkillStageSpec[];
149
- parallel_modes: PrimarySkillParallelMode[];
150
- captured_at: string;
151
- }
152
- /**
153
- * 单 session detail(GET /api/sessions/:id)。列表接口返回 SessionInfo,
154
- * detail 在此基础上附加 primary_skill_snapshot。
155
- */
156
117
  export interface SessionDetail extends SessionInfo {
157
- primary_skill_snapshot?: PrimarySkillSnapshot | null;
158
118
  preview_url?: string | null;
159
119
  /**
160
120
  * 会话级环境变量(owner-only)。后端仅在 GET detail 和 PUT /env 响应中返回,
@@ -0,0 +1,7 @@
1
+ /** An explicit asset selection for one user message, never a persistent session choice. */
2
+ export interface TopicAssetRef {
3
+ topic_id: string;
4
+ path: string;
5
+ }
6
+ /** Read display identities only. The server rechecks access and resolves current metadata. */
7
+ export declare function normalizeTopicAssetRefs(value: unknown): TopicAssetRef[];
@@ -0,0 +1,2 @@
1
+ export declare function syncServerTime(client: object, timestamp: unknown, receivedAt?: number): void;
2
+ export declare function getServerTime(client: object | null, now?: number): number | null;
@@ -1,3 +1,5 @@
1
+ import { type ContextAttachment } from "../schemas/context-attachments";
2
+ import type { TopicAssetRef } from "../schemas/topic-assets";
1
3
  import { type RawEvent } from "../shared/projection";
2
4
  import type { MessageContent } from "../schemas/message";
3
5
  import type { PatchEnvelope, TurnProjection } from "../schemas/projection";
@@ -57,6 +59,7 @@ export interface AttachAppOptions {
57
59
  getContext: () => Record<string, unknown> | Promise<Record<string, unknown>>;
58
60
  }
59
61
  export interface SendOptions {
62
+ contextAttachments?: ContextAttachment[];
60
63
  /** planning / executing 模式。 */
61
64
  mode?: string;
62
65
  /** AskUserQuestion 的作答(tool_call_id + 选项)。 */
@@ -74,13 +77,37 @@ export interface SendOptions {
74
77
  };
75
78
  replayDecision?: "keep_replay" | "continue_replay";
76
79
  /** 用户显式选择的知识库 id;后端将元信息作为 once Context 提供给模型。 */
77
- kbIds?: number[];
80
+ /** Explicit topic assets for this message only. */
81
+ refs?: import("../schemas/plugin-refs").MessageRef[];
82
+ topicAssetRefs?: TopicAssetRef[];
78
83
  /**
79
84
  * 声明"会话在跑就把这条消息放进等待队列"。默认不排队、运行中直接报错:
80
85
  * 是否真的入队由服务端按运行状态判定(等待回答时发送即作答,不会被误排队)。
81
86
  */
82
87
  queueWhenRunning?: boolean;
83
88
  }
89
+ /** Durable text input with message-scoped application data. Persist this JSON value before calling sendPrepared. */
90
+ export interface PreparedSend {
91
+ sessionId: string;
92
+ requestId: string;
93
+ content: string;
94
+ options: PreparedSendOptions;
95
+ }
96
+ export interface PreparedSendOptions {
97
+ contextAttachments?: ContextAttachment[];
98
+ mode?: "planning" | "executing";
99
+ model?: string;
100
+ thinkingOverride?: boolean;
101
+ reasoningLevel?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
102
+ }
103
+ export interface DeliveryReceipt {
104
+ requestId: string;
105
+ status: "accepted" | "not_found" | "rejected" | "unknown";
106
+ itemId?: string;
107
+ queueStatus?: string;
108
+ executionId?: string | null;
109
+ message?: string;
110
+ }
84
111
  export declare function sessionStatusFromChatEnd(status: string | undefined): SessionStatus;
85
112
  /**
86
113
  * 一个会话的实时状态机:封装 Socket.IO 订阅、历史 + 流式合流、断线补数,
@@ -90,6 +117,7 @@ export declare function sessionStatusFromChatEnd(status: string | undefined): Se
90
117
  * 状态完全归属实例:同一页面创建多个 AgentSession 互不干扰。
91
118
  */
92
119
  export declare class AgentSession {
120
+ private readonly logCursor;
93
121
  readonly sessionId: string;
94
122
  private state;
95
123
  /** status 每变化一次加一(单调递增)。异步读取会话详情时据此判断请求期间状态是否变过,避免 running→终态→running 这类来回被误认为「没变」。 */
@@ -100,6 +128,7 @@ export declare class AgentSession {
100
128
  private readonly emitter;
101
129
  private readonly commands;
102
130
  private readonly runtime;
131
+ private activeReplayPlaybackId;
103
132
  private readonly projectionBuilder;
104
133
  private readonly pendingTurnPatches;
105
134
  private patchFlushHandle;
@@ -128,7 +157,10 @@ export declare class AgentSession {
128
157
  private bufferedCommandDeliveries;
129
158
  private pendingReplayMessage;
130
159
  private pendingReplayMode;
131
- private pendingReplayKbIds;
160
+ private pendingReplayRequestId;
161
+ private pendingReplayAttachments;
162
+ private pendingReplayRefs;
163
+ private pendingReplayTopicAssetRefs;
132
164
  private recentChatEndAt;
133
165
  /**
134
166
  * 最近一次已经通过 `error` 事件投递过的服务端失败(`message` + `code`)。
@@ -148,9 +180,14 @@ export declare class AgentSession {
148
180
  private disposed;
149
181
  private getAppContext;
150
182
  private sendPending;
151
- private manualCompactionPending;
183
+ private manualCompactionRequest;
184
+ /** Reload requests from retracts/epoch changes; done only when a reload started after the latest one succeeds. */
185
+ private epochReloadRequested;
186
+ private epochReloadDone;
187
+ private epochReloadRunning;
152
188
  /** 手动整理的在途标记,同时写进状态(界面据此保持「正在整理」,见 SessionState.compactionPending)。 */
153
- private setManualCompactionPending;
189
+ private setManualCompactionRequest;
190
+ private handleManualCompactionFinished;
154
191
  /** 最近一次还在等服务端结果的发送请求 id;排队中断的 chat:end 据此判断回滚是否过期。 */
155
192
  private pendingChatRequestId;
156
193
  /** 会话详情给出的运行时类型;"native" 时启用原生智能体的投影规则(见 _handleTurnEvents / _handleChatEnd)。 */
@@ -215,6 +252,7 @@ export declare class AgentSession {
215
252
  * chat:end 会让界面停在「运行中」)。
216
253
  */
217
254
  reloadHistory(): Promise<boolean>;
255
+ private reloadHistoryWindow;
218
256
  /**
219
257
  * 向服务端确认会话此刻是否在运行,校准流式状态(残留的「运行中」会被清掉)。只在已加入房间时
220
258
  * 生效;不带 resume,服务端不会重发上一轮的终态事件(否则会被当成一次新的结束)。
@@ -253,6 +291,12 @@ export declare class AgentSession {
253
291
  * CLI 安装成功后才保存 getContext;之后每次 send 前恰好读取一次。
254
292
  */
255
293
  attachApp(options: AttachAppOptions): Promise<AppCliAttachment | null>;
294
+ /** Prepare a durable text input without sending any network request. */
295
+ prepareSend(content: string, options?: PreparedSendOptions): PreparedSend;
296
+ /** Durably enqueue an ordinary text input. Retries must reuse the saved request. */
297
+ sendPrepared(request: PreparedSend): Promise<DeliveryReceipt>;
298
+ /** Owner-authorized lookup; receipts remain until the session is deleted. */
299
+ getDelivery(requestId: string): Promise<DeliveryReceipt>;
256
300
  /** 发送一条消息。字符串或多模态内容均可。 */
257
301
  send(content: MessageContent, options?: SendOptions): Promise<boolean>;
258
302
  /**
@@ -348,8 +392,9 @@ export declare class AgentSession {
348
392
  _handleTurnPatch(patch: PatchEnvelope): void;
349
393
  /** @internal */
350
394
  _handleTurnEnd(turn: TurnProjection): void;
395
+ private runEpochReload;
351
396
  /** @internal 历史回放通道(event_format: raw)。 */
352
- _handleTurnEvents(events: RawEvent[], replayed?: boolean): void;
397
+ _handleTurnEvents(incoming: RawEvent[], replayed?: boolean): void;
353
398
  /** @internal */
354
399
  _handleChatStart(): void;
355
400
  /**
@@ -370,7 +415,6 @@ export declare class AgentSession {
370
415
  intent?: string;
371
416
  status?: SessionStatus;
372
417
  model?: string | null;
373
- bound_skill_id?: string | null;
374
418
  replay_state?: Record<string, unknown> | null;
375
419
  }): void;
376
420
  /** @internal */
@@ -385,7 +429,7 @@ export declare class AgentSession {
385
429
  /** @internal */
386
430
  _handleBackgroundTask(task: AgentSessionEvents["backgroundTask"]): void;
387
431
  /** @internal */
388
- _handleArtifact(event: AgentSessionEvents["artifact"]): void;
432
+ _handleArtifact(data: Record<string, unknown>, kind: "created" | "updated", replayed?: boolean): void;
389
433
  /** @internal 加入房间的应答里带 is_running,据此校准流式状态。 */
390
434
  _applyRunningState(isRunning: boolean, liveRevisionAtJoin?: number): void;
391
435
  private markRunningIfIdle;
@@ -0,0 +1,14 @@
1
+ import type { AgentSessionEvents } from "./events";
2
+ export type BackgroundTaskEvent = {
3
+ id?: string;
4
+ task_id?: string;
5
+ command?: string;
6
+ description?: string;
7
+ status?: string;
8
+ failure_reason?: string | null;
9
+ exit_code?: number | null;
10
+ elapsed_seconds?: number;
11
+ output_lines_count?: number;
12
+ output_preview?: string[];
13
+ };
14
+ export declare function completedBackgroundTask(task: BackgroundTaskEvent): AgentSessionEvents["backgroundTask"] | null;
@@ -137,7 +137,6 @@ export interface AgentSessionEvents {
137
137
  intent?: string;
138
138
  status?: SessionStatus;
139
139
  model?: string | null;
140
- boundSkillId?: string | null;
141
140
  replayState?: Record<string, unknown> | null;
142
141
  };
143
142
  /** 回放输入不匹配,需要决定保持回放还是转自主模式。 */
@@ -71,6 +71,8 @@ export declare class SessionHub {
71
71
  private streamTokens;
72
72
  /** 状态订阅(mode: "status")的持有计数。 */
73
73
  private readonly statusWatchCounts;
74
+ private readonly statusLogCursors;
75
+ private readonly replayPlaybackIds;
74
76
  /** 启动连接门控:扣住期间只登记「需要连接」,放开后连一次。 */
75
77
  private connectionHeld;
76
78
  private connectDeferred;
@@ -143,6 +145,7 @@ export declare class SessionHub {
143
145
  * 归零才退订房间并从路由表移除。
144
146
  */
145
147
  private release;
148
+ private statusCursor;
146
149
  private emitStatusSubscribe;
147
150
  /** 不管还有几方持有都立即释放(启动失败、切换身份)。 */
148
151
  private forceRelease;
@@ -0,0 +1,14 @@
1
+ import type { RawEvent } from "../shared/projection";
2
+ /** Shared by full and status subscriptions. UI sequence and run_id are unrelated. */
3
+ export declare class LogCursor {
4
+ private sequence;
5
+ private epoch;
6
+ private readonly deltas;
7
+ subscription(): {
8
+ after_log_seq?: number;
9
+ };
10
+ consume(events: RawEvent[]): {
11
+ events: RawEvent[];
12
+ reload: boolean;
13
+ };
14
+ }
@@ -1,3 +1,4 @@
1
+ import type { TopicAssetRef } from "../schemas/topic-assets";
1
2
  import type { ChatMessage, CompactionInfo, MessageContent } from "../schemas/message";
2
3
  import type { ContentBlock, PatchEnvelope, TurnProjection } from "../schemas/projection";
3
4
  import type { ReplaySpeed, ReplayState, SessionStatus } from "../schemas/session";
@@ -106,7 +107,7 @@ export declare function withTurns(state: SessionState, turns: TurnProjection[]):
106
107
  * 直接返回原 state——引用不变,订阅者不会收到多余通知。
107
108
  */
108
109
  export declare function withQueue(state: SessionState, snapshot: SessionQueueSnapshot): SessionState;
109
- export declare function addUserMessage(state: SessionState, content: MessageContent, clientRequestId?: string): SessionState;
110
+ export declare function addUserMessage(state: SessionState, content: MessageContent, clientRequestId?: string, topicAssetRefs?: TopicAssetRef[], refs?: import("../schemas/plugin-refs").MessageRef[], contextAttachments?: import("../schemas/context-attachments").ContextAttachment[]): SessionState;
110
111
  export declare function upsertTurn(state: SessionState, turn: TurnProjection): SessionState;
111
112
  export declare function applyTurnPatch(state: SessionState, patch: PatchEnvelope): SessionState;
112
113
  export declare function addErrorMessage(state: SessionState, content: string): SessionState;
@@ -8,14 +8,20 @@ import type { TurnProjection } from "../schemas/projection";
8
8
  * - 工具调用结束后:一律用工具结果里留存的 `[workflow] …` 行重建(落盘,历史也只有这一份)。
9
9
  * 这样实时、历史、重连、回放在运行结束后得到同一份时间线。
10
10
  */
11
- export type WorkflowRunEntry = {
11
+ export type WorkflowRunEntry =
12
+ /** status:步骤终态(done / error / cancelled);落史与直播的终态更新都会带上。 */
13
+ {
12
14
  kind: "step";
13
15
  stepId: string;
14
16
  desc: string;
15
17
  stepKind: string;
16
- } | {
18
+ status?: string;
19
+ }
20
+ /** stepId:这行属于哪一步。并行分支的输出不按宣告顺序到达,不能按位置归到上一步。 */
21
+ | {
17
22
  kind: "log";
18
23
  text: string;
24
+ stepId?: string;
19
25
  };
20
26
  export interface WorkflowRunState {
21
27
  /** 触发它的 workflow:run 工具调用 id。 */
@@ -35,7 +41,8 @@ export declare function isWorkflowRunToolName(name: string): boolean;
35
41
  * 非前缀行(最终输出 / traceback)不参与,由界面在外层展示。
36
42
  */
37
43
  export declare function workflowEntriesFromOutput(output: string): WorkflowRunEntry[];
38
- /** 工作流名只从工具参数取:历史没有实时事件,两条路径都用这一个来源。 */
44
+ /** 运行的标题只从工具参数取:历史没有实时事件,两条路径都用这一个来源。
45
+ * 与 host 起跑时发的 label 同款:「技能「org/x」」,非 main 流程再带「 · 流程 x」。 */
39
46
  export declare function workflowNameFromArguments(argumentsJson: string): string;
40
47
  export declare function isWorkflowEvent(type: string): boolean;
41
48
  /**
@@ -1,5 +1,8 @@
1
1
  import type { TurnProjection } from "../../schemas/projection";
2
2
  export interface RawEvent {
3
+ log_seq?: number;
4
+ step_log_seq?: number;
5
+ delta_seq?: number;
3
6
  type: string;
4
7
  payload: Record<string, unknown>;
5
8
  }
@@ -45,6 +48,8 @@ export declare class ClientProjectionBuilder {
45
48
  processBatch(events: RawEvent[]): ProjectionUpdate[];
46
49
  processEvent(event: RawEvent): ProjectionUpdate[] | null;
47
50
  reset(): void;
51
+ /** A durable snapshot supersedes only this turn's temporary overlay. */
52
+ acceptDurableTurn(turn: TurnProjection): void;
48
53
  seedSequence(maxSeq: number): void;
49
54
  _seedTurns(turns: TurnProjection[]): void;
50
55
  private onMemoryInject;
@@ -54,3 +54,5 @@ export declare function normalizeChildPause(pausePayload: Record<string, unknown
54
54
  childToolCallId: string;
55
55
  description: string;
56
56
  };
57
+ /** Copy only the trusted protocol field, never evidence embedded in output. */
58
+ export declare function attachToolEvidence(call: ToolCallProjection | undefined, evidence: unknown): void;
@@ -1,4 +1,5 @@
1
1
  export { acceptedPostChatFollowupCompletesLatestRun, acknowledgeTurnEvents, ClientProjectionBuilder, hasChatRunEvent, type RawEvent, type ProjectionUpdate, } from "./builder";
2
2
  export { type TurnState, createTurnState, snapshot, PAUSE_TOOL_NAMES } from "./state";
3
3
  export { projectHistory, type RawHistoryEntry } from "./history";
4
+ export { workflowEntriesFromSteps, workflowRunCancelled, type WorkflowTimelineEntry, } from "./workflow";
4
5
  export { buildContextTurn } from "./context";
@@ -0,0 +1,24 @@
1
+ import type { WorkflowStepProjection } from "../../schemas/projection";
2
+ /** 固定流程时间线的一条事件:step 开一张步骤卡,log 归并进上一张卡。
3
+ * 形状与 session/workflow.ts 的 WorkflowRunEntry 一致(结构化兼容,直接互喂)。 */
4
+ export type WorkflowTimelineEntry = {
5
+ kind: "step";
6
+ stepId: string;
7
+ desc: string;
8
+ stepKind: string;
9
+ status?: string;
10
+ } | {
11
+ kind: "log";
12
+ text: string;
13
+ stepId?: string;
14
+ };
15
+ /** 解释执行落史的结构化步骤 → 时间线事件流:与 host live 事件逐行同文案、同顺序。
16
+ * 命令步骤的「└ 输出」行从同一 4KiB 截断串推导(含 …(共N字) 记号),叶子步骤的
17
+ * 「失败:」行还原 error 条目里存的失败说明(容器步骤的 error 条目不带说明)。
18
+ * 条目按终态落盘(容器晚于子步骤、并行分支按完成先后),带 seq / log_seq 时按它们
19
+ * 排回直播时的顺序;旧记录没有序号就按落盘顺序。流式与刷新重建必须渲染出相同结果。 */
20
+ export declare function workflowEntriesFromSteps(steps: readonly WorkflowStepProjection[]): WorkflowTimelineEntry[];
21
+ /** 取消的运行在工具层留档是通用错误串(status=error),真相在步骤条目里:有步骤标记
22
+ * cancelled 且没有步骤失败,整次运行按「已取消」呈现。并行分支失败时兄弟分支也会被
23
+ * 取消,那是失败不是取消。 */
24
+ export declare function workflowRunCancelled(steps: readonly WorkflowStepProjection[]): boolean;
@@ -0,0 +1,51 @@
1
+ import type { BladeClient } from "./blade-client";
2
+ export interface ProviderTool {
3
+ name: string;
4
+ description?: string;
5
+ inputSchema: Record<string, unknown>;
6
+ handler: (arguments_: Record<string, unknown>, context: {
7
+ sessionId: string;
8
+ signal: AbortSignal;
9
+ }) => Promise<ProviderToolResult>;
10
+ }
11
+ export interface ProviderToolResult {
12
+ content: Array<{
13
+ type: "text";
14
+ text: string;
15
+ }>;
16
+ structuredContent?: Record<string, unknown>;
17
+ isError?: boolean;
18
+ }
19
+ export interface ToolProviderOptions {
20
+ /** Stable application-owned ID, preserved across reconnects. */
21
+ providerId: string;
22
+ /** Secret bound to the session's mcp_sources bearer_token. */
23
+ capability: string;
24
+ tools: ProviderTool[];
25
+ onError?: (error: Error) => void;
26
+ }
27
+ /** Backend-only outbound connection. Reconnects registrations, never tool calls. */
28
+ export declare class ToolProvider {
29
+ private client;
30
+ private options;
31
+ private onDispose;
32
+ readonly url: string;
33
+ private socket?;
34
+ private timer?;
35
+ private registrationTimer?;
36
+ private disposed;
37
+ private registered;
38
+ private attempts;
39
+ private calls;
40
+ private waiters;
41
+ constructor(client: BladeClient, options: ToolProviderOptions, onDispose: () => void);
42
+ /** Resolves only after BA has authenticated and registered this connection. */
43
+ ready(): Promise<void>;
44
+ reconnect(): void;
45
+ private reset;
46
+ private fail;
47
+ private open;
48
+ private schedule;
49
+ private receive;
50
+ dispose(): void;
51
+ }