@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.
- package/AGENTS.md +39 -34
- package/CHANGELOG.md +30 -0
- package/README.md +21 -21
- package/package.json +5 -5
- package/src/abideResolverPlugin.ts +1 -1
- package/src/build.ts +1 -1
- package/src/compile.ts +1 -1
- package/src/lib/bundle/BundleMenu.ts +1 -1
- package/src/lib/bundle/BundleMenuItem.ts +1 -1
- package/src/lib/bundle/BundleWindow.ts +1 -1
- package/src/lib/bundle/bundled.ts +1 -1
- package/src/lib/bundle/disconnected.abide +105 -75
- package/src/lib/bundle/onMenu.ts +1 -1
- package/src/lib/mcp/createMcpServer.ts +1 -1
- package/src/lib/server/AppModule.ts +1 -1
- package/src/lib/server/DELETE.ts +1 -1
- package/src/lib/server/GET.ts +1 -1
- package/src/lib/server/HEAD.ts +1 -1
- package/src/lib/server/PATCH.ts +1 -1
- package/src/lib/server/POST.ts +1 -1
- package/src/lib/server/PUT.ts +1 -1
- package/src/lib/server/agent.ts +1 -1
- package/src/lib/server/appDataDir.ts +1 -1
- package/src/lib/server/cookies.ts +1 -1
- package/src/lib/server/env.ts +1 -1
- package/src/lib/server/error.ts +1 -1
- package/src/lib/server/json.ts +1 -1
- package/src/lib/server/jsonl.ts +1 -1
- package/src/lib/server/prompts/definePrompt.ts +1 -1
- package/src/lib/server/prompts/renderPromptTemplate.ts +1 -1
- package/src/lib/server/reachable.ts +1 -1
- package/src/lib/server/redirect.ts +1 -1
- package/src/lib/server/request.ts +1 -1
- package/src/lib/server/rpc/defineVerb.ts +1 -1
- package/src/lib/server/runtime/buildCacheSnapshot.ts +1 -1
- package/src/lib/server/runtime/types/InspectorCacheEntry.ts +2 -2
- package/src/lib/server/runtime/types/InspectorContext.ts +2 -2
- package/src/lib/server/server.ts +1 -1
- package/src/lib/server/socket.ts +1 -1
- package/src/lib/server/sockets/defineSocket.ts +1 -1
- package/src/lib/server/sse.ts +1 -1
- package/src/lib/shared/HttpError.ts +1 -1
- package/src/lib/shared/cache.ts +18 -18
- package/src/lib/shared/createSubscriber.ts +1 -1
- package/src/lib/shared/health.ts +1 -1
- package/src/lib/shared/html.ts +1 -1
- package/src/lib/shared/isSubscribable.ts +1 -1
- package/src/lib/shared/log.ts +1 -1
- package/src/lib/shared/online.ts +1 -1
- package/src/lib/shared/page.ts +1 -1
- package/src/lib/shared/pending.ts +2 -2
- package/src/lib/shared/probeRegistries.ts +2 -2
- package/src/lib/shared/refreshing.ts +2 -2
- package/src/lib/shared/selectorMatcher.ts +8 -8
- package/src/lib/shared/selectorPrefix.ts +1 -1
- package/src/lib/shared/snippet.ts +1 -1
- package/src/lib/shared/toTagSet.ts +4 -0
- package/src/lib/shared/trace.ts +1 -1
- package/src/lib/shared/types/CacheEntry.ts +3 -3
- package/src/lib/shared/types/CacheOptions.ts +3 -3
- package/src/lib/shared/types/CacheSelector.ts +2 -2
- package/src/lib/shared/url.ts +1 -1
- package/src/lib/shared/withJsonSchema.ts +1 -1
- package/src/lib/test/assertAgentFrameConformance.ts +1 -1
- package/src/lib/test/createScriptedSurface.ts +1 -1
- package/src/lib/test/createTestApp.ts +1 -1
- package/src/lib/ui/compile/REACTIVE_CALLEES.ts +7 -2
- package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +3 -4
- package/src/lib/ui/compile/abideUiPlugin.ts +1 -1
- package/src/lib/ui/compile/analyzeComponent.ts +2 -1
- package/src/lib/ui/compile/compileComponent.ts +3 -3
- package/src/lib/ui/compile/compileModule.ts +30 -2
- package/src/lib/ui/compile/compileSSR.ts +5 -5
- package/src/lib/ui/compile/compileShadow.ts +62 -37
- package/src/lib/ui/compile/desugarSignals.ts +147 -18
- package/src/lib/ui/compile/generateBuild.ts +15 -28
- package/src/lib/ui/compile/generateSSR.ts +20 -13
- package/src/lib/ui/compile/isControlFlow.ts +18 -0
- package/src/lib/ui/compile/isTextLeaf.ts +15 -0
- package/src/lib/ui/compile/lowerContext.ts +45 -5
- package/src/lib/ui/compile/prepareNestedScript.ts +12 -8
- package/src/lib/ui/compile/renameSignalRefs.ts +21 -4
- package/src/lib/ui/compile/skeletonable.ts +1 -14
- package/src/lib/ui/compile/types/AnalyzedComponent.ts +1 -0
- package/src/lib/ui/computed.ts +32 -0
- package/src/lib/ui/createScope.ts +91 -0
- package/src/lib/ui/dom/anchorCursor.ts +1 -1
- package/src/lib/ui/dom/appendSnippet.ts +1 -1
- package/src/lib/ui/dom/appendStatic.ts +1 -1
- package/src/lib/ui/dom/appendText.ts +1 -1
- package/src/lib/ui/dom/appendTextAt.ts +1 -1
- package/src/lib/ui/dom/applyResolved.ts +1 -1
- package/src/lib/ui/dom/attach.ts +7 -2
- package/src/lib/ui/dom/attr.ts +1 -1
- package/src/lib/ui/dom/awaitBlock.ts +1 -1
- package/src/lib/ui/dom/cloneStatic.ts +1 -1
- package/src/lib/ui/dom/each.ts +4 -3
- package/src/lib/ui/dom/eachAsync.ts +1 -1
- package/src/lib/ui/dom/hydrate.ts +20 -6
- package/src/lib/ui/dom/mount.ts +12 -1
- package/src/lib/ui/dom/mountChild.ts +6 -2
- package/src/lib/ui/dom/mountSlot.ts +1 -1
- package/src/lib/ui/dom/on.ts +10 -4
- package/src/lib/ui/dom/openMarker.ts +3 -3
- package/src/lib/ui/dom/skeleton.ts +13 -5
- package/src/lib/ui/dom/switchBlock.ts +1 -1
- package/src/lib/ui/dom/text.ts +1 -1
- package/src/lib/ui/dom/tryBlock.ts +1 -1
- package/src/lib/ui/dom/when.ts +1 -1
- package/src/lib/ui/effect.ts +7 -2
- package/src/lib/ui/enterScope.ts +18 -0
- package/src/lib/ui/exitScope.ts +8 -0
- package/src/lib/ui/history.ts +102 -0
- package/src/lib/ui/installHotBridge.ts +6 -8
- package/src/lib/ui/linked.ts +0 -1
- package/src/lib/ui/navigate.ts +1 -1
- package/src/lib/ui/outbox.ts +115 -0
- package/src/lib/ui/persist.ts +112 -0
- package/src/lib/ui/probeNavigation.ts +1 -1
- package/src/lib/ui/remoteProxy.ts +1 -1
- package/src/lib/ui/renderToStream.ts +1 -1
- package/src/lib/ui/router.ts +1 -1
- package/src/lib/ui/runtime/CURRENT_SCOPE.ts +10 -0
- package/src/lib/ui/runtime/OUTLET_TAG.ts +1 -1
- package/src/lib/ui/runtime/PATCH_BUS.ts +28 -0
- package/src/lib/ui/runtime/RESUME.ts +1 -1
- package/src/lib/ui/runtime/captureModelDoc.ts +29 -0
- package/src/lib/ui/runtime/claimExpected.ts +26 -0
- package/src/lib/ui/runtime/createComputedNode.ts +1 -1
- package/src/lib/ui/runtime/createDoc.ts +73 -3
- package/src/lib/ui/runtime/enterRenderPass.ts +1 -1
- package/src/lib/ui/runtime/escapeKey.ts +13 -0
- package/src/lib/ui/runtime/exitRenderPass.ts +1 -1
- package/src/lib/ui/runtime/hotReplace.ts +17 -8
- package/src/lib/ui/runtime/inScope.ts +19 -0
- package/src/lib/ui/runtime/localStoragePersistence.ts +34 -0
- package/src/lib/ui/runtime/nextBlockId.ts +1 -1
- package/src/lib/ui/runtime/seedModelDoc.ts +26 -0
- package/src/lib/ui/runtime/types/{Derived.ts → Computed.ts} +1 -1
- package/src/lib/ui/runtime/types/Doc.ts +3 -0
- package/src/lib/ui/runtime/types/HotInstance.ts +6 -2
- package/src/lib/ui/runtime/types/PatchEvent.ts +16 -0
- package/src/lib/ui/runtime/unescapeKey.ts +12 -0
- package/src/lib/ui/runtime/walkPath.ts +3 -1
- package/src/lib/ui/scope.ts +19 -0
- package/src/lib/ui/socketProxy.ts +1 -1
- package/src/lib/ui/startClient.ts +1 -1
- package/src/lib/ui/state.ts +1 -2
- package/src/lib/ui/sync.ts +42 -0
- package/src/lib/ui/tail.ts +1 -1
- package/src/lib/ui/types/History.ts +14 -0
- package/src/lib/ui/types/Outbox.ts +14 -0
- package/src/lib/ui/types/PersistHandle.ts +11 -0
- package/src/lib/ui/types/PersistenceStore.ts +12 -0
- package/src/lib/ui/types/Scope.ts +57 -0
- package/src/lib/ui/types/SyncTransport.ts +13 -0
- package/src/preload.ts +1 -1
- package/src/lib/shared/toScopeSet.ts +0 -4
- package/src/lib/ui/derived.ts +0 -49
- 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
|
-
|
|
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
|
-
|
|
152
|
+
<img src={logo} alt="" class="h-16 w-16 rounded-xl object-contain opacity-90" />
|
|
160
153
|
</template>
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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 & 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>
|
package/src/lib/bundle/onMenu.ts
CHANGED
|
@@ -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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
-
// @
|
|
16
|
+
// @documentation plumbing
|
|
17
17
|
export type AppModule = {
|
|
18
18
|
/*
|
|
19
19
|
Extra inbound header names to forward onto in-process rpc Requests, on
|
package/src/lib/server/DELETE.ts
CHANGED
|
@@ -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
|
-
// @
|
|
9
|
+
// @documentation rpc
|
|
10
10
|
export const DELETE: VerbHelper = (_fn: any, _opts?: any) => unprocessed('DELETE')
|
package/src/lib/server/GET.ts
CHANGED
|
@@ -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
|
-
// @
|
|
9
|
+
// @documentation rpc
|
|
10
10
|
export const GET: VerbHelper = (_fn: any, _opts?: any) => unprocessed('GET')
|
package/src/lib/server/HEAD.ts
CHANGED
|
@@ -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
|
-
// @
|
|
9
|
+
// @documentation rpc
|
|
10
10
|
export const HEAD: VerbHelper = (_fn: any, _opts?: any) => unprocessed('HEAD')
|
package/src/lib/server/PATCH.ts
CHANGED
|
@@ -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
|
-
// @
|
|
9
|
+
// @documentation rpc
|
|
10
10
|
export const PATCH: VerbHelper = (_fn: any, _opts?: any) => unprocessed('PATCH')
|
package/src/lib/server/POST.ts
CHANGED
|
@@ -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
|
-
// @
|
|
9
|
+
// @documentation rpc
|
|
10
10
|
export const POST: VerbHelper = (_fn: any, _opts?: any) => unprocessed('POST')
|
package/src/lib/server/PUT.ts
CHANGED
|
@@ -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
|
-
// @
|
|
9
|
+
// @documentation rpc
|
|
10
10
|
export const PUT: VerbHelper = (_fn: any, _opts?: any) => unprocessed('PUT')
|
package/src/lib/server/agent.ts
CHANGED
|
@@ -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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
-
// @
|
|
20
|
+
// @documentation request-scope
|
|
21
21
|
export function cookies(): Bun.CookieMap {
|
|
22
22
|
const store = requestContext.getStore()
|
|
23
23
|
if (!store) {
|
package/src/lib/server/env.ts
CHANGED
|
@@ -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
|
-
// @
|
|
29
|
+
// @documentation configuration
|
|
30
30
|
export function env<Schema extends StandardSchemaV1>(
|
|
31
31
|
schema: Schema,
|
|
32
32
|
): StandardSchemaV1.InferOutput<Schema> {
|
package/src/lib/server/error.ts
CHANGED
|
@@ -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
|
-
// @
|
|
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(
|
package/src/lib/server/json.ts
CHANGED
|
@@ -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
|
-
// @
|
|
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(
|
package/src/lib/server/jsonl.ts
CHANGED
|
@@ -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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
-
// @
|
|
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]),
|
|
@@ -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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
-
|
|
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
|
|
19
|
-
|
|
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
|
-
// @
|
|
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,
|
|
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
|
package/src/lib/server/server.ts
CHANGED
|
@@ -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
|
-
// @
|
|
21
|
+
// @documentation request-scope
|
|
22
22
|
export function server(): Server<unknown> {
|
|
23
23
|
const active = getActiveServer()
|
|
24
24
|
if (active) {
|
package/src/lib/server/socket.ts
CHANGED
|
@@ -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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
package/src/lib/server/sse.ts
CHANGED
|
@@ -31,7 +31,7 @@ import { withResponseDefaults } from './runtime/withResponseDefaults.ts'
|
|
|
31
31
|
|
|
32
32
|
const KEEPALIVE_INTERVAL_MS = 15000
|
|
33
33
|
|
|
34
|
-
// @
|
|
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
|
-
// @
|
|
7
|
+
// @documentation response
|
|
8
8
|
export class HttpError extends Error {
|
|
9
9
|
readonly status: number
|
|
10
10
|
readonly statusText: string
|
package/src/lib/shared/cache.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
// @
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 `
|
|
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
|
|
924
|
-
return new Set([...(existing ?? []), ...
|
|
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
|
|
929
|
-
reaches entries hydrated from the SSR snapshot (which carry a value but no
|
|
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
|
|
931
|
+
drop tags another read site already added; a no-op when the read passes no tags.
|
|
932
932
|
*/
|
|
933
|
-
function
|
|
934
|
-
if (
|
|
935
|
-
entry.
|
|
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
|
|
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
|
-
// @
|
|
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
|