@myagentroam/agent 0.10.59 → 0.10.61

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.
Files changed (58) hide show
  1. package/dist/agent-core/runtime/compaction/history.d.ts +1 -1
  2. package/dist/agent-core/runtime/compaction/retained-context.d.ts +1 -1
  3. package/dist/agent-core/runtime/compaction/retained-context.js +1 -1
  4. package/dist/agent-core/runtime/compaction/smart.d.ts +1 -1
  5. package/dist/agent-core/runtime/compaction/smart.js +1 -1
  6. package/dist/agent-core/runtime/context/gc-runtime.d.ts +1 -1
  7. package/dist/agent-core/runtime/context/gc-runtime.js +20 -14
  8. package/dist/agent-core/runtime/context/gc.d.ts +1 -1
  9. package/dist/agent-core/runtime/context/gc.js +4 -10
  10. package/dist/agent-core/runtime/context/projection.d.ts +1 -1
  11. package/dist/agent-core/runtime/context/projection.js +3 -5
  12. package/dist/agent-core/runtime/context/restore.d.ts +4 -4
  13. package/dist/agent-core/runtime/context/restore.js +1 -1
  14. package/dist/agent-core/runtime/context/usage.d.ts +2 -2
  15. package/dist/agent-core/runtime/context/usage.js +1 -1
  16. package/dist/agent-core/runtime/context/world-state.d.ts +2 -2
  17. package/dist/agent-core/runtime/context/world-state.js +1 -1
  18. package/dist/agent-core/sdk/agent.js +2 -2
  19. package/dist/agent-core/sdk/extension-agents.js +5 -1
  20. package/dist/agent-core/sdk/native-steer.d.ts +1 -1
  21. package/dist/agent-core/sdk/session.d.ts +19 -13
  22. package/dist/agent-core/sdk/session.js +35 -40
  23. package/dist/agent-core/sdk/subagent-backend.d.ts +1 -1
  24. package/dist/agent-core/sdk/subagent-backend.js +20 -17
  25. package/dist/agent-core/session/catalog.js +1 -1
  26. package/dist/agent-core/session/context-gc-checkpoint.d.ts +4 -8
  27. package/dist/agent-core/session/context-gc-checkpoint.js +82 -137
  28. package/dist/agent-core/session/context-gc-observations.d.ts +1 -1
  29. package/dist/agent-core/session/context-gc-replacements.d.ts +4 -7
  30. package/dist/agent-core/session/context-gc-replacements.js +25 -59
  31. package/dist/agent-core/session/context-gc-subagent.d.ts +0 -3
  32. package/dist/agent-core/session/context-gc-subagent.js +2 -16
  33. package/dist/agent-core/session/deferred-input.d.ts +1 -1
  34. package/dist/agent-core/session/store/current-state.d.ts +17 -0
  35. package/dist/agent-core/session/store/current-state.js +53 -0
  36. package/dist/agent-core/session/store/directory-index.d.ts +18 -0
  37. package/dist/agent-core/session/store/directory-index.js +169 -0
  38. package/dist/agent-core/session/store/execution-state.d.ts +18 -0
  39. package/dist/agent-core/session/store/execution-state.js +187 -0
  40. package/dist/agent-core/session/store/history.d.ts +25 -0
  41. package/dist/agent-core/session/store/history.js +157 -0
  42. package/dist/agent-core/session/store/images.d.ts +21 -0
  43. package/dist/agent-core/session/store/images.js +248 -0
  44. package/dist/agent-core/session/store/index.d.ts +4 -0
  45. package/dist/agent-core/session/store/index.js +2 -0
  46. package/dist/agent-core/session/{jsonl-store.d.ts → store/jsonl-store.d.ts} +14 -94
  47. package/dist/agent-core/session/{jsonl-store.js → store/jsonl-store.js} +323 -1269
  48. package/dist/agent-core/session/store/records.d.ts +23 -0
  49. package/dist/agent-core/session/store/records.js +249 -0
  50. package/dist/agent-core/session/store/types.d.ts +84 -0
  51. package/dist/agent-core/session/store/types.js +1 -0
  52. package/dist/agent-core/session/tool-result-resources.d.ts +1 -1
  53. package/dist/agent-core/subagent/scheduler.js +1 -1
  54. package/dist/agent-core/subagent/session-controller.d.ts +5 -2
  55. package/dist/agent-core/subagent/session-controller.js +99 -15
  56. package/dist/agent-core/tools/code-mode/state.d.ts +1 -1
  57. package/dist/agent-core/tools/code-mode/state.js +2 -2
  58. package/package.json +1 -1
@@ -1,4 +1,3 @@
1
- import { createHash } from 'node:crypto';
2
1
  import { posix, win32 } from 'node:path';
3
2
  import { isDeepStrictEqual } from 'node:util';
4
3
  import { codeCallEvidence, codePartialPatchCallEvidence, callsFromRecord, codeObservationEvidence, observationsFromRecord, retainedCodeInputs } from './context-gc-observations.js';
@@ -10,7 +9,7 @@ export const CONTEXT_GC_MAX_TARGETS = 4_096;
10
9
  /** Disposable memoization for one evaluation's immutable record snapshot. */
11
10
  export class ContextGcCheckpointCache {
12
11
  #snapshot;
13
- read(records, boundarySequence = records.at(-1)?.sequence ?? 0, workspace = sessionWorkspace(records)) {
12
+ read(records, boundarySequence = records.at(-1)?.sequence ?? 0, workspace) {
14
13
  const cached = this.#snapshot;
15
14
  if (cached?.records === records &&
16
15
  cached.boundarySequence === boundarySequence &&
@@ -24,18 +23,6 @@ export class ContextGcCheckpointCache {
24
23
  export function contextGcMinimumUsageGrowth(contextWindowTokens) {
25
24
  return Math.max(2_000, Math.floor(contextWindowTokens * 0.05));
26
25
  }
27
- const PROJECTION_RECORD_TYPES = new Set([
28
- 'compact.completed',
29
- 'context.environment',
30
- 'execution.header',
31
- 'message.completed',
32
- 'model.context',
33
- 'plan.completed',
34
- 'turn.user'
35
- ]);
36
- export function contextGcRecordSourceHash(record) {
37
- return createHash('sha256').update(stableJson(record.payload)).digest('hex');
38
- }
39
26
  export function contextGcLogicalPathKey(path, workspace, platform) {
40
27
  if (!path || !workspace || path.includes('\0') || workspace.includes('\0'))
41
28
  return undefined;
@@ -76,32 +63,34 @@ export function contextGcBaseFromRecords(records, boundarySequence = records.at(
76
63
  export function contextGcBaseSequence(base) {
77
64
  return base.type === 'COMPACT' ? base.sequence : base.firstSequence;
78
65
  }
79
- export function contextGcSourceProjectionHash(records, boundarySequence, base = contextGcBaseFromRecords(records, boundarySequence)) {
80
- if (!base || !isValidBoundary(boundarySequence))
81
- return undefined;
82
- const baseSequence = contextGcBaseSequence(base);
83
- if (!sameContextGcBase(base, contextGcBaseFromRecords(records, boundarySequence)))
84
- return undefined;
85
- const source = records
86
- .filter((record) => record.sequence >= baseSequence &&
87
- record.sequence <= boundarySequence &&
88
- PROJECTION_RECORD_TYPES.has(record.type))
89
- .map((record) => ({
90
- sequence: record.sequence,
91
- recordId: record.recordId,
92
- type: record.type,
93
- payload: record.payload
94
- }));
95
- return createHash('sha256').update(stableJson(source)).digest('hex');
96
- }
97
66
  export function normalizeContextGcReplacements(replacements) {
98
67
  const normalized = new Map();
68
+ const readItems = new Map();
99
69
  for (const replacement of replacements) {
100
70
  if (!isContextGcReplacement(replacement))
101
71
  return undefined;
102
- normalized.set(contextGcReplacementKey(replacement), structuredClone(replacement));
72
+ const value = structuredClone(replacement);
73
+ const key = contextGcReplacementKey(value);
74
+ if (value.kind === 'READ_OUTPUT_ITEMS') {
75
+ const items = normalized.get(key)?.kind === 'READ_OUTPUT_ITEMS'
76
+ ? readItems.get(key)
77
+ : new Map();
78
+ for (const item of value.items)
79
+ items.set(item.index, item);
80
+ readItems.set(key, items);
81
+ }
82
+ normalized.set(key, value);
103
83
  }
104
- const values = [...normalized.values()];
84
+ const values = [...normalized].map(([key, value]) => {
85
+ if (value.kind !== 'READ_OUTPUT_ITEMS')
86
+ return value;
87
+ const items = [...readItems.get(key).values()];
88
+ return {
89
+ ...value,
90
+ items,
91
+ evidenceSequences: [...new Set(items.map((item) => item.evidenceSequence))]
92
+ };
93
+ });
105
94
  const targets = new Set(values.flatMap((replacement) => [
106
95
  contextGcTargetKey(replacement.target),
107
96
  ...(replacement.kind === 'TOOL_CALL_INPUT'
@@ -122,7 +111,6 @@ export function parseContextGcCheckpoint(record) {
122
111
  !isPositiveInteger(payload.generation) ||
123
112
  !isContextGcBase(payload.base) ||
124
113
  !isPositiveInteger(payload.boundarySequence) ||
125
- !isSha256(payload.sourceProjectionHash) ||
126
114
  !Array.isArray(payload.replacements) ||
127
115
  payload.replacements.length === 0 ||
128
116
  !isContextGcTrigger(payload.trigger) ||
@@ -138,14 +126,13 @@ export function parseContextGcCheckpoint(record) {
138
126
  generation: payload.generation,
139
127
  base: structuredClone(payload.base),
140
128
  boundarySequence: payload.boundarySequence,
141
- sourceProjectionHash: payload.sourceProjectionHash,
142
129
  replacements,
143
130
  trigger: structuredClone(payload.trigger),
144
131
  economics: structuredClone(payload.economics),
145
132
  metrics: structuredClone(payload.metrics)
146
133
  };
147
134
  }
148
- export function validateContextGcCheckpoint(records, record, workspace = sessionWorkspace(records)) {
135
+ export function validateContextGcCheckpoint(records, record, workspace = sessionWorkspace(records), committedReplacements = []) {
149
136
  const payload = parseContextGcCheckpoint(record);
150
137
  if (!payload || payload.boundarySequence >= record.sequence)
151
138
  return undefined;
@@ -153,28 +140,45 @@ export function validateContextGcCheckpoint(records, record, workspace = session
153
140
  if (!sameContextGcBase(payload.base, base))
154
141
  return undefined;
155
142
  const baseSequence = contextGcBaseSequence(payload.base);
156
- if (contextGcSourceProjectionHash(records, payload.boundarySequence, payload.base) !==
157
- payload.sourceProjectionHash)
158
- return undefined;
159
143
  // Later cell completion cannot retroactively authorize an earlier checkpoint.
160
144
  records = records.filter((item) => item.sequence <= payload.boundarySequence);
161
145
  const recordsBySequence = new Map(records.map((item) => [item.sequence, item]));
162
146
  if (!triggerMatchesRecords(records, recordsBySequence, payload))
163
147
  return undefined;
148
+ const committed = new Map(committedReplacements.map((replacement) => [contextGcReplacementKey(replacement), replacement]));
149
+ const changed = payload.replacements.flatMap((replacement) => {
150
+ const previous = committed.get(contextGcReplacementKey(replacement));
151
+ if (isDeepStrictEqual(previous, replacement))
152
+ return [];
153
+ if (previous?.kind === 'READ_OUTPUT_ITEMS' && replacement.kind === 'READ_OUTPUT_ITEMS') {
154
+ const retained = new Map(previous.items.map((item) => [item.index, item]));
155
+ const items = replacement.items.filter((item) => !isDeepStrictEqual(retained.get(item.index), item));
156
+ if (items.length > 0)
157
+ return [
158
+ {
159
+ ...replacement,
160
+ items,
161
+ evidenceSequences: [...new Set(items.map((item) => item.evidenceSequence))]
162
+ }
163
+ ];
164
+ }
165
+ return [replacement];
166
+ });
164
167
  const targets = payload.replacements.flatMap((replacement) => [
165
168
  replacement.target,
166
169
  ...(replacement.kind === 'TOOL_CALL_INPUT' ? replacement.providerAliasTargets : [])
167
170
  ]);
168
171
  if (new Set(targets.map(contextGcTargetKey)).size !== targets.length)
169
172
  return undefined;
170
- for (const target of targets) {
171
- const source = recordsBySequence.get(target.sequence);
172
- if (!source ||
173
- source.sequence > payload.boundarySequence ||
174
- !targetMatchesRecord(target, source))
175
- return undefined;
176
- }
177
- for (const replacement of payload.replacements) {
173
+ for (const replacement of changed) {
174
+ for (const target of [
175
+ replacement.target,
176
+ ...(replacement.kind === 'TOOL_CALL_INPUT' ? replacement.providerAliasTargets : [])
177
+ ]) {
178
+ const source = recordsBySequence.get(target.sequence);
179
+ if (!source || !targetMatchesRecord(target, source))
180
+ return undefined;
181
+ }
178
182
  const evidence = replacement.kind === 'READ_OUTPUT_ITEMS'
179
183
  ? replacement.evidenceSequences
180
184
  : [
@@ -194,18 +198,23 @@ export function validateContextGcCheckpoint(records, record, workspace = session
194
198
  }
195
199
  return payload;
196
200
  }
197
- export function latestValidContextGcCheckpoint(records, boundarySequence = records.at(-1)?.sequence ?? 0, workspace = sessionWorkspace(records)) {
201
+ export function latestValidContextGcCheckpoint(records, boundarySequence = records.at(-1)?.sequence ?? 0, _workspace) {
198
202
  const base = contextGcBaseFromRecords(records, boundarySequence);
199
203
  if (!base)
200
204
  return undefined;
201
- const candidates = records
202
- .filter((record) => record.sequence <= boundarySequence &&
203
- record.sequence >= contextGcBaseSequence(base) &&
204
- record.type === 'context.gc.completed')
205
- .toReversed();
206
- for (const record of candidates) {
207
- const payload = validateContextGcCheckpoint(records, record, workspace);
208
- if (payload && sameContextGcBase(payload.base, base))
205
+ const baseSequence = contextGcBaseSequence(base);
206
+ // Committed local checkpoints are trusted; historical evidence is checked at commit only.
207
+ for (let index = records.length - 1; index >= 0; index--) {
208
+ const record = records[index];
209
+ if (record.sequence < baseSequence)
210
+ break;
211
+ if (record.sequence > boundarySequence || record.type !== 'context.gc.completed')
212
+ continue;
213
+ const payload = parseContextGcCheckpoint(record);
214
+ if (payload &&
215
+ payload.boundarySequence >= baseSequence &&
216
+ payload.boundarySequence < record.sequence &&
217
+ sameContextGcBase(payload.base, base))
209
218
  return { record, payload };
210
219
  }
211
220
  return undefined;
@@ -222,7 +231,6 @@ export function sameContextGcBase(left, right) {
222
231
  function targetMatchesRecord(target, record) {
223
232
  if (record.type !== 'model.context' ||
224
233
  record.recordId !== target.recordId ||
225
- contextGcRecordSourceHash(record) !== target.sourceHash ||
226
234
  !isRecord(record.payload) ||
227
235
  record.payload.role !== target.role)
228
236
  return false;
@@ -283,10 +291,7 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
283
291
  contextGcStaleReadReplacement({
284
292
  path: item.path,
285
293
  content: original.content,
286
- evidenceSequence: item.evidenceSequence,
287
- supersededByCallId: evidence.callId,
288
- operation: evidence.file.operation,
289
- formatVersion: staleReadReplacementFormatVersion(item.replacement)
294
+ operation: evidence.file.operation
290
295
  }));
291
296
  });
292
297
  }
@@ -296,7 +301,7 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
296
301
  return (evidence?.callId === replacement.callId &&
297
302
  evidence.call.sequence === replacement.target.sequence &&
298
303
  result !== undefined &&
299
- isDeepStrictEqual(replacement.replacementArguments, contextGcApplyPatchInputReplacement(source.payload.arguments, result, replacement.evidenceSequence, applyPatchReplacementFormatVersion(replacement.replacementArguments))));
304
+ isDeepStrictEqual(replacement.replacementArguments, contextGcApplyPatchInputReplacement(source.payload.arguments, result)));
300
305
  }
301
306
  if (replacement.kind === 'TOOL_CALL_INPUT' && replacement.toolName === 'code_exec') {
302
307
  const evidence = successfulToolEvidence(records, recordsBySequence, replacement.evidenceSequence, replacement.toolName);
@@ -363,10 +368,7 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
363
368
  contextGcSubagentOutputReplacement({
364
369
  sourceContent: sourceEvidence.result.payload.content,
365
370
  source: sourceSnapshot,
366
- terminal: terminalSnapshot,
367
- terminalCallId: replacement.terminalCallId,
368
- evidenceSequence: replacement.evidenceSequence,
369
- formatVersion: subagentReplacementFormatVersion(replacement.replacementContent)
371
+ terminal: terminalSnapshot
370
372
  }));
371
373
  }
372
374
  if (replacement.kind === 'WEB_OUTPUT') {
@@ -387,50 +389,12 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
387
389
  if (!isSuccessfulExecLifecycleEvidence(replacement, source, records, recordsBySequence))
388
390
  return false;
389
391
  if (replacement.kind === 'TOOL_CALL_INPUT')
390
- return isDeepStrictEqual(replacement.replacementArguments, contextGcExecInputReplacement(source.payload.arguments, execInputReplacementFormatVersion(replacement.replacementArguments), replacement.toolName));
392
+ return isDeepStrictEqual(replacement.replacementArguments, contextGcExecInputReplacement(source.payload.arguments, replacement.toolName));
391
393
  const targetEvidence = successfulToolEvidence(records, recordsBySequence, source.sequence, 'exec', replacement.callId) ??
392
394
  successfulToolEvidence(records, recordsBySequence, source.sequence, 'exec_wait', replacement.callId);
393
395
  const result = normalizeContextGcExecResult(source.payload.content, targetEvidence?.completed.payload);
394
396
  return (result !== undefined &&
395
- replacement.replacementContent ===
396
- contextGcExecOutputReplacement(result, execOutputReplacementFormatVersion(replacement.replacementContent)));
397
- }
398
- function staleReadReplacementFormatVersion(value) {
399
- return value.includes(' formatVersion="2"') ? 2 : 1;
400
- }
401
- function applyPatchReplacementFormatVersion(value) {
402
- return typeof value === 'string' && value.includes(' formatVersion="2"') ? 2 : 1;
403
- }
404
- function subagentReplacementFormatVersion(value) {
405
- try {
406
- const parsed = JSON.parse(value);
407
- return isRecord(parsed) && isRecord(parsed.contextGc) && parsed.contextGc.formatVersion === 2
408
- ? 2
409
- : 1;
410
- }
411
- catch {
412
- return 1;
413
- }
414
- }
415
- function execInputReplacementFormatVersion(value) {
416
- if (typeof value === 'string' && value.includes(' formatVersion="3"'))
417
- return 3;
418
- if (!isRecord(value) || !isRecord(value.contextGc))
419
- return 1;
420
- return value.contextGc.formatVersion === 3 ? 3 : value.contextGc.formatVersion === 2 ? 2 : 1;
421
- }
422
- function execOutputReplacementFormatVersion(value) {
423
- try {
424
- const parsed = JSON.parse(value);
425
- return isRecord(parsed) && parsed.contextGcFormatVersion === 3
426
- ? 3
427
- : isRecord(parsed) && parsed.contextGcFormatVersion === 2
428
- ? 2
429
- : 1;
430
- }
431
- catch {
432
- return 1;
433
- }
397
+ replacement.replacementContent === contextGcExecOutputReplacement(result));
434
398
  }
435
399
  function toolNameForCallId(records, callId, beforeSequence) {
436
400
  const call = modelToolCallForCallId(records, callId, beforeSequence);
@@ -713,7 +677,7 @@ function isContextGcReplacement(value) {
713
677
  if (value.kind === 'READ_OUTPUT_ITEMS') {
714
678
  const items = value.items;
715
679
  const evidenceSequences = value.evidenceSequences;
716
- return (hasOnlyKeys(value, ['kind', 'callId', 'target', 'items', 'evidenceSequences']) &&
680
+ if (!(hasOnlyKeys(value, ['kind', 'callId', 'target', 'items', 'evidenceSequences']) &&
717
681
  value.target.role === 'tool' &&
718
682
  Array.isArray(items) &&
719
683
  items.length > 0 &&
@@ -732,11 +696,14 @@ function isContextGcReplacement(value) {
732
696
  isPositiveInteger(item.evidenceSequence)) &&
733
697
  Array.isArray(evidenceSequences) &&
734
698
  evidenceSequences.length > 0 &&
735
- evidenceSequences.every(isPositiveInteger) &&
736
- new Set(items.map((item) => item.index)).size === items.length &&
737
- new Set(evidenceSequences).size === evidenceSequences.length &&
738
- items.every((item) => evidenceSequences.includes(item.evidenceSequence)) &&
739
- evidenceSequences.every((sequence) => items.some((item) => item.evidenceSequence === sequence)));
699
+ evidenceSequences.every(isPositiveInteger)))
700
+ return false;
701
+ const evidence = new Set(evidenceSequences);
702
+ const usedEvidence = new Set(items.map((item) => item.evidenceSequence));
703
+ return (new Set(items.map((item) => item.index)).size === items.length &&
704
+ evidence.size === evidenceSequences.length &&
705
+ usedEvidence.size === evidence.size &&
706
+ evidenceSequences.every((sequence) => usedEvidence.has(sequence)));
740
707
  }
741
708
  if (value.kind === 'TOOL_CALL_INPUT')
742
709
  return (hasOnlyKeys(value, [
@@ -829,23 +796,14 @@ function isContextGcReplacement(value) {
829
796
  }
830
797
  function isContextGcTarget(value) {
831
798
  return (isRecord(value) &&
832
- hasOnlyKeys(value, [
833
- 'sequence',
834
- 'recordId',
835
- 'role',
836
- 'callId',
837
- 'toolName',
838
- 'sourceHash',
839
- 'observationId'
840
- ]) &&
799
+ hasOnlyKeys(value, ['sequence', 'recordId', 'role', 'callId', 'toolName', 'observationId']) &&
841
800
  (value.observationId === undefined ||
842
801
  (value.role === 'tool' && isNonemptyString(value.observationId))) &&
843
802
  isPositiveInteger(value.sequence) &&
844
803
  isNonemptyString(value.recordId) &&
845
804
  (value.role === 'tool_call' || value.role === 'tool' || value.role === 'provider') &&
846
805
  (value.callId === undefined || isNonemptyString(value.callId)) &&
847
- (value.toolName === undefined || isNonemptyString(value.toolName)) &&
848
- isSha256(value.sourceHash));
806
+ (value.toolName === undefined || isNonemptyString(value.toolName)));
849
807
  }
850
808
  function isContextGcBase(value) {
851
809
  return (isRecord(value) &&
@@ -928,9 +886,6 @@ function hasOnlyKeys(value, keys) {
928
886
  function isNonemptyString(value) {
929
887
  return typeof value === 'string' && value.length > 0;
930
888
  }
931
- function isSha256(value) {
932
- return typeof value === 'string' && /^[a-f0-9]{64}$/u.test(value);
933
- }
934
889
  function isPositiveInteger(value) {
935
890
  return Number.isSafeInteger(value) && Number(value) > 0;
936
891
  }
@@ -943,13 +898,3 @@ function isNonnegativeFinite(value) {
943
898
  function isValidBoundary(value) {
944
899
  return Number.isSafeInteger(value) && value > 0;
945
900
  }
946
- function stableJson(value) {
947
- if (Array.isArray(value))
948
- return `[${value.map(stableJson).join(',')}]`;
949
- if (value !== null && typeof value === 'object')
950
- return `{${Object.entries(value)
951
- .sort(([left], [right]) => left.localeCompare(right))
952
- .map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`)
953
- .join(',')}}`;
954
- return JSON.stringify(value) ?? 'undefined';
955
- }
@@ -1,4 +1,4 @@
1
- import type { SessionRecord } from './jsonl-store.js';
1
+ import type { SessionRecord } from './store/index.js';
2
2
  import { type CodeObservation, type CodeToolCallRecord } from '../tools/code-mode/observations.js';
3
3
  /** Resolve private observation identity to real dispatch facts, not Provider tool calls. */
4
4
  export declare function codeObservationEvidence(records: readonly SessionRecord[], result: SessionRecord, observation: Extract<CodeObservation, {
@@ -47,19 +47,16 @@ export type ContextGcExecResult = {
47
47
  };
48
48
  export declare function contextGcPatchResultFromCompletedPayload(payload: unknown): ContextGcPatchResult | undefined;
49
49
  export declare function contextGcPatchResultFromFailedPayload(payload: unknown): ContextGcPatchResult | undefined;
50
- export declare function contextGcApplyPatchInputReplacement(arguments_: unknown, result: ContextGcPatchResult, evidenceSequence: number, formatVersion?: 1 | 2): string;
50
+ export declare function contextGcApplyPatchInputReplacement(arguments_: unknown, result: ContextGcPatchResult): string;
51
51
  export declare function contextGcStaleReadReplacement(input: {
52
52
  readonly path: string;
53
53
  readonly content: string;
54
- readonly evidenceSequence: number;
55
- readonly supersededByCallId: string;
56
54
  readonly operation: Exclude<ContextGcPatchFile['operation'], 'added'>;
57
- readonly formatVersion?: 1 | 2;
58
55
  }): string;
59
56
  export declare function contextGcWebOutputReplacement(toolName: ContextGcWebToolName, originalContent: string, truncated: boolean): string;
60
- export declare function contextGcExecInputReplacement(arguments_: unknown, formatVersion?: 1 | 2 | 3, toolName?: string): unknown;
61
- export declare function contextGcExecOutputReplacement(result: ContextGcExecResult, formatVersion?: 1 | 2 | 3): string;
57
+ export declare function contextGcExecInputReplacement(arguments_: unknown, toolName?: string): unknown;
58
+ export declare function contextGcExecOutputReplacement(result: ContextGcExecResult): string;
62
59
  export declare function normalizeContextGcExecResult(modelContent: unknown, completedPayload: unknown): ContextGcExecResult | undefined;
63
60
  export declare function parseContextGcExecResult(value: unknown): ContextGcExecResult | undefined;
64
61
  /** A returned tool wait is not proof that its retained JavaScript cell finished. */
65
- export declare function codeCellCompletionSequence(records: readonly import('./jsonl-store.js').SessionRecord[], completed: import('./jsonl-store.js').SessionRecord): number | undefined;
62
+ export declare function codeCellCompletionSequence(records: readonly import('./store/index.js').SessionRecord[], completed: import('./store/index.js').SessionRecord): number | undefined;
@@ -1,5 +1,4 @@
1
1
  import { contextGcMarkup } from './context-gc-markup.js';
2
- import { createHash } from 'node:crypto';
3
2
  import { parseApplyPatchResult, parseApplyPatchPartialResult } from '../tools/shared/patch-result.js';
4
3
  const RAW_MODEL_CONTEXT_PREVIEW_CHARACTERS = 256;
5
4
  const EXEC_INPUT_COMPLETE_CHARACTERS = 512;
@@ -51,31 +50,22 @@ export function contextGcPatchResultFromFailedPayload(payload) {
51
50
  return undefined;
52
51
  return parseApplyPatchPartialResult(payload.data);
53
52
  }
54
- export function contextGcApplyPatchInputReplacement(arguments_, result, evidenceSequence, formatVersion = 2) {
53
+ export function contextGcApplyPatchInputReplacement(arguments_, result) {
55
54
  const original = typeof arguments_ === 'string' ? arguments_ : stableJson(arguments_);
56
55
  const summary = result.files
57
56
  .map((file) => `${file.operation} ${file.path}${file.targetPath ? ` -> ${file.targetPath}` : ''} (+${file.addedLines}/-${file.deletedLines})`)
58
57
  .join('; ');
59
58
  return contextGcMarkup('successful_apply_patch_input', {
60
- ...(formatVersion === 2 ? { formatVersion: 2 } : {}),
59
+ formatVersion: 2,
61
60
  originalBytes: Buffer.byteLength(original),
62
- ...(formatVersion === 1 ? { originalSha256: sha256(original), evidenceSequence } : {}),
63
61
  contextGc: `Applied successfully: ${summary}. Totals: ${result.totals.files} files, +${result.totals.addedLines}/-${result.totals.deletedLines}. The original patch body was reclaimed.`
64
62
  });
65
63
  }
66
64
  export function contextGcStaleReadReplacement(input) {
67
- const formatVersion = input.formatVersion ?? 2;
68
65
  return contextGcMarkup('stale_read', {
69
66
  path: input.path,
70
- ...(formatVersion === 2 ? { formatVersion: 2 } : {}),
67
+ formatVersion: 2,
71
68
  originalBytes: Buffer.byteLength(input.content),
72
- ...(formatVersion === 1
73
- ? {
74
- originalSha256: sha256(input.content),
75
- supersededByCallId: input.supersededByCallId,
76
- evidenceSequence: input.evidenceSequence
77
- }
78
- : {}),
79
69
  operation: input.operation,
80
70
  contextGc: 'This read predates a successful apply_patch. Re-read the path before relying on its contents.'
81
71
  });
@@ -92,12 +82,11 @@ export function contextGcWebOutputReplacement(toolName, originalContent, truncat
92
82
  contextGc: 'Detailed web tool output was reclaimed after six successful rollouts. An incomplete preview is not the complete search result or page, and GC did not access the network.'
93
83
  });
94
84
  }
95
- export function contextGcExecInputReplacement(arguments_, formatVersion = 3, toolName = 'exec') {
85
+ export function contextGcExecInputReplacement(arguments_, toolName = 'exec') {
96
86
  if (!isRecord(arguments_))
97
87
  return contextGcMarkup('terminal_exec_input', {
98
- ...(formatVersion === 3 ? { formatVersion: 3 } : {}),
99
- originalBytes: Buffer.byteLength(stableJson(arguments_)),
100
- ...(formatVersion === 3 ? {} : { originalSha256: sha256(stableJson(arguments_)) })
88
+ formatVersion: 3,
89
+ originalBytes: Buffer.byteLength(stableJson(arguments_))
101
90
  });
102
91
  const action = typeof arguments_.action === 'string'
103
92
  ? arguments_.action
@@ -111,21 +100,20 @@ export function contextGcExecInputReplacement(arguments_, formatVersion = 3, too
111
100
  action,
112
101
  contextGc: {
113
102
  kind: 'terminal_exec_input',
114
- ...(formatVersion >= 2 ? { formatVersion } : {}),
115
- originalBytes: Buffer.byteLength(original),
116
- ...(formatVersion <= 2 ? { originalSha256: sha256(original) } : {})
103
+ formatVersion: 3,
104
+ originalBytes: Buffer.byteLength(original)
117
105
  }
118
106
  };
119
107
  for (const key of ['cwd', 'processId', 'timeoutMs', 'yieldMs'])
120
108
  if (arguments_[key] !== undefined)
121
109
  retained[key] = arguments_[key];
122
110
  if (typeof arguments_.command === 'string')
123
- retainExecText(retained, 'command', arguments_.command, formatVersion);
111
+ retainExecText(retained, 'command', arguments_.command);
124
112
  if (typeof arguments_.data === 'string')
125
- retainExecText(retained, 'data', arguments_.data, formatVersion);
113
+ retainExecText(retained, 'data', arguments_.data);
126
114
  return retained;
127
115
  }
128
- export function contextGcExecOutputReplacement(result, formatVersion = 3) {
116
+ export function contextGcExecOutputReplacement(result) {
129
117
  if (result.source === 'MODEL_CONTEXT_TRUNCATED')
130
118
  return JSON.stringify({
131
119
  status: result.status,
@@ -139,8 +127,7 @@ export function contextGcExecOutputReplacement(result, formatVersion = 3) {
139
127
  modelContextTruncated: true,
140
128
  modelContextBytes: Buffer.byteLength(result.modelContextContent),
141
129
  modelContextPreview: unicodeHeadTail(result.modelContextContent, RAW_MODEL_CONTEXT_PREVIEW_CHARACTERS),
142
- ...(formatVersion >= 2 ? { contextGcFormatVersion: formatVersion } : {}),
143
- ...(formatVersion <= 2 ? { modelContextSha256: sha256(result.modelContextContent) } : {}),
130
+ contextGcFormatVersion: 3,
144
131
  contextGc: 'The model-visible terminal result was truncated after execution and is no longer valid JSON. Detailed terminal input/output was reclaimed after the process reached a stable terminal state. Re-run the command if full output is required.'
145
132
  });
146
133
  const stdout = result.stdout;
@@ -156,32 +143,20 @@ export function contextGcExecOutputReplacement(result, formatVersion = 3) {
156
143
  stderrBytes: nonnegativeNumber(result.stderrBytes) ?? Buffer.byteLength(stderr),
157
144
  stdoutDroppedBytes: nonnegativeNumber(result.stdoutDroppedBytes) ?? 0,
158
145
  stderrDroppedBytes: nonnegativeNumber(result.stderrDroppedBytes) ?? 0,
159
- ...(formatVersion <= 2
160
- ? {
161
- stdoutSha256: sha256(stdout),
162
- stderrSha256: sha256(stderr)
163
- }
164
- : {}),
165
146
  stdoutPreview,
166
147
  stderrPreview,
167
- ...(formatVersion >= 2
168
- ? {
169
- stdoutLines: lineCount(stdout),
170
- stderrLines: lineCount(stderr),
171
- stdoutPreviewComplete: result.truncated === false &&
172
- result.stdoutDroppedBytes === 0 &&
173
- result.stdoutBytes === Buffer.byteLength(stdout) &&
174
- stdoutPreview === stdout,
175
- stderrPreviewComplete: result.truncated === false &&
176
- result.stderrDroppedBytes === 0 &&
177
- result.stderrBytes === Buffer.byteLength(stderr) &&
178
- stderrPreview === stderr,
179
- contextGcFormatVersion: formatVersion
180
- }
181
- : {}),
182
- contextGc: formatVersion >= 2
183
- ? 'Detailed terminal input/output was reclaimed after the process reached a stable terminal state. An incomplete preview is not the complete result. Re-run the command if full output is required.'
184
- : 'Detailed terminal input/output was reclaimed after the process reached a stable terminal state. Re-run the command if full output is required.'
148
+ stdoutLines: lineCount(stdout),
149
+ stderrLines: lineCount(stderr),
150
+ stdoutPreviewComplete: result.truncated === false &&
151
+ result.stdoutDroppedBytes === 0 &&
152
+ result.stdoutBytes === Buffer.byteLength(stdout) &&
153
+ stdoutPreview === stdout,
154
+ stderrPreviewComplete: result.truncated === false &&
155
+ result.stderrDroppedBytes === 0 &&
156
+ result.stderrBytes === Buffer.byteLength(stderr) &&
157
+ stderrPreview === stderr,
158
+ contextGcFormatVersion: 3,
159
+ contextGc: 'Detailed terminal input/output was reclaimed after the process reached a stable terminal state. An incomplete preview is not the complete result. Re-run the command if full output is required.'
185
160
  });
186
161
  }
187
162
  export function normalizeContextGcExecResult(modelContent, completedPayload) {
@@ -277,19 +252,13 @@ function unicodeHeadTail(value, count) {
277
252
  .slice(-count)
278
253
  .join('')}`;
279
254
  }
280
- function retainExecText(retained, key, value, formatVersion) {
281
- if (formatVersion === 1) {
282
- retained[`${key}Prefix`] = [...value].slice(0, EXEC_INPUT_PREVIEW_CHARACTERS).join('');
283
- return;
284
- }
255
+ function retainExecText(retained, key, value) {
285
256
  if ([...value].length <= EXEC_INPUT_COMPLETE_CHARACTERS) {
286
257
  retained[key] = value;
287
258
  return;
288
259
  }
289
260
  retained[`${key}Preview`] = unicodeHeadTail(value, EXEC_INPUT_PREVIEW_CHARACTERS);
290
261
  retained[`${key}Bytes`] = Buffer.byteLength(value);
291
- if (formatVersion === 2)
292
- retained[`${key}Sha256`] = sha256(value);
293
262
  }
294
263
  function lineCount(value) {
295
264
  return value.length === 0 ? 0 : value.split('\n').length;
@@ -297,9 +266,6 @@ function lineCount(value) {
297
266
  function nonnegativeNumber(value) {
298
267
  return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;
299
268
  }
300
- function sha256(value) {
301
- return createHash('sha256').update(value).digest('hex');
302
- }
303
269
  function stableJson(value) {
304
270
  if (Array.isArray(value))
305
271
  return `[${value.map(stableJson).join(',')}]`;
@@ -50,7 +50,4 @@ export declare function contextGcSubagentOutputReplacement(input: {
50
50
  readonly sourceContent: string;
51
51
  readonly source: ContextGcSubagentSnapshot;
52
52
  readonly terminal: ContextGcSubagentSnapshot;
53
- readonly terminalCallId: string;
54
- readonly evidenceSequence: number;
55
- readonly formatVersion?: 1 | 2;
56
53
  }): string;
@@ -1,4 +1,3 @@
1
- import { createHash } from 'node:crypto';
2
1
  export function normalizeContextGcSubagentSnapshot(modelContent, completedPayload, toolName) {
3
2
  if (typeof modelContent !== 'string' ||
4
3
  !isRecord(completedPayload) ||
@@ -92,7 +91,6 @@ export function contextGcSubagentSnapshotIsPreciselyCovered(source, retained) {
92
91
  }
93
92
  export function contextGcSubagentOutputReplacement(input) {
94
93
  const latestMessage = input.source.latestMessage;
95
- const formatVersion = input.formatVersion ?? 2;
96
94
  return JSON.stringify({
97
95
  agentId: input.source.agentId,
98
96
  description: input.source.description,
@@ -115,12 +113,10 @@ export function contextGcSubagentOutputReplacement(input) {
115
113
  turnId: latestMessage.turnId,
116
114
  phase: latestMessage.phase,
117
115
  timestamp: latestMessage.timestamp,
118
- ...(formatVersion === 1 ? { itemId: latestMessage.itemId } : {}),
119
116
  ...(latestMessage.truncated === undefined
120
117
  ? {}
121
118
  : { truncated: latestMessage.truncated }),
122
- textBytes: Buffer.byteLength(latestMessage.text),
123
- ...(formatVersion === 1 ? { textSha256: sha256(latestMessage.text) } : {})
119
+ textBytes: Buffer.byteLength(latestMessage.text)
124
120
  }
125
121
  }),
126
122
  ...(input.source.latestActivity === undefined
@@ -128,18 +124,11 @@ export function contextGcSubagentOutputReplacement(input) {
128
124
  : { latestActivity: input.source.latestActivity }),
129
125
  contextGc: {
130
126
  kind: 'superseded_subagent_snapshot',
131
- ...(formatVersion === 2 ? { formatVersion } : {}),
127
+ formatVersion: 2,
132
128
  originalBytes: Buffer.byteLength(input.sourceContent),
133
- ...(formatVersion === 1 ? { originalSha256: sha256(input.sourceContent) } : {}),
134
129
  terminalStatus: input.terminal.status,
135
130
  terminalTurnId: contextGcCompletedSubagentTurnId(input.terminal) ??
136
131
  contextGcSubagentSnapshotTurnId(input.terminal),
137
- ...(formatVersion === 1
138
- ? {
139
- terminalCallId: input.terminalCallId,
140
- evidenceSequence: input.evidenceSequence
141
- }
142
- : {}),
143
132
  note: input.terminal.status === 'completed'
144
133
  ? 'This intermediate child-agent snapshot was superseded by retained completed evidence; complete Turn results remain in retained completed snapshots.'
145
134
  : 'This duplicate child-agent snapshot was superseded by a retained non-completed terminal snapshot. Only fields exactly covered by the retained snapshot were reclaimed.'
@@ -327,9 +316,6 @@ function evidenceIsCovered(source, terminal) {
327
316
  return (source === undefined ||
328
317
  source.every((item) => terminal?.some((candidate) => stableJson(candidate) === stableJson(item))));
329
318
  }
330
- function sha256(value) {
331
- return createHash('sha256').update(value).digest('hex');
332
- }
333
319
  function stableJson(value) {
334
320
  if (Array.isArray(value))
335
321
  return `[${value.map(stableJson).join(',')}]`;
@@ -1,4 +1,4 @@
1
- import type { SessionRecord } from './jsonl-store.js';
1
+ import type { SessionRecord } from './store/index.js';
2
2
  /** The application is self-contained; the receive record may precede the Compact window. */
3
3
  export declare function appliedInputRecord(record: SessionRecord): SessionRecord | undefined;
4
4
  /** Only the last checkpoint and its tail are needed, never a historical consume index. */