@sigrun/shared 0.1.1 → 0.2.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +1 -1
  3. package/dist/access.d.ts +0 -55
  4. package/dist/access.js +0 -72
  5. package/dist/ambient.d.ts +0 -111
  6. package/dist/ambient.js +0 -23
  7. package/dist/blocks/format.d.ts +0 -28
  8. package/dist/blocks/format.js +0 -199
  9. package/dist/blocks/icons.d.ts +0 -12
  10. package/dist/blocks/icons.js +0 -64
  11. package/dist/blocks/index.d.ts +0 -24
  12. package/dist/blocks/index.js +0 -20
  13. package/dist/blocks/lttb.d.ts +0 -16
  14. package/dist/blocks/lttb.js +0 -67
  15. package/dist/blocks/ops.d.ts +0 -44
  16. package/dist/blocks/ops.js +0 -294
  17. package/dist/blocks/text.d.ts +0 -43
  18. package/dist/blocks/text.js +0 -790
  19. package/dist/blocks/transport.d.ts +0 -77
  20. package/dist/blocks/transport.js +0 -11
  21. package/dist/blocks/types.d.ts +0 -541
  22. package/dist/blocks/types.js +0 -17
  23. package/dist/commands.d.ts +0 -75
  24. package/dist/commands.js +0 -25
  25. package/dist/conversations.d.ts +0 -31
  26. package/dist/conversations.js +0 -94
  27. package/dist/interactions.d.ts +0 -91
  28. package/dist/interactions.js +0 -21
  29. package/dist/jobs.d.ts +0 -109
  30. package/dist/jobs.js +0 -19
  31. package/dist/json.d.ts +0 -20
  32. package/dist/json.js +0 -13
  33. package/dist/live.d.ts +0 -71
  34. package/dist/live.js +0 -82
  35. package/dist/session-meta.d.ts +0 -119
  36. package/dist/session-meta.js +0 -13
  37. package/dist/settings.d.ts +0 -408
  38. package/dist/settings.js +0 -19
  39. package/dist/themes.d.ts +0 -50
  40. package/dist/themes.js +0 -156
  41. package/dist/turns.d.ts +0 -119
  42. package/dist/turns.js +0 -197
  43. package/dist/view-delta.d.ts +0 -54
  44. package/dist/view-delta.js +0 -135
  45. package/dist/views.d.ts +0 -784
  46. package/dist/views.js +0 -38
package/dist/views.d.ts DELETED
@@ -1,784 +0,0 @@
1
- /**
2
- * §5 wire types (Tasks 9a–9d) — THE channel contract.
3
- *
4
- * Every HTTP/SSE payload shape both clients (webui, tui) consume is
5
- * declared or re-exported here, and both import it directly (the tui
6
- * imports from `@sigrun/shared`, never from server source). It is the
7
- * intended basis for a generated OpenAPI schema later, so the purity
8
- * rules are enforced by `test/views-purity.test.ts`:
9
- *
10
- * - imports and re-exports are `import type`/`export type` from SIBLING
11
- * shared modules only, and type-only — they erase at compile time and
12
- * contribute no runtime (the only runtime exports here are local pure
13
- * constants);
14
- * - no external package imports, no server/framework types, no route
15
- * logic (the server's `src/server/views.ts` owns the RUNTIME
16
- * serializer and re-exports this module);
17
- * - no `node:` imports (the webui compiles DOM-only against this file).
18
- *
19
- * Spec §5: the server serves pi-durable's NATIVE views, not a bespoke
20
- * endpoint list — so the conversation wire payload IS the view shape
21
- * (`{ conversation, entries, docs }`; JSON-safe by construction) PLUS
22
- * the sigrun-side `steer` field. The upstream view's inner shapes are
23
- * re-declared STRUCTURALLY below (`ViewConversation`, `ViewEntry`,
24
- * `ViewMessage`, `WireBlock`): deliberately loose where channels only
25
- * read a subset, and structurally compatible with the upstream types so
26
- * the server's serializer (which spreads an upstream
27
- * `ConversationView`) typechecks against this declaration — the
28
- * captured-schema fixture (`src/server/schema-fixture.ts`,
29
- * `view-schema.json`) pins the UPSTREAM shape, and
30
- * `test/schema-drift.test.ts` trips on upstream drift.
31
- *
32
- * `serializeConversationView` (src/server/views.ts) is the single
33
- * chokepoint every §5 endpoint that returns a conversation goes through
34
- * — including each SSE watch frame (T9d) — so the fixture continues to
35
- * describe the wire.
36
- */
37
- import type { JsonObject } from "./json.js";
38
- import type { Sharing } from "./access.js";
39
- import type { JobWire } from "./jobs.js";
40
- import type { InteractionAnswer, InteractionBody, InteractionDiff, InteractionField, InteractionOption, InteractionRecord, InteractionStatus } from "./interactions.js";
41
- import type { AmbientBody, AmbientGauge, AmbientLedgerEntry, AmbientLine, AmbientMetrics, AmbientRecord, AmbientRow } from "./ambient.js";
42
- import type { EffectiveServerSetting, SettingsFile } from "./settings.js";
43
- /** A model reference as served on the wire (pi-durable `ModelRef`). */
44
- export interface ModelRefWire {
45
- readonly provider: string;
46
- readonly modelId: string;
47
- }
48
- /** A model's thinking level (pi-ai `ModelThinkingLevel` union). */
49
- export type ThinkingLevelWire = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
50
- /** One content block of a message (`{type: "text", text}`, `{type:
51
- * "thinking", thinking}`, image/file parts, tool calls) — the loose
52
- * block shape every renderer dispatches on. */
53
- export interface WireBlock {
54
- readonly type: string;
55
- readonly text?: string;
56
- /** The thinking text on `{type: "thinking"}` blocks. */
57
- readonly thinking?: string;
58
- /** Tool-call identity on `{type: "toolCall"}` blocks. */
59
- readonly id?: string;
60
- readonly name?: string;
61
- readonly arguments?: unknown;
62
- }
63
- /** One model message carried by a view entry (pi-ai JSON shape). */
64
- export interface ViewMessage {
65
- readonly role: string;
66
- readonly content: string | readonly WireBlock[];
67
- /** Tool correlation — present on `toolResult`-role messages. */
68
- readonly toolName?: string;
69
- readonly toolCallId?: string;
70
- readonly isError?: boolean;
71
- }
72
- /** One entry of the view's entry list. */
73
- export interface ViewEntry {
74
- readonly id: number;
75
- readonly conversationId?: number;
76
- /** Application-defined entry discriminator (`pi.user`, `pi.assistant`, …). */
77
- readonly kind: string;
78
- /** Messages contributed to model context; absent on display/bookkeeping entries. */
79
- readonly model?: readonly ViewMessage[];
80
- /** The entry's kind-specific JSON payload, when it carries one. */
81
- readonly data?: unknown;
82
- }
83
- /** One conversation as pi-durable serves it (the upstream view). */
84
- export interface ViewConversation {
85
- readonly id: number;
86
- /** Fork lineage (the upstream `parent`), when this conversation is a fork. */
87
- readonly parent?: {
88
- readonly conversationId?: number;
89
- readonly at?: number;
90
- };
91
- /** Creator edge, when the conversation was produced by durable work. */
92
- readonly owner?: unknown;
93
- }
94
- /** The upstream view, as the channel reads it. */
95
- export interface ConversationViewBase {
96
- readonly conversation: ViewConversation;
97
- readonly entries: readonly ViewEntry[];
98
- /** Built-in conversation documents keyed by kind; absent documents are absent. */
99
- readonly docs: Readonly<Record<string, JsonObject>>;
100
- }
101
- /**
102
- * The per-conversation steer field (spec §5: "reflecting submit-while-busy
103
- * queue semantics"). `busy` = a run is live; `queued` = submissions
104
- * waiting in the inbox behind it.
105
- */
106
- export interface SteerField {
107
- readonly busy: boolean;
108
- readonly queued: number;
109
- }
110
- /**
111
- * One conversation as served over the wire: the upstream view plus the
112
- * derived `steer` field (see the server's
113
- * `serializeConversationView` — every §5 endpoint that returns a
114
- * conversation, including each SSE watch frame, goes through it).
115
- */
116
- export type ConversationViewWire = ConversationViewBase & {
117
- readonly steer: SteerField;
118
- };
119
- /** One list item of `GET /v1/conversations` (Task 9a: ids, not full views). */
120
- export interface ConversationSummary {
121
- readonly id: number;
122
- /** The conversation this summary describes is the reserved root. */
123
- readonly root: boolean;
124
- /**
125
- * The conversation's session-meta owner, when stamped (Task 2's
126
- * `X-Sigrun-User` seam — Task 3 surfaced it here so a picker can show
127
- * who owns what). Absent when the doc never carried one.
128
- */
129
- readonly owner?: string;
130
- /**
131
- * The display name: the user's `meta.name`, else the server-owned
132
- * `meta.autoName` (A2's auto-namer). Absent when neither was written.
133
- */
134
- readonly name?: string;
135
- /**
136
- * The server-owned auto-generated name (A2), when written and no user
137
- * `name` overrides it. Surfaced so `conversation.changed` events can
138
- * report an auto-name landing without a user edit.
139
- */
140
- readonly autoName?: string;
141
- /**
142
- * The session-meta source — who created the session (spec §9.5):
143
- * `"user"` for HTTP creates, the extension slug for channel-bridge
144
- * creates through `host.conversations`. Absent when the doc was never
145
- * written (defaults are free).
146
- */
147
- readonly source?: string;
148
- /**
149
- * The last activity instant, ISO 8601 (activity.ts stamps it at
150
- * submission admission and run settlement). Absent on a conversation
151
- * that was never used.
152
- */
153
- readonly lastActivityAt?: string;
154
- /**
155
- * Fork lineage: the source conversation id and the entry the history
156
- * was forked at, when this conversation is a fork. Absent on a root
157
- * or plainly created conversation.
158
- */
159
- readonly parent?: {
160
- readonly id: number;
161
- readonly at: number;
162
- };
163
- /** The session-meta archive flag (the sidebar's hide), default false. */
164
- readonly archived: boolean;
165
- /** The session-meta pin flag (pinned conversations float to top), default false. */
166
- readonly pinned: boolean;
167
- /**
168
- * The §5.9 sharing state, when the conversation carries one (absent =
169
- * private). Surfaced so a picker can show what is shared.
170
- */
171
- readonly sharing?: Sharing;
172
- /**
173
- * THIS caller's resolved access to the conversation (§5.9 `accessOf`):
174
- * conversations the caller cannot see are filtered from the list
175
- * entirely, so every listed row is at least `read`.
176
- */
177
- readonly access: "read" | "write";
178
- }
179
- /** The list response of `GET /v1/conversations`. */
180
- export interface ConversationList {
181
- readonly conversations: readonly ConversationSummary[];
182
- }
183
- /** The create response of `POST /v1/conversations`. */
184
- export interface ConversationCreateResponse {
185
- readonly id: number;
186
- readonly view: ConversationViewWire;
187
- }
188
- /** `GET /v1/jobs`: the caller-visible jobs (`accessOf ≠ "none"`), each row
189
- * carrying the caller's resolved `access`. */
190
- export interface JobsResponse {
191
- readonly jobs: readonly JobWire[];
192
- }
193
- /** `POST /v1/jobs/:id/run`: the fire outcome plus the run's conversation
194
- * when one exists (a skipped/blocked fire may have none). */
195
- export interface JobRunResponse {
196
- readonly outcome: "running" | "skipped" | "blocked";
197
- readonly conversationId?: number;
198
- }
199
- /** The `Content-Type` of the JSONL export/import wire (Task 5b/5c). */
200
- export declare const JSONL_CONTENT_TYPE = "application/x-ndjson";
201
- /**
202
- * The fork response of `POST /v1/conversations/:id/fork` (Task 5a): the
203
- * create shape — a NEW conversation id plus its first view frame.
204
- */
205
- export type ConversationForkResponse = ConversationCreateResponse;
206
- /**
207
- * The import response of `POST /v1/conversations/import` (Task 5c): the
208
- * create shape — the new conversation id plus its view with the appended
209
- * entries in order.
210
- */
211
- export type ConversationImportResponse = ConversationCreateResponse;
212
- /**
213
- * The durable submission record on the wire (§7.1): the record as it
214
- * stands when read — `status` is `queued` | `placed` | `done` |
215
- * `unanswered`; `entry`/`answer`/`reason`/`detail` appear per status.
216
- */
217
- export interface SubmissionRecordWire {
218
- readonly id: number;
219
- readonly conversationId: number;
220
- /** Host-provided deduplication key, scoped to the conversation. */
221
- readonly requestId?: string;
222
- readonly type: string;
223
- readonly status: string;
224
- readonly entry?: number;
225
- readonly answer?: number;
226
- readonly reason?: string;
227
- readonly detail?: unknown;
228
- }
229
- /**
230
- * The admit response of `POST /v1/conversations/:id/submissions` (§7.1):
231
- * `202 {submission}` AT ADMISSION — the record as it stands the moment
232
- * the submission is admitted. `?waitMs=<n>` (a positive int ≤ 60 000)
233
- * opts into a bounded settlement wait; `GET …/submissions/:submissionId`
234
- * polls the record later.
235
- */
236
- export interface SubmissionResponse {
237
- readonly submission: SubmissionRecordWire;
238
- }
239
- /** The upload response of `POST /v1/conversations/:id/uploads` (Task 9b). */
240
- export interface UploadResponse {
241
- /** The workspace-relative path to use in submission content parts. */
242
- readonly path: string;
243
- }
244
- /** One `GET /v1/conversations/:id/files` entry (upstream `FileInfo`). */
245
- export interface FileEntry {
246
- readonly name: string;
247
- readonly path: string;
248
- readonly kind: "file" | "directory" | "symlink";
249
- readonly size: number;
250
- readonly mtimeMs: number;
251
- }
252
- /** The list response of `GET /v1/conversations/:id/files` (Task 9b). */
253
- export interface FileListResponse {
254
- readonly entries: readonly FileEntry[];
255
- }
256
- /** The read response of `GET /v1/conversations/:id/files/content`. */
257
- export interface FileContentResponse {
258
- /** `"text"` (valid UTF-8) or `"base64"` (binary). */
259
- readonly encoding: "text" | "base64";
260
- readonly content: string;
261
- /** Size in bytes. */
262
- readonly size: number;
263
- }
264
- /** One `GET /v1/models` entry (Task 9b): picker fields, no provider internals. */
265
- export interface ModelEntry {
266
- /** `"provider/modelId"` — the id submission/configure `model` takes. */
267
- readonly id: string;
268
- readonly provider: string;
269
- readonly modelId: string;
270
- readonly name: string;
271
- readonly contextWindow: number;
272
- readonly maxTokens: number;
273
- readonly reasoning: boolean;
274
- readonly input: readonly string[];
275
- readonly cost: {
276
- readonly input: number;
277
- readonly output: number;
278
- readonly cacheRead: number;
279
- readonly cacheWrite: number;
280
- };
281
- }
282
- /** The response of `GET /v1/models`. */
283
- export interface ModelsResponse {
284
- readonly models: readonly ModelEntry[];
285
- }
286
- /** The configured agent surface `POST .../configure` returns (T9c-i). */
287
- export interface ConfigureResponse {
288
- /** Absent when unset — no model means no generation. */
289
- readonly model?: ModelRefWire;
290
- readonly thinkingLevel: ThinkingLevelWire;
291
- }
292
- /** The result mapping `POST .../abort` returns (T9c-i). */
293
- export type AbortResponse = {
294
- readonly result: "aborted";
295
- readonly submissionId: number;
296
- } | {
297
- readonly result: "already_placed";
298
- readonly submissionId: number;
299
- } | {
300
- readonly result: "settled";
301
- readonly submissionId: number;
302
- };
303
- /**
304
- * The admit response of `POST /v1/conversations/:id/compact` (Task 4, pi
305
- * parity): the durable compaction task's id. The task is conversation-owned
306
- * (manual): it compacts even when idle and places its summary through a
307
- * write submission; the SSE stream carries the `pi.compaction` entry.
308
- */
309
- export interface CompactResponse {
310
- readonly taskId: number;
311
- }
312
- /** One interaction record on the wire (the envelope + body + details). */
313
- export type InteractionWire = InteractionRecord;
314
- /** The response of `GET /v1/conversations/:id/interactions`. */
315
- export interface InteractionList {
316
- readonly interactions: readonly InteractionWire[];
317
- }
318
- /**
319
- * One pending interaction in the cross-conversation inbox (§7.5): the
320
- * record plus the conversation it waits in, so a client can answer
321
- * without opening each conversation (answers still go through the
322
- * per-conversation answer route).
323
- */
324
- export type InboxInteraction = InteractionWire & {
325
- readonly conversationId: number;
326
- };
327
- /**
328
- * The response of `GET /v1/interactions?status=pending` (§7.5): every
329
- * pending interaction in a conversation the caller can see, sorted by
330
- * `createdAt` ascending. `pending` is the only indexed (and accepted)
331
- * status.
332
- */
333
- export interface InboxResponse {
334
- readonly interactions: readonly InboxInteraction[];
335
- }
336
- /** The response of `POST .../interactions/:callId/answer`. */
337
- export interface InteractionAnswered {
338
- readonly callId: string;
339
- readonly status: "answered";
340
- readonly answer: InteractionAnswer;
341
- }
342
- /** One ambient surface on the wire (envelope + body + details). */
343
- export type AmbientWire = AmbientRecord;
344
- /** The response of `GET /v1/conversations/:id/ambient`. */
345
- export interface AmbientList {
346
- readonly ambient: readonly AmbientWire[];
347
- }
348
- export type { InteractionAnswer, InteractionBody, InteractionDiff, InteractionField, InteractionOption, InteractionStatus, };
349
- export type { AmbientBody, AmbientGauge, AmbientLedgerEntry, AmbientLine, AmbientMetrics, AmbientRow, };
350
- /**
351
- * The `GET/PATCH /v1/settings` payload (Task 8b): the settings file's
352
- * effective contents — the `HarnessSettings` pass-throughs plus the
353
- * sigrun-resolved fields — plus `toolRoster`, the registry-driven roster
354
- * the settings panel renders `defaultTools` over (Task 3, codemode
355
- * parity). Absent file = every default; the roster is SERVER-COMPUTED
356
- * from the live registry snapshot per request (never persisted, never
357
- * snapshotted at boot), so extension tools installed later — codemode,
358
- * tool_search — appear without panel changes. `toolRoster` is NOT a
359
- * settable key: the store's validation rejects it on PATCH (400
360
- * `invalid_field`), and the wire patch type Omits it.
361
- */
362
- export interface SettingsResponse extends SettingsFile {
363
- /** The live registry snapshot's composed tool names, deduplicated. */
364
- readonly toolRoster: readonly string[];
365
- /**
366
- * The resolved server section per flattened dotted key
367
- * (`"server.port"`, `"server.compaction.reserveTokens"`, …), each
368
- * with its resolved value and which tier supplied it — `"env"`,
369
- * `"file"`, or `"default"` (spec §6.6: the generalization of the
370
- * build spec's webui-key special case; since the bootstrap persists
371
- * only env-set values, this block is where the full resolved section
372
- * is visible). Computed per request, never persisted. NOT a settable
373
- * key: the store's validation rejects it on PATCH (400
374
- * `invalid_field`), and the wire patch type Omits it.
375
- */
376
- readonly effective: Readonly<Record<string, EffectiveServerSetting>>;
377
- }
378
- /** Spec §3 health status: ok unless the surface knows it is degraded. */
379
- export type HealthStatus = "ok" | "degraded";
380
- /**
381
- * One idle worker an extension declared (memory-seam Task 5): the bus's
382
- * per-worker observability record as `/v1/meta` serves it.
383
- */
384
- export type WorkerStatus = {
385
- readonly name: string;
386
- readonly lastRunAt?: number;
387
- readonly lastError?: string;
388
- };
389
- /** The `GET /v1/meta` payload (spec §5; the health block is Task 9e). */
390
- export interface MetaResponse {
391
- /** The sigrun server's own version (the package manifest). */
392
- readonly version: string;
393
- readonly harnessVersion: string;
394
- readonly schemaVersion: string;
395
- readonly extensions: readonly {
396
- readonly name: string;
397
- readonly status: string;
398
- readonly error?: string;
399
- /**
400
- * The extension's idle workers (memory-seam Task 5), when it
401
- * declared any; `lastRunAt`/`lastError` stay absent until the
402
- * worker's first run.
403
- */
404
- readonly workers?: readonly WorkerStatus[];
405
- }[];
406
- /**
407
- * §5 health: pure aggregation over boot-retained §3 producers (spec
408
- * §3) — synchronous status reads, never network. The one deliberate
409
- * exception is `backup` (§6.8): its §6.8 derivation reads the small
410
- * `backup/last-success.json` marker from the state root per request
411
- * (the CronJob is a separate process; the filesystem is the only
412
- * fresh-enough view).
413
- */
414
- readonly health: {
415
- /**
416
- * §6.8 backup honesty: presence-derived when no target is
417
- * configured ("unconfigured"); with a target, "configured" only
418
- * while the last-success marker is present and younger than
419
- * `server.backup.staleAfterHours` (default 36 h) — absent, corrupt,
420
- * or stale all read "degraded".
421
- */
422
- readonly backup: "configured" | "unconfigured" | "degraded";
423
- /** The memory extension's §3 producer, else "ok" (no-op default). */
424
- readonly memory: HealthStatus;
425
- /** Any contributor's §3 producer degraded → "degraded"; empty → "ok". */
426
- readonly providers: HealthStatus;
427
- /**
428
- * The gateway engine's health (gateway C2): present ONLY when an
429
- * engine loaded (a no-engine deploy reports NO gateway health —
430
- * degenerate "ok" by absence, never a synthesized field); the
431
- * wrapped engine health (a throwing `health()` reads "degraded";
432
- * a rejected `start` latches degraded until restart).
433
- */
434
- readonly gateway?: HealthStatus;
435
- };
436
- /**
437
- * The auth block (core hardening W1 Task 6, spec §5.7): the effective
438
- * authenticator list (`ctx.methods` — loopback-derived or explicit) and
439
- * the onboarding state (`claimed` = the user directory has its first
440
- * user). A pure boot+store derivation, like the rest of meta — clients
441
- * may cache it only per boot, since the claim flips it.
442
- */
443
- readonly auth: {
444
- readonly methods: readonly ("token" | "proxy")[];
445
- readonly claimed: boolean;
446
- };
447
- /**
448
- * §6.8: the last successful backup's timestamp (the marker's `at`),
449
- * surfaced whenever a readable marker exists against a configured
450
- * target — including a STALE one (the degraded badge's "when was the
451
- * last success"). Absent otherwise.
452
- */
453
- readonly backup: {
454
- readonly lastSuccessAt?: string;
455
- };
456
- readonly capabilities: {
457
- readonly backup: boolean;
458
- readonly channels: readonly string[];
459
- };
460
- /**
461
- * The development flag (spec §14.2/§14.4): `server.dev` / `SIGRUN_DEV`,
462
- * default `false`. Gates the U1 blocks gallery, U3's development
463
- * error bodies (validation errors in `surface_failed` responses) and
464
- * U4 — a boot constant, like the rest of meta.
465
- */
466
- readonly dev: boolean;
467
- /**
468
- * The seam inventory (docs/approval-ux-seams.md): per extension, the
469
- * interaction kinds / ambient surface keys its factory declared.
470
- * Extensions that declared nothing are absent — an absent entry means
471
- * the extension writes no seam records, which is exactly the fail-open
472
- * posture (channels render what is declared, nothing more).
473
- */
474
- readonly seam: {
475
- readonly interactions: readonly {
476
- readonly extension: string;
477
- readonly kinds: readonly string[];
478
- }[];
479
- readonly ambient: readonly {
480
- readonly extension: string;
481
- readonly keys: readonly string[];
482
- }[];
483
- };
484
- /**
485
- * Boot-merge collisions (build-and-webui Task 6): name collisions among
486
- * extension-contributed webui bundles, the provider-catalog merge sink,
487
- * and extension COMMAND names (W5 Task 3). All three merges are
488
- * last-registered-wins by design — the record is the operator's
489
- * visibility into a co-installed replacement, never an error; empty
490
- * arrays are the no-collision boot. A command colliding with a CORE
491
- * name is DROPPED with a boot warning and deliberately NOT recorded
492
- * here (core commands are reserved, not replaceable — there is no
493
- * "winner" to report).
494
- */
495
- readonly collisions: {
496
- readonly webui: readonly {
497
- readonly kind: "webui-bundle";
498
- /** The bundle name that collided. */
499
- readonly name: string;
500
- /** Extension slug that previously owned the name. */
501
- readonly previous: string;
502
- /** Extension slug whose contribution won. */
503
- readonly contributor: string;
504
- }[];
505
- readonly providers: readonly {
506
- readonly kind: "provider";
507
- /** The provider id that collided. */
508
- readonly provider: string;
509
- /** Model ids present in both the previous and replacing catalog. */
510
- readonly modelIds: readonly string[];
511
- /** Contributor name that previously owned the provider. */
512
- readonly previous: string;
513
- /** Contributor name whose contribution won. */
514
- readonly contributor: string;
515
- }[];
516
- readonly commands: readonly {
517
- readonly kind: "command";
518
- /** The command name that collided. */
519
- readonly name: string;
520
- /** Extension slug that previously owned the name. */
521
- readonly previous: string;
522
- /** Extension slug whose contribution won. */
523
- readonly contributor: string;
524
- }[];
525
- };
526
- }
527
- /**
528
- * Provider auth readiness statuses (Task 6, spec §6.4 + provider plugins
529
- * Task 6): statuses only. The legacy vocabulary (`ready` | `not_ready` |
530
- * `invalid`) is preserved VERBATIM for every derivation that exists today
531
- * — the legacy producer mapping (tracker-less contributors) and the
532
- * degenerate env-presence mapping — so old consumers keep working; the
533
- * provider-plugins three-state vocabulary (`not_configured` |
534
- * `degraded` | `ready`) is ADDED for tracker-backed providers, where
535
- * `ready` is the shared spelling.
536
- */
537
- export type AuthStatus = "ready" | "not_ready" | "invalid" | "not_configured" | "degraded";
538
- /**
539
- * One `GET /v1/providers` entry — provider id + status, never key
540
- * material. `detail` (provider plugins Task 6) is the optional
541
- * tracker-facing operator detail; the legacy derivations never set it.
542
- * Core hardening W3 Task 6 (spec §7.6) adds the catalog `models` count
543
- * and the owning extension `owner` (absent for the env-degenerate
544
- * provider) — the deprecated `/v1/auth/check` alias serves this same
545
- * entry, one shape for both routes.
546
- */
547
- export interface AuthCheckProvider {
548
- readonly provider: string;
549
- readonly status: AuthStatus;
550
- /** How many models the provider currently serves (best-effort count). */
551
- readonly models: number;
552
- /** The owning contributor's name; absent for the env-degenerate provider. */
553
- readonly owner?: string;
554
- readonly detail?: string;
555
- }
556
- /**
557
- * The `GET /v1/providers` payload (core hardening W1 Task 6, spec
558
- * §5.7/§7.6): the auth-check derivation under its new home — `/v1/auth`
559
- * is API auth only, and the secret-free readiness report lives at
560
- * `/v1/providers`. `GET /v1/auth/check` serves this same payload as a
561
- * deprecated alias for one release (its responses carry a `Deprecation`
562
- * header).
563
- */
564
- export interface ProvidersResponse {
565
- readonly providers: readonly AuthCheckProvider[];
566
- }
567
- /** The `GET /v1/auth/check` payload (Task 6): per-provider statuses, never credentials. */
568
- export interface AuthCheckResponse {
569
- readonly providers: readonly AuthCheckProvider[];
570
- }
571
- /**
572
- * One `GET /v1/extensions` entry: a loaded outcome enriched with the
573
- * declared seam kinds, the idle-worker projection, the package
574
- * manifest `version` (absent when the entry carries no readable
575
- * manifest), and the declared HTTP routes (W5 Task 2 — present on
576
- * every served entry, empty when the extension declared none). The
577
- * webui's Extensions settings section renders this list.
578
- */
579
- export interface ExtensionInfo {
580
- readonly name: string;
581
- readonly status: string;
582
- readonly error?: string;
583
- readonly version?: string;
584
- /** The interaction kinds the factory declared (empty when none). */
585
- readonly interactionKinds: readonly string[];
586
- /** The ambient surface keys the factory declared (empty when none). */
587
- readonly ambientKeys: readonly string[];
588
- /** The extension's idle workers (empty when it declared none). */
589
- readonly workers: readonly WorkerStatus[];
590
- /** The declared HTTP routes, one `{method, path, auth}` each (W5 Task 2). */
591
- routes?: readonly ExtensionRouteInfo[];
592
- /**
593
- * The channel ids this extension contributes (gateway C1, spec §7):
594
- * present only on rows of extensions whose factory result carried
595
- * `channels`; unique across every loaded extension (a collision
596
- * quarantines the later loader). Absent when the extension declared
597
- * none.
598
- */
599
- readonly channels?: readonly string[];
600
- /**
601
- * The inert marker (gateway C2): `"no gateway"` on rows of
602
- * extensions that contributed `channels` while NO gateway engine
603
- * loaded — their adapters are inert (nothing drives them; one boot
604
- * warning says so). Absent everywhere else.
605
- */
606
- readonly inert?: "no gateway";
607
- /**
608
- * Built-in extensions (Task 2, pi parity): `true` marks a core-shipped
609
- * built-in (codemode / MCP / tool search); ABSENT on configured
610
- * extensions. A replaced built-in reports its row with `builtin: true`
611
- * and `replacedBy` (its status is the skip, never `"ok"`); a disabled
612
- * built-in is absent from the list entirely.
613
- */
614
- readonly builtin?: boolean;
615
- /** The configured specifier that replaced this built-in (replacement rule). */
616
- readonly replacedBy?: string;
617
- }
618
- /** One `GET /v1/extensions` entry's route rows (W5 Task 2, spec §9.2). */
619
- export interface ExtensionRouteInfo {
620
- readonly method: string;
621
- /** The declared relative path — mounted at `/v1/ext/<slug>/<path>`. */
622
- readonly path: string;
623
- readonly auth: string;
624
- }
625
- /** The `GET /v1/extensions` payload (spec §7.7). */
626
- export interface ExtensionsResponse {
627
- readonly extensions: readonly ExtensionInfo[];
628
- }
629
- /**
630
- * A `GET /v1/extensions/:slug/secrets` entry: the key and its winning
631
- * source — NEVER the value (the API lists and writes secrets; it never
632
- * returns them).
633
- */
634
- export interface ExtensionSecret {
635
- readonly key: string;
636
- readonly source: "stored" | "env";
637
- }
638
- /** The `GET`/`PUT`/`DELETE `/v1/extensions/:slug/secrets` payloads: the key list. */
639
- export interface ExtensionSecretsResponse {
640
- readonly secrets: readonly ExtensionSecret[];
641
- }
642
- export type { CommandsResponse, CommandRunResponse, SlashCommand } from "./commands.js";
643
- export type { SessionMeta, SessionMetaPatch } from "./session-meta.js";
644
- /**
645
- * The `GET /v1/auth/whoami` payload (core hardening W1 Task 3, spec
646
- * §5.8): the resolved principal, verbatim. `user` is absent only under
647
- * the naive empty-method path with no `X-Sigrun-User` header;
648
- * `service` marks the env service token. `method` mirrors the extension
649
- * contract's `Principal.method` (gateway C4b added `"host"` — an
650
- * in-process host-built principal; no HTTP route ever resolves one, but
651
- * the two unions stay aligned so the whoami build from a principal can
652
- * never drift from the wire type).
653
- */
654
- export interface WhoamiResponse {
655
- readonly user?: string;
656
- readonly name?: string;
657
- readonly email?: string;
658
- readonly admin: boolean;
659
- readonly service: boolean;
660
- readonly method: "none" | "token" | "proxy" | "host";
661
- }
662
- /**
663
- * The `GET /v1/onboarding` payload (core hardening W1 Task 4, spec
664
- * §5.8): what an unauthenticated client needs to drive the claim flow.
665
- * `codeRequired` is false on a loopback bind or when the request itself
666
- * carries a trusted proxy identity (either is trust enough — no code);
667
- * `proxyIdentity` is present exactly then, carrying what the headers
668
- * vouch for so the webui can render its confirm screen.
669
- */
670
- export interface OnboardingState {
671
- readonly state: "unclaimed" | "claimed";
672
- readonly methods: readonly ("token" | "proxy")[];
673
- readonly codeRequired: boolean;
674
- readonly proxyIdentity?: {
675
- readonly user: string;
676
- readonly name?: string;
677
- readonly email?: string;
678
- };
679
- }
680
- /**
681
- * One directory user on the wire (Task 4): the full record — emails are
682
- * admin-visible material and the routes that serve this type are
683
- * admin-gated. `createdAt` is epoch ms.
684
- *
685
- * `admin` is the STORED flag (the users-admin UI toggles it); the proxy
686
- * group grant rides separately as `groupAdmin` (gateway C8): effective
687
- * admin is `admin || groupAdmin === true`, and the last-admin guard
688
- * counts `admin` alone.
689
- */
690
- export interface UserWire {
691
- readonly user: string;
692
- readonly name?: string;
693
- readonly email?: string;
694
- readonly admin: boolean;
695
- /** The persisted proxy-group grant — present only under `adminGroups`. */
696
- readonly groupAdmin?: boolean;
697
- readonly createdAt: number;
698
- readonly source: "proxy" | "invite" | "cli";
699
- }
700
- /** The `POST /v1/onboarding/claim` payload (Task 4): the user (plus the
701
- * minted token when `issueToken` was requested — shown once, never
702
- * persisted). */
703
- export interface ClaimResponse {
704
- readonly user: UserWire;
705
- readonly token?: string;
706
- }
707
- /** The `POST /v1/users/invites` payload (Task 4): the one-time code is
708
- * shown once, never stored in the clear. */
709
- export interface InviteResponse {
710
- readonly id: string;
711
- readonly code: string;
712
- readonly expiresAt: number;
713
- }
714
- /**
715
- * One API token on the wire (Task 4): the token store's record minus the
716
- * `sha256` digest — digests never leave the server. Created by the
717
- * claim route (`issueToken`) and `POST /v1/auth/tokens`.
718
- */
719
- export interface TokenWire {
720
- readonly id: string;
721
- readonly name: string;
722
- readonly user: string;
723
- readonly createdAt: number;
724
- }
725
- /** The `POST /v1/auth/tokens` payload (Task 4): the secret once, the
726
- * digest-free record alongside it. */
727
- export interface TokenCreateResponse {
728
- readonly token: string;
729
- readonly record: TokenWire;
730
- }
731
- /**
732
- * One host event on the `GET /v1/events` SSE wire: `event: <type>` plus
733
- * this object as the single-line `data:` JSON. Conversation-scoped
734
- * events are delivered only when the connecting principal's `accessOf`
735
- * against a FRESH SessionMeta snapshot is not `"none"` (per-event
736
- * re-check: share → delivered, un-share → withheld);
737
- * `providers.changed` reaches every authenticated principal;
738
- * `job.changed` carries the changed job's `JobWire` summary WITHOUT
739
- * `access` — the events stream computes and adds it per principal before
740
- * delivery (the hub's copy is access-neutral).
741
- * No replay: a client that reconnects refetches (the list GET); the
742
- * stream only nudges.
743
- */
744
- export type HostEventWire = {
745
- readonly type: "conversation.created";
746
- readonly conversationId: number;
747
- } | {
748
- readonly type: "conversation.changed";
749
- readonly conversationId: number;
750
- /** The summary fields that changed, with their new values. */
751
- readonly fields: Partial<ConversationSummary>;
752
- } | {
753
- readonly type: "run.admitted";
754
- readonly conversationId: number;
755
- readonly submissionId: number;
756
- } | {
757
- readonly type: "run.settled";
758
- readonly conversationId: number;
759
- readonly outcome: "answered" | "unanswered";
760
- readonly reason?: string;
761
- } | {
762
- readonly type: "interaction.pending" | "interaction.settled";
763
- readonly conversationId: number;
764
- readonly callId: string;
765
- readonly kind: string;
766
- } | {
767
- readonly type: "ambient.changed";
768
- readonly conversationId: number;
769
- readonly key: string;
770
- } | {
771
- readonly type: "providers.changed";
772
- readonly provider: string;
773
- readonly status: string;
774
- } | {
775
- /** A task table write with a TERMINAL status (jobs Task 3, §8.1): the jobs observer settles `task`-action run records from it — `completed` → `succeeded`, any other terminal → `failed` + `error`. Hub-side only (not an SSE wire event): the task table is host machinery, not principal-facing surface. */
776
- readonly type: "taskSettled";
777
- readonly taskId: number;
778
- readonly status: string;
779
- readonly error?: string;
780
- } | {
781
- /** W4 Task 4 (§8.4): the changed job's summary, WITHOUT `access` — the events stream computes `accessOf` per principal and adds it before delivery (a hidden job's event is withheld entirely). */
782
- readonly type: "job.changed";
783
- readonly job: Omit<JobWire, "access">;
784
- };