@myagentroam/agent 0.11.54 → 0.11.55

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.
@@ -2,9 +2,10 @@ import type { ModelUsage } from '../../model/contracts.js';
2
2
  import { type ContextGcEconomicsPolicy } from '../../session/context-gc-checkpoint.js';
3
3
  export declare const CONTEXT_GC_POLICY: ContextGcEconomicsPolicy;
4
4
  export declare const COMPACT_CREDIT_ACTIVATION_RATIO = 0.8;
5
- export declare const COMPACT_THRESHOLD_RATIO = 0.9;
5
+ export declare const COMPACT_THRESHOLD_RATIO: number;
6
6
  interface ContextGcEconomicsInput {
7
7
  readonly contextUsageTokens: number;
8
+ readonly contextWindowTokens: number;
8
9
  readonly reclaimedTokens: number;
9
10
  readonly reclaimedCachedTokens: number;
10
11
  readonly cacheReadTokens: number;
@@ -17,10 +18,8 @@ interface ContextGcEconomicsInput {
17
18
  }
18
19
  export interface ContextGcEconomicsResult {
19
20
  readonly cacheRebuildPenaltyCostUnits: number;
20
- readonly requiredPositiveNetRollouts: number;
21
- readonly requiredTargetRoiRollouts: number;
21
+ readonly requiredPositiveNetRollouts: number | null;
22
22
  readonly expectedNetSavedCostUnits: number;
23
- readonly cacheInvestmentRoi: number;
24
23
  readonly grossReductionRate: number;
25
24
  readonly passes: boolean;
26
25
  }
@@ -1,3 +1,4 @@
1
+ import { AGENT_EXECUTION_POLICY } from '../execution-policy.js';
1
2
  export const CONTEXT_GC_POLICY = {
2
3
  version: 1,
3
4
  immediatePaybackRollouts: 3,
@@ -8,18 +9,16 @@ export const CONTEXT_GC_POLICY = {
8
9
  stageAProtectionRollouts: 6,
9
10
  largeExecProtectionRollouts: 6,
10
11
  normalInputCostRate: 1,
11
- cacheReadCostRate: 0.1,
12
- cacheWriteCostRate: 1.25,
12
+ cacheReadCostRate: 0.05,
13
13
  outputCostRate: 1,
14
- minimumGrossReductionRate: 0.2,
15
- minimumCacheInvestmentRoi: 0.1
14
+ minimumGrossReductionRate: 0.2
16
15
  };
17
16
  const CONTEXT_GC_START_RATIO = 0.5;
18
17
  const HIGH_WATER_GROSS_REDUCTION_START_RATIO = 0.7;
19
18
  const HIGH_WATER_MINIMUM_GROSS_REDUCTION_RATE = 0.1;
20
19
  const MINIMUM_CONTEXT_WINDOW_REDUCTION_RATIO = 0.05;
21
20
  export const COMPACT_CREDIT_ACTIVATION_RATIO = 0.8;
22
- export const COMPACT_THRESHOLD_RATIO = 0.9;
21
+ export const COMPACT_THRESHOLD_RATIO = AGENT_EXECUTION_POLICY.backgroundCompactionPercent / 100;
23
22
  const IMMINENT_COMPACT_CREDIT_DISCOUNT = 0.8;
24
23
  export function evaluateContextGcEconomics(input) {
25
24
  const reclaimedTokens = Math.max(0, input.reclaimedTokens);
@@ -28,49 +27,58 @@ export function evaluateContextGcEconomics(input) {
28
27
  const invalidatedCachedSuffixTokens = cacheReadTokens - preservedCachedPrefixTokens;
29
28
  const reclaimedCachedTokens = clamp(input.reclaimedCachedTokens, 0, invalidatedCachedSuffixTokens);
30
29
  const invalidatedRetainedCachedTokens = Math.max(0, invalidatedCachedSuffixTokens - reclaimedCachedTokens);
31
- const cacheRebuildPenaltyCostUnits = invalidatedRetainedCachedTokens *
32
- (CONTEXT_GC_POLICY.cacheWriteCostRate - CONTEXT_GC_POLICY.cacheReadCostRate);
30
+ // Calculate token-derived costs in cache-read units to keep exact zero exact.
31
+ const unitsPerNormalInput = CONTEXT_GC_POLICY.normalInputCostRate / CONTEXT_GC_POLICY.cacheReadCostRate;
32
+ const cacheRebuildPenalty = invalidatedRetainedCachedTokens * (unitsPerNormalInput - 1);
33
+ const cacheRebuildPenaltyCostUnits = cacheRebuildPenalty * CONTEXT_GC_POLICY.cacheReadCostRate;
33
34
  const reclaimedUncachedTokens = Math.max(0, reclaimedTokens - reclaimedCachedTokens);
34
- const firstRolloutSavingsCostUnits = reclaimedCachedTokens * CONTEXT_GC_POLICY.cacheReadCostRate +
35
- reclaimedUncachedTokens * CONTEXT_GC_POLICY.normalInputCostRate;
36
- const steadyRolloutSavingsCostUnits = reclaimedTokens * CONTEXT_GC_POLICY.cacheReadCostRate;
37
- const netAt = (rollouts) => input.compactDeferralCreditCostUnits -
38
- cacheRebuildPenaltyCostUnits +
39
- (rollouts <= 0
40
- ? 0
41
- : firstRolloutSavingsCostUnits + Math.max(0, rollouts - 1) * steadyRolloutSavingsCostUnits);
42
- const maximumSearch = Math.max(CONTEXT_GC_POLICY.maximumPaybackRollouts + 1, 10_000);
43
- const requiredPositiveNetRollouts = firstMatchingRollout(maximumSearch, (rollouts) => netAt(rollouts) > 0);
44
- const requiredTargetRoiRollouts = cacheRebuildPenaltyCostUnits === 0
45
- ? requiredPositiveNetRollouts
46
- : firstMatchingRollout(maximumSearch, (rollouts) => netAt(rollouts) > 0 &&
47
- netAt(rollouts) / cacheRebuildPenaltyCostUnits >=
48
- CONTEXT_GC_POLICY.minimumCacheInvestmentRoi);
49
- const targetRollouts = Number.isFinite(requiredTargetRoiRollouts)
50
- ? requiredTargetRoiRollouts
51
- : CONTEXT_GC_POLICY.maximumPaybackRollouts;
52
- const expectedNetSavedCostUnits = netAt(targetRollouts);
53
- const cacheInvestmentRoi = cacheRebuildPenaltyCostUnits === 0
54
- ? 0
55
- : expectedNetSavedCostUnits / cacheRebuildPenaltyCostUnits;
35
+ const firstRolloutSavings = reclaimedCachedTokens + reclaimedUncachedTokens * unitsPerNormalInput;
36
+ const steadyRolloutSavings = reclaimedTokens;
37
+ const netAt = (rollouts) => (rollouts <= 0
38
+ ? -cacheRebuildPenalty
39
+ : firstRolloutSavings +
40
+ Math.max(0, rollouts - 1) * steadyRolloutSavings -
41
+ cacheRebuildPenalty) +
42
+ input.compactDeferralCreditCostUnits / CONTEXT_GC_POLICY.cacheReadCostRate;
43
+ let requiredPositiveNetRollouts;
44
+ if (netAt(0) > 0)
45
+ requiredPositiveNetRollouts = 0;
46
+ else if (netAt(1) > 0)
47
+ requiredPositiveNetRollouts = 1;
48
+ else if (steadyRolloutSavings <= 0)
49
+ requiredPositiveNetRollouts = null;
50
+ else {
51
+ requiredPositiveNetRollouts = Math.max(2, Math.floor(-netAt(1) / steadyRolloutSavings) + 2);
52
+ if (netAt(requiredPositiveNetRollouts - 1) > 0)
53
+ requiredPositiveNetRollouts--;
54
+ else if (netAt(requiredPositiveNetRollouts) <= 0)
55
+ requiredPositiveNetRollouts++;
56
+ }
57
+ const expectedNetSavedCostUnits = netAt(requiredPositiveNetRollouts ?? 0) * CONTEXT_GC_POLICY.cacheReadCostRate;
56
58
  const grossReductionRate = reclaimedTokens / Math.max(1, Math.max(0, input.contextUsageTokens));
57
59
  const minimumGrossReductionRate = Math.max(0, input.minimumGrossReductionRate ?? CONTEXT_GC_POLICY.minimumGrossReductionRate);
58
60
  const minimumReclaimedTokens = Math.max(0, input.minimumReclaimedTokens ??
59
61
  Math.ceil(Math.max(0, input.contextUsageTokens) * minimumGrossReductionRate));
60
- const immediate = requiredTargetRoiRollouts <= CONTEXT_GC_POLICY.immediatePaybackRollouts;
62
+ const usageRatio = input.contextUsageTokens / input.contextWindowTokens;
63
+ const thresholdPercent = AGENT_EXECUTION_POLICY.backgroundCompactionPercent;
64
+ const activationPercent = COMPACT_CREDIT_ACTIVATION_RATIO * 100;
65
+ const withinWindow = requiredPositiveNetRollouts !== null &&
66
+ (usageRatio <= COMPACT_CREDIT_ACTIVATION_RATIO
67
+ ? requiredPositiveNetRollouts <= CONTEXT_GC_POLICY.maximumPaybackRollouts
68
+ : requiredPositiveNetRollouts *
69
+ (thresholdPercent * input.contextWindowTokens - 100 * input.contextUsageTokens) <=
70
+ CONTEXT_GC_POLICY.maximumPaybackRollouts *
71
+ (thresholdPercent - activationPercent) *
72
+ input.contextWindowTokens);
61
73
  const passes = reclaimedTokens > 0 &&
62
74
  reclaimedTokens >= minimumReclaimedTokens &&
63
- Number.isFinite(requiredTargetRoiRollouts) &&
64
- (immediate ||
65
- (requiredTargetRoiRollouts <= CONTEXT_GC_POLICY.maximumPaybackRollouts &&
66
- input.contextGrowthSampleCount >= CONTEXT_GC_POLICY.minimumContextGrowthSamples &&
67
- requiredTargetRoiRollouts <= input.projectedRolloutsUntilCompactAfterGc));
75
+ Number.isFinite(usageRatio) &&
76
+ usageRatio < COMPACT_THRESHOLD_RATIO &&
77
+ withinWindow;
68
78
  return {
69
79
  cacheRebuildPenaltyCostUnits,
70
80
  requiredPositiveNetRollouts,
71
- requiredTargetRoiRollouts,
72
81
  expectedNetSavedCostUnits,
73
- cacheInvestmentRoi,
74
82
  grossReductionRate,
75
83
  passes
76
84
  };
@@ -128,12 +136,6 @@ export function modelContextUsage(value) {
128
136
  ? context
129
137
  : undefined;
130
138
  }
131
- function firstMatchingRollout(limit, predicate) {
132
- for (let rollouts = 0; rollouts <= limit; rollouts++)
133
- if (predicate(rollouts))
134
- return rollouts;
135
- return Number.POSITIVE_INFINITY;
136
- }
137
139
  export function clamp(value, minimum, maximum) {
138
140
  return Math.min(maximum, Math.max(minimum, value));
139
141
  }
@@ -181,19 +181,13 @@ function finalizePlan(input, evaluated, includeMedia = false) {
181
181
  compactDeferralCreditCostUnits: evaluated.compactDeferralCreditCostUnits,
182
182
  imminentCompactAvoidanceCreditCostUnits: evaluated.imminentCompactAvoidanceCreditCostUnits,
183
183
  appliedCompactCreditCostUnits: evaluated.appliedCompactCreditCostUnits,
184
- requiredPositiveNetRollouts: Number.isFinite(evaluated.economics.requiredPositiveNetRollouts)
185
- ? evaluated.economics.requiredPositiveNetRollouts
186
- : null,
187
- requiredTargetRoiRollouts: Number.isFinite(evaluated.economics.requiredTargetRoiRollouts)
188
- ? evaluated.economics.requiredTargetRoiRollouts
189
- : null,
184
+ requiredPositiveNetRollouts: evaluated.economics.requiredPositiveNetRollouts,
190
185
  projectedRolloutsUntilCompactAfterGc: evaluated.projectedRolloutsUntilCompactAfterGc,
191
186
  projectedTokensBeforeGc: evaluated.projectedTokensBeforeGc,
192
187
  projectedTokensAfterGc: evaluated.projectedTokensAfterGc,
193
188
  contextGrowthSampleCount: evaluated.contextGrowthSamples.length,
194
189
  contextGrowthP75Tokens: evaluated.contextGrowthP75Tokens,
195
190
  expectedNetSavedCostUnits: evaluated.economics.expectedNetSavedCostUnits,
196
- cacheInvestmentRoi: evaluated.economics.cacheInvestmentRoi,
197
191
  minimumObservedRollouts: evaluated.minimumObservedRollouts,
198
192
  protectedCandidateTokens: evaluated.protectedCandidateTokens,
199
193
  eligibleCandidateCount: evaluated.eligibleCandidateCount,
@@ -254,8 +248,6 @@ function evaluateCandidateSet(input, existing, candidates, state, mediaProjectio
254
248
  const pendingTokens = Math.max(0, input.usage.outputTokens ?? 0) + contextGcMessageTokens(input, pendingMessages);
255
249
  const projectedTokensBeforeGc = state.contextUsageTokens + pendingTokens;
256
250
  const projectedTokensAfterGc = Math.max(0, projectedTokensBeforeGc - reclaimedTokens);
257
- if (!state.mediaOnly && projectedTokensAfterGc >= compactThresholdTokens)
258
- return undefined;
259
251
  const projectedRolloutsUntilCompactAfterGc = contextGrowthP75Tokens <= 0
260
252
  ? 0
261
253
  : Math.max(0, Math.floor((compactThresholdTokens - projectedTokensAfterGc) / Math.max(1, contextGrowthP75Tokens)));
@@ -273,6 +265,7 @@ function evaluateCandidateSet(input, existing, candidates, state, mediaProjectio
273
265
  const appliedCompactCreditCostUnits = contextGcAppliedCompactCreditCostUnits(compactDeferralCreditCostUnits, imminentCompactAvoidanceCreditCostUnits);
274
266
  const economics = evaluateContextGcEconomics({
275
267
  contextUsageTokens: state.contextUsageTokens,
268
+ contextWindowTokens: input.contextWindowTokens,
276
269
  reclaimedTokens,
277
270
  reclaimedCachedTokens: cache.reclaimedCachedTokens,
278
271
  cacheReadTokens: input.usage.cacheReadTokens ?? 0,
@@ -382,20 +375,15 @@ function compactDeferralCredit(input, reclaimedTokens, compactThresholdTokens) {
382
375
  const usage = compact.payload.usage;
383
376
  const contextInput = modelContextUsage(usage);
384
377
  const cacheRead = nonnegativeNumber(usage.cacheReadTokens);
385
- const cacheWrite = nonnegativeNumber(usage.cacheWriteTokens);
386
378
  const output = nonnegativeNumber(usage.outputTokens);
387
- if (contextInput === undefined ||
388
- cacheRead === undefined ||
389
- cacheWrite === undefined ||
390
- output === undefined)
379
+ if (contextInput === undefined || cacheRead === undefined || output === undefined)
391
380
  return 0;
392
381
  const baseline = firstMatchingUsageAfter(input.records, compact.sequence, input.modelId, input.contextWindowTokens);
393
382
  if (baseline === undefined || baseline >= compactThresholdTokens)
394
383
  return 0;
395
- const fresh = Math.max(0, contextInput - cacheRead - cacheWrite);
384
+ const fresh = Math.max(0, contextInput - cacheRead);
396
385
  const compactCost = fresh * CONTEXT_GC_POLICY.normalInputCostRate +
397
386
  cacheRead * CONTEXT_GC_POLICY.cacheReadCostRate +
398
- cacheWrite * CONTEXT_GC_POLICY.cacheWriteCostRate +
399
387
  output * CONTEXT_GC_POLICY.outputCostRate;
400
388
  const cycleCapacity = Math.max(1, compactThresholdTokens - baseline);
401
389
  return compactCost * clamp(reclaimedTokens / cycleCapacity, 0, 1);
@@ -1113,11 +1113,10 @@ function isContextGcEconomicsPolicy(value) {
1113
1113
  [
1114
1114
  'normalInputCostRate',
1115
1115
  'cacheReadCostRate',
1116
- 'cacheWriteCostRate',
1117
1116
  'outputCostRate',
1118
- 'minimumGrossReductionRate',
1119
- 'minimumCacheInvestmentRoi'
1120
- ].every((key) => isNonnegativeFinite(value[key])));
1117
+ 'minimumGrossReductionRate'
1118
+ ].every((key) => isNonnegativeFinite(value[key])) &&
1119
+ ['cacheWriteCostRate', 'minimumCacheInvestmentRoi'].every((key) => value[key] === undefined || isNonnegativeFinite(value[key])));
1121
1120
  }
1122
1121
  function isContextGcMetrics(value) {
1123
1122
  if (!isRecord(value) ||
@@ -1150,10 +1149,13 @@ function isContextGcMetrics(value) {
1150
1149
  'projectedTokensAfterGc'
1151
1150
  ];
1152
1151
  return (nonnegative.every((key) => isNonnegativeFinite(value[key])) &&
1153
- ['requiredPositiveNetRollouts', 'requiredTargetRoiRollouts'].every((key) => isNonnegativeFinite(value[key]) || (value.stage === 'INLINE_MEDIA' && value[key] === null)) &&
1152
+ [
1153
+ 'requiredPositiveNetRollouts',
1154
+ ...(value.requiredTargetRoiRollouts === undefined ? [] : ['requiredTargetRoiRollouts'])
1155
+ ].every((key) => isNonnegativeFinite(value[key]) || (value.stage === 'INLINE_MEDIA' && value[key] === null)) &&
1154
1156
  optionalNonnegative.every((key) => value[key] === undefined || isNonnegativeFinite(value[key])) &&
1155
1157
  Number.isFinite(value.expectedNetSavedCostUnits) &&
1156
- Number.isFinite(value.cacheInvestmentRoi) &&
1158
+ (value.cacheInvestmentRoi === undefined || Number.isFinite(value.cacheInvestmentRoi)) &&
1157
1159
  (value.tokenEstimator === undefined || value.tokenEstimator === 'UTF8_BYTES_V1') &&
1158
1160
  (value.cachePenaltyKnown === undefined || typeof value.cachePenaltyKnown === 'boolean'));
1159
1161
  }
@@ -13,10 +13,10 @@ export interface ContextGcEconomicsPolicy {
13
13
  readonly largeExecProtectionRollouts: number;
14
14
  readonly normalInputCostRate: number;
15
15
  readonly cacheReadCostRate: number;
16
- readonly cacheWriteCostRate: number;
16
+ readonly cacheWriteCostRate?: number;
17
17
  readonly outputCostRate: number;
18
18
  readonly minimumGrossReductionRate: number;
19
- readonly minimumCacheInvestmentRoi: number;
19
+ readonly minimumCacheInvestmentRoi?: number;
20
20
  }
21
21
  export type ContextGcBase = {
22
22
  readonly type: 'SESSION_START';
@@ -112,14 +112,14 @@ export interface ContextGcMetrics {
112
112
  readonly imminentCompactAvoidanceCreditCostUnits?: number;
113
113
  readonly appliedCompactCreditCostUnits?: number;
114
114
  readonly requiredPositiveNetRollouts: number | null;
115
- readonly requiredTargetRoiRollouts: number | null;
115
+ readonly requiredTargetRoiRollouts?: number | null;
116
116
  readonly projectedRolloutsUntilCompactAfterGc: number;
117
117
  readonly projectedTokensBeforeGc?: number;
118
118
  readonly projectedTokensAfterGc?: number;
119
119
  readonly contextGrowthSampleCount: number;
120
120
  readonly contextGrowthP75Tokens: number;
121
121
  readonly expectedNetSavedCostUnits: number;
122
- readonly cacheInvestmentRoi: number;
122
+ readonly cacheInvestmentRoi?: number;
123
123
  readonly minimumObservedRollouts: number;
124
124
  readonly protectedCandidateTokens: number;
125
125
  readonly eligibleCandidateCount: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/agent",
3
- "version": "0.11.54",
3
+ "version": "0.11.55",
4
4
  "description": "Embeddable MAR coding agent SDK and CLI.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",