@chances-ai/engine 30.0.0 → 31.0.0
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/ai/adapters/ai-sdk-stream.d.ts +13 -1
- package/dist/ai/adapters/ai-sdk-stream.d.ts.map +1 -1
- package/dist/ai/adapters/ai-sdk-stream.js +140 -39
- package/dist/ai/adapters/ai-sdk-stream.js.map +1 -1
- package/dist/ai/adapters/ai-sdk.d.ts +8 -0
- package/dist/ai/adapters/ai-sdk.d.ts.map +1 -1
- package/dist/ai/adapters/ai-sdk.js +39 -1
- package/dist/ai/adapters/ai-sdk.js.map +1 -1
- package/dist/ai/adapters/mock.d.ts.map +1 -1
- package/dist/ai/adapters/mock.js +6 -2
- package/dist/ai/adapters/mock.js.map +1 -1
- package/dist/ai/adapters/native-anthropic.d.ts +51 -0
- package/dist/ai/adapters/native-anthropic.d.ts.map +1 -0
- package/dist/ai/adapters/native-anthropic.js +179 -0
- package/dist/ai/adapters/native-anthropic.js.map +1 -0
- package/dist/ai/adapters/openai-compatible.d.ts +17 -1
- package/dist/ai/adapters/openai-compatible.d.ts.map +1 -1
- package/dist/ai/adapters/openai-compatible.js +105 -1
- package/dist/ai/adapters/openai-compatible.js.map +1 -1
- package/dist/ai/compat.d.ts +30 -0
- package/dist/ai/compat.d.ts.map +1 -0
- package/dist/ai/compat.js +93 -0
- package/dist/ai/compat.js.map +1 -0
- package/dist/ai/cost.d.ts +9 -0
- package/dist/ai/cost.d.ts.map +1 -1
- package/dist/ai/cost.js +15 -2
- package/dist/ai/cost.js.map +1 -1
- package/dist/ai/index.d.ts +6 -2
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +5 -1
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/known-models.d.ts +20 -6
- package/dist/ai/known-models.d.ts.map +1 -1
- package/dist/ai/known-models.generated.d.ts +3 -0
- package/dist/ai/known-models.generated.d.ts.map +1 -0
- package/dist/ai/known-models.generated.js +518 -0
- package/dist/ai/known-models.generated.js.map +1 -0
- package/dist/ai/known-models.js +29 -128
- package/dist/ai/known-models.js.map +1 -1
- package/dist/ai/provider-table.d.ts +36 -0
- package/dist/ai/provider-table.d.ts.map +1 -0
- package/dist/ai/provider-table.js +80 -0
- package/dist/ai/provider-table.js.map +1 -0
- package/dist/ai/retry.d.ts +74 -3
- package/dist/ai/retry.d.ts.map +1 -1
- package/dist/ai/retry.js +246 -6
- package/dist/ai/retry.js.map +1 -1
- package/dist/ai/router.d.ts +12 -0
- package/dist/ai/router.d.ts.map +1 -1
- package/dist/ai/router.js +19 -0
- package/dist/ai/router.js.map +1 -1
- package/dist/ai/sampling.d.ts +37 -0
- package/dist/ai/sampling.d.ts.map +1 -0
- package/dist/ai/sampling.js +34 -0
- package/dist/ai/sampling.js.map +1 -0
- package/dist/ai/setup.d.ts.map +1 -1
- package/dist/ai/setup.js +27 -3
- package/dist/ai/setup.js.map +1 -1
- package/dist/ai/summarizer.d.ts.map +1 -1
- package/dist/ai/summarizer.js +6 -1
- package/dist/ai/summarizer.js.map +1 -1
- package/dist/ai/think-filter.d.ts +30 -0
- package/dist/ai/think-filter.d.ts.map +1 -0
- package/dist/ai/think-filter.js +193 -0
- package/dist/ai/think-filter.js.map +1 -0
- package/dist/ai/thinking.d.ts +77 -0
- package/dist/ai/thinking.d.ts.map +1 -0
- package/dist/ai/thinking.js +174 -0
- package/dist/ai/thinking.js.map +1 -0
- package/dist/ai/types.d.ts +134 -7
- package/dist/ai/types.d.ts.map +1 -1
- package/dist/core/compaction/compactor.d.ts.map +1 -1
- package/dist/core/compaction/compactor.js +44 -6
- package/dist/core/compaction/compactor.js.map +1 -1
- package/dist/core/engine.d.ts +16 -1
- package/dist/core/engine.d.ts.map +1 -1
- package/dist/core/engine.js +122 -18
- package/dist/core/engine.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { native } from "@chances-ai/native";
|
|
2
|
+
import { detectCompat } from "../compat.js";
|
|
3
|
+
import { effortToThinkingBudget } from "../thinking.js";
|
|
4
|
+
import { extractRetryAfterSeconds } from "../retry.js";
|
|
5
|
+
import { AiSdkAdapter, redactStream } from "./ai-sdk.js";
|
|
6
|
+
/**
|
|
7
|
+
* (7.10 W6) `api="anthropic-messages"` adapter. Prefers the hand-rolled native
|
|
8
|
+
* client (chances-natives `anthropic` feature) which gives us cache_control
|
|
9
|
+
* 3-anchor placement, byte-faithful thinking signatures, and structured
|
|
10
|
+
* status/Retry-After the AI-SDK hides; falls back to `@ai-sdk/anthropic` when no
|
|
11
|
+
* native client is loaded (the per-fn JS-fallback invariant — the live path
|
|
12
|
+
* works today regardless of the addon build).
|
|
13
|
+
*
|
|
14
|
+
* Both paths emit the SAME `ProviderEvent` sequence (the native parser is the
|
|
15
|
+
* golden-equivalence target), so the engine is oblivious to which ran.
|
|
16
|
+
*/
|
|
17
|
+
export class NativeAnthropicAdapter {
|
|
18
|
+
opts;
|
|
19
|
+
id = "anthropic";
|
|
20
|
+
fallback;
|
|
21
|
+
constructor(opts) {
|
|
22
|
+
this.opts = opts;
|
|
23
|
+
this.fallback = new AiSdkAdapter({
|
|
24
|
+
provider: "anthropic",
|
|
25
|
+
apiKey: opts.apiKey,
|
|
26
|
+
models: opts.models,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
listModels() {
|
|
30
|
+
return this.opts.models;
|
|
31
|
+
}
|
|
32
|
+
async *stream(req, signal) {
|
|
33
|
+
if (!native.hasAnthropicClient()) {
|
|
34
|
+
// No native build loaded → the AI-SDK anthropic path (the JS fallback).
|
|
35
|
+
yield* this.fallback.stream(req, signal);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
yield* redactStream(this.streamNative(req, signal), this.opts.apiKey);
|
|
39
|
+
}
|
|
40
|
+
/** Bridge the native callback stream to an async iterable. The Rust worker
|
|
41
|
+
* pushes ProviderEvent JSON on a libuv-thread callback; we queue + hand them
|
|
42
|
+
* out in order, ending on the terminal `done`/`error` or on abort. */
|
|
43
|
+
async *streamNative(req, signal) {
|
|
44
|
+
if (signal.aborted)
|
|
45
|
+
return; // pre-abort: never hit the network
|
|
46
|
+
const reqJson = JSON.stringify(this.buildNativeRequest(req));
|
|
47
|
+
const queue = [];
|
|
48
|
+
let wake = null;
|
|
49
|
+
let done = false;
|
|
50
|
+
const push = (ev) => {
|
|
51
|
+
queue.push(ev);
|
|
52
|
+
if (ev.type === "done" || ev.type === "error")
|
|
53
|
+
done = true;
|
|
54
|
+
wake?.();
|
|
55
|
+
};
|
|
56
|
+
const onEvent = (json) => {
|
|
57
|
+
try {
|
|
58
|
+
push(this.parseEvent(JSON.parse(json)));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
push({ type: "error", message: "native anthropic: malformed event" });
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const handle = native.anthropicStream(reqJson, this.buildNativeOptions(req), onEvent);
|
|
65
|
+
const onAbort = () => {
|
|
66
|
+
done = true;
|
|
67
|
+
handle.abort();
|
|
68
|
+
wake?.();
|
|
69
|
+
};
|
|
70
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
71
|
+
try {
|
|
72
|
+
for (;;) {
|
|
73
|
+
while (queue.length > 0) {
|
|
74
|
+
const ev = queue.shift();
|
|
75
|
+
if (signal.aborted)
|
|
76
|
+
return;
|
|
77
|
+
yield ev;
|
|
78
|
+
if (ev.type === "done" || ev.type === "error")
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (done || signal.aborted)
|
|
82
|
+
return;
|
|
83
|
+
await new Promise((resolve) => {
|
|
84
|
+
wake = resolve;
|
|
85
|
+
});
|
|
86
|
+
wake = null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
signal.removeEventListener("abort", onAbort);
|
|
91
|
+
handle.abort(); // stop the worker if we leave early (consumer break/throw)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
parseEvent(e) {
|
|
95
|
+
return normalizeNativeError(e);
|
|
96
|
+
}
|
|
97
|
+
buildNativeRequest(req) {
|
|
98
|
+
return buildNativeAnthropicRequest(req, this.opts.models);
|
|
99
|
+
}
|
|
100
|
+
buildNativeOptions(req) {
|
|
101
|
+
const compat = detectCompat("anthropic-messages", {
|
|
102
|
+
provider: "anthropic",
|
|
103
|
+
modelId: req.model,
|
|
104
|
+
});
|
|
105
|
+
const beta = [];
|
|
106
|
+
// The extended (1h) cache TTL is a beta; only request it when this model
|
|
107
|
+
// supports it AND the caller asked for the long retention.
|
|
108
|
+
if (req.cacheRetention === "long" && compat.supportsLongCacheRetention) {
|
|
109
|
+
beta.push("extended-cache-ttl-2025-04-11");
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
apiKey: this.opts.apiKey,
|
|
113
|
+
...(this.opts.baseURL ? { baseUrl: this.opts.baseURL } : {}),
|
|
114
|
+
...(beta.length > 0 ? { beta } : {}),
|
|
115
|
+
...(req.sampling?.timeoutMs !== undefined ? { timeoutMs: req.sampling.timeoutMs } : {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* (7.10 W6) The JSON the Rust `build_request_body` consumes. Pure + exported so
|
|
121
|
+
* the request shaping is unit-tested without a native build. effort→budget lives
|
|
122
|
+
* ONCE (here, via `thinking.ts`); the cache compat flags come from the model.
|
|
123
|
+
* Reasoning and sampling are mutually exclusive on anthropic — when a thinking
|
|
124
|
+
* budget is present the Rust builder drops temperature/top_p, so we omit them.
|
|
125
|
+
*/
|
|
126
|
+
export function buildNativeAnthropicRequest(req, models) {
|
|
127
|
+
const descriptor = models.find((m) => m.id === req.model);
|
|
128
|
+
const compat = detectCompat("anthropic-messages", {
|
|
129
|
+
provider: "anthropic",
|
|
130
|
+
modelId: req.model,
|
|
131
|
+
});
|
|
132
|
+
const out = {
|
|
133
|
+
model: req.model,
|
|
134
|
+
messages: req.messages,
|
|
135
|
+
tools: req.tools,
|
|
136
|
+
maxTokens: req.sampling?.maxTokens ?? descriptor?.maxTokens ?? 4096,
|
|
137
|
+
cacheRetention: req.cacheRetention ?? "short",
|
|
138
|
+
compat: {
|
|
139
|
+
longCache: compat.supportsLongCacheRetention ?? false,
|
|
140
|
+
cacheOnTools: compat.supportsCacheControlOnTools ?? false,
|
|
141
|
+
allowEmptySignature: compat.allowEmptySignature ?? false,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
if (req.system)
|
|
145
|
+
out.system = req.system;
|
|
146
|
+
if (req.reasoning) {
|
|
147
|
+
out.thinkingBudget = effortToThinkingBudget(req.reasoning);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
if (req.sampling?.temperature !== undefined)
|
|
151
|
+
out.temperature = req.sampling.temperature;
|
|
152
|
+
if (req.sampling?.topP !== undefined)
|
|
153
|
+
out.topP = req.sampling.topP;
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* (7.10 W6) Map a raw native event object to a {@link ProviderEvent}. Pure +
|
|
159
|
+
* exported for unit tests. The native `error` event carries `status` +
|
|
160
|
+
* `retryAfter` (raw header); we normalize the Retry-After (incl. an HTTP-date)
|
|
161
|
+
* to seconds and fold it into the message so the engine's classifier
|
|
162
|
+
* (`classifyProviderError`) classifies by the HTTP code AND honors the
|
|
163
|
+
* server-directed delay — the precise path the AI-SDK hides.
|
|
164
|
+
*/
|
|
165
|
+
export function normalizeNativeError(e) {
|
|
166
|
+
if (e.type !== "error")
|
|
167
|
+
return e;
|
|
168
|
+
let message = typeof e.message === "string" ? e.message : "anthropic error";
|
|
169
|
+
const retryAfter = e.retryAfter;
|
|
170
|
+
if (retryAfter !== undefined && !/retry\s*after/i.test(message)) {
|
|
171
|
+
const secs = extractRetryAfterSeconds({
|
|
172
|
+
"retry-after": typeof retryAfter === "string" ? retryAfter : String(retryAfter),
|
|
173
|
+
});
|
|
174
|
+
if (secs !== undefined)
|
|
175
|
+
message += ` (retry after ${secs} seconds)`;
|
|
176
|
+
}
|
|
177
|
+
return { type: "error", message };
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=native-anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-anthropic.js","sourceRoot":"","sources":["../../../src/ai/adapters/native-anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChatRequest, ModelDescriptor, ProviderAdapter, ProviderEvent } from "../types.js";
|
|
1
|
+
import type { ChatRequest, Effort, ModelDescriptor, ProviderAdapter, ProviderEvent, ThinkingFormat } from "../types.js";
|
|
2
2
|
export interface OpenAICompatibleAdapterOptions {
|
|
3
3
|
/** Provider id, e.g. "deepseek" or "xai". Becomes the adapter id. */
|
|
4
4
|
provider: string;
|
|
@@ -20,4 +20,20 @@ export declare class OpenAICompatibleAdapter implements ProviderAdapter {
|
|
|
20
20
|
listModels(): ModelDescriptor[];
|
|
21
21
|
stream(req: ChatRequest, signal: AbortSignal): AsyncIterable<ProviderEvent>;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* (7.10 §3.4, codex W3 R2-M1) The request-body fields that enable reasoning for
|
|
25
|
+
* an openai-completions vendor, keyed by its `thinkingFormat`. Returned object is
|
|
26
|
+
* spread into the body by the SDK's chat getArgs. `undefined` ⇒ no reasoning
|
|
27
|
+
* (off, or a dialect that needs no request field — string-thinking emits inline).
|
|
28
|
+
* Pure + exported so each dialect's wire shape is unit-tested.
|
|
29
|
+
*
|
|
30
|
+
* (7.10 TS re-review) `supportsReasoningEffort` GATES the plain-OpenAI dialect:
|
|
31
|
+
* kimi/moonshot, grok and groq detect as `thinkingFormat:"openai"` but
|
|
32
|
+
* `detectCompat` flags them `supportsReasoningEffort:false` (they have no
|
|
33
|
+
* `reasoning_effort` field — reasoning is automatic on their reasoning models).
|
|
34
|
+
* Without this gate the flag was dead and we sent `reasoning_effort` to vendors
|
|
35
|
+
* that reject it (6.9 work-vs-silently-dropped). The dedicated dialects
|
|
36
|
+
* (deepseek/openrouter/zai/qwen) carry their own enable field and are unaffected.
|
|
37
|
+
*/
|
|
38
|
+
export declare function reasoningBody(format: ThinkingFormat | undefined, reasoning: Effort | undefined, supportsReasoningEffort?: boolean): Record<string, unknown> | undefined;
|
|
23
39
|
//# sourceMappingURL=openai-compatible.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-compatible.d.ts","sourceRoot":"","sources":["../../../src/ai/adapters/openai-compatible.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"openai-compatible.d.ts","sourceRoot":"","sources":["../../../src/ai/adapters/openai-compatible.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EACX,MAAM,EACN,eAAe,EAEf,eAAe,EACf,aAAa,EACb,cAAc,EACf,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,8BAA8B;IAC7C,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED;;;;;GAKG;AACH,qBAAa,uBAAwB,YAAW,eAAe;IAGjD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;gBAES,IAAI,EAAE,8BAA8B;IAIjE,UAAU,IAAI,eAAe,EAAE;IAIxB,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,aAAa,CAAC,aAAa,CAAC;CAmDnF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,uBAAuB,UAAO,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAqBrC"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { detectCompat } from "../compat.js";
|
|
2
|
+
import { ThinkFilter } from "../think-filter.js";
|
|
3
|
+
import { mapEffortToOpenAIReasoningEffort } from "../thinking.js";
|
|
1
4
|
import { streamFromAiSdk } from "./ai-sdk-stream.js";
|
|
2
5
|
import { redact, redactStream } from "./ai-sdk.js";
|
|
3
6
|
/**
|
|
@@ -36,10 +39,111 @@ export class OpenAICompatibleAdapter {
|
|
|
36
39
|
yield { type: "error", message: redact(message, this.opts.apiKey) };
|
|
37
40
|
return;
|
|
38
41
|
}
|
|
42
|
+
// (7.10) Resolve this provider's quirks from the baseURL/id and translate the
|
|
43
|
+
// requested reasoning effort to THIS vendor's wire dialect (codex W3 R2-M1).
|
|
44
|
+
// The openai-compatible chat getArgs SPREADS providerOptions[providerName]
|
|
45
|
+
// raw into the request body, so per-dialect fields (deepseek `thinking`,
|
|
46
|
+
// zai/glm `enable_thinking`, openrouter `reasoning`) reach the endpoint.
|
|
47
|
+
const quirks = detectCompat("openai-completions", {
|
|
48
|
+
provider: this.opts.provider,
|
|
49
|
+
baseURL: this.opts.baseURL,
|
|
50
|
+
modelId: req.model,
|
|
51
|
+
});
|
|
52
|
+
const body = reasoningBody(quirks.thinkingFormat, req.reasoning, quirks.supportsReasoningEffort);
|
|
53
|
+
const providerOptions = body ? { [this.opts.provider]: body } : undefined;
|
|
39
54
|
// Redact downstream stream errors too — same defense-in-depth posture as
|
|
40
55
|
// AiSdkAdapter. We pass `apiKey` into a third-party constructor, so any
|
|
41
56
|
// future SDK that echoes the key on throw shouldn't reach the bus.
|
|
42
|
-
|
|
57
|
+
let stream = streamFromAiSdk(provider(req.model), req, signal, undefined, { providerOptions });
|
|
58
|
+
// Endpoints that fold reasoning INLINE as `<think>…</think>` in the content
|
|
59
|
+
// (rather than a separate reasoning field) get the streaming splitter so it
|
|
60
|
+
// surfaces as thinking, not answer text. Dormant for our declared providers
|
|
61
|
+
// (they use a reasoning field), available for proxies that don't.
|
|
62
|
+
if (quirks.thinkingFormat === "string-thinking")
|
|
63
|
+
stream = applyThinkFilter(stream);
|
|
64
|
+
yield* redactStream(stream, this.opts.apiKey);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* (7.10 §3.4, codex W3 R2-M1) The request-body fields that enable reasoning for
|
|
69
|
+
* an openai-completions vendor, keyed by its `thinkingFormat`. Returned object is
|
|
70
|
+
* spread into the body by the SDK's chat getArgs. `undefined` ⇒ no reasoning
|
|
71
|
+
* (off, or a dialect that needs no request field — string-thinking emits inline).
|
|
72
|
+
* Pure + exported so each dialect's wire shape is unit-tested.
|
|
73
|
+
*
|
|
74
|
+
* (7.10 TS re-review) `supportsReasoningEffort` GATES the plain-OpenAI dialect:
|
|
75
|
+
* kimi/moonshot, grok and groq detect as `thinkingFormat:"openai"` but
|
|
76
|
+
* `detectCompat` flags them `supportsReasoningEffort:false` (they have no
|
|
77
|
+
* `reasoning_effort` field — reasoning is automatic on their reasoning models).
|
|
78
|
+
* Without this gate the flag was dead and we sent `reasoning_effort` to vendors
|
|
79
|
+
* that reject it (6.9 work-vs-silently-dropped). The dedicated dialects
|
|
80
|
+
* (deepseek/openrouter/zai/qwen) carry their own enable field and are unaffected.
|
|
81
|
+
*/
|
|
82
|
+
export function reasoningBody(format, reasoning, supportsReasoningEffort = true) {
|
|
83
|
+
if (!reasoning)
|
|
84
|
+
return undefined;
|
|
85
|
+
const effort = mapEffortToOpenAIReasoningEffort(reasoning);
|
|
86
|
+
switch (format) {
|
|
87
|
+
case "openai":
|
|
88
|
+
return supportsReasoningEffort ? { reasoning_effort: effort } : undefined;
|
|
89
|
+
case "deepseek":
|
|
90
|
+
// deepseek-reasoner: turn thinking on + the granular effort.
|
|
91
|
+
return { thinking: { type: "enabled" }, reasoning_effort: effort };
|
|
92
|
+
case "openrouter":
|
|
93
|
+
return { reasoning: { effort } };
|
|
94
|
+
case "qwen":
|
|
95
|
+
case "zai":
|
|
96
|
+
// Top-level boolean toggle — no granular effort tier.
|
|
97
|
+
return { enable_thinking: true };
|
|
98
|
+
case "string-thinking":
|
|
99
|
+
case undefined:
|
|
100
|
+
// Inline-<think> models emit reasoning in content (ThinkFilter handles the
|
|
101
|
+
// output); they take no request field. Unknown format → send nothing.
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* (7.10) Wrap a provider stream so inline `<think>…</think>` in `text-delta`
|
|
107
|
+
* events is split into the thinking lifecycle. Non-text events pass through.
|
|
108
|
+
* Opens the block on the first thinking text and closes it when answer content
|
|
109
|
+
* resumes (or at stream end).
|
|
110
|
+
*/
|
|
111
|
+
async function* applyThinkFilter(source) {
|
|
112
|
+
const filter = new ThinkFilter();
|
|
113
|
+
let thinkingOpen = false;
|
|
114
|
+
function* drain(content, thinking) {
|
|
115
|
+
if (thinking) {
|
|
116
|
+
if (!thinkingOpen) {
|
|
117
|
+
thinkingOpen = true;
|
|
118
|
+
yield { type: "thinking-start" };
|
|
119
|
+
}
|
|
120
|
+
yield { type: "thinking-delta", text: thinking };
|
|
121
|
+
}
|
|
122
|
+
if (content) {
|
|
123
|
+
if (thinkingOpen) {
|
|
124
|
+
thinkingOpen = false;
|
|
125
|
+
yield { type: "thinking-end" };
|
|
126
|
+
}
|
|
127
|
+
yield { type: "text-delta", text: content };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
for await (const ev of source) {
|
|
131
|
+
if (ev.type === "text-delta") {
|
|
132
|
+
const out = filter.push(ev.text);
|
|
133
|
+
yield* drain(out.content, out.thinking);
|
|
134
|
+
}
|
|
135
|
+
else if (ev.type === "done") {
|
|
136
|
+
const out = filter.finish();
|
|
137
|
+
yield* drain(out.content, out.thinking);
|
|
138
|
+
if (thinkingOpen) {
|
|
139
|
+
thinkingOpen = false;
|
|
140
|
+
yield { type: "thinking-end" };
|
|
141
|
+
}
|
|
142
|
+
yield ev;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
yield ev;
|
|
146
|
+
}
|
|
43
147
|
}
|
|
44
148
|
}
|
|
45
149
|
//# sourceMappingURL=openai-compatible.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-compatible.js","sourceRoot":"","sources":["../../../src/ai/adapters/openai-compatible.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"openai-compatible.js","sourceRoot":"","sources":["../../../src/ai/adapters/openai-compatible.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AAUlE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAWnD;;;;;GAKG;AACH,MAAM,OAAO,uBAAuB;IAGL;IAFpB,EAAE,CAAS;IAEpB,YAA6B,IAAoC;QAApC,SAAI,GAAJ,IAAI,CAAgC;QAC/D,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC1B,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CAAC,GAAgB,EAAE,MAAmB;QASjD,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAwB,CAAC;QACpG,MAAM,MAAM,GAAG,MAAM,EAAE,sBAAsB,CAAC;QAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,4CAA4C,EAAE,CAAC;YAC/E,OAAO;QACT,CAAC;QACD,IAAI,QAAsC,CAAC;QAC3C,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,CAAC;gBAChB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ;gBACxB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;gBAC1B,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;aACzB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC3D,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACpE,OAAO;QACT,CAAC;QACD,8EAA8E;QAC9E,6EAA6E;QAC7E,2EAA2E;QAC3E,yEAAyE;QACzE,yEAAyE;QACzE,MAAM,MAAM,GAAG,YAAY,CAAC,oBAAoB,EAAE;YAChD,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ;YAC5B,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;YAC1B,OAAO,EAAE,GAAG,CAAC,KAAK;SACnB,CAA4B,CAAC;QAC9B,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,uBAAuB,CAAC,CAAC;QACjG,MAAM,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAE1E,yEAAyE;QACzE,wEAAwE;QACxE,mEAAmE;QACnE,IAAI,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC;QAC/F,4EAA4E;QAC5E,4EAA4E;QAC5E,4EAA4E;QAC5E,kEAAkE;QAClE,IAAI,MAAM,CAAC,cAAc,KAAK,iBAAiB;YAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACnF,KAAK,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,CAAC;CACF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAkC,EAClC,SAA6B,EAC7B,uBAAuB,GAAG,IAAI;IAE9B,IAAI,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IACjC,MAAM,MAAM,GAAG,gCAAgC,CAAC,SAAS,CAAC,CAAC;IAC3D,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,uBAAuB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5E,KAAK,UAAU;YACb,6DAA6D;YAC7D,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC;QACrE,KAAK,YAAY;YACf,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC;QACnC,KAAK,MAAM,CAAC;QACZ,KAAK,KAAK;YACR,sDAAsD;YACtD,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;QACnC,KAAK,iBAAiB,CAAC;QACvB,KAAK,SAAS;YACZ,2EAA2E;YAC3E,sEAAsE;YACtE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,SAAS,CAAC,CAAC,gBAAgB,CAC9B,MAAoC;IAEpC,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;IACjC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,QAAQ,CAAC,CAAC,KAAK,CAAC,OAAe,EAAE,QAAgB;QAC/C,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,YAAY,GAAG,IAAI,CAAC;gBACpB,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;YACnC,CAAC;YACD,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACnD,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,YAAY,EAAE,CAAC;gBACjB,YAAY,GAAG,KAAK,CAAC;gBACrB,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;YACjC,CAAC;YACD,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,IAAI,KAAK,EAAE,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QAC9B,IAAI,EAAE,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YACjC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;aAAM,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxC,IAAI,YAAY,EAAE,CAAC;gBACjB,YAAY,GAAG,KAAK,CAAC;gBACrB,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;YACjC,CAAC;YACD,MAAM,EAAE,CAAC;QACX,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Api, ModelCompat } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* (7.10 §3.1) Resolve the per-model quirk matrix from the wire protocol +
|
|
4
|
+
* baseURL + provider id — pi's `detectCompat` pattern (`openai-completions.ts:1075`).
|
|
5
|
+
* This is the mechanism that makes ONE `openai-completions` path serve every
|
|
6
|
+
* vendor correctly: the difference between reasoning working vs being silently
|
|
7
|
+
* dropped on deepseek/glm/kimi/qwen lives here, as data.
|
|
8
|
+
*
|
|
9
|
+
* The generated catalog pins `compat` per model; for any model that arrives
|
|
10
|
+
* WITHOUT one (custom baseURL, pre-catalog rows) the adapter falls back to this
|
|
11
|
+
* auto-detection. Explicit `model.compat?.X` always wins (`X ?? detected.X`,
|
|
12
|
+
* see {@link mergeCompat}).
|
|
13
|
+
*
|
|
14
|
+
* @param api wire protocol — only `openai-completions` / `anthropic-messages`
|
|
15
|
+
* carry quirks; everything else returns `{}`.
|
|
16
|
+
* @param opts `baseURL` + `provider` drive detection; `modelId` is needed
|
|
17
|
+
* only for the openrouter→anthropic cache-control corner case.
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectCompat(api: Api, opts: {
|
|
20
|
+
baseURL?: string;
|
|
21
|
+
provider: string;
|
|
22
|
+
modelId?: string;
|
|
23
|
+
}): ModelCompat;
|
|
24
|
+
/**
|
|
25
|
+
* (7.10 §3.1) Field-level merge: an explicit per-model override beats the
|
|
26
|
+
* auto-detected default (`override ?? detected`), pi `getCompat` semantics. Only
|
|
27
|
+
* meaningful within one api family — callers pass same-shaped objects.
|
|
28
|
+
*/
|
|
29
|
+
export declare function mergeCompat<T extends ModelCompat>(detected: T, override?: Partial<T>): T;
|
|
30
|
+
//# sourceMappingURL=compat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../../src/ai/compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,GAAG,EACH,WAAW,EAEZ,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,GAAG,EACR,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D,WAAW,CAIb;AAkED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,WAAW,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAQxF"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (7.10 §3.1) Resolve the per-model quirk matrix from the wire protocol +
|
|
3
|
+
* baseURL + provider id — pi's `detectCompat` pattern (`openai-completions.ts:1075`).
|
|
4
|
+
* This is the mechanism that makes ONE `openai-completions` path serve every
|
|
5
|
+
* vendor correctly: the difference between reasoning working vs being silently
|
|
6
|
+
* dropped on deepseek/glm/kimi/qwen lives here, as data.
|
|
7
|
+
*
|
|
8
|
+
* The generated catalog pins `compat` per model; for any model that arrives
|
|
9
|
+
* WITHOUT one (custom baseURL, pre-catalog rows) the adapter falls back to this
|
|
10
|
+
* auto-detection. Explicit `model.compat?.X` always wins (`X ?? detected.X`,
|
|
11
|
+
* see {@link mergeCompat}).
|
|
12
|
+
*
|
|
13
|
+
* @param api wire protocol — only `openai-completions` / `anthropic-messages`
|
|
14
|
+
* carry quirks; everything else returns `{}`.
|
|
15
|
+
* @param opts `baseURL` + `provider` drive detection; `modelId` is needed
|
|
16
|
+
* only for the openrouter→anthropic cache-control corner case.
|
|
17
|
+
*/
|
|
18
|
+
export function detectCompat(api, opts) {
|
|
19
|
+
if (api === "anthropic-messages")
|
|
20
|
+
return detectAnthropicCompat(opts.provider);
|
|
21
|
+
if (api === "openai-completions")
|
|
22
|
+
return detectOpenAICompletionsCompat(opts);
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
function detectAnthropicCompat(provider) {
|
|
26
|
+
// First-party Anthropic supports 1h cache + cache_control on tools. Empty
|
|
27
|
+
// signatures are NOT allowed (downgrade interrupted thinking to text);
|
|
28
|
+
// Bedrock/Vertex anthropic relays (out of the declared set today) would set
|
|
29
|
+
// allowEmptySignature where their replay tolerates it.
|
|
30
|
+
const firstParty = provider === "anthropic";
|
|
31
|
+
return {
|
|
32
|
+
supportsLongCacheRetention: firstParty,
|
|
33
|
+
supportsCacheControlOnTools: firstParty,
|
|
34
|
+
allowEmptySignature: false,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function detectOpenAICompletionsCompat(opts) {
|
|
38
|
+
const url = (opts.baseURL ?? "").toLowerCase();
|
|
39
|
+
const p = opts.provider;
|
|
40
|
+
const isDeepSeek = p === "deepseek" || url.includes("deepseek.com");
|
|
41
|
+
// glm / z.ai share the "enable_thinking" (zai) dialect.
|
|
42
|
+
const isZai = p === "glm" || url.includes("open.bigmodel.cn") || url.includes("api.z.ai");
|
|
43
|
+
const isMoonshot = p === "kimi" || url.includes("moonshot");
|
|
44
|
+
const isOpenRouter = p === "openrouter" || url.includes("openrouter.ai");
|
|
45
|
+
const isGrok = p === "xai" || url.includes("x.ai");
|
|
46
|
+
const isGroq = p === "groq" || url.includes("groq.com");
|
|
47
|
+
const isDoubao = p === "doubao" || url.includes("volces.com");
|
|
48
|
+
const isMiniMax = p === "minimax" || url.includes("minimax");
|
|
49
|
+
// "Non-standard" OpenAI-compat endpoints: most Chinese vendors + grok/groq
|
|
50
|
+
// reject the OpenAI-native `store` field and want plain `max_tokens`.
|
|
51
|
+
const isNonStandard = isDeepSeek || isZai || isMoonshot || isGrok || isGroq || isDoubao || isMiniMax;
|
|
52
|
+
// enable_thinking vendors (zai/glm + qwen-family) don't take reasoning_effort;
|
|
53
|
+
// grok/groq/moonshot don't expose effort either.
|
|
54
|
+
const supportsReasoningEffort = !(isZai || isGrok || isGroq || isMoonshot);
|
|
55
|
+
const thinkingFormat = isDeepSeek
|
|
56
|
+
? "deepseek"
|
|
57
|
+
: isZai
|
|
58
|
+
? "zai"
|
|
59
|
+
: isOpenRouter
|
|
60
|
+
? "openrouter"
|
|
61
|
+
: "openai";
|
|
62
|
+
return {
|
|
63
|
+
thinkingFormat,
|
|
64
|
+
maxTokensField: isNonStandard ? "max_tokens" : "max_completion_tokens",
|
|
65
|
+
supportsReasoningEffort,
|
|
66
|
+
supportsStore: !isNonStandard,
|
|
67
|
+
// Moonshot/Kimi reject `strict` in tool defs; everyone else accepts it.
|
|
68
|
+
supportsStrictMode: !isMoonshot,
|
|
69
|
+
supportsUsageInStreaming: true,
|
|
70
|
+
supportsDeveloperRole: false,
|
|
71
|
+
// DeepSeek requires replayed assistant messages to carry reasoning_content.
|
|
72
|
+
requiresReasoningContentOnAssistantMessages: isDeepSeek,
|
|
73
|
+
// OpenRouter routing an Anthropic model expects Anthropic cache markers.
|
|
74
|
+
cacheControlFormat: isOpenRouter && (opts.modelId ?? "").startsWith("anthropic/") ? "anthropic" : undefined,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* (7.10 §3.1) Field-level merge: an explicit per-model override beats the
|
|
79
|
+
* auto-detected default (`override ?? detected`), pi `getCompat` semantics. Only
|
|
80
|
+
* meaningful within one api family — callers pass same-shaped objects.
|
|
81
|
+
*/
|
|
82
|
+
export function mergeCompat(detected, override) {
|
|
83
|
+
if (!override)
|
|
84
|
+
return detected;
|
|
85
|
+
const out = { ...detected };
|
|
86
|
+
for (const k of Object.keys(override)) {
|
|
87
|
+
const v = override[k];
|
|
88
|
+
if (v !== undefined)
|
|
89
|
+
out[k] = v;
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat.js","sourceRoot":"","sources":["../../src/ai/compat.ts"],"names":[],"mappings":"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"}
|
package/dist/ai/cost.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
import type { ModelDescriptor, Usage } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* (7.10 §3.3) Cache-aware cost over the 4-bucket {@link Usage}. Each bucket
|
|
4
|
+
* bills at its own $/1M rate; a cache hit is far cheaper than fresh input and a
|
|
5
|
+
* cache write slightly dearer. When the catalog omits a cache rate we fall back
|
|
6
|
+
* to the input rate (a conservative upper bound — never under-bills), so models
|
|
7
|
+
* without published cache pricing still compute a sane number. This replaces the
|
|
8
|
+
* old 2-rate formula that billed cached requests as if every token were fresh
|
|
9
|
+
* input (Axis 6.3 — a real over-count for cache-heavy coding turns).
|
|
10
|
+
*/
|
|
2
11
|
export declare function estimateCost(model: ModelDescriptor, usage: Usage): number;
|
|
3
12
|
//# sourceMappingURL=cost.d.ts.map
|
package/dist/ai/cost.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/ai/cost.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEzD,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/ai/cost.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEzD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CASzE"}
|
package/dist/ai/cost.js
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (7.10 §3.3) Cache-aware cost over the 4-bucket {@link Usage}. Each bucket
|
|
3
|
+
* bills at its own $/1M rate; a cache hit is far cheaper than fresh input and a
|
|
4
|
+
* cache write slightly dearer. When the catalog omits a cache rate we fall back
|
|
5
|
+
* to the input rate (a conservative upper bound — never under-bills), so models
|
|
6
|
+
* without published cache pricing still compute a sane number. This replaces the
|
|
7
|
+
* old 2-rate formula that billed cached requests as if every token were fresh
|
|
8
|
+
* input (Axis 6.3 — a real over-count for cache-heavy coding turns).
|
|
9
|
+
*/
|
|
1
10
|
export function estimateCost(model, usage) {
|
|
2
|
-
|
|
3
|
-
|
|
11
|
+
const cacheRead = model.cacheReadCostPerMTok ?? model.inputCostPerMTok;
|
|
12
|
+
const cacheWrite = model.cacheWriteCostPerMTok ?? model.inputCostPerMTok;
|
|
13
|
+
return ((usage.input / 1_000_000) * model.inputCostPerMTok +
|
|
14
|
+
(usage.output / 1_000_000) * model.outputCostPerMTok +
|
|
15
|
+
(usage.cacheRead / 1_000_000) * cacheRead +
|
|
16
|
+
(usage.cacheWrite / 1_000_000) * cacheWrite);
|
|
4
17
|
}
|
|
5
18
|
//# sourceMappingURL=cost.js.map
|
package/dist/ai/cost.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/ai/cost.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,KAAsB,EAAE,KAAY;IAC/D,OAAO,CACL,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/ai/cost.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,KAAsB,EAAE,KAAY;IAC/D,MAAM,SAAS,GAAG,KAAK,CAAC,oBAAoB,IAAI,KAAK,CAAC,gBAAgB,CAAC;IACvE,MAAM,UAAU,GAAG,KAAK,CAAC,qBAAqB,IAAI,KAAK,CAAC,gBAAgB,CAAC;IACzE,OAAO,CACL,CAAC,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,gBAAgB;QAClD,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,iBAAiB;QACpD,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,SAAS;QACzC,CAAC,KAAK,CAAC,UAAU,GAAG,SAAS,CAAC,GAAG,UAAU,CAC5C,CAAC;AACJ,CAAC"}
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
export type { Role, ContentPart, Message, ToolDefinition, ToolCallRequest, Usage,
|
|
1
|
+
export type { Role, ContentPart, Message, ToolDefinition, ToolCallRequest, Usage, Api, Effort, CacheRetention, SamplingOptions, ModelThinkingLevel, ThinkingLevelMap, ThinkingFormat, OpenAICompletionsCompat, AnthropicMessagesCompat, ModelCompat, ModelDescriptor, ChatRequest, ProviderEvent, ProviderAdapter, } from "./types.js";
|
|
2
|
+
export { detectCompat, mergeCompat } from "./compat.js";
|
|
3
|
+
export { clampSampling, SAMPLING_BOUNDS } from "./sampling.js";
|
|
4
|
+
export { THINKING_LEVELS, getSupportedThinkingLevels, clampThinkingLevel, anthropicHasRealXHighEffort, mapEffortToAnthropicAdaptiveEffort, effortToThinkingBudget, mapEffortToOpenAIReasoningEffort, effortToGoogleThinkingBudget, thinkingBlockToProvider, type ThinkingBlock, } from "./thinking.js";
|
|
5
|
+
export { ThinkFilter, splitThinkBlocks } from "./think-filter.js";
|
|
2
6
|
export { ModelRegistry } from "./registry.js";
|
|
3
7
|
export { ModelRouter, type RouteHints, type Route } from "./router.js";
|
|
4
8
|
export { estimateCost } from "./cost.js";
|
|
@@ -8,6 +12,6 @@ export { AiSdkAdapter, AI_SDK_PACKAGES, type AiSdkAdapterOptions, type AiSdkProv
|
|
|
8
12
|
export { OpenAICompatibleAdapter, type OpenAICompatibleAdapterOptions, } from "./adapters/openai-compatible.js";
|
|
9
13
|
export { KNOWN_MODELS, type ProviderEntry } from "./known-models.js";
|
|
10
14
|
export { buildRegistry, envByProviderFrom, type RegistryOptions } from "./setup.js";
|
|
11
|
-
export { classifyProviderError, defaultRetryConfig, type RetryConfig, type RetryDecision, } from "./retry.js";
|
|
15
|
+
export { classifyProviderError, classifyByStatus, extractRetryAfterSeconds, computeRetryDelayMs, defaultRetryConfig, withMaxRetries, type RetryConfig, type RetryDecision, type ProviderErrorKind, type HeadersLike, } from "./retry.js";
|
|
12
16
|
export { summarizeConversation, COMPACT_SUMMARY_SYSTEM } from "./summarizer.js";
|
|
13
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/ai/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,IAAI,EACJ,WAAW,EACX,OAAO,EACP,cAAc,EACd,eAAe,EACf,KAAK,EACL,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,IAAI,EACJ,WAAW,EACX,OAAO,EACP,cAAc,EACd,eAAe,EACf,KAAK,EACL,GAAG,EACH,MAAM,EACN,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,uBAAuB,EACvB,uBAAuB,EACvB,WAAW,EACX,eAAe,EACf,WAAW,EACX,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,kBAAkB,EAClB,2BAA2B,EAC3B,kCAAkC,EAClC,sBAAsB,EACtB,gCAAgC,EAChC,4BAA4B,EAC5B,uBAAuB,EACvB,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,KAAK,cAAc,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EACL,YAAY,EACZ,eAAe,EACf,KAAK,mBAAmB,EACxB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,uBAAuB,EACvB,KAAK,8BAA8B,GACpC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,wBAAwB,EACxB,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/ai/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export { detectCompat, mergeCompat } from "./compat.js";
|
|
2
|
+
export { clampSampling, SAMPLING_BOUNDS } from "./sampling.js";
|
|
3
|
+
export { THINKING_LEVELS, getSupportedThinkingLevels, clampThinkingLevel, anthropicHasRealXHighEffort, mapEffortToAnthropicAdaptiveEffort, effortToThinkingBudget, mapEffortToOpenAIReasoningEffort, effortToGoogleThinkingBudget, thinkingBlockToProvider, } from "./thinking.js";
|
|
4
|
+
export { ThinkFilter, splitThinkBlocks } from "./think-filter.js";
|
|
1
5
|
export { ModelRegistry } from "./registry.js";
|
|
2
6
|
export { ModelRouter } from "./router.js";
|
|
3
7
|
export { estimateCost } from "./cost.js";
|
|
@@ -7,6 +11,6 @@ export { AiSdkAdapter, AI_SDK_PACKAGES, } from "./adapters/ai-sdk.js";
|
|
|
7
11
|
export { OpenAICompatibleAdapter, } from "./adapters/openai-compatible.js";
|
|
8
12
|
export { KNOWN_MODELS } from "./known-models.js";
|
|
9
13
|
export { buildRegistry, envByProviderFrom } from "./setup.js";
|
|
10
|
-
export { classifyProviderError, defaultRetryConfig, } from "./retry.js";
|
|
14
|
+
export { classifyProviderError, classifyByStatus, extractRetryAfterSeconds, computeRetryDelayMs, defaultRetryConfig, withMaxRetries, } from "./retry.js";
|
|
11
15
|
export { summarizeConversation, COMPACT_SUMMARY_SYSTEM } from "./summarizer.js";
|
|
12
16
|
//# sourceMappingURL=index.js.map
|
package/dist/ai/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,kBAAkB,EAClB,2BAA2B,EAC3B,kCAAkC,EAClC,sBAAsB,EACtB,gCAAgC,EAChC,4BAA4B,EAC5B,uBAAuB,GAExB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,WAAW,EAA+B,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAuB,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EACL,YAAY,EACZ,eAAe,GAGhB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,uBAAuB,GAExB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,YAAY,EAAsB,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAwB,MAAM,YAAY,CAAC;AACpF,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,wBAAwB,EACxB,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,GAKf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1,20 +1,34 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Api, ModelDescriptor } from "./types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Per-provider metadata used by `buildRegistry` to wire the right adapter.
|
|
4
4
|
* `models` is the capability table the registry indexes; `envKey` resolves
|
|
5
|
-
* the API key; `baseURL` is required for the `openai-
|
|
5
|
+
* the API key; `baseURL` is required for the `openai-completions` wire protocol
|
|
6
6
|
* (Chinese providers + xai/groq/openrouter) and ignored for the native ones.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* (7.10) Assembled from {@link PROVIDER_TABLE} (hand-maintained connection
|
|
9
|
+
* config) + {@link GENERATED_MODELS} (the models.dev catalog, regenerated by
|
|
10
|
+
* `scripts/generate-models.ts`). Prices are USD per 1M tokens.
|
|
11
11
|
*/
|
|
12
12
|
export interface ProviderEntry {
|
|
13
13
|
id: string;
|
|
14
|
-
api:
|
|
14
|
+
api: Api;
|
|
15
15
|
envKey: string;
|
|
16
16
|
baseURL?: string;
|
|
17
17
|
models: ModelDescriptor[];
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* (7.10 §3.2) Merge each provider's generated catalog rows with its
|
|
21
|
+
* hand-maintained `models` (doubao isn't on models.dev) and drop any `exclude`d
|
|
22
|
+
* ids. `provider` + `api` on every row already match the entry (the generator
|
|
23
|
+
* stamps them from the table), which the registry consistency guard verifies.
|
|
24
|
+
*
|
|
25
|
+
* Model ids must be globally unique (the registry indexes by id, so a collision
|
|
26
|
+
* is ambiguous routing). A few open-weight ids appear under BOTH a direct host
|
|
27
|
+
* AND the openrouter aggregator (e.g. groq + openrouter both list
|
|
28
|
+
* `openai/gpt-oss-120b`). We dedup with **earlier-table-entry-wins**: direct
|
|
29
|
+
* providers precede openrouter in {@link PROVIDER_TABLE}, so the direct (faster,
|
|
30
|
+
* cheaper) host keeps the id and the aggregator's duplicate is dropped — and any
|
|
31
|
+
* future collision resolves deterministically without manual `exclude` upkeep.
|
|
32
|
+
*/
|
|
19
33
|
export declare const KNOWN_MODELS: ProviderEntry[];
|
|
20
34
|
//# sourceMappingURL=known-models.d.ts.map
|