@opengeni/worker-bundle 2.0.1 → 2.0.3-canary.36199476632001
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/activities/agent-turn/agent-build.d.ts +2 -0
- package/dist/activities/agent-turn/code-search.d.ts +60 -0
- package/dist/activities/agent-turn/codex-capacity.d.ts +13 -0
- package/dist/activities/agent-turn/errors.d.ts +12 -1
- package/dist/activities/agent-turn/failure-settlement.d.ts +1 -1
- package/dist/activities/agent-turn/governance-model.d.ts +2 -0
- package/dist/activities/agent-turn/history.d.ts +2 -0
- package/dist/activities/agent-turn/media-artifacts.d.ts +5 -3
- package/dist/activities/agent-turn/session-title.d.ts +32 -2
- package/dist/activities/agent-turn/tool-environment.d.ts +4 -0
- package/dist/activities/context-compaction.d.ts +10 -2
- package/dist/activities/knowledge-indexing.d.ts +19 -0
- package/dist/activities/retained-screenshots.d.ts +7 -2
- package/dist/activities/sandbox-lease.d.ts +3 -4
- package/dist/{activities-control-QA6OLRQY.js → activities-control-I72CRMAE.js} +283 -35
- package/dist/activities-control-I72CRMAE.js.map +1 -0
- package/dist/{activities-turn-YVVKCGAK.js → activities-turn-CSDKK4N3.js} +531 -77
- package/dist/activities-turn-CSDKK4N3.js.map +1 -0
- package/dist/artifact-outbox-entry.js +3 -0
- package/dist/artifact-outbox-entry.js.map +1 -1
- package/dist/{chunk-M3NVMF2V.js → chunk-7M6G2SCF.js} +172 -17
- package/dist/chunk-7M6G2SCF.js.map +1 -0
- package/dist/{chunk-I7HKKMUJ.js → chunk-DSPP6CZL.js} +48 -3
- package/dist/chunk-DSPP6CZL.js.map +1 -0
- package/dist/index.js +10 -5
- package/dist/index.js.map +1 -1
- package/dist/observability-metrics.d.ts +11 -1
- package/dist/sandbox-resume.d.ts +46 -0
- package/dist/workflow-bundle.js +80 -2
- package/dist/workflows/session.d.ts +30 -0
- package/package.json +20 -19
- package/src/activities/agent-turn/agent-build.ts +4 -0
- package/src/activities/agent-turn/code-search.ts +275 -0
- package/src/activities/agent-turn/codex-capacity.ts +37 -2
- package/src/activities/agent-turn/compaction-prep.ts +52 -16
- package/src/activities/agent-turn/errors.ts +67 -4
- package/src/activities/agent-turn/failure-settlement.ts +40 -8
- package/src/activities/agent-turn/governance-model.ts +17 -1
- package/src/activities/agent-turn/history.ts +14 -1
- package/src/activities/agent-turn/media-artifacts.ts +2 -1
- package/src/activities/agent-turn/run.ts +4 -0
- package/src/activities/agent-turn/sandbox-establish.ts +12 -1
- package/src/activities/agent-turn/sandbox-runtime.ts +25 -9
- package/src/activities/agent-turn/session-title.ts +73 -3
- package/src/activities/agent-turn/stream-attempt.ts +27 -15
- package/src/activities/agent-turn/tool-environment.ts +65 -0
- package/src/activities/context-compaction.ts +49 -14
- package/src/activities/knowledge-indexing.ts +240 -15
- package/src/activities/retained-screenshots.ts +82 -11
- package/src/activities/sandbox-lease.ts +141 -21
- package/src/activities/scheduled-tasks.ts +18 -2
- package/src/activity-services.ts +16 -4
- package/src/editable-artifact-hint-broker.ts +3 -0
- package/src/index.ts +2 -2
- package/src/observability-metrics.ts +70 -1
- package/src/personal-github-git-credentials.ts +2 -0
- package/src/sandbox-resume.ts +211 -5
- package/src/workflows/activities.ts +14 -1
- package/src/workflows/session.ts +102 -6
- package/dist/activities-control-QA6OLRQY.js.map +0 -1
- package/dist/activities-turn-YVVKCGAK.js.map +0 -1
- package/dist/chunk-I7HKKMUJ.js.map +0 -1
- package/dist/chunk-M3NVMF2V.js.map +0 -1
|
@@ -61,7 +61,7 @@ import {
|
|
|
61
61
|
import {
|
|
62
62
|
compactRetainedScreenshotHistory,
|
|
63
63
|
sdkEventContainsInlineImage,
|
|
64
|
-
|
|
64
|
+
retainSessionScreenshot,
|
|
65
65
|
typedScreenshotFromSdkEvent,
|
|
66
66
|
unavailableRetainedSessionImage,
|
|
67
67
|
} from "../retained-screenshots";
|
|
@@ -108,6 +108,7 @@ import {
|
|
|
108
108
|
import {
|
|
109
109
|
pendingToolCallFromSdkEvent,
|
|
110
110
|
toolCallProducesRetainableSessionImage,
|
|
111
|
+
retainableBrowserScreenshotToolCall,
|
|
111
112
|
completedToolCallFromSdkEvent,
|
|
112
113
|
} from "./history";
|
|
113
114
|
import { checkpointHistoryBeforeProviderDispatch } from "./provider-dispatch-barrier";
|
|
@@ -125,7 +126,10 @@ import {
|
|
|
125
126
|
recordModelUsageAndDebitCredits,
|
|
126
127
|
recordAuthoritativeModelCallFact,
|
|
127
128
|
} from "./model-usage";
|
|
128
|
-
import {
|
|
129
|
+
import {
|
|
130
|
+
sessionTitleGenerationOptions,
|
|
131
|
+
startParallelSessionTitleGeneration,
|
|
132
|
+
} from "./session-title";
|
|
129
133
|
import {
|
|
130
134
|
assertAgentStreamNotCancelled,
|
|
131
135
|
assertSuccessfulAgentStreamCompletion,
|
|
@@ -1125,6 +1129,12 @@ export async function runTurnStreamAttempt(
|
|
|
1125
1129
|
currentToolBatchCallIds.add(pendingToolCall.callId);
|
|
1126
1130
|
if (toolCallProducesRetainableSessionImage(pendingToolCall.callName)) {
|
|
1127
1131
|
media.retainedSessionImageCallIds.add(pendingToolCall.callId);
|
|
1132
|
+
if (retainableBrowserScreenshotToolCall(pendingToolCall.callName)) {
|
|
1133
|
+
media.retainedSessionImageKindsByCallId.set(
|
|
1134
|
+
pendingToolCall.callId,
|
|
1135
|
+
"browser_screenshot",
|
|
1136
|
+
);
|
|
1137
|
+
}
|
|
1128
1138
|
}
|
|
1129
1139
|
}
|
|
1130
1140
|
const completedToolCall = completedToolCallFromSdkEvent(durableSdkEvent);
|
|
@@ -1147,6 +1157,7 @@ export async function runTurnStreamAttempt(
|
|
|
1147
1157
|
toolCallId: completedToolCall.callId,
|
|
1148
1158
|
toolOutputId: completedToolCall.callId,
|
|
1149
1159
|
reason: "unsupported",
|
|
1160
|
+
kind: media.retainedSessionImageKindsByCallId.get(completedToolCall.callId),
|
|
1150
1161
|
});
|
|
1151
1162
|
media.retainedScreenshotReceiptsByCallId.set(
|
|
1152
1163
|
completedToolCall.callId,
|
|
@@ -1169,12 +1180,13 @@ export async function runTurnStreamAttempt(
|
|
|
1169
1180
|
toolCallId: typedScreenshot.callId,
|
|
1170
1181
|
toolOutputId: typedScreenshot.toolOutputId,
|
|
1171
1182
|
reason: "pending",
|
|
1183
|
+
kind: media.retainedSessionImageKindsByCallId.get(completedToolCall.callId),
|
|
1172
1184
|
});
|
|
1173
1185
|
media.retainedScreenshotReceiptsByCallId.set(
|
|
1174
1186
|
completedToolCall.callId,
|
|
1175
1187
|
retainedScreenshotMetadata,
|
|
1176
1188
|
);
|
|
1177
|
-
retainedScreenshotMetadata = await
|
|
1189
|
+
retainedScreenshotMetadata = await retainSessionScreenshot({
|
|
1178
1190
|
db,
|
|
1179
1191
|
objectStorage,
|
|
1180
1192
|
accountId: input.accountId,
|
|
@@ -1183,6 +1195,7 @@ export async function runTurnStreamAttempt(
|
|
|
1183
1195
|
turnId: activeTurnId,
|
|
1184
1196
|
attemptId: input.attemptId,
|
|
1185
1197
|
output: typedScreenshot,
|
|
1198
|
+
kind: media.retainedSessionImageKindsByCallId.get(completedToolCall.callId),
|
|
1186
1199
|
});
|
|
1187
1200
|
media.retainedScreenshotReceiptsByCallId.set(
|
|
1188
1201
|
completedToolCall.callId,
|
|
@@ -1339,6 +1352,7 @@ export async function runTurnStreamAttempt(
|
|
|
1339
1352
|
}
|
|
1340
1353
|
for (const callId of stableToolCallIdsToClear) {
|
|
1341
1354
|
media.retainedSessionImageCallIds.delete(callId);
|
|
1355
|
+
media.retainedSessionImageKindsByCallId.delete(callId);
|
|
1342
1356
|
}
|
|
1343
1357
|
}
|
|
1344
1358
|
}
|
|
@@ -1775,18 +1789,16 @@ export async function runTurnStreamAttempt(
|
|
|
1775
1789
|
signal: runtimeCancellationSignal,
|
|
1776
1790
|
generate: async (signal) =>
|
|
1777
1791
|
await withSessionTitleProviderRequestContext(() =>
|
|
1778
|
-
runtime.generateSessionTitle!(
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
signal,
|
|
1789
|
-
}),
|
|
1792
|
+
runtime.generateSessionTitle!(
|
|
1793
|
+
runSettings,
|
|
1794
|
+
sessionTitlePrompt,
|
|
1795
|
+
sessionTitleGenerationOptions({
|
|
1796
|
+
resolvedModel,
|
|
1797
|
+
modelName: turnExecutionPolicy.upstreamModelId,
|
|
1798
|
+
serviceTier,
|
|
1799
|
+
signal,
|
|
1800
|
+
}),
|
|
1801
|
+
),
|
|
1790
1802
|
),
|
|
1791
1803
|
onError: (error) => {
|
|
1792
1804
|
observability.warn("parallel session title generation failed", {
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
organizationModelProviderConnectionActiveForWorkspace,
|
|
16
16
|
persistAttemptToolCatalog,
|
|
17
17
|
prepareConnectorActionApproval,
|
|
18
|
+
recordUsageEvent,
|
|
18
19
|
previewConnectorActionApproval,
|
|
19
20
|
namedSubjectHasLiveWorkspaceAuthority,
|
|
20
21
|
updateSessionTitleWithEvent,
|
|
@@ -101,11 +102,13 @@ import type {
|
|
|
101
102
|
} from "./turn-context";
|
|
102
103
|
import {
|
|
103
104
|
createSessionTitleAttemptToolDefinition,
|
|
105
|
+
routeAllowsSessionTitleRequests,
|
|
104
106
|
sessionTitleToolPlan,
|
|
105
107
|
shouldRequestMissingSessionTitle,
|
|
106
108
|
} from "./session-title";
|
|
107
109
|
import { resolveTurnSandboxAccess } from "./turn-sandbox-access";
|
|
108
110
|
import { createListModelsAttemptToolDefinition } from "./list-models";
|
|
111
|
+
import { codeSearchToolDefinitions, codeSearchWorkspaceFromChannel } from "./code-search";
|
|
109
112
|
import { createWorkspaceSkillTools } from "./skill-tools";
|
|
110
113
|
import { loadConfiguredBundledSkills } from "./skill-selection";
|
|
111
114
|
import { guardSkillFilesystem } from "./skill-transfer";
|
|
@@ -152,6 +155,7 @@ export type PrepareTurnToolRuntimeDeps = {
|
|
|
152
155
|
turnExecutionPolicy: ClaimTurnOk["turnExecutionPolicy"];
|
|
153
156
|
trigger: ClaimTurnOk["trigger"];
|
|
154
157
|
runSettings: GovernanceModelOk["runSettings"];
|
|
158
|
+
resolvedModel: GovernanceModelOk["resolvedModel"];
|
|
155
159
|
lazyToolTransport: GovernanceModelOk["lazyToolTransport"];
|
|
156
160
|
turnTools: ReturnType<typeof withFirstPartyTools>;
|
|
157
161
|
connectionScope: { accountId: string; workspaceId: string };
|
|
@@ -163,6 +167,8 @@ export type PrepareTurnToolRuntimeDeps = {
|
|
|
163
167
|
credentialSubjectId: ClaimTurnOk["credentialSubjectId"];
|
|
164
168
|
interactionInterventionResume: ClaimTurnOk["interactionInterventionResume"];
|
|
165
169
|
runWorkspaceMutationForSandbox: SandboxTurnRuntime["runWorkspaceMutationForSandbox"];
|
|
170
|
+
/** Deployment and workspace allow the Jev-backed code_search tool. */
|
|
171
|
+
codeSearchEnabled: boolean;
|
|
166
172
|
throwIfWorkerShuttingDown: () => void;
|
|
167
173
|
throwIfTurnCancelled: () => void;
|
|
168
174
|
};
|
|
@@ -371,6 +377,7 @@ export async function prepareTurnToolRuntime(deps: PrepareTurnToolRuntimeDeps) {
|
|
|
371
377
|
turnExecutionPolicy,
|
|
372
378
|
trigger,
|
|
373
379
|
runSettings: canonicalRunSettings,
|
|
380
|
+
resolvedModel,
|
|
374
381
|
lazyToolTransport,
|
|
375
382
|
turnTools: canonicalTurnTools,
|
|
376
383
|
sandboxArtifactRuntime,
|
|
@@ -381,6 +388,7 @@ export async function prepareTurnToolRuntime(deps: PrepareTurnToolRuntimeDeps) {
|
|
|
381
388
|
credentialSubjectId,
|
|
382
389
|
interactionInterventionResume,
|
|
383
390
|
runWorkspaceMutationForSandbox,
|
|
391
|
+
codeSearchEnabled,
|
|
384
392
|
throwIfWorkerShuttingDown,
|
|
385
393
|
throwIfTurnCancelled,
|
|
386
394
|
} = deps;
|
|
@@ -573,6 +581,7 @@ export async function prepareTurnToolRuntime(deps: PrepareTurnToolRuntimeDeps) {
|
|
|
573
581
|
firstPartyMcpPermissions: effectiveFirstPartyPermissions,
|
|
574
582
|
}),
|
|
575
583
|
parallelGenerationAvailable: typeof runtime.generateSessionTitle === "function",
|
|
584
|
+
routeAllowsTitleRequests: routeAllowsSessionTitleRequests(resolvedModel),
|
|
576
585
|
});
|
|
577
586
|
const googleDrivePublicationAllowed =
|
|
578
587
|
selectedFirstPartyMcpTools.includes("editable_artifact_export") &&
|
|
@@ -762,6 +771,60 @@ export async function prepareTurnToolRuntime(deps: PrepareTurnToolRuntimeDeps) {
|
|
|
762
771
|
return ((await prepared.ready) ?? prepared).attemptToolEnvironment;
|
|
763
772
|
},
|
|
764
773
|
});
|
|
774
|
+
const codeSearchTools = codeSearchToolDefinitions({
|
|
775
|
+
enabled: codeSearchEnabled,
|
|
776
|
+
settings: runSettings,
|
|
777
|
+
backend: activeSandboxBackend ?? groupBoxBackend,
|
|
778
|
+
machineWorkspaceRoot: sandboxState.machinePrimarySession?.workspaceRoot ?? null,
|
|
779
|
+
observability,
|
|
780
|
+
// OpenGeni's Jev key pays for these calls whatever model billing the
|
|
781
|
+
// workspace uses; record them per workspace so the cost stays visible.
|
|
782
|
+
recordUsage: async (usage) => {
|
|
783
|
+
const shared = {
|
|
784
|
+
accountId: input.accountId,
|
|
785
|
+
workspaceId: input.workspaceId,
|
|
786
|
+
sourceResourceType: "code_search",
|
|
787
|
+
sourceResourceId: usage.operationId,
|
|
788
|
+
sessionId: input.sessionId,
|
|
789
|
+
turnId: turn.id,
|
|
790
|
+
turnAttemptId: input.attemptId,
|
|
791
|
+
};
|
|
792
|
+
await recordUsageEvent(db, {
|
|
793
|
+
...shared,
|
|
794
|
+
eventType: "code_search.jev_input_tokens",
|
|
795
|
+
quantity: usage.jevInputTokens,
|
|
796
|
+
unit: "tokens",
|
|
797
|
+
idempotencyKey: `usage:code_search.jev_input_tokens:${input.attemptId}:${usage.operationId}`,
|
|
798
|
+
});
|
|
799
|
+
await recordUsageEvent(db, {
|
|
800
|
+
...shared,
|
|
801
|
+
eventType: "code_search.jev_cost",
|
|
802
|
+
quantity: Math.round(usage.jevCostUsd * 1_000_000),
|
|
803
|
+
unit: "usd_micros",
|
|
804
|
+
idempotencyKey: `usage:code_search.jev_cost:${input.attemptId}:${usage.operationId}`,
|
|
805
|
+
});
|
|
806
|
+
},
|
|
807
|
+
workspace: async () => {
|
|
808
|
+
throwIfWorkerShuttingDown();
|
|
809
|
+
throwIfTurnCancelled();
|
|
810
|
+
const access = await resolveTurnSandboxAccess(
|
|
811
|
+
sandboxState,
|
|
812
|
+
media.sdkOwnedSandboxSession,
|
|
813
|
+
"code_search requires a sandbox or Connected Machine.",
|
|
814
|
+
);
|
|
815
|
+
const machineRoot = sandboxState.machinePrimarySession?.workspaceRoot;
|
|
816
|
+
const runAs = sandboxRunAs(runSettings);
|
|
817
|
+
return codeSearchWorkspaceFromChannel(
|
|
818
|
+
new SandboxChannelAService({
|
|
819
|
+
session: access.session,
|
|
820
|
+
workspaceRoot: machineRoot ?? "/workspace",
|
|
821
|
+
...(machineRoot ? { providerPathMode: "workspace-relative" as const } : {}),
|
|
822
|
+
leaseEpoch: access.leaseEpoch,
|
|
823
|
+
...(runAs ? { runAs } : {}),
|
|
824
|
+
}),
|
|
825
|
+
);
|
|
826
|
+
},
|
|
827
|
+
});
|
|
765
828
|
const attemptToolDefinitions = [
|
|
766
829
|
...(operationReadStore
|
|
767
830
|
? [
|
|
@@ -903,6 +966,7 @@ export async function prepareTurnToolRuntime(deps: PrepareTurnToolRuntimeDeps) {
|
|
|
903
966
|
...(googleDrivePublicationTool && googleDrivePublicationAllowed
|
|
904
967
|
? [googleDrivePublicationTool]
|
|
905
968
|
: []),
|
|
969
|
+
...codeSearchTools,
|
|
906
970
|
];
|
|
907
971
|
recordTurnStartupPhase(observability, {
|
|
908
972
|
phase: "tool_context_preparation",
|
|
@@ -1124,6 +1188,7 @@ export async function prepareTurnToolRuntime(deps: PrepareTurnToolRuntimeDeps) {
|
|
|
1124
1188
|
...titleToolPlan.preparationIndependentToolNames,
|
|
1125
1189
|
"skill_read",
|
|
1126
1190
|
],
|
|
1191
|
+
codeSearchAvailable: codeSearchTools.length > 0,
|
|
1127
1192
|
skillCatalog,
|
|
1128
1193
|
};
|
|
1129
1194
|
}
|
|
@@ -9,7 +9,8 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
EmptyCompactionSummaryError,
|
|
11
11
|
REMOTE_COMPACTION_V2_IMPLEMENTATION,
|
|
12
|
-
|
|
12
|
+
compactionSummaryOutputTokens,
|
|
13
|
+
buildSummaryItem,
|
|
13
14
|
buildCompactionReplacementHistory,
|
|
14
15
|
buildRemoteV2ReplacementHistory,
|
|
15
16
|
compactionThresholdTokens,
|
|
@@ -58,7 +59,13 @@ export type MaybeCompactResult =
|
|
|
58
59
|
* Codex, call Codex `/codex/responses` with `compaction_trigger` and persist the
|
|
59
60
|
* opaque compaction item. Fail closed — never silently fall back to portable.
|
|
60
61
|
*/
|
|
61
|
-
export type CompactionSummarizer = (
|
|
62
|
+
export type CompactionSummarizer = ((
|
|
63
|
+
settings: Settings,
|
|
64
|
+
input: CompactionItem[],
|
|
65
|
+
) => Promise<string>) & {
|
|
66
|
+
/** Model-visible instructions and tool schemas outside the history estimate. */
|
|
67
|
+
estimatePrefixTokens?: () => number;
|
|
68
|
+
};
|
|
62
69
|
|
|
63
70
|
/** Returns the opaque Codex remote compaction v2 item. */
|
|
64
71
|
export type RemoteCompactionV2Requester = (
|
|
@@ -81,7 +88,7 @@ export async function maybeCompactContext(
|
|
|
81
88
|
// Injectable for tests; defaults to the real provider-aware model call.
|
|
82
89
|
summarize: CompactionSummarizer = (s, m) =>
|
|
83
90
|
summarizeForCompaction(s, m, {
|
|
84
|
-
maxOutputTokens:
|
|
91
|
+
maxOutputTokens: compactionSummaryOutputTokens(s.contextWindowTokens),
|
|
85
92
|
}),
|
|
86
93
|
// Operator-forced (the /compact command): bypass the budget trigger and
|
|
87
94
|
// compact now if there is anything to summarize. Structural guards still hold.
|
|
@@ -300,6 +307,7 @@ async function settleSkippedAfterStart(
|
|
|
300
307
|
reason:
|
|
301
308
|
| "no_history"
|
|
302
309
|
| "replacement_not_smaller"
|
|
310
|
+
| "replacement_exceeds_model_budget"
|
|
303
311
|
| "replacement_unchanged"
|
|
304
312
|
| "summarization_failed",
|
|
305
313
|
): Promise<Extract<MaybeCompactResult, { compacted: false }>> {
|
|
@@ -455,12 +463,23 @@ async function compactContextPortable(
|
|
|
455
463
|
const summarized = await summarizeWithCodexOverflowTrimming(summarize, settings, items);
|
|
456
464
|
const summaryBody = summarized.summaryBody;
|
|
457
465
|
const retainedTokens = await retentionTokenCounts(canonicalItems, projectForWire);
|
|
466
|
+
const outputReserve = compactionSummaryOutputTokens(settings.contextWindowTokens);
|
|
467
|
+
const structuralBudget = Math.min(
|
|
468
|
+
contextInputBudgetTokens(settings) || settings.contextWindowTokens - outputReserve,
|
|
469
|
+
settings.contextWindowTokens - outputReserve,
|
|
470
|
+
);
|
|
471
|
+
const prefixTokens = Math.max(0, Math.ceil(summarize.estimatePrefixTokens?.() ?? 0));
|
|
472
|
+
const summaryTokens = estimateTokens([buildSummaryItem(summaryBody)]);
|
|
458
473
|
const replacementHistory = buildCompactionReplacementHistory(
|
|
459
474
|
canonicalItems,
|
|
460
475
|
summaryBody,
|
|
461
476
|
(item) => retainedTokens.get(item) ?? estimateTokens([item]),
|
|
477
|
+
Math.min(outputReserve, Math.max(0, structuralBudget - prefixTokens - summaryTokens)),
|
|
462
478
|
);
|
|
463
479
|
const estimatedTokensAfter = estimateTokens(await projectForWire(replacementHistory));
|
|
480
|
+
if (estimatedTokensAfter + prefixTokens > structuralBudget) {
|
|
481
|
+
return await settleSkippedAfterStart(db, scope, options, "replacement_exceeds_model_budget");
|
|
482
|
+
}
|
|
464
483
|
const replacementFingerprint = compactionReplacementFingerprint(replacementHistory);
|
|
465
484
|
const previousReplacementFingerprint = latestCompactionReplacementFingerprint(canonicalItems);
|
|
466
485
|
const summaryIndex =
|
|
@@ -520,7 +539,7 @@ async function compactContextPortable(
|
|
|
520
539
|
};
|
|
521
540
|
}
|
|
522
541
|
|
|
523
|
-
async function summarizeWithCodexOverflowTrimming(
|
|
542
|
+
export async function summarizeWithCodexOverflowTrimming(
|
|
524
543
|
summarize: CompactionSummarizer,
|
|
525
544
|
settings: Settings,
|
|
526
545
|
activeHistory: CompactionItem[],
|
|
@@ -531,17 +550,32 @@ async function summarizeWithCodexOverflowTrimming(
|
|
|
531
550
|
}> {
|
|
532
551
|
// Codex's estimator is intentionally coarse. Keep the explicit checkpoint
|
|
533
552
|
// request below both the effective input window and the raw window minus the
|
|
534
|
-
// requested summary
|
|
535
|
-
//
|
|
536
|
-
//
|
|
537
|
-
const summaryAwareBudget = Math.max(
|
|
553
|
+
// requested summary. Preserve the full portable history copy on the first
|
|
554
|
+
// call whenever it fits; only trim further after an actual provider overflow.
|
|
555
|
+
// Durable active history remains untouched until applyContextCompaction.
|
|
556
|
+
const summaryAwareBudget = Math.max(
|
|
557
|
+
0,
|
|
558
|
+
settings.contextWindowTokens - compactionSummaryOutputTokens(settings.contextWindowTokens),
|
|
559
|
+
);
|
|
538
560
|
const configuredInputBudget = contextInputBudgetTokens(settings);
|
|
539
561
|
const structuralBudget = Math.min(
|
|
540
562
|
configuredInputBudget > 0 ? configuredInputBudget : summaryAwareBudget,
|
|
541
563
|
summaryAwareBudget,
|
|
542
564
|
);
|
|
543
|
-
const
|
|
565
|
+
const prefixTokens = Math.max(0, Math.ceil(summarize.estimatePrefixTokens?.() ?? 0));
|
|
566
|
+
const initialBudget = Math.max(0, structuralBudget - prefixTokens);
|
|
544
567
|
let preparation = prepareCompactionPromptInput(activeHistory, initialBudget);
|
|
568
|
+
// A checkpoint prompt without source history cannot summarize that history.
|
|
569
|
+
// Do not let a plausible-sounding reply replace durable active context.
|
|
570
|
+
const requireHistory = () => {
|
|
571
|
+
if (activeHistory.length > 0 && preparation.input.length === 1) {
|
|
572
|
+
throw new EmptyCompactionSummaryError({
|
|
573
|
+
stage: "portable_input_budget",
|
|
574
|
+
reason: "no_history_fit",
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
requireHistory();
|
|
545
579
|
try {
|
|
546
580
|
return {
|
|
547
581
|
summaryBody: await summarize(settings, preparation.input),
|
|
@@ -551,15 +585,16 @@ async function summarizeWithCodexOverflowTrimming(
|
|
|
551
585
|
} catch (error) {
|
|
552
586
|
if (!isContextWindowExceeded(error)) throw error;
|
|
553
587
|
// The provider is more authoritative than the byte/4 estimate. Refit once
|
|
554
|
-
// to
|
|
588
|
+
// to 40% of both the available target and the actual prepared estimate;
|
|
555
589
|
// then fail terminally with prior history intact. Never issue one failing
|
|
556
|
-
// request per oldest item. The
|
|
557
|
-
// provider can count slightly more than twice the byte/4 estimate
|
|
558
|
-
//
|
|
590
|
+
// request per oldest item. The retry is bounded, not a guarantee: the
|
|
591
|
+
// provider can count slightly more than twice the byte/4 estimate. The
|
|
592
|
+
// prepared prefix has already been reserved from the available budget.
|
|
559
593
|
const retryBudget = Math.floor(
|
|
560
|
-
Math.min(initialBudget * 0.
|
|
594
|
+
Math.min(initialBudget * 0.4, preparation.estimatedInputTokens * 0.4),
|
|
561
595
|
);
|
|
562
596
|
preparation = prepareCompactionPromptInput(activeHistory, retryBudget);
|
|
597
|
+
requireHistory();
|
|
563
598
|
return {
|
|
564
599
|
summaryBody: await summarize(settings, preparation.input),
|
|
565
600
|
preparation,
|