@code-yeongyu/senpi-ai 2026.7.26 → 2026.7.28
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/api/anthropic-messages.d.ts +1 -0
- package/dist/api/anthropic-messages.d.ts.map +1 -1
- package/dist/api/anthropic-messages.js +161 -50
- package/dist/api/anthropic-messages.js.map +1 -1
- package/dist/api/azure-openai-responses.js +3 -1
- package/dist/api/azure-openai-responses.js.map +1 -1
- package/dist/api/bedrock-converse-stream.d.ts +1 -0
- package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
- package/dist/api/bedrock-converse-stream.js +2 -43
- package/dist/api/bedrock-converse-stream.js.map +1 -1
- package/dist/api/openai-codex-responses/reasoning.d.ts +14 -0
- package/dist/api/openai-codex-responses/reasoning.d.ts.map +1 -0
- package/dist/api/openai-codex-responses/reasoning.js +27 -0
- package/dist/api/openai-codex-responses/reasoning.js.map +1 -0
- package/dist/api/openai-codex-responses.d.ts +2 -1
- package/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/dist/api/openai-codex-responses.js +4 -12
- package/dist/api/openai-codex-responses.js.map +1 -1
- package/dist/api/openai-completions.d.ts +3 -8
- package/dist/api/openai-completions.d.ts.map +1 -1
- package/dist/api/openai-completions.js +8 -122
- package/dist/api/openai-completions.js.map +1 -1
- package/dist/api/openai-responses.d.ts.map +1 -1
- package/dist/api/openai-responses.js +1 -0
- package/dist/api/openai-responses.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/model.d.ts +7 -0
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js.map +1 -1
- package/dist/oauth.d.ts +2 -1
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +2 -1
- package/dist/oauth.js.map +1 -1
- package/dist/openai-responses-compat.d.ts +24 -0
- package/dist/openai-responses-compat.d.ts.map +1 -0
- package/dist/openai-responses-compat.js +2 -0
- package/dist/openai-responses-compat.js.map +1 -0
- package/dist/providers/data/.manifest.json +1 -1
- package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/dist/providers/data/fireworks.json +1 -1
- package/dist/providers/data/huggingface.json +1 -1
- package/dist/providers/data/nvidia.json +1 -1
- package/dist/providers/data/openai.json +1 -1
- package/dist/providers/data/opencode.json +1 -1
- package/dist/providers/data/openrouter.json +1 -1
- package/dist/providers/data/together.json +1 -1
- package/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/dist/types.d.ts +8 -22
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/prompt-cache-ttl.d.ts +32 -0
- package/dist/utils/prompt-cache-ttl.d.ts.map +1 -0
- package/dist/utils/prompt-cache-ttl.js +294 -0
- package/dist/utils/prompt-cache-ttl.js.map +1 -0
- package/dist/utils/provider-retry.d.ts +5 -0
- package/dist/utils/provider-retry.d.ts.map +1 -1
- package/dist/utils/provider-retry.js +46 -1
- package/dist/utils/provider-retry.js.map +1 -1
- package/dist/utils/retry.d.ts +7 -0
- package/dist/utils/retry.d.ts.map +1 -1
- package/dist/utils/retry.js +14 -1
- package/dist/utils/retry.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Anthropic from "@anthropic-ai/sdk";
|
|
2
2
|
import type { SimpleStreamOptions, StreamFunction, StreamOptions } from "../types.ts";
|
|
3
|
+
export { getAnthropicCompat } from "../utils/prompt-cache-ttl.ts";
|
|
3
4
|
export type AnthropicEffort = "low" | "medium" | "high" | "xhigh" | "max";
|
|
4
5
|
export type AnthropicThinkingDisplay = "summarized" | "omitted";
|
|
5
6
|
export interface AnthropicOptions extends StreamOptions {
|
|
@@ -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,
|
|
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,EAOb,MAAM,aAAa,CAAC;AA+BrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AA6JlE,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1E,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG,SAAS,CAAC;AAoEhE,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;AA8zBD,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,oBAAoB,EAAE,gBAAgB,CAqYzE,CAAC;AA0FF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,mBAAmB,CA2ClF,CAAC"}
|
|
@@ -6,6 +6,7 @@ import { splitDeferredTools } from "../utils/deferred-tools.js";
|
|
|
6
6
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
7
7
|
import { headersToRecord, providerHeadersToRecord } from "../utils/headers.js";
|
|
8
8
|
import { parseJsonWithRepair, parseStreamingJson } from "../utils/json-parse.js";
|
|
9
|
+
import { getAnthropicCompat, isAnthropicApiBaseUrl } from "../utils/prompt-cache-ttl.js";
|
|
9
10
|
import { getProviderEnvValue } from "../utils/provider-env.js";
|
|
10
11
|
import { retryProviderRequest } from "../utils/provider-retry.js";
|
|
11
12
|
import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
|
|
@@ -17,6 +18,7 @@ import { resolveJsonSchemaStrictSampling } from "./constrained-sampling.js";
|
|
|
17
18
|
import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
|
|
18
19
|
import { ANTHROPIC_RESERVED_BODY_KEYS, adjustMaxTokensForThinking, buildBaseOptions, clampMaxTokensToContext, } from "./simple-options.js";
|
|
19
20
|
import { transformMessages } from "./transform-messages.js";
|
|
21
|
+
export { getAnthropicCompat } from "../utils/prompt-cache-ttl.js";
|
|
20
22
|
/**
|
|
21
23
|
* Resolve cache retention preference.
|
|
22
24
|
* Defaults to the provided fallback and uses PI_CACHE_RETENTION for backward compatibility.
|
|
@@ -33,14 +35,6 @@ function resolveCacheRetention(cacheRetention, env, fallback = "short") {
|
|
|
33
35
|
}
|
|
34
36
|
return fallback;
|
|
35
37
|
}
|
|
36
|
-
function isAnthropicApiBaseUrl(baseUrl) {
|
|
37
|
-
try {
|
|
38
|
-
return new URL(baseUrl).hostname === "api.anthropic.com";
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
38
|
function getCacheControl(model, cacheRetention, env) {
|
|
45
39
|
const retention = resolveCacheRetention(cacheRetention, env, "long");
|
|
46
40
|
if (retention === "none") {
|
|
@@ -168,7 +162,6 @@ const NATIVE_XHIGH_EFFORT_MODEL_MARKERS = [
|
|
|
168
162
|
* gateway rows carry no generated compat, so the family fact has to live here as well.
|
|
169
163
|
*/
|
|
170
164
|
const DISABLED_THINKING_REJECTING_MODEL_MARKERS = ["fable-5", "mythos-5"];
|
|
171
|
-
const CLAUDE_FABLE_OR_MYTHOS_MODEL_ID = /^claude-(?:fable|mythos)(?:-|$)/i;
|
|
172
165
|
const UNSUPPORTED_NATIVE_COMPUTER_TOOL_MODEL_MARKERS = [
|
|
173
166
|
"opus-4-6",
|
|
174
167
|
"opus-4.6",
|
|
@@ -191,47 +184,6 @@ function isInvalidUnsignedThinkingSignatureError(error) {
|
|
|
191
184
|
error instanceof Error &&
|
|
192
185
|
/Invalid signature in thinking block/i.test(error.message));
|
|
193
186
|
}
|
|
194
|
-
function getAnthropicCompat(model) {
|
|
195
|
-
// Auto-detect session affinity and cache control support from provider
|
|
196
|
-
const isFireworks = model.provider === "fireworks";
|
|
197
|
-
const isCloudflareAiGatewayAnthropic = model.provider === "cloudflare-ai-gateway" && model.baseUrl.includes("anthropic");
|
|
198
|
-
const isXiaomi = model.provider === "xiaomi" || model.provider.startsWith("xiaomi-token-plan-");
|
|
199
|
-
return {
|
|
200
|
-
supportsEagerToolInputStreaming: model.compat?.supportsEagerToolInputStreaming ?? !isFireworks,
|
|
201
|
-
supportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? !isFireworks,
|
|
202
|
-
sendSessionAffinityHeaders: model.compat?.sendSessionAffinityHeaders ?? !!(isFireworks || isCloudflareAiGatewayAnthropic),
|
|
203
|
-
supportsCacheControlOnTools: model.compat?.supportsCacheControlOnTools ?? !isFireworks,
|
|
204
|
-
supportsDisabledThinking: model.compat?.supportsDisabledThinking ?? !isXiaomi,
|
|
205
|
-
supportsTemperature: model.compat?.supportsTemperature ?? true,
|
|
206
|
-
supportsToolChoice: model.compat?.supportsToolChoice ?? true,
|
|
207
|
-
supportsForcedToolChoice: model.compat?.supportsForcedToolChoice ?? !CLAUDE_FABLE_OR_MYTHOS_MODEL_ID.test(model.id),
|
|
208
|
-
allowEmptySignature: model.compat?.allowEmptySignature ?? false,
|
|
209
|
-
unsignedThinkingReplay: model.compat?.unsignedThinkingReplay ?? (model.compat?.allowEmptySignature ? "empty-signature" : "text"),
|
|
210
|
-
supportsStrictTools: model.compat?.supportsStrictTools ?? false,
|
|
211
|
-
supportsToolReferences: model.compat?.supportsToolReferences ?? defaultSupportsToolReferences(model),
|
|
212
|
-
// Default: first-party Anthropic only. Anthropic-compatible providers
|
|
213
|
-
// (kimi-coding, fireworks, copilot, gateways) may execute the server-side
|
|
214
|
-
// search but reject the replayed server_tool_use / web_search_tool_result
|
|
215
|
-
// blocks on the next request (kimi-coding 400s with `tool_call_id is not
|
|
216
|
-
// found`).
|
|
217
|
-
supportsWebSearch: model.compat?.supportsWebSearch ?? isAnthropicApiBaseUrl(model.baseUrl),
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Default for `supportsToolReferences`: first-party Anthropic models except
|
|
222
|
-
* Haiku (rejects client-side tool_reference blocks) and models that predate
|
|
223
|
-
* tool search (Claude 3.x, Opus/Sonnet 4.0, Opus 4.1).
|
|
224
|
-
*/
|
|
225
|
-
function defaultSupportsToolReferences(model) {
|
|
226
|
-
if (model.provider !== "anthropic" || model.id.includes("haiku"))
|
|
227
|
-
return false;
|
|
228
|
-
const version = model.id.match(/^claude-(?:opus|sonnet|fable)-(\d+)(?:-(\d+))?(?:-|$)/);
|
|
229
|
-
if (!version)
|
|
230
|
-
return false;
|
|
231
|
-
const major = Number(version[1]);
|
|
232
|
-
const minor = version[2] && version[2].length < 8 ? Number(version[2]) : 0;
|
|
233
|
-
return major > 4 || (major === 4 && minor >= 5);
|
|
234
|
-
}
|
|
235
187
|
function mergeHeaders(...headerSources) {
|
|
236
188
|
const merged = {};
|
|
237
189
|
for (const headers of headerSources) {
|
|
@@ -569,6 +521,164 @@ function sanitizeUnsupportedNativeTools(model, params) {
|
|
|
569
521
|
}
|
|
570
522
|
return changed ? sanitized : params;
|
|
571
523
|
}
|
|
524
|
+
/**
|
|
525
|
+
* Anthropic validates that every tool referenced by the message history is
|
|
526
|
+
* available in the same request — defined in `tools` or discovered through a
|
|
527
|
+
* `tool_reference` block — and rejects the whole request otherwise
|
|
528
|
+
* ("Tool reference '<name>' not found in available tools"). Sessions outlive
|
|
529
|
+
* their tools: an MCP server can be absent after a resume, an extension can
|
|
530
|
+
* stop registering a tool, or a payload hook can strip a definition while the
|
|
531
|
+
* history still carries the call. Demote those references to plain text so
|
|
532
|
+
* the turn can proceed; the matching tool_result is demoted in lockstep so no
|
|
533
|
+
* orphan pairing error replaces the original one.
|
|
534
|
+
*/
|
|
535
|
+
function demoteUnavailableToolReferences(params) {
|
|
536
|
+
const messages = params.messages;
|
|
537
|
+
if (!Array.isArray(messages) || messages.length === 0)
|
|
538
|
+
return params;
|
|
539
|
+
const definedNames = new Set();
|
|
540
|
+
if (Array.isArray(params.tools)) {
|
|
541
|
+
for (const tool of params.tools) {
|
|
542
|
+
if (isRecord(tool) && typeof tool.name === "string")
|
|
543
|
+
definedNames.add(tool.name);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
// `tool_reference` blocks — emitted for deferred tools or replayed from a
|
|
547
|
+
// server-side tool search — make their targets available without a
|
|
548
|
+
// non-deferred definition.
|
|
549
|
+
const discoveredNames = new Set();
|
|
550
|
+
collectToolReferenceNames(messages, discoveredNames);
|
|
551
|
+
const demotedCallNames = new Map();
|
|
552
|
+
for (const message of messages) {
|
|
553
|
+
if (message.role !== "assistant" || !Array.isArray(message.content))
|
|
554
|
+
continue;
|
|
555
|
+
for (const block of message.content) {
|
|
556
|
+
if (isRecord(block) &&
|
|
557
|
+
block.type === "tool_use" &&
|
|
558
|
+
typeof block.name === "string" &&
|
|
559
|
+
!definedNames.has(block.name) &&
|
|
560
|
+
!discoveredNames.has(block.name)) {
|
|
561
|
+
demotedCallNames.set(block.id, block.name);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
// A `tool_reference` without its definition 400s the same way.
|
|
566
|
+
const danglingReferenceNames = new Set();
|
|
567
|
+
for (const name of discoveredNames) {
|
|
568
|
+
if (!definedNames.has(name))
|
|
569
|
+
danglingReferenceNames.add(name);
|
|
570
|
+
}
|
|
571
|
+
if (demotedCallNames.size === 0 && danglingReferenceNames.size === 0)
|
|
572
|
+
return params;
|
|
573
|
+
let changed = false;
|
|
574
|
+
const rewrittenMessages = [];
|
|
575
|
+
for (const message of messages) {
|
|
576
|
+
if (!Array.isArray(message.content)) {
|
|
577
|
+
rewrittenMessages.push(message);
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
let messageChanged = false;
|
|
581
|
+
const content = [];
|
|
582
|
+
for (const block of message.content) {
|
|
583
|
+
if (message.role === "assistant" && isRecord(block) && block.type === "tool_use") {
|
|
584
|
+
const demotedName = demotedCallNames.get(block.id);
|
|
585
|
+
if (demotedName !== undefined) {
|
|
586
|
+
messageChanged = true;
|
|
587
|
+
content.push({ type: "text", text: demotedToolCallText(demotedName, block.input) });
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (isRecord(block) && block.type === "tool_result") {
|
|
592
|
+
const demotedName = demotedCallNames.get(block.tool_use_id);
|
|
593
|
+
if (demotedName !== undefined) {
|
|
594
|
+
messageChanged = true;
|
|
595
|
+
content.push({ type: "text", text: demotedToolResultText(demotedName, block.content) });
|
|
596
|
+
continue;
|
|
597
|
+
}
|
|
598
|
+
if (danglingReferenceNames.size > 0 && Array.isArray(block.content)) {
|
|
599
|
+
const kept = [];
|
|
600
|
+
const omitted = [];
|
|
601
|
+
for (const item of block.content) {
|
|
602
|
+
if (isRecord(item) &&
|
|
603
|
+
item.type === "tool_reference" &&
|
|
604
|
+
typeof item.tool_name === "string" &&
|
|
605
|
+
danglingReferenceNames.has(item.tool_name)) {
|
|
606
|
+
omitted.push(item.tool_name);
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
kept.push(item);
|
|
610
|
+
}
|
|
611
|
+
if (omitted.length > 0) {
|
|
612
|
+
messageChanged = true;
|
|
613
|
+
const nextContent = kept.length > 0
|
|
614
|
+
? kept
|
|
615
|
+
: [{ type: "text", text: `Tool reference unavailable: ${[...new Set(omitted)].join(", ")}` }];
|
|
616
|
+
content.push({ ...block, content: nextContent });
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
content.push(block);
|
|
622
|
+
}
|
|
623
|
+
if (content.length === 0) {
|
|
624
|
+
changed = true;
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
if (messageChanged) {
|
|
628
|
+
changed = true;
|
|
629
|
+
rewrittenMessages.push({ ...message, content });
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
rewrittenMessages.push(message);
|
|
633
|
+
}
|
|
634
|
+
if (!changed)
|
|
635
|
+
return params;
|
|
636
|
+
return { ...params, messages: rewrittenMessages };
|
|
637
|
+
}
|
|
638
|
+
function collectToolReferenceNames(value, names) {
|
|
639
|
+
if (Array.isArray(value)) {
|
|
640
|
+
for (const item of value)
|
|
641
|
+
collectToolReferenceNames(item, names);
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
if (!isRecord(value))
|
|
645
|
+
return;
|
|
646
|
+
if (value.type === "tool_reference" && typeof value.tool_name === "string")
|
|
647
|
+
names.add(value.tool_name);
|
|
648
|
+
for (const nested of Object.values(value))
|
|
649
|
+
collectToolReferenceNames(nested, names);
|
|
650
|
+
}
|
|
651
|
+
function demotedToolCallText(name, input) {
|
|
652
|
+
let serializedInput;
|
|
653
|
+
try {
|
|
654
|
+
serializedInput = JSON.stringify(input ?? {});
|
|
655
|
+
}
|
|
656
|
+
catch {
|
|
657
|
+
serializedInput = "{}";
|
|
658
|
+
}
|
|
659
|
+
return `[Called tool "${name}" (no longer available in this session) with input: ${serializedInput}]`;
|
|
660
|
+
}
|
|
661
|
+
function demotedToolResultText(name, content) {
|
|
662
|
+
return `[Result of unavailable tool "${name}": ${toolResultText(content)}]`;
|
|
663
|
+
}
|
|
664
|
+
function toolResultText(content) {
|
|
665
|
+
if (typeof content === "string")
|
|
666
|
+
return content;
|
|
667
|
+
if (Array.isArray(content)) {
|
|
668
|
+
const parts = [];
|
|
669
|
+
for (const item of content) {
|
|
670
|
+
if (!isRecord(item))
|
|
671
|
+
continue;
|
|
672
|
+
if (item.type === "text" && typeof item.text === "string")
|
|
673
|
+
parts.push(item.text);
|
|
674
|
+
else if (typeof item.type === "string")
|
|
675
|
+
parts.push(`[${item.type}]`);
|
|
676
|
+
}
|
|
677
|
+
if (parts.length > 0)
|
|
678
|
+
return parts.join("\n");
|
|
679
|
+
}
|
|
680
|
+
return "Tool output unavailable.";
|
|
681
|
+
}
|
|
572
682
|
function sanitizeAdaptiveThinkingPayload(model, params, options) {
|
|
573
683
|
if (!supportsAdaptiveThinking(model)) {
|
|
574
684
|
return params;
|
|
@@ -817,6 +927,7 @@ export const stream = (model, context, options) => {
|
|
|
817
927
|
}
|
|
818
928
|
params = sanitizeAdaptiveThinkingPayload(model, params, options);
|
|
819
929
|
params = sanitizeUnsupportedNativeTools(model, params);
|
|
930
|
+
params = demoteUnavailableToolReferences(params);
|
|
820
931
|
const payloadRequestMetadata = extractPayloadRequestMetadata(params);
|
|
821
932
|
params = payloadRequestMetadata.params;
|
|
822
933
|
const requestOptions = {
|