@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
@@ -18,6 +18,12 @@ import { Account, APIResult, AuthenticationManager, AuthenticationProvider, type
18
18
  */
19
19
  export declare function setAuthDoInitProbeSink(sink: ((line: string) => void) | undefined): void;
20
20
  export declare class AuthenticationManagerImpl implements AuthenticationManager {
21
+ /** Host observation hook, called after currentSessionSubject published the session. No-op by default. */
22
+ protected observeSession(_session: AuthSession | undefined, _source: string, _observation?: unknown): void;
23
+ /** Captures host metadata while the storage publisher's synchronous context is available. */
24
+ protected captureSessionObservation(): unknown;
25
+ private notifySessionObserver;
26
+ private safelyCaptureSessionObservation;
21
27
  protected readonly productManager: ProductManager;
22
28
  protected readonly productEnvService: ProductEnvService;
23
29
  protected readonly authenticationProvider: Provider<AuthenticationProvider>;
@@ -0,0 +1,36 @@
1
+ import { type Span } from '../../../telemetry/lib/common/index.js';
2
+ /** Login observation helpers. Every export swallows its own failures; authentication never depends on them. */
3
+ /** W3C context for the login chain only; the shared Span.requestHeaders stay legacy-only. */
4
+ export declare function loginTraceCarrier(span?: Span): {
5
+ traceparent?: string;
6
+ tracestate?: string;
7
+ };
8
+ /** Only for a host that registered login observation; other products keep their legacy login trace unchanged. */
9
+ export declare function addLoginSpanEvent(span: Span | undefined, name: string, attributes?: Record<string, string>): void;
10
+ /** Host login observation context registered together with setLoginStepCallback. */
11
+ export interface LoginObservationContext {
12
+ /** Reauthentication correlation (`recovery_of_loss_id` / `previous_auth_session_id`). */
13
+ recovery?: Record<string, string>;
14
+ /** The host's login attempt ID; the web login page records it as the owner of its journey. */
15
+ journeyOwnerId?: string;
16
+ /** Entry context of the host-owned login journey. */
17
+ traceparent?: string;
18
+ }
19
+ export declare function setLoginObservationContext(context?: LoginObservationContext): void;
20
+ export declare function appendLoginTraceParams(url: URL, span?: Span): void;
21
+ /** Web login page parameters that join the host login journey. */
22
+ export declare function appendLoginObservationParams(url: URL, handoffSpan?: Span): void;
23
+ /** Narrow host hook: no credential/header objects or telemetry implementation cross this boundary. */
24
+ export interface AuthRequestObservationInput {
25
+ method?: string;
26
+ url?: string;
27
+ traceparent?: string;
28
+ }
29
+ export type AuthRequestObservation = (request: AuthRequestObservationInput) => ((status?: number, businessCode?: number) => void) | undefined;
30
+ export declare function setAuthRequestObservation(observer?: AuthRequestObservation): void;
31
+ export declare function observeAuthRequest(config: {
32
+ method?: string;
33
+ url?: string;
34
+ headers?: Record<string, unknown>;
35
+ }): void;
36
+ export declare function observeAuthResponse(config: unknown, status?: number, businessCode?: unknown): void;
@@ -67,6 +67,27 @@ export declare const HTTP_HEADER_NO_AUTHORIZATION = "X-No-Authorization";
67
67
  * 用于请求发往自定义端点(如 LiteLLM 网关)时,避免携带 copilot 内部认证信息。
68
68
  */
69
69
  export declare const HTTP_HEADER_SKIP_AUTH_INTERCEPTOR = "X-Skip-Auth-Interceptor";
70
+ /**
71
+ * `auth/state` 额外请求头数据源(可选 DI 依赖,中立抽象;Issue #94672)。
72
+ *
73
+ * authentication 包对具体头一无所知:只负责在登录链路的 `auth/state` 请求上
74
+ * 把本 provider 返回的所有 header 原样透传。**具体带哪些头、值怎么取,全部由
75
+ * 业务侧(WorkBuddy Desktop daemon 装配层)在实现里决定**,让上游 authentication
76
+ * 包无需反向依赖 Electron / Turing / qimei 等下游能力。
77
+ *
78
+ * 由宿主**可选**绑定到 CellJS 容器;未绑定(CLI / Web / headless / 单测)时按
79
+ * `@Optional()` 注入为 undefined,`auth/state` 不携带任何额外 header,对这些形态
80
+ * 零影响。
81
+ *
82
+ * 语义约定:**尽力而为、不等待、不阻断登录**。`provide()` 应立即返回当前快照
83
+ * (读缓存 / env),拿不到的头业务侧自己省略即可;内部异常由 authentication 包
84
+ * 兜底吞掉,绝不因遥测公参阻断登录。
85
+ */
86
+ export declare const AuthStateHeaderProvider: unique symbol;
87
+ export interface AuthStateHeaderProvider {
88
+ /** 返回要附加到 `auth/state` 请求上的额外 header 集合(可能为空)。 */
89
+ provide(): Promise<Record<string, string>>;
90
+ }
70
91
  export declare const enum Edition {
71
92
  Pro = "pro",
72
93
  Personal = "personal",
@@ -1,8 +1,9 @@
1
1
  import { RestOperations } from '@celljs/http';
2
2
  import { AuthenticationType, ClientInfoProvider, ProductManager } from '../../../product/lib/common/index.js';
3
3
  import { ExternalUriOpener } from '../../../runtime/lib/common/index.js';
4
- import { Logger } from '../../../telemetry/lib/common/index.js';
5
- import { Account, APIResult, AuthenticationProvider, AuthSession, LoginContext, LogoutOptions, ProductEnvService, SignContext, SignLicenseError } from './authentication-protocol.js';
4
+ import { Logger, type Span } from '../../../telemetry/lib/common/index.js';
5
+ import { type LoginObservationContext } from './authentication-observation.js';
6
+ import { Account, APIResult, AuthenticationProvider, AuthSession, AuthStateHeaderProvider, LoginContext, LogoutOptions, ProductEnvService, SignContext, SignLicenseError } from './authentication-protocol.js';
6
7
  /** 登录漏斗步骤回调,由外部消费者(如 workbuddy-server)注入上报逻辑。 */
7
8
  export type LoginStepCallback = (step: string, dims: Record<string, string>) => void;
8
9
  /**
@@ -10,9 +11,14 @@ export type LoginStepCallback = (step: string, dims: Record<string, string>) =>
10
11
  * @param callback 回调函数,undefined 表示清除
11
12
  * @param onlyIfVersion 可选,传入时只有当前 version 匹配才执行清除(防止旧轮 finally 覆盖新轮)
12
13
  * @param loginSessionId 可选,当前登录会话 ID,供 openAuthUrl 注入到 authUrl 中传递给 Web 登录页
14
+ * @param observation 可选,宿主登录观测上下文,与回调同生命周期
13
15
  * @returns 设置后的 version
14
16
  */
15
- export declare function setLoginStepCallback(callback: LoginStepCallback | undefined, onlyIfVersion?: number, loginSessionId?: string): number;
17
+ export declare function setLoginStepCallback(callback: LoginStepCallback | undefined, onlyIfVersion?: number, loginSessionId?: string, observation?: LoginObservationContext): number;
18
+ /** Whether the host registered login observation; other products keep their login URLs unchanged. */
19
+ export declare function hasHostLoginObservation(): boolean;
20
+ /** 让 Web 登录页加入宿主登录 journey(仅国内版 workbuddy 平台);宿主未注册观测时不改 URL。 */
21
+ export declare function appendHostLoginJourneyParams(url: URL, platform: string | undefined, handoffSpan?: Span): void;
16
22
  interface AuthState {
17
23
  state: string;
18
24
  authUrl: string;
@@ -35,6 +41,11 @@ export declare class ExternalLinkAuthenticationProvider implements Authenticatio
35
41
  protected readonly restOperations: RestOperations;
36
42
  protected readonly logger: Logger;
37
43
  protected readonly clientInfoProvider: ClientInfoProvider;
44
+ /**
45
+ * `auth/state` 额外请求头数据源(Issue #94672)。可选依赖:仅 WorkBuddy Desktop
46
+ * daemon 绑定,CLI / Web / headless / 单测未绑定时为 undefined,不携带额外 header。
47
+ */
48
+ protected readonly authStateHeaderProvider?: AuthStateHeaderProvider;
38
49
  private configuration;
39
50
  /**
40
51
  * The last auth URL that was opened in the browser.
@@ -57,8 +68,13 @@ export declare class ExternalLinkAuthenticationProvider implements Authenticatio
57
68
  refreshSession(session: AuthSession, ctx: SignContext): Promise<AuthSession>;
58
69
  removeSession(session?: AuthSession, options?: LogoutOptions): Promise<void>;
59
70
  switchAccount(account: Account, authSession: AuthSession, ctx: SignContext): Promise<AuthSession>;
71
+ /**
72
+ * 取 `auth/state` 的额外请求头(Issue #94672)。provider 未绑定(CLI / Web /
73
+ * headless / 单测)返回空对象;实现内部任何异常都吞掉退化为空,绝不阻断登录。
74
+ */
75
+ private resolveAuthStateExtraHeaders;
60
76
  private fetchAuthState;
61
- protected openAuthUrl(authState: AuthState): Promise<void>;
77
+ protected openAuthUrl(authState: AuthState, handoffSpan?: Span): Promise<void>;
62
78
  /**
63
79
  * 打开登录页前对 authUrl 追加环境相关参数的可覆写钩子。
64
80
  * 基类默认不追加任何参数;子类(如 CLI IOA 分支)覆写此方法即可注入自己的 query,
@@ -10,3 +10,4 @@ export * from './custom-token-authentication-storage.js';
10
10
  export * from './wx-authentication-provider.js';
11
11
  export * from './product-env-service.js';
12
12
  export * from './account-utils.js';
13
+ export * from './authentication-observation.js';
@@ -30,6 +30,7 @@ export interface CheckpointService {
30
30
  * @param options.autoAddToHistory - 是否自动添加到 session history (默认 true)
31
31
  * @param options.messageId - 快照关联的消息ID (默认为空)
32
32
  * @param options.isSnapshotUpdate - 是否为快照更新 (默认 false)
33
+ * @param options.filePath - 只更新该路径的文件版本 (默认更新全部已跟踪文件)
33
34
  * @returns 创建的 checkpoint,无需创建时返回 undefined
34
35
  */
35
36
  createCheckpoint(session: Session, options?: {
@@ -37,6 +38,7 @@ export interface CheckpointService {
37
38
  throwOnError?: boolean;
38
39
  messageId?: string;
39
40
  isSnapshotUpdate?: boolean;
41
+ filePath?: string;
40
42
  }): Promise<Checkpoint | undefined>;
41
43
  /** 回退到指定 checkpoint */
42
44
  revertToCheckpoint(session: Session, checkpoint: Checkpoint, scope: RevertScope): Promise<void>;
@@ -16,6 +16,7 @@ export declare class CheckpointServiceImpl implements CheckpointService {
16
16
  throwOnError?: boolean;
17
17
  messageId?: string;
18
18
  isSnapshotUpdate?: boolean;
19
+ filePath?: string;
19
20
  }): Promise<Checkpoint | undefined>;
20
21
  revertToCheckpoint(session: Session, checkpoint: Checkpoint, scope: import('./checkpoint-protocol.js').RevertScope): Promise<void>;
21
22
  getRewindableCheckpoints(session: Session): Checkpoint[];
@@ -550,6 +550,19 @@ export interface AgentServiceRunControlOptions {
550
550
  bypassMessageQueue?: boolean;
551
551
  /** Input is already present in Session history; do not append it again. */
552
552
  skipAddHistory?: boolean;
553
+ /** Let an interactive host route external `/compact` before normal run admission. */
554
+ routeManualCompact?: boolean;
555
+ /**
556
+ * Per-call out-signal of `runDefault`: invoked once, synchronously, after
557
+ * this call passed run admission (its startup controller is installed on
558
+ * the Session) and before the agent is resolved. Not invoked when admission
559
+ * throws. It says nothing about the model having started or the run
560
+ * succeeding; without `bypassMessageQueue` the run may still be queued
561
+ * afterwards (see `onEnqueued`). A throwing callback is logged and does not
562
+ * affect the run. Internal re-runs pass fresh options and never carry it; it
563
+ * is stripped before AgentRunRequest and the SDK.
564
+ */
565
+ onAdmitted?: () => void;
553
566
  }
554
567
  /** Options for an isolated run or an SDK RunState resume. */
555
568
  export type AgentStandardRunOptions<TContext = Session> = AgentSdkRunOptions<TContext> & AgentServiceRunControlOptions & {
@@ -566,6 +579,8 @@ export type AgentStandardRunOptions<TContext = Session> = AgentSdkRunOptions<TCo
566
579
  * cannot clobber each other's outcome.
567
580
  */
568
581
  onEnqueued?: () => void;
582
+ /** Exact result of this arrival, including execution after a queue drain. */
583
+ onResult?: (result: NonNullable<Session['resultSubject']['value']>) => void;
569
584
  };
570
585
  /**
571
586
  * Explicitly claim the current process-local logical turn.
@@ -585,12 +600,19 @@ export interface AgentService {
585
600
  tryCloseTaskSession?(session: Session, result: NonNullable<Session['resultSubject']['value']>): Promise<boolean>;
586
601
  /** Stop accepting task work and join its physical runs before releasing dependencies. */
587
602
  retireTaskSession?(session: Session): Promise<void>;
603
+ /**
604
+ * 有界等待该 session 上的物理 run 收尾(含它把最终产出写进 history)。
605
+ *
606
+ * `agent_end` 早于 run 的 finalize,所以「上一轮 history 已写完」不能靠 `agent_end`
607
+ * 判定;需要该因果的调用方(队列 drain)join 到这里。超时会放行并告警,不会挂死。
608
+ */
609
+ waitForRunsSettled?(session: Session): Promise<void>;
588
610
  run<TAgent extends Agent<any, any>>(agent: TAgent, input: string | AgentInputItem[], options: AgentCurrentContinuationOptions): Promise<void>;
589
611
  run<TAgent extends Agent<any, any>, TContext = Session>(agent: TAgent, input: string | AgentInputItem[] | RunState<TContext, TAgent>, options?: AgentStandardRunOptions<TContext>): Promise<void>;
590
612
  runDefault<TAgent extends Agent<any, any>>(input: string | AgentInputItem[], options: AgentCurrentContinuationOptions): Promise<void>;
591
613
  runDefault<TAgent extends Agent<any, any>, TContext = Session>(input: string | AgentInputItem[] | RunState<TContext, TAgent>, options?: AgentStandardRunOptions<TContext>): Promise<void>;
592
- runOneTime<TContext = Session>(agentName: string, input: string | AgentInputItem[], options?: NonStreamRunOptions<TContext>): Promise<string>;
593
- runOneTime<TContext = Session>(agentName: string, input: string | AgentInputItem[], options?: StreamRunOptions<TContext>): Promise<string>;
614
+ runOneTime<TContext = Session>(agentName: string, input: string | AgentInputItem[], options?: NonStreamRunOptions<TContext> & OneTimeRunOptions): Promise<string>;
615
+ runOneTime<TContext = Session>(agentName: string, input: string | AgentInputItem[], options?: StreamRunOptions<TContext> & OneTimeRunOptions): Promise<string>;
594
616
  /**
595
617
  * Run a one-shot agent call in a forked (isolated) session that inherits
596
618
  * the conversation history from the parent session. The forked session is
@@ -656,6 +678,11 @@ export interface ForkedAgentOptions {
656
678
  /** Optional cap on number of turns (default: 1 for one-shot) */
657
679
  maxTurns?: number;
658
680
  }
681
+ /** Options of `runOneTime` on top of the SDK run options. */
682
+ export interface OneTimeRunOptions {
683
+ /** X-Agent-Purpose of the call; defaults to the agent's `AGENT_PURPOSE_MAP` entry, else its name. */
684
+ purpose?: string;
685
+ }
659
686
  export interface RunRequest {
660
687
  prompt?: string;
661
688
  inputFormat?: 'text' | 'stream-json';
@@ -697,6 +724,8 @@ export interface AgentRunRequest<TContext = Session> extends SessionOptions {
697
724
  skipAddHistory?: boolean;
698
725
  bypassMessageQueue?: boolean;
699
726
  inputOrigin?: AgentRunOrigin;
727
+ /** Process-local arrival callback; never passed to the SDK. */
728
+ onResult?: AgentStandardRunOptions['onResult'];
700
729
  traceId?: string;
701
730
  /**
702
731
  * #59319-5: 普通 run 二次裁决发现 session 仍 busy 时由 AgentService 设置。
@@ -58,7 +58,9 @@ export declare enum AgentPurpose {
58
58
  /** Auto mode permission risk classification (runOneTime: AUTO_MODE_CLASSIFIER) */
59
59
  AutoModeClassifier = "auto_mode_classifier",
60
60
  /** Automation scheduled task execution */
61
- Automation = "automation"
61
+ Automation = "automation",
62
+ /** `/btw` side question on a forked Session (runForked); Claude Code's `side_question` source */
63
+ SideQuestion = "side_question"
62
64
  }
63
65
  /**
64
66
  * Dynamic purpose prefix for built-in subagents.
@@ -127,6 +129,9 @@ export declare const AUXILIARY_PURPOSES: ReadonlySet<string>;
127
129
  * 时 purpose 可能尚未设置的普通对话仍按原行为发出 MODEL_REQUEST_STARTED。
128
130
  */
129
131
  export declare function isAuxiliaryPurpose(purpose?: string): boolean;
132
+ /** Purposes of compaction summary calls (X-Agent-Type `compaction`). */
133
+ export declare const COMPACTION_PURPOSES: ReadonlySet<string>;
134
+ export declare function isCompactionPurpose(purpose?: string): boolean;
130
135
  /**
131
136
  * 按 purpose 旁路 agent 生命周期事件(agent_start / agent_end / tool / handoff)。
132
137
  *
@@ -145,9 +150,8 @@ export declare function isAuxiliaryPurpose(purpose?: string): boolean;
145
150
  *
146
151
  * 因此这里只收 PreMessage 这一种 purpose。
147
152
  *
148
- * 依赖前提:`PreMessageCompactStrategy` 在 runOneTime 前后设置 / 还原
149
- * `session.agentPurpose`,且用 try/finally 保证异常路径也会还原——否则 purpose 泄漏
150
- * 会让**主 run** 也被误旁路,反而放大本要修复的孤儿 run 问题。
153
+ * The purpose is scoped to the summary call (`runOneTime` → `runWithAgentPurpose`), so it
154
+ * cannot leak onto the pending main run.
151
155
  *
152
156
  * multi-session(#44317)回归时,PreMessage 承载应改回临时子 Session;本名单保留为
153
157
  * 冗余防线即可(临时 Session 上旁路是无害的)。
@@ -0,0 +1,46 @@
1
+ import type { AgentType } from '../../../../telemetry/lib/common/index.js';
2
+ interface PurposeCarrier {
3
+ agentPurpose?: string;
4
+ conversationRequestId?: string;
5
+ }
6
+ /**
7
+ * Runs an auxiliary model call (title, summary, WebFetch analysis, ...) on a
8
+ * caller-owned Session without writing its purpose / request id onto the shared
9
+ * Session, where a concurrent main run would read and send them as its own.
10
+ */
11
+ export declare function runWithAgentPurpose<T>(session: object, purpose: string, callback: () => T, options?: {
12
+ conversationRequestId?: string;
13
+ }): T;
14
+ /** True when the current async chain is an auxiliary call scoped to `session`. */
15
+ export declare function isInAgentPurposeScope(session: object | undefined): boolean;
16
+ /** Purpose of the model call running in the current async chain. */
17
+ export declare function getEffectiveAgentPurpose(session: PurposeCarrier | undefined): string | undefined;
18
+ /** Request id of the model call running in the current async chain. */
19
+ export declare function getEffectiveConversationRequestId(session: PurposeCarrier | undefined): string | undefined;
20
+ /** Purposes whose model calls are steps of a Session's own agent loop. */
21
+ export declare function isMainConversationPurpose(purpose: string | undefined): boolean;
22
+ /** True when the model call in the current async chain is a step of `session`'s agent loop. */
23
+ export declare function isMainLoopModelCall(session: PurposeCarrier | undefined): boolean;
24
+ /** True when the model call in the current async chain has an `AUXILIARY_PURPOSES` purpose. */
25
+ export declare function isAuxiliaryPurposeCall(session: PurposeCarrier | undefined): boolean;
26
+ /**
27
+ * Runs `callback` outside any purpose scope. A run started from a helper call's async
28
+ * chain (e.g. a queued message drained on its agent_end) is a new agent-loop run.
29
+ */
30
+ export declare function runOutsideAgentPurposeScope<T>(callback: () => T): T;
31
+ export type ModelCallAgentType = AgentType;
32
+ /** Role of the Session's own agent loop, for request-level events. */
33
+ export declare function resolveSessionAgentType(session: {
34
+ meta?: Record<string, unknown>;
35
+ }): 'main' | 'subagent' | 'team';
36
+ /**
37
+ * Role of the model call in the current async chain (X-Agent-Type / telemetry
38
+ * `agentType`), mirroring Claude Code's `x-claude-code-request-class`: compaction
39
+ * summaries report `compaction`, other one-shot helpers (title, WebFetch analysis,
40
+ * ...) report `auxiliary`, whatever Session they run on. The specific helper
41
+ * stays in X-Agent-Purpose.
42
+ */
43
+ export declare function resolveModelCallAgentType(session: PurposeCarrier & {
44
+ meta?: Record<string, unknown>;
45
+ }): ModelCallAgentType;
46
+ export {};
@@ -3,10 +3,11 @@ import { AuthenticationManager } from '../../../../authentication/lib/common/ind
3
3
  import { type AbortLinkDisposer, Agent, type AgentInputItem, type NonStreamRunOptions, RunState, type StreamRunOptions } from '../../../../cbc-shared/lib/node/index.js';
4
4
  import { type LanguageModel } from '../../../../product/lib/common/index.js';
5
5
  import { Logger } from '../../../../telemetry/lib/common/index.js';
6
+ import { type ManualCompactRequestHandler as ManualCompactRequestHandlerContract } from '../context/context-protocol.js';
6
7
  import { type FileRollbackOperationLock as FileRollbackOperationLockContract } from '../file-rollback/file-rollback-service-protocol.js';
7
8
  import { Session, SessionManager } from '../session/session-protocol.js';
8
9
  import { SessionRunStateMachine } from '../session/session-run-state-machine-protocol.js';
9
- import { type AgentCurrentContinuationOptions, AgentManager, AgentRunInterceptor, AgentRunRequest, AgentService, type AgentStandardRunOptions, RunnerProvider } from './agent-protocol.js';
10
+ import { type AgentCurrentContinuationOptions, AgentManager, AgentRunInterceptor, AgentRunRequest, AgentService, type AgentStandardRunOptions, type OneTimeRunOptions, RunnerProvider } from './agent-protocol.js';
10
11
  import { type AgentRunScope as IAgentRunScope } from './agent-run-scope.js';
11
12
  import { AgentPluginRefresh, AgentRunObserver, AgentRuntimeResolver } from './agent-runtime-protocol.js';
12
13
  export declare class AgentServiceImpl implements AgentService {
@@ -22,6 +23,7 @@ export declare class AgentServiceImpl implements AgentService {
22
23
  protected readonly agentRunInterceptorProvider: Provider<AgentRunInterceptor>;
23
24
  protected readonly fileRollbackOperationLock?: FileRollbackOperationLockContract;
24
25
  protected readonly logger: Logger;
26
+ protected readonly manualCompactRequestHandler?: ManualCompactRequestHandlerContract;
25
27
  /**
26
28
  * Preserve the pre-start cancellation snapshot across runDefault's agent
27
29
  * lookup controller and run()'s own controller. This is process-local
@@ -40,6 +42,20 @@ export declare class AgentServiceImpl implements AgentService {
40
42
  protected getLifecycleOwners(): WeakMap<Session, AbortController>;
41
43
  tryCloseTaskSession(session: Session, result: NonNullable<Session['resultSubject']['value']>): Promise<boolean>;
42
44
  retireTaskSession(session: Session): Promise<void>;
45
+ waitForRunsSettled(session: Session): Promise<void>;
46
+ /**
47
+ * 有界 join:等到该 session 上的物理 run 全部交还 lifecycle owner 与 in-flight 信号。
48
+ *
49
+ * 为什么需要它而不是直接看 `agent_end`:`finalizeRun` 晚于本轮把最终产出写进
50
+ * history,`agent_end` 却早于 `finalizeRun`。任何依赖「上一轮 history 已写完」这个
51
+ * 因果的调用方(如队列 drain)必须 join 到这里。
52
+ *
53
+ * Bounded: `runSettledSubject` is optional, so a session built without
54
+ * one has nothing to observe and would hang the caller's cleanup — which
55
+ * owns hook, MCP and background-shell teardown. `agent_end` 也可能来自没有物理
56
+ * run 的路径(skipRun / 迟到事件),无界等待会把调用方永久挂住。
57
+ */
58
+ private joinRunsSettled;
43
59
  /** compare-and-delete:仅当 token 仍指向本轮 controller 时清除。 */
44
60
  private clearLifecycleOwner;
45
61
  /** 本轮是否是当前 lifecycle owner。 */
@@ -156,6 +172,7 @@ export declare class AgentServiceImpl implements AgentService {
156
172
  protected resolveRunOneTimeModel(agentName: string, session?: Session): Promise<LanguageModel>;
157
173
  run<TAgent extends Agent<any, any>>(agent: TAgent, input: string | AgentInputItem[], options: AgentCurrentContinuationOptions): Promise<void>;
158
174
  run<TAgent extends Agent<any, any>, TContext = Session>(agent: TAgent, input: string | AgentInputItem[] | RunState<TContext, TAgent>, options?: AgentStandardRunOptions<TContext>): Promise<void>;
175
+ private runPipeline;
159
176
  /**
160
177
  * #59319-stream: 抽取的 physical run cleanup 逻辑。
161
178
  * 非 stream 路径由 run() finally 同步调用;
@@ -189,8 +206,14 @@ export declare class AgentServiceImpl implements AgentService {
189
206
  private prepareRunAdmission;
190
207
  runDefault<TAgent extends Agent<any, any>>(input: string | AgentInputItem[], options: AgentCurrentContinuationOptions): Promise<void>;
191
208
  runDefault<TAgent extends Agent<any, any>, TContext = Session>(input: string | AgentInputItem[] | RunState<TContext, TAgent>, options?: AgentStandardRunOptions<TContext>): Promise<void>;
192
- runOneTime<TContext = Session>(agentName: string, input: string | AgentInputItem[], options?: NonStreamRunOptions<TContext>): Promise<string>;
193
- runOneTime<TContext = Session>(agentName: string, input: string | AgentInputItem[], options?: StreamRunOptions<TContext>): Promise<string>;
209
+ /**
210
+ * Streams the text of a one-shot run on `session`. A reused caller Session is shared
211
+ * with its in-flight main run, so the call's purpose and request id live in its async
212
+ * scope instead of on the Session.
213
+ */
214
+ private streamOneTimeText;
215
+ runOneTime<TContext = Session>(agentName: string, input: string | AgentInputItem[], options?: NonStreamRunOptions<TContext> & OneTimeRunOptions): Promise<string>;
216
+ runOneTime<TContext = Session>(agentName: string, input: string | AgentInputItem[], options?: StreamRunOptions<TContext> & OneTimeRunOptions): Promise<string>;
194
217
  /**
195
218
  * Enhanced version of runOneTime that supports per-request overrides
196
219
  * for temperature, maxTokens, maxTurns, systemPrompt, and bypassPermissions.
@@ -1,5 +1,8 @@
1
1
  export * from './agent-protocol.js';
2
2
  export * from './agent-purpose-protocol.js';
3
+ export * from './agent-purpose-scope.js';
4
+ export * from './model-step-sequence.js';
5
+ export * from './model-call-failure.js';
3
6
  export * from './agent-runtime-protocol.js';
4
7
  export * from './agent-run-scope.js';
5
8
  export * from './agent-service.js';
@@ -0,0 +1,9 @@
1
+ import type { ModelCallGeneration } from '../session/session-protocol.js';
2
+ /**
3
+ * Marks `error` as the failure of one model call. The call's ids live in the model-call
4
+ * async scope, which does not reach the consumer of the SDK run stream; the error does.
5
+ * An error rethrown through an outer call keeps the innermost call's mark.
6
+ */
7
+ export declare function markModelCallFailure<T>(error: T, sessionId: string, generation: ModelCallGeneration): T;
8
+ /** The model call of this Session that failed with `error`; undefined when the failure is not one. */
9
+ export declare function getFailedModelCall(error: unknown, sessionId: string): ModelCallGeneration | undefined;
@@ -0,0 +1,11 @@
1
+ import type { Session } from '../session/session-protocol.js';
2
+ type StepSequenceSession = Pick<Session, 'id' | 'history' | 'agentPurpose' | 'modelStepSeq'>;
3
+ /** Latest step of the Session's agent loop, restored from persisted history after resume. */
4
+ export declare function currentModelStepSeq(session: StepSequenceSession): number;
5
+ /**
6
+ * Step number for the model call in the current async chain. Agent-loop calls
7
+ * advance the counter; auxiliary calls reuse the latest step. The counter never
8
+ * resets across runs, compaction continuations or teammate wake-ups.
9
+ */
10
+ export declare function allocateModelStepSeq(session: StepSequenceSession): number;
11
+ export {};
@@ -21,6 +21,14 @@ export interface ModelInputMemoryPressure {
21
21
  headroom: number;
22
22
  inputItems: number;
23
23
  estimatedInputBytes?: number;
24
+ /**
25
+ * Whether the retained-size walk finished (fully traversed, or provably ≥ the byte budget).
26
+ * `false` means the walk stopped on the node cap with bytes still under budget — the graph is
27
+ * deep/wide but not necessarily large, so `estimatedInputBytes` must NOT drive a rejection.
28
+ */
29
+ estimateComplete: boolean;
30
+ /** Real, content-independent OOM signal: heap is already near its ceiling. */
31
+ heapCritical: boolean;
24
32
  reject: boolean;
25
33
  }
26
34
  export declare function assessModelInputMemoryPressure(input: AgentInputItem[], heapUsed?: number, heapLimit?: number): ModelInputMemoryPressure;
@@ -80,8 +88,18 @@ export declare class RunnerFactoryImpl implements RunnerFactory {
80
88
  * 否则前端的 sending 态无人清除、永久转圈(#73022)。
81
89
  */
82
90
  protected readonly acpBroadcastService?: AgentQueueOutput;
91
+ /** Sessions with a deferred emergency compaction already scheduled (see scheduleEmergencyCompact). */
92
+ private readonly emergencyCompactInFlight;
83
93
  create(config?: Partial<RunConfig>): Promise<Runner>;
84
94
  private assertModelInputCloneHeadroom;
95
+ /**
96
+ * Fire a one-shot emergency compaction for an over-large history so the user's retry can
97
+ * succeed. Deferred + de-duplicated per session; failures are swallowed because the surfaced
98
+ * error already tells the user how to recover. Mirrors checkAutoCompact's non-blocking branch
99
+ * (setImmediate keeps it off the current runner's abort signal). compactAndSummarize has its
100
+ * own session-level lock, so the in-flight set only avoids scheduling redundant callbacks.
101
+ */
102
+ private scheduleEmergencyCompact;
85
103
  /**
86
104
  * 在每次模型请求前检查是否需要自动压缩。
87
105
  * 此时所有工具都已执行完毕,可以安全地触发压缩。
@@ -90,10 +108,10 @@ export declare class RunnerFactoryImpl implements RunnerFactory {
90
108
  /**
91
109
  * Mode B:把「立即发送」队列项注入正在运行的 turn(#73022)。
92
110
  *
93
- * 调用点在 `callModelInputFilter`(见 `create()`),即**每次模型请求之前**,
94
- * 且此时本轮工具已全部执行完、tool result 已回填。选这个边界是因为既不用
95
- * 打断在跑的工具,也不会破坏 `tool_call` 与 `tool_result` 的配对——Codex 与
96
- * Claude Code 同样选在这个位置。
111
+ * 调用点在 `callModelInputFilter`(见 `create()`),即**每次模型请求之前**。
112
+ * rich message / notification / drain prompt 仍在这里注入请求副本;真实 steer
113
+ * 由 `continuationInputProvider` 在 `prepareTurn` 前写入 SDK RunState,避免后续
114
+ * 工具 step 从权威状态重建请求时丢失。
97
115
  *
98
116
  * 注入内容已经进入本次模型请求,无需再为“曾经注入过”强制续圈。只有模型响应期间
99
117
  * 新到达、尚未被取出的消息,才由 `__codebuddySteerPending` 在收尾时实时判定是否
@@ -111,6 +129,22 @@ export declare class RunnerFactoryImpl implements RunnerFactory {
111
129
  * `create()` 注释)。payload 与授权同为调用局部值,天然不跨 run 共享。
112
130
  */
113
131
  private injectSendNowItems;
132
+ /**
133
+ * Drain steer only at the SDK continuation boundary, before it prepares the next model step.
134
+ *
135
+ * The returned model items are installed by the SDK into RunState.generatedItems before
136
+ * `prepareTurn`. This makes steer authoritative input for every later tool/model step instead
137
+ * of an ephemeral `callModelInputFilter` addition. The visible history stays the bare user
138
+ * message; it is admitted exactly once, by the stream consumer, in RunState order.
139
+ */
140
+ private takeSteerContinuationInput;
141
+ /**
142
+ * Visible-history + ACP admission of one drained steer group.
143
+ *
144
+ * Ordering is the caller's responsibility (continuation-history-queue.ts); this only performs
145
+ * the writes and must never throw back into the run.
146
+ */
147
+ private admitSteerToVisibleHistory;
114
148
  /**
115
149
  * #100404:落定来源一(rich queue sendNow)的消费。
116
150
  *
@@ -139,11 +173,11 @@ export declare class RunnerFactoryImpl implements RunnerFactory {
139
173
  * (`session/session-manager.ts` 的 `MODEL_STREAM_STARTED`),涉及跨模块反向布线与
140
174
  * 事件类型白名单依赖,另开 issue 跟进。
141
175
  *
142
- * **落史顺序反转(显式接受)**:`modelData.input` 的 push 顺序是来源一 → 二 → 三 → 四,
143
- * 但来源一的 `addHistory` 推迟到本方法内执行,来源二/三/四仍在 `injectSendNowItems` 里
144
- * 就地 addHistory。同一 model step 同时命中多个来源时,history 里队员消息会排在
145
- * steer / 通知之后,与模型当时看到的输入顺序相反。已确认下游按 role/type 消费、不依赖
146
- * 交错位置,故接受该反转,不做「四来源 historyItems 统一收敛」的重构。
176
+ * **落史顺序反转(显式接受)**:`modelData.input` 的 filter push 顺序是来源一 → 三 → 四,
177
+ * 但来源一的 `addHistory` 推迟到本方法内执行,来源三/四仍在 `injectSendNowItems` 里
178
+ * 就地 addHistory。同一 model step 同时命中多个来源时,history 里队员消息会排在通知
179
+ * 之后,与模型当时看到的输入顺序相反。steer 已在更早的 SDK continuation 边界同时进入
180
+ * RunState 与可见历史,不参与这段反转。下游按 role/type 消费、不依赖交错位置,故接受。
147
181
  *
148
182
  * at-most-once 由**作用域**保证,不再依赖「commit 前清暂存」这类补偿动作:`pending` 是
149
183
  * 单次 `callModelInputFilter` 调用的局部值,每次调用最多把它 commit 一次,也不可能被
@@ -27,7 +27,7 @@ export declare const TOOL_CALL_LOOP_STOPPED_MESSAGE = "Request aborted: user sto
27
27
  * - `ToolCallLoopDetector` 在**模型请求前**拦截,静默向模型注入停止消息,用户无感;
28
28
  * 它覆盖的是旧的三条规则(黑名单同参 4 次 / Read 同文件 40 次 / 非黑名单同参 40 次)。
29
29
  * - `ToolCallLoopGuard` 在**工具执行前**拦截,弹窗让用户自己决定继续还是停止;
30
- * 它覆盖新增的两条规则(同工具连续 40 次,Bash 单独放到 80 次 / 周期序列重复 10 轮)。
30
+ * 它覆盖新增的两条规则(同工具连续 40 次,Bash 与 Write 单独放到 80 次 / 周期序列重复 10 轮)。
31
31
  *
32
32
  * 两者刻意并存:旧规则的静默语义已被线上验证,不因新能力回归。
33
33
  */
@@ -5,11 +5,11 @@
5
5
  */
6
6
  import type { ToolCallLoopTriggerType } from '../../../../telemetry/lib/common/event/types/craft.js';
7
7
  export interface ToolCallLoopThresholds {
8
- /** 同一工具连续调用达到该次数即判定为循环。Bash 走单独阈值。 */
8
+ /** 同一工具连续调用达到该次数即判定为循环。Bash / Write 走单独阈值。 */
9
9
  consecutiveThreshold: number;
10
10
  /**
11
- * Bash 连续调用的单独阈值。长任务里模型会连续跑很多条不同命令,
12
- * 只看工具名时 40 次容易把正常推进误判成循环。
11
+ * Bash 与 Write 连续调用的单独阈值。长任务里模型会连续跑很多条命令、
12
+ * 或连续落很多个文件,只看工具名时 40 次容易把正常推进误判成循环。
13
13
  */
14
14
  bashConsecutiveThreshold: number;
15
15
  /** AAB 块需要连续重复的轮数。 */
@@ -22,8 +22,9 @@ export interface ToolCallLoopHit {
22
22
  /** 重复序列的周期长度;AAB 恒为 3,连续同工具恒为 1。 */
23
23
  patternLength: number;
24
24
  }
25
- /** 与 `ToolNames.BASH` 对齐。模式识别层不依赖 agent-protocol,避免把工具名枚举拉进来。 */
25
+ /** 与 `ToolNames.BASH` / `ToolNames.WRITE` 对齐。模式识别层不依赖 agent-protocol,避免把工具名枚举拉进来。 */
26
26
  export declare const BASH_LOOP_TOOL_NAME = "Bash";
27
+ export declare const WRITE_LOOP_TOOL_NAME = "Write";
27
28
  export declare const DEFAULT_TOOL_CALL_LOOP_THRESHOLDS: ToolCallLoopThresholds;
28
29
  /** AAB 块的长度。多工具循环只识别这一种形状,因此是常量而非可配阈值。 */
29
30
  export declare const AAB_PERIOD = 3;
@@ -43,7 +44,7 @@ export declare class ToolCallLoopTracker {
43
44
  * 记录一次即将执行的工具调用,返回本次是否命中循环。
44
45
  *
45
46
  * 命中优先级:先判连续同工具,再判 AAB 重复。两条规则的阈值默认不重叠
46
- * (普通工具 40 次、Bash 80 次 vs AAB 重复 10 轮),实践中不会互相抢占。
47
+ * (普通工具 40 次、Bash / Write 80 次 vs AAB 重复 10 轮),实践中不会互相抢占。
47
48
  */
48
49
  record(toolName: string): ToolCallLoopHit | undefined;
49
50
  /**
@@ -59,7 +60,7 @@ export declare class ToolCallLoopTracker {
59
60
  * - `ABC`(三者互不相同)通常是正常的多步工作流(读文件 → 改文件 → 跑测试,
60
61
  * 然后换下一个文件),按周期重复判它循环误伤面太大;
61
62
  * - `ABAB` 这类两工具交替同样不判,避免把翻页 / 分批处理误当循环;
62
- * - `AAA…` 属于连续同工具,由 consecutiveThreshold / bashConsecutiveThreshold 那条规则负责。
63
+ * - `AAA…` 属于连续同工具,由 consecutiveThreshold / bashConsecutiveThreshold(Bash、Write)那条规则负责。
63
64
  *
64
65
  * `X ≠ Y` 顺带保证了 AAB 一定是本原周期(唯一可能的更短整除周期是 1,
65
66
  * 那要求三个元素全等),所以不需要额外的本原性校验。
@@ -69,8 +70,8 @@ export declare function matchesRepeatedAabSequence(history: readonly string[], r
69
70
  * 读取阈值配置。环境变量只用于 QA 快速复现,生产不设置即走默认值。
70
71
  * AAB 的周期是形状定义的一部分,不开放配置。
71
72
  *
72
- * `CBC_LOOP_GUARD_CONSECUTIVE_THRESHOLD` 只覆盖非 Bash 工具。Bash 用
73
- * `CBC_LOOP_GUARD_BASH_CONSECUTIVE_THRESHOLD`,避免 QA 把通用阈值压低时
73
+ * `CBC_LOOP_GUARD_CONSECUTIVE_THRESHOLD` 只覆盖非 Bash / Write 工具。Bash 与 Write
74
+ * 共用 `CBC_LOOP_GUARD_BASH_CONSECUTIVE_THRESHOLD`,避免 QA 把通用阈值压低时
74
75
  * 把长任务放宽一并关掉。
75
76
  */
76
77
  export declare function resolveToolCallLoopThresholds(env?: NodeJS.ProcessEnv): ToolCallLoopThresholds;
@@ -0,0 +1,39 @@
1
+ import type { CompactionKind, CompactionTrigger } from '../../../../telemetry/lib/common/index.js';
2
+ import type { Session } from '../session/session-protocol.js';
3
+ export type { CompactionKind, CompactionTrigger };
4
+ export declare function compactionKindOf(trigger: CompactionTrigger): CompactionKind;
5
+ /** Compactions of a Session's context. Never resets, like `modelStepSeq`. */
6
+ export interface CompactionLineage {
7
+ /** Completed compactions. */
8
+ count: number;
9
+ /** Compaction the current context starts from. */
10
+ lastId?: string;
11
+ /** Trigger of the completed compaction the next agent-loop model call reports. */
12
+ pending?: CompactionTrigger;
13
+ }
14
+ type LineageSession = Pick<Session, 'id' | 'history' | 'compactionLineage' | 'meta'>;
15
+ /** Compaction lineage of `session`, restored from its history after resume. */
16
+ export declare function getCompactionLineage(session: LineageSession): CompactionLineage;
17
+ /**
18
+ * Numbers a compaction boundary item before it enters history and stamps the running
19
+ * compaction onto it; the next agent-loop model call reports it.
20
+ */
21
+ export declare function recordCompactionBoundary(session: LineageSession, providerData: Record<string, unknown>): void;
22
+ /** Compaction lineage of one model call (gateway headers, `chat_message_send`). */
23
+ export interface ModelCallCompaction {
24
+ /** Completed compactions of the Session when the call is sent. */
25
+ readonly count: number;
26
+ /** Compaction the call's context starts from. */
27
+ readonly id?: string;
28
+ /** Compaction calls: class of the running compaction (`X-Compaction`). */
29
+ readonly kind?: CompactionKind;
30
+ /** First agent-loop call after a compaction: its class (`X-Context-Compacted`) and trigger. */
31
+ readonly contextCompacted?: CompactionKind;
32
+ readonly trigger?: CompactionTrigger;
33
+ }
34
+ /**
35
+ * Compaction lineage for the model call in the current async chain. Only the first
36
+ * agent-loop call after a compaction reports it, like Claude Code's
37
+ * `consumePendingContextCompacted`.
38
+ */
39
+ export declare function resolveModelCallCompaction(session: LineageSession & Pick<Session, 'agentPurpose' | 'conversationRequestId'>): ModelCallCompaction;