@happyvertical/smrt-web 0.51.32 → 0.51.34
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/dist/__typechecks__/webmcp-tool-definition.d.ts +2 -0
- package/dist/__typechecks__/webmcp-tool-definition.d.ts.map +1 -0
- package/dist/ai.d.ts +330 -358
- package/dist/ai.d.ts.map +1 -0
- package/dist/capability-classification.d.ts +89 -0
- package/dist/capability-classification.d.ts.map +1 -0
- package/dist/capability.d.ts +191 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/data-query.d.ts +121 -0
- package/dist/data-query.d.ts.map +1 -0
- package/dist/data-surface-actions.d.ts +118 -0
- package/dist/data-surface-actions.d.ts.map +1 -0
- package/dist/durable-store.d.ts +88 -0
- package/dist/durable-store.d.ts.map +1 -0
- package/dist/index.d.ts +468 -2245
- package/dist/index.d.ts.map +1 -0
- package/dist/intents.d.ts +273 -300
- package/dist/intents.d.ts.map +1 -0
- package/dist/internal.d.ts +15 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/offline/durable-queue.d.ts +171 -0
- package/dist/offline/durable-queue.d.ts.map +1 -0
- package/dist/offline/engine.d.ts +359 -0
- package/dist/offline/engine.d.ts.map +1 -0
- package/dist/offline/leader.d.ts +57 -0
- package/dist/offline/leader.d.ts.map +1 -0
- package/dist/offline/types.d.ts +232 -0
- package/dist/offline/types.d.ts.map +1 -0
- package/dist/offline.d.ts +258 -0
- package/dist/offline.d.ts.map +1 -0
- package/dist/persistence/snapshot-store.d.ts +121 -0
- package/dist/persistence/snapshot-store.d.ts.map +1 -0
- package/dist/persistence.d.ts +157 -0
- package/dist/persistence.d.ts.map +1 -0
- package/dist/remote-query.d.ts +61 -0
- package/dist/remote-query.d.ts.map +1 -0
- package/dist/sse-client.d.ts +182 -0
- package/dist/sse-client.d.ts.map +1 -0
- package/dist/update-state/meta-store.d.ts +66 -0
- package/dist/update-state/meta-store.d.ts.map +1 -0
- package/dist/update-state.d.ts +115 -0
- package/dist/update-state.d.ts.map +1 -0
- package/dist/webmcp-tool-names.d.ts +106 -112
- package/dist/webmcp-tool-names.d.ts.map +1 -0
- package/dist/webmcp.d.ts +193 -653
- package/dist/webmcp.d.ts.map +1 -0
- package/package.json +4 -4
package/dist/ai.d.ts
CHANGED
|
@@ -1,358 +1,330 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
export
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
export
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
export declare
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
export declare
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
*
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*/
|
|
281
|
-
|
|
282
|
-
export
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
*
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
* deadline the route backend would have enforced must not be quietly ignored
|
|
332
|
-
* by a local one.
|
|
333
|
-
*/
|
|
334
|
-
export declare function requestSignal(chatOptions?: InferenceChatOptions): AbortSignal | undefined;
|
|
335
|
-
|
|
336
|
-
export declare interface RouteInferenceBackendOptions {
|
|
337
|
-
/** Full URL of a `text/event-stream` endpoint accepting `{ messages, session }`. */
|
|
338
|
-
endpoint: string;
|
|
339
|
-
/** Backend id. Defaults to `'route'`. */
|
|
340
|
-
id?: string;
|
|
341
|
-
/** Extra request headers, evaluated per call (auth tokens rotate). */
|
|
342
|
-
headers?: () => Record<string, string>;
|
|
343
|
-
/** Fetch credentials mode. Defaults to the platform default. */
|
|
344
|
-
credentials?: RequestCredentials;
|
|
345
|
-
/** Session metadata attached to the request body. */
|
|
346
|
-
session?: Record<string, unknown>;
|
|
347
|
-
/** Injectable fetch (tests, SSR-safe wrappers). */
|
|
348
|
-
fetchImpl?: typeof fetch;
|
|
349
|
-
/**
|
|
350
|
-
* Model id recorded on the returned `InferenceResponse`. Reporting only —
|
|
351
|
-
* the route resolves the model it actually uses, and a caller cannot widen
|
|
352
|
-
* it by naming one here (the generation caps live in the server-resolved
|
|
353
|
-
* stream context).
|
|
354
|
-
*/
|
|
355
|
-
model?: string;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
export { }
|
|
1
|
+
/**
|
|
2
|
+
* Browser inference path — ONE call-site object over interchangeable inference
|
|
3
|
+
* backends.
|
|
4
|
+
*
|
|
5
|
+
* A caller (a component, a hook, a workbench) holds a single `InferencePath`
|
|
6
|
+
* and calls `chat()`/`stream()` on it. Which backend actually answers is
|
|
7
|
+
* resolved **per call**, never cached on the path, so changing the preference
|
|
8
|
+
* between two calls takes effect on the next one. That is what makes "switch
|
|
9
|
+
* between the local model and the server route mid-session" a property
|
|
10
|
+
* assignment rather than session state to unwind.
|
|
11
|
+
*
|
|
12
|
+
* ## Why a mirror rather than an import
|
|
13
|
+
*
|
|
14
|
+
* `InferenceMessage`/`InferenceResponse`/`InferenceChatOptions` are TEXTUAL
|
|
15
|
+
* structural mirrors of `@happyvertical/ai`'s `AIMessage`/`AIResponse`/
|
|
16
|
+
* `ChatOptions`, and `InferenceProgress` mirrors the browser adapters'
|
|
17
|
+
* `DownloadProgressInfo`. smrt-web deliberately has no `@happyvertical/*`
|
|
18
|
+
* dependency (`AGENTS.md`, "No inter-smrt dependencies"), so an `AIInterface`
|
|
19
|
+
* — the ecosystem's canonical inference boundary — is described here by shape.
|
|
20
|
+
*
|
|
21
|
+
* The mirror covers the text-generation surface only. A backend whose
|
|
22
|
+
* `chat`/`stream` accept these shapes satisfies the consumers in this
|
|
23
|
+
* repository; a consumer that needs more of `AIInterface` adapts at its own
|
|
24
|
+
* boundary rather than widening this contract.
|
|
25
|
+
*
|
|
26
|
+
* ## What this module does NOT own
|
|
27
|
+
*
|
|
28
|
+
* Backends arrive as arguments, the same way definitions and fetchers do
|
|
29
|
+
* everywhere else in this package. A WebLLM backend lives beside the adapter
|
|
30
|
+
* it wraps; `createRouteInferenceBackend` here covers the streaming-route case
|
|
31
|
+
* because that one is pure `fetch` plus an SSE frame reader.
|
|
32
|
+
*
|
|
33
|
+
* @module
|
|
34
|
+
*/
|
|
35
|
+
/** Text content part (mirrors `TextContentPart`). */
|
|
36
|
+
export interface InferenceTextPart {
|
|
37
|
+
type: 'text';
|
|
38
|
+
text: string;
|
|
39
|
+
}
|
|
40
|
+
/** Image content part (mirrors `ImageContentPart`). */
|
|
41
|
+
export interface InferenceImagePart {
|
|
42
|
+
type: 'image_url';
|
|
43
|
+
image_url: {
|
|
44
|
+
url: string;
|
|
45
|
+
detail?: 'auto' | 'low' | 'high';
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export type InferenceContentPart = InferenceTextPart | InferenceImagePart;
|
|
49
|
+
/** Message roles, mirroring `AIMessage['role']`. */
|
|
50
|
+
export type InferenceRole = 'system' | 'user' | 'assistant' | 'function' | 'tool';
|
|
51
|
+
export interface InferenceToolCall {
|
|
52
|
+
id: string;
|
|
53
|
+
type: 'function';
|
|
54
|
+
function: {
|
|
55
|
+
name: string;
|
|
56
|
+
arguments: string;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** One conversation message (mirrors `AIMessage`). */
|
|
60
|
+
export interface InferenceMessage {
|
|
61
|
+
role: InferenceRole;
|
|
62
|
+
content: string | InferenceContentPart[];
|
|
63
|
+
name?: string;
|
|
64
|
+
tool_calls?: InferenceToolCall[];
|
|
65
|
+
}
|
|
66
|
+
/** A tool definition offered to the model (mirrors `AITool`). */
|
|
67
|
+
export interface InferenceTool {
|
|
68
|
+
type: 'function';
|
|
69
|
+
function: {
|
|
70
|
+
name: string;
|
|
71
|
+
description?: string;
|
|
72
|
+
parameters?: Record<string, unknown>;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/** Token usage (mirrors `TokenUsage`). */
|
|
76
|
+
export interface InferenceUsage {
|
|
77
|
+
promptTokens: number;
|
|
78
|
+
completionTokens: number;
|
|
79
|
+
totalTokens: number;
|
|
80
|
+
}
|
|
81
|
+
/** A completion result (mirrors `AIResponse`). */
|
|
82
|
+
export interface InferenceResponse {
|
|
83
|
+
content: string;
|
|
84
|
+
usage?: InferenceUsage;
|
|
85
|
+
model?: string;
|
|
86
|
+
finishReason?: 'stop' | 'length' | 'tool_calls' | 'content_filter';
|
|
87
|
+
toolCalls?: InferenceToolCall[];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Per-call options (mirrors the `ChatOptions` fields a browser backend can
|
|
91
|
+
* honor).
|
|
92
|
+
*
|
|
93
|
+
* `signal` is the cancellation seam a backend SHOULD respect — one that cannot
|
|
94
|
+
* (the browser LLM adapter has no cancel path) ignores it rather than
|
|
95
|
+
* pretending, so a caller must not read an abort as proof the work stopped.
|
|
96
|
+
*
|
|
97
|
+
* `tools` is refused, not ignored: every backend here is a text conversation,
|
|
98
|
+
* and a backend that silently dropped a tool definition would let a caller
|
|
99
|
+
* believe an answer was produced with tools it never received. Use
|
|
100
|
+
* {@link assertTextOnlyTurn} to check a turn up front.
|
|
101
|
+
*/
|
|
102
|
+
export interface InferenceChatOptions {
|
|
103
|
+
model?: string;
|
|
104
|
+
maxTokens?: number;
|
|
105
|
+
temperature?: number;
|
|
106
|
+
topP?: number;
|
|
107
|
+
stop?: string | string[];
|
|
108
|
+
tools?: InferenceTool[];
|
|
109
|
+
toolChoice?: 'auto' | 'none' | {
|
|
110
|
+
type: 'function';
|
|
111
|
+
function: {
|
|
112
|
+
name: string;
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
/** Token sink for a streamed reply. Backends that cannot stream ignore it. */
|
|
116
|
+
onProgress?: (chunk: string) => void;
|
|
117
|
+
/**
|
|
118
|
+
* Caller cancellation. Honored by the route backend and by bitgpu, which
|
|
119
|
+
* aborts a live generation; both compose it with `timeout`. The WebLLM
|
|
120
|
+
* adapter cannot cancel a generation already running on the GPU and does not
|
|
121
|
+
* read it.
|
|
122
|
+
*/
|
|
123
|
+
signal?: AbortSignal;
|
|
124
|
+
/**
|
|
125
|
+
* Deadline in milliseconds for one call. Honored by the route backend, which
|
|
126
|
+
* aborts the request when it elapses, and by bitgpu, which aborts the
|
|
127
|
+
* generation. The WebLLM adapter has no cancellation seam and ignores it.
|
|
128
|
+
*/
|
|
129
|
+
timeout?: number;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Model load/download progress, mirroring the browser adapters'
|
|
133
|
+
* `DownloadProgressInfo` so a `DownloadProgress` control can render it
|
|
134
|
+
* directly.
|
|
135
|
+
*/
|
|
136
|
+
export interface InferenceProgress {
|
|
137
|
+
state: 'idle' | 'downloading' | 'extracting' | 'complete' | 'error';
|
|
138
|
+
bytesLoaded: number;
|
|
139
|
+
bytesTotal: number;
|
|
140
|
+
percent: number;
|
|
141
|
+
currentFile?: string;
|
|
142
|
+
estimatedTimeRemaining?: number;
|
|
143
|
+
error?: string;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Cap on one undelivered SSE line, in UTF-16 code units. Without it a peer
|
|
147
|
+
* that streams bytes with no `\n` grows the reader's buffer until the tab's
|
|
148
|
+
* heap is exhausted.
|
|
149
|
+
*/
|
|
150
|
+
export declare const MAX_INFERENCE_STREAM_LINE_UNITS = 1048576;
|
|
151
|
+
/** Cap on total bytes read for one route call. */
|
|
152
|
+
export declare const MAX_INFERENCE_STREAM_BYTES: number;
|
|
153
|
+
/** Cap on the reply a route backend's `chat()` will assemble. */
|
|
154
|
+
export declare const MAX_INFERENCE_REPLY_UNITS: number;
|
|
155
|
+
/**
|
|
156
|
+
* A turn in the subset every backend in this module can carry: a text
|
|
157
|
+
* conversation with no tool traffic.
|
|
158
|
+
*/
|
|
159
|
+
export interface InferenceTextMessage {
|
|
160
|
+
role: 'system' | 'user' | 'assistant';
|
|
161
|
+
content: string;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Reject a turn this module's backends cannot faithfully carry, narrowing
|
|
165
|
+
* `messages` to {@link InferenceTextMessage} on success.
|
|
166
|
+
*
|
|
167
|
+
* Every backend here is a TEXT conversation: roles `user`/`assistant`/
|
|
168
|
+
* `system`, string content, no tools. Each of those limits is a real
|
|
169
|
+
* difference between the backends' transports, so refusing up front is the
|
|
170
|
+
* only way a caller can tell "this backend can't carry my turn" from "this
|
|
171
|
+
* backend answered". The route wire contract (`chat-stream.ts`
|
|
172
|
+
* `normalizeMessages`) and the local adapter both silently DROP exactly these
|
|
173
|
+
* shapes, which is why this check is shared rather than reimplemented per
|
|
174
|
+
* backend — two copies would drift, and the whole point is that both backends
|
|
175
|
+
* agree.
|
|
176
|
+
*
|
|
177
|
+
* `backendLabel` names the backend in the message so a caller knows which one
|
|
178
|
+
* refused.
|
|
179
|
+
*/
|
|
180
|
+
export declare function assertTextOnlyTurn(backendLabel: string, messages: InferenceMessage[], options?: InferenceChatOptions): asserts messages is InferenceTextMessage[];
|
|
181
|
+
/**
|
|
182
|
+
* Whether a backend can answer right now.
|
|
183
|
+
*
|
|
184
|
+
* - `unavailable` — cannot run in this environment at all (no WebGPU, model
|
|
185
|
+
* not offered). Never auto-selected.
|
|
186
|
+
* - `idle` — could run, nothing loaded yet. Not auto-selected; call `load()`.
|
|
187
|
+
* - `loading` — a load is in progress. Not auto-selected.
|
|
188
|
+
* - `ready` — can answer now. The only state auto-selection picks.
|
|
189
|
+
* - `error` — the last load or call failed. Never auto-selected.
|
|
190
|
+
*/
|
|
191
|
+
export type InferenceBackendStatus = 'unavailable' | 'idle' | 'loading' | 'ready' | 'error';
|
|
192
|
+
/** Where a backend executes. Reporting only — the path never branches on it. */
|
|
193
|
+
export type InferenceBackendKind = 'local' | 'route';
|
|
194
|
+
export interface InferenceBackend {
|
|
195
|
+
/** Stable id, unique across a path. A preference names this. */
|
|
196
|
+
readonly id: string;
|
|
197
|
+
/**
|
|
198
|
+
* Where this backend runs. Purely descriptive: it exists so a UI can say
|
|
199
|
+
* "runs on your device" and so callers can order backends sensibly. The
|
|
200
|
+
* path's resolution never reads it.
|
|
201
|
+
*/
|
|
202
|
+
readonly kind: InferenceBackendKind;
|
|
203
|
+
readonly status: InferenceBackendStatus;
|
|
204
|
+
/** Present while `status` is `loading` (and after a failure). */
|
|
205
|
+
readonly progress?: InferenceProgress;
|
|
206
|
+
/** Load whatever `status: 'idle'` is waiting on. No-op when already ready. */
|
|
207
|
+
load?(onProgress?: (progress: InferenceProgress) => void): Promise<void>;
|
|
208
|
+
/** Release loaded resources. No-op for backends with nothing to release. */
|
|
209
|
+
unload?(): Promise<void>;
|
|
210
|
+
chat(messages: InferenceMessage[], options?: InferenceChatOptions): Promise<InferenceResponse>;
|
|
211
|
+
stream(messages: InferenceMessage[], options?: InferenceChatOptions): AsyncIterable<string>;
|
|
212
|
+
/**
|
|
213
|
+
* Optional change notification. A backend that exposes this lets the path
|
|
214
|
+
* re-broadcast status/progress changes to UI subscribers; one that omits it
|
|
215
|
+
* is simply non-reactive for those fields.
|
|
216
|
+
*/
|
|
217
|
+
subscribe?(listener: () => void): () => void;
|
|
218
|
+
}
|
|
219
|
+
/** Why a call was routed to the backend it was routed to. */
|
|
220
|
+
export interface InferenceResolution {
|
|
221
|
+
backend: InferenceBackend;
|
|
222
|
+
/**
|
|
223
|
+
* - `preferred` — an explicit preference named this backend and it is usable.
|
|
224
|
+
* - `fallback` — an explicit preference was unusable; `requested` names it.
|
|
225
|
+
* - `auto` — no explicit preference; first usable backend in declared order.
|
|
226
|
+
*/
|
|
227
|
+
reason: 'preferred' | 'fallback' | 'auto';
|
|
228
|
+
/** The preference that could not be honored (`reason: 'fallback'` only). */
|
|
229
|
+
requested?: string;
|
|
230
|
+
/** Ids skipped because `canUse` returned false, in declared order. */
|
|
231
|
+
skipped: readonly string[];
|
|
232
|
+
}
|
|
233
|
+
export interface InferencePathOptions {
|
|
234
|
+
/**
|
|
235
|
+
* Candidate backends, in priority order. Order IS the auto-selection
|
|
236
|
+
* preference: list the local model first to prefer it when it is usable.
|
|
237
|
+
*/
|
|
238
|
+
backends: readonly InferenceBackend[];
|
|
239
|
+
/** Backend id to prefer, or `'auto'`. Defaults to `'auto'`. */
|
|
240
|
+
preference?: string;
|
|
241
|
+
/**
|
|
242
|
+
* Whether a backend may answer. Defaults to `backend.status === 'ready'`,
|
|
243
|
+
* so an unloaded (`idle`) local backend is skipped rather than silently
|
|
244
|
+
* triggering a multi-gigabyte download mid-conversation.
|
|
245
|
+
*/
|
|
246
|
+
canUse?: (backend: InferenceBackend) => boolean;
|
|
247
|
+
}
|
|
248
|
+
export interface InferencePath {
|
|
249
|
+
readonly backends: readonly InferenceBackend[];
|
|
250
|
+
/** The backend the NEXT call would use; `null` when none is usable. */
|
|
251
|
+
readonly activeId: string | null;
|
|
252
|
+
/** The configured preference, or `'auto'`. Settable; takes effect next call. */
|
|
253
|
+
preference: string;
|
|
254
|
+
/** The resolution the next call would produce, without making one. */
|
|
255
|
+
resolve(): InferenceResolution;
|
|
256
|
+
/** Pin to a backend id, or back to `'auto'`. */
|
|
257
|
+
select(preference: string): void;
|
|
258
|
+
chat(messages: InferenceMessage[], options?: InferenceChatOptions): Promise<InferenceResponse>;
|
|
259
|
+
stream(messages: InferenceMessage[], options?: InferenceChatOptions): AsyncIterable<string>;
|
|
260
|
+
/**
|
|
261
|
+
* Notified when a backend reports a status/progress change or the
|
|
262
|
+
* preference changes. Returns an unsubscribe function.
|
|
263
|
+
*/
|
|
264
|
+
subscribe(listener: () => void): () => void;
|
|
265
|
+
/** Detach every backend subscription and drop all listeners. */
|
|
266
|
+
dispose(): void;
|
|
267
|
+
}
|
|
268
|
+
export type InferencePathErrorCode = 'no_backends' | 'duplicate_backend' | 'unknown_backend' | 'no_usable_backend' | 'unsupported_message' | 'route_request_failed' | 'route_stream_error' | 'route_stream_truncated';
|
|
269
|
+
export declare class InferencePathError extends Error {
|
|
270
|
+
readonly code: InferencePathErrorCode;
|
|
271
|
+
constructor(message: string, code: InferencePathErrorCode);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Create the browser's single inference path over `options.backends`.
|
|
275
|
+
*
|
|
276
|
+
* Resolution happens inside every `chat`/`stream` call, so a `preference` or
|
|
277
|
+
* `select()` change made between calls is honored by the next one. A call
|
|
278
|
+
* whose resolution finds nothing usable throws `InferencePathError` with
|
|
279
|
+
* `code: 'no_usable_backend'` rather than falling back to a fake answer.
|
|
280
|
+
*/
|
|
281
|
+
export declare function createInferencePath(options: InferencePathOptions): InferencePath;
|
|
282
|
+
export interface RouteInferenceBackendOptions {
|
|
283
|
+
/** Full URL of a `text/event-stream` endpoint accepting `{ messages, session }`. */
|
|
284
|
+
endpoint: string;
|
|
285
|
+
/** Backend id. Defaults to `'route'`. */
|
|
286
|
+
id?: string;
|
|
287
|
+
/** Extra request headers, evaluated per call (auth tokens rotate). */
|
|
288
|
+
headers?: () => Record<string, string>;
|
|
289
|
+
/** Fetch credentials mode. Defaults to the platform default. */
|
|
290
|
+
credentials?: RequestCredentials;
|
|
291
|
+
/** Session metadata attached to the request body. */
|
|
292
|
+
session?: Record<string, unknown>;
|
|
293
|
+
/** Injectable fetch (tests, SSR-safe wrappers). */
|
|
294
|
+
fetchImpl?: typeof fetch;
|
|
295
|
+
/**
|
|
296
|
+
* Model id recorded on the returned `InferenceResponse`. Reporting only —
|
|
297
|
+
* the route resolves the model it actually uses, and a caller cannot widen
|
|
298
|
+
* it by naming one here (the generation caps live in the server-resolved
|
|
299
|
+
* stream context).
|
|
300
|
+
*/
|
|
301
|
+
model?: string;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Compose the caller's cancellation signal with this call's deadline, so a
|
|
305
|
+
* request with a `timeout` cannot outlive it even when no signal was passed.
|
|
306
|
+
*
|
|
307
|
+
* Exported so every backend that CAN cancel enforces `timeout` the same way: a
|
|
308
|
+
* deadline the route backend would have enforced must not be quietly ignored
|
|
309
|
+
* by a local one.
|
|
310
|
+
*/
|
|
311
|
+
export declare function requestSignal(chatOptions?: InferenceChatOptions): AbortSignal | undefined;
|
|
312
|
+
/**
|
|
313
|
+
* A backend over a `text/event-stream` inference route.
|
|
314
|
+
*
|
|
315
|
+
* The wire contract is `@happyvertical/smrt-chat`'s `ChatStreamEvent` framing
|
|
316
|
+
* (token deltas, then a terminal `done` or `error`), consumed here without
|
|
317
|
+
* depending on that package: smrt-web carries no inter-SMRT dependencies, so
|
|
318
|
+
* the frame vocabulary is mirrored the same way the rest of this module is.
|
|
319
|
+
*
|
|
320
|
+
* `status` is always `'ready'` — there is nothing to load — so an `auto` path
|
|
321
|
+
* picks this backend until a local one reports ready. It defines neither
|
|
322
|
+
* `load` nor `unload`, so a control must not offer those actions for it.
|
|
323
|
+
*
|
|
324
|
+
* A turn this wire cannot carry (tool turns, multimodal content, tool
|
|
325
|
+
* definitions) is REFUSED with `unsupported_message` rather than forwarded:
|
|
326
|
+
* the route silently drops those shapes, so forwarding would answer a
|
|
327
|
+
* different question than the caller asked.
|
|
328
|
+
*/
|
|
329
|
+
export declare function createRouteInferenceBackend(options: RouteInferenceBackendOptions): InferenceBackend;
|
|
330
|
+
//# sourceMappingURL=ai.d.ts.map
|