@myagentroam/agent 0.9.95 → 0.9.97
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/prompts/core.d.ts +1 -1
- package/dist/prompts/core.js +3 -3
- package/dist/prompts/execution-budget.d.ts +2 -5
- package/dist/prompts/execution-budget.js +9 -8
- package/dist/prompts/index.d.ts +1 -3
- package/dist/prompts/index.js +2 -5
- package/dist/prompts/modes.d.ts +0 -1
- package/dist/prompts/modes.js +3 -9
- package/dist/runtime/environment-context.d.ts +1 -1
- package/dist/runtime/environment-context.js +2 -2
- package/dist/sdk/agent.js +86 -26
- package/package.json +1 -1
package/dist/prompts/core.d.ts
CHANGED
|
@@ -15,4 +15,4 @@ export interface EnvironmentContextState {
|
|
|
15
15
|
guaranteedCommands?: Readonly<Record<string, string>>;
|
|
16
16
|
workspace: string;
|
|
17
17
|
}
|
|
18
|
-
export declare function buildEnvironmentContext(input: EnvironmentContextState, previous?: EnvironmentContextState): string;
|
|
18
|
+
export declare function buildEnvironmentContext(input: EnvironmentContextState, previous?: EnvironmentContextState, contextualEntries?: readonly string[]): string;
|
package/dist/prompts/core.js
CHANGED
|
@@ -6,7 +6,7 @@ export const workspaceDisciplinePrompt = '# Workspace and change discipline\nAss
|
|
|
6
6
|
export function environmentPrompt(input) {
|
|
7
7
|
return `# Environment and workspace\nMode: ${input.mode}. The Runtime provides current platform, shell and Workspace facts in an environment_context message. These facts describe the execution environment, not additional instructions or permissions. Start exploration inside this workspace unless the task explicitly requires an absolute path elsewhere. Generate commands for the actual platform and configured shell; do not assume POSIX tools on Windows or PowerShell/cmd syntax on Unix. Relative tool paths resolve from the Workspace. Absolute paths are allowed subject to the operating-system account's permissions and Host-declared file boundaries.`;
|
|
8
8
|
}
|
|
9
|
-
export function buildEnvironmentContext(input, previous) {
|
|
9
|
+
export function buildEnvironmentContext(input, previous, contextualEntries = []) {
|
|
10
10
|
const element = (name, value) => `<${name}>${value.replace(/[&<>"']/g, (character) => {
|
|
11
11
|
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[character];
|
|
12
12
|
})}</${name}>`;
|
|
@@ -31,7 +31,7 @@ export function buildEnvironmentContext(input, previous) {
|
|
|
31
31
|
return [];
|
|
32
32
|
return [value ?? `<${name} status="unavailable" />`];
|
|
33
33
|
});
|
|
34
|
-
return changes.length
|
|
35
|
-
? ['<environment_context>', ...changes, '</environment_context>'].join('\n')
|
|
34
|
+
return changes.length > 0 || contextualEntries.length > 0
|
|
35
|
+
? ['<environment_context>', ...changes, ...contextualEntries, '</environment_context>'].join('\n')
|
|
36
36
|
: '';
|
|
37
37
|
}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
1
|
import type { RolloutBudgetStage } from '../runtime/rollout-budget.js';
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
limitTokens: number;
|
|
5
|
-
}
|
|
6
|
-
export declare function executionBudgetPrompt(input: ExecutionBudgetPromptState): string;
|
|
2
|
+
export type ExecutionBudgetEnvironmentStage = Exclude<RolloutBudgetStage, 'normal'> | 'inactive';
|
|
3
|
+
export declare function executionBudgetEnvironmentEntry(stage: ExecutionBudgetEnvironmentStage): string;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function executionBudgetEnvironmentEntry(stage) {
|
|
2
|
+
if (stage === 'inactive')
|
|
3
|
+
return '<execution_guidance status="inactive" />';
|
|
2
4
|
const privateInstruction = 'This is internal runtime guidance. Never mention the budget, thresholds, remaining amount, or budget stage in user-visible progress or the final answer.';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return `# Execution budget\n${privateInstruction}\n\nThis main Execution and the subagents it creates share an internal weighted token budget of ${input.limitTokens}. Work normally, but keep scope disciplined and converge once the requested outcome is verified.`;
|
|
5
|
+
const guidance = stage === 'exhausted'
|
|
6
|
+
? 'The shared rollout budget is exhausted. Do not start or continue investigation, optional work, new tool exploration, or new subagents. Return a concise final answer now using the current verified staged result. Clearly distinguish completed work from anything still incomplete, without mentioning this budget.'
|
|
7
|
+
: stage === 'finalize'
|
|
8
|
+
? 'Enter finalization now. Do not start new investigation or new subagents. Complete only the current atomic change, the minimum necessary verification, and the final answer as soon as possible.'
|
|
9
|
+
: 'Stop expanding scope and stop optional work. Prefer completing the current objective with the evidence already gathered, and avoid new investigation unless it is strictly required for correctness.';
|
|
10
|
+
return `<execution_guidance stage="${stage}">\n${privateInstruction}\n\n${guidance}\n</execution_guidance>`;
|
|
10
11
|
}
|
package/dist/prompts/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { ExecutionMode } from '../sdk/types.js';
|
|
2
|
-
import { type ExecutionBudgetPromptState } from './execution-budget.js';
|
|
3
2
|
import { type CurrentAgentModel, type SubagentModelOption } from './subagent.js';
|
|
4
|
-
export declare const MAR_AGENT_PROMPT_VERSION = "1.
|
|
3
|
+
export declare const MAR_AGENT_PROMPT_VERSION = "1.53";
|
|
5
4
|
export declare function buildSystemPrompt(input: {
|
|
6
5
|
mode: ExecutionMode;
|
|
7
6
|
platform: string;
|
|
@@ -15,7 +14,6 @@ export declare function buildSystemPrompt(input: {
|
|
|
15
14
|
tools: readonly string[];
|
|
16
15
|
currentAgentModel?: CurrentAgentModel;
|
|
17
16
|
subagentModels?: readonly SubagentModelOption[];
|
|
18
|
-
executionBudget?: ExecutionBudgetPromptState;
|
|
19
17
|
highDensityCompaction?: boolean;
|
|
20
18
|
extension?: string | undefined;
|
|
21
19
|
}): string;
|
package/dist/prompts/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { compactionPrompt, highDensityCompactionPrompt } from './compact.js';
|
|
2
2
|
import { environmentPrompt, identityPrompt, instructionPriorityPrompt, workspaceDisciplinePrompt } from './core.js';
|
|
3
|
-
import { executionBudgetPrompt } from './execution-budget.js';
|
|
4
3
|
import { modePrompt } from './modes.js';
|
|
5
4
|
import { outputStylePrompt } from './output.js';
|
|
6
5
|
import { subagentModelOptionsPrompt, subagentPrompt, currentAgentModelPrompt } from './subagent.js';
|
|
7
6
|
import { interactionPrompt, longRunningPrompt, safetyPrompt, toolUsagePrompt, workflowPrompt } from './workflow.js';
|
|
8
|
-
export const MAR_AGENT_PROMPT_VERSION = '1.
|
|
7
|
+
export const MAR_AGENT_PROMPT_VERSION = '1.53';
|
|
9
8
|
export function buildSystemPrompt(input) {
|
|
10
9
|
const toolNames = new Set(input.tools);
|
|
11
10
|
const hasLongRunningCapability = [
|
|
@@ -27,10 +26,8 @@ export function buildSystemPrompt(input) {
|
|
|
27
26
|
environmentPrompt(input),
|
|
28
27
|
input.tools.length > 0 ? toolUsagePrompt(input.tools) : '',
|
|
29
28
|
hasLongRunningCapability ? longRunningPrompt(input.tools) : '',
|
|
30
|
-
input.executionBudget ? executionBudgetPrompt(input.executionBudget) : '',
|
|
31
29
|
modePrompt(input.mode, {
|
|
32
|
-
questionAvailable: toolNames.has('question')
|
|
33
|
-
forceFinalize: input.executionBudget?.stage === 'exhausted'
|
|
30
|
+
questionAvailable: toolNames.has('question')
|
|
34
31
|
}),
|
|
35
32
|
input.mode === 'compact'
|
|
36
33
|
? input.highDensityCompaction
|
package/dist/prompts/modes.d.ts
CHANGED
package/dist/prompts/modes.js
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
export function modePrompt(mode, input) {
|
|
2
2
|
if (mode !== 'plan')
|
|
3
3
|
return '';
|
|
4
|
-
const investigationGuidance =
|
|
5
|
-
? 'Use only evidence already gathered; do not start or continue Plan exploration.'
|
|
6
|
-
: 'Resolve discoverable facts through targeted read-only investigation. Ask about user-owned preferences and tradeoffs early when they cannot be inferred from the request, conversation, or workspace evidence.';
|
|
4
|
+
const investigationGuidance = 'Resolve discoverable facts through targeted read-only investigation. Ask about user-owned preferences and tradeoffs early when they cannot be inferred from the request, conversation, or workspace evidence. If current environment guidance requires finalization, stop further exploration and use only evidence already gathered.';
|
|
7
5
|
const decisionGuidance = input.questionAvailable
|
|
8
6
|
? 'Use question for unresolved choices that materially change the result; do not finalize the plan while such choices remain. Do not invent support for multiple outcomes or silently choose a default to avoid asking.'
|
|
9
|
-
: input.
|
|
10
|
-
|
|
11
|
-
: 'Ask a concise plain-text question for unresolved user-owned choices that materially change the result instead of finalizing an ambiguous plan. Do not invent support for multiple outcomes or silently choose a default.';
|
|
12
|
-
const finalGuidance = input.forceFinalize
|
|
13
|
-
? 'Return only the concise staged plan now, distinguishing verified conclusions from incomplete work and unresolved decisions. Do not ask whether to proceed or claim unresolved work is complete.'
|
|
14
|
-
: 'Once the plan is decision-complete, return only a concise, actionable plan. Break the work into meaningful, logically ordered deliverables that are easy to verify. Do not pad the plan with filler or obvious steps. Include the implementation and verification detail needed to execute it, without drafting the implementation itself. Do not ask whether to proceed or claim planned work is completed.';
|
|
7
|
+
: 'Ask a concise plain-text question for unresolved user-owned choices that materially change the result instead of finalizing an ambiguous plan. When current environment guidance requires finalization and user input is unavailable, state the unresolved decision and its impact instead of guessing. Do not invent support for multiple outcomes or silently choose a default.';
|
|
8
|
+
const finalGuidance = 'Once the plan is decision-complete, return only a concise, actionable plan. Break the work into meaningful, logically ordered deliverables that are easy to verify. Do not pad the plan with filler or obvious steps. Include the implementation and verification detail needed to execute it, without drafting the implementation itself. When current environment guidance requires finalization, return the concise verified staged plan and distinguish incomplete work or unresolved decisions. Do not ask whether to proceed or claim unresolved work is complete.';
|
|
15
9
|
return `# Plan mode
|
|
16
10
|
Use tools only for read-only investigation that reduces uncertainty and improves the plan. Do not create, modify, delete, rename, or move files, and do not run commands intended to mutate repository-tracked state or implement the requested work. This is behavioral guidance, not a security boundary; the normal tools and Host policies remain available.
|
|
17
11
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ModelMessage } from '../model/contracts.js';
|
|
2
2
|
import { type EnvironmentContextState } from '../prompts/core.js';
|
|
3
3
|
export declare function restoreEnvironmentState(payload: unknown): EnvironmentContextState | undefined;
|
|
4
|
-
export declare function environmentContextUpdate(current: EnvironmentContextState, previous?: EnvironmentContextState): ModelMessage | undefined;
|
|
4
|
+
export declare function environmentContextUpdate(current: EnvironmentContextState, previous?: EnvironmentContextState, contextualEntries?: readonly string[]): ModelMessage | undefined;
|
|
@@ -35,7 +35,7 @@ export function restoreEnvironmentState(payload) {
|
|
|
35
35
|
...(guaranteedCommands === undefined ? {} : { guaranteedCommands })
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
|
-
export function environmentContextUpdate(current, previous) {
|
|
39
|
-
const content = buildEnvironmentContext(current, previous);
|
|
38
|
+
export function environmentContextUpdate(current, previous, contextualEntries = []) {
|
|
39
|
+
const content = buildEnvironmentContext(current, previous, contextualEntries);
|
|
40
40
|
return content ? { role: 'user', contextKind: 'environment', content } : undefined;
|
|
41
41
|
}
|
package/dist/sdk/agent.js
CHANGED
|
@@ -21,6 +21,7 @@ import { buildEnvironmentContext } from '../prompts/core.js';
|
|
|
21
21
|
import { modelOutputContinuationMessage } from '../prompts/output.js';
|
|
22
22
|
import { retainedSessionResourcesSnapshot, retainedSessionResourcesUpdate } from '../prompts/resources.js';
|
|
23
23
|
import { environmentContextUpdate, restoreEnvironmentState } from '../runtime/environment-context.js';
|
|
24
|
+
import { executionBudgetEnvironmentEntry } from '../prompts/execution-budget.js';
|
|
24
25
|
import { childSubagentInstruction } from '../prompts/subagent.js';
|
|
25
26
|
import { sessionTitlePrompt } from '../prompts/title.js';
|
|
26
27
|
import { loadAgentInstructions, renderAgentInstructions } from '../runtime/instructions.js';
|
|
@@ -278,6 +279,20 @@ export async function createMarAgent(options) {
|
|
|
278
279
|
includeImages: mode !== 'compact'
|
|
279
280
|
});
|
|
280
281
|
const messages = restored.messages;
|
|
282
|
+
let projectedExecutionBudgetStage;
|
|
283
|
+
const appendExecutionBudgetEnvironment = () => {
|
|
284
|
+
const currentStage = rolloutBudget?.active ? rolloutBudget.stage : 'inactive';
|
|
285
|
+
if (currentStage === projectedExecutionBudgetStage)
|
|
286
|
+
return;
|
|
287
|
+
const previousStage = projectedExecutionBudgetStage;
|
|
288
|
+
projectedExecutionBudgetStage = currentStage;
|
|
289
|
+
if ((previousStage === undefined &&
|
|
290
|
+
(currentStage === 'normal' || currentStage === 'inactive')) ||
|
|
291
|
+
(currentStage === 'inactive' && previousStage === 'normal'))
|
|
292
|
+
return;
|
|
293
|
+
const entry = executionBudgetEnvironmentEntry(currentStage === 'normal' ? 'inactive' : currentStage);
|
|
294
|
+
messages.push(environmentContextUpdate(currentEnvironment, currentEnvironment, [entry]));
|
|
295
|
+
};
|
|
281
296
|
const appendMailboxMessages = async () => {
|
|
282
297
|
let appended = false;
|
|
283
298
|
while (mailbox.length > 0) {
|
|
@@ -536,14 +551,6 @@ export async function createMarAgent(options) {
|
|
|
536
551
|
}))
|
|
537
552
|
: [],
|
|
538
553
|
highDensityCompaction: selectedModel.highDensityCompaction,
|
|
539
|
-
...(rolloutBudget?.active
|
|
540
|
-
? {
|
|
541
|
-
executionBudget: {
|
|
542
|
-
stage: rolloutBudget.stage,
|
|
543
|
-
limitTokens: rolloutBudget.limitTokens
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
: {}),
|
|
547
554
|
extension: [
|
|
548
555
|
options.systemInstruction,
|
|
549
556
|
instructionContext?.skillCatalog,
|
|
@@ -576,8 +583,7 @@ export async function createMarAgent(options) {
|
|
|
576
583
|
estimatedRequestTokens: estimatedRequestTokens(compactSystemPrompt, nativeMessages, executionTools),
|
|
577
584
|
contextWindowTokens: selectedModel.contextWindowTokens,
|
|
578
585
|
latestUsage: lastServerUsage,
|
|
579
|
-
|
|
580
|
-
lastServerUsage.historyMessageCount === compactHistory.length,
|
|
586
|
+
historyMessages: compactHistory,
|
|
581
587
|
appendedMessages: nativeMessages.slice(projectedHistory.length)
|
|
582
588
|
});
|
|
583
589
|
messages.splice(0, messages.length, ...(useNative ? nativeMessages : fallbackMessages()));
|
|
@@ -611,7 +617,7 @@ export async function createMarAgent(options) {
|
|
|
611
617
|
const current = messages.at(-1);
|
|
612
618
|
if (!current || messages.length < 2)
|
|
613
619
|
return false;
|
|
614
|
-
const retainCurrent = current.role === 'user';
|
|
620
|
+
const retainCurrent = current.role === 'user' && current.contextKind !== 'environment';
|
|
615
621
|
let compactSummary = '';
|
|
616
622
|
const compactSystemPrompt = buildExecutionSystemPrompt(executionTools, 'run');
|
|
617
623
|
const compactHistory = retainCurrent ? messages.slice(0, -1) : messages;
|
|
@@ -627,8 +633,7 @@ export async function createMarAgent(options) {
|
|
|
627
633
|
estimatedRequestTokens: estimatedRequestTokens(compactSystemPrompt, nativeCompactMessages, executionTools),
|
|
628
634
|
contextWindowTokens: selectedModel.contextWindowTokens,
|
|
629
635
|
latestUsage: lastServerUsage,
|
|
630
|
-
|
|
631
|
-
lastServerUsage.historyMessageCount === compactHistory.length,
|
|
636
|
+
historyMessages: compactHistory,
|
|
632
637
|
appendedMessages: nativeCompactMessages.slice(projectedHistory.length)
|
|
633
638
|
});
|
|
634
639
|
const fallbackMessages = () => buildCompactionMessages(buildCompactionInput(compactHistory, {
|
|
@@ -703,6 +708,7 @@ export async function createMarAgent(options) {
|
|
|
703
708
|
});
|
|
704
709
|
contextGc.reset();
|
|
705
710
|
messages.splice(0, messages.length, environmentContextUpdate(currentEnvironment), ...compactedHistoryMessages(replacementHistory));
|
|
711
|
+
projectedExecutionBudgetStage = undefined;
|
|
706
712
|
compactionUserMessages = replacementHistory
|
|
707
713
|
.filter((message) => message.kind === 'user_input')
|
|
708
714
|
.map((message) => message.content);
|
|
@@ -737,12 +743,15 @@ export async function createMarAgent(options) {
|
|
|
737
743
|
const modelRetryState = { attempts: 0 };
|
|
738
744
|
while (true) {
|
|
739
745
|
await appendMailboxMessages();
|
|
746
|
+
appendExecutionBudgetEnvironment();
|
|
740
747
|
let stop;
|
|
741
748
|
let sawTool = false;
|
|
742
749
|
let latestUsage;
|
|
750
|
+
let roundServerUsage;
|
|
743
751
|
const pendingTools = [];
|
|
744
752
|
let incompleteToolCall = false;
|
|
745
753
|
await ensureContextBudget();
|
|
754
|
+
appendExecutionBudgetEnvironment();
|
|
746
755
|
const toolsAllowed = mode !== 'compact' && (!rolloutBudget?.active || rolloutBudget.stage !== 'exhausted');
|
|
747
756
|
const roundTools = mode === 'compact' ? executionTools : toolsAllowed ? executionTools : [];
|
|
748
757
|
const systemPrompt = mode === 'compact'
|
|
@@ -885,14 +894,13 @@ export async function createMarAgent(options) {
|
|
|
885
894
|
Number.isSafeInteger(reportedContext) &&
|
|
886
895
|
reportedContext >= 0) {
|
|
887
896
|
lastServerContextTokens = reportedContext;
|
|
888
|
-
|
|
897
|
+
roundServerUsage = {
|
|
889
898
|
contextInputTokens: reportedContext,
|
|
890
899
|
outputTokens: typeof event.usage.outputTokens === 'number' &&
|
|
891
900
|
Number.isSafeInteger(event.usage.outputTokens) &&
|
|
892
901
|
event.usage.outputTokens >= 0
|
|
893
902
|
? event.usage.outputTokens
|
|
894
|
-
: undefined
|
|
895
|
-
historyMessageCount: messages.length
|
|
903
|
+
: undefined
|
|
896
904
|
};
|
|
897
905
|
}
|
|
898
906
|
await emit({ type: 'usage.updated', ...publicModelUsage(event.usage) });
|
|
@@ -973,6 +981,11 @@ export async function createMarAgent(options) {
|
|
|
973
981
|
throw error;
|
|
974
982
|
}
|
|
975
983
|
recoveringFromContextOverflow = false;
|
|
984
|
+
if (roundServerUsage !== undefined)
|
|
985
|
+
lastServerUsage = {
|
|
986
|
+
...roundServerUsage,
|
|
987
|
+
historyMessages: [...messages]
|
|
988
|
+
};
|
|
976
989
|
if (pendingTools.length === 0 && mailbox.length > 0) {
|
|
977
990
|
await appendMailboxMessages();
|
|
978
991
|
finalAnswer = '';
|
|
@@ -1155,6 +1168,7 @@ export async function createMarAgent(options) {
|
|
|
1155
1168
|
projection: committed.projection
|
|
1156
1169
|
});
|
|
1157
1170
|
messages.splice(0, messages.length, ...refreshed.messages);
|
|
1171
|
+
projectedExecutionBudgetStage = undefined;
|
|
1158
1172
|
compactionUserMessages = [...refreshed.userMessages];
|
|
1159
1173
|
agentInstructionInsertIndex =
|
|
1160
1174
|
refreshed.currentTurnUserIndex ?? Math.max(0, messages.length - 1);
|
|
@@ -1705,22 +1719,50 @@ function currentExecutionImages(modelInputImages, toolImages) {
|
|
|
1705
1719
|
}
|
|
1706
1720
|
function latestModelUsage(records, selectedModelId) {
|
|
1707
1721
|
let usage;
|
|
1722
|
+
const toolCallIds = new Set();
|
|
1708
1723
|
// readContext starts at compact.completed, whose execution header is before the boundary.
|
|
1709
1724
|
let activeModelId = selectedModelId;
|
|
1710
1725
|
for (const record of records) {
|
|
1711
1726
|
const payload = record.payload;
|
|
1712
1727
|
if (compactSummaryFromCheckpoint(record) !== undefined) {
|
|
1713
1728
|
usage = undefined;
|
|
1729
|
+
toolCallIds.clear();
|
|
1714
1730
|
activeModelId = modelIdFromPayload(payload);
|
|
1715
1731
|
continue;
|
|
1716
1732
|
}
|
|
1717
1733
|
if (record.type === 'execution.header') {
|
|
1718
1734
|
activeModelId = modelIdFromPayload(payload);
|
|
1719
1735
|
usage = undefined;
|
|
1736
|
+
toolCallIds.clear();
|
|
1720
1737
|
continue;
|
|
1721
1738
|
}
|
|
1722
|
-
if (
|
|
1723
|
-
|
|
1739
|
+
if (record.type === 'model.context' && payload.role === 'tool_call') {
|
|
1740
|
+
if (typeof payload.callId === 'string' && payload.callId.length > 0)
|
|
1741
|
+
toolCallIds.add(payload.callId);
|
|
1742
|
+
else
|
|
1743
|
+
usage = undefined;
|
|
1744
|
+
}
|
|
1745
|
+
if (usage !== undefined) {
|
|
1746
|
+
if (record.type === 'model.context') {
|
|
1747
|
+
const role = payload.role;
|
|
1748
|
+
if (role === 'tool') {
|
|
1749
|
+
if (typeof payload.callId !== 'string' || !toolCallIds.has(payload.callId))
|
|
1750
|
+
usage = undefined;
|
|
1751
|
+
else
|
|
1752
|
+
usage = {
|
|
1753
|
+
...usage,
|
|
1754
|
+
appendedMessages: [
|
|
1755
|
+
...(usage.appendedMessages ?? []),
|
|
1756
|
+
payload
|
|
1757
|
+
]
|
|
1758
|
+
};
|
|
1759
|
+
}
|
|
1760
|
+
else if (role !== 'tool_call' && role !== 'assistant' && role !== 'provider')
|
|
1761
|
+
usage = undefined;
|
|
1762
|
+
}
|
|
1763
|
+
else if (invalidatesUsageCalibration(record.type, payload.type))
|
|
1764
|
+
usage = undefined;
|
|
1765
|
+
}
|
|
1724
1766
|
if (payload.type === 'usage.updated' && activeModelId === selectedModelId) {
|
|
1725
1767
|
const value = payload.contextInputTokens ?? payload.inputTokens;
|
|
1726
1768
|
if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0)
|
|
@@ -1739,20 +1781,38 @@ function latestModelUsage(records, selectedModelId) {
|
|
|
1739
1781
|
function shouldUseNativeCompaction(input) {
|
|
1740
1782
|
if (input.estimatedRequestTokens <= input.contextWindowTokens)
|
|
1741
1783
|
return true;
|
|
1742
|
-
if (input.latestUsage === undefined ||
|
|
1743
|
-
|
|
1744
|
-
|
|
1784
|
+
if (input.latestUsage === undefined || input.latestUsage.outputTokens === undefined)
|
|
1785
|
+
return false;
|
|
1786
|
+
const historyDelta = appendOnlyUsageDelta(input.latestUsage, input.historyMessages);
|
|
1787
|
+
if (historyDelta === undefined)
|
|
1745
1788
|
return false;
|
|
1746
|
-
const appendedTokens = countModelTokens(stableJson(input.appendedMessages));
|
|
1789
|
+
const appendedTokens = countModelTokens(stableJson([...historyDelta, ...input.appendedMessages]));
|
|
1747
1790
|
return (input.latestUsage.contextInputTokens + input.latestUsage.outputTokens + appendedTokens <=
|
|
1748
1791
|
input.contextWindowTokens);
|
|
1749
1792
|
}
|
|
1793
|
+
function appendOnlyUsageDelta(usage, historyMessages) {
|
|
1794
|
+
if (usage.historyMessages === undefined)
|
|
1795
|
+
return usage.appendedMessages ?? [];
|
|
1796
|
+
if (historyMessages.length < usage.historyMessages.length)
|
|
1797
|
+
return undefined;
|
|
1798
|
+
for (let index = 0; index < usage.historyMessages.length; index++)
|
|
1799
|
+
if (!isDeepStrictEqual(usage.historyMessages[index], historyMessages[index]))
|
|
1800
|
+
return undefined;
|
|
1801
|
+
const appended = historyMessages.slice(usage.historyMessages.length);
|
|
1802
|
+
const toolCallIds = new Set(usage.historyMessages
|
|
1803
|
+
.filter((message) => message.role === 'tool_call')
|
|
1804
|
+
.map((message) => message.callId));
|
|
1805
|
+
return appended.every((message) => (message.role === 'tool' && toolCallIds.has(message.callId)) ||
|
|
1806
|
+
(message.role === 'user' && message.contextKind === 'environment'))
|
|
1807
|
+
? appended
|
|
1808
|
+
: undefined;
|
|
1809
|
+
}
|
|
1750
1810
|
function invalidatesUsageCalibration(recordType, payloadType) {
|
|
1751
|
-
if (recordType === 'turn.user' ||
|
|
1811
|
+
if (recordType === 'turn.user' ||
|
|
1812
|
+
recordType === 'context.environment' ||
|
|
1813
|
+
recordType === 'context.gc.completed')
|
|
1752
1814
|
return true;
|
|
1753
|
-
return
|
|
1754
|
-
payloadType === 'tool.completed' ||
|
|
1755
|
-
payloadType === 'tool.failed');
|
|
1815
|
+
return payloadType === 'message.completed';
|
|
1756
1816
|
}
|
|
1757
1817
|
const PROVIDER_CONTEXT_OVERFLOW_CODES = new Set([
|
|
1758
1818
|
'mar_agent_context_limit',
|