@runtypelabs/sdk 1.8.0 → 1.8.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/index.cjs +613 -95
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -1
- package/dist/index.d.ts +85 -1
- package/dist/index.js +613 -95
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3108,7 +3108,11 @@ var designPhase = {
|
|
|
3108
3108
|
buildTransitionSummary(_state, _nextPhaseName) {
|
|
3109
3109
|
return [
|
|
3110
3110
|
"Automatic phase transition: design \u2192 build.",
|
|
3111
|
-
"Requirements understood. Build the game and deploy it using deploy_sandbox
|
|
3111
|
+
"Requirements understood. Build the game and deploy it using deploy_sandbox.",
|
|
3112
|
+
"",
|
|
3113
|
+
"MANDATORY: Use the `files` parameter for ALL game HTML/JS/CSS.",
|
|
3114
|
+
"code = minimal Express static server (~4 lines), files = game assets.",
|
|
3115
|
+
"NEVER embed HTML inside res.send() template literals."
|
|
3112
3116
|
].join("\n");
|
|
3113
3117
|
},
|
|
3114
3118
|
interceptToolCall(toolName, _args, _ctx) {
|
|
@@ -3168,7 +3172,32 @@ var buildPhase = {
|
|
|
3168
3172
|
" 4. If the deploy fails, read the error output, fix the code, and call deploy_sandbox again.",
|
|
3169
3173
|
" 5. The sandbox is persistent \u2014 subsequent calls reuse the same sandbox.",
|
|
3170
3174
|
" 6. Load game libraries from CDN in your HTML (e.g., Three.js from unpkg/cdnjs) OR include them in packageJson.",
|
|
3171
|
-
" 7. Make the game fullscreen by default (width: 100vw, height: 100vh, no margin/padding on body)."
|
|
3175
|
+
" 7. Make the game fullscreen by default (width: 100vw, height: 100vh, no margin/padding on body).",
|
|
3176
|
+
"",
|
|
3177
|
+
"STARTER TEMPLATES \u2014 Copy and customize based on the game type:",
|
|
3178
|
+
"",
|
|
3179
|
+
"ALL templates use this server code:",
|
|
3180
|
+
' code: `const express = require("express"); const app = express(); app.use(express.static("public")); app.listen(3000, () => console.log("Game server running on port 3000"));`',
|
|
3181
|
+
' packageJson: { "dependencies": { "express": "^4.18.2" } }',
|
|
3182
|
+
' language: "javascript"',
|
|
3183
|
+
"",
|
|
3184
|
+
"THREE.JS (3D games \u2014 racing, flying, FPS, etc.):",
|
|
3185
|
+
" files: {",
|
|
3186
|
+
' "public/index.html": HTML with <script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js"}}</script> and <script type="module" src="game.js"></script>',
|
|
3187
|
+
' "public/game.js": Import three, create scene/camera/renderer, game loop with requestAnimationFrame',
|
|
3188
|
+
" }",
|
|
3189
|
+
"",
|
|
3190
|
+
"PHASER (2D games \u2014 platformers, shooters, puzzles):",
|
|
3191
|
+
" files: {",
|
|
3192
|
+
' "public/index.html": HTML with <script src="https://cdn.jsdelivr.net/npm/phaser@3.80.1/dist/phaser.min.js"></script> and <script src="game.js"></script>',
|
|
3193
|
+
' "public/game.js": Phaser.Game config with scenes, preload/create/update lifecycle',
|
|
3194
|
+
" }",
|
|
3195
|
+
"",
|
|
3196
|
+
"CANVAS 2D (simple games \u2014 pong, snake, breakout):",
|
|
3197
|
+
" files: {",
|
|
3198
|
+
' "public/index.html": HTML with <canvas id="game" width="800" height="600"></canvas> and <script src="game.js"></script>',
|
|
3199
|
+
' "public/game.js": Get canvas context, game loop with requestAnimationFrame, draw calls',
|
|
3200
|
+
" }"
|
|
3172
3201
|
].join("\n");
|
|
3173
3202
|
},
|
|
3174
3203
|
buildToolGuidance(_state) {
|
|
@@ -3182,8 +3211,23 @@ var buildPhase = {
|
|
|
3182
3211
|
isComplete() {
|
|
3183
3212
|
return false;
|
|
3184
3213
|
},
|
|
3185
|
-
interceptToolCall(toolName,
|
|
3186
|
-
|
|
3214
|
+
interceptToolCall(toolName, args, _ctx) {
|
|
3215
|
+
const localBlock = blockLocalTools(toolName);
|
|
3216
|
+
if (localBlock) return localBlock;
|
|
3217
|
+
if (toolName === "deploy_sandbox" && args) {
|
|
3218
|
+
const hasFiles = args.files && typeof args.files === "object" && Object.keys(args.files).length > 0;
|
|
3219
|
+
const codeStr = typeof args.code === "string" ? args.code : "";
|
|
3220
|
+
const embedsHtml = /res\.send\s*\(/.test(codeStr) && /<html|<body|<script/i.test(codeStr);
|
|
3221
|
+
if (!hasFiles && embedsHtml) {
|
|
3222
|
+
return [
|
|
3223
|
+
"Blocked: You are embedding HTML inside res.send() \u2014 this will break due to nested template literals.",
|
|
3224
|
+
"You MUST use the `files` parameter. Put your game HTML/JS/CSS in files and use a minimal Express static server for code.",
|
|
3225
|
+
'Example: code: `const express = require("express"); const app = express(); app.use(express.static("public")); app.listen(3000);`',
|
|
3226
|
+
'files: { "public/index.html": "<!DOCTYPE html>...", "public/game.js": "// game code" }'
|
|
3227
|
+
].join("\n");
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
return void 0;
|
|
3187
3231
|
},
|
|
3188
3232
|
canAcceptCompletion(_state, trace) {
|
|
3189
3233
|
return trace.entries.some((entry) => entry.startsWith("deploy_sandbox"));
|
|
@@ -5479,6 +5523,8 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
5479
5523
|
this.updateWorkflowPhase(state, this.createEmptyToolTrace(), workflow);
|
|
5480
5524
|
let recordId;
|
|
5481
5525
|
const localToolNames = options.localTools ? Object.keys(options.localTools) : void 0;
|
|
5526
|
+
const builtinToolSchemas = await this.loadBuiltinToolSchemas(options.toolIds);
|
|
5527
|
+
const compactInstructions = this.resolveCompactInstructions(options.compactInstructions, agent);
|
|
5482
5528
|
if (!options.previousMessages) {
|
|
5483
5529
|
if (workflow.generateBootstrapContext) {
|
|
5484
5530
|
state.bootstrapContext = await workflow.generateBootstrapContext(
|
|
@@ -5512,7 +5558,7 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
5512
5558
|
if (session === 0 && !options.previousMessages) {
|
|
5513
5559
|
state.originalMessage = options.message;
|
|
5514
5560
|
}
|
|
5515
|
-
const
|
|
5561
|
+
const preparedSession = await this.prepareSessionContext(
|
|
5516
5562
|
options.message,
|
|
5517
5563
|
state,
|
|
5518
5564
|
session,
|
|
@@ -5520,61 +5566,93 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
5520
5566
|
localToolNames,
|
|
5521
5567
|
continuationContext,
|
|
5522
5568
|
workflow,
|
|
5523
|
-
options.toolIds
|
|
5569
|
+
options.toolIds,
|
|
5570
|
+
{
|
|
5571
|
+
autoCompactTokenThreshold: options.autoCompactTokenThreshold,
|
|
5572
|
+
contextLimitTokens: options.contextLimitTokens,
|
|
5573
|
+
model: options.model,
|
|
5574
|
+
compactStrategy: options.compactStrategy,
|
|
5575
|
+
compactInstructions,
|
|
5576
|
+
localTools: options.localTools,
|
|
5577
|
+
builtinToolSchemas,
|
|
5578
|
+
onContextCompaction: options.onContextCompaction,
|
|
5579
|
+
onContextNotice: options.onContextNotice
|
|
5580
|
+
}
|
|
5524
5581
|
);
|
|
5582
|
+
const {
|
|
5583
|
+
messages,
|
|
5584
|
+
requestContextManagement,
|
|
5585
|
+
pendingNativeCompactionEvent
|
|
5586
|
+
} = preparedSession;
|
|
5525
5587
|
let sessionResult;
|
|
5526
5588
|
const sessionData = {
|
|
5527
5589
|
messages,
|
|
5528
5590
|
debugMode: options.debugMode,
|
|
5529
5591
|
model: options.model,
|
|
5530
|
-
...options.toolIds?.length ? { tools: { toolIds: options.toolIds } } : {}
|
|
5592
|
+
...options.toolIds?.length ? { tools: { toolIds: options.toolIds } } : {},
|
|
5593
|
+
...requestContextManagement ? { contextManagement: requestContextManagement } : {}
|
|
5531
5594
|
};
|
|
5532
5595
|
let sessionToolMessages = [];
|
|
5533
|
-
if (
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5596
|
+
if (pendingNativeCompactionEvent) {
|
|
5597
|
+
await this.emitContextCompactionEvent(options.onContextCompaction, {
|
|
5598
|
+
phase: "start",
|
|
5599
|
+
...pendingNativeCompactionEvent
|
|
5600
|
+
});
|
|
5601
|
+
}
|
|
5602
|
+
try {
|
|
5603
|
+
if (useStream && options.localTools) {
|
|
5604
|
+
const localToolResult = await this.executeWithLocalTools(
|
|
5605
|
+
id,
|
|
5606
|
+
sessionData,
|
|
5607
|
+
sessionLocalTools || options.localTools,
|
|
5608
|
+
sessionCallbacks,
|
|
5609
|
+
{
|
|
5610
|
+
onLocalToolResult: this.createLocalToolLoopGuard(state, sessionTrace, workflow)
|
|
5611
|
+
},
|
|
5612
|
+
state.taskName
|
|
5613
|
+
);
|
|
5614
|
+
if (!localToolResult) {
|
|
5615
|
+
throw new Error("Agent stream ended without a complete event");
|
|
5616
|
+
}
|
|
5617
|
+
const { completeEvent, toolMessages: captured } = localToolResult;
|
|
5618
|
+
sessionToolMessages = captured;
|
|
5619
|
+
sessionResult = {
|
|
5620
|
+
success: completeEvent.success,
|
|
5621
|
+
result: completeEvent.finalOutput || "",
|
|
5622
|
+
iterations: completeEvent.iterations,
|
|
5623
|
+
totalCost: completeEvent.totalCost || 0,
|
|
5624
|
+
totalTokens: completeEvent.totalTokens,
|
|
5625
|
+
stopReason: completeEvent.stopReason,
|
|
5626
|
+
error: completeEvent.error
|
|
5627
|
+
};
|
|
5628
|
+
} else if (useStream && options.streamCallbacks) {
|
|
5629
|
+
const completeEvent = await this.executeWithCallbacks(
|
|
5630
|
+
id,
|
|
5631
|
+
sessionData,
|
|
5632
|
+
sessionCallbacks || options.streamCallbacks
|
|
5633
|
+
);
|
|
5634
|
+
if (!completeEvent) {
|
|
5635
|
+
throw new Error("Agent stream ended without a complete event");
|
|
5636
|
+
}
|
|
5637
|
+
sessionResult = {
|
|
5638
|
+
success: completeEvent.success,
|
|
5639
|
+
result: completeEvent.finalOutput || "",
|
|
5640
|
+
iterations: completeEvent.iterations,
|
|
5641
|
+
totalCost: completeEvent.totalCost || 0,
|
|
5642
|
+
totalTokens: completeEvent.totalTokens,
|
|
5643
|
+
stopReason: completeEvent.stopReason,
|
|
5644
|
+
error: completeEvent.error
|
|
5645
|
+
};
|
|
5646
|
+
} else {
|
|
5647
|
+
sessionResult = await this.execute(id, sessionData);
|
|
5546
5648
|
}
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
totalCost: completeEvent.totalCost || 0,
|
|
5554
|
-
totalTokens: completeEvent.totalTokens,
|
|
5555
|
-
stopReason: completeEvent.stopReason,
|
|
5556
|
-
error: completeEvent.error
|
|
5557
|
-
};
|
|
5558
|
-
} else if (useStream && options.streamCallbacks) {
|
|
5559
|
-
const completeEvent = await this.executeWithCallbacks(
|
|
5560
|
-
id,
|
|
5561
|
-
sessionData,
|
|
5562
|
-
sessionCallbacks || options.streamCallbacks
|
|
5563
|
-
);
|
|
5564
|
-
if (!completeEvent) {
|
|
5565
|
-
throw new Error("Agent stream ended without a complete event");
|
|
5649
|
+
} finally {
|
|
5650
|
+
if (pendingNativeCompactionEvent) {
|
|
5651
|
+
await this.emitContextCompactionEvent(options.onContextCompaction, {
|
|
5652
|
+
phase: "complete",
|
|
5653
|
+
...pendingNativeCompactionEvent
|
|
5654
|
+
});
|
|
5566
5655
|
}
|
|
5567
|
-
sessionResult = {
|
|
5568
|
-
success: completeEvent.success,
|
|
5569
|
-
result: completeEvent.finalOutput || "",
|
|
5570
|
-
iterations: completeEvent.iterations,
|
|
5571
|
-
totalCost: completeEvent.totalCost || 0,
|
|
5572
|
-
totalTokens: completeEvent.totalTokens,
|
|
5573
|
-
stopReason: completeEvent.stopReason,
|
|
5574
|
-
error: completeEvent.error
|
|
5575
|
-
};
|
|
5576
|
-
} else {
|
|
5577
|
-
sessionResult = await this.execute(id, sessionData);
|
|
5578
5656
|
}
|
|
5579
5657
|
const toolTraceSummary = this.buildToolTraceSummary(sessionTrace);
|
|
5580
5658
|
const effectiveSessionOutput = this.buildEffectiveSessionOutput(
|
|
@@ -5661,7 +5739,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
5661
5739
|
}
|
|
5662
5740
|
}
|
|
5663
5741
|
if (!state.messages) state.messages = [];
|
|
5664
|
-
if (
|
|
5742
|
+
if (this.isCompactHistoryMessageSet(messages)) {
|
|
5743
|
+
state.messages = [...messages];
|
|
5744
|
+
} else if (state.messages.length > 0 && messages.length > state.messages.length) {
|
|
5665
5745
|
const newMessages = messages.slice(state.messages.length);
|
|
5666
5746
|
state.messages.push(...newMessages);
|
|
5667
5747
|
} else {
|
|
@@ -5726,41 +5806,379 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
5726
5806
|
const upper = output.toUpperCase();
|
|
5727
5807
|
return _AgentsEndpoint.STOP_PHRASES.some((phrase) => upper.includes(phrase.toUpperCase()));
|
|
5728
5808
|
}
|
|
5809
|
+
resolveReservedOutputTokens(contextLimitTokens) {
|
|
5810
|
+
if (typeof contextLimitTokens !== "number" || !Number.isFinite(contextLimitTokens) || contextLimitTokens <= 0) {
|
|
5811
|
+
return void 0;
|
|
5812
|
+
}
|
|
5813
|
+
return Math.max(8e3, Math.min(64e3, Math.floor(contextLimitTokens * 0.15)));
|
|
5814
|
+
}
|
|
5815
|
+
resolveEffectiveInputBudgetTokens(contextLimitTokens) {
|
|
5816
|
+
if (typeof contextLimitTokens !== "number" || !Number.isFinite(contextLimitTokens) || contextLimitTokens <= 0) {
|
|
5817
|
+
return void 0;
|
|
5818
|
+
}
|
|
5819
|
+
const reservedOutputTokens = this.resolveReservedOutputTokens(contextLimitTokens) ?? 0;
|
|
5820
|
+
return Math.max(1, contextLimitTokens - reservedOutputTokens);
|
|
5821
|
+
}
|
|
5822
|
+
resolveCompactStrategy(strategy, modelId) {
|
|
5823
|
+
if (strategy === "summary_fallback") {
|
|
5824
|
+
return "summary_fallback";
|
|
5825
|
+
}
|
|
5826
|
+
const normalizedModelId = modelId?.trim().toLowerCase() ?? "";
|
|
5827
|
+
const supportsAnthropicNativeCompaction = normalizedModelId.includes("claude") || normalizedModelId.includes("anthropic");
|
|
5828
|
+
if (strategy === "provider_native") {
|
|
5829
|
+
return supportsAnthropicNativeCompaction ? "provider_native" : "summary_fallback";
|
|
5830
|
+
}
|
|
5831
|
+
return supportsAnthropicNativeCompaction ? "provider_native" : "summary_fallback";
|
|
5832
|
+
}
|
|
5833
|
+
estimateTextTokens(text) {
|
|
5834
|
+
if (!text) return 0;
|
|
5835
|
+
return Math.ceil(text.length / 4);
|
|
5836
|
+
}
|
|
5837
|
+
estimateUnknownTokens(value) {
|
|
5838
|
+
if (typeof value === "string") return this.estimateTextTokens(value);
|
|
5839
|
+
try {
|
|
5840
|
+
return this.estimateTextTokens(JSON.stringify(value));
|
|
5841
|
+
} catch {
|
|
5842
|
+
return 0;
|
|
5843
|
+
}
|
|
5844
|
+
}
|
|
5845
|
+
estimateMessageContentTokens(content) {
|
|
5846
|
+
if (typeof content === "string") return this.estimateTextTokens(content);
|
|
5847
|
+
return content.reduce((total, part) => {
|
|
5848
|
+
if (typeof part.text === "string") total += this.estimateTextTokens(part.text);
|
|
5849
|
+
if (typeof part.image === "string") total += 85;
|
|
5850
|
+
if (typeof part.data === "string") {
|
|
5851
|
+
total += Math.min(200, this.estimateTextTokens(part.data));
|
|
5852
|
+
}
|
|
5853
|
+
return total + 4;
|
|
5854
|
+
}, 0);
|
|
5855
|
+
}
|
|
5856
|
+
estimateToolCallTokens(toolCalls) {
|
|
5857
|
+
if (!toolCalls || toolCalls.length === 0) return 0;
|
|
5858
|
+
return toolCalls.reduce(
|
|
5859
|
+
(sum, toolCall) => sum + 12 + this.estimateTextTokens(toolCall.toolName) + this.estimateUnknownTokens(toolCall.args),
|
|
5860
|
+
0
|
|
5861
|
+
);
|
|
5862
|
+
}
|
|
5863
|
+
estimateToolResultTokens(toolResults) {
|
|
5864
|
+
if (!toolResults || toolResults.length === 0) return 0;
|
|
5865
|
+
return toolResults.reduce(
|
|
5866
|
+
(sum, toolResult) => sum + 12 + this.estimateTextTokens(toolResult.toolName) + this.estimateUnknownTokens(toolResult.result),
|
|
5867
|
+
0
|
|
5868
|
+
);
|
|
5869
|
+
}
|
|
5870
|
+
estimateMessageTokens(message) {
|
|
5871
|
+
return 6 + this.estimateMessageContentTokens(message.content) + this.estimateToolCallTokens(message.toolCalls) + this.estimateToolResultTokens(message.toolResults);
|
|
5872
|
+
}
|
|
5873
|
+
estimateConversationTokens(messages) {
|
|
5874
|
+
return messages.reduce((sum, message) => sum + this.estimateMessageTokens(message), 0);
|
|
5875
|
+
}
|
|
5876
|
+
estimateConversationBreakdown(messages) {
|
|
5877
|
+
let historyTokens = 0;
|
|
5878
|
+
let toolOutputTokens = 0;
|
|
5879
|
+
for (const message of messages) {
|
|
5880
|
+
const contentTokens = this.estimateMessageContentTokens(message.content);
|
|
5881
|
+
const toolCallTokens = this.estimateToolCallTokens(message.toolCalls);
|
|
5882
|
+
const toolResultTokens = this.estimateToolResultTokens(message.toolResults);
|
|
5883
|
+
const messageTotal = 6 + contentTokens + toolCallTokens + toolResultTokens;
|
|
5884
|
+
if (message.role === "tool") {
|
|
5885
|
+
toolOutputTokens += messageTotal;
|
|
5886
|
+
} else {
|
|
5887
|
+
historyTokens += 6 + contentTokens + toolCallTokens;
|
|
5888
|
+
toolOutputTokens += toolResultTokens;
|
|
5889
|
+
}
|
|
5890
|
+
}
|
|
5891
|
+
return {
|
|
5892
|
+
historyTokens,
|
|
5893
|
+
toolOutputTokens,
|
|
5894
|
+
estimatedInputTokens: historyTokens + toolOutputTokens
|
|
5895
|
+
};
|
|
5896
|
+
}
|
|
5897
|
+
estimateToolDefinitionTokens(localTools, builtinToolSchemas) {
|
|
5898
|
+
const localToolDefinitions = Object.entries(localTools || {}).map(([name, definition]) => ({
|
|
5899
|
+
name,
|
|
5900
|
+
description: definition.description,
|
|
5901
|
+
parametersSchema: definition.parametersSchema
|
|
5902
|
+
}));
|
|
5903
|
+
const payload = [...localToolDefinitions, ...builtinToolSchemas];
|
|
5904
|
+
if (payload.length === 0) return 0;
|
|
5905
|
+
return this.estimateUnknownTokens(payload);
|
|
5906
|
+
}
|
|
5907
|
+
async loadBuiltinToolSchemas(toolIds) {
|
|
5908
|
+
if (!toolIds || toolIds.length === 0) return [];
|
|
5909
|
+
try {
|
|
5910
|
+
const schemas = await this.client.get("/tools/schema", { toolIds });
|
|
5911
|
+
return Array.isArray(schemas) ? schemas : [];
|
|
5912
|
+
} catch {
|
|
5913
|
+
return [];
|
|
5914
|
+
}
|
|
5915
|
+
}
|
|
5916
|
+
buildDefaultCompactInstructions() {
|
|
5917
|
+
return [
|
|
5918
|
+
"Preserve changed files or best candidate paths.",
|
|
5919
|
+
"Preserve verification or test results.",
|
|
5920
|
+
"Preserve the current workflow phase and remaining work.",
|
|
5921
|
+
"Preserve unresolved blockers or follow-up risks.",
|
|
5922
|
+
"Preserve artifact references and offloaded tool outputs."
|
|
5923
|
+
].join(" ");
|
|
5924
|
+
}
|
|
5925
|
+
resolveCompactInstructions(optionInstructions, agent) {
|
|
5926
|
+
if (typeof optionInstructions === "string" && optionInstructions.trim()) {
|
|
5927
|
+
return optionInstructions.trim();
|
|
5928
|
+
}
|
|
5929
|
+
const config = agent.config;
|
|
5930
|
+
if (!config || typeof config !== "object") {
|
|
5931
|
+
return void 0;
|
|
5932
|
+
}
|
|
5933
|
+
const compactInstructions = config.compactInstructions;
|
|
5934
|
+
return typeof compactInstructions === "string" && compactInstructions.trim() ? compactInstructions.trim() : void 0;
|
|
5935
|
+
}
|
|
5936
|
+
extractArtifactReferences(state) {
|
|
5937
|
+
const references = /* @__PURE__ */ new Set();
|
|
5938
|
+
const offloadPrefix = "[Output saved to ";
|
|
5939
|
+
for (const message of state.messages ?? []) {
|
|
5940
|
+
if (!message.toolResults) continue;
|
|
5941
|
+
for (const toolResult of message.toolResults) {
|
|
5942
|
+
if (typeof toolResult.result !== "string") continue;
|
|
5943
|
+
let startIndex = 0;
|
|
5944
|
+
while (startIndex < toolResult.result.length) {
|
|
5945
|
+
const prefixIndex = toolResult.result.indexOf(offloadPrefix, startIndex);
|
|
5946
|
+
if (prefixIndex === -1) break;
|
|
5947
|
+
const pathStart = prefixIndex + offloadPrefix.length;
|
|
5948
|
+
const closingBracket = toolResult.result.indexOf("]", pathStart);
|
|
5949
|
+
if (closingBracket === -1) break;
|
|
5950
|
+
const bracketContent = toolResult.result.slice(pathStart, closingBracket);
|
|
5951
|
+
const separatorIndex = bracketContent.indexOf(" \u2014 ");
|
|
5952
|
+
const pathText = separatorIndex === -1 ? bracketContent.trim() : bracketContent.slice(0, separatorIndex).trim();
|
|
5953
|
+
if (pathText) {
|
|
5954
|
+
references.add(pathText);
|
|
5955
|
+
}
|
|
5956
|
+
startIndex = closingBracket + 1;
|
|
5957
|
+
}
|
|
5958
|
+
}
|
|
5959
|
+
}
|
|
5960
|
+
if (state.planPath) {
|
|
5961
|
+
references.add(state.planPath);
|
|
5962
|
+
}
|
|
5963
|
+
return [...references].slice(0, 8);
|
|
5964
|
+
}
|
|
5965
|
+
buildContextBudgetBreakdown(details) {
|
|
5966
|
+
const conversationBreakdown = this.estimateConversationBreakdown(details.historyMessages);
|
|
5967
|
+
const currentTurnTokens = this.estimateTextTokens(details.currentTurnContent);
|
|
5968
|
+
const toolDefinitionTokens = this.estimateToolDefinitionTokens(
|
|
5969
|
+
details.localTools,
|
|
5970
|
+
details.builtinToolSchemas
|
|
5971
|
+
);
|
|
5972
|
+
const reservedOutputTokens = this.resolveReservedOutputTokens(details.contextLimitTokens);
|
|
5973
|
+
const effectiveInputBudgetTokens = this.resolveEffectiveInputBudgetTokens(details.contextLimitTokens);
|
|
5974
|
+
const summaryTokens = details.summaryText ? this.estimateTextTokens(
|
|
5975
|
+
`${_AgentsEndpoint.AUTO_COMPACT_SUMMARY_PREFIX}
|
|
5976
|
+
|
|
5977
|
+
${details.summaryText}
|
|
5978
|
+
|
|
5979
|
+
Do NOT redo any of the above work.`
|
|
5980
|
+
) : void 0;
|
|
5981
|
+
return {
|
|
5982
|
+
historyTokens: conversationBreakdown.historyTokens,
|
|
5983
|
+
toolOutputTokens: conversationBreakdown.toolOutputTokens,
|
|
5984
|
+
currentTurnTokens,
|
|
5985
|
+
toolDefinitionTokens,
|
|
5986
|
+
...summaryTokens ? { summaryTokens } : {},
|
|
5987
|
+
...reservedOutputTokens ? { reservedOutputTokens } : {},
|
|
5988
|
+
...effectiveInputBudgetTokens ? { effectiveInputBudgetTokens } : {},
|
|
5989
|
+
estimatedInputTokens: conversationBreakdown.estimatedInputTokens + currentTurnTokens + toolDefinitionTokens
|
|
5990
|
+
};
|
|
5991
|
+
}
|
|
5992
|
+
async emitContextCompactionEvent(onContextCompaction, event) {
|
|
5993
|
+
if (!onContextCompaction) return;
|
|
5994
|
+
try {
|
|
5995
|
+
await onContextCompaction(event);
|
|
5996
|
+
} catch {
|
|
5997
|
+
}
|
|
5998
|
+
}
|
|
5999
|
+
async emitContextNotice(onContextNotice, event) {
|
|
6000
|
+
if (!onContextNotice) return;
|
|
6001
|
+
try {
|
|
6002
|
+
await onContextNotice(event);
|
|
6003
|
+
} catch {
|
|
6004
|
+
}
|
|
6005
|
+
}
|
|
6006
|
+
async buildCompactHistoryMessagesWithLifecycle(state, userContent, sessionIndex, details) {
|
|
6007
|
+
const baseEvent = {
|
|
6008
|
+
mode: details.mode,
|
|
6009
|
+
strategy: details.strategy,
|
|
6010
|
+
sessionIndex: sessionIndex + 1,
|
|
6011
|
+
model: details.model,
|
|
6012
|
+
estimatedTokens: details.beforeTokens,
|
|
6013
|
+
thresholdTokens: details.thresholdTokens,
|
|
6014
|
+
contextLimitTokens: details.contextLimitTokens,
|
|
6015
|
+
effectiveInputBudgetTokens: details.effectiveInputBudgetTokens,
|
|
6016
|
+
reservedOutputTokens: details.reservedOutputTokens,
|
|
6017
|
+
beforeTokens: details.beforeTokens,
|
|
6018
|
+
afterTokens: details.afterTokens,
|
|
6019
|
+
breakdown: details.breakdown
|
|
6020
|
+
};
|
|
6021
|
+
await this.emitContextCompactionEvent(details.onContextCompaction, {
|
|
6022
|
+
phase: "start",
|
|
6023
|
+
...baseEvent
|
|
6024
|
+
});
|
|
6025
|
+
const compactMessages = this.buildCompactHistoryMessages(
|
|
6026
|
+
state,
|
|
6027
|
+
userContent,
|
|
6028
|
+
details.compactInstructions,
|
|
6029
|
+
details.mode
|
|
6030
|
+
);
|
|
6031
|
+
await this.emitContextCompactionEvent(details.onContextCompaction, {
|
|
6032
|
+
phase: "complete",
|
|
6033
|
+
...baseEvent
|
|
6034
|
+
});
|
|
6035
|
+
return compactMessages;
|
|
6036
|
+
}
|
|
6037
|
+
buildCompactHistoryMessages(state, userContent, compactInstructions, mode = "auto") {
|
|
6038
|
+
const summary = this.generateCompactSummary(state, compactInstructions);
|
|
6039
|
+
const prefix = mode === "forced" ? _AgentsEndpoint.FORCED_COMPACT_SUMMARY_PREFIX : _AgentsEndpoint.AUTO_COMPACT_SUMMARY_PREFIX;
|
|
6040
|
+
return [
|
|
6041
|
+
{
|
|
6042
|
+
role: "system",
|
|
6043
|
+
content: `${prefix}
|
|
6044
|
+
|
|
6045
|
+
${summary}
|
|
6046
|
+
|
|
6047
|
+
Do NOT redo any of the above work.`
|
|
6048
|
+
},
|
|
6049
|
+
{
|
|
6050
|
+
role: "user",
|
|
6051
|
+
content: userContent
|
|
6052
|
+
}
|
|
6053
|
+
];
|
|
6054
|
+
}
|
|
6055
|
+
isCompactHistoryMessageSet(messages) {
|
|
6056
|
+
if (messages.length === 0) return false;
|
|
6057
|
+
const firstMessage = messages[0];
|
|
6058
|
+
return firstMessage?.role === "system" && typeof firstMessage.content === "string" && (firstMessage.content.startsWith(_AgentsEndpoint.AUTO_COMPACT_SUMMARY_PREFIX) || firstMessage.content.startsWith(_AgentsEndpoint.FORCED_COMPACT_SUMMARY_PREFIX));
|
|
6059
|
+
}
|
|
5729
6060
|
/**
|
|
5730
6061
|
* Generate a compact summary of prior work for continuation context.
|
|
5731
6062
|
* Used when compact mode is enabled to keep token usage low.
|
|
5732
6063
|
*/
|
|
5733
|
-
generateCompactSummary(state) {
|
|
5734
|
-
const
|
|
5735
|
-
|
|
6064
|
+
generateCompactSummary(state, compactInstructions) {
|
|
6065
|
+
const recentSessions = (state.sessions ?? []).slice(-5);
|
|
6066
|
+
const sessionSummaries = recentSessions.map(
|
|
6067
|
+
(session) => `- Session ${session.index}: ${session.stopReason} ($${session.cost.toFixed(4)}) ${session.outputPreview.slice(0, 160)}`
|
|
5736
6068
|
).join("\n");
|
|
6069
|
+
const candidatePaths = Array.from(
|
|
6070
|
+
new Set(
|
|
6071
|
+
[
|
|
6072
|
+
...state.bestCandidatePath ? [state.bestCandidatePath] : [],
|
|
6073
|
+
...state.candidatePaths ?? []
|
|
6074
|
+
].filter(Boolean)
|
|
6075
|
+
)
|
|
6076
|
+
).slice(0, 8);
|
|
6077
|
+
const verificationSummary = state.bestCandidateVerified ? "Latest candidate verified." : state.bestCandidateNeedsVerification ? "Latest candidate still needs verification." : state.lastVerificationPassed ? "Latest verification passed." : state.verificationRequired ? "Verification is still required." : "No verification requirement recorded.";
|
|
6078
|
+
const artifactReferences = this.extractArtifactReferences(state);
|
|
6079
|
+
const pendingNextStep = state.lastStopReason === "complete" ? "Confirm nothing else remains before declaring the task complete." : `Continue the ${state.workflowPhase || "research"} phase without redoing prior work.`;
|
|
6080
|
+
const instructions = compactInstructions || this.buildDefaultCompactInstructions();
|
|
5737
6081
|
return [
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
...
|
|
6082
|
+
"Task + Phase",
|
|
6083
|
+
`- Task: ${state.taskName}`,
|
|
6084
|
+
`- Status: ${state.status}`,
|
|
6085
|
+
`- Workflow phase: ${state.workflowPhase || "research"}`,
|
|
6086
|
+
`- Sessions completed: ${state.sessionCount}`,
|
|
6087
|
+
`- Total cost: $${state.totalCost.toFixed(4)}`,
|
|
6088
|
+
"",
|
|
6089
|
+
"Completed Work",
|
|
6090
|
+
...sessionSummaries ? [sessionSummaries] : ["- No completed session summaries recorded yet."],
|
|
6091
|
+
"",
|
|
6092
|
+
"Changed Files / Candidate Paths",
|
|
6093
|
+
...candidatePaths.length > 0 ? candidatePaths.map((candidatePath) => `- ${candidatePath}`) : ["- No candidate paths recorded yet."],
|
|
6094
|
+
...state.planPath ? [`- Plan path: ${state.planPath}`] : [],
|
|
6095
|
+
...state.planWritten ? ["- Planning artifact has been written."] : [],
|
|
6096
|
+
...state.bestCandidateReason ? [`- Best candidate rationale: ${state.bestCandidateReason}`] : [],
|
|
6097
|
+
"",
|
|
6098
|
+
"Verification Status",
|
|
6099
|
+
`- ${verificationSummary}`,
|
|
6100
|
+
...state.lastError ? [`- Last error: ${state.lastError}`] : [],
|
|
6101
|
+
"",
|
|
6102
|
+
"Pending Next Step",
|
|
6103
|
+
`- ${pendingNextStep}`,
|
|
5750
6104
|
"",
|
|
5751
|
-
"
|
|
5752
|
-
|
|
6105
|
+
"Artifact / Tool Output References",
|
|
6106
|
+
...artifactReferences.length > 0 ? artifactReferences.map((reference) => `- ${reference}`) : ["- No offloaded artifacts recorded."],
|
|
5753
6107
|
"",
|
|
5754
|
-
"
|
|
5755
|
-
|
|
6108
|
+
"Compaction Instructions",
|
|
6109
|
+
`- ${instructions}`,
|
|
6110
|
+
"",
|
|
6111
|
+
"Last Output (truncated)",
|
|
6112
|
+
(state.lastOutput || "").slice(0, 1800) || "- No final output recorded yet."
|
|
5756
6113
|
].join("\n");
|
|
5757
6114
|
}
|
|
5758
6115
|
/**
|
|
5759
6116
|
* Build messages for a session, injecting progress context for continuation sessions.
|
|
5760
6117
|
* Optionally accepts continuation context for marathon resume scenarios.
|
|
5761
6118
|
*/
|
|
5762
|
-
buildSessionMessages(originalMessage, state, sessionIndex, maxSessions, localToolNames, continuationContext, workflow, builtinToolIds) {
|
|
6119
|
+
async buildSessionMessages(originalMessage, state, sessionIndex, maxSessions, localToolNames, continuationContext, workflow, builtinToolIds, compactionOptions) {
|
|
6120
|
+
const prepared = await this.prepareSessionContext(
|
|
6121
|
+
originalMessage,
|
|
6122
|
+
state,
|
|
6123
|
+
sessionIndex,
|
|
6124
|
+
maxSessions,
|
|
6125
|
+
localToolNames,
|
|
6126
|
+
continuationContext,
|
|
6127
|
+
workflow,
|
|
6128
|
+
builtinToolIds,
|
|
6129
|
+
compactionOptions
|
|
6130
|
+
);
|
|
6131
|
+
return prepared.messages;
|
|
6132
|
+
}
|
|
6133
|
+
async prepareSessionContext(originalMessage, state, sessionIndex, maxSessions, localToolNames, continuationContext, workflow, builtinToolIds, compactionOptions) {
|
|
5763
6134
|
const wf = workflow ?? defaultWorkflow;
|
|
6135
|
+
const compactInstructions = compactionOptions?.compactInstructions;
|
|
6136
|
+
const resolvedStrategy = continuationContext?.compact ? "summary_fallback" : this.resolveCompactStrategy(compactionOptions?.compactStrategy, compactionOptions?.model);
|
|
6137
|
+
const requestContextManagement = resolvedStrategy === "provider_native" && typeof compactionOptions?.autoCompactTokenThreshold === "number" && compactionOptions.autoCompactTokenThreshold > 0 ? {
|
|
6138
|
+
compactStrategy: resolvedStrategy,
|
|
6139
|
+
...compactInstructions ? { compactInstructions } : {},
|
|
6140
|
+
nativeCompaction: {
|
|
6141
|
+
provider: "anthropic",
|
|
6142
|
+
thresholdTokens: compactionOptions.autoCompactTokenThreshold
|
|
6143
|
+
}
|
|
6144
|
+
} : void 0;
|
|
6145
|
+
const maybeEmitToolDefinitionWarning = async (breakdown) => {
|
|
6146
|
+
if (sessionIndex !== 0) return;
|
|
6147
|
+
if (typeof compactionOptions?.contextLimitTokens !== "number" || compactionOptions.contextLimitTokens <= 0) {
|
|
6148
|
+
return;
|
|
6149
|
+
}
|
|
6150
|
+
if (breakdown.toolDefinitionTokens <= 0) return;
|
|
6151
|
+
const ratio = breakdown.toolDefinitionTokens / compactionOptions.contextLimitTokens;
|
|
6152
|
+
if (ratio < 0.1) return;
|
|
6153
|
+
await this.emitContextNotice(compactionOptions?.onContextNotice, {
|
|
6154
|
+
kind: "tool_definitions_warning",
|
|
6155
|
+
sessionIndex: sessionIndex + 1,
|
|
6156
|
+
model: compactionOptions?.model,
|
|
6157
|
+
message: `Tool definitions consume about ${(ratio * 100).toFixed(1)}% of the ${compactionOptions.contextLimitTokens.toLocaleString()} token context window. Reduce the enabled tool set if context pressure remains high.`,
|
|
6158
|
+
estimatedTokens: breakdown.toolDefinitionTokens,
|
|
6159
|
+
contextLimitTokens: compactionOptions.contextLimitTokens,
|
|
6160
|
+
effectiveInputBudgetTokens: breakdown.effectiveInputBudgetTokens,
|
|
6161
|
+
reservedOutputTokens: breakdown.reservedOutputTokens
|
|
6162
|
+
});
|
|
6163
|
+
};
|
|
6164
|
+
const buildNativeCompactionEvent = (mode, breakdown) => {
|
|
6165
|
+
if (resolvedStrategy !== "provider_native" || typeof compactionOptions?.autoCompactTokenThreshold !== "number" || compactionOptions.autoCompactTokenThreshold <= 0 || breakdown.estimatedInputTokens < compactionOptions.autoCompactTokenThreshold) {
|
|
6166
|
+
return void 0;
|
|
6167
|
+
}
|
|
6168
|
+
return {
|
|
6169
|
+
mode,
|
|
6170
|
+
strategy: resolvedStrategy,
|
|
6171
|
+
sessionIndex: sessionIndex + 1,
|
|
6172
|
+
model: compactionOptions?.model,
|
|
6173
|
+
estimatedTokens: breakdown.estimatedInputTokens,
|
|
6174
|
+
thresholdTokens: compactionOptions.autoCompactTokenThreshold,
|
|
6175
|
+
contextLimitTokens: compactionOptions.contextLimitTokens,
|
|
6176
|
+
effectiveInputBudgetTokens: breakdown.effectiveInputBudgetTokens,
|
|
6177
|
+
reservedOutputTokens: breakdown.reservedOutputTokens,
|
|
6178
|
+
beforeTokens: breakdown.estimatedInputTokens,
|
|
6179
|
+
breakdown
|
|
6180
|
+
};
|
|
6181
|
+
};
|
|
5764
6182
|
const currentPhase = wf.phases.find((p) => p.name === state.workflowPhase);
|
|
5765
6183
|
const toolGuidanceLines = currentPhase?.buildToolGuidance(state) ?? [];
|
|
5766
6184
|
const isDeployWorkflow = wf.name === "deploy";
|
|
@@ -5789,25 +6207,16 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
5789
6207
|
if (continuationContext && sessionIndex === 0) {
|
|
5790
6208
|
const defaultContinueMessage = "Continue the task. Review your prior work above and proceed with any remaining work. If everything is already complete, respond with TASK_COMPLETE.";
|
|
5791
6209
|
const userMessage = continuationContext.newUserMessage || defaultContinueMessage;
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
},
|
|
5803
|
-
{
|
|
5804
|
-
role: "user",
|
|
5805
|
-
content: [userMessage, phaseBlock, toolsBlock, bootstrapBlock, candidateBlock, "", multiSessionInstruction].join("\n")
|
|
5806
|
-
}
|
|
5807
|
-
];
|
|
5808
|
-
return messages2;
|
|
5809
|
-
}
|
|
5810
|
-
const messages = [
|
|
6210
|
+
const userContent = [
|
|
6211
|
+
userMessage,
|
|
6212
|
+
phaseBlock,
|
|
6213
|
+
toolsBlock,
|
|
6214
|
+
bootstrapBlock,
|
|
6215
|
+
candidateBlock,
|
|
6216
|
+
"",
|
|
6217
|
+
multiSessionInstruction
|
|
6218
|
+
].join("\n");
|
|
6219
|
+
const fullHistoryMessages = [
|
|
5811
6220
|
...continuationContext.previousMessages,
|
|
5812
6221
|
{
|
|
5813
6222
|
role: "system",
|
|
@@ -5815,14 +6224,79 @@ Do NOT redo any of the above work.`
|
|
|
5815
6224
|
},
|
|
5816
6225
|
{
|
|
5817
6226
|
role: "user",
|
|
5818
|
-
content:
|
|
6227
|
+
content: userContent
|
|
5819
6228
|
}
|
|
5820
6229
|
];
|
|
5821
|
-
|
|
6230
|
+
const summaryText = this.generateCompactSummary(state, compactInstructions);
|
|
6231
|
+
const breakdown = this.buildContextBudgetBreakdown({
|
|
6232
|
+
historyMessages: continuationContext.previousMessages,
|
|
6233
|
+
currentTurnContent: userContent,
|
|
6234
|
+
localTools: compactionOptions?.localTools,
|
|
6235
|
+
builtinToolSchemas: compactionOptions?.builtinToolSchemas || [],
|
|
6236
|
+
summaryText,
|
|
6237
|
+
contextLimitTokens: compactionOptions?.contextLimitTokens
|
|
6238
|
+
});
|
|
6239
|
+
await maybeEmitToolDefinitionWarning(breakdown);
|
|
6240
|
+
if (continuationContext.compact) {
|
|
6241
|
+
return {
|
|
6242
|
+
messages: await this.buildCompactHistoryMessagesWithLifecycle(
|
|
6243
|
+
state,
|
|
6244
|
+
userContent,
|
|
6245
|
+
sessionIndex,
|
|
6246
|
+
{
|
|
6247
|
+
mode: "forced",
|
|
6248
|
+
strategy: "summary_fallback",
|
|
6249
|
+
model: compactionOptions?.model,
|
|
6250
|
+
beforeTokens: breakdown.estimatedInputTokens,
|
|
6251
|
+
afterTokens: (breakdown.summaryTokens || 0) + breakdown.currentTurnTokens + breakdown.toolDefinitionTokens,
|
|
6252
|
+
thresholdTokens: compactionOptions?.autoCompactTokenThreshold,
|
|
6253
|
+
contextLimitTokens: compactionOptions?.contextLimitTokens,
|
|
6254
|
+
effectiveInputBudgetTokens: breakdown.effectiveInputBudgetTokens,
|
|
6255
|
+
reservedOutputTokens: breakdown.reservedOutputTokens,
|
|
6256
|
+
breakdown,
|
|
6257
|
+
onContextCompaction: compactionOptions?.onContextCompaction,
|
|
6258
|
+
compactInstructions
|
|
6259
|
+
}
|
|
6260
|
+
),
|
|
6261
|
+
requestContextManagement
|
|
6262
|
+
};
|
|
6263
|
+
}
|
|
6264
|
+
if (resolvedStrategy === "summary_fallback" && typeof compactionOptions?.autoCompactTokenThreshold === "number" && compactionOptions.autoCompactTokenThreshold > 0 && breakdown.estimatedInputTokens >= compactionOptions.autoCompactTokenThreshold) {
|
|
6265
|
+
return {
|
|
6266
|
+
messages: await this.buildCompactHistoryMessagesWithLifecycle(
|
|
6267
|
+
state,
|
|
6268
|
+
userContent,
|
|
6269
|
+
sessionIndex,
|
|
6270
|
+
{
|
|
6271
|
+
mode: "auto",
|
|
6272
|
+
strategy: "summary_fallback",
|
|
6273
|
+
model: compactionOptions?.model,
|
|
6274
|
+
beforeTokens: breakdown.estimatedInputTokens,
|
|
6275
|
+
afterTokens: (breakdown.summaryTokens || 0) + breakdown.currentTurnTokens + breakdown.toolDefinitionTokens,
|
|
6276
|
+
thresholdTokens: compactionOptions?.autoCompactTokenThreshold,
|
|
6277
|
+
contextLimitTokens: compactionOptions?.contextLimitTokens,
|
|
6278
|
+
effectiveInputBudgetTokens: breakdown.effectiveInputBudgetTokens,
|
|
6279
|
+
reservedOutputTokens: breakdown.reservedOutputTokens,
|
|
6280
|
+
breakdown,
|
|
6281
|
+
onContextCompaction: compactionOptions?.onContextCompaction,
|
|
6282
|
+
compactInstructions
|
|
6283
|
+
}
|
|
6284
|
+
),
|
|
6285
|
+
requestContextManagement
|
|
6286
|
+
};
|
|
6287
|
+
}
|
|
6288
|
+
return {
|
|
6289
|
+
messages: fullHistoryMessages,
|
|
6290
|
+
requestContextManagement,
|
|
6291
|
+
pendingNativeCompactionEvent: buildNativeCompactionEvent("auto", breakdown)
|
|
6292
|
+
};
|
|
5822
6293
|
}
|
|
5823
6294
|
if (sessionIndex === 0) {
|
|
5824
6295
|
const content2 = [originalMessage, phaseBlock, toolsBlock, bootstrapBlock, candidateBlock, "", multiSessionInstruction].join("\n");
|
|
5825
|
-
return
|
|
6296
|
+
return {
|
|
6297
|
+
messages: [{ role: "user", content: content2 }],
|
|
6298
|
+
requestContextManagement
|
|
6299
|
+
};
|
|
5826
6300
|
}
|
|
5827
6301
|
const recentSessions = state.sessions.slice(-5);
|
|
5828
6302
|
const progressSummary = recentSessions.map(
|
|
@@ -5856,10 +6330,49 @@ Do NOT redo any of the above work.`
|
|
|
5856
6330
|
...historyMessages.slice(-MAX_HISTORY_MESSAGES)
|
|
5857
6331
|
];
|
|
5858
6332
|
}
|
|
5859
|
-
|
|
6333
|
+
const summaryText = this.generateCompactSummary(state, compactInstructions);
|
|
6334
|
+
const breakdown = this.buildContextBudgetBreakdown({
|
|
6335
|
+
historyMessages,
|
|
6336
|
+
currentTurnContent: continuationContent,
|
|
6337
|
+
localTools: compactionOptions?.localTools,
|
|
6338
|
+
builtinToolSchemas: compactionOptions?.builtinToolSchemas || [],
|
|
6339
|
+
summaryText,
|
|
6340
|
+
contextLimitTokens: compactionOptions?.contextLimitTokens
|
|
6341
|
+
});
|
|
6342
|
+
await maybeEmitToolDefinitionWarning(breakdown);
|
|
6343
|
+
const messages = [
|
|
5860
6344
|
...historyMessages,
|
|
5861
6345
|
{ role: "user", content: continuationContent }
|
|
5862
6346
|
];
|
|
6347
|
+
if (resolvedStrategy === "summary_fallback" && typeof compactionOptions?.autoCompactTokenThreshold === "number" && compactionOptions.autoCompactTokenThreshold > 0 && breakdown.estimatedInputTokens >= compactionOptions.autoCompactTokenThreshold) {
|
|
6348
|
+
return {
|
|
6349
|
+
messages: await this.buildCompactHistoryMessagesWithLifecycle(
|
|
6350
|
+
state,
|
|
6351
|
+
continuationContent,
|
|
6352
|
+
sessionIndex,
|
|
6353
|
+
{
|
|
6354
|
+
mode: "auto",
|
|
6355
|
+
strategy: "summary_fallback",
|
|
6356
|
+
model: compactionOptions?.model,
|
|
6357
|
+
beforeTokens: breakdown.estimatedInputTokens,
|
|
6358
|
+
afterTokens: (breakdown.summaryTokens || 0) + breakdown.currentTurnTokens + breakdown.toolDefinitionTokens,
|
|
6359
|
+
thresholdTokens: compactionOptions?.autoCompactTokenThreshold,
|
|
6360
|
+
contextLimitTokens: compactionOptions?.contextLimitTokens,
|
|
6361
|
+
effectiveInputBudgetTokens: breakdown.effectiveInputBudgetTokens,
|
|
6362
|
+
reservedOutputTokens: breakdown.reservedOutputTokens,
|
|
6363
|
+
breakdown,
|
|
6364
|
+
onContextCompaction: compactionOptions?.onContextCompaction,
|
|
6365
|
+
compactInstructions
|
|
6366
|
+
}
|
|
6367
|
+
),
|
|
6368
|
+
requestContextManagement
|
|
6369
|
+
};
|
|
6370
|
+
}
|
|
6371
|
+
return {
|
|
6372
|
+
messages,
|
|
6373
|
+
requestContextManagement,
|
|
6374
|
+
pendingNativeCompactionEvent: buildNativeCompactionEvent("auto", breakdown)
|
|
6375
|
+
};
|
|
5863
6376
|
}
|
|
5864
6377
|
const recoveryMessage = this.buildStuckTurnRecoveryMessage(state, wf);
|
|
5865
6378
|
const content = [
|
|
@@ -5879,7 +6392,10 @@ Do NOT redo any of the above work.`
|
|
|
5879
6392
|
"",
|
|
5880
6393
|
"Continue where you left off. Do not redo previous work. If the task is already complete, respond with TASK_COMPLETE."
|
|
5881
6394
|
].join("\n");
|
|
5882
|
-
return
|
|
6395
|
+
return {
|
|
6396
|
+
messages: [{ role: "user", content }],
|
|
6397
|
+
requestContextManagement
|
|
6398
|
+
};
|
|
5883
6399
|
}
|
|
5884
6400
|
/**
|
|
5885
6401
|
* Upsert a record to sync long-task progress to the dashboard.
|
|
@@ -5929,6 +6445,8 @@ Do NOT redo any of the above work.`
|
|
|
5929
6445
|
}
|
|
5930
6446
|
}
|
|
5931
6447
|
};
|
|
6448
|
+
_AgentsEndpoint.AUTO_COMPACT_SUMMARY_PREFIX = "You are continuing a long-running task. Here is a compact summary of prior work:";
|
|
6449
|
+
_AgentsEndpoint.FORCED_COMPACT_SUMMARY_PREFIX = "You are continuing a previously completed task. Here is a summary of prior work:";
|
|
5932
6450
|
/** Stop phrases that indicate the agent considers its task complete. */
|
|
5933
6451
|
_AgentsEndpoint.STOP_PHRASES = [
|
|
5934
6452
|
"DONE:",
|