@wrenautomation/models 0.0.0-stage → 0.1.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/LICENSE.md +91 -0
- package/README.md +87 -2
- package/dist/command.d.ts +44 -0
- package/dist/command.js +151 -0
- package/dist/command.js.map +1 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.js +79 -0
- package/dist/errors.js.map +1 -0
- package/dist/fake.d.ts +5 -0
- package/dist/fake.js +33 -0
- package/dist/fake.js.map +1 -0
- package/dist/hear.d.ts +63 -0
- package/dist/hear.js +95 -0
- package/dist/hear.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/keys.d.ts +27 -0
- package/dist/keys.js +73 -0
- package/dist/keys.js.map +1 -0
- package/dist/model.d.ts +21 -0
- package/dist/model.js +68 -0
- package/dist/model.js.map +1 -0
- package/dist/parse.d.ts +15 -0
- package/dist/parse.js +66 -0
- package/dist/parse.js.map +1 -0
- package/dist/prices.d.ts +50 -0
- package/dist/prices.js +146 -0
- package/dist/prices.js.map +1 -0
- package/dist/providers.d.ts +66 -0
- package/dist/providers.js +122 -0
- package/dist/providers.js.map +1 -0
- package/dist/sdk.d.ts +27 -0
- package/dist/sdk.js +153 -0
- package/dist/sdk.js.map +1 -0
- package/dist/spec.d.ts +11 -0
- package/dist/spec.js +70 -0
- package/dist/spec.js.map +1 -0
- package/dist/types.d.ts +88 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +68 -4
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type RotateOptions } from "./keys.js";
|
|
2
|
+
import type { Model } from "./types.js";
|
|
3
|
+
/** Short names for the current Claude models. A full id passes through. */
|
|
4
|
+
export declare const ANTHROPIC_MODELS: Readonly<Record<string, string>>;
|
|
5
|
+
export declare const anthropicModelId: (name: string) => string;
|
|
6
|
+
export interface VendorOptions {
|
|
7
|
+
key: string | readonly string[];
|
|
8
|
+
/** A model id or, on Anthropic, a short name. */
|
|
9
|
+
model?: string;
|
|
10
|
+
rotate?: RotateOptions;
|
|
11
|
+
limitMs?: number;
|
|
12
|
+
/** For tests: the wire. */
|
|
13
|
+
fetch?: typeof fetch;
|
|
14
|
+
}
|
|
15
|
+
/** Claude on Wren's own key. Default Haiku 5.5. */
|
|
16
|
+
export declare function anthropic(o: VendorOptions): Model;
|
|
17
|
+
/** Gemini on the free key ring. It takes every part kind, YouTube URLs as video included. */
|
|
18
|
+
export declare function gemini(o: VendorOptions): Model;
|
|
19
|
+
/** Cohere's own API on the free key ring: text and images. */
|
|
20
|
+
export declare function cohere(o: VendorOptions): Model;
|
|
21
|
+
/** OpenAI-compatible vendors: base URL, default model, and whether Wren's keys there are free. */
|
|
22
|
+
export declare const COMPATIBLE: {
|
|
23
|
+
readonly groq: {
|
|
24
|
+
readonly baseURL: "https://api.groq.com/openai/v1";
|
|
25
|
+
readonly model: "openai/gpt-oss-120b";
|
|
26
|
+
readonly free: () => boolean;
|
|
27
|
+
};
|
|
28
|
+
readonly openrouter: {
|
|
29
|
+
readonly baseURL: "https://openrouter.ai/api/v1";
|
|
30
|
+
readonly model: "google/gemma-4-31b-it:free";
|
|
31
|
+
readonly free: (m: string) => boolean;
|
|
32
|
+
};
|
|
33
|
+
readonly mistral: {
|
|
34
|
+
readonly baseURL: "https://api.mistral.ai/v1";
|
|
35
|
+
readonly model: "mistral-small-latest";
|
|
36
|
+
readonly free: () => boolean;
|
|
37
|
+
};
|
|
38
|
+
readonly cerebras: {
|
|
39
|
+
readonly baseURL: "https://api.cerebras.ai/v1";
|
|
40
|
+
readonly model: "gpt-oss-120b";
|
|
41
|
+
readonly free: () => boolean;
|
|
42
|
+
};
|
|
43
|
+
readonly openai: {
|
|
44
|
+
readonly baseURL: "https://api.openai.com/v1";
|
|
45
|
+
readonly model: "gpt-5-mini";
|
|
46
|
+
readonly free: () => boolean;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
export type CompatibleVendor = keyof typeof COMPATIBLE;
|
|
50
|
+
export declare const isCompatible: (v: string) => v is CompatibleVendor;
|
|
51
|
+
export declare function compatible(vendor: CompatibleVendor, o: VendorOptions): Model;
|
|
52
|
+
/** The gateway's Gemini spends output tokens thinking first: 400 asked came back as 27 chars. */
|
|
53
|
+
export declare const GATEWAY_THINKING = 4096;
|
|
54
|
+
/** `<url>/v1`; a URL given with its `/v1` is not doubled. */
|
|
55
|
+
export declare const gatewayBase: (url: string) => string;
|
|
56
|
+
/**
|
|
57
|
+
* Wren's LLM gateway (llm.wrenautomation.com): it holds the free keys and one ledger. Its model is
|
|
58
|
+
* an alias (`free`, `cohere`) or `<vendor>/<model>`. `free` costs 0.
|
|
59
|
+
*/
|
|
60
|
+
export declare function gateway(o: {
|
|
61
|
+
url: string;
|
|
62
|
+
token: string;
|
|
63
|
+
model?: string;
|
|
64
|
+
limitMs?: number;
|
|
65
|
+
fetch?: typeof fetch;
|
|
66
|
+
}): Model;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The vendors. Each maker returns a `Model`; a list of keys returns one rotating over them.
|
|
3
|
+
* Free key rings (Cohere, Gemini, Groq, OpenRouter's `:free` models, the gateway's `free` alias)
|
|
4
|
+
* cost 0 and keep their list price; the rest are priced from the table.
|
|
5
|
+
*/
|
|
6
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
7
|
+
import { createCohere } from "@ai-sdk/cohere";
|
|
8
|
+
import { createGoogle } from "@ai-sdk/google";
|
|
9
|
+
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
10
|
+
import { rotating } from "./keys.js";
|
|
11
|
+
import { TEXT_ONLY } from "./model.js";
|
|
12
|
+
import { sdkModel } from "./sdk.js";
|
|
13
|
+
const kinds = (...k) => new Set(k);
|
|
14
|
+
const keyList = (key) => (typeof key === "string" ? [key] : key);
|
|
15
|
+
const ring = (keys, make, o, vendor) => {
|
|
16
|
+
if (!keys.length)
|
|
17
|
+
throw new Error(`${vendor} needs at least one key`);
|
|
18
|
+
return rotating(keys.map(make), o);
|
|
19
|
+
};
|
|
20
|
+
/** Short names for the current Claude models. A full id passes through. */
|
|
21
|
+
export const ANTHROPIC_MODELS = {
|
|
22
|
+
haiku: "claude-haiku-5-5",
|
|
23
|
+
sonnet: "claude-sonnet-5-5",
|
|
24
|
+
opus: "claude-opus-5-5",
|
|
25
|
+
};
|
|
26
|
+
export const anthropicModelId = (name) => ANTHROPIC_MODELS[name] ?? name;
|
|
27
|
+
const wire = (o) => (o.fetch ? { fetch: o.fetch } : {});
|
|
28
|
+
/** Claude on Wren's own key. Default Haiku 5.5. */
|
|
29
|
+
export function anthropic(o) {
|
|
30
|
+
const modelId = anthropicModelId(o.model ?? "haiku");
|
|
31
|
+
return ring(keyList(o.key), (apiKey) => sdkModel({
|
|
32
|
+
provider: "anthropic",
|
|
33
|
+
modelId,
|
|
34
|
+
model: createAnthropic({ apiKey, ...wire(o) })(modelId),
|
|
35
|
+
takes: kinds("text", "image", "pdf"),
|
|
36
|
+
...(o.limitMs ? { limitMs: o.limitMs } : {}),
|
|
37
|
+
}), o.rotate, "anthropic");
|
|
38
|
+
}
|
|
39
|
+
/** Gemini on the free key ring. It takes every part kind, YouTube URLs as video included. */
|
|
40
|
+
export function gemini(o) {
|
|
41
|
+
const modelId = o.model ?? "gemini-3.5-flash";
|
|
42
|
+
return ring(keyList(o.key), (apiKey) => sdkModel({
|
|
43
|
+
provider: "google",
|
|
44
|
+
modelId,
|
|
45
|
+
model: createGoogle({ apiKey, ...wire(o) })(modelId),
|
|
46
|
+
takes: kinds("text", "image", "video", "audio", "pdf"),
|
|
47
|
+
free: true,
|
|
48
|
+
...(o.limitMs ? { limitMs: o.limitMs } : {}),
|
|
49
|
+
}), o.rotate, "gemini");
|
|
50
|
+
}
|
|
51
|
+
/** Cohere's own API on the free key ring: text and images. */
|
|
52
|
+
export function cohere(o) {
|
|
53
|
+
const modelId = o.model ?? "command-a-03-2025";
|
|
54
|
+
return ring(keyList(o.key), (apiKey) => sdkModel({
|
|
55
|
+
provider: "cohere",
|
|
56
|
+
modelId,
|
|
57
|
+
model: createCohere({ apiKey, ...wire(o) })(modelId),
|
|
58
|
+
takes: modelId.includes("vision") ? kinds("text", "image") : TEXT_ONLY,
|
|
59
|
+
free: true,
|
|
60
|
+
...(o.limitMs ? { limitMs: o.limitMs } : {}),
|
|
61
|
+
}), o.rotate, "cohere");
|
|
62
|
+
}
|
|
63
|
+
/** OpenAI-compatible vendors: base URL, default model, and whether Wren's keys there are free. */
|
|
64
|
+
export const COMPATIBLE = {
|
|
65
|
+
groq: {
|
|
66
|
+
baseURL: "https://api.groq.com/openai/v1",
|
|
67
|
+
model: "openai/gpt-oss-120b",
|
|
68
|
+
free: () => true,
|
|
69
|
+
},
|
|
70
|
+
openrouter: {
|
|
71
|
+
baseURL: "https://openrouter.ai/api/v1",
|
|
72
|
+
model: "google/gemma-4-31b-it:free",
|
|
73
|
+
free: (m) => m.endsWith(":free"),
|
|
74
|
+
},
|
|
75
|
+
mistral: {
|
|
76
|
+
baseURL: "https://api.mistral.ai/v1",
|
|
77
|
+
model: "mistral-small-latest",
|
|
78
|
+
free: () => false,
|
|
79
|
+
},
|
|
80
|
+
cerebras: { baseURL: "https://api.cerebras.ai/v1", model: "gpt-oss-120b", free: () => false },
|
|
81
|
+
openai: { baseURL: "https://api.openai.com/v1", model: "gpt-5-mini", free: () => false },
|
|
82
|
+
};
|
|
83
|
+
export const isCompatible = (v) => Object.hasOwn(COMPATIBLE, v);
|
|
84
|
+
export function compatible(vendor, o) {
|
|
85
|
+
const spec = COMPATIBLE[vendor];
|
|
86
|
+
const modelId = o.model ?? spec.model;
|
|
87
|
+
return ring(keyList(o.key), (apiKey) => sdkModel({
|
|
88
|
+
provider: vendor,
|
|
89
|
+
modelId,
|
|
90
|
+
model: createOpenAICompatible({ name: vendor, baseURL: spec.baseURL, apiKey, ...wire(o) })(modelId),
|
|
91
|
+
takes: TEXT_ONLY,
|
|
92
|
+
free: spec.free(modelId),
|
|
93
|
+
...(o.limitMs ? { limitMs: o.limitMs } : {}),
|
|
94
|
+
}), o.rotate, vendor);
|
|
95
|
+
}
|
|
96
|
+
/** The gateway's Gemini spends output tokens thinking first: 400 asked came back as 27 chars. */
|
|
97
|
+
export const GATEWAY_THINKING = 4096;
|
|
98
|
+
/** `<url>/v1`; a URL given with its `/v1` is not doubled. */
|
|
99
|
+
export const gatewayBase = (url) => `${url.replace(/\/$/, "").replace(/\/v1$/, "")}/v1`;
|
|
100
|
+
/**
|
|
101
|
+
* Wren's LLM gateway (llm.wrenautomation.com): it holds the free keys and one ledger. Its model is
|
|
102
|
+
* an alias (`free`, `cohere`) or `<vendor>/<model>`. `free` costs 0.
|
|
103
|
+
*/
|
|
104
|
+
export function gateway(o) {
|
|
105
|
+
const modelId = o.model ?? "free";
|
|
106
|
+
return sdkModel({
|
|
107
|
+
provider: "gateway",
|
|
108
|
+
modelId,
|
|
109
|
+
model: createOpenAICompatible({
|
|
110
|
+
name: "gateway",
|
|
111
|
+
baseURL: gatewayBase(o.url),
|
|
112
|
+
apiKey: o.token,
|
|
113
|
+
...wire(o),
|
|
114
|
+
})(modelId),
|
|
115
|
+
takes: TEXT_ONLY,
|
|
116
|
+
thinking: GATEWAY_THINKING,
|
|
117
|
+
free: modelId === "free",
|
|
118
|
+
priceId: modelId.slice(modelId.indexOf("/") + 1),
|
|
119
|
+
...(o.limitMs ? { limitMs: o.limitMs } : {}),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"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"}
|
package/dist/sdk.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One AI SDK language model as a `Model`. The SDK speaks each vendor's wire; this maps our
|
|
3
|
+
* request in and the reply, tokens, price and errors out. The SDK's own retries are off: the
|
|
4
|
+
* caller (a runner, a key ring) owns trying again.
|
|
5
|
+
*/
|
|
6
|
+
import { type LanguageModel } from "ai";
|
|
7
|
+
import type { Model, PartKind } from "./types.js";
|
|
8
|
+
/** The ceiling when a request names none. A long extract with quotes passed 4096 on a live run. */
|
|
9
|
+
export declare const DEFAULT_MAX_TOKENS = 8192;
|
|
10
|
+
/** One call, wall clock: a long draft takes a minute or two. */
|
|
11
|
+
export declare const CALL_LIMIT_MS: number;
|
|
12
|
+
export interface SdkModelOptions {
|
|
13
|
+
/** The vendor (`anthropic`, `groq`, `gateway`). */
|
|
14
|
+
provider: string;
|
|
15
|
+
/** The vendor's model id. */
|
|
16
|
+
modelId: string;
|
|
17
|
+
model: LanguageModel;
|
|
18
|
+
takes: ReadonlySet<PartKind>;
|
|
19
|
+
/** Tokens added to every ceiling for a model that thinks inside its output budget. */
|
|
20
|
+
thinking?: number;
|
|
21
|
+
/** A free key: the reply costs 0 and keeps its list price. */
|
|
22
|
+
free?: boolean;
|
|
23
|
+
/** The id the price table knows, when it is not `modelId`. */
|
|
24
|
+
priceId?: string;
|
|
25
|
+
limitMs?: number;
|
|
26
|
+
}
|
|
27
|
+
export declare function sdkModel(o: SdkModelOptions): Model;
|
package/dist/sdk.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One AI SDK language model as a `Model`. The SDK speaks each vendor's wire; this maps our
|
|
3
|
+
* request in and the reply, tokens, price and errors out. The SDK's own retries are off: the
|
|
4
|
+
* caller (a runner, a key ring) owns trying again.
|
|
5
|
+
*/
|
|
6
|
+
import { APICallError, generateText, } from "ai";
|
|
7
|
+
import { Cut, statusError, Transient, transport } from "./errors.js";
|
|
8
|
+
import { modelOf } from "./model.js";
|
|
9
|
+
import { wellFormed } from "./parse.js";
|
|
10
|
+
import { priced } from "./prices.js";
|
|
11
|
+
/** The ceiling when a request names none. A long extract with quotes passed 4096 on a live run. */
|
|
12
|
+
export const DEFAULT_MAX_TOKENS = 8192;
|
|
13
|
+
/** The least a call may answer in: a lower cap only cuts an answer off. */
|
|
14
|
+
const FLOOR_TOKENS = 2048;
|
|
15
|
+
/** One call, wall clock: a long draft takes a minute or two. */
|
|
16
|
+
export const CALL_LIMIT_MS = 5 * 60_000;
|
|
17
|
+
const GEMINI_LEVEL = {
|
|
18
|
+
low: "low",
|
|
19
|
+
medium: "medium",
|
|
20
|
+
high: "high",
|
|
21
|
+
xhigh: "high",
|
|
22
|
+
max: "high",
|
|
23
|
+
};
|
|
24
|
+
function effortOptions(provider, effort) {
|
|
25
|
+
if (!effort)
|
|
26
|
+
return {};
|
|
27
|
+
if (provider === "anthropic")
|
|
28
|
+
return { providerOptions: { anthropic: { effort } } };
|
|
29
|
+
if (provider === "google")
|
|
30
|
+
return {
|
|
31
|
+
providerOptions: { google: { thinkingConfig: { thinkingLevel: GEMINI_LEVEL[effort] } } },
|
|
32
|
+
};
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
function contentOf(parts) {
|
|
36
|
+
return parts.map((p) => {
|
|
37
|
+
switch (p.type) {
|
|
38
|
+
case "text":
|
|
39
|
+
return { type: "text", text: wellFormed(p.text) };
|
|
40
|
+
case "image":
|
|
41
|
+
return { type: "image", image: p.data, mediaType: p.mediaType };
|
|
42
|
+
case "pdf":
|
|
43
|
+
return { type: "file", data: p.data, mediaType: "application/pdf" };
|
|
44
|
+
default:
|
|
45
|
+
return { type: "file", data: p.data, mediaType: p.mediaType };
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/** System and prompt in the SDK's shape. On Anthropic the system carries a cache breakpoint. */
|
|
50
|
+
function input(provider, req) {
|
|
51
|
+
const body = typeof req.prompt === "string"
|
|
52
|
+
? { prompt: wellFormed(req.prompt) }
|
|
53
|
+
: { messages: [{ role: "user", content: contentOf(req.prompt) }] };
|
|
54
|
+
if (!req.system)
|
|
55
|
+
return body;
|
|
56
|
+
if (provider !== "anthropic")
|
|
57
|
+
return { system: wellFormed(req.system), ...body };
|
|
58
|
+
return {
|
|
59
|
+
system: {
|
|
60
|
+
role: "system",
|
|
61
|
+
content: wellFormed(req.system),
|
|
62
|
+
providerOptions: { anthropic: { cacheControl: { type: "ephemeral" } } },
|
|
63
|
+
},
|
|
64
|
+
...body,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function failure(what, err, signal) {
|
|
68
|
+
if (signal?.aborted)
|
|
69
|
+
return err;
|
|
70
|
+
if (APICallError.isInstance(err)) {
|
|
71
|
+
if (err.statusCode === undefined)
|
|
72
|
+
return transport(what, err);
|
|
73
|
+
const detail = err.message.slice(0, 300);
|
|
74
|
+
return statusError(`${what}: HTTP ${err.statusCode} ${detail}`, err.statusCode, err.responseHeaders?.["retry-after"]);
|
|
75
|
+
}
|
|
76
|
+
if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError"))
|
|
77
|
+
return new Transient(`${what}: no answer in time`, { cause: err });
|
|
78
|
+
if (err instanceof TypeError)
|
|
79
|
+
return transport(what, err);
|
|
80
|
+
return err;
|
|
81
|
+
}
|
|
82
|
+
export function sdkModel(o) {
|
|
83
|
+
const id = o.provider === "anthropic" ? o.modelId : `${o.provider}:${o.modelId}`;
|
|
84
|
+
const limitMs = o.limitMs ?? CALL_LIMIT_MS;
|
|
85
|
+
return modelOf({
|
|
86
|
+
id,
|
|
87
|
+
provider: o.provider,
|
|
88
|
+
takes: o.takes,
|
|
89
|
+
async complete(req) {
|
|
90
|
+
const started = performance.now();
|
|
91
|
+
const timeout = AbortSignal.timeout(limitMs);
|
|
92
|
+
const abortSignal = req.signal ? AbortSignal.any([req.signal, timeout]) : timeout;
|
|
93
|
+
let result;
|
|
94
|
+
try {
|
|
95
|
+
result = await generateText({
|
|
96
|
+
model: o.model,
|
|
97
|
+
...input(o.provider, req),
|
|
98
|
+
maxOutputTokens: Math.max(req.maxTokens ?? DEFAULT_MAX_TOKENS, FLOOR_TOKENS) + (o.thinking ?? 0),
|
|
99
|
+
...effortOptions(o.provider, req.effort),
|
|
100
|
+
maxRetries: 0,
|
|
101
|
+
abortSignal,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
throw failure(id, err, req.signal);
|
|
106
|
+
}
|
|
107
|
+
const u = result.usage;
|
|
108
|
+
const tokens = {};
|
|
109
|
+
if (u.inputTokens !== undefined)
|
|
110
|
+
tokens.input = u.inputTokens;
|
|
111
|
+
if (u.outputTokens !== undefined)
|
|
112
|
+
tokens.output = u.outputTokens;
|
|
113
|
+
if (u.inputTokenDetails?.cacheReadTokens)
|
|
114
|
+
tokens.cacheRead = u.inputTokenDetails.cacheReadTokens;
|
|
115
|
+
if (u.inputTokenDetails?.cacheWriteTokens)
|
|
116
|
+
tokens.cacheWrite = u.inputTokenDetails.cacheWriteTokens;
|
|
117
|
+
const usage = priced(o.priceId ?? o.modelId, tokens, { free: o.free ?? false });
|
|
118
|
+
const stop = result.rawFinishReason ?? result.finishReason;
|
|
119
|
+
if (result.finishReason === "length")
|
|
120
|
+
throw new Cut(`${id} stopped at its output cap (${stop})`, result.text, usage);
|
|
121
|
+
if (!result.text)
|
|
122
|
+
throw new Error(`${id}: no text in the reply (stop ${stop})`);
|
|
123
|
+
return {
|
|
124
|
+
text: result.text,
|
|
125
|
+
usage,
|
|
126
|
+
model: result.response.modelId || o.modelId,
|
|
127
|
+
stop,
|
|
128
|
+
ms: Math.round(performance.now() - started),
|
|
129
|
+
raw: {
|
|
130
|
+
provider: o.provider,
|
|
131
|
+
model: o.modelId,
|
|
132
|
+
stop_reason: stop,
|
|
133
|
+
finish_reason_unified: result.finishReason,
|
|
134
|
+
usage: {
|
|
135
|
+
input_tokens: u.inputTokens ?? null,
|
|
136
|
+
output_tokens: u.outputTokens ?? null,
|
|
137
|
+
reasoning_tokens: u.outputTokenDetails?.reasoningTokens ?? null,
|
|
138
|
+
cache_read_tokens: u.inputTokenDetails?.cacheReadTokens ?? null,
|
|
139
|
+
cache_write_tokens: u.inputTokenDetails?.cacheWriteTokens ?? null,
|
|
140
|
+
},
|
|
141
|
+
response: {
|
|
142
|
+
id: result.response.id,
|
|
143
|
+
model_id: result.response.modelId,
|
|
144
|
+
timestamp: result.response.timestamp.toISOString(),
|
|
145
|
+
},
|
|
146
|
+
provider_metadata: result.providerMetadata ?? null,
|
|
147
|
+
warnings: result.warnings ?? [],
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=sdk.js.map
|
package/dist/sdk.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"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"}
|
package/dist/spec.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type EnvMap, type RotateOptions } from "./keys.js";
|
|
2
|
+
import type { Model } from "./types.js";
|
|
3
|
+
export declare const SPEC_NAMES: readonly ["fake", "claude-code", "anthropic", "gateway", "gemini", "cohere", "command", ...string[]];
|
|
4
|
+
/**
|
|
5
|
+
* Keys come from the environment by vendor (`ANTHROPIC_API_KEY`, `GROQ_API_KEY_1`...); the
|
|
6
|
+
* gateway reads `WREN_LLM_GATEWAY_URL` and `WREN_LLM_GATEWAY_TOKEN`. `rotate` sets how a key ring
|
|
7
|
+
* waits when every key is busy.
|
|
8
|
+
*/
|
|
9
|
+
export declare function modelFromSpec(spec: string, env?: EnvMap, o?: {
|
|
10
|
+
rotate?: RotateOptions;
|
|
11
|
+
}): Model;
|
package/dist/spec.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A model from one string and the environment, for a CLI flag or a setting (Node only: it can
|
|
3
|
+
* start `claude -p`). Grammar: `fake` | `claude-code[:model]` | `anthropic[:haiku|sonnet|opus|id]` |
|
|
4
|
+
* `gateway[:alias]` | `gemini[:id]` | `cohere[:id]` | `<groq|openrouter|mistral|cerebras|openai>[:id]` |
|
|
5
|
+
* `command:<shell command>` (the prompt on stdin, the answer on stdout).
|
|
6
|
+
*/
|
|
7
|
+
import { claudeCode, commandModel } from "./command.js";
|
|
8
|
+
import { fakeModel } from "./fake.js";
|
|
9
|
+
import { fleetKeys } from "./keys.js";
|
|
10
|
+
import { anthropic, COMPATIBLE, cohere, compatible, gateway, gemini, isCompatible, } from "./providers.js";
|
|
11
|
+
export const SPEC_NAMES = [
|
|
12
|
+
"fake",
|
|
13
|
+
"claude-code",
|
|
14
|
+
"anthropic",
|
|
15
|
+
"gateway",
|
|
16
|
+
"gemini",
|
|
17
|
+
"cohere",
|
|
18
|
+
"command",
|
|
19
|
+
...Object.keys(COMPATIBLE),
|
|
20
|
+
];
|
|
21
|
+
const keysFor = (env, vendor) => {
|
|
22
|
+
const keys = fleetKeys(env, vendor);
|
|
23
|
+
if (keys.length)
|
|
24
|
+
return keys;
|
|
25
|
+
const upper = vendor.toUpperCase();
|
|
26
|
+
throw new Error(`${vendor} needs ${upper}_API_KEY, or NUM_${upper} and ${upper}_API_KEY_1..N`);
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Keys come from the environment by vendor (`ANTHROPIC_API_KEY`, `GROQ_API_KEY_1`...); the
|
|
30
|
+
* gateway reads `WREN_LLM_GATEWAY_URL` and `WREN_LLM_GATEWAY_TOKEN`. `rotate` sets how a key ring
|
|
31
|
+
* waits when every key is busy.
|
|
32
|
+
*/
|
|
33
|
+
export function modelFromSpec(spec, env = process.env, o = {}) {
|
|
34
|
+
const at = spec.indexOf(":");
|
|
35
|
+
const name = at < 0 ? spec : spec.slice(0, at);
|
|
36
|
+
const rest = at < 0 ? undefined : spec.slice(at + 1) || undefined;
|
|
37
|
+
const vendor = (v) => ({
|
|
38
|
+
key: keysFor(env, v),
|
|
39
|
+
...(rest ? { model: rest } : {}),
|
|
40
|
+
...(o.rotate ? { rotate: o.rotate } : {}),
|
|
41
|
+
});
|
|
42
|
+
switch (name) {
|
|
43
|
+
case "fake":
|
|
44
|
+
return fakeModel();
|
|
45
|
+
case "command":
|
|
46
|
+
if (!rest)
|
|
47
|
+
throw new Error("command needs the command after `command:`");
|
|
48
|
+
return commandModel(rest);
|
|
49
|
+
case "claude-code":
|
|
50
|
+
return claudeCode(rest);
|
|
51
|
+
case "anthropic":
|
|
52
|
+
return anthropic(vendor("anthropic"));
|
|
53
|
+
case "gemini":
|
|
54
|
+
return gemini(vendor("gemini"));
|
|
55
|
+
case "cohere":
|
|
56
|
+
return cohere(vendor("cohere"));
|
|
57
|
+
case "gateway": {
|
|
58
|
+
const url = env.WREN_LLM_GATEWAY_URL;
|
|
59
|
+
const token = env.WREN_LLM_GATEWAY_TOKEN;
|
|
60
|
+
if (!url || !token)
|
|
61
|
+
throw new Error("gateway needs WREN_LLM_GATEWAY_URL and WREN_LLM_GATEWAY_TOKEN");
|
|
62
|
+
return gateway({ url, token, ...(rest ? { model: rest } : {}) });
|
|
63
|
+
}
|
|
64
|
+
default:
|
|
65
|
+
if (isCompatible(name))
|
|
66
|
+
return compatible(name, vendor(name));
|
|
67
|
+
throw new Error(`unknown model '${spec}'; expected one of ${SPEC_NAMES.join(", ")} [:model]`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=spec.js.map
|
package/dist/spec.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../src/spec.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one shape every model call has. A prompt is a string or a list of parts; a reply is text,
|
|
3
|
+
* tokens, USD and why it stopped. `ask` parses the reply to a zod shape. raven's and falcon's
|
|
4
|
+
* `Model` (`id` plus `ask(prompt, shape)`) are met by structure: a `Model` from here is one.
|
|
5
|
+
*/
|
|
6
|
+
import type { ZodType } from "zod";
|
|
7
|
+
/** What a part holds: bytes (base64 or raw) or a URL the vendor fetches itself. */
|
|
8
|
+
export type Source = Uint8Array | string | URL;
|
|
9
|
+
export type Part = {
|
|
10
|
+
type: "text";
|
|
11
|
+
text: string;
|
|
12
|
+
} | {
|
|
13
|
+
type: "image";
|
|
14
|
+
data: Source;
|
|
15
|
+
mediaType: string;
|
|
16
|
+
} | {
|
|
17
|
+
type: "video";
|
|
18
|
+
data: Source;
|
|
19
|
+
mediaType: string;
|
|
20
|
+
} | {
|
|
21
|
+
type: "audio";
|
|
22
|
+
data: Source;
|
|
23
|
+
mediaType: string;
|
|
24
|
+
} | {
|
|
25
|
+
type: "pdf";
|
|
26
|
+
data: Source;
|
|
27
|
+
};
|
|
28
|
+
export type PartKind = Part["type"];
|
|
29
|
+
/** How hard a model thinks. Anthropic and Gemini read it; others ignore it. */
|
|
30
|
+
export type Effort = "low" | "medium" | "high" | "xhigh" | "max";
|
|
31
|
+
export interface Request {
|
|
32
|
+
prompt: string | readonly Part[];
|
|
33
|
+
/** The standing instructions. On Anthropic it carries a cache breakpoint. */
|
|
34
|
+
system?: string;
|
|
35
|
+
/** A ceiling against a runaway answer, never the length: the prompt says how long. */
|
|
36
|
+
maxTokens?: number;
|
|
37
|
+
effort?: Effort;
|
|
38
|
+
/** What the call is for (`triage`, `drafts`). No vendor sees it; meters group by it. */
|
|
39
|
+
purpose?: string;
|
|
40
|
+
signal?: AbortSignal;
|
|
41
|
+
}
|
|
42
|
+
export interface Usage {
|
|
43
|
+
/** Every input token, cache reads and writes included. */
|
|
44
|
+
input?: number;
|
|
45
|
+
output?: number;
|
|
46
|
+
/** Of `input`: read from the vendor's prompt cache. */
|
|
47
|
+
cacheRead?: number;
|
|
48
|
+
/** Of `input`: written to the cache (5 minutes unless `cacheWrite1h` says). */
|
|
49
|
+
cacheWrite?: number;
|
|
50
|
+
/** Of `cacheWrite`: the share that lives 1 hour. */
|
|
51
|
+
cacheWrite1h?: number;
|
|
52
|
+
/** What the call cost. 0 on a free key; absent only when the model has no price. */
|
|
53
|
+
usd?: number;
|
|
54
|
+
/** The call ran on a free tier: `usd` is 0 and `listUsd` is what it would cost. */
|
|
55
|
+
free?: boolean;
|
|
56
|
+
listUsd?: number;
|
|
57
|
+
}
|
|
58
|
+
export interface Reply {
|
|
59
|
+
text: string;
|
|
60
|
+
usage: Usage;
|
|
61
|
+
/** The model that answered, as the vendor names it. */
|
|
62
|
+
model: string;
|
|
63
|
+
/** The vendor's own stop reason (`end_turn`, `max_tokens`, `STOP`, `length`). */
|
|
64
|
+
stop: string | undefined;
|
|
65
|
+
/** Wall-clock milliseconds for the round trip. */
|
|
66
|
+
ms: number;
|
|
67
|
+
/** The vendor's response metadata, kept for the caller to store. */
|
|
68
|
+
raw: Record<string, unknown>;
|
|
69
|
+
}
|
|
70
|
+
/** A parsed answer and what it cost. */
|
|
71
|
+
export interface Answer<T> {
|
|
72
|
+
value: T;
|
|
73
|
+
usage?: Usage;
|
|
74
|
+
}
|
|
75
|
+
export interface AskOptions extends Omit<Request, "prompt"> {
|
|
76
|
+
/** More calls after an answer that does not parse, each told why. Default 1. */
|
|
77
|
+
repairs?: number;
|
|
78
|
+
}
|
|
79
|
+
export interface Model {
|
|
80
|
+
/** The model id, as spends and records name it (`claude-haiku-5-5`, `groq:openai/gpt-oss-120b`). */
|
|
81
|
+
readonly id: string;
|
|
82
|
+
/** The vendor alone (`anthropic`, `groq`), for per-vendor sums. */
|
|
83
|
+
readonly provider: string;
|
|
84
|
+
/** The part kinds it takes. A part outside this set throws `Unsupported`, never dropped. */
|
|
85
|
+
readonly takes: ReadonlySet<PartKind>;
|
|
86
|
+
complete(request: Request | string): Promise<Reply>;
|
|
87
|
+
ask<T>(prompt: string | readonly Part[], shape: ZodType<T>, o?: AskOptions): Promise<Answer<T>>;
|
|
88
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,70 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrenautomation/models",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "One door to every model: a Model takes text, image, video, audio and PDF parts, answers with text, tokens and USD, and parses an answer to a zod shape. Adapters for Anthropic, Gemini, Cohere, any OpenAI-compatible server and a shell command (claude -p); ears for speech to text; one price table; one key ring.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/wrenautomation/models.git"
|
|
8
|
+
},
|
|
9
|
+
"license": "PolyForm-Shield-1.0.0",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"!dist/**/*.test.*",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE.md"
|
|
15
|
+
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./prices": {
|
|
26
|
+
"types": "./dist/prices.d.ts",
|
|
27
|
+
"import": "./dist/prices.js"
|
|
28
|
+
},
|
|
29
|
+
"./hear": {
|
|
30
|
+
"types": "./dist/hear.d.ts",
|
|
31
|
+
"import": "./dist/hear.js"
|
|
32
|
+
},
|
|
33
|
+
"./command": {
|
|
34
|
+
"types": "./dist/command.d.ts",
|
|
35
|
+
"import": "./dist/command.js"
|
|
36
|
+
},
|
|
37
|
+
"./spec": {
|
|
38
|
+
"types": "./dist/spec.d.ts",
|
|
39
|
+
"import": "./dist/spec.js"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"packageManager": "pnpm@9.15.0",
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=24"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"prepare": "git config core.hooksPath .githooks || true",
|
|
48
|
+
"lint": "biome check --error-on-warnings .",
|
|
49
|
+
"lint:fix": "biome check --write .",
|
|
50
|
+
"typecheck": "tsc --noEmit",
|
|
51
|
+
"build": "rm -rf dist && tsc",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"gates": "lockf -t 900 /tmp/wren_automation-checks.lock sh -c 'pnpm lint && pnpm typecheck && pnpm test'",
|
|
54
|
+
"prepublishOnly": "pnpm build"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@ai-sdk/anthropic": "4.0.90",
|
|
58
|
+
"@ai-sdk/cohere": "4.0.71",
|
|
59
|
+
"@ai-sdk/google": "4.0.107",
|
|
60
|
+
"@ai-sdk/openai-compatible": "3.0.80",
|
|
61
|
+
"ai": "7.0.155",
|
|
62
|
+
"zod": "4.6.5"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@biomejs/biome": "2.5.14",
|
|
66
|
+
"@types/node": "22.20.3",
|
|
67
|
+
"typescript": "5.9.3",
|
|
68
|
+
"vitest": "5.0.1"
|
|
69
|
+
}
|
|
70
|
+
}
|