@code-yeongyu/senpi 2026.7.4 → 2026.7.5-2
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/CHANGELOG.md +20 -0
- package/examples/sdk/12-full-control.ts +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +115 -19
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +1 -171
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts +0 -170
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js +3 -173
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.js +4 -4
- package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +4 -4
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/npm-shrinkwrap.json +9 -9
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2026.7.5-2] - 2026-07-05
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
### Removed
|
|
12
|
+
|
|
13
|
+
## [2026.7.5] - 2026-07-05
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
### Removed
|
|
22
|
+
|
|
3
23
|
## [2026.7.4] - 2026-07-04
|
|
4
24
|
|
|
5
25
|
### Added
|
|
@@ -26,7 +26,7 @@ if (process.env.MY_ANTHROPIC_KEY) {
|
|
|
26
26
|
// Model registry with no custom models.json
|
|
27
27
|
const modelRegistry = ModelRegistry.inMemory(authStorage);
|
|
28
28
|
|
|
29
|
-
const model = getModel("anthropic", "claude-
|
|
29
|
+
const model = getModel("anthropic", "claude-opus-4-5");
|
|
30
30
|
if (!model) throw new Error("Model not found");
|
|
31
31
|
|
|
32
32
|
// In-memory settings with overrides
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-agent-core",
|
|
3
3
|
"private": true,
|
|
4
|
-
"version": "2026.7.
|
|
4
|
+
"version": "2026.7.5-2",
|
|
5
5
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"prepublishOnly": "npm run clean && npm run build"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@earendil-works/pi-ai": "^2026.7.
|
|
33
|
+
"@earendil-works/pi-ai": "^2026.7.5-2",
|
|
34
34
|
"ignore": "7.0.5",
|
|
35
35
|
"typebox": "1.1.38",
|
|
36
36
|
"yaml": "2.9.0"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic-messages.d.ts","sourceRoot":"","sources":["../../src/api/anthropic-messages.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAU1C,OAAO,KAAK,EAWX,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAMb,MAAM,aAAa,CAAC;AA+JrB,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1E,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG,SAAS,CAAC;AAwChE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"anthropic-messages.d.ts","sourceRoot":"","sources":["../../src/api/anthropic-messages.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAU1C,OAAO,KAAK,EAWX,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAMb,MAAM,aAAa,CAAC;AA+JrB,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1E,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG,SAAS,CAAC;AAwChE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB;AAghBD,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,oBAAoB,EAAE,gBAAgB,CAoTzE,CAAC;AAuEF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,mBAAmB,CA2ClF,CAAC"}
|
|
@@ -174,15 +174,80 @@ const REPLAYABLE_ANTHROPIC_PROVIDER_NATIVE_TYPES = new Set([
|
|
|
174
174
|
"tool_search_tool_result",
|
|
175
175
|
"container_upload",
|
|
176
176
|
// Server-side fallback beta (server-side-fallback-2026-06-01) emits a
|
|
177
|
-
// `fallback`
|
|
178
|
-
//
|
|
179
|
-
//
|
|
180
|
-
//
|
|
177
|
+
// `fallback` marker mid-response. The marker itself is replayed as a kept
|
|
178
|
+
// audit block. Blocks emitted *before* the final marker are the declined
|
|
179
|
+
// attempt and are pruned in convertMessages (see lastAnthropicFallbackBoundary
|
|
180
|
+
// and collectDiscardedFallbackToolCallIds); the marker onward replays verbatim.
|
|
181
181
|
"fallback",
|
|
182
182
|
]);
|
|
183
183
|
function isReplayableAnthropicProviderNativeBlock(raw) {
|
|
184
184
|
return isRecord(raw) && typeof raw.type === "string" && REPLAYABLE_ANTHROPIC_PROVIDER_NATIVE_TYPES.has(raw.type);
|
|
185
185
|
}
|
|
186
|
+
function isSameAnthropicModel(message, model) {
|
|
187
|
+
return message.provider === model.provider && message.api === model.api && message.model === model.id;
|
|
188
|
+
}
|
|
189
|
+
function isAnthropicFallbackMarkerBlock(block) {
|
|
190
|
+
return (block.type === "providerNative" &&
|
|
191
|
+
block.subtype === "fallback" &&
|
|
192
|
+
isRecord(block.raw) &&
|
|
193
|
+
block.raw.type === "fallback");
|
|
194
|
+
}
|
|
195
|
+
// The server-side fallback beta (server-side-fallback-2026-06-01) can emit a
|
|
196
|
+
// `fallback` marker mid-message after a declined attempt is replaced. Blocks
|
|
197
|
+
// before the final marker belong to the discarded attempt: replaying its
|
|
198
|
+
// thinking/tool_use makes the API reject the turn (a discarded tool_use has no
|
|
199
|
+
// matching tool_result after normalization). Returns the index of the last
|
|
200
|
+
// fallback marker, or -1 when the message has none.
|
|
201
|
+
function lastAnthropicFallbackBoundary(content) {
|
|
202
|
+
let boundary = -1;
|
|
203
|
+
for (let index = 0; index < content.length; index++) {
|
|
204
|
+
if (isAnthropicFallbackMarkerBlock(content[index])) {
|
|
205
|
+
boundary = index;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return boundary;
|
|
209
|
+
}
|
|
210
|
+
function isAnthropicServerToolUseBlock(raw) {
|
|
211
|
+
return isRecord(raw) && raw.type === "server_tool_use" && typeof raw.id === "string";
|
|
212
|
+
}
|
|
213
|
+
// tool_use ids referenced by server-tool result blocks in content[0, boundary).
|
|
214
|
+
// A pre-boundary `server_tool_use` whose id is absent here is unpaired — the
|
|
215
|
+
// fallback interrupted the declined attempt before its result arrived — so
|
|
216
|
+
// replaying it would leave a server tool_use with no adjacent result and 400 the
|
|
217
|
+
// turn. Paired server-tool blocks replay verbatim per the fallback contract.
|
|
218
|
+
function pairedServerToolUseIdsBeforeBoundary(content, boundary) {
|
|
219
|
+
const paired = new Set();
|
|
220
|
+
for (let index = 0; index < boundary; index++) {
|
|
221
|
+
const block = content[index];
|
|
222
|
+
if (block.type !== "providerNative" || !isRecord(block.raw))
|
|
223
|
+
continue;
|
|
224
|
+
const toolUseId = block.raw.tool_use_id;
|
|
225
|
+
if (typeof toolUseId === "string")
|
|
226
|
+
paired.add(toolUseId);
|
|
227
|
+
}
|
|
228
|
+
return paired;
|
|
229
|
+
}
|
|
230
|
+
// Tool-call ids emitted by a discarded pre-fallback attempt on a same-model
|
|
231
|
+
// assistant turn. These tool_use blocks are dropped from the assistant turn, so
|
|
232
|
+
// their tool_result blocks must be dropped from the following user turn too — an
|
|
233
|
+
// orphaned tool_result triggers its own 400.
|
|
234
|
+
function collectDiscardedFallbackToolCallIds(messages, model) {
|
|
235
|
+
const discarded = new Set();
|
|
236
|
+
for (const message of messages) {
|
|
237
|
+
if (message.role !== "assistant" || !isSameAnthropicModel(message, model))
|
|
238
|
+
continue;
|
|
239
|
+
const boundary = lastAnthropicFallbackBoundary(message.content);
|
|
240
|
+
if (boundary < 0)
|
|
241
|
+
continue;
|
|
242
|
+
for (let index = 0; index < boundary; index++) {
|
|
243
|
+
const block = message.content[index];
|
|
244
|
+
if (block.type === "toolCall") {
|
|
245
|
+
discarded.add(block.id);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return discarded;
|
|
250
|
+
}
|
|
186
251
|
function stringRecord(value) {
|
|
187
252
|
if (!isRecord(value)) {
|
|
188
253
|
return undefined;
|
|
@@ -1070,6 +1135,9 @@ function convertMessages(messages, model, isOAuthToken, cacheControl, preserveTh
|
|
|
1070
1135
|
preserveThinking,
|
|
1071
1136
|
preserveUnsignedThinking: true,
|
|
1072
1137
|
});
|
|
1138
|
+
// Tool calls from a declined pre-fallback attempt are dropped from their
|
|
1139
|
+
// assistant turn below; drop their tool_results in lockstep so none dangle.
|
|
1140
|
+
const discardedFallbackToolCallIds = collectDiscardedFallbackToolCallIds(transformedMessages, model);
|
|
1073
1141
|
for (let i = 0; i < transformedMessages.length; i++) {
|
|
1074
1142
|
const msg = transformedMessages[i];
|
|
1075
1143
|
if (msg.role === "user") {
|
|
@@ -1116,8 +1184,28 @@ function convertMessages(messages, model, isOAuthToken, cacheControl, preserveTh
|
|
|
1116
1184
|
}
|
|
1117
1185
|
else if (msg.role === "assistant") {
|
|
1118
1186
|
const blocks = [];
|
|
1119
|
-
const isSameModel = msg
|
|
1120
|
-
|
|
1187
|
+
const isSameModel = isSameAnthropicModel(msg, model);
|
|
1188
|
+
// Blocks before the final fallback marker are the declined attempt; the
|
|
1189
|
+
// marker onward is the serving model's output and replays verbatim.
|
|
1190
|
+
const fallbackBoundary = isSameModel ? lastAnthropicFallbackBoundary(msg.content) : -1;
|
|
1191
|
+
const preBoundaryPairedServerToolUseIds = fallbackBoundary >= 0
|
|
1192
|
+
? pairedServerToolUseIdsBeforeBoundary(msg.content, fallbackBoundary)
|
|
1193
|
+
: new Set();
|
|
1194
|
+
for (let blockIndex = 0; blockIndex < msg.content.length; blockIndex++) {
|
|
1195
|
+
const block = msg.content[blockIndex];
|
|
1196
|
+
if (fallbackBoundary >= 0 && blockIndex < fallbackBoundary) {
|
|
1197
|
+
// Drop the declined attempt's model-internal blocks: thinking,
|
|
1198
|
+
// tool_use, and any unpaired server_tool_use. Paired server-tool
|
|
1199
|
+
// blocks and text survive per the fallback replay contract.
|
|
1200
|
+
if (block.type === "thinking" || block.type === "toolCall") {
|
|
1201
|
+
continue;
|
|
1202
|
+
}
|
|
1203
|
+
if (block.type === "providerNative" &&
|
|
1204
|
+
isAnthropicServerToolUseBlock(block.raw) &&
|
|
1205
|
+
!preBoundaryPairedServerToolUseIds.has(block.raw.id)) {
|
|
1206
|
+
continue;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1121
1209
|
if (block.type === "text") {
|
|
1122
1210
|
if (block.text.trim().length === 0)
|
|
1123
1211
|
continue;
|
|
@@ -1184,27 +1272,35 @@ function convertMessages(messages, model, isOAuthToken, cacheControl, preserveTh
|
|
|
1184
1272
|
else if (msg.role === "toolResult") {
|
|
1185
1273
|
// Collect all consecutive toolResult messages, needed for z.ai Anthropic endpoint
|
|
1186
1274
|
const toolResults = [];
|
|
1187
|
-
// Add the current tool result
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1275
|
+
// Add the current tool result, unless its tool_use was dropped as a
|
|
1276
|
+
// declined pre-fallback attempt (its result would otherwise dangle).
|
|
1277
|
+
if (!discardedFallbackToolCallIds.has(msg.toolCallId)) {
|
|
1278
|
+
toolResults.push({
|
|
1279
|
+
type: "tool_result",
|
|
1280
|
+
tool_use_id: msg.toolCallId,
|
|
1281
|
+
content: convertContentBlocks(msg.content),
|
|
1282
|
+
is_error: msg.isError,
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1194
1285
|
// Look ahead for consecutive toolResult messages
|
|
1195
1286
|
let j = i + 1;
|
|
1196
1287
|
while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
|
|
1197
1288
|
const nextMsg = transformedMessages[j]; // We know it's a toolResult
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1289
|
+
if (!discardedFallbackToolCallIds.has(nextMsg.toolCallId)) {
|
|
1290
|
+
toolResults.push({
|
|
1291
|
+
type: "tool_result",
|
|
1292
|
+
tool_use_id: nextMsg.toolCallId,
|
|
1293
|
+
content: convertContentBlocks(nextMsg.content),
|
|
1294
|
+
is_error: nextMsg.isError,
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1204
1297
|
j++;
|
|
1205
1298
|
}
|
|
1206
1299
|
// Skip the messages we've already processed
|
|
1207
1300
|
i = j - 1;
|
|
1301
|
+
// Every result in this run may have been dropped; don't emit an empty turn.
|
|
1302
|
+
if (toolResults.length === 0)
|
|
1303
|
+
continue;
|
|
1208
1304
|
// Add a single user message with all tool results
|
|
1209
1305
|
params.push({
|
|
1210
1306
|
role: "user",
|