@plurnk/plurnk-providers 0.1.4 → 0.1.7
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 +2 -0
- package/SPEC.md +20 -3
- package/dist/OpenAICompat.d.ts +1 -0
- package/dist/OpenAICompat.d.ts.map +1 -1
- package/dist/OpenAICompat.js +15 -1
- package/dist/OpenAICompat.js.map +1 -1
- package/dist/env.js +4 -4
- package/dist/env.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/standardProviders.d.ts +2 -1
- package/dist/standardProviders.d.ts.map +1 -1
- package/dist/standardProviders.js +38 -5
- package/dist/standardProviders.js.map +1 -1
- package/dist/telemetry.d.ts +24 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +58 -0
- package/dist/telemetry.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,8 @@ Framework + contract for `@plurnk/plurnk-providers-*` sibling packages (LLM tran
|
|
|
14
14
|
- `OpenAICompatProvider` (+ `OpenAICompatConfig`, `ReasoningStyle`, `effortFromBudget`) — shared OpenAI-compatible transport spine; siblings extend it (SPEC §11).
|
|
15
15
|
- `chatCompletionStream`, `OpenAiHttpError`, `StreamResponse` — the shared SSE client.
|
|
16
16
|
- `parseRequiredInt`, `parseOptionalInt`, `requireEnv` — env helpers.
|
|
17
|
+
- `normalizeUsage`, `computeCost` (+ `RawUsage`, `TokenRates`) — usage normalization to the §2 invariant and the single cost formula (SPEC §11).
|
|
18
|
+
- `ProviderError`, `classifyProviderError`, `toProviderError`, `providerSource` (+ `TelemetryEvent`, `ProviderTelemetryKind`) — the TelemetryEvent envelope for transport failures (SPEC §12).
|
|
17
19
|
- `tokenizerFor`, `tokenizerByPublisher`, `parseTokenizerFamily` (+ `TokenizerFamily`, `CountTokens`) — synchronous tokenizer strategies.
|
|
18
20
|
- `STANDARD_PROVIDERS`, `isStandardProvider`, `standardProviderFromEnv` — pure-config OpenAI-compatible providers (no sibling package needed).
|
|
19
21
|
- `Mock` — reference implementation + test fixture (dual-purpose).
|
package/SPEC.md
CHANGED
|
@@ -38,7 +38,7 @@ interface ProviderResponse {
|
|
|
38
38
|
assistant: {
|
|
39
39
|
content: string; // raw model emission; consumer parses
|
|
40
40
|
reasoning: string | null; // wire-reported CoT; null if absent
|
|
41
|
-
usage: ProviderUsage; // { prompt, completion, cached, total }
|
|
41
|
+
usage: ProviderUsage; // { prompt, completion, reasoning, cached, total }
|
|
42
42
|
finishReason: "stop" | "length" | "tool_calls" | "content_filter" | null;
|
|
43
43
|
model: string; // wire-reported (may differ from requested for relay providers)
|
|
44
44
|
};
|
|
@@ -181,7 +181,7 @@ A sibling package satisfies the contract when:
|
|
|
181
181
|
2. Instance exposes `contextSize: number | null` and `model: string` (non-empty).
|
|
182
182
|
3. Instance exposes `countTokens(text): number` and `costFor(usage): number`.
|
|
183
183
|
4. `countTokens("")` returns `0`; `countTokens("…")` returns a non-negative integer.
|
|
184
|
-
5. `costFor({prompt:0,completion:0,cached:0,total:0})` returns `0` (or non-negative pico-USD for non-free models).
|
|
184
|
+
5. `costFor({prompt:0,completion:0,reasoning:0,cached:0,total:0})` returns `0` (or non-negative pico-USD for non-free models).
|
|
185
185
|
6. Identity getters return stable values across reads.
|
|
186
186
|
7. `generate` resolves with a valid `ProviderResponse` shape.
|
|
187
187
|
8. `generate` invoked with a pre-aborted `signal` rejects without making a wire call.
|
|
@@ -215,4 +215,21 @@ The framework ships the transport spine every OpenAI-compatible provider had bee
|
|
|
215
215
|
- **`tokenizerFor(family)` / `tokenizerByPublisher(model, table, index)` / `parseTokenizerFamily(...)`** — synchronous tokenizer strategies (`heuristic` | `cl100k` | `llama`) and per-publisher dispatch for relay providers.
|
|
216
216
|
- **`effortFromBudget(budget)`** — the shared `PLURNK_REASON` → `low|medium|high` breakpoints.
|
|
217
217
|
|
|
218
|
-
A **bespoke sibling** therefore reduces to a thin class whose `fromEnv` probes whatever it needs (model catalog, pricing, context window), builds the config, and returns `new OpenAICompatProvider(config)`. A **standard provider** (§5 tier 1) needs no sibling at all — it's a frozen entry in `STANDARD_PROVIDERS` describing its key var, base URL, reasoning style, and tokenizer; `standardProviderFromEnv` does the rest.
|
|
218
|
+
A **bespoke sibling** therefore reduces to a thin class whose `fromEnv` probes whatever it needs (model catalog, pricing, context window), builds the config, and returns `new OpenAICompatProvider(config)`. A **standard provider** (§5 tier 1) needs no sibling at all — it's a frozen entry in `STANDARD_PROVIDERS` describing its key var, base URL, reasoning style, and tokenizer; `standardProviderFromEnv(name, env, model)` (async — returns `Promise<Provider | null>`) does the rest.
|
|
219
|
+
|
|
220
|
+
`contextSize` for a standard provider resolves: `PLURNK_PROVIDER_CONTEXT_SIZE` → endpoint `n_ctx` (for `probeNctx`-flagged specs like `openai`, queried from `GET /v1/models` — llama-server/vLLM report their loaded window there; cloud endpoints don't, yielding `null`) → `null`. The probe is best-effort: any failure resolves to `null` (a legitimate "context unknown"), never throws.
|
|
221
|
+
|
|
222
|
+
## §12 Telemetry — provider failures
|
|
223
|
+
|
|
224
|
+
Transport failures surface as a `ProviderError` (extends `Error`, so existing catchers keep working) that carries the plurnk **TelemetryEvent** envelope via `toTelemetryEvent()`:
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
{ source: "provider:<vendor>", kind: ProviderTelemetryKind, message: string, position: null }
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
- `source` is `provider:<vendor>` (schema pattern `^[a-z]+(:[a-z][a-z0-9-]*)?$`); standard providers set it from their name, siblings via the `source` config field (default `"provider"`).
|
|
231
|
+
- `kind` ∈ `rate_limit | network_failure | model_refused | invalid_response | unauthorized | quota_exceeded`. HTTP status maps: 401/403→`unauthorized`, 402→`quota_exceeded`, 429→`rate_limit`, ≥500→`network_failure`, other 4xx→`invalid_response`; timeouts/fetch errors→`network_failure`. (`model_refused` is response-level — minted consumer-side from a `content_filter` finish reason, not from a thrown error.)
|
|
232
|
+
- `message` is terse and factual (no guidance prose); `position` is `null` (provider failures aren't localizable into prior content).
|
|
233
|
+
- **Caller-initiated abort is NOT telemetry** — an aborted `signal` rethrows the original abort, never a `ProviderError`.
|
|
234
|
+
|
|
235
|
+
The `TelemetryEvent` shape is mirrored **locally** (`./telemetry.ts`), structurally matching `@plurnk/plurnk-grammar`'s `TelemetryEvent.json`, so the framework keeps zero grammar dependency (§11). Consumers route provider events through the same `source`+`kind` discriminator as parse/rail events.
|
package/dist/OpenAICompat.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export type OpenAICompatConfig = {
|
|
|
10
10
|
reasoningStyle?: ReasoningStyle;
|
|
11
11
|
countTokens?: (text: string) => number;
|
|
12
12
|
costFor?: (usage: ProviderUsage) => number;
|
|
13
|
+
source?: string;
|
|
13
14
|
};
|
|
14
15
|
export declare const effortFromBudget: (budget: number) => "low" | "medium" | "high";
|
|
15
16
|
export default class OpenAICompatProvider implements Provider {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenAICompat.d.ts","sourceRoot":"","sources":["../src/OpenAICompat.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAgB,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"OpenAICompat.d.ts","sourceRoot":"","sources":["../src/OpenAICompat.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAgB,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAUvG,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,mBAAmB,GAAG,QAAQ,CAAC;AAE/E,MAAM,MAAM,kBAAkB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,MAAM,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AASF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,KAAK,GAAG,QAAQ,GAAG,MAIpE,CAAC;AAIF,MAAM,CAAC,OAAO,OAAO,oBAAqB,YAAW,QAAQ;;gBAY7C,MAAM,EAAE,kBAAkB;IAatC,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAA8B;IAC9D,IAAI,KAAK,IAAI,MAAM,CAAwB;IAE3C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IACjC,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM;IAY/B,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE;QAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA8BrH"}
|
package/dist/OpenAICompat.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// Pure-config providers come from ./standardProviders.ts with no sibling at all.
|
|
10
10
|
import { chatCompletionStream } from "./openaiStream.js";
|
|
11
11
|
import { normalizeUsage } from "./usage.js";
|
|
12
|
+
import { toProviderError } from "./telemetry.js";
|
|
12
13
|
// SPEC §2 closed set. Wire values outside it (provider-specific or absent)
|
|
13
14
|
// collapse to null — the consumer treats null as "no signal".
|
|
14
15
|
const FINISH_REASONS = new Set(["stop", "length", "tool_calls", "content_filter"]);
|
|
@@ -32,6 +33,7 @@ export default class OpenAICompatProvider {
|
|
|
32
33
|
#reasoningStyle;
|
|
33
34
|
#countTokens;
|
|
34
35
|
#costFor;
|
|
36
|
+
#source;
|
|
35
37
|
constructor(config) {
|
|
36
38
|
this.#model = config.model;
|
|
37
39
|
this.#url = config.url;
|
|
@@ -42,6 +44,7 @@ export default class OpenAICompatProvider {
|
|
|
42
44
|
this.#reasoningStyle = config.reasoningStyle ?? "none";
|
|
43
45
|
this.#countTokens = config.countTokens ?? heuristicTokens;
|
|
44
46
|
this.#costFor = config.costFor ?? (() => 0);
|
|
47
|
+
this.#source = config.source ?? "provider";
|
|
45
48
|
}
|
|
46
49
|
get contextSize() { return this.#contextSize; }
|
|
47
50
|
get model() { return this.#model; }
|
|
@@ -63,7 +66,18 @@ export default class OpenAICompatProvider {
|
|
|
63
66
|
const timeoutSignal = AbortSignal.timeout(this.#fetchTimeoutMs);
|
|
64
67
|
const effectiveSignal = signal !== undefined ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
65
68
|
const body = { model: this.#model, messages, ...this.#reasoningBody() };
|
|
66
|
-
|
|
69
|
+
let raw;
|
|
70
|
+
try {
|
|
71
|
+
raw = await chatCompletionStream({ url: this.#url, headers: this.#headers, body, signal: effectiveSignal });
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
// Caller-initiated abort is cancellation, not a telemetry-worthy
|
|
75
|
+
// provider failure — rethrow as-is. Everything else (HTTP error,
|
|
76
|
+
// timeout, network) becomes a classified ProviderError.
|
|
77
|
+
if (signal?.aborted)
|
|
78
|
+
throw err;
|
|
79
|
+
throw toProviderError(err, this.#source);
|
|
80
|
+
}
|
|
67
81
|
return {
|
|
68
82
|
assistant: {
|
|
69
83
|
content: raw.content,
|
package/dist/OpenAICompat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenAICompat.js","sourceRoot":"","sources":["../src/OpenAICompat.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,oEAAoE;AACpE,wEAAwE;AACxE,EAAE;AACF,4EAA4E;AAC5E,2EAA2E;AAC3E,0EAA0E;AAC1E,8EAA8E;AAC9E,iFAAiF;AAGjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"OpenAICompat.js","sourceRoot":"","sources":["../src/OpenAICompat.ts"],"names":[],"mappings":"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"}
|
package/dist/env.js
CHANGED
|
@@ -5,16 +5,16 @@ export const parseRequiredInt = (raw, name, label) => {
|
|
|
5
5
|
if (raw === undefined || raw.length === 0)
|
|
6
6
|
throw new Error(`${label} provider: ${name} must be set`);
|
|
7
7
|
const n = Number(raw);
|
|
8
|
-
if (!Number.
|
|
9
|
-
throw new Error(`${label} provider: ${name} must be a
|
|
8
|
+
if (!Number.isInteger(n) || n < 0)
|
|
9
|
+
throw new Error(`${label} provider: ${name} must be a non-negative integer (got "${raw}")`);
|
|
10
10
|
return n;
|
|
11
11
|
};
|
|
12
12
|
export const parseOptionalInt = (raw, name, label) => {
|
|
13
13
|
if (raw === undefined || raw.length === 0)
|
|
14
14
|
return null;
|
|
15
15
|
const n = Number(raw);
|
|
16
|
-
if (!Number.
|
|
17
|
-
throw new Error(`${label} provider: ${name} must be a
|
|
16
|
+
if (!Number.isInteger(n) || n < 0)
|
|
17
|
+
throw new Error(`${label} provider: ${name} must be a non-negative integer (got "${raw}")`);
|
|
18
18
|
return n;
|
|
19
19
|
};
|
|
20
20
|
export const requireEnv = (raw, name, label) => {
|
package/dist/env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,4EAA4E;AAC5E,8EAA8E;AAE9E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAuB,EAAE,IAAY,EAAE,KAAa,EAAU,EAAE;IAC7F,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,cAAc,IAAI,cAAc,CAAC,CAAC;IACrG,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,4EAA4E;AAC5E,8EAA8E;AAE9E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAuB,EAAE,IAAY,EAAE,KAAa,EAAU,EAAE;IAC7F,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,cAAc,IAAI,cAAc,CAAC,CAAC;IACrG,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,cAAc,IAAI,yCAAyC,GAAG,IAAI,CAAC,CAAC;IAC/H,OAAO,CAAC,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAuB,EAAE,IAAY,EAAE,KAAa,EAAiB,EAAE;IACpG,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,cAAc,IAAI,yCAAyC,GAAG,IAAI,CAAC,CAAC;IAC/H,OAAO,CAAC,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAuB,EAAE,IAAY,EAAE,KAAa,EAAU,EAAE;IACvF,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,cAAc,IAAI,cAAc,CAAC,CAAC;IACrG,OAAO,GAAG,CAAC;AACf,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export { tokenizerFor, tokenizerByPublisher, parseTokenizerFamily } from "./toke
|
|
|
9
9
|
export type { TokenizerFamily, CountTokens } from "./tokenizers.ts";
|
|
10
10
|
export { normalizeUsage, computeCost } from "./usage.ts";
|
|
11
11
|
export type { RawUsage, TokenRates } from "./usage.ts";
|
|
12
|
+
export { ProviderError, classifyProviderError, toProviderError, providerSource } from "./telemetry.ts";
|
|
13
|
+
export type { TelemetryEvent, ProviderTelemetryKind } from "./telemetry.ts";
|
|
12
14
|
export { STANDARD_PROVIDERS, isStandardProvider, standardProviderFromEnv } from "./standardProviders.ts";
|
|
13
15
|
export { default as Mock } from "./Mock.ts";
|
|
14
16
|
export type { MockAssistant, MockResponse, MockReturnedAssistant } from "./Mock.ts";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACR,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,aAAa,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACH,mBAAmB,EACnB,kBAAkB,GACrB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACtF,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC1E,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC3F,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzD,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEzG,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACR,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,aAAa,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACH,mBAAmB,EACnB,kBAAkB,GACrB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACtF,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC1E,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC3F,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzD,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACvG,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEzG,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export { chatCompletionStream, OpenAiHttpError } from "./openaiStream.js";
|
|
|
6
6
|
export { parseRequiredInt, parseOptionalInt, requireEnv } from "./env.js";
|
|
7
7
|
export { tokenizerFor, tokenizerByPublisher, parseTokenizerFamily } from "./tokenizers.js";
|
|
8
8
|
export { normalizeUsage, computeCost } from "./usage.js";
|
|
9
|
+
export { ProviderError, classifyProviderError, toProviderError, providerSource } from "./telemetry.js";
|
|
9
10
|
export { STANDARD_PROVIDERS, isStandardProvider, standardProviderFromEnv } from "./standardProviders.js";
|
|
10
11
|
export { default as Mock } from "./Mock.js";
|
|
11
12
|
export { mockDefaultUsage } from "./Mock.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACH,mBAAmB,EACnB,kBAAkB,GACrB,MAAM,uBAAuB,CAAC;AAE/B,yEAAyE;AACzE,oDAAoD;AACpD,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEtF,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE1E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAE3F,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEzG,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACH,mBAAmB,EACnB,kBAAkB,GACrB,MAAM,uBAAuB,CAAC;AAE/B,yEAAyE;AACzE,oDAAoD;AACpD,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEtF,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE1E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAE3F,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEvG,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEzG,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -11,9 +11,10 @@ type StandardProviderSpec = {
|
|
|
11
11
|
reasoningStyle: ReasoningStyle;
|
|
12
12
|
tokenizerDefault: TokenizerFamily;
|
|
13
13
|
tokenizerEnvVar: string;
|
|
14
|
+
probeNctx?: boolean;
|
|
14
15
|
};
|
|
15
16
|
export declare const STANDARD_PROVIDERS: Readonly<Record<string, StandardProviderSpec>>;
|
|
16
17
|
export declare const isStandardProvider: (name: string) => boolean;
|
|
17
|
-
export declare const standardProviderFromEnv: (name: string, env: NodeJS.ProcessEnv, model: string) => Provider | null
|
|
18
|
+
export declare const standardProviderFromEnv: (name: string, env: NodeJS.ProcessEnv, model: string) => Promise<Provider | null>;
|
|
18
19
|
export {};
|
|
19
20
|
//# sourceMappingURL=standardProviders.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standardProviders.d.ts","sourceRoot":"","sources":["../src/standardProviders.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAA6B,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE9E,OAAO,EAAsC,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"standardProviders.d.ts","sourceRoot":"","sources":["../src/standardProviders.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAA6B,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE9E,OAAO,EAAsC,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAG3F,KAAK,oBAAoB,GAAG;IAGxB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IAGxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,QAAQ,EAAE,MAAM,CAAC;IAIjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,eAAe,CAAC;IAClC,eAAe,EAAE,MAAM,CAAC;IAKxB,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAGF,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAwC5E,CAAC;AAEH,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,OAAqC,CAAC;AAoCxF,eAAO,MAAM,uBAAuB,GAAU,MAAM,MAAM,EAAE,KAAK,MAAM,CAAC,UAAU,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAgC1H,CAAC"}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import OpenAICompatProvider from "./OpenAICompat.js";
|
|
11
11
|
import { parseRequiredInt, parseOptionalInt, requireEnv } from "./env.js";
|
|
12
12
|
import { parseTokenizerFamily, tokenizerFor } from "./tokenizers.js";
|
|
13
|
+
import { providerSource } from "./telemetry.js";
|
|
13
14
|
// Frozen so a downstream can't mutate the shared table.
|
|
14
15
|
export const STANDARD_PROVIDERS = Object.freeze({
|
|
15
16
|
// Generic OpenAI-compatible endpoint (OpenAI proper, llama-server, vLLM,
|
|
@@ -19,6 +20,7 @@ export const STANDARD_PROVIDERS = Object.freeze({
|
|
|
19
20
|
apiKeyVar: "OPENAI_API_KEY", apiKeyRequired: false,
|
|
20
21
|
baseUrlVar: "OPENAI_BASE_URL", chatPath: "/v1/chat/completions", flexBaseStrip: true,
|
|
21
22
|
reasoningStyle: "think", tokenizerDefault: "heuristic", tokenizerEnvVar: "OPENAI_TOKENIZER",
|
|
23
|
+
probeNctx: true,
|
|
22
24
|
},
|
|
23
25
|
groq: {
|
|
24
26
|
apiKeyVar: "GROQ_API_KEY", apiKeyRequired: true,
|
|
@@ -61,9 +63,32 @@ const resolveUrl = (spec, env, label) => {
|
|
|
61
63
|
const trimmed = spec.flexBaseStrip === true ? base.replace(/\/v1\/?$/, "") : base.replace(/\/$/, "");
|
|
62
64
|
return `${trimmed}${spec.chatPath}`;
|
|
63
65
|
};
|
|
66
|
+
// Context-window resolution: PLURNK_PROVIDER_CONTEXT_SIZE → endpoint n_ctx
|
|
67
|
+
// (probe, opt-in per spec) → null. llama-server / vLLM report the loaded window
|
|
68
|
+
// as `n_ctx` on GET /v1/models; cloud endpoints don't, so the probe yields null
|
|
69
|
+
// there. Best-effort: any failure (unreachable, no field, non-2xx) → null,
|
|
70
|
+
// which is a legitimate "context unknown", not a swallowed contract violation.
|
|
71
|
+
const probeNctx = async (chatUrl, headers, model, fetchTimeoutMs) => {
|
|
72
|
+
const modelsUrl = chatUrl.replace(/\/chat\/completions$/, "/models");
|
|
73
|
+
try {
|
|
74
|
+
const res = await fetch(modelsUrl, { headers, signal: AbortSignal.timeout(fetchTimeoutMs) });
|
|
75
|
+
if (!res.ok)
|
|
76
|
+
return null;
|
|
77
|
+
// llama-server nests the window under `meta`; vLLM reports it top-level.
|
|
78
|
+
const data = (await res.json());
|
|
79
|
+
const rows = data.data ?? [];
|
|
80
|
+
const row = rows.find((r) => r.id === model) ?? rows[0];
|
|
81
|
+
const n = row?.meta?.n_ctx ?? row?.n_ctx;
|
|
82
|
+
return typeof n === "number" && n > 0 ? n : null;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
64
88
|
// Returns a configured Provider, or null when `name` is not a standard
|
|
65
|
-
// provider (so the consumer falls through to dynamic import).
|
|
66
|
-
|
|
89
|
+
// provider (so the consumer falls through to dynamic import). Async because a
|
|
90
|
+
// probeNctx-enabled provider queries /v1/models at construction.
|
|
91
|
+
export const standardProviderFromEnv = async (name, env, model) => {
|
|
67
92
|
const spec = STANDARD_PROVIDERS[name];
|
|
68
93
|
if (spec === undefined)
|
|
69
94
|
return null;
|
|
@@ -74,15 +99,23 @@ export const standardProviderFromEnv = (name, env, model) => {
|
|
|
74
99
|
if (apiKey.length > 0)
|
|
75
100
|
headers.Authorization = `Bearer ${apiKey}`;
|
|
76
101
|
const family = parseTokenizerFamily(env[spec.tokenizerEnvVar], spec.tokenizerDefault, spec.tokenizerEnvVar, name);
|
|
102
|
+
const url = resolveUrl(spec, env, name);
|
|
103
|
+
const fetchTimeoutMs = parseRequiredInt(env.PLURNK_FETCH_TIMEOUT, "PLURNK_FETCH_TIMEOUT", name);
|
|
104
|
+
// Explicit env wins; otherwise probe the endpoint when the spec opts in.
|
|
105
|
+
let contextSize = parseOptionalInt(env.PLURNK_PROVIDER_CONTEXT_SIZE, "PLURNK_PROVIDER_CONTEXT_SIZE", name);
|
|
106
|
+
if (contextSize === null && spec.probeNctx === true) {
|
|
107
|
+
contextSize = await probeNctx(url, headers, model, fetchTimeoutMs);
|
|
108
|
+
}
|
|
77
109
|
return new OpenAICompatProvider({
|
|
78
110
|
model,
|
|
79
|
-
url
|
|
111
|
+
url,
|
|
80
112
|
headers,
|
|
81
|
-
contextSize
|
|
82
|
-
fetchTimeoutMs
|
|
113
|
+
contextSize,
|
|
114
|
+
fetchTimeoutMs,
|
|
83
115
|
reasonBudget: parseRequiredInt(env.PLURNK_REASON, "PLURNK_REASON", name),
|
|
84
116
|
reasoningStyle: spec.reasoningStyle,
|
|
85
117
|
countTokens: tokenizerFor(family),
|
|
118
|
+
source: providerSource(name),
|
|
86
119
|
});
|
|
87
120
|
};
|
|
88
121
|
//# sourceMappingURL=standardProviders.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standardProviders.js","sourceRoot":"","sources":["../src/standardProviders.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,8EAA8E;AAC9E,2EAA2E;AAC3E,8EAA8E;AAC9E,6DAA6D;AAC7D,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,2EAA2E;AAG3E,OAAO,oBAA6C,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAwB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"standardProviders.js","sourceRoot":"","sources":["../src/standardProviders.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type TelemetryEvent = {
|
|
2
|
+
source: string;
|
|
3
|
+
kind: string;
|
|
4
|
+
message?: string | null;
|
|
5
|
+
position?: null;
|
|
6
|
+
};
|
|
7
|
+
export type ProviderTelemetryKind = "rate_limit" | "network_failure" | "model_refused" | "invalid_response" | "unauthorized" | "quota_exceeded";
|
|
8
|
+
export declare const providerSource: (vendor: string) => string;
|
|
9
|
+
export declare class ProviderError extends Error {
|
|
10
|
+
readonly source: string;
|
|
11
|
+
readonly kind: ProviderTelemetryKind;
|
|
12
|
+
readonly status: number | null;
|
|
13
|
+
constructor(source: string, kind: ProviderTelemetryKind, message: string, options?: {
|
|
14
|
+
status?: number | null;
|
|
15
|
+
cause?: unknown;
|
|
16
|
+
});
|
|
17
|
+
toTelemetryEvent(): TelemetryEvent;
|
|
18
|
+
}
|
|
19
|
+
export declare const classifyProviderError: (err: unknown) => {
|
|
20
|
+
kind: ProviderTelemetryKind;
|
|
21
|
+
message: string;
|
|
22
|
+
};
|
|
23
|
+
export declare const toProviderError: (err: unknown, source: string) => ProviderError;
|
|
24
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,cAAc,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,IAAI,CAAC;CACnB,CAAC;AAGF,MAAM,MAAM,qBAAqB,GAC3B,YAAY,GACZ,iBAAiB,GACjB,eAAe,GACf,kBAAkB,GAClB,cAAc,GACd,gBAAgB,CAAC;AAGvB,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,KAAG,MAA8B,CAAC;AAK/E,qBAAa,aAAc,SAAQ,KAAK;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;gBAEnB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;IAQnI,gBAAgB,IAAI,cAAc;CAGrC;AAID,eAAO,MAAM,qBAAqB,GAAI,KAAK,OAAO,KAAG;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAalG,CAAC;AAIF,eAAO,MAAM,eAAe,GAAI,KAAK,OAAO,EAAE,QAAQ,MAAM,KAAG,aAK9D,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Provider telemetry — the TelemetryEvent envelope for transport failures.
|
|
2
|
+
//
|
|
3
|
+
// TelemetryEvent is plurnk's cross-ecosystem error envelope (canonical schema:
|
|
4
|
+
// @plurnk/plurnk-grammar's schemas.plurnk.dev/v0/TelemetryEvent.json). It is
|
|
5
|
+
// mirrored here STRUCTURALLY rather than imported, so the framework keeps zero
|
|
6
|
+
// dependency on grammar (see SPEC §11). Consumers route provider events through
|
|
7
|
+
// the same `source` + `kind` discriminator as parse/rail events.
|
|
8
|
+
import { OpenAiHttpError } from "./openaiStream.js";
|
|
9
|
+
// Build a provider source label (`provider:<vendor>`), schema-pattern-valid.
|
|
10
|
+
export const providerSource = (vendor) => `provider:${vendor}`;
|
|
11
|
+
// A transport failure carrying its TelemetryEvent classification. IS-an Error
|
|
12
|
+
// (existing catchers keep working); telemetry-aware consumers call
|
|
13
|
+
// toTelemetryEvent() and route on source+kind.
|
|
14
|
+
export class ProviderError extends Error {
|
|
15
|
+
source;
|
|
16
|
+
kind;
|
|
17
|
+
status;
|
|
18
|
+
constructor(source, kind, message, options = {}) {
|
|
19
|
+
super(message, options.cause !== undefined ? { cause: options.cause } : undefined);
|
|
20
|
+
this.name = "ProviderError";
|
|
21
|
+
this.source = source;
|
|
22
|
+
this.kind = kind;
|
|
23
|
+
this.status = options.status ?? null;
|
|
24
|
+
}
|
|
25
|
+
toTelemetryEvent() {
|
|
26
|
+
return { source: this.source, kind: this.kind, message: this.message, position: null };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Map a thrown transport error to a (kind, message). Conservative; the message
|
|
30
|
+
// is factual, no guidance prose (consumer SPEC §15.1 policy).
|
|
31
|
+
export const classifyProviderError = (err) => {
|
|
32
|
+
if (err instanceof OpenAiHttpError) {
|
|
33
|
+
const { status, message } = err;
|
|
34
|
+
if (status === 401 || status === 403)
|
|
35
|
+
return { kind: "unauthorized", message };
|
|
36
|
+
if (status === 402)
|
|
37
|
+
return { kind: "quota_exceeded", message };
|
|
38
|
+
if (status === 429)
|
|
39
|
+
return { kind: "rate_limit", message };
|
|
40
|
+
if (status >= 500)
|
|
41
|
+
return { kind: "network_failure", message };
|
|
42
|
+
return { kind: "invalid_response", message };
|
|
43
|
+
}
|
|
44
|
+
const e = err;
|
|
45
|
+
const message = (e?.message ?? String(err)) || "request failed";
|
|
46
|
+
// Timeouts / fetch-level failures are transport, not a usable response.
|
|
47
|
+
return { kind: "network_failure", message };
|
|
48
|
+
};
|
|
49
|
+
// Wrap any thrown error as a ProviderError tagged with this provider's source.
|
|
50
|
+
// Already-classified errors pass through unchanged.
|
|
51
|
+
export const toProviderError = (err, source) => {
|
|
52
|
+
if (err instanceof ProviderError)
|
|
53
|
+
return err;
|
|
54
|
+
const { kind, message } = classifyProviderError(err);
|
|
55
|
+
const status = err instanceof OpenAiHttpError ? err.status : null;
|
|
56
|
+
return new ProviderError(source, kind, message, { status, cause: err });
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|