@kenkaiiii/ggcoder 5.25.0 → 5.26.1
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/dist/core/agent-notifications.d.ts +62 -0
- package/dist/core/agent-notifications.d.ts.map +1 -0
- package/dist/core/agent-notifications.js +92 -0
- package/dist/core/agent-notifications.js.map +1 -0
- package/dist/core/agent-notifications.test.d.ts +2 -0
- package/dist/core/agent-notifications.test.d.ts.map +1 -0
- package/dist/core/agent-notifications.test.js +97 -0
- package/dist/core/agent-notifications.test.js.map +1 -0
- package/dist/core/agent-session-model-switch.test.d.ts +2 -0
- package/dist/core/agent-session-model-switch.test.d.ts.map +1 -0
- package/dist/core/agent-session-model-switch.test.js +161 -0
- package/dist/core/agent-session-model-switch.test.js.map +1 -0
- package/dist/core/agent-session-notifications.test.d.ts +2 -0
- package/dist/core/agent-session-notifications.test.d.ts.map +1 -0
- package/dist/core/agent-session-notifications.test.js +114 -0
- package/dist/core/agent-session-notifications.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +55 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +172 -25
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/event-bus.d.ts +6 -0
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +7 -0
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/process-manager-notifications.test.d.ts +2 -0
- package/dist/core/process-manager-notifications.test.d.ts.map +1 -0
- package/dist/core/process-manager-notifications.test.js +113 -0
- package/dist/core/process-manager-notifications.test.js.map +1 -0
- package/dist/core/process-manager.d.ts +29 -0
- package/dist/core/process-manager.d.ts.map +1 -1
- package/dist/core/process-manager.js +123 -0
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +2 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/steering.d.ts +12 -0
- package/dist/core/steering.d.ts.map +1 -1
- package/dist/core/steering.js +16 -0
- package/dist/core/steering.js.map +1 -1
- package/dist/core/subagent-manager.d.ts +13 -0
- package/dist/core/subagent-manager.d.ts.map +1 -1
- package/dist/core/subagent-manager.js +30 -0
- package/dist/core/subagent-manager.js.map +1 -1
- package/dist/core/subagent-manager.test.js +16 -0
- package/dist/core/subagent-manager.test.js.map +1 -1
- package/dist/modes/json-mode.d.ts.map +1 -1
- package/dist/modes/json-mode.js +5 -0
- package/dist/modes/json-mode.js.map +1 -1
- package/dist/modes/subagent-worker-mode.d.ts.map +1 -1
- package/dist/modes/subagent-worker-mode.js +3 -1
- package/dist/modes/subagent-worker-mode.js.map +1 -1
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/subagent-control.d.ts.map +1 -1
- package/dist/tools/subagent-control.js +6 -2
- package/dist/tools/subagent-control.js.map +1 -1
- package/dist/tools/subagent-shared.d.ts +6 -0
- package/dist/tools/subagent-shared.d.ts.map +1 -1
- package/dist/tools/subagent-shared.js +6 -0
- package/dist/tools/subagent-shared.js.map +1 -1
- package/dist/tools/task-output.d.ts.map +1 -1
- package/dist/tools/task-output.js +3 -1
- package/dist/tools/task-output.js.map +1 -1
- package/package.json +4 -4
|
@@ -27,6 +27,13 @@ export interface AgentSessionOptions {
|
|
|
27
27
|
continueRecent?: boolean;
|
|
28
28
|
maxTokens?: number;
|
|
29
29
|
maxTurns?: number;
|
|
30
|
+
/**
|
|
31
|
+
* How many times the turn budget may be extended when the agent is still
|
|
32
|
+
* making progress. Defaults to the agent-loop default (2); sub-agents pass a
|
|
33
|
+
* stricter cap because a child's extensions multiply against the parent's
|
|
34
|
+
* own budget.
|
|
35
|
+
*/
|
|
36
|
+
maxTurnExtensions?: number;
|
|
30
37
|
thinkingLevel?: ThinkingLevel;
|
|
31
38
|
signal?: AbortSignal;
|
|
32
39
|
/** Prefix used for provider prompt-cache routing keys. */
|
|
@@ -192,6 +199,12 @@ export declare class AgentSession {
|
|
|
192
199
|
private processManager?;
|
|
193
200
|
private lspManager?;
|
|
194
201
|
private subAgentManager?;
|
|
202
|
+
/**
|
|
203
|
+
* Out-of-band push notifications (finished children, background-process
|
|
204
|
+
* progress). Producers enqueue; `getHookSteeringMessages` drains into the
|
|
205
|
+
* live turn so the agent never has to spend a turn asking.
|
|
206
|
+
*/
|
|
207
|
+
private readonly notifications;
|
|
195
208
|
private managerAbortSignal?;
|
|
196
209
|
private readonly managerAbortHandler;
|
|
197
210
|
private mcpManager?;
|
|
@@ -316,12 +329,19 @@ export declare class AgentSession {
|
|
|
316
329
|
*/
|
|
317
330
|
private trackHookEvent;
|
|
318
331
|
/**
|
|
319
|
-
* Mid-loop steering hook:
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
332
|
+
* Mid-loop steering hook: delivers pushed notifications and queued user
|
|
333
|
+
* steering, fires the loop-breaker when the agent looks stuck, then
|
|
334
|
+
* post-compaction re-grounding. At most one loop-break/re-grounding per run.
|
|
335
|
+
* Mirrors the TUI's getSteeringMessages ordering.
|
|
323
336
|
*/
|
|
324
337
|
private getHookSteeringMessages;
|
|
338
|
+
/**
|
|
339
|
+
* Turn-budget extension gate. The loop consults this instead of stopping
|
|
340
|
+
* mid-task when it exhausts `maxTurns`. Grant ONLY on evidence of progress —
|
|
341
|
+
* handing more turns to a spinning agent just buys it more tokens to spin
|
|
342
|
+
* with — so reuse the same stuck signals that drive the loop-breaker.
|
|
343
|
+
*/
|
|
344
|
+
private shouldExtendTurnBudget;
|
|
325
345
|
/**
|
|
326
346
|
* Pre-stop Ideal review phase machine. Once review starts, completion is
|
|
327
347
|
* blocked until harness-owned post-injection reads cover every changed file.
|
|
@@ -332,6 +352,18 @@ export declare class AgentSession {
|
|
|
332
352
|
/** Auto-compact if needed, run agent loop with auth retry, and persist messages. */
|
|
333
353
|
private runLoop;
|
|
334
354
|
switchModel(provider: string, model: string): Promise<void>;
|
|
355
|
+
/**
|
|
356
|
+
* Record the switch as its own trailing message at the point it happened,
|
|
357
|
+
* rather than by rewriting the system prompt. Two reasons: the system prompt
|
|
358
|
+
* is the cached prefix and rewriting it costs a full cache write, and a
|
|
359
|
+
* resumed transcript can only attribute output to the right model if the
|
|
360
|
+
* switch sits in message order.
|
|
361
|
+
*
|
|
362
|
+
* Skipped before the conversation starts (nothing to disambiguate) and while
|
|
363
|
+
* an assistant turn has unresolved tool calls, where inserting a user message
|
|
364
|
+
* would break tool_use/tool_result pairing.
|
|
365
|
+
*/
|
|
366
|
+
private appendModelSwitchNote;
|
|
335
367
|
compact(existingCredentials?: {
|
|
336
368
|
accessToken: string;
|
|
337
369
|
accountId?: string;
|
|
@@ -429,7 +461,26 @@ export declare class AgentSession {
|
|
|
429
461
|
private promptEnvironment;
|
|
430
462
|
/** Rebuild messages[0] from current plan-mode + approved-plan state. */
|
|
431
463
|
private rebuildSystemPromptInPlace;
|
|
464
|
+
/**
|
|
465
|
+
* Compose the system message: stable prefix, then everything volatile behind
|
|
466
|
+
* the `<!-- uncached -->` marker that providers split on for cache control.
|
|
467
|
+
*
|
|
468
|
+
* Anything that varies with the live model/provider/thinking level belongs in
|
|
469
|
+
* the tail. Putting it in the prefix means every model switch rewrites cached
|
|
470
|
+
* bytes and the next turn pays a full cache write instead of a read.
|
|
471
|
+
*/
|
|
432
472
|
private withSystemPromptTail;
|
|
473
|
+
/**
|
|
474
|
+
* Sol/Terra async-orchestration guidance for the CURRENT model and thinking
|
|
475
|
+
* level. Per-switch volatile by definition, so it is rendered as a tail part
|
|
476
|
+
* rather than spliced into the cached prefix.
|
|
477
|
+
*/
|
|
478
|
+
private orchestrationPolicyTail;
|
|
479
|
+
/**
|
|
480
|
+
* Re-render the uncached tail of messages[0] in place. The cached prefix is
|
|
481
|
+
* byte-identical afterwards, so this is safe to call on every model /
|
|
482
|
+
* thinking-level change.
|
|
483
|
+
*/
|
|
433
484
|
private refreshSystemPromptTail;
|
|
434
485
|
getMessages(): Message[];
|
|
435
486
|
getTurnMetrics(): TurnMetricPayload[];
|
|
@@ -506,8 +557,6 @@ export declare class AgentSession {
|
|
|
506
557
|
/** Set the reasoning/thinking level (undefined turns thinking off). Takes
|
|
507
558
|
* effect on the next prompt, since the in-flight loop reads it at start. */
|
|
508
559
|
setThinkingLevel(level: ThinkingLevel | undefined): void;
|
|
509
|
-
/** Sol/Terra Ultra delegates proactively; lower levels require an explicit request. */
|
|
510
|
-
private syncUltraOrchestrationPrompt;
|
|
511
560
|
/** Replace the abort signal (e.g. after cancellation). */
|
|
512
561
|
setSignal(signal: AbortSignal): void;
|
|
513
562
|
private bindManagerCancellation;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../src/core/agent-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EAEf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,QAAQ,EAEb,KAAK,aAAa,EAInB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EACL,oBAAoB,EAGrB,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAML,KAAK,UAAU,EAEf,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAoB9B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAW9D,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-session.d.ts","sourceRoot":"","sources":["../../src/core/agent-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,13 +32,19 @@ import { detectProjectStack } from "./language-detector.js";
|
|
|
32
32
|
import { evaluateIdealReview, buildIdealReviewMessage, buildReviewCoverageMessage, withReviewCoverageRequirements, detectTestDrift, ReviewCoverageTracker, } from "./ideal-review.js";
|
|
33
33
|
import { evaluateLoopBreak, buildLoopBreakMessage, CycleDetector, ToolCallProgressTracker, detectTextRepetition, } from "./loop-breaker.js";
|
|
34
34
|
import { buildRegroundingMessage } from "./regrounding.js";
|
|
35
|
-
import { wrapSteeringText, STEERING_PREFIX } from "./steering.js";
|
|
35
|
+
import { wrapSteeringText, buildNotificationSteeringText, STEERING_PREFIX } from "./steering.js";
|
|
36
|
+
import { AgentNotificationQueue } from "./agent-notifications.js";
|
|
36
37
|
import { findUserSessionPrompt, getUserSessionPrompt } from "./session-preview.js";
|
|
37
38
|
import { normalizeMessageImages } from "./message-images.js";
|
|
38
39
|
import crypto from "node:crypto";
|
|
39
40
|
import fs from "node:fs/promises";
|
|
40
41
|
import os from "node:os";
|
|
41
42
|
import path from "node:path";
|
|
43
|
+
/**
|
|
44
|
+
* A run whose tool calls fail more often than this is thrashing, not
|
|
45
|
+
* progressing — refuse to extend its turn budget.
|
|
46
|
+
*/
|
|
47
|
+
const TURN_EXTENSION_MAX_FAILURE_RATIO = 0.5;
|
|
42
48
|
// ── Tool-result policy ─────────────────────────────────────
|
|
43
49
|
/** Resolve the per-result cap passed to the agent loop for the active transport. */
|
|
44
50
|
export function resolveSessionToolResultCharLimit(model, provider, accountId) {
|
|
@@ -57,6 +63,17 @@ export function resolveSessionTurnToolResultCharLimit(model, provider, accountId
|
|
|
57
63
|
const contextChars = getContextWindow(model, { provider, accountId }) * 3.5;
|
|
58
64
|
return Math.max(100_000, Math.min(Math.floor(contextChars * 0.15), 240_000));
|
|
59
65
|
}
|
|
66
|
+
/** Marker the compactor prepends to the summary message it injects. */
|
|
67
|
+
/**
|
|
68
|
+
* True when an assistant message ends a turn with tool calls still awaiting
|
|
69
|
+
* their results. Inserting a user message there would orphan the tool_use
|
|
70
|
+
* blocks and the provider rejects the next request.
|
|
71
|
+
*/
|
|
72
|
+
function hasUnresolvedToolCalls(message) {
|
|
73
|
+
if (typeof message.content === "string" || !Array.isArray(message.content))
|
|
74
|
+
return false;
|
|
75
|
+
return message.content.some((part) => part.type === "tool_call");
|
|
76
|
+
}
|
|
60
77
|
// ── Agent Session ──────────────────────────────────────────
|
|
61
78
|
export class AgentSession {
|
|
62
79
|
eventBus = new EventBus();
|
|
@@ -132,6 +149,12 @@ export class AgentSession {
|
|
|
132
149
|
processManager;
|
|
133
150
|
lspManager;
|
|
134
151
|
subAgentManager;
|
|
152
|
+
/**
|
|
153
|
+
* Out-of-band push notifications (finished children, background-process
|
|
154
|
+
* progress). Producers enqueue; `getHookSteeringMessages` drains into the
|
|
155
|
+
* live turn so the agent never has to spend a turn asking.
|
|
156
|
+
*/
|
|
157
|
+
notifications = new AgentNotificationQueue();
|
|
135
158
|
managerAbortSignal;
|
|
136
159
|
managerAbortHandler = () => {
|
|
137
160
|
void this.subAgentManager?.interruptAll();
|
|
@@ -285,6 +308,7 @@ export class AgentSession {
|
|
|
285
308
|
getMaxPerModel: () => this.settingsManager.get("subagentMaxPerModel"),
|
|
286
309
|
disableAsyncSubagents: this.opts.subagentWorker,
|
|
287
310
|
onSubAgentState: (snapshot) => this.eventBus.emit("subagent_state", snapshot),
|
|
311
|
+
notifications: this.notifications,
|
|
288
312
|
// Plan mode: only wired when the host supplies callbacks. The ref is
|
|
289
313
|
// shared so bash/edit/write enforce read-only restrictions live.
|
|
290
314
|
...(this.opts.onEnterPlan || this.opts.onExitPlan
|
|
@@ -324,7 +348,6 @@ export class AgentSession {
|
|
|
324
348
|
(await buildSystemPrompt(this.cwd, this.skills, false, undefined, this.tools.map((tool) => tool.name), undefined, this.provider, this.promptEnvironment()));
|
|
325
349
|
this.baseSystemPrompt = basePrompt;
|
|
326
350
|
this.messages = [{ role: "system", content: this.withSystemPromptTail(basePrompt) }];
|
|
327
|
-
this.syncUltraOrchestrationPrompt();
|
|
328
351
|
// Load or create session. Transient sessions (subagent spawns) never
|
|
329
352
|
// touch the session store — sessionPath stays empty and persistMessage
|
|
330
353
|
// is a no-op so their transcripts can't pollute `ggcoder continue`.
|
|
@@ -728,12 +751,31 @@ export class AgentSession {
|
|
|
728
751
|
}
|
|
729
752
|
}
|
|
730
753
|
/**
|
|
731
|
-
* Mid-loop steering hook:
|
|
732
|
-
*
|
|
733
|
-
*
|
|
734
|
-
*
|
|
754
|
+
* Mid-loop steering hook: delivers pushed notifications and queued user
|
|
755
|
+
* steering, fires the loop-breaker when the agent looks stuck, then
|
|
756
|
+
* post-compaction re-grounding. At most one loop-break/re-grounding per run.
|
|
757
|
+
* Mirrors the TUI's getSteeringMessages ordering.
|
|
735
758
|
*/
|
|
736
759
|
getHookSteeringMessages() {
|
|
760
|
+
// Push notifications: a child that finished or a background build that
|
|
761
|
+
// exited is new *fact*, not a correction, and it is cheap (bounded to 1 KiB
|
|
762
|
+
// per drain). Drained above the loop-break checks so the agent can act on
|
|
763
|
+
// it in the very next turn instead of discovering it at the pre-stop
|
|
764
|
+
// completion gate — but it never displaces user steering, which rides out
|
|
765
|
+
// in the same batch when both are pending.
|
|
766
|
+
const notified = this.notifications.drain();
|
|
767
|
+
const notificationMessage = notified.length > 0
|
|
768
|
+
? {
|
|
769
|
+
role: "user",
|
|
770
|
+
content: buildNotificationSteeringText(notified.map((entry) => entry.text)),
|
|
771
|
+
}
|
|
772
|
+
: null;
|
|
773
|
+
if (notificationMessage) {
|
|
774
|
+
log("INFO", "notifications", "Injecting pushed notifications", {
|
|
775
|
+
count: String(notified.length),
|
|
776
|
+
chars: String(notificationMessage.content.length),
|
|
777
|
+
});
|
|
778
|
+
}
|
|
737
779
|
// User steering wins: drain any messages queued during this run first so the
|
|
738
780
|
// agent sees them mid-loop instead of after it stops.
|
|
739
781
|
if (this.userQueue.length > 0) {
|
|
@@ -743,7 +785,7 @@ export class AgentSession {
|
|
|
743
785
|
// the original task and silently drops it. ONE message per queued item
|
|
744
786
|
// (not merged): each persists as its own user message, so a resumed
|
|
745
787
|
// session shows the same number of bubbles the live run did.
|
|
746
|
-
|
|
788
|
+
const steeringMessages = queued.map((m) => {
|
|
747
789
|
if (m.attachments.length === 0) {
|
|
748
790
|
return { role: "user", content: wrapSteeringText(m.text) };
|
|
749
791
|
}
|
|
@@ -755,7 +797,10 @@ export class AgentSession {
|
|
|
755
797
|
];
|
|
756
798
|
return { role: "user", content: parts };
|
|
757
799
|
});
|
|
800
|
+
return notificationMessage ? [...steeringMessages, notificationMessage] : steeringMessages;
|
|
758
801
|
}
|
|
802
|
+
if (notificationMessage)
|
|
803
|
+
return [notificationMessage];
|
|
759
804
|
if (this.opts.selfCorrectionHooks === false)
|
|
760
805
|
return null;
|
|
761
806
|
if (!this.settingsManager.get("idealReviewEnabled"))
|
|
@@ -797,6 +842,39 @@ export class AgentSession {
|
|
|
797
842
|
}
|
|
798
843
|
return null;
|
|
799
844
|
}
|
|
845
|
+
/**
|
|
846
|
+
* Turn-budget extension gate. The loop consults this instead of stopping
|
|
847
|
+
* mid-task when it exhausts `maxTurns`. Grant ONLY on evidence of progress —
|
|
848
|
+
* handing more turns to a spinning agent just buys it more tokens to spin
|
|
849
|
+
* with — so reuse the same stuck signals that drive the loop-breaker.
|
|
850
|
+
*/
|
|
851
|
+
shouldExtendTurnBudget(ctx) {
|
|
852
|
+
const refusals = [];
|
|
853
|
+
const stuck = evaluateLoopBreak({
|
|
854
|
+
consecutiveFailures: this.hookConsecutiveFailures,
|
|
855
|
+
repeatedNoProgressCalls: this.hookRepeatedNoProgressCalls,
|
|
856
|
+
textRepetitionDetected: detectTextRepetition(this.hookText),
|
|
857
|
+
...(this.hookCyclicPattern ? { cyclicPattern: this.hookCyclicPattern } : {}),
|
|
858
|
+
});
|
|
859
|
+
if (stuck.shouldBreak)
|
|
860
|
+
refusals.push(...stuck.reasons);
|
|
861
|
+
// Stage 2 means the loop-breaker already detected spinning twice and told
|
|
862
|
+
// the agent to stop and report. Do not overrule that with more turns.
|
|
863
|
+
if (this.loopBreakInjected >= 2)
|
|
864
|
+
refusals.push("loop-breaker already escalated");
|
|
865
|
+
const { toolCalls, toolFailures } = this.hookStats;
|
|
866
|
+
if (toolCalls > 0 && toolFailures / toolCalls > TURN_EXTENSION_MAX_FAILURE_RATIO) {
|
|
867
|
+
refusals.push(`${toolFailures}/${toolCalls} tool calls failed`);
|
|
868
|
+
}
|
|
869
|
+
const granted = refusals.length === 0;
|
|
870
|
+
log("INFO", "turn-budget", granted ? "Extending turn budget" : "Refusing turn-budget extension", {
|
|
871
|
+
turn: String(ctx.turn),
|
|
872
|
+
maxTurns: String(ctx.maxTurns),
|
|
873
|
+
extension: String(ctx.extension),
|
|
874
|
+
...(granted ? {} : { reasons: refusals.join(", ") }),
|
|
875
|
+
});
|
|
876
|
+
return granted;
|
|
877
|
+
}
|
|
800
878
|
/**
|
|
801
879
|
* Pre-stop Ideal review phase machine. Once review starts, completion is
|
|
802
880
|
* blocked until harness-owned post-injection reads cover every changed file.
|
|
@@ -963,6 +1041,7 @@ export class AgentSession {
|
|
|
963
1041
|
webSearch: true,
|
|
964
1042
|
maxTokens: this.maxTokens,
|
|
965
1043
|
maxTurns: this.opts.maxTurns,
|
|
1044
|
+
maxTurnExtensions: this.opts.maxTurnExtensions,
|
|
966
1045
|
thinking: this.thinkingLevel,
|
|
967
1046
|
apiKey,
|
|
968
1047
|
baseUrl: effectiveBaseUrl,
|
|
@@ -991,6 +1070,7 @@ export class AgentSession {
|
|
|
991
1070
|
// polled mid-loop; the ideal review is polled when the agent would stop.
|
|
992
1071
|
getSteeringMessages: () => this.getHookSteeringMessages(),
|
|
993
1072
|
getFollowUpMessages: () => this.getHookFollowUpMessages(),
|
|
1073
|
+
onTurnBudgetExhausted: (ctx) => this.shouldExtendTurnBudget(ctx),
|
|
994
1074
|
// Check authoritative provider usage before every model/tool step.
|
|
995
1075
|
// Forced overflow recovery bypasses settings and cooldown; proactive
|
|
996
1076
|
// checks honor both and estimate only messages unseen by the provider.
|
|
@@ -1168,6 +1248,11 @@ export class AgentSession {
|
|
|
1168
1248
|
}
|
|
1169
1249
|
async switchModel(provider, model) {
|
|
1170
1250
|
const prevProvider = this.provider;
|
|
1251
|
+
const prevModel = this.model;
|
|
1252
|
+
// Diff gate: a "switch" to the model already in use is not state change.
|
|
1253
|
+
// Recording it anyway would write a redundant marker and a redundant
|
|
1254
|
+
// history note on every no-op re-selection from the UI.
|
|
1255
|
+
const changed = model !== prevModel || (Boolean(provider) && provider !== prevProvider);
|
|
1171
1256
|
if (provider)
|
|
1172
1257
|
this.provider = provider;
|
|
1173
1258
|
this.model = model;
|
|
@@ -1176,7 +1261,6 @@ export class AgentSession {
|
|
|
1176
1261
|
// the live selection after an in-session model switch.
|
|
1177
1262
|
this.opts.provider = this.provider;
|
|
1178
1263
|
this.opts.model = this.model;
|
|
1179
|
-
this.syncUltraOrchestrationPrompt();
|
|
1180
1264
|
setEstimatorModel(model);
|
|
1181
1265
|
// maxTokens must follow the active model — it was frozen at the boot
|
|
1182
1266
|
// model's `maxOutputTokens` in the constructor, so without this a session
|
|
@@ -1197,6 +1281,27 @@ export class AgentSession {
|
|
|
1197
1281
|
const newReadTool = this.rebuildReadTool(model);
|
|
1198
1282
|
this.tools = this.tools.map((t) => (t.name === "read" ? newReadTool : t));
|
|
1199
1283
|
}
|
|
1284
|
+
// Model-dependent guidance lives in the uncached tail, so this rewrites
|
|
1285
|
+
// only the bytes after the cache marker — the cached prefix survives the
|
|
1286
|
+
// switch intact and the next turn still reads from cache.
|
|
1287
|
+
this.refreshSystemPromptTail();
|
|
1288
|
+
if (changed) {
|
|
1289
|
+
// Durable, replayable record of which model produced which segment. Rides
|
|
1290
|
+
// the existing app-marker path (parentId null, anchored by message count)
|
|
1291
|
+
// so a resumed session reconstructs the switch without the LLM seeing an
|
|
1292
|
+
// extra transcript row.
|
|
1293
|
+
await this.persistAppMarker("model_switch", {
|
|
1294
|
+
from: prevModel,
|
|
1295
|
+
to: this.model,
|
|
1296
|
+
provider: this.provider,
|
|
1297
|
+
fromProvider: prevProvider,
|
|
1298
|
+
}).catch((error) => {
|
|
1299
|
+
log("WARN", "session", "Failed to persist model-switch marker", {
|
|
1300
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1301
|
+
});
|
|
1302
|
+
});
|
|
1303
|
+
this.appendModelSwitchNote(prevModel, prevProvider);
|
|
1304
|
+
}
|
|
1200
1305
|
// Update provider-specific tools when provider changes
|
|
1201
1306
|
if (provider && provider !== prevProvider) {
|
|
1202
1307
|
// Add/remove client-side web_search tool based on provider.
|
|
@@ -1251,6 +1356,30 @@ export class AgentSession {
|
|
|
1251
1356
|
}
|
|
1252
1357
|
}
|
|
1253
1358
|
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Record the switch as its own trailing message at the point it happened,
|
|
1361
|
+
* rather than by rewriting the system prompt. Two reasons: the system prompt
|
|
1362
|
+
* is the cached prefix and rewriting it costs a full cache write, and a
|
|
1363
|
+
* resumed transcript can only attribute output to the right model if the
|
|
1364
|
+
* switch sits in message order.
|
|
1365
|
+
*
|
|
1366
|
+
* Skipped before the conversation starts (nothing to disambiguate) and while
|
|
1367
|
+
* an assistant turn has unresolved tool calls, where inserting a user message
|
|
1368
|
+
* would break tool_use/tool_result pairing.
|
|
1369
|
+
*/
|
|
1370
|
+
appendModelSwitchNote(prevModel, prevProvider) {
|
|
1371
|
+
const last = this.messages[this.messages.length - 1];
|
|
1372
|
+
if (!last || last.role === "system")
|
|
1373
|
+
return;
|
|
1374
|
+
if (last.role === "assistant" && hasUnresolvedToolCalls(last))
|
|
1375
|
+
return;
|
|
1376
|
+
const from = prevProvider === this.provider ? prevModel : `${prevProvider}/${prevModel}`;
|
|
1377
|
+
const to = prevProvider === this.provider ? this.model : `${this.provider}/${this.model}`;
|
|
1378
|
+
this.messages.push({
|
|
1379
|
+
role: "user",
|
|
1380
|
+
content: `[Model switched from ${from} to ${to}. Everything above was produced under the previous model; continue the current task from here.]`,
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1254
1383
|
async compact(existingCredentials) {
|
|
1255
1384
|
this.lastCompactionCompacted = false;
|
|
1256
1385
|
const creds = existingCredentials ??
|
|
@@ -1350,7 +1479,6 @@ export class AgentSession {
|
|
|
1350
1479
|
(await buildSystemPrompt(this.cwd, this.skills, false, undefined, this.tools.map((tool) => tool.name), undefined, this.provider, this.promptEnvironment()));
|
|
1351
1480
|
this.baseSystemPrompt = basePrompt;
|
|
1352
1481
|
this.messages = [{ role: "system", content: this.withSystemPromptTail(basePrompt) }];
|
|
1353
|
-
this.syncUltraOrchestrationPrompt();
|
|
1354
1482
|
// Fresh conversation — new entries must not chain onto the old DAG's leaf.
|
|
1355
1483
|
this.currentLeafId = null;
|
|
1356
1484
|
// Transient sessions (Ken chat/autopilot, subagent spawns) never touch the
|
|
@@ -1498,7 +1626,6 @@ export class AgentSession {
|
|
|
1498
1626
|
else {
|
|
1499
1627
|
this.messages.unshift({ role: "system", content });
|
|
1500
1628
|
}
|
|
1501
|
-
this.syncUltraOrchestrationPrompt();
|
|
1502
1629
|
}
|
|
1503
1630
|
/**
|
|
1504
1631
|
* Toggle plan mode: flips the shared ref (so tools enforce read-only
|
|
@@ -1593,18 +1720,47 @@ export class AgentSession {
|
|
|
1593
1720
|
else {
|
|
1594
1721
|
this.messages.unshift({ role: "system", content });
|
|
1595
1722
|
}
|
|
1596
|
-
this.syncUltraOrchestrationPrompt();
|
|
1597
1723
|
}
|
|
1724
|
+
/**
|
|
1725
|
+
* Compose the system message: stable prefix, then everything volatile behind
|
|
1726
|
+
* the `<!-- uncached -->` marker that providers split on for cache control.
|
|
1727
|
+
*
|
|
1728
|
+
* Anything that varies with the live model/provider/thinking level belongs in
|
|
1729
|
+
* the tail. Putting it in the prefix means every model switch rewrites cached
|
|
1730
|
+
* bytes and the next turn pays a full cache write instead of a read.
|
|
1731
|
+
*/
|
|
1598
1732
|
withSystemPromptTail(basePrompt) {
|
|
1599
|
-
|
|
1733
|
+
const tailParts = [];
|
|
1734
|
+
const orchestration = this.orchestrationPolicyTail();
|
|
1735
|
+
if (orchestration)
|
|
1736
|
+
tailParts.push(orchestration);
|
|
1737
|
+
const hostTail = this.opts.getSystemPromptTail?.();
|
|
1738
|
+
if (hostTail)
|
|
1739
|
+
tailParts.push(hostTail);
|
|
1740
|
+
if (tailParts.length === 0)
|
|
1600
1741
|
return basePrompt;
|
|
1601
|
-
return `${basePrompt}\n\n<!-- uncached -->\n${
|
|
1742
|
+
return `${basePrompt}\n\n<!-- uncached -->\n${tailParts.join("\n\n")}`;
|
|
1602
1743
|
}
|
|
1744
|
+
/**
|
|
1745
|
+
* Sol/Terra async-orchestration guidance for the CURRENT model and thinking
|
|
1746
|
+
* level. Per-switch volatile by definition, so it is rendered as a tail part
|
|
1747
|
+
* rather than spliced into the cached prefix.
|
|
1748
|
+
*/
|
|
1749
|
+
orchestrationPolicyTail() {
|
|
1750
|
+
if (this.opts.orchestrationPrompt === false)
|
|
1751
|
+
return "";
|
|
1752
|
+
return applyAsyncSubagentPolicy("", this.provider, this.model, this.thinkingLevel, this.tools.map((tool) => tool.name)).trim();
|
|
1753
|
+
}
|
|
1754
|
+
/**
|
|
1755
|
+
* Re-render the uncached tail of messages[0] in place. The cached prefix is
|
|
1756
|
+
* byte-identical afterwards, so this is safe to call on every model /
|
|
1757
|
+
* thinking-level change.
|
|
1758
|
+
*/
|
|
1603
1759
|
refreshSystemPromptTail() {
|
|
1604
|
-
if (!this.opts.getSystemPromptTail)
|
|
1605
|
-
return;
|
|
1606
1760
|
const content = this.withSystemPromptTail(this.baseSystemPrompt);
|
|
1607
1761
|
if (this.messages[0]?.role === "system") {
|
|
1762
|
+
if (this.messages[0].content === content)
|
|
1763
|
+
return;
|
|
1608
1764
|
this.messages[0] = { role: "system", content };
|
|
1609
1765
|
}
|
|
1610
1766
|
else {
|
|
@@ -1842,16 +1998,7 @@ export class AgentSession {
|
|
|
1842
1998
|
* effect on the next prompt, since the in-flight loop reads it at start. */
|
|
1843
1999
|
setThinkingLevel(level) {
|
|
1844
2000
|
this.thinkingLevel = level;
|
|
1845
|
-
this.
|
|
1846
|
-
}
|
|
1847
|
-
/** Sol/Terra Ultra delegates proactively; lower levels require an explicit request. */
|
|
1848
|
-
syncUltraOrchestrationPrompt() {
|
|
1849
|
-
if (this.opts.orchestrationPrompt === false)
|
|
1850
|
-
return;
|
|
1851
|
-
const systemMessage = this.messages[0];
|
|
1852
|
-
if (systemMessage?.role !== "system" || typeof systemMessage.content !== "string")
|
|
1853
|
-
return;
|
|
1854
|
-
systemMessage.content = applyAsyncSubagentPolicy(systemMessage.content, this.provider, this.model, this.thinkingLevel, this.tools.map((tool) => tool.name));
|
|
2001
|
+
this.refreshSystemPromptTail();
|
|
1855
2002
|
}
|
|
1856
2003
|
/** Replace the abort signal (e.g. after cancellation). */
|
|
1857
2004
|
setSignal(signal) {
|