@vincemakes/kiso-provider-anthropic 0.15.12 → 0.16.1
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/index.js +86 -4
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -39,6 +39,13 @@ export function createAnthropicAdapter(client, adapterOpts = {}) {
|
|
|
39
39
|
try {
|
|
40
40
|
stream = client.messages.stream({
|
|
41
41
|
model: options.model,
|
|
42
|
+
// XP-1: the resolved effort (the effort doc, read
|
|
43
|
+
// 2026-08-26): output_config.effort. Absent adds NO
|
|
44
|
+
// key. The thinking-mode WIRE is deliberately not
|
|
45
|
+
// serialized yet — the registry carries no sourced
|
|
46
|
+
// mode list for the entered models, so no valid
|
|
47
|
+
// selection can produce one; nothing is guessed.
|
|
48
|
+
...(options.reasoning?.effort !== undefined ? { output_config: { effort: options.reasoning.effort } } : {}),
|
|
42
49
|
...(options.systemPrompt !== undefined
|
|
43
50
|
? {
|
|
44
51
|
system: caching
|
|
@@ -47,7 +54,7 @@ export function createAnthropicAdapter(client, adapterOpts = {}) {
|
|
|
47
54
|
}
|
|
48
55
|
: {}),
|
|
49
56
|
max_tokens: options.maxTokens ?? 4096,
|
|
50
|
-
messages: caching ? withCacheBreakpoint(toAnthropicMessages(options.messages)) : toAnthropicMessages(options.messages),
|
|
57
|
+
messages: caching ? withCacheBreakpoint(toAnthropicMessages(options.messages, options.model)) : toAnthropicMessages(options.messages, options.model),
|
|
51
58
|
...(options.tools?.length ? { tools: toAnthropicTools(options.tools) } : {}),
|
|
52
59
|
...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
|
|
53
60
|
},
|
|
@@ -70,6 +77,14 @@ export function createAnthropicAdapter(client, adapterOpts = {}) {
|
|
|
70
77
|
let stopReasonSeen = false;
|
|
71
78
|
let stopReason = "end_turn";
|
|
72
79
|
const toolBuffer = new Map();
|
|
80
|
+
// MG-1 (A5): thinking-family blocks are captured WHOLE — one
|
|
81
|
+
// opaque entry per block, closed at its content_block_stop so
|
|
82
|
+
// interleaving order is preserved verbatim. The provider
|
|
83
|
+
// requires the complete blocks back on a tool-use continuation;
|
|
84
|
+
// an aggregated reasoning string cannot reconstruct them.
|
|
85
|
+
const thinkBuffer = new Map();
|
|
86
|
+
const contEntries = [];
|
|
87
|
+
let sawToolUse = false;
|
|
73
88
|
try {
|
|
74
89
|
for await (const event of stream) {
|
|
75
90
|
switch (event.type) {
|
|
@@ -88,6 +103,7 @@ export function createAnthropicAdapter(client, adapterOpts = {}) {
|
|
|
88
103
|
yield { seq: 0, type: "text_start" };
|
|
89
104
|
}
|
|
90
105
|
else if (block.type === "tool_use") {
|
|
106
|
+
sawToolUse = true;
|
|
91
107
|
toolBuffer.set(event.index, { id: block.id, name: block.name, json: "" });
|
|
92
108
|
yield {
|
|
93
109
|
seq: 0,
|
|
@@ -96,6 +112,12 @@ export function createAnthropicAdapter(client, adapterOpts = {}) {
|
|
|
96
112
|
name: block.name,
|
|
97
113
|
};
|
|
98
114
|
}
|
|
115
|
+
else if (block.type === "thinking") {
|
|
116
|
+
thinkBuffer.set(event.index, { type: "thinking", thinking: "", signature: "" });
|
|
117
|
+
}
|
|
118
|
+
else if (block.type === "redacted_thinking") {
|
|
119
|
+
thinkBuffer.set(event.index, { type: "redacted_thinking", data: block.data ?? "" });
|
|
120
|
+
}
|
|
99
121
|
break;
|
|
100
122
|
}
|
|
101
123
|
case "content_block_delta": {
|
|
@@ -116,8 +138,18 @@ export function createAnthropicAdapter(client, adapterOpts = {}) {
|
|
|
116
138
|
}
|
|
117
139
|
}
|
|
118
140
|
else if (delta.type === "thinking_delta") {
|
|
141
|
+
const t = thinkBuffer.get(event.index);
|
|
142
|
+
if (t?.type === "thinking")
|
|
143
|
+
t.thinking += delta.thinking;
|
|
119
144
|
yield { seq: 0, type: "thinking", text: delta.thinking };
|
|
120
145
|
}
|
|
146
|
+
else if (delta.type === "signature_delta") {
|
|
147
|
+
// A5: the signature is continuation material only —
|
|
148
|
+
// never a projection event.
|
|
149
|
+
const t = thinkBuffer.get(event.index);
|
|
150
|
+
if (t?.type === "thinking")
|
|
151
|
+
t.signature += delta.signature ?? "";
|
|
152
|
+
}
|
|
121
153
|
break;
|
|
122
154
|
}
|
|
123
155
|
case "content_block_stop": {
|
|
@@ -139,6 +171,13 @@ export function createAnthropicAdapter(client, adapterOpts = {}) {
|
|
|
139
171
|
input,
|
|
140
172
|
};
|
|
141
173
|
}
|
|
174
|
+
// A5: a thinking-family block closes HERE — pushed at
|
|
175
|
+
// its stop so interleaving order lands verbatim.
|
|
176
|
+
const think = thinkBuffer.get(event.index);
|
|
177
|
+
if (think) {
|
|
178
|
+
thinkBuffer.delete(event.index);
|
|
179
|
+
contEntries.push({ kind: "anthropic.content_block", data: JSON.stringify(think) });
|
|
180
|
+
}
|
|
142
181
|
// Text blocks end implicitly: the next TextStart (or
|
|
143
182
|
// the terminal) closes the previous block (ADR-0003).
|
|
144
183
|
break;
|
|
@@ -182,7 +221,25 @@ export function createAnthropicAdapter(client, adapterOpts = {}) {
|
|
|
182
221
|
// D3: a message_stop with NO delta means the
|
|
183
222
|
// provider never reported a stop reason — that is
|
|
184
223
|
// an error, never a default end_turn.
|
|
185
|
-
|
|
224
|
+
// A5: the captured blocks ride the stop as opaque
|
|
225
|
+
// entries (self-reported scope; the kernel
|
|
226
|
+
// re-stamps it — adapters are not trusted).
|
|
227
|
+
// `required` follows the turn: a tool-use
|
|
228
|
+
// continuation is INVALID without its thinking
|
|
229
|
+
// blocks; elsewhere omission degrades, not 400s.
|
|
230
|
+
yield {
|
|
231
|
+
seq: 0,
|
|
232
|
+
type: "stop",
|
|
233
|
+
reason: stopReasonSeen ? stopReason : "error",
|
|
234
|
+
...(contEntries.length > 0
|
|
235
|
+
? {
|
|
236
|
+
continuation: {
|
|
237
|
+
scope: { providerId: "anthropic", apiId: "anthropic-messages", modelId: options.model },
|
|
238
|
+
entries: contEntries.map((e) => ({ ...e, required: sawToolUse })),
|
|
239
|
+
},
|
|
240
|
+
}
|
|
241
|
+
: {}),
|
|
242
|
+
};
|
|
186
243
|
break;
|
|
187
244
|
}
|
|
188
245
|
}
|
|
@@ -240,7 +297,32 @@ function toAnthropicContent(content) {
|
|
|
240
297
|
};
|
|
241
298
|
});
|
|
242
299
|
}
|
|
243
|
-
|
|
300
|
+
/** A5: the stored blocks replay ONLY to the scope that produced them —
|
|
301
|
+
* provider AND api AND model (thinking blocks bind to the model that
|
|
302
|
+
* produced them; the provider requires foreign ones stripped). A
|
|
303
|
+
* mismatched or absent envelope replays nothing; an unparseable stored
|
|
304
|
+
* entry is skipped, never a crash. */
|
|
305
|
+
function continuationBlocks(msg, model) {
|
|
306
|
+
const c = msg.continuation;
|
|
307
|
+
if (c === undefined)
|
|
308
|
+
return [];
|
|
309
|
+
const s = c.scope;
|
|
310
|
+
if (s.providerId !== "anthropic" || s.apiId !== "anthropic-messages" || s.modelId !== model)
|
|
311
|
+
return [];
|
|
312
|
+
const out = [];
|
|
313
|
+
for (const e of c.entries) {
|
|
314
|
+
if (e.kind !== "anthropic.content_block")
|
|
315
|
+
continue;
|
|
316
|
+
try {
|
|
317
|
+
out.push(JSON.parse(e.data));
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
// skipped — opaque bytes that no longer parse must not kill the request
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return out;
|
|
324
|
+
}
|
|
325
|
+
function toAnthropicMessages(messages, model) {
|
|
244
326
|
const out = [];
|
|
245
327
|
for (const msg of messages) {
|
|
246
328
|
if (msg.role === "user") {
|
|
@@ -249,7 +331,7 @@ function toAnthropicMessages(messages) {
|
|
|
249
331
|
else if (msg.role === "assistant") {
|
|
250
332
|
out.push({
|
|
251
333
|
role: "assistant",
|
|
252
|
-
content: msg.blocks.map(toAnthropicBlock),
|
|
334
|
+
content: [...continuationBlocks(msg, model), ...msg.blocks.map(toAnthropicBlock)],
|
|
253
335
|
});
|
|
254
336
|
}
|
|
255
337
|
else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-provider-anthropic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "kiso Anthropic adapter \u2014 official SDK wire events mapped to the kiso event union.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@anthropic-ai/sdk": "^0.115.0",
|
|
25
|
-
"@vincemakes/kiso-core": "0.
|
|
25
|
+
"@vincemakes/kiso-core": "0.16.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^26.1.2",
|