@tencent-ai/agent-harness 0.2.0-beta.10 → 0.2.0-beta.11

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 (140) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/cli/CHANGELOG.md +42 -0
  3. package/cli/dist-server/shared.cjs +316 -315
  4. package/cli/dist-server/types/node/agent/agent-controller.d.ts +1 -0
  5. package/cli/dist-server/types/node/agent/index.d.ts +1 -0
  6. package/cli/dist-server/types/node/agent/interceptors/image-interceptors.d.ts +1 -2
  7. package/cli/dist-server/types/node/agent/interceptors/sandbox-interceptor.d.ts +1 -0
  8. package/cli/dist-server/types/node/agent/steer-model-input-preparer.d.ts +11 -0
  9. package/cli/dist-server/types/node/agent-task/agent-task.d.ts +12 -0
  10. package/cli/dist-server/types/node/agent-team/backends/teammate-backend-protocol.d.ts +2 -0
  11. package/cli/dist-server/types/node/agent-view/session-handoff.d.ts +7 -0
  12. package/cli/dist-server/types/node/channel/channel-protocol.d.ts +8 -8
  13. package/cli/dist-server/types/node/cli/cli-runtime-options.d.ts +24 -1
  14. package/cli/dist-server/types/node/command/clear-command-executor.d.ts +2 -0
  15. package/cli/dist-server/types/node/hooks/hook-protocol.d.ts +3 -67
  16. package/cli/dist-server/types/node/loopback/endpoint-provider.d.ts +3 -0
  17. package/cli/dist-server/types/node/loopback/server-protocol.d.ts +7 -0
  18. package/cli/dist-server/types/node/memory/memory-relevance-protocol.d.ts +6 -1
  19. package/cli/dist-server/types/node/memory/memory-relevance-service.d.ts +3 -2
  20. package/cli/dist-server/types/node/model/model-protocol.d.ts +4 -0
  21. package/cli/dist-server/types/node/security-review/gate.d.ts +1 -0
  22. package/cli/dist-server/types/node/security-review/protocol.d.ts +2 -0
  23. package/cli/dist-server/types/node/session/session-hook-host-adapter.d.ts +2 -2
  24. package/cli/dist-server/types/node/settings/current-session-model-transition.d.ts +5 -4
  25. package/cli/dist-server/types/node/settings/settings-protocol.d.ts +2 -0
  26. package/cli/dist-server/types/node/tools/a2a-cancel-task-tool.d.ts +4 -4
  27. package/cli/dist-server/types/node/tools/a2a-get-task-tool.d.ts +4 -4
  28. package/cli/dist-server/types/node/tools/audio-transcribe-tool.d.ts +1 -2
  29. package/cli/dist-server/types/node/tools/grep-tool.d.ts +2 -0
  30. package/cli/dist-server/types/node/tools/image-service.d.ts +3 -1
  31. package/cli/dist-server/types/node/tools/index.d.ts +1 -0
  32. package/cli/dist-server/types/node/tools/media-file-writer.d.ts +12 -0
  33. package/cli/dist-server/types/node/tools/multi-edit-tool.d.ts +4 -4
  34. package/cli/dist-server/types/node/tools/powershell-tool.d.ts +2 -0
  35. package/cli/dist-server/types/node/tools/send-message-tool.d.ts +2 -2
  36. package/cli/dist-server/types/node/tools/tool-hook-manager.d.ts +2 -2
  37. package/cli/dist-server/types/node/tools/tool-manager.d.ts +1 -0
  38. package/cli/dist-server/types/node/tools/tool-protocol.d.ts +2 -2
  39. package/cli/dist-server/types/node/tools/video-service.d.ts +2 -0
  40. package/cli/dist-server/types/node/tools/wecom-reply-tool.d.ts +2 -2
  41. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-protocol.d.ts +12 -0
  42. package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-service.d.ts +11 -0
  43. package/cli/dist-server/types/vendor/cbc-core/node/agent/index.d.ts +1 -0
  44. package/cli/dist-server/types/vendor/cbc-core/node/agent/runner-factory.d.ts +6 -0
  45. package/cli/dist-server/types/vendor/cbc-core/node/context/compact-strategy-base.d.ts +17 -5
  46. package/cli/dist-server/types/vendor/cbc-core/node/context/pre-switch-model.d.ts +34 -0
  47. package/cli/dist-server/types/vendor/cbc-core/node/hooks/hook-protocol.d.ts +118 -3
  48. package/cli/dist-server/types/vendor/cbc-core/node/message-queue/index.d.ts +1 -0
  49. package/cli/dist-server/types/vendor/cbc-core/node/message-queue/injectable-content.d.ts +15 -18
  50. package/cli/dist-server/types/vendor/cbc-core/node/message-queue/steer-input-buffer-protocol.d.ts +12 -13
  51. package/cli/dist-server/types/vendor/cbc-core/node/message-queue/steer-input-buffer.d.ts +1 -2
  52. package/cli/dist-server/types/vendor/cbc-core/node/message-queue/steer-model-input-preparer-protocol.d.ts +13 -0
  53. package/cli/dist-server/types/vendor/cbc-core/node/session/interruption-service.d.ts +11 -0
  54. package/cli/dist-server/types/vendor/cbc-core/node/session/session-fork-guard.d.ts +2 -1
  55. package/cli/dist-server/types/vendor/cbc-core/node/session/session-hook-manager.d.ts +2 -2
  56. package/cli/dist-server/types/vendor/cbc-core/node/session/session-manager.d.ts +9 -0
  57. package/cli/dist-server/types/vendor/cbc-core/node/session/session-protocol.d.ts +9 -2
  58. package/cli/dist-server/types/vendor/cbc-core/node/session/session-store.d.ts +3 -3
  59. package/cli/dist-server/types/vendor/cbc-core/node/trace/trace-turn-gate.d.ts +13 -0
  60. package/cli/dist-server/types/vendor/cbc-core/node/utils/error-utils.d.ts +7 -0
  61. package/cli/dist-server/types/vendor/cbc-core/node/utils/index.d.ts +2 -0
  62. package/cli/dist-server/types/vendor/cbc-core/node/utils/markdown-code-utils.d.ts +15 -0
  63. package/cli/dist-server/types/vendor/cbc-core/node/utils/message-content-utils.d.ts +3 -1
  64. package/cli/dist-server/types/vendor/cbc-core/node/utils/responses-api-utils.d.ts +21 -0
  65. package/cli/dist-server/types/vendor/cbc-core/node/utils/session-utils.d.ts +20 -0
  66. package/cli/dist-server/types/vendor/cbc-core/node/utils/usage-utils.d.ts +18 -0
  67. package/cli/dist-server/types/vendor/cbc-shared/node/agent/openai-agents-types.d.ts +3 -1
  68. package/cli/dist-server/types/vendor/cbc-shared/node/index.d.ts +1 -0
  69. package/cli/dist-server/types/vendor/cbc-shared/node/logging/structured-event-log.d.ts +64 -0
  70. package/cli/dist-server/types/vendor/cbc-shared/node/model/model-errors.d.ts +10 -0
  71. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-http-interceptor.d.ts +1 -15
  72. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-manager.d.ts +13 -0
  73. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-protocol.d.ts +7 -0
  74. package/cli/dist-server/types/workspace/authentication/lib/common/authentication-refresh-bypass.d.ts +9 -0
  75. package/cli/dist-server/types/workspace/authentication/lib/common/index.d.ts +1 -0
  76. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-protocol.d.ts +12 -0
  77. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-service.d.ts +11 -0
  78. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/index.d.ts +1 -0
  79. package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/runner-factory.d.ts +6 -0
  80. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/compact-strategy-base.d.ts +17 -5
  81. package/cli/dist-server/types/workspace/cbc-core/lib/node/context/pre-switch-model.d.ts +34 -0
  82. package/cli/dist-server/types/workspace/cbc-core/lib/node/hooks/hook-protocol.d.ts +118 -3
  83. package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/index.d.ts +1 -0
  84. package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/injectable-content.d.ts +15 -18
  85. package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/steer-input-buffer-protocol.d.ts +12 -13
  86. package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/steer-input-buffer.d.ts +1 -2
  87. package/cli/dist-server/types/workspace/cbc-core/lib/node/message-queue/steer-model-input-preparer-protocol.d.ts +13 -0
  88. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/interruption-service.d.ts +11 -0
  89. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-fork-guard.d.ts +2 -1
  90. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-hook-manager.d.ts +2 -2
  91. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-manager.d.ts +9 -0
  92. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-protocol.d.ts +9 -2
  93. package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-store.d.ts +3 -3
  94. package/cli/dist-server/types/workspace/cbc-core/lib/node/trace/trace-turn-gate.d.ts +13 -0
  95. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/error-utils.d.ts +7 -0
  96. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/index.d.ts +2 -0
  97. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/markdown-code-utils.d.ts +15 -0
  98. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/message-content-utils.d.ts +3 -1
  99. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/responses-api-utils.d.ts +21 -0
  100. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/session-utils.d.ts +20 -0
  101. package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/usage-utils.d.ts +18 -0
  102. package/cli/dist-server/types/workspace/cbc-daemon/lib/node/daemon/daemon-auto-restart.d.ts +2 -2
  103. package/cli/dist-server/types/workspace/cbc-daemon/lib/node/daemon/daemon-protocol.d.ts +17 -1
  104. package/cli/dist-server/types/workspace/cbc-plugins/lib/node/mods/engine/enable-flag.d.ts +28 -24
  105. package/cli/dist-server/types/workspace/cbc-plugins/lib/node/mods/loader/bootstrap.d.ts +2 -2
  106. package/cli/dist-server/types/workspace/cbc-shared/lib/node/agent/openai-agents-types.d.ts +3 -1
  107. package/cli/dist-server/types/workspace/cbc-shared/lib/node/index.d.ts +1 -0
  108. package/cli/dist-server/types/workspace/cbc-shared/lib/node/logging/structured-event-log.d.ts +64 -0
  109. package/cli/dist-server/types/workspace/cbc-shared/lib/node/model/model-errors.d.ts +10 -0
  110. package/cli/dist-server/types/workspace/core/lib/common/utils/env-utils.d.ts +12 -1
  111. package/cli/dist-server/types/workspace/product/lib/common/model-catalog/index.d.ts +2 -0
  112. package/cli/dist-server/types/workspace/product/lib/common/types/features.d.ts +36 -0
  113. package/cli/dist-server/types/workspace/product/lib/common/types/language-model.d.ts +7 -0
  114. package/cli/dist-server/types/workspace/sandbox-cli/lib/node/sandbox-center-client.d.ts +1 -1
  115. package/cli/dist-server/types/workspace/telemetry/lib/common/event/types/craft.d.ts +2 -1
  116. package/cli/dist-server/types/workspace/telemetry/lib/common/tracing/index.d.ts +2 -2
  117. package/cli/dist-server/types/workspace/telemetry/lib/common/tracing/otel-env.d.ts +16 -5
  118. package/cli/dist-server/types/workspace/telemetry/lib/common/tracing/trace-protocol.d.ts +9 -0
  119. package/cli/package.json +1 -1
  120. package/cli/product.cloudhosted.json +1 -1
  121. package/cli/product.internal.json +1 -1
  122. package/cli/product.ioa.json +1 -1
  123. package/cli/product.json +1 -1
  124. package/cli/product.selfhosted.json +1 -1
  125. package/cli/vendor/shim/node-safe-delete-shim.cjs +20 -3
  126. package/cli/vendor/shim/sitecustomize.py +17 -4
  127. package/docs/acp-v2.md +21 -2
  128. package/docs/client.md +44 -0
  129. package/docs/errors.md +1 -0
  130. package/docs/in-process.md +1 -0
  131. package/lib/agent/v2.js +1 -1
  132. package/lib/application/services.d.ts +1 -0
  133. package/lib/application/services.js +1 -1
  134. package/lib/cli/main.js +3 -3
  135. package/lib/cli/options.d.ts +2 -1
  136. package/lib/cli/options.js +4 -2
  137. package/lib/harness/runtime.js +1 -1
  138. package/lib/harness/types.d.ts +2 -0
  139. package/lib/runtime/component-protocol.js +1 -1
  140. package/package.json +9 -9
@@ -3,6 +3,7 @@ import { type AgentInputItem, ApprovalOptions, type Checkpoint, FinalStopReason,
3
3
  import { Command } from '../../../../workspace/product/lib/common/index.js';
4
4
  import { BehaviorSubject, Subject } from 'rxjs';
5
5
  import type { CompactionLineage } from '../context/compaction-lineage';
6
+ import type { InternalHookContext } from '../hooks/hook-protocol';
6
7
  import { BackgroundTask } from './background-task-protocol';
7
8
  import type { SessionRunStateSnapshot } from './session-run-state-machine-protocol';
8
9
  import type { Lane, LanePointer, SessionKey, SessionStoreEntry } from './session-store-contract';
@@ -516,6 +517,11 @@ export interface Session {
516
517
  telemetryClientInfo?: TelemetryClientInfo;
517
518
  /** Root span for current conversation request, used to extract B3 trace headers */
518
519
  conversationRequestRootSpan?: import('../../../../workspace/telemetry/lib/common/index.js').Span;
520
+ /**
521
+ * 释放 tracing 重初始化闸门(见 trace/trace-reinit-gate.ts)。TraceStartHook 建
522
+ * root span 时置入,TraceStopHook / 强制收尾旧 root 时调用一次(幂等)。genie#113158。
523
+ */
524
+ _traceTurnRelease?: () => void;
519
525
  messageId?: string;
520
526
  /**
521
527
  * @deprecated Hooks 的 `generation_id` 现直接取 `conversationRequestId`(Request ID),
@@ -1239,7 +1245,8 @@ export interface SessionManager {
1239
1245
  * 拦截器/ModelUtils 的权威优先级是 requestOptions.model > options.model > agent 默认;
1240
1246
  * --model 启动参数固化在 options.model,仅写 settings/cli 无法覆盖它。override map
1241
1247
  * 供 applyOverrideModel 每轮重建 requestOptions(Issue #82146)。/model 命令与模型面板
1242
- * 共用此入口;ACP set_model(applyRuntimeSessionModel)仍为独立实现,待统一收敛。
1248
+ * 共用此入口;ACP set_model 经 applyRuntimeSessionModel 调用。
1249
+ * 切换前模型不在这里记录,压缩路径从会话历史里最近一次用量推导。
1243
1250
  */
1244
1251
  setRuntimeModel(session: Session | undefined, modelId: string, source?: OverrideModelSource): void;
1245
1252
  /**
@@ -1476,7 +1483,7 @@ export interface SessionHookManager {
1476
1483
  * final terminal state and will not continue via the current Stop hook.
1477
1484
  * Does NOT support continueRequest.
1478
1485
  */
1479
- executeFinalStopHooks(session: Session, reason?: FinalStopReason): Promise<void>;
1486
+ executeFinalStopHooks(session: Session, reason?: FinalStopReason, internalContext?: Pick<InternalHookContext, 'interceptorGate'>): Promise<void>;
1480
1487
  /**
1481
1488
  * UserPromptExpansion — Claude Code 官方事件(非 cbc 专属扩展):任何用户输入的
1482
1489
  * 命令/skill 在展开成 prompt、送进模型之前统一从这里触发,可阻断展开。适用于
@@ -61,12 +61,13 @@ export declare const SESSION_TITLE_META_KEY = "codebuddy.ai/sessionTitle";
61
61
  * never lands on disk. Literals kept in sync with MAIN_AGENT_META_KEY /
62
62
  * MAIN_AGENT_HOST_KIND_KEY (agent/main-agent-session.ts, #97166) and
63
63
  * MULTITASK_MODE_META_KEY (multitask overlay) and A2A_CONTEXTS_META_KEY
64
- * (a2a/a2a-context-store.ts), plus SESSION_TITLE_META_KEY above (#138181).
64
+ * (a2a/a2a-context-store.ts), plus SESSION_TITLE_META_KEY above (#138181) and
65
+ * PRIVATE_DATA_STICKY_META_KEY above (#127752).
65
66
  * The spec asserts the sync. Growing this list is a review decision, not a
66
67
  * side effect of putting a key on session.meta.
67
68
  * Role / locks / parentSessionId stay runtime-only.
68
69
  */
69
- export declare const PERSISTED_SESSION_META_KEYS: readonly ['codebuddy.ai/mainAgent', 'codebuddy.ai/hostKind', 'multitaskMode', 'codebuddy.ai/a2aContexts', "codebuddy.ai/sessionTitle"];
70
+ export declare const PERSISTED_SESSION_META_KEYS: readonly ['codebuddy.ai/mainAgent', 'codebuddy.ai/hostKind', 'multitaskMode', 'codebuddy.ai/a2aContexts', "codebuddy.ai/sessionTitle", "codebuddy.ai/privateDataSticky"];
70
71
  /**
71
72
  * Meta a fork inherits from its source: the persisted whitelist minus title
72
73
  * facts, which describe the source conversation and must not label the child
@@ -481,7 +482,6 @@ export declare class SessionStoreImpl implements SessionStore {
481
482
  */
482
483
  private deserializeForkSubagentSession;
483
484
  private assertForkGraphAcyclic;
484
- private assertForkChildSupported;
485
485
  private resolveForkChildPrefixEnd;
486
486
  private readForkRuntimeSessionId;
487
487
  private assertForkChildMetaLineage;
@@ -0,0 +1,13 @@
1
+ import type { Session } from '../session/session-protocol';
2
+ /**
3
+ * 归还本轮 turn 持有的 tracing 重初始化闸门(genie#113158)。
4
+ *
5
+ * 闸门计数只能由持有 release 的那一轮归还,且 session 上只存一个 release 槽位。
6
+ * 因此**每一个结束本轮 root span 的出口**都必须调用本函数:正常 Stop、PTL 无
7
+ * 续跑的兜底清理、下一轮开始时对残留 root span 的强制收尾。任一出口漏掉,
8
+ * 下一轮的 markTraceTurnOpen 就会覆盖掉未归还的 release,计数从此单调递增、
9
+ * 永不归零——后续 re-init 被无限推迟,auth/product 配置变更再也不生效。
10
+ *
11
+ * release 自身幂等,重复调用安全。
12
+ */
13
+ export declare function releaseTraceTurnGate(session: Session): void;
@@ -2,6 +2,8 @@ export interface ErrorInfo {
2
2
  status?: number;
3
3
  code?: number;
4
4
  message?: string;
5
+ /** 会话层是否会自动重试本次错误;未知时按会重试处理,沿用流超时文案的既有口径。 */
6
+ isRetryable?: boolean;
5
7
  }
6
8
  /**
7
9
  * 后端业务错误码枚举
@@ -157,6 +159,11 @@ export declare namespace ErrorUtils {
157
159
  * 避免 acp-agent 分类时静默退化为通用 "Network error" 文案。对齐 isStreamTimeoutError 风格。
158
160
  */
159
161
  function isEmptyStreamError(error: unknown): boolean;
162
+ /**
163
+ * 空流里已经流出过思考、但没有正文或工具调用就 `finish_reason=error`。
164
+ * 只认 instanceof:与 `isRetryableEmptyStreamError` 同口径,丢了 prototype 的空流本就不会被重试。
165
+ */
166
+ function isReasoningOnlyEmptyStreamError(error: unknown): boolean;
160
167
  /**
161
168
  * 将错误信息序列化为 JSON 字符串,用于 ACP 协议传输
162
169
  * ACP SDK 会尝试解析这个 JSON 字符串并将其放到 error.data 中
@@ -3,6 +3,7 @@ export * from '../session-title/session-title-utils';
3
3
  export * from './command-message-utils';
4
4
  export * from './content-block-sanitizer';
5
5
  export * from './conversation-request-id';
6
+ export * from './markdown-code-utils';
6
7
  export * from './error-message-host-protocol';
7
8
  export * from './error-utils';
8
9
  export * from './failure-classifier';
@@ -20,6 +21,7 @@ export * from './message-utils';
20
21
  export * from './model-utils';
21
22
  export * from './number-utils';
22
23
  export * from './queue-dispatch-utils';
24
+ export * from './responses-api-utils';
23
25
  export * from './run-result-utils';
24
26
  export * from './session-utils';
25
27
  export * from './summary-utils';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Markdown code-span detection shared by `@path` reference scanners
3
+ * (agent-cli `ImportUtils` and resource reporting), so both agree on which
4
+ * mentions are real references.
5
+ *
6
+ * Rule: a position is inside code when an odd number of ``` fences, or of lone
7
+ * ` ticks (not part of a ``` run), precedes it.
8
+ */
9
+ export declare function isInMarkdownCode(text: string, position: number): boolean;
10
+ /**
11
+ * Same rule as {@link isInMarkdownCode}, with the counts accumulated in one
12
+ * forward pass. Query positions in ascending order; a text with many mentions
13
+ * is then scanned once instead of once per mention.
14
+ */
15
+ export declare function markdownCodeTester(text: string): (position: number) => boolean;
@@ -1,5 +1,7 @@
1
1
  import { type AgentInputItem, type UserMessageItem } from '../../../cbc-shared/node/index.js';
2
2
  export declare abstract class MessageContentUtils {
3
+ /** 用户消息是否携带图片/文件附件块(无文本的纯附件提问也算用户输入)。 */
4
+ static hasAttachmentContent(item: UserMessageItem): boolean;
3
5
  /**
4
6
  * 检查用户消息是否有可见的内容
5
7
  */
@@ -18,7 +20,7 @@ export declare abstract class MessageContentUtils {
18
20
  /** 移除文本中的 system-reminder 标签及其内容 */
19
21
  private static stripSystemReminder;
20
22
  /** 检测 input_text 块是否为 image_local_path 标记 */
21
- private static isImageLocalPathBlock;
23
+ static isImageLocalPathBlock(text: string | undefined): boolean;
22
24
  /**
23
25
  * 将 <teammate-message> 标签替换为友好的摘要文本
24
26
  * 优先使用 summary 属性,否则提取标签内容
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Chat-completions-style finish reason of a terminal OpenAI Responses API stream event
3
+ * (`response.completed` / `response.incomplete` / `response.failed` / `error`);
4
+ * `undefined` for every other event.
5
+ */
6
+ export declare function responsesFinishReason(event: unknown): string | undefined;
7
+ /**
8
+ * The terminal Responses event behind an SDK `response_done` event: the SDK keeps the event
9
+ * type in `providerData` and the rest of the response (status, model, incomplete_details) in
10
+ * `response.providerData`. `undefined` for chat-completions responses.
11
+ */
12
+ export declare function responsesTerminalEventOf(done: {
13
+ providerData?: Record<string, any>;
14
+ response?: {
15
+ output?: unknown;
16
+ providerData?: Record<string, any>;
17
+ };
18
+ }): {
19
+ type: string;
20
+ response: Record<string, any>;
21
+ } | undefined;
@@ -1,6 +1,11 @@
1
1
  import type { AgentInputItem } from '../../../cbc-shared/node/index.js';
2
2
  import type { Session } from '../session/session-protocol';
3
3
  export declare const ENV_KEY_CODEBUDDY_TASK_LIST_ID = "CODEBUDDY_TASK_LIST_ID";
4
+ /**
5
+ * Runtime meta on a session that runs on behalf of another one (one-off helper runs, `/btw`,
6
+ * subagents): the owner's {@link SessionUtils.resolveRootSessionId}.
7
+ */
8
+ export declare const ROOT_SESSION_META_KEY = "codebuddy.ai/rootSessionId";
4
9
  export declare abstract class SessionUtils {
5
10
  static is(session?: any): session is Session;
6
11
  /**
@@ -60,6 +65,21 @@ export declare abstract class SessionUtils {
60
65
  };
61
66
  id?: string;
62
67
  } | undefined, teamName?: string): string | undefined;
68
+ /**
69
+ * Root of a session's lineage: the id behind `${CODEBUDDY_SESSION_ID}` in model credentials,
70
+ * which aihub uses as `cache_task_id` to pin every call of a task to one upstream account.
71
+ * A history replaying Responses items keeps the root they were produced under
72
+ * (`providerData.upstream.rootSessionId`), so forks stay on the account that can decrypt
73
+ * the replayed reasoning. Unlike {@link resolveTaskSessionId}, which picks task-list storage.
74
+ */
75
+ static resolveRootSessionId(session: {
76
+ id: string;
77
+ history?: readonly unknown[];
78
+ meta?: Record<string, unknown>;
79
+ }): string;
80
+ /** Marks `session` as running on behalf of `owner`, sharing its lineage root. */
81
+ static adoptRootSession(session: Session, owner: Session | undefined): void;
82
+ private static replayedRootSessionId;
63
83
  static resolveTaskSessionId(session?: {
64
84
  meta?: {
65
85
  parentSessionId?: string;
@@ -7,6 +7,11 @@ export interface LatestUsageSnapshot {
7
7
  rawUsage: unknown;
8
8
  /** Completion time of the history item carrying this usage. */
9
9
  timestamp?: number;
10
+ /**
11
+ * 这条用量对应的执行模型。优先 requestModelId(用户选中的模型),
12
+ * 没有时回退到响应里的 model。Auto 路由下两者可能不同。
13
+ */
14
+ model?: string;
10
15
  }
11
16
  export declare abstract class UsageUtils {
12
17
  /** Normalize persisted records and per-response stream usage for SDK aggregation. */
@@ -22,6 +27,19 @@ export declare abstract class UsageUtils {
22
27
  * cache fields and response timestamp.
23
28
  */
24
29
  static getLatestUsageSnapshot(session: Session): LatestUsageSnapshot | undefined;
30
+ /**
31
+ * 最近一个压缩边界之后,最后一条带 usage 的消息上的执行模型。
32
+ * 和 currentModelId 相同、或边界之后没有用量时返回 undefined。
33
+ *
34
+ * 压缩边界之前的用量不算:压缩完成后旧模型自动失效,不必再清一份内存记录。
35
+ * A→B→C 且 B 没跑过时,最后一条用量仍是 A。
36
+ */
37
+ static resolvePreSwitchModelId(session: {
38
+ history?: AgentInputItem[];
39
+ }, currentModelId: string | undefined): string | undefined;
40
+ private static findLatestUsageSnapshot;
41
+ /** 用户选中的模型优先于响应里的实际路由模型。 */
42
+ private static readExecutedModelId;
25
43
  static getTotalUsage(items: AgentInputItem[]): Usage;
26
44
  /**
27
45
  * 从单个 item 的 rawUsage/usage 提取 cache_read_input_tokens(命中缓存的输入 token)。
@@ -26,7 +26,7 @@
26
26
  * 未 preload 直接用 `new Agent(...)` 会 fail-loud(TypeError: undefined is not
27
27
  * a constructor)——刻意设计,静默 sync require 回退会让整个 lazy 化归零。
28
28
  */
29
- import type { addTraceProcessor as addTraceProcessorFn, Agent as AgentTypeCtor, AgentConfiguration, AgentInputItem as OriginalAgentInputItem, AgentOptions, AssistantMessageItem as OriginalAssistantMessageItem, ComputerCallResultItem as OriginalComputerCallResultItem, ComputerUseCallItem as OriginalComputerUseCallItem, FunctionCallItem as OriginalFunctionCallItem, FunctionCallResultItem as OriginalFunctionCallResultItem, FunctionTool as FunctionToolTypeCtor, Handoff as HandoffTypeCtor, handoff as handoffFn, HostedToolCallItem as OriginalHostedToolCallItem, Model as ModelType, ModelProvider as ModelProviderType, NonStreamRunOptions, OpenAIChatCompletionsModel as OpenAIChatCompletionsModelTypeCtor, ReasoningItem as OriginalReasoningItem, ResponseStreamEvent, RunConfig, RunContext as RunContextTypeCtor, RunItem, Runner as RunnerTypeCtor, RunResult as RunResultTypeCtor, RunState as RunStateTypeCtor, RunToolApprovalItem as RunToolApprovalItemTypeCtor, setTraceProcessors as setTraceProcessorsFn, StreamedRunResult as RawStreamedRunResultTypeCtor, StreamRunOptions, SystemMessageItem as OriginalSystemMessageItem, Tool as OpenAIToolType, tool as toolTypeCtor, ToolExecuteArgument, UnknownItem as OriginalUnknownItem, Usage as UsageTypeCtor, UserMessageItem as OriginalUserMessageItem } from '@openai/agents';
29
+ import type { addTraceProcessor as addTraceProcessorFn, Agent as AgentTypeCtor, AgentConfiguration, AgentInputItem as OriginalAgentInputItem, AgentOptions, AssistantMessageItem as OriginalAssistantMessageItem, ComputerCallResultItem as OriginalComputerCallResultItem, ComputerUseCallItem as OriginalComputerUseCallItem, FunctionCallItem as OriginalFunctionCallItem, FunctionCallResultItem as OriginalFunctionCallResultItem, FunctionTool as FunctionToolTypeCtor, Handoff as HandoffTypeCtor, handoff as handoffFn, HostedToolCallItem as OriginalHostedToolCallItem, Model as ModelType, ModelProvider as ModelProviderType, NonStreamRunOptions, OpenAIChatCompletionsModel as OpenAIChatCompletionsModelTypeCtor, OpenAIResponsesModel as OpenAIResponsesModelTypeCtor, ReasoningItem as OriginalReasoningItem, ResponseStreamEvent, RunConfig, RunContext as RunContextTypeCtor, RunItem, Runner as RunnerTypeCtor, RunResult as RunResultTypeCtor, RunState as RunStateTypeCtor, RunToolApprovalItem as RunToolApprovalItemTypeCtor, setTraceProcessors as setTraceProcessorsFn, StreamedRunResult as RawStreamedRunResultTypeCtor, StreamRunOptions, SystemMessageItem as OriginalSystemMessageItem, Tool as OpenAIToolType, tool as toolTypeCtor, ToolExecuteArgument, UnknownItem as OriginalUnknownItem, Usage as UsageTypeCtor, UserMessageItem as OriginalUserMessageItem } from '@openai/agents';
30
30
  import type { AgentOutputType, getAllMcpTools as getAllMcpToolsFn, MaxTurnsExceededError as MaxTurnsExceededErrorTypeCtor, ModelBehaviorError as ModelBehaviorErrorTypeCtor } from '@openai/agents-core';
31
31
  import type { TextOutput, UnknownContext, UserContent } from '@openai/agents-core/types';
32
32
  import type { AcpTerminalStateItem, CreditUsageItem, FileHistorySnapshotItem, ModelUsageItem, ResendForkNoticeItem } from './custom-input-item-types';
@@ -43,6 +43,7 @@ export type FunctionTool = FunctionToolTypeCtor;
43
43
  export type Handoff<TContext = UnknownContext, TOutput extends AgentOutputType = TextOutput> = HandoffTypeCtor<TContext, TOutput>;
44
44
  export type OpenAITool = OpenAIToolType;
45
45
  export type OpenAIChatCompletionsModel = OpenAIChatCompletionsModelTypeCtor;
46
+ export type OpenAIResponsesModel = OpenAIResponsesModelTypeCtor;
46
47
  export type Model = ModelType;
47
48
  export type RawModelProvider = ModelProviderType;
48
49
  export type MaxTurnsExceededError = MaxTurnsExceededErrorTypeCtor;
@@ -59,6 +60,7 @@ export declare let tool: typeof toolTypeCtor;
59
60
  export declare let Handoff: typeof HandoffTypeCtor;
60
61
  export declare let handoff: typeof handoffFn;
61
62
  export declare let OpenAIChatCompletionsModel: typeof OpenAIChatCompletionsModelTypeCtor;
63
+ export declare let OpenAIResponsesModel: typeof OpenAIResponsesModelTypeCtor;
62
64
  export declare let getAllMcpTools: typeof getAllMcpToolsFn;
63
65
  export declare let MaxTurnsExceededError: typeof MaxTurnsExceededErrorTypeCtor;
64
66
  export declare let ModelBehaviorError: typeof ModelBehaviorErrorTypeCtor;
@@ -15,3 +15,4 @@ export * from './tools/tool-names';
15
15
  export * from './command/command-types';
16
16
  export * from './acp/terminal-types';
17
17
  export * from './model/model-errors';
18
+ export * from './logging/structured-event-log';
@@ -0,0 +1,64 @@
1
+ export type StructuredEventResult = 'success' | 'failed' | 'rejected' | 'cancelled';
2
+ export type StructuredEventErrorType = 'cancelled' | 'timeout' | 'decode' | 'unknown';
3
+ export type StructuredEventValue = string | number | boolean;
4
+ export type StructuredEventFields = object;
5
+ export interface StructuredEventLogger {
6
+ info(message: string): void;
7
+ warn?(message: string): void;
8
+ error(message: string): void;
9
+ }
10
+ export interface StructuredEventCorrelation {
11
+ request_id?: string;
12
+ trace_id?: string;
13
+ user_id?: string;
14
+ enterprise_id?: string;
15
+ conversation_id?: string;
16
+ conversation_request_id?: string;
17
+ conversation_message_id?: string;
18
+ task_id?: string;
19
+ runtime_id?: string;
20
+ session_id?: string;
21
+ call_id?: string;
22
+ }
23
+ export interface StructuredEventBaseRecord extends StructuredEventCorrelation {
24
+ event_id: string;
25
+ event_name: string;
26
+ service: string;
27
+ msg: string;
28
+ result: StructuredEventResult;
29
+ duration_ms: number;
30
+ stage?: string;
31
+ stop_reason?: 'cancelled';
32
+ error_code?: string;
33
+ error_type?: StructuredEventErrorType;
34
+ error_summary_omitted?: true;
35
+ raw?: string;
36
+ }
37
+ type ReservedEventField = keyof StructuredEventBaseRecord;
38
+ type BusinessEventFields<T extends StructuredEventFields> = {
39
+ [K in keyof T]: T[K] extends StructuredEventValue | undefined ? T[K] : never;
40
+ } & Partial<Record<ReservedEventField, never>>;
41
+ export type StructuredEventRecord<T extends StructuredEventFields = Record<string, StructuredEventValue | undefined>> = StructuredEventBaseRecord & T;
42
+ export interface StructuredEventInput<T extends StructuredEventFields> {
43
+ logger: StructuredEventLogger;
44
+ eventName: string;
45
+ service: string;
46
+ message: string;
47
+ result: StructuredEventResult;
48
+ startedAt: number;
49
+ stage?: string;
50
+ correlation?: StructuredEventCorrelation;
51
+ fields: BusinessEventFields<T>;
52
+ raw?: string | ((durationMs: number) => string);
53
+ rejectedLevel?: 'info' | 'warn';
54
+ error?: unknown;
55
+ errorCode?: string;
56
+ errorType?: StructuredEventErrorType;
57
+ }
58
+ /**
59
+ * Emits one JSON terminal event through the caller's existing logger.
60
+ * Business domains own typed adapters and fixed field names; this shared layer
61
+ * only owns the common event contract and safe error diagnosis.
62
+ */
63
+ export declare function logStructuredEvent<T extends StructuredEventFields>(input: StructuredEventInput<T>): StructuredEventRecord<T> | undefined;
64
+ export {};
@@ -67,8 +67,18 @@ export declare class EmptyStreamError extends StreamTimeoutError {
67
67
  readonly data: Readonly<{
68
68
  category: "empty_model_response";
69
69
  }>;
70
+ /** reasoning-only 时已流出的思考,由 {@link withStreamedReasoning} 挂上;`declare` 保证未挂时不产生自有属性。 */
71
+ readonly streamedReasoning?: string;
70
72
  constructor(chunkCount: number, totalBytes: number, kind?: EmptyStreamKind, elapsedMs?: number, finishReason?: EmptyStreamFinishReason);
71
73
  }
74
+ /**
75
+ * 把 reasoning-only 空流里已流出的思考挂到错误上,供会话层带着它续写。
76
+ *
77
+ * 模型层拦下 error 帧时不把这次响应交给 SDK(#63761):与 error 帧同一分片的思考从未转发,
78
+ * 先转发的分片也会随流报错被清出队列,所以思考只能由模型层随错误交出。
79
+ * 不可枚举:错误会被打进日志、序列化后经 ACP / stream-json 上报,思考正文不能随之外泄。
80
+ */
81
+ export declare function withStreamedReasoning(error: EmptyStreamError, reasoning: string): EmptyStreamError;
72
82
  /**
73
83
  * 认证缺失错误
74
84
  * 缺少有效的 API Key 时抛出
@@ -11,11 +11,6 @@ export declare class AuthenticationHttpInterceptor implements ApplicationLifecyc
11
11
  protected readonly productManager: ProductManager;
12
12
  initialize(): void;
13
13
  private checkToLogout;
14
- /**
15
- * 从 request url 抽出 path 部分。绝对 URL 用 `new URL().pathname`,相对路径直接
16
- * 以 `?` 之前的部分作为 path;解析失败返回 undefined。逻辑与 isLogoutWhitelistedPath
17
- * 保持一致。
18
- */
19
14
  private extractPath;
20
15
  /**
21
16
  * 【issue-91861】业务 API 401 refresh 兜底。
@@ -29,16 +24,7 @@ export declare class AuthenticationHttpInterceptor implements ApplicationLifecyc
29
24
  * - refresh 失败 → 同样进入 30s 冷却,避免业务 API 401 把 refresh 打成连发
30
25
  */
31
26
  private tryRefreshOnBusinessApi401;
32
- /**
33
- * 判断当前请求 url 的 path 是否落在登出白名单内。
34
- *
35
- * 仅按 url path 维度匹配,不做子串匹配,避免 `/api/memory/profile-extra`
36
- * 这类前缀近似的路径被错误命中。绝对 URL 用 `new URL().pathname`,相对路径
37
- * 直接以 `?` 之前的部分作为 path;解析失败一律保守返回 false(仍走原 logout 流程)。
38
- *
39
- * 匹配两类白名单:`LOGOUT_BYPASS_PATHS`(字面量精确匹配)与
40
- * `LOGOUT_BYPASS_PATH_PATTERNS`(含动态段的正则匹配)。源自 ADR-005 / issue-65830。
41
- */
27
+ /** 登出 / 续期白名单,见 authentication-refresh-bypass(ADR-005 / issue-65830)。 */
42
28
  private isLogoutWhitelistedPath;
43
29
  /**
44
30
  * 判断请求目标是否匹配产品 endpoint。
@@ -57,6 +57,9 @@ export declare class AuthenticationManagerImpl implements AuthenticationManager
57
57
  private lastRefreshAttemptAt;
58
58
  /** 用户主动切换账号优先于后台 refresh,避免 refresh 反向中断切换操作。 */
59
59
  private accountSwitchInFlight;
60
+ private readonly refreshRejectedListeners;
61
+ /** 续期被服务端拒绝时的 accessToken;用于冷却期内重放失效结论。 */
62
+ private rejectedAccessToken?;
60
63
  /** Prevent concurrent login requests — avoids opening multiple browser tabs */
61
64
  private loginInFlight;
62
65
  private static readonly MIN_REFRESH_DELAY_MS;
@@ -106,6 +109,16 @@ export declare class AuthenticationManagerImpl implements AuthenticationManager
106
109
  logout(options?: LogoutOptions): Promise<void>;
107
110
  refreshSession(): Promise<void>;
108
111
  waitForSessionRefresh(): Promise<void>;
112
+ refreshSessionOnUnauthorized(url: string): void;
113
+ onRefreshRejected(listener: () => void): () => void;
114
+ /**
115
+ * 只认 provider 抛出的 `UnauthorizedError`(refresh 接口 401/403);manager 自己因身份/authority
116
+ * 校验抛的同类错误不算「凭据被拒」。被刷新的 session 已不是当前 session(登出/切号)时不通知。
117
+ */
118
+ private refreshWithProvider;
119
+ /** 当前 session 是否就是续期已被服务端拒绝的那份(重登/切号换了 token 即自然失配)。 */
120
+ private isCurrentSessionRejected;
121
+ private notifyRefreshRejected;
109
122
  refreshSessionForAuthenticationFailure(): Promise<AuthSession>;
110
123
  private forceRefreshManagedSession;
111
124
  switchAccount(account: Account): Promise<void>;
@@ -260,6 +260,13 @@ export interface AuthenticationManager {
260
260
  waitForSessionRefresh(): Promise<void>;
261
261
  /** Force one authoritative, singleflight refresh after an auth failure. */
262
262
  refreshSessionForAuthenticationFailure(): Promise<AuthSession>;
263
+ /**
264
+ * 订阅「续期凭据被服务端拒绝」:provider 刷新时 401/403(`UnauthorizedError`),
265
+ * 即当前 session 已不可恢复。session 本身不清理,是否登出由订阅方决定(issue #140485)。
266
+ */
267
+ onRefreshRejected?(listener: () => void): () => void;
268
+ /** 当前 token 的业务 API 401:白名单路径忽略,其余触发后台续期(不等待、不抛错)。 */
269
+ refreshSessionOnUnauthorized?(url: string): void;
263
270
  switchAccount(account: Account): Promise<void>;
264
271
  waitAuthSession(): Promise<AuthSession>;
265
272
  setAuthenticationProvider(authenticationType: AuthenticationType): Promise<void>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 业务 API 401 不应触发登出 / 续期的路径白名单。零依赖,供 RestOperations 拦截器与
3
+ * daemon runtime-http 共用,保证两条 HTTP 出口对「哪些 401 不代表会话失效」口径一致(issue #140485)。
4
+ */
5
+ export declare const TOKEN_REFRESH_PATH_PATTERN: RegExp;
6
+ /** 从 request url 抽出 path:绝对 URL 取 pathname,相对路径取 `?` 之前部分;解析失败返回 undefined。 */
7
+ export declare function extractAuthRequestPath(url?: string): string | undefined;
8
+ /** url path 是否命中白名单(精确匹配,不做子串匹配);解析失败保守返回 false。 */
9
+ export declare function isLogoutBypassPath(url?: string): boolean;
@@ -11,3 +11,4 @@ export * from './wx-authentication-provider.js';
11
11
  export * from './product-env-service.js';
12
12
  export * from './account-utils.js';
13
13
  export * from './authentication-observation.js';
14
+ export * from './authentication-refresh-bypass.js';
@@ -727,6 +727,18 @@ export interface ForkedAgentOptions {
727
727
  export interface OneTimeRunOptions {
728
728
  /** X-Agent-Purpose of the call; defaults to the agent's `AGENT_PURPOSE_MAP` entry, else its name. */
729
729
  purpose?: string;
730
+ /**
731
+ * 本次一次性调用使用的模型 id / name / alias。
732
+ * 解析成功时优先于会话当前模型和 agent 默认模型;解析不到时回落到原有解析。
733
+ * 用于切换模型后的压缩摘要:阈值按新模型,摘要请求仍走切换前的模型。
734
+ */
735
+ model?: string;
736
+ /**
737
+ * 本次调用的 modelSettings,整体替换 run-scoped agent 的 modelSettings,不写回共享 agent。
738
+ * 按会话变化的参数(如 maxTokens)必须走这里:共享 agent 实例进程内各会话共用,
739
+ * 先写共享实例再调用会被并发会话覆盖。
740
+ */
741
+ modelSettings?: Agent['modelSettings'];
730
742
  }
731
743
  export interface RunRequest {
732
744
  prompt?: string;
@@ -213,6 +213,17 @@ export declare class AgentServiceImpl implements AgentService {
213
213
  * scope instead of on the Session.
214
214
  */
215
215
  private streamOneTimeText;
216
+ /**
217
+ * 辅助一次性 run(调用方没传 context、由本方法新建 session)复用「当前会话」的信任锚点:
218
+ * 敏感审批锚 `sensitiveGrantSessionId` 与会话级隐私锁定位。
219
+ *
220
+ * Auxiliary one-time runs inherit the main session's sensitive approval anchor so a
221
+ * previously admitted input remains admitted throughout the trusted call chain.
222
+ *
223
+ * 前提:调用发生在该会话的 async 链内(`getCurrent()` 读 ALS,由 SessionMiddleware
224
+ * 每轮 setCurrent)。纯定时器驱动的调用取不到,此时与既有行为一致地不做任何事。
225
+ */
226
+ private inheritGrantsFromCurrentSession;
216
227
  runOneTime<TContext = Session>(agentName: string, input: string | AgentInputItem[], options?: NonStreamRunOptions<TContext> & OneTimeRunOptions): Promise<string>;
217
228
  runOneTime<TContext = Session>(agentName: string, input: string | AgentInputItem[], options?: StreamRunOptions<TContext> & OneTimeRunOptions): Promise<string>;
218
229
  runReviewerOneTime(request: ReviewerOneTimeRequest): Promise<ReviewerOneTimeResult>;
@@ -24,6 +24,7 @@ export * from './interceptors/pre-message-compact-interceptor.js';
24
24
  export * from '../tools/prompt-cache-tool-metadata.js';
25
25
  export * from '../trace/turn-context.js';
26
26
  export * from '../trace/trace-id-utils.js';
27
+ export * from '../trace/trace-turn-gate.js';
27
28
  export * from '../file-rollback/file-rollback-service-protocol.js';
28
29
  export * from '../file-rollback/file-rollback-operation-lock.js';
29
30
  export * from './reviewer-recovery.js';
@@ -140,6 +140,12 @@ export declare class RunnerFactoryImpl implements RunnerFactory {
140
140
  * of an ephemeral `callModelInputFilter` addition. The visible history stays the bare user
141
141
  * message; it is admitted exactly once, by the stream consumer, in RunState order.
142
142
  */
143
+ /**
144
+ * 与普通 prompt 的图片拦截器同一实现(#140576):只加工模型输入副本(压缩 / 按模型能力过滤图片),
145
+ * 历史项保留原图。宿主未提供实现(精简变体)时跳过;加工失败按原内容插入,不丢消息。
146
+ */
147
+ private prepareSteerModelInput;
148
+ private resolveSteerModelInputPreparer;
143
149
  private takeSteerContinuationInput;
144
150
  /**
145
151
  * Visible-history + ACP admission of one drained steer group.
@@ -1,4 +1,4 @@
1
- import { AgentInputItem } from '../../../../cbc-shared/lib/node/index.js';
1
+ import { type Agent, AgentInputItem } from '../../../../cbc-shared/lib/node/index.js';
2
2
  import { ProductManager } from '../../../../product/lib/common/index.js';
3
3
  import { Logger } from '../../../../telemetry/lib/common/index.js';
4
4
  import { AgentManager, AgentService } from '../agent/agent-protocol.js';
@@ -6,6 +6,7 @@ import { HistoryReloadReason, Session, SessionHookManager, SessionManager } from
6
6
  import { SessionRunStateMachine } from '../session/session-run-state-machine-protocol.js';
7
7
  import { CompactBroadcast } from './context-host-protocol.js';
8
8
  import { CompactStrategy, CompactStrategyContext, ContextCompactSummarizeOptions, PromptRenderer, SummaryScenario } from './context-protocol.js';
9
+ import { type CompactSummaryModel } from './pre-switch-model.js';
9
10
  /**
10
11
  * 压缩策略共享基类,封装 session 状态管理、广播、continue 消息、abort 等基础设施方法。
11
12
  * 各具体策略通过继承获得这些能力,只需关注自己的压缩逻辑。
@@ -94,20 +95,31 @@ export declare abstract class CompactStrategyBase implements CompactStrategy {
94
95
  */
95
96
  protected sendContinueMessage(session: Session, preCompactAgentName?: string, overrideInput?: AgentInputItem[]): Promise<boolean>;
96
97
  /**
97
- * 为 contextSummary agent 准备 modelSettings。
98
+ * 计算 contextSummary 本次调用的 modelSettings,由调用方经 `runOneTime({ modelSettings })` 传入。
99
+ * 不写共享的 contextSummary agent:serve/daemon 多会话并发压缩时,maxTokens 随会话的
100
+ * 切换前模型变化,写共享实例会被其他会话覆盖。
98
101
  *
99
102
  * contextSummary 经 `runOneTime` 调用,绕过 ModelConfigAgentRunInterceptor,
100
103
  * 因此不会自动获得主 agent 那套采样参数(temperature / maxTokens / reasoning / text 等)。
101
104
  *
102
105
  * 这里做两件事:
103
106
  * 1) 继承主 agent 当前的 modelSettings(temperature、maxTokens、reasoning、text、providerData 等),
104
- * 使摘要请求与主对话使用一致的模型配置。contextSummary 始终继承主 agent 的模型,
107
+ * 使摘要请求与主对话使用一致的模型配置。contextSummary 默认继承主 agent 的模型,
105
108
  * 故继承到的 maxTokens 已是该模型经 ModelUtils.getMaxOutputTokens 处理后的值,无需重算。
106
- * 2) 仅当继承后仍缺 maxTokens(模型未配 maxOutputTokens 且未设 CODEBUDDY_CODE_MAX_OUTPUT_TOKENS,
109
+ * 有切换前模型时,maxTokens 按那个模型重算(继承到的是新模型的输出上限)。
110
+ * 2) 仍缺 maxTokens(模型未配 maxOutputTokens 且未设 CODEBUDDY_CODE_MAX_OUTPUT_TOKENS,
107
111
  * 此时主 agent 自身也不写 maxTokens)时,补摘要兜底 24k,避免请求不带 `max_tokens`
108
112
  * 让上游网关回退到模型原生输出上限。
113
+ *
114
+ * 失败时返回 undefined,runOneTime 沿用 contextSummary agent 自身的 modelSettings。
115
+ */
116
+ protected buildSummaryModelSettings(summaryModel?: CompactSummaryModel): Promise<Agent['modelSettings'] | undefined>;
117
+ /**
118
+ * 切换后第一次压缩的摘要模型。从历史用量推导;没有、解析不到、或窗口不比当前大时
119
+ * 返回 undefined,调用方保持「用当前会话模型做摘要」。预算按该模型的物理窗口,
120
+ * 不用新模型的档位 override。
109
121
  */
110
- protected applySummaryAgentModelSettings(): Promise<void>;
122
+ protected resolveSummaryModel(session: Session): Promise<CompactSummaryModel | undefined>;
111
123
  /**
112
124
  * Render summary prompt template based on scenario.
113
125
  */
@@ -0,0 +1,34 @@
1
+ import type { AgentInputItem } from '../../../../cbc-shared/lib/node/index.js';
2
+ import { type ModelContextWindowLike } from './context-protocol.js';
3
+ /** 摘要请求用切换前模型执行,inputTokens 是它预留输出后的可用输入。 */
4
+ export interface CompactSummaryModel {
5
+ id: string;
6
+ maxOutputTokens?: number;
7
+ inputTokens?: number;
8
+ }
9
+ /** 比较上下文窗口时需要的模型字段。不含会话档位 override。 */
10
+ export interface PreSwitchModelLike {
11
+ id: string;
12
+ maxInputTokens?: number;
13
+ maxOutputTokens?: number;
14
+ contextWindow?: ModelContextWindowLike;
15
+ }
16
+ /**
17
+ * 从会话历史推导切换前真正执行过的模型。
18
+ *
19
+ * 只有它能解析出来,且有效窗口大于当前模型时才返回。窗口不更大时不当作切换:
20
+ * Auto 路由可能让 requestModelId 和会话模型不一致,换到更大窗口也不需要强制压缩。
21
+ * 预算用模型自己的窗口,不用会话上的档位 override。
22
+ */
23
+ export declare function resolveEligiblePreSwitchModel(input: {
24
+ session: {
25
+ history?: AgentInputItem[];
26
+ };
27
+ currentModel: PreSwitchModelLike;
28
+ resolveModel: (modelId: string) => Promise<PreSwitchModelLike | undefined>;
29
+ logger?: {
30
+ warn: (message: string) => void;
31
+ };
32
+ }): Promise<PreSwitchModelLike | undefined>;
33
+ /** 按切换前模型的物理窗口计算摘要预算,不用当前模型的档位 override。 */
34
+ export declare function buildPreSwitchSummaryModel(model: PreSwitchModelLike): CompactSummaryModel;