@mono-agent/web 0.20.11 → 0.21.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 (70) hide show
  1. package/README.md +397 -68
  2. package/dist/contracts.d.ts +437 -8
  3. package/dist/contracts.d.ts.map +1 -1
  4. package/dist/contracts.js +2 -0
  5. package/dist/contracts.js.map +1 -1
  6. package/dist/cron-reply-context.d.ts +27 -0
  7. package/dist/cron-reply-context.d.ts.map +1 -0
  8. package/dist/cron-reply-context.js +241 -0
  9. package/dist/cron-reply-context.js.map +1 -0
  10. package/dist/discovery.d.ts +1 -0
  11. package/dist/discovery.d.ts.map +1 -1
  12. package/dist/discovery.js +8 -6
  13. package/dist/discovery.js.map +1 -1
  14. package/dist/effort-ladder.d.ts +111 -0
  15. package/dist/effort-ladder.d.ts.map +1 -0
  16. package/dist/effort-ladder.js +155 -0
  17. package/dist/effort-ladder.js.map +1 -0
  18. package/dist/index.d.ts +3 -3
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/long-lived-fetch.d.ts +5 -0
  23. package/dist/long-lived-fetch.d.ts.map +1 -0
  24. package/dist/long-lived-fetch.js +22 -0
  25. package/dist/long-lived-fetch.js.map +1 -0
  26. package/dist/monitor-reply.d.ts +10 -0
  27. package/dist/monitor-reply.d.ts.map +1 -0
  28. package/dist/monitor-reply.js +67 -0
  29. package/dist/monitor-reply.js.map +1 -0
  30. package/dist/notification-client.d.ts +11 -2
  31. package/dist/notification-client.d.ts.map +1 -1
  32. package/dist/notification-client.js +5 -4
  33. package/dist/notification-client.js.map +1 -1
  34. package/dist/notification-ingress.d.ts +8 -1
  35. package/dist/notification-ingress.d.ts.map +1 -1
  36. package/dist/notification-ingress.js +28 -6
  37. package/dist/notification-ingress.js.map +1 -1
  38. package/dist/operator-client.d.ts +35 -2
  39. package/dist/operator-client.d.ts.map +1 -1
  40. package/dist/operator-client.js +276 -9
  41. package/dist/operator-client.js.map +1 -1
  42. package/dist/server.d.ts +42 -1
  43. package/dist/server.d.ts.map +1 -1
  44. package/dist/server.js +679 -52
  45. package/dist/server.js.map +1 -1
  46. package/dist/service.d.ts +299 -18
  47. package/dist/service.d.ts.map +1 -1
  48. package/dist/service.js +1915 -160
  49. package/dist/service.js.map +1 -1
  50. package/dist/store-migrations.d.ts +23 -0
  51. package/dist/store-migrations.d.ts.map +1 -0
  52. package/dist/store-migrations.js +212 -0
  53. package/dist/store-migrations.js.map +1 -0
  54. package/dist/store.d.ts +389 -21
  55. package/dist/store.d.ts.map +1 -1
  56. package/dist/store.js +2087 -245
  57. package/dist/store.js.map +1 -1
  58. package/package.json +9 -8
  59. package/webapp/dist/assets/{assistant-ui-BzN2E6n6.js → assistant-ui-pZmGxIp2.js} +16 -16
  60. package/webapp/dist/assets/index-6uQ7TVQe.css +1 -0
  61. package/webapp/dist/assets/index-CsSMjSgW.js +156 -0
  62. package/webapp/dist/assets/{markdown-Vq23xgh7.js → markdown-Du5t10ja.js} +1 -1
  63. package/webapp/dist/badge-96.png +0 -0
  64. package/webapp/dist/index.html +26 -6
  65. package/webapp/dist/manifest.webmanifest +1 -1
  66. package/webapp/dist/notification-sw.js +3 -1
  67. package/webapp/dist/sw.js +1 -1
  68. package/webapp/dist/{workbox-9c191d2f.js → workbox-2fbc6a65.js} +1 -1
  69. package/webapp/dist/assets/index-BT463dRM.css +0 -1
  70. package/webapp/dist/assets/index-Co-qDQPq.js +0 -155
@@ -1,4 +1,4 @@
1
- import { type AgentReplyMcpAppPart, type AgentReplyPartFailure, type CronOperatorHealth, type CronOperatorJob, type CronOperatorOverview, type CronOperatorRun, type CronOperatorRunBase, type CronOperatorRunDetail, type CronOperatorRunPage, type CronOperatorRunStatus, type CronOperatorRunSummary, type CronOperatorRunTrigger, type CronOperatorRunTruncatedField, type SessionToolHistoryEventMetadata, type ProcessJobProjection } from "@mono-agent/agent-contracts";
1
+ import { type AgentReplyMcpAppPart, type AgentReplyPartFailure, type CronOperatorHealth, type CronOperatorJob, type CronOperatorOverview, type CronOperatorRun, type CronOperatorRunBase, type CronOperatorRunDetail, type CronOperatorRunPage, type CronOperatorRunStatus, type CronOperatorRunSummary, type CronOperatorRunTrigger, type CronOperatorRunTruncatedField, type SessionToolHistoryEventMetadata, type MonitorProjection, type ProcessJobProjection } from "@mono-agent/agent-contracts";
2
2
  /** Machine-readable discovery contract consumed by local ACP clients such as Worklab. */
3
3
  export declare const ACP_BRIDGE_DISCOVERY_SCHEMA: "mono-agent.acp-discovery.v1";
4
4
  export declare const ACP_BRIDGE_SOURCE_SCHEMA: "mono-agent.acp-source.v1";
@@ -47,6 +47,8 @@ export declare const WEB_API_VERSION: 1;
47
47
  export declare const WEB_THEMES: readonly ["evergreen", "ocean", "plum", "terracotta"];
48
48
  export type WebTheme = (typeof WEB_THEMES)[number];
49
49
  export declare const DEFAULT_WEB_THEME: WebTheme;
50
+ /** Canonical upper bound on the operator-chosen console label. */
51
+ export declare const WEB_CONSOLE_NAME_MAX_CHARACTERS = 80;
50
52
  export declare const WEB_MAX_FILES_PER_TURN = 10;
51
53
  export declare const WEB_MAX_TURN_ATTACHMENT_BYTES: number;
52
54
  export declare const WEB_STAGED_UPLOAD_TTL_MS: number;
@@ -59,7 +61,7 @@ export declare const WEB_MAX_TURN_TEXT_CHARACTERS = 200000;
59
61
  export declare const WEB_MAX_LIVE_INPUTS_PER_THREAD = 100;
60
62
  export type WebAgentStatus = "online" | "offline" | "degraded";
61
63
  export type WebThreadNotificationTriggerKind = "cron" | "webhook";
62
- export type WebNotificationTriggerKind = WebThreadNotificationTriggerKind | "job";
64
+ export type WebNotificationTriggerKind = WebThreadNotificationTriggerKind | "job" | "monitor";
63
65
  export type WebThreadTrigger = {
64
66
  readonly kind: "webhook";
65
67
  } | {
@@ -74,28 +76,84 @@ export interface WebCronCapability {
74
76
  }
75
77
  export interface WebModelOption {
76
78
  readonly effortLevels?: readonly string[];
79
+ /** Configured fallback effort; null means provider default. */
80
+ readonly effort?: string | null;
77
81
  readonly reasoning?: boolean;
78
82
  readonly reasoningMode?: string;
79
83
  readonly label?: string;
80
84
  readonly contextWindow?: number;
81
85
  }
86
+ export type WebRunSettingSource = "config" | "override";
87
+ /** Config defaults, optional web-console overrides, and the effective values for new conversations. */
88
+ export interface WebAgentRunSettings {
89
+ readonly config: {
90
+ readonly model?: string;
91
+ readonly effort?: string;
92
+ };
93
+ readonly override: {
94
+ readonly model?: string;
95
+ readonly effort?: string;
96
+ } | null;
97
+ readonly effective: {
98
+ readonly model?: string;
99
+ readonly modelSource: WebRunSettingSource;
100
+ readonly effort?: string;
101
+ readonly effortSource: WebRunSettingSource;
102
+ };
103
+ }
82
104
  export interface WebAgentSummary {
83
105
  readonly sourceId: string;
106
+ /**
107
+ * Opaque token for the agent PROCESS this summary describes: stable while
108
+ * that process lives, different once it is replaced. Additive, and additive
109
+ * only -- no client is required to read it.
110
+ *
111
+ * A source id outlives the process behind it, so anything a client caches
112
+ * per agent (the `/v1/models` pages the model picker fetches, above all)
113
+ * outlives the catalog that filled it. The console's server already scopes
114
+ * its own catalog cache this way; before this field the browser had nothing
115
+ * generation-shaped to observe at all -- no pid, no start time, and an
116
+ * `updatedAt` that is a discovery heartbeat -- so a tab kept offering a
117
+ * restarted agent's retired models until it was reloaded.
118
+ *
119
+ * Absent on any summary not built from a live discovery pass.
120
+ */
121
+ readonly generation?: string;
84
122
  readonly label: string;
85
123
  readonly status: WebAgentStatus;
86
124
  readonly pinned?: boolean;
87
125
  readonly health?: string;
88
126
  readonly supportsAttachments: boolean;
127
+ /**
128
+ * Agent operator exposes Pi provider authentication v1. The operator client
129
+ * adds a bearer only when that discovered endpoint has an API key.
130
+ *
131
+ * Usability is projected from the live connection's `/v1/info`; a stored bit
132
+ * is presentation state, never authorization to call the agent.
133
+ */
134
+ readonly supportsProviderAuth?: true;
135
+ /** Additive explicit live-check action; passive status remains traffic-free. */
136
+ readonly supportsProviderAuthChecks?: true;
89
137
  readonly models?: readonly string[];
90
138
  readonly defaultModel?: string;
91
139
  readonly defaultEffort?: string;
92
140
  readonly efforts?: readonly string[];
93
141
  readonly modelOptions?: Readonly<Record<string, WebModelOption>>;
142
+ /** Web-console-owned defaults copied into conversations created after they are saved. */
143
+ readonly runSettings: WebAgentRunSettings;
144
+ /**
145
+ * Providers this agent supports. `models`/`modelOptions` stay the configured
146
+ * shortlist; this is what the selector groups and filters by, and what tells
147
+ * a client which providers are worth requesting a `/v1/models` page for.
148
+ * Absent when the agent predates the provider catalog.
149
+ */
150
+ readonly providers?: readonly WebAgentProvider[];
94
151
  /** Absent when the addressed agent predates first-class cron operator routes. */
95
152
  readonly cron?: WebCronCapability;
96
153
  readonly supportsAskById?: boolean;
97
154
  readonly updatedAt: string;
98
155
  }
156
+ export type { ProviderAuthCheckResult, ProviderAuthCheckSessionSnapshot, ProviderAuthCheckStartInput, ProviderAuthMethod, ProviderAuthPrompt, ProviderAuthProviderStatus, ProviderAuthSessionInput, ProviderAuthSessionSnapshot, ProviderAuthSessionStartInput, ProviderAuthStatusSnapshot, ProviderAuthUsage, } from "@mono-agent/agent-contracts";
99
157
  export type WebSkillAvailability = "inlined" | "on-demand" | "unavailable";
100
158
  export type WebSkillUnavailableReason = "not-selected" | "read-skill-disabled" | "unsupported-name";
101
159
  export interface WebSkillInfo {
@@ -115,17 +173,62 @@ export type WebSkillRegistry = {
115
173
  readonly items: readonly [];
116
174
  };
117
175
  export type WebRunStatus = "idle" | "running" | "complete" | "failed" | "cancelled" | "interrupted";
176
+ export interface WebRunSelection {
177
+ readonly model?: string;
178
+ readonly effort?: string;
179
+ }
180
+ export interface WebRunExecution extends WebRunSelection {
181
+ readonly effectiveEffort?: string;
182
+ }
183
+ export interface WebRunTransition {
184
+ readonly from: string;
185
+ readonly to: string;
186
+ readonly attemptIndex?: number;
187
+ readonly reason?: string;
188
+ }
189
+ export interface WebRunRetry {
190
+ readonly model?: string;
191
+ readonly retryIndex?: number;
192
+ readonly attempts?: number;
193
+ readonly reason?: string;
194
+ }
195
+ export interface WebRunAttribution {
196
+ readonly requested: WebRunSelection;
197
+ readonly attempted?: WebRunExecution;
198
+ readonly executed?: WebRunExecution;
199
+ readonly disposition: "requested" | "fallback" | "unknown";
200
+ readonly transitions: readonly WebRunTransition[];
201
+ readonly retries: readonly WebRunRetry[];
202
+ readonly truncated?: true;
203
+ }
118
204
  export interface WebRunState {
119
205
  readonly id?: string;
120
206
  readonly status: WebRunStatus;
121
207
  readonly startedAt?: string;
122
208
  readonly finishedAt?: string;
209
+ /** Previous meaningful outcome when this completion was a silent host-only wake. */
210
+ readonly lastOutcome?: {
211
+ readonly status: WebRunStatus;
212
+ readonly finishedAt?: string;
213
+ } | null;
123
214
  readonly error?: {
124
215
  readonly code?: string;
125
216
  readonly message: string;
126
217
  };
127
218
  readonly model?: string;
128
219
  readonly effort?: string;
220
+ readonly attribution?: WebRunAttribution;
221
+ }
222
+ /** Bounded activity derived from every retained process-job card in a thread. */
223
+ export interface WebJobActivity {
224
+ readonly queued: number;
225
+ readonly starting: number;
226
+ readonly running: number;
227
+ readonly latestTerminal?: {
228
+ readonly state: Exclude<ProcessJobProjection["state"], "queued" | "starting" | "running">;
229
+ readonly completedAt: string;
230
+ readonly replyPreview?: string;
231
+ };
129
232
  }
130
233
  export interface WebThread {
131
234
  readonly id: string;
@@ -139,11 +242,63 @@ export interface WebThread {
139
242
  readonly lastMessagePreview?: string;
140
243
  readonly messageCount: number;
141
244
  readonly runState: WebRunState;
245
+ readonly jobActivity?: WebJobActivity;
142
246
  readonly canSend: boolean;
143
247
  readonly canUpload: boolean;
248
+ /** Per-conversation model override, or null when the agent default applies. */
249
+ readonly runModel: string | null;
250
+ /** Per-conversation effort override, or null when the agent default applies. */
251
+ readonly runEffort: string | null;
144
252
  }
145
253
  export type WebMessageStatus = "running" | "complete" | "failed" | "cancelled" | "interrupted";
146
254
  export type WebToolCallStatus = "running" | "complete" | "failed";
255
+ export interface WebCronReplyContextPart {
256
+ readonly type: "cron-reply-context";
257
+ readonly schema: "mono-agent.web.cron-reply-context.v1";
258
+ readonly untrusted: true;
259
+ readonly source: {
260
+ readonly sourceId: string;
261
+ readonly jobId: string;
262
+ readonly runId: string;
263
+ };
264
+ readonly run: {
265
+ readonly sequence: number;
266
+ readonly trigger: WebCronRunTrigger;
267
+ readonly status: WebCronRunStatus;
268
+ readonly scheduledAt: string;
269
+ readonly orderedAt: string;
270
+ readonly startedAt?: string;
271
+ readonly completedAt?: string;
272
+ readonly blockedByRunId?: string;
273
+ readonly blockedByTrigger?: WebCronRunTrigger;
274
+ readonly queueDepth?: number;
275
+ };
276
+ readonly snapshot: {
277
+ readonly capturedAt: string;
278
+ readonly kind: WebCronReplySnapshotKind;
279
+ readonly sourceTruncationKnown: boolean;
280
+ readonly sourceFieldsTruncated: readonly WebCronRunTruncatedField[];
281
+ readonly maxBytes: number;
282
+ readonly originalErrorBytes: number;
283
+ readonly retainedErrorBytes: number;
284
+ readonly originalResultBytes: number;
285
+ readonly retainedResultBytes: number;
286
+ readonly truncatedFields: readonly ("failure.message" | "result.text")[];
287
+ };
288
+ readonly result: {
289
+ readonly text: string;
290
+ };
291
+ readonly failure: {
292
+ readonly code?: string;
293
+ readonly message?: string;
294
+ };
295
+ /** Exact human-readable framing which precedes the JSON on the agent wire. */
296
+ readonly prefix: string;
297
+ /** Exact JSON substring from the imported wire text; never re-serialized. */
298
+ readonly rawJson: string;
299
+ /** Exact imported wire text retained for diagnostics and copy-safe display. */
300
+ readonly rawText: string;
301
+ }
147
302
  /** One tool call, whether the agent made it or one of its subagents did. */
148
303
  export interface WebToolCall {
149
304
  readonly toolCallId: string;
@@ -151,9 +306,8 @@ export interface WebToolCall {
151
306
  readonly args?: unknown;
152
307
  readonly result?: unknown;
153
308
  /**
154
- * An MCP tool's machine-readable result, when it returned one. `result` is the
155
- * model-facing text and is lossy; renderers that must reason about the outcome
156
- * (the AskUser card reads `interactionId`/`answered`) read this instead.
309
+ * A bounded machine-readable tool result, from MCP or a canonical host tool
310
+ * outcome. `result` is model-facing and lossy; consumers validate the schema here.
157
311
  */
158
312
  readonly structuredResult?: unknown;
159
313
  readonly status: WebToolCallStatus;
@@ -165,6 +319,33 @@ export interface WebToolCall {
165
319
  readonly executionMs?: number;
166
320
  /** Canonical durable-tool record metadata received on the live event. */
167
321
  readonly history?: SessionToolHistoryEventMetadata;
322
+ /**
323
+ * Set when the transcript carries only the head of `result`. A 20 KB `Exec`
324
+ * body is the single largest thing a conversation read transfers and almost
325
+ * none of it is ever looked at, so a browser read gets a preview and the
326
+ * whole body stays one request away at
327
+ * `/threads/:id/messages/:messageId/tool-calls/:toolCallId`. Never set on a
328
+ * `?full=1` read.
329
+ */
330
+ readonly resultTruncated?: boolean;
331
+ /** Character length of the untruncated `result` text, when it was truncated. */
332
+ readonly resultBytes?: number;
333
+ /**
334
+ * Lowercase sha-256 hex of the SERIALIZED untruncated `result` -- the string
335
+ * itself for a string payload, its JSON otherwise.
336
+ *
337
+ * Carried by a truncated preview AND by the whole body the tool-call route
338
+ * serves, so a console holding a repaired body can prove the preview that
339
+ * arrived after it describes the same content. It is an identity, not a
340
+ * signature: nothing here is secret and nothing is keyed.
341
+ */
342
+ readonly resultDigest?: string;
343
+ /** As {@link resultTruncated}, for the call's arguments. */
344
+ readonly argsTruncated?: boolean;
345
+ /** Character length of the untruncated `args` text, when it was truncated. */
346
+ readonly argsBytes?: number;
347
+ /** As {@link resultDigest}, for the call's arguments. */
348
+ readonly argsDigest?: string;
168
349
  }
169
350
  export type WebMessagePart = {
170
351
  readonly type: "text";
@@ -172,7 +353,7 @@ export type WebMessagePart = {
172
353
  } | {
173
354
  readonly type: "reasoning";
174
355
  readonly text: string;
175
- } | ({
356
+ } | WebCronReplyContextPart | ({
176
357
  readonly type: "tool-call";
177
358
  } & WebToolCall)
178
359
  /**
@@ -194,8 +375,19 @@ export type WebMessagePart = {
194
375
  readonly executionMs?: number;
195
376
  /** What this delegation cost, when the runtime priced its model. */
196
377
  readonly costUsd?: number;
378
+ /** Provider route requested, attempted, and executed by this child. */
379
+ readonly attribution?: WebRunAttribution;
197
380
  /** Metadata for the persisted parent `Agent` call; child internals omit it. */
198
381
  readonly history?: SessionToolHistoryEventMetadata;
382
+ /** See {@link WebToolCall.resultTruncated}; the delegation's report is truncated the same way. */
383
+ readonly resultTruncated?: boolean;
384
+ readonly resultBytes?: number;
385
+ /** See {@link WebToolCall.resultDigest}. */
386
+ readonly resultDigest?: string;
387
+ readonly argsTruncated?: boolean;
388
+ readonly argsBytes?: number;
389
+ /** See {@link WebToolCall.resultDigest}. */
390
+ readonly argsDigest?: string;
199
391
  readonly status: WebToolCallStatus;
200
392
  readonly calls: readonly WebToolCall[];
201
393
  } | {
@@ -204,8 +396,31 @@ export type WebMessagePart = {
204
396
  /** Bounded normal-turn answer produced by the terminal wake, when ready. */
205
397
  readonly responseText?: string;
206
398
  } | {
399
+ /** Chronological marker for the point where a retained job wake was applied. */
400
+ readonly type: "process-job-wake";
401
+ readonly jobId: string;
402
+ readonly deliveryKey: string;
403
+ readonly disposition: "steered" | "follow_up";
404
+ } | {
405
+ readonly type: "monitor-activity";
406
+ /** One compact run-level row, with one latest projection per Monitor. */
407
+ readonly monitors: readonly {
408
+ readonly projection: MonitorProjection;
409
+ /** Exact delivered wake identities, retained only for idempotent UI aggregation. */
410
+ readonly deliveryKeys: readonly string[];
411
+ }[];
412
+ }
413
+ /**
414
+ * One runtime/provider diagnostic. `data` is present only for the events the
415
+ * console actually renders or sums; everything else keeps its identity (and
416
+ * its position, which the transcript's index-based reads depend on) and drops
417
+ * the payload. `kind` names a stripped `runtime_telemetry`'s variant so the
418
+ * part still says what it was.
419
+ */
420
+ | {
207
421
  readonly type: "telemetry";
208
422
  readonly event: string;
423
+ readonly kind?: string;
209
424
  readonly data?: unknown;
210
425
  } | {
211
426
  readonly type: "error";
@@ -273,8 +488,24 @@ export interface WebMessage {
273
488
  readonly attachments: readonly WebAttachment[];
274
489
  readonly createdAt: string;
275
490
  readonly updatedAt: string;
491
+ /**
492
+ * When the turn that produced this assistant message reached a terminal state
493
+ * (complete, failed, cancelled or interrupted). `createdAt` is that turn's
494
+ * start, so the pair is the turn's wall-clock window. Absent while the turn
495
+ * runs, on user and system rows, and on assistant rows with no turn.
496
+ */
497
+ readonly finishedAt?: string;
276
498
  readonly status: WebMessageStatus;
277
- readonly liveInputStatus?: "pending" | "applied" | "queued" | "cancelled";
499
+ readonly liveInputStatus?: "pending" | "applied" | "queued" | "cancelled" | "uncertain";
500
+ readonly attribution?: WebRunAttribution;
501
+ /**
502
+ * How many times this message's parts have been persisted, counted from the
503
+ * row's creation. It is what makes a {@link WebMessageDelta} safe to apply:
504
+ * a holder of `seq` can tell the very next write from one that skipped ahead
505
+ * of it, and re-read the message instead of guessing. Rows written before the
506
+ * console counted read 0.
507
+ */
508
+ readonly seq: number;
278
509
  }
279
510
  export interface WebQuote {
280
511
  readonly text: string;
@@ -337,6 +568,46 @@ export interface WebCronRunPage extends CronOperatorRunPage {
337
568
  /** Canonical messages reconciled by the web backend for this page. */
338
569
  readonly messages?: readonly WebMessage[];
339
570
  }
571
+ export type WebCronReplySnapshotKind = "summary" | "detail";
572
+ export interface CreateWebCronReplyInput {
573
+ readonly operationId: string;
574
+ readonly snapshotKind: WebCronReplySnapshotKind;
575
+ }
576
+ /** One durable, server-owned import receipt. `duplicate` means local replay. */
577
+ export interface WebCronReplyReceipt {
578
+ readonly operationId: string;
579
+ readonly sourceId: string;
580
+ readonly jobId: string;
581
+ readonly runId: string;
582
+ readonly duplicate: boolean;
583
+ readonly thread: WebThread;
584
+ /** Presentation-shaped messages. The two canonical stored rows fold to one card. */
585
+ readonly messages: readonly WebMessage[];
586
+ }
587
+ /** One provider an agent advertises as supported. */
588
+ export interface WebAgentProvider {
589
+ readonly id: string;
590
+ readonly label: string;
591
+ /** The agent declared this provider or routes through it. */
592
+ readonly configured?: true;
593
+ }
594
+ /** One model served by the lazy agent `/v1/models` catalog endpoint. */
595
+ export interface WebCatalogModel {
596
+ readonly id: string;
597
+ readonly name: string;
598
+ readonly provider: string;
599
+ readonly providerLabel: string;
600
+ readonly contextWindow?: number;
601
+ readonly reasoning?: boolean;
602
+ readonly effortLevels?: readonly string[];
603
+ readonly reasoningMode?: string;
604
+ }
605
+ /** A bounded model-catalog page proxied from an agent's `/v1/models` endpoint. */
606
+ export interface WebModelPage {
607
+ readonly models: readonly WebCatalogModel[];
608
+ readonly nextCursor?: string;
609
+ readonly truncated: boolean;
610
+ }
340
611
  export interface WebCronConfirmation {
341
612
  readonly token: string;
342
613
  readonly expiresAt: string;
@@ -365,7 +636,10 @@ export interface WebChannelConfigView {
365
636
  readonly fields: readonly WebChannelConfigViewField[];
366
637
  }
367
638
  export interface WebConsoleIdentity {
639
+ /** Machine hostname; the default display name and the LAN identity operators recognise. */
368
640
  readonly hostName: string;
641
+ /** Operator-chosen console label (`mono-agent web --name`), falling back to `hostName`. */
642
+ readonly displayName: string;
369
643
  readonly theme: WebTheme;
370
644
  }
371
645
  export interface WebPushBootstrap {
@@ -385,12 +659,32 @@ export interface WebPushSubscriptionStatus {
385
659
  readonly lastErrorAt?: string;
386
660
  readonly lastErrorCode?: string;
387
661
  }
662
+ /**
663
+ * What a bootstrap should carry, when the console knows.
664
+ *
665
+ * A bootstrap used to carry every discovered agent's conversations -- one
666
+ * 200-row bucket per agent per archive state -- and the console then re-read
667
+ * the single bucket its sidebar shows. `sourceId` names the bucket it wants;
668
+ * an absent or unknown one falls back rather than failing, because the first
669
+ * request a fresh console makes has no selection to name yet.
670
+ */
671
+ export interface WebBootstrapScope {
672
+ readonly sourceId?: string;
673
+ readonly archived?: boolean;
674
+ readonly limit?: number;
675
+ }
388
676
  export interface WebBootstrap {
389
677
  readonly version: typeof WEB_API_VERSION;
390
678
  readonly console: WebConsoleIdentity;
391
679
  readonly push: WebPushBootstrap;
680
+ /** Every discovered agent, in full: the rail shows all of them at once. */
392
681
  readonly agents: readonly WebAgentSummary[];
682
+ /** One page of ONE (agent, archived) bucket -- the one `threadsSourceId` names. */
393
683
  readonly threads: readonly WebThread[];
684
+ /** The bucket `threads` came from, or `null` when there is no agent to open on. */
685
+ readonly threadsSourceId: string | null;
686
+ /** Keyset cursor for the next older page of that bucket, or `null` at its end. */
687
+ readonly threadsNextCursor: string | null;
394
688
  readonly currentThreadId?: string;
395
689
  readonly limits: {
396
690
  readonly maxFileBytes: number;
@@ -399,17 +693,125 @@ export interface WebBootstrap {
399
693
  readonly accept: readonly string[];
400
694
  };
401
695
  }
402
- export type WebEventType = "ready" | "agents.changed" | "cron.changed" | "threads.changed" | "thread.changed" | "message.changed" | "turn.changed" | "attachment.changed" | "push.pending";
696
+ export type WebEventType = "ready" | "agents.changed" | "cron.changed" | "threads.changed" | "thread.changed" | "message.changed" | "message.delta" | "turn.changed" | "attachment.changed" | "push.pending";
697
+ /**
698
+ * The payload of every `thread.changed`/`threads.changed` that names a
699
+ * conversation.
700
+ *
701
+ * The fresh summary travels WITH the event: one that only named a conversation
702
+ * cost every connected console a page of its bucket to find out what had
703
+ * changed about a row it was already holding. A removal has no summary left to
704
+ * carry, so it says so.
705
+ */
706
+ export type WebThreadChangedPayload = {
707
+ readonly thread: WebThread;
708
+ } | {
709
+ readonly threadId: string;
710
+ readonly removed: true;
711
+ };
712
+ /**
713
+ * What an `agents.changed` says about itself.
714
+ *
715
+ * A pin is a one-field write the writing tab already applied from the PATCH
716
+ * response, so it names the agent and the new state rather than telling every
717
+ * console to re-read the bootstrap, its skills and its cron. Discovery-driven
718
+ * invalidations carry nothing: an agent that appeared, went away, or advertises
719
+ * something different can have changed anything at all.
720
+ */
721
+ export type WebAgentsChangedPayload = {
722
+ readonly sourceId: string;
723
+ readonly pinned: boolean;
724
+ } | undefined;
725
+ /**
726
+ * One edit to a message's part array.
727
+ *
728
+ * Ops are ordered so that applying them front to back is always well defined: a
729
+ * `truncate` comes first when the array shrank, and the rest ascend by index,
730
+ * which is also why an index never names a slot the shortened array lost.
731
+ */
732
+ export type WebMessageDeltaOp =
733
+ /** Text streamed onto the end of the `text`/`reasoning` part at `index`. */
734
+ {
735
+ readonly op: "append";
736
+ readonly index: number;
737
+ readonly delta: string;
738
+ }
739
+ /** The whole part at `index`, replaced or appended one past the end. */
740
+ | {
741
+ readonly op: "set";
742
+ readonly index: number;
743
+ readonly part: WebMessagePart;
744
+ }
745
+ /** Drop every part from `length` onward. Emitted first when it is emitted. */
746
+ | {
747
+ readonly op: "truncate";
748
+ readonly length: number;
749
+ };
750
+ /**
751
+ * One persisted parts write, as content rather than an invalidation hint.
752
+ *
753
+ * A streaming answer is rewritten every ~50 ms, and a hint made every console
754
+ * answer each one by re-reading the whole conversation. This says what actually
755
+ * changed instead. `baseSeq` is the version the ops apply to and `seq` the one
756
+ * they produce: a client whose message is not at `baseSeq` has missed a write
757
+ * and must re-read that message rather than apply anything.
758
+ */
759
+ export interface WebMessageDelta {
760
+ readonly messageId: string;
761
+ /** The message's {@link WebMessage.seq} BEFORE this write. */
762
+ readonly baseSeq: number;
763
+ /** The message's `seq` after it, always `baseSeq + 1`. */
764
+ readonly seq: number;
765
+ readonly status: WebMessageStatus;
766
+ readonly updatedAt: string;
767
+ /**
768
+ * {@link WebMessage.finishedAt}, carried by the write that SETS it.
769
+ *
770
+ * The turn's wall-clock window is `createdAt` to this, and a console holding
771
+ * only the first half had to re-read the whole conversation at every turn
772
+ * finish to draw it. Absent on every write that leaves the turn running.
773
+ */
774
+ readonly finishedAt?: string;
775
+ /** Full replacement snapshot when provider routing metadata changed. */
776
+ readonly attribution?: WebRunAttribution;
777
+ readonly ops: readonly WebMessageDeltaOp[];
778
+ }
779
+ /**
780
+ * The payload of a `message.changed`: the message moved, go and read it.
781
+ *
782
+ * `deltaDeclined` is NOT part of the wire contract -- the event stream strips
783
+ * it, and a browser reads the same two fields either way. It marks the hint the
784
+ * delta path emits when the delta it built would have cost more than the
785
+ * message it describes, so the stream layer can tell one write-rate frame from
786
+ * a reconciliation and rate-limit only the first.
787
+ */
788
+ export interface WebMessageChangedPayload {
789
+ readonly messageId: string;
790
+ readonly updatedAt: string;
791
+ readonly deltaDeclined?: true;
792
+ }
403
793
  export interface WebEvent {
404
794
  readonly id: string;
405
795
  readonly version: typeof WEB_API_VERSION;
406
796
  readonly type: WebEventType;
407
797
  readonly at: string;
408
798
  readonly threadId?: string;
799
+ /**
800
+ * Event-specific detail. A payload-less `agents.changed` invalidates the
801
+ * bootstrap snapshot; see {@link WebAgentsChangedPayload}.
802
+ */
409
803
  readonly payload?: unknown;
410
804
  }
411
805
  export interface CreateWebThreadInput {
412
806
  readonly sourceId: string;
807
+ /** Explicit draft choice; absent inherits the web default and null selects config. */
808
+ readonly model?: string | null;
809
+ /** Explicit draft choice; absent inherits the web default and null selects config. */
810
+ readonly effort?: string | null;
811
+ }
812
+ export interface PutWebAgentRunSettingsInput {
813
+ readonly model: string | null;
814
+ readonly effort: string | null;
413
815
  }
414
816
  export interface PatchWebAgentInput {
415
817
  readonly pinned: boolean;
@@ -417,6 +819,19 @@ export interface PatchWebAgentInput {
417
819
  export interface PatchWebThreadInput {
418
820
  readonly title?: string;
419
821
  readonly archived?: boolean;
822
+ readonly model?: string | null;
823
+ readonly effort?: string | null;
824
+ /**
825
+ * Compare-and-set: apply nothing unless this conversation still has NO run
826
+ * override. The console's one-time adoption of a browser-local preference
827
+ * reads the thread and then writes it, and between those two calls another
828
+ * tab (or another device) can set a real override -- an unconditional write
829
+ * then makes the adopting tab's stale local value the final server state.
830
+ * The precondition is checked and the write applied in one synchronous step,
831
+ * so nothing can interleave. When it does not hold the current thread comes
832
+ * back untouched, which is exactly what the caller must adopt.
833
+ */
834
+ readonly ifRunConfigUnset?: boolean;
420
835
  }
421
836
  export interface StartWebTurnInput {
422
837
  readonly text?: string;
@@ -428,6 +843,20 @@ export interface StartWebTurnInput {
428
843
  export interface StartWebLiveInputInput {
429
844
  readonly text: string;
430
845
  }
846
+ export interface StartWebSubmissionInput extends StartWebTurnInput {
847
+ readonly submissionId: string;
848
+ }
849
+ export interface WebSubmissionReceipt {
850
+ readonly submissionId: string;
851
+ readonly threadId: string;
852
+ readonly outcome: "turn" | "live-input" | "rejected";
853
+ readonly reason?: "active_attachments_unsupported" | "unsupported_targeting" | "closed_before_dispatch" | "operator_inactive" | "operator_unsupported" | "operator_too_large" | "operator_full" | "operator_invalid" | "mailbox_unsupported" | "mailbox_closed" | "mailbox_failed";
854
+ readonly disposition?: "pending" | "queued";
855
+ readonly messageId?: string;
856
+ readonly turnId?: string;
857
+ readonly message?: WebMessage;
858
+ readonly turn?: WebRunState;
859
+ }
431
860
  export interface WebLiveInputReceipt {
432
861
  readonly message: WebMessage;
433
862
  readonly disposition: "pending" | "queued";