@providerkit/core 0.5.1 → 0.7.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/README.md +15 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/presets.d.ts +249 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +199 -0
- package/dist/presets.js.map +1 -0
- package/dist/providers/anthropic.d.ts +9 -0
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +19 -3
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/factory.d.ts +19 -0
- package/dist/providers/factory.d.ts.map +1 -0
- package/dist/providers/factory.js +82 -0
- package/dist/providers/factory.js.map +1 -0
- package/dist/providers/openai.d.ts +4 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +1 -1
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/zai.d.ts +18 -0
- package/dist/providers/zai.d.ts.map +1 -0
- package/dist/providers/zai.js +27 -0
- package/dist/providers/zai.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +3 -0
- package/src/presets.ts +265 -0
- package/src/providers/anthropic.ts +36 -10
- package/src/providers/factory.ts +102 -0
- package/src/providers/openai.ts +5 -1
- package/src/providers/zai.ts +31 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// The one-line switch: resolve a preset id into a wired provider.
|
|
2
|
+
//
|
|
3
|
+
// Consumers used to write their own switch over providers — the same
|
|
4
|
+
// dispatch, re-derived per codebase, each quietly accumulating dialect
|
|
5
|
+
// knowledge (which gateway takes Bearer, which needs the thinking marker).
|
|
6
|
+
// The presets table + this factory is that dispatch, said once: a caller
|
|
7
|
+
// names an id and hands over a credential, and the header style, endpoint
|
|
8
|
+
// and adapter come from the table.
|
|
9
|
+
//
|
|
10
|
+
// `effort` passes through to the adapter unchanged — the per-endpoint
|
|
11
|
+
// thinking dialects (Z.ai's explicit disabled marker, OpenRouter's floors)
|
|
12
|
+
// are the adapters' knowledge, and this factory must not re-derive them.
|
|
13
|
+
import { createAnthropicProvider } from "./anthropic.ts";
|
|
14
|
+
import { createGeminiProvider } from "./gemini.ts";
|
|
15
|
+
import { createOpenAIProvider } from "./openai.ts";
|
|
16
|
+
import { createResponsesProvider } from "./responses.ts";
|
|
17
|
+
import { PRESET_IDS, PROVIDER_PRESETS, type ProviderPreset, type ProviderPresetId } from "../presets.ts";
|
|
18
|
+
import type { Effort, Provider } from "../types.ts";
|
|
19
|
+
|
|
20
|
+
export interface PresetProviderConfig {
|
|
21
|
+
/** The credential: an API key for `key`/`bearer` presets, an ACCESS TOKEN
|
|
22
|
+
* for `oauth` ones. Acquiring the token is the caller's job. */
|
|
23
|
+
apiKey: string;
|
|
24
|
+
/** Which model to run. Absent = the preset's `defaultModel`; a preset
|
|
25
|
+
* without either throws rather than sending a request nobody chose. */
|
|
26
|
+
model?: string;
|
|
27
|
+
effort?: Effort;
|
|
28
|
+
/** Output ceiling. The Anthropic shape requires one; adapters default it. */
|
|
29
|
+
maxTokens?: number;
|
|
30
|
+
/** Per-request headers (request ids, `ChatGPT-Account-Id`) on top of the
|
|
31
|
+
* preset's static protocol headers. */
|
|
32
|
+
headers?: Record<string, string>;
|
|
33
|
+
fetchImpl?: typeof fetch;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function createPresetProvider(id: ProviderPresetId, config: PresetProviderConfig): Provider {
|
|
37
|
+
// The table is closed (`satisfies`), but a caller may hold an id as a plain
|
|
38
|
+
// string — validate rather than index into undefined.
|
|
39
|
+
if (!(id in PROVIDER_PRESETS)) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`[providerkit] Unknown provider preset "${id}". Valid ids: ${PRESET_IDS.join(", ")}`,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
const preset: ProviderPreset = PROVIDER_PRESETS[id];
|
|
45
|
+
const model = config.model ?? preset.defaultModel;
|
|
46
|
+
if (!model) {
|
|
47
|
+
throw new Error(`[providerkit] Preset "${id}" has no defaultModel — pass a model.`);
|
|
48
|
+
}
|
|
49
|
+
const headers = { ...preset.headers, ...config.headers };
|
|
50
|
+
|
|
51
|
+
switch (preset.shape) {
|
|
52
|
+
case "anthropic":
|
|
53
|
+
// `key` rides Anthropic's native x-api-key; coding plans and OAuth
|
|
54
|
+
// tokens read Bearer (measured across the family's coding endpoints).
|
|
55
|
+
return createAnthropicProvider({
|
|
56
|
+
apiKey: config.apiKey,
|
|
57
|
+
model,
|
|
58
|
+
effort: config.effort,
|
|
59
|
+
maxTokens: config.maxTokens,
|
|
60
|
+
baseUrl: preset.baseUrl,
|
|
61
|
+
id,
|
|
62
|
+
headers,
|
|
63
|
+
bearer: preset.auth !== "key",
|
|
64
|
+
// The endpoint's thinking dialect rides the table (zai: silence means
|
|
65
|
+
// the model default, which is ON — "none" must be said out loud).
|
|
66
|
+
...(preset.explicitNone ? { explicitNone: true } : {}),
|
|
67
|
+
fetchImpl: config.fetchImpl,
|
|
68
|
+
});
|
|
69
|
+
case "openai":
|
|
70
|
+
return createOpenAIProvider({
|
|
71
|
+
id,
|
|
72
|
+
apiKey: config.apiKey,
|
|
73
|
+
model,
|
|
74
|
+
effort: config.effort,
|
|
75
|
+
maxTokens: config.maxTokens,
|
|
76
|
+
baseUrl: preset.baseUrl,
|
|
77
|
+
headers,
|
|
78
|
+
fetchImpl: config.fetchImpl,
|
|
79
|
+
});
|
|
80
|
+
case "responses":
|
|
81
|
+
return createResponsesProvider({
|
|
82
|
+
apiKey: config.apiKey,
|
|
83
|
+
model,
|
|
84
|
+
effort: config.effort,
|
|
85
|
+
maxTokens: config.maxTokens,
|
|
86
|
+
baseUrl: preset.baseUrl,
|
|
87
|
+
id,
|
|
88
|
+
headers,
|
|
89
|
+
fetchImpl: config.fetchImpl,
|
|
90
|
+
});
|
|
91
|
+
case "gemini":
|
|
92
|
+
return createGeminiProvider({
|
|
93
|
+
apiKey: config.apiKey,
|
|
94
|
+
model,
|
|
95
|
+
effort: config.effort,
|
|
96
|
+
baseUrl: preset.baseUrl,
|
|
97
|
+
id,
|
|
98
|
+
headers,
|
|
99
|
+
fetchImpl: config.fetchImpl,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
package/src/providers/openai.ts
CHANGED
|
@@ -24,6 +24,10 @@ export interface OpenAIConfig {
|
|
|
24
24
|
model: string;
|
|
25
25
|
/** Any OpenAI-compatible endpoint. Defaults to OpenAI itself. */
|
|
26
26
|
baseUrl?: string;
|
|
27
|
+
/** Path appended to baseUrl. Defaults to /v1/chat/completions. Set
|
|
28
|
+
* /chat/completions when the base already includes the API version, such as
|
|
29
|
+
* a gateway using /v4 rather than /v1. */
|
|
30
|
+
path?: string;
|
|
27
31
|
/** Names the provider in errors and logs — "openrouter", "deepseek", … It
|
|
28
32
|
* also picks the effort dialect below, unless `effortDialect` overrides. */
|
|
29
33
|
id?: string;
|
|
@@ -398,7 +402,7 @@ export function createOpenAIProvider(config: OpenAIConfig): Provider {
|
|
|
398
402
|
}
|
|
399
403
|
|
|
400
404
|
for await (const data of streamSse({
|
|
401
|
-
url: apiUrl(baseUrl, "/v1/chat/completions"),
|
|
405
|
+
url: apiUrl(baseUrl, config.path ?? "/v1/chat/completions"),
|
|
402
406
|
headers: { authorization: `Bearer ${config.apiKey}`, ...config.headers },
|
|
403
407
|
body: request,
|
|
404
408
|
provider: id,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createAnthropicProvider, type AnthropicConfig } from "./anthropic.ts";
|
|
2
|
+
import type { Provider } from "../types.ts";
|
|
3
|
+
|
|
4
|
+
/** Z.ai Coding Plan's Anthropic-compatible API root, not its pay-per-token API. */
|
|
5
|
+
export const ZAI_CODING_BASE_URL = "https://api.z.ai/api/anthropic";
|
|
6
|
+
|
|
7
|
+
export type ZaiCodingConfig = Omit<AnthropicConfig, "baseUrl" | "id" | "bearer">;
|
|
8
|
+
|
|
9
|
+
/** Use a Z.ai Coding Plan key with the shared Messages adapter. The preset owns
|
|
10
|
+
* the endpoint, Bearer auth and the thinking dialect; callers still choose
|
|
11
|
+
* their model and effort. Tool calls, usage and errors use the existing
|
|
12
|
+
* adapter.
|
|
13
|
+
*
|
|
14
|
+
* Dialect notes, measured 2026-09-13 against the live endpoint on
|
|
15
|
+
* `glm-5.3-flash`: an absent thinking field means the MODEL's default —
|
|
16
|
+
* thinking ON — so `effort: "none"` is sent as an explicit
|
|
17
|
+
* `thinking: { type: "disabled" }`; `low`–`max` ride the standard thinking
|
|
18
|
+
* budgets, which the endpoint accepts. Images force a thinking block even
|
|
19
|
+
* under `disabled` (the model's choice, billed as output). */
|
|
20
|
+
export function createZaiCodingProvider(config: ZaiCodingConfig): Provider {
|
|
21
|
+
return createAnthropicProvider({
|
|
22
|
+
...config,
|
|
23
|
+
id: "zai",
|
|
24
|
+
baseUrl: ZAI_CODING_BASE_URL,
|
|
25
|
+
bearer: true,
|
|
26
|
+
explicitNone: true,
|
|
27
|
+
// Coding gateways can allocate a 32K thinking budget themselves. Leave room
|
|
28
|
+
// for the answer; callers can still set a smaller cap for their model.
|
|
29
|
+
maxTokens: config.maxTokens ?? 65_536,
|
|
30
|
+
});
|
|
31
|
+
}
|