@tencent-ai/agent-harness 0.2.0-beta.2 → 0.2.0-beta.4

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 (182) hide show
  1. package/CHANGELOG.md +40 -2
  2. package/cli/CHANGELOG.md +64 -0
  3. package/cli/dist-server/shared.cjs +450 -329
  4. package/cli/dist-server/types/node/acp/acp-protocol.d.ts +8 -0
  5. package/cli/dist-server/types/node/bash-sandbox/bash-sandbox-protocol.d.ts +3 -0
  6. package/cli/dist-server/types/node/cli/cli-protocol.d.ts +3 -0
  7. package/cli/dist-server/types/node/cli/stream-json-protocol.d.ts +8 -1
  8. package/cli/dist-server/types/node/loopback/server-protocol.d.ts +5 -0
  9. package/cli/dist-server/types/node/sensitive-content/sensitive-content-protocol.d.ts +7 -0
  10. package/cli/dist-server/types/node/server/boot.d.ts +7 -4
  11. package/{lib/components → cli/dist-server/types/node/server/formats}/acp/acp-error-model.d.ts +1 -1
  12. package/{lib/components → cli/dist-server/types/node/server/formats}/acp/acp-protocol.d.ts +2 -3
  13. package/cli/dist-server/types/node/server/formats/acp/index.d.ts +12 -0
  14. package/cli/dist-server/types/node/server/formats/acp/projection.d.ts +10 -0
  15. package/cli/dist-server/types/node/server/index.d.ts +1 -1
  16. package/cli/dist-server/types/node/server/sessions.d.ts +3 -2
  17. package/cli/dist-server/types/node/server/types.d.ts +59 -7
  18. package/cli/dist-server/types/node/tools/tool-protocol.d.ts +39 -24
  19. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-protocol.d.ts +31 -2
  20. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-purpose-protocol.d.ts +8 -4
  21. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-purpose-scope.d.ts +46 -0
  22. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-service.d.ts +26 -3
  23. package/cli/dist-server/types/vendor/cbc-core/node/agent/index.d.ts +3 -0
  24. package/cli/dist-server/types/vendor/cbc-core/node/agent/model-call-failure.d.ts +9 -0
  25. package/cli/dist-server/types/vendor/cbc-core/node/agent/model-step-sequence.d.ts +11 -0
  26. package/cli/dist-server/types/vendor/cbc-core/node/agent/runner-factory.d.ts +43 -9
  27. package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
  28. package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-pattern.d.ts +9 -8
  29. package/cli/dist-server/types/vendor/cbc-core/node/context/compaction-lineage.d.ts +39 -0
  30. package/cli/dist-server/types/vendor/cbc-core/node/context/context-compact-summarizer.d.ts +2 -0
  31. package/cli/dist-server/types/vendor/cbc-core/node/context/context-protocol.d.ts +17 -0
  32. package/cli/dist-server/types/vendor/cbc-core/node/context/index.d.ts +2 -0
  33. package/cli/dist-server/types/vendor/cbc-core/node/context/mods-bridge.d.ts +115 -0
  34. package/cli/dist-server/types/vendor/cbc-core/node/context/pre-message-compact-strategy.d.ts +1 -2
  35. package/cli/dist-server/types/vendor/cbc-core/node/message-queue/followup-queue-protocol.d.ts +3 -2
  36. package/cli/dist-server/types/vendor/cbc-core/node/message-queue/followup-queue.d.ts +1 -1
  37. package/cli/dist-server/types/vendor/cbc-core/node/message-queue/steer-input-buffer-protocol.d.ts +4 -0
  38. package/cli/dist-server/types/vendor/cbc-core/node/session/can-use-tool.d.ts +4 -0
  39. package/cli/dist-server/types/vendor/cbc-core/node/session/index.d.ts +1 -0
  40. package/cli/dist-server/types/vendor/cbc-core/node/session/interruption-service.d.ts +8 -0
  41. package/cli/dist-server/types/vendor/cbc-core/node/session/model-request-retry-phase.d.ts +16 -0
  42. package/cli/dist-server/types/vendor/cbc-core/node/session/model-response-interceptors.d.ts +15 -0
  43. package/cli/dist-server/types/vendor/cbc-core/node/session/session-manager-host-protocol.d.ts +3 -2
  44. package/cli/dist-server/types/vendor/cbc-core/node/session/session-manager.d.ts +37 -3
  45. package/cli/dist-server/types/vendor/cbc-core/node/session/session-protocol.d.ts +59 -5
  46. package/cli/dist-server/types/vendor/cbc-core/node/session/session-run-state-machine-protocol.d.ts +14 -1
  47. package/cli/dist-server/types/vendor/cbc-core/node/session/stream-timeout-retry-budget.d.ts +8 -1
  48. package/cli/dist-server/types/vendor/cbc-core/node/trace/turn-context.d.ts +28 -1
  49. package/cli/dist-server/types/vendor/cbc-core/node/utils/command-message-utils.d.ts +20 -0
  50. package/cli/dist-server/types/vendor/cbc-core/node/utils/history-utils.d.ts +4 -4
  51. package/cli/dist-server/types/vendor/cbc-core/node/utils/input-item-utils.d.ts +9 -1
  52. package/cli/dist-server/types/vendor/cbc-core/node/utils/token-utils.d.ts +3 -1
  53. package/cli/dist-server/types/vendor/cbc-shared/node/agent/openai-agents-types.d.ts +1 -0
  54. package/cli/dist-server/types/vendor/cbc-shared/node/checkpoint/checkpoint-types.d.ts +6 -0
  55. package/cli/dist-server/types/vendor/cbc-shared/node/model/model-errors.d.ts +30 -2
  56. package/cli/dist-server/types/workspace/agent-client-protocol/lib/common/index.d.ts +1 -0
  57. package/cli/dist-server/types/workspace/agent-client-protocol/lib/common/prompt-codec.d.ts +4 -0
  58. package/cli/dist-server/types/workspace/agent-client-protocol/lib/common/sandbox-rule-context.d.ts +38 -0
  59. package/cli/dist-server/types/workspace/agent-client-protocol/lib/common/types.d.ts +15 -1
  60. package/cli/dist-server/types/workspace/authentication/lib/common/account-scoped-external-link-authentication-provider.d.ts +3 -3
  61. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-manager.d.ts +6 -0
  62. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-observation.d.ts +36 -0
  63. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-protocol.d.ts +21 -0
  64. package/cli/dist-server/types/workspace/authentication/lib/common/external-link-authentication-provider.d.ts +20 -4
  65. package/cli/dist-server/types/workspace/authentication/lib/common/index.d.ts +1 -0
  66. package/cli/dist-server/types/workspace/cbc-checkpoint/lib/node/checkpoint/checkpoint-protocol.d.ts +2 -0
  67. package/cli/dist-server/types/workspace/cbc-checkpoint/lib/node/checkpoint/checkpoint-service.d.ts +1 -0
  68. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-protocol.d.ts +31 -2
  69. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-purpose-protocol.d.ts +8 -4
  70. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-purpose-scope.d.ts +46 -0
  71. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-service.d.ts +26 -3
  72. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/index.d.ts +3 -0
  73. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/model-call-failure.d.ts +9 -0
  74. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/model-step-sequence.d.ts +11 -0
  75. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/runner-factory.d.ts +43 -9
  76. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
  77. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-pattern.d.ts +9 -8
  78. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/compaction-lineage.d.ts +39 -0
  79. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/context-compact-summarizer.d.ts +2 -0
  80. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/context-protocol.d.ts +17 -0
  81. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/index.d.ts +2 -0
  82. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/mods-bridge.d.ts +115 -0
  83. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/pre-message-compact-strategy.d.ts +1 -2
  84. package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/followup-queue-protocol.d.ts +3 -2
  85. package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/followup-queue.d.ts +1 -1
  86. package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/steer-input-buffer-protocol.d.ts +4 -0
  87. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/can-use-tool.d.ts +4 -0
  88. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/index.d.ts +1 -0
  89. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/interruption-service.d.ts +8 -0
  90. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/model-request-retry-phase.d.ts +16 -0
  91. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/model-response-interceptors.d.ts +15 -0
  92. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-manager-host-protocol.d.ts +3 -2
  93. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-manager.d.ts +37 -3
  94. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-protocol.d.ts +59 -5
  95. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-run-state-machine-protocol.d.ts +14 -1
  96. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/stream-timeout-retry-budget.d.ts +8 -1
  97. package/cli/dist-server/types/workspace/cbc-core/lib/node/trace/turn-context.d.ts +28 -1
  98. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/command-message-utils.d.ts +20 -0
  99. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/history-utils.d.ts +4 -4
  100. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/input-item-utils.d.ts +9 -1
  101. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/token-utils.d.ts +3 -1
  102. package/cli/dist-server/types/workspace/cbc-shared/lib/node/agent/openai-agents-types.d.ts +1 -0
  103. package/cli/dist-server/types/workspace/cbc-shared/lib/node/checkpoint/checkpoint-types.d.ts +6 -0
  104. package/cli/dist-server/types/workspace/cbc-shared/lib/node/model/model-errors.d.ts +30 -2
  105. package/cli/dist-server/types/workspace/cbc-worktree/lib/node/worktree/worktree-service.d.ts +5 -0
  106. package/cli/dist-server/types/workspace/core/lib/common/protocol.d.ts +8 -1
  107. package/cli/dist-server/types/workspace/product/lib/common/index.d.ts +1 -0
  108. package/cli/dist-server/types/workspace/product/lib/common/tencent-docs-endpoint.d.ts +37 -0
  109. package/cli/dist-server/types/workspace/product/lib/common/types/config.d.ts +12 -0
  110. package/cli/dist-server/types/workspace/product/lib/common/types/features.d.ts +17 -9
  111. package/cli/dist-server/types/workspace/product/lib/common/types/product.d.ts +15 -0
  112. package/cli/dist-server/types/workspace/prompts/lib/common/product-prompt-provider.d.ts +3 -1
  113. package/cli/dist-server/types/workspace/prompts/lib/common/prompt-protocol.d.ts +6 -0
  114. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/center-protocol.generated.d.ts +5 -0
  115. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/file-policy.d.ts +4 -1
  116. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/http-policy.d.ts +20 -0
  117. package/cli/dist-server/types/workspace/sandbox-cli/lib/common/rule-config.d.ts +10 -0
  118. package/cli/dist-server/types/workspace/sandbox-cli/lib/node/sandbox-center-client.d.ts +3 -0
  119. package/cli/dist-server/types/workspace/telemetry/lib/common/event/types/craft.d.ts +43 -3
  120. package/cli/package.json +1 -1
  121. package/cli/product.cloudhosted.json +1 -803
  122. package/cli/product.internal.json +1 -1057
  123. package/cli/product.ioa.json +1 -1515
  124. package/cli/product.json +1 -2189
  125. package/cli/product.selfhosted.json +1 -364
  126. package/cli/vendor/shim/brokered-bin/7z +675 -0
  127. package/cli/vendor/shim/brokered-bin/7za +675 -0
  128. package/cli/vendor/shim/brokered-bin/7zz +675 -0
  129. package/cli/vendor/shim/brokered-bin/rar +675 -0
  130. package/cli/vendor/shim/brokered-bin/tar +675 -0
  131. package/cli/vendor/shim/brokered-bin/zip +187 -0
  132. package/docs/acp-v2.md +19 -0
  133. package/docs/client.md +7 -0
  134. package/docs/in-process.md +26 -2
  135. package/docs/product.md +4 -0
  136. package/docs/protocol.md +10 -2
  137. package/docs/server.md +2 -0
  138. package/lib/agent/v2.js +1 -1
  139. package/lib/application/services.js +1 -1
  140. package/lib/auth/module.d.ts +3 -1
  141. package/lib/auth/module.js +1 -1
  142. package/lib/client/client.js +1 -1
  143. package/lib/client/mcp.d.ts +1 -1
  144. package/lib/client/mcp.js +1 -1
  145. package/lib/components/acp-mcp-transport.d.mts +84 -1
  146. package/lib/components/question-elicitation.d.mts +20 -1
  147. package/lib/components/sandbox.d.mts +2 -0
  148. package/lib/components/sandbox.mjs +1 -0
  149. package/lib/components/{acp/acp-prompt-input.d.ts → session/prompt-input.d.ts} +1 -1
  150. package/lib/components/session-replay.d.mts +8 -7
  151. package/lib/components/session-replay.mjs +1 -1
  152. package/lib/effect-runtime/concurrency.d.mts +2 -4
  153. package/lib/effect-runtime/concurrency.mjs +1 -1
  154. package/lib/effect-runtime/mcp-lifecycle.mjs +1 -1
  155. package/lib/effect-runtime/process-runtime-context.d.ts +5 -1
  156. package/lib/harness/create-harness.js +1 -1
  157. package/lib/integration/agent-integration.d.ts +5 -0
  158. package/lib/protocol/acp-v2-credits.d.ts +10 -0
  159. package/lib/protocol/acp-v2-credits.js +1 -0
  160. package/lib/protocol/acp-v2-private-client.d.ts +1 -10
  161. package/lib/runtime/codebuddy-auth.d.ts +5 -3
  162. package/lib/runtime/codebuddy-auth.js +1 -1
  163. package/lib/runtime/private-runtime-role.js +1 -1
  164. package/lib/session/agent-backend.d.ts +3 -0
  165. package/lib/session/agent-backend.js +1 -1
  166. package/lib/session/config-defaults.d.ts +4 -0
  167. package/lib/session/config-defaults.js +1 -0
  168. package/lib/session/config-store.d.ts +1 -1
  169. package/lib/session/config-store.js +1 -1
  170. package/lib/session/replay.d.ts +3 -3
  171. package/lib/session/replay.js +1 -1
  172. package/lib/session/server-config.d.ts +11 -2
  173. package/lib/session/server-config.js +1 -1
  174. package/lib/session/server-events.d.ts +10 -8
  175. package/lib/session/server-events.js +1 -1
  176. package/lib/session/server-interactions.js +1 -1
  177. package/lib/session/server-mcp.js +1 -1
  178. package/lib/subagent/history.js +1 -1
  179. package/package.json +26 -20
  180. package/lib/components/acp/acp-client-channel.d.ts +0 -36
  181. package/lib/components/acp/acp-mcp-transport.d.ts +0 -84
  182. package/lib/components/acp/acp-question-elicitation.d.ts +0 -20
@@ -16,6 +16,7 @@ import { CompactStrategy, type ContextCompactResult, ContextCompactSummarizeOpti
16
16
  * 不包含任何具体的压缩逻辑实现。
17
17
  */
18
18
  export declare class ContextCompactSummarizerImpl implements ContextCompactSummarizer {
19
+ private activeCompactions?;
19
20
  protected readonly productManager: ProductManager;
20
21
  protected readonly agentManager: AgentManager;
21
22
  protected readonly logger: Logger;
@@ -25,6 +26,7 @@ export declare class ContextCompactSummarizerImpl implements ContextCompactSumma
25
26
  protected readonly strategyProvider: Provider<CompactStrategy>;
26
27
  compactAndSummarize(session: Session, options?: ContextCompactSummarizeOptions): Promise<boolean>;
27
28
  compactWithResult(session: Session, options?: ContextCompactSummarizeOptions): Promise<ContextCompactResult>;
29
+ private compactWithResultOwned;
28
30
  /**
29
31
  * 按优先级匹配(PreMessage → MaxToken),跳过 Blocking(仅作最终兜底),执行第一个命中的策略;
30
32
  * 都不命中则安全网回落到 Blocking。逻辑与压缩 span 化之前完全一致,只是把散落的 `return` 收敛成
@@ -1,7 +1,10 @@
1
+ import type { AgentInputItem } from '../../../../cbc-shared/lib/node/index.js';
2
+ import type { CompactionTrigger } from '../../../../telemetry/lib/common/index.js';
1
3
  import { Session } from '../session/session-protocol.js';
2
4
  export declare const PromptContextProvider: unique symbol;
3
5
  export declare const PromptContextInitializer: unique symbol;
4
6
  export declare const ContextCompactSummarizer: unique symbol;
7
+ export declare const ManualCompactRequestHandler: unique symbol;
5
8
  export declare const PromptRenderer: unique symbol;
6
9
  export declare const COMPACT_PROMPT = "compact-prompt";
7
10
  export declare const DEFAULT_TOKEN_THRESHOLD = 0.7;
@@ -190,6 +193,8 @@ export interface ContextCompactSummarizeOptions {
190
193
  type?: CompactType;
191
194
  /** Stable identity shared by live updates and the durable compact boundary. */
192
195
  compactionId?: string;
196
+ /** Why this compaction runs; defaults from `type` (manual / pre_message_threshold / emergency_threshold). */
197
+ trigger?: CompactionTrigger;
193
198
  }
194
199
  export type ContextCompactSkipReason = 'already_compacting' | 'pending_interruption' | 'auto_disabled' | 'empty_history' | 'already_compacted' | 'non_default_agent' | 'below_threshold';
195
200
  export type ContextCompactFailureReason = 'strategy_failed' | 'strategy_unavailable';
@@ -214,6 +219,8 @@ export declare function createCompactionId(): string;
214
219
  export declare const SESSION_META_COMPACT_TYPE: 'compactType';
215
220
  /** Current stable compaction identity, persisted onto the boundary item. */
216
221
  export declare const SESSION_META_COMPACTION_ID: 'compactionId';
222
+ /** Trigger of the compaction the summarizer is running; unset for a typed `/compact`. */
223
+ export declare const SESSION_META_COMPACTION_TRIGGER: 'compactionTrigger';
217
224
  /**
218
225
  * session.meta 上标记当前 compact 成功后会继续执行一次真实 agent run。
219
226
  *
@@ -321,6 +328,16 @@ export interface ContextCompactSummarizer {
321
328
  /** Compatibility wrapper for existing automatic-compaction callers. */
322
329
  compactAndSummarize(session: Session, options?: ContextCompactSummarizeOptions): Promise<boolean>;
323
330
  }
331
+ /**
332
+ * Host-owned boundary for external `/compact` requests.
333
+ *
334
+ * AgentService invokes this before creating a normal run lifecycle when an
335
+ * interactive host opts in. Implementations must return false for internal compact
336
+ * inputs so strategy-owned internal runs cannot recursively re-enter this boundary.
337
+ */
338
+ export interface ManualCompactRequestHandler {
339
+ tryHandle(input: string | AgentInputItem[], session: Session): Promise<boolean>;
340
+ }
324
341
  export interface PromptRenderer {
325
342
  render(template: string, context?: PromptContext): Promise<string>;
326
343
  }
@@ -1,5 +1,7 @@
1
1
  export * from './context-protocol.js';
2
+ export * from './compaction-lineage.js';
2
3
  export * from './context-host-protocol.js';
4
+ export * from './mods-bridge.js';
3
5
  export * from './prompt-context-provider.js';
4
6
  export * from './prompt-renderer.js';
5
7
  export * from './context-compact-summarizer.js';
@@ -0,0 +1,115 @@
1
+ import type { AgentInputItem } from '../../../../cbc-shared/lib/node/index.js';
2
+ import type { PromptContext } from './context-protocol.js';
3
+ export interface ModsPromptSubmitResult {
4
+ text?: string;
5
+ drop?: string;
6
+ }
7
+ /** Host-only provenance: a mod initiated submission has already traversed the fold. */
8
+ export declare const MODS_PROMPT_SUBMITTED_KEY = "modsPromptSubmitted";
9
+ /**
10
+ * Function hooks(Claude mods)在 core 侧的**窄接口**。
11
+ *
12
+ * ## 为什么 core 不直接调 mods
13
+ *
14
+ * `cbc-core` 只允许依赖 `@genie/cbc-shared`(见仓库 CODEBUDDY.md 的单向依赖卡点,
15
+ * `package-boundaries.spec.ts` 会扫源码 import、动态 import 与依赖声明)。而 mods
16
+ * 引擎住在 `cbc-plugins`。所以 core 这一侧只声明「我会在这几个时刻问一句」,具体
17
+ * 分发由宿主实现后注入。
18
+ *
19
+ * ## 为什么形状映射也不在 core
20
+ *
21
+ * cbc 的 `PromptContext` 是一个松散字典,官方 `prompt.context` 事件是
22
+ * `{ blocks, instructionFiles }`。两者的对应关系属于**适配**,而适配是宿主的事 ——
23
+ * 让 core 认识官方 payload 等于把上游协议渗进核心包,将来上游改一次形状,core 就
24
+ * 得跟着改。因此接口按 core 自己的类型说话,桥的实现负责翻译。
25
+ *
26
+ * ## 未注入时必须是零开销
27
+ *
28
+ * function hooks 默认关闭。没有桥时每个调用点只多一次 `=== undefined` 判断,
29
+ * 不构造对象、不进 async、不改变任何既有行为。
30
+ */
31
+ export interface ModsBridge {
32
+ /**
33
+ * 上下文装配完成、尚未拼成最终 prompt 时问一句。
34
+ *
35
+ * @param context 当前这一版上下文
36
+ * @returns 可能被 mod 改写过的上下文;桥自身出问题时应原样返回入参
37
+ */
38
+ promptContext(context: PromptContext): Promise<PromptContext>;
39
+ /**
40
+ * 会话建立时通知一次。
41
+ *
42
+ * @param input 会话 cwd 与是否交互式 —— 官方 `session.start` 的入参
43
+ */
44
+ sessionStart(input: {
45
+ cwd: string;
46
+ isInteractive: boolean;
47
+ }): Promise<void>;
48
+ /**
49
+ * 用户提交输入时问一句。对齐官方 `prompt.submit`。
50
+ *
51
+ * @param input 即将送达模型的文本
52
+ * @returns `{ drop }` 阻断输入,`{ text }` 改写可见文本;附件与隐藏上下文由 core 保留。
53
+ */
54
+ promptSubmit(input: {
55
+ text: string;
56
+ sessionId?: string;
57
+ signal?: AbortSignal;
58
+ }): Promise<ModsPromptSubmitResult | undefined>;
59
+ /**
60
+ * 把一条 mod 打出来的 `$.ui.log` 行落到用户可见的会话里。
61
+ *
62
+ * ## 为什么走桥而不是让 core 直接推消息
63
+ *
64
+ * `$.ui.log` 是 mod 侧发起的用户可见事件(官方语义:进 transcript),但 core
65
+ * 不知道"当前会话"是哪一个(AsyncLocalStorage 上下文由宿主入口决定),也不认
66
+ * `plugin` 这个身份维度(那是 mods 引擎的概念)。宿主拿到这一对
67
+ * `(text, plugin)` 之后,负责取当前 session 并 push 进 `inputSubject` /
68
+ * `combineSubject` / `sessionStore.appendHistory`,就跟宿主自己的系统消息
69
+ * 是同一条路径。
70
+ *
71
+ * ## 未装桥时的兜底在哪
72
+ *
73
+ * 宿主没实现这一项时,`bindings.log` 侧应当把行文继续写到 stderr(headless /
74
+ * bootstrap 早期 / 无当前 session 时用得到)—— 那种场景下用户看不到"消息历史",
75
+ * 但仍能通过日志追溯这一行,与既有行为保持一致。
76
+ *
77
+ * @param text 已由宿主前缀好 `<plugin>: ` 的完整行文(core 不重复加前缀)
78
+ * @param meta 至少携带 `plugin`;用于前端识别 / 分组
79
+ */
80
+ pushModLog?(text: string, meta: {
81
+ plugin: string;
82
+ }): void;
83
+ }
84
+ /**
85
+ * 注入桥。宿主在 mods 运行时起来之后调用一次。
86
+ *
87
+ * @param next 桥实现;传 `undefined` 卸载(测试用)
88
+ */
89
+ export declare function setModsBridge(next: ModsBridge | undefined): void;
90
+ /** 当前桥;未注入时 undefined。 */
91
+ export declare function currentModsBridge(): ModsBridge | undefined;
92
+ /**
93
+ * 经桥过一遍上下文。
94
+ *
95
+ * **桥出问题不能影响主流程**:mod 是第三方代码,它抛错、超时、返回垃圾,都只该
96
+ * 让 function hooks 这一层失效,而不是让会话起不来。因此这里兜住一切异常并回退到
97
+ * 原上下文 —— 与「加载失败不阻塞宿主」同一条原则。
98
+ *
99
+ * @param context 当前上下文
100
+ * @returns 改写后的上下文;无桥或出错时是原对象
101
+ */
102
+ export declare function throughModsPromptContext(context: PromptContext): Promise<PromptContext>;
103
+ /** A failed third-party fold must not corrupt or lose the original input. */
104
+ export declare function throughModsPromptSubmit(text: string, sessionId?: string, signal?: AbortSignal): Promise<ModsPromptSubmitResult | undefined>;
105
+ /** Mutates only user text, before the shared history/model consumers see these items. */
106
+ export declare function applyModsPromptSubmit(items: AgentInputItem[], sessionId: string, signal?: AbortSignal): Promise<string | undefined>;
107
+ /**
108
+ * 通知会话开始。同样绝不向外抛。
109
+ *
110
+ * @param input 会话 cwd 与是否交互式
111
+ */
112
+ export declare function notifyModsSessionStart(input: {
113
+ cwd: string;
114
+ isInteractive: boolean;
115
+ }): Promise<void>;
@@ -4,8 +4,7 @@ import { CompactStrategyContext, ContextCompactSummarizeOptions } from './contex
4
4
  /**
5
5
  * PreMessage 压缩策略:在发送用户消息前触发。
6
6
  *
7
- * 触发条件:PRE_MESSAGE_AUTO 或 WorkBuddy 的 USER_COMMAND。
8
- * CBC 手动 /compact 不走该策略,继续由 compact agent 路径处理。
7
+ * 触发条件:PRE_MESSAGE_AUTO 或 USER_COMMAND(WorkBuddy / TUI 手动压缩)。
9
8
  *
10
9
  * 流程:
11
10
  * 1. Engineering compact (no LLM call)
@@ -30,12 +30,13 @@ export interface FollowupQueueSnapshot {
30
30
  items: FollowupQueueItemView[];
31
31
  }
32
32
  /** ACP `session/steer` 回调。服务不直接碰 ACP,方便单测。 */
33
- export type FollowupSteerFn = (contentBlocks: unknown[]) => Promise<{
33
+ export type FollowupSteerFn = (contentBlocks: unknown[], modsPromptSubmitted?: true) => Promise<{
34
34
  steered: boolean;
35
35
  }>;
36
36
  export interface FollowupQueueService {
37
37
  snapshot(session: Session): FollowupQueueSnapshot;
38
- enqueue(session: Session, contentBlocks: unknown[], hold: boolean): FollowupQueueSnapshot;
38
+ /** modsPromptSubmitted is host-validated provenance, never a client flag. */
39
+ enqueue(session: Session, contentBlocks: unknown[], hold: boolean, modsPromptSubmitted?: true): FollowupQueueSnapshot;
39
40
  remove(session: Session, itemId: string): FollowupQueueSnapshot;
40
41
  /**
41
42
  * 立即发送:能插入当前回合就 `steer` 并从队列拿掉;否则只摘 queueHold。
@@ -23,7 +23,7 @@ export declare class FollowupQueueServiceImpl implements FollowupQueueService {
23
23
  */
24
24
  private readonly pendingBroadcasts;
25
25
  snapshot(session: Session): FollowupQueueSnapshot;
26
- enqueue(session: Session, contentBlocks: unknown[], hold: boolean): FollowupQueueSnapshot;
26
+ enqueue(session: Session, contentBlocks: unknown[], hold: boolean, modsPromptSubmitted?: true): FollowupQueueSnapshot;
27
27
  remove(session: Session, itemId: string): FollowupQueueSnapshot;
28
28
  sendNow(session: Session, itemId: string, steer?: FollowupSteerFn): Promise<FollowupQueueSnapshot>;
29
29
  watch(session: Session): void;
@@ -28,6 +28,8 @@ export declare const SteerInputBuffer: unique symbol;
28
28
  * drain 返回的一组:待插入内容 + 独立对账 id + 客户端不透明 metadata。
29
29
  */
30
30
  export interface SteerDrainedGroup {
31
+ /** Set only after the host validates a one-time mod prompt receipt. */
32
+ readonly modsPromptSubmitted?: true;
31
33
  readonly blocks: unknown[];
32
34
  /** Native, already reviewed messages. Kept by reference for in-memory admission markers. */
33
35
  readonly messages?: readonly UserMessageItem[];
@@ -49,6 +51,8 @@ export interface SteerDrainedGroup {
49
51
  * push 的归属 + 客户端不透明 metadata 入参(合并为一个对象,避免 push 参数过多)。
50
52
  */
51
53
  export interface SteerPushInput {
54
+ /** Server-only provenance, independent of untrusted clientMeta. */
55
+ readonly modsPromptSubmitted?: true;
52
56
  /**
53
57
  * 这组消息归属的请求 id(当前正在执行的 turn 的 requestId);
54
58
  * `undefined` 表示无归属信息(drain 时按「当前也无归属」放行,退化为旧行为)。
@@ -40,6 +40,8 @@ export type PermissionResult = {
40
40
  updatedPermissions?: PermissionUpdate[];
41
41
  toolUseID?: string;
42
42
  decisionClassification?: PermissionDecisionClassification;
43
+ /** Optional host response metadata; interpreted only by the requesting tool. */
44
+ metadata?: Record<string, unknown>;
43
45
  } | {
44
46
  behavior: 'deny';
45
47
  message: string;
@@ -68,6 +70,8 @@ export interface CanUseToolOptions {
68
70
  displayName?: string;
69
71
  /** 桥端渲染的副标题说明。 */
70
72
  description?: string;
73
+ /** Tool-provided display/context metadata for host permission UIs. Not an authorization grant. */
74
+ metadata?: Record<string, unknown>;
71
75
  /** 本次工具调用在 assistant 消息内的唯一 id。 */
72
76
  toolUseID: string;
73
77
  /** 子代理上下文中触发时,子代理的 id。 */
@@ -36,6 +36,7 @@ export * from './stream-timeout-retry-budget.js';
36
36
  export { consumeRecoveryRequestPending } from './recovery-budget.js';
37
37
  export * from './session-run-state-machine-protocol.js';
38
38
  export * from './session-run-state-machine.js';
39
+ export * from './model-request-retry-phase.js';
39
40
  export * from './session-run-state-projection-service.js';
40
41
  export * from './local-jsonl-session-store.js';
41
42
  export * from './transcript-branch.js';
@@ -93,6 +93,13 @@ export declare class InterruptionServiceImpl implements InterruptionService {
93
93
  protected readonly idleQueueDrainService?: IIdleQueueDrainService;
94
94
  protected readonly traceCollector?: SessionInterruptionTraceHost;
95
95
  protected get startupProfiler(): SessionInterruptionProfilerHost;
96
+ /**
97
+ * 标记「用户取消本轮」的拒绝项(`reject(item, { cancelTurn: true })`)。
98
+ * 语义是取消当前 turn,而不是「拒绝并让模型带反馈续跑」。
99
+ * 记在 WeakSet 而不是 `rawItem.providerData`(那会落进历史),也不改
100
+ * deferred 的 reject 形状(下游按 error 类型分支的逻辑保持不变)。
101
+ */
102
+ private readonly cancelTurnItems;
96
103
  /** Claim before calling out: sandbox callbacks can throw or synchronously re-enter. */
97
104
  private takeSandboxResolve;
98
105
  approve(item: RunToolApprovalItem, options?: {
@@ -101,6 +108,7 @@ export declare class InterruptionServiceImpl implements InterruptionService {
101
108
  }): void;
102
109
  reject(item: RunToolApprovalItem, options?: {
103
110
  decision?: 'deny' | 'rejectAndExitPlan';
111
+ cancelTurn?: boolean;
104
112
  }): void;
105
113
  /**
106
114
  * 取消指定 session 上所有未决的 interruption Deferred。
@@ -0,0 +1,16 @@
1
+ import type { AgentRetryReason, Session } from './session-protocol.js';
2
+ import { ModelRequestRetryPhase, SessionRunStateMachine } from './session-run-state-machine-protocol.js';
3
+ export declare class ModelRequestRetryPhaseImpl implements ModelRequestRetryPhase {
4
+ protected readonly stateMachine: SessionRunStateMachine;
5
+ during<T>(session: Session | undefined, reason: AgentRetryReason, wait: () => Promise<T>): Promise<T>;
6
+ /**
7
+ * 辅助型调用复用主 session 却不回送 AGENT_ENDED(#52320),不得驱动其状态;
8
+ * 状态已离开 MODEL_REQUESTING 说明另有路径在推进,此时不抢写。
9
+ */
10
+ private enter;
11
+ /**
12
+ * 必须回到 MODEL_REQUESTING:RETRYING 不接收 TOOL_STARTED / MODEL_RESPONSE_DONE 等后续事件,
13
+ * 停留会让错误处理路径的转换被静默忽略。已被取消等事件推走时不再改写。
14
+ */
15
+ private leave;
16
+ }
@@ -215,6 +215,21 @@ export declare class MediaContentErrorInterceptor implements ModelResponseInterc
215
215
  private static readonly MAX_RETRY_ATTEMPTS;
216
216
  private static readonly MAX_MIME_MISMATCH_RETRY_ATTEMPTS;
217
217
  private static readonly GIF_UNSUPPORTED_ERROR_CODES;
218
+ /**
219
+ * Gateway business codes that mean "the model refused the images in this
220
+ * request" (`11135 InvalidInputImage`).
221
+ *
222
+ * The code is the only stable signal. The gateway folds several unrelated
223
+ * upstream causes into one hard-coded English sentence and overwrites the
224
+ * upstream text, so `ERROR_TYPE_PATTERNS` matching that sentence breaks the
225
+ * moment the wording is changed or localized (`docs/error-codes.md` already
226
+ * ships a Chinese user-facing string for this code). The code is carried on
227
+ * the error object all the way here — `error-analyzer` puts the parsed body
228
+ * code into the response, the SDK surfaces it as `APIError.error.code`, and
229
+ * `ErrorUtils.extractBizCode` recovers it — so key off it and keep the
230
+ * phrasing match only as a fallback for gateways that send no code.
231
+ */
232
+ private static readonly IMAGE_REJECTED_ERROR_CODES;
218
233
  private static readonly GIF_UNSUPPORTED_PLACEHOLDER;
219
234
  private static readonly ERROR_TYPE_PATTERNS;
220
235
  intercept(ctx: ModelResponseInterceptorContext): Promise<boolean | void>;
@@ -1,5 +1,5 @@
1
1
  import type { AgentInputItem } from '../../../../cbc-shared/lib/node/index.js';
2
- import type { ModelResponseMetadata, Session } from './session-protocol.js';
2
+ import type { ModelCallGeneration, ModelResponseMetadata, Session } from './session-protocol.js';
3
3
  export declare const SessionCheckpointHost: unique symbol;
4
4
  export interface SessionCheckpointHost {
5
5
  createCheckpoint(session: Session): Promise<void>;
@@ -57,7 +57,8 @@ export declare const SessionResponseTelemetryHost: unique symbol;
57
57
  export interface SessionResponseTelemetryHost {
58
58
  reportChatRequestResponseTelemetry(session: Session, result: NonNullable<Session['resultSubject']['value']>, isSuccessful: boolean, error: unknown, metadata: ModelResponseMetadata): Promise<void>;
59
59
  reportMessageResponseTelemetryStream(session: Session, usage: SessionResponseUsage | undefined, metadata: ModelResponseMetadata, error: unknown): Promise<void>;
60
- reportChatMessageStatus(session: Session, errorCode: string, error?: unknown): Promise<void>;
60
+ /** Status of one model call (`generation`); run failures no model call owns are not reported. */
61
+ reportChatMessageStatus(session: Session, errorCode: string, generation: ModelCallGeneration, error?: unknown): Promise<void>;
61
62
  }
62
63
  export type SessionResponseTelemetrySnapshot = Pick<NonNullable<Session['telemetry']>, 'modelId' | 'modelName' | 'currentTurn' | 'traceId'>;
63
64
  export declare const SessionResponseObserver: unique symbol;
@@ -4,7 +4,7 @@ import { Logger } from '../../../../telemetry/lib/common/index.js';
4
4
  import { BehaviorSubject } from 'rxjs';
5
5
  import { SessionRequestContextHost, SessionSettingsHost as SettingsManager, SessionUsageHost as UserStateManager } from './session-host-protocol.js';
6
6
  import { SessionBackgroundTaskHost as ToolManager, SessionCheckpointHost as CheckpointService, SessionProgressHost as ProgressSyncService, SessionResponseObserver as GalileoSessionBridge, SessionResponseTelemetryHost as TelemetryService, SessionSchedulerHost as CronSchedulerService, SessionSensitiveProjectionHost, SessionTaskLifecycleHost as AgentTaskManager } from './session-manager-host-protocol.js';
7
- import { AgentInputItemProcessor, InterruptionService, ModelResponseInterceptor, ModelResponseMetadata, Session, SessionFactory, SessionGetOptions, SessionHookManager, SessionManager, SessionStore } from './session-protocol.js';
7
+ import { AgentInputItemProcessor, InterruptionService, ModelResponseInterceptor, ModelResponseMetadata, OverrideModelSource, Session, SessionFactory, SessionGetOptions, SessionHookManager, SessionManager, SessionStore } from './session-protocol.js';
8
8
  import { SessionRunStateMachine } from './session-run-state-machine-protocol.js';
9
9
  export declare class SessionManagerImpl implements SessionManager, ApplicationLifecycle<Application> {
10
10
  protected readonly sessionFactory: SessionFactory;
@@ -32,6 +32,7 @@ export declare class SessionManagerImpl implements SessionManager, ApplicationLi
32
32
  private skipHistoryContext;
33
33
  private sessionStartTimes;
34
34
  private addHistoryLocks;
35
+ private promptAdmissions;
35
36
  private resultSubscriptions;
36
37
  private readonly resultSubscriptionOwners;
37
38
  /**
@@ -44,6 +45,8 @@ export declare class SessionManagerImpl implements SessionManager, ApplicationLi
44
45
  private readonly liveSessionsById;
45
46
  private overridePermissionModes;
46
47
  private overrideModels;
48
+ /** 与 overrideModels 同生命周期的意图来源(user / declared / materialized)。 */
49
+ private overrideModelSources;
47
50
  /**
48
51
  * Issue #12554:会话级 thinking override(按 sessionId 隔离)。
49
52
  * 由 ACP setSessionConfigOption('thought_level') 或 prompt _meta 写入。
@@ -106,6 +109,7 @@ export declare class SessionManagerImpl implements SessionManager, ApplicationLi
106
109
  private readonly loadedSessionIds;
107
110
  private resetIdleTimer;
108
111
  addHistory(session: Session, input: string | AgentInputItem[]): Promise<void>;
112
+ private writeHistory;
109
113
  /**
110
114
  * Record a UserPromptSubmit hook block as an in-band assistant message
111
115
  * (issue #71907, cc-aligned: cc surfaces a warning system message and ends the
@@ -123,6 +127,34 @@ export declare class SessionManagerImpl implements SessionManager, ApplicationLi
123
127
  * (use-message-sender). chalk=false because ACP does not strip ANSI codes.
124
128
  */
125
129
  private recordHookBlockedMessage;
130
+ /**
131
+ * 把一条 mod 打出来的 `$.ui.log` 落到当前 session 的可见消息流里。
132
+ *
133
+ * ## 与 `recordHookBlockedMessage` 的关系
134
+ *
135
+ * 二者走**同一条落地路径**(history + inputSubject + combineSubject +
136
+ * sessionStore.appendHistory),因此 TUI / ACP / persisted transcript 都用
137
+ * 既有渲染,不必新增 sessionUpdate 类型(对齐根 CODEBUDDY.md 的 ACP 约束)。
138
+ *
139
+ * ## 与 hook 阻断消息刻意不同的三点
140
+ *
141
+ * 1. **不动 `session.lastMessageId`**:hook-block 是回合终点,需要挂上 replay
142
+ * 分支;mod-log 是**装饰性**通知,如果推进 lastMessageId 会让 `/rewind`
143
+ * 退到"一条 log 中间",语义混乱。
144
+ * 2. **不挂 `parentId`**:同样出于 replay 分支洁净。
145
+ * 3. **`chalk: false`**:ACP 侧不剥 ANSI,chalk 转义码会露出到 Web UI;此外
146
+ * 宿主已在 `<plugin>: <text>` 里给足了归属信号,terminal 也不再需要额外
147
+ * 颜色包装(TUI 侧后续可按 `hookStatus === 'mod-log'` 做专属渲染)。
148
+ *
149
+ * ## 失败语义
150
+ *
151
+ * 与 hook-block 同款:写盘失败只记日志,不向外抛 —— mod 打日志不该把 CLI 弄挂。
152
+ *
153
+ * @param session 目标 session(宿主取当前 session 后传入)
154
+ * @param text 已由宿主前缀成 `<plugin>: <text>` 的完整行文
155
+ * @param plugin 发起本次调用的 mod 名(`origin.plugin`),用于前端识别
156
+ */
157
+ recordModLogMessage(session: Session, text: string, plugin: string): Promise<void>;
126
158
  private readonly inflightSessionStarts;
127
159
  emitSessionStart(session: Session, source: SessionStartSource): Promise<void>;
128
160
  create(options?: Partial<Session>, needHandleRunResult?: boolean, parentSession?: Session): Promise<Session>;
@@ -190,9 +222,11 @@ export declare class SessionManagerImpl implements SessionManager, ApplicationLi
190
222
  rename(session: Session, name: string): Promise<void>;
191
223
  setOverridePermissionMode(sessionId: string, mode: PermissionMode): void;
192
224
  getOverridePermissionMode(sessionId: string): PermissionMode | undefined;
193
- setOverrideModel(sessionId: string, model: string): void;
225
+ setOverrideModel(sessionId: string, model: string, source?: OverrideModelSource): void;
194
226
  getOverrideModel(sessionId: string): string | undefined;
195
- setRuntimeModel(session: Session | undefined, modelId: string): void;
227
+ getOverrideModelSource(sessionId: string): OverrideModelSource | undefined;
228
+ clearOverrideModel(sessionId: string): void;
229
+ setRuntimeModel(session: Session | undefined, modelId: string, source?: OverrideModelSource): void;
196
230
  setRuntimeOutputStyle(session: Session | undefined, style: string): void;
197
231
  /**
198
232
  * Issue #83229:把 settings.json 中的 model / outputStyle 读一次"钉"进 session.options,
@@ -2,6 +2,7 @@ import { Deferred } from '@celljs/core';
2
2
  import { type AgentInputItem, ApprovalOptions, type Checkpoint, FinalStopReason, NotificationType, PermissionMode, ReasoningEffortLevel, type ResponseStreamEvent, type RunItem, type RunResult, type RunState, type RunToolApprovalItem, type SdkCapabilities, SessionEndReason, SessionStartSource, type StreamedRunResult, type TerminalEvent, type ToolDeferOverlaySnapshot, ToolPermissionContext, type Usage } from '../../../../cbc-shared/lib/node/index.js';
3
3
  import { Command } from '../../../../product/lib/common/index.js';
4
4
  import { BehaviorSubject, Subject } from 'rxjs';
5
+ import type { CompactionLineage } from '../context/compaction-lineage.js';
5
6
  import { BackgroundTask } from './background-task-protocol.js';
6
7
  import type { SessionRunStateSnapshot } from './session-run-state-machine-protocol.js';
7
8
  import type { Lane, LanePointer, SessionKey, SessionStoreEntry } from './session-store-contract.js';
@@ -86,6 +87,7 @@ export type AgentState = 'agent_pending' | 'agent_start' | 'agent_tool_start' |
86
87
  * 则 emit,触发 UI 显示"正在同步文件"提示)
87
88
  */
88
89
  export type AgentPhase = 'preparing' | 'model_requesting' | 'model_streaming' | 'model_done' | 'tool_executing' | 'waiting_for_permission' | 'waiting_for_user' | 'retrying' | 'finalization_file_projection_sync' | 'finalization_file_projection_sync_notify' | 'idle';
90
+ export type AgentRetryReason = 'network';
89
91
  export interface AgentPhaseInfo {
90
92
  phase: AgentPhase;
91
93
  toolName?: string;
@@ -102,6 +104,13 @@ export interface AgentPhaseInfo {
102
104
  current: number;
103
105
  total: number;
104
106
  };
107
+ /**
108
+ * 仅 retrying phase 使用,经 ACP `_meta['codebuddy.ai/agentPhase']` 透传给上层。
109
+ * 缺省表示原因未分类(如流超时),不代表网络正常。
110
+ */
111
+ retry?: {
112
+ reason: AgentRetryReason;
113
+ };
105
114
  }
106
115
  export declare const AgentPhaseUtils: {
107
116
  /** Create an AgentPhaseInfo with the current timestamp. */
@@ -353,6 +362,14 @@ export interface Session {
353
362
  * field and pass it through as `options.maxTurns` explicitly.
354
363
  */
355
364
  lastRunMaxTurns?: number;
365
+ /**
366
+ * Latest agent-loop model call number (`providerData.stepSeq`). Unlike the
367
+ * SDK turn counter it survives runs, compaction and resume; see
368
+ * `allocateModelStepSeq`.
369
+ */
370
+ modelStepSeq?: number;
371
+ /** Compactions of this Session's context; see `getCompactionLineage`. */
372
+ compactionLineage?: CompactionLineage;
356
373
  queue: AgentInputItem[];
357
374
  queueSubject: BehaviorSubject<AgentInputItem[]>;
358
375
  /**
@@ -860,7 +877,7 @@ export interface SubagentInvocationRecord {
860
877
  lifecycle: SubagentLifecycleSnapshot;
861
878
  }
862
879
  export type SubagentLifecycleDescriptor = Omit<SubagentLifecycleSnapshot, 'status' | 'updatedAt' | 'usage'>;
863
- export type CombineEvent = (AgentInputItemEvent | ModelRawResponseEvent | ResultEndEvent | InterruptResultEvent | NoticeEvent | SubagentStatusEvent | CompactionLifecycleEvent | TerminalEvent) & CombineEventMeta;
880
+ export type CombineEvent = (AgentInputItemEvent | AgentSdkStreamEvent | ModelRawResponseEvent | ResultEndEvent | InterruptResultEvent | NoticeEvent | SubagentStatusEvent | CompactionLifecycleEvent | TerminalEvent) & CombineEventMeta;
864
881
  export interface CompactionLifecycleEvent {
865
882
  type: 'compaction';
866
883
  data: {
@@ -875,6 +892,11 @@ export interface SubagentStatusEvent {
875
892
  type: 'subagent_status';
876
893
  data: SubagentLifecycleSnapshot;
877
894
  }
895
+ /** Original SDK stream payload, observed by the existing single stream consumer. */
896
+ export interface AgentSdkStreamEvent {
897
+ type: 'sdk';
898
+ data: import('../../../../cbc-shared/lib/node/index.js').RunStreamEvent;
899
+ }
878
900
  export interface AgentInputItemEvent {
879
901
  type: 'input';
880
902
  data: AgentInputItem;
@@ -1063,6 +1085,13 @@ export interface SessionRewindMutationOptions {
1063
1085
  cwd: string;
1064
1086
  headMessageId: string | undefined;
1065
1087
  }
1088
+ /**
1089
+ * model override 的意图来源:决定该值是否等价于「用户显式选择」。
1090
+ * - 'user':/model 命令、ACP set_model、SDK 控制信号等用户动作;
1091
+ * - 'declared':主 Agent 声明模型(declaredModel)联动写入;
1092
+ * - 'materialized':Web UI 会话装配期钉住的兜底解析值(非用户意图)。
1093
+ */
1094
+ export type OverrideModelSource = 'user' | 'declared' | 'materialized';
1066
1095
  export interface SessionManager {
1067
1096
  getCurrent(): Session;
1068
1097
  setCurrent(session: Session): void;
@@ -1088,6 +1117,18 @@ export interface SessionManager {
1088
1117
  * before injecting `additionalContext`.
1089
1118
  */
1090
1119
  emitSessionStart(session: Session, source: SessionStartSource): Promise<void>;
1120
+ /**
1121
+ * Record a mod-plugin `$.ui.log` line as a user-visible message on the
1122
+ * session transcript (mirrors `recordHookBlockedMessage` — same
1123
+ * inputSubject / combineSubject / sessionStore path — but leaves
1124
+ * `lastMessageId` and `parentId` untouched because mod logs are
1125
+ * decorative and must not become anchors on the replay branch).
1126
+ *
1127
+ * @param session target session (host resolves current session and passes it in)
1128
+ * @param text already prefixed as `<plugin>: <text>` by the host bridge
1129
+ * @param plugin the calling mod's name (`origin.plugin`), for provider metadata
1130
+ */
1131
+ recordModLogMessage(session: Session, text: string, plugin: string): Promise<void>;
1091
1132
  addHistory(session: Session, input: string | AgentInputItem[]): Promise<void>;
1092
1133
  save(session: Session): Promise<void>;
1093
1134
  /** Initialize an immutable full snapshot for a new fork; target must be absent or empty. */
@@ -1165,11 +1206,15 @@ export interface SessionManager {
1165
1206
  setOverridePermissionMode(sessionId: string, mode: PermissionMode): void;
1166
1207
  getOverridePermissionMode(sessionId: string): PermissionMode | undefined;
1167
1208
  /**
1168
- * 设置 session 的 model 覆盖值(来自 SDK control signal)
1169
- * 这些值会覆盖 CLI 参数和配置文件的设置
1209
+ * 设置 session 的 model 覆盖值。source 记录意图来源,供「是否用户显式选择」判定:
1210
+ * - 'user'(默认):/model 命令、ACP set_model、SDK 控制信号等用户动作;
1211
+ * - 'declared':主 Agent 声明模型(declaredModel)联动写入;
1212
+ * - 'materialized':Web UI 会话装配期钉住的兜底解析值(非用户意图)。
1170
1213
  */
1171
- setOverrideModel(sessionId: string, model: string): void;
1214
+ setOverrideModel(sessionId: string, model: string, source?: OverrideModelSource): void;
1172
1215
  getOverrideModel(sessionId: string): string | undefined;
1216
+ getOverrideModelSource(sessionId: string): OverrideModelSource | undefined;
1217
+ clearOverrideModel(sessionId: string): void;
1173
1218
  /**
1174
1219
  * 设置会话运行时模型:同步写 session.options.model + requestOptions.model + override map。
1175
1220
  *
@@ -1178,7 +1223,7 @@ export interface SessionManager {
1178
1223
  * 供 applyOverrideModel 每轮重建 requestOptions(Issue #82146)。/model 命令与模型面板
1179
1224
  * 共用此入口;ACP set_model(applyRuntimeSessionModel)仍为独立实现,待统一收敛。
1180
1225
  */
1181
- setRuntimeModel(session: Session | undefined, modelId: string): void;
1226
+ setRuntimeModel(session: Session | undefined, modelId: string, source?: OverrideModelSource): void;
1182
1227
  /**
1183
1228
  * 设置会话运行时 outputStyle:同步写 session.options.outputStyle。
1184
1229
  *
@@ -1502,6 +1547,7 @@ export interface InterruptionService {
1502
1547
  approve(item: RunToolApprovalItem, options?: ApprovalOptions): void;
1503
1548
  reject(item: RunToolApprovalItem, options?: {
1504
1549
  decision?: 'deny' | 'rejectAndExitPlan';
1550
+ cancelTurn?: boolean;
1505
1551
  }): void;
1506
1552
  waitFor(session: Session): Promise<void>;
1507
1553
  /** Resolve the main/leader session for a given session (returns self if already main). */
@@ -1712,6 +1758,12 @@ export interface TurnMetricsReporter {
1712
1758
  */
1713
1759
  unregister(sessionId: string): void;
1714
1760
  }
1761
+ /** Ids of one model call, as stamped by the model wrapper. */
1762
+ export interface ModelCallGeneration {
1763
+ messageId: string;
1764
+ conversationRequestId?: string;
1765
+ stepSeq?: number;
1766
+ }
1715
1767
  export interface ModelResponseMetadata {
1716
1768
  /** 响应中的模型 ID */
1717
1769
  model?: string;
@@ -1725,6 +1777,8 @@ export interface ModelResponseMetadata {
1725
1777
  * 都带 providerData.messageId === 此值,handleContentFilteredResponse 据此剔除并替换为安全提示。
1726
1778
  */
1727
1779
  contentFilterMessageId?: string;
1780
+ /** Correlation of the generation that just completed, as stamped by the model wrapper. */
1781
+ generation?: ModelCallGeneration;
1728
1782
  usage?: {
1729
1783
  prompt_tokens: number;
1730
1784
  completion_tokens: number;
@@ -1,5 +1,5 @@
1
1
  import type { Observable } from 'rxjs';
2
- import type { Session } from './session-protocol.js';
2
+ import type { AgentRetryReason, Session } from './session-protocol.js';
3
3
  export declare const SessionRunStateMachine: unique symbol;
4
4
  export declare const SessionRunStateProjectionService: unique symbol;
5
5
  export declare const SESSION_RUN_STATE_PROJECTION_SCHEMA: 'session-run-state.v1';
@@ -144,6 +144,7 @@ export type SessionRunEvent = {
144
144
  } | {
145
145
  type: SessionRunEventType.RETRYING;
146
146
  reason?: string;
147
+ retryReason?: AgentRetryReason;
147
148
  } | {
148
149
  type: SessionRunEventType.COMPACT_STARTED;
149
150
  reason?: string;
@@ -189,6 +190,18 @@ export interface SessionRunStateMachine {
189
190
  */
190
191
  getChange$(session: Session, skipFirst?: boolean): Observable<void>;
191
192
  }
193
+ export declare const ModelRequestRetryPhase: unique symbol;
194
+ /**
195
+ * 模型请求层(宿主 provider)在同一次请求内部退避重发时,借此把会话投影为 retrying。
196
+ * 状态写入与守卫收口在 core,宿主只包住退避等待,不直接驱动状态机。
197
+ */
198
+ export interface ModelRequestRetryPhase {
199
+ /**
200
+ * `wait` 期间会话显示 retrying 并携带 `reason`;结束(含抛错 / 取消)后恢复 model_requesting。
201
+ * 非本轮主请求(无 session、辅助型 purpose、状态不在 model_requesting)时只执行 `wait`。
202
+ */
203
+ during<T>(session: Session | undefined, reason: AgentRetryReason, wait: () => Promise<T>): Promise<T>;
204
+ }
192
205
  /**
193
206
  * Pure derivations from a `SessionRunStatus`. The state machine implementation
194
207
  * MUST keep its instance methods (`getLifecycle`, `isBusy`, etc.) consistent
@@ -9,11 +9,18 @@ export declare function hasExhaustedStreamTimeoutRetryBudget(session: Session, i
9
9
  /**
10
10
  * `finish_reason=error` 且没有可用输出的两种空流:reasoning-only 与 no-token。
11
11
  * placeholder(空 200 / 心跳帧)仍是会话层终态,由拦截器切一次备站。
12
+ *
13
+ * 额外的时长闸门(#132616):这两种 kind 之所以可重试,前提是「上游瞬时失败」——秒级
14
+ * 空响应重跑一次大概率就好了。但当这条流已经跑满上游的硬时限才收到 error 时,前提不成立:
15
+ * 同一段 prompt 重跑必然再次跑满同一个时限。实测 7 个会话全部重试、全部再次撞墙、0 次恢复,
16
+ * 而 `#130098` 把预算从 1 提到 3 之后,同样的输入会从 2×900s 变成 4×900s ≈ 60 分钟静默。
17
+ * 重试的期望收益不随 elapsed 增长,成本却线性增长,所以按 elapsed 收口。
12
18
  */
13
19
  export declare function isRetryableEmptyStreamError(error: unknown): boolean;
14
20
  /**
15
21
  * Empty 200 / placeholder-only:拦截器最多切一次备站,会话层终态(#115866)。
16
- * reasoning-only / no-token + finish_reason=error:上游瞬时失败,按 error 预算重试。
22
+ * reasoning-only / no-token + finish_reason=error:上游瞬时失败,按 error 预算重试;
23
+ * 已烧满上游硬时限的那些除外,见 {@link isRetryableEmptyStreamError} 的时长闸门(#132616)。
17
24
  * 流空闲超时 / 首 token 超时:按各自的超时预算重试。
18
25
  */
19
26
  export declare function shouldAutoRetryStreamTimeout(session: Session, error: unknown): boolean;