@abide/abide 0.33.1 → 0.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/AGENTS.md +39 -34
  2. package/CHANGELOG.md +30 -0
  3. package/README.md +21 -21
  4. package/package.json +5 -5
  5. package/src/abideResolverPlugin.ts +1 -1
  6. package/src/build.ts +1 -1
  7. package/src/compile.ts +1 -1
  8. package/src/lib/bundle/BundleMenu.ts +1 -1
  9. package/src/lib/bundle/BundleMenuItem.ts +1 -1
  10. package/src/lib/bundle/BundleWindow.ts +1 -1
  11. package/src/lib/bundle/bundled.ts +1 -1
  12. package/src/lib/bundle/disconnected.abide +105 -75
  13. package/src/lib/bundle/onMenu.ts +1 -1
  14. package/src/lib/mcp/createMcpServer.ts +1 -1
  15. package/src/lib/server/AppModule.ts +1 -1
  16. package/src/lib/server/DELETE.ts +1 -1
  17. package/src/lib/server/GET.ts +1 -1
  18. package/src/lib/server/HEAD.ts +1 -1
  19. package/src/lib/server/PATCH.ts +1 -1
  20. package/src/lib/server/POST.ts +1 -1
  21. package/src/lib/server/PUT.ts +1 -1
  22. package/src/lib/server/agent.ts +1 -1
  23. package/src/lib/server/appDataDir.ts +1 -1
  24. package/src/lib/server/cookies.ts +1 -1
  25. package/src/lib/server/env.ts +1 -1
  26. package/src/lib/server/error.ts +1 -1
  27. package/src/lib/server/json.ts +1 -1
  28. package/src/lib/server/jsonl.ts +1 -1
  29. package/src/lib/server/prompts/definePrompt.ts +1 -1
  30. package/src/lib/server/prompts/renderPromptTemplate.ts +1 -1
  31. package/src/lib/server/reachable.ts +1 -1
  32. package/src/lib/server/redirect.ts +1 -1
  33. package/src/lib/server/request.ts +1 -1
  34. package/src/lib/server/rpc/defineVerb.ts +1 -1
  35. package/src/lib/server/runtime/buildCacheSnapshot.ts +1 -1
  36. package/src/lib/server/runtime/types/InspectorCacheEntry.ts +2 -2
  37. package/src/lib/server/runtime/types/InspectorContext.ts +2 -2
  38. package/src/lib/server/server.ts +1 -1
  39. package/src/lib/server/socket.ts +1 -1
  40. package/src/lib/server/sockets/defineSocket.ts +1 -1
  41. package/src/lib/server/sse.ts +1 -1
  42. package/src/lib/shared/HttpError.ts +1 -1
  43. package/src/lib/shared/cache.ts +18 -18
  44. package/src/lib/shared/createSubscriber.ts +1 -1
  45. package/src/lib/shared/health.ts +1 -1
  46. package/src/lib/shared/html.ts +1 -1
  47. package/src/lib/shared/isSubscribable.ts +1 -1
  48. package/src/lib/shared/log.ts +1 -1
  49. package/src/lib/shared/online.ts +1 -1
  50. package/src/lib/shared/page.ts +1 -1
  51. package/src/lib/shared/pending.ts +2 -2
  52. package/src/lib/shared/probeRegistries.ts +2 -2
  53. package/src/lib/shared/refreshing.ts +2 -2
  54. package/src/lib/shared/selectorMatcher.ts +8 -8
  55. package/src/lib/shared/selectorPrefix.ts +1 -1
  56. package/src/lib/shared/snippet.ts +1 -1
  57. package/src/lib/shared/toTagSet.ts +4 -0
  58. package/src/lib/shared/trace.ts +1 -1
  59. package/src/lib/shared/types/CacheEntry.ts +3 -3
  60. package/src/lib/shared/types/CacheOptions.ts +3 -3
  61. package/src/lib/shared/types/CacheSelector.ts +2 -2
  62. package/src/lib/shared/url.ts +1 -1
  63. package/src/lib/shared/withJsonSchema.ts +1 -1
  64. package/src/lib/test/assertAgentFrameConformance.ts +1 -1
  65. package/src/lib/test/createScriptedSurface.ts +1 -1
  66. package/src/lib/test/createTestApp.ts +1 -1
  67. package/src/lib/ui/compile/REACTIVE_CALLEES.ts +7 -2
  68. package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +3 -4
  69. package/src/lib/ui/compile/abideUiPlugin.ts +1 -1
  70. package/src/lib/ui/compile/analyzeComponent.ts +2 -1
  71. package/src/lib/ui/compile/compileComponent.ts +3 -3
  72. package/src/lib/ui/compile/compileModule.ts +30 -2
  73. package/src/lib/ui/compile/compileSSR.ts +5 -5
  74. package/src/lib/ui/compile/compileShadow.ts +62 -37
  75. package/src/lib/ui/compile/desugarSignals.ts +147 -18
  76. package/src/lib/ui/compile/generateBuild.ts +15 -28
  77. package/src/lib/ui/compile/generateSSR.ts +20 -13
  78. package/src/lib/ui/compile/isControlFlow.ts +18 -0
  79. package/src/lib/ui/compile/isTextLeaf.ts +15 -0
  80. package/src/lib/ui/compile/lowerContext.ts +45 -5
  81. package/src/lib/ui/compile/prepareNestedScript.ts +12 -8
  82. package/src/lib/ui/compile/renameSignalRefs.ts +21 -4
  83. package/src/lib/ui/compile/skeletonable.ts +1 -14
  84. package/src/lib/ui/compile/types/AnalyzedComponent.ts +1 -0
  85. package/src/lib/ui/computed.ts +32 -0
  86. package/src/lib/ui/createScope.ts +91 -0
  87. package/src/lib/ui/dom/anchorCursor.ts +1 -1
  88. package/src/lib/ui/dom/appendSnippet.ts +1 -1
  89. package/src/lib/ui/dom/appendStatic.ts +1 -1
  90. package/src/lib/ui/dom/appendText.ts +1 -1
  91. package/src/lib/ui/dom/appendTextAt.ts +1 -1
  92. package/src/lib/ui/dom/applyResolved.ts +1 -1
  93. package/src/lib/ui/dom/attach.ts +7 -2
  94. package/src/lib/ui/dom/attr.ts +1 -1
  95. package/src/lib/ui/dom/awaitBlock.ts +1 -1
  96. package/src/lib/ui/dom/cloneStatic.ts +1 -1
  97. package/src/lib/ui/dom/each.ts +4 -3
  98. package/src/lib/ui/dom/eachAsync.ts +1 -1
  99. package/src/lib/ui/dom/hydrate.ts +20 -6
  100. package/src/lib/ui/dom/mount.ts +12 -1
  101. package/src/lib/ui/dom/mountChild.ts +6 -2
  102. package/src/lib/ui/dom/mountSlot.ts +1 -1
  103. package/src/lib/ui/dom/on.ts +10 -4
  104. package/src/lib/ui/dom/openMarker.ts +3 -3
  105. package/src/lib/ui/dom/skeleton.ts +13 -5
  106. package/src/lib/ui/dom/switchBlock.ts +1 -1
  107. package/src/lib/ui/dom/text.ts +1 -1
  108. package/src/lib/ui/dom/tryBlock.ts +1 -1
  109. package/src/lib/ui/dom/when.ts +1 -1
  110. package/src/lib/ui/effect.ts +7 -2
  111. package/src/lib/ui/enterScope.ts +18 -0
  112. package/src/lib/ui/exitScope.ts +8 -0
  113. package/src/lib/ui/history.ts +102 -0
  114. package/src/lib/ui/installHotBridge.ts +6 -8
  115. package/src/lib/ui/linked.ts +0 -1
  116. package/src/lib/ui/navigate.ts +1 -1
  117. package/src/lib/ui/outbox.ts +115 -0
  118. package/src/lib/ui/persist.ts +112 -0
  119. package/src/lib/ui/probeNavigation.ts +1 -1
  120. package/src/lib/ui/remoteProxy.ts +1 -1
  121. package/src/lib/ui/renderToStream.ts +1 -1
  122. package/src/lib/ui/router.ts +1 -1
  123. package/src/lib/ui/runtime/CURRENT_SCOPE.ts +10 -0
  124. package/src/lib/ui/runtime/OUTLET_TAG.ts +1 -1
  125. package/src/lib/ui/runtime/PATCH_BUS.ts +28 -0
  126. package/src/lib/ui/runtime/RESUME.ts +1 -1
  127. package/src/lib/ui/runtime/captureModelDoc.ts +29 -0
  128. package/src/lib/ui/runtime/claimExpected.ts +26 -0
  129. package/src/lib/ui/runtime/createComputedNode.ts +1 -1
  130. package/src/lib/ui/runtime/createDoc.ts +73 -3
  131. package/src/lib/ui/runtime/enterRenderPass.ts +1 -1
  132. package/src/lib/ui/runtime/escapeKey.ts +13 -0
  133. package/src/lib/ui/runtime/exitRenderPass.ts +1 -1
  134. package/src/lib/ui/runtime/hotReplace.ts +17 -8
  135. package/src/lib/ui/runtime/inScope.ts +19 -0
  136. package/src/lib/ui/runtime/localStoragePersistence.ts +34 -0
  137. package/src/lib/ui/runtime/nextBlockId.ts +1 -1
  138. package/src/lib/ui/runtime/seedModelDoc.ts +26 -0
  139. package/src/lib/ui/runtime/types/{Derived.ts → Computed.ts} +1 -1
  140. package/src/lib/ui/runtime/types/Doc.ts +3 -0
  141. package/src/lib/ui/runtime/types/HotInstance.ts +6 -2
  142. package/src/lib/ui/runtime/types/PatchEvent.ts +16 -0
  143. package/src/lib/ui/runtime/unescapeKey.ts +12 -0
  144. package/src/lib/ui/runtime/walkPath.ts +3 -1
  145. package/src/lib/ui/scope.ts +19 -0
  146. package/src/lib/ui/socketProxy.ts +1 -1
  147. package/src/lib/ui/startClient.ts +1 -1
  148. package/src/lib/ui/state.ts +1 -2
  149. package/src/lib/ui/sync.ts +42 -0
  150. package/src/lib/ui/tail.ts +1 -1
  151. package/src/lib/ui/types/History.ts +14 -0
  152. package/src/lib/ui/types/Outbox.ts +14 -0
  153. package/src/lib/ui/types/PersistHandle.ts +11 -0
  154. package/src/lib/ui/types/PersistenceStore.ts +12 -0
  155. package/src/lib/ui/types/Scope.ts +57 -0
  156. package/src/lib/ui/types/SyncTransport.ts +13 -0
  157. package/src/preload.ts +1 -1
  158. package/src/lib/shared/toScopeSet.ts +0 -4
  159. package/src/lib/ui/derived.ts +0 -49
  160. package/src/lib/ui/doc.ts +0 -15
@@ -147,90 +147,120 @@ async function saveConfig() {
147
147
  </script>
148
148
 
149
149
  <template if={phase === 'splash'}>
150
- <div class="flex min-h-screen items-center justify-center bg-gray-50 dark:bg-gray-950">
151
- <template if={logo}>
152
- <img src={logo} alt="" class="h-16 w-16 rounded-xl object-contain opacity-90">
153
- </template>
154
- </div>
155
- <template else>
156
- <main class="flex min-h-screen items-center justify-center bg-gray-50 p-6 text-gray-900 dark:bg-gray-950 dark:text-gray-100">
157
- <div class="w-full max-w-sm rounded-2xl bg-white p-8 shadow-sm ring-1 ring-gray-200 dark:bg-gray-900 dark:ring-gray-800">
150
+ <div class="flex min-h-screen items-center justify-center bg-gray-50 dark:bg-gray-950">
158
151
  <template if={logo}>
159
- <img src={logo} alt="" class="mx-auto mb-5 h-16 w-16 rounded-xl object-contain">
152
+ <img src={logo} alt="" class="h-16 w-16 rounded-xl object-contain opacity-90" />
160
153
  </template>
161
- <h1 class="mb-6 text-center text-xl font-semibold tracking-tight">{heading}</h1>
162
-
163
- <form class="flex flex-col gap-3" onsubmit={(event) => { event.preventDefault(); void connect() }}>
164
- <input type="url" bind:value={url} placeholder={placeholder} autocomplete="url"
165
- class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900 focus:ring-1 focus:ring-gray-900 dark:border-gray-700 dark:bg-gray-800 dark:focus:border-gray-100 dark:focus:ring-gray-100">
166
- <button type="submit"
167
- class="w-full rounded-lg bg-gray-900 px-3 py-2 text-sm font-medium text-white hover:bg-gray-700 dark:bg-gray-100 dark:text-gray-900 dark:hover:bg-gray-300">
168
- Connect
169
- </button>
170
- </form>
171
-
172
- <div class="my-5 flex items-center gap-3 text-xs text-gray-400 dark:text-gray-500">
173
- <span class="h-px flex-1 bg-gray-200 dark:bg-gray-800"></span>
174
- or
175
- <span class="h-px flex-1 bg-gray-200 dark:bg-gray-800"></span>
176
- </div>
154
+ </div>
155
+ <template else>
156
+ <main
157
+ class="flex min-h-screen items-center justify-center bg-gray-50 p-6 text-gray-900 dark:bg-gray-950 dark:text-gray-100">
158
+ <div
159
+ class="w-full max-w-sm rounded-2xl bg-white p-8 shadow-sm ring-1 ring-gray-200 dark:bg-gray-900 dark:ring-gray-800">
160
+ <template if={logo}>
161
+ <img
162
+ src={logo}
163
+ alt=""
164
+ class="mx-auto mb-5 h-16 w-16 rounded-xl object-contain" />
165
+ </template>
166
+ <h1 class="mb-6 text-center text-xl font-semibold tracking-tight">{heading}</h1>
177
167
 
178
- <button type="button" onclick={() => void start()}
179
- class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm font-medium hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800">
180
- Start server
181
- </button>
168
+ <form class="flex flex-col gap-3" onsubmit={(event) => { event.preventDefault(); void connect() }}>
169
+ <input
170
+ type="url"
171
+ bind:value={url}
172
+ placeholder={placeholder}
173
+ autocomplete="url"
174
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900 focus:ring-1 focus:ring-gray-900 dark:border-gray-700 dark:bg-gray-800 dark:focus:border-gray-100 dark:focus:ring-gray-100" />
175
+ <button
176
+ type="submit"
177
+ class="w-full rounded-lg bg-gray-900 px-3 py-2 text-sm font-medium text-white hover:bg-gray-700 dark:bg-gray-100 dark:text-gray-900 dark:hover:bg-gray-300">
178
+ Connect
179
+ </button>
180
+ </form>
182
181
 
183
- <template if={error}>
184
- <p class="mt-4 text-center text-sm text-red-600 dark:text-red-400">{error}</p>
185
- </template>
182
+ <div class="my-5 flex items-center gap-3 text-xs text-gray-400 dark:text-gray-500">
183
+ <span class="h-px flex-1 bg-gray-200 dark:bg-gray-800"></span>
184
+ or
185
+ <span class="h-px flex-1 bg-gray-200 dark:bg-gray-800"></span>
186
+ </div>
186
187
 
187
- <p class="mt-8 text-center text-xs text-gray-400 dark:text-gray-500">
188
- made with
189
- <a href="https://github.com/briancray/abide" class="underline hover:text-gray-600 dark:hover:text-gray-300">abide</a>
190
- </p>
191
- </div>
192
- </main>
193
- </template>
188
+ <button
189
+ type="button"
190
+ onclick={() => void start()}
191
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm font-medium hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800">
192
+ Start server
193
+ </button>
194
+
195
+ <template if={error}>
196
+ <p class="mt-4 text-center text-sm text-red-600 dark:text-red-400">
197
+ {error}
198
+ </p>
199
+ </template>
200
+
201
+ <p class="mt-8 text-center text-xs text-gray-400 dark:text-gray-500">
202
+ made with
203
+ <a
204
+ href="https://github.com/briancray/abide"
205
+ class="underline hover:text-gray-600 dark:hover:text-gray-300"
206
+ >abide</a
207
+ >
208
+ </p>
209
+ </div>
210
+ </main>
211
+ </template>
194
212
  </template>
195
213
 
196
214
  <template if={showConfig}>
197
- <div class="fixed inset-0 z-10 flex items-center justify-center bg-black/40 p-6 text-gray-900 dark:text-gray-100">
198
- <div class="w-full max-w-sm rounded-2xl bg-white p-8 shadow-lg ring-1 ring-gray-200 dark:bg-gray-900 dark:ring-gray-800">
199
- <h2 class="mb-5 text-lg font-semibold tracking-tight">Set up {heading}</h2>
200
-
201
- <form class="flex flex-col gap-4" onsubmit={(event) => { event.preventDefault(); void saveConfig() }}>
202
- <template each={configFields} as="field" key="field.key">
203
- <label class="flex flex-col gap-1 text-sm">
204
- <span class="font-medium">{field.label}</span>
205
- <template if={field.inputType === 'checkbox'}>
206
- <input type="checkbox" onchange={(event) => { configValues[field.key] = event.currentTarget.checked ? 'true' : 'false' }}
207
- class="mt-1 size-4 self-start rounded border-gray-300 dark:border-gray-700">
208
- <template else>
209
- <input type={field.inputType} value={configValues[field.key]} oninput={(event) => { configValues[field.key] = event.currentTarget.value }}
210
- class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900 focus:ring-1 focus:ring-gray-900 dark:border-gray-700 dark:bg-gray-800 dark:focus:border-gray-100 dark:focus:ring-gray-100">
211
- </template>
212
- </template>
213
- <template if={field.description}>
214
- <span class="text-xs text-gray-400 dark:text-gray-500">{field.description}</span>
215
- </template>
216
- </label>
217
- </template>
215
+ <div
216
+ class="fixed inset-0 z-10 flex items-center justify-center bg-black/40 p-6 text-gray-900 dark:text-gray-100">
217
+ <div
218
+ class="w-full max-w-sm rounded-2xl bg-white p-8 shadow-lg ring-1 ring-gray-200 dark:bg-gray-900 dark:ring-gray-800">
219
+ <h2 class="mb-5 text-lg font-semibold tracking-tight">Set up {heading}</h2>
218
220
 
219
- <div class="mt-1 flex gap-3">
220
- <button type="button" onclick={() => { showConfig = false }}
221
- class="flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm font-medium hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800">
222
- Cancel
223
- </button>
224
- <button type="submit"
225
- class="flex-1 rounded-lg bg-gray-900 px-3 py-2 text-sm font-medium text-white hover:bg-gray-700 disabled:opacity-60 dark:bg-gray-100 dark:text-gray-900 dark:hover:bg-gray-300">
226
- Save &amp; start
227
- </button>
228
- </div>
229
- </form>
221
+ <form class="flex flex-col gap-4" onsubmit={(event) => { event.preventDefault(); void saveConfig() }}>
222
+ <template each={configFields} as="field" key="field.key">
223
+ <label class="flex flex-col gap-1 text-sm">
224
+ <span class="font-medium">{field.label}</span>
225
+ <template if={field.inputType === 'checkbox'}>
226
+ <input
227
+ type="checkbox"
228
+ onchange={(event) => { configValues[field.key] = event.currentTarget.checked ? 'true' : 'false' }}
229
+ class="mt-1 size-4 self-start rounded border-gray-300 dark:border-gray-700" />
230
+ <template else>
231
+ <input
232
+ type={field.inputType}
233
+ value={configValues[field.key]}
234
+ oninput={(event) => { configValues[field.key] = event.currentTarget.value }}
235
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900 focus:ring-1 focus:ring-gray-900 dark:border-gray-700 dark:bg-gray-800 dark:focus:border-gray-100 dark:focus:ring-gray-100" />
236
+ </template>
237
+ </template>
238
+ <template if={field.description}>
239
+ <span class="text-xs text-gray-400 dark:text-gray-500"
240
+ >{field.description}</span
241
+ >
242
+ </template>
243
+ </label>
244
+ </template>
230
245
 
231
- <template if={error}>
232
- <p class="mt-4 text-center text-sm text-red-600 dark:text-red-400">{error}</p>
233
- </template>
246
+ <div class="mt-1 flex gap-3">
247
+ <button
248
+ type="button"
249
+ onclick={() => { showConfig = false }}
250
+ class="flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm font-medium hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800">
251
+ Cancel
252
+ </button>
253
+ <button
254
+ type="submit"
255
+ class="flex-1 rounded-lg bg-gray-900 px-3 py-2 text-sm font-medium text-white hover:bg-gray-700 disabled:opacity-60 dark:bg-gray-100 dark:text-gray-900 dark:hover:bg-gray-300">
256
+ Save &amp; start
257
+ </button>
258
+ </div>
259
+ </form>
260
+
261
+ <template if={error}>
262
+ <p class="mt-4 text-center text-sm text-red-600 dark:text-red-400">{error}</p>
263
+ </template>
264
+ </div>
234
265
  </div>
235
- </div>
236
266
  </template>
@@ -18,7 +18,7 @@ Inert during SSR and in a plain browser tab — `effect` only runs client-side,
18
18
  the native menu that fires the event exists only in the bundled desktop app,
19
19
  and `window` is guarded so importing the module never assumes a DOM.
20
20
  */
21
- // @readme bundle
21
+ // @documentation bundle
22
22
  export function onMenu(handler: (name: string) => void): () => void
23
23
  export function onMenu(name: string, handler: () => void): () => void
24
24
  export function onMenu(
@@ -23,7 +23,7 @@ feeds each rpc tool's annotations. Auth inherits from the inbound request
23
23
  each rpc handler. An optional `authorize` hook in opts can short-circuit
24
24
  the request before any tool dispatches.
25
25
  */
26
- // @readme plumbing
26
+ // @documentation mcp
27
27
  export function createMcpServer(opts: McpServerOptions = {}): McpServer {
28
28
  const serverInfo = {
29
29
  name: opts.name ?? DEFAULT_NAME,
@@ -13,7 +13,7 @@ Inside request scopes, the live Bun.Server is reachable via the
13
13
  exported `server()` function from `abide/server`; `init` receives it
14
14
  explicitly because it runs outside a request.
15
15
  */
16
- // @readme plumbing
16
+ // @documentation plumbing
17
17
  export type AppModule = {
18
18
  /*
19
19
  Extra inbound header names to forward onto in-process rpc Requests, on
@@ -6,5 +6,5 @@ DELETE verb helper. The bundler rewrites every `export const x = DELETE(fn)` ins
6
6
  `src/server/rpc/<file>.ts` into a defineVerb call (server target) or a
7
7
  remoteProxy stub (client target). Calling this directly throws.
8
8
  */
9
- // @readme rpc
9
+ // @documentation rpc
10
10
  export const DELETE: VerbHelper = (_fn: any, _opts?: any) => unprocessed('DELETE')
@@ -6,5 +6,5 @@ GET verb helper. The bundler rewrites every `export const x = GET(fn)` inside
6
6
  `src/server/rpc/<file>.ts` into a defineVerb call (server target) or a
7
7
  remoteProxy stub (client target). Calling this directly throws.
8
8
  */
9
- // @readme rpc
9
+ // @documentation rpc
10
10
  export const GET: VerbHelper = (_fn: any, _opts?: any) => unprocessed('GET')
@@ -6,5 +6,5 @@ HEAD verb helper. The bundler rewrites every `export const x = HEAD(fn)` inside
6
6
  `src/server/rpc/<file>.ts` into a defineVerb call (server target) or a
7
7
  remoteProxy stub (client target). Calling this directly throws.
8
8
  */
9
- // @readme rpc
9
+ // @documentation rpc
10
10
  export const HEAD: VerbHelper = (_fn: any, _opts?: any) => unprocessed('HEAD')
@@ -6,5 +6,5 @@ PATCH verb helper. The bundler rewrites every `export const x = PATCH(fn)` insid
6
6
  `src/server/rpc/<file>.ts` into a defineVerb call (server target) or a
7
7
  remoteProxy stub (client target). Calling this directly throws.
8
8
  */
9
- // @readme rpc
9
+ // @documentation rpc
10
10
  export const PATCH: VerbHelper = (_fn: any, _opts?: any) => unprocessed('PATCH')
@@ -6,5 +6,5 @@ POST verb helper. The bundler rewrites every `export const x = POST(fn)` inside
6
6
  `src/server/rpc/<file>.ts` into a defineVerb call (server target) or a
7
7
  remoteProxy stub (client target). Calling this directly throws.
8
8
  */
9
- // @readme rpc
9
+ // @documentation rpc
10
10
  export const POST: VerbHelper = (_fn: any, _opts?: any) => unprocessed('POST')
@@ -6,5 +6,5 @@ PUT verb helper. The bundler rewrites every `export const x = PUT(fn)` inside
6
6
  `src/server/rpc/<file>.ts` into a defineVerb call (server target) or a
7
7
  remoteProxy stub (client target). Calling this directly throws.
8
8
  */
9
- // @readme rpc
9
+ // @documentation rpc
10
10
  export const PUT: VerbHelper = (_fn: any, _opts?: any) => unprocessed('PUT')
@@ -27,7 +27,7 @@ tool) are fenced by static rules in the engine's config.
27
27
  */
28
28
 
29
29
  // A turn in the conversation, provider-neutral. The engine maps these to its provider's wire shape.
30
- // @readme agent
30
+ // @documentation agent
31
31
  export type NeutralMessage =
32
32
  | { role: 'user'; text: string }
33
33
  | {
@@ -10,7 +10,7 @@ the path derives from the bundler-injected program name, not the process working
10
10
  directory (which `open` sets to `/`). Pure: computes the path, never touches the
11
11
  filesystem.
12
12
  */
13
- // @readme reference
13
+ // @documentation bundle
14
14
  export function appDataDir(): string {
15
15
  return appDataDirForName(cliProgramName)
16
16
  }
@@ -17,7 +17,7 @@ Materialized lazily on first call and cached on the request store, so a request
17
17
  that never touches cookies parses nothing and emits no `Set-Cookie`. Throws
18
18
  outside a request scope, like request().
19
19
  */
20
- // @readme request-scope
20
+ // @documentation request-scope
21
21
  export function cookies(): Bun.CookieMap {
22
22
  const store = requestContext.getStore()
23
23
  if (!store) {
@@ -26,7 +26,7 @@ Validation must be synchronous — boot can't await config — so a schema whose
26
26
  (path + message) so a misconfigured deploy shows the full list rather than one
27
27
  variable per restart.
28
28
  */
29
- // @readme configuration
29
+ // @documentation configuration
30
30
  export function env<Schema extends StandardSchemaV1>(
31
31
  schema: Schema,
32
32
  ): StandardSchemaV1.InferOutput<Schema> {
@@ -56,7 +56,7 @@ the union of branches in a handler narrow to whatever the success
56
56
  branch carries (`TypedResponse<{user}> | TypedResponse<never>` → Return
57
57
  = {user}).
58
58
  */
59
- // @readme response
59
+ // @documentation response
60
60
  export function error(status: number, message?: string, init?: ResponseInit): TypedResponse<never> {
61
61
  const body = message ?? STATUS_TEXT[status] ?? `HTTP ${status}`
62
62
  return new Response(
@@ -27,7 +27,7 @@ paths, so a handler typed `Shape | undefined` round-trips the wire. The
27
27
  helper owns the 204 (a body-bearing status with no body would break the
28
28
  round trip), so it wins over any `init.status`.
29
29
  */
30
- // @readme response
30
+ // @documentation response
31
31
  export function json<T>(data: T, init?: ResponseInit): TypedResponse<T> {
32
32
  if (data === undefined) {
33
33
  return new Response(
@@ -27,7 +27,7 @@ import type { TypedResponse } from './rpc/types/TypedResponse.ts'
27
27
  import { streamFromIterator } from './runtime/streamFromIterator.ts'
28
28
  import { withResponseDefaults } from './runtime/withResponseDefaults.ts'
29
29
 
30
- // @readme response
30
+ // @documentation response
31
31
  export function jsonl<Frame>(
32
32
  iterable: AsyncIterable<Frame>,
33
33
  init?: ResponseInit,
@@ -9,7 +9,7 @@ Builds a Prompt from a name + options. The resolver plugin parses every
9
9
  path becomes the prompt's identity. Registers itself so the MCP dispatcher
10
10
  can enumerate and render it.
11
11
  */
12
- // @readme plumbing
12
+ // @documentation plumbing
13
13
  export function definePrompt(name: string, opts: PromptOptions): Prompt {
14
14
  const self: Prompt = {
15
15
  name,
@@ -9,7 +9,7 @@ string — MCP only enforces `required` at the client, so an optional
9
9
  argument the model omits should vanish from the text. Called by the
10
10
  render closure the resolver plugin generates for every `.md` prompt.
11
11
  */
12
- // @readme plumbing
12
+ // @documentation plumbing
13
13
  export function renderPromptTemplate(template: string, args: Record<string, string>): string {
14
14
  return template.replace(PLACEHOLDER, (_match, key: string) =>
15
15
  args[key] === undefined ? '' : String(args[key]),
@@ -37,7 +37,7 @@ async function probeOrigin(origin: string): Promise<boolean> {
37
37
  }
38
38
  }
39
39
 
40
- // @readme observability
40
+ // @documentation observability
41
41
  export const reachable = createReachable({
42
42
  probe: probeOrigin,
43
43
  intervalMs: TTL_MS,
@@ -30,7 +30,7 @@ the wire response is a 3xx with no body the caller resolves to, so it
30
30
  must not pollute the inferred `Return` of a route that conditionally
31
31
  redirects vs returns json.
32
32
  */
33
- // @readme response
33
+ // @documentation response
34
34
  export function redirect(
35
35
  url: string,
36
36
  status: RedirectStatus = 302,
@@ -7,7 +7,7 @@ the fetch boundary. Throws if called outside a request scope (e.g. from
7
7
  top-level module code or from app.ts init) — silent undefined would mask
8
8
  the misuse.
9
9
  */
10
- // @readme request-scope
10
+ // @documentation request-scope
11
11
  export function request(): Request {
12
12
  const store = requestContext.getStore()
13
13
  if (!store) {
@@ -44,7 +44,7 @@ the Request via parseArgs).
44
44
  Every raw invocation records the synthesized Request against the returned
45
45
  promise so cache() can stash it on the entry without re-building.
46
46
  */
47
- // @readme plumbing
47
+ // @documentation plumbing
48
48
  export function defineVerb<Args, Return>(
49
49
  method: HttpVerb,
50
50
  url: string,
@@ -41,7 +41,7 @@ function projectEntry(entry: CacheEntry, now: number): InspectorCacheEntry {
41
41
  remote: entry.request !== undefined,
42
42
  ttl: entry.ttl,
43
43
  expiresInMs: entry.expiresAt !== undefined ? entry.expiresAt - now : undefined,
44
- scope: entry.scope ? [...entry.scope] : [],
44
+ tags: entry.tags ? [...entry.tags] : [],
45
45
  value: preview(entry.value),
46
46
  policy: policyLabel(entry),
47
47
  }
@@ -15,8 +15,8 @@ export type InspectorCacheEntry = {
15
15
  ttl: number | undefined
16
16
  /* Ms until expiry from snapshot time; undefined = no expiry armed. */
17
17
  expiresInMs: number | undefined
18
- /* The call's scope tags (cache.invalidate({ scope }) targets). */
19
- scope: string[]
18
+ /* The call's tags (cache.invalidate({ tags }) targets). */
19
+ tags: string[]
20
20
  /* A short JSON preview of the decoded warm value, when the entry holds one. */
21
21
  value: string | undefined
22
22
  /* An armed swr policy (`swr`, optionally + throttle/debounce + ms), if declared. */
@@ -10,14 +10,14 @@ surface for it (mirrors how AppModule / AgentEngine are the documented seams).
10
10
  Everything here is already produced by the runtime: the registries behind
11
11
  loadSurface(), the log chokepoint behind onRecord().
12
12
  */
13
- // @readme plumbing
13
+ // @documentation plumbing
14
14
  export type InspectorContext = {
15
15
  /* App identity for the UI header — the same name/version the health probe reports. */
16
16
  app: { name: string; version: string }
17
17
  /* Eager-loads the registries, then projects the current RPC + socket catalog. */
18
18
  loadSurface: () => Promise<InspectorSurface>
19
19
  /* Snapshots the persistent (global) cache store — current entries with their
20
- lifecycle state, retention, scope tags, and a value preview. */
20
+ lifecycle state, retention, tags, and a value preview. */
21
21
  cacheSnapshot: () => InspectorCacheSnapshot
22
22
  /*
23
23
  Subscribes to the unified event stream: every emitted log record (the log's
@@ -18,7 +18,7 @@ When no Bun.serve has booted, resolution forks on the request scope:
18
18
  app.ts init); keep throwing — silent undefined would mask it and strand
19
19
  later property reads with cryptic errors.
20
20
  */
21
- // @readme request-scope
21
+ // @documentation request-scope
22
22
  export function server(): Server<unknown> {
23
23
  const active = getActiveServer()
24
24
  if (active) {
@@ -6,7 +6,7 @@ import type { SocketOptions } from './sockets/types/SocketOptions.ts'
6
6
  Declares a Socket inside a file under `src/server/sockets/`. Each file contains
7
7
  exactly one export, named after the file (e.g. `chat.ts` →
8
8
  `export const chat = socket<ChatMessage>(...)`). The bundler reads the
9
- // @readme sockets
9
+ // @documentation sockets
10
10
  export name from the filename and the socket name from the file path
11
11
  under `src/server/sockets/`, then rewrites this call to bind the name into the
12
12
  runtime implementation (defineSocket on the server, socketProxy on the
@@ -26,7 +26,7 @@ called server-side it both notifies in-process iterators and broadcasts
26
26
  to remote subscribers; called client-side (via socketProxy) it sends a
27
27
  `pub` frame the dispatcher validates and forwards.
28
28
  */
29
- // @readme plumbing
29
+ // @documentation plumbing
30
30
  export function defineSocket<T>(name: string, opts: SocketOptions = {}): Socket<T> {
31
31
  const retention = opts.tail ?? 0
32
32
  const ttl = opts.ttl
@@ -31,7 +31,7 @@ import { withResponseDefaults } from './runtime/withResponseDefaults.ts'
31
31
 
32
32
  const KEEPALIVE_INTERVAL_MS = 15000
33
33
 
34
- // @readme response
34
+ // @documentation response
35
35
  export function sse<Frame>(
36
36
  iterable: AsyncIterable<Frame>,
37
37
  init?: ResponseInit,
@@ -4,7 +4,7 @@ status. Carries the raw Response so callers can inspect body, headers, or
4
4
  status text — useful for showing user-friendly error UI without having to
5
5
  opt every call site into the `.raw()` escape hatch.
6
6
  */
7
- // @readme response
7
+ // @documentation response
8
8
  export class HttpError extends Error {
9
9
  readonly status: number
10
10
  readonly statusText: string
@@ -15,7 +15,7 @@ import { REPLAYABLE_METHODS } from './REPLAYABLE_METHODS.ts'
15
15
  import { SocketDisconnectedError } from './SocketDisconnectedError.ts'
16
16
  import { selectorMatcher } from './selectorMatcher.ts'
17
17
  import { selectorPrefix } from './selectorPrefix.ts'
18
- import { toScopeSet } from './toScopeSet.ts'
18
+ import { toTagSet } from './toTagSet.ts'
19
19
  import type { CacheEntry } from './types/CacheEntry.ts'
20
20
  import type { CacheOnContext } from './types/CacheOnContext.ts'
21
21
  import type { CacheOptions } from './types/CacheOptions.ts'
@@ -116,7 +116,7 @@ keep streaming reads in a parent that never top-level awaits — the
116
116
  await-everything mode is per component instance, so a child's await blocks only
117
117
  the child.
118
118
  */
119
- // @readme cache
119
+ // @documentation cache
120
120
  export function cache<Args, Return>(
121
121
  fn: RemoteFunction<Args, Return>,
122
122
  options?: CacheOptions,
@@ -173,7 +173,7 @@ export function cache<Args, Return>(
173
173
  const existing = store.entries.get(key)
174
174
  recordRead(options?.global ? activeCacheStore() : store, key, existing)
175
175
  if (existing) {
176
- tagScope(existing, options?.scope)
176
+ tagEntry(existing, options?.tags)
177
177
  attachPolicy(existing, options, () => remote(args as Args))
178
178
  adoptTtl(store, existing, options)
179
179
  }
@@ -278,7 +278,7 @@ function warnAnonymousProducer(producer: (args?: never) => unknown): void {
278
278
  }
279
279
  warnedAnonymousProducers.add(source)
280
280
  abideLog.warn(
281
- 'cache() received an anonymous function — each call mints a fresh identity, so it never coalesces and pending()/refreshing() never match it. Hoist it to a named binding, or add a scope tag to probe it from elsewhere.',
281
+ 'cache() received an anonymous function — each call mints a fresh identity, so it never coalesces and pending()/refreshing() never match it. Hoist it to a named binding, or add a tag to probe it from elsewhere.',
282
282
  )
283
283
  }
284
284
 
@@ -298,7 +298,7 @@ function invokeProducer<Args, Return>(
298
298
  const existing = store.entries.get(key)
299
299
  recordRead(options?.global ? activeCacheStore() : store, key, existing)
300
300
  if (existing) {
301
- tagScope(existing, options?.scope)
301
+ tagEntry(existing, options?.tags)
302
302
  attachPolicy(existing, options, () => producer(args))
303
303
  const shared = existing.promise as Promise<Return>
304
304
  /* A coalesced join waits on the in-flight producer — time the block so the
@@ -368,7 +368,7 @@ function registerEntry(
368
368
  request,
369
369
  ttl,
370
370
  expiresAt: undefined,
371
- scope: options?.scope === undefined ? undefined : toScopeSet(options.scope),
371
+ tags: options?.tags === undefined ? undefined : toTagSet(options.tags),
372
372
  refreshing,
373
373
  invalidation,
374
374
  }
@@ -451,7 +451,7 @@ function armTtlExpiry(store: CacheStore, entry: CacheEntry, ttl: number): void {
451
451
  }
452
452
 
453
453
  /*
454
- Mirrors tagScope/attachPolicy for retention: a hydrated snapshot entry ships
454
+ Mirrors tagEntry/attachPolicy for retention: a hydrated snapshot entry ships
455
455
  without its wrap options (they live at call sites, not on the wire), so the
456
456
  first read adopts its call site's ttl declaration. Omitted = forever, exactly
457
457
  as shipped; ttl > 0 = the expiry clock starts at this read; ttl = 0 = the warm
@@ -530,7 +530,7 @@ function invalidate<Args, Return>(arg?: CacheSelector<Args, Return>, args?: Args
530
530
  Human-readable selector identity for the tripwire and cache.on coverage: the
531
531
  key prefix for fn selectors — the exact key when args narrow it — falling
532
532
  back to the function's name for a producer never cached, the tag list for
533
- scopes, `*` for the bare form.
533
+ a `{ tags }` selector, `*` for the bare form.
534
534
  */
535
535
  function selectorLabel<Args, Return>(
536
536
  arg?: CacheSelector<Args, Return>,
@@ -543,7 +543,7 @@ function selectorLabel<Args, Return>(
543
543
  if (typeof arg === 'function') {
544
544
  return prefix ?? selectorPrefix(arg, args) ?? (arg.name || 'anonymous producer')
545
545
  }
546
- return `scope: ${[...toScopeSet(arg.scope ?? [])].join(', ')}`
546
+ return `tags: ${[...toTagSet(arg.tags ?? [])].join(', ')}`
547
547
  }
548
548
 
549
549
  cache.invalidate = invalidate
@@ -920,24 +920,24 @@ function settleRefetchFailure(store: CacheStore, entry: CacheEntry, status?: num
920
920
  }
921
921
 
922
922
  /* Folds new tags into an entry's existing set without duplicating them. */
923
- function mergeScopes(existing: Set<string> | undefined, incoming: string | string[]): Set<string> {
924
- return new Set([...(existing ?? []), ...toScopeSet(incoming)])
923
+ function mergeTags(existing: Set<string> | undefined, incoming: string | string[]): Set<string> {
924
+ return new Set([...(existing ?? []), ...toTagSet(incoming)])
925
925
  }
926
926
 
927
927
  /*
928
- Tags an existing entry with a read's scope so a later cache.invalidate({ scope })
929
- reaches entries hydrated from the SSR snapshot (which carry a value but no scope)
928
+ Tags an existing entry with a read's tags so a later cache.invalidate({ tags })
929
+ reaches entries hydrated from the SSR snapshot (which carry a value but no tags)
930
930
  without a refetch. Merges rather than replaces so a read tagging one group can't
931
- drop tags another read site already added; a no-op when the read passes no scope.
931
+ drop tags another read site already added; a no-op when the read passes no tags.
932
932
  */
933
- function tagScope(entry: CacheEntry, scope: CacheOptions['scope']): void {
934
- if (scope !== undefined) {
935
- entry.scope = mergeScopes(entry.scope, scope)
933
+ function tagEntry(entry: CacheEntry, tags: CacheOptions['tags']): void {
934
+ if (tags !== undefined) {
935
+ entry.tags = mergeTags(entry.tags, tags)
936
936
  }
937
937
  }
938
938
 
939
939
  /*
940
- Mirrors tagScope for invalidate policies: a read declaring a policy arms an
940
+ Mirrors tagEntry for invalidate policies: a read declaring a policy arms an
941
941
  existing entry that lacks one. Hydrated snapshot entries carry a value but no
942
942
  refetch thunk — without this, the first invalidate after hydration would hard-
943
943
  drop the entry (a pending flash) instead of revalidating stale-in-place, and a
@@ -24,7 +24,7 @@ resource down and reopening it across a re-run. Called outside any tracking scop
24
24
  `track` is a no-op, observers stay empty, and the resource never opens — matching
25
25
  the open-on-first-read contract.
26
26
  */
27
- // @readme plumbing
27
+ // @documentation plumbing
28
28
  export function createSubscriber(start: (update: () => void) => () => void): () => void {
29
29
  const node = createSignalNode(undefined)
30
30
  let cleanup: (() => void) | undefined