@gajae-code/coding-agent 0.11.8 → 0.11.10
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 +35 -1
- package/dist/types/cli.d.ts +1 -0
- package/dist/types/config/model-profiles.d.ts +2 -3
- package/dist/types/config/model-registry.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +12 -5
- package/dist/types/gjc-runtime/deep-interview-draft.d.ts +8 -0
- package/dist/types/gjc-runtime/deep-interview-payload.d.ts +41 -0
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +32 -17
- package/dist/types/gjc-runtime/deep-interview-repair.d.ts +17 -0
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +135 -4
- package/dist/types/gjc-runtime/state-writer.d.ts +45 -0
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +5 -3
- package/dist/types/modes/components/welcome.d.ts +2 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +16 -8
- package/dist/types/runtime-mcp/redaction.d.ts +2 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +3 -1
- package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
- package/dist/types/sdk/bus/index.d.ts +8 -1
- package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +14 -7
- package/dist/types/sdk/bus/telegram-daemon.d.ts +74 -5
- package/dist/types/sdk/session.d.ts +7 -0
- package/dist/types/session/agent-session.d.ts +2 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +13 -3
- package/dist/types/session/internal/managed-session-storage.d.ts +8 -3
- package/dist/types/session/session-manager.d.ts +5 -1
- package/dist/types/session/session-storage.d.ts +13 -0
- package/dist/types/skill-state/active-state.d.ts +4 -0
- package/dist/types/task/provider-retry-status.d.ts +13 -0
- package/dist/types/task/types.d.ts +3 -0
- package/dist/types/tools/index.d.ts +3 -1
- package/package.json +8 -8
- package/scripts/generate-sdk-operation-inventory.ts +1 -0
- package/src/cli/mcp-cli.ts +4 -21
- package/src/cli/notify-cli.ts +1 -0
- package/src/cli.ts +32 -0
- package/src/commands/deep-interview.ts +9 -4
- package/src/commit/agentic/index.ts +3 -3
- package/src/commit/map-reduce/index.ts +2 -2
- package/src/config/model-profiles.ts +9 -10
- package/src/config/model-registry.ts +4 -2
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +78 -163
- package/src/eval/js/tool-bridge.ts +1 -1
- package/src/gjc-runtime/deep-interview-ambiguity.ts +68 -47
- package/src/gjc-runtime/deep-interview-draft.ts +843 -0
- package/src/gjc-runtime/deep-interview-payload.ts +262 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +310 -227
- package/src/gjc-runtime/deep-interview-repair.ts +1674 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +264 -103
- package/src/gjc-runtime/deep-interview-state.ts +916 -4
- package/src/gjc-runtime/ralplan-runtime.ts +3 -1
- package/src/gjc-runtime/state-writer.ts +166 -2
- package/src/gjc-runtime/workflow-manifest.generated.json +386 -1
- package/src/gjc-runtime/workflow-manifest.ts +191 -5
- package/src/hooks/skill-state.ts +23 -1
- package/src/internal-urls/docs-index.generated.ts +6 -5
- package/src/modes/components/welcome.ts +10 -2
- package/src/modes/controllers/selector-controller.ts +38 -8
- package/src/modes/interactive-mode.ts +29 -9
- package/src/prompts/agent-fragments/restricted-bash.md +1 -1
- package/src/prompts/agents/architect.md +8 -1
- package/src/prompts/agents/critic.md +8 -1
- package/src/prompts/agents/planner.md +8 -1
- package/src/prompts/system/system-prompt.md +1 -0
- package/src/runtime-mcp/json-rpc.ts +7 -4
- package/src/runtime-mcp/redaction.ts +30 -0
- package/src/sdk/broker/identity.ts +22 -12
- package/src/sdk/broker/session-index.ts +11 -1
- package/src/sdk/bus/chat-daemon-control.ts +5 -3
- package/src/sdk/bus/daemon-paths.ts +2 -0
- package/src/sdk/bus/index.ts +60 -5
- package/src/sdk/bus/notification-service.ts +19 -5
- package/src/sdk/bus/operator-runtime.ts +31 -5
- package/src/sdk/bus/telegram-cli.ts +6 -13
- package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +15 -7
- package/src/sdk/bus/telegram-daemon-control.ts +14 -5
- package/src/sdk/bus/telegram-daemon.ts +685 -120
- package/src/sdk/protocol/operation-inventory.generated.json +11 -0
- package/src/sdk/session.ts +12 -0
- package/src/session/agent-session.ts +140 -10
- package/src/session/internal/managed-session-scope.ts +339 -228
- package/src/session/internal/managed-session-storage.ts +17 -4
- package/src/session/session-manager.ts +96 -33
- package/src/session/session-storage.ts +23 -0
- package/src/skill-state/active-state.ts +10 -0
- package/src/skill-state/workflow-mutation-guard.ts +41 -7
- package/src/task/executor.ts +154 -44
- package/src/task/provider-retry-status.ts +88 -0
- package/src/task/render.ts +45 -26
- package/src/task/types.ts +3 -0
- package/src/tools/ask.ts +1 -0
- package/src/tools/bash-allowed-prefixes.ts +45 -1
- package/src/tools/index.ts +3 -1
- package/src/tools/subagent-render.ts +74 -16
- package/src/tools/subagent.ts +2 -0
- package/vendor/insane-search/MANIFEST.json +4 -1
- package/vendor/insane-search/engine/bias_check.py +5 -0
- package/vendor/insane-search/engine/fetch_chain.py +67 -1
- package/vendor/insane-search/engine/transport.py +13 -2
- package/vendor/insane-search/engine/validators.py +4 -1
|
@@ -2659,6 +2659,17 @@
|
|
|
2659
2659
|
"testIds": "not_applicable"
|
|
2660
2660
|
}
|
|
2661
2661
|
},
|
|
2662
|
+
{
|
|
2663
|
+
"sourceId": "agent_session:getToolForExecution",
|
|
2664
|
+
"sourceFile": "packages/coding-agent/src/session/agent-session.ts",
|
|
2665
|
+
"sourceKind": "agent_session",
|
|
2666
|
+
"decision": "exclude",
|
|
2667
|
+
"rationale": "internal accessor/plumbing, not a user-facing control seam",
|
|
2668
|
+
"exclusionMetadata": {
|
|
2669
|
+
"adapterMappings": "not_applicable",
|
|
2670
|
+
"testIds": "not_applicable"
|
|
2671
|
+
}
|
|
2672
|
+
},
|
|
2662
2673
|
{
|
|
2663
2674
|
"sourceId": "agent_session:registerForegroundBashBackgroundRequestHandler",
|
|
2664
2675
|
"sourceFile": "packages/coding-agent/src/session/agent-session.ts",
|
package/src/sdk/session.ts
CHANGED
|
@@ -428,6 +428,13 @@ export interface CreateAgentSessionOptions {
|
|
|
428
428
|
goalToolAllowedOps?: readonly ("create" | "get" | "complete" | "resume" | "drop" | "pause")[];
|
|
429
429
|
/** Optional per-session allowlist for tools exposed through search_tool_bm25. */
|
|
430
430
|
discoverableToolAllowedNames?: readonly string[];
|
|
431
|
+
/**
|
|
432
|
+
* Discoverable built-in tools that must stay in the initial active set even when
|
|
433
|
+
* `tools.discoveryMode === "all"` would otherwise hide them behind `search_tool_bm25`.
|
|
434
|
+
* Used for coordination tools (e.g. `irc`) that a subagent must be able to use
|
|
435
|
+
* immediately without first spending a discovery round-trip to find them.
|
|
436
|
+
*/
|
|
437
|
+
alwaysActiveToolNames?: readonly string[];
|
|
431
438
|
/** Optional shared agent registry for IRC routing. Default: AgentRegistry.global(). */
|
|
432
439
|
agentRegistry?: AgentRegistry;
|
|
433
440
|
/** Parent task ID prefix for nested artifact naming (e.g., "6-Extensions") */
|
|
@@ -1542,6 +1549,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1542
1549
|
goalToolAllowedOps: options.goalToolAllowedOps,
|
|
1543
1550
|
discoverableToolAllowedNames: options.discoverableToolAllowedNames,
|
|
1544
1551
|
getToolByName: name => session?.getToolByName(name),
|
|
1552
|
+
getToolForExecution: name => session?.getToolForExecution(name),
|
|
1545
1553
|
agentRegistry,
|
|
1546
1554
|
getSessionSpawns: () => options.spawns ?? "*",
|
|
1547
1555
|
getModelString: () => (hasExplicitModel && model ? formatModelString(model) : undefined),
|
|
@@ -2329,6 +2337,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2329
2337
|
// from the initial set unless they were explicitly requested or restored from persistence.
|
|
2330
2338
|
// The model finds them via search_tool_bm25 and activates them on demand.
|
|
2331
2339
|
if (effectiveDiscoveryMode === "all") {
|
|
2340
|
+
const alwaysActiveDiscoveredBuiltinNames = new Set(
|
|
2341
|
+
(options.alwaysActiveToolNames ?? []).map(name => name.toLowerCase()),
|
|
2342
|
+
);
|
|
2332
2343
|
const essentialBuiltinNames = new Set(computeEssentialBuiltinNames(settings));
|
|
2333
2344
|
const allowedDiscoveredBuiltinNames = options.discoverableToolAllowedNames
|
|
2334
2345
|
? new Set(options.discoverableToolAllowedNames.map(name => name.toLowerCase()))
|
|
@@ -2337,6 +2348,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2337
2348
|
const tool = toolRegistry.get(name);
|
|
2338
2349
|
if (!tool?.loadMode) return true; // not a built-in — leave MCP/custom/extension to existing logic
|
|
2339
2350
|
if (tool.loadMode === "essential") return true;
|
|
2351
|
+
if (alwaysActiveDiscoveredBuiltinNames.has(name)) return true;
|
|
2340
2352
|
return essentialBuiltinNames.has(name);
|
|
2341
2353
|
});
|
|
2342
2354
|
explicitlyRequestedDiscoveredBuiltinToolNames = selectRestorableDiscoveredBuiltinToolNames(
|
|
@@ -785,6 +785,22 @@ type RetryErrorClassification =
|
|
|
785
785
|
|
|
786
786
|
const BARE_DEFAULT_WATCHDOG_ERROR =
|
|
787
787
|
/^(?:[A-Za-z][A-Za-z0-9-]*(?: [A-Za-z][A-Za-z0-9-]*){0,3} )stream (?:timed out while waiting for the first event|stalled while waiting for the next event)$/;
|
|
788
|
+
const KIMI_CODE_FIRST_EVENT_TIMEOUT_MESSAGES = {
|
|
789
|
+
"anthropic-messages": new Set([
|
|
790
|
+
"Provider stream timed out while waiting for the first event",
|
|
791
|
+
"Anthropic stream timed out while waiting for the first event",
|
|
792
|
+
]),
|
|
793
|
+
"openai-completions": new Set([
|
|
794
|
+
"Provider stream timed out while waiting for the first event",
|
|
795
|
+
"OpenAI completions stream timed out while waiting for the first event",
|
|
796
|
+
]),
|
|
797
|
+
} as const;
|
|
798
|
+
|
|
799
|
+
const ALIBABA_TOKEN_PLAN_PROVIDER = "alibaba-token-plan";
|
|
800
|
+
const ALIBABA_TOKEN_PLAN_FIRST_EVENT_TIMEOUT_MESSAGES = {
|
|
801
|
+
"openai-responses": "OpenAI responses stream timed out while waiting for the first event",
|
|
802
|
+
"openai-completions": "OpenAI completions stream timed out while waiting for the first event",
|
|
803
|
+
} as const;
|
|
788
804
|
|
|
789
805
|
function hasBareDefaultRetryDisqualifyingFacts(message: AssistantMessage): boolean {
|
|
790
806
|
if (message.errorKind !== undefined || message.errorStatus !== undefined) return true;
|
|
@@ -1032,12 +1048,16 @@ function createHandoffContext(document: string): string {
|
|
|
1032
1048
|
// ============================================================================
|
|
1033
1049
|
|
|
1034
1050
|
/** Tools that require user permission before execution when an ACP client is connected. */
|
|
1035
|
-
const PERMISSION_REQUIRED_TOOLS = new Set(["bash", "monitor", "edit", "delete", "move"]);
|
|
1051
|
+
const PERMISSION_REQUIRED_TOOLS = new Set(["bash", "monitor", "eval", "edit", "delete", "move"]);
|
|
1036
1052
|
|
|
1037
1053
|
function isShellExecutionPermissionTool(toolName: string): boolean {
|
|
1038
1054
|
return toolName === "bash" || toolName === "monitor";
|
|
1039
1055
|
}
|
|
1040
1056
|
|
|
1057
|
+
function isExecutionPermissionTool(toolName: string): boolean {
|
|
1058
|
+
return isShellExecutionPermissionTool(toolName) || toolName === "eval";
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1041
1061
|
/** Permission options presented to the client on each gated tool call. */
|
|
1042
1062
|
const PERMISSION_OPTIONS: ClientBridgePermissionOption[] = [
|
|
1043
1063
|
{ optionId: "allow_once", name: "Allow once", kind: "allow_once" },
|
|
@@ -1105,6 +1125,18 @@ function getPermissionIntent(
|
|
|
1105
1125
|
const cmd = getStringProperty(a, "command")?.slice(0, 80);
|
|
1106
1126
|
return { toolName, title: cmd || toolName, cacheKey: toolName };
|
|
1107
1127
|
}
|
|
1128
|
+
if (toolName === "eval") {
|
|
1129
|
+
const cells = Array.isArray(a.cells) ? a.cells : [];
|
|
1130
|
+
const firstCell = cells.find(cell => cell && typeof cell === "object" && !Array.isArray(cell));
|
|
1131
|
+
const cell = firstCell as Record<string, unknown> | undefined;
|
|
1132
|
+
const title = cell ? getStringProperty(cell, "title") : undefined;
|
|
1133
|
+
const language = cell ? getStringProperty(cell, "language") : undefined;
|
|
1134
|
+
return {
|
|
1135
|
+
toolName,
|
|
1136
|
+
title: title ?? (language ? `Eval ${language}` : "eval"),
|
|
1137
|
+
cacheKey: toolName,
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1108
1140
|
if (toolName === "delete") {
|
|
1109
1141
|
const p = getStringProperty(a, "path");
|
|
1110
1142
|
return { toolName, title: p ? `Delete ${p}` : toolName, paths: p ? [p] : undefined, cacheKey: toolName };
|
|
@@ -5486,6 +5518,12 @@ export class AgentSession {
|
|
|
5486
5518
|
return undefined;
|
|
5487
5519
|
}
|
|
5488
5520
|
|
|
5521
|
+
/** Get a registered tool with the same guards used for model-facing execution. */
|
|
5522
|
+
getToolForExecution(name: string): AgentTool | undefined {
|
|
5523
|
+
const tool = this.getToolByName(name);
|
|
5524
|
+
return tool ? this.#prepareToolForExecution(tool) : undefined;
|
|
5525
|
+
}
|
|
5526
|
+
|
|
5489
5527
|
/**
|
|
5490
5528
|
* Register a UI/control-plane request handler for a currently foregrounded
|
|
5491
5529
|
* managed bash execution. This is intentionally narrower than generic
|
|
@@ -5750,6 +5788,7 @@ export class AgentSession {
|
|
|
5750
5788
|
return await target.execute(toolCallId, args as never, signal, onUpdate, ctx);
|
|
5751
5789
|
}
|
|
5752
5790
|
const isShellExecutionTool = isShellExecutionPermissionTool(target.name);
|
|
5791
|
+
const isExecutionTool = isExecutionPermissionTool(target.name);
|
|
5753
5792
|
const command =
|
|
5754
5793
|
isShellExecutionTool && args && typeof args === "object" && !Array.isArray(args)
|
|
5755
5794
|
? getStringProperty(args as Record<string, unknown>, "command")
|
|
@@ -5792,7 +5831,7 @@ export class AgentSession {
|
|
|
5792
5831
|
toolCallId,
|
|
5793
5832
|
toolName: target.name,
|
|
5794
5833
|
title: permissionIntent.title,
|
|
5795
|
-
...(
|
|
5834
|
+
...(isExecutionTool ? { kind: "execute" } : {}),
|
|
5796
5835
|
status: "pending",
|
|
5797
5836
|
rawInput: args,
|
|
5798
5837
|
...(commandContent ? { content: commandContent } : {}),
|
|
@@ -7514,7 +7553,11 @@ export class AgentSession {
|
|
|
7514
7553
|
}
|
|
7515
7554
|
|
|
7516
7555
|
// Validate API key
|
|
7517
|
-
const apiKey = await this.#
|
|
7556
|
+
const apiKey = await this.#awaitPromptPreflight(
|
|
7557
|
+
generation,
|
|
7558
|
+
preflightSignal,
|
|
7559
|
+
this.#modelRegistry.getApiKey(this.model, this.sessionId, { signal: preflightSignal }),
|
|
7560
|
+
);
|
|
7518
7561
|
if (!apiKey) {
|
|
7519
7562
|
throw new Error(formatNoCredentialOnboardingError(this.model.provider));
|
|
7520
7563
|
}
|
|
@@ -8997,6 +9040,10 @@ export class AgentSession {
|
|
|
8997
9040
|
this.agent.reset();
|
|
8998
9041
|
if (!options?.drop) await this.sessionManager.flush();
|
|
8999
9042
|
await this.sessionManager.newSession(options);
|
|
9043
|
+
// Gate the successor local:// root before the successor identity is
|
|
9044
|
+
// published to the agent, the workflow-gate emitter, hooks, or any
|
|
9045
|
+
// synchronous resolver (#2797 / #2925).
|
|
9046
|
+
await initializeLocalRoot(this.#localProtocolOptions());
|
|
9000
9047
|
this.setTodoPhases([]);
|
|
9001
9048
|
this.#syncAgentSessionId();
|
|
9002
9049
|
this.#bindWorkflowGateEmitter(previousWorkflowGateSessionId);
|
|
@@ -9064,6 +9111,10 @@ export class AgentSession {
|
|
|
9064
9111
|
this.#rebindProviderSessionState(new Map());
|
|
9065
9112
|
this.agent.reset();
|
|
9066
9113
|
await this.sessionManager.newSession(options);
|
|
9114
|
+
// Gate the successor local:// root before the successor identity is
|
|
9115
|
+
// published to the agent, the workflow-gate emitter, hooks, or any
|
|
9116
|
+
// synchronous resolver (#2797 / #2925).
|
|
9117
|
+
await initializeLocalRoot(this.#localProtocolOptions());
|
|
9067
9118
|
this.setTodoPhases([]);
|
|
9068
9119
|
this.#syncAgentSessionId();
|
|
9069
9120
|
this.#bindWorkflowGateEmitter(previousWorkflowGateSessionId);
|
|
@@ -9207,6 +9258,9 @@ export class AgentSession {
|
|
|
9207
9258
|
return false;
|
|
9208
9259
|
}
|
|
9209
9260
|
|
|
9261
|
+
// Fork rotates the session identity (and copies artifacts); gate the
|
|
9262
|
+
// successor local:// root before that identity is published (#2797 / #2925).
|
|
9263
|
+
await initializeLocalRoot(this.#localProtocolOptions());
|
|
9210
9264
|
// Update agent session ID
|
|
9211
9265
|
this.#syncAgentSessionId();
|
|
9212
9266
|
this.#bindWorkflowGateEmitter(previousWorkflowGateSessionId);
|
|
@@ -10614,6 +10668,10 @@ export class AgentSession {
|
|
|
10614
10668
|
previousSessionFile ? { parentSession: previousSessionFile } : undefined,
|
|
10615
10669
|
);
|
|
10616
10670
|
successorSessionFile = this.sessionFile;
|
|
10671
|
+
// Gate the successor local:// root inside the reversible prepare
|
|
10672
|
+
// window, before the successor identity is published; a gate failure
|
|
10673
|
+
// here rolls back (#2797 / #2925).
|
|
10674
|
+
await initializeLocalRoot(this.#localProtocolOptions());
|
|
10617
10675
|
this.agent.reset();
|
|
10618
10676
|
this.#syncAgentSessionId();
|
|
10619
10677
|
this.#rekeyHindsightMemoryForCurrentSessionId();
|
|
@@ -12432,6 +12490,7 @@ export class AgentSession {
|
|
|
12432
12490
|
}
|
|
12433
12491
|
const retryAfterMs = this.#parseRetryAfterMsFromError(message);
|
|
12434
12492
|
const shouldRetry =
|
|
12493
|
+
!this.#isTerminalProviderCompactionTimeout(candidate, message) &&
|
|
12435
12494
|
retrySettings.enabled &&
|
|
12436
12495
|
attempt < retrySettings.maxRetries &&
|
|
12437
12496
|
(retryAfterMs !== undefined ||
|
|
@@ -12617,7 +12676,61 @@ export class AgentSession {
|
|
|
12617
12676
|
* unknown/no-code errors are retryable.
|
|
12618
12677
|
*/
|
|
12619
12678
|
|
|
12679
|
+
#isKimiCodeFirstEventTimeout(message: AssistantMessage): boolean {
|
|
12680
|
+
if (message.stopReason !== "error" || message.provider !== "kimi-code") return false;
|
|
12681
|
+
const errorMessage = message.errorMessage ?? "";
|
|
12682
|
+
if (message.api === "anthropic-messages") {
|
|
12683
|
+
return KIMI_CODE_FIRST_EVENT_TIMEOUT_MESSAGES["anthropic-messages"].has(errorMessage);
|
|
12684
|
+
}
|
|
12685
|
+
if (message.api === "openai-completions") {
|
|
12686
|
+
return KIMI_CODE_FIRST_EVENT_TIMEOUT_MESSAGES["openai-completions"].has(errorMessage);
|
|
12687
|
+
}
|
|
12688
|
+
return false;
|
|
12689
|
+
}
|
|
12690
|
+
|
|
12691
|
+
#isKimiCodeCompactionTimeout(candidate: Model, errorMessage: string): boolean {
|
|
12692
|
+
if (candidate.provider !== "kimi-code") return false;
|
|
12693
|
+
return /^(?:Summarization failed|Turn prefix summarization failed): (?:Provider|Anthropic|OpenAI completions) stream timed out while waiting for the first event$/.test(
|
|
12694
|
+
errorMessage,
|
|
12695
|
+
);
|
|
12696
|
+
}
|
|
12697
|
+
|
|
12698
|
+
#alibabaTokenPlanCanonicalTimeoutForApi(api: string): string | undefined {
|
|
12699
|
+
if (api === "openai-responses" || api === "openai-completions") {
|
|
12700
|
+
return ALIBABA_TOKEN_PLAN_FIRST_EVENT_TIMEOUT_MESSAGES[api];
|
|
12701
|
+
}
|
|
12702
|
+
return undefined;
|
|
12703
|
+
}
|
|
12704
|
+
|
|
12705
|
+
#isAlibabaTokenPlanFirstEventTimeout(message: AssistantMessage): boolean {
|
|
12706
|
+
if (message.stopReason !== "error" || message.provider !== ALIBABA_TOKEN_PLAN_PROVIDER) return false;
|
|
12707
|
+
const canonicalMessage = this.#alibabaTokenPlanCanonicalTimeoutForApi(message.api);
|
|
12708
|
+
return canonicalMessage !== undefined && message.errorMessage === canonicalMessage;
|
|
12709
|
+
}
|
|
12710
|
+
|
|
12711
|
+
#isAlibabaTokenPlanCompactionTimeout(candidate: Model, errorMessage: string): boolean {
|
|
12712
|
+
if (candidate.provider !== ALIBABA_TOKEN_PLAN_PROVIDER) return false;
|
|
12713
|
+
const canonicalMessage = this.#alibabaTokenPlanCanonicalTimeoutForApi(candidate.api);
|
|
12714
|
+
if (canonicalMessage === undefined) return false;
|
|
12715
|
+
return (
|
|
12716
|
+
errorMessage === `Summarization failed: ${canonicalMessage}` ||
|
|
12717
|
+
errorMessage === `Turn prefix summarization failed: ${canonicalMessage}`
|
|
12718
|
+
);
|
|
12719
|
+
}
|
|
12720
|
+
|
|
12721
|
+
#isTerminalProviderFirstEventTimeout(message: AssistantMessage): boolean {
|
|
12722
|
+
return this.#isKimiCodeFirstEventTimeout(message) || this.#isAlibabaTokenPlanFirstEventTimeout(message);
|
|
12723
|
+
}
|
|
12724
|
+
|
|
12725
|
+
#isTerminalProviderCompactionTimeout(candidate: Model, errorMessage: string): boolean {
|
|
12726
|
+
return (
|
|
12727
|
+
this.#isKimiCodeCompactionTimeout(candidate, errorMessage) ||
|
|
12728
|
+
this.#isAlibabaTokenPlanCompactionTimeout(candidate, errorMessage)
|
|
12729
|
+
);
|
|
12730
|
+
}
|
|
12731
|
+
|
|
12620
12732
|
#isRetryableError(message: AssistantMessage): boolean {
|
|
12733
|
+
if (this.#isTerminalProviderFirstEventTimeout(message)) return false;
|
|
12621
12734
|
if (message.errorMessage?.startsWith("Model fallback chain exhausted;")) return false;
|
|
12622
12735
|
const transportFailure = message.transportFailure;
|
|
12623
12736
|
const contextWindow = this.model?.contextWindow ?? 0;
|
|
@@ -12767,6 +12880,9 @@ export class AgentSession {
|
|
|
12767
12880
|
if (isTerminalHttp4xx && (explicitStatus !== undefined || !/rate.?limit|too many requests/i.test(err))) {
|
|
12768
12881
|
return "terminal";
|
|
12769
12882
|
}
|
|
12883
|
+
if (this.#isTerminalProviderFirstEventTimeout(message)) {
|
|
12884
|
+
return "terminal";
|
|
12885
|
+
}
|
|
12770
12886
|
// A first-event timeout on ollama-cloud (the ollama-chat API) must not
|
|
12771
12887
|
// join the unbounded transient class: each continuation retry re-issues
|
|
12772
12888
|
// the full request to a remote, billable backend, so an unbounded loop
|
|
@@ -12949,6 +13065,18 @@ export class AgentSession {
|
|
|
12949
13065
|
},
|
|
12950
13066
|
};
|
|
12951
13067
|
}
|
|
13068
|
+
if (this.#isTerminalProviderFirstEventTimeout(outcome.failure.message)) {
|
|
13069
|
+
// The managed transport discarded this attempt before session policy saw it.
|
|
13070
|
+
// Remove its provisional controller charge and surface the original message.
|
|
13071
|
+
this.#defaultFallbackChain().discardStartedAttempt();
|
|
13072
|
+
return {
|
|
13073
|
+
type: "terminal",
|
|
13074
|
+
terminal: {
|
|
13075
|
+
stopReason: "error",
|
|
13076
|
+
messages: [outcome.failure.message],
|
|
13077
|
+
},
|
|
13078
|
+
};
|
|
13079
|
+
}
|
|
12952
13080
|
return this.#handleRetryableError(
|
|
12953
13081
|
outcome.failure.message,
|
|
12954
13082
|
true,
|
|
@@ -14471,6 +14599,10 @@ export class AgentSession {
|
|
|
14471
14599
|
|
|
14472
14600
|
try {
|
|
14473
14601
|
await this.sessionManager.setSessionFile(sessionPath);
|
|
14602
|
+
// The successor identity is already rotated in the manager but not yet
|
|
14603
|
+
// published; gate its local:// root before publication so no observer
|
|
14604
|
+
// can resolve against an ungated root (#2797 / #2925).
|
|
14605
|
+
if (switchingToDifferentSession) await initializeLocalRoot(this.#localProtocolOptions());
|
|
14474
14606
|
this.#syncAgentSessionId();
|
|
14475
14607
|
this.#rekeyHindsightMemoryForCurrentSessionId();
|
|
14476
14608
|
|
|
@@ -14547,13 +14679,8 @@ export class AgentSession {
|
|
|
14547
14679
|
await this.sessionManager.ensureOnDisk();
|
|
14548
14680
|
|
|
14549
14681
|
if (switchingToDifferentSession) {
|
|
14550
|
-
//
|
|
14551
|
-
//
|
|
14552
|
-
// post-commit session_switch / local path resolution. createAgentSession
|
|
14553
|
-
// already does this at cold start (#2797); switchSession previously omitted
|
|
14554
|
-
// it, so resolving local:// after /resume could fail-closed with
|
|
14555
|
-
// "legacy migration must complete before path resolution" (#2925).
|
|
14556
|
-
await initializeLocalRoot(this.#localProtocolOptions());
|
|
14682
|
+
// The local:// migration gate for this successor already ran above,
|
|
14683
|
+
// before the identity was published (#2797 / #2925).
|
|
14557
14684
|
this.#resetHindsightConversationTrackingIfHindsight();
|
|
14558
14685
|
this.#resetIrcRosterDeliveryState();
|
|
14559
14686
|
}
|
|
@@ -14685,6 +14812,9 @@ export class AgentSession {
|
|
|
14685
14812
|
} else {
|
|
14686
14813
|
this.sessionManager.createBranchedSession(selectedEntry.parentId);
|
|
14687
14814
|
}
|
|
14815
|
+
// Branch/tree-jump establishes a new session identity; gate the successor
|
|
14816
|
+
// local:// root before that identity is published (#2797 / #2925).
|
|
14817
|
+
await initializeLocalRoot(this.#localProtocolOptions());
|
|
14688
14818
|
this.#syncTodoPhasesFromBranch();
|
|
14689
14819
|
this.#syncAgentSessionId();
|
|
14690
14820
|
this.#bindWorkflowGateEmitter(previousWorkflowGateSessionId);
|