modelpact 2.0.2

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.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +372 -0
  3. package/dist/helpers/abort.d.ts +14 -0
  4. package/dist/helpers/abort.d.ts.map +1 -0
  5. package/dist/helpers/abort.js +22 -0
  6. package/dist/helpers/abort.js.map +1 -0
  7. package/dist/helpers/lifetime.d.ts +34 -0
  8. package/dist/helpers/lifetime.d.ts.map +1 -0
  9. package/dist/helpers/lifetime.js +71 -0
  10. package/dist/helpers/lifetime.js.map +1 -0
  11. package/dist/helpers/monitor.d.ts +52 -0
  12. package/dist/helpers/monitor.d.ts.map +1 -0
  13. package/dist/helpers/monitor.js +69 -0
  14. package/dist/helpers/monitor.js.map +1 -0
  15. package/dist/helpers/ndjson.d.ts +19 -0
  16. package/dist/helpers/ndjson.d.ts.map +1 -0
  17. package/dist/helpers/ndjson.js +39 -0
  18. package/dist/helpers/ndjson.js.map +1 -0
  19. package/dist/helpers/overflow.d.ts +50 -0
  20. package/dist/helpers/overflow.d.ts.map +1 -0
  21. package/dist/helpers/overflow.js +72 -0
  22. package/dist/helpers/overflow.js.map +1 -0
  23. package/dist/helpers/transcript.d.ts +22 -0
  24. package/dist/helpers/transcript.d.ts.map +1 -0
  25. package/dist/helpers/transcript.js +26 -0
  26. package/dist/helpers/transcript.js.map +1 -0
  27. package/dist/index.d.ts +23 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +19 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/lifecycle/01_access.d.ts +13 -0
  32. package/dist/lifecycle/01_access.d.ts.map +1 -0
  33. package/dist/lifecycle/01_access.js +45 -0
  34. package/dist/lifecycle/01_access.js.map +1 -0
  35. package/dist/lifecycle/02_download.d.ts +8 -0
  36. package/dist/lifecycle/02_download.d.ts.map +1 -0
  37. package/dist/lifecycle/02_download.js +12 -0
  38. package/dist/lifecycle/02_download.js.map +1 -0
  39. package/dist/lifecycle/03_open.d.ts +22 -0
  40. package/dist/lifecycle/03_open.d.ts.map +1 -0
  41. package/dist/lifecycle/03_open.js +39 -0
  42. package/dist/lifecycle/03_open.js.map +1 -0
  43. package/dist/lifecycle/04_generate.d.ts +15 -0
  44. package/dist/lifecycle/04_generate.d.ts.map +1 -0
  45. package/dist/lifecycle/04_generate.js +154 -0
  46. package/dist/lifecycle/04_generate.js.map +1 -0
  47. package/dist/lifecycle/05_close.d.ts +4 -0
  48. package/dist/lifecycle/05_close.d.ts.map +1 -0
  49. package/dist/lifecycle/05_close.js +8 -0
  50. package/dist/lifecycle/05_close.js.map +1 -0
  51. package/dist/providers/create.d.ts +5 -0
  52. package/dist/providers/create.d.ts.map +1 -0
  53. package/dist/providers/create.js +7 -0
  54. package/dist/providers/create.js.map +1 -0
  55. package/dist/providers/mock.d.ts +36 -0
  56. package/dist/providers/mock.d.ts.map +1 -0
  57. package/dist/providers/mock.js +128 -0
  58. package/dist/providers/mock.js.map +1 -0
  59. package/dist/providers/ollama.d.ts +33 -0
  60. package/dist/providers/ollama.d.ts.map +1 -0
  61. package/dist/providers/ollama.js +275 -0
  62. package/dist/providers/ollama.js.map +1 -0
  63. package/dist/providers/prompt-api.d.ts +23 -0
  64. package/dist/providers/prompt-api.d.ts.map +1 -0
  65. package/dist/providers/prompt-api.js +203 -0
  66. package/dist/providers/prompt-api.js.map +1 -0
  67. package/dist/providers/registry.d.ts +22 -0
  68. package/dist/providers/registry.d.ts.map +1 -0
  69. package/dist/providers/registry.js +30 -0
  70. package/dist/providers/registry.js.map +1 -0
  71. package/dist/testing/contract.d.ts +47 -0
  72. package/dist/testing/contract.d.ts.map +1 -0
  73. package/dist/testing/contract.js +518 -0
  74. package/dist/testing/contract.js.map +1 -0
  75. package/dist/testing/index.d.ts +9 -0
  76. package/dist/testing/index.d.ts.map +1 -0
  77. package/dist/testing/index.js +9 -0
  78. package/dist/testing/index.js.map +1 -0
  79. package/dist/types/backend.d.ts +63 -0
  80. package/dist/types/backend.d.ts.map +1 -0
  81. package/dist/types/backend.js +11 -0
  82. package/dist/types/backend.js.map +1 -0
  83. package/dist/types/failures.d.ts +115 -0
  84. package/dist/types/failures.d.ts.map +1 -0
  85. package/dist/types/failures.js +68 -0
  86. package/dist/types/failures.js.map +1 -0
  87. package/dist/types/foundations.d.ts +35 -0
  88. package/dist/types/foundations.d.ts.map +1 -0
  89. package/dist/types/foundations.js +30 -0
  90. package/dist/types/foundations.js.map +1 -0
  91. package/dist/types/messages.d.ts +30 -0
  92. package/dist/types/messages.d.ts.map +1 -0
  93. package/dist/types/messages.js +2 -0
  94. package/dist/types/messages.js.map +1 -0
  95. package/dist/types/provider.d.ts +22 -0
  96. package/dist/types/provider.d.ts.map +1 -0
  97. package/dist/types/provider.js +2 -0
  98. package/dist/types/provider.js.map +1 -0
  99. package/dist/types/session.d.ts +156 -0
  100. package/dist/types/session.d.ts.map +1 -0
  101. package/dist/types/session.js +2 -0
  102. package/dist/types/session.js.map +1 -0
  103. package/dist/types/usage.d.ts +25 -0
  104. package/dist/types/usage.d.ts.map +1 -0
  105. package/dist/types/usage.js +16 -0
  106. package/dist/types/usage.js.map +1 -0
  107. package/package.json +85 -0
@@ -0,0 +1,518 @@
1
+ /**
2
+ * One set of assertions, run against every `AiProvider`.
3
+ *
4
+ * Written once and called for each backend, which sets a hard rule for what
5
+ * may be asserted here: only what `../types` promises. Anything about how a
6
+ * provider works inside — how many requests it made, what the prompt string
7
+ * looked like, which internal method ran first — differs between backends and
8
+ * would quietly turn this into a test of one of them.
9
+ *
10
+ * Published as `modelpact/testing`, so a backend written outside this package
11
+ * is held to the same standard as the ones inside it. `vitest` is a peer
12
+ * dependency: the file is `describe`/`test` calls, and two copies of the runner
13
+ * would register them in the wrong one.
14
+ *
15
+ * The filename carries no `.test` — the runner's glob is `src/**\/*.test.ts`
16
+ * and misses this file, which is a function others call rather than a suite of
17
+ * its own.
18
+ */
19
+ import { describe, expect, test } from "vitest";
20
+ import { jsonSchema } from "../types/foundations.js";
21
+ import { AiError } from "../types/failures.js";
22
+ /**
23
+ * A question whose answer is several words in any implementation. The suite
24
+ * asserts the answer arrives in more than one delta, which needs an answer long
25
+ * enough that no reasonable backend sends it whole.
26
+ */
27
+ const LONG_QUESTION = "List the numbers from one to ten, separated by commas.";
28
+ // A literal written on the next line: null here would be a typo in this file,
29
+ // not a case a provider can reach.
30
+ const asSchema = (value) => {
31
+ const schema = jsonSchema(value);
32
+ if (schema === null)
33
+ throw new Error("not a schema");
34
+ return schema;
35
+ };
36
+ /**
37
+ * The constraint the suite sends, and the shape a provider that honours one is
38
+ * measured against.
39
+ *
40
+ * Exported because a backend able to honour a schema has to be handed an answer
41
+ * that fits this exact one — a mock configures its reply against it. Kept to
42
+ * four keywords because the suite validates the answer itself: a general JSON
43
+ * Schema validator would be a dependency, and a second thing that can be wrong.
44
+ */
45
+ export const CONTRACT_SCHEMA = asSchema({
46
+ type: "object",
47
+ properties: { city: { type: "string" } },
48
+ required: ["city"],
49
+ additionalProperties: false,
50
+ });
51
+ /** Reader loop, not `for await`: async iteration of a stream is missing in Safari, and `lib` excludes it on purpose. */
52
+ async function drainStream(stream) {
53
+ const reader = stream.getReader();
54
+ const chunks = [];
55
+ for (;;) {
56
+ const { done, value } = await reader.read();
57
+ if (done)
58
+ return chunks;
59
+ chunks.push(value);
60
+ }
61
+ }
62
+ /** The `ready` branch or a failed test: every group below this line needs a session. */
63
+ async function mustOpenSession(access, options) {
64
+ if (access.kind !== "ready")
65
+ throw new Error(`expected ready, got ${access.kind}`);
66
+ const sessionResult = await access.open(options);
67
+ if (!sessionResult.ok)
68
+ throw new Error(`open refused: ${sessionResult.error.kind}`);
69
+ return sessionResult.value;
70
+ }
71
+ /** A signal that fires after the call has started, which is what "in flight" means here. */
72
+ const soonAbortedSignal = () => {
73
+ const controller = new AbortController();
74
+ setTimeout(() => controller.abort(), 0);
75
+ return controller.signal;
76
+ };
77
+ export function describeContract(name, makeProvider) {
78
+ /**
79
+ * A session for the scenario, or null once the test has been marked skipped.
80
+ *
81
+ * Null rather than a throw or a narrowing `skip`: the caller returns on it,
82
+ * which the compiler follows without a non-null assertion.
83
+ */
84
+ const stageSession = async (ctx, scenario) => {
85
+ const provider = await makeProvider(scenario);
86
+ if (provider === null) {
87
+ ctx.skip(`${scenario} cannot be staged`);
88
+ return null;
89
+ }
90
+ return mustOpenSession(await provider.access());
91
+ };
92
+ describe(`AiProvider contract: ${name}`, () => {
93
+ describe("access", () => {
94
+ test("resolves instead of throwing", async (ctx) => {
95
+ const provider = await makeProvider("ready");
96
+ if (provider === null)
97
+ return ctx.skip();
98
+ const access = await provider.access();
99
+ expect(["ready", "needs-download", "unavailable"]).toContain(access.kind);
100
+ });
101
+ test("unavailable carries a reason and no way to open", async (ctx) => {
102
+ const provider = await makeProvider("unavailable");
103
+ if (provider === null)
104
+ return ctx.skip();
105
+ const access = await provider.access();
106
+ expect(access.kind).toBe("unavailable");
107
+ if (access.kind !== "unavailable")
108
+ return;
109
+ expect(typeof access.reason.kind).toBe("string");
110
+ // The whole point of the union: there is nothing to call by mistake.
111
+ expect("open" in access).toBe(false);
112
+ });
113
+ test("the request is part of the question", async (ctx) => {
114
+ const provider = await makeProvider("ready");
115
+ if (provider === null)
116
+ return ctx.skip();
117
+ // A modality no text backend serves. Answering `ready` is allowed —
118
+ // the contract does not promise a refusal — but an answer there must
119
+ // be, and a refusal must name the vocabulary rather than throw.
120
+ const access = await provider.access({ outputs: [{ type: "audio" }] });
121
+ expect(["ready", "needs-download", "unavailable"]).toContain(access.kind);
122
+ if (access.kind === "unavailable") {
123
+ expect(typeof access.reason.kind).toBe("string");
124
+ }
125
+ });
126
+ test("needs-download reports progress, then opens", async (ctx) => {
127
+ const provider = await makeProvider("needs-download");
128
+ if (provider === null)
129
+ return ctx.skip();
130
+ const access = await provider.access();
131
+ expect(access.kind).toBe("needs-download");
132
+ if (access.kind !== "needs-download")
133
+ return;
134
+ const seenProgress = [];
135
+ const sessionResult = await access.open((monitor) => {
136
+ monitor.ondownloadprogress = (event) => seenProgress.push(event.loaded / event.total);
137
+ });
138
+ expect(seenProgress.length).toBeGreaterThan(0);
139
+ // Never decreasing, and finished: a bar that goes backwards or stops
140
+ // short is worse than no bar.
141
+ let previousProgress = 0;
142
+ for (const progress of seenProgress) {
143
+ expect(progress).toBeGreaterThanOrEqual(previousProgress);
144
+ previousProgress = progress;
145
+ }
146
+ expect(seenProgress.at(-1)).toBe(1);
147
+ expect(sessionResult.ok).toBe(true);
148
+ if (sessionResult.ok)
149
+ sessionResult.value.close();
150
+ });
151
+ });
152
+ describe("prompt", () => {
153
+ test("answers with text", async (ctx) => {
154
+ const session = await stageSession(ctx, "ready");
155
+ if (session === null)
156
+ return;
157
+ const answerResult = await session.prompt("Name the capital of France.");
158
+ expect(answerResult.ok).toBe(true);
159
+ if (answerResult.ok)
160
+ expect(answerResult.value.length).toBeGreaterThan(0);
161
+ session.close();
162
+ });
163
+ test("usage grows from one turn to the next", async (ctx) => {
164
+ const session = await stageSession(ctx, "ready");
165
+ if (session === null)
166
+ return;
167
+ const usageBefore = session.usage();
168
+ // A backend that reports no budget has nothing to compare.
169
+ if (usageBefore.kind === "unknown") {
170
+ session.close();
171
+ ctx.skip("usage is unknown for this backend");
172
+ }
173
+ await session.prompt("Name the capital of France.");
174
+ const usageAfter = session.usage();
175
+ if (usageAfter.kind !== "unknown" && usageBefore.kind !== "unknown") {
176
+ expect(usageAfter.used).toBeGreaterThan(usageBefore.used);
177
+ }
178
+ session.close();
179
+ });
180
+ });
181
+ describe("promptStream", () => {
182
+ test("delivers the answer in more than one delta", async (ctx) => {
183
+ const session = await stageSession(ctx, "ready");
184
+ if (session === null)
185
+ return;
186
+ const streamResult = await session.promptStream(LONG_QUESTION);
187
+ expect(streamResult.ok).toBe(true);
188
+ if (streamResult.ok)
189
+ expect((await drainStream(streamResult.value)).length).toBeGreaterThan(1);
190
+ session.close();
191
+ });
192
+ test("stays a stream: tee gives two readable branches", async (ctx) => {
193
+ const session = await stageSession(ctx, "ready");
194
+ if (session === null)
195
+ return;
196
+ const streamResult = await session.promptStream(LONG_QUESTION);
197
+ if (!streamResult.ok)
198
+ throw new AiError(streamResult.error);
199
+ const [leftBranch, rightBranch] = streamResult.value.tee();
200
+ const [leftChunks, rightChunks] = await Promise.all([
201
+ drainStream(leftBranch),
202
+ drainStream(rightBranch),
203
+ ]);
204
+ expect(leftChunks.join("")).toBe(rightChunks.join(""));
205
+ session.close();
206
+ });
207
+ });
208
+ describe("schema", () => {
209
+ test("a schema is honoured or refused, never ignored", async (ctx) => {
210
+ const session = await stageSession(ctx, "ready");
211
+ if (session === null)
212
+ return;
213
+ const answerResult = await session.prompt("Name the capital of France.", {
214
+ schema: CONTRACT_SCHEMA,
215
+ });
216
+ if (!answerResult.ok) {
217
+ // A refusal is the other half of the promise: a provider that cannot
218
+ // constrain decoding says so instead of answering prose.
219
+ expect(typeof answerResult.error.kind).toBe("string");
220
+ session.close();
221
+ return;
222
+ }
223
+ const parsedAnswer = JSON.parse(answerResult.value);
224
+ expect(typeof parsedAnswer).toBe("object");
225
+ expect(parsedAnswer).not.toBeNull();
226
+ expect(typeof parsedAnswer.city).toBe("string");
227
+ session.close();
228
+ });
229
+ });
230
+ describe("one at a time", () => {
231
+ test("a second generation is refused while the first runs", async (ctx) => {
232
+ const session = await stageSession(ctx, "ready");
233
+ if (session === null)
234
+ return;
235
+ const firstTurn = session.prompt(LONG_QUESTION);
236
+ const secondResult = await session.prompt("and again");
237
+ expect(secondResult.ok).toBe(false);
238
+ if (!secondResult.ok)
239
+ expect(secondResult.error.kind).toBe("busy");
240
+ await firstTurn;
241
+ session.close();
242
+ });
243
+ test("a stream in flight holds the session too", async (ctx) => {
244
+ const session = await stageSession(ctx, "ready");
245
+ if (session === null)
246
+ return;
247
+ const streamResult = await session.promptStream(LONG_QUESTION);
248
+ if (!streamResult.ok)
249
+ throw new AiError(streamResult.error);
250
+ const duringResult = await session.prompt("and again");
251
+ expect(duringResult.ok).toBe(false);
252
+ if (!duringResult.ok)
253
+ expect(duringResult.error.kind).toBe("busy");
254
+ await drainStream(streamResult.value);
255
+ session.close();
256
+ });
257
+ test("a finished stream frees the session", async (ctx) => {
258
+ const session = await stageSession(ctx, "ready");
259
+ if (session === null)
260
+ return;
261
+ const streamResult = await session.promptStream(LONG_QUESTION);
262
+ if (!streamResult.ok)
263
+ throw new AiError(streamResult.error);
264
+ await drainStream(streamResult.value);
265
+ // The turn is over, so the next one is allowed: `busy` is about a
266
+ // generation in flight, not about the session having been used.
267
+ const nextResult = await session.prompt("Name the capital of France.");
268
+ expect(nextResult.ok).toBe(true);
269
+ session.close();
270
+ });
271
+ });
272
+ describe("abort", () => {
273
+ test("an already-aborted signal fails the call, not the process", async (ctx) => {
274
+ const session = await stageSession(ctx, "ready");
275
+ if (session === null)
276
+ return;
277
+ const answerResult = await session.prompt("hello", {
278
+ signal: AbortSignal.abort(),
279
+ });
280
+ expect(answerResult.ok).toBe(false);
281
+ if (!answerResult.ok)
282
+ expect(answerResult.error.kind).toBe("aborted");
283
+ session.close();
284
+ });
285
+ test("aborting a prompt in flight fails it", async (ctx) => {
286
+ const session = await stageSession(ctx, "ready");
287
+ if (session === null)
288
+ return;
289
+ const answerResult = await session.prompt(LONG_QUESTION, {
290
+ signal: soonAbortedSignal(),
291
+ });
292
+ expect(answerResult.ok).toBe(false);
293
+ if (!answerResult.ok)
294
+ expect(answerResult.error.kind).toBe("aborted");
295
+ session.close();
296
+ });
297
+ test("aborting a stream in flight errors it", async (ctx) => {
298
+ const session = await stageSession(ctx, "ready");
299
+ if (session === null)
300
+ return;
301
+ const streamResult = await session.promptStream(LONG_QUESTION, {
302
+ signal: soonAbortedSignal(),
303
+ });
304
+ // Either the start is refused, or the stream errors partway: both are
305
+ // the same refusal, and which one arrives depends on timing the
306
+ // contract does not fix.
307
+ if (streamResult.ok)
308
+ await expect(drainStream(streamResult.value)).rejects.toThrow();
309
+ else
310
+ expect(streamResult.error.kind).toBe("aborted");
311
+ session.close();
312
+ });
313
+ test("an aborted generation does not end the session", async (ctx) => {
314
+ const session = await stageSession(ctx, "ready");
315
+ if (session === null)
316
+ return;
317
+ await session.prompt(LONG_QUESTION, { signal: soonAbortedSignal() });
318
+ const nextResult = await session.prompt("Name the capital of France.");
319
+ expect(nextResult.ok).toBe(true);
320
+ session.close();
321
+ });
322
+ test("cancelling the reader does not end the session either", async (ctx) => {
323
+ const session = await stageSession(ctx, "ready");
324
+ if (session === null)
325
+ return;
326
+ const streamResult = await session.promptStream(LONG_QUESTION);
327
+ if (!streamResult.ok)
328
+ throw new AiError(streamResult.error);
329
+ const reader = streamResult.value.getReader();
330
+ await reader.read();
331
+ await reader.cancel();
332
+ const nextResult = await session.prompt("Name the capital of France.");
333
+ expect(nextResult.ok).toBe(true);
334
+ session.close();
335
+ });
336
+ });
337
+ describe("contextoverflow", () => {
338
+ test("fires when a turn spends more than the window holds", async (ctx) => {
339
+ const session = await stageSession(ctx, "tiny-window");
340
+ if (session === null)
341
+ return;
342
+ let fired = 0;
343
+ session.oncontextoverflow = () => (fired += 1);
344
+ await session.prompt(LONG_QUESTION);
345
+ await session.prompt(LONG_QUESTION);
346
+ expect(fired).toBeGreaterThan(0);
347
+ // Once: the window does not un-overflow, and every turn after the
348
+ // first is over the same line.
349
+ expect(fired).toBe(1);
350
+ session.close();
351
+ });
352
+ test("stays quiet while the transcript fits", async (ctx) => {
353
+ const session = await stageSession(ctx, "ready");
354
+ if (session === null)
355
+ return;
356
+ let fired = 0;
357
+ session.oncontextoverflow = () => (fired += 1);
358
+ await session.prompt("hi");
359
+ expect(fired).toBe(0);
360
+ session.close();
361
+ });
362
+ test("the handler unsubscribes when set back to null", async (ctx) => {
363
+ const session = await stageSession(ctx, "tiny-window");
364
+ if (session === null)
365
+ return;
366
+ let fired = 0;
367
+ session.oncontextoverflow = () => (fired += 1);
368
+ session.oncontextoverflow = null;
369
+ await session.prompt(LONG_QUESTION);
370
+ await session.prompt(LONG_QUESTION);
371
+ expect(fired).toBe(0);
372
+ session.close();
373
+ });
374
+ });
375
+ describe("history", () => {
376
+ const HANDED_HISTORY = [
377
+ { role: "user", content: "Name the capital of France." },
378
+ { role: "assistant", content: "Paris." },
379
+ ];
380
+ test("starts as what was handed at open", async (ctx) => {
381
+ const provider = await makeProvider("ready");
382
+ if (provider === null)
383
+ return ctx.skip();
384
+ const session = await mustOpenSession(await provider.access(), {
385
+ history: HANDED_HISTORY,
386
+ });
387
+ expect(session.history()).toEqual(HANDED_HISTORY);
388
+ session.close();
389
+ });
390
+ test("a completed prompt adds the question and the answer", async (ctx) => {
391
+ const session = await stageSession(ctx, "ready");
392
+ if (session === null)
393
+ return;
394
+ const answerResult = await session.prompt("Name the capital of France.");
395
+ if (!answerResult.ok)
396
+ throw new AiError(answerResult.error);
397
+ expect(session.history()).toEqual([
398
+ { role: "user", content: "Name the capital of France." },
399
+ { role: "assistant", content: answerResult.value },
400
+ ]);
401
+ session.close();
402
+ });
403
+ test("a drained stream adds the answer as one message", async (ctx) => {
404
+ const session = await stageSession(ctx, "ready");
405
+ if (session === null)
406
+ return;
407
+ const streamResult = await session.promptStream(LONG_QUESTION);
408
+ if (!streamResult.ok)
409
+ throw new AiError(streamResult.error);
410
+ const deltas = await drainStream(streamResult.value);
411
+ expect(session.history().at(-1)).toEqual({
412
+ role: "assistant",
413
+ content: deltas.join(""),
414
+ });
415
+ session.close();
416
+ });
417
+ test("only turns that returned ok are in it", async (ctx) => {
418
+ const session = await stageSession(ctx, "ready");
419
+ if (session === null)
420
+ return;
421
+ const answerResult = await session.prompt(LONG_QUESTION, {
422
+ signal: soonAbortedSignal(),
423
+ });
424
+ // The record and the Result agree by construction: a turn that was
425
+ // refused or interrupted is in neither.
426
+ expect(session.history()).toHaveLength(answerResult.ok ? 2 : 0);
427
+ session.close();
428
+ });
429
+ test("a cancelled stream adds nothing", async (ctx) => {
430
+ const session = await stageSession(ctx, "ready");
431
+ if (session === null)
432
+ return;
433
+ const streamResult = await session.promptStream(LONG_QUESTION);
434
+ if (!streamResult.ok)
435
+ throw new AiError(streamResult.error);
436
+ const reader = streamResult.value.getReader();
437
+ await reader.read();
438
+ await reader.cancel();
439
+ expect(session.history()).toEqual([]);
440
+ session.close();
441
+ });
442
+ test("what was read does not change under later turns", async (ctx) => {
443
+ const session = await stageSession(ctx, "ready");
444
+ if (session === null)
445
+ return;
446
+ const historyBefore = session.history();
447
+ await session.prompt("Name the capital of France.");
448
+ expect(historyBefore).toEqual([]);
449
+ session.close();
450
+ });
451
+ test("handed back to open, it continues the same conversation", async (ctx) => {
452
+ const provider = await makeProvider("ready");
453
+ if (provider === null)
454
+ return ctx.skip();
455
+ const firstSession = await mustOpenSession(await provider.access());
456
+ await firstSession.prompt("Name the capital of France.");
457
+ const savedHistory = firstSession.history();
458
+ firstSession.close();
459
+ // A reload: the session is gone, the record is not.
460
+ const reopenedSession = await mustOpenSession(await provider.access(), {
461
+ history: savedHistory,
462
+ });
463
+ expect(reopenedSession.history()).toEqual(savedHistory);
464
+ reopenedSession.close();
465
+ });
466
+ });
467
+ describe("close", () => {
468
+ test("later calls fail with aborted", async (ctx) => {
469
+ const session = await stageSession(ctx, "ready");
470
+ if (session === null)
471
+ return;
472
+ session.close();
473
+ const answerResult = await session.prompt("hello");
474
+ expect(answerResult.ok).toBe(false);
475
+ if (!answerResult.ok)
476
+ expect(answerResult.error.kind).toBe("aborted");
477
+ });
478
+ test("a call in flight fails too", async (ctx) => {
479
+ const session = await stageSession(ctx, "ready");
480
+ if (session === null)
481
+ return;
482
+ const flightTurn = session.prompt(LONG_QUESTION);
483
+ session.close();
484
+ const answerResult = await flightTurn;
485
+ expect(answerResult.ok).toBe(false);
486
+ if (!answerResult.ok)
487
+ expect(answerResult.error.kind).toBe("aborted");
488
+ });
489
+ test("a stream in flight errors", async (ctx) => {
490
+ const session = await stageSession(ctx, "ready");
491
+ if (session === null)
492
+ return;
493
+ const streamResult = await session.promptStream(LONG_QUESTION);
494
+ if (!streamResult.ok)
495
+ throw new AiError(streamResult.error);
496
+ session.close();
497
+ await expect(drainStream(streamResult.value)).rejects.toThrow();
498
+ });
499
+ test("closing twice is a no-op", async (ctx) => {
500
+ const session = await stageSession(ctx, "ready");
501
+ if (session === null)
502
+ return;
503
+ session.close();
504
+ expect(() => session.close()).not.toThrow();
505
+ });
506
+ test("usage still answers", async (ctx) => {
507
+ const session = await stageSession(ctx, "ready");
508
+ if (session === null)
509
+ return;
510
+ session.close();
511
+ // Reading the meter is not generating: a closed session still knows
512
+ // what it spent, which is what a caller shows after an abort.
513
+ expect(typeof session.usage().kind).toBe("string");
514
+ });
515
+ });
516
+ });
517
+ }
518
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/testing/contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `modelpact/testing`: the contract suite, run against any `AiProvider`.
3
+ *
4
+ * A separate entry because it calls `describe` and `test`, and `vitest` is an
5
+ * optional peer dependency — an app that only consumes a provider never loads
6
+ * this.
7
+ */
8
+ export { CONTRACT_SCHEMA, describeContract, type ContractScenario, type ProviderFactory, } from "./contract.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `modelpact/testing`: the contract suite, run against any `AiProvider`.
3
+ *
4
+ * A separate entry because it calls `describe` and `test`, and `vitest` is an
5
+ * optional peer dependency — an app that only consumes a provider never loads
6
+ * this.
7
+ */
8
+ export { CONTRACT_SCHEMA, describeContract, } from "./contract.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,eAAe,EACf,gBAAgB,GAGjB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * What a backend supplies; `../lifecycle` turns it into an `AiProvider`.
3
+ *
4
+ * The contract's runtime guarantees — one generation at a time, an abort that
5
+ * leaves the session open, a close that refuses everything after it, an
6
+ * overflow that fires once — are implemented once, in `../lifecycle/01_access.ts`
7
+ * through `05_close.ts`. A backend never sees them: it says what the model is
8
+ * and how to talk to it, and the order of calls is the lifecycle's business.
9
+ */
10
+ import type { Fraction, JsonSchema, Result } from "./foundations.js";
11
+ import type { AiFailure } from "./failures.js";
12
+ import type { AiMessage, Modality, ModelRequest } from "./messages.js";
13
+ import type { ProviderName } from "./provider.js";
14
+ import type { SessionOptions } from "./session.js";
15
+ import type { ContextUsage } from "./usage.js";
16
+ /** `ModelAccess` without `open`; the lifecycle attaches that. */
17
+ export type Availability = {
18
+ readonly kind: "unavailable";
19
+ readonly reason: AiFailure;
20
+ } | {
21
+ readonly kind: "ready";
22
+ } | {
23
+ readonly kind: "needs-download";
24
+ readonly started: boolean;
25
+ };
26
+ export interface ConnectOptions {
27
+ /** The request `access` was asked with; the Prompt API wants it again as `expectedInputs`. */
28
+ readonly request: ModelRequest;
29
+ readonly session: SessionOptions;
30
+ /** Already subscribed to when `connect` runs; a no-op on the `ready` branch. */
31
+ readonly reportProgress: (progress: Fraction) => void;
32
+ /** For a backend that hears its own overflow event. Idempotent. */
33
+ readonly reportOverflow: () => void;
34
+ }
35
+ export interface GenerateRequest {
36
+ /** The session's lifetime linked with the call's own; pass it on wherever the backend can be interrupted. */
37
+ readonly signal: AbortSignal;
38
+ readonly schema?: JsonSchema;
39
+ /**
40
+ * Every completed turn before this one, starting from what `connect` was
41
+ * handed; `input` is not in it. A backend that keeps its own record, as the
42
+ * Prompt API does, ignores this — a stateless one sends it whole.
43
+ */
44
+ readonly history: readonly AiMessage[];
45
+ }
46
+ /** One open connection to a model. Busy, abort and usage are checked around these calls, not inside them. */
47
+ export interface ModelConnection {
48
+ readonly generateStream: (input: string, request: GenerateRequest) => Promise<Result<ReadableStream<string>, AiFailure>>;
49
+ /** Absent, `prompt` drains `generateStream`; present for a backend with a cheaper whole-answer call. */
50
+ readonly generateWhole?: (input: string, request: GenerateRequest) => Promise<Result<string, AiFailure>>;
51
+ readonly usage: () => ContextUsage;
52
+ /** Called once, from `close`. */
53
+ readonly dispose: () => void;
54
+ }
55
+ export interface ModelBackend {
56
+ readonly name: ProviderName;
57
+ /** What the model can be asked for; a request outside it is refused before `availability` runs. */
58
+ readonly modalities: readonly Modality[];
59
+ readonly availability: (request: ModelRequest) => Availability | Promise<Availability>;
60
+ /** Downloads if it must, reporting through `reportProgress`, then connects. */
61
+ readonly connect: (options: ConnectOptions) => Promise<Result<ModelConnection, AiFailure>>;
62
+ }
63
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/types/backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,iEAAiE;AACjE,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnE,MAAM,WAAW,cAAc;IAC7B,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,gFAAgF;IAChF,QAAQ,CAAC,cAAc,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtD,mEAAmE;IACnE,QAAQ,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,eAAe;IAC9B,6GAA6G;IAC7G,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;CACxC;AAED,6GAA6G;AAC7G,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,cAAc,EAAE,CACvB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,eAAe,KACrB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;IACxD,wGAAwG;IACxG,QAAQ,CAAC,aAAa,CAAC,EAAE,CACvB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,eAAe,KACrB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,YAAY,CAAC;IACnC,iCAAiC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,mGAAmG;IACnG,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzC,QAAQ,CAAC,YAAY,EAAE,CACrB,OAAO,EAAE,YAAY,KAClB,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1C,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,CAChB,OAAO,EAAE,cAAc,KACpB,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,CAAC;CAClD"}