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.
- package/LICENSE +21 -0
- package/README.md +372 -0
- package/dist/helpers/abort.d.ts +14 -0
- package/dist/helpers/abort.d.ts.map +1 -0
- package/dist/helpers/abort.js +22 -0
- package/dist/helpers/abort.js.map +1 -0
- package/dist/helpers/lifetime.d.ts +34 -0
- package/dist/helpers/lifetime.d.ts.map +1 -0
- package/dist/helpers/lifetime.js +71 -0
- package/dist/helpers/lifetime.js.map +1 -0
- package/dist/helpers/monitor.d.ts +52 -0
- package/dist/helpers/monitor.d.ts.map +1 -0
- package/dist/helpers/monitor.js +69 -0
- package/dist/helpers/monitor.js.map +1 -0
- package/dist/helpers/ndjson.d.ts +19 -0
- package/dist/helpers/ndjson.d.ts.map +1 -0
- package/dist/helpers/ndjson.js +39 -0
- package/dist/helpers/ndjson.js.map +1 -0
- package/dist/helpers/overflow.d.ts +50 -0
- package/dist/helpers/overflow.d.ts.map +1 -0
- package/dist/helpers/overflow.js +72 -0
- package/dist/helpers/overflow.js.map +1 -0
- package/dist/helpers/transcript.d.ts +22 -0
- package/dist/helpers/transcript.d.ts.map +1 -0
- package/dist/helpers/transcript.js +26 -0
- package/dist/helpers/transcript.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle/01_access.d.ts +13 -0
- package/dist/lifecycle/01_access.d.ts.map +1 -0
- package/dist/lifecycle/01_access.js +45 -0
- package/dist/lifecycle/01_access.js.map +1 -0
- package/dist/lifecycle/02_download.d.ts +8 -0
- package/dist/lifecycle/02_download.d.ts.map +1 -0
- package/dist/lifecycle/02_download.js +12 -0
- package/dist/lifecycle/02_download.js.map +1 -0
- package/dist/lifecycle/03_open.d.ts +22 -0
- package/dist/lifecycle/03_open.d.ts.map +1 -0
- package/dist/lifecycle/03_open.js +39 -0
- package/dist/lifecycle/03_open.js.map +1 -0
- package/dist/lifecycle/04_generate.d.ts +15 -0
- package/dist/lifecycle/04_generate.d.ts.map +1 -0
- package/dist/lifecycle/04_generate.js +154 -0
- package/dist/lifecycle/04_generate.js.map +1 -0
- package/dist/lifecycle/05_close.d.ts +4 -0
- package/dist/lifecycle/05_close.d.ts.map +1 -0
- package/dist/lifecycle/05_close.js +8 -0
- package/dist/lifecycle/05_close.js.map +1 -0
- package/dist/providers/create.d.ts +5 -0
- package/dist/providers/create.d.ts.map +1 -0
- package/dist/providers/create.js +7 -0
- package/dist/providers/create.js.map +1 -0
- package/dist/providers/mock.d.ts +36 -0
- package/dist/providers/mock.d.ts.map +1 -0
- package/dist/providers/mock.js +128 -0
- package/dist/providers/mock.js.map +1 -0
- package/dist/providers/ollama.d.ts +33 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +275 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/prompt-api.d.ts +23 -0
- package/dist/providers/prompt-api.d.ts.map +1 -0
- package/dist/providers/prompt-api.js +203 -0
- package/dist/providers/prompt-api.js.map +1 -0
- package/dist/providers/registry.d.ts +22 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +30 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/testing/contract.d.ts +47 -0
- package/dist/testing/contract.d.ts.map +1 -0
- package/dist/testing/contract.js +518 -0
- package/dist/testing/contract.js.map +1 -0
- package/dist/testing/index.d.ts +9 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +9 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types/backend.d.ts +63 -0
- package/dist/types/backend.d.ts.map +1 -0
- package/dist/types/backend.js +11 -0
- package/dist/types/backend.js.map +1 -0
- package/dist/types/failures.d.ts +115 -0
- package/dist/types/failures.d.ts.map +1 -0
- package/dist/types/failures.js +68 -0
- package/dist/types/failures.js.map +1 -0
- package/dist/types/foundations.d.ts +35 -0
- package/dist/types/foundations.d.ts.map +1 -0
- package/dist/types/foundations.js +30 -0
- package/dist/types/foundations.js.map +1 -0
- package/dist/types/messages.d.ts +30 -0
- package/dist/types/messages.d.ts.map +1 -0
- package/dist/types/messages.js +2 -0
- package/dist/types/messages.js.map +1 -0
- package/dist/types/provider.d.ts +22 -0
- package/dist/types/provider.d.ts.map +1 -0
- package/dist/types/provider.js +2 -0
- package/dist/types/provider.js.map +1 -0
- package/dist/types/session.d.ts +156 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +2 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/usage.d.ts +25 -0
- package/dist/types/usage.d.ts.map +1 -0
- package/dist/types/usage.js +16 -0
- package/dist/types/usage.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Download progress as the platform reports it: an `EventTarget` that fires
|
|
3
|
+
* `downloadprogress`.
|
|
4
|
+
*
|
|
5
|
+
* The Prompt API hands `create()` a `CreateMonitor` and fires a `ProgressEvent`
|
|
6
|
+
* on it. This is the same object for a provider with no browser behind it, and
|
|
7
|
+
* both satisfy `DownloadMonitor` from `../types/session.ts` —
|
|
8
|
+
* `src/types.test-d.ts` checks the ambient declaration against it.
|
|
9
|
+
*
|
|
10
|
+
* `ProgressEvent` is not a global in Node 22 — `typeof ProgressEvent` is
|
|
11
|
+
* `"undefined"` there, while `Event`, `EventTarget` and `CustomEvent` are
|
|
12
|
+
* present — and the vitest suites run in the node environment. So the event is
|
|
13
|
+
* a subclass of `Event` carrying the three `ProgressEvent` fields, which is
|
|
14
|
+
* what a listener reads. `CustomEvent` was the alternative and puts the numbers
|
|
15
|
+
* behind `detail`, where a listener written against the spec would not look.
|
|
16
|
+
*/
|
|
17
|
+
export const DOWNLOAD_PROGRESS = "downloadprogress";
|
|
18
|
+
/**
|
|
19
|
+
* `total` is 1 and `loaded` is the ratio. MDN names the normalization on
|
|
20
|
+
* `ProgressEvent` itself ("if using 1 as a total, then loaded would be a
|
|
21
|
+
* decimal value between 0 and 1"), and it settles the one thing the Prompt API
|
|
22
|
+
* docs disagree about: `e.loaded / e.total` and a bare `e.loaded` are the same
|
|
23
|
+
* number here.
|
|
24
|
+
*/
|
|
25
|
+
export class DownloadProgressEvent extends Event {
|
|
26
|
+
loaded;
|
|
27
|
+
lengthComputable = true;
|
|
28
|
+
total = 1;
|
|
29
|
+
constructor(loaded) {
|
|
30
|
+
super(DOWNLOAD_PROGRESS);
|
|
31
|
+
this.loaded = loaded;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Our `CreateMonitor`. `report` is not part of `DownloadMonitor`, so a caller
|
|
36
|
+
* holding the contract type can listen but cannot invent progress —
|
|
37
|
+
* `src/types.test-d.ts` checks that it cannot.
|
|
38
|
+
*/
|
|
39
|
+
export class ProgressMonitor extends EventTarget {
|
|
40
|
+
#handler = null;
|
|
41
|
+
#loaded = null;
|
|
42
|
+
/**
|
|
43
|
+
* An `onevent` property is not free with `EventTarget`: only interfaces the
|
|
44
|
+
* platform defines have one, and it is a listener registration behind an
|
|
45
|
+
* accessor — assigning twice replaces, assigning null unsubscribes. Here it
|
|
46
|
+
* also carries the event's type, which `addEventListener` cannot: see the
|
|
47
|
+
* note on `DownloadMonitor`.
|
|
48
|
+
*/
|
|
49
|
+
get ondownloadprogress() {
|
|
50
|
+
return this.#handler;
|
|
51
|
+
}
|
|
52
|
+
set ondownloadprogress(handler) {
|
|
53
|
+
if (this.#handler !== null) {
|
|
54
|
+
this.removeEventListener(DOWNLOAD_PROGRESS, this.#handler);
|
|
55
|
+
}
|
|
56
|
+
this.#handler = handler;
|
|
57
|
+
if (handler !== null) {
|
|
58
|
+
this.addEventListener(DOWNLOAD_PROGRESS, handler);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Dropped rather than dispatched when it does not move forward — the contract's non-decreasing guarantee. */
|
|
62
|
+
report(loaded) {
|
|
63
|
+
if (this.#loaded !== null && loaded <= this.#loaded)
|
|
64
|
+
return;
|
|
65
|
+
this.#loaded = loaded;
|
|
66
|
+
this.dispatchEvent(new DownloadProgressEvent(loaded));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../src/helpers/monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAIzB;IAHZ,gBAAgB,GAAG,IAAI,CAAC;IACxB,KAAK,GAAG,CAAC,CAAC;IAEnB,YAAqB,MAAgB;QACnC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QADN,WAAM,GAAN,MAAM,CAAU;IAErC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,GAA4C,IAAI,CAAC;IACzD,OAAO,GAAoB,IAAI,CAAC;IAEhC;;;;;;OAMG;IACH,IAAI,kBAAkB;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,IAAI,kBAAkB,CAAC,OAAgD;QACrE,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,mBAAmB,CACtB,iBAAiB,EACjB,IAAI,CAAC,QAAyB,CAC/B,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,OAAwB,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,8GAA8G;IAC9G,MAAM,CAAC,MAAgB;QACrB,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QAC5D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `TransformStream` that cuts decoded text into NDJSON lines.
|
|
3
|
+
*
|
|
4
|
+
* Network chunks and protocol lines are unrelated cuts of the same bytes. A
|
|
5
|
+
* chunk is whatever arrived in one TCP read: it can hold six frames, or the
|
|
6
|
+
* first half of one, and the boundary can fall inside a multi-byte character —
|
|
7
|
+
* which is `TextDecoderStream`'s job upstream, not this one's. Feeding chunks
|
|
8
|
+
* to `JSON.parse` therefore fails on the first delta long enough to be split.
|
|
9
|
+
*
|
|
10
|
+
* A stage rather than a `let buffer` in the reader loop, for three things a
|
|
11
|
+
* variable cannot do: `flush` runs at end-of-stream, so a body that stops
|
|
12
|
+
* without a trailing newline still yields its last line; the stage takes part
|
|
13
|
+
* in backpressure, since the readable side of a `TransformStream` has
|
|
14
|
+
* `highWaterMark` 0 and stops pulling while the consumer is behind; and
|
|
15
|
+
* cancelling anywhere in a `pipeThrough` chain tears down the whole chain,
|
|
16
|
+
* buffer included.
|
|
17
|
+
*/
|
|
18
|
+
export declare function ndjsonLines(): TransformStream<string, string>;
|
|
19
|
+
//# sourceMappingURL=ndjson.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ndjson.d.ts","sourceRoot":"","sources":["../../src/helpers/ndjson.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,IAAI,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAkB7D"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `TransformStream` that cuts decoded text into NDJSON lines.
|
|
3
|
+
*
|
|
4
|
+
* Network chunks and protocol lines are unrelated cuts of the same bytes. A
|
|
5
|
+
* chunk is whatever arrived in one TCP read: it can hold six frames, or the
|
|
6
|
+
* first half of one, and the boundary can fall inside a multi-byte character —
|
|
7
|
+
* which is `TextDecoderStream`'s job upstream, not this one's. Feeding chunks
|
|
8
|
+
* to `JSON.parse` therefore fails on the first delta long enough to be split.
|
|
9
|
+
*
|
|
10
|
+
* A stage rather than a `let buffer` in the reader loop, for three things a
|
|
11
|
+
* variable cannot do: `flush` runs at end-of-stream, so a body that stops
|
|
12
|
+
* without a trailing newline still yields its last line; the stage takes part
|
|
13
|
+
* in backpressure, since the readable side of a `TransformStream` has
|
|
14
|
+
* `highWaterMark` 0 and stops pulling while the consumer is behind; and
|
|
15
|
+
* cancelling anywhere in a `pipeThrough` chain tears down the whole chain,
|
|
16
|
+
* buffer included.
|
|
17
|
+
*/
|
|
18
|
+
export function ndjsonLines() {
|
|
19
|
+
let tail = "";
|
|
20
|
+
return new TransformStream({
|
|
21
|
+
transform(chunk, controller) {
|
|
22
|
+
const lines = (tail + chunk).split("\n");
|
|
23
|
+
// `split` always yields at least one element, and the last is what comes
|
|
24
|
+
// before the next newline — "" when the chunk ended on one.
|
|
25
|
+
tail = lines.pop() ?? "";
|
|
26
|
+
for (const line of lines) {
|
|
27
|
+
// Blank lines are legal NDJSON padding. `\r` is not stripped: it is
|
|
28
|
+
// JSON whitespace, so `JSON.parse` takes a CRLF line as it stands.
|
|
29
|
+
if (line.trim() !== "")
|
|
30
|
+
controller.enqueue(line);
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
flush(controller) {
|
|
34
|
+
if (tail.trim() !== "")
|
|
35
|
+
controller.enqueue(tail);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=ndjson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ndjson.js","sourceRoot":"","sources":["../../src/helpers/ndjson.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,OAAO,IAAI,eAAe,CAAC;QACzB,SAAS,CAAC,KAAK,EAAE,UAAU;YACzB,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,yEAAyE;YACzE,4DAA4D;YAC5D,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,oEAAoE;gBACpE,mEAAmE;gBACnE,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;oBAAE,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QACD,KAAK,CAAC,UAAU;YACd,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `contextoverflow` event, carried for every provider by one object.
|
|
3
|
+
*
|
|
4
|
+
* Shared for the reason `turn.ts` is shared: the contract suite would watch
|
|
5
|
+
* each provider fire and never notice that they fire on different arithmetic.
|
|
6
|
+
* The rule lives here — a session that has spent more of the window than the
|
|
7
|
+
* window holds — and nothing but this file decides it.
|
|
8
|
+
*
|
|
9
|
+
* A session is not an `EventTarget` by construction: a provider builds one as
|
|
10
|
+
* an object of closures. So the closures are assigned onto an instance of
|
|
11
|
+
* this class, the way `ProgressMonitor` carries `downloadprogress`.
|
|
12
|
+
*/
|
|
13
|
+
import type { AiSession } from "../types/session.js";
|
|
14
|
+
import type { ContextUsage } from "../types/usage.js";
|
|
15
|
+
export declare const CONTEXT_OVERFLOW = "contextoverflow";
|
|
16
|
+
export declare class ContextEvents extends EventTarget {
|
|
17
|
+
#private;
|
|
18
|
+
/**
|
|
19
|
+
* As on `DownloadMonitor`: an `onevent` property is not free with
|
|
20
|
+
* `EventTarget`, and it is the only registration that carries the event's
|
|
21
|
+
* type — `addEventListener` on a subclass takes a bare `EventListener`.
|
|
22
|
+
*/
|
|
23
|
+
get oncontextoverflow(): ((event: Event) => void) | null;
|
|
24
|
+
set oncontextoverflow(handler: ((event: Event) => void) | null);
|
|
25
|
+
/**
|
|
26
|
+
* Called with what the session now holds, after a turn has been charged.
|
|
27
|
+
*
|
|
28
|
+
* Fires at most once. The window does not un-overflow: the backend has
|
|
29
|
+
* already dropped the oldest turns to make the last one fit, and every turn
|
|
30
|
+
* after it is over the same line. A listener wants to hear that the conversation
|
|
31
|
+
* started losing its beginning, not to be told again each turn.
|
|
32
|
+
*
|
|
33
|
+
* `unbounded` and `unknown` never fire — there is no line to cross.
|
|
34
|
+
*/
|
|
35
|
+
report(usage: ContextUsage): void;
|
|
36
|
+
/**
|
|
37
|
+
* For a backend that decides this itself. The browser fires its own
|
|
38
|
+
* `contextoverflow`, and forwarding that is more truthful than re-deriving it
|
|
39
|
+
* from counters it may already have trimmed — by the time a listener reads
|
|
40
|
+
* them the dropped turns are gone and `used` can be under the window again.
|
|
41
|
+
*/
|
|
42
|
+
announce(): void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A session's closures on top of an event target, which is the one way to build
|
|
46
|
+
* an `AiSession` — the contract extends `EventTarget`, and an object literal is
|
|
47
|
+
* not one.
|
|
48
|
+
*/
|
|
49
|
+
export declare function withEvents(events: ContextEvents, session: Omit<AiSession, keyof EventTarget | "oncontextoverflow">): AiSession;
|
|
50
|
+
//# sourceMappingURL=overflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overflow.d.ts","sourceRoot":"","sources":["../../src/helpers/overflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAElD,qBAAa,aAAc,SAAQ,WAAW;;IAI5C;;;;OAIG;IACH,IAAI,iBAAiB,IAAI,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAEvD;IAED,IAAI,iBAAiB,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,EAM7D;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAOjC;;;;;OAKG;IACH,QAAQ,IAAI,IAAI;CAKjB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,MAAM,WAAW,GAAG,mBAAmB,CAAC,GAChE,SAAS,CAEX"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `contextoverflow` event, carried for every provider by one object.
|
|
3
|
+
*
|
|
4
|
+
* Shared for the reason `turn.ts` is shared: the contract suite would watch
|
|
5
|
+
* each provider fire and never notice that they fire on different arithmetic.
|
|
6
|
+
* The rule lives here — a session that has spent more of the window than the
|
|
7
|
+
* window holds — and nothing but this file decides it.
|
|
8
|
+
*
|
|
9
|
+
* A session is not an `EventTarget` by construction: a provider builds one as
|
|
10
|
+
* an object of closures. So the closures are assigned onto an instance of
|
|
11
|
+
* this class, the way `ProgressMonitor` carries `downloadprogress`.
|
|
12
|
+
*/
|
|
13
|
+
export const CONTEXT_OVERFLOW = "contextoverflow";
|
|
14
|
+
export class ContextEvents extends EventTarget {
|
|
15
|
+
#handler = null;
|
|
16
|
+
#fired = false;
|
|
17
|
+
/**
|
|
18
|
+
* As on `DownloadMonitor`: an `onevent` property is not free with
|
|
19
|
+
* `EventTarget`, and it is the only registration that carries the event's
|
|
20
|
+
* type — `addEventListener` on a subclass takes a bare `EventListener`.
|
|
21
|
+
*/
|
|
22
|
+
get oncontextoverflow() {
|
|
23
|
+
return this.#handler;
|
|
24
|
+
}
|
|
25
|
+
set oncontextoverflow(handler) {
|
|
26
|
+
if (this.#handler !== null) {
|
|
27
|
+
this.removeEventListener(CONTEXT_OVERFLOW, this.#handler);
|
|
28
|
+
}
|
|
29
|
+
this.#handler = handler;
|
|
30
|
+
if (handler !== null)
|
|
31
|
+
this.addEventListener(CONTEXT_OVERFLOW, handler);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Called with what the session now holds, after a turn has been charged.
|
|
35
|
+
*
|
|
36
|
+
* Fires at most once. The window does not un-overflow: the backend has
|
|
37
|
+
* already dropped the oldest turns to make the last one fit, and every turn
|
|
38
|
+
* after it is over the same line. A listener wants to hear that the conversation
|
|
39
|
+
* started losing its beginning, not to be told again each turn.
|
|
40
|
+
*
|
|
41
|
+
* `unbounded` and `unknown` never fire — there is no line to cross.
|
|
42
|
+
*/
|
|
43
|
+
report(usage) {
|
|
44
|
+
if (this.#fired || usage.kind !== "bounded")
|
|
45
|
+
return;
|
|
46
|
+
// Strictly greater: a transcript that exactly fills the window still fits.
|
|
47
|
+
if (usage.used <= usage.total)
|
|
48
|
+
return;
|
|
49
|
+
this.announce();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* For a backend that decides this itself. The browser fires its own
|
|
53
|
+
* `contextoverflow`, and forwarding that is more truthful than re-deriving it
|
|
54
|
+
* from counters it may already have trimmed — by the time a listener reads
|
|
55
|
+
* them the dropped turns are gone and `used` can be under the window again.
|
|
56
|
+
*/
|
|
57
|
+
announce() {
|
|
58
|
+
if (this.#fired)
|
|
59
|
+
return;
|
|
60
|
+
this.#fired = true;
|
|
61
|
+
this.dispatchEvent(new Event(CONTEXT_OVERFLOW));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A session's closures on top of an event target, which is the one way to build
|
|
66
|
+
* an `AiSession` — the contract extends `EventTarget`, and an object literal is
|
|
67
|
+
* not one.
|
|
68
|
+
*/
|
|
69
|
+
export function withEvents(events, session) {
|
|
70
|
+
return Object.assign(events, session);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=overflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overflow.js","sourceRoot":"","sources":["../../src/helpers/overflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,MAAM,CAAC,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAElD,MAAM,OAAO,aAAc,SAAQ,WAAW;IAC5C,QAAQ,GAAoC,IAAI,CAAC;IACjD,MAAM,GAAG,KAAK,CAAC;IAEf;;;;OAIG;IACH,IAAI,iBAAiB;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,IAAI,iBAAiB,CAAC,OAAwC;QAC5D,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,OAAO,KAAK,IAAI;YAAE,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IACzE,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAmB;QACxB,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;YAAE,OAAO;QACpD,2EAA2E;QAC3E,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK;YAAE,OAAO;QACtC,IAAI,CAAC,QAAQ,EAAE,CAAC;IAClB,CAAC;IAED;;;;;OAKG;IACH,QAAQ;QACN,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAClD,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,MAAqB,EACrB,OAAiE;IAEjE,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The conversation as the session has actually had it: what was handed at
|
|
3
|
+
* open, then every completed turn, in order.
|
|
4
|
+
*
|
|
5
|
+
* Completed only. An aborted, cancelled or failed turn adds nothing, and the
|
|
6
|
+
* event that appends is the one that charges usage (`04_generate.ts`), so the
|
|
7
|
+
* meter and the record cannot disagree. It also keeps the prefix a stateless
|
|
8
|
+
* backend resends stable from turn to turn, which is what a server's KV cache
|
|
9
|
+
* matches on — any edit before the end invalidates everything after it.
|
|
10
|
+
*
|
|
11
|
+
* Never trimmed. What to drop when the window overflows is a decision about
|
|
12
|
+
* the conversation, and only the app knows what it can lose; the lifecycle
|
|
13
|
+
* reports the overflow and keeps the whole record.
|
|
14
|
+
*/
|
|
15
|
+
import type { AiMessage } from "../types/messages.js";
|
|
16
|
+
export interface Transcript {
|
|
17
|
+
/** Stable once read: a later `append` builds a new array rather than writing into this one. */
|
|
18
|
+
readonly entries: () => readonly AiMessage[];
|
|
19
|
+
readonly append: (input: string, answer: string) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function createTranscript(seed?: readonly AiMessage[]): Transcript;
|
|
22
|
+
//# sourceMappingURL=transcript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../../src/helpers/transcript.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,UAAU;IACzB,+FAA+F;IAC/F,QAAQ,CAAC,OAAO,EAAE,MAAM,SAAS,SAAS,EAAE,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,SAAS,SAAS,EAAO,GAAG,UAAU,CAU5E"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The conversation as the session has actually had it: what was handed at
|
|
3
|
+
* open, then every completed turn, in order.
|
|
4
|
+
*
|
|
5
|
+
* Completed only. An aborted, cancelled or failed turn adds nothing, and the
|
|
6
|
+
* event that appends is the one that charges usage (`04_generate.ts`), so the
|
|
7
|
+
* meter and the record cannot disagree. It also keeps the prefix a stateless
|
|
8
|
+
* backend resends stable from turn to turn, which is what a server's KV cache
|
|
9
|
+
* matches on — any edit before the end invalidates everything after it.
|
|
10
|
+
*
|
|
11
|
+
* Never trimmed. What to drop when the window overflows is a decision about
|
|
12
|
+
* the conversation, and only the app knows what it can lose; the lifecycle
|
|
13
|
+
* reports the overflow and keeps the whole record.
|
|
14
|
+
*/
|
|
15
|
+
export function createTranscript(seed = []) {
|
|
16
|
+
let entries = [...seed];
|
|
17
|
+
return {
|
|
18
|
+
entries: () => entries,
|
|
19
|
+
append: (input, answer) => {
|
|
20
|
+
const question = { role: "user", content: input };
|
|
21
|
+
const reply = { role: "assistant", content: answer };
|
|
22
|
+
entries = [...entries, question, reply];
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=transcript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../../src/helpers/transcript.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,MAAM,UAAU,gBAAgB,CAAC,OAA6B,EAAE;IAC9D,IAAI,OAAO,GAAyB,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO;QACL,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO;QACtB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACxB,MAAM,QAAQ,GAAc,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC7D,MAAM,KAAK,GAAc,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;YAChE,OAAO,GAAG,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The package: a contract for language-model backends, the lifecycle that
|
|
3
|
+
* holds it, and one backend with nothing behind it.
|
|
4
|
+
*
|
|
5
|
+
* Three ways in. An app picks a provider and talks to a session — `AiSession`
|
|
6
|
+
* and the failure vocabulary are the whole surface for that. An app that ships
|
|
7
|
+
* several picks from its own registry. A backend author fills in `ModelBackend`
|
|
8
|
+
* and hands it to `createProvider`, then proves it with `modelpact/testing`.
|
|
9
|
+
*/
|
|
10
|
+
export { createProvider } from "./providers/create.js";
|
|
11
|
+
export { defineProviders, findProviderName, type ProviderRegistry, } from "./providers/registry.js";
|
|
12
|
+
export { makeMockProvider, type MockConfig } from "./providers/mock.js";
|
|
13
|
+
export { makeOllamaProvider, type OllamaConfig } from "./providers/ollama.js";
|
|
14
|
+
export { makePromptApiProvider } from "./providers/prompt-api.js";
|
|
15
|
+
export type { AiProvider, ProviderName } from "./types/provider.js";
|
|
16
|
+
export type { AccessKind, AiSession, DownloadMonitor, GenerateOptions, ModelAccess, SessionOptions, } from "./types/session.js";
|
|
17
|
+
export type { AiMessage, AiRole, Modality, ModalityExpectation, ModelRequest, } from "./types/messages.js";
|
|
18
|
+
export { AiError, failureFromError, type AiFailure, type FailureKind, } from "./types/failures.js";
|
|
19
|
+
export { contextUsage, type ContextUsage, type UsageKind, } from "./types/usage.js";
|
|
20
|
+
export { err, fraction, jsonSchema, ok, tokens, type Fraction, type JsonSchema, type Result, type Tokens, } from "./types/foundations.js";
|
|
21
|
+
export type { Availability, ConnectOptions, GenerateRequest, ModelBackend, ModelConnection, } from "./types/backend.js";
|
|
22
|
+
export { ndjsonLines } from "./helpers/ndjson.js";
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,KAAK,gBAAgB,GACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACpE,YAAY,EACV,UAAU,EACV,SAAS,EACT,eAAe,EACf,eAAe,EACf,WAAW,EACX,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,mBAAmB,EACnB,YAAY,GACb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,OAAO,EACP,gBAAgB,EAChB,KAAK,SAAS,EACd,KAAK,WAAW,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,SAAS,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,GAAG,EACH,QAAQ,EACR,UAAU,EACV,EAAE,EACF,MAAM,EACN,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,MAAM,EACX,KAAK,MAAM,GACZ,MAAM,wBAAwB,CAAC;AAIhC,YAAY,EACV,YAAY,EACZ,cAAc,EACd,eAAe,EACf,YAAY,EACZ,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The package: a contract for language-model backends, the lifecycle that
|
|
3
|
+
* holds it, and one backend with nothing behind it.
|
|
4
|
+
*
|
|
5
|
+
* Three ways in. An app picks a provider and talks to a session — `AiSession`
|
|
6
|
+
* and the failure vocabulary are the whole surface for that. An app that ships
|
|
7
|
+
* several picks from its own registry. A backend author fills in `ModelBackend`
|
|
8
|
+
* and hands it to `createProvider`, then proves it with `modelpact/testing`.
|
|
9
|
+
*/
|
|
10
|
+
export { createProvider } from "./providers/create.js";
|
|
11
|
+
export { defineProviders, findProviderName, } from "./providers/registry.js";
|
|
12
|
+
export { makeMockProvider } from "./providers/mock.js";
|
|
13
|
+
export { makeOllamaProvider } from "./providers/ollama.js";
|
|
14
|
+
export { makePromptApiProvider } from "./providers/prompt-api.js";
|
|
15
|
+
export { AiError, failureFromError, } from "./types/failures.js";
|
|
16
|
+
export { contextUsage, } from "./types/usage.js";
|
|
17
|
+
export { err, fraction, jsonSchema, ok, tokens, } from "./types/foundations.js";
|
|
18
|
+
export { ndjsonLines } from "./helpers/ndjson.js";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACL,eAAe,EACf,gBAAgB,GAEjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAmB,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAqB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAkBlE,OAAO,EACL,OAAO,EACP,gBAAgB,GAGjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,YAAY,GAGb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,GAAG,EACH,QAAQ,EACR,UAAU,EACV,EAAE,EACF,MAAM,GAKP,MAAM,wBAAwB,CAAC;AAWhC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage one: is there a model for this request. `open` is attached only to the
|
|
3
|
+
* branches that can, which is what makes opening an unavailable model
|
|
4
|
+
* unwritable.
|
|
5
|
+
*
|
|
6
|
+
* The backend the stages run on is `../types/backend.ts`; the entry that puts
|
|
7
|
+
* them together is `../providers/create.ts`.
|
|
8
|
+
*/
|
|
9
|
+
import type { ModelRequest } from "../types/messages.js";
|
|
10
|
+
import type { ModelAccess } from "../types/session.js";
|
|
11
|
+
import type { ModelBackend } from "../types/backend.js";
|
|
12
|
+
export declare const checkAccess: (backend: ModelBackend, request?: ModelRequest) => Promise<ModelAccess>;
|
|
13
|
+
//# sourceMappingURL=01_access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"01_access.d.ts","sourceRoot":"","sources":["../../src/lifecycle/01_access.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAY,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAkBxD,eAAO,MAAM,WAAW,GACtB,SAAS,YAAY,EACrB,UAAS,YAAiB,KACzB,OAAO,CAAC,WAAW,CA6BrB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage one: is there a model for this request. `open` is attached only to the
|
|
3
|
+
* branches that can, which is what makes opening an unavailable model
|
|
4
|
+
* unwritable.
|
|
5
|
+
*
|
|
6
|
+
* The backend the stages run on is `../types/backend.ts`; the entry that puts
|
|
7
|
+
* them together is `../providers/create.ts`.
|
|
8
|
+
*/
|
|
9
|
+
import { openAfterDownload } from "./02_download.js";
|
|
10
|
+
import { openSession } from "./03_open.js";
|
|
11
|
+
const findUnsupportedModalities = (request, supported) => {
|
|
12
|
+
const expectations = [...(request.inputs ?? []), ...(request.outputs ?? [])];
|
|
13
|
+
const modalities = expectations.map((expectation) => expectation.type);
|
|
14
|
+
const unsupported = modalities.filter((modality) => !supported.includes(modality));
|
|
15
|
+
return unsupported;
|
|
16
|
+
};
|
|
17
|
+
const ignoreProgress = () => undefined;
|
|
18
|
+
export const checkAccess = async (backend, request = {}) => {
|
|
19
|
+
const unsupportedModalities = findUnsupportedModalities(request, backend.modalities);
|
|
20
|
+
if (unsupportedModalities.length > 0) {
|
|
21
|
+
return {
|
|
22
|
+
kind: "unavailable",
|
|
23
|
+
reason: {
|
|
24
|
+
kind: "unsupported-config",
|
|
25
|
+
languages: [],
|
|
26
|
+
modalities: unsupportedModalities,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const availability = await backend.availability(request);
|
|
31
|
+
if (availability.kind === "unavailable")
|
|
32
|
+
return availability;
|
|
33
|
+
if (availability.kind === "needs-download") {
|
|
34
|
+
return {
|
|
35
|
+
kind: "needs-download",
|
|
36
|
+
started: availability.started,
|
|
37
|
+
open: (subscribe, options) => openAfterDownload(backend, request, subscribe, options),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
kind: "ready",
|
|
42
|
+
open: (options) => openSession(backend, request, options, ignoreProgress),
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=01_access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"01_access.js","sourceRoot":"","sources":["../../src/lifecycle/01_access.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,yBAAyB,GAAG,CAChC,OAAqB,EACrB,SAA8B,EACT,EAAE;IACvB,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7E,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACvE,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CACnC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAC5C,CAAC;IACF,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC;AAE7C,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,OAAqB,EACrB,UAAwB,EAAE,EACJ,EAAE;IACxB,MAAM,qBAAqB,GAAG,yBAAyB,CACrD,OAAO,EACP,OAAO,CAAC,UAAU,CACnB,CAAC;IACF,IAAI,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,OAAO;YACL,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE;gBACN,IAAI,EAAE,oBAAoB;gBAC1B,SAAS,EAAE,EAAE;gBACb,UAAU,EAAE,qBAAqB;aAClC;SACF,CAAC;IACJ,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,YAAY,CAAC,IAAI,KAAK,aAAa;QAAE,OAAO,YAAY,CAAC;IAC7D,IAAI,YAAY,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QAC3C,OAAO;YACL,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,YAAY,CAAC,OAAO;YAC7B,IAAI,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,CAC3B,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC;SAC1D,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC;KAC1E,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Stage two, on the `needs-download` branch only: subscribe the monitor, then let the backend fetch and connect. */
|
|
2
|
+
import type { Result } from "../types/foundations.js";
|
|
3
|
+
import type { AiFailure } from "../types/failures.js";
|
|
4
|
+
import type { ModelRequest } from "../types/messages.js";
|
|
5
|
+
import type { AiSession, DownloadMonitor, SessionOptions } from "../types/session.js";
|
|
6
|
+
import type { ModelBackend } from "../types/backend.js";
|
|
7
|
+
export declare const openAfterDownload: (backend: ModelBackend, request: ModelRequest, subscribe: (monitor: DownloadMonitor) => void, options?: SessionOptions) => Promise<Result<AiSession, AiFailure>>;
|
|
8
|
+
//# sourceMappingURL=02_download.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"02_download.d.ts","sourceRoot":"","sources":["../../src/lifecycle/02_download.ts"],"names":[],"mappings":"AAAA,qHAAqH;AAGrH,OAAO,KAAK,EAAY,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,cAAc,EACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,eAAO,MAAM,iBAAiB,GAC5B,SAAS,YAAY,EACrB,SAAS,YAAY,EACrB,WAAW,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,EAC7C,UAAU,cAAc,KACvB,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAOtC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Stage two, on the `needs-download` branch only: subscribe the monitor, then let the backend fetch and connect. */
|
|
2
|
+
import { ProgressMonitor } from "../helpers/monitor.js";
|
|
3
|
+
import { openSession } from "./03_open.js";
|
|
4
|
+
export const openAfterDownload = (backend, request, subscribe, options) => {
|
|
5
|
+
const monitor = new ProgressMonitor();
|
|
6
|
+
// Before the first await: subscribing after the promise settles is
|
|
7
|
+
// subscribing after the download.
|
|
8
|
+
subscribe(monitor);
|
|
9
|
+
const reportProgress = (loaded) => monitor.report(loaded);
|
|
10
|
+
return openSession(backend, request, options, reportProgress);
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=02_download.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"02_download.js","sourceRoot":"","sources":["../../src/lifecycle/02_download.ts"],"names":[],"mappings":"AAAA,qHAAqH;AAErH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAUxD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,OAAqB,EACrB,OAAqB,EACrB,SAA6C,EAC7C,OAAwB,EACe,EAAE;IACzC,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;IACtC,mEAAmE;IACnE,kCAAkC;IAClC,SAAS,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,cAAc,GAAG,CAAC,MAAgB,EAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1E,OAAO,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;AAChE,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage three: a connected model becomes an `AiSession` with the lifecycle's
|
|
3
|
+
* closures on it. `SessionState` is what those closures share from here on.
|
|
4
|
+
*/
|
|
5
|
+
import { ContextEvents } from "../helpers/overflow.js";
|
|
6
|
+
import { type SessionLifetime } from "../helpers/lifetime.js";
|
|
7
|
+
import { type Transcript } from "../helpers/transcript.js";
|
|
8
|
+
import { type Fraction, type Result } from "../types/foundations.js";
|
|
9
|
+
import type { AiFailure } from "../types/failures.js";
|
|
10
|
+
import type { ModelRequest } from "../types/messages.js";
|
|
11
|
+
import type { AiSession, SessionOptions } from "../types/session.js";
|
|
12
|
+
import type { ModelConnection, ModelBackend } from "../types/backend.js";
|
|
13
|
+
export interface SessionState {
|
|
14
|
+
readonly model: ModelConnection;
|
|
15
|
+
/** Idle, generating or closed, and the only way between the three. */
|
|
16
|
+
readonly lifetime: SessionLifetime;
|
|
17
|
+
readonly events: ContextEvents;
|
|
18
|
+
/** Seeded from `options.history`; the backend got the same seed at `connect`. */
|
|
19
|
+
readonly transcript: Transcript;
|
|
20
|
+
}
|
|
21
|
+
export declare const openSession: (backend: ModelBackend, request: ModelRequest, options: SessionOptions | undefined, reportProgress: (loaded: Fraction) => void) => Promise<Result<AiSession, AiFailure>>;
|
|
22
|
+
//# sourceMappingURL=03_open.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"03_open.d.ts","sourceRoot":"","sources":["../../src/lifecycle/03_open.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAc,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAW,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIzE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,iFAAiF;IACjF,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC;AAED,eAAO,MAAM,WAAW,GACtB,SAAS,YAAY,EACrB,SAAS,YAAY,EACrB,SAAS,cAAc,GAAG,SAAS,EACnC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,KAAK,IAAI,KACzC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CA4BtC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage three: a connected model becomes an `AiSession` with the lifecycle's
|
|
3
|
+
* closures on it. `SessionState` is what those closures share from here on.
|
|
4
|
+
*/
|
|
5
|
+
import { abortFailure } from "../helpers/abort.js";
|
|
6
|
+
import { ContextEvents, withEvents } from "../helpers/overflow.js";
|
|
7
|
+
import { createSessionLifetime, } from "../helpers/lifetime.js";
|
|
8
|
+
import { createTranscript } from "../helpers/transcript.js";
|
|
9
|
+
import { err, ok } from "../types/foundations.js";
|
|
10
|
+
import { prompt, promptStream } from "./04_generate.js";
|
|
11
|
+
import { closeSession } from "./05_close.js";
|
|
12
|
+
export const openSession = async (backend, request, options, reportProgress) => {
|
|
13
|
+
if (options?.signal?.aborted === true)
|
|
14
|
+
return err(abortFailure(options.signal));
|
|
15
|
+
const events = new ContextEvents();
|
|
16
|
+
const modelResult = await backend.connect({
|
|
17
|
+
request,
|
|
18
|
+
session: options ?? {},
|
|
19
|
+
reportProgress,
|
|
20
|
+
reportOverflow: () => events.announce(),
|
|
21
|
+
});
|
|
22
|
+
if (!modelResult.ok)
|
|
23
|
+
return modelResult;
|
|
24
|
+
const state = {
|
|
25
|
+
model: modelResult.value,
|
|
26
|
+
lifetime: createSessionLifetime(),
|
|
27
|
+
events,
|
|
28
|
+
transcript: createTranscript(options?.history),
|
|
29
|
+
};
|
|
30
|
+
const session = withEvents(events, {
|
|
31
|
+
prompt: (input, generateOptions) => prompt(state, input, generateOptions),
|
|
32
|
+
promptStream: (input, generateOptions) => promptStream(state, input, generateOptions),
|
|
33
|
+
usage: () => state.model.usage(),
|
|
34
|
+
history: () => state.transcript.entries(),
|
|
35
|
+
close: () => closeSession(state),
|
|
36
|
+
});
|
|
37
|
+
return ok(session);
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=03_open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"03_open.js","sourceRoot":"","sources":["../../src/lifecycle/03_open.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EACL,qBAAqB,GAEtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAmB,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,GAAG,EAAE,EAAE,EAA8B,MAAM,yBAAyB,CAAC;AAK9E,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAW7C,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,OAAqB,EACrB,OAAqB,EACrB,OAAmC,EACnC,cAA0C,EACH,EAAE;IACzC,IAAI,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI;QACnC,OAAO,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;IACnC,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;QACxC,OAAO;QACP,OAAO,EAAE,OAAO,IAAI,EAAE;QACtB,cAAc;QACd,cAAc,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE;KACxC,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,CAAC,EAAE;QAAE,OAAO,WAAW,CAAC;IAExC,MAAM,KAAK,GAAiB;QAC1B,KAAK,EAAE,WAAW,CAAC,KAAK;QACxB,QAAQ,EAAE,qBAAqB,EAAE;QACjC,MAAM;QACN,UAAU,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC;KAC/C,CAAC;IACF,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,EAAE;QACjC,MAAM,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,eAAe,CAAC;QACzE,YAAY,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,CACvC,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,eAAe,CAAC;QAC7C,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE;QAChC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE;QACzC,KAAK,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC;KACjC,CAAC,CAAC;IACH,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage four, once per turn: refuse at the door, hold the session, guard the
|
|
3
|
+
* stream, record the turn, free the session.
|
|
4
|
+
*
|
|
5
|
+
* `prompt` is `promptStream` drained, unless the backend has a whole-answer
|
|
6
|
+
* call. Either way a turn cannot leave the session held: every exit from the
|
|
7
|
+
* guarded stream — done, error, abort, reader cancel — ends it.
|
|
8
|
+
*/
|
|
9
|
+
import { type Result } from "../types/foundations.js";
|
|
10
|
+
import { type AiFailure } from "../types/failures.js";
|
|
11
|
+
import type { GenerateOptions } from "../types/session.js";
|
|
12
|
+
import type { SessionState } from "./03_open.js";
|
|
13
|
+
export declare const prompt: (state: SessionState, input: string, options?: GenerateOptions) => Promise<Result<string, AiFailure>>;
|
|
14
|
+
export declare const promptStream: (state: SessionState, input: string, options?: GenerateOptions) => Promise<Result<ReadableStream<string>, AiFailure>>;
|
|
15
|
+
//# sourceMappingURL=04_generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"04_generate.d.ts","sourceRoot":"","sources":["../../src/lifecycle/04_generate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAkLjD,eAAO,MAAM,MAAM,GACjB,OAAO,YAAY,EACnB,OAAO,MAAM,EACb,UAAU,eAAe,KACxB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAQnC,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,OAAO,YAAY,EACnB,OAAO,MAAM,EACb,UAAU,eAAe,KACxB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CACA,CAAC"}
|