@oh-my-pi/pi-coding-agent 16.3.14 → 16.4.0
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 -0
- package/dist/cli.js +3053 -3158
- package/dist/types/advisor/config.d.ts +7 -0
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/config/model-resolver.d.ts +1 -1
- package/dist/types/config/models-config-schema.d.ts +28 -15
- package/dist/types/config/models-config.d.ts +6 -0
- package/dist/types/config/settings-schema.d.ts +7 -2
- package/dist/types/dap/config.d.ts +13 -1
- package/dist/types/extensibility/extensions/types.d.ts +6 -0
- package/dist/types/lsp/config.d.ts +7 -1
- package/dist/types/main.d.ts +2 -0
- package/dist/types/mcp/transports/stdio.d.ts +8 -3
- package/dist/types/modes/components/hook-selector.d.ts +2 -0
- package/dist/types/modes/theme/defaults/index.d.ts +2 -0
- package/dist/types/modes/theme/theme.d.ts +3 -2
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +5 -3
- package/dist/types/session/session-context.test.d.ts +1 -0
- package/dist/types/session/session-entries.d.ts +4 -0
- package/dist/types/thinking.d.ts +6 -3
- package/dist/types/utils/file-display-mode.d.ts +1 -1
- package/package.json +12 -12
- package/src/advisor/__tests__/config.test.ts +84 -0
- package/src/advisor/config.ts +28 -0
- package/src/cli/args.ts +1 -0
- package/src/cli/flag-tables.ts +3 -0
- package/src/config/model-registry.ts +1 -1
- package/src/config/model-resolver.ts +14 -12
- package/src/config/models-config-schema.ts +3 -2
- package/src/config/settings-schema.ts +5 -2
- package/src/dap/config.ts +136 -39
- package/src/dap/defaults.json +1 -1
- package/src/eval/js/shared/runtime.ts +20 -4
- package/src/eval/js/worker-core.ts +9 -2
- package/src/exec/bash-executor.ts +8 -1
- package/src/extensibility/extensions/types.ts +6 -0
- package/src/internal-urls/docs-index.generated.txt +1 -1
- package/src/lsp/config.ts +27 -13
- package/src/lsp/index.ts +114 -29
- package/src/main.ts +21 -1
- package/src/mcp/transports/stdio.test.ts +12 -0
- package/src/mcp/transports/stdio.ts +14 -8
- package/src/modes/components/hook-selector.ts +9 -2
- package/src/modes/controllers/extension-ui-controller.ts +3 -0
- package/src/modes/controllers/input-controller.ts +4 -4
- package/src/modes/controllers/selector-controller.ts +1 -1
- package/src/modes/theme/defaults/dark-poimandres.json +6 -5
- package/src/modes/theme/defaults/light-poimandres.json +6 -5
- package/src/modes/theme/theme-schema.json +6 -2
- package/src/modes/theme/theme.ts +24 -18
- package/src/prompts/agents/init.md +1 -1
- package/src/prompts/agents/plan.md +2 -2
- package/src/prompts/agents/reviewer.md +1 -1
- package/src/prompts/agents/{explore.md → scout.md} +3 -2
- package/src/prompts/system/plan-mode-active.md +2 -2
- package/src/prompts/system/system-prompt.md +5 -3
- package/src/prompts/tools/ast-grep.md +1 -1
- package/src/prompts/tools/debug.md +4 -4
- package/src/prompts/tools/grep.md +1 -1
- package/src/prompts/tools/task.md +2 -2
- package/src/sdk.ts +68 -45
- package/src/session/agent-session.ts +215 -64
- package/src/session/session-context.test.ts +83 -0
- package/src/session/session-context.ts +1 -0
- package/src/session/session-entries.ts +4 -0
- package/src/session/session-manager.ts +9 -1
- package/src/system-prompt.test.ts +20 -11
- package/src/task/agents.ts +2 -5
- package/src/task/executor.ts +111 -74
- package/src/thinking.ts +16 -7
- package/src/tools/ask.ts +51 -13
- package/src/tools/browser/cmux/cmux-tab.ts +21 -12
- package/src/tools/debug.ts +41 -11
- package/src/utils/file-display-mode.ts +1 -1
- package/src/prompts/agents/tester.md +0 -111
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
createToolScopedAbortReason,
|
|
39
39
|
resolveTelemetry,
|
|
40
40
|
type StreamFn,
|
|
41
|
+
TERMINAL_TOOL_RESULT_ABORT_REASON,
|
|
41
42
|
ThinkingLevel,
|
|
42
43
|
type ToolChoiceDirective,
|
|
43
44
|
} from "@oh-my-pi/pi-agent-core";
|
|
@@ -84,6 +85,7 @@ import type {
|
|
|
84
85
|
AssistantMessageEvent,
|
|
85
86
|
AssistantRetryRecovery,
|
|
86
87
|
AssistantRetryRecoveryKind,
|
|
88
|
+
CodexCompactionContext,
|
|
87
89
|
Context,
|
|
88
90
|
ImageContent,
|
|
89
91
|
Message,
|
|
@@ -117,6 +119,7 @@ import {
|
|
|
117
119
|
streamSimple,
|
|
118
120
|
} from "@oh-my-pi/pi-ai";
|
|
119
121
|
import * as AIError from "@oh-my-pi/pi-ai/error";
|
|
122
|
+
import { resetOpenAICodexHistoryAfterCompaction } from "@oh-my-pi/pi-ai/providers/openai-codex-responses";
|
|
120
123
|
import { toolWireSchema } from "@oh-my-pi/pi-ai/utils/schema";
|
|
121
124
|
import { GeminiHeaderRunDetector, isGeminiThinkingModel } from "@oh-my-pi/pi-ai/utils/thinking-loop";
|
|
122
125
|
import { type RepeatedToolCallDetection, ToolCallLoopGuard } from "@oh-my-pi/pi-ai/utils/tool-call-loop-guard";
|
|
@@ -154,6 +157,7 @@ import {
|
|
|
154
157
|
AdvisorTranscriptRecorder,
|
|
155
158
|
advisorTranscriptFilename,
|
|
156
159
|
formatAdvisorBatchContent,
|
|
160
|
+
getOrCreateAdvisorProviderSessionId,
|
|
157
161
|
isAdvisorInterruptImmuneTurnActive,
|
|
158
162
|
isInterruptingSeverity,
|
|
159
163
|
resolveAdvisorDeliveryChannel,
|
|
@@ -602,6 +606,20 @@ function compactionDeadEndWarning(remedies: string): string {
|
|
|
602
606
|
);
|
|
603
607
|
}
|
|
604
608
|
|
|
609
|
+
function createCodexCompactionContext(options: {
|
|
610
|
+
trigger: CodexCompactionContext["trigger"];
|
|
611
|
+
reason: CodexCompactionContext["reason"];
|
|
612
|
+
phase: CodexCompactionContext["phase"];
|
|
613
|
+
}): CodexCompactionContext {
|
|
614
|
+
return {
|
|
615
|
+
operationId: crypto.randomUUID(),
|
|
616
|
+
trigger: options.trigger,
|
|
617
|
+
reason: options.reason,
|
|
618
|
+
phase: options.phase,
|
|
619
|
+
strategy: "memento",
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
|
|
605
623
|
/**
|
|
606
624
|
* Per-turn prune cache window. A tool result whose all-message suffix exceeds
|
|
607
625
|
* this is in the warm, already-sent prompt-cache prefix: re-writing it costs the
|
|
@@ -793,6 +811,8 @@ export interface AgentSessionConfig {
|
|
|
793
811
|
* so that credential sticky selection is consistent with the session's streaming calls.
|
|
794
812
|
*/
|
|
795
813
|
providerSessionId?: string;
|
|
814
|
+
/** Marks `agent.promptCacheKey` as fork-inherited so incompatible route changes can clear it. */
|
|
815
|
+
providerPromptCacheKeySource?: "explicit" | "fork";
|
|
796
816
|
/**
|
|
797
817
|
* Full advisor toolset, pre-built in `createAgentSession` against a distinct,
|
|
798
818
|
* advisor-scoped `ToolSession` (its own `-advisor` session/agent id) so the
|
|
@@ -1061,7 +1081,7 @@ function parseRetryFallbackSelector(
|
|
|
1061
1081
|
const trimmed = selector.trim();
|
|
1062
1082
|
if (!trimmed) return undefined;
|
|
1063
1083
|
const parsed = parseModelString(trimmed, {
|
|
1064
|
-
|
|
1084
|
+
allowMaxSuffix: true,
|
|
1065
1085
|
allowAutoAlias: true,
|
|
1066
1086
|
isLiteralModelId: (provider, id) => modelLookup?.find(provider, id) !== undefined,
|
|
1067
1087
|
});
|
|
@@ -1599,6 +1619,8 @@ export class AgentSession {
|
|
|
1599
1619
|
#advisors: ActiveAdvisor[] = [];
|
|
1600
1620
|
/** Configured advisor roster from WATCHDOG.yml; undefined/empty → single legacy advisor. */
|
|
1601
1621
|
#advisorConfigs?: AdvisorConfig[];
|
|
1622
|
+
/** Provider-facing UUIDv7 identities keyed by primary provider session and advisor slug. */
|
|
1623
|
+
#advisorProviderSessionIds = new Map<string, string>();
|
|
1602
1624
|
/** Aggregate of the most recent stop's recorder closes; awaited by dispose() and
|
|
1603
1625
|
* used as the open barrier for the next build so two writers never share a file. */
|
|
1604
1626
|
#advisorRecorderClosed: Promise<void> = Promise.resolve();
|
|
@@ -1697,6 +1719,7 @@ export class AgentSession {
|
|
|
1697
1719
|
#agentKind: "main" | "sub" = "main";
|
|
1698
1720
|
#providerSessionId: string | undefined;
|
|
1699
1721
|
#freshProviderSessionId: string | undefined;
|
|
1722
|
+
#inheritedProviderPromptCacheKey: string | undefined;
|
|
1700
1723
|
#isDisposed = false;
|
|
1701
1724
|
// Extension system
|
|
1702
1725
|
#extensionRunner: ExtensionRunner | undefined = undefined;
|
|
@@ -1846,6 +1869,7 @@ export class AgentSession {
|
|
|
1846
1869
|
* Cleared before every new prompt turn so the next turn evaluates cleanly.
|
|
1847
1870
|
*/
|
|
1848
1871
|
#yieldTerminationPending = false;
|
|
1872
|
+
#synchronouslyTerminatedYieldToolCallIds = new Set<string>();
|
|
1849
1873
|
#providerSessionState = new Map<string, ProviderSessionState>();
|
|
1850
1874
|
#hindsightSessionState: HindsightSessionState | undefined = undefined;
|
|
1851
1875
|
readonly rawSseDebugBuffer: RawSseDebugBuffer;
|
|
@@ -2212,6 +2236,8 @@ export class AgentSession {
|
|
|
2212
2236
|
this.#agentId = config.agentId;
|
|
2213
2237
|
this.#agentKind = config.agentKind ?? "main";
|
|
2214
2238
|
this.#providerSessionId = config.providerSessionId;
|
|
2239
|
+
this.#inheritedProviderPromptCacheKey =
|
|
2240
|
+
config.providerPromptCacheKeySource === "fork" ? this.agent.promptCacheKey : undefined;
|
|
2215
2241
|
this.agent.setAssistantMessageEventInterceptor((message, assistantMessageEvent) => {
|
|
2216
2242
|
const event: AgentEvent = {
|
|
2217
2243
|
type: "message_update",
|
|
@@ -2222,8 +2248,8 @@ export class AgentSession {
|
|
|
2222
2248
|
this.#maybeAbortStreamingEdit(event);
|
|
2223
2249
|
this.#maybeInterruptGeminiHeaderRunaway(message, assistantMessageEvent);
|
|
2224
2250
|
});
|
|
2225
|
-
//
|
|
2226
|
-
this.agent.afterToolCall = ctx => this.#
|
|
2251
|
+
// Tool-result hook owns synchronous post-tool actions that must affect the current loop.
|
|
2252
|
+
this.agent.afterToolCall = ctx => this.#afterToolCall(ctx);
|
|
2227
2253
|
this.agent.providerSessionState = this.#providerSessionState;
|
|
2228
2254
|
this.#syncAgentSessionId();
|
|
2229
2255
|
this.#syncTodoPhasesFromBranch();
|
|
@@ -2477,18 +2503,26 @@ export class AgentSession {
|
|
|
2477
2503
|
const names = config.tools?.length ? new Set(config.tools) : ADVISOR_DEFAULT_TOOL_NAMES;
|
|
2478
2504
|
const tools = (this.#advisorTools ?? []).filter(t => names.has(t.name));
|
|
2479
2505
|
|
|
2480
|
-
const
|
|
2506
|
+
const primaryProviderSessionId = this.sessionId;
|
|
2507
|
+
const advisorSessionLabel = slug
|
|
2508
|
+
? `${primaryProviderSessionId}-advisor-${slug}`
|
|
2509
|
+
: `${primaryProviderSessionId}-advisor`;
|
|
2510
|
+
const advisorProviderSessionId = getOrCreateAdvisorProviderSessionId(
|
|
2511
|
+
this.#advisorProviderSessionIds,
|
|
2512
|
+
primaryProviderSessionId,
|
|
2513
|
+
slug,
|
|
2514
|
+
);
|
|
2481
2515
|
const appendOnlyContext = new AppendOnlyContextManager();
|
|
2482
2516
|
|
|
2483
2517
|
// Thread the primary's telemetry into the advisor loop so the advisor
|
|
2484
|
-
// model's GenAI spans + usage/cost hooks fire stamped with the advisor
|
|
2485
|
-
//
|
|
2486
|
-
//
|
|
2518
|
+
// model's GenAI spans + usage/cost hooks fire stamped with the local advisor
|
|
2519
|
+
// identity. `conversationId` is cleared so provider telemetry falls back to
|
|
2520
|
+
// the UUIDv7 provider session id, not the local `-advisor` label.
|
|
2487
2521
|
const advisorTelemetry = this.agent.telemetry
|
|
2488
2522
|
? {
|
|
2489
2523
|
...this.agent.telemetry,
|
|
2490
2524
|
agent: {
|
|
2491
|
-
id:
|
|
2525
|
+
id: advisorSessionLabel,
|
|
2492
2526
|
name: slug ? `${MODEL_ROLES.advisor.name}: ${advisorName}` : MODEL_ROLES.advisor.name,
|
|
2493
2527
|
description: formatModelString(advisorModel),
|
|
2494
2528
|
},
|
|
@@ -2500,10 +2534,10 @@ export class AgentSession {
|
|
|
2500
2534
|
// advisor's requests cache, route, and obfuscate like the main turn.
|
|
2501
2535
|
// `promptCacheKey` preserves an explicitly pinned provider cache key
|
|
2502
2536
|
// unchanged so tan/shared-session advisor calls read the exact shard the
|
|
2503
|
-
// parent turn populated
|
|
2504
|
-
//
|
|
2505
|
-
//
|
|
2506
|
-
const advisorPromptCacheKey = this.agent.promptCacheKey ??
|
|
2537
|
+
// parent turn populated. Otherwise the advisor uses its provider UUIDv7 so
|
|
2538
|
+
// Codex request identity remains UUID-shaped while local labels keep the
|
|
2539
|
+
// `-advisor` suffix.
|
|
2540
|
+
const advisorPromptCacheKey = this.agent.promptCacheKey ?? advisorProviderSessionId;
|
|
2507
2541
|
const advisorAgent = new Agent({
|
|
2508
2542
|
initialState: {
|
|
2509
2543
|
systemPrompt,
|
|
@@ -2512,11 +2546,11 @@ export class AgentSession {
|
|
|
2512
2546
|
tools: [adviseTool, ...tools],
|
|
2513
2547
|
},
|
|
2514
2548
|
appendOnlyContext,
|
|
2515
|
-
sessionId:
|
|
2549
|
+
sessionId: advisorProviderSessionId,
|
|
2516
2550
|
promptCacheKey: advisorPromptCacheKey,
|
|
2517
2551
|
providerSessionState: this.#providerSessionState,
|
|
2518
2552
|
preferWebsockets: this.#preferWebsockets,
|
|
2519
|
-
getApiKey: requestModel => this.#modelRegistry.resolver(requestModel,
|
|
2553
|
+
getApiKey: requestModel => this.#modelRegistry.resolver(requestModel, advisorProviderSessionId),
|
|
2520
2554
|
streamFn: this.#advisorStreamFn,
|
|
2521
2555
|
onPayload: this.#onPayload,
|
|
2522
2556
|
onResponse: this.#onResponse,
|
|
@@ -2575,11 +2609,15 @@ export class AgentSession {
|
|
|
2575
2609
|
// suspect-mark a credential on a transient advisor error).
|
|
2576
2610
|
const message = error instanceof Error ? error.message : String(error);
|
|
2577
2611
|
if (!isUsageLimitOutcome(extractHttpStatusFromError(error), message)) return;
|
|
2578
|
-
await this.#modelRegistry.authStorage.markUsageLimitReached(
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2612
|
+
await this.#modelRegistry.authStorage.markUsageLimitReached(
|
|
2613
|
+
advisorModel.provider,
|
|
2614
|
+
advisorProviderSessionId,
|
|
2615
|
+
{
|
|
2616
|
+
retryAfterMs: extractRetryHint(undefined, message),
|
|
2617
|
+
baseUrl: advisorModel.baseUrl,
|
|
2618
|
+
modelId: advisorModel.id,
|
|
2619
|
+
},
|
|
2620
|
+
);
|
|
2583
2621
|
},
|
|
2584
2622
|
notifyFailure: error => {
|
|
2585
2623
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -2633,13 +2671,6 @@ export class AgentSession {
|
|
|
2633
2671
|
return this.#advisors.length > 0;
|
|
2634
2672
|
}
|
|
2635
2673
|
|
|
2636
|
-
/** Provider/session id for an advisor's loop. The slug suffix MUST match the
|
|
2637
|
-
* advisor's transcript filename so stats/telemetry attribute the same advisor. */
|
|
2638
|
-
#advisorSessionId(slug: string): string | undefined {
|
|
2639
|
-
if (!this.sessionId) return undefined;
|
|
2640
|
-
return slug ? `${this.sessionId}-advisor-${slug}` : `${this.sessionId}-advisor`;
|
|
2641
|
-
}
|
|
2642
|
-
|
|
2643
2674
|
/**
|
|
2644
2675
|
* Route one accepted advice note from `advisor` to the primary. Concern and
|
|
2645
2676
|
* blocker interrupt the running agent through the steering channel; once the
|
|
@@ -2845,11 +2876,15 @@ export class AgentSession {
|
|
|
2845
2876
|
// No compaction candidates, fallback to re-prime
|
|
2846
2877
|
return true;
|
|
2847
2878
|
}
|
|
2848
|
-
const
|
|
2879
|
+
const advisorProviderSessionId = getOrCreateAdvisorProviderSessionId(
|
|
2880
|
+
this.#advisorProviderSessionIds,
|
|
2881
|
+
this.sessionId,
|
|
2882
|
+
advisor.slug,
|
|
2883
|
+
);
|
|
2849
2884
|
const preparation = prepareCompaction(
|
|
2850
2885
|
pathEntries,
|
|
2851
2886
|
compactionSettings,
|
|
2852
|
-
await this.#runnableCompactionCandidates(candidates,
|
|
2887
|
+
await this.#runnableCompactionCandidates(candidates, advisorProviderSessionId),
|
|
2853
2888
|
);
|
|
2854
2889
|
if (!preparation) {
|
|
2855
2890
|
// Cannot prepare compaction, fallback to re-prime
|
|
@@ -2869,17 +2904,23 @@ export class AgentSession {
|
|
|
2869
2904
|
let lastError: unknown;
|
|
2870
2905
|
// Instrument the advisor's overflow-compaction one-shot like the primary
|
|
2871
2906
|
// compaction path so the advisor model's maintenance call also emits spans.
|
|
2872
|
-
const telemetry = resolveTelemetry(agent.telemetry,
|
|
2907
|
+
const telemetry = resolveTelemetry(agent.telemetry, advisorProviderSessionId);
|
|
2908
|
+
|
|
2909
|
+
const codexCompaction = createCodexCompactionContext({
|
|
2910
|
+
trigger: "auto",
|
|
2911
|
+
reason: "context_limit",
|
|
2912
|
+
phase: "pre_turn",
|
|
2913
|
+
});
|
|
2873
2914
|
|
|
2874
2915
|
for (const candidate of candidates) {
|
|
2875
|
-
const apiKey = await this.#modelRegistry.getApiKey(candidate,
|
|
2916
|
+
const apiKey = await this.#modelRegistry.getApiKey(candidate, advisorProviderSessionId);
|
|
2876
2917
|
if (!apiKey) continue;
|
|
2877
2918
|
|
|
2878
2919
|
try {
|
|
2879
2920
|
compactResult = await compact(
|
|
2880
2921
|
preparation,
|
|
2881
2922
|
candidate,
|
|
2882
|
-
this.#modelRegistry.resolver(candidate,
|
|
2923
|
+
this.#modelRegistry.resolver(candidate, advisorProviderSessionId),
|
|
2883
2924
|
undefined,
|
|
2884
2925
|
undefined,
|
|
2885
2926
|
{
|
|
@@ -2887,8 +2928,10 @@ export class AgentSession {
|
|
|
2887
2928
|
convertToLlm: messages => this.#convertToLlmForSideRequest(messages),
|
|
2888
2929
|
telemetry,
|
|
2889
2930
|
tools: agent.state.tools,
|
|
2890
|
-
sessionId:
|
|
2891
|
-
promptCacheKey:
|
|
2931
|
+
sessionId: advisorProviderSessionId,
|
|
2932
|
+
promptCacheKey: advisorProviderSessionId,
|
|
2933
|
+
providerSessionState: this.#providerSessionState,
|
|
2934
|
+
codexCompaction,
|
|
2892
2935
|
},
|
|
2893
2936
|
);
|
|
2894
2937
|
break;
|
|
@@ -3671,9 +3714,12 @@ export class AgentSession {
|
|
|
3671
3714
|
this.#planModeReminderAwaitingProgress = false;
|
|
3672
3715
|
}
|
|
3673
3716
|
}
|
|
3674
|
-
if (event.type === "tool_execution_end" && event
|
|
3675
|
-
|
|
3676
|
-
|
|
3717
|
+
if (event.type === "tool_execution_end" && this.#isTerminalYieldToolResult(event)) {
|
|
3718
|
+
const alreadyTerminated = this.#synchronouslyTerminatedYieldToolCallIds.delete(event.toolCallId);
|
|
3719
|
+
if (!alreadyTerminated) {
|
|
3720
|
+
this.#markTerminalYieldToolCall(event.toolCallId);
|
|
3721
|
+
this.agent.abort(TERMINAL_TOOL_RESULT_ABORT_REASON);
|
|
3722
|
+
}
|
|
3677
3723
|
}
|
|
3678
3724
|
|
|
3679
3725
|
// TTSR: Check for pattern matches on assistant text/thinking and tool argument deltas
|
|
@@ -4418,6 +4464,21 @@ export class AgentSession {
|
|
|
4418
4464
|
}
|
|
4419
4465
|
}
|
|
4420
4466
|
|
|
4467
|
+
#afterToolCall(ctx: AfterToolCallContext): AfterToolCallResult | undefined {
|
|
4468
|
+
if (
|
|
4469
|
+
this.#isTerminalYieldToolResult({
|
|
4470
|
+
toolName: ctx.toolCall.name,
|
|
4471
|
+
isError: ctx.isError,
|
|
4472
|
+
result: ctx.result,
|
|
4473
|
+
})
|
|
4474
|
+
) {
|
|
4475
|
+
this.#markTerminalYieldToolCall(ctx.toolCall.id);
|
|
4476
|
+
this.#synchronouslyTerminatedYieldToolCallIds.add(ctx.toolCall.id);
|
|
4477
|
+
this.agent.abort(TERMINAL_TOOL_RESULT_ABORT_REASON);
|
|
4478
|
+
}
|
|
4479
|
+
return this.#ttsrAfterToolCall(ctx);
|
|
4480
|
+
}
|
|
4481
|
+
|
|
4421
4482
|
/** `afterToolCall` hook: fold any per-tool TTSR reminders into the result. */
|
|
4422
4483
|
#ttsrAfterToolCall(ctx: AfterToolCallContext): AfterToolCallResult | undefined {
|
|
4423
4484
|
const rules = this.#perToolTtsrInjections.get(ctx.toolCall.id);
|
|
@@ -5570,6 +5631,23 @@ export class AgentSession {
|
|
|
5570
5631
|
return this.#freshProviderSessionId ?? this.#providerSessionId ?? sessionId ?? this.sessionManager.getSessionId();
|
|
5571
5632
|
}
|
|
5572
5633
|
|
|
5634
|
+
#adoptInheritedProviderPromptCacheKey(): void {
|
|
5635
|
+
const key = this.sessionManager.getHeader()?.providerPromptCacheKey;
|
|
5636
|
+
if (!key) return;
|
|
5637
|
+
if (this.#inheritedProviderPromptCacheKey !== undefined || this.agent.promptCacheKey === undefined) {
|
|
5638
|
+
this.agent.promptCacheKey = key;
|
|
5639
|
+
this.#inheritedProviderPromptCacheKey = key;
|
|
5640
|
+
}
|
|
5641
|
+
}
|
|
5642
|
+
|
|
5643
|
+
#clearInheritedProviderPromptCacheKey(): void {
|
|
5644
|
+
const key = this.#inheritedProviderPromptCacheKey;
|
|
5645
|
+
this.#inheritedProviderPromptCacheKey = undefined;
|
|
5646
|
+
if (key !== undefined && this.agent.promptCacheKey === key) {
|
|
5647
|
+
this.agent.promptCacheKey = undefined;
|
|
5648
|
+
}
|
|
5649
|
+
}
|
|
5650
|
+
|
|
5573
5651
|
/**
|
|
5574
5652
|
* Set agent.sessionId from the session manager and install a dynamic
|
|
5575
5653
|
* metadata resolver so every Anthropic API request carries
|
|
@@ -6375,6 +6453,9 @@ export class AgentSession {
|
|
|
6375
6453
|
if (this.#rebuildSystemPrompt) {
|
|
6376
6454
|
const signature = this.#computeAppliedToolSignature(validToolNames, tools);
|
|
6377
6455
|
if (signature !== this.#lastAppliedToolSignature) {
|
|
6456
|
+
if (this.#lastAppliedToolSignature !== undefined) {
|
|
6457
|
+
this.#clearInheritedProviderPromptCacheKey();
|
|
6458
|
+
}
|
|
6378
6459
|
const built = await this.#rebuildSystemPrompt(validToolNames, this.#toolRegistry);
|
|
6379
6460
|
this.#baseSystemPrompt = built.systemPrompt;
|
|
6380
6461
|
this.#baseSystemPromptBeforeMemoryPromotion = undefined;
|
|
@@ -6461,9 +6542,16 @@ export class AgentSession {
|
|
|
6461
6542
|
if (!this.#rebuildSystemPrompt) return;
|
|
6462
6543
|
const activeToolNames = this.getActiveToolNames();
|
|
6463
6544
|
this.#setActiveToolNames?.(activeToolNames);
|
|
6545
|
+
const previousBaseSystemPrompt = this.#baseSystemPrompt;
|
|
6464
6546
|
const built = await this.#rebuildSystemPrompt(activeToolNames, this.#toolRegistry);
|
|
6465
6547
|
this.#baseSystemPrompt = built.systemPrompt;
|
|
6466
6548
|
this.#baseSystemPromptBeforeMemoryPromotion = undefined;
|
|
6549
|
+
if (
|
|
6550
|
+
previousBaseSystemPrompt.length !== this.#baseSystemPrompt.length ||
|
|
6551
|
+
previousBaseSystemPrompt.some((part, index) => part !== this.#baseSystemPrompt[index])
|
|
6552
|
+
) {
|
|
6553
|
+
this.#clearInheritedProviderPromptCacheKey();
|
|
6554
|
+
}
|
|
6467
6555
|
this.agent.setSystemPrompt(this.#baseSystemPrompt);
|
|
6468
6556
|
this.#promptModelKey = this.#currentPromptModelKey();
|
|
6469
6557
|
// Refresh the cached signature so a subsequent `#applyActiveToolsByName` with
|
|
@@ -6593,8 +6681,8 @@ export class AgentSession {
|
|
|
6593
6681
|
*
|
|
6594
6682
|
* @param mcpTools The new MCP tools to register.
|
|
6595
6683
|
* @param options.activateAll When true, force-activates every newly registered MCP tool
|
|
6596
|
-
* regardless of prior selection state. Used when
|
|
6597
|
-
*
|
|
6684
|
+
* regardless of prior selection state. Used when MCP discovery is disabled and tools
|
|
6685
|
+
* arrive after initial session activation.
|
|
6598
6686
|
*/
|
|
6599
6687
|
async refreshMCPTools(mcpTools: CustomTool[], options?: { activateAll?: boolean }): Promise<void> {
|
|
6600
6688
|
const previousSelectedMCPToolNames = this.getSelectedMCPToolNames();
|
|
@@ -6639,10 +6727,10 @@ export class AgentSession {
|
|
|
6639
6727
|
|
|
6640
6728
|
if (options?.activateAll) {
|
|
6641
6729
|
// Force-activate every newly registered MCP tool. This path is used
|
|
6642
|
-
// when
|
|
6643
|
-
//
|
|
6644
|
-
//
|
|
6645
|
-
//
|
|
6730
|
+
// when MCP discovery is disabled and tools arrive after initial
|
|
6731
|
+
// activation — without it, getSelectedMCPToolNames() returns only
|
|
6732
|
+
// already-active tools (circular deadlock: tools can only become
|
|
6733
|
+
// active if they're already active).
|
|
6646
6734
|
const newMcpNames = mcpTools.map(t => t.name);
|
|
6647
6735
|
const nextActive = [...new Set([...this.#getActiveNonMCPToolNames(), ...newMcpNames])];
|
|
6648
6736
|
await this.#applyActiveToolsByName(nextActive, { previousSelectedMCPToolNames });
|
|
@@ -8704,6 +8792,7 @@ export class AgentSession {
|
|
|
8704
8792
|
this.#clearCheckpointRuntimeState();
|
|
8705
8793
|
this.setTodoPhases([]);
|
|
8706
8794
|
this.#freshProviderSessionId = undefined;
|
|
8795
|
+
this.#clearInheritedProviderPromptCacheKey();
|
|
8707
8796
|
this.#syncAgentSessionId();
|
|
8708
8797
|
this.#rekeyHindsightMemoryForCurrentSessionId();
|
|
8709
8798
|
this.#rekeyMnemopiMemoryForCurrentSessionId();
|
|
@@ -8804,6 +8893,7 @@ export class AgentSession {
|
|
|
8804
8893
|
|
|
8805
8894
|
// Update agent session ID
|
|
8806
8895
|
this.#freshProviderSessionId = undefined;
|
|
8896
|
+
this.#adoptInheritedProviderPromptCacheKey();
|
|
8807
8897
|
this.#syncAgentSessionId();
|
|
8808
8898
|
this.#rekeyHindsightMemoryForCurrentSessionId();
|
|
8809
8899
|
this.#rekeyMnemopiMemoryForCurrentSessionId();
|
|
@@ -9125,6 +9215,9 @@ export class AgentSession {
|
|
|
9125
9215
|
this.#autoThinking = true;
|
|
9126
9216
|
this.#autoResolvedLevel = undefined;
|
|
9127
9217
|
this.#thinkingLevel = provisional;
|
|
9218
|
+
if (!wasAuto) {
|
|
9219
|
+
this.#clearInheritedProviderPromptCacheKey();
|
|
9220
|
+
}
|
|
9128
9221
|
this.#applyThinkingLevelToAgent(provisional);
|
|
9129
9222
|
if (persist) {
|
|
9130
9223
|
this.settings.set("defaultThinkingLevel", AUTO_THINKING);
|
|
@@ -9148,6 +9241,7 @@ export class AgentSession {
|
|
|
9148
9241
|
this.#applyThinkingLevelToAgent(effectiveLevel);
|
|
9149
9242
|
|
|
9150
9243
|
if (isChanging) {
|
|
9244
|
+
this.#clearInheritedProviderPromptCacheKey();
|
|
9151
9245
|
this.sessionManager.appendThinkingLevelChange(effectiveLevel, effectiveLevel);
|
|
9152
9246
|
if (persist && effectiveLevel !== undefined && effectiveLevel !== ThinkingLevel.Off) {
|
|
9153
9247
|
this.settings.set("defaultThinkingLevel", effectiveLevel);
|
|
@@ -9166,7 +9260,7 @@ export class AgentSession {
|
|
|
9166
9260
|
}
|
|
9167
9261
|
|
|
9168
9262
|
/**
|
|
9169
|
-
* Cycle to next thinking level: off → auto → minimal..
|
|
9263
|
+
* Cycle to next thinking level: off → auto → minimal..max → off.
|
|
9170
9264
|
* @returns New selector, or undefined if model doesn't support thinking
|
|
9171
9265
|
*/
|
|
9172
9266
|
cycleThinkingLevel(): ConfiguredThinkingLevel | undefined {
|
|
@@ -9208,8 +9302,9 @@ export class AgentSession {
|
|
|
9208
9302
|
let resolved: Effort | undefined;
|
|
9209
9303
|
if (this.#magicKeywordEnabled("ultrathink") && containsUltrathink(promptText)) {
|
|
9210
9304
|
// The user explicitly asked for maximum thinking; bypass the classifier
|
|
9211
|
-
// and jump straight to the highest
|
|
9212
|
-
|
|
9305
|
+
// (and its xhigh auto ceiling) and jump straight to the highest
|
|
9306
|
+
// supported level for this model.
|
|
9307
|
+
resolved = clampAutoThinkingEffort(model, Effort.Max);
|
|
9213
9308
|
} else {
|
|
9214
9309
|
const controller = new AbortController();
|
|
9215
9310
|
const timer = setTimeout(() => controller.abort(), AgentSession.#AUTO_THINKING_TIMEOUT_MS);
|
|
@@ -9751,6 +9846,7 @@ export class AgentSession {
|
|
|
9751
9846
|
let firstKeptEntryId: string;
|
|
9752
9847
|
let tokensBefore: number;
|
|
9753
9848
|
let details: unknown;
|
|
9849
|
+
let codexCompaction: CodexCompactionContext | undefined;
|
|
9754
9850
|
|
|
9755
9851
|
// Snapcompact runs locally first. The frame cap is sized from the live
|
|
9756
9852
|
// model window via #computeSnapcompactMaxFrames so the post-render context
|
|
@@ -9830,6 +9926,11 @@ export class AgentSession {
|
|
|
9830
9926
|
details = snapcompactResult.details;
|
|
9831
9927
|
preserveData = { ...(compactionPrep.preserveData ?? {}), ...(snapcompactResult.preserveData ?? {}) };
|
|
9832
9928
|
} else {
|
|
9929
|
+
codexCompaction = createCodexCompactionContext({
|
|
9930
|
+
trigger: "manual",
|
|
9931
|
+
reason: "user_requested",
|
|
9932
|
+
phase: "standalone_turn",
|
|
9933
|
+
});
|
|
9833
9934
|
// Generate compaction result. Only convert known abort-shaped
|
|
9834
9935
|
// rejections (AbortError raised while the abort signal is set,
|
|
9835
9936
|
// or an already-typed sentinel) into `CompactionCancelledError`
|
|
@@ -9851,6 +9952,7 @@ export class AgentSession {
|
|
|
9851
9952
|
extraContext: compactionPrep.hookContext,
|
|
9852
9953
|
remoteInstructions: this.#baseSystemPrompt.join("\n\n"),
|
|
9853
9954
|
convertToLlm: messages => this.#convertToLlmForSideRequest(messages),
|
|
9955
|
+
codexCompaction,
|
|
9854
9956
|
},
|
|
9855
9957
|
compactionCandidates,
|
|
9856
9958
|
);
|
|
@@ -9893,7 +9995,11 @@ export class AgentSession {
|
|
|
9893
9995
|
this.#planReferenceSent = false;
|
|
9894
9996
|
this.#resetAllAdvisorRuntimes();
|
|
9895
9997
|
this.#syncTodoPhasesFromBranch();
|
|
9896
|
-
|
|
9998
|
+
if (codexCompaction) {
|
|
9999
|
+
this.#resetCodexProviderAfterCompaction(codexCompaction);
|
|
10000
|
+
} else {
|
|
10001
|
+
this.#closeCodexProviderSessionsForHistoryRewrite();
|
|
10002
|
+
}
|
|
9897
10003
|
|
|
9898
10004
|
// Get the saved compaction entry for the hook
|
|
9899
10005
|
const savedCompactionEntry = newEntries.find(e => e.type === "compaction" && e.summary === summary) as
|
|
@@ -10259,6 +10365,7 @@ export class AgentSession {
|
|
|
10259
10365
|
await this.#runAutoCompaction("threshold", false, false, false, {
|
|
10260
10366
|
autoContinue: false,
|
|
10261
10367
|
triggerContextTokens: contextTokens,
|
|
10368
|
+
phase: "pre_turn",
|
|
10262
10369
|
});
|
|
10263
10370
|
}
|
|
10264
10371
|
|
|
@@ -10333,6 +10440,7 @@ export class AgentSession {
|
|
|
10333
10440
|
suppressContinuation: true,
|
|
10334
10441
|
suppressHandoff: true,
|
|
10335
10442
|
triggerContextTokens: contextTokens,
|
|
10443
|
+
phase: "mid_turn",
|
|
10336
10444
|
});
|
|
10337
10445
|
|
|
10338
10446
|
if (signal?.aborted) return;
|
|
@@ -10579,6 +10687,7 @@ export class AgentSession {
|
|
|
10579
10687
|
return await this.#runAutoCompaction("threshold", false, false, allowDefer, {
|
|
10580
10688
|
autoContinue,
|
|
10581
10689
|
triggerContextTokens: postMaintenanceContextTokens,
|
|
10690
|
+
phase: "pre_turn",
|
|
10582
10691
|
});
|
|
10583
10692
|
}
|
|
10584
10693
|
logger.debug("Auto-compaction threshold satisfied but context promotion took over", {
|
|
@@ -10589,6 +10698,24 @@ export class AgentSession {
|
|
|
10589
10698
|
}
|
|
10590
10699
|
return COMPACTION_CHECK_NONE;
|
|
10591
10700
|
}
|
|
10701
|
+
#isTerminalYieldToolResult(event: { toolName: string; isError?: boolean; result?: { details?: unknown } }): boolean {
|
|
10702
|
+
if (event.toolName !== "yield" || event.isError) return false;
|
|
10703
|
+
const details = event.result?.details;
|
|
10704
|
+
if (!details || typeof details !== "object") return true;
|
|
10705
|
+
const record = details as Record<string, unknown>;
|
|
10706
|
+
return !(
|
|
10707
|
+
record.status === "success" &&
|
|
10708
|
+
Array.isArray(record.type) &&
|
|
10709
|
+
record.type.length > 0 &&
|
|
10710
|
+
record.type.every(item => typeof item === "string")
|
|
10711
|
+
);
|
|
10712
|
+
}
|
|
10713
|
+
|
|
10714
|
+
#markTerminalYieldToolCall(toolCallId: string): void {
|
|
10715
|
+
this.#lastSuccessfulYieldToolCallId = toolCallId;
|
|
10716
|
+
this.#yieldTerminationPending = true;
|
|
10717
|
+
}
|
|
10718
|
+
|
|
10592
10719
|
#assistantMessageHasSuccessfulYieldToolCall(assistantMessage: AssistantMessage, toolCallId: string): boolean {
|
|
10593
10720
|
const lastToolCall = assistantMessage.content
|
|
10594
10721
|
.slice()
|
|
@@ -10939,7 +11066,11 @@ export class AgentSession {
|
|
|
10939
11066
|
): Promise<CompactionCheckResult> {
|
|
10940
11067
|
const compactionEntryBefore = getLatestCompactionEntry(this.sessionManager.getBranch());
|
|
10941
11068
|
await this.#dropPersistedAssistantTurn(assistantMessage);
|
|
10942
|
-
const result = await this.#runAutoCompaction(reason, true, false, allowDefer,
|
|
11069
|
+
const result = await this.#runAutoCompaction(reason, true, false, allowDefer, {
|
|
11070
|
+
autoContinue: options.autoContinue,
|
|
11071
|
+
triggerContextTokens: options.triggerContextTokens,
|
|
11072
|
+
phase: "mid_turn",
|
|
11073
|
+
});
|
|
10943
11074
|
const compactionEntryAfter = getLatestCompactionEntry(this.sessionManager.getBranch());
|
|
10944
11075
|
if (result.historyRewritten !== true && compactionEntryAfter === compactionEntryBefore) {
|
|
10945
11076
|
this.#restoreFailedAssistantTurn(assistantMessage);
|
|
@@ -11538,6 +11669,9 @@ export class AgentSession {
|
|
|
11538
11669
|
const currentModel = this.model;
|
|
11539
11670
|
if (currentModel) {
|
|
11540
11671
|
this.#closeProviderSessionsForModelSwitch(currentModel, model);
|
|
11672
|
+
if (!modelsAreEqual(currentModel, model)) {
|
|
11673
|
+
this.#clearInheritedProviderPromptCacheKey();
|
|
11674
|
+
}
|
|
11541
11675
|
}
|
|
11542
11676
|
this.agent.setModel(model);
|
|
11543
11677
|
|
|
@@ -11551,6 +11685,14 @@ export class AgentSession {
|
|
|
11551
11685
|
this.#closeProviderSessionsForModelSwitch(currentModel, currentModel);
|
|
11552
11686
|
}
|
|
11553
11687
|
|
|
11688
|
+
#resetCodexProviderAfterCompaction(compaction: CodexCompactionContext): void {
|
|
11689
|
+
resetOpenAICodexHistoryAfterCompaction({
|
|
11690
|
+
providerSessionState: this.#providerSessionState,
|
|
11691
|
+
sessionId: this.sessionId,
|
|
11692
|
+
compaction,
|
|
11693
|
+
});
|
|
11694
|
+
}
|
|
11695
|
+
|
|
11554
11696
|
#resetCurrentResponsesProviderSession(reason: string): void {
|
|
11555
11697
|
const currentModel = this.model;
|
|
11556
11698
|
if (currentModel?.api !== "openai-responses" && currentModel?.api !== "openai-codex-responses") {
|
|
@@ -11826,7 +11968,7 @@ export class AgentSession {
|
|
|
11826
11968
|
if (!trimmedTarget) return undefined;
|
|
11827
11969
|
|
|
11828
11970
|
const parsed = parseModelString(trimmedTarget, {
|
|
11829
|
-
|
|
11971
|
+
allowMaxSuffix: true,
|
|
11830
11972
|
allowAutoAlias: true,
|
|
11831
11973
|
isLiteralModelId: (provider, id) =>
|
|
11832
11974
|
availableModels.some(model => model.provider === provider && model.id === id),
|
|
@@ -11921,18 +12063,6 @@ export class AgentSession {
|
|
|
11921
12063
|
|
|
11922
12064
|
return candidates;
|
|
11923
12065
|
}
|
|
11924
|
-
#isCompactionAuthFailure(error: unknown): boolean {
|
|
11925
|
-
if (!(error instanceof Error)) return false;
|
|
11926
|
-
// Real provider 401/403 — surfaced as `.status` by the compaction layer
|
|
11927
|
-
// (see `createSummarizationError` in packages/agent/src/compaction/compaction.ts).
|
|
11928
|
-
// Without this branch, an expired/revoked Anthropic key would bypass the
|
|
11929
|
-
// authenticated-fallback path and dump the raw HTTP body into the UI.
|
|
11930
|
-
const status = (error as Error & { status?: number }).status;
|
|
11931
|
-
if (status === 401 || status === 403) return true;
|
|
11932
|
-
// pi-native gateway synthetic for "no credential configured" (issue #986).
|
|
11933
|
-
// Carries no HTTP status, so the legacy message regex stays.
|
|
11934
|
-
return /auth_unavailable|no auth available/i.test(error.message);
|
|
11935
|
-
}
|
|
11936
12066
|
|
|
11937
12067
|
#buildCompactionAuthError(): Error {
|
|
11938
12068
|
const currentModel = this.model;
|
|
@@ -11982,6 +12112,7 @@ export class AgentSession {
|
|
|
11982
12112
|
tools: this.agent.state.tools,
|
|
11983
12113
|
sessionId: this.sessionId,
|
|
11984
12114
|
promptCacheKey: this.sessionId,
|
|
12115
|
+
providerSessionState: this.#providerSessionState,
|
|
11985
12116
|
// Route every summarization HTTP request through the
|
|
11986
12117
|
// session's side-stream transport so the provider
|
|
11987
12118
|
// concurrency cap (e.g. providers.ollama-cloud.maxConcurrency)
|
|
@@ -11997,7 +12128,7 @@ export class AgentSession {
|
|
|
11997
12128
|
},
|
|
11998
12129
|
);
|
|
11999
12130
|
} catch (error) {
|
|
12000
|
-
if (!
|
|
12131
|
+
if (!AIError.is(AIError.classify(error, candidate.api), AIError.Flag.AuthFailed)) {
|
|
12001
12132
|
throw error;
|
|
12002
12133
|
}
|
|
12003
12134
|
}
|
|
@@ -12320,6 +12451,7 @@ export class AgentSession {
|
|
|
12320
12451
|
triggerContextTokens?: number;
|
|
12321
12452
|
suppressContinuation?: boolean;
|
|
12322
12453
|
suppressHandoff?: boolean;
|
|
12454
|
+
phase?: CodexCompactionContext["phase"];
|
|
12323
12455
|
} = {},
|
|
12324
12456
|
): Promise<CompactionCheckResult> {
|
|
12325
12457
|
const compactionSettings = this.settings.getGroup("compaction");
|
|
@@ -12362,7 +12494,7 @@ export class AgentSession {
|
|
|
12362
12494
|
async signal => {
|
|
12363
12495
|
await Promise.resolve();
|
|
12364
12496
|
if (signal.aborted) return;
|
|
12365
|
-
await this.#runAutoCompaction(reason, willRetry, true);
|
|
12497
|
+
await this.#runAutoCompaction(reason, willRetry, true, true, { phase: options.phase });
|
|
12366
12498
|
},
|
|
12367
12499
|
{ generation },
|
|
12368
12500
|
);
|
|
@@ -12509,6 +12641,7 @@ export class AgentSession {
|
|
|
12509
12641
|
let hookCompaction: CompactionResult | undefined;
|
|
12510
12642
|
let fromExtension = false;
|
|
12511
12643
|
let preserveData: Record<string, unknown> | undefined;
|
|
12644
|
+
let codexCompaction: CodexCompactionContext | undefined;
|
|
12512
12645
|
|
|
12513
12646
|
if (this.#extensionRunner?.hasHandlers("session_before_compact")) {
|
|
12514
12647
|
const hookResult = (await this.#extensionRunner.emit({
|
|
@@ -12647,6 +12780,13 @@ export class AgentSession {
|
|
|
12647
12780
|
const telemetry = resolveTelemetry(this.agent.telemetry, this.sessionId);
|
|
12648
12781
|
let compactResult: CompactionResult | undefined;
|
|
12649
12782
|
let lastError: unknown;
|
|
12783
|
+
codexCompaction = createCodexCompactionContext({
|
|
12784
|
+
trigger: "auto",
|
|
12785
|
+
reason: "context_limit",
|
|
12786
|
+
phase:
|
|
12787
|
+
options.phase ??
|
|
12788
|
+
(reason === "threshold" ? "pre_turn" : reason === "idle" ? "standalone_turn" : "mid_turn"),
|
|
12789
|
+
});
|
|
12650
12790
|
|
|
12651
12791
|
for (let candidateIndex = 0; candidateIndex < candidates.length; candidateIndex++) {
|
|
12652
12792
|
const candidate = candidates[candidateIndex];
|
|
@@ -12679,6 +12819,8 @@ export class AgentSession {
|
|
|
12679
12819
|
tools: this.agent.state.tools,
|
|
12680
12820
|
sessionId: this.sessionId,
|
|
12681
12821
|
promptCacheKey: this.sessionId,
|
|
12822
|
+
providerSessionState: this.#providerSessionState,
|
|
12823
|
+
codexCompaction,
|
|
12682
12824
|
},
|
|
12683
12825
|
);
|
|
12684
12826
|
break;
|
|
@@ -12689,7 +12831,7 @@ export class AgentSession {
|
|
|
12689
12831
|
|
|
12690
12832
|
const message = error instanceof Error ? error.message : String(error);
|
|
12691
12833
|
const id = AIError.classify(error, candidate.api);
|
|
12692
|
-
if (
|
|
12834
|
+
if (AIError.is(id, AIError.Flag.AuthFailed)) {
|
|
12693
12835
|
lastError = this.#buildCompactionAuthError();
|
|
12694
12836
|
break;
|
|
12695
12837
|
}
|
|
@@ -12797,7 +12939,11 @@ export class AgentSession {
|
|
|
12797
12939
|
this.#planReferenceSent = false;
|
|
12798
12940
|
this.#resetAllAdvisorRuntimes();
|
|
12799
12941
|
this.#syncTodoPhasesFromBranch();
|
|
12800
|
-
|
|
12942
|
+
if (codexCompaction) {
|
|
12943
|
+
this.#resetCodexProviderAfterCompaction(codexCompaction);
|
|
12944
|
+
} else {
|
|
12945
|
+
this.#closeCodexProviderSessionsForHistoryRewrite();
|
|
12946
|
+
}
|
|
12801
12947
|
|
|
12802
12948
|
// Get the saved compaction entry for the hook
|
|
12803
12949
|
const savedCompactionEntry = newEntries.find(e => e.type === "compaction" && e.summary === summary) as
|
|
@@ -14679,6 +14825,7 @@ export class AgentSession {
|
|
|
14679
14825
|
const previousSystemPrompt = this.agent.state.systemPrompt;
|
|
14680
14826
|
const previousBaseSystemPromptBeforeMemoryPromotion = this.#baseSystemPromptBeforeMemoryPromotion;
|
|
14681
14827
|
const previousFreshProviderSessionId = this.#freshProviderSessionId;
|
|
14828
|
+
const previousInheritedProviderPromptCacheKey = this.#inheritedProviderPromptCacheKey;
|
|
14682
14829
|
const previousFallbackSelectedMCPToolNames = previousSessionFile
|
|
14683
14830
|
? this.#getSessionDefaultSelectedMCPToolNames(previousSessionFile)
|
|
14684
14831
|
: undefined;
|
|
@@ -14700,6 +14847,8 @@ export class AgentSession {
|
|
|
14700
14847
|
await this.sessionManager.setSessionFile(sessionPath);
|
|
14701
14848
|
if (switchingToDifferentSession) {
|
|
14702
14849
|
this.#freshProviderSessionId = undefined;
|
|
14850
|
+
this.#clearInheritedProviderPromptCacheKey();
|
|
14851
|
+
this.#adoptInheritedProviderPromptCacheKey();
|
|
14703
14852
|
}
|
|
14704
14853
|
this.#syncAgentSessionId();
|
|
14705
14854
|
this.#rekeyHindsightMemoryForCurrentSessionId();
|
|
@@ -14853,6 +15002,7 @@ export class AgentSession {
|
|
|
14853
15002
|
this.agent.replaceQueues(previousSteeringMessages, previousFollowUpMessages);
|
|
14854
15003
|
this.#pendingNextTurnMessages = previousPendingNextTurnMessages;
|
|
14855
15004
|
this.#scheduledHiddenNextTurnGeneration = previousScheduledHiddenNextTurnGeneration;
|
|
15005
|
+
this.#inheritedProviderPromptCacheKey = previousInheritedProviderPromptCacheKey;
|
|
14856
15006
|
this.#checkpointState = previousCheckpointState;
|
|
14857
15007
|
this.#pendingRewindReport = previousPendingRewindReport;
|
|
14858
15008
|
this.#lastCompletedRewind = previousLastCompletedRewind;
|
|
@@ -14928,6 +15078,7 @@ export class AgentSession {
|
|
|
14928
15078
|
this.#rehydrateCheckpointRewindState();
|
|
14929
15079
|
this.#syncTodoPhasesFromBranch();
|
|
14930
15080
|
this.#freshProviderSessionId = undefined;
|
|
15081
|
+
this.#clearInheritedProviderPromptCacheKey();
|
|
14931
15082
|
this.#syncAgentSessionId();
|
|
14932
15083
|
this.#rekeyHindsightMemoryForCurrentSessionId();
|
|
14933
15084
|
this.#rekeyMnemopiMemoryForCurrentSessionId();
|