@tencent-ai/agent-harness 0.2.0-beta.1 → 0.2.0-beta.2
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.
- package/CHANGELOG.md +20 -0
- package/README.md +1 -1
- package/cli/CHANGELOG.md +71 -0
- package/cli/dist-server/shared.cjs +318 -314
- package/cli/dist-server/types/node/acp/acp-protocol.d.ts +40 -12
- package/cli/dist-server/types/node/acp/usage-by-category-calculator.d.ts +21 -0
- package/cli/dist-server/types/node/cli/stream-json-protocol.d.ts +15 -1
- package/cli/dist-server/types/node/data-fs/index.d.ts +13 -1
- package/cli/dist-server/types/node/hooks/hook-protocol.d.ts +2 -2
- package/cli/dist-server/types/node/server/sessions.d.ts +24 -0
- package/cli/dist-server/types/node/server/types.d.ts +6 -0
- package/cli/dist-server/types/node/settings/settings-protocol.d.ts +5 -0
- package/cli/dist-server/types/node/tools/tool-protocol.d.ts +112 -2
- package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-protocol.d.ts +29 -0
- package/cli/dist-server/types/vendor/cbc-core/node/agent/agent-service.d.ts +2 -0
- package/cli/dist-server/types/vendor/cbc-core/node/agent/index.d.ts +1 -0
- package/cli/dist-server/types/vendor/cbc-core/node/agent/interceptors/input-interceptors.d.ts +1 -6
- package/cli/dist-server/types/vendor/cbc-core/node/agent/runner-factory.d.ts +31 -11
- package/cli/dist-server/types/vendor/cbc-core/node/agent/speaker-label.d.ts +44 -0
- package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-detector-service.d.ts +5 -4
- package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
- package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-pattern.d.ts +15 -4
- package/cli/dist-server/types/vendor/cbc-core/node/hooks/agent-trigger.d.ts +6 -22
- package/cli/dist-server/types/vendor/cbc-core/node/hooks/hook-protocol.d.ts +4 -1
- package/cli/dist-server/types/vendor/cbc-core/node/session/idle-queue-drain-service.d.ts +4 -56
- package/cli/dist-server/types/vendor/cbc-core/node/session/index.d.ts +3 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/interruption-service.d.ts +55 -9
- package/cli/dist-server/types/vendor/cbc-core/node/session/model-response-interceptors.d.ts +18 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/recovery-budget.d.ts +55 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-hook-manager.d.ts +15 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-manager.d.ts +10 -1
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-persistence-error.d.ts +43 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-protocol.d.ts +63 -4
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-run-state-machine-protocol.d.ts +1 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-runtime-lifecycle.d.ts +5 -0
- package/cli/dist-server/types/vendor/cbc-core/node/session/session-store.d.ts +150 -4
- package/cli/dist-server/types/vendor/cbc-core/node/session/stream-timeout-retry-budget.d.ts +13 -1
- package/cli/dist-server/types/vendor/cbc-core/node/utils/history-utils.d.ts +23 -0
- package/cli/dist-server/types/vendor/cbc-core/node/utils/index.d.ts +1 -0
- package/cli/dist-server/types/vendor/cbc-core/node/utils/message-utils.d.ts +12 -0
- package/cli/dist-server/types/vendor/cbc-core/node/utils/model-utils.d.ts +7 -0
- package/cli/dist-server/types/vendor/cbc-core/node/utils/queue-dispatch-utils.d.ts +24 -2
- package/cli/dist-server/types/vendor/cbc-core/node/utils/session-utils.d.ts +4 -1
- package/cli/dist-server/types/vendor/cbc-core/node/utils/string-retention-utils.d.ts +4 -0
- package/cli/dist-server/types/vendor/cbc-shared/node/hooks/hook-types.d.ts +7 -1
- package/cli/dist-server/types/vendor/cbc-shared/node/index.d.ts +2 -0
- package/cli/dist-server/types/vendor/cbc-shared/node/model/model-errors.d.ts +7 -3
- package/cli/dist-server/types/vendor/cbc-shared/node/tools/tool-names.d.ts +1 -0
- package/cli/dist-server/types/vendor/cbc-shared/node/utils/retry-backoff.d.ts +30 -0
- package/cli/dist-server/types/vendor/cbc-shared/node/utils/retry-policy.d.ts +26 -0
- package/cli/dist-server/types/workspace/authentication/lib/common/account-scoped-external-link-authentication-provider.d.ts +2 -2
- package/cli/dist-server/types/workspace/authentication/lib/common/account-utils.d.ts +25 -0
- package/cli/dist-server/types/workspace/authentication/lib/common/authentication-manager.d.ts +2 -2
- package/cli/dist-server/types/workspace/authentication/lib/common/authentication-protocol.d.ts +19 -2
- package/cli/dist-server/types/workspace/authentication/lib/common/external-link-authentication-provider.d.ts +2 -2
- package/cli/dist-server/types/workspace/authentication/lib/common/wx-authentication-provider.d.ts +2 -2
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-protocol.d.ts +29 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/agent-service.d.ts +2 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/index.d.ts +1 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/interceptors/input-interceptors.d.ts +1 -6
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/runner-factory.d.ts +31 -11
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/speaker-label.d.ts +44 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-detector-service.d.ts +5 -4
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-guard-protocol.d.ts +1 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/agent/tool-call-loop-pattern.d.ts +15 -4
- package/cli/dist-server/types/workspace/cbc-core/lib/node/hooks/agent-trigger.d.ts +6 -22
- package/cli/dist-server/types/workspace/cbc-core/lib/node/hooks/hook-protocol.d.ts +4 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/idle-queue-drain-service.d.ts +4 -56
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/index.d.ts +3 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/interruption-service.d.ts +55 -9
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/model-response-interceptors.d.ts +18 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/recovery-budget.d.ts +55 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-hook-manager.d.ts +15 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-manager.d.ts +10 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-persistence-error.d.ts +43 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-protocol.d.ts +63 -4
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-run-state-machine-protocol.d.ts +1 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-runtime-lifecycle.d.ts +5 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/session-store.d.ts +150 -4
- package/cli/dist-server/types/workspace/cbc-core/lib/node/session/stream-timeout-retry-budget.d.ts +13 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/history-utils.d.ts +23 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/index.d.ts +1 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/message-utils.d.ts +12 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/model-utils.d.ts +7 -0
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/queue-dispatch-utils.d.ts +24 -2
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/session-utils.d.ts +4 -1
- package/cli/dist-server/types/workspace/cbc-core/lib/node/utils/string-retention-utils.d.ts +4 -0
- package/cli/dist-server/types/workspace/cbc-shared/lib/node/hooks/hook-types.d.ts +7 -1
- package/cli/dist-server/types/workspace/cbc-shared/lib/node/index.d.ts +2 -0
- package/cli/dist-server/types/workspace/cbc-shared/lib/node/model/model-errors.d.ts +7 -3
- package/cli/dist-server/types/workspace/cbc-shared/lib/node/tools/tool-names.d.ts +1 -0
- package/cli/dist-server/types/workspace/cbc-shared/lib/node/utils/retry-backoff.d.ts +30 -0
- package/cli/dist-server/types/workspace/cbc-shared/lib/node/utils/retry-policy.d.ts +26 -0
- package/cli/dist-server/types/workspace/cbc-workflow/lib/node/workflow/workflow-execution.d.ts +14 -1
- package/cli/dist-server/types/workspace/cbc-workflow/lib/node/workflow/workflow-manager.d.ts +7 -0
- package/cli/dist-server/types/workspace/cbc-worktree/lib/node/worktree/worktree-session.d.ts +3 -0
- package/cli/dist-server/types/workspace/product/lib/common/cloud-product-provider.d.ts +9 -0
- package/cli/dist-server/types/workspace/product/lib/common/index.d.ts +1 -0
- package/cli/dist-server/types/workspace/product/lib/common/pick-market-skill-id.d.ts +13 -0
- package/cli/dist-server/types/workspace/product/lib/common/tool-control-catalog.d.ts +2 -2
- package/cli/dist-server/types/workspace/product/lib/common/types/features.d.ts +62 -2
- package/cli/dist-server/types/workspace/product/lib/common/types/language-model.d.ts +66 -0
- package/cli/dist-server/types/workspace/product/lib/common/types/product.d.ts +7 -1
- package/cli/dist-server/types/workspace/sandbox-cli/lib/common/backup-policy.d.ts +10 -1
- package/cli/dist-server/types/workspace/sandbox-cli/lib/common/center-protocol.generated.d.ts +370 -4
- package/cli/dist-server/types/workspace/sandbox-cli/lib/common/file-policy.d.ts +1 -1
- package/cli/dist-server/types/workspace/sandbox-cli/lib/node/sandbox-center-client.d.ts +216 -0
- package/cli/package.json +1 -1
- package/cli/product.cloudhosted.json +2 -2
- package/cli/product.internal.json +259 -40
- package/cli/product.ioa.json +333 -148
- package/cli/product.json +309 -351
- package/cli/product.selfhosted.json +2 -2
- package/docs/README.md +1 -0
- package/docs/in-process.md +16 -0
- package/lib/application/services.d.ts +3 -1
- package/lib/application/services.js +1 -1
- package/lib/components/sandbox-center.d.mts +2 -0
- package/lib/components/sandbox-center.mjs +1 -0
- package/lib/components/session-config.d.mts +2 -0
- package/lib/components/session-config.mjs +1 -1
- package/lib/harness/create-harness.js +1 -1
- package/lib/harness/runtime.js +1 -1
- package/lib/harness/types.d.ts +3 -0
- package/lib/integration/executor-supervisor.js +1 -1
- package/lib/public.d.ts +1 -0
- package/lib/runtime/sandbox-center.d.ts +21 -0
- package/lib/runtime/sandbox-center.js +1 -0
- package/lib/server/public.d.ts +1 -0
- package/lib/session/agent-backend.d.ts +2 -0
- package/lib/session/agent-backend.js +1 -1
- package/lib/session/local-fs.js +1 -1
- package/lib/session/server-config.js +1 -1
- package/lib/session/server-interactions.js +1 -1
- package/package.json +25 -15
- package/lib/session/local-options.d.ts +0 -50
- package/lib/session/local-options.js +0 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare function resolveMessageSpeakerLabel(input: {
|
|
2
|
+
session?: {
|
|
3
|
+
id?: string;
|
|
4
|
+
storeId?: string;
|
|
5
|
+
meta?: Record<string, unknown>;
|
|
6
|
+
} | undefined;
|
|
7
|
+
runAgentName?: string;
|
|
8
|
+
}): string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* 子会话的**展示名**(给人看):团队成员用成员名,其余子代理用自身预设名(`meta.agentName`);
|
|
11
|
+
* 主会话 / 无会话 / 无身份线索返回 undefined。**只用于展示与遥测标签,不要拿它查表。**
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveSubAgentDisplayName(session: {
|
|
14
|
+
id?: string;
|
|
15
|
+
storeId?: string;
|
|
16
|
+
meta?: Record<string, unknown>;
|
|
17
|
+
} | undefined): string | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* 子会话的**查表键**(REPL 沙箱白名单 / overlay 缓存用):只认「预设名」这一种语义。
|
|
20
|
+
*
|
|
21
|
+
* 与展示名刻意分开(评审):团队成员会把自己的成员名写进 `meta.agentName`(teammate-runner),
|
|
22
|
+
* 于是 `meta.agentName` 同时承载「预设名」与「成员名」两种含义 —— 拿成员名去查 agent 配置查不到,
|
|
23
|
+
* 只能落到默认 agent 的兜底(既不是成员自己的白名单、也不是「不过滤」)。取不到可信的预设名时
|
|
24
|
+
* 返回 undefined = 不额外收窄(与改动前一致),不去猜。
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveSubAgentAgentKey(session: {
|
|
27
|
+
id?: string;
|
|
28
|
+
storeId?: string;
|
|
29
|
+
meta?: Record<string, unknown>;
|
|
30
|
+
} | undefined): string | undefined;
|
|
31
|
+
/** 展示名的**派发侧镜像**:子会话还没建时拿不到 `meta.teamContext`,但这对值就是稍后写进 session 的同一对。 */
|
|
32
|
+
export declare function resolveSubAgentDisplayNameFromParts(input: {
|
|
33
|
+
memberName?: string;
|
|
34
|
+
presetName?: string;
|
|
35
|
+
}): string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* 查表键的**派发侧镜像**(AgentManager.sandboxScopedAgentView 传身份用):
|
|
38
|
+
* 预设名与成员名**同值**(团队成员把自己的名字写进 meta.agentName)时判为「没有可信预设名」→ undefined,
|
|
39
|
+
* 与运行期 `resolveSubAgentAgentKey` 同源 —— 否则派发侧按成员名收窄、执行侧判不到,两边分叉。
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveSubAgentAgentKeyFromParts(input: {
|
|
42
|
+
memberName?: string;
|
|
43
|
+
presetName?: string;
|
|
44
|
+
}): string | undefined;
|
package/cli/dist-server/types/vendor/cbc-core/node/agent/tool-call-loop-detector-service.d.ts
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* wastes tokens/credits.
|
|
7
7
|
*
|
|
8
8
|
* Detection rules:
|
|
9
|
-
* 1. Generic loop: blacklisted tool with identical arguments 4 consecutive times
|
|
9
|
+
* 1. Generic loop: blacklisted tool with semantically identical JSON arguments 4 consecutive times
|
|
10
10
|
* 2. Read file loop: Read tool targeting the same file_path 40 consecutive times
|
|
11
|
-
* 3. Non-blacklist loop: any tool NOT in blacklist with identical arguments 40 consecutive times
|
|
11
|
+
* 3. Non-blacklist loop: any tool NOT in blacklist with semantically identical JSON arguments 40 consecutive times
|
|
12
12
|
*/
|
|
13
13
|
import type { AgentInputItem } from '../../../cbc-shared/node/index.js';
|
|
14
14
|
import { Logger } from '../../../../workspace/telemetry/lib/common/index.js';
|
|
@@ -38,14 +38,15 @@ export declare class ToolCallLoopDetectorImpl implements ToolCallLoopDetector {
|
|
|
38
38
|
arguments: string;
|
|
39
39
|
}>;
|
|
40
40
|
/**
|
|
41
|
-
* Check for generic loop: same tool with identical arguments
|
|
41
|
+
* Check for generic loop: same tool with semantically identical JSON arguments
|
|
42
|
+
* N consecutive times. Malformed or very large argument payloads retain exact-string semantics.
|
|
42
43
|
*/
|
|
43
44
|
protected checkGenericLoop(tailCalls: Array<{
|
|
44
45
|
name: string;
|
|
45
46
|
arguments: string;
|
|
46
47
|
}>): LoopDetectionResult;
|
|
47
48
|
/**
|
|
48
|
-
* Check for non-blacklist tool loop: any tool NOT in the blacklist with identical arguments
|
|
49
|
+
* Check for non-blacklist tool loop: any tool NOT in the blacklist with semantically identical JSON arguments
|
|
49
50
|
* called N consecutive times (threshold: NON_BLACKLIST_LOOP_THRESHOLD).
|
|
50
51
|
* Scans from the tail of input, collecting only non-blacklist function_call items.
|
|
51
52
|
*/
|
|
@@ -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 次 / 周期序列重复 10 轮)。
|
|
30
|
+
* 它覆盖新增的两条规则(同工具连续 40 次,Bash 单独放到 80 次 / 周期序列重复 10 轮)。
|
|
31
31
|
*
|
|
32
32
|
* 两者刻意并存:旧规则的静默语义已被线上验证,不因新能力回归。
|
|
33
33
|
*/
|
|
@@ -5,8 +5,13 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { ToolCallLoopTriggerType } from '../../../../workspace/telemetry/lib/common/event/types/craft.js';
|
|
7
7
|
export interface ToolCallLoopThresholds {
|
|
8
|
-
/** 同一工具连续调用达到该次数即判定为循环。 */
|
|
8
|
+
/** 同一工具连续调用达到该次数即判定为循环。Bash 走单独阈值。 */
|
|
9
9
|
consecutiveThreshold: number;
|
|
10
|
+
/**
|
|
11
|
+
* Bash 连续调用的单独阈值。长任务里模型会连续跑很多条不同命令,
|
|
12
|
+
* 只看工具名时 40 次容易把正常推进误判成循环。
|
|
13
|
+
*/
|
|
14
|
+
bashConsecutiveThreshold: number;
|
|
10
15
|
/** AAB 块需要连续重复的轮数。 */
|
|
11
16
|
sequenceRepeats: number;
|
|
12
17
|
}
|
|
@@ -17,6 +22,8 @@ export interface ToolCallLoopHit {
|
|
|
17
22
|
/** 重复序列的周期长度;AAB 恒为 3,连续同工具恒为 1。 */
|
|
18
23
|
patternLength: number;
|
|
19
24
|
}
|
|
25
|
+
/** 与 `ToolNames.BASH` 对齐。模式识别层不依赖 agent-protocol,避免把工具名枚举拉进来。 */
|
|
26
|
+
export declare const BASH_LOOP_TOOL_NAME = "Bash";
|
|
20
27
|
export declare const DEFAULT_TOOL_CALL_LOOP_THRESHOLDS: ToolCallLoopThresholds;
|
|
21
28
|
/** AAB 块的长度。多工具循环只识别这一种形状,因此是常量而非可配阈值。 */
|
|
22
29
|
export declare const AAB_PERIOD = 3;
|
|
@@ -36,7 +43,7 @@ export declare class ToolCallLoopTracker {
|
|
|
36
43
|
* 记录一次即将执行的工具调用,返回本次是否命中循环。
|
|
37
44
|
*
|
|
38
45
|
* 命中优先级:先判连续同工具,再判 AAB 重复。两条规则的阈值默认不重叠
|
|
39
|
-
*
|
|
46
|
+
* (普通工具 40 次、Bash 80 次 vs AAB 重复 10 轮),实践中不会互相抢占。
|
|
40
47
|
*/
|
|
41
48
|
record(toolName: string): ToolCallLoopHit | undefined;
|
|
42
49
|
/**
|
|
@@ -52,14 +59,18 @@ export declare class ToolCallLoopTracker {
|
|
|
52
59
|
* - `ABC`(三者互不相同)通常是正常的多步工作流(读文件 → 改文件 → 跑测试,
|
|
53
60
|
* 然后换下一个文件),按周期重复判它循环误伤面太大;
|
|
54
61
|
* - `ABAB` 这类两工具交替同样不判,避免把翻页 / 分批处理误当循环;
|
|
55
|
-
* - `AAA…` 属于连续同工具,由 consecutiveThreshold 那条规则负责。
|
|
62
|
+
* - `AAA…` 属于连续同工具,由 consecutiveThreshold / bashConsecutiveThreshold 那条规则负责。
|
|
56
63
|
*
|
|
57
64
|
* `X ≠ Y` 顺带保证了 AAB 一定是本原周期(唯一可能的更短整除周期是 1,
|
|
58
65
|
* 那要求三个元素全等),所以不需要额外的本原性校验。
|
|
59
66
|
*/
|
|
60
67
|
export declare function matchesRepeatedAabSequence(history: readonly string[], repeats: number): boolean;
|
|
61
68
|
/**
|
|
62
|
-
*
|
|
69
|
+
* 读取阈值配置。环境变量只用于 QA 快速复现,生产不设置即走默认值。
|
|
63
70
|
* AAB 的周期是形状定义的一部分,不开放配置。
|
|
71
|
+
*
|
|
72
|
+
* `CBC_LOOP_GUARD_CONSECUTIVE_THRESHOLD` 只覆盖非 Bash 工具。Bash 用
|
|
73
|
+
* `CBC_LOOP_GUARD_BASH_CONSECUTIVE_THRESHOLD`,避免 QA 把通用阈值压低时
|
|
74
|
+
* 把长任务放宽一并关掉。
|
|
64
75
|
*/
|
|
65
76
|
export declare function resolveToolCallLoopThresholds(env?: NodeJS.ProcessEnv): ToolCallLoopThresholds;
|
|
@@ -1,31 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent-trigger payload helper, shared by SessionHookManager and ToolHookManager.
|
|
3
|
-
*
|
|
4
|
-
* Mirrors Claude Code's `createBaseHookInput` (utils/hooks.ts) so that every
|
|
5
|
-
* hook event carries enough context for users to branch on
|
|
6
|
-
* "main thread vs sub-agent" inside their Settings-level hooks.
|
|
7
|
-
*
|
|
8
|
-
* Rules (CC parity):
|
|
9
|
-
* - `agent_type` is the agent's display name; populated from `session.agentName`
|
|
10
|
-
* when set. On the main thread this is the `--agent` flag (when used) or the
|
|
11
|
-
* default agent name. Inside a sub-agent this is the sub-agent's `name`
|
|
12
|
-
* (e.g. "Explore", "Plan", "general-purpose").
|
|
13
|
-
* - `agent_id` is only meaningful inside a sub-agent run — CC leaves it
|
|
14
|
-
* `undefined` on the main thread. We honour the same convention by only
|
|
15
|
-
* emitting it when `session.storeId` is present (sub-agent sessions get a
|
|
16
|
-
* `agent-{8}` storeId; main sessions do not).
|
|
17
|
-
*
|
|
18
|
-
* Kept dependency-free so it can be imported from anywhere — including modules
|
|
19
|
-
* that must avoid pulling the full `../session` barrel (which transitively
|
|
20
|
-
* loads SessionManager / tips and triggers IoC initialisation).
|
|
21
|
-
*/
|
|
22
1
|
export interface AgentTriggerLike {
|
|
23
2
|
id?: string;
|
|
24
3
|
agentName?: string;
|
|
25
4
|
storeId?: string;
|
|
5
|
+
/** 会话 meta:身份标签要读 agentName / teamContext.memberName,parentSessionId 供子会话判定。 */
|
|
26
6
|
meta?: {
|
|
27
7
|
parentSessionId?: string;
|
|
28
|
-
|
|
8
|
+
agentName?: string;
|
|
9
|
+
teamContext?: {
|
|
10
|
+
memberName?: unknown;
|
|
11
|
+
};
|
|
12
|
+
} & Record<string, unknown>;
|
|
29
13
|
}
|
|
30
14
|
export declare function buildAgentTrigger(session: AgentTriggerLike | undefined | null): {
|
|
31
15
|
agent_id?: string;
|
|
@@ -31,7 +31,10 @@ export interface HookInput {
|
|
|
31
31
|
*/
|
|
32
32
|
reason?: SessionEndReason;
|
|
33
33
|
/**
|
|
34
|
-
* User prompt content
|
|
34
|
+
* User prompt content.
|
|
35
|
+
* - UserPromptSubmit: the submitted prompt text.
|
|
36
|
+
* - UserPromptExpansion: Claude Code spec required field, always sent — the
|
|
37
|
+
* raw, pre-expansion text as typed by the user (e.g. "/deploy prod").
|
|
35
38
|
*/
|
|
36
39
|
prompt?: string;
|
|
37
40
|
/**
|
|
@@ -1,44 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* =====================
|
|
6
|
-
* 用户在 agent 还在跑(streaming 末尾、工具执行中等)时输入新消息,UI 调
|
|
7
|
-
* `agentService.run([userMsg])` 进来,`MessageQueueAgentRunInterceptor`
|
|
8
|
-
* (input-interceptors.ts:77-84) 看到 `inConversation=true`,把消息塞进
|
|
9
|
-
* `session.queue` 并设 `skipRun=true`。当前 turn 自然结束、emit `agent_end`,
|
|
10
|
-
* 但**没有任何组件**会主动调一次 `agentService.run([], session)` 来触发
|
|
11
|
-
* interceptor 的 drain 分支(input-interceptors.ts:85-103,那条分支会
|
|
12
|
-
* `mergeConsecutiveUserMessages` 把队列里的消息拍成一个新 turn)。
|
|
13
|
-
*
|
|
14
|
-
* 结果:消息僵在 `session.queue`,UI 显示"已发送",agent 永远不回。
|
|
15
|
-
*
|
|
16
|
-
* `TeamInboxDispatchService` 看起来形态对,但它只检查
|
|
17
|
-
* `RichMessageQueueManager`(团队成员消息进的那个 queue),全 codebase 只有
|
|
18
|
-
* `team-create-tool.ts:332` 一处往 rich queue 写 —— 普通 TUI 用户输入完全
|
|
19
|
-
* 走 `session.queue`,团队 dispatcher 看不到。
|
|
20
|
-
*
|
|
21
|
-
* 这个 service 就填这个空:每个 session 都订阅 `agent_end`,guard 通过后
|
|
22
|
-
* 调一次空 input 的 `agentService.run`,让现有 interceptor 自己合并消费。
|
|
23
|
-
*
|
|
24
|
-
* 与 TeamInboxDispatchService 的关系
|
|
25
|
-
* ==================================
|
|
26
|
-
* - Mode A(默认):`isDeferredDispatchEnabledSync()===false`。
|
|
27
|
-
* IdleQueueDrainService 接管 `session.queue` 的 drain;TeamInboxDispatchService
|
|
28
|
-
* 也订阅了,但它看 rich queue(一般为空)→ short-circuit。
|
|
29
|
-
* - Mode B:`isDeferredDispatchEnabledSync()===true`。
|
|
30
|
-
* IdleQueueDrainService 入口 short-circuit;TeamInboxDispatchService 走
|
|
31
|
-
* rich queue 的 immediate/pending 路径。
|
|
32
|
-
* 两 service 各自有 `dispatching` Set,最坏情况下都是 short-circuit return,
|
|
33
|
-
* 不会双重发起 run。
|
|
34
|
-
*
|
|
35
|
-
* 它不做的事
|
|
36
|
-
* ==========
|
|
37
|
-
* - 不动 `session.queue` 里的内容(让 interceptor 现有 mergeConsecutive 逻辑
|
|
38
|
-
* 作为唯一消费点,避免逻辑漂移)。
|
|
39
|
-
* - 不在 compact 中触发(`session.isCompressing` guard)。
|
|
40
|
-
* - 不在 Mode B 中触发。
|
|
41
|
-
* - 不影响 cancel 路径的 abort 行为(只在 `agent_end` 后做兜底)。
|
|
2
|
+
* Wake local queues after a turn ends. Mode A owns session.queue; Mode B tasks
|
|
3
|
+
* own its non-mirror items. Mode B main sessions remain with rich queue.
|
|
4
|
+
* MessageQueueAgentRunInterceptor remains the only dequeue/merge point.
|
|
42
5
|
*/
|
|
43
6
|
import { Logger } from '../../../../workspace/telemetry/lib/common/index.js';
|
|
44
7
|
import { AgentManager, AgentService } from '../agent/agent-protocol';
|
|
@@ -64,21 +27,6 @@ export declare class IdleQueueDrainServiceImpl implements IdleQueueDrainService
|
|
|
64
27
|
* 空队列直接返回。
|
|
65
28
|
*/
|
|
66
29
|
requestDrain(session: Session): void;
|
|
67
|
-
/**
|
|
68
|
-
* Guard 链 + 调 agentService.run 触发 interceptor 的 drain 分支。
|
|
69
|
-
*
|
|
70
|
-
* Guard 顺序(逐个 short-circuit return):
|
|
71
|
-
* 1. 重入:同 session 上一次 tryDrain 还没 await 完。
|
|
72
|
-
* 2. compact 中:`session.isCompressing===true`。compact 自身的
|
|
73
|
-
* continue-run 也会 emit `agent_end`,必须避让。
|
|
74
|
-
* 3. Mode B:rich queue 通道由 TeamInboxDispatchService 处理。
|
|
75
|
-
* 4. DI 兜底:headless 等变体可能没拉到 AgentService/AgentManager。
|
|
76
|
-
* 5. 空队列:没东西好 drain。
|
|
77
|
-
* 6. 取消记账在途:见下方注释。
|
|
78
|
-
*
|
|
79
|
-
* 失败回灌:interceptor 在 line 95 已经 `clearQueue`,如果后续 run 抛错,
|
|
80
|
-
* 队列里的消息会"被消费但又没真消费",相当于丢了。所以在调 run 之前
|
|
81
|
-
* 快照 queue,run 抛错时检查 queue 是否被清空、被清空就把快照灌回。
|
|
82
|
-
*/
|
|
30
|
+
/** Reuse the existing idle drain and its pre-result failure restoration. */
|
|
83
31
|
private tryDrain;
|
|
84
32
|
}
|
|
@@ -8,6 +8,7 @@ export * from './session-response-host-protocol';
|
|
|
8
8
|
export * from './background-task-protocol';
|
|
9
9
|
export * from './root-session-scope';
|
|
10
10
|
export * from './session-factory';
|
|
11
|
+
export { assertSessionRuntimeOpen, closeSessionRuntime, isSessionRuntimeClosed, sessionRuntimeSignal, } from './session-runtime-lifecycle';
|
|
11
12
|
export * from './session-admission-service';
|
|
12
13
|
export * from './session-manager';
|
|
13
14
|
export * from './session-store';
|
|
@@ -25,12 +26,14 @@ export { getSessionCanUseTool, resolveCanUseTool, resolveCanUseToolOwner, setSes
|
|
|
25
26
|
export type { CanUseTool, CanUseToolOptions, CanUseToolOwner, PermissionBehavior, PermissionDecisionClassification, PermissionResult as CanUseToolPermissionResult, PermissionRuleValue, PermissionUpdate as CanUseToolPermissionUpdate, PermissionUpdateDestination, } from './can-use-tool';
|
|
26
27
|
export * from './dual-channel-interaction';
|
|
27
28
|
export * from './session-persistence';
|
|
29
|
+
export * from './session-persistence-error';
|
|
28
30
|
export * from './session-set-current';
|
|
29
31
|
export * from './cancel-session-runtime-state';
|
|
30
32
|
export * from './user-request-boundary';
|
|
31
33
|
export { isTruncationRecoveryActive } from './truncation-recovery';
|
|
32
34
|
export * from './aborted-stream-draft-store';
|
|
33
35
|
export * from './stream-timeout-retry-budget';
|
|
36
|
+
export { consumeRecoveryRequestPending } from './recovery-budget';
|
|
34
37
|
export * from './session-run-state-machine-protocol';
|
|
35
38
|
export * from './session-run-state-machine';
|
|
36
39
|
export * from './session-run-state-projection-service';
|
|
@@ -8,12 +8,44 @@ import { InterruptionService, type PendingApprovalView, Session, SessionHookMana
|
|
|
8
8
|
import { SessionRunStateMachine } from './session-run-state-machine-protocol';
|
|
9
9
|
type IIdleQueueDrainService = import('./session-protocol').IdleQueueDrainService;
|
|
10
10
|
export declare class InterruptionServiceImpl implements InterruptionService {
|
|
11
|
+
private readonly resolvedSandboxItems;
|
|
11
12
|
private pendingInterruptions;
|
|
12
13
|
private itemToSessionMap;
|
|
13
14
|
private interruptionQueues;
|
|
14
15
|
private parentIdToMainSession;
|
|
15
16
|
private childToMainSession;
|
|
16
17
|
private waitForSubscriptions;
|
|
18
|
+
private readonly approvalSources;
|
|
19
|
+
private readonly handlingStates;
|
|
20
|
+
private readonly reportedStaleStates;
|
|
21
|
+
private readonly reportedDiscardedApprovals;
|
|
22
|
+
private readonly handledResults;
|
|
23
|
+
private readonly resumeProgress;
|
|
24
|
+
/**
|
|
25
|
+
* Terminal by design: a blocked continuation already proved it cannot make
|
|
26
|
+
* progress, and a later user request arrives on a *new* RunState, so the
|
|
27
|
+
* session is never stranded.
|
|
28
|
+
*/
|
|
29
|
+
private readonly blockedResumeStates;
|
|
30
|
+
/**
|
|
31
|
+
* Deliberately not `session.meta.consecutiveEmptyDrainCount`: the idle
|
|
32
|
+
* empty-drain guard both increments that counter (tripping this
|
|
33
|
+
* continuation early, aborting a legitimate resume) and resets it
|
|
34
|
+
* (stretching the budget without bound).
|
|
35
|
+
*/
|
|
36
|
+
private readonly resumeNoProgressCount;
|
|
37
|
+
private assertApprovalSource;
|
|
38
|
+
private approveSource;
|
|
39
|
+
private awaitPermissionReply;
|
|
40
|
+
/**
|
|
41
|
+
* A decision the user actually clicked must never disappear without a word.
|
|
42
|
+
*
|
|
43
|
+
* The card is dequeued and the deferred rejected, but the run that owned it
|
|
44
|
+
* is already gone — so nothing downstream surfaces the rejection and the
|
|
45
|
+
* user is left believing the tool was approved.
|
|
46
|
+
*/
|
|
47
|
+
private reportDiscardedDecision;
|
|
48
|
+
private reportStaleSource;
|
|
17
49
|
/**
|
|
18
50
|
* 权限审批全局真相源(方案一:统一数据源)。
|
|
19
51
|
*
|
|
@@ -61,6 +93,8 @@ export declare class InterruptionServiceImpl implements InterruptionService {
|
|
|
61
93
|
protected readonly idleQueueDrainService?: IIdleQueueDrainService;
|
|
62
94
|
protected readonly traceCollector?: SessionInterruptionTraceHost;
|
|
63
95
|
protected get startupProfiler(): SessionInterruptionProfilerHost;
|
|
96
|
+
/** Claim before calling out: sandbox callbacks can throw or synchronously re-enter. */
|
|
97
|
+
private takeSandboxResolve;
|
|
64
98
|
approve(item: RunToolApprovalItem, options?: {
|
|
65
99
|
alwaysApprove?: boolean;
|
|
66
100
|
scope?: 'session' | 'localSettings';
|
|
@@ -101,8 +135,9 @@ export declare class InterruptionServiceImpl implements InterruptionService {
|
|
|
101
135
|
*
|
|
102
136
|
* 幂等:未注册的 sessionId 为 no-op。
|
|
103
137
|
*/
|
|
104
|
-
releaseSession(
|
|
105
|
-
protected handleInterruptions(session: Session, interruptions: RunToolApprovalItem[]): Promise<void>;
|
|
138
|
+
releaseSession(target: string | Session): void;
|
|
139
|
+
protected handleInterruptions(session: Session, interruptions: RunToolApprovalItem[], result?: RunResult<any, any> | StreamedRunResult<any, any> | undefined): Promise<void>;
|
|
140
|
+
private processInterruptions;
|
|
106
141
|
protected executePendingManualPostCompactHook(session: Session, result: RunResult<any, any> | StreamedRunResult<any, any>): Promise<void>;
|
|
107
142
|
waitFor(session: Session): Promise<void>;
|
|
108
143
|
/**
|
|
@@ -334,15 +369,26 @@ export declare class InterruptionServiceImpl implements InterruptionService {
|
|
|
334
369
|
private static sanitizeToolNotFoundMessage;
|
|
335
370
|
private hasRecentModelErrorRetry;
|
|
336
371
|
/**
|
|
337
|
-
*
|
|
338
|
-
*
|
|
372
|
+
* 网络 / 流错误自动恢复的统一前置步骤:认领额度 → 可取消的指数退避 → 标记恢复轮。
|
|
373
|
+
*
|
|
374
|
+
* 认领放在退避之前、且晚于本 catch 里的第一个 await:session-manager 的 gate 在
|
|
375
|
+
* `result.completed` reject 后同步读取同一份预算判据,认领若早于 gate 读取,最后
|
|
376
|
+
* 一次重试会被 gate 误判为「预算已耗尽」而提前下发终态。
|
|
377
|
+
*
|
|
378
|
+
* 退避期间会话处于 RETRYING:失败的 run 与写入中断结果的 skipRun run 都已收尾回 idle,
|
|
379
|
+
* 这里重新置为 busy,TUI 继续显示进行中并响应 Esc,用户新消息进队列而不是直接起 run。
|
|
380
|
+
* 恢复 run 带 bypassMessageQueue 从 RETRYING 直接发起,中间不回 idle,不留让新 run
|
|
381
|
+
* 插入的空窗;恢复 run 收尾(AGENT_ENDED)时回 idle 并带出排队消息。
|
|
382
|
+
*
|
|
383
|
+
* 退避期间用户取消时退回额度、以 RUN_FAILED 收回 idle 并返回 `cancelled`,调用方不得
|
|
384
|
+
* 再发起。取消信号在等待前现取:写入中断结果的 skipRun run 会替换 `session.abortController`,
|
|
385
|
+
* 用户此后按下的 Stop 作用在新 controller 上;排队消息接管 owner 时,其 abort 会级联到这里。
|
|
339
386
|
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
* 将 retry marker 推出 5 条消息的窗口,导致误判为"可以再次重试"
|
|
387
|
+
* 等待结束时若状态既不是 RETRYING 也不是 idle,说明 RETRYING 被迟到的收尾事件冲掉后
|
|
388
|
+
* 已有新 run 被接纳并在执行,返回 `superseded`,否则恢复 run 会与它同时写同一个会话。
|
|
389
|
+
* 此时不退回额度——新请求边界已经清零,再减一次会扣掉新链的额度。
|
|
344
390
|
*/
|
|
345
|
-
private
|
|
391
|
+
private prepareRecoveryAttempt;
|
|
346
392
|
/**
|
|
347
393
|
* CLI TUI 手打 `/compact` 裸跑成功后补发 SessionStart('compact')。
|
|
348
394
|
*
|
|
@@ -29,6 +29,24 @@ export declare class finishReasonErrorInterceptor implements ModelResponseInterc
|
|
|
29
29
|
protected readonly sessionStore: SessionStore;
|
|
30
30
|
protected readonly telemetryService: TelemetryService;
|
|
31
31
|
intercept(ctx: ModelResponseInterceptorContext): Promise<boolean | void>;
|
|
32
|
+
/**
|
|
33
|
+
* 处理「已经产出实质内容之后才 `finish_reason=error`」:自动续写,最多 3 次、1s 起步 2 倍退避。
|
|
34
|
+
*
|
|
35
|
+
* 没有任何实质输出就 error 的两种形态(仅 reasoning / 零 token)在模型层被转成可重试的
|
|
36
|
+
* EmptyStreamError,走 interruption-service 的流错误恢复;三者认领同一份 error 预算。
|
|
37
|
+
*
|
|
38
|
+
* 能走到这里说明这次 run 已经结束:SDK 只要本轮还有可执行的工具调用就会继续循环,
|
|
39
|
+
* 不会把控制权交回。因此不存在「参数完整但尚未执行」的工具调用;万一出现,每次构造
|
|
40
|
+
* 请求前的 `fillFunctionCallResultHistory` 也会补齐配对,不会因孤儿调用触发上游 400。
|
|
41
|
+
* 本期只统计孤儿数量用于验证这一推论,不改补齐逻辑。
|
|
42
|
+
*
|
|
43
|
+
* 预算用尽、退避期间被取消或发起失败时都**不返回 `true`**:没有重跑在路上,本轮必须
|
|
44
|
+
* 正常收敛给上层,否则 CLI 会一直等一个不存在的 run。
|
|
45
|
+
*/
|
|
46
|
+
private handleErrorFinishReason;
|
|
47
|
+
private writeErrorTerminalMessage;
|
|
48
|
+
/** 统计本轮以 error 收尾时残留的无配对结果工具调用,用于验证「此处不应有孤儿」的推论。 */
|
|
49
|
+
private logOrphanToolCallsOnError;
|
|
32
50
|
private shouldSkipExpectedSubagentToolCalls;
|
|
33
51
|
/**
|
|
34
52
|
* 处理 length 类型的完成原因:从断点续写(#119765)。
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Session } from './session-protocol';
|
|
2
|
+
/**
|
|
3
|
+
* `finish_reason=error` 三种表现(已有输出 / 仅 reasoning / 零 token)共用的预算键。
|
|
4
|
+
*
|
|
5
|
+
* 三者是同一次上游故障的不同形态,而且会在恢复过程中互相转化(第一次零 token、
|
|
6
|
+
* 重试后只吐 reasoning、再重试吐了内容后又 error)。各记各的会让一次故障的总轮数
|
|
7
|
+
* 远超约定上限,所以必须认领同一个键。
|
|
8
|
+
*/
|
|
9
|
+
export declare const ERROR_RECOVERY_COUNT_META_KEY = "errorRecoveryCount";
|
|
10
|
+
/**
|
|
11
|
+
* 流开始之后的网络错误(错误仍带原始 errno)使用的预算键。
|
|
12
|
+
*
|
|
13
|
+
* 响应头之前的连接失败由模型层连接级重试处理,耗尽后被归一化成 HTTP 502 上抛,
|
|
14
|
+
* 不会再走到这里——两层不会为同一次失败接力。
|
|
15
|
+
*/
|
|
16
|
+
export declare const NETWORK_RECOVERY_COUNT_META_KEY = "networkErrorRetryCount";
|
|
17
|
+
/**
|
|
18
|
+
* `finish_reason=error` 后注入给模型的续写提示。
|
|
19
|
+
*
|
|
20
|
+
* 与截断续写(TRUNCATION_CONTINUATION_PROMPT)的区别是刻意去掉了「把剩下的工作拆小」:
|
|
21
|
+
* 那句是在修「一次输出太长」的因果,上游内部错误与输出长度无关,带上它既是错误归因,
|
|
22
|
+
* 也可能让模型把任务切碎、多烧轮次。同样不告诉模型「是服务端出错」——那会给它道歉和
|
|
23
|
+
* 复述的由头,与 no apology / no recap 自相矛盾。
|
|
24
|
+
*/
|
|
25
|
+
export declare const ERROR_RECOVERY_PROMPT: string;
|
|
26
|
+
/**
|
|
27
|
+
* 包成 error-recovery system-reminder:stream-json 等输出通道会把只含 system-reminder
|
|
28
|
+
* 的内部用户消息清空丢弃,避免恢复提示混进用户可见的对话。
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildErrorRecoveryReminder(): string;
|
|
31
|
+
export declare function readRecoveryBudgetCount(session: Session, key: string): number;
|
|
32
|
+
export declare function hasExhaustedRecoveryBudget(session: Session, key: string, limit?: number): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* 同步完成「判定 + 认领」,返回本次恢复的序号(1-based);预算已用尽返回 `undefined`。
|
|
35
|
+
*
|
|
36
|
+
* 判定与消耗必须在同一个同步段里完成:分散到 `await` 两侧时,两处调用可能同时在
|
|
37
|
+
* `count = limit - 1` 通过检查,上限就不再成立。
|
|
38
|
+
*/
|
|
39
|
+
export declare function claimRecoveryBudget(session: Session, key: string, limit?: number): number | undefined;
|
|
40
|
+
/** 认领后没有真正发起恢复(退避期间被取消、发起失败)时退回额度。 */
|
|
41
|
+
export declare function releaseRecoveryBudget(session: Session, key: string): void;
|
|
42
|
+
/** 清零并返回旧值,供日志使用。 */
|
|
43
|
+
export declare function resetRecoveryBudget(session: Session, key: string): number;
|
|
44
|
+
/**
|
|
45
|
+
* 「下一个模型请求是自动恢复轮」的一次性标记。
|
|
46
|
+
*
|
|
47
|
+
* 恢复轮的首 token 时限比首次请求短(见模型层)。这个标记在发起恢复 run 前由恢复
|
|
48
|
+
* 入口显式写入,由模型层在该 run 的第一个模型请求上读取并清除——之后同一 run 的工具
|
|
49
|
+
* 循环请求回到普通时限。不能改用重试计数反推「是否恢复轮」:计数跨多个模型请求累计,
|
|
50
|
+
* 反推会让恢复链之后的所有请求都被当成恢复轮。
|
|
51
|
+
*/
|
|
52
|
+
export declare const RECOVERY_REQUEST_PENDING_META_KEY = "recoveryRequestPending";
|
|
53
|
+
export declare function markRecoveryRequestPending(session: Session): void;
|
|
54
|
+
export declare function consumeRecoveryRequestPending(session: Session | undefined): boolean;
|
|
55
|
+
export declare function clearRecoveryRequestPending(session: Session): void;
|
|
@@ -208,4 +208,19 @@ export declare class SessionHookManagerImpl implements SessionHookManager {
|
|
|
208
208
|
* Does NOT support continueRequest.
|
|
209
209
|
*/
|
|
210
210
|
executeFinalStopHooks(session: Session, reason?: FinalStopReason): Promise<void>;
|
|
211
|
+
/**
|
|
212
|
+
* UserPromptExpansion — Claude Code 官方事件:任何用户输入的命令/skill 展开成
|
|
213
|
+
* prompt、送进模型之前统一从这里触发,可阻断展开。`command_args` / `prompt` 按
|
|
214
|
+
* 官方 schema 是必填字段(无参数时发空串,而不是整个省略 key)。
|
|
215
|
+
*/
|
|
216
|
+
executeUserPromptExpansionHooks(session: Session, payload: {
|
|
217
|
+
expansionType: 'slash_command' | 'mcp_prompt' | string;
|
|
218
|
+
commandName: string;
|
|
219
|
+
commandArgs: string;
|
|
220
|
+
commandSource?: string;
|
|
221
|
+
prompt: string;
|
|
222
|
+
}): Promise<{
|
|
223
|
+
allowed: boolean;
|
|
224
|
+
message?: string;
|
|
225
|
+
}>;
|
|
211
226
|
}
|
|
@@ -33,6 +33,15 @@ export declare class SessionManagerImpl implements SessionManager, ApplicationLi
|
|
|
33
33
|
private sessionStartTimes;
|
|
34
34
|
private addHistoryLocks;
|
|
35
35
|
private resultSubscriptions;
|
|
36
|
+
private readonly resultSubscriptionOwners;
|
|
37
|
+
/**
|
|
38
|
+
* 每个 sessionId 当前活着的会话对象。身份守卫不能只认 result 订阅的登记:
|
|
39
|
+
* 订阅由调用方事后 `initRunResultHandler` 挂上(teammate / agent-task),而
|
|
40
|
+
* drain / team-inbox / turn-metrics 在 create 时就按 id 注册了,中间那段
|
|
41
|
+
* 「已注册、无订阅」的窗口里 owner 读不到,旧任务的延迟释放会摘掉同 id 后继
|
|
42
|
+
* 会话的注册。WeakRef:登记不得延长会话寿命,deref 为空即无需保护的对象。
|
|
43
|
+
*/
|
|
44
|
+
private readonly liveSessionsById;
|
|
36
45
|
private overridePermissionModes;
|
|
37
46
|
private overrideModels;
|
|
38
47
|
/**
|
|
@@ -177,7 +186,7 @@ export declare class SessionManagerImpl implements SessionManager, ApplicationLi
|
|
|
177
186
|
*
|
|
178
187
|
* 幂等:未注册的 id 为 no-op;DI 容错:精简变体缺 service 时降级跳过。
|
|
179
188
|
*/
|
|
180
|
-
releaseInMemory(
|
|
189
|
+
releaseInMemory(target: string | Session): void;
|
|
181
190
|
rename(session: Session, name: string): Promise<void>;
|
|
182
191
|
setOverridePermissionMode(sessionId: string, mode: PermissionMode): void;
|
|
183
192
|
getOverridePermissionMode(sessionId: string): PermissionMode | undefined;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed local-transcript I/O failure (issue #119545).
|
|
3
|
+
*
|
|
4
|
+
* The only reason this type exists: `addHistory` must be able to tell "the
|
|
5
|
+
* local JSONL copy could not be written" apart from "this turn is broken".
|
|
6
|
+
* Windows `EBUSY` on the transcript is a third-party sharing violation, and a
|
|
7
|
+
* side-channel copy must never terminate a turn that is still executing tools.
|
|
8
|
+
*
|
|
9
|
+
* Everything else about persistence stays best-effort on purpose: there is no
|
|
10
|
+
* pending queue, no cross-process outbox and no durability barrier, so nothing
|
|
11
|
+
* else in the runtime waits on, or can be vetoed by, this file.
|
|
12
|
+
*/
|
|
13
|
+
export type SessionPersistencePhase = 'open' | 'stat' | 'write' | 'close' | 'rollback';
|
|
14
|
+
export type SessionPersistenceRollbackOutcome = 'not-needed' | 'succeeded' | 'failed';
|
|
15
|
+
export interface SessionPersistenceErrorOptions {
|
|
16
|
+
phase: SessionPersistencePhase;
|
|
17
|
+
cause: unknown;
|
|
18
|
+
attempt?: number;
|
|
19
|
+
rollbackOutcome?: SessionPersistenceRollbackOutcome;
|
|
20
|
+
retryable?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Windows sharing violations and their POSIX lookalikes. `EBUSY` is the one
|
|
24
|
+
* this ticket measured (25% of appends within 10ms of the previous write);
|
|
25
|
+
* `EPERM` / `EACCES` ride along because the same scanners produce them.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isRetryableSessionPersistenceError(error: unknown): boolean;
|
|
28
|
+
export declare class SessionPersistenceError extends Error {
|
|
29
|
+
readonly phase: SessionPersistencePhase;
|
|
30
|
+
readonly code?: string;
|
|
31
|
+
readonly attempt: number;
|
|
32
|
+
readonly rollbackOutcome: SessionPersistenceRollbackOutcome;
|
|
33
|
+
readonly retryable: boolean;
|
|
34
|
+
constructor(options: SessionPersistenceErrorOptions);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Duck-typed on purpose: core and the host package can each hold their own copy
|
|
38
|
+
* of this class, so `instanceof` is not reliable across the package boundary.
|
|
39
|
+
* The required fields keep a foreign error named `SessionPersistenceError` from
|
|
40
|
+
* being mistaken for one of ours — an unrecognized error still fails the run,
|
|
41
|
+
* which is the safe direction.
|
|
42
|
+
*/
|
|
43
|
+
export declare function isSessionPersistenceError(error: unknown): error is SessionPersistenceError;
|