@downcity/agent 1.1.188 → 1.1.195

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 (78) hide show
  1. package/bin/executor/Executor.d.ts +4 -0
  2. package/bin/executor/Executor.d.ts.map +1 -1
  3. package/bin/executor/Executor.js +40 -1
  4. package/bin/executor/Executor.js.map +1 -1
  5. package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts +9 -0
  6. package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts.map +1 -1
  7. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.d.ts.map +1 -1
  8. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js +1 -0
  9. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js.map +1 -1
  10. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts +2 -0
  11. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts.map +1 -1
  12. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js +49 -5
  13. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js.map +1 -1
  14. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.d.ts +1 -1
  15. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.d.ts.map +1 -1
  16. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.js +2 -0
  17. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.js.map +1 -1
  18. package/bin/executor/messages/SessionMessageCodec.d.ts +1 -1
  19. package/bin/executor/messages/SessionMessageCodec.d.ts.map +1 -1
  20. package/bin/executor/messages/SessionMessageCodec.js +6 -1
  21. package/bin/executor/messages/SessionMessageCodec.js.map +1 -1
  22. package/bin/executor/store/history/SessionHistoryStore.d.ts +22 -0
  23. package/bin/executor/store/history/SessionHistoryStore.d.ts.map +1 -1
  24. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts +7 -0
  25. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts.map +1 -1
  26. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js +53 -0
  27. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js.map +1 -1
  28. package/bin/executor/types/SessionMessages.d.ts +15 -2
  29. package/bin/executor/types/SessionMessages.d.ts.map +1 -1
  30. package/bin/executor/types/SessionMessages.js +9 -1
  31. package/bin/executor/types/SessionMessages.js.map +1 -1
  32. package/bin/index.d.ts +1 -0
  33. package/bin/index.d.ts.map +1 -1
  34. package/bin/index.js.map +1 -1
  35. package/bin/session/browse/Browse.d.ts.map +1 -1
  36. package/bin/session/browse/Browse.js +22 -0
  37. package/bin/session/browse/Browse.js.map +1 -1
  38. package/bin/session/services/SessionStateService.d.ts +21 -1
  39. package/bin/session/services/SessionStateService.d.ts.map +1 -1
  40. package/bin/session/services/SessionStateService.js +101 -11
  41. package/bin/session/services/SessionStateService.js.map +1 -1
  42. package/bin/session/services/SessionTurnService.d.ts.map +1 -1
  43. package/bin/session/services/SessionTurnService.js +9 -0
  44. package/bin/session/services/SessionTurnService.js.map +1 -1
  45. package/bin/session/services/SessionViewService.d.ts.map +1 -1
  46. package/bin/session/services/SessionViewService.js +42 -8
  47. package/bin/session/services/SessionViewService.js.map +1 -1
  48. package/bin/types/agent/SessionTypes.d.ts +22 -1
  49. package/bin/types/agent/SessionTypes.d.ts.map +1 -1
  50. package/bin/types/executor/SessionRunContext.d.ts +10 -0
  51. package/bin/types/executor/SessionRunContext.d.ts.map +1 -1
  52. package/bin/types/sdk/AgentSessionEvent.d.ts +2 -1
  53. package/bin/types/sdk/AgentSessionEvent.d.ts.map +1 -1
  54. package/bin/types/sdk/AgentSessionOperation.d.ts +99 -0
  55. package/bin/types/sdk/AgentSessionOperation.d.ts.map +1 -0
  56. package/bin/types/sdk/AgentSessionOperation.js +10 -0
  57. package/bin/types/sdk/AgentSessionOperation.js.map +1 -0
  58. package/package.json +3 -3
  59. package/scripts/session-operation-message.test.mjs +182 -0
  60. package/src/executor/Executor.ts +49 -1
  61. package/src/executor/composer/compaction/SessionCompactionComposer.ts +10 -0
  62. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.ts +1 -0
  63. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.ts +64 -5
  64. package/src/executor/composer/history/jsonl/JsonlSessionHistoryComposer.ts +5 -1
  65. package/src/executor/messages/SessionMessageCodec.ts +11 -2
  66. package/src/executor/store/history/SessionHistoryStore.ts +27 -0
  67. package/src/executor/store/history/jsonl/JsonlSessionHistoryStore.ts +66 -0
  68. package/src/executor/types/SessionMessages.ts +26 -2
  69. package/src/index.ts +7 -0
  70. package/src/session/browse/Browse.ts +24 -0
  71. package/src/session/services/SessionStateService.ts +125 -11
  72. package/src/session/services/SessionTurnService.ts +8 -0
  73. package/src/session/services/SessionViewService.ts +47 -10
  74. package/src/types/agent/SessionTypes.ts +22 -1
  75. package/src/types/executor/SessionRunContext.ts +20 -0
  76. package/src/types/sdk/AgentSessionEvent.ts +2 -0
  77. package/src/types/sdk/AgentSessionOperation.ts +125 -0
  78. package/tsconfig.tsbuildinfo +1 -1
package/src/index.ts CHANGED
@@ -55,6 +55,13 @@ export type {
55
55
  AgentSessionSubscriber,
56
56
  AgentSessionUnsubscribe,
57
57
  } from "./types/sdk/AgentSessionEvent.js";
58
+ export type {
59
+ AgentSessionOperationCallback,
60
+ AgentSessionOperationEvent,
61
+ AgentSessionOperationName,
62
+ AgentSessionOperationRecord,
63
+ AgentSessionOperationStatus,
64
+ } from "./types/sdk/AgentSessionOperation.js";
58
65
  export type { AgentSessionPromptInput, SessionUserMessagePart } from "./types/sdk/AgentSessionPrompt.js";
59
66
  export type { AgentSessionStopResult } from "./types/sdk/AgentSessionStop.js";
60
67
  export type {
@@ -29,6 +29,7 @@ import type {
29
29
  SessionMessageV1,
30
30
  SessionMetadataV1,
31
31
  } from "@/executor/types/SessionMessages.js";
32
+ import { isSessionOperationMessage } from "@/executor/types/SessionMessages.js";
32
33
  import type { SessionHistoryMetaV1 } from "@/executor/types/SessionHistoryMeta.js";
33
34
  import { pickLastSuccessfulChatSendText } from "@/executor/messages/UserVisibleText.js";
34
35
  import { getSdkAgentSessionMessagesPath } from "@/session/storage/Paths.js";
@@ -240,6 +241,15 @@ function toTimelineEvent(params: {
240
241
  ...(typeof metadata?.source === "string" ? { source: metadata.source } : {}),
241
242
  text: params.text,
242
243
  ...(params.toolName ? { toolName: params.toolName } : {}),
244
+ ...(params.role === "operation" && metadata?.operation?.operationId
245
+ ? { operationId: metadata.operation.operationId }
246
+ : {}),
247
+ ...(params.role === "operation" && metadata?.operation?.name
248
+ ? { operationName: metadata.operation.name }
249
+ : {}),
250
+ ...(params.role === "operation" && metadata?.operation?.status
251
+ ? { operationStatus: metadata.operation.status }
252
+ : {}),
243
253
  };
244
254
  }
245
255
 
@@ -249,6 +259,20 @@ function toTimelineEvent(params: {
249
259
  export function toSessionTimelineEvents(
250
260
  message: SessionMessageV1,
251
261
  ): AgentSessionTimelineEvent[] {
262
+ if (isSessionOperationMessage(message)) {
263
+ const metadata = (message.metadata || null) as SessionMetadataV1 | null;
264
+ return [
265
+ toTimelineEvent({
266
+ message,
267
+ role: "operation",
268
+ text:
269
+ String(metadata?.operation?.label || "").trim() ||
270
+ resolveSessionMessagePreview(message),
271
+ sequence: 0,
272
+ }),
273
+ ];
274
+ }
275
+
252
276
  if (message.role !== "assistant") {
253
277
  return [
254
278
  toTimelineEvent({
@@ -30,6 +30,10 @@ import type {
30
30
  import type {
31
31
  AgentSessionEvent,
32
32
  } from "@/types/sdk/AgentSessionEvent.js";
33
+ import type {
34
+ AgentSessionOperationEvent,
35
+ AgentSessionOperationRecord,
36
+ } from "@/types/sdk/AgentSessionOperation.js";
33
37
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
34
38
  import type {
35
39
  SessionMessageV1,
@@ -80,6 +84,20 @@ type SessionStateServiceOptions = {
80
84
  publish_event: (event: AgentSessionEvent) => void;
81
85
  };
82
86
 
87
+ type SessionSetOptions = {
88
+ /**
89
+ * 是否写入并发布 model-switching operation。
90
+ *
91
+ * 说明(中文)
92
+ * - 公开 `session.set()` 应保持默认开启。
93
+ * - fork 内部复制模型配置时关闭,避免污染 forked session 历史。
94
+ */
95
+ emit_operation?: boolean;
96
+ };
97
+
98
+ type EmitOperationInput = Omit<AgentSessionOperationRecord, "operationId"> &
99
+ Partial<Pick<AgentSessionOperationRecord, "operationId">>;
100
+
83
101
  /**
84
102
  * 本地 Session 状态与持久化服务。
85
103
  */
@@ -203,18 +221,66 @@ export class SessionStateService {
203
221
  /**
204
222
  * 写入当前 session 配置。
205
223
  */
206
- async set(input: AgentSessionSetInput): Promise<void> {
207
- if (input.model) {
208
- this.state.sessionConfig.model = normalizeAgentModel(input.model);
209
- this.state.sessionConfig.modelLabel = inferAgentModelLabel(input.model);
210
- this.executor.clearExecutor();
224
+ async set(input: AgentSessionSetInput, options?: SessionSetOptions): Promise<void> {
225
+ const should_emit_operation = options?.emit_operation !== false;
226
+ const previous_model_label = this.state.sessionConfig.modelLabel;
227
+ const next_model_label = input.model
228
+ ? inferAgentModelLabel(input.model)
229
+ : undefined;
230
+ const operation_id = `model-switching:${this.session_id}:${Date.now()}:${generateId()}`;
231
+
232
+ if (input.model && should_emit_operation) {
233
+ await this.emit_operation_event({
234
+ operationId: operation_id,
235
+ name: "model-switching",
236
+ status: "started",
237
+ label: "Switching session model",
238
+ result: {
239
+ ...(previous_model_label ? { previousModelLabel: previous_model_label } : {}),
240
+ ...(next_model_label ? { modelLabel: next_model_label } : {}),
241
+ },
242
+ });
243
+ }
244
+
245
+ try {
246
+ if (input.model) {
247
+ this.state.sessionConfig.model = normalizeAgentModel(input.model);
248
+ this.state.sessionConfig.modelLabel = next_model_label;
249
+ this.executor.clearExecutor();
250
+ }
251
+ await patchSessionModelLabel({
252
+ projectRoot: this.project_root,
253
+ agentId: this.agent_id,
254
+ sessionId: this.session_id,
255
+ model: this.state.sessionConfig.model,
256
+ });
257
+ } catch (error) {
258
+ if (input.model && should_emit_operation) {
259
+ await this.emit_operation_event({
260
+ operationId: operation_id,
261
+ name: "model-switching",
262
+ status: "failed",
263
+ label: "Session model switch failed",
264
+ error: error instanceof Error ? error.message : String(error),
265
+ });
266
+ }
267
+ throw error;
268
+ }
269
+
270
+ if (input.model && should_emit_operation) {
271
+ await this.emit_operation_event({
272
+ operationId: operation_id,
273
+ name: "model-switching",
274
+ status: "finished",
275
+ label: "Session model switched",
276
+ result: {
277
+ ...(previous_model_label ? { previousModelLabel: previous_model_label } : {}),
278
+ ...(this.state.sessionConfig.modelLabel
279
+ ? { modelLabel: this.state.sessionConfig.modelLabel }
280
+ : {}),
281
+ },
282
+ });
211
283
  }
212
- await patchSessionModelLabel({
213
- projectRoot: this.project_root,
214
- agentId: this.agent_id,
215
- sessionId: this.session_id,
216
- model: this.state.sessionConfig.model,
217
- });
218
284
  }
219
285
 
220
286
  /**
@@ -301,6 +367,54 @@ export class SessionStateService {
301
367
  });
302
368
  }
303
369
 
370
+ /**
371
+ * 持久化一条 operation message。
372
+ */
373
+ async persist_operation_event(
374
+ event: AgentSessionOperationEvent,
375
+ ): Promise<void> {
376
+ const message = this.history_store.operation({
377
+ operation: {
378
+ operationId: event.operationId,
379
+ name: event.name,
380
+ status: event.status,
381
+ ...(event.turnId ? { turnId: event.turnId } : {}),
382
+ ...(event.label ? { label: event.label } : {}),
383
+ ...(event.reason ? { reason: event.reason } : {}),
384
+ ...(typeof event.progress === "number" ? { progress: event.progress } : {}),
385
+ ...(event.result !== undefined ? { result: event.result } : {}),
386
+ ...(event.error ? { error: event.error } : {}),
387
+ ...(event.visible === false ? { visible: false } : {}),
388
+ },
389
+ metadata: {
390
+ sessionId: this.session_id,
391
+ },
392
+ });
393
+ await this.history_store.append(message);
394
+ await this.touch_metadata();
395
+ }
396
+
397
+ /**
398
+ * 写入并发布一条 operation。
399
+ */
400
+ async emit_operation_event(input: EmitOperationInput): Promise<void> {
401
+ const operation_id =
402
+ String(input.operationId || "").trim() ||
403
+ `${input.name}:${this.session_id}:${Date.now()}:${generateId()}`;
404
+ const event: AgentSessionOperationEvent = {
405
+ type: "operation",
406
+ sessionId: this.session_id,
407
+ ...input,
408
+ operationId: operation_id,
409
+ };
410
+ try {
411
+ await this.persist_operation_event(event);
412
+ } catch {
413
+ // operation 持久化失败不应阻断宿主操作。
414
+ }
415
+ this.publish_event(event);
416
+ }
417
+
304
418
  /**
305
419
  * 构造并持久化一条 prompt user 消息。
306
420
  */
@@ -198,6 +198,14 @@ export class SessionTurnService {
198
198
  this.publish_event(session_event);
199
199
  }
200
200
  },
201
+ onOperationCallback: async (event) => {
202
+ try {
203
+ await this.state_service.persist_operation_event(event);
204
+ } catch {
205
+ // operation 持久化失败不应阻断当前 turn。
206
+ }
207
+ this.publish_event(event);
208
+ },
201
209
  injectedUserMessages: [],
202
210
  deferredPersistedUserMessages: [],
203
211
  pendingAssistantFileParts: [],
@@ -278,19 +278,56 @@ export class SessionViewService<TSession extends Pick<AgentSession, "set">> {
278
278
  !message_id
279
279
  ? messages
280
280
  : this.resolve_fork_messages(messages, message_id);
281
+ const operation_id = `history-forking:${this.session_id}:${Date.now()}:${nanoid(8)}`;
281
282
 
282
- const forked_bundle = await this.create_fork_session(
283
- `fork-${Date.now()}-${nanoid(8)}`,
284
- );
285
- const forked = forked_bundle.session;
286
- const session_config = this.state_service.get_config();
287
- if (session_config.model) {
288
- await forked.set({
289
- model: session_config.model,
283
+ await this.state_service.emit_operation_event({
284
+ operationId: operation_id,
285
+ name: "history-forking",
286
+ status: "started",
287
+ label: "Forking session history",
288
+ result: {
289
+ messageCount: fork_messages.length,
290
+ ...(message_id ? { messageId: message_id } : {}),
291
+ },
292
+ });
293
+
294
+ try {
295
+ const forked_bundle = await this.create_fork_session(
296
+ `fork-${Date.now()}-${nanoid(8)}`,
297
+ );
298
+ const forked = forked_bundle.session;
299
+ const session_config = this.state_service.get_config();
300
+ if (session_config.model) {
301
+ await forked_bundle.state_service.set(
302
+ {
303
+ model: session_config.model,
304
+ },
305
+ { emit_operation: false },
306
+ );
307
+ }
308
+ await this.append_fork_messages(forked_bundle, fork_messages);
309
+ await this.state_service.emit_operation_event({
310
+ operationId: operation_id,
311
+ name: "history-forking",
312
+ status: "finished",
313
+ label: "Session history forked",
314
+ result: {
315
+ forkedSessionId: String((forked as { id?: unknown }).id || ""),
316
+ messageCount: fork_messages.length,
317
+ ...(message_id ? { messageId: message_id } : {}),
318
+ },
319
+ });
320
+ return forked;
321
+ } catch (error) {
322
+ await this.state_service.emit_operation_event({
323
+ operationId: operation_id,
324
+ name: "history-forking",
325
+ status: "failed",
326
+ label: "Session history fork failed",
327
+ error: error instanceof Error ? error.message : String(error),
290
328
  });
329
+ throw error;
291
330
  }
292
- await this.append_fork_messages(forked_bundle, fork_messages);
293
- return forked;
294
331
  }
295
332
 
296
333
  private resolve_fork_messages(
@@ -99,7 +99,7 @@ export interface AgentSessionTimelineEvent {
99
99
  * 说明(中文)
100
100
  * - `tool-call` / `tool-result` 用于把 assistant 内部工具过程平铺给 UI。
101
101
  */
102
- role: "user" | "assistant" | "tool-call" | "tool-result";
102
+ role: "user" | "assistant" | "tool-call" | "tool-result" | "operation";
103
103
  /** 事件时间戳(毫秒)。 */
104
104
  ts?: number;
105
105
  /** 事件所属消息种类。 */
@@ -115,6 +115,27 @@ export interface AgentSessionTimelineEvent {
115
115
  * - 仅 `tool-call` / `tool-result` 这类事件通常会携带该字段。
116
116
  */
117
117
  toolName?: string;
118
+ /**
119
+ * 当前 operation ID。
120
+ *
121
+ * 说明(中文)
122
+ * - 仅 `role=operation` 的事件通常会携带该字段。
123
+ */
124
+ operationId?: string;
125
+ /**
126
+ * 当前 operation 名称。
127
+ *
128
+ * 说明(中文)
129
+ * - 仅 `role=operation` 的事件通常会携带该字段。
130
+ */
131
+ operationName?: string;
132
+ /**
133
+ * 当前 operation 状态。
134
+ *
135
+ * 说明(中文)
136
+ * - 仅 `role=operation` 的事件通常会携带该字段。
137
+ */
138
+ operationStatus?: string;
118
139
  }
119
140
 
120
141
  /**
@@ -7,6 +7,11 @@
7
7
  * - tool 深层回调等无法直接传参的场景,才通过 run scope 间接读取这个对象。
8
8
  */
9
9
 
10
+ import type {
11
+ AgentSessionOperationCallback,
12
+ AgentSessionOperationEvent,
13
+ AgentSessionOperationRecord,
14
+ } from "@/types/sdk/AgentSessionOperation.js";
10
15
  import type {
11
16
  SessionAssistantStepCallback,
12
17
  SessionUiMessageChunkCallback,
@@ -66,6 +71,15 @@ export interface SessionRunContext {
66
71
  */
67
72
  onUiMessageChunkCallback?: SessionUiMessageChunkCallback;
68
73
 
74
+ /**
75
+ * operation 发布回调。
76
+ *
77
+ * 关键点(中文)
78
+ * - 用于把 compaction 等辅助操作转成 session event 与 operation message。
79
+ * - operation 不代表 assistant 正文,也不会进入 LLM 输入。
80
+ */
81
+ onOperationCallback?: AgentSessionOperationCallback;
82
+
69
83
  /**
70
84
  * 当前 turn 的取消信号。
71
85
  *
@@ -101,3 +115,9 @@ export interface SessionRunContext {
101
115
  */
102
116
  pendingAssistantFileParts: FileUIPart[];
103
117
  }
118
+
119
+ export type {
120
+ AgentSessionOperationCallback,
121
+ AgentSessionOperationEvent,
122
+ AgentSessionOperationRecord,
123
+ };
@@ -8,6 +8,7 @@
8
8
 
9
9
  import type { JsonValue } from "@/types/common/Json.js";
10
10
  import type { SessionAssistantStepVisibility } from "@/executor/types/SessionRun.js";
11
+ import type { AgentSessionOperationEvent } from "@/types/sdk/AgentSessionOperation.js";
11
12
 
12
13
  /**
13
14
  * 单个 turn 开始事件。
@@ -354,6 +355,7 @@ export type AgentSessionEvent =
354
355
  | AgentSessionToolApprovalResultEvent
355
356
  | AgentSessionAssistantStepEvent
356
357
  | AgentSessionTitleEvent
358
+ | AgentSessionOperationEvent
357
359
  | AgentSessionTurnFinishEvent
358
360
  | AgentSessionErrorEvent;
359
361
 
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Agent Session operation 类型定义。
3
+ *
4
+ * 关键点(中文)
5
+ * - operation 描述 session 内部正在发生的辅助操作,不代表 assistant 正文。
6
+ * - operation 可以同时作为订阅事件发布,也可以作为 UIMessage 持久化到 JSONL。
7
+ * - operation message 只用于前端时间线与调试,不应进入 LLM 输入。
8
+ */
9
+
10
+ import type { JsonValue } from "@/types/common/Json.js";
11
+
12
+ /**
13
+ * Session operation 当前状态。
14
+ */
15
+ export type AgentSessionOperationStatus =
16
+ | "started"
17
+ | "progress"
18
+ | "finished"
19
+ | "skipped"
20
+ | "failed";
21
+
22
+ /**
23
+ * Session operation 名称。
24
+ *
25
+ * 说明(中文)
26
+ * - 内置名称用于 SDK 与前端约定常见辅助操作。
27
+ * - 字符串扩展允许 plugin 或宿主运行时声明自己的 operation。
28
+ */
29
+ export type AgentSessionOperationName =
30
+ | "compacting"
31
+ | "model-switching"
32
+ | "history-forking"
33
+ | (string & {});
34
+
35
+ /**
36
+ * Session operation 记录。
37
+ */
38
+ export interface AgentSessionOperationRecord {
39
+ /**
40
+ * 同一个 operation 生命周期内稳定复用的 ID。
41
+ */
42
+ operationId: string;
43
+
44
+ /**
45
+ * 当前 operation 名称。
46
+ */
47
+ name: AgentSessionOperationName;
48
+
49
+ /**
50
+ * 当前 operation 状态。
51
+ */
52
+ status: AgentSessionOperationStatus;
53
+
54
+ /**
55
+ * 当前 operation 关联的 turn 标识。
56
+ *
57
+ * 说明(中文)
58
+ * - turn 内触发的 operation 应写入该字段。
59
+ * - session 级 operation 可以省略。
60
+ */
61
+ turnId?: string;
62
+
63
+ /**
64
+ * 面向用户展示的短文本。
65
+ */
66
+ label?: string;
67
+
68
+ /**
69
+ * 机器可读原因。
70
+ *
71
+ * 示例(中文)
72
+ * - `under_budget`:未达到压缩阈值。
73
+ * - `summary_fallback`:摘要生成失败后使用降级摘要。
74
+ */
75
+ reason?: string;
76
+
77
+ /**
78
+ * 当前 operation 进度,范围 0 到 1。
79
+ *
80
+ * 说明(中文)
81
+ * - 无法估算进度时省略。
82
+ */
83
+ progress?: number;
84
+
85
+ /**
86
+ * operation 完成后产生的轻量结果。
87
+ */
88
+ result?: JsonValue;
89
+
90
+ /**
91
+ * operation 失败时的错误文本。
92
+ */
93
+ error?: string;
94
+
95
+ /**
96
+ * 是否建议前端展示。
97
+ *
98
+ * 说明(中文)
99
+ * - 默认视为 `true`。
100
+ * - 调试或审计类辅助事件可显式写入 `false`。
101
+ */
102
+ visible?: boolean;
103
+ }
104
+
105
+ /**
106
+ * Session operation 订阅事件。
107
+ */
108
+ export interface AgentSessionOperationEvent extends AgentSessionOperationRecord {
109
+ /**
110
+ * 当前事件类型。
111
+ */
112
+ type: "operation";
113
+
114
+ /**
115
+ * 当前 session 唯一标识。
116
+ */
117
+ sessionId: string;
118
+ }
119
+
120
+ /**
121
+ * Session operation 发布回调。
122
+ */
123
+ export type AgentSessionOperationCallback = (
124
+ operation: AgentSessionOperationEvent,
125
+ ) => Promise<void>;