@abide/abide 0.41.0 → 0.42.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.
- package/AGENTS.md +333 -326
- package/CHANGELOG.md +92 -0
- package/README.md +91 -83
- package/package.json +1 -1
- package/src/abideLsp.ts +46 -8
- package/src/abideResolverPlugin.ts +3 -5
- package/src/lib/server/runtime/devClientFingerprint.ts +2 -1
- package/src/lib/shared/escapeRegex.ts +9 -0
- package/src/lib/shared/fileName.ts +9 -0
- package/src/lib/shared/fileStem.ts +3 -1
- package/src/lib/shared/programNameForPackage.ts +3 -1
- package/src/lib/shared/stripImport.ts +3 -1
- package/src/lib/ui/compile/ABIDE_SEMANTIC_TOKENS_LEGEND.ts +45 -0
- package/src/lib/ui/compile/SSR_ESCAPE.ts +3 -1
- package/src/lib/ui/compile/abideUiPlugin.ts +2 -1
- package/src/lib/ui/compile/compileShadow.ts +46 -9
- package/src/lib/ui/compile/createShadowLanguageService.ts +48 -0
- package/src/lib/ui/compile/encodeSemanticTokens.ts +37 -0
- package/src/lib/ui/compile/generateBuild.ts +13 -6
- package/src/lib/ui/compile/generateSSR.ts +23 -14
- package/src/lib/ui/compile/makeVarNamer.ts +10 -0
- package/src/lib/ui/compile/offsetToPosition.ts +9 -0
- package/src/lib/ui/compile/parseTemplate.ts +524 -104
- package/src/lib/ui/compile/skeletonContext.ts +67 -79
- package/src/lib/ui/compile/structuralBlockTokens.ts +101 -0
- package/src/lib/ui/compile/templateAnchorAdapter.ts +61 -0
- package/src/lib/ui/compile/templateElementAdapter.ts +44 -0
- package/src/lib/ui/compile/types/SemanticToken.ts +11 -0
- package/src/lib/ui/compile/types/TemplateNode.ts +9 -0
- package/src/lib/ui/compile/walkAnchorOrder.ts +57 -0
- package/src/lib/ui/compile/walkElementOrder.ts +60 -0
- package/src/lib/ui/dom/appendSnippet.ts +9 -8
- package/src/lib/ui/dom/appendText.ts +1 -5
- package/src/lib/ui/dom/applyResolved.ts +4 -9
- package/src/lib/ui/dom/awaitBlock.ts +37 -31
- package/src/lib/ui/dom/buildDetachedRange.ts +30 -0
- package/src/lib/ui/dom/depthZeroNodes.ts +34 -0
- package/src/lib/ui/dom/domAnchorAdapter.ts +29 -0
- package/src/lib/ui/dom/domElementAdapter.ts +20 -0
- package/src/lib/ui/dom/each.ts +7 -11
- package/src/lib/ui/dom/eachAsync.ts +12 -17
- package/src/lib/ui/dom/isComment.ts +6 -0
- package/src/lib/ui/dom/isElement.ts +6 -0
- package/src/lib/ui/dom/markerDepthDelta.ts +19 -0
- package/src/lib/ui/dom/mountRange.ts +4 -3
- package/src/lib/ui/dom/mountSlot.ts +4 -3
- package/src/lib/ui/dom/on.ts +6 -1
- package/src/lib/ui/dom/replaceRange.ts +24 -0
- package/src/lib/ui/dom/skeleton.ts +35 -92
- package/src/lib/ui/dom/switchBlock.ts +13 -10
- package/src/lib/ui/dom/when.ts +13 -10
- package/src/lib/ui/runtime/RANGE_MARKER.ts +16 -0
- package/src/lib/ui/runtime/batch.ts +22 -0
- package/src/lib/ui/runtime/clientPage.ts +3 -8
- package/src/lib/ui/runtime/createDoc.ts +12 -16
- package/src/lib/ui/runtime/pathSegments.ts +10 -0
- package/src/lib/ui/seedResolved.ts +28 -0
- package/src/lib/ui/startClient.ts +6 -4
- package/src/lib/ui/types/ResolvedFrame.ts +15 -0
- package/template/.zed/settings.json +4 -0
- package/template/src/ui/pages/page.abide +4 -4
package/AGENTS.md
CHANGED
|
@@ -1,403 +1,410 @@
|
|
|
1
1
|
# AGENTS.md — abide complete surface map
|
|
2
2
|
|
|
3
|
-
> The exhaustive index of abide's public surface: every `exports` key appears
|
|
4
|
-
> grouped by namespace, with its import specifier and a one-line spec
|
|
5
|
-
> grasps the whole API in one read
|
|
6
|
-
>
|
|
7
|
-
> glossary
|
|
8
|
-
>
|
|
9
|
-
>
|
|
10
|
-
>
|
|
11
|
-
>
|
|
12
|
-
>
|
|
3
|
+
> The exhaustive index of abide's public surface: every `exports` key appears
|
|
4
|
+
> once, grouped by namespace, with its import specifier and a one-line spec, so
|
|
5
|
+
> an agent grasps the whole API in one read. The README is the curated
|
|
6
|
+
> three-primitive intro (RPCs, sockets, components); this map is complete.
|
|
7
|
+
> `CONTEXT.md` is the glossary; `docs/adr/` holds the rationale.
|
|
8
|
+
>
|
|
9
|
+
> **No barrels.** Every public name has its own module path —
|
|
10
|
+
> `@abide/abide/server/GET`, `@abide/abide/shared/cache`, `@abide/abide/ui/scope`. The namespace
|
|
11
|
+
> marks the side a name runs on: `@abide/abide/server/*` is server-only,
|
|
12
|
+
> `@abide/abide/ui/*` is client-only, `@abide/abide/shared/*` is isomorphic (same callable,
|
|
13
|
+
> same behaviour on both sides — the bundler swaps the runtime). There is no
|
|
14
|
+
> umbrella `index.ts`, so importing one name never drags in side-effecting
|
|
15
|
+
> siblings.
|
|
16
|
+
>
|
|
17
|
+
> Package `@abide/abide`, runtime Bun ≥ 1.3.0, one direct dependency
|
|
18
|
+
> (`typescript`); `tailwindcss` + `bun-plugin-tailwind` are optional peers.
|
|
19
|
+
> Import specifiers below are `package.json` `exports` keys, not file paths —
|
|
20
|
+
> `@abide/abide/server/GET` resolves to `src/lib/server/GET.ts`.
|
|
13
21
|
|
|
14
22
|
## The premise
|
|
15
23
|
|
|
16
|
-
One typed verb declaration fans out to
|
|
24
|
+
One typed verb declaration fans out to every consumer:
|
|
25
|
+
|
|
17
26
|
```text
|
|
18
27
|
getMessages = GET(fn, { inputSchema })
|
|
19
28
|
│
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
┌─────────────┬─────────┼──────────┬──────────────┐
|
|
30
|
+
▼ ▼ ▼ ▼ ▼
|
|
31
|
+
SSR call browser MCP tool CLI sub- OpenAPI
|
|
32
|
+
cache(fn)() fetch (read) command operation
|
|
33
|
+
proxy
|
|
23
34
|
```
|
|
24
35
|
|
|
25
|
-
A
|
|
26
|
-
never auto-exposes to MCP — it
|
|
36
|
+
A Standard Schema unlocks the CLI for every verb and MCP for read-only verbs
|
|
37
|
+
(`GET` / `HEAD`); a mutating verb never auto-exposes to MCP — it opts in with
|
|
38
|
+
`clients: { mcp: true }`. The same gating applies to sockets: a schema flips
|
|
39
|
+
the MCP/CLI read faces on.
|
|
27
40
|
|
|
28
41
|
## File-based conventions
|
|
29
42
|
|
|
30
|
-
The bundler reads these paths by convention:
|
|
31
|
-
|
|
32
|
-
| Path
|
|
33
|
-
|
|
|
34
|
-
| `src/server/rpc/<name>.ts`
|
|
35
|
-
| `src/server/sockets/<name>.ts`
|
|
36
|
-
| `src/server/
|
|
37
|
-
| `src/
|
|
38
|
-
| `src/
|
|
39
|
-
| `src/
|
|
40
|
-
| `src/
|
|
41
|
-
| `src/
|
|
42
|
-
| `src/ui/
|
|
43
|
-
| `src
|
|
44
|
-
| `
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
`$mcp` → `src/mcp/`, `$cli` → `src/cli/`.
|
|
43
|
+
The bundler reads these paths by convention (`cwd` is the app root):
|
|
44
|
+
|
|
45
|
+
| Path | Meaning |
|
|
46
|
+
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
47
|
+
| `src/server/rpc/<name>.ts` | One RPC verb per file; export name = filename = URL under `/rpc/`. Server: real handler; client: `remoteProxy`. |
|
|
48
|
+
| `src/server/sockets/<name>.ts` | One socket per file; export name = filename. Server: `defineSocket`; client: `socketProxy`. |
|
|
49
|
+
| `src/server/config.ts` | Optional. Eager-imported for boot-time `env()` validation (virtual `abide:config`). |
|
|
50
|
+
| `src/mcp/prompts/*.md` | MCP prompts; frontmatter (description, JSON Schema) + `{{name}}` body. Rewritten to `definePrompt`. |
|
|
51
|
+
| `src/mcp/resources/**` | MCP resource files, gzip-embedded into the standalone binary. |
|
|
52
|
+
| `src/app.ts` | Optional `AppModule` — `init` / `handle` / `handleError` / `health` / `forwardHeaders` hooks (virtual `abide:app`). |
|
|
53
|
+
| `src/bundle/window.ts` | Optional desktop-bundle config (`BundleWindow`); baked into the launcher. |
|
|
54
|
+
| `src/bundle/disconnected.abide` | Optional custom connect screen; falls back to the built-in component. |
|
|
55
|
+
| `src/ui/pages/**/page.abide` | A page; its folder path is the route. `[id]` folder = dynamic segment → `page.params.id`. |
|
|
56
|
+
| `src/ui/pages/**/layout.abide` | A layout wrapping pages at/below its folder; its `<slot/>` is the router outlet. |
|
|
57
|
+
| `src/ui/public/**` | Static assets served at site root; gzip-embedded into the standalone binary. |
|
|
58
|
+
| `src/.abide/*.d.ts` | Generated types written each build — `routes`, `rpc`, `sockets`, `health`, `publicAssets`, and test surfaces. |
|
|
59
|
+
| `dist/_app/` | Client bundle output (hashed chunks; prod adds precompressed `.gz` siblings). |
|
|
48
60
|
|
|
49
61
|
## CLI
|
|
50
62
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Tests preload the framework: `preload = ["@abide/abide/preload"]` in `bunfig.toml`
|
|
66
|
-
registers `.abide` compilation so `bun test` runs the same runtime as the server.
|
|
67
|
-
|
|
68
|
-
## Authoring contracts
|
|
69
|
-
|
|
70
|
-
What you write into each convention path, and the contract the framework holds
|
|
71
|
-
you to. The per-export specs below are exhaustive; this is the shape of the code
|
|
72
|
-
that produces them.
|
|
73
|
-
|
|
74
|
-
### RPC verb — `src/server/rpc/<name>.ts`
|
|
75
|
-
|
|
76
|
-
- One `export const <name> = METHOD(handler, opts?)` per file (`METHOD` ∈ `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`HEAD`); the file path is the route.
|
|
77
|
-
- The handler receives the **validated** input — `InferOutput<inputSchema>`, or `{}` when schemaless — and may read request scope via `request()` / `cookies()`. It returns `json()`, `jsonl()`, `sse()`, `error()`, `redirect()`, or a raw `Response`; the union of those branches is the verb's typed result.
|
|
78
|
-
- `opts`: `{ inputSchema?, outputSchema?, filesSchema?, clients?: { browser, mcp, cli }, crossOrigin?, maxBodySize?, timeout? }`. A Standard Schema flips MCP + CLI on automatically; a **mutating** verb still needs explicit `clients: { mcp: true }`. `crossOrigin: true` exempts a mutating verb from the same-origin CSRF check. `timeout` (ms) bounds the handler on every surface (504 past it). `filesSchema` validates multipart `File` parts (the caller sends `FormData`).
|
|
79
|
-
- Query args arrive as **strings** — validate with `z.coerce.*`.
|
|
80
|
-
- Consume four ways: `cache(verb)(args)` in-process (SSR, warm hydration), the same call over a swapped `fetch` in the browser, `verb.raw(args)` for the undecoded `Response`, `verb.stream(args)` for an iterable body view.
|
|
81
|
-
|
|
82
|
-
### Socket — `src/server/sockets/<name>.ts`
|
|
83
|
-
|
|
84
|
-
- One `export const <name> = socket({ schema, tail?, ttl?, clientPublish?, clients? })`; the file name is the topic.
|
|
85
|
-
- `.publish(msg)` validates then broadcasts; `.tail(n?)` replays the retained window then streams live; bare `for await` is live-only. `tail` = frames retained, `ttl` = frame expiry (ms), `clientPublish` = allow a browser `POST` (default off, so route writes through a verb that validates first).
|
|
86
|
-
- HTTP face `/__abide/sockets/<name>`: `GET` returns the tail, `POST` publishes (gated by `clientPublish`).
|
|
87
|
-
- Consume in a component with `tail(socket)` (latest-wins) or `tail(socket, { last: n })` (window).
|
|
88
|
-
|
|
89
|
-
### Page & layout — `src/ui/pages/**`
|
|
90
|
-
|
|
91
|
-
- `page.abide` is a route; the folder path is the URL. `[id]` segments become params read off the `page` proxy (`page.params.id`), typed via generated `src/.abide/routes.d.ts`, reactive across navigation.
|
|
92
|
-
- `layout.abide` wraps every page at or below its folder; its `<slot/>` (compiled to an outlet) holds the nested page or child layout.
|
|
93
|
-
- Build links with `url('/pages/product/[id]', { id })` and move with `navigate(href)`.
|
|
94
|
-
|
|
95
|
-
### App module & config — `src/app.ts`, `src/server/config.ts` (both optional)
|
|
63
|
+
```text
|
|
64
|
+
abide scaffold <name> scaffold the bundled template, install deps, start dev
|
|
65
|
+
abide dev build client + run server with hot reload
|
|
66
|
+
abide build single client build into dist/_app
|
|
67
|
+
abide start run the production server against a built dist/
|
|
68
|
+
abide run <file> [...] run a script under the abide preload (same runtime)
|
|
69
|
+
abide compile build a standalone server executable
|
|
70
|
+
abide cli build a thin CLI binary (remote client + bundled server)
|
|
71
|
+
abide bundle build a movable self-contained desktop app bundle
|
|
72
|
+
abide check type-check every .abide template + props
|
|
73
|
+
abide lsp run the .abide language server over stdio (JSON-RPC)
|
|
74
|
+
abide init-agent write/refresh the CLAUDE.md pointer to this surface map
|
|
75
|
+
```
|
|
96
76
|
|
|
97
|
-
|
|
98
|
-
|
|
77
|
+
`bun test` in a scaffolded app preloads abide via `bunfig.toml`
|
|
78
|
+
(`[test] preload = ["@abide/abide/preload"]`) so `.abide` modules resolve.
|
|
99
79
|
|
|
100
|
-
|
|
80
|
+
## Authoring contracts
|
|
101
81
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
82
|
+
**RPC verb** — `export const <name> = GET(handler, opts?)` (same shape for
|
|
83
|
+
`POST` / `PUT` / `PATCH` / `DELETE` / `HEAD`). The handler receives the parsed
|
|
84
|
+
args bag (`InferOutput<inputSchema>`, merged with validated files when
|
|
85
|
+
`filesSchema` is set), may read `request()` / `cookies()` / `server()` from
|
|
86
|
+
request scope, and returns `json` / `jsonl` / `sse` / `error` / `redirect` or a
|
|
87
|
+
raw `Response`. `opts`: `inputSchema` (validates args, infers the type, gates
|
|
88
|
+
CLI + read-MCP), `outputSchema` (documents the 200 body for OpenAPI/MCP),
|
|
89
|
+
`filesSchema` (multipart File parts), `clients: { browser, mcp, cli }` (explicit
|
|
90
|
+
surface targeting; explicit wins over schema auto-flip), `crossOrigin` (exempt
|
|
91
|
+
a mutating verb from the same-origin gate), `maxBodySize` (per-verb 413
|
|
92
|
+
ceiling), `timeout` (handler deadline in ms; 504 on every surface). Query args
|
|
93
|
+
arrive as strings — use `z.coerce.*`. Consume four ways: `cache(verb)(args)`
|
|
94
|
+
in-process, the swapped browser `fetch`, `verb.raw(args)` for the `Response`,
|
|
95
|
+
`verb.stream(args)` to iterate a streaming body.
|
|
96
|
+
|
|
97
|
+
**Socket** — `export const <name> = socket({ schema?, tail?, ttl?,
|
|
98
|
+
clientPublish?, clients? })`. `tail` retains the last N frames for late joiners
|
|
99
|
+
and the read faces; `ttl` lazily evicts frames older than N ms; `clientPublish`
|
|
100
|
+
(default off) gates browser publishes; `schema` validates publishes
|
|
101
|
+
synchronously and flips MCP/CLI on. Isomorphic `AsyncIterable<T>`: bare
|
|
102
|
+
iteration is the live stream, `.tail(count?)` seeds from retention,
|
|
103
|
+
`.publish(msg)` fans out in-process + over the multiplexed ws.
|
|
104
|
+
|
|
105
|
+
**Page / layout** — a `[id]` folder segment becomes `page.params.id`. A layout's
|
|
106
|
+
`<slot/>` is the outlet the next layer fills. Read `page` (route, params, url,
|
|
107
|
+
navigating) and call `navigate(path)` for SPA transitions.
|
|
108
|
+
|
|
109
|
+
**App / config** — `src/app.ts` default-exports an `AppModule`; `src/server/config.ts`
|
|
110
|
+
runs `env(schema)` at boot.
|
|
111
|
+
|
|
112
|
+
**Isomorphism move** — wrap an SSR read in `cache(fn)()` so the value serializes
|
|
113
|
+
into the document and the client hydrates warm instead of refetching.
|
|
107
114
|
|
|
108
115
|
## .abide template grammar
|
|
109
116
|
|
|
110
|
-
A
|
|
111
|
-
|
|
112
|
-
component-scoped `<style>`. Ambient in
|
|
113
|
-
`props`, `effect`, `html`,
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
|
142
|
-
|
|
|
143
|
-
| `
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
|
148
|
-
|
|
|
149
|
-
| `{
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
|
154
|
-
|
|
|
155
|
-
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
- `@abide/abide/server/
|
|
178
|
-
- `@abide/abide/server/
|
|
179
|
-
- `@abide/abide/server/
|
|
180
|
-
- `@abide/abide/server/
|
|
181
|
-
- `@abide/abide/server/DELETE` — as `GET`, for `DELETE`.
|
|
182
|
-
- `@abide/abide/server/HEAD` — as `GET`, for `HEAD`.
|
|
183
|
-
- `@abide/abide/server/rpc/defineVerb` — the verb factory (plumbing): handler + options (`inputSchema`, `outputSchema`, `filesSchema`, `clients`, `timeout`, `maxBodySize`, `crossOrigin`); returns a `RemoteFunction` — plain call decodes by Content-Type and throws `HttpError` on non-2xx, `.raw(args)` returns the `Response`, `.stream(args)` an iterable body view; auto-exposes to CLI/MCP per schema + method.
|
|
184
|
-
|
|
185
|
-
### Response helpers — @documentation response
|
|
186
|
-
|
|
187
|
-
- `@abide/abide/server/json` — JSON `Response`, `Cache-Control: no-store`; `undefined` → 204; phantom `TypedResponse` brand carries the return type.
|
|
188
|
-
- `@abide/abide/server/jsonl` — wraps `AsyncIterable<Frame>` as JSON Lines; frame errors emit a `{"$error":...}` line; cancellation flows to `iter.return()`.
|
|
189
|
-
- `@abide/abide/server/sse` — wraps `AsyncIterable<Frame>` as Server-Sent Events; 15s keepalive comments, error frames as `event: error`.
|
|
190
|
-
- `@abide/abide/server/error` — plain-text error `Response(status, message?, init?)`; defaults to the standard status text; `TypedResponse<never>` so error branches union cleanly.
|
|
191
|
-
- `@abide/abide/server/redirect` — redirect `Response(url, status=302, init?)`; relative URLs allowed, 301/302/303/307/308, `TypedResponse<never>`.
|
|
117
|
+
A component file is `<script>` (module-level JS: imports, handlers,
|
|
118
|
+
reactive declarations) + optional `<template name="…">` snippet definitions +
|
|
119
|
+
markup + an optional component-scoped `<style>`. Ambient in-scope names need no
|
|
120
|
+
import: `scope`, `props` / `prop`, `effect`, `html`, `snippet`.
|
|
121
|
+
|
|
122
|
+
**Reactive state**
|
|
123
|
+
|
|
124
|
+
| Form | Meaning |
|
|
125
|
+
| ---------------------------------- | ---------------------------------------------------------------------------------- |
|
|
126
|
+
| `scope().state(v)` | Writable reactive cell (`{ value }`); the sole writable surface. |
|
|
127
|
+
| `scope().computed(fn)` | Read-only derived cell; re-runs when its reads change. |
|
|
128
|
+
| `scope().linked(initial, reseed?)` | Cell bound to a reactive-document path; reflects/drives the root doc. |
|
|
129
|
+
| `effect(fn)` | Runs now, re-runs on dep change; may return a teardown; returns a disposer. |
|
|
130
|
+
| `props()` / `prop(name)` | Read the component's props (thunks for reactivity), e.g. `const { id } = props()`. |
|
|
131
|
+
|
|
132
|
+
**Bindings**
|
|
133
|
+
|
|
134
|
+
| Form | Meaning |
|
|
135
|
+
| --------------------------- | -------------------------------------------------------------------------------------------- |
|
|
136
|
+
| `{expr}` | Escaped text interpolation; raw markup via the `html` tag; `{snippet(args)}` mounts a snippet. |
|
|
137
|
+
| `name={expr}` | Reactive attribute (boolean `true` sets bare, falsy removes). |
|
|
138
|
+
| `on<event>={fn}` | Event listener, e.g. `onclick={handler}`. |
|
|
139
|
+
| `bind:value={x}` | Two-way input binding. |
|
|
140
|
+
| `bind:checked={x}` | Two-way checkbox binding. |
|
|
141
|
+
| `bind:group={x}` | Radio/checkbox group (radio → one value, checkbox → array). |
|
|
142
|
+
| `bind:value={{ get, set }}` | Writable computed at the binding site. |
|
|
143
|
+
| `{...expr}` | Spread keys as attributes (elements) or props (components). |
|
|
144
|
+
| `attach={fn}` | Build-time element attachment with optional teardown. |
|
|
145
|
+
|
|
146
|
+
**Control flow** — `{#…}` blocks (each head reads as the JS clause it lowers to):
|
|
147
|
+
|
|
148
|
+
| Form | Meaning |
|
|
149
|
+
| ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
150
|
+
| `{#if c}` / `{:else if c}` / `{:else}` / `{/if}` | Conditional, source-order, re-evaluated reactively. |
|
|
151
|
+
| `{#for x of list}` / `{#for x, i of list by x.id}` / `{/for}` | Keyed list (`for…of`); `, i` index reactive; `by` key reconciles rows in place; key defaults to item. |
|
|
152
|
+
| `{#for await x of asyncIter by x.id}` … `{:catch e}` / `{/for}` | Async keyed list (`for await…of`); rows append as the iterator yields. |
|
|
153
|
+
| `{#await p}` / `{:then v}` / `{:catch e}` / `{:finally}` / `{/await}` | Promise branches; pending content (before `{:then}`) streams. |
|
|
154
|
+
| `{#await p then v}` / `{/await}` | Blocking: no pending, resolved inline (SSR settles before the first flush). |
|
|
155
|
+
| `{#switch s}` / `{:case v}` / `{:default}` / `{/switch}` | First strict (`===`) match wins. |
|
|
156
|
+
| `{#try}` / `{:catch e}` / `{:finally}` / `{/try}` | Synchronous render error boundary. |
|
|
157
|
+
|
|
158
|
+
**Reusable markup** — `<template>`:
|
|
159
|
+
|
|
160
|
+
| Form | Meaning |
|
|
161
|
+
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
162
|
+
| `<template name="row" args={item}>` … `{row(item)}` | Named template (snippet) definition + call. A `<template>` with a control-flow attribute (`if`/`each`/…) is a compile error — use the `{#…}` block. |
|
|
163
|
+
|
|
164
|
+
**Components & slots** — a capitalised tag (`<Card title={x}>`) mounts a child;
|
|
165
|
+
attributes become props, children fill the child's `<slot>` (with fallback when
|
|
166
|
+
empty). `<style>` is scoped to the component and its children. Component files
|
|
167
|
+
end in `.abide`. A block's binding names (`{:then v}`, `{#for x of …}`) lexically
|
|
168
|
+
shadow same-named component state inside the block.
|
|
169
|
+
|
|
170
|
+
## Server surface — abide/server/\* (server-only)
|
|
171
|
+
|
|
172
|
+
### RPC — @documentation rpc
|
|
173
|
+
|
|
174
|
+
- `@abide/abide/server/GET` — declare a `GET` verb; args from the query string. Schema auto-exposes CLI + read-MCP.
|
|
175
|
+
- `@abide/abide/server/POST` — declare a `POST` verb; args from JSON/form/multipart body (body wins on collision).
|
|
176
|
+
- `@abide/abide/server/PUT` — declare a `PUT` verb (body args; mutating).
|
|
177
|
+
- `@abide/abide/server/PATCH` — declare a `PATCH` verb (body args; mutating).
|
|
178
|
+
- `@abide/abide/server/DELETE` — declare a `DELETE` verb (query args; mutating).
|
|
179
|
+
- `@abide/abide/server/HEAD` — declare a `HEAD` verb (query args; read-only, headers-only response).
|
|
180
|
+
|
|
181
|
+
### Response — @documentation response
|
|
182
|
+
|
|
183
|
+
- `@abide/abide/server/json` — `json(data, init?)`: JSON `TypedResponse` (`Cache-Control: no-store`); `undefined` → 204.
|
|
184
|
+
- `@abide/abide/server/jsonl` — `jsonl(asyncIterable, init?)`: JSONL stream, one value per line; errors emit a `{"$error"}` final line.
|
|
185
|
+
- `@abide/abide/server/sse` — `sse(asyncIterable, init?)`: Server-Sent Events with 15s keepalive comments; errors as an `error` event.
|
|
186
|
+
- `@abide/abide/server/error` — `error(status, message?, init?)`: plain-text error `TypedResponse<never>` (narrows out of the success union).
|
|
187
|
+
- `@abide/abide/server/redirect` — `redirect(url, status=302, init?)`: redirect accepting relative URLs; `TypedResponse<never>`.
|
|
192
188
|
|
|
193
189
|
### Request scope — @documentation request-scope
|
|
194
190
|
|
|
195
|
-
- `@abide/abide/server/request` — the inbound `Request`
|
|
196
|
-
- `@abide/abide/server/cookies` — `Bun.CookieMap
|
|
197
|
-
- `@abide/abide/server/server` — the active `Bun.serve` instance (
|
|
191
|
+
- `@abide/abide/server/request` — `request()`: the inbound `Request` from request-scoped ALS; throws outside scope.
|
|
192
|
+
- `@abide/abide/server/cookies` — `cookies()`: live `Bun.CookieMap`; writes flush to `Set-Cookie`; throws outside scope.
|
|
193
|
+
- `@abide/abide/server/server` — `server()`: the active `Bun.serve` instance (in-process shim for CLI/MCP/test dispatch).
|
|
198
194
|
|
|
199
195
|
### Configuration — @documentation configuration
|
|
200
196
|
|
|
201
|
-
- `@abide/abide/server/env` — validate `
|
|
202
|
-
|
|
203
|
-
### Reachability — @documentation observability
|
|
204
|
-
|
|
205
|
-
- `@abide/abide/server/reachable` — server-only probe of an external host: awaits a `HEAD` (`ABIDE_REACHABLE_TIMEOUT`), then background-polls at `ABIDE_REACHABLE_TTL`; returns a boolean, status-agnostic (any completed HTTP counts).
|
|
197
|
+
- `@abide/abide/server/env` — `env(schema)`: validate `process.env` against a Standard Schema at boot (synchronous; reports all issues).
|
|
206
198
|
|
|
207
199
|
### Sockets — @documentation sockets
|
|
208
200
|
|
|
209
|
-
- `@abide/abide/server/socket` — `
|
|
210
|
-
- `@abide/abide/server/sockets/defineSocket` — server socket factory (plumbing): `name` + `{ tail, ttl, schema, clientPublish, clients }`; `.publish(msg)` validates then broadcasts via `server.publish`, `.tail(count?, hooks?)` replays history then streams live, bare iteration is live-only; auto-MCP/CLI when a schema is present.
|
|
201
|
+
- `@abide/abide/server/socket` — `socket({ schema?, tail?, ttl?, clientPublish?, clients? })`: declare a broadcast topic; isomorphic `Socket<T>`.
|
|
211
202
|
|
|
212
203
|
### Agent — @documentation agent
|
|
213
204
|
|
|
214
|
-
- `@abide/abide/server/agent` —
|
|
205
|
+
- `@abide/abide/server/agent` — `agent(engine, messages)`: run an `AgentEngine` against the request's MCP surface; yields `AgentFrame`s (wrap in `jsonl`/`sse`). Exports the `AgentEngine` / `AgentSurface` / `NeutralMessage` / `AgentFrame` types; provider engines ship in `@abide/<provider>`.
|
|
215
206
|
|
|
216
|
-
###
|
|
207
|
+
### Observability — @documentation observability
|
|
217
208
|
|
|
218
|
-
- `@abide/abide/server/
|
|
219
|
-
- `@abide/abide/server/prompts/renderPromptTemplate` — substitute `{{name}}` placeholders in a markdown template from a `Record<string,string>`; missing args render empty.
|
|
209
|
+
- `@abide/abide/server/reachable` — `reachable(host)`: cached outbound reachability HEAD (first call probes, then polls every TTL); any HTTP response counts as up. Tuned by `ABIDE_REACHABLE_TTL` / `ABIDE_REACHABLE_TIMEOUT`.
|
|
220
210
|
|
|
221
|
-
###
|
|
211
|
+
### Plumbing — @documentation plumbing
|
|
222
212
|
|
|
223
|
-
- `@abide/abide/server/AppModule` —
|
|
224
|
-
- `@abide/abide/server/InspectorContext` —
|
|
213
|
+
- `@abide/abide/server/AppModule` — type of `src/app.ts`: optional `forwardHeaders`, `init`, `handle`, `handleError`, `health` hooks.
|
|
214
|
+
- `@abide/abide/server/InspectorContext` — type of the capability bundle the core injects into `@abide/inspector` when `ABIDE_ENABLE_INSPECTOR=true`.
|
|
215
|
+
- `@abide/abide/server/rpc/defineVerb` — `defineVerb(method, url, handler, opts?)`: low-level builder the GET/POST/… helpers wrap.
|
|
216
|
+
- `@abide/abide/server/sockets/defineSocket` — `defineSocket(name, opts?)`: server-side `Socket` construction (per-subscriber queue, shared retained tail).
|
|
225
217
|
|
|
226
|
-
## Isomorphic surface — abide/shared
|
|
218
|
+
## Isomorphic surface — abide/shared/\* (same callable both sides)
|
|
227
219
|
|
|
228
|
-
###
|
|
220
|
+
### Cache — @documentation cache
|
|
229
221
|
|
|
230
|
-
- `@abide/abide/shared/
|
|
222
|
+
- `@abide/abide/shared/cache` — `cache(fn, opts?)`: coalesce/memoize a remote verb or producer per store (request-scoped server, tab-scoped client). `opts`: `global` (process store), `ttl`, `swr`. Methods: `cache.invalidate`, `cache.on`, `cache.patch`. Warm SSR reads resolve synchronously on hydrate.
|
|
231
223
|
|
|
232
|
-
###
|
|
224
|
+
### Templating — @documentation templating
|
|
233
225
|
|
|
234
|
-
- `@abide/abide/shared/
|
|
226
|
+
- `@abide/abide/shared/html` — `html` (tagged template or `html(str)`): mark a string as trusted raw HTML so `{expr}` inserts nodes verbatim (no auto-escape).
|
|
227
|
+
- `@abide/abide/shared/snippet` — `snippet(payload)`: brand a snippet payload (client DOM builder / server HTML string) so `{expr}` mounts it.
|
|
235
228
|
|
|
236
|
-
###
|
|
229
|
+
### Response — @documentation response
|
|
237
230
|
|
|
238
|
-
- `@abide/abide/shared/
|
|
231
|
+
- `@abide/abide/shared/HttpError` — `class HttpError extends Error`: thrown by remote calls on non-2xx; carries `status`, `statusText`, the raw `response`.
|
|
239
232
|
|
|
240
|
-
###
|
|
233
|
+
### RPC — @documentation rpc
|
|
241
234
|
|
|
242
|
-
- `@abide/abide/shared/
|
|
243
|
-
- `@abide/abide/shared/snippet` — brand a snippet payload (DOM builder on the client, HTML string on the server) so interpolations mount it instead of escaping.
|
|
235
|
+
- `@abide/abide/shared/withJsonSchema` — `withJsonSchema(schema, toJsonSchema)`: attach a `toJSONSchema()` method (for schemas lacking one) feeding OpenAPI/MCP/CLI/bundle forms.
|
|
244
236
|
|
|
245
237
|
### Page — @documentation page
|
|
246
238
|
|
|
247
|
-
- `@abide/abide/shared/page` — reactive page
|
|
239
|
+
- `@abide/abide/shared/page` — reactive `page` proxy: `{ route, params, url, navigating }`; server reads per-request store, client reads the router snapshot.
|
|
248
240
|
|
|
249
|
-
###
|
|
241
|
+
### URL — @documentation url
|
|
250
242
|
|
|
251
|
-
- `@abide/abide/shared/
|
|
252
|
-
- `@abide/abide/shared/refreshing` — reactive: a cache call holds a value while revalidating, or a stream reconnects with its window retained.
|
|
253
|
-
- `@abide/abide/shared/online` — reactive connectivity: `navigator.onLine` on the client, the request's `OFFLINE_HEADER` on the server.
|
|
254
|
-
- `@abide/abide/shared/health` — reactive backend health: a `reachable` flag polled from `/__abide/health` every 10s while visible, plus app `health()` fields; `navigator.onLine` composes at read.
|
|
243
|
+
- `@abide/abide/shared/url` — `url(path, ...args)`: base-correct, typed in-app URLs for RPCs (args → query), page routes (`[name]` params), and assets; external URLs pass through untouched.
|
|
255
244
|
|
|
256
|
-
###
|
|
245
|
+
### Probes — @documentation probes
|
|
257
246
|
|
|
258
|
-
- `@abide/abide/shared/
|
|
247
|
+
- `@abide/abide/shared/pending` — `pending(selector?, args?)`: reactive — any/specific/exact/tagged call in flight, or a stream awaiting its first frame.
|
|
248
|
+
- `@abide/abide/shared/refreshing` — `refreshing(selector?, args?)`: reactive — a value held while fresh data is in flight (SWR refetch / reconnect with retained value).
|
|
249
|
+
- `@abide/abide/shared/online` — `online()`: reactive connectivity (client `navigator.onLine`; server reads the caller's reported state); reports, never acts.
|
|
259
250
|
|
|
260
251
|
### Observability — @documentation observability
|
|
261
252
|
|
|
262
|
-
- `@abide/abide/shared/
|
|
263
|
-
- `@abide/abide/shared/
|
|
253
|
+
- `@abide/abide/shared/health` — `health()`: reactive backend health (`reachable` + app fields) polled from `/__abide/health` only while read; SSR-seeded.
|
|
254
|
+
- `@abide/abide/shared/log` — `log(...)` / `.warn` / `.error` / `.trace(label, fn)` / `.channel(name)`: request-scoped logger; TSV or JSON (`ABIDE_LOG_FORMAT`).
|
|
255
|
+
- `@abide/abide/shared/trace` — `trace()`: the current request's W3C `traceparent`, or `undefined` outside request scope; isomorphic.
|
|
264
256
|
|
|
265
|
-
###
|
|
257
|
+
### Plumbing — @documentation plumbing
|
|
266
258
|
|
|
267
|
-
- `@abide/abide/shared/createSubscriber` —
|
|
259
|
+
- `@abide/abide/shared/createSubscriber` — `createSubscriber(start)`: open-on-first-read / close-on-last-reader resource lifecycle on the signal core.
|
|
268
260
|
|
|
269
|
-
## UI surface — abide/ui
|
|
261
|
+
## UI surface — abide/ui/\* (client-only)
|
|
270
262
|
|
|
271
263
|
### Reactive state — @documentation reactive-state
|
|
272
264
|
|
|
273
|
-
- `@abide/abide/ui/scope` —
|
|
265
|
+
- `@abide/abide/ui/scope` — `scope(address?)`: resolve the lexical reactive scope; `.state` / `.computed` / `.linked` are the reactive cells (see grammar).
|
|
274
266
|
|
|
275
|
-
###
|
|
267
|
+
### Effect — @documentation effect
|
|
276
268
|
|
|
277
|
-
- `@abide/abide/ui/effect` —
|
|
269
|
+
- `@abide/abide/ui/effect` — `effect(fn)`: run now, re-run on dep change, optional teardown return; returns a disposer.
|
|
278
270
|
|
|
279
271
|
### Tail — @documentation tail
|
|
280
272
|
|
|
281
|
-
- `@abide/abide/ui/tail` — reactive
|
|
282
|
-
|
|
283
|
-
###
|
|
284
|
-
|
|
285
|
-
- `@abide/abide/ui/navigate` —
|
|
286
|
-
|
|
287
|
-
###
|
|
288
|
-
|
|
289
|
-
- `@abide/abide/ui/outbox` — durable FIFO mutation queue for local-first writes
|
|
290
|
-
|
|
291
|
-
###
|
|
292
|
-
|
|
293
|
-
- `@abide/abide/ui/
|
|
294
|
-
- `@abide/abide/ui/
|
|
295
|
-
- `@abide/abide/ui/
|
|
296
|
-
- `@abide/abide/ui/
|
|
297
|
-
- `@abide/abide/ui/
|
|
298
|
-
- `@abide/abide/ui/
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
- `@abide/abide/ui/dom/
|
|
306
|
-
- `@abide/abide/ui/dom/
|
|
307
|
-
- `@abide/abide/ui/dom/
|
|
308
|
-
- `@abide/abide/ui/dom/
|
|
309
|
-
- `@abide/abide/ui/dom/
|
|
310
|
-
- `@abide/abide/ui/dom/
|
|
311
|
-
- `@abide/abide/ui/dom/
|
|
312
|
-
- `@abide/abide/ui/dom/appendStatic` — a static text node,
|
|
313
|
-
- `@abide/abide/ui/dom/
|
|
314
|
-
- `@abide/abide/ui/dom/
|
|
315
|
-
- `@abide/abide/ui/dom/
|
|
316
|
-
- `@abide/abide/ui/dom/
|
|
317
|
-
- `@abide/abide/ui/dom/
|
|
318
|
-
- `@abide/abide/ui/dom/attr` — bind an element attribute to
|
|
319
|
-
- `@abide/abide/ui/dom/on` — attach an event listener
|
|
320
|
-
- `@abide/abide/ui/dom/attach` — run
|
|
321
|
-
- `@abide/abide/ui/dom/each` — keyed list binding
|
|
322
|
-
- `@abide/abide/ui/dom/eachAsync` — async keyed list
|
|
323
|
-
- `@abide/abide/ui/dom/when` — conditional binding
|
|
324
|
-
- `@abide/abide/ui/dom/awaitBlock` — async binding
|
|
325
|
-
- `@abide/abide/ui/dom/tryBlock` — synchronous error boundary
|
|
326
|
-
- `@abide/abide/ui/dom/switchBlock` — multi-branch binding
|
|
327
|
-
- `@abide/abide/ui/dom/applyResolved` — bundle-side consumer of
|
|
328
|
-
- `@abide/abide/ui/
|
|
329
|
-
- `@abide/abide/ui/
|
|
330
|
-
- `@abide/abide/ui/
|
|
331
|
-
- `@abide/abide/ui/
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
- `@abide/abide/
|
|
338
|
-
- `@abide/abide/
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
- `@abide/abide/
|
|
344
|
-
- `@abide/abide/
|
|
345
|
-
- `@abide/abide/
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
- `@abide/abide/
|
|
353
|
-
- `@abide/abide/bundle/
|
|
354
|
-
- `@abide/abide/bundle/
|
|
355
|
-
- `@abide/abide/bundle/
|
|
356
|
-
- `@abide/abide/bundle/
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
- `@abide/abide/
|
|
367
|
-
- `@abide/abide/
|
|
273
|
+
- `@abide/abide/ui/tail` — `tail(subscribable, opts?)`: reactive consumer of a `Socket<T>` or `fn.stream` result (latest-wins, or windowed via `{ last }`); seeds from retention; no-op on the server.
|
|
274
|
+
|
|
275
|
+
### Navigate — @documentation navigate
|
|
276
|
+
|
|
277
|
+
- `@abide/abide/ui/navigate` — `navigate(path, { replace?, keepScroll? })`: client navigation; writes history and re-mounts the page chain.
|
|
278
|
+
|
|
279
|
+
### UI — @documentation ui
|
|
280
|
+
|
|
281
|
+
- `@abide/abide/ui/outbox` — `outbox({ key, send, store, online, onDrop })`: durable FIFO mutation queue for local-first writes; drains while online, retries on reconnect, at-least-once.
|
|
282
|
+
|
|
283
|
+
### Plumbing — @documentation plumbing
|
|
284
|
+
|
|
285
|
+
- `@abide/abide/ui/enterScope` — `enterScope()`: open a fresh lexical scope for an SSR render; returns the previous to restore.
|
|
286
|
+
- `@abide/abide/ui/exitScope` — `exitScope(previous)`: restore the scope `enterScope` saved.
|
|
287
|
+
- `@abide/abide/ui/router` — `router(host, loaders, layoutLoaders, probe?)`: History-API router; diffs the layout/page chain on nav. Returns a disposer.
|
|
288
|
+
- `@abide/abide/ui/startClient` — `startClient(routes, layoutRoutes, target)`: official client entry; reads `__SSR__`, seeds cache, starts the router.
|
|
289
|
+
- `@abide/abide/ui/renderToStream` — `renderToStream(render)`: out-of-order SSR streaming; yields the shell, then one `<abide-resolve>` fragment per streaming await.
|
|
290
|
+
- `@abide/abide/ui/remoteProxy` — `remoteProxy(method, url)`: client substitute for a verb handler; identical `RemoteFunction` shape so `cache()` matches both sides.
|
|
291
|
+
- `@abide/abide/ui/socketProxy` — `socketProxy(name)`: client substitute for a server `Socket`; subscribes over the multiplexed ws channel.
|
|
292
|
+
- `@abide/abide/ui/dom/mount` — mount a top-level page/layout into a host under an ownership scope; returns a disposer.
|
|
293
|
+
- `@abide/abide/ui/dom/mountChild` — mount a child component as a marker-bounded range (no wrapper element); records the instance for hot reload.
|
|
294
|
+
- `@abide/abide/ui/dom/mergeProps` — compose child props from ordered layers (thunks, spreads, slot) via a Proxy; last layer wins.
|
|
295
|
+
- `@abide/abide/ui/dom/spreadProps` — wrap a `{...source}` spread so each key resolves to a live thunk.
|
|
296
|
+
- `@abide/abide/ui/dom/restProps` — the unconsumed rest of a component's props as a live, enumerable object.
|
|
297
|
+
- `@abide/abide/ui/dom/spreadAttrs` — spread an object onto a native element: `on*` keys as listeners, others as reactive attributes.
|
|
298
|
+
- `@abide/abide/ui/dom/readCall` — guarded reactive-doc method call with scope-path error messages.
|
|
299
|
+
- `@abide/abide/ui/dom/hydrate` — adopt server-rendered DOM, attaching listeners/effects in place with a claim cursor.
|
|
300
|
+
- `@abide/abide/ui/dom/text` — a text node whose content tracks `read()`.
|
|
301
|
+
- `@abide/abide/ui/dom/appendText` — reactive `{expr}` interpolation (escaped text, raw `html`, or snippet).
|
|
302
|
+
- `@abide/abide/ui/dom/appendTextAt` — reactive `{expr}` at a skeleton anchor comment, interleaved with element siblings.
|
|
303
|
+
- `@abide/abide/ui/dom/appendSnippet` — `{snippet(args)}` interpolation in a marker-bounded range; re-reads args reactively.
|
|
304
|
+
- `@abide/abide/ui/dom/appendStatic` — a static (non-reactive) text node, created or claimed from SSR.
|
|
305
|
+
- `@abide/abide/ui/dom/cloneStatic` — append a fully-static subtree by template clone (create) or claim (hydrate).
|
|
306
|
+
- `@abide/abide/ui/dom/skeleton` — realize a compiled skeleton under a parent; returns element holes (by path) and anchors (in order).
|
|
307
|
+
- `@abide/abide/ui/dom/anchorCursor` — position a skeleton-anchored control-flow block; parks the claim cursor (hydrate) or returns a create reference.
|
|
308
|
+
- `@abide/abide/ui/dom/mountSlot` — mount a component's `<slot>` content in a marker-bounded range (rendered once).
|
|
309
|
+
- `@abide/abide/ui/dom/outlet` — a layout's `<slot/>` outlet (comment-bounded boundary the router fills with the next layer).
|
|
310
|
+
- `@abide/abide/ui/dom/attr` — bind an element attribute to `read()` (boolean present/absent semantics).
|
|
311
|
+
- `@abide/abide/ui/dom/on` — attach an event listener pinned to its ownership scope.
|
|
312
|
+
- `@abide/abide/ui/dom/attach` — run a build-time attachment against an element with optional teardown.
|
|
313
|
+
- `@abide/abide/ui/dom/each` — keyed list binding; reconciles by key, reorders/re-keys in place; claims SSR rows on hydrate.
|
|
314
|
+
- `@abide/abide/ui/dom/eachAsync` — async keyed list over an `AsyncIterable`; rows append/reconcile as the iterator yields.
|
|
315
|
+
- `@abide/abide/ui/dom/when` — conditional binding; swaps the range on truthy↔falsy flips; adopts the server branch on hydrate.
|
|
316
|
+
- `@abide/abide/ui/dom/awaitBlock` — async binding (pending/then/catch); patches a re-settling `then` value in place rather than rebuilding.
|
|
317
|
+
- `@abide/abide/ui/dom/tryBlock` — synchronous error boundary; builds the catch subtree if the guarded one throws (rendered once).
|
|
318
|
+
- `@abide/abide/ui/dom/switchBlock` — multi-branch binding; picks the first matching case, else default; swaps on subject change.
|
|
319
|
+
- `@abide/abide/ui/dom/applyResolved` — bundle-side consumer of an SSR stream chunk; routes cache-seed/resolve frames into await boundaries.
|
|
320
|
+
- `@abide/abide/ui/runtime/escapeKey` — escape one object key into a JSON-Pointer token (`~`→`~0`, `/`→`~1`).
|
|
321
|
+
- `@abide/abide/ui/runtime/nextBlockId` — the next block id in the current render pass (await/try blocks, document order).
|
|
322
|
+
- `@abide/abide/ui/runtime/enterRenderPass` — mark entry into a render/mount pass; depth 0 resets the block-id counter.
|
|
323
|
+
- `@abide/abide/ui/runtime/exitRenderPass` — mark exit from a render/mount pass, unwinding the depth.
|
|
324
|
+
|
|
325
|
+
## Build / tooling
|
|
326
|
+
|
|
327
|
+
### Building — @documentation building
|
|
328
|
+
|
|
329
|
+
- `@abide/abide/build` — `build(opts)`: build the client bundle into `dist/_app` (optional gzip); returns success.
|
|
330
|
+
- `@abide/abide/compile` — `compile(opts)`: build a standalone server executable (runs the client build first); returns the binary path.
|
|
331
|
+
|
|
332
|
+
### Plumbing — @documentation plumbing
|
|
333
|
+
|
|
334
|
+
- `@abide/abide/preload` — the Bun plugin stack (`abideUiPlugin` + resolver) registered via `bunfig.toml` preload.
|
|
335
|
+
- `@abide/abide/resolver-plugin` — `abideResolverPlugin({ cwd, embedAssets, target })`: resolves the `abide:*` virtual modules and convention dirs.
|
|
336
|
+
- `@abide/abide/ui-plugin` — `abideUiPlugin`: Bun plugin that compiles `.abide` single-file components (with scoped CSS) to ES modules.
|
|
337
|
+
- `@abide/abide/tsconfig` — `tsconfig.app.json`: the app TypeScript config (ESNext, DOM lib, Bun types, strict, no-emit).
|
|
338
|
+
|
|
339
|
+
## Desktop bundle
|
|
340
|
+
|
|
341
|
+
### Bundle — @documentation bundle
|
|
342
|
+
|
|
343
|
+
- `@abide/abide/server/appDataDir` — `appDataDir()`: the running bundle's per-user data directory (keyed by injected program name; cwd-independent). Overridable via `ABIDE_DATA_DIR`.
|
|
344
|
+
- `@abide/abide/bundle/BundleWindow` — type of `src/bundle/window.ts`: window config (title, size, menu, `configSchema`).
|
|
345
|
+
- `@abide/abide/bundle/BundleMenu` — type of a top-level menu-bar menu (label + items).
|
|
346
|
+
- `@abide/abide/bundle/BundleMenuItem` — type of one menu entry (divider, emit event, or navigate URL).
|
|
347
|
+
- `@abide/abide/bundle/onMenu` — `onMenu(name?, handler)`: subscribe to bundle menu clicks (`abide:menu` CustomEvent).
|
|
348
|
+
- `@abide/abide/bundle/bundled` — `bundled()`: true when running inside the abide desktop bundle.
|
|
349
|
+
|
|
350
|
+
## MCP
|
|
351
|
+
|
|
352
|
+
### MCP — @documentation mcp
|
|
353
|
+
|
|
354
|
+
- `@abide/abide/mcp/createMcpServer` — `createMcpServer(opts)`: MCP server bound to the project registry; derives tools from verbs/sockets, handles auth.
|
|
355
|
+
|
|
356
|
+
### Prompts — @documentation plumbing
|
|
357
|
+
|
|
358
|
+
- `@abide/abide/server/prompts/definePrompt` — `definePrompt(name, opts)`: build a `Prompt` from an `src/mcp/prompts/*.md` file (the bundler emits the call).
|
|
359
|
+
- `@abide/abide/server/prompts/renderPromptTemplate` — `renderPromptTemplate(template, args)`: substitute `{{name}}` placeholders (missing → empty string).
|
|
360
|
+
|
|
361
|
+
## Testing
|
|
362
|
+
|
|
363
|
+
### Testing — @documentation testing
|
|
364
|
+
|
|
365
|
+
- `@abide/abide/test/createTestApp` — `createTestApp(opts)`: in-memory test server with a typed `app.rpc.<verb>` / `app.sockets.<name>` surface.
|
|
366
|
+
|
|
367
|
+
### Plumbing — @documentation plumbing
|
|
368
|
+
|
|
369
|
+
- `@abide/abide/test/createScriptedSurface` — `createScriptedSurface(tools)`: a scripted `AgentSurface` for engine tests (records calls, stubs results).
|
|
370
|
+
- `@abide/abide/test/assertAgentFrameConformance` — `assertAgentFrameConformance(stream)`: assert engine frame-stream invariants (done frame, tool use/result pairing).
|
|
368
371
|
|
|
369
372
|
## Generated machine surfaces
|
|
370
373
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
|
374
|
-
|
|
|
375
|
-
| `/
|
|
376
|
-
| `/__abide/
|
|
377
|
-
| `/__abide/
|
|
378
|
-
| `/__abide/
|
|
379
|
-
| `/__abide/
|
|
374
|
+
Runtime routes the framework serves:
|
|
375
|
+
|
|
376
|
+
| Route | Serves |
|
|
377
|
+
| -------------------- | ----------------------------------------------------------------------------------------- |
|
|
378
|
+
| `/openapi.json` | OpenAPI document for the `/rpc/*` HTTP surface. |
|
|
379
|
+
| `/__abide/mcp` | MCP endpoint (POST) routed to `createMcpServer`. |
|
|
380
|
+
| `/__abide/health` | Unauthenticated health payload (`reachable` + `src/app.ts` `health` fields). |
|
|
381
|
+
| `/__abide/sockets` | WebSocket multiplex for every declared socket; `/<name>` adds the HTTP tail/publish face. |
|
|
382
|
+
| `/__abide/cli` | CLI download (`/<platform>`): gzipped tarball with the thin binary + `.env`. |
|
|
383
|
+
| `/__abide/hot/<id>` | Dev-only hot-module endpoint for edited `.abide` components. |
|
|
384
|
+
| `/__abide/identity` | Server identity (app name + version) for CLI connectivity probes. |
|
|
385
|
+
| `/__abide/inspector` | Inspector UI, gated by `ABIDE_ENABLE_INSPECTOR` and the installed package. |
|
|
380
386
|
|
|
381
387
|
## Environment variables
|
|
382
388
|
|
|
383
|
-
| Variable
|
|
384
|
-
|
|
|
385
|
-
| `PORT`
|
|
386
|
-
| `APP_URL`
|
|
387
|
-
| `ABIDE_APP_URL`
|
|
388
|
-
| `ABIDE_APP_TOKEN`
|
|
389
|
-
| `ABIDE_CLIENT_TIMEOUT`
|
|
390
|
-
| `ABIDE_MAX_REQUEST_BODY_SIZE` | Server-wide request body ceiling
|
|
391
|
-
| `ABIDE_IDLE_TIMEOUT`
|
|
392
|
-
| `
|
|
393
|
-
| `
|
|
394
|
-
| `
|
|
395
|
-
| `ABIDE_LOG_FORMAT`
|
|
396
|
-
| `DEBUG`
|
|
397
|
-
| `ABIDE_ENABLE_INSPECTOR`
|
|
398
|
-
| `ABIDE_INSPECT`
|
|
389
|
+
| Variable | Effect |
|
|
390
|
+
| ----------------------------- | --------------------------------------------------------------------------------------------- |
|
|
391
|
+
| `PORT` | Port the server binds (scans upward from the default if taken). |
|
|
392
|
+
| `APP_URL` | Request origin the CLI download writes into the downloaded `.env` (`ABIDE_APP_URL`). |
|
|
393
|
+
| `ABIDE_APP_URL` | Server URL baked into a CLI binary at build time; runtime-overridable. |
|
|
394
|
+
| `ABIDE_APP_TOKEN` | Bearer token written into the CLI download's `.env` when the request carries `Authorization`. |
|
|
395
|
+
| `ABIDE_CLIENT_TIMEOUT` | Client-side RPC fetch timeout in ms (1–600000); shipped via `__SSR__`. |
|
|
396
|
+
| `ABIDE_MAX_REQUEST_BODY_SIZE` | Server-wide request body ceiling in bytes. |
|
|
397
|
+
| `ABIDE_IDLE_TIMEOUT` | Per-connection idle timeout in seconds (0–255, default 10); streaming opts out. |
|
|
398
|
+
| `ABIDE_REACHABLE_TIMEOUT` | `reachable()` probe timeout in ms (100–60000, default 3000). |
|
|
399
|
+
| `ABIDE_REACHABLE_TTL` | `reachable()` poll cadence / freshness in ms (1000–600000, default 30000). |
|
|
400
|
+
| `ABIDE_DATA_DIR` | Override for the app data directory (used as-is, no program name appended). |
|
|
401
|
+
| `ABIDE_LOG_FORMAT` | `json` for one JSON object per line; default is tab-separated. |
|
|
402
|
+
| `DEBUG` | Diagnostic channel gate (e.g. `DEBUG=abide:*` or `abide:build`). |
|
|
403
|
+
| `ABIDE_ENABLE_INSPECTOR` | `true` activates the optional inspector. |
|
|
404
|
+
| `ABIDE_INSPECT` | Enable DevTools inspection in a desktop bundle's webview. |
|
|
399
405
|
|
|
400
406
|
---
|
|
401
407
|
|
|
402
|
-
|
|
403
|
-
`bun run packages/abide/scripts/readmeSurfaces.ts` and update
|
|
408
|
+
This map mirrors `package.json` `exports`. After adding or renaming an export,
|
|
409
|
+
run `bun run packages/abide/scripts/readmeSurfaces.ts` and update the matching
|
|
410
|
+
bullet here.
|