@myagentroam/agent 0.11.53 → 0.11.54
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/model/native-context.d.ts +6 -2
- package/dist/model/native-context.js +8 -19
- package/dist/runtime/compaction/retained-context.d.ts +5 -0
- package/dist/runtime/compaction/retained-context.js +44 -1
- package/dist/sdk/execution-compact-commit.d.ts +4 -2
- package/dist/sdk/execution-compact-commit.js +7 -3
- package/dist/sdk/execution-compaction.d.ts +1 -1
- package/dist/sdk/execution-compaction.js +21 -16
- package/dist/sdk/session-execution-factory.js +2 -1
- package/package.json +1 -1
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { ModelMessage } from './contracts.js';
|
|
2
|
-
/**
|
|
3
|
-
export declare function completedNativeThinkingIdentity(payload:
|
|
2
|
+
/** Adapters persist native items at completion; consumers need only type and identity. */
|
|
3
|
+
export declare function completedNativeThinkingIdentity(payload: {
|
|
4
|
+
role?: unknown;
|
|
5
|
+
provider?: unknown;
|
|
6
|
+
item?: unknown;
|
|
7
|
+
}, recordId: string): string | undefined;
|
|
4
8
|
/** Interpret only the existing native context record shapes and their model ownership. */
|
|
5
9
|
export declare function restoreNativeModelContext(payload: Record<string, unknown>, activeModelId?: string): ModelMessage | undefined;
|
|
@@ -1,29 +1,18 @@
|
|
|
1
1
|
import { anthropicThinkingBlock } from './anthropic-thinking.js';
|
|
2
|
-
/**
|
|
2
|
+
/** Adapters persist native items at completion; consumers need only type and identity. */
|
|
3
3
|
export function completedNativeThinkingIdentity(payload, recordId) {
|
|
4
4
|
if (payload.role !== 'provider')
|
|
5
5
|
return undefined;
|
|
6
|
+
const item = payload.item;
|
|
7
|
+
if (!item || typeof item !== 'object' || Array.isArray(item))
|
|
8
|
+
return undefined;
|
|
9
|
+
const block = item;
|
|
6
10
|
if (payload.provider === 'ANTHROPIC_MESSAGES') {
|
|
7
|
-
|
|
8
|
-
if (!item || typeof item !== 'object' || Array.isArray(item))
|
|
9
|
-
return undefined;
|
|
10
|
-
const block = item;
|
|
11
|
-
return (block.type === 'thinking' &&
|
|
12
|
-
typeof block.thinking === 'string' &&
|
|
13
|
-
typeof block.signature === 'string' &&
|
|
14
|
-
block.signature.length > 0) ||
|
|
15
|
-
(block.type === 'redacted_thinking' &&
|
|
16
|
-
typeof block.data === 'string' &&
|
|
17
|
-
block.data.length > 0)
|
|
18
|
-
? recordId
|
|
19
|
-
: undefined;
|
|
11
|
+
return block.type === 'thinking' || block.type === 'redacted_thinking' ? recordId : undefined;
|
|
20
12
|
}
|
|
21
|
-
|
|
22
|
-
if (!message?.item)
|
|
23
|
-
return undefined;
|
|
24
|
-
if (message.provider !== 'OPENAI_RESPONSES' || message.item.type !== 'reasoning')
|
|
13
|
+
if (payload.provider !== 'OPENAI_RESPONSES' || block.type !== 'reasoning')
|
|
25
14
|
return undefined;
|
|
26
|
-
return typeof
|
|
15
|
+
return typeof block.id === 'string' ? block.id : recordId;
|
|
27
16
|
}
|
|
28
17
|
/** Interpret only the existing native context record shapes and their model ownership. */
|
|
29
18
|
export function restoreNativeModelContext(payload, activeModelId) {
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { SessionModelMessage as ModelMessage } from '../../session/model-request.js';
|
|
2
2
|
import type { CompactSnapshotAnchor } from '../events.js';
|
|
3
|
+
/** Keep the live suffix intact, extending into the snapshot only to fill three native blocks. */
|
|
4
|
+
export declare function compactRetainedStart(messages: readonly ModelMessage[], snapshotLength: number, model: {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly protocol: ModelMessage['provider'];
|
|
7
|
+
}): number;
|
|
3
8
|
/** Use a public native identity, never private context text, as the visible boundary. */
|
|
4
9
|
export declare function compactSnapshotAnchor(messages: readonly ModelMessage[], sources: WeakMap<ModelMessage, import('../../session/record-contract.js').SessionRecord>): CompactSnapshotAnchor | undefined;
|
|
5
10
|
/** Decode the SDK-owned checkpoint suffix without promoting contextual text to real input. */
|
|
@@ -1,6 +1,49 @@
|
|
|
1
1
|
import { parseModelInputMetadata } from '../../session/record-projection.js';
|
|
2
|
-
import { restoreModelContext } from '../context/projection.js';
|
|
2
|
+
import { providerToolCallId, restoreModelContext } from '../context/projection.js';
|
|
3
3
|
import { parseModelImages } from '../../model/image.js';
|
|
4
|
+
import { completedNativeThinkingIdentity } from '../../model/native-context.js';
|
|
5
|
+
/** Keep the live suffix intact, extending into the snapshot only to fill three native blocks. */
|
|
6
|
+
export function compactRetainedStart(messages, snapshotLength, model) {
|
|
7
|
+
let start = snapshotLength;
|
|
8
|
+
const thinking = new Set();
|
|
9
|
+
for (let index = messages.length - 1; index >= 0 && thinking.size < 3; index--) {
|
|
10
|
+
const message = messages[index];
|
|
11
|
+
if (message.provider !== model.protocol ||
|
|
12
|
+
(message.providerModelId !== undefined && message.providerModelId !== model.id))
|
|
13
|
+
continue;
|
|
14
|
+
const identity = completedNativeThinkingIdentity(message, `message:${index}`);
|
|
15
|
+
if (identity === undefined || thinking.has(identity))
|
|
16
|
+
continue;
|
|
17
|
+
thinking.add(identity);
|
|
18
|
+
start = Math.min(start, index);
|
|
19
|
+
}
|
|
20
|
+
// The existing snapshot boundary already closes tool groups.
|
|
21
|
+
if (start === snapshotLength)
|
|
22
|
+
return start;
|
|
23
|
+
// A native item can follow text or tool calls within the same assistant response.
|
|
24
|
+
while (start > 0 && messages[start - 1].role !== 'user' && messages[start - 1].role !== 'tool')
|
|
25
|
+
start--;
|
|
26
|
+
// Resolve any retained result back to its call's assistant group in two linear passes.
|
|
27
|
+
const calls = new Map();
|
|
28
|
+
let responseStart = 0;
|
|
29
|
+
for (let index = 0; index < start; index++) {
|
|
30
|
+
const message = messages[index];
|
|
31
|
+
if (message.role === 'user' || message.role === 'tool')
|
|
32
|
+
responseStart = index + 1;
|
|
33
|
+
const callId = message.role === 'tool_call' ? message.callId : providerToolCallId(message);
|
|
34
|
+
if (callId !== undefined && !calls.has(callId))
|
|
35
|
+
calls.set(callId, responseStart);
|
|
36
|
+
}
|
|
37
|
+
for (let index = messages.length - 1; index >= start; index--) {
|
|
38
|
+
const message = messages[index];
|
|
39
|
+
if (message.role !== 'tool' || message.callId === undefined)
|
|
40
|
+
continue;
|
|
41
|
+
const callStart = calls.get(message.callId);
|
|
42
|
+
if (callStart !== undefined)
|
|
43
|
+
start = Math.min(start, callStart);
|
|
44
|
+
}
|
|
45
|
+
return start;
|
|
46
|
+
}
|
|
4
47
|
/** Use a public native identity, never private context text, as the visible boundary. */
|
|
5
48
|
export function compactSnapshotAnchor(messages, sources) {
|
|
6
49
|
for (let index = messages.length - 1; index >= 0; index--) {
|
|
@@ -2,6 +2,7 @@ import type { SessionModelMessage } from '../session/model-request.js';
|
|
|
2
2
|
import type { SessionRecord } from '../session/record-contract.js';
|
|
3
3
|
import type { SessionStore, SessionStoreCompactInput } from '../session/store/contracts.js';
|
|
4
4
|
import type { ResourceInputProjection } from './resource-input.js';
|
|
5
|
+
import { compactRetainedStart } from '../runtime/compaction/retained-context.js';
|
|
5
6
|
/** Commits one validated snapshot and records its fact before fallible live projection. */
|
|
6
7
|
export declare function commitExecutionCompaction(input: {
|
|
7
8
|
readonly store: Pick<SessionStore, 'compact'>;
|
|
@@ -9,9 +10,10 @@ export declare function commitExecutionCompaction(input: {
|
|
|
9
10
|
readonly signal: AbortSignal;
|
|
10
11
|
readonly prefix: readonly SessionModelMessage[];
|
|
11
12
|
readonly messages: readonly SessionModelMessage[];
|
|
13
|
+
readonly model: Parameters<typeof compactRetainedStart>[2];
|
|
12
14
|
readonly generation: string | undefined;
|
|
13
15
|
readonly messageSources: WeakMap<SessionModelMessage, SessionRecord>;
|
|
14
|
-
draft(): Omit<SessionStoreCompactInput, 'retainedModelContext' | 'inlineMediaState'>;
|
|
16
|
+
draft(retainedStart: number): Omit<SessionStoreCompactInput, 'retainedModelContext' | 'inlineMediaState'>;
|
|
15
17
|
readonly checkpoint: ResourceInputProjection['checkpoint'];
|
|
16
18
|
readonly withProjection: <T>(action: () => Promise<T>) => Promise<T>;
|
|
17
19
|
readonly currentGeneration: () => string | undefined;
|
|
@@ -20,4 +22,4 @@ export declare function commitExecutionCompaction(input: {
|
|
|
20
22
|
}): Promise<{
|
|
21
23
|
record: SessionRecord;
|
|
22
24
|
retained: SessionModelMessage[];
|
|
23
|
-
}>;
|
|
25
|
+
} | undefined>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AgentError } from '../error.js';
|
|
2
|
+
import { compactRetainedStart } from '../runtime/compaction/retained-context.js';
|
|
2
3
|
/** Commits one validated snapshot and records its fact before fallible live projection. */
|
|
3
4
|
export async function commitExecutionCompaction(input) {
|
|
4
5
|
return input.withProjection(async () => {
|
|
@@ -6,14 +7,17 @@ export async function commitExecutionCompaction(input) {
|
|
|
6
7
|
if (input.currentGeneration() !== input.generation ||
|
|
7
8
|
input.prefix.some((message, index) => input.messages[index] !== message))
|
|
8
9
|
throw new AgentError('MAR_AGENT_COMPACT_STALE', 'The compaction prefix has changed.');
|
|
10
|
+
const retainedStart = compactRetainedStart(input.messages, input.prefix.length, input.model);
|
|
11
|
+
if (retainedStart === 0)
|
|
12
|
+
return undefined;
|
|
9
13
|
const retained = input.messages
|
|
10
|
-
.slice(
|
|
14
|
+
.slice(retainedStart)
|
|
11
15
|
.filter((message) => message.contextKind !== 'private' || message.role === 'provider');
|
|
12
16
|
const retainedModelContext = retained.map((message) => {
|
|
13
17
|
const source = input.messageSources.get(message);
|
|
14
18
|
const saved = source?.type === 'model.context' && source.payload.inputRef
|
|
15
19
|
? source.payload
|
|
16
|
-
: source?.type === 'compact.completed'
|
|
20
|
+
: source?.type === 'compact.completed' && message.metadata?.recordId !== undefined
|
|
17
21
|
? (source.payload
|
|
18
22
|
.retainedModelContext ?? []).find((item) => item.inputRef === message.metadata?.recordId)
|
|
19
23
|
: undefined;
|
|
@@ -30,7 +34,7 @@ export async function commitExecutionCompaction(input) {
|
|
|
30
34
|
};
|
|
31
35
|
});
|
|
32
36
|
const record = await input.store.compact(input.sessionId, {
|
|
33
|
-
...input.draft(),
|
|
37
|
+
...input.draft(retainedStart),
|
|
34
38
|
inlineMediaState: input.checkpoint(retained),
|
|
35
39
|
retainedModelContext
|
|
36
40
|
}, { signal: input.signal });
|
|
@@ -17,7 +17,7 @@ export declare function createExecutionCompaction(ports: {
|
|
|
17
17
|
readonly sessionId: string;
|
|
18
18
|
readonly executionId: string;
|
|
19
19
|
readonly turnId: string;
|
|
20
|
-
readonly model: Pick<ResolvedModelConfiguration, 'id' | 'contextWindowTokens'>;
|
|
20
|
+
readonly model: Pick<ResolvedModelConfiguration, 'id' | 'protocol' | 'contextWindowTokens'>;
|
|
21
21
|
readonly messages: SessionModelMessage[];
|
|
22
22
|
readonly pendingInputs: Map<string, SessionRecord>;
|
|
23
23
|
readonly messageSources: WeakMap<SessionModelMessage, SessionRecord>;
|
|
@@ -17,7 +17,6 @@ export function createExecutionCompaction(ports) {
|
|
|
17
17
|
message.contextKind === 'summary'))
|
|
18
18
|
return false;
|
|
19
19
|
const history = structuredClone(prefix).map(({ images: _images, ...message }) => message);
|
|
20
|
-
const prefixInputs = modelContext.compactInputs(prefix);
|
|
21
20
|
const tools = structuredClone(ports.snapshotTools());
|
|
22
21
|
const generation = modelContext.worldState.generation;
|
|
23
22
|
const usage = ports.usage();
|
|
@@ -62,7 +61,7 @@ export function createExecutionCompaction(ports) {
|
|
|
62
61
|
await prepare();
|
|
63
62
|
signal.throwIfAborted();
|
|
64
63
|
const resources = await ports.retainedResources();
|
|
65
|
-
|
|
64
|
+
let replacementHistory;
|
|
66
65
|
let committed = false;
|
|
67
66
|
let retained;
|
|
68
67
|
try {
|
|
@@ -72,6 +71,7 @@ export function createExecutionCompaction(ports) {
|
|
|
72
71
|
signal,
|
|
73
72
|
prefix,
|
|
74
73
|
messages,
|
|
74
|
+
model: ports.model,
|
|
75
75
|
generation,
|
|
76
76
|
messageSources: ports.messageSources,
|
|
77
77
|
checkpoint: (value) => ports.resourceInput.checkpoint(value),
|
|
@@ -85,21 +85,26 @@ export function createExecutionCompaction(ports) {
|
|
|
85
85
|
modelContext.replaceCompactMessages(replacementHistory, value);
|
|
86
86
|
ports.updateBoundary(messages.length - value.length);
|
|
87
87
|
},
|
|
88
|
-
draft: () =>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
88
|
+
draft: (retainedStart) => {
|
|
89
|
+
replacementHistory = buildCompactedHistory(candidate.summary, modelContext.compactInputs(prefix.slice(0, retainedStart)), ports.userTokenLimit);
|
|
90
|
+
return {
|
|
91
|
+
summary: candidate.summary,
|
|
92
|
+
replacementHistory,
|
|
93
|
+
pendingInputs: [...ports.pendingInputs.values()],
|
|
94
|
+
snapshotMessageCount: prefix.length,
|
|
95
|
+
...(anchorRecordId ? { snapshotRecordId: anchorRecordId } : {}),
|
|
96
|
+
automatic: ports.mode !== 'compact',
|
|
97
|
+
environment: ports.environment(),
|
|
98
|
+
modelId: ports.model.id,
|
|
99
|
+
contextWindowTokens: ports.model.contextWindowTokens,
|
|
100
|
+
...(candidate.usage === undefined ? {} : { usage: candidate.usage }),
|
|
101
|
+
executionId: ports.executionId,
|
|
102
|
+
turnId: ports.turnId
|
|
103
|
+
};
|
|
104
|
+
}
|
|
102
105
|
});
|
|
106
|
+
if (!result)
|
|
107
|
+
return false;
|
|
103
108
|
retained = result.retained;
|
|
104
109
|
await modelContext.adoptCompactCheckpoint(result.record.recordId, replacementHistory, retained, resources);
|
|
105
110
|
ports.invalidateUsage();
|
|
@@ -165,7 +165,8 @@ export function createSessionExecutionFactory(ports) {
|
|
|
165
165
|
const compactMayContainAgentInstructions = contextRecords.some((record) => compactSummaryFromCheckpoint(record) !== undefined);
|
|
166
166
|
const restored = await restoreMessages(store, sessionId, contextRecords, {
|
|
167
167
|
messageSources,
|
|
168
|
-
|
|
168
|
+
// Keep durable references for the retained tail; the Compact snapshot removes images.
|
|
169
|
+
includeImages: true
|
|
169
170
|
});
|
|
170
171
|
let modelLifecycle;
|
|
171
172
|
let applyCompactBoundary = () => { };
|