@ponythewhite/base-context 1.0.7 → 1.0.8
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 +19 -0
- package/dist/base-context-runtime/pyproject.toml +1 -1
- package/dist/base-context-runtime/src/rlm/__init__.py +3 -0
- package/dist/base-context-runtime/src/rlm/harness.py +86 -48
- package/dist/base-context-runtime/test/test_harness.py +215 -140
- package/dist/base-context-runtime/uv.lock +1 -1
- package/dist/build-info.json +1 -1
- package/dist/bundle/amazon-bedrock.js +3 -3
- package/dist/bundle/{anthropic-UV5GZDGU.js → anthropic-5PSCZEER.js} +2 -7
- package/dist/bundle/{azure-openai-responses-WSNPXLYC.js → azure-openai-responses-AYTLJR33.js} +2 -2
- package/dist/bundle/{bundled-modules-PS66L3IT.js → bundled-modules-IGMJH2MU.js} +5 -5
- package/dist/bundle/{chunk-UPVDERMD.js → chunk-2IPDSTDR.js} +11 -9
- package/dist/bundle/chunk-D3KOF57W.js +22040 -0
- package/dist/bundle/{chunk-VCW3YDFF.js → chunk-EXEFSSF4.js} +1475 -562
- package/dist/bundle/{chunk-VSIYFWYI.js → chunk-KT2BNEPE.js} +21 -8
- package/dist/bundle/{chunk-KTNETTHI.js → chunk-Q3MBSBEB.js} +3 -101
- package/dist/bundle/{chunk-LFPWHI42.js → chunk-QKIFBA7N.js} +2 -2
- package/dist/bundle/{chunk-PFROC4EV.js → chunk-RVJVXZCS.js} +12 -9
- package/dist/bundle/{cli-main-MMHTK7EB.js → cli-main-BUK7QTHO.js} +4 -4
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/{google-T32FMD4G.js → google-HTMCUJ7X.js} +2 -2
- package/dist/bundle/{google-vertex-56KP6I3B.js → google-vertex-ZQO65AXF.js} +2 -2
- package/dist/bundle/{main-XAIVH4Y7.js → main-2FWHT2WZ.js} +5 -5
- package/dist/bundle/{mistral-WGBMYIVU.js → mistral-SB7LU56G.js} +1 -1
- package/dist/bundle/{openai-codex-responses-PIV2RQ3G.js → openai-codex-responses-5CEW4VN3.js} +53 -27
- package/dist/bundle/{openai-completions-64C3JPR4.js → openai-completions-BAZJQSS2.js} +1 -1
- package/dist/bundle/{openai-responses-UI7RSTDV.js → openai-responses-VHOE427P.js} +48 -5
- package/dist/core/agent-session.d.ts +6 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +177 -24
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/canonical-context.d.ts +8 -0
- package/dist/core/canonical-context.d.ts.map +1 -1
- package/dist/core/canonical-context.js +37 -5
- package/dist/core/canonical-context.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +2 -2
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +31 -13
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/context-epoch.d.ts +1 -1
- package/dist/core/context-epoch.d.ts.map +1 -1
- package/dist/core/context-epoch.js +2 -1
- package/dist/core/context-epoch.js.map +1 -1
- package/dist/core/extensions/types.d.ts +2 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/history-index-worker.d.ts.map +1 -1
- package/dist/core/history-index-worker.js +29 -8
- package/dist/core/history-index-worker.js.map +1 -1
- package/dist/core/history-index.d.ts +11 -1
- package/dist/core/history-index.d.ts.map +1 -1
- package/dist/core/history-index.js +2 -1
- package/dist/core/history-index.js.map +1 -1
- package/dist/core/inference-coordinator.d.ts.map +1 -1
- package/dist/core/inference-coordinator.js +108 -13
- package/dist/core/inference-coordinator.js.map +1 -1
- package/dist/core/kernel/bootstrap.d.ts.map +1 -1
- package/dist/core/kernel/bootstrap.js +97 -107
- package/dist/core/kernel/bootstrap.js.map +1 -1
- package/dist/core/kernel/repl-manager.d.ts.map +1 -1
- package/dist/core/kernel/repl-manager.js +11 -0
- package/dist/core/kernel/repl-manager.js.map +1 -1
- package/dist/core/kernel/shared.d.ts +2 -0
- package/dist/core/kernel/shared.d.ts.map +1 -1
- package/dist/core/kernel/shared.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +4 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/prompts/rlm.d.ts.map +1 -1
- package/dist/core/prompts/rlm.js +4 -2
- package/dist/core/prompts/rlm.js.map +1 -1
- package/dist/core/public-context.d.ts.map +1 -1
- package/dist/core/public-context.js +16 -0
- package/dist/core/public-context.js.map +1 -1
- package/dist/core/refinement/refinement.d.ts +19 -5
- package/dist/core/refinement/refinement.d.ts.map +1 -1
- package/dist/core/refinement/refinement.js +90 -35
- package/dist/core/refinement/refinement.js.map +1 -1
- package/dist/core/request-view-selection.d.ts +10 -2
- package/dist/core/request-view-selection.d.ts.map +1 -1
- package/dist/core/request-view-selection.js +235 -100
- package/dist/core/request-view-selection.js.map +1 -1
- package/dist/core/retained-tool-output.d.ts +28 -0
- package/dist/core/retained-tool-output.d.ts.map +1 -0
- package/dist/core/retained-tool-output.js +102 -0
- package/dist/core/retained-tool-output.js.map +1 -0
- package/dist/core/selective-recovery.d.ts +47 -3
- package/dist/core/selective-recovery.d.ts.map +1 -1
- package/dist/core/selective-recovery.js +428 -109
- package/dist/core/selective-recovery.js.map +1 -1
- package/dist/core/session-history-index.d.ts +3 -1
- package/dist/core/session-history-index.d.ts.map +1 -1
- package/dist/core/session-history-index.js +1 -1
- package/dist/core/session-history-index.js.map +1 -1
- package/dist/core/settings-manager.d.ts +5 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +3 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts +3 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +3 -3
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/task-frame.d.ts +1 -1
- package/dist/core/task-frame.d.ts.map +1 -1
- package/dist/core/task-frame.js +21 -1
- package/dist/core/task-frame.js.map +1 -1
- package/dist/core/task-state-reader.d.ts +10 -2
- package/dist/core/task-state-reader.d.ts.map +1 -1
- package/dist/core/task-state-reader.js +75 -9
- package/dist/core/task-state-reader.js.map +1 -1
- package/dist/core/tools/ipython.d.ts +5 -0
- package/dist/core/tools/ipython.d.ts.map +1 -1
- package/dist/core/tools/ipython.js +59 -17
- package/dist/core/tools/ipython.js.map +1 -1
- package/dist/core/tools/prime-context.d.ts.map +1 -1
- package/dist/core/tools/prime-context.js +1 -1
- package/dist/core/tools/prime-context.js.map +1 -1
- package/dist/core/view-units.d.ts +4 -0
- package/dist/core/view-units.d.ts.map +1 -1
- package/dist/core/view-units.js +28 -19
- package/dist/core/view-units.js.map +1 -1
- package/dist/installer.mjs +98 -77
- package/dist/modes/interactive/components/refinement-outcome-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/refinement-outcome-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +5 -5
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/skills/skill-creator/SKILL.md +18 -1
- package/docs/settings.md +45 -0
- package/docs/skills.md +77 -2
- package/package.json +4 -4
- package/skills/skill-creator/SKILL.md +18 -1
- package/dist/bundle/chunk-W46VZFI6.js +0 -21681
|
@@ -5,7 +5,7 @@ import { tmpdir } from "node:os";
|
|
|
5
5
|
import { basename, dirname, join, resolve } from "node:path";
|
|
6
6
|
import { isDeepStrictEqual } from "node:util";
|
|
7
7
|
import { Agent, AgentContinueError, AgentOutputLimitError, } from "@ponythewhite/base-context-agent";
|
|
8
|
-
import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, isTransientProviderFailure, modelsAreEqual, resetApiProviders, supportsFastMode, } from "@ponythewhite/base-context-ai";
|
|
8
|
+
import { clampThinkingLevel, cleanupSessionResources, conservativeTextTokenCost, getSupportedThinkingLevels, isContextOverflow, isTransientProviderFailure, modelsAreEqual, resetApiProviders, supportsFastMode, } from "@ponythewhite/base-context-ai";
|
|
9
9
|
import { theme } from "../modes/interactive/theme/theme.js";
|
|
10
10
|
import { PRODUCT } from "../product-identity.js";
|
|
11
11
|
import { sleep } from "../utils/sleep.js";
|
|
@@ -31,13 +31,13 @@ import { snapshotPathIn } from "./kernel/state-snapshot.js";
|
|
|
31
31
|
import { convertToLlm, createCompactionOutcomeMessage, createHeartbeatPromptMessage, createRefinementOutcomeMessage, createRlmChildFailureMessage, createRlmChildTerminalNoticeMessage, createSessionSlashCommandMessage, createSessionSlashCommandResultMessage, HEARTBEAT_PROMPT_CUSTOM_TYPE, HEARTBEAT_PROMPT_PREVIEW_LABEL, IPYTHON_STATE_RESTORED_CUSTOM_TYPE, isSessionSlashCommandMessage, RLM_CHILD_FAILURE_CUSTOM_TYPE, RLM_CHILD_TERMINAL_NOTICE_CUSTOM_TYPE, } from "./messages.js";
|
|
32
32
|
import { throwIfPromptAdmissionCancelled } from "./prompt-admission.js";
|
|
33
33
|
import { expandPromptTemplate } from "./prompt-templates.js";
|
|
34
|
-
import { appendGlobalRefinement, applyRefinementProposal, generateRefinementId, getGlobalHarnessStateDir, getLocalHarnessStateDir, getRefinementHistory, inferRefinementResultScope, loadGlobalRefinementHistory, loadHarnessState, mergeHarnessStates, mergeRefinementHistory, normalizeRefinementProposal, planRefinement, prepareRefinementApplication, REFINE_SKILL_NAME, reviewAutoRefine, saveHarnessState, takeNativePlannerRequestWrite, withRefinementBaseline, } from "./refinement/index.js";
|
|
34
|
+
import { appendGlobalRefinement, applyRefinementProposal, generateRefinementId, getGlobalHarnessStateDir, getLocalHarnessStateDir, getRefinementHistory, getWorkspaceHarnessStateDir, inferRefinementResultScope, loadGlobalRefinementHistory, loadHarnessState, mergeHarnessStates, mergeRefinementHistory, normalizeRefinementProposal, planRefinement, prepareRefinementApplication, REFINE_SKILL_NAME, reviewAutoRefine, saveHarnessState, takeNativePlannerRequestWrite, withRefinementBaseline, } from "./refinement/index.js";
|
|
35
35
|
import { PublicContextBudgetError } from "./request-view-selection.js";
|
|
36
36
|
import { resolveConfigValue } from "./resolve-config-value.js";
|
|
37
37
|
import { assertResourceCurrent } from "./resource-view.js";
|
|
38
38
|
import { createDefaultRlmSubagentSessionName, createRlmDeleteSubagentHostHandler, createRlmFindModelsHostHandler, createRlmListSubagentsHostHandler, createRlmRunHostHandler, findRlmModelMatches, normalizeRequestedRlmSubagentModel, normalizeRequestedRlmSubagentSessionName, normalizeRequestedRlmSubagentThinkingLevel, } from "./rlm-runtime.js";
|
|
39
39
|
import { captureSelectedSkill, captureSkillDescriptor, readSkillSelection, sameSelectedSkills, selectedSkillBlock, selectedSkillIdentity, } from "./selected-skills.js";
|
|
40
|
-
import { createNativeRecoveryRefusal, DEFAULT_NATIVE_RECOVERY_LIMITS, NativeRecoveryBudgetRefusal, parseNativeRecoveryInput, recoverCapturedHistory, } from "./selective-recovery.js";
|
|
40
|
+
import { createNativeRecoveryRefusal, DEFAULT_NATIVE_RECOVERY_LIMITS, NativeRecoveryBudgetRefusal, NativeRecoveryCursorStore, parseNativeRecoveryInput, recoverCapturedHistory, } from "./selective-recovery.js";
|
|
41
41
|
import { modelRequestHeaders, SemanticEdgeRecorder, semanticEdgeLedgerPath, wrapStreamFnWithSemanticEdges, } from "./semantic-edges.js";
|
|
42
42
|
import { ActionStore, canSelectSessionAction, queuedMessageLaneDeliveryPolicy, transitionSessionAction, } from "./session-action-store.js";
|
|
43
43
|
import { readSessionBootstrap } from "./session-bootstrap.js";
|
|
@@ -281,6 +281,7 @@ export class AgentSession {
|
|
|
281
281
|
requests;
|
|
282
282
|
runtimeServices;
|
|
283
283
|
_contextCompiler = new CanonicalContextCompiler();
|
|
284
|
+
_failedAutomaticCompaction;
|
|
284
285
|
_contextEpochsEnabled;
|
|
285
286
|
_initialContextMode;
|
|
286
287
|
_contextMode;
|
|
@@ -444,6 +445,8 @@ export class AgentSession {
|
|
|
444
445
|
_modelRegistry;
|
|
445
446
|
_toolRegistry = new Map();
|
|
446
447
|
_nativeRecoveryTools = new WeakMap();
|
|
448
|
+
_nativeRecoveryCursors = new NativeRecoveryCursorStore();
|
|
449
|
+
_nativeRecoveryCursorSource;
|
|
447
450
|
_nativeRecoveryProducer = new AsyncLocalStorage();
|
|
448
451
|
_toolDefinitions = new Map();
|
|
449
452
|
_toolPromptSnippets = new Map();
|
|
@@ -452,6 +455,7 @@ export class AgentSession {
|
|
|
452
455
|
_baseSystemPromptOptions;
|
|
453
456
|
_assistantTurnsSinceAutoRefine = 0;
|
|
454
457
|
_lastAutoRefineReviewAt = 0;
|
|
458
|
+
_lastAutoRefineEvidence;
|
|
455
459
|
_autoRefineInProgress = false;
|
|
456
460
|
_autoRefineAdmissionClosed = false;
|
|
457
461
|
_autoRefineOperations = new Set();
|
|
@@ -610,7 +614,8 @@ export class AgentSession {
|
|
|
610
614
|
const epochContext = getCanonicalEpochContext(messages);
|
|
611
615
|
if (epochContext)
|
|
612
616
|
this._contextMode = epochContext.mode;
|
|
613
|
-
const unbudgetedPublic = !contextEpochsEnabled &&
|
|
617
|
+
const unbudgetedPublic = !contextEpochsEnabled &&
|
|
618
|
+
Boolean(epochContext?.toolContinuations?.length || epochContext?.taskFrameRebased || epochContext?.checkpoint);
|
|
614
619
|
const nativeSkills = Boolean(contextEpochsEnabled || epochContext?.checkpoint || unbudgetedPublic);
|
|
615
620
|
const skillPolicy = nativeSkills ? (this._nativeRecoveryEnabled() ? "enabled" : "unavailable") : undefined;
|
|
616
621
|
if (this._baseSystemPromptOptions.nativeSkillSelection !== skillPolicy) {
|
|
@@ -637,6 +642,7 @@ export class AgentSession {
|
|
|
637
642
|
message.content.some((part) => part.type !== "text" || part.textSignature !== undefined)));
|
|
638
643
|
let accepted;
|
|
639
644
|
let acceptedBody;
|
|
645
|
+
let acceptedResponseIdentity;
|
|
640
646
|
let acceptedReplayContract;
|
|
641
647
|
let acknowledged;
|
|
642
648
|
const commitFailure = (cause) => {
|
|
@@ -656,7 +662,7 @@ export class AgentSession {
|
|
|
656
662
|
candidate.projection.pendingPublicMessageGroups?.length))
|
|
657
663
|
throw new Error("Tool continuation requires its exact public candidate before epoch ACK");
|
|
658
664
|
assertResourceCurrent(resource);
|
|
659
|
-
const representation = contextEpochRepresentation(candidate.request, candidate.assessment, limits.maxSourceBytes, unbudgetedPublic);
|
|
665
|
+
const representation = contextEpochRepresentation(candidate.request, candidate.assessment, limits.maxSourceBytes, unbudgetedPublic, candidate.responseItemIdentity);
|
|
660
666
|
const replayContract = "replayContract" in candidate.projection &&
|
|
661
667
|
candidate.projection.replayContract === "message-groups"
|
|
662
668
|
? "message-groups"
|
|
@@ -669,6 +675,7 @@ export class AgentSession {
|
|
|
669
675
|
candidate.publicMessages !== undefined,
|
|
670
676
|
candidate.selectedUnitIds,
|
|
671
677
|
]);
|
|
678
|
+
acceptedResponseIdentity = candidate.responseItemIdentity;
|
|
672
679
|
if (accepted !== undefined) {
|
|
673
680
|
if (accepted !== selection)
|
|
674
681
|
throw new Error("Captured epoch request selection changed after acceptance");
|
|
@@ -738,12 +745,13 @@ export class AgentSession {
|
|
|
738
745
|
}
|
|
739
746
|
return;
|
|
740
747
|
}
|
|
748
|
+
if (epochContext.taskFrameRebased && acceptedBody === undefined)
|
|
749
|
+
throw new Error("Task frame rebase requires a committed epoch boundary");
|
|
741
750
|
if (!committed)
|
|
742
751
|
return;
|
|
743
752
|
if (acceptedBody === undefined || request.body !== acceptedBody)
|
|
744
753
|
throw new Error("Committed context epoch requires a compatible final provider projection");
|
|
745
|
-
if (contextEpochRepresentation(request, assessment, limits.maxSourceBytes, unbudgetedPublic) !==
|
|
746
|
-
committed.representation)
|
|
754
|
+
if (contextEpochRepresentation(request, assessment, limits.maxSourceBytes, unbudgetedPublic, acceptedResponseIdentity) !== committed.representation)
|
|
747
755
|
throw new Error("Context epoch representation changed without a committed boundary");
|
|
748
756
|
if (committed.resourceRevision !== epochContext.resourceRevision)
|
|
749
757
|
throw new Error("Context epoch resource revision requires a committed boundary");
|
|
@@ -844,9 +852,41 @@ export class AgentSession {
|
|
|
844
852
|
error.source.sessionFile !== owner.sessionFile ||
|
|
845
853
|
error.source.leafId !== owner.manager.getLeafId())
|
|
846
854
|
return false;
|
|
855
|
+
// Rebase this captured frame before paying for a summary. The replacement still
|
|
856
|
+
// needs the normal full provider projection and epoch ACK before MAIN can send.
|
|
857
|
+
if (error.taskFrameRebaseAvailable) {
|
|
858
|
+
this._contextCompiler.requestTaskFrameRebase();
|
|
859
|
+
return "reprepare";
|
|
860
|
+
}
|
|
861
|
+
if (error.mandatoryAssessment?.status === "over-budget")
|
|
862
|
+
return false;
|
|
847
863
|
// The loop released its unsent inference and captured projection before this handoff.
|
|
848
864
|
// Continue in-place only after the real summary ACK and canonical owner adoption.
|
|
849
|
-
|
|
865
|
+
const key = error.getCompactionKey();
|
|
866
|
+
const current = {
|
|
867
|
+
key: key ?? "",
|
|
868
|
+
systemPrompt: this.agent.state.systemPrompt,
|
|
869
|
+
tools: this.agent.state.tools,
|
|
870
|
+
settings: JSON.stringify(this.settingsManager.getCompactionSettings()),
|
|
871
|
+
};
|
|
872
|
+
const failed = this._failedAutomaticCompaction;
|
|
873
|
+
if (key &&
|
|
874
|
+
failed &&
|
|
875
|
+
failed.key === key &&
|
|
876
|
+
failed.systemPrompt === current.systemPrompt &&
|
|
877
|
+
failed.tools === current.tools &&
|
|
878
|
+
failed.settings === current.settings)
|
|
879
|
+
return false;
|
|
880
|
+
this._failedAutomaticCompaction = undefined;
|
|
881
|
+
let succeeded = false;
|
|
882
|
+
try {
|
|
883
|
+
succeeded = await this._runAutoCompaction("threshold", false, owner, true, error);
|
|
884
|
+
return succeeded;
|
|
885
|
+
}
|
|
886
|
+
finally {
|
|
887
|
+
if (!succeeded && key && this._isCompactionSourceOwnerCurrent(owner))
|
|
888
|
+
this._failedAutomaticCompaction = current;
|
|
889
|
+
}
|
|
850
890
|
});
|
|
851
891
|
this.agent.bindProviderFailureRecoveryOwner({
|
|
852
892
|
recover: (message, signal) => this._handleRetryableError(message, signal),
|
|
@@ -4107,6 +4147,9 @@ export class AgentSession {
|
|
|
4107
4147
|
* the latest state reaches disk instead of racing process exit.
|
|
4108
4148
|
*/
|
|
4109
4149
|
async disposeAsync(options) {
|
|
4150
|
+
this._failedAutomaticCompaction = undefined;
|
|
4151
|
+
this._contextCompiler.clear();
|
|
4152
|
+
this._nativeRecoveryCursors.clear();
|
|
4110
4153
|
for (const admission of this._rlmChildAdmissions)
|
|
4111
4154
|
admission.cancel("Parent session disposed");
|
|
4112
4155
|
if (this._disposeAsyncPromise)
|
|
@@ -4340,6 +4383,9 @@ export class AgentSession {
|
|
|
4340
4383
|
return this._disposeCallbacksPromise;
|
|
4341
4384
|
}
|
|
4342
4385
|
dispose() {
|
|
4386
|
+
this._failedAutomaticCompaction = undefined;
|
|
4387
|
+
this._contextCompiler.clear();
|
|
4388
|
+
this._nativeRecoveryCursors.clear();
|
|
4343
4389
|
if (this._disposed) {
|
|
4344
4390
|
return;
|
|
4345
4391
|
}
|
|
@@ -4583,7 +4629,7 @@ export class AgentSession {
|
|
|
4583
4629
|
}
|
|
4584
4630
|
return Array.from(unique);
|
|
4585
4631
|
}
|
|
4586
|
-
_rebuildSystemPrompt(toolNames, nativeEpoch = this.sessionManager.isPersisted() && this._contextEpochsEnabled) {
|
|
4632
|
+
_rebuildSystemPrompt(toolNames, nativeEpoch = this.sessionManager.isPersisted() && this._contextEpochsEnabled, operation = this._baseSystemPromptOptions?.errorFixSelection?.operation) {
|
|
4587
4633
|
const validToolNames = toolNames.filter((name) => this._toolRegistry.has(name));
|
|
4588
4634
|
const toolSnippets = {};
|
|
4589
4635
|
const promptGuidelines = [];
|
|
@@ -4617,6 +4663,14 @@ export class AgentSession {
|
|
|
4617
4663
|
rlmDepth: this._rlmDepth,
|
|
4618
4664
|
rlmParentAgent: this._rlmParentAgent,
|
|
4619
4665
|
harnessState: this._loadMergedHarnessState(),
|
|
4666
|
+
errorFixSelection: {
|
|
4667
|
+
enabled: this.settingsManager.getLearningEnabled(),
|
|
4668
|
+
tools: validToolNames,
|
|
4669
|
+
operation,
|
|
4670
|
+
goal: this._goalState.objective,
|
|
4671
|
+
environment: { cwd: this._cwd, platform: process.platform },
|
|
4672
|
+
countTokens: conservativeTextTokenCost,
|
|
4673
|
+
},
|
|
4620
4674
|
genericMcpServers: this._mcpManager?.getEnabledPersistentGenericServers(),
|
|
4621
4675
|
};
|
|
4622
4676
|
return buildSystemPrompt(this._baseSystemPromptOptions);
|
|
@@ -6099,6 +6153,12 @@ export class AgentSession {
|
|
|
6099
6153
|
const preparationAction = activeTurns().at(-1);
|
|
6100
6154
|
if (!preparationAction)
|
|
6101
6155
|
return undefined;
|
|
6156
|
+
if (this.settingsManager.getLearningEnabled() ||
|
|
6157
|
+
this._baseSystemPromptOptions.errorFixSelection?.enabled) {
|
|
6158
|
+
// Capture advice for this task before extensions and provider preparation.
|
|
6159
|
+
// Tool continuations keep the same prompt until the next task boundary.
|
|
6160
|
+
this._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames(), this._baseSystemPromptOptions.nativeSkillSelection !== undefined, preparationAction.payload.text);
|
|
6161
|
+
}
|
|
6102
6162
|
const basePromptSnapshot = this._baseSystemPrompt;
|
|
6103
6163
|
const result = await this._extensionRunner.emitBeforeAgentStart(preparationAction.payload.text, preparationAction.payload.images, basePromptSnapshot, this._baseSystemPromptOptions);
|
|
6104
6164
|
if (activeTurns().at(-1) !== preparationAction)
|
|
@@ -7759,7 +7819,11 @@ export class AgentSession {
|
|
|
7759
7819
|
const summaryRequests = requests[captureNativeCompactionRequests]();
|
|
7760
7820
|
let summaryFailure;
|
|
7761
7821
|
try {
|
|
7762
|
-
nativeCompaction = await compact(preparation, model, apiKey, headers, customInstructions, signal, thinkingLevel, summaryCall, summaryRequests
|
|
7822
|
+
nativeCompaction = await compact(preparation, model, apiKey, headers, customInstructions, signal, thinkingLevel, summaryCall, summaryRequests, options.capacity
|
|
7823
|
+
? (wrapper) => options.capacity.remainingSummaryTokens(new Set(pathEntries
|
|
7824
|
+
.slice(pathEntries.findIndex((entry) => entry.id === preparation.firstKeptEntryId))
|
|
7825
|
+
.map((entry) => entry.id)), wrapper)
|
|
7826
|
+
: undefined);
|
|
7763
7827
|
({ summary, firstKeptEntryId, tokensBefore, details, usage } = nativeCompaction);
|
|
7764
7828
|
}
|
|
7765
7829
|
catch (error) {
|
|
@@ -8320,9 +8384,9 @@ export class AgentSession {
|
|
|
8320
8384
|
}
|
|
8321
8385
|
}
|
|
8322
8386
|
catch (error) {
|
|
8323
|
-
//
|
|
8324
|
-
//
|
|
8325
|
-
|
|
8387
|
+
// Consume this exact automatic proposal after failure. New evidence can
|
|
8388
|
+
// request a new review; manual /refine remains independent.
|
|
8389
|
+
this._pendingAutoRefineReview = undefined;
|
|
8326
8390
|
this._lastAutoRefineReviewAt = Date.now();
|
|
8327
8391
|
if (error instanceof RefineSkippedError) {
|
|
8328
8392
|
// A skipped round is consumed like a reviewer decline, not retained for retry.
|
|
@@ -8362,7 +8426,78 @@ export class AgentSession {
|
|
|
8362
8426
|
throw new Error(`autoRefine.model thinkingLevel ${selection.thinkingLevel} is not supported by ${selection.provider}/${selection.modelId}`);
|
|
8363
8427
|
return { model: { ...model, cost: { ...model.cost } }, thinkingLevel: selection.thinkingLevel, explicit: true };
|
|
8364
8428
|
}
|
|
8429
|
+
async _autoRefineEvidence(harnessState) {
|
|
8430
|
+
const manager = this.sessionManager;
|
|
8431
|
+
const goalEvidence = ({ active, status, goalId, objective, tokenBudget, lastError }) => ({
|
|
8432
|
+
active,
|
|
8433
|
+
status,
|
|
8434
|
+
goalId,
|
|
8435
|
+
objective,
|
|
8436
|
+
tokenBudget,
|
|
8437
|
+
lastError,
|
|
8438
|
+
});
|
|
8439
|
+
const frontier = manager.supportsCapturedHistoryReads()
|
|
8440
|
+
? await manager.readBranchHistory(async (history) => {
|
|
8441
|
+
const goal = (await history.branchBootstrap()).goalState;
|
|
8442
|
+
const limits = this.settingsManager.getCanonicalContextLimits();
|
|
8443
|
+
let goalState = emptyGoalState();
|
|
8444
|
+
if (goal) {
|
|
8445
|
+
const hydrated = await history.hydrateEntry(goal.id, limits.maxSourceBytes);
|
|
8446
|
+
if (!hydrated ||
|
|
8447
|
+
hydrated.source.retention === "retained-import" ||
|
|
8448
|
+
hydrated.entry.type !== "custom" ||
|
|
8449
|
+
hydrated.entry.customType !== GOAL_STATE_CUSTOM_TYPE ||
|
|
8450
|
+
!isPersistedGoalState(hydrated.entry.data))
|
|
8451
|
+
throw new RefineSkippedError("Automatic refinement goal source is unavailable or ineligible");
|
|
8452
|
+
goalState = normalizeGoalState(hydrated.entry.data);
|
|
8453
|
+
}
|
|
8454
|
+
let id = history.source.leafId;
|
|
8455
|
+
const maxEntries = limits.maxMessages;
|
|
8456
|
+
for (let scanned = 0; scanned < maxEntries; scanned++) {
|
|
8457
|
+
const entry = id ? await history.get(id) : undefined;
|
|
8458
|
+
if (id && !entry)
|
|
8459
|
+
throw new RefineSkippedError("Automatic refinement task frontier is unavailable");
|
|
8460
|
+
const message = entry?.kind === "message" ? entry : undefined;
|
|
8461
|
+
if (message || !entry)
|
|
8462
|
+
return {
|
|
8463
|
+
sessionId: history.source.sessionId,
|
|
8464
|
+
sessionFile: history.source.sessionFile,
|
|
8465
|
+
message: message ? [message.id, message.revision] : undefined,
|
|
8466
|
+
goal: goalEvidence(goalState),
|
|
8467
|
+
};
|
|
8468
|
+
id = entry.parentId;
|
|
8469
|
+
}
|
|
8470
|
+
throw new RefineSkippedError("Automatic refinement task frontier exceeds the context read limit");
|
|
8471
|
+
})
|
|
8472
|
+
: (() => {
|
|
8473
|
+
const branch = manager.getBranch().slice().reverse();
|
|
8474
|
+
const message = branch.find((entry) => entry.type === "message");
|
|
8475
|
+
return {
|
|
8476
|
+
sessionId: manager.getSessionId(),
|
|
8477
|
+
sessionFile: manager.getSessionFile(),
|
|
8478
|
+
message: message ? [message.id, message.timestamp] : undefined,
|
|
8479
|
+
goal: goalEvidence(this._loadPersistedGoalState()),
|
|
8480
|
+
};
|
|
8481
|
+
})();
|
|
8482
|
+
return {
|
|
8483
|
+
...frontier,
|
|
8484
|
+
systemPrompt: this.agent.state.systemPrompt,
|
|
8485
|
+
model: JSON.stringify([this.model?.provider, this.model?.id, this.settingsManager.getAutoRefineModel()]),
|
|
8486
|
+
harnessEntries: Object.fromEntries(Object.entries(harnessState.entries).map(([kind, entries]) => [
|
|
8487
|
+
kind,
|
|
8488
|
+
Object.fromEntries(Object.entries(entries).map(([id, { version: _version, created_at: _created, updated_at: _updated, ...entry }]) => [id, entry])),
|
|
8489
|
+
])),
|
|
8490
|
+
};
|
|
8491
|
+
}
|
|
8365
8492
|
async _reviewAutoRefine(context, signal) {
|
|
8493
|
+
const harnessState = this._loadMergedHarnessState();
|
|
8494
|
+
const evidence = await this._autoRefineEvidence(harnessState);
|
|
8495
|
+
signal?.throwIfAborted();
|
|
8496
|
+
if (isDeepStrictEqual(evidence, this._lastAutoRefineEvidence))
|
|
8497
|
+
return { shouldRefine: false, rationale: "No new task evidence since the previous automatic review." };
|
|
8498
|
+
// Reserve before any inference wait. Equivalent running, declined or failed
|
|
8499
|
+
// automatic reviews do not buy another call; explicit /refine stays independent.
|
|
8500
|
+
this._lastAutoRefineEvidence = evidence;
|
|
8366
8501
|
if (this._autoRefineReviewer)
|
|
8367
8502
|
return this._autoRefineReviewer(context, signal);
|
|
8368
8503
|
const selected = this._resolveRefinementModel();
|
|
@@ -8370,7 +8505,6 @@ export class AgentSession {
|
|
|
8370
8505
|
return { shouldRefine: false, rationale: "No model selected." };
|
|
8371
8506
|
const { model, thinkingLevel, explicit } = selected;
|
|
8372
8507
|
const messages = structuredClone(this.agent.state.messages);
|
|
8373
|
-
const harnessState = this._loadMergedHarnessState();
|
|
8374
8508
|
const reviewContext = { ...context };
|
|
8375
8509
|
const requests = this.requests[captureNativeReviewerRequests]();
|
|
8376
8510
|
try {
|
|
@@ -8382,10 +8516,10 @@ export class AgentSession {
|
|
|
8382
8516
|
await requests.dispose();
|
|
8383
8517
|
}
|
|
8384
8518
|
}
|
|
8385
|
-
/**
|
|
8519
|
+
/** Merge existing session/global memory with the selected project's workspace memory. */
|
|
8386
8520
|
_loadMergedHarnessState() {
|
|
8387
8521
|
const localHarnessStateDir = this._localHarnessStateDir();
|
|
8388
|
-
return mergeHarnessStates(loadHarnessState(getGlobalHarnessStateDir(), "global"), localHarnessStateDir ? loadHarnessState(localHarnessStateDir, "local") : undefined);
|
|
8522
|
+
return mergeHarnessStates(loadHarnessState(getGlobalHarnessStateDir(), "global"), localHarnessStateDir ? loadHarnessState(localHarnessStateDir, "local") : undefined, loadHarnessState(getWorkspaceHarnessStateDir(this._cwd), "workspace"));
|
|
8389
8523
|
}
|
|
8390
8524
|
async _loadRefinementHistory() {
|
|
8391
8525
|
const limits = {
|
|
@@ -8843,7 +8977,21 @@ export class AgentSession {
|
|
|
8843
8977
|
}
|
|
8844
8978
|
if (!this._isCompactionOwnerCurrent(owner))
|
|
8845
8979
|
return false;
|
|
8846
|
-
|
|
8980
|
+
let assistantIsFromBeforeCompaction = compactionTimestamp !== undefined && assistantMessage.timestamp <= compactionTimestamp;
|
|
8981
|
+
const assistantEntryId = this._findAssistantEntryIdForMessage(assistantMessage);
|
|
8982
|
+
if (assistantEntryId && owner.manager.supportsCapturedHistoryReads()) {
|
|
8983
|
+
const ordered = await owner.manager.readBranchHistory(async (history) => {
|
|
8984
|
+
const assistant = await history.get(assistantEntryId);
|
|
8985
|
+
const boundary = (await history.branchBootstrap()).latestCompaction;
|
|
8986
|
+
return assistant && boundary ? assistant.sequence <= boundary.sequence : undefined;
|
|
8987
|
+
});
|
|
8988
|
+
if (!this._isCompactionOwnerCurrent(owner))
|
|
8989
|
+
return false;
|
|
8990
|
+
// Provider messages are timestamped before request preparation, which may
|
|
8991
|
+
// commit an epoch. Canonical append order, not that start time, owns staleness.
|
|
8992
|
+
if (ordered !== undefined)
|
|
8993
|
+
assistantIsFromBeforeCompaction = ordered;
|
|
8994
|
+
}
|
|
8847
8995
|
// Case 1: Overflow - takes priority over a pending model request so the error
|
|
8848
8996
|
// strip + retry still happen; the compaction it runs consumes the request.
|
|
8849
8997
|
if (!assistantIsFromBeforeCompaction &&
|
|
@@ -8935,7 +9083,7 @@ export class AgentSession {
|
|
|
8935
9083
|
this._emit({ type: "message_start", message: outcomeMessage });
|
|
8936
9084
|
this._emit({ type: "message_end", message: outcomeMessage });
|
|
8937
9085
|
}
|
|
8938
|
-
async _runAutoCompaction(reason, willRetry, capturedOwner, resumeInPlace = false) {
|
|
9086
|
+
async _runAutoCompaction(reason, willRetry, capturedOwner, resumeInPlace = false, capacity) {
|
|
8939
9087
|
const checkpoint = this._pendingCheckpoint;
|
|
8940
9088
|
const pending = this._pendingRequestedCompaction;
|
|
8941
9089
|
const owner = checkpoint?.owner ?? pending?.owner ?? capturedOwner ?? this._captureCompactionOwner();
|
|
@@ -9018,6 +9166,7 @@ export class AgentSession {
|
|
|
9018
9166
|
signal: abort.signal,
|
|
9019
9167
|
// Only confirmed public-budget recovery resumes within the same invocation.
|
|
9020
9168
|
budgetPressure: resumeInPlace,
|
|
9169
|
+
capacity,
|
|
9021
9170
|
});
|
|
9022
9171
|
const result = committed.result;
|
|
9023
9172
|
// Release this captured source before arming success. A later release failure still carries the ACK.
|
|
@@ -9613,7 +9762,12 @@ export class AgentSession {
|
|
|
9613
9762
|
producer?.skillOwner?.writer.assertCurrent();
|
|
9614
9763
|
if (this.sessionManager !== manager)
|
|
9615
9764
|
throw new Error("Native recovery source changed");
|
|
9616
|
-
|
|
9765
|
+
const cursorSource = JSON.stringify([manager.getSessionId(), manager.getSessionFile()]);
|
|
9766
|
+
if (this._nativeRecoveryCursorSource !== cursorSource) {
|
|
9767
|
+
this._nativeRecoveryCursors.clear();
|
|
9768
|
+
this._nativeRecoveryCursorSource = cursorSource;
|
|
9769
|
+
}
|
|
9770
|
+
return await manager.readBranchHistory((history) => recoverCapturedHistory(history.branchContext, request, { ...DEFAULT_NATIVE_RECOVERY_LIMITS, maxBytes: responseBytes }, signal, this._nativeRecoveryCursors));
|
|
9617
9771
|
}
|
|
9618
9772
|
catch (error) {
|
|
9619
9773
|
signal?.throwIfAborted();
|
|
@@ -9762,6 +9916,7 @@ export class AgentSession {
|
|
|
9762
9916
|
BASE_CONTEXT_RLM_DEPTH: String(this._rlmDepth),
|
|
9763
9917
|
BASE_CONTEXT_RLM_MAX_DEPTH: String(this._rlmMaxDepth),
|
|
9764
9918
|
BASE_CONTEXT_GLOBAL_HARNESS_STATE_DIR: getGlobalHarnessStateDir(),
|
|
9919
|
+
BASE_CONTEXT_WORKSPACE_HARNESS_STATE_DIR: getWorkspaceHarnessStateDir(this._cwd),
|
|
9765
9920
|
};
|
|
9766
9921
|
const rlmSessionDir = this._ensureRlmSessionDir();
|
|
9767
9922
|
if (rlmSessionDir) {
|
|
@@ -9854,15 +10009,13 @@ export class AgentSession {
|
|
|
9854
10009
|
if (message?.role !== "assistant")
|
|
9855
10010
|
return;
|
|
9856
10011
|
if (this.sessionManager.isPersisted()) {
|
|
9857
|
-
const
|
|
9858
|
-
if (!
|
|
9859
|
-
acknowledged.sessionId !== this.sessionId ||
|
|
9860
|
-
acknowledged.sessionFile !== this.sessionFile)
|
|
10012
|
+
const entryId = this._findAssistantEntryIdForMessage(message);
|
|
10013
|
+
if (!entryId)
|
|
9861
10014
|
throw new Error("Cannot identify the acknowledged assistant response removed by retry control");
|
|
9862
10015
|
if (this._contextOmissions?.sessionId !== this.sessionId ||
|
|
9863
10016
|
this._contextOmissions?.sessionFile !== this.sessionFile)
|
|
9864
10017
|
this._contextOmissions = { sessionId: this.sessionId, sessionFile: this.sessionFile, ids: new Set() };
|
|
9865
|
-
this._contextOmissions.ids.add(
|
|
10018
|
+
this._contextOmissions.ids.add(entryId);
|
|
9866
10019
|
}
|
|
9867
10020
|
this.agent.state.messages = messages.slice(0, -1);
|
|
9868
10021
|
}
|