@abide/abide 0.124.1 → 0.125.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/ABIDE.md +4 -0
  2. package/CHANGELOG.md +36 -0
  3. package/bin/abide.ts +3 -2
  4. package/docs/REGISTRY.md +66 -40
  5. package/docs/RULEBOOK.md +202 -18
  6. package/docs/abide.md +391 -67
  7. package/package.json +1 -1
  8. package/src/compiler/appMap.ts +14 -1
  9. package/src/compiler/declaredExports.ts +41 -0
  10. package/src/compiler/handlersUnder.ts +1 -0
  11. package/src/compiler/hookCalls.ts +1 -0
  12. package/src/compiler/projectShadow.ts +52 -2
  13. package/src/compiler/readsIn.ts +39 -34
  14. package/src/server/PageRender.ts +7 -8
  15. package/src/server/abideModules.ts +6 -0
  16. package/src/server/answerRequest.ts +115 -52
  17. package/src/server/answerSocket.ts +6 -5
  18. package/src/server/answerWorker.ts +34 -23
  19. package/src/server/assistant.ts +141 -35
  20. package/src/server/banner.ts +9 -5
  21. package/src/server/bridgeRelay.ts +3 -3
  22. package/src/server/callerOf.ts +5 -0
  23. package/src/server/claudeCode.ts +20 -11
  24. package/src/server/commands.ts +14 -7
  25. package/src/server/createApp.ts +65 -12
  26. package/src/server/devWorker.ts +18 -16
  27. package/src/server/generatedSurfaces.ts +6 -5
  28. package/src/server/handlerFileMount.ts +2 -0
  29. package/src/server/hooks.ts +54 -8
  30. package/src/server/index.ts +18 -4
  31. package/src/server/invokeHandler.ts +1 -1
  32. package/src/server/mountHandlers.ts +6 -0
  33. package/src/server/principal.ts +3 -2
  34. package/src/server/render.ts +11 -2
  35. package/src/server/requestScope.ts +61 -1
  36. package/src/server/responseRelay.ts +9 -3
  37. package/src/server/serveDev.ts +18 -3
  38. package/src/server/sqliteStore.ts +65 -0
  39. package/src/server/testMount.ts +1 -0
  40. package/src/shared/AssistantEvent.ts +40 -0
  41. package/src/shared/BrowserHooks.ts +73 -0
  42. package/src/shared/CURRENT_ROUTER.ts +3 -1
  43. package/src/shared/Issues.ts +11 -3
  44. package/src/shared/Middleware.ts +9 -9
  45. package/src/shared/UNEXPECTED.ts +1 -1
  46. package/src/shared/answerOf.ts +9 -4
  47. package/src/shared/imagePiece.ts +85 -0
  48. package/src/shared/index.ts +17 -0
  49. package/src/shared/isServer.ts +15 -0
  50. package/src/shared/navigate.ts +10 -3
  51. package/src/shared/onError.ts +51 -0
  52. package/src/shared/onRefusal.ts +47 -0
  53. package/src/shared/online.ts +5 -1
  54. package/src/shared/reactive/Keyed.ts +12 -1
  55. package/src/shared/reactive/Reactive.ts +53 -25
  56. package/src/shared/reactive/cellShape.ts +4 -3
  57. package/src/shared/reactive/poll.ts +49 -0
  58. package/src/shared/reactive/scoped.ts +10 -1
  59. package/src/shared/reactive/scoping.ts +14 -0
  60. package/src/shared/reactive/watch.ts +19 -8
  61. package/src/shared/resultsOf.ts +21 -0
  62. package/src/shared/route.ts +18 -4
  63. package/src/shared/rpc.ts +112 -26
  64. package/src/shared/seededDocument.ts +5 -6
  65. package/src/shared/storedValue.ts +32 -0
  66. package/src/shared/webStore.ts +54 -0
  67. package/src/ui/Router.ts +42 -9
  68. package/src/ui/outboxQueue.ts +1 -1
  69. package/src/ui/wire.ts +4 -4
  70. package/src/shared/KEEP_OPENED.ts +0 -7
  71. /package/src/{server → shared}/IMAGE_TYPES.ts +0 -0
package/docs/abide.md CHANGED
@@ -28,6 +28,8 @@ at its address with `.md` on the end, and the links below point at those files.
28
28
  - `reactive` — `reference/reactive.md`
29
29
  - `Transformer` — `reference/types/Transformer.md`
30
30
  - `Store` — `reference/types/Store.md`
31
+ - `webStore` — `reference/webStore.md`
32
+ - `sqliteStore` — `reference/sqliteStore.md`
31
33
  - `Shared` — `reference/types/Shared.md`
32
34
  - `ReactiveOptions` — `reference/types/ReactiveOptions.md`
33
35
  - `structural` — `reference/structural.md`
@@ -78,9 +80,13 @@ at its address with `.md` on the end, and the links below point at those files.
78
80
  - `AssistantEvent` — `reference/types/AssistantEvent.md`
79
81
  - `AssistantOptions` — `reference/types/AssistantOptions.md`
80
82
  - `Provider` — `reference/types/Provider.md`
83
+ - `ProviderEvent` — `reference/types/ProviderEvent.md`
81
84
  - `Toolbox` — `reference/types/Toolbox.md`
82
85
  - `ToolAnswer` — `reference/types/ToolAnswer.md`
83
86
  - `ToolDefinition` — `reference/types/ToolDefinition.md`
87
+ - `resultsOf` — `reference/resultsOf.md`
88
+ - `imagePiece` — `reference/imagePiece.md`
89
+ - `imageFiles` — `reference/imageFiles.md`
84
90
  - `claudeApi` — `reference/claudeApi.md`
85
91
  - `ClaudeApiConfig` — `reference/types/ClaudeApiConfig.md`
86
92
  - `claudeCode` — `reference/claudeCode.md`
@@ -89,6 +95,8 @@ at its address with `.md` on the end, and the links below point at those files.
89
95
  - `cookies` — `reference/cookies.md`
90
96
  - `Cookies` — `reference/types/Cookies.md`
91
97
  - `request` — `reference/request.md`
98
+ - `requestIP` — `reference/requestIP.md`
99
+ - `ReceivedFrom` — `reference/types/ReceivedFrom.md`
92
100
  - `response` — `reference/response.md`
93
101
  - `route` — `reference/route.md`
94
102
  - `Params` — `reference/types/Params.md`
@@ -98,6 +106,7 @@ at its address with `.md` on the end, and the links below point at those files.
98
106
  - `reachable` — `reference/reachable.md`
99
107
  - `trace` — `reference/trace.md`
100
108
  - `server` — `reference/server.md`
109
+ - `isServer` — `reference/isServer.md`
101
110
  - `health` — `reference/health.md`
102
111
  - `Health` — `reference/types/Health.md`
103
112
  - `onHealth` — `reference/onHealth.md`
@@ -135,9 +144,11 @@ at its address with `.md` on the end, and the links below point at those files.
135
144
  - `render` — `reference/render.md`
136
145
  - Configuration — `reference/configuration.md`
137
146
  - `middleware` — `reference/middleware.md`
147
+ - `Lane` — `reference/types/Lane.md`
138
148
  - `onStart` — `reference/onStart.md`
139
149
  - `onStop` — `reference/onStop.md`
140
150
  - `onError` — `reference/onError.md`
151
+ - `onRefusal` — `reference/onRefusal.md`
141
152
  - `onPrincipal` — `reference/onPrincipal.md`
142
153
  - `onLauncher` — `reference/onLauncher.md`
143
154
  - `LauncherOptions` — `reference/types/LauncherOptions.md`
@@ -576,7 +587,7 @@ A `Reactive` can also be awaited, so code that takes a promise for a load asks `
576
587
  | Command | What it does for the CRM |
577
588
  | --- | --- |
578
589
  | `abide scaffold <name>` | writes the starter app above |
579
- | `abide dev [--port <n>]` | serves the app and restarts it on every save; takes the first free port from 3000, or the one you name |
590
+ | `abide dev [--port <n>] [--hostname <host>]` | serves the app and restarts it on every save; takes the first free port from 3000, or the one you name, on every interface or the one you name |
580
591
  | `abide run <file> [args…]` | runs one script with the app's own modules, such as a script that loads contacts from a spreadsheet |
581
592
  | `--help` · `-h` · `abide help` | prints every command |
582
593
  | `--version` · `-v` | prints the version installed |
@@ -715,7 +726,7 @@ A value that starts as a number binds as one, and so does an `<input type="numbe
715
726
  import { reactive } from '@abide/abide'
716
727
 
717
728
  let phone = reactive('', {
718
- transform: (typed: string) => typed.replace(/\D/g, ''),
729
+ transform: (typed) => typed.replace(/\D/g, ''),
719
730
  })
720
731
  </script>
721
732
 
@@ -1481,12 +1492,12 @@ type NewDeal = { name: string; company: string; amount: number }
1481
1492
 
1482
1493
  let name = reactive('Ledger audit')
1483
1494
  let company = reactive('')
1484
- let amount = reactive(0)
1495
+ let amount = reactive<number | undefined>(0)
1485
1496
  let issues = reactive<Issues<NewDeal>>({})
1486
1497
 
1487
1498
  async function add() {
1488
1499
  try {
1489
- await createDeal({ name, company, amount })
1500
+ await createDeal({ name, company, amount: amount ?? 0 })
1490
1501
  issues = {}
1491
1502
  } catch (error) {
1492
1503
  if (!createDeal.isError(error, 'ValidationError')) throw error
@@ -1499,7 +1510,7 @@ async function add() {
1499
1510
  <div class="row">
1500
1511
  <label>name <input bind:value={name}></label>
1501
1512
  <label>company <input bind:value={company}></label>
1502
- <label>amount <input bind:value={amount}></label>
1513
+ <label>amount <input type="number" bind:value={amount}></label>
1503
1514
  <button onclick={add}>Add deal</button>
1504
1515
  </div>
1505
1516
 
@@ -1530,7 +1541,7 @@ const NEW_DEAL = jsonSchema<NewDeal>({
1530
1541
  })
1531
1542
 
1532
1543
  export default POST(
1533
- ({ name, company, amount }: NewDeal) => {
1544
+ ({ name, company, amount }) => {
1534
1545
  // Every caller shares one list: past ten, the newest replaces the last.
1535
1546
  if (DEALS.length >= 10) DEALS.pop()
1536
1547
  const deal = {
@@ -2124,6 +2135,7 @@ Reach for one or the other, not both. A reload over a value marked stale has not
2124
2135
  | `s.refresh` | reloads one value now, serving what is held until the new one lands |
2125
2136
  | `s.invalidate` | marks one value stale; the next read loads |
2126
2137
  | `ttl` | `{ ttl: 60_000 }` lets a value expire a minute after it loaded. Expiry wakes nobody, and the next read loads |
2138
+ | `poll` | `{ poll: 60_000 }` refreshes a value every minute for as long as the component or request that built it stands, skipping a minute its load is still running |
2127
2139
 
2128
2140
  ## After a write, reload only the entries it changed
2129
2141
 
@@ -2583,6 +2595,9 @@ The draft is read in the effect, not inside the timer: a read there happens afte
2583
2595
  | `Disposer` | what tears the previous run down |
2584
2596
  | `s.peek` | reads what is held without subscribing |
2585
2597
  | `flushSync` | runs every effect a write woke before it returns, for a handler that measures or scrolls the page the write left |
2598
+ | `isServer` | whether the effect is running on the server, for work only a browser can do |
2599
+
2600
+ A watch runs on the server too, while the page renders. Guard work that needs the browser, such as `localStorage`, with `isServer()` rather than `typeof window`: a test renders the server half beside a DOM, and `isServer()` still answers for the side the work is on.
2586
2601
 
2587
2602
  The effect is the one place in this card where a read subscribes. Its `Disposer` does not, and nor does any function abide calls without rebuilding it:
2588
2603
 
@@ -2604,7 +2619,7 @@ import { dollars } from './dollars.ts'
2604
2619
  import { targetStore } from './targetStore.ts'
2605
2620
 
2606
2621
  // One option, and the reads and writes below are untouched.
2607
- let target = reactive(500_000, { store: targetStore })
2622
+ let target = reactive<number | undefined>(500_000, { store: targetStore })
2608
2623
  </script>
2609
2624
 
2610
2625
  <label>the team's target this quarter
@@ -2612,7 +2627,7 @@ let target = reactive(500_000, { store: targetStore })
2612
2627
  </label>
2613
2628
 
2614
2629
  <ul class="tiles">
2615
- <li><span>target</span><strong>{dollars(target)}</strong></li>
2630
+ <li><span>target</span><strong>{dollars(target ?? 0)}</strong></li>
2616
2631
  </ul>
2617
2632
  ```
2618
2633
 
@@ -2623,10 +2638,12 @@ import getTarget from '../getTarget.handler.ts'
2623
2638
  import setTarget from '../setTarget.handler.ts'
2624
2639
 
2625
2640
  /** The team's target, kept on the server, so every visitor reads one. */
2626
- export const targetStore: Store<number> = {
2641
+ export const targetStore: Store<number | undefined> = {
2627
2642
  // Never set answers `null`, which is the miss.
2628
2643
  get: async () => (await getTarget()) ?? undefined,
2629
2644
  set: async (target) => {
2645
+ // A blank field is no target, and the team's stands.
2646
+ if (target === undefined) return
2630
2647
  await setTarget({ target })
2631
2648
  // The next read asks the server, not this tab's copy.
2632
2649
  getTarget.invalidate()
@@ -2695,12 +2712,21 @@ test('a target set once is what every later visit opens on', async () => {
2695
2712
  })
2696
2713
  ```
2697
2714
 
2698
- A `Store` is a `get` and a `set`. The value reads the store when it is built and falls back to `500_000` on a miss, and every change is written back. The reads and writes in the markup do not change.
2715
+ A `Store` is a `get` and a `set`. The value reads the store when it is built and falls back to `500_000` on a miss without writing it, and every change is written back. The reads and writes in the markup do not change.
2699
2716
 
2700
2717
  This store goes through two handlers, so the target is one value on the server: the next visit opens on it, and so does everyone else's, painted right the first time. After a write, `set` invalidates the read it made, so the next read asks the server rather than this tab's copy. A setting one visitor alone sees, such as a theme, belongs in a cookie instead.
2701
2718
 
2702
2719
  Where the stored value can change from outside the app, such as a file another program edits, the store adds `watch`. It is handed a function to call when that happens, and returns the function that stops watching. The value reads `get` again, and the body does not run.
2703
2720
 
2721
+ Two stores come with abide, for the places a value most often lives:
2722
+
2723
+ | Name | Where the value lives |
2724
+ | --- | --- |
2725
+ | `webStore` | `webStore('layout')` keeps it in this browser's `localStorage`, or `sessionStorage` with `{ area: 'session' }`, and follows a write another tab makes. On the server it is never there, so the page renders the fallback |
2726
+ | `sqliteStore` | `sqliteStore('crm.db', 'target')`, from `@abide/abide/server`, keeps it in a SQLite table, so a restarted server opens on it |
2727
+
2728
+ Both keep the value as JSON with the value's `ttl` beside it, and pass what they read through a `schema` when given one: a restore skips the value's own, so an entry an older build wrote is a miss rather than a wrong value.
2729
+
2704
2730
  ## Next
2705
2731
 
2706
2732
  - [Make it live](/guide/make-it-live.md) — every open tab sees a change as it happens
@@ -3680,6 +3706,8 @@ An address that matches the page already shown moves `route.url` and keeps the p
3680
3706
 
3681
3707
  A plain `<a href>` click does the same. Reach for `navigate` when code decides where to go. `route.navigating` is true while a navigation is in flight, which is what a progress bar reads.
3682
3708
 
3709
+ `navigate(-1)` steps back through the history the way `history.go` does, and its promise settles once the page it steps to is on screen. `route.index` is the entry's place in the history the app wrote: a step back of up to that many entries stays inside the app.
3710
+
3683
3711
  ## A view transition carries the company across pages
3684
3712
 
3685
3713
  **`view-transition-name` — a company name that moves to where it lands** — A rep opens a company from the list, and the name they clicked becomes the heading they land on. Open one and watch it travel.
@@ -4396,7 +4424,7 @@ test('the claims resolve to the member they name', async () => {
4396
4424
 
4397
4425
  `onPrincipal` is handed the claims and returns your half of the caller. It runs on the server, at most once per request, where the team records are. So the cookie stays small, and a rename shows on the next request rather than at the next sign-in. Filed in any handler file or `.abide`, it resolves the caller for every route.
4398
4426
 
4399
- A test signs in without the cookie. `app.run(fn, { principal: { id: 'theo' } })` hands those claims to `onPrincipal` as a sealed cookie's are, and the card's test reads the member they name.
4427
+ A test signs in without the cookie. `app.run(fn, { principal: { id: 'theo' } })` hands those claims to `onPrincipal` as a sealed cookie's are, and the card's test reads the member they name. `app.fetch(request, { principal })` sends one request signed in the same way, and `caller` beside it names the browser.
4400
4428
 
4401
4429
  What it returns is read as `principal.resolved`, typed by `Principal`. Declare your fields on that interface, as the app's `lib/TEAM.server.ts` does beside the team it reads. abide's own three fields are `authenticated`, `expiresAt` and `error`, and they win any collision, so a resolver cannot sign a caller in by returning `authenticated: true`. A resolver that throws fills `error` and leaves the caller signed out.
4402
4430
 
@@ -4741,9 +4769,91 @@ test('an admin is let through to both', async () => {
4741
4769
  })
4742
4770
  ```
4743
4771
 
4744
- The same `adminsOnly` fits a layout, and there it runs over every page and handler below it. Its refusal is answered in the lane the request was in: the section's `error.abide` paints it over a page, and a handler answers it as Problem Details. A layout's rung has the request and nothing else, so it cannot read a handler's arguments.
4772
+ The same `adminsOnly` fits a layout, and there it runs over every page and handler below it. Its refusal is answered in the lane the request was in: the section's `error.abide` paints it over a page, and a handler answers it as Problem Details. A layout's rung has the request and its `lane` — what answers it — and not a handler's arguments.
4773
+
4774
+ Filed in the root `src/layout.abide`, a rung runs before routing, over every request the app answers, abide's own addresses included, each addressed below the mount. A gate over pages alone tests `lane === 'page'` rather than spelling out which paths are abide's. `abide routes` lists each rung beside the route it is filed at, and the rungs each handler names.
4775
+
4776
+ ## `onRefusal` hears a session end on any call
4777
+
4778
+ **`onRefusal(fn)` — one hook for every call refused 401** — Your commission is for a member signed in. Sign in as Theo, then as Nobody: the next call is refused 401, and the card asks for a sign-in.
4779
+
4780
+ ```abide src/account/lib/SignInAgain.abide
4781
+ <script>
4782
+ import { onRefusal, principal, reactive, watch } from '@abide/abide'
4783
+
4784
+ import getCommission from '../getCommission.handler.ts'
4785
+ import SignInAs from './SignInAs.abide'
4786
+
4787
+ let signedOut = reactive(false)
4788
+
4789
+ // Any call on the page refused 401, whoever made it, asks for a sign-in.
4790
+ onRefusal((refusal) => {
4791
+ if (refusal.status === 401) signedOut = true
4792
+ })
4793
+
4794
+ const commission = reactive(() => getCommission())
4795
+
4796
+ watch(principal.resolved, () => {
4797
+ signedOut = false
4798
+ getCommission.refresh()
4799
+ })
4800
+ </script>
4801
+
4802
+ <SignInAs />
4803
+
4804
+ {#if signedOut}
4805
+ <p class="status">Your session ended. Pick a member to sign in again.</p>
4806
+ {:else}
4807
+ <ul class="fields">
4808
+ <li><span>commission</span>
4809
+ <strong>{commission.ready() ? commission.amount : '—'}</strong></li>
4810
+ </ul>
4811
+ {/if}
4812
+ ```
4813
+
4814
+ ```ts src/account/getCommission.handler.ts
4815
+ import { principal, refuse } from '@abide/abide'
4816
+ import { GET } from '@abide/abide/server'
4817
+
4818
+ /** What the member signed in has earned this quarter. */
4819
+ export default GET(
4820
+ async () => {
4821
+ const { name } = await principal.resolved
4822
+ if (name === undefined) return refuse(401, 'Sign in again.')
4823
+ return { amount: '$6,200' }
4824
+ },
4825
+ { description: "The signed-in member's commission this quarter." },
4826
+ )
4827
+ ```
4828
+
4829
+ ```ts src/account/lib/SignInAgain.test.ts
4830
+ import { expect, test } from 'bun:test'
4831
+
4832
+ import { createApp } from '@abide/abide/server'
4833
+
4834
+ import getCommission from '../getCommission.handler.ts'
4745
4835
 
4746
- Filed in the root `src/layout.abide`, a rung runs before routing, over every request the app answers. `abide routes` lists each rung beside the route it is filed at.
4836
+ test('a member signed in reads their commission', async () => {
4837
+ await using app = await createApp()
4838
+ const commission = await app.run(async () => await getCommission(), {
4839
+ principal: { id: 'theo' },
4840
+ })
4841
+ expect(commission.amount).toBe('$6,200')
4842
+ })
4843
+
4844
+ test('a caller whose session ended is refused 401', async () => {
4845
+ await using app = await createApp()
4846
+ const answer = await app.fetch(
4847
+ new Request('http://crm.invalid/account/getCommission'),
4848
+ )
4849
+ // The status `onRefusal` reads in the browser, from a call nobody caught.
4850
+ expect(answer.status).toBe(401)
4851
+ })
4852
+ ```
4853
+
4854
+ A call that is refused does not throw. The refusal lands on the value's `error`, so `onError` never hears it. `onRefusal`, called in a component's `<script>`, hears every refusal a call from this browser gets while that component stands. That is the server's, a 401 from a proxy in front of it, the 503 for no answer at all, and one a call in `outbox` gets. Each hook gets the call's method and URL beside the refusal, the nearest component's first.
4855
+
4856
+ The hook hears the refusal and leaves it where it is. The value still refuses, so the card that made the call shows what it shows for any refusal. An aborted call is not a refusal, and a hook filed in a layout hears every page below it.
4747
4857
 
4748
4858
  ## `crossOrigin` opens one handler to a partner
4749
4859
 
@@ -5095,7 +5205,8 @@ test('adding a contact answers 201, and where it lives', async () => {
5095
5205
  | --- | --- |
5096
5206
  | `request()` | the platform's `Request`: headers, URL, method, signal |
5097
5207
  | `response()` | the status and headers being sent back |
5098
- | `server()` | the listening `Bun.Server`, for what abide does not carry, such as a client's IP |
5208
+ | `requestIP()` | the address the request came from, the same under `abide dev` and `abide start`, or `'in-process'` for a call the app made of itself |
5209
+ | `server()` | the listening `Bun.Server`, for what abide does not carry |
5099
5210
 
5100
5211
  On an rpc route the body is `ctx.args()`'s. A body reads once, so a rung that reads `request().json()` leaves nothing for the handler.
5101
5212
 
@@ -6191,9 +6302,11 @@ test('the model calls the CRM search, through the app', async () => {
6191
6302
  | --- | --- |
6192
6303
  | `AssistantMessage` | One turn of the transcript, `{ role, content }`. The last is the user's. Its `content` is its words, or its pieces in order. |
6193
6304
  | `AssistantContent` | One piece of a turn: `text`, or an `image` as base64 with its type, so a rep can show the assistant a photo of a business card. PNG, JPEG, GIF and WebP, in the rep's own turns. |
6194
- | `AssistantOptions` | `mcp` to offer the tools, and `maxTurns`, 10 by default, to cap the model's turns in one call. |
6195
- | `AssistantEvent` | What the page reads: `text`, `tool` as a call starts, `input` once it is written, `result`, then `done` with the stop reason and token usage. The same events from every provider. |
6196
- | `Provider` | What runs the conversation: one method, `run`, handed every turn as its pieces. Write one for another model, or a recording for a test. |
6305
+ | `AssistantOptions` | `mcp` to offer the tools, `maxTurns`, 10 by default, to cap the model's turns in one call, and `signal` to end the conversation early, as a rep leaving ends it. |
6306
+ | `AssistantEvent` | What the page reads: `text`, `tool` as a call starts, `input` once it is written, `result`, then `done` with the stop reason and token usage. The same events from every provider. A call to one of your handlers carries its `handler`, the `method` and `address` its import reads, and a result the `value` it answered. Import these types from `@abide/abide` in the page. |
6307
+ | `resultsOf` | What every successful call to one handler answered, in order: `resultsOf(events, searchContacts)` is every list of contacts the assistant searched for, typed as the handler's value. |
6308
+ | `imagePiece` | A pasted, dropped or picked image as a turn's piece, drawn down to 1568 pixels on its long side so a full-size screenshot is not sent with every turn. `imageFiles` is the images a paste or a drop carries. |
6309
+ | `Provider` | What runs the conversation: one method, `run`, handed every turn as its pieces, yielding `ProviderEvent`s — events before the handler and the value are read — naming each tool as `list` does. Write one for another model, or a recording for a test. |
6197
6310
  | `Toolbox` | What a provider is handed: `list` of the tools, and `call` to run one as the asker. |
6198
6311
  | `ToolAnswer` | What `call` answers: its `content`, the same pieces as a turn — the tool's text, or the image a handler drew, which the model is shown as a picture — and whether it failed. |
6199
6312
  | `ToolDefinition` | One tool in `list`: its name, description and input schema. |
@@ -6523,7 +6636,7 @@ The tools the conversation calls run as the visitor, on the sign-in their ask ca
6523
6636
  | Name | What it does for the CRM |
6524
6637
  | --- | --- |
6525
6638
  | `claudeCode.bridge` | Streams this browser's pairing: unpaired with the command to run and the link to open, then paired. |
6526
- | `BridgeStatus` | One status in that stream, `{ paired, command, link }`. |
6639
+ | `BridgeStatus` | One status in that stream, `{ paired, command, link, install }`. `install` is the command that installs the app the link opens, at the release the command runs. |
6527
6640
  | `claudeCode.bridgeCommand` | Mints the command and the link alone, for a page that wants them without the stream. Its code expires unused after ten minutes. |
6528
6641
  | `/__abide/bridge` | Where the visitor's bridge connects. It opens the first time a command is minted. |
6529
6642
 
@@ -6627,7 +6740,7 @@ test('the summary answers in process as it does on the wire', async () => {
6627
6740
  | Name | What it does for the CRM |
6628
6741
  | --- | --- |
6629
6742
  | `App` | what `createApp` hands back, to a test, a script or a host |
6630
- | `App.fetch` | one request, through the whole app, in this process |
6743
+ | `App.fetch` | one request, through the whole app, in this process, as the `principal` and the `caller` you give it |
6631
6744
  | `App.run` | runs a function inside one request's scope, so two reads of one key load once, signed in as the `principal` claims you give it |
6632
6745
  | `App.listen` | binds the socket, for a test that needs a real `WebSocket` |
6633
6746
  | `App.stop` | stops the app: every `onStop`, wrapped around draining what is in flight |
@@ -7273,7 +7386,7 @@ singleQuote = true
7273
7386
  sortImports = true
7274
7387
  ```
7275
7388
 
7276
- `abide build` writes content-hashed chunks and a manifest naming them. `abide start [--port <n>]` serves what was built, and builds first where nothing was. Configuration is checked as it starts, so a misconfigured deployment fails to come up.
7389
+ `abide build` writes content-hashed chunks and a manifest naming them. `abide start [--port <n>] [--hostname <host>]` serves what was built, and builds first where nothing was. Configuration is checked as it starts, so a misconfigured deployment fails to come up.
7277
7390
 
7278
7391
  | Name | What it does for the CRM |
7279
7392
  | --- | --- |
@@ -7403,6 +7516,8 @@ Arrive here knowing which name you want. Each page is read off the registry: the
7403
7516
  | [`reactive`](/reference/reactive.md) | `@abide/abide` |
7404
7517
  | [`Transformer`](/reference/types/Transformer.md) | `@abide/abide` |
7405
7518
  | [`Store`](/reference/types/Store.md) | `@abide/abide` |
7519
+ | [`webStore`](/reference/webStore.md) | `@abide/abide` |
7520
+ | [`sqliteStore`](/reference/sqliteStore.md) | `@abide/abide/server` |
7406
7521
  | [`Shared`](/reference/types/Shared.md) | `@abide/abide` |
7407
7522
  | [`ReactiveOptions`](/reference/types/ReactiveOptions.md) | `@abide/abide` |
7408
7523
  | [`structural`](/reference/structural.md) | `@abide/abide` |
@@ -7463,14 +7578,18 @@ Arrive here knowing which name you want. Each page is read off the registry: the
7463
7578
  | Page | Imported from |
7464
7579
  | --- | --- |
7465
7580
  | [`assistant`](/reference/assistant.md) | `@abide/abide/server` |
7466
- | [`AssistantMessage`](/reference/types/AssistantMessage.md) | `@abide/abide/server` |
7467
- | [`AssistantContent`](/reference/types/AssistantContent.md) | `@abide/abide/server` |
7468
- | [`AssistantEvent`](/reference/types/AssistantEvent.md) | `@abide/abide/server` |
7581
+ | [`AssistantMessage`](/reference/types/AssistantMessage.md) | `@abide/abide` |
7582
+ | [`AssistantContent`](/reference/types/AssistantContent.md) | `@abide/abide` |
7583
+ | [`AssistantEvent`](/reference/types/AssistantEvent.md) | `@abide/abide` |
7469
7584
  | [`AssistantOptions`](/reference/types/AssistantOptions.md) | `@abide/abide/server` |
7470
7585
  | [`Provider`](/reference/types/Provider.md) | `@abide/abide/server` |
7586
+ | [`ProviderEvent`](/reference/types/ProviderEvent.md) | `@abide/abide/server` |
7471
7587
  | [`Toolbox`](/reference/types/Toolbox.md) | `@abide/abide/server` |
7472
7588
  | [`ToolAnswer`](/reference/types/ToolAnswer.md) | `@abide/abide/server` |
7473
7589
  | [`ToolDefinition`](/reference/types/ToolDefinition.md) | `@abide/abide/server` |
7590
+ | [`resultsOf`](/reference/resultsOf.md) | `@abide/abide` |
7591
+ | [`imagePiece`](/reference/imagePiece.md) | `@abide/abide` |
7592
+ | [`imageFiles`](/reference/imageFiles.md) | `@abide/abide` |
7474
7593
  | [`claudeApi`](/reference/claudeApi.md) | `@abide/abide/server` |
7475
7594
  | [`ClaudeApiConfig`](/reference/types/ClaudeApiConfig.md) | `@abide/abide/server` |
7476
7595
  | [`claudeCode`](/reference/claudeCode.md) | `@abide/abide/server` |
@@ -7484,6 +7603,8 @@ Arrive here knowing which name you want. Each page is read off the registry: the
7484
7603
  | [`cookies`](/reference/cookies.md) | `@abide/abide` |
7485
7604
  | [`Cookies`](/reference/types/Cookies.md) | `@abide/abide` |
7486
7605
  | [`request`](/reference/request.md) | `@abide/abide/server` |
7606
+ | [`requestIP`](/reference/requestIP.md) | `@abide/abide/server` |
7607
+ | [`ReceivedFrom`](/reference/types/ReceivedFrom.md) | `@abide/abide/server` |
7487
7608
  | [`response`](/reference/response.md) | `@abide/abide/server` |
7488
7609
  | [`route`](/reference/route.md) | `@abide/abide` |
7489
7610
  | [`Params`](/reference/types/Params.md) | `@abide/abide` |
@@ -7493,6 +7614,7 @@ Arrive here knowing which name you want. Each page is read off the registry: the
7493
7614
  | [`reachable`](/reference/reachable.md) | `@abide/abide/server` |
7494
7615
  | [`trace`](/reference/trace.md) | `@abide/abide/server` |
7495
7616
  | [`server`](/reference/server.md) | `@abide/abide/server` |
7617
+ | [`isServer`](/reference/isServer.md) | `@abide/abide` |
7496
7618
  | [`health`](/reference/health.md) | `@abide/abide` |
7497
7619
  | [`Health`](/reference/types/Health.md) | `@abide/abide` |
7498
7620
  | [`onHealth`](/reference/onHealth.md) | `@abide/abide/server` |
@@ -7550,9 +7672,11 @@ Arrive here knowing which name you want. Each page is read off the registry: the
7550
7672
  | --- | --- |
7551
7673
  | [Configuration](/reference/configuration.md) | written in place |
7552
7674
  | [`middleware`](/reference/middleware.md) | `@abide/abide/server` |
7675
+ | [`Lane`](/reference/types/Lane.md) | `@abide/abide/server` |
7553
7676
  | [`onStart`](/reference/onStart.md) | `@abide/abide/server` |
7554
7677
  | [`onStop`](/reference/onStop.md) | `@abide/abide/server` |
7555
- | [`onError`](/reference/onError.md) | `@abide/abide/server` |
7678
+ | [`onError`](/reference/onError.md) | `@abide/abide` |
7679
+ | [`onRefusal`](/reference/onRefusal.md) | `@abide/abide` |
7556
7680
  | [`onPrincipal`](/reference/onPrincipal.md) | `@abide/abide/server` |
7557
7681
  | [`onLauncher`](/reference/onLauncher.md) | `@abide/abide/server` |
7558
7682
  | [`LauncherOptions`](/reference/types/LauncherOptions.md) | `@abide/abide/server` |
@@ -7769,8 +7893,8 @@ Arrive here knowing which name you want. Each page is read off the registry: the
7769
7893
  | Name | Signature | Meaning | Rules |
7770
7894
  | --- | --- | --- | --- |
7771
7895
  | `Shaped` | `unknown` | What a `transform` hands back: the value to store, or a refusal. | [4.6](/rulebook#4.6), [4.9](/rulebook#4.9) |
7772
- | `reactive` | `<Computed, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>>(body: () => Computed, options?: Omit<ReactiveOptions<Awaited<NoInfer<Computed>>, Kept<Shaped>, never>, 'schema'> & { transform?: (value: Awaited<NoInfer<Computed>>) => Shaped; schema?: Gate & Schema<Awaited<NoInfer<Computed>>> }) => Reactive<Kept<Shaped>, Awaited<Computed>, AdoptedFailures<Computed> \| Refused<Shaped> \| Gated<Gate, Awaited<Computed>>, AdoptedProduced<Computed, Kept<Shaped>>>` | The unkeyed body overload. | [3.9](/rulebook#3.9), [11.1](/rulebook#11.1), [11.3](/rulebook#11.3), [11.5](/rulebook#11.5), [11.7](/rulebook#11.7), [11.8](/rulebook#11.8), [11.9](/rulebook#11.9), [11.10](/rulebook#11.10), [11.11](/rulebook#11.11), [11.12](/rulebook#11.12), [11.13](/rulebook#11.13), [11.14](/rulebook#11.14), [11.15](/rulebook#11.15), [11.16](/rulebook#11.16), [11.17](/rulebook#11.17), [11.18](/rulebook#11.18), [11.19](/rulebook#11.19), [11.20](/rulebook#11.20), [11.21](/rulebook#11.21), [11.22](/rulebook#11.22), [11.32](/rulebook#11.32), [11.33](/rulebook#11.33), [11.50](/rulebook#11.50), [11.51](/rulebook#11.51), [11.52](/rulebook#11.52), [11.53](/rulebook#11.53), [11.54](/rulebook#11.54), [11.57](/rulebook#11.57), [11.58](/rulebook#11.58), [41.6](/rulebook#41.6), [11.62](/rulebook#11.62), [11.63](/rulebook#11.63), [11.65](/rulebook#11.65), [11.66](/rulebook#11.66), [12.14](/rulebook#12.14), [19.24](/rulebook#19.24) |
7773
- | `reactive` | `<Chunk, Shaped = Chunk[], Gate = Schema<Chunk[]>>(body: () => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Omit<ReactiveOptions<Chunk[], Kept<Shaped>, never>, 'schema'> & { transform?: (value: Chunk[]) => Shaped; schema?: Gate & Schema<Chunk[]> }) => Reactive<Kept<Shaped>, Chunk[], Refused<Shaped> \| Gated<Gate, Chunk[]>, Chunk>` | The streaming body overload. | [3.7](/rulebook#3.7), [3.8](/rulebook#3.8), [4.8](/rulebook#4.8), [9.1](/rulebook#9.1), [9.2](/rulebook#9.2), [9.6](/rulebook#9.6), [9.7](/rulebook#9.7), [9.8](/rulebook#9.8), [9.9](/rulebook#9.9) |
7896
+ | `reactive` | `<Computed, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>>(body: () => Computed, options?: Omit<ReactiveOptions<Awaited<NoInfer<Computed>>, Kept<Shaped>, never>, 'schema'> & { transform?: (value: Awaited<NoInfer<Computed>>) => Shaped; schema?: Gate & Schema<Awaited<NoInfer<Computed>>> }) => Reactive<Kept<Shaped>, Awaited<Computed>, AdoptedFailures<Computed> \| Refused<Shaped> \| Gated<Gate, Awaited<Computed>>, AdoptedProduced<Computed, Kept<Shaped>>>` | The unkeyed body overload. | [3.9](/rulebook#3.9), [11.1](/rulebook#11.1), [11.3](/rulebook#11.3), [11.5](/rulebook#11.5), [11.7](/rulebook#11.7), [11.8](/rulebook#11.8), [11.9](/rulebook#11.9), [11.10](/rulebook#11.10), [11.11](/rulebook#11.11), [11.12](/rulebook#11.12), [11.13](/rulebook#11.13), [11.14](/rulebook#11.14), [11.15](/rulebook#11.15), [11.16](/rulebook#11.16), [11.17](/rulebook#11.17), [11.18](/rulebook#11.18), [11.19](/rulebook#11.19), [11.20](/rulebook#11.20), [11.21](/rulebook#11.21), [11.22](/rulebook#11.22), [11.32](/rulebook#11.32), [11.33](/rulebook#11.33), [11.50](/rulebook#11.50), [11.51](/rulebook#11.51), [11.52](/rulebook#11.52), [11.53](/rulebook#11.53), [11.54](/rulebook#11.54), [11.57](/rulebook#11.57), [11.58](/rulebook#11.58), [41.6](/rulebook#41.6), [11.62](/rulebook#11.62), [11.63](/rulebook#11.63), [11.65](/rulebook#11.65), [11.66](/rulebook#11.66), [12.14](/rulebook#12.14), [12.17](/rulebook#12.17), [19.24](/rulebook#19.24) |
7897
+ | `reactive` | `<Chunk, Shaped = Chunk[], Gate = Schema<Chunk[]>>(body: () => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Omit<ReactiveOptions<Chunk[], Kept<Shaped>, never>, 'schema'> & { transform?: (value: Chunk[]) => Shaped; schema?: Gate & Schema<Chunk[]> }) => Reactive<Kept<Shaped>, Chunk[], Refused<Shaped> \| Gated<Gate, Chunk[]>, Chunk>` | The streaming body overload. | [3.7](/rulebook#3.7), [3.8](/rulebook#3.8), [4.8](/rulebook#4.8), [9.1](/rulebook#9.1), [9.2](/rulebook#9.2), [9.6](/rulebook#9.6), [9.7](/rulebook#9.7), [9.8](/rulebook#9.8), [9.9](/rulebook#9.9), [12.14](/rulebook#12.14), [12.17](/rulebook#12.17), [12.16](/rulebook#12.16) |
7774
7898
  | `reactive` | `<Chunk, Args, Shaped = Chunk[], Gate = Schema<Chunk[]>, ArgsGate = Schema<Args>>(body: (args: Args) => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Omit<ReactiveOptions<Chunk[], Kept<Shaped>, never, Args>, 'schema' \| 'args'> & { transform?: (value: Chunk[]) => Shaped; schema?: Gate & Schema<Chunk[]>; args?: ArgsGate & Schema<Args> }) => Keyed<Kept<Shaped>, Args, Chunk[], Refused<Shaped> \| Gated<Gate, Chunk[]> \| Gated<ArgsGate, Args>, Chunk>` | The keyed streaming body overload. | [9.6](/rulebook#9.6), [9.9](/rulebook#9.9) |
7775
7899
  | `reactive` | `<Chunk, Args, Shaped = Chunk[], Gate = Schema<Chunk[]>, ArgsGate = Schema<Args \| undefined>>(body: (args?: Args) => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Omit<ReactiveOptions<Chunk[], Kept<Shaped>, never, Args \| undefined>, 'schema' \| 'args'> & { transform?: (value: Chunk[]) => Shaped; schema?: Gate & Schema<Chunk[]>; args?: ArgsGate & Schema<Args \| undefined> }) => Keyed<Kept<Shaped>, Args \| undefined, Chunk[], Refused<Shaped> \| Gated<Gate, Chunk[]> \| Gated<ArgsGate, Args \| undefined>, Chunk>` | The keyed streaming overload for a body whose parameter is optional. | [11.2](/rulebook#11.2) |
7776
7900
  | `reactive` | `<Computed, Args, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>, ArgsGate = Schema<Args>>(body: (args: Args) => Computed, options?: Omit<ReactiveOptions<Awaited<NoInfer<Computed>>, Kept<Shaped>, never, Args>, 'schema' \| 'args'> & { transform?: (value: Awaited<NoInfer<Computed>>) => Shaped; schema?: Gate & Schema<Awaited<NoInfer<Computed>>>; args?: ArgsGate & Schema<Args> }) => Keyed<Kept<Shaped>, Args, Awaited<Computed>, AdoptedFailures<Computed> \| Refused<Shaped> \| Gated<Gate, Awaited<Computed>> \| Gated<ArgsGate, Args>, AdoptedProduced<Computed, Kept<Shaped>>>` | The keyed body overload. | [11.2](/rulebook#11.2), [11.3](/rulebook#11.3), [11.4](/rulebook#11.4), [11.6](/rulebook#11.6), [11.7](/rulebook#11.7), [11.23](/rulebook#11.23), [11.55](/rulebook#11.55), [11.62](/rulebook#11.62), [19.24](/rulebook#19.24) |
@@ -7823,6 +7947,42 @@ Arrive here knowing which name you want. Each page is read off the registry: the
7823
7947
 
7824
7948
  ---
7825
7949
 
7950
+ <!-- reference/webStore.md -->
7951
+
7952
+ # `webStore`
7953
+
7954
+ `import { webStore } from '@abide/abide'`
7955
+
7956
+ ## The value
7957
+
7958
+ | Name | Signature | Meaning | Rules |
7959
+ | --- | --- | --- | --- |
7960
+ | `webStore` | `<Stored>(key: string, options?: { area?: 'local' \| 'session'; schema?: Schema<Stored> }) => Store<Stored>` | A `Store` kept in the browser's Web Storage. | [8.22](/rulebook#8.22), [8.23](/rulebook#8.23), [8.24](/rulebook#8.24), [8.26](/rulebook#8.26), [8.27](/rulebook#8.27), [8.28](/rulebook#8.28) |
7961
+
7962
+ ## Taught in
7963
+
7964
+ - [Keep it current](/guide/keep-it-current.md)
7965
+
7966
+ ---
7967
+
7968
+ <!-- reference/sqliteStore.md -->
7969
+
7970
+ # `sqliteStore`
7971
+
7972
+ `import { sqliteStore } from '@abide/abide/server'`
7973
+
7974
+ ## The value
7975
+
7976
+ | Name | Signature | Meaning | Rules |
7977
+ | --- | --- | --- | --- |
7978
+ | `sqliteStore` | `<Stored>(database: Database \| string, key: string, options?: { table?: string; schema?: Schema<Stored> }) => Store<Stored>` | A `Store` kept in a `bun:sqlite` table, from `@abide/abide/server`. | [8.25](/rulebook#8.25), [8.26](/rulebook#8.26), [8.27](/rulebook#8.27), [8.28](/rulebook#8.28) |
7979
+
7980
+ ## Taught in
7981
+
7982
+ - [Keep it current](/guide/keep-it-current.md)
7983
+
7984
+ ---
7985
+
7826
7986
  <!-- reference/types/Shared.md -->
7827
7987
 
7828
7988
  # `Shared`
@@ -7857,6 +8017,7 @@ Arrive here knowing which name you want. Each page is read off the registry: the
7857
8017
  | `identity` | `(next: Stored, previous: Stored) => unknown` | What makes it the same value. | [5.1](/rulebook#5.1), [5.2](/rulebook#5.2), [5.3](/rulebook#5.3), [5.4](/rulebook#5.4), [5.5](/rulebook#5.5), [9.3](/rulebook#9.3), [11.17](/rulebook#11.17), [18.4](/rulebook#18.4) |
7858
8018
  | `by` | `(keyof Element & string) \| ((element: Element) => unknown)`, over the `Element` a `Stored` array holds | What tells one element of the value from another. | [5.22](/rulebook#5.22), [18.4](/rulebook#18.4), [18.15](/rulebook#18.15), [32.32](/rulebook#32.32) |
7859
8019
  | `ttl` | `number` | The life of a production, or of a keyed entry. | [6.1](/rulebook#6.1), [6.2](/rulebook#6.2), [6.3](/rulebook#6.3), [6.4](/rulebook#6.4), [6.5](/rulebook#6.5), [6.6](/rulebook#6.6), [6.7](/rulebook#6.7), [6.8](/rulebook#6.8), [6.9](/rulebook#6.9), [6.10](/rulebook#6.10), [11.6](/rulebook#11.6), [11.35](/rulebook#11.35), [11.45](/rulebook#11.45), [11.48](/rulebook#11.48), [11.49](/rulebook#11.49), [11.69](/rulebook#11.69) |
8020
+ | `poll` | `number` | How often the value refreshes itself, in milliseconds. | [7.20](/rulebook#7.20), [7.21](/rulebook#7.21), [7.22](/rulebook#7.22), [7.23](/rulebook#7.23), [7.24](/rulebook#7.24), [7.25](/rulebook#7.25) |
7860
8021
  | `args` | `Schema<Args>` | The gate on a keyed value's args. | [9.4](/rulebook#9.4), [11.28](/rulebook#11.28), [11.30](/rulebook#11.30), [11.40](/rulebook#11.40), [11.41](/rulebook#11.41), [11.56](/rulebook#11.56), [11.60](/rulebook#11.60), [11.68](/rulebook#11.68), [11.72](/rulebook#11.72) |
7861
8022
  | `global` | `boolean` | Opts out of the default scope into one cache shared by every caller in the process. | [11.34](/rulebook#11.34), [11.35](/rulebook#11.35), [11.36](/rulebook#11.36), [11.37](/rulebook#11.37), [11.38](/rulebook#11.38), [11.39](/rulebook#11.39), [11.53](/rulebook#11.53), [11.67](/rulebook#11.67) |
7862
8023
  | `tags` | `string[] \| ((args: Args) => string[])` | What a `Selection` matches on. | [11.43](/rulebook#11.43), [11.44](/rulebook#11.44), [18.4](/rulebook#18.4), [18.15](/rulebook#18.15) |
@@ -8284,7 +8445,7 @@ Reactive primitives: what is written in place rather than imported.
8284
8445
 
8285
8446
  | Name | Signature | Meaning | Rules |
8286
8447
  | --- | --- | --- | --- |
8287
- | `Middleware` | `Middleware<Answer = never, Extra extends object = object> = <Given extends { request: Request } & Extra, Result>(next: (ctx?: Given) => Promise<Result>, ctx: Given) => Result \| Answer \| Failed<string, unknown> \| Promise<Result \| Answer \| Failed<string, unknown>>` | One rung, written once for every lane whose context carries `Extra`. | [16.14](/rulebook#16.14), [16.15](/rulebook#16.15), [16.16](/rulebook#16.16), [16.21](/rulebook#16.21), [37.14](/rulebook#37.14), [37.15](/rulebook#37.15) |
8448
+ | `Middleware` | `Middleware<Answer = never, Extra extends object = object, Refused extends Failed<string, unknown> = Failed<string, unknown>> = <Given extends { request: Request } & Extra, Result>(next: (ctx?: Given) => Promise<Result>, ctx: Given) => Result \| Answer \| Refused \| Promise<Result \| Answer \| Refused>` | One rung, written once for every lane whose context carries `Extra`. | [16.8](/rulebook#16.8), [16.14](/rulebook#16.14), [16.15](/rulebook#16.15), [16.16](/rulebook#16.16), [16.21](/rulebook#16.21), [16.86](/rulebook#16.86), [37.14](/rulebook#37.14), [37.15](/rulebook#37.15) |
8288
8449
 
8289
8450
  ## Taught in
8290
8451
 
@@ -8302,15 +8463,15 @@ Reactive primitives: what is written in place rather than imported.
8302
8463
 
8303
8464
  | Name | Signature | Meaning | Rules |
8304
8465
  | --- | --- | --- | --- |
8305
- | `GET` | `<Stored, Accepted, Failures, Produced>(handler: Reactive<Stored, Accepted, Failures, Produced>, options?: RpcOptions<undefined>) => Rpc<Stored, undefined, Failures, Produced>` | Declares a read any surface may call. | [16.1](/rulebook#16.1), [16.2](/rulebook#16.2), [16.5](/rulebook#16.5), [16.6](/rulebook#16.6), [16.30](/rulebook#16.30), [16.31](/rulebook#16.31), [16.32](/rulebook#16.32), [16.68](/rulebook#16.68), [16.76](/rulebook#16.76), [16.34](/rulebook#16.34), [16.35](/rulebook#16.35), [16.36](/rulebook#16.36), [16.37](/rulebook#16.37), [16.39](/rulebook#16.39), [16.44](/rulebook#16.44), [16.45](/rulebook#16.45), [16.46](/rulebook#16.46), [16.47](/rulebook#16.47), [16.75](/rulebook#16.75), [16.50](/rulebook#16.50), [16.51](/rulebook#16.51), [16.52](/rulebook#16.52), [16.64](/rulebook#16.64), [18.1](/rulebook#18.1), [18.3](/rulebook#18.3), [18.6](/rulebook#18.6), [18.8](/rulebook#18.8), [18.10](/rulebook#18.10), [18.12](/rulebook#18.12), [18.21](/rulebook#18.21), [18.24](/rulebook#18.24), [18.27](/rulebook#18.27) |
8306
- | `GET` | `<Stored, Args, Accepted, Failures, Produced>(handler: Keyed<Stored, Args, Accepted, Failures, Produced>, options?: RpcOptions<Args>) => Rpc<Stored, Args, Failures, Produced>` | The keyed overload, for a `Keyed` given an address. | [11.2](/rulebook#11.2), [16.1](/rulebook#16.1), [16.3](/rulebook#16.3), [16.6](/rulebook#16.6) |
8307
- | `GET` | `<Chunk, Shaped = Chunk[], Gate = Schema<Chunk[]>>(handler: () => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Shaping<Chunk[], Shaped, never, Gate> & RpcOptions<undefined>) => Rpc<Kept<Shaped>, undefined, Refusals<Shaped, Gate, Chunk[]>, Chunk>` | The streaming overload, whose options build the value it becomes beside its address. | [16.1](/rulebook#16.1), [16.6](/rulebook#16.6), [16.7](/rulebook#16.7), [16.44](/rulebook#16.44), [16.45](/rulebook#16.45), [16.46](/rulebook#16.46), [16.47](/rulebook#16.47) |
8308
- | `GET` | `<Chunk, Args, Shaped = Chunk[], Gate = Schema<Chunk[]>, ArgsGate = Schema<Args>>(handler: (args: Args) => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Shaping<Chunk[], Shaped, Args, Gate, ArgsGate> & RpcOptions<Args>) => Rpc<Kept<Shaped>, Args, Refusals<Shaped, Gate, Chunk[], ArgsGate, Args>, Chunk>` | The keyed streaming overload. | [11.2](/rulebook#11.2), [16.1](/rulebook#16.1), [16.6](/rulebook#16.6), [16.7](/rulebook#16.7) |
8309
- | `GET` | `<Chunk, Args, Shaped = Chunk[], Gate = Schema<Chunk[]>, ArgsGate = Schema<Args \| undefined>>(handler: (args?: Args) => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Shaping<Chunk[], Shaped, Args \| undefined, Gate, ArgsGate> & RpcOptions<Args \| undefined>) => Rpc<Kept<Shaped>, Args \| undefined, Refusals<Shaped, Gate, Chunk[], ArgsGate, Args \| undefined>, Chunk>` | The keyed streaming overload for a body whose parameter is optional. | [11.2](/rulebook#11.2) |
8310
- | `GET` | `<Computed, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>>(handler: () => Computed, options?: Shaping<Awaited<Computed>, Shaped, never, Gate> & RpcOptions<undefined>) => Rpc<Kept<Shaped>, undefined, AdoptedFailures<Computed> \| Refusals<Shaped, Gate, Awaited<Computed>>, AdoptedProduced<Computed, Kept<Shaped>>>` | The plain-function overload, whose options (`ttl`, `global`, `debounce` and the rest) build the value it becomes beside its address. | [16.1](/rulebook#16.1), [16.6](/rulebook#16.6), [16.7](/rulebook#16.7) |
8311
- | `GET` | `<Computed, Args, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>, ArgsGate = Schema<Args>>(handler: (args: Args) => Computed, options?: Shaping<Awaited<Computed>, Shaped, Args, Gate, ArgsGate> & RpcOptions<Args>) => Rpc<Kept<Shaped>, Args, AdoptedFailures<Computed> \| Refusals<Shaped, Gate, Awaited<Computed>, ArgsGate, Args>, AdoptedProduced<Computed, Kept<Shaped>>>` | The keyed plain-function overload. | [11.2](/rulebook#11.2), [16.1](/rulebook#16.1), [16.6](/rulebook#16.6), [16.7](/rulebook#16.7) |
8312
- | `GET` | `<Computed, Args, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>, ArgsGate = Schema<Args \| undefined>>(handler: (args?: Args) => Computed, options?: Shaping<Awaited<Computed>, Shaped, Args \| undefined, Gate, ArgsGate> & RpcOptions<Args \| undefined>) => Rpc<Kept<Shaped>, Args \| undefined, AdoptedFailures<Computed> \| Refusals<Shaped, Gate, Awaited<Computed>, ArgsGate, Args \| undefined>, AdoptedProduced<Computed, Kept<Shaped>>>` | The keyed plain-function overload for a body whose parameter is optional. | [11.2](/rulebook#11.2) |
8313
- | `GET` | `<Accepted, Shaped = Accepted, Gate = Schema<Accepted>>(handler: Accepted \| PromiseLike<Accepted>, options?: Shaping<Accepted, Shaped, never, Gate> & RpcOptions<undefined>) => Rpc<Kept<Shaped>, undefined, Refusals<Shaped, Gate, Accepted>>` | The value overload, for what the handler owns outright, whose options build the value it becomes. | [16.1](/rulebook#16.1), [16.6](/rulebook#16.6), [16.7](/rulebook#16.7) |
8466
+ | `GET` | `<Stored, Accepted, Failures, Produced, Answers extends readonly unknown[] = unknown[]>(handler: Reactive<Stored, Accepted, Failures, Produced>, options?: RpcOptions<undefined, Answers>) => Rpc<Stored, undefined, Failures \| RungRefusals<Answers>, Produced>` | Declares a read any surface may call. | [16.1](/rulebook#16.1), [16.2](/rulebook#16.2), [16.5](/rulebook#16.5), [16.6](/rulebook#16.6), [16.30](/rulebook#16.30), [16.31](/rulebook#16.31), [16.32](/rulebook#16.32), [16.68](/rulebook#16.68), [16.76](/rulebook#16.76), [16.34](/rulebook#16.34), [16.35](/rulebook#16.35), [16.36](/rulebook#16.36), [16.37](/rulebook#16.37), [16.39](/rulebook#16.39), [16.44](/rulebook#16.44), [16.45](/rulebook#16.45), [16.46](/rulebook#16.46), [16.47](/rulebook#16.47), [16.75](/rulebook#16.75), [16.50](/rulebook#16.50), [16.51](/rulebook#16.51), [16.52](/rulebook#16.52), [16.64](/rulebook#16.64), [12.17](/rulebook#12.17), [18.1](/rulebook#18.1), [18.3](/rulebook#18.3), [18.6](/rulebook#18.6), [18.8](/rulebook#18.8), [18.10](/rulebook#18.10), [18.12](/rulebook#18.12), [18.21](/rulebook#18.21), [18.24](/rulebook#18.24), [18.27](/rulebook#18.27) |
8467
+ | `GET` | `<Stored, Args, Accepted, Failures, Produced, Answers extends readonly unknown[] = unknown[]>(handler: Keyed<Stored, Args, Accepted, Failures, Produced>, options?: RpcOptions<Args, Answers>) => Rpc<Stored, Args, Failures \| RungRefusals<Answers>, Produced>` | The keyed overload, for a `Keyed` given an address. | [11.2](/rulebook#11.2), [16.1](/rulebook#16.1), [16.3](/rulebook#16.3), [16.6](/rulebook#16.6) |
8468
+ | `GET` | `<Chunk, Shaped = Chunk[], Gate = Schema<Chunk[]>, Answers extends readonly unknown[] = unknown[]>(handler: () => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Shaping<Chunk[], Shaped, never, Gate> & RpcOptions<undefined, Answers>) => Rpc<Kept<Shaped>, undefined, Refusals<Shaped, Gate, Chunk[]> \| RungRefusals<Answers>, Chunk>` | The streaming overload, whose options build the value it becomes beside its address. | [16.1](/rulebook#16.1), [16.6](/rulebook#16.6), [16.7](/rulebook#16.7), [16.44](/rulebook#16.44), [16.45](/rulebook#16.45), [16.46](/rulebook#16.46), [16.47](/rulebook#16.47) |
8469
+ | `GET` | `<Chunk, Args, Shaped = Chunk[], Gate = Schema<Chunk[]>, ArgsGate = Schema<Args>, Answers extends readonly unknown[] = unknown[]>(handler: (args: Args) => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Shaping<Chunk[], Shaped, Args, Gate, ArgsGate> & RpcOptions<Args, Answers>) => Rpc<Kept<Shaped>, Args, Refusals<Shaped, Gate, Chunk[], ArgsGate, Args> \| RungRefusals<Answers>, Chunk>` | The keyed streaming overload. | [11.2](/rulebook#11.2), [16.1](/rulebook#16.1), [16.6](/rulebook#16.6), [16.7](/rulebook#16.7), [16.87](/rulebook#16.87) |
8470
+ | `GET` | `<Chunk, Args, Shaped = Chunk[], Gate = Schema<Chunk[]>, ArgsGate = Schema<Args \| undefined>, Answers extends readonly unknown[] = unknown[]>(handler: (args?: Args) => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Shaping<Chunk[], Shaped, Args \| undefined, Gate, ArgsGate> & RpcOptions<Args \| undefined, Answers>) => Rpc<Kept<Shaped>, Args \| undefined, Refusals<Shaped, Gate, Chunk[], ArgsGate, Args \| undefined> \| RungRefusals<Answers>, Chunk>` | The keyed streaming overload for a body whose parameter is optional. | [11.2](/rulebook#11.2), [16.87](/rulebook#16.87) |
8471
+ | `GET` | `<Computed, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>, Answers extends readonly unknown[] = unknown[]>(handler: () => Computed, options?: Shaping<Awaited<Computed>, Shaped, never, Gate> & RpcOptions<undefined, Answers>) => Rpc<Kept<Shaped>, undefined, AdoptedFailures<Computed> \| Refusals<Shaped, Gate, Awaited<Computed>> \| RungRefusals<Answers>, AdoptedProduced<Computed, Kept<Shaped>>>` | The plain-function overload, whose options (`ttl`, `global`, `debounce` and the rest) build the value it becomes beside its address. | [16.1](/rulebook#16.1), [16.6](/rulebook#16.6), [16.7](/rulebook#16.7) |
8472
+ | `GET` | `<Computed, Args, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>, ArgsGate = Schema<Args>, Answers extends readonly unknown[] = unknown[]>(handler: (args: Args) => Computed, options?: Shaping<Awaited<Computed>, Shaped, Args, Gate, ArgsGate> & RpcOptions<Args, Answers>) => Rpc<Kept<Shaped>, Args, AdoptedFailures<Computed> \| Refusals<Shaped, Gate, Awaited<Computed>, ArgsGate, Args> \| RungRefusals<Answers>, AdoptedProduced<Computed, Kept<Shaped>>>` | The keyed plain-function overload. | [11.2](/rulebook#11.2), [16.1](/rulebook#16.1), [16.6](/rulebook#16.6), [16.7](/rulebook#16.7), [16.87](/rulebook#16.87) |
8473
+ | `GET` | `<Computed, Args, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>, ArgsGate = Schema<Args \| undefined>, Answers extends readonly unknown[] = unknown[]>(handler: (args?: Args) => Computed, options?: Shaping<Awaited<Computed>, Shaped, Args \| undefined, Gate, ArgsGate> & RpcOptions<Args \| undefined, Answers>) => Rpc<Kept<Shaped>, Args \| undefined, AdoptedFailures<Computed> \| Refusals<Shaped, Gate, Awaited<Computed>, ArgsGate, Args \| undefined> \| RungRefusals<Answers>, AdoptedProduced<Computed, Kept<Shaped>>>` | The keyed plain-function overload for a body whose parameter is optional. | [11.2](/rulebook#11.2), [16.87](/rulebook#16.87) |
8474
+ | `GET` | `<Accepted, Shaped = Accepted, Gate = Schema<Accepted>, Answers extends readonly unknown[] = unknown[]>(handler: Accepted \| PromiseLike<Accepted>, options?: Shaping<Accepted, Shaped, never, Gate> & RpcOptions<undefined, Answers>) => Rpc<Kept<Shaped>, undefined, Refusals<Shaped, Gate, Accepted> \| RungRefusals<Answers>>` | The value overload, for what the handler owns outright, whose options build the value it becomes. | [16.1](/rulebook#16.1), [16.6](/rulebook#16.6), [16.7](/rulebook#16.7) |
8314
8475
 
8315
8476
  ## Taught in
8316
8477
 
@@ -8365,7 +8526,7 @@ Reactive primitives: what is written in place rather than imported.
8365
8526
  | Name | Signature | Meaning | Rules |
8366
8527
  | --- | --- | --- | --- |
8367
8528
  | `description` | `string` | The human description carried onto every generated surface. | [16.28](/rulebook#16.28) |
8368
- | `middleware` | `((next: (ctx?: { request: Request; args: () => Args }) => Promise<unknown>, ctx: { request: Request; args: () => Args }) => unknown)[]` | The rungs run per call. | [16.11](/rulebook#16.11), [16.12](/rulebook#16.12), [16.16](/rulebook#16.16), [16.17](/rulebook#16.17), [16.18](/rulebook#16.18), [16.19](/rulebook#16.19), [16.20](/rulebook#16.20) |
8529
+ | `middleware` | `{ [At in keyof Answers]: (next: (ctx?: { request: Request; args: () => Args }) => Promise<Reached>, ctx: { request: Request; args: () => Args }) => Answers[At] \| Promise<Answers[At]> }` | The rungs run per call. | [16.8](/rulebook#16.8), [16.11](/rulebook#16.11), [16.12](/rulebook#16.12), [16.16](/rulebook#16.16), [16.17](/rulebook#16.17), [16.18](/rulebook#16.18), [16.19](/rulebook#16.19), [16.20](/rulebook#16.20), [16.86](/rulebook#16.86) |
8369
8530
  | `timeout` | `number` | How long the call may go without progress. | [16.22](/rulebook#16.22), [16.58](/rulebook#16.58), [16.59](/rulebook#16.59), [16.60](/rulebook#16.60), [16.61](/rulebook#16.61), [16.77](/rulebook#16.77) |
8370
8531
  | `clients` | `Clients` | Which surfaces carry this handler. | [16.37](/rulebook#16.37), [20.3](/rulebook#20.3) |
8371
8532
  | `crossOrigin` | `boolean \| string[]` | Whether other origins may call it, or follow it over the mux. | [16.24](/rulebook#16.24), [18.2](/rulebook#18.2), [21.19](/rulebook#21.19) |
@@ -8618,7 +8779,7 @@ Transports: what is written in place rather than imported.
8618
8779
 
8619
8780
  | Name | Signature | Meaning | Rules |
8620
8781
  | --- | --- | --- | --- |
8621
- | `Issues<T>` | `T extends object ? Partial<Record<Paths<T> \| '', string[]>> : string[]` | What was wrong, keyed by where. | [19.4](/rulebook#19.4), [19.19](/rulebook#19.19) |
8782
+ | `Issues<T>` | `T extends Rpc<infer _Value, infer Args, infer _Failures, infer _Produced> ? Issues<Args> : T extends object ? Partial<Record<Paths<T> \| '', string[]>> : string[]` | What was wrong, keyed by where. | [19.4](/rulebook#19.4), [19.19](/rulebook#19.19), [19.26](/rulebook#19.26) |
8622
8783
 
8623
8784
  ## Taught in
8624
8785
 
@@ -8734,7 +8895,7 @@ Generated surfaces: what is written in place rather than imported.
8734
8895
 
8735
8896
  | Name | Signature | Meaning | Rules |
8736
8897
  | --- | --- | --- | --- |
8737
- | `assistant` | `(messages: AssistantMessage[], provider: Provider, options?: AssistantOptions) => AsyncGenerator<AssistantEvent>` | A conversation with a model, as the events it produces. | [44.1](/rulebook#44.1), [44.2](/rulebook#44.2), [44.3](/rulebook#44.3), [44.4](/rulebook#44.4), [44.21](/rulebook#44.21), [44.36](/rulebook#44.36), [44.37](/rulebook#44.37), [44.39](/rulebook#44.39) |
8898
+ | `assistant` | `(messages: AssistantMessage[], provider: Provider, options?: AssistantOptions) => AsyncGenerator<AssistantEvent>` | A conversation with a model, as the events it produces. | [44.1](/rulebook#44.1), [44.2](/rulebook#44.2), [44.3](/rulebook#44.3), [44.4](/rulebook#44.4), [44.21](/rulebook#44.21), [44.36](/rulebook#44.36), [44.37](/rulebook#44.37), [44.39](/rulebook#44.39), [44.57](/rulebook#44.57) |
8738
8899
 
8739
8900
  ## Taught in
8740
8901
 
@@ -8746,7 +8907,7 @@ Generated surfaces: what is written in place rather than imported.
8746
8907
 
8747
8908
  # `AssistantMessage`
8748
8909
 
8749
- `import type { AssistantMessage } from '@abide/abide/server'`
8910
+ `import type { AssistantMessage } from '@abide/abide'`
8750
8911
 
8751
8912
  ## Assistant
8752
8913
 
@@ -8764,7 +8925,7 @@ Generated surfaces: what is written in place rather than imported.
8764
8925
 
8765
8926
  # `AssistantContent`
8766
8927
 
8767
- `import type { AssistantContent } from '@abide/abide/server'`
8928
+ `import type { AssistantContent } from '@abide/abide'`
8768
8929
 
8769
8930
  ## Assistant
8770
8931
 
@@ -8782,13 +8943,13 @@ Generated surfaces: what is written in place rather than imported.
8782
8943
 
8783
8944
  # `AssistantEvent`
8784
8945
 
8785
- `import type { AssistantEvent } from '@abide/abide/server'`
8946
+ `import type { AssistantEvent } from '@abide/abide'`
8786
8947
 
8787
8948
  ## Assistant
8788
8949
 
8789
8950
  | Name | Signature | Meaning | Rules |
8790
8951
  | --- | --- | --- | --- |
8791
- | `AssistantEvent` | `{ type: 'text'; text: string } \| { type: 'tool'; id: string; name: string } \| { type: 'input'; id: string; input: unknown } \| { type: 'result'; id: string; text: string; failed: boolean } \| { type: 'done'; stop: string; usage: { input: number; output: number } }` | What a conversation produces: text, a tool call as it starts, its input once written, its result, and the end. | [44.2](/rulebook#44.2), [44.11](/rulebook#44.11), [44.28](/rulebook#44.28) |
8952
+ | `AssistantEvent` | `{ type: 'text'; text: string } \| { type: 'tool'; id: string; name: string; handler: { method: string; address: string } \| undefined } \| { type: 'input'; id: string; input: unknown } \| { type: 'result'; id: string; text: string; failed: boolean; handler: { method: string; address: string } \| undefined; value: unknown } \| { type: 'done'; stop: string; usage: { input: number; output: number } }` | What a conversation produces: text, a tool call as it starts, its input once written, its result, and the end. | [44.2](/rulebook#44.2), [44.11](/rulebook#44.11), [44.28](/rulebook#44.28), [44.48](/rulebook#44.48), [44.49](/rulebook#44.49) |
8792
8953
 
8793
8954
  ## Taught in
8794
8955
 
@@ -8806,7 +8967,7 @@ Generated surfaces: what is written in place rather than imported.
8806
8967
 
8807
8968
  | Name | Signature | Meaning | Rules |
8808
8969
  | --- | --- | --- | --- |
8809
- | `AssistantOptions` | `{ mcp?: boolean; maxTurns?: number }` | What `assistant` takes beside a provider. | [44.6](/rulebook#44.6), [44.8](/rulebook#44.8), [44.11](/rulebook#44.11) |
8970
+ | `AssistantOptions` | `{ mcp?: boolean; maxTurns?: number; signal?: AbortSignal }` | What `assistant` takes beside a provider. | [44.6](/rulebook#44.6), [44.8](/rulebook#44.8), [44.11](/rulebook#44.11), [44.57](/rulebook#44.57) |
8810
8971
 
8811
8972
  ## Taught in
8812
8973
 
@@ -8824,7 +8985,25 @@ Generated surfaces: what is written in place rather than imported.
8824
8985
 
8825
8986
  | Name | Signature | Meaning | Rules |
8826
8987
  | --- | --- | --- | --- |
8827
- | `Provider` | `{ run(messages: (AssistantMessage & { content: AssistantContent[] })[], tools: Toolbox, limits: { maxTurns: number; signal: AbortSignal }): AsyncGenerator<AssistantEvent> }` | What runs a conversation. | [44.2](/rulebook#44.2), [44.28](/rulebook#44.28), [44.39](/rulebook#44.39) |
8988
+ | `Provider` | `{ run(messages: (AssistantMessage & { content: AssistantContent[] })[], tools: Toolbox, limits: { maxTurns: number; signal: AbortSignal }): AsyncGenerator<ProviderEvent> }` | What runs a conversation. | [44.2](/rulebook#44.2), [44.28](/rulebook#44.28), [44.39](/rulebook#44.39), [44.50](/rulebook#44.50), [44.57](/rulebook#44.57) |
8989
+
8990
+ ## Taught in
8991
+
8992
+ - [Open it to machines](/guide/open-it-to-machines.md)
8993
+
8994
+ ---
8995
+
8996
+ <!-- reference/types/ProviderEvent.md -->
8997
+
8998
+ # `ProviderEvent`
8999
+
9000
+ `import type { ProviderEvent } from '@abide/abide/server'`
9001
+
9002
+ ## Assistant
9003
+
9004
+ | Name | Signature | Meaning | Rules |
9005
+ | --- | --- | --- | --- |
9006
+ | `ProviderEvent` | `Exclude<AssistantEvent, { type: 'tool' \| 'result' }> \| { type: 'tool'; id: string; name: string } \| { type: 'result'; id: string; text: string; failed: boolean }` | An `AssistantEvent` as a provider yields it, before `assistant` reads the handler and the value off the app's surface. | [44.28](/rulebook#44.28), [44.35](/rulebook#44.35), [44.50](/rulebook#44.50) |
8828
9007
 
8829
9008
  ## Taught in
8830
9009
 
@@ -8886,6 +9065,60 @@ Generated surfaces: what is written in place rather than imported.
8886
9065
 
8887
9066
  ---
8888
9067
 
9068
+ <!-- reference/resultsOf.md -->
9069
+
9070
+ # `resultsOf`
9071
+
9072
+ `import { resultsOf } from '@abide/abide'`
9073
+
9074
+ ## Assistant
9075
+
9076
+ | Name | Signature | Meaning | Rules |
9077
+ | --- | --- | --- | --- |
9078
+ | `resultsOf` | `<Value>(events: readonly AssistantEvent[], handler: Rpc<Value, never, unknown, unknown>) => Value[]` | What a conversation's calls to one handler answered. | [44.51](/rulebook#44.51) |
9079
+
9080
+ ## Taught in
9081
+
9082
+ - [Open it to machines](/guide/open-it-to-machines.md)
9083
+
9084
+ ---
9085
+
9086
+ <!-- reference/imagePiece.md -->
9087
+
9088
+ # `imagePiece`
9089
+
9090
+ `import { imagePiece } from '@abide/abide'`
9091
+
9092
+ ## Assistant
9093
+
9094
+ | Name | Signature | Meaning | Rules |
9095
+ | --- | --- | --- | --- |
9096
+ | `imagePiece` | `(image: Blob) => Promise<{ type: 'image'; data: string; mimeType: string }>` | An image as a turn's image piece, drawn down to what a model looks at. | [44.52](/rulebook#44.52), [44.53](/rulebook#44.53), [44.54](/rulebook#44.54) |
9097
+
9098
+ ## Taught in
9099
+
9100
+ - [Open it to machines](/guide/open-it-to-machines.md)
9101
+
9102
+ ---
9103
+
9104
+ <!-- reference/imageFiles.md -->
9105
+
9106
+ # `imageFiles`
9107
+
9108
+ `import { imageFiles } from '@abide/abide'`
9109
+
9110
+ ## Assistant
9111
+
9112
+ | Name | Signature | Meaning | Rules |
9113
+ | --- | --- | --- | --- |
9114
+ | `imageFiles` | `(data: DataTransfer \| null) => File[]` | The images a paste or a drop carries that a model is shown. | [44.55](/rulebook#44.55) |
9115
+
9116
+ ## Taught in
9117
+
9118
+ - [Open it to machines](/guide/open-it-to-machines.md)
9119
+
9120
+ ---
9121
+
8889
9122
  <!-- reference/claudeApi.md -->
8890
9123
 
8891
9124
  # `claudeApi`
@@ -8933,7 +9166,7 @@ Generated surfaces: what is written in place rather than imported.
8933
9166
  | Name | Signature | Meaning | Rules |
8934
9167
  | --- | --- | --- | --- |
8935
9168
  | `claudeCode` | `(config?: ClaudeCodeConfig) => Provider` | The visitor's own Claude Code, reached through the bridge paired with their browser, as a provider. | [44.5](/rulebook#44.5), [44.13](/rulebook#44.13), [44.17](/rulebook#44.17), [44.18](/rulebook#44.18), [44.19](/rulebook#44.19), [44.33](/rulebook#44.33) |
8936
- | `claudeCode.bridgeCommand` | `(options?: { tools?: string[] }) => { command: string; link: string; expires: number }` | The command and the link that pair a bridge with this browser, granting the built-in tools it is given. | [44.14](/rulebook#44.14), [44.32](/rulebook#44.32), [44.33](/rulebook#44.33), [44.40](/rulebook#44.40) |
9169
+ | `claudeCode.bridgeCommand` | `(options?: { tools?: string[] }) => { command: string; link: string; install: string; expires: number }` | The command and the link that pair a bridge with this browser, granting the built-in tools it is given, and the command that installs the app the link opens. | [44.14](/rulebook#44.14), [44.32](/rulebook#44.32), [44.33](/rulebook#44.33), [44.40](/rulebook#44.40), [44.56](/rulebook#44.56) |
8937
9170
  | `claudeCode.bridge` | `(options?: { tools?: string[] }) => AsyncGenerator<BridgeStatus>` | This browser's pairing, as it changes. | [44.20](/rulebook#44.20), [44.22](/rulebook#44.22), [44.32](/rulebook#44.32), [44.33](/rulebook#44.33), [44.34](/rulebook#44.34), [44.40](/rulebook#44.40) |
8938
9171
  | `/__abide/bridge` | `GET`, `POST` | Where a bridge pairs, and is relayed its turns. | [36.7](/rulebook#36.7), [44.14](/rulebook#44.14), [44.15](/rulebook#44.15), [44.19](/rulebook#44.19), [44.23](/rulebook#44.23), [44.26](/rulebook#44.26), [16.57](/rulebook#16.57), [16.78](/rulebook#16.78) |
8939
9172
 
@@ -8971,7 +9204,7 @@ Generated surfaces: what is written in place rather than imported.
8971
9204
 
8972
9205
  | Name | Signature | Meaning | Rules |
8973
9206
  | --- | --- | --- | --- |
8974
- | `BridgeStatus` | `{ paired: boolean; command: string \| undefined; link: string \| undefined }` | Whether a bridge is paired, and the command and the link that pair one where none is. | [44.20](/rulebook#44.20), [44.40](/rulebook#44.40) |
9207
+ | `BridgeStatus` | `{ paired: boolean; command: string \| undefined; link: string \| undefined; install: string \| undefined }` | Whether a bridge is paired, and the command and the link that pair one where none is, with the command that installs the app the link opens. | [44.20](/rulebook#44.20), [44.40](/rulebook#44.40), [44.56](/rulebook#44.56) |
8975
9208
 
8976
9209
  ## Taught in
8977
9210
 
@@ -9033,6 +9266,42 @@ Generated surfaces: what is written in place rather than imported.
9033
9266
 
9034
9267
  ---
9035
9268
 
9269
+ <!-- reference/requestIP.md -->
9270
+
9271
+ # `requestIP`
9272
+
9273
+ `import { requestIP } from '@abide/abide/server'`
9274
+
9275
+ ## `requestIP`
9276
+
9277
+ | Name | Signature | Meaning | Rules |
9278
+ | --- | --- | --- | --- |
9279
+ | `requestIP` | `() => ReceivedFrom \| 'in-process'` | Where the request being served came from. | [22.1](/rulebook#22.1), [22.12](/rulebook#22.12), [22.13](/rulebook#22.13) |
9280
+
9281
+ ## Taught in
9282
+
9283
+ - [Who sees what](/guide/decide-who-sees-what.md)
9284
+
9285
+ ---
9286
+
9287
+ <!-- reference/types/ReceivedFrom.md -->
9288
+
9289
+ # `ReceivedFrom`
9290
+
9291
+ `import type { ReceivedFrom } from '@abide/abide/server'`
9292
+
9293
+ ## `requestIP`
9294
+
9295
+ | Name | Signature | Meaning | Rules |
9296
+ | --- | --- | --- | --- |
9297
+ | `ReceivedFrom` | `{ address: string; family: 'IPv4' \| 'IPv6'; port: number } \| null` | The peer a listener received a request from. | [22.12](/rulebook#22.12) |
9298
+
9299
+ ## Taught in
9300
+
9301
+ - [Who sees what](/guide/decide-who-sees-what.md)
9302
+
9303
+ ---
9304
+
9036
9305
  <!-- reference/response.md -->
9037
9306
 
9038
9307
  # `response`
@@ -9064,6 +9333,7 @@ Generated surfaces: what is written in place rather than imported.
9064
9333
  | `route.url` | `Reactive<URL>` | Where we are, fragment included. | [23.1](/rulebook#23.1), [23.2](/rulebook#23.2), [23.3](/rulebook#23.3), [23.4](/rulebook#23.4), [30.20](/rulebook#30.20), [30.21](/rulebook#30.21), [30.23](/rulebook#30.23), [30.33](/rulebook#30.33), [19.16](/rulebook#19.16), [31.15](/rulebook#31.15) |
9065
9334
  | `route.params` | `Reactive<Params>` | The matched route's segments — typed by its own route in a page or a layout, and `Params` in any other file. | [23.1](/rulebook#23.1), [23.5](/rulebook#23.5), [23.9](/rulebook#23.9), [30.23](/rulebook#30.23), [31.15](/rulebook#31.15) |
9066
9335
  | `route.name` | `Reactive<string>` | The resolution path, the same under any mount path. | [23.1](/rulebook#23.1), [23.6](/rulebook#23.6), [23.14](/rulebook#23.14), [31.15](/rulebook#31.15) |
9336
+ | `route.index` | `Reactive<number>` | The place of the entry the address bar stands at in the history this app's router wrote. | [23.1](/rulebook#23.1), [23.28](/rulebook#23.28), [23.29](/rulebook#23.29), [31.15](/rulebook#31.15) |
9067
9337
  | `route.navigating` | `Reactive<boolean>` | Whether a navigation is in flight. | [23.1](/rulebook#23.1), [31.15](/rulebook#31.15) |
9068
9338
 
9069
9339
  ## Taught in
@@ -9204,6 +9474,24 @@ Generated surfaces: what is written in place rather than imported.
9204
9474
 
9205
9475
  ---
9206
9476
 
9477
+ <!-- reference/isServer.md -->
9478
+
9479
+ # `isServer`
9480
+
9481
+ `import { isServer } from '@abide/abide'`
9482
+
9483
+ ## `isServer`
9484
+
9485
+ | Name | Signature | Meaning | Rules |
9486
+ | --- | --- | --- | --- |
9487
+ | `isServer` | `() => boolean` | Whether the work running is a server's. | [22.11](/rulebook#22.11), [12.7](/rulebook#12.7), [23.7](/rulebook#23.7), [23.8](/rulebook#23.8) |
9488
+
9489
+ ## Taught in
9490
+
9491
+ - [Keep it current](/guide/keep-it-current.md)
9492
+
9493
+ ---
9494
+
9207
9495
  <!-- reference/health.md -->
9208
9496
 
9209
9497
  # `health`
@@ -9726,7 +10014,7 @@ Generated surfaces: what is written in place rather than imported.
9726
10014
 
9727
10015
  | Name | Signature | Meaning | Rules |
9728
10016
  | --- | --- | --- | --- |
9729
- | `navigate` | `(url?: URL \| string, options?: { replace?: boolean, keepScroll?: boolean }) => Promise<void>` | Navigates. | [30.7](/rulebook#30.7), [30.9](/rulebook#30.9), [30.10](/rulebook#30.10), [30.11](/rulebook#30.11), [30.12](/rulebook#30.12), [30.13](/rulebook#30.13), [30.14](/rulebook#30.14), [30.15](/rulebook#30.15), [30.16](/rulebook#30.16), [30.17](/rulebook#30.17), [30.18](/rulebook#30.18), [30.20](/rulebook#30.20), [30.21](/rulebook#30.21), [30.22](/rulebook#30.22), [30.23](/rulebook#30.23), [30.24](/rulebook#30.24), [30.25](/rulebook#30.25), [30.27](/rulebook#30.27), [30.29](/rulebook#30.29), [30.30](/rulebook#30.30), [30.31](/rulebook#30.31), [30.32](/rulebook#30.32), [45.12](/rulebook#45.12), [45.24](/rulebook#45.24) |
10017
+ | `navigate` | `{ (by: number): Promise<void>; (url?: URL \| string, options?: { replace?: boolean, keepScroll?: boolean }): Promise<void> }` | Navigates to an address, or steps through the history. | [30.7](/rulebook#30.7), [30.38](/rulebook#30.38), [30.39](/rulebook#30.39), [30.9](/rulebook#30.9), [30.10](/rulebook#30.10), [30.11](/rulebook#30.11), [30.12](/rulebook#30.12), [30.13](/rulebook#30.13), [30.14](/rulebook#30.14), [30.15](/rulebook#30.15), [30.16](/rulebook#30.16), [30.17](/rulebook#30.17), [30.18](/rulebook#30.18), [30.20](/rulebook#30.20), [30.21](/rulebook#30.21), [30.22](/rulebook#30.22), [30.23](/rulebook#30.23), [30.24](/rulebook#30.24), [30.25](/rulebook#30.25), [30.27](/rulebook#30.27), [30.29](/rulebook#30.29), [30.30](/rulebook#30.30), [30.31](/rulebook#30.31), [30.32](/rulebook#30.32), [45.12](/rulebook#45.12), [45.24](/rulebook#45.24) |
9730
10018
 
9731
10019
  ## Taught in
9732
10020
 
@@ -9766,13 +10054,13 @@ Generated surfaces: what is written in place rather than imported.
9766
10054
  | `name={expr}` | A reactive attribute or property. | [32.3](/rulebook#32.3), [32.20](/rulebook#32.20), [32.23](/rulebook#32.23), [32.37](/rulebook#32.37), [32.70](/rulebook#32.70), [32.71](/rulebook#32.71) |
9767
10055
  | `on<event>={fn}` | A native listener on an element, and an ordinary prop on a component. | [32.4](/rulebook#32.4), [32.75](/rulebook#32.75) |
9768
10056
  | `name="…{expr}…"` | An interpolated quoted value. | [32.3](/rulebook#32.3), [32.71](/rulebook#32.71) |
9769
- | `bind:value` | Two-way bind on an element. | [5.16](/rulebook#5.16), [32.5](/rulebook#32.5), [32.58](/rulebook#32.58), [32.59](/rulebook#32.59), [32.60](/rulebook#32.60), [32.61](/rulebook#32.61), [32.62](/rulebook#32.62), [32.72](/rulebook#32.72), [32.74](/rulebook#32.74), [32.75](/rulebook#32.75), [32.76](/rulebook#32.76) |
10057
+ | `bind:value` | Two-way bind on an element. | [5.16](/rulebook#5.16), [32.5](/rulebook#32.5), [32.58](/rulebook#32.58), [32.59](/rulebook#32.59), [32.60](/rulebook#32.60), [32.61](/rulebook#32.61), [32.62](/rulebook#32.62), [32.72](/rulebook#32.72), [32.74](/rulebook#32.74), [32.75](/rulebook#32.75), [32.76](/rulebook#32.76), [32.78](/rulebook#32.78) |
9770
10058
  | `bind:prop={state}` | Hands a component prop the caller's `Reactive`, or a `{get, set}` pair, to write through. | [32.6](/rulebook#32.6), [33.6](/rulebook#33.6), [33.8](/rulebook#33.8), [14.18](/rulebook#14.18), [32.76](/rulebook#32.76) |
9771
- | `bind:checked` | A boolean bind on an input. | [32.7](/rulebook#32.7), [32.72](/rulebook#32.72), [32.74](/rulebook#32.74), [32.75](/rulebook#32.75), [32.76](/rulebook#32.76) |
9772
- | `bind:open` | The same, on a `<details>`. | [32.7](/rulebook#32.7), [32.72](/rulebook#32.72), [32.74](/rulebook#32.74), [32.75](/rulebook#32.75), [32.76](/rulebook#32.76) |
10059
+ | `bind:checked` | A boolean bind on an input. | [32.7](/rulebook#32.7), [32.72](/rulebook#32.72), [32.74](/rulebook#32.74), [32.75](/rulebook#32.75), [32.76](/rulebook#32.76), [32.78](/rulebook#32.78) |
10060
+ | `bind:open` | The same, on a `<details>`. | [32.7](/rulebook#32.7), [32.72](/rulebook#32.72), [32.74](/rulebook#32.74), [32.75](/rulebook#32.75), [32.76](/rulebook#32.76), [32.78](/rulebook#32.78) |
9773
10061
  | `bind:group` | Radio or checkbox membership. | [32.8](/rulebook#32.8), [32.72](/rulebook#32.72), [32.74](/rulebook#32.74), [32.75](/rulebook#32.75), [32.76](/rulebook#32.76) |
9774
- | `bind:files` | A file input's files, as a list. | [32.73](/rulebook#32.73), [32.72](/rulebook#32.72), [32.74](/rulebook#32.74), [32.75](/rulebook#32.75), [32.76](/rulebook#32.76) |
9775
- | `bind:value={{get, set}}` | Two-way bind over an explicit accessor pair, on an element or a component. | [32.5](/rulebook#32.5), [32.6](/rulebook#32.6) |
10062
+ | `bind:files` | A file input's files, as a list. | [32.73](/rulebook#32.73), [32.72](/rulebook#32.72), [32.74](/rulebook#32.74), [32.75](/rulebook#32.75), [32.76](/rulebook#32.76), [32.78](/rulebook#32.78) |
10063
+ | `bind:value={{get, set}}` | Two-way bind over an explicit accessor pair, on an element or a component. | [32.5](/rulebook#32.5), [32.6](/rulebook#32.6), [32.78](/rulebook#32.78) |
9776
10064
  | `bind:element={Reactive<Element> \| ((element: Element) => void \| Disposer)}` | A node reference. | [32.9](/rulebook#32.9), [32.38](/rulebook#32.38), [32.66](/rulebook#32.66), [32.68](/rulebook#32.68), [32.69](/rulebook#32.69) |
9777
10065
  | `class:name={cond}` | Toggles a class. | [32.10](/rulebook#32.10), [32.71](/rulebook#32.71) |
9778
10066
  | `style:prop={value}` | Sets one style property. | [32.10](/rulebook#32.10), [32.19](/rulebook#32.19), [32.71](/rulebook#32.71) |
@@ -9905,7 +10193,7 @@ Pages and routing: what is written in place rather than imported.
9905
10193
  | `[[name]]` | An optional segment. | [23.5](/rulebook#23.5), [30.4](/rulebook#30.4), [30.34](/rulebook#30.34), [30.36](/rulebook#30.36) |
9906
10194
  | `[...name]` | A rest segment, terminal. | [23.5](/rulebook#23.5), [30.5](/rulebook#30.5), [30.34](/rulebook#30.34), [30.36](/rulebook#30.36) |
9907
10195
  | `[name=NAME]` · `[[name=NAME]]` · `[...name=NAME]` | A dynamic segment a param file's matcher decides. | [19.1](/rulebook#19.1), [23.26](/rulebook#23.26), [23.27](/rulebook#23.27), [30.19](/rulebook#30.19), [30.35](/rulebook#30.35), [30.36](/rulebook#30.36), [30.37](/rulebook#30.37) |
9908
- | `/__abide/**` | Every endpoint abide controls. | [20.8](/rulebook#20.8) |
10196
+ | `/__abide/**` | Every endpoint abide controls. | [20.8](/rulebook#20.8), [37.19](/rulebook#37.19) |
9909
10197
 
9910
10198
  ## Sinks
9911
10199
 
@@ -9982,7 +10270,7 @@ Configuration: what is written in place rather than imported.
9982
10270
  | `ABIDE_MAX_REQUEST_BODY_SIZE` | `number` | The default ceiling on a mutation's body. | [16.13](/rulebook#16.13), [16.54](/rulebook#16.54), [16.55](/rulebook#16.55), [16.78](/rulebook#16.78) |
9983
10271
  | `ABIDE_MAX_SOCKET_MESSAGE_SIZE` | `number` | The ceiling on a frame received over the socket mux, in bytes. | [18.28](/rulebook#18.28) |
9984
10272
  | `ABIDE_MAX_SOCKET_SUBSCRIPTIONS` | `number` | How many values one connection to the socket mux may follow. | [18.31](/rulebook#18.31), [18.32](/rulebook#18.32) |
9985
- | `ABIDE_OFFLINE` | `boolean` | Whether the app keeps its pages and its bundle on the device, for when the network is gone. | [45.1](/rulebook#45.1), [45.2](/rulebook#45.2), [45.3](/rulebook#45.3), [45.4](/rulebook#45.4), [45.5](/rulebook#45.5), [45.6](/rulebook#45.6), [45.7](/rulebook#45.7), [45.8](/rulebook#45.8), [45.9](/rulebook#45.9), [45.10](/rulebook#45.10), [45.11](/rulebook#45.11), [45.12](/rulebook#45.12), [45.13](/rulebook#45.13), [45.14](/rulebook#45.14), [45.15](/rulebook#45.15), [45.16](/rulebook#45.16), [45.17](/rulebook#45.17), [45.18](/rulebook#45.18), [45.19](/rulebook#45.19), [45.20](/rulebook#45.20), [45.21](/rulebook#45.21), [45.22](/rulebook#45.22), [45.23](/rulebook#45.23), [45.24](/rulebook#45.24) |
10273
+ | `ABIDE_OFFLINE` | `boolean` | Whether the app keeps its pages and its bundle on the device, for when the network is gone. | [45.1](/rulebook#45.1), [45.2](/rulebook#45.2), [45.3](/rulebook#45.3), [45.4](/rulebook#45.4), [45.5](/rulebook#45.5), [45.6](/rulebook#45.6), [45.7](/rulebook#45.7), [45.8](/rulebook#45.8), [45.9](/rulebook#45.9), [45.10](/rulebook#45.10), [45.11](/rulebook#45.11), [45.12](/rulebook#45.12), [45.13](/rulebook#45.13), [45.14](/rulebook#45.14), [45.15](/rulebook#45.15), [45.16](/rulebook#45.16), [45.17](/rulebook#45.17), [45.18](/rulebook#45.18), [45.19](/rulebook#45.19), [45.20](/rulebook#45.20), [45.21](/rulebook#45.21), [45.22](/rulebook#45.22), [45.23](/rulebook#45.23), [45.24](/rulebook#45.24), [45.25](/rulebook#45.25), [45.26](/rulebook#45.26) |
9986
10274
  | `ABIDE_STOP_TIMEOUT` | `number` | How long `App.stop` drains, in ms. | [42.17](/rulebook#42.17), [42.18](/rulebook#42.18) |
9987
10275
  | `ABIDE_MAX_STREAM_BUFFER_SIZE` | `number` | The cap on a stream transcript held in memory. | [36.18](/rulebook#36.18) |
9988
10276
  | `ABIDE_MAX_LOG_BUFFER_COUNT` | `number` | How many lines `log.records` is trimmed back to. | [28.1](/rulebook#28.1) |
@@ -10043,7 +10331,25 @@ Configuration: what is written in place rather than imported.
10043
10331
 
10044
10332
  | Name | Signature | Meaning | Rules |
10045
10333
  | --- | --- | --- | --- |
10046
- | `middleware` | `(...rungs: ((next: (ctx?: { request: Request }) => Promise<Response>, ctx: { request: Request }) => Response \| Failed<string, unknown> \| Promise<Response \| Failed<string, unknown>>)[]) => () => void` | The per-request lane at the calling file's route. | [18.26](/rulebook#18.26), [37.2](/rulebook#37.2), [37.3](/rulebook#37.3), [37.13](/rulebook#37.13), [37.14](/rulebook#37.14), [37.15](/rulebook#37.15) |
10334
+ | `middleware` | `(...rungs: ((next: (ctx?: { request: Request }) => Promise<Response>, ctx: { request: Request; lane: Lane }) => Response \| Failed<string, unknown> \| Promise<Response \| Failed<string, unknown>>)[]) => () => void` | The per-request lane at the calling file's route. | [18.26](/rulebook#18.26), [37.2](/rulebook#37.2), [37.3](/rulebook#37.3), [37.13](/rulebook#37.13), [37.14](/rulebook#37.14), [37.15](/rulebook#37.15), [37.19](/rulebook#37.19), [37.20](/rulebook#37.20) |
10335
+
10336
+ ## Taught in
10337
+
10338
+ - [Who sees what](/guide/decide-who-sees-what.md)
10339
+
10340
+ ---
10341
+
10342
+ <!-- reference/types/Lane.md -->
10343
+
10344
+ # `Lane`
10345
+
10346
+ `import type { Lane } from '@abide/abide/server'`
10347
+
10348
+ ## Lifecycle hooks
10349
+
10350
+ | Name | Signature | Meaning | Rules |
10351
+ | --- | --- | --- | --- |
10352
+ | `Lane` | `'page' \| 'handler' \| 'file' \| 'openapi' \| 'mcp' \| 'bridge' \| 'socket' \| 'abide'` | What answers a request a `middleware` rung is handed. | [37.19](/rulebook#37.19) |
10047
10353
 
10048
10354
  ## Taught in
10049
10355
 
@@ -10091,13 +10397,13 @@ Configuration: what is written in place rather than imported.
10091
10397
 
10092
10398
  # `onError`
10093
10399
 
10094
- `import { onError } from '@abide/abide/server'`
10400
+ `import { onError } from '@abide/abide'`
10095
10401
 
10096
10402
  ## Lifecycle hooks
10097
10403
 
10098
10404
  | Name | Signature | Meaning | Rules |
10099
10405
  | --- | --- | --- | --- |
10100
- | `onError` | `(fn: (error: unknown) => unknown) => () => void` | Runs on an unexpected error at the calling file's route. | [37.5](/rulebook#37.5), [37.8](/rulebook#37.8), [37.13](/rulebook#37.13) |
10406
+ | `onError` | `(fn: (error: unknown) => unknown) => () => void` | Runs on an unexpected error at the calling file's route, or in the browser below the calling component. | [37.5](/rulebook#37.5), [37.8](/rulebook#37.8), [37.13](/rulebook#37.13), [37.16](/rulebook#37.16), [37.17](/rulebook#37.17), [37.18](/rulebook#37.18), [37.21](/rulebook#37.21), [12.6](/rulebook#12.6) |
10101
10407
 
10102
10408
  ## Taught in
10103
10409
 
@@ -10105,6 +10411,24 @@ Configuration: what is written in place rather than imported.
10105
10411
 
10106
10412
  ---
10107
10413
 
10414
+ <!-- reference/onRefusal.md -->
10415
+
10416
+ # `onRefusal`
10417
+
10418
+ `import { onRefusal } from '@abide/abide'`
10419
+
10420
+ ## Lifecycle hooks
10421
+
10422
+ | Name | Signature | Meaning | Rules |
10423
+ | --- | --- | --- | --- |
10424
+ | `onRefusal` | `(fn: (refusal: Failed<string, unknown>, call: { method: 'GET' \| 'POST' \| 'PUT' \| 'PATCH' \| 'DELETE'; url: string }) => unknown) => () => void` | What the browser hands each refusal a call over http is answered with, below the calling component. | [37.13](/rulebook#37.13), [37.22](/rulebook#37.22), [37.23](/rulebook#37.23), [37.24](/rulebook#37.24), [37.25](/rulebook#37.25), [37.26](/rulebook#37.26), [37.27](/rulebook#37.27) |
10425
+
10426
+ ## Taught in
10427
+
10428
+ - [Who sees what](/guide/decide-who-sees-what.md)
10429
+
10430
+ ---
10431
+
10108
10432
  <!-- reference/onPrincipal.md -->
10109
10433
 
10110
10434
  # `onPrincipal`
@@ -10315,8 +10639,8 @@ Configuration: what is written in place rather than imported.
10315
10639
  | Name | Signature | Meaning | Rules |
10316
10640
  | --- | --- | --- | --- |
10317
10641
  | `App` | `interface App` | What a host, a test or a script holds the app as. | [42.12](/rulebook#42.12), [42.13](/rulebook#42.13) |
10318
- | `App.fetch` | `(request: Request) => Promise<Response>` | The whole request path, entered in process. | [42.5](/rulebook#42.5), [42.6](/rulebook#42.6) |
10319
- | `App.run` | `<Result>(fn: () => Result \| Promise<Result>, options?: { request?: Request; principal?: Record<string, unknown> }) => Promise<Result>` | One scope around a function, and nothing else. | [42.7](/rulebook#42.7), [42.8](/rulebook#42.8), [42.19](/rulebook#42.19), [11.38](/rulebook#11.38) |
10642
+ | `App.fetch` | `(request: Request, options?: { principal?: Record<string, unknown>; caller?: string }) => Promise<Response>` | The whole request path, entered in process. | [42.5](/rulebook#42.5), [42.6](/rulebook#42.6), [42.20](/rulebook#42.20), [42.21](/rulebook#42.21) |
10643
+ | `App.run` | `<Result>(fn: () => Result \| Promise<Result>, options?: { request?: Request; principal?: Record<string, unknown>; caller?: string }) => Promise<Result>` | One scope around a function, and nothing else. | [42.7](/rulebook#42.7), [42.8](/rulebook#42.8), [42.19](/rulebook#42.19), [42.21](/rulebook#42.21), [11.38](/rulebook#11.38) |
10320
10644
  | `App.listen` | `(options?: { port?: number; hostname?: string; unix?: string }) => Promise<void>` | The socket, bound. | [42.9](/rulebook#42.9), [16.23](/rulebook#16.23), [16.56](/rulebook#16.56), [18.28](/rulebook#18.28), [18.29](/rulebook#18.29), [18.30](/rulebook#18.30) |
10321
10645
  | `App.stop` | `() => Promise<void>` | The drain and the teardown. | [42.10](/rulebook#42.10), [42.11](/rulebook#42.11), [42.15](/rulebook#42.15), [42.17](/rulebook#42.17), [37.4](/rulebook#37.4) |
10322
10646
  | `App[Symbol.asyncDispose]` | `() => Promise<void>` | `App.stop`, under the name `await using` calls. | [42.14](/rulebook#42.14) |
@@ -10337,7 +10661,7 @@ Configuration: what is written in place rather than imported.
10337
10661
 
10338
10662
  | Name | Signature | Meaning | Rules |
10339
10663
  | --- | --- | --- | --- |
10340
- | `mount` | `(component: Component) => Promise<Mounted>` | A bound component, rendered into the document's body and hydrated there. | [38.119](/rulebook#38.119), [38.121](/rulebook#38.121) |
10664
+ | `mount` | `(component: Component) => Promise<Mounted>` | A bound component, rendered into the document's body and hydrated there. | [38.119](/rulebook#38.119), [38.121](/rulebook#38.121), [38.134](/rulebook#38.134) |
10341
10665
 
10342
10666
  ## Taught in
10343
10667
 
@@ -10499,7 +10823,7 @@ The measurement harness: what is written in place rather than imported.
10499
10823
 
10500
10824
  | Name | Meaning | Rules |
10501
10825
  | --- | --- | --- |
10502
- | `preload = ["@abide/harness/preload"]` | The `[test]` preload that registers a DOM with the measure lane's patches installed. | [43.4](/rulebook#43.4), [43.28](/rulebook#43.28) |
10826
+ | `preload = ["@abide/harness/preload"]` | The `[test]` preload that registers a DOM with the measure lane's patches installed. | [43.4](/rulebook#43.4), [43.28](/rulebook#43.28), [43.35](/rulebook#43.35) |
10503
10827
 
10504
10828
  ## `@abide/harness/runner` — runners that print rows, and the bench runner
10505
10829
 
@@ -11272,16 +11596,16 @@ CLI: what is written in place rather than imported.
11272
11596
  | `abide run <file> [args…]` | Runs a script under the abide runtime. | [38.2](/rulebook#38.2), [38.57](/rulebook#38.57) |
11273
11597
  | `abide check [dir…]` | The type-checker over a `.abide` tree. | [38.3](/rulebook#38.3), [38.31](/rulebook#38.31), [38.32](/rulebook#38.32), [38.33](/rulebook#38.33), [38.40](/rulebook#38.40), [38.105](/rulebook#38.105), [38.123](/rulebook#38.123) |
11274
11598
  | `abide format [--check] [dir…]` | The formatter over a `.abide` tree. | [38.25](/rulebook#38.25), [38.125](/rulebook#38.125), [38.126](/rulebook#38.126), [38.127](/rulebook#38.127), [38.128](/rulebook#38.128), [38.129](/rulebook#38.129) |
11275
- | `abide routes [--json]` | Every address the app answers, the file answering it, what each matcher takes, and where each hook is filed. | [38.108](/rulebook#38.108), [38.123](/rulebook#38.123) |
11276
- | `abide dev [--port <n>]` | Watches the project and keeps the app up. | [16.23](/rulebook#16.23), [16.56](/rulebook#16.56), [37.8](/rulebook#37.8), [37.9](/rulebook#37.9), [38.4](/rulebook#38.4), [38.14](/rulebook#38.14), [38.15](/rulebook#38.15), [38.16](/rulebook#38.16), [38.17](/rulebook#38.17), [38.19](/rulebook#38.19), [38.24](/rulebook#38.24), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.28](/rulebook#38.28), [38.30](/rulebook#38.30), [38.35](/rulebook#38.35), [38.36](/rulebook#38.36), [38.37](/rulebook#38.37), [38.38](/rulebook#38.38), [38.41](/rulebook#38.41), [38.43](/rulebook#38.43), [38.58](/rulebook#38.58), [38.63](/rulebook#38.63), [38.64](/rulebook#38.64), [38.65](/rulebook#38.65), [38.94](/rulebook#38.94), [38.96](/rulebook#38.96), [38.97](/rulebook#38.97), [38.123](/rulebook#38.123) |
11599
+ | `abide routes [--json]` | Every address the app answers, the file answering it, what each matcher takes, the rungs each handler names, and where each hook is filed. | [38.108](/rulebook#38.108), [38.123](/rulebook#38.123), [38.135](/rulebook#38.135) |
11600
+ | `abide dev [--port <n>] [--hostname <host>]` | Watches the project and keeps the app up. | [16.23](/rulebook#16.23), [16.56](/rulebook#16.56), [37.8](/rulebook#37.8), [37.9](/rulebook#37.9), [38.4](/rulebook#38.4), [38.14](/rulebook#38.14), [38.15](/rulebook#38.15), [38.16](/rulebook#38.16), [38.17](/rulebook#38.17), [38.19](/rulebook#38.19), [38.24](/rulebook#38.24), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.28](/rulebook#38.28), [38.30](/rulebook#38.30), [38.35](/rulebook#38.35), [38.36](/rulebook#38.36), [38.37](/rulebook#38.37), [38.38](/rulebook#38.38), [38.41](/rulebook#38.41), [38.43](/rulebook#38.43), [38.58](/rulebook#38.58), [38.63](/rulebook#38.63), [38.64](/rulebook#38.64), [38.65](/rulebook#38.65), [38.94](/rulebook#38.94), [38.96](/rulebook#38.96), [38.97](/rulebook#38.97), [38.123](/rulebook#38.123), [38.136](/rulebook#38.136) |
11277
11601
  | `abide build` | Builds the client into content-hashed chunks and a manifest. | [38.43](/rulebook#38.43), [38.5](/rulebook#38.5), [38.18](/rulebook#38.18), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.27](/rulebook#38.27), [38.30](/rulebook#38.30), [38.66](/rulebook#38.66), [38.94](/rulebook#38.94), [38.123](/rulebook#38.123) |
11278
- | `abide start [--port <n>]` | Boots the built app. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.6](/rulebook#38.6), [38.100](/rulebook#38.100), [38.20](/rulebook#38.20), [38.21](/rulebook#38.21), [38.22](/rulebook#38.22), [38.23](/rulebook#38.23), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.27](/rulebook#38.27), [38.28](/rulebook#38.28), [38.29](/rulebook#38.29), [38.58](/rulebook#38.58), [38.67](/rulebook#38.67), [38.68](/rulebook#38.68), [38.95](/rulebook#38.95), [38.97](/rulebook#38.97), [38.110](/rulebook#38.110), [38.123](/rulebook#38.123) |
11279
- | `abide [--url <origin>] [--port <n>]` | The interactive shell — on the built app it boots, or on the running app `--url` names. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.6](/rulebook#38.6), [38.7](/rulebook#38.7), [38.53](/rulebook#38.53), [38.54](/rulebook#38.54), [38.55](/rulebook#38.55), [38.58](/rulebook#38.58), [38.59](/rulebook#38.59), [38.60](/rulebook#38.60), [38.62](/rulebook#38.62), [38.123](/rulebook#38.123) |
11602
+ | `abide start [--port <n>] [--hostname <host>]` | Boots the built app. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.6](/rulebook#38.6), [38.100](/rulebook#38.100), [38.20](/rulebook#38.20), [38.21](/rulebook#38.21), [38.22](/rulebook#38.22), [38.23](/rulebook#38.23), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.27](/rulebook#38.27), [38.28](/rulebook#38.28), [38.29](/rulebook#38.29), [38.58](/rulebook#38.58), [38.67](/rulebook#38.67), [38.68](/rulebook#38.68), [38.95](/rulebook#38.95), [38.97](/rulebook#38.97), [38.110](/rulebook#38.110), [38.123](/rulebook#38.123), [38.136](/rulebook#38.136) |
11603
+ | `abide [--url <origin>] [--port <n>] [--hostname <host>]` | The interactive shell — on the built app it boots, or on the running app `--url` names. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.6](/rulebook#38.6), [38.7](/rulebook#38.7), [38.53](/rulebook#38.53), [38.54](/rulebook#38.54), [38.55](/rulebook#38.55), [38.58](/rulebook#38.58), [38.59](/rulebook#38.59), [38.60](/rulebook#38.60), [38.62](/rulebook#38.62), [38.123](/rulebook#38.123), [38.136](/rulebook#38.136) |
11280
11604
  | `abide call <address> [args]` | One call to one handler. | [38.8](/rulebook#38.8), [38.61](/rulebook#38.61), [38.110](/rulebook#38.110) |
11281
11605
  | `abide openapi [--url <origin>]` | The OpenAPI document printed rather than served. | [38.9](/rulebook#38.9), [38.25](/rulebook#38.25), [38.110](/rulebook#38.110), [38.111](/rulebook#38.111), [38.123](/rulebook#38.123) |
11282
11606
  | `abide mcp [--url <origin>]` | The app's MCP server over stdio. | [38.9](/rulebook#38.9), [38.13](/rulebook#38.13), [38.25](/rulebook#38.25), [38.110](/rulebook#38.110), [38.123](/rulebook#38.123) |
11283
11607
  | `abide watch <address> [args]` | A live subscription to one of the app's followed `GET`s. | [38.69](/rulebook#38.69) |
11284
- | `abide compile [--target] [--out] [--platforms]` | One standalone executable. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.10](/rulebook#38.10), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.44](/rulebook#38.44), [38.45](/rulebook#38.45), [38.46](/rulebook#38.46), [38.47](/rulebook#38.47), [38.48](/rulebook#38.48), [38.49](/rulebook#38.49), [38.50](/rulebook#38.50), [38.51](/rulebook#38.51), [38.52](/rulebook#38.52), [38.56](/rulebook#38.56), [38.93](/rulebook#38.93), [38.97](/rulebook#38.97), [38.123](/rulebook#38.123) |
11608
+ | `abide compile [--target] [--out] [--platforms]` | One standalone executable. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.10](/rulebook#38.10), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.44](/rulebook#38.44), [38.45](/rulebook#38.45), [38.46](/rulebook#38.46), [38.47](/rulebook#38.47), [38.48](/rulebook#38.48), [38.49](/rulebook#38.49), [38.50](/rulebook#38.50), [38.51](/rulebook#38.51), [38.52](/rulebook#38.52), [38.56](/rulebook#38.56), [38.93](/rulebook#38.93), [38.97](/rulebook#38.97), [38.123](/rulebook#38.123), [38.136](/rulebook#38.136) |
11285
11609
  | `abide bundle [--out]` | A desktop app for the host platform, with a window on the app. | [38.10](/rulebook#38.10), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.70](/rulebook#38.70), [38.71](/rulebook#38.71), [38.72](/rulebook#38.72), [38.73](/rulebook#38.73), [38.74](/rulebook#38.74), [38.75](/rulebook#38.75), [38.76](/rulebook#38.76), [38.77](/rulebook#38.77), [38.78](/rulebook#38.78), [38.79](/rulebook#38.79), [38.80](/rulebook#38.80), [38.81](/rulebook#38.81), [38.82](/rulebook#38.82), [38.83](/rulebook#38.83), [38.84](/rulebook#38.84), [38.85](/rulebook#38.85), [38.86](/rulebook#38.86), [38.87](/rulebook#38.87), [38.88](/rulebook#38.88), [38.89](/rulebook#38.89), [38.90](/rulebook#38.90), [38.91](/rulebook#38.91), [38.92](/rulebook#38.92), [38.101](/rulebook#38.101), [38.102](/rulebook#38.102), [38.123](/rulebook#38.123) |
11286
11610
  | `abide lsp` | The `.abide` language server, over stdio. | [38.11](/rulebook#38.11), [38.34](/rulebook#38.34), [38.39](/rulebook#38.39), [38.98](/rulebook#38.98), [38.116](/rulebook#38.116), [38.117](/rulebook#38.117), [38.118](/rulebook#38.118), [38.130](/rulebook#38.130) |
11287
11611
  | `--help` · `-h` · `abide help` | Usage, generated from the command list. | [38.12](/rulebook#38.12), [38.113](/rulebook#38.113), [38.114](/rulebook#38.114) |