chainlesschain 0.166.136 → 0.166.139
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/README.md +43 -1
- package/package.json +1 -1
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/agent.js +12 -0
- package/src/data/changelog.json +39 -0
- package/src/gateways/ws/ws-server.js +16 -0
- package/src/harness/prompt-compressor.js +57 -0
- package/src/harness/provider-backed-compaction.js +6 -0
- package/src/lib/coding-change-review-context.js +51 -0
- package/src/lib/coding-task-guidance.js +3 -1
- package/src/lib/context-memory-kernel/jsonl-session-context-port.js +19 -10
- package/src/lib/context-memory-kernel/live-compaction.js +114 -6
- package/src/lib/context-memory-kernel/message-adapter.js +17 -13
- package/src/lib/context-memory-kernel/task-binding.js +41 -0
- package/src/lib/context-memory-kernel/task-worklog-port.js +26 -3
- package/src/lib/evolution/evidence-json-text.js +324 -14
- package/src/lib/evolution/evolution-evidence-projector.js +67 -1
- package/src/lib/read-file-loop-guard.js +146 -13
- package/src/lib/read-file-page.js +4 -1
- package/src/lib/source-read-recovery.js +89 -0
- package/src/lib/tool-result-preview.js +18 -5
- package/src/repl/agent-repl.js +2 -0
- package/src/runtime/agent-core.js +103 -40
- package/src/runtime/headless-runner.js +1 -0
- package/src/runtime/headless-stream.js +82 -10
- package/src/runtime/message-roles.js +28 -0
- package/src/runtime/policies/agent-policy.js +1 -0
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
projectMessagesWithTaskBinding,
|
|
3
|
+
getTaskCompactionBindings,
|
|
4
|
+
} from "./message-roles.js";
|
|
2
5
|
import {
|
|
3
6
|
providerFetch,
|
|
4
7
|
requireUnscopedToolExecution,
|
|
@@ -74,7 +77,12 @@ import {
|
|
|
74
77
|
CODING_TASK_QUALITY_GUIDANCE,
|
|
75
78
|
CODING_CHANGE_REVIEW_PROMPT,
|
|
76
79
|
} from "../lib/coding-task-guidance.js";
|
|
77
|
-
import {
|
|
80
|
+
import {
|
|
81
|
+
CodingChangeReviewContext,
|
|
82
|
+
changeReviewBudgetNotice,
|
|
83
|
+
changeReviewBudgetInsufficientError,
|
|
84
|
+
canReserveChangeReview,
|
|
85
|
+
} from "../lib/coding-change-review-context.js";
|
|
78
86
|
import { RemoteReadLoopGuard } from "../lib/remote-read-loop-guard.js";
|
|
79
87
|
import {
|
|
80
88
|
isPrActionRequest,
|
|
@@ -12375,7 +12383,10 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
12375
12383
|
),
|
|
12376
12384
|
{
|
|
12377
12385
|
signal,
|
|
12378
|
-
retries:
|
|
12386
|
+
retries:
|
|
12387
|
+
options.workflowEffectId || options.disableTransportRetry === true
|
|
12388
|
+
? 0
|
|
12389
|
+
: undefined,
|
|
12379
12390
|
strictRetryObserver: options.strictUsageTelemetry === true,
|
|
12380
12391
|
...(typeof options.onStreamRetry === "function"
|
|
12381
12392
|
? {
|
|
@@ -12527,7 +12538,10 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
12527
12538
|
),
|
|
12528
12539
|
{
|
|
12529
12540
|
signal,
|
|
12530
|
-
retries:
|
|
12541
|
+
retries:
|
|
12542
|
+
options.workflowEffectId || options.disableTransportRetry === true
|
|
12543
|
+
? 0
|
|
12544
|
+
: undefined,
|
|
12531
12545
|
strictRetryObserver: options.strictUsageTelemetry === true,
|
|
12532
12546
|
...(typeof options.onStreamRetry === "function"
|
|
12533
12547
|
? {
|
|
@@ -12655,7 +12669,10 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
12655
12669
|
),
|
|
12656
12670
|
{
|
|
12657
12671
|
signal,
|
|
12658
|
-
retries:
|
|
12672
|
+
retries:
|
|
12673
|
+
options.workflowEffectId || options.disableTransportRetry === true
|
|
12674
|
+
? 0
|
|
12675
|
+
: undefined,
|
|
12659
12676
|
strictRetryObserver: options.strictUsageTelemetry === true,
|
|
12660
12677
|
...(typeof options.onStreamRetry === "function"
|
|
12661
12678
|
? {
|
|
@@ -12720,7 +12737,10 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
12720
12737
|
),
|
|
12721
12738
|
{
|
|
12722
12739
|
signal,
|
|
12723
|
-
retries:
|
|
12740
|
+
retries:
|
|
12741
|
+
options.workflowEffectId || options.disableTransportRetry === true
|
|
12742
|
+
? 0
|
|
12743
|
+
: undefined,
|
|
12724
12744
|
strictRetryObserver: options.strictUsageTelemetry === true,
|
|
12725
12745
|
...(typeof options.onStreamRetry === "function"
|
|
12726
12746
|
? {
|
|
@@ -12768,7 +12788,10 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
12768
12788
|
),
|
|
12769
12789
|
{
|
|
12770
12790
|
signal,
|
|
12771
|
-
retries:
|
|
12791
|
+
retries:
|
|
12792
|
+
options.workflowEffectId || options.disableTransportRetry === true
|
|
12793
|
+
? 0
|
|
12794
|
+
: undefined,
|
|
12772
12795
|
strictRetryObserver: options.strictUsageTelemetry === true,
|
|
12773
12796
|
...(typeof options.onStreamRetry === "function"
|
|
12774
12797
|
? {
|
|
@@ -14607,6 +14630,9 @@ async function _getAutoCompactor(options) {
|
|
|
14607
14630
|
onToken: undefined,
|
|
14608
14631
|
onStall: undefined,
|
|
14609
14632
|
onStreamRetry: undefined,
|
|
14633
|
+
// Summary spend is settled once at the compactor boundary.
|
|
14634
|
+
// A second transport attempt would bypass that accounting.
|
|
14635
|
+
disableTransportRetry: true,
|
|
14610
14636
|
providerRequestId:
|
|
14611
14637
|
requestBinding?.providerRequestId || undefined,
|
|
14612
14638
|
maxOutputTokens,
|
|
@@ -14642,6 +14668,7 @@ async function _getAutoCompactor(options) {
|
|
|
14642
14668
|
return compactLiveMessagesCanonical(messages, {
|
|
14643
14669
|
compressor: compatibilitySummarizer,
|
|
14644
14670
|
compressOptions,
|
|
14671
|
+
requiredUserBindings: compressOptions.requiredUserBindings,
|
|
14645
14672
|
sessionId: options.sessionId,
|
|
14646
14673
|
operationId: `auto-${randomUUID()}`,
|
|
14647
14674
|
provider: options.provider || "ollama",
|
|
@@ -14979,6 +15006,11 @@ export async function* agentLoop(messages, options) {
|
|
|
14979
15006
|
).length === 1,
|
|
14980
15007
|
}
|
|
14981
15008
|
: null;
|
|
15009
|
+
const taskCompactionBindings = getTaskCompactionBindings(
|
|
15010
|
+
options.projectProviderMessages,
|
|
15011
|
+
messages,
|
|
15012
|
+
currentUserTaskBinding,
|
|
15013
|
+
);
|
|
14982
15014
|
if (options.serviceTier != null) {
|
|
14983
15015
|
resolveModelServiceTier(
|
|
14984
15016
|
resolveModelCapabilityProfile(options),
|
|
@@ -15581,6 +15613,37 @@ export async function* agentLoop(messages, options) {
|
|
|
15581
15613
|
toolContext.readFileLoopGuard = readFileLoopGuard;
|
|
15582
15614
|
let lastTaskProgressIntervention = null;
|
|
15583
15615
|
|
|
15616
|
+
// Both an author completion and the reserved review window enter the same
|
|
15617
|
+
// phase. Neither path manufactures an author response or adds request budget.
|
|
15618
|
+
const beginChangeReview = (draft = null) => {
|
|
15619
|
+
throwIfAborted(signal);
|
|
15620
|
+
if (budget.remaining() < 2)
|
|
15621
|
+
throw changeReviewBudgetInsufficientError(budget.remaining());
|
|
15622
|
+
if (independentReviewSetupError) throw independentReviewSetupError;
|
|
15623
|
+
changeReviewState.requested = true;
|
|
15624
|
+
const reviewPrompt = markRuntimeOnlySessionMessage({
|
|
15625
|
+
role: "user",
|
|
15626
|
+
content: CODING_CHANGE_REVIEW_PROMPT,
|
|
15627
|
+
});
|
|
15628
|
+
if (draft)
|
|
15629
|
+
appendMessages(
|
|
15630
|
+
markRuntimeOnlySessionMessage({
|
|
15631
|
+
role: "assistant",
|
|
15632
|
+
content: draft.content || "",
|
|
15633
|
+
}),
|
|
15634
|
+
);
|
|
15635
|
+
appendMessages(reviewPrompt);
|
|
15636
|
+
if (independentReviewContext) {
|
|
15637
|
+
independentReviewContext.activate(reviewPrompt);
|
|
15638
|
+
changeReviewState.independentReviewPending = true;
|
|
15639
|
+
readFileLoopGuard = new ReadFileLoopGuard();
|
|
15640
|
+
remoteReadLoopGuard = new RemoteReadLoopGuard();
|
|
15641
|
+
taskProgressTracker = new TaskProgressTracker();
|
|
15642
|
+
toolContext.readFileLoopGuard = readFileLoopGuard;
|
|
15643
|
+
lastTaskProgressIntervention = null;
|
|
15644
|
+
}
|
|
15645
|
+
};
|
|
15646
|
+
|
|
15584
15647
|
while (budget.hasRemaining()) {
|
|
15585
15648
|
if (loopMcpCatalog) {
|
|
15586
15649
|
currentMcpSnapshot = readMcpToolCatalog(loopMcpCatalog);
|
|
@@ -15627,6 +15690,24 @@ export async function* agentLoop(messages, options) {
|
|
|
15627
15690
|
return;
|
|
15628
15691
|
}
|
|
15629
15692
|
readFileLoopGuard.finishBatch();
|
|
15693
|
+
if (
|
|
15694
|
+
canReserveChangeReview({
|
|
15695
|
+
enabled: options.reviewChanges,
|
|
15696
|
+
changed: hasFileContentChanges,
|
|
15697
|
+
requested: changeReviewState.requested,
|
|
15698
|
+
usageKnown: changeReviewState.usageKnown,
|
|
15699
|
+
pendingMutations: pendingSubtreeMutations.size,
|
|
15700
|
+
pendingChildren: backgroundSubAgents.size,
|
|
15701
|
+
remaining: budget.remaining(),
|
|
15702
|
+
limit: budget.limit,
|
|
15703
|
+
})
|
|
15704
|
+
) {
|
|
15705
|
+
beginChangeReview();
|
|
15706
|
+
yield {
|
|
15707
|
+
type: "iteration-warning",
|
|
15708
|
+
message: "Reviewing changed files against the task before finishing.",
|
|
15709
|
+
};
|
|
15710
|
+
}
|
|
15630
15711
|
if (remoteReadLoopGuard.stalled && !remoteReadLoopGuard.synthesisRequired) {
|
|
15631
15712
|
await _awaitBackgroundUsageSettlement(
|
|
15632
15713
|
backgroundSubAgents,
|
|
@@ -15901,6 +15982,7 @@ export async function* agentLoop(messages, options) {
|
|
|
15901
15982
|
}
|
|
15902
15983
|
: await compactor.compress(workingMessages, {
|
|
15903
15984
|
preserveToolPairs: true,
|
|
15985
|
+
requiredUserBindings: taskCompactionBindings,
|
|
15904
15986
|
...pinOpts,
|
|
15905
15987
|
});
|
|
15906
15988
|
if (
|
|
@@ -15936,6 +16018,9 @@ export async function* agentLoop(messages, options) {
|
|
|
15936
16018
|
reason:
|
|
15937
16019
|
stats.summaryUsageUnknownReason ||
|
|
15938
16020
|
"provider_transport_outcome_unknown",
|
|
16021
|
+
...(stats.summaryProviderError
|
|
16022
|
+
? { providerError: stats.summaryProviderError }
|
|
16023
|
+
: {}),
|
|
15939
16024
|
};
|
|
15940
16025
|
}
|
|
15941
16026
|
}
|
|
@@ -16042,6 +16127,9 @@ export async function* agentLoop(messages, options) {
|
|
|
16042
16127
|
? compactionUsageCall.model
|
|
16043
16128
|
: stats.summaryModel || options.model || null,
|
|
16044
16129
|
reason: unknownReason,
|
|
16130
|
+
...(stats.summaryProviderError
|
|
16131
|
+
? { providerError: stats.summaryProviderError }
|
|
16132
|
+
: {}),
|
|
16045
16133
|
code:
|
|
16046
16134
|
unknownReason === "provider_usage_not_reported"
|
|
16047
16135
|
? "provider_usage_missing"
|
|
@@ -16551,7 +16639,10 @@ export async function* agentLoop(messages, options) {
|
|
|
16551
16639
|
`Execution budget: this request plus ${furtherRequests} further model requests. ` +
|
|
16552
16640
|
"For requested changes, reserve requests for implementation, focused validation, and repair or an accurate unfinished-work report. " +
|
|
16553
16641
|
"Reading or an existing passing baseline does not deliver requested changes. " +
|
|
16554
|
-
"For research or monitoring, use the remaining requests for evidence and the requested answer; do not create files just to show activity."
|
|
16642
|
+
"For research or monitoring, use the remaining requests for evidence and the requested answer; do not create files just to show activity." +
|
|
16643
|
+
(options.reviewChanges === true
|
|
16644
|
+
? changeReviewBudgetNotice(budget, changeReviewState.requested)
|
|
16645
|
+
: ""),
|
|
16555
16646
|
},
|
|
16556
16647
|
];
|
|
16557
16648
|
contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
|
|
@@ -16954,7 +17045,7 @@ export async function* agentLoop(messages, options) {
|
|
|
16954
17045
|
}
|
|
16955
17046
|
throwIfAborted(signal);
|
|
16956
17047
|
if (
|
|
16957
|
-
|
|
17048
|
+
options.reviewChanges === true &&
|
|
16958
17049
|
changeReviewState.usageKnown === false
|
|
16959
17050
|
) {
|
|
16960
17051
|
const error = new Error(
|
|
@@ -17213,42 +17304,14 @@ export async function* agentLoop(messages, options) {
|
|
|
17213
17304
|
};
|
|
17214
17305
|
return;
|
|
17215
17306
|
}
|
|
17216
|
-
//
|
|
17217
|
-
// Never emit a provisional completion or turn this self-check into an
|
|
17218
|
-
// acceptance verdict. Failed/deferred writes do not arm the review.
|
|
17307
|
+
// Author completion is provisional until the independent review phase.
|
|
17219
17308
|
if (
|
|
17220
17309
|
options.reviewChanges === true &&
|
|
17221
17310
|
hasFileContentChanges &&
|
|
17222
17311
|
!changeReviewState.requested &&
|
|
17223
|
-
changeReviewState.usageKnown !== false
|
|
17224
|
-
budget.hasRemaining()
|
|
17312
|
+
changeReviewState.usageKnown !== false
|
|
17225
17313
|
) {
|
|
17226
|
-
|
|
17227
|
-
if (independentReviewSetupError) throw independentReviewSetupError;
|
|
17228
|
-
changeReviewState.requested = true;
|
|
17229
|
-
const reviewPrompt = markRuntimeOnlySessionMessage({
|
|
17230
|
-
role: "user",
|
|
17231
|
-
content: CODING_CHANGE_REVIEW_PROMPT,
|
|
17232
|
-
});
|
|
17233
|
-
appendMessages(
|
|
17234
|
-
markRuntimeOnlySessionMessage({
|
|
17235
|
-
role: "assistant",
|
|
17236
|
-
content: msg.content || "",
|
|
17237
|
-
}),
|
|
17238
|
-
reviewPrompt,
|
|
17239
|
-
);
|
|
17240
|
-
if (independentReviewContext) {
|
|
17241
|
-
independentReviewContext.activate(reviewPrompt);
|
|
17242
|
-
changeReviewState.independentReviewPending = true;
|
|
17243
|
-
// These are phase-local discovery hints, not permission or spend
|
|
17244
|
-
// authorities. Fresh inspection must not inherit author assertions,
|
|
17245
|
-
// old visible file pages, or a pause caused by author exploration.
|
|
17246
|
-
readFileLoopGuard = new ReadFileLoopGuard();
|
|
17247
|
-
remoteReadLoopGuard = new RemoteReadLoopGuard();
|
|
17248
|
-
taskProgressTracker = new TaskProgressTracker();
|
|
17249
|
-
toolContext.readFileLoopGuard = readFileLoopGuard;
|
|
17250
|
-
lastTaskProgressIntervention = null;
|
|
17251
|
-
}
|
|
17314
|
+
beginChangeReview(msg);
|
|
17252
17315
|
yield {
|
|
17253
17316
|
type: "iteration-warning",
|
|
17254
17317
|
message: "Reviewing changed files against the task before finishing.",
|
|
@@ -2942,6 +2942,7 @@ async function runAgentHeadlessInWorkspace(
|
|
|
2942
2942
|
});
|
|
2943
2943
|
};
|
|
2944
2944
|
const loopOptions = {
|
|
2945
|
+
contextMemoryModelWindowTokens: options.contextMemoryModelWindowTokens,
|
|
2945
2946
|
...(evolutionIngress === null ? {} : { evolutionIngress }),
|
|
2946
2947
|
model,
|
|
2947
2948
|
provider,
|
|
@@ -964,6 +964,7 @@ async function runTurn(
|
|
|
964
964
|
let endReason = "complete";
|
|
965
965
|
let stopForCost = false;
|
|
966
966
|
let stopForCompactionUsageUnknown = false;
|
|
967
|
+
let compactionUsageUnknown = null;
|
|
967
968
|
let responseCompleted = false;
|
|
968
969
|
// P0-2: the side-effect op currently in flight (at most one — the loop runs
|
|
969
970
|
// tools serially). Non-null only between a dangerous tool's tool-executing
|
|
@@ -1223,6 +1224,7 @@ async function runTurn(
|
|
|
1223
1224
|
}
|
|
1224
1225
|
break;
|
|
1225
1226
|
case "compaction-usage-unknown":
|
|
1227
|
+
compactionUsageUnknown = compactionUsageUnknownDiagnostic(event);
|
|
1226
1228
|
if (event.ledgerPersisted !== true) {
|
|
1227
1229
|
persistUsageEvent?.({
|
|
1228
1230
|
...event,
|
|
@@ -1282,7 +1284,52 @@ async function runTurn(
|
|
|
1282
1284
|
) {
|
|
1283
1285
|
sideEffects.persist();
|
|
1284
1286
|
}
|
|
1285
|
-
return { finalText, endReason, usage, toolCalls };
|
|
1287
|
+
return { finalText, endReason, usage, toolCalls, compactionUsageUnknown };
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
function compactionUsageUnknownDiagnostic(event) {
|
|
1291
|
+
const reason =
|
|
1292
|
+
event?.reason === "provider_usage_not_reported"
|
|
1293
|
+
? "provider_usage_not_reported"
|
|
1294
|
+
: "provider_transport_outcome_unknown";
|
|
1295
|
+
const providerError = event?.providerError;
|
|
1296
|
+
const providerHints = {
|
|
1297
|
+
authentication:
|
|
1298
|
+
"Provider authentication failed; check the API credentials.",
|
|
1299
|
+
access_denied: "Provider access was denied; check model permissions.",
|
|
1300
|
+
rate_limit: "The provider rate limit was reached; wait before resuming.",
|
|
1301
|
+
server_error:
|
|
1302
|
+
"The provider returned a server error; check service availability.",
|
|
1303
|
+
http_error:
|
|
1304
|
+
"The provider rejected the compaction request; check the model endpoint.",
|
|
1305
|
+
network: "The model connection failed; check network and proxy settings.",
|
|
1306
|
+
invalid_response:
|
|
1307
|
+
"The provider returned an invalid response; check API compatibility.",
|
|
1308
|
+
unknown: "The provider request failed.",
|
|
1309
|
+
};
|
|
1310
|
+
const category = providerError?.category;
|
|
1311
|
+
const projected = Object.hasOwn(providerHints, category || "")
|
|
1312
|
+
? {
|
|
1313
|
+
category,
|
|
1314
|
+
...(Number.isInteger(providerError.httpStatus) &&
|
|
1315
|
+
providerError.httpStatus >= 400 &&
|
|
1316
|
+
providerError.httpStatus <= 599
|
|
1317
|
+
? { httpStatus: providerError.httpStatus }
|
|
1318
|
+
: {}),
|
|
1319
|
+
}
|
|
1320
|
+
: null;
|
|
1321
|
+
return {
|
|
1322
|
+
code: "CC_COMPACTION_USAGE_UNKNOWN",
|
|
1323
|
+
usage_unknown_reason: reason,
|
|
1324
|
+
...(projected ? { provider_error: projected } : {}),
|
|
1325
|
+
error:
|
|
1326
|
+
(reason === "provider_usage_not_reported"
|
|
1327
|
+
? "Compaction provider did not report valid token usage"
|
|
1328
|
+
: "Compaction request failed before provider usage could be confirmed") +
|
|
1329
|
+
"; the session stopped without retrying the request. " +
|
|
1330
|
+
(projected ? providerHints[category] + " " : "") +
|
|
1331
|
+
"Review the saved session and provider usage, check the model connection, then resume explicitly.",
|
|
1332
|
+
};
|
|
1286
1333
|
}
|
|
1287
1334
|
|
|
1288
1335
|
/**
|
|
@@ -3821,6 +3868,31 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
3821
3868
|
{ code: "CC_SESSION_TOOL_ROUND_SETTLEMENT_HEAD_UNKNOWN" },
|
|
3822
3869
|
);
|
|
3823
3870
|
}
|
|
3871
|
+
// Only a new, acknowledged tool_round has item positions to associate
|
|
3872
|
+
// with live IDE output. A no-op settlement returns an existing head only.
|
|
3873
|
+
if (appended.event?.type === "tool_round") {
|
|
3874
|
+
const items = appended.event.data.messages.map((message, itemIndex) => ({
|
|
3875
|
+
itemIndex,
|
|
3876
|
+
role: message.role,
|
|
3877
|
+
toolCallId:
|
|
3878
|
+
message.role === "assistant"
|
|
3879
|
+
? message.tool_calls[0].id
|
|
3880
|
+
: message.tool_call_id,
|
|
3881
|
+
}));
|
|
3882
|
+
for (let offset = 0; offset < items.length; offset += 100) {
|
|
3883
|
+
emit({
|
|
3884
|
+
type: "system",
|
|
3885
|
+
subtype: "tool_round_persisted",
|
|
3886
|
+
session_id: sessionId,
|
|
3887
|
+
transcript_refs: {
|
|
3888
|
+
schema: "chainlesschain.session-tool-round-references/v1",
|
|
3889
|
+
sessionId,
|
|
3890
|
+
eventId: appended.hash,
|
|
3891
|
+
items: items.slice(offset, offset + 100),
|
|
3892
|
+
},
|
|
3893
|
+
});
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3824
3896
|
return appended;
|
|
3825
3897
|
};
|
|
3826
3898
|
const settleToolRoundsForHost = (phase, clientMessageId = null) => {
|
|
@@ -3873,6 +3945,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
3873
3945
|
return settleToolRoundsForHost(phase);
|
|
3874
3946
|
};
|
|
3875
3947
|
const loopOptionsBase = {
|
|
3948
|
+
contextMemoryModelWindowTokens: options.contextMemoryModelWindowTokens,
|
|
3876
3949
|
...(evolutionIngress === null ? {} : { evolutionIngress }),
|
|
3877
3950
|
reviewChanges: options.reviewChanges === true,
|
|
3878
3951
|
model,
|
|
@@ -4851,9 +4924,11 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
4851
4924
|
type: "result",
|
|
4852
4925
|
subtype: "error_compaction_usage_unknown",
|
|
4853
4926
|
is_error: true,
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4927
|
+
...compactionUsageUnknownDiagnostic(
|
|
4928
|
+
compatibilityResult?.usageUnknownEvent || {
|
|
4929
|
+
reason: "provider_transport_outcome_unknown",
|
|
4930
|
+
},
|
|
4931
|
+
),
|
|
4857
4932
|
session_id: sessionId,
|
|
4858
4933
|
});
|
|
4859
4934
|
sawError = true;
|
|
@@ -4905,9 +4980,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
4905
4980
|
type: "result",
|
|
4906
4981
|
subtype: "error_compaction_usage_unknown",
|
|
4907
4982
|
is_error: true,
|
|
4908
|
-
|
|
4909
|
-
error:
|
|
4910
|
-
"Compaction provider usage is unknown; the paid compaction is not retried",
|
|
4983
|
+
...compactionUsageUnknownDiagnostic(usageUnknownEvent),
|
|
4911
4984
|
session_id: sessionId,
|
|
4912
4985
|
...(costBudget ? { budget_state: "unverifiable" } : {}),
|
|
4913
4986
|
});
|
|
@@ -5908,9 +5981,8 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5908
5981
|
type: "result",
|
|
5909
5982
|
subtype: "error_compaction_usage_unknown",
|
|
5910
5983
|
is_error: true,
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
"Compaction provider usage is unknown; the paid compaction is not retried",
|
|
5984
|
+
...(outcome.compactionUsageUnknown ||
|
|
5985
|
+
compactionUsageUnknownDiagnostic(null)),
|
|
5914
5986
|
session_id: sessionId,
|
|
5915
5987
|
turn: turns,
|
|
5916
5988
|
usage: outcome.usage,
|
|
@@ -166,6 +166,34 @@ export function createResumeRoleProjection(messages) {
|
|
|
166
166
|
return projection;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
/** Capture the original user sources needed by an owned resume merge. */
|
|
170
|
+
export function getTaskCompactionBindings(projection, input, taskBinding) {
|
|
171
|
+
if (!taskBinding) return [];
|
|
172
|
+
const owned = RESUME_ROLE_PROJECTIONS.get(projection);
|
|
173
|
+
const capture = (binding) => ({
|
|
174
|
+
...binding,
|
|
175
|
+
matchCount: input.filter((message) =>
|
|
176
|
+
isDeepStrictEqual(message, binding.message),
|
|
177
|
+
).length,
|
|
178
|
+
});
|
|
179
|
+
if (!owned) return [capture(taskBinding)];
|
|
180
|
+
const sourceIndex = input.indexOf(taskBinding.original);
|
|
181
|
+
const group = owned(input).sources.find((indices) =>
|
|
182
|
+
indices.includes(sourceIndex),
|
|
183
|
+
);
|
|
184
|
+
return (group || [sourceIndex]).map((index) => {
|
|
185
|
+
if (index === sourceIndex) return capture(taskBinding);
|
|
186
|
+
const original = input[index];
|
|
187
|
+
return capture({
|
|
188
|
+
original,
|
|
189
|
+
message: JSON.parse(canonicalJson(original)),
|
|
190
|
+
allowContentRelocation:
|
|
191
|
+
input.filter((message) => isDeepStrictEqual(message, original))
|
|
192
|
+
.length === 1,
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
169
197
|
/**
|
|
170
198
|
* Preserve a bound task through this module's exact, captured resume merges.
|
|
171
199
|
* Arbitrary callbacks, wrappers and forged properties never receive lineage.
|
|
@@ -23,6 +23,7 @@ export function resolveAgentPolicy({
|
|
|
23
23
|
|
|
24
24
|
return {
|
|
25
25
|
model: connection.model || defaults.model || "qwen2:7b",
|
|
26
|
+
contextMemoryModelWindowTokens: overrides.contextMemoryModelWindowTokens,
|
|
26
27
|
visionModel: overrides.visionModel,
|
|
27
28
|
provider: connection.provider,
|
|
28
29
|
baseUrl: connection.baseUrl,
|