@plurnk/plurnk-providers 1.18.0 → 1.19.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/.env.defaults +8 -4
- package/README.md +4 -16
- package/SPEC.md +41 -11
- package/dist/AiSdkProvider.d.ts +2 -4
- package/dist/AiSdkProvider.d.ts.map +1 -1
- package/dist/AiSdkProvider.js +7 -17
- package/dist/AiSdkProvider.js.map +1 -1
- package/dist/AiSdkRequestBody.d.ts +1 -4
- package/dist/AiSdkRequestBody.d.ts.map +1 -1
- package/dist/AiSdkRequestBody.js +10 -48
- package/dist/AiSdkRequestBody.js.map +1 -1
- package/dist/Mock.d.ts +2 -2
- package/dist/Mock.d.ts.map +1 -1
- package/dist/Mock.js +3 -3
- package/dist/Mock.js.map +1 -1
- package/dist/ProviderRegistry.js +2 -2
- package/dist/ProviderRegistry.js.map +1 -1
- package/dist/accounting.d.ts +0 -1
- package/dist/accounting.d.ts.map +1 -1
- package/dist/accounting.js +1 -7
- package/dist/accounting.js.map +1 -1
- package/dist/aiSdkTransport.d.ts.map +1 -1
- package/dist/aiSdkTransport.js +79 -7
- package/dist/aiSdkTransport.js.map +1 -1
- package/dist/catalogProvider.d.ts.map +1 -1
- package/dist/catalogProvider.js +13 -3
- package/dist/catalogProvider.js.map +1 -1
- package/dist/compatibleProvider.d.ts +1 -1
- package/dist/compatibleProvider.d.ts.map +1 -1
- package/dist/compatibleProvider.js +13 -25
- package/dist/compatibleProvider.js.map +1 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +1 -0
- package/dist/env.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +0 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/AiSdkProvider.test.ts +97 -126
- package/src/AiSdkProvider.ts +8 -22
- package/src/AiSdkRequestBody.ts +10 -42
- package/src/Mock.test.ts +11 -3
- package/src/Mock.ts +3 -3
- package/src/ProviderRegistry.test.ts +0 -1
- package/src/ProviderRegistry.ts +1 -1
- package/src/accounting.test.ts +0 -11
- package/src/accounting.ts +0 -8
- package/src/aiSdkTransport.test.ts +63 -1
- package/src/aiSdkTransport.ts +82 -7
- package/src/boundaries.test.ts +1 -1
- package/src/capacity.test.ts +2 -2
- package/src/catalogProvider.test.ts +46 -1
- package/src/catalogProvider.ts +12 -3
- package/src/compatibleProvider.test.ts +6 -6
- package/src/compatibleProvider.ts +13 -28
- package/src/cost.test.ts +3 -3
- package/src/discover.test.ts +11 -2
- package/src/env.test.ts +3 -0
- package/src/env.ts +2 -1
- package/src/errors.test.ts +2 -2
- package/src/index.ts +0 -1
- package/src/inputModalities.test.ts +2 -1
- package/src/sdkModels.test.ts +1 -1
- package/src/types.ts +8 -35
package/src/errors.test.ts
CHANGED
|
@@ -15,7 +15,7 @@ const apiError = (statusCode: number, responseBody = "body") => new APICallError
|
|
|
15
15
|
|
|
16
16
|
const SOURCE_PATTERN = /^[a-z]+(:[a-z][a-z0-9-]*)?$/;
|
|
17
17
|
|
|
18
|
-
test("HTTP request rejection preserves its cause without becoming a response-contract strike", () => {
|
|
18
|
+
test("{§provider-request-rejection} HTTP request rejection preserves its cause without becoming a response-contract strike", () => {
|
|
19
19
|
for (const status of [400, 404, 405, 422]) {
|
|
20
20
|
const message = "The requested model is not available on this endpoint.";
|
|
21
21
|
const cause = apiError(status, JSON.stringify({ error: { message } }));
|
|
@@ -54,7 +54,7 @@ test("classifyProviderError maps HTTP status to kind", () => {
|
|
|
54
54
|
assert.equal(k(404), "request_rejected");
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
test("capacity normalization prefers structured provider codes and keeps generic 400s distinct", () => {
|
|
57
|
+
test("{§provider-capacity-failure} capacity normalization prefers structured provider codes and keeps generic 400s distinct", () => {
|
|
58
58
|
const openai = apiError(400, JSON.stringify({
|
|
59
59
|
error: {
|
|
60
60
|
type: "invalid_request_error",
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ const parts: ChatMessage = {
|
|
|
16
16
|
{ type: "text", text: "look at this" },
|
|
17
17
|
{ type: "file", data: PNG, mediaType: "image/png" },
|
|
18
18
|
{ type: "file", data: PDF, mediaType: "application/pdf" },
|
|
19
|
+
{ type: "file", data: new Uint8Array([82, 73, 70, 70]), mediaType: "audio/wav" },
|
|
19
20
|
],
|
|
20
21
|
};
|
|
21
22
|
|
|
@@ -37,7 +38,7 @@ test("{§provider-input-modalities} the Mock declares modalities by option and r
|
|
|
37
38
|
const seeing = new Mock({ contextWindow: 200000, responses: [], inputModalities: ["image", "pdf"] });
|
|
38
39
|
assert.ok(seeing.inputModalities.has("image") && seeing.inputModalities.has("pdf") && !seeing.inputModalities.has("audio"));
|
|
39
40
|
assert.equal(tokensOf(await seeing.countPromptTokens([parts])), Math.ceil("look at this".length / 2));
|
|
40
|
-
await assert.rejects(seeing.generate({ messages: [parts], maxOutputTokens: 16, workerId: "1",
|
|
41
|
+
await assert.rejects(seeing.generate({ messages: [parts], maxOutputTokens: 16, workerId: "1", callKind: "bare" } as never));
|
|
41
42
|
assert.equal(seeing.received.length, 1, "the request was recorded before the empty queue refused it");
|
|
42
43
|
const received = seeing.received[0]?.[0]?.content;
|
|
43
44
|
assert.ok(Array.isArray(received) && received[1]?.type === "file" && received[1].mediaType === "image/png" && received[2]?.type === "file" && received[2].mediaType === "application/pdf");
|
package/src/sdkModels.test.ts
CHANGED
|
@@ -103,7 +103,7 @@ test("{§model-catalog-readiness}: an authenticated operator declaration reports
|
|
|
103
103
|
);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
test("createSdkModel uses Models.dev provider facts and operator credentials", () => {
|
|
106
|
+
test("{§provider-sdk-boundary} createSdkModel uses Models.dev provider facts and operator credentials", () => {
|
|
107
107
|
const sdk = createSdkModel("xai", "grok-build-0.1", { XAI_API_KEY: "test-key" });
|
|
108
108
|
assert.notEqual(sdk, null);
|
|
109
109
|
assert.equal(sdk?.catalog?.npm, "@ai-sdk/xai");
|
package/src/types.ts
CHANGED
|
@@ -230,16 +230,13 @@ export type ProviderAttempt = ProviderResponse<ProviderAttemptFinishReason>;
|
|
|
230
230
|
export interface ProviderGenerateArgs {
|
|
231
231
|
readonly messages: ChatMessage[];
|
|
232
232
|
readonly workerId: string;
|
|
233
|
-
readonly primaryWorkerId?: string;
|
|
234
233
|
readonly signal?: AbortSignal;
|
|
235
234
|
readonly grammar?: string;
|
|
236
235
|
readonly maxOutputTokens?: number;
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
236
|
+
// The workspace this call serves: ordinary call context for an adapter that
|
|
237
|
+
// fronts more than one workspace. It is never transported to a backend and
|
|
238
|
+
// never model-facing.
|
|
240
239
|
readonly workspaceId?: string;
|
|
241
|
-
readonly loop?: number;
|
|
242
|
-
readonly turn?: number;
|
|
243
240
|
readonly sampling?: Record<string, unknown>;
|
|
244
241
|
readonly observeRequest?: ProviderRequestObserver;
|
|
245
242
|
readonly observeReasoning?: ProviderReasoningObserver;
|
|
@@ -265,42 +262,18 @@ export interface Provider {
|
|
|
265
262
|
// its content. The consumer never sees or chooses backend resources
|
|
266
263
|
// (slot integers, connections); the mechanism is the provider's.
|
|
267
264
|
//
|
|
268
|
-
// `attributions` is opaque consumer-supplied creator telemetry; the consumer
|
|
269
|
-
// owns what contribution that set claims ({§attribution}). `client` is the
|
|
270
|
-
// consumer's workspace-stable, self-identified frontend. They are forwarded ONLY by a
|
|
271
|
-
// provider whose spec opts in (the first-party `plurnk` endpoint, via
|
|
272
|
-
// `Plurnk-Attribution` / `Plurnk-Client` headers); every other provider DROPS
|
|
273
|
-
// them — the gate is structural so first-party metadata can never leak to a
|
|
274
|
-
// third-party backend.
|
|
275
|
-
//
|
|
276
265
|
// `sampling` is an optional bag of standard OpenAI-compat sampling params
|
|
277
266
|
// (temperature, top_p, top_k, min_p, penalties, stop, seed, …) forwarded into
|
|
278
267
|
// the request body UNDER the provider's managed fields — model/messages/grammar/
|
|
279
268
|
// reasoning/max_tokens/slot always win, and transport/protocol keys (stream,
|
|
280
269
|
// response_format, grammar, id_slot) are stripped, so it carries sampling intent
|
|
281
270
|
// only and can't bypass grammar transport ({§provider-request-authority}). A
|
|
282
|
-
// proxy consumer
|
|
283
|
-
//
|
|
284
|
-
// knobs through; a direct consumer typically leaves it unset.
|
|
285
|
-
//
|
|
286
|
-
// `strikes` is the worker's CURRENT rail-strike streak at time-of-generate
|
|
287
|
-
// (0 = clean; a clean turn zeroes it; every loop starts at 0 — contract
|
|
288
|
-
// {§strikes-first-party-metadata}). Forwarded as a `Plurnk-Strikes` header ONLY under the
|
|
289
|
-
// same firstPartyMetadata gate as attributions/client; dropped everywhere
|
|
290
|
-
// else. Headers only — the packet NEVER carries strike state (the model must
|
|
291
|
-
// not see engine accounting; it would become a metric to game).
|
|
292
|
-
//
|
|
293
|
-
// `workspaceId`/`loop`/`turn` are the turn coordinate ({§lifecycle-terms}) — the
|
|
294
|
-
// daemon-side sequence of the turn being generated, which the endpoint can
|
|
295
|
-
// never scrape from the wire. Forwarded as `Plurnk-Workspace-Id`/`Plurnk-Loop`/
|
|
296
|
-
// `Plurnk-Turn` ONLY under the same firstPartyMetadata gate; dropped
|
|
297
|
-
// everywhere else. Coordinates are 1-based: absent/0 emits no header (no
|
|
298
|
-
// strikes-style zero exception). Headers only, never the packet.
|
|
271
|
+
// proxy consumer fronting its own backends uses it to pass its caller's
|
|
272
|
+
// sampling knobs through; a direct consumer typically leaves it unset.
|
|
299
273
|
//
|
|
300
|
-
// `callKind` is the caller's explicit output contract
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
// supplies `emission` or `bare`.
|
|
274
|
+
// `callKind` is the caller's explicit output contract, never inferred from
|
|
275
|
+
// the request shape. Generic callers may omit it; Core always supplies
|
|
276
|
+
// `emission` or `bare`.
|
|
304
277
|
generate(args: ProviderGenerateArgs): Promise<ProviderResponse>;
|
|
305
278
|
// {§model-fact-resolution} — effective total context envelope in tokens,
|
|
306
279
|
// including any stricter operator cap. `null` means unknown; under
|