@deepstrike/sdk 0.2.66 → 0.2.68
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/memory/protocols.d.ts +0 -1
- package/dist/providers/anthropic-adapter.js +0 -2
- package/dist/providers/base.js +9 -6
- package/dist/providers/content-normalization.d.ts +0 -1
- package/dist/providers/content-normalization.js +2 -8
- package/dist/providers/gemini-adapter.js +0 -5
- package/dist/providers/openai-chat.js +0 -3
- package/dist/providers/openai-responses-adapter.js +0 -4
- package/dist/runtime/kernel-step.js +5 -13
- package/dist/runtime/mcp-proxy-plane.d.ts +9 -0
- package/dist/runtime/mcp-proxy-plane.js +8 -2
- package/dist/runtime/replay-fixture.d.ts +2 -2
- package/dist/runtime/replay-fixture.js +2 -4
- package/dist/runtime/replay-provider.d.ts +2 -2
- package/dist/runtime/replay-provider.js +3 -4
- package/dist/runtime/runner.js +2 -17
- package/dist/runtime/session-repair.d.ts +1 -1
- package/dist/runtime/session-repair.js +2 -5
- package/dist/types/agent.d.ts +0 -1
- package/dist/types/agent.js +0 -2
- package/dist/types.d.ts +4 -12
- package/package.json +2 -2
|
@@ -325,13 +325,11 @@ export class AnthropicMessagesAdapter {
|
|
|
325
325
|
}
|
|
326
326
|
if (hasTextualToolCall(content, decodeInput.input))
|
|
327
327
|
throw textualToolCallError();
|
|
328
|
-
const usage = this.normalizeUsage(raw.usage);
|
|
329
328
|
const blocks = raw.content;
|
|
330
329
|
return {
|
|
331
330
|
message: {
|
|
332
331
|
role: "assistant",
|
|
333
332
|
content,
|
|
334
|
-
...(usage ? { tokenCount: usage.outputTokens } : {}),
|
|
335
333
|
toolCalls,
|
|
336
334
|
},
|
|
337
335
|
...(blocks?.length ? { replay: { protocol: "anthropic-messages", native_blocks: blocks } } : {}),
|
package/dist/providers/base.js
CHANGED
|
@@ -134,10 +134,11 @@ export function toAnthropicContent(msg) {
|
|
|
134
134
|
if (p.type === "text")
|
|
135
135
|
return { type: "text", text: p.text };
|
|
136
136
|
if (p.type === "image") {
|
|
137
|
-
if (p.
|
|
138
|
-
return { type: "image", source: { type: "base64", media_type: p.mediaType ?? "image/png", data: p.data } };
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
if (p.source.kind === "base64")
|
|
138
|
+
return { type: "image", source: { type: "base64", media_type: p.mediaType ?? "image/png", data: p.source.data } };
|
|
139
|
+
if (p.source.kind === "url")
|
|
140
|
+
return { type: "image", source: { type: "url", url: p.source.url } };
|
|
141
|
+
return { type: "text", text: "[image]" };
|
|
141
142
|
}
|
|
142
143
|
if (p.type === "audio") {
|
|
143
144
|
throw new UnsupportedModalityError("audio", "anthropic");
|
|
@@ -254,11 +255,13 @@ export function toOpenAIContent(msg) {
|
|
|
254
255
|
if (p.type === "text")
|
|
255
256
|
return { type: "text", text: p.text };
|
|
256
257
|
if (p.type === "image") {
|
|
257
|
-
const url = p.
|
|
258
|
+
const url = p.source.kind === "base64" ? `data:${p.mediaType ?? "image/png"};base64,${p.source.data}` : p.source.kind === "url" ? p.source.url : "";
|
|
258
259
|
return { type: "image_url", image_url: { url, ...(p.detail ? { detail: p.detail } : {}) } };
|
|
259
260
|
}
|
|
260
261
|
if (p.type === "audio") {
|
|
261
|
-
|
|
262
|
+
if (p.source.kind !== "base64")
|
|
263
|
+
return { type: "text", text: "[audio]" };
|
|
264
|
+
return { type: "input_audio", input_audio: { data: p.source.data, format: openaiAudioFormat(p.mediaType) } };
|
|
262
265
|
}
|
|
263
266
|
if (p.type === "tool_result") {
|
|
264
267
|
return { type: "text", text: p.output };
|
|
@@ -21,7 +21,6 @@ export interface CanonicalMessage {
|
|
|
21
21
|
/** `blocks` remains authoritative; this only preserves an observable wire-shape distinction. */
|
|
22
22
|
readonly contentForm?: "text" | "blocks";
|
|
23
23
|
readonly toolCalls?: readonly ToolCall[];
|
|
24
|
-
readonly tokenCount?: number;
|
|
25
24
|
readonly providerReplay?: ProviderReplay;
|
|
26
25
|
}
|
|
27
26
|
export interface CanonicalRenderedContext {
|
|
@@ -145,14 +145,9 @@ function normalizeMessage(message, replayForMessage) {
|
|
|
145
145
|
if (part.type === "text")
|
|
146
146
|
return { type: "text", text: part.text };
|
|
147
147
|
if (part.type === "image") {
|
|
148
|
-
if ((part.url === undefined) === (part.data === undefined)) {
|
|
149
|
-
throw new ContentValidationError("image requires exactly one of url or data");
|
|
150
|
-
}
|
|
151
148
|
return {
|
|
152
149
|
type: "image",
|
|
153
|
-
source: part.
|
|
154
|
-
? { kind: "base64", data: part.data }
|
|
155
|
-
: { kind: "url", url: part.url },
|
|
150
|
+
source: part.source,
|
|
156
151
|
...(part.mediaType ? { mediaType: part.mediaType } : {}),
|
|
157
152
|
...(part.detail ? { providerOptions: { openai_detail: part.detail } } : {}),
|
|
158
153
|
};
|
|
@@ -160,7 +155,7 @@ function normalizeMessage(message, replayForMessage) {
|
|
|
160
155
|
if (part.type === "audio") {
|
|
161
156
|
return {
|
|
162
157
|
type: "audio",
|
|
163
|
-
source:
|
|
158
|
+
source: part.source,
|
|
164
159
|
mediaType: part.mediaType,
|
|
165
160
|
};
|
|
166
161
|
}
|
|
@@ -171,7 +166,6 @@ function normalizeMessage(message, replayForMessage) {
|
|
|
171
166
|
blocks,
|
|
172
167
|
contentForm: message.contentParts === undefined ? "text" : "blocks",
|
|
173
168
|
...(message.toolCalls ? { toolCalls: message.toolCalls } : {}),
|
|
174
|
-
...(message.tokenCount !== undefined ? { tokenCount: message.tokenCount } : {}),
|
|
175
169
|
...(providerReplay ? { providerReplay } : {}),
|
|
176
170
|
};
|
|
177
171
|
}
|
|
@@ -171,15 +171,10 @@ export class GeminiAdapter {
|
|
|
171
171
|
}
|
|
172
172
|
decodeComplete(raw, _input) {
|
|
173
173
|
const decoded = decodeParts(raw);
|
|
174
|
-
const usage = this.normalizeUsage(raw.usageMetadata);
|
|
175
|
-
const rawUsage = raw.usageMetadata;
|
|
176
|
-
const tokenCount = usage?.outputTokens
|
|
177
|
-
?? (rawUsage ? numberField(rawUsage, "totalTokenCount") : undefined);
|
|
178
174
|
return {
|
|
179
175
|
message: {
|
|
180
176
|
role: "assistant",
|
|
181
177
|
content: decoded.content,
|
|
182
|
-
...(tokenCount !== undefined ? { tokenCount } : {}),
|
|
183
178
|
toolCalls: decoded.toolCalls,
|
|
184
179
|
},
|
|
185
180
|
};
|
|
@@ -235,9 +235,6 @@ export class OpenAIChatAdapter {
|
|
|
235
235
|
const message = {
|
|
236
236
|
role: "assistant",
|
|
237
237
|
content,
|
|
238
|
-
...(usage ? {
|
|
239
|
-
tokenCount: numberField(usage, "completion_tokens") ?? numberField(usage, "total_tokens"),
|
|
240
|
-
} : {}),
|
|
241
238
|
toolCalls,
|
|
242
239
|
};
|
|
243
240
|
const replay = replayForTurn(dialect, "complete", input.input.resolved.identity.modelId, content, toolCalls, {
|
|
@@ -191,15 +191,11 @@ export class OpenAIResponsesAdapter {
|
|
|
191
191
|
: undefined;
|
|
192
192
|
if (usage)
|
|
193
193
|
this.normalizeUsage(usage);
|
|
194
|
-
const tokenCount = usage
|
|
195
|
-
? numberField(usage, "output_tokens") ?? numberField(usage, "total_tokens")
|
|
196
|
-
: undefined;
|
|
197
194
|
return {
|
|
198
195
|
message: {
|
|
199
196
|
role: "assistant",
|
|
200
197
|
content: decoded.content,
|
|
201
198
|
toolCalls: decoded.toolCalls,
|
|
202
|
-
...(tokenCount !== undefined ? { tokenCount } : {}),
|
|
203
199
|
},
|
|
204
200
|
};
|
|
205
201
|
}
|
|
@@ -77,9 +77,6 @@ export function messageToKernelMessage(message) {
|
|
|
77
77
|
arguments: tryParseJson(tc.arguments) ?? {},
|
|
78
78
|
})),
|
|
79
79
|
};
|
|
80
|
-
if (message.tokenCount !== undefined) {
|
|
81
|
-
out.token_count = message.tokenCount;
|
|
82
|
-
}
|
|
83
80
|
if (message.contentParts && message.contentParts.length > 0) {
|
|
84
81
|
out.content = message.contentParts.map(part => {
|
|
85
82
|
if (part.type === "text")
|
|
@@ -95,14 +92,13 @@ export function messageToKernelMessage(message) {
|
|
|
95
92
|
if (part.type === "image") {
|
|
96
93
|
return {
|
|
97
94
|
type: "image",
|
|
98
|
-
|
|
99
|
-
data: part.data,
|
|
95
|
+
source: part.source,
|
|
100
96
|
media_type: part.mediaType,
|
|
101
97
|
detail: part.detail,
|
|
102
98
|
};
|
|
103
99
|
}
|
|
104
100
|
if (part.type === "audio") {
|
|
105
|
-
return { type: "audio",
|
|
101
|
+
return { type: "audio", source: part.source, media_type: part.mediaType };
|
|
106
102
|
}
|
|
107
103
|
return { type: "text", text: message.content };
|
|
108
104
|
});
|
|
@@ -113,12 +109,12 @@ export function messageToKernelMessage(message) {
|
|
|
113
109
|
return out;
|
|
114
110
|
}
|
|
115
111
|
export function toolResultToKernel(result) {
|
|
112
|
+
// Usage evidence enters through the host event contract; content alone cannot establish usage.
|
|
116
113
|
const out = {
|
|
117
114
|
call_id: result.callId,
|
|
118
115
|
output: result.output,
|
|
119
116
|
is_error: result.isError,
|
|
120
117
|
is_fatal: result.isFatal ?? false,
|
|
121
|
-
token_count: result.tokenCount ?? null,
|
|
122
118
|
};
|
|
123
119
|
if (result.errorKind !== undefined) {
|
|
124
120
|
out.error_kind = result.errorKind;
|
|
@@ -212,9 +208,6 @@ export function kernelMessageToSdk(raw) {
|
|
|
212
208
|
arguments: JSON.stringify(tc.arguments ?? {}),
|
|
213
209
|
})),
|
|
214
210
|
};
|
|
215
|
-
if (typeof (raw.tokens ?? raw.token_count) === "number") {
|
|
216
|
-
message.tokenCount = Number(raw.tokens ?? raw.token_count);
|
|
217
|
-
}
|
|
218
211
|
if (structuredContent) {
|
|
219
212
|
message.contentParts = structuredContent
|
|
220
213
|
.filter((part) => typeof part === "object" && part !== null)
|
|
@@ -233,8 +226,7 @@ export function kernelMessageToSdk(raw) {
|
|
|
233
226
|
if (part.type === "image") {
|
|
234
227
|
return {
|
|
235
228
|
type: "image",
|
|
236
|
-
|
|
237
|
-
data: part.data,
|
|
229
|
+
source: part.source,
|
|
238
230
|
mediaType: part.media_type,
|
|
239
231
|
detail: part.detail,
|
|
240
232
|
};
|
|
@@ -242,7 +234,7 @@ export function kernelMessageToSdk(raw) {
|
|
|
242
234
|
if (part.type === "audio") {
|
|
243
235
|
return {
|
|
244
236
|
type: "audio",
|
|
245
|
-
|
|
237
|
+
source: part.source,
|
|
246
238
|
mediaType: String(part.media_type ?? "audio/wav"),
|
|
247
239
|
};
|
|
248
240
|
}
|
|
@@ -6,6 +6,15 @@ import type { CredentialVault } from "./credential-vault.js";
|
|
|
6
6
|
export interface McpContentBlock {
|
|
7
7
|
type: string;
|
|
8
8
|
text?: string;
|
|
9
|
+
source?: {
|
|
10
|
+
kind?: string;
|
|
11
|
+
url?: string;
|
|
12
|
+
data?: string;
|
|
13
|
+
id?: string;
|
|
14
|
+
handle?: string;
|
|
15
|
+
owner?: string;
|
|
16
|
+
payloadRef?: string;
|
|
17
|
+
};
|
|
9
18
|
data?: string;
|
|
10
19
|
mimeType?: string;
|
|
11
20
|
}
|
|
@@ -29,10 +29,16 @@ export function mcpResultToToolOutput(result) {
|
|
|
29
29
|
if (c.type === "text")
|
|
30
30
|
return { type: "text", text: c.text ?? "" };
|
|
31
31
|
if (c.type === "image") {
|
|
32
|
-
|
|
32
|
+
const source = c.source?.kind === "url" && c.source.url
|
|
33
|
+
? { kind: "url", url: c.source.url }
|
|
34
|
+
: { kind: "base64", data: c.source?.data ?? c.data ?? "" };
|
|
35
|
+
return { type: "image", source, mediaType: c.mimeType };
|
|
33
36
|
}
|
|
34
37
|
if (c.type === "audio") {
|
|
35
|
-
|
|
38
|
+
const source = c.source?.kind === "url" && c.source.url
|
|
39
|
+
? { kind: "url", url: c.source.url }
|
|
40
|
+
: { kind: "base64", data: c.source?.data ?? c.data ?? "" };
|
|
41
|
+
return { type: "audio", source, mediaType: c.mimeType ?? "audio/wav" };
|
|
36
42
|
}
|
|
37
43
|
return { type: "text", text: JSON.stringify(c) };
|
|
38
44
|
});
|
|
@@ -15,8 +15,8 @@ import type { SessionEvent } from "./session-log.js";
|
|
|
15
15
|
* one Message per event. Pass the result directly to `new ReplayProvider(messages)`.
|
|
16
16
|
*
|
|
17
17
|
* Accepts both wire shapes the SDK uses interchangeably:
|
|
18
|
-
* - in-memory: `{ toolCalls,
|
|
19
|
-
* - serialised session-log: `{ tool_calls, token_count, provider_replay }` (snake_case)
|
|
18
|
+
* - in-memory: `{ toolCalls, providerReplay }` (camelCase)
|
|
19
|
+
* - serialised session-log: `{ tool_calls, token_count, provider_replay }` (snake_case; token_count is wire evidence)
|
|
20
20
|
*
|
|
21
21
|
* @param events Session events, in original order. Accepts both `{ event, seq }` (the shape
|
|
22
22
|
* `SessionLog.read()` returns) and a bare `SessionEvent[]`.
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* one Message per event. Pass the result directly to `new ReplayProvider(messages)`.
|
|
14
14
|
*
|
|
15
15
|
* Accepts both wire shapes the SDK uses interchangeably:
|
|
16
|
-
* - in-memory: `{ toolCalls,
|
|
17
|
-
* - serialised session-log: `{ tool_calls, token_count, provider_replay }` (snake_case)
|
|
16
|
+
* - in-memory: `{ toolCalls, providerReplay }` (camelCase)
|
|
17
|
+
* - serialised session-log: `{ tool_calls, token_count, provider_replay }` (snake_case; token_count is wire evidence)
|
|
18
18
|
*
|
|
19
19
|
* @param events Session events, in original order. Accepts both `{ event, seq }` (the shape
|
|
20
20
|
* `SessionLog.read()` returns) and a bare `SessionEvent[]`.
|
|
@@ -27,14 +27,12 @@ export function extractRecordedMessages(events) {
|
|
|
27
27
|
continue;
|
|
28
28
|
const e = event;
|
|
29
29
|
const tcRaw = (e.toolCalls ?? e.tool_calls);
|
|
30
|
-
const tokenCount = (e.tokenCount ?? e.token_count);
|
|
31
30
|
out.push({
|
|
32
31
|
role: "assistant",
|
|
33
32
|
content: typeof e.content === "string" ? e.content : "",
|
|
34
33
|
...(Array.isArray(tcRaw) && tcRaw.length > 0
|
|
35
34
|
? { toolCalls: normalizeToolCalls(tcRaw) }
|
|
36
35
|
: {}),
|
|
37
|
-
...(tokenCount !== undefined ? { tokenCount } : {}),
|
|
38
36
|
});
|
|
39
37
|
}
|
|
40
38
|
return out;
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
* - `inputTokens` is ESTIMATED from the rendered context this call carries (NOT a recorded value
|
|
17
17
|
* from the original run). That's the point of replay-for-benchmarking: prompt may differ across
|
|
18
18
|
* variants, response is pinned, so a cost Δ purely reflects the prompt change.
|
|
19
|
-
* - `outputTokens` is
|
|
20
|
-
*
|
|
19
|
+
* - `outputTokens` is estimated from `message.content.length / 4`; provider usage belongs to
|
|
20
|
+
* the session measurement plane, never to the public Message mirror.
|
|
21
21
|
* - `cacheReadInputTokens` / `cacheCreationInputTokens` are emitted as 0 — replay has no real
|
|
22
22
|
* cache state. Mechanisms whose Δ depends on cache behavior must validate with a live A/B too.
|
|
23
23
|
*
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
* - `inputTokens` is ESTIMATED from the rendered context this call carries (NOT a recorded value
|
|
17
17
|
* from the original run). That's the point of replay-for-benchmarking: prompt may differ across
|
|
18
18
|
* variants, response is pinned, so a cost Δ purely reflects the prompt change.
|
|
19
|
-
* - `outputTokens` is
|
|
20
|
-
*
|
|
19
|
+
* - `outputTokens` is estimated from `message.content.length / 4`; provider usage belongs to
|
|
20
|
+
* the session measurement plane, never to the public Message mirror.
|
|
21
21
|
* - `cacheReadInputTokens` / `cacheCreationInputTokens` are emitted as 0 — replay has no real
|
|
22
22
|
* cache state. Mechanisms whose Δ depends on cache behavior must validate with a live A/B too.
|
|
23
23
|
*
|
|
@@ -68,13 +68,12 @@ export class ReplayProvider {
|
|
|
68
68
|
role: "assistant",
|
|
69
69
|
content: msg.content,
|
|
70
70
|
...(msg.toolCalls ? { toolCalls: msg.toolCalls } : {}),
|
|
71
|
-
...(msg.tokenCount !== undefined ? { tokenCount: msg.tokenCount } : {}),
|
|
72
71
|
};
|
|
73
72
|
}
|
|
74
73
|
async *stream(context, tools, _extensions, _state, _signal) {
|
|
75
74
|
const msg = this.pull();
|
|
76
75
|
const inputTokens = this.estimateInputTokens(context, tools);
|
|
77
|
-
const outputTokens =
|
|
76
|
+
const outputTokens = this.tokenizer(msg.content || "");
|
|
78
77
|
const usage = {
|
|
79
78
|
type: "usage",
|
|
80
79
|
totalTokens: inputTokens + outputTokens,
|
package/dist/runtime/runner.js
CHANGED
|
@@ -1869,7 +1869,6 @@ export class RuntimeRunner {
|
|
|
1869
1869
|
role: "assistant",
|
|
1870
1870
|
content: finalText,
|
|
1871
1871
|
toolCalls: canonicalToolCalls,
|
|
1872
|
-
tokenCount: turnOutputTokens || turnTokens || undefined,
|
|
1873
1872
|
};
|
|
1874
1873
|
// P4 §2: assemble the measurement from the exact numbers that cross the boundary today
|
|
1875
1874
|
// (inputTokens/outputTokens turn counters), enriched with the raw provider frame's cache
|
|
@@ -2325,7 +2324,6 @@ export class RuntimeRunner {
|
|
|
2325
2324
|
call_id: r.callId,
|
|
2326
2325
|
output: r.output,
|
|
2327
2326
|
is_error: r.isError,
|
|
2328
|
-
token_count: r.tokenCount,
|
|
2329
2327
|
content: { blocks: toolOutputBlocksToDurable(r.contentParts?.length ? r.contentParts : [{ type: "text", text: r.output }]) },
|
|
2330
2328
|
})),
|
|
2331
2329
|
effect_id: toolEffectId,
|
|
@@ -2520,7 +2518,6 @@ export class RuntimeRunner {
|
|
|
2520
2518
|
role: m.role,
|
|
2521
2519
|
content: m.content,
|
|
2522
2520
|
contentParts: m.contentParts,
|
|
2523
|
-
tokenCount: m.tokenCount,
|
|
2524
2521
|
toolCalls: m.toolCalls?.length ? m.toolCalls : undefined,
|
|
2525
2522
|
}));
|
|
2526
2523
|
if (newMsgs.length > 0) {
|
|
@@ -2815,14 +2812,13 @@ function attachmentsToKernelMessage(parts) {
|
|
|
2815
2812
|
if (p.type === "image") {
|
|
2816
2813
|
return {
|
|
2817
2814
|
type: "image",
|
|
2818
|
-
|
|
2819
|
-
...(p.data ? { data: p.data } : {}),
|
|
2815
|
+
source: p.source,
|
|
2820
2816
|
...(p.mediaType ? { media_type: p.mediaType } : {}),
|
|
2821
2817
|
...(p.detail ? { detail: p.detail } : {}),
|
|
2822
2818
|
};
|
|
2823
2819
|
}
|
|
2824
2820
|
if (p.type === "audio")
|
|
2825
|
-
return { type: "audio",
|
|
2821
|
+
return { type: "audio", source: p.source, media_type: p.mediaType };
|
|
2826
2822
|
if (p.type === "text")
|
|
2827
2823
|
return { type: "text", text: p.text };
|
|
2828
2824
|
return { type: "text", text: "" };
|
|
@@ -2886,7 +2882,6 @@ export function pairOrphanToolCalls(messages) {
|
|
|
2886
2882
|
content: "",
|
|
2887
2883
|
toolCalls: [],
|
|
2888
2884
|
contentParts: [{ type: "tool_result", callId: c.id, output: `[${c.name} handled by kernel]`, isError: false }],
|
|
2889
|
-
tokenCount: 1,
|
|
2890
2885
|
});
|
|
2891
2886
|
}
|
|
2892
2887
|
}
|
|
@@ -2917,7 +2912,6 @@ export function replayMessages(events, maxBytes) {
|
|
|
2917
2912
|
content: userText,
|
|
2918
2913
|
...(contentParts ? { contentParts } : {}),
|
|
2919
2914
|
toolCalls: [],
|
|
2920
|
-
tokenCount: Math.max(1, Math.ceil(userText.length / 4)),
|
|
2921
2915
|
});
|
|
2922
2916
|
}
|
|
2923
2917
|
else if (e.kind === "compressed") {
|
|
@@ -2928,7 +2922,6 @@ export function replayMessages(events, maxBytes) {
|
|
|
2928
2922
|
role: "system",
|
|
2929
2923
|
content: systemText,
|
|
2930
2924
|
toolCalls: [],
|
|
2931
|
-
tokenCount: Math.max(1, Math.ceil(systemText.length / 4)),
|
|
2932
2925
|
});
|
|
2933
2926
|
}
|
|
2934
2927
|
}
|
|
@@ -2937,7 +2930,6 @@ export function replayMessages(events, maxBytes) {
|
|
|
2937
2930
|
role: "assistant",
|
|
2938
2931
|
content: sanitizeReplayText(e.content, maxBytes),
|
|
2939
2932
|
toolCalls: e.tool_calls ?? [],
|
|
2940
|
-
tokenCount: e.token_count,
|
|
2941
2933
|
});
|
|
2942
2934
|
}
|
|
2943
2935
|
else if (e.kind === "tool_completed") {
|
|
@@ -2952,7 +2944,6 @@ export function replayMessages(events, maxBytes) {
|
|
|
2952
2944
|
content: "",
|
|
2953
2945
|
toolCalls: [],
|
|
2954
2946
|
contentParts: [{ type: "tool_result", callId: durable.call_id, output: sanitizeReplayText(r.output, maxBytes), isError: durable.is_error, ...(durable.blocks.length ? { contentParts: durableBlocksToToolOutput(durable.blocks) } : {}) }],
|
|
2955
|
-
tokenCount: r.token_count,
|
|
2956
2947
|
});
|
|
2957
2948
|
}
|
|
2958
2949
|
}
|
|
@@ -2990,7 +2981,6 @@ export async function replayMessagesAsync(events, maxBytes, loadArchive) {
|
|
|
2990
2981
|
content: userText,
|
|
2991
2982
|
...(contentParts ? { contentParts } : {}),
|
|
2992
2983
|
toolCalls: [],
|
|
2993
|
-
tokenCount: Math.max(1, Math.ceil(userText.length / 4)),
|
|
2994
2984
|
});
|
|
2995
2985
|
}
|
|
2996
2986
|
else if (e.kind === "compressed") {
|
|
@@ -3006,7 +2996,6 @@ export async function replayMessagesAsync(events, maxBytes, loadArchive) {
|
|
|
3006
2996
|
role: "system",
|
|
3007
2997
|
content: systemText,
|
|
3008
2998
|
toolCalls: [],
|
|
3009
|
-
tokenCount: Math.max(1, Math.ceil(systemText.length / 4)),
|
|
3010
2999
|
});
|
|
3011
3000
|
}
|
|
3012
3001
|
}
|
|
@@ -3019,7 +3008,6 @@ export async function replayMessagesAsync(events, maxBytes, loadArchive) {
|
|
|
3019
3008
|
role: msg.role,
|
|
3020
3009
|
content: sanitizeReplayText(msg.content, maxBytes),
|
|
3021
3010
|
toolCalls: msg.toolCalls ?? [],
|
|
3022
|
-
tokenCount: msg.tokenCount,
|
|
3023
3011
|
});
|
|
3024
3012
|
}
|
|
3025
3013
|
}
|
|
@@ -3030,7 +3018,6 @@ export async function replayMessagesAsync(events, maxBytes, loadArchive) {
|
|
|
3030
3018
|
role: "system",
|
|
3031
3019
|
content: systemText,
|
|
3032
3020
|
toolCalls: [],
|
|
3033
|
-
tokenCount: Math.max(1, Math.ceil(systemText.length / 4)),
|
|
3034
3021
|
});
|
|
3035
3022
|
}
|
|
3036
3023
|
}
|
|
@@ -3040,7 +3027,6 @@ export async function replayMessagesAsync(events, maxBytes, loadArchive) {
|
|
|
3040
3027
|
role: "assistant",
|
|
3041
3028
|
content: sanitizeReplayText(e.content, maxBytes),
|
|
3042
3029
|
toolCalls: e.tool_calls ?? [],
|
|
3043
|
-
tokenCount: e.token_count,
|
|
3044
3030
|
});
|
|
3045
3031
|
}
|
|
3046
3032
|
else if (e.kind === "tool_completed") {
|
|
@@ -3055,7 +3041,6 @@ export async function replayMessagesAsync(events, maxBytes, loadArchive) {
|
|
|
3055
3041
|
content: "",
|
|
3056
3042
|
toolCalls: [],
|
|
3057
3043
|
contentParts: [{ type: "tool_result", callId: durable.call_id, output: sanitizeReplayText(r.output, maxBytes), isError: durable.is_error, ...(durable.blocks.length ? { contentParts: durableBlocksToToolOutput(durable.blocks) } : {}) }],
|
|
3058
|
-
tokenCount: r.token_count,
|
|
3059
3044
|
});
|
|
3060
3045
|
}
|
|
3061
3046
|
}
|
|
@@ -5,7 +5,7 @@ export { REPLAY_CONTENT_MAX_BYTES as RECOVERY_CONTENT_MAX_BYTES } from "./replay
|
|
|
5
5
|
/**
|
|
6
6
|
* Normalize a persisted llm_completed event for recovery.
|
|
7
7
|
*
|
|
8
|
-
* Content is sanitized
|
|
8
|
+
* Content is sanitized while any existing token_count remains raw evidence, but the stored
|
|
9
9
|
* `provider_replay` envelope is passed through verbatim — this layer is
|
|
10
10
|
* provider-neutral and must never synthesize protocol-specific replay shapes
|
|
11
11
|
* (e.g. Anthropic `native_blocks`). Canonical replay seeding for a given protocol
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { sanitizeReplayText } from "./replay-sanitize.js";
|
|
2
2
|
export { REPLAY_CONTENT_MAX_BYTES as RECOVERY_CONTENT_MAX_BYTES } from "./replay-sanitize.js";
|
|
3
|
-
function estimateTokenCount(text) {
|
|
4
|
-
return Math.max(1, Math.ceil(text.length / 4));
|
|
5
|
-
}
|
|
6
3
|
/**
|
|
7
4
|
* Normalize a persisted llm_completed event for recovery.
|
|
8
5
|
*
|
|
9
|
-
* Content is sanitized
|
|
6
|
+
* Content is sanitized while any existing token_count remains raw evidence, but the stored
|
|
10
7
|
* `provider_replay` envelope is passed through verbatim — this layer is
|
|
11
8
|
* provider-neutral and must never synthesize protocol-specific replay shapes
|
|
12
9
|
* (e.g. Anthropic `native_blocks`). Canonical replay seeding for a given protocol
|
|
@@ -25,7 +22,7 @@ export function normalizeLlmCompleted(event, maxBytes) {
|
|
|
25
22
|
turn: event.turn,
|
|
26
23
|
content,
|
|
27
24
|
tool_calls: toolCalls,
|
|
28
|
-
token_count: event.token_count
|
|
25
|
+
...(event.token_count !== undefined ? { token_count: event.token_count } : {}),
|
|
29
26
|
...(providerReplay ? { provider_replay: providerReplay } : {}),
|
|
30
27
|
...(event.effect_id !== undefined ? { effect_id: event.effect_id } : {}),
|
|
31
28
|
...(event.invocation_id !== undefined ? { invocation_id: event.invocation_id } : {}),
|
package/dist/types/agent.d.ts
CHANGED
package/dist/types/agent.js
CHANGED
|
@@ -93,7 +93,6 @@ export function subAgentResultToKernel(result) {
|
|
|
93
93
|
name: tc.name,
|
|
94
94
|
arguments: safeParseToolArgs(tc.arguments),
|
|
95
95
|
})),
|
|
96
|
-
...(finalMessage.tokenCount !== undefined ? { token_count: finalMessage.tokenCount } : {}),
|
|
97
96
|
}
|
|
98
97
|
: null,
|
|
99
98
|
turns_used: result.result.turnsUsed,
|
|
@@ -171,7 +170,6 @@ export function workflowNodeOutcomeFromKernel(raw) {
|
|
|
171
170
|
name: call.name,
|
|
172
171
|
arguments: JSON.stringify(call.arguments ?? {}),
|
|
173
172
|
})),
|
|
174
|
-
...(output.token_count != null ? { tokenCount: output.token_count } : {}),
|
|
175
173
|
},
|
|
176
174
|
}
|
|
177
175
|
: {}),
|
package/dist/types.d.ts
CHANGED
|
@@ -5,20 +5,14 @@ export interface TextPart {
|
|
|
5
5
|
}
|
|
6
6
|
export interface ImagePart {
|
|
7
7
|
type: "image";
|
|
8
|
-
|
|
9
|
-
url?: string;
|
|
10
|
-
/** Raw base64-encoded image bytes (mutually exclusive with `url`). */
|
|
11
|
-
data?: string;
|
|
12
|
-
/** MIME type, e.g. `"image/png"`. Required when `data` is set. */
|
|
8
|
+
source: MediaSource;
|
|
13
9
|
mediaType?: string;
|
|
14
10
|
/** OpenAI vision detail level. */
|
|
15
11
|
detail?: "auto" | "low" | "high";
|
|
16
12
|
}
|
|
17
13
|
export interface AudioPart {
|
|
18
14
|
type: "audio";
|
|
19
|
-
|
|
20
|
-
data: string;
|
|
21
|
-
/** MIME type, e.g. `"audio/wav"`. */
|
|
15
|
+
source: MediaSource;
|
|
22
16
|
mediaType: string;
|
|
23
17
|
}
|
|
24
18
|
export interface ToolResultPart {
|
|
@@ -34,8 +28,8 @@ export type ContentPart = TextPart | ImagePart | AudioPart | ToolResultPart;
|
|
|
34
28
|
/**
|
|
35
29
|
* spc_011-B-05: canonical multimodal content, additive alongside `ContentPart` during the
|
|
36
30
|
* migration. `ContentBlockImage`/`ContentBlockAudio`/etc.
|
|
37
|
-
* are distinctly named (not reusing `ImagePart`/`AudioPart`)
|
|
38
|
-
*
|
|
31
|
+
* are distinctly named (not reusing `ImagePart`/`AudioPart`) because they are tool-output blocks
|
|
32
|
+
* with provider options and a durable `source` mirror.
|
|
39
33
|
*/
|
|
40
34
|
export type MediaSource = {
|
|
41
35
|
kind: "url";
|
|
@@ -96,7 +90,6 @@ export interface Message {
|
|
|
96
90
|
content: string;
|
|
97
91
|
/** Structured multimodal content. When present, takes precedence over `content` for provider calls. */
|
|
98
92
|
contentParts?: ContentPart[];
|
|
99
|
-
tokenCount?: number;
|
|
100
93
|
toolCalls?: ToolCall[];
|
|
101
94
|
}
|
|
102
95
|
export interface ToolCall {
|
|
@@ -111,7 +104,6 @@ export interface ToolResult {
|
|
|
111
104
|
isError: boolean;
|
|
112
105
|
isFatal?: boolean;
|
|
113
106
|
errorKind?: ToolErrorKind;
|
|
114
|
-
tokenCount?: number;
|
|
115
107
|
/** spc_012-N-01: same additive contract as `ToolResultPart.contentParts` (see there). */
|
|
116
108
|
contentParts?: ToolOutputBlock[];
|
|
117
109
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstrike/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.68",
|
|
4
4
|
"description": "DeepStrike Node.js SDK",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"@anthropic-ai/sdk": "^0.99.0",
|
|
76
|
-
"@deepstrike/core": "0.2.
|
|
76
|
+
"@deepstrike/core": "0.2.68",
|
|
77
77
|
"@google/generative-ai": "^0.24.1",
|
|
78
78
|
"openai": "^7.5.0"
|
|
79
79
|
},
|