@jigs.design/server 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -14
- package/dist/chat.d.ts +2 -2
- package/dist/chat.js +46 -34
- package/dist/compile-cache.js +60 -0
- package/dist/compile.d.ts +1 -1
- package/dist/compile.js +169 -65
- package/dist/{server.d.ts → core.d.ts} +7 -3
- package/dist/{server.js → core.js} +310 -396
- package/dist/design.d.ts +6 -3
- package/dist/design.js +0 -1
- package/dist/errors.d.ts +3 -3
- package/dist/errors.js +3 -3
- package/dist/events.js +129 -0
- package/dist/handler.d.ts +4 -0
- package/dist/handler.js +344 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +3 -2
- package/dist/model-server.js +154 -0
- package/dist/outputs.js +2 -7
- package/dist/session.d.ts +1 -2
- package/dist/session.js +116 -52
- package/dist/types.d.ts +277 -51
- package/package.json +6 -5
package/dist/types.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { Advice, DesignCheckCode, Placement } from "./design.js";
|
|
|
2
2
|
import { ConfirmationStore } from "./confirm.js";
|
|
3
3
|
import { EditFailureReason } from "@jigs.design/compiler";
|
|
4
4
|
import { PromptMode } from "@jigs.design/prompt";
|
|
5
|
-
import { ActionDefinition, CallPolicy, Catalog, Host, InputOf, MutationDefinition, OutputOf, ProcedureDefinition, Procedures } from "@jigs.design/host";
|
|
6
|
-
import { ChatBlock, ChatBlockStatus, Diagnostic, Invalidation, JigsErrorData, Message, Program, SessionEvent } from "@jigs.design/
|
|
5
|
+
import { ActionDefinition, CallPolicy, Catalog, Host, InputOf, JigDefinition, MutationDefinition, OutputOf, PageName, ProcedureDefinition, Procedures, QueryDefinition } from "@jigs.design/host";
|
|
6
|
+
import { ChatBlock, ChatBlockStatus, Diagnostic, Invalidation, JigsErrorData, Message, PageInvalidation, PageProps, PageRef, Program, SessionEvent } from "@jigs.design/protocol";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
//#region src/types.d.ts
|
|
9
9
|
/**
|
|
@@ -25,7 +25,11 @@ export type ModelRequestKind = "chat-repair" | "repair" | "session";
|
|
|
25
25
|
export interface ModelRequest<TContext, TOptions> {
|
|
26
26
|
ctx: TContext;
|
|
27
27
|
kind: ModelRequestKind;
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* The conversation, with the server's repair turns added. In a session
|
|
30
|
+
* about a document, the last user message carries the current UI before
|
|
31
|
+
* the ask (`withDocument`), on every call.
|
|
32
|
+
*/
|
|
29
33
|
messages: ReadonlyArray<Message>;
|
|
30
34
|
options: TOptions;
|
|
31
35
|
signal: AbortSignal;
|
|
@@ -51,9 +55,10 @@ export interface TurnEdits {
|
|
|
51
55
|
blocks: number;
|
|
52
56
|
/**
|
|
53
57
|
* Why the first edit that failed did: its SEARCH text is not in the
|
|
54
|
-
* source (`"missing"`) or is there more than once (`"ambiguous"`),
|
|
55
|
-
*
|
|
56
|
-
*
|
|
58
|
+
* source (`"missing"`) or is there more than once (`"ambiguous"`), an
|
|
59
|
+
* earlier edit of the reply changes some of the same lines
|
|
60
|
+
* (`"overlapping"`), the block is broken (`"malformed"`), or the edit
|
|
61
|
+
* left a tag unclosed or closed one twice (`"broken"`).
|
|
57
62
|
*/
|
|
58
63
|
reason?: EditFailureReason;
|
|
59
64
|
}
|
|
@@ -110,6 +115,12 @@ export interface Turn<TContext, TOptions> {
|
|
|
110
115
|
ctx: TContext;
|
|
111
116
|
/** The diagnostics sent with `done`; empty when the turn did not finish. */
|
|
112
117
|
diagnostics: ReadonlyArray<Diagnostic>;
|
|
118
|
+
/**
|
|
119
|
+
* The source the turn started from, as the request carried it or the
|
|
120
|
+
* page it named resolved to; null when the turn wrote a new UI. A chat
|
|
121
|
+
* repair's is the block it repairs.
|
|
122
|
+
*/
|
|
123
|
+
document: string | null;
|
|
113
124
|
/**
|
|
114
125
|
* Milliseconds from the start of the turn to its first `program` event;
|
|
115
126
|
* null when it sent none. A chat repair sends its block once, when it is
|
|
@@ -118,6 +129,7 @@ export interface Turn<TContext, TOptions> {
|
|
|
118
129
|
firstProgramMs: number | null;
|
|
119
130
|
/** A session turn, or the repair of a chat block, which is a turn of its own. */
|
|
120
131
|
kind: "chat-repair" | "session";
|
|
132
|
+
/** The conversation as the request carried it, without the document. */
|
|
121
133
|
messages: ReadonlyArray<Message>;
|
|
122
134
|
options: TOptions;
|
|
123
135
|
/**
|
|
@@ -169,7 +181,10 @@ export type PolicyCall<TProcedures extends Procedures, TContext> = { [K in Mutat
|
|
|
169
181
|
* "confirmed" when it ran with the user's approval.
|
|
170
182
|
*/
|
|
171
183
|
export type CallReportOutcome = "confirmed" | "denied" | "error" | "requires-action" | "success";
|
|
172
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* One call to a query, mutation or action, or one page request, as
|
|
186
|
+
* `onCall` receives it.
|
|
187
|
+
*/
|
|
173
188
|
export interface CallReport<TContext> {
|
|
174
189
|
ctx: TContext;
|
|
175
190
|
/** From the call's arrival to its outcome, in milliseconds. */
|
|
@@ -181,26 +196,124 @@ export interface CallReport<TContext> {
|
|
|
181
196
|
* failed before its input parsed.
|
|
182
197
|
*/
|
|
183
198
|
input: unknown;
|
|
184
|
-
/**
|
|
185
|
-
|
|
199
|
+
/**
|
|
200
|
+
* The kind the call declared, or "page" for a page request on the wire,
|
|
201
|
+
* whose `input` is its props.
|
|
202
|
+
*/
|
|
203
|
+
kind: ProcedureDefinition["kind"] | "page";
|
|
186
204
|
name: string;
|
|
187
205
|
/**
|
|
188
|
-
* "denied" when a policy or a bad confirmation refused the call,
|
|
189
|
-
* for any other failure, including one
|
|
206
|
+
* "denied" when a policy or a bad confirmation refused the call, or
|
|
207
|
+
* `pagePolicy` a page; "error" for any other failure, including one
|
|
208
|
+
* `run` threw and a page no list has.
|
|
190
209
|
*/
|
|
191
210
|
outcome: CallReportOutcome;
|
|
192
211
|
}
|
|
212
|
+
/** The names of a host's queries. */
|
|
213
|
+
type QueryName<TProcedures extends Procedures> = { [K in keyof TProcedures & string]: TProcedures[K] extends QueryDefinition ? K : never; }[keyof TProcedures & string];
|
|
214
|
+
/**
|
|
215
|
+
* One query a push event refreshes, by name. `input` is typed against the
|
|
216
|
+
* query's input schema, as a mutation's scopes are, and the views' queries
|
|
217
|
+
* whose input contains it refetch; without it, every input does. It is a
|
|
218
|
+
* match key that every client the event reaches can read, never a record.
|
|
219
|
+
*/
|
|
220
|
+
export type PushInvalidation<TProcedures extends Procedures> = { [K in QueryName<TProcedures>]: {
|
|
221
|
+
input?: TProcedures[K]["input"] extends z.ZodType ? z.input<TProcedures[K]["input"]> : never;
|
|
222
|
+
name: K;
|
|
223
|
+
}; }[QueryName<TProcedures>];
|
|
224
|
+
/** Queries for one client's push stream to refetch. */
|
|
225
|
+
export interface PushInvalidate<TProcedures extends Procedures> {
|
|
226
|
+
invalidate: ReadonlyArray<PushInvalidation<TProcedures>>;
|
|
227
|
+
type: "invalidate";
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* One page a push event refreshes: a page of the host by its name, or, with
|
|
231
|
+
* `saved: true`, any name `resolvePage` may answer. Without `props`, every
|
|
232
|
+
* props of the page refetches; with them, the pages whose props contain
|
|
233
|
+
* them. `saved` stays on the server: the client sees `{ name, props }`.
|
|
234
|
+
*/
|
|
235
|
+
export type PushPage<TPageName extends string> = PageInvalidation<TPageName> | (PageInvalidation & {
|
|
236
|
+
saved: true;
|
|
237
|
+
});
|
|
238
|
+
/** Pages for one client's push stream to refetch, by name. */
|
|
239
|
+
export interface PushInvalidatePages<TPageName extends string> {
|
|
240
|
+
pages: ReadonlyArray<PushPage<TPageName>>;
|
|
241
|
+
type: "invalidate-pages";
|
|
242
|
+
}
|
|
243
|
+
/** What `send` writes to one client's push stream. */
|
|
244
|
+
export type PushSend<TProcedures extends Procedures, TPageName extends string> = PushInvalidate<TProcedures> | PushInvalidatePages<TPageName>;
|
|
245
|
+
/** One client's push stream, as the `events` option receives it. */
|
|
246
|
+
export interface EventSubscriber<TProcedures extends Procedures, TContext, TPageName extends string = string> {
|
|
247
|
+
/**
|
|
248
|
+
* Writes a `close` event and ends the stream, for a platform that caps how
|
|
249
|
+
* long a response may last: the client reconnects and, having been told,
|
|
250
|
+
* refetches nothing.
|
|
251
|
+
*/
|
|
252
|
+
close: () => void;
|
|
253
|
+
/** What `context` returned for the request that opened the stream. */
|
|
254
|
+
ctx: TContext;
|
|
255
|
+
/**
|
|
256
|
+
* Writes one event. `id` is yours (a log offset, a stream id), at most
|
|
257
|
+
* 200 printable characters; it comes back as `since` when the client
|
|
258
|
+
* reconnects. Give ids only if you replay from `since`: a client that
|
|
259
|
+
* resumed refetches nothing on its own. A send after the stream ended is
|
|
260
|
+
* ignored.
|
|
261
|
+
*/
|
|
262
|
+
send: (event: PushSend<TProcedures, TPageName>, options?: {
|
|
263
|
+
id?: string;
|
|
264
|
+
}) => void;
|
|
265
|
+
/** Aborts when the client leaves or the stream ends. */
|
|
266
|
+
signal: AbortSignal;
|
|
267
|
+
/**
|
|
268
|
+
* The `Last-Event-ID` the client reconnected with, or null: none, or one
|
|
269
|
+
* longer than 200 characters or with a character that is not printable.
|
|
270
|
+
*/
|
|
271
|
+
since: string | null;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* The host's push fan-out: subscribe `send` to your own source of changes
|
|
275
|
+
* (an in-process emitter, Postgres `LISTEN`, Redis) and return the
|
|
276
|
+
* unsubscribe, which runs once when the stream ends. Filter by `ctx`: every
|
|
277
|
+
* event you send reaches that client.
|
|
278
|
+
*/
|
|
279
|
+
export type EventsFunction<TProcedures extends Procedures, TContext, TPageName extends string = string> = (subscriber: EventSubscriber<TProcedures, TContext, TPageName>) => (() => void) | Promise<() => void>;
|
|
193
280
|
export interface ErrorInfo {
|
|
194
|
-
/** The procedure, for a call. */
|
|
281
|
+
/** The procedure, for a call; the page, for a page. */
|
|
195
282
|
name?: string;
|
|
196
|
-
/**
|
|
197
|
-
|
|
283
|
+
/**
|
|
284
|
+
* The request it came from: a call, a session turn, a chat turn with its
|
|
285
|
+
* repairs, the push stream, or a page (`jigs.page` or its wire request).
|
|
286
|
+
*/
|
|
287
|
+
type: "call" | "chat" | "events" | "page" | "session";
|
|
288
|
+
}
|
|
289
|
+
/** A page `resolvePage` found: the source as the app stored it. */
|
|
290
|
+
export interface SavedPage {
|
|
291
|
+
/** The source, with its pragma line when the app kept it. */
|
|
292
|
+
source: string;
|
|
198
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* Finds a page the host does not ship, by name, for the caller `ctx` names.
|
|
296
|
+
* `null` is "no such page for this caller". Runs on every request for the
|
|
297
|
+
* name; cache in it if the store is slow. Throw a `JigsError` to refuse.
|
|
298
|
+
*/
|
|
299
|
+
export type PageResolver<TContext> = (name: string, call: {
|
|
300
|
+
ctx: TContext;
|
|
301
|
+
signal?: AbortSignal;
|
|
302
|
+
}) => Promise<SavedPage | null> | SavedPage | null;
|
|
303
|
+
/**
|
|
304
|
+
* Whether a shipped page may be served on the wire to the caller `ctx`
|
|
305
|
+
* names. Saved pages are scoped by `resolvePage` instead.
|
|
306
|
+
*/
|
|
307
|
+
export type PagePolicy<TContext, TPageName extends string = string> = (page: {
|
|
308
|
+
ctx: TContext;
|
|
309
|
+
name: TPageName;
|
|
310
|
+
props: PageProps;
|
|
311
|
+
}) => "allow" | "deny";
|
|
199
312
|
/**
|
|
200
313
|
* `TContext` is inferred from `context`; `run` only reads it (`NoInfer`), so
|
|
201
314
|
* a mistake in one `run` function is reported at that function.
|
|
202
315
|
*/
|
|
203
|
-
export interface JigsServerOptions<TProcedures extends Procedures, TCatalog extends Catalog, TContext,
|
|
316
|
+
export interface JigsServerOptions<TProcedures extends Procedures, TCatalog extends Catalog, TContext, TJigs extends ReadonlyArray<JigDefinition> = ReadonlyArray<JigDefinition>> {
|
|
204
317
|
/** Origins whose views may call this server and embed its frame. */
|
|
205
318
|
allowedOrigins?: ReadonlyArray<string>;
|
|
206
319
|
/**
|
|
@@ -221,12 +334,12 @@ export interface JigsServerOptions<TProcedures extends Procedures, TCatalog exte
|
|
|
221
334
|
*/
|
|
222
335
|
context: ContextFunction<TContext>;
|
|
223
336
|
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
337
|
+
* Opens the push stream: a `GET` to the handler with `Accept:
|
|
338
|
+
* text/event-stream`, after `context`. Without it, that `GET` answers
|
|
339
|
+
* `204` and the client stops asking. See `EventsFunction`.
|
|
227
340
|
*/
|
|
228
|
-
|
|
229
|
-
host: Host<TProcedures, TCatalog>;
|
|
341
|
+
events?: EventsFunction<NoInfer<TProcedures>, NoInfer<TContext>, NoInfer<PageName<TJigs>>>;
|
|
342
|
+
host: Host<TProcedures, TCatalog, TJigs>;
|
|
230
343
|
/**
|
|
231
344
|
* The app's own instructions to the model, such as its persona, today's
|
|
232
345
|
* date or its safety rules. Every prompt carries them: document-mode
|
|
@@ -235,23 +348,26 @@ export interface JigsServerOptions<TProcedures extends Procedures, TCatalog exte
|
|
|
235
348
|
instructions?: string;
|
|
236
349
|
/** The largest request body accepted, in bytes. Default 1,000,000. */
|
|
237
350
|
maxBodyBytes?: number;
|
|
238
|
-
/** Repair rounds after a turn that ends with errors. Default 1. */
|
|
239
|
-
maxRepairs?: number;
|
|
240
|
-
model?: ModelFunction<TContext, TOptions>;
|
|
241
351
|
/** The clock confirmation tokens expire by, in ms since the epoch. Default `Date.now`. */
|
|
242
352
|
now?: () => number;
|
|
243
353
|
/**
|
|
244
354
|
* Runs after every call to a query, mutation or action, including ones
|
|
245
|
-
* refused before `run
|
|
355
|
+
* refused before `run`, and after every page request on the wire, with
|
|
356
|
+
* `kind: "page"`, so both can be audited and rate-limited by `ctx`. The response does not wait for it, and a value it
|
|
246
357
|
* throws or rejects with goes to `onError`.
|
|
247
358
|
*/
|
|
248
359
|
onCall?: (call: CallReport<NoInfer<TContext>>) => Promise<void> | void;
|
|
249
360
|
onError?: (cause: unknown, info: ErrorInfo) => void;
|
|
250
|
-
onTurn?: (turn: Turn<TContext, TOptions>) => Promise<void> | void;
|
|
251
|
-
/** Schema for the app options sent with each turn. */
|
|
252
|
-
options?: z.ZodType<TOptions>;
|
|
253
361
|
/** This server's origin, when the request URL does not show it (behind a proxy). */
|
|
254
362
|
origin?: string;
|
|
363
|
+
/**
|
|
364
|
+
* Decides whether a shipped page is served on the wire (`POST { type:
|
|
365
|
+
* "page" }`) to this `ctx`, after `context` and before any compile.
|
|
366
|
+
* "deny" answers `NOT_FOUND`, as for a page no list has. Default: every
|
|
367
|
+
* page to everyone `context` admits. A value it throws, or anything but
|
|
368
|
+
* "allow" or "deny", goes to `onError` and the page is denied.
|
|
369
|
+
*/
|
|
370
|
+
pagePolicy?: PagePolicy<NoInfer<TContext>, PageName<TJigs>>;
|
|
255
371
|
/**
|
|
256
372
|
* Decides a mutation call's policy from its `ctx` and parsed input, after
|
|
257
373
|
* the input parses and before `run`; `undefined` keeps the host's. A
|
|
@@ -259,13 +375,12 @@ export interface JigsServerOptions<TProcedures extends Procedures, TCatalog exte
|
|
|
259
375
|
*/
|
|
260
376
|
policy?: (call: PolicyCall<NoInfer<TProcedures>, NoInfer<TContext>>) => CallPolicy | undefined;
|
|
261
377
|
/**
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
* program always goes out. Default 250; 0 sends every change.
|
|
378
|
+
* Answers `page(name, props, { ctx })` and the wire's page requests for a
|
|
379
|
+
* name the host does not have, such as a page a user saved. A name on
|
|
380
|
+
* the host never reaches it. Saved pages compile leniently unless the
|
|
381
|
+
* call says `strict`. See `PageResolver`.
|
|
267
382
|
*/
|
|
268
|
-
|
|
383
|
+
resolvePage?: PageResolver<NoInfer<TContext>>;
|
|
269
384
|
run: RunFunctions<NoInfer<TProcedures>, NoInfer<TContext>>;
|
|
270
385
|
/**
|
|
271
386
|
* Signs confirmation tokens, at least 32 characters; keep it out of the
|
|
@@ -273,11 +388,33 @@ export interface JigsServerOptions<TProcedures extends Procedures, TCatalog exte
|
|
|
273
388
|
* "confirm": the server refuses to start without it.
|
|
274
389
|
*/
|
|
275
390
|
secret?: string;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* What `withModel` takes: everything that exists only because a model does.
|
|
394
|
+
* `TContext` is already the core's, so `ctx` is typed inside `model` and
|
|
395
|
+
* `onTurn` with no inference of its own.
|
|
396
|
+
*/
|
|
397
|
+
export interface ModelOptions<TContext, TOptions> {
|
|
276
398
|
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
399
|
+
* Design checks whose advice gets a repair round, as errors do: at most
|
|
400
|
+
* one per turn or chat block, within `maxRepairs`. Default none, since a
|
|
401
|
+
* repair round is a full model call.
|
|
279
402
|
*/
|
|
280
|
-
|
|
403
|
+
designRepair?: ReadonlyArray<DesignCheckCode>;
|
|
404
|
+
/** Repair rounds after a turn that ends with errors. Default 1. */
|
|
405
|
+
maxRepairs?: number;
|
|
406
|
+
model: ModelFunction<TContext, TOptions>;
|
|
407
|
+
onTurn?: (turn: Turn<TContext, TOptions>) => Promise<void> | void;
|
|
408
|
+
/** Schema for the app options sent with each turn. */
|
|
409
|
+
options?: z.ZodType<TOptions>;
|
|
410
|
+
/**
|
|
411
|
+
* While a reply streams, the least time between two program updates, in
|
|
412
|
+
* ms. Each update carries the whole program, so a long reply that changed
|
|
413
|
+
* it at every line sent it hundreds of times. The first program goes out
|
|
414
|
+
* at once, a newer one replaces one still waiting, and the reply's last
|
|
415
|
+
* program always goes out. Default 250; 0 sends every change.
|
|
416
|
+
*/
|
|
417
|
+
programIntervalMs?: number;
|
|
281
418
|
}
|
|
282
419
|
export interface CompileOptions {
|
|
283
420
|
/**
|
|
@@ -328,14 +465,20 @@ export interface CallRequest {
|
|
|
328
465
|
name: string;
|
|
329
466
|
}
|
|
330
467
|
export interface SessionRequest {
|
|
331
|
-
/**
|
|
468
|
+
/**
|
|
469
|
+
* Plain JSON from the browser: `{ source }`, or `{ name, props? }` for a
|
|
470
|
+
* page the server serves, opened as a document. Absent for a new UI.
|
|
471
|
+
*/
|
|
472
|
+
document?: unknown;
|
|
473
|
+
/** Plain JSON from the browser; parsed with the session schema. */
|
|
332
474
|
messages: unknown;
|
|
333
475
|
/** Plain JSON from the browser; parsed with the `options` schema. */
|
|
334
476
|
options?: unknown;
|
|
335
477
|
}
|
|
336
478
|
/** An earlier block of the conversation, as the chat stored it. */
|
|
337
479
|
export interface ChatBlockSource {
|
|
338
|
-
id
|
|
480
|
+
/** The block's name, the fence id. */
|
|
481
|
+
name: string;
|
|
339
482
|
/** Its checked source; with or without the pragma line. */
|
|
340
483
|
source: string;
|
|
341
484
|
}
|
|
@@ -359,16 +502,19 @@ export interface ChatBlockResult {
|
|
|
359
502
|
/** Set when the block was SEARCH/REPLACE edits to an earlier block. */
|
|
360
503
|
edits?: TurnEdits;
|
|
361
504
|
/**
|
|
362
|
-
* Set when the block is done without a program of its own: an edit to
|
|
363
|
-
*
|
|
505
|
+
* Set when the block is done without a program of its own: an edit to a
|
|
506
|
+
* name the conversation does not have (`NOT_FOUND`), a block past the
|
|
364
507
|
* reply's limit (`RATE_LIMITED`), or an edit or repair that failed
|
|
365
508
|
* (`INTERNAL`). The same error the block carries.
|
|
366
509
|
*/
|
|
367
510
|
error?: JigsErrorData;
|
|
368
511
|
/** False for Jigs the model wrote without a fence. */
|
|
369
512
|
fenced: boolean;
|
|
370
|
-
id: string;
|
|
371
513
|
key: string;
|
|
514
|
+
/** The block's name, the fence id. */
|
|
515
|
+
name: string;
|
|
516
|
+
/** Set when the block is one tag naming a page, as on the block. */
|
|
517
|
+
ref?: PageRef;
|
|
372
518
|
/**
|
|
373
519
|
* The rounds of the block's repair, the ones its "chat-repair" turn gives
|
|
374
520
|
* `onTurn`; empty when it had none. The last one's diagnostics are the
|
|
@@ -437,15 +583,58 @@ export interface ChatTurn {
|
|
|
437
583
|
/** The start of `system` that is the same on every turn, as on `ModelRequest`. */
|
|
438
584
|
systemPrefix: string;
|
|
439
585
|
}
|
|
440
|
-
|
|
441
|
-
|
|
586
|
+
/** A page, compiled, and what the checks said about it. */
|
|
587
|
+
export interface ResolvedPage {
|
|
588
|
+
/** The design checks' advice, numbered like `diagnostics`. */
|
|
589
|
+
advice: ReadonlyArray<Advice>;
|
|
442
590
|
/**
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
* failure rejects with a `JigsError`. See `ChatTurn`.
|
|
591
|
+
* Never an error or warning for a shipped page, or a saved one compiled
|
|
592
|
+
* with `strict`. A saved page is lenient by default: these say what
|
|
593
|
+
* broke, beside a program that still runs. Show a notice when one is.
|
|
447
594
|
*/
|
|
448
|
-
|
|
595
|
+
diagnostics: ReadonlyArray<Diagnostic>;
|
|
596
|
+
/** "shipped": a jig listed on the host; "saved": one `resolvePage` found. */
|
|
597
|
+
origin: "saved" | "shipped";
|
|
598
|
+
program: Program;
|
|
599
|
+
/**
|
|
600
|
+
* What was compiled: a document page's source, or a define page's
|
|
601
|
+
* one-tag use, such as `<orders status={"open"}/>`.
|
|
602
|
+
*/
|
|
603
|
+
source: string;
|
|
604
|
+
}
|
|
605
|
+
/** How `page` finds a name the host may not ship: through `resolvePage`, for `ctx`. */
|
|
606
|
+
export interface PageCall<TContext> {
|
|
607
|
+
ctx: TContext;
|
|
608
|
+
signal?: AbortSignal;
|
|
609
|
+
/**
|
|
610
|
+
* Reject with a `JigsCompileError` when a saved page has an error or
|
|
611
|
+
* warning diagnostic, instead of resolving with them. Default false. A
|
|
612
|
+
* shipped page is always strict.
|
|
613
|
+
*/
|
|
614
|
+
strict?: boolean;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* A page by name: a shipped one with only a name and props, or any name
|
|
618
|
+
* with `{ ctx }`, which may ask `resolvePage`.
|
|
619
|
+
*/
|
|
620
|
+
export interface PageFunction<TContext, TPageName extends string> {
|
|
621
|
+
/**
|
|
622
|
+
* A shipped page. Rejects with a `JigsError` whose code is `BAD_INPUT`
|
|
623
|
+
* when the props are not the define's, so a route that takes props from
|
|
624
|
+
* a URL answers 400.
|
|
625
|
+
*/
|
|
626
|
+
(name: TPageName, props?: PageProps, call?: {
|
|
627
|
+
signal?: AbortSignal;
|
|
628
|
+
}): Promise<ResolvedPage>;
|
|
629
|
+
/**
|
|
630
|
+
* Any name: a shipped page wins and never asks `resolvePage`; otherwise
|
|
631
|
+
* `resolvePage` with `ctx`. Null when neither has it. A saved page takes
|
|
632
|
+
* no props (`BAD_INPUT`).
|
|
633
|
+
*/
|
|
634
|
+
(name: string, props: PageProps | undefined, call: PageCall<TContext>): Promise<ResolvedPage | null>;
|
|
635
|
+
}
|
|
636
|
+
export interface JigsServer<TContext, TPageName extends string = never> {
|
|
637
|
+
call: (request: CallRequest, context: CallContext<TContext>) => Promise<CallOutcome>;
|
|
449
638
|
/** Checks and compiles a source with no model. Strict unless told otherwise. */
|
|
450
639
|
compile: (source: string, options?: CompileOptions) => Promise<{
|
|
451
640
|
/** The design checks' advice, numbered like `diagnostics`. */
|
|
@@ -453,11 +642,30 @@ export interface JigsServer<TContext, TSpecName extends string = never> {
|
|
|
453
642
|
diagnostics: ReadonlyArray<Diagnostic>;
|
|
454
643
|
program: Program;
|
|
455
644
|
}>;
|
|
645
|
+
/**
|
|
646
|
+
* The push stream for `request`, whose `ctx` the caller already has: a
|
|
647
|
+
* foreign `Origin` is `403`, a server without `events` answers `204`, and
|
|
648
|
+
* an `events` that throws is `500`. `handler` does this for a `GET` that
|
|
649
|
+
* accepts `text/event-stream`, after `context`.
|
|
650
|
+
*/
|
|
651
|
+
events: (request: Request, context: CallContext<TContext>) => Promise<Response>;
|
|
456
652
|
/** The sandbox frame document, with its own content security policy. */
|
|
457
653
|
frame: (request?: Request) => Response;
|
|
654
|
+
/**
|
|
655
|
+
* Serves the frame, the push stream, calls, pages and session turns. Without `withModel`, a
|
|
656
|
+
* session turn that would ask the model answers `404 NOT_FOUND`; one
|
|
657
|
+
* that carries a document and no ask is still compiled and streamed.
|
|
658
|
+
*/
|
|
458
659
|
handler: (request: Request) => Promise<Response>;
|
|
459
660
|
/** The largest request body `handler` accepts, in bytes. */
|
|
460
661
|
maxBodyBytes: number;
|
|
662
|
+
/**
|
|
663
|
+
* A page, compiled: a jig with `page: true`, by its name, with the props
|
|
664
|
+
* its `<define>` declares, or with `{ ctx }`, a page `resolvePage` finds.
|
|
665
|
+
* Shipped pages that need no props compile at startup, and every shipped
|
|
666
|
+
* page compiles strictly. See `PageFunction`.
|
|
667
|
+
*/
|
|
668
|
+
page: PageFunction<TContext, TPageName>;
|
|
461
669
|
/**
|
|
462
670
|
* The system prompt for this host. "document" (default) is what sessions
|
|
463
671
|
* use: every reply is one UI. "chat" is Markdown with UIs in fenced
|
|
@@ -471,11 +679,29 @@ export interface JigsServer<TContext, TSpecName extends string = never> {
|
|
|
471
679
|
* `@jigs.design/ai-sdk`).
|
|
472
680
|
*/
|
|
473
681
|
promptPrefix: (mode?: PromptMode) => string;
|
|
474
|
-
session: (body: SessionRequest, context: CallContext<TContext>) => AsyncIterable<SessionEvent>;
|
|
475
|
-
/** A spec from `specs`, compiled at startup. */
|
|
476
|
-
spec: (name: TSpecName) => Program;
|
|
477
682
|
/** Changes whenever the compiler, the runtime or the host does. */
|
|
478
683
|
version: string;
|
|
684
|
+
/**
|
|
685
|
+
* This server with a model: the same core, plus `session` and `chat`,
|
|
686
|
+
* and a handler that runs session turns that ask the model.
|
|
687
|
+
*/
|
|
688
|
+
withModel: <TOptions = undefined>(options: ModelOptions<TContext, TOptions>) => JigsModelServer<TContext, TPageName>;
|
|
689
|
+
}
|
|
690
|
+
/** What `withModel` returns: the core, plus the turns that call the model. */
|
|
691
|
+
export interface JigsModelServer<TContext, TPageName extends string = never> extends Omit<JigsServer<TContext, TPageName>, "withModel"> {
|
|
692
|
+
/**
|
|
693
|
+
* Starts a chat reply for `request`. It refuses the request as `handler`
|
|
694
|
+
* would (an `Origin` that may not call this server, or a body that is not
|
|
695
|
+
* JSON), then runs `context` and parses `blocks` and `options`. Each
|
|
696
|
+
* failure rejects with a `JigsError`. See `ChatTurn`.
|
|
697
|
+
*/
|
|
698
|
+
chat: (request: Request, options?: ChatOptions) => Promise<ChatTurn>;
|
|
699
|
+
/**
|
|
700
|
+
* One session turn: a document whose conversation does not end with an
|
|
701
|
+
* ask is compiled again with no model call; otherwise the model answers,
|
|
702
|
+
* editing the document when there is one.
|
|
703
|
+
*/
|
|
704
|
+
session: (body: SessionRequest, context: CallContext<TContext>) => AsyncIterable<SessionEvent>;
|
|
479
705
|
}
|
|
480
706
|
//#endregion
|
|
481
707
|
export type { EditFailureReason };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jigs.design/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "createJigsServer: checks and streams programs, runs procedures, and serves the sandbox frame.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,10 +29,11 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@jigs.design/
|
|
33
|
-
"@jigs.design/prompt": "0.
|
|
34
|
-
"@jigs.design/
|
|
35
|
-
"@jigs.design/runtime": "0.
|
|
32
|
+
"@jigs.design/compiler": "0.3.0",
|
|
33
|
+
"@jigs.design/prompt": "0.3.0",
|
|
34
|
+
"@jigs.design/protocol": "0.3.0",
|
|
35
|
+
"@jigs.design/runtime": "0.3.0",
|
|
36
|
+
"@jigs.design/host": "0.3.0"
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|
|
38
39
|
"zod": "^4.0.0"
|