@cfbender/cesium 0.3.5
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/ARCHITECTURE.md +304 -0
- package/CHANGELOG.md +335 -0
- package/LICENSE +21 -0
- package/README.md +479 -0
- package/agents/cesium.md +39 -0
- package/assets/styleguide.html +857 -0
- package/package.json +61 -0
- package/src/cli/commands/ls.ts +186 -0
- package/src/cli/commands/open.ts +208 -0
- package/src/cli/commands/prune.ts +348 -0
- package/src/cli/commands/restart.ts +38 -0
- package/src/cli/commands/serve.ts +214 -0
- package/src/cli/commands/stop.ts +130 -0
- package/src/cli/commands/theme.ts +333 -0
- package/src/cli/index.ts +78 -0
- package/src/config.ts +94 -0
- package/src/index.ts +35 -0
- package/src/prompt/system-fragment.md +97 -0
- package/src/render/client-js.ts +316 -0
- package/src/render/controls.ts +302 -0
- package/src/render/critique.ts +360 -0
- package/src/render/extract.ts +83 -0
- package/src/render/scrub.ts +141 -0
- package/src/render/theme.ts +712 -0
- package/src/render/validate.ts +524 -0
- package/src/render/wrap.ts +165 -0
- package/src/server/api.ts +166 -0
- package/src/server/http.ts +195 -0
- package/src/server/lifecycle.ts +331 -0
- package/src/server/stop.ts +124 -0
- package/src/storage/index-cache.ts +71 -0
- package/src/storage/index-gen.ts +447 -0
- package/src/storage/lock.ts +108 -0
- package/src/storage/mutate.ts +396 -0
- package/src/storage/paths.ts +159 -0
- package/src/storage/project-summaries.ts +19 -0
- package/src/storage/theme-write.ts +19 -0
- package/src/storage/write.ts +75 -0
- package/src/tools/ask.ts +353 -0
- package/src/tools/critique.ts +66 -0
- package/src/tools/publish.ts +404 -0
- package/src/tools/stop.ts +53 -0
- package/src/tools/styleguide.ts +23 -0
- package/src/tools/wait.ts +192 -0
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Cesium is an opencode plugin that converts substantive agent responses into self-contained
|
|
4
|
+
HTML artifacts stored on disk and served locally. This document describes the architectural
|
|
5
|
+
decisions made for v1.
|
|
6
|
+
|
|
7
|
+
**Status: v0.3.0 shipped.** See [`CHANGELOG.md`](CHANGELOG.md) for release notes.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Vision
|
|
12
|
+
|
|
13
|
+
When the agent produces something worth keeping — a plan, comparison, code review, audit,
|
|
14
|
+
explainer, or RFC — it generates a beautiful `.html` file instead of printing markdown to
|
|
15
|
+
the terminal. The artifact lives in `~/.local/state/cesium/` and can be opened in a browser,
|
|
16
|
+
shared over SSH, or archived as-is. The terminal remains the control surface. Each artifact
|
|
17
|
+
is 100% self-contained: no external stylesheets, no CDN scripts, no network required to view.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Trigger model
|
|
22
|
+
|
|
23
|
+
Cesium is **agent-decided via tool call**, not automatic on every response. The plugin
|
|
24
|
+
injects a ~40-line system-prompt fragment (~600 tokens) into every agent session that
|
|
25
|
+
describes when to publish vs. stay in the terminal.
|
|
26
|
+
|
|
27
|
+
**Publish heuristics (baked into the injected prompt):**
|
|
28
|
+
|
|
29
|
+
- Response would be >= ~400 words, OR
|
|
30
|
+
- Contains a comparison, decision matrix, or multi-section plan/PRD/RFC, OR
|
|
31
|
+
- A code review with more than 3 findings, OR
|
|
32
|
+
- Anything the user is likely to revisit or share.
|
|
33
|
+
|
|
34
|
+
**Stay in terminal:**
|
|
35
|
+
|
|
36
|
+
- Direct factual question, short status update, mid-tool-loop chatter.
|
|
37
|
+
|
|
38
|
+
**User override always wins:** `/cesium`, "publish this", "make me an HTML report" force
|
|
39
|
+
publish; "just tell me", "in terminal" suppress it.
|
|
40
|
+
|
|
41
|
+
**Tie-breaker:** when uncertain, publish and emit a 2-3 line terminal summary.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Tool surface
|
|
46
|
+
|
|
47
|
+
Two tools are registered by the plugin:
|
|
48
|
+
|
|
49
|
+
### `cesium_publish` (primary)
|
|
50
|
+
|
|
51
|
+
Accepts the body HTML and metadata for one artifact. The plugin owns the full HTML shell:
|
|
52
|
+
`<!doctype html>`, `<head>`, the inlined CSS framework, embedded metadata, and the footer
|
|
53
|
+
with revision links. The agent writes only the `<body>` inner HTML.
|
|
54
|
+
|
|
55
|
+
Input fields:
|
|
56
|
+
|
|
57
|
+
- `title` (string, required)
|
|
58
|
+
- `kind` — `"plan" | "review" | "comparison" | "report" | "explainer" | "design" | "audit" | "rfc" | "other"`
|
|
59
|
+
- `html` — body inner HTML
|
|
60
|
+
- `summary` — optional 1-2 line terminal blurb
|
|
61
|
+
- `tags` — optional string array
|
|
62
|
+
- `supersedes` — optional id of artifact this revises
|
|
63
|
+
|
|
64
|
+
Returns: `{ id, filePath, fileUrl, httpUrl, indexUrl }`
|
|
65
|
+
|
|
66
|
+
### `cesium_styleguide` (on-demand reference)
|
|
67
|
+
|
|
68
|
+
Returns the full CSS reference page as a string. Called by the agent before starting a
|
|
69
|
+
complex artifact. Kept separate to avoid bloating every tool call.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## HTML generation strategy
|
|
74
|
+
|
|
75
|
+
**Approach:** shared inline CSS framework + agent-written semantic HTML.
|
|
76
|
+
|
|
77
|
+
The plugin injects a known-good `<style>` block (~3kb) into every artifact. The agent
|
|
78
|
+
composes content using a named class vocabulary (documented in the tool description and
|
|
79
|
+
retrievable via `cesium_styleguide`). The agent may also use inline `style="..."` and
|
|
80
|
+
inline `<svg>` for bespoke diagrams.
|
|
81
|
+
|
|
82
|
+
**Strict portability rule:** no external resources. The scrub pass strips or rewrites:
|
|
83
|
+
|
|
84
|
+
- `<link rel="stylesheet" href="...">` — removed, comment left
|
|
85
|
+
- `<script src="...">` — removed, comment left
|
|
86
|
+
- `url(https://...)` in style — removed
|
|
87
|
+
- `<img src="http...">` — removed, comment left
|
|
88
|
+
|
|
89
|
+
Broken or unparseable HTML is tolerated: the file is written anyway with a warning banner
|
|
90
|
+
prepended. Validation errors (missing title, empty html, invalid kind) are caught before
|
|
91
|
+
write and returned as tool errors.
|
|
92
|
+
|
|
93
|
+
**Color tokens (default theme):**
|
|
94
|
+
|
|
95
|
+
| Token | Value | Role |
|
|
96
|
+
| ------------- | --------- | --------------------- |
|
|
97
|
+
| `--bg` | `#FAF9F5` | ivory page background |
|
|
98
|
+
| `--surface` | `#FFFFFF` | card/panel surface |
|
|
99
|
+
| `--surface-2` | `#F0EEE6` | secondary surface |
|
|
100
|
+
| `--oat` | `#E3DACC` | muted border fill |
|
|
101
|
+
| `--rule` | `#D1CFC5` | rule / divider |
|
|
102
|
+
| `--ink` | `#141413` | primary text |
|
|
103
|
+
| `--ink-soft` | `#3D3D3A` | secondary text |
|
|
104
|
+
| `--muted` | `#87867F` | placeholder / caption |
|
|
105
|
+
| `--accent` | `#D97757` | clay — callout/link |
|
|
106
|
+
| `--olive` | `#788C5D` | sage — success |
|
|
107
|
+
| `--code-bg` | `#141413` | code panel bg |
|
|
108
|
+
| `--code-fg` | `#E8E6DE` | code panel fg |
|
|
109
|
+
|
|
110
|
+
User theme overrides: `~/.config/opencode/cesium.json` → `theme` field (per-token overrides
|
|
111
|
+
stack on top of the active preset). Four named presets are shipped (`warm`, `cool`, `mono`,
|
|
112
|
+
`paper`) selectable via `themePreset` — see README for the full preset reference.
|
|
113
|
+
|
|
114
|
+
**Type stack:** system fonts only (`ui-serif`, `system-ui`, `ui-monospace`) — strict
|
|
115
|
+
portability requires no remote font loads.
|
|
116
|
+
|
|
117
|
+
**Named component classes the agent uses:**
|
|
118
|
+
`.eyebrow`, `.h-display`, `.h-section`, `.section-num`, `.card`, `.tldr`, `.callout`,
|
|
119
|
+
`.code`, `.timeline`, `.diagram`, `.compare-table`, `.risk-table`, `.kbd`, `.pill`,
|
|
120
|
+
`.tag`, `.byline`
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Storage layout
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
~/.local/state/cesium/
|
|
128
|
+
├── index.html # global cross-project index
|
|
129
|
+
├── index.json # global cache (rebuilt on every publish)
|
|
130
|
+
└── projects/
|
|
131
|
+
└── <project-slug>/
|
|
132
|
+
├── index.html # per-project index
|
|
133
|
+
├── index.json # per-project cache
|
|
134
|
+
└── artifacts/
|
|
135
|
+
├── 2026-05-11T14-22-09Z__plan-auth-rewrite__a7K9pQ.html
|
|
136
|
+
└── ...
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Project slug derivation (priority order):**
|
|
140
|
+
|
|
141
|
+
1. Git remote `origin`, normalized: `github-com-cfb-cesium`
|
|
142
|
+
2. `<cwd-basename>-<6char-hash-of-absolute-path>` — prevents collisions when multiple repos
|
|
143
|
+
share the same basename
|
|
144
|
+
|
|
145
|
+
**Worktrees** of one repo merge into one project directory. Branch is captured in artifact
|
|
146
|
+
metadata, not in the path.
|
|
147
|
+
|
|
148
|
+
**Filename:** `<iso-utc-timestamp>__<title-slug>__<6char-nanoid>.html`
|
|
149
|
+
Sortable, greppable, human-readable, collision-resistant.
|
|
150
|
+
|
|
151
|
+
**Metadata: dual-source.**
|
|
152
|
+
Each artifact embeds a `<script type="application/json" id="cesium-meta">` block — the
|
|
153
|
+
source of truth. The artifact is 100% self-contained; metadata travels with the file.
|
|
154
|
+
`index.json` is a derived cache rebuilt on every publish (not the authoritative store).
|
|
155
|
+
|
|
156
|
+
**Metadata fields:** `id`, `title`, `kind`, `summary`, `tags`, `createdAt`, `model`,
|
|
157
|
+
`sessionId`, `projectSlug`, `projectName`, `cwd`, `worktree`, `gitBranch`, `gitCommit`,
|
|
158
|
+
`supersedes?`, `supersededBy?`, `contentSha256`
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Index & serving
|
|
163
|
+
|
|
164
|
+
**Index:** per-project and global `index.html` regenerated atomically on every publish.
|
|
165
|
+
Lists artifacts grouped by week, with kind filter chips, inline title search (tiny inline
|
|
166
|
+
JS), and revision-chain collapsing (latest version visible by default). Pre-rendered — works
|
|
167
|
+
without the server (archivable, rsync-friendly).
|
|
168
|
+
|
|
169
|
+
**Server:** lazy auto-start, single global process, port 3030 (increments to 3031..3050 if
|
|
170
|
+
busy).
|
|
171
|
+
|
|
172
|
+
- Bun HTTP server bound to `127.0.0.1:3030`, rooted at `~/.local/state/cesium/`.
|
|
173
|
+
- Starts on first publish in an opencode session.
|
|
174
|
+
- Idle-shuts after 30 minutes of no requests (configurable via `cesium.json`).
|
|
175
|
+
- PID file at `~/.local/state/cesium/.server.pid`. Stale PID detected and cleared on startup.
|
|
176
|
+
- SIGTERM handler for clean shutdown.
|
|
177
|
+
- SSH detection: if `$SSH_CONNECTION` is set, publish output reminds the user to forward
|
|
178
|
+
the port. Server does NOT bind to `0.0.0.0` by default.
|
|
179
|
+
|
|
180
|
+
**Terminal output after publish:**
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
Cesium · Auth design (plan)
|
|
184
|
+
http://localhost:3030/projects/github-com-cfb-cesium/artifacts/...
|
|
185
|
+
file:///Users/cfb/.local/state/cesium/...
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Revision chains
|
|
191
|
+
|
|
192
|
+
When `cesium_publish` receives a `supersedes` id:
|
|
193
|
+
|
|
194
|
+
1. New artifact is written with `supersedes` populated.
|
|
195
|
+
2. Previous artifact's embedded metadata is patched in-place: `supersededBy` field added.
|
|
196
|
+
Visual content is untouched.
|
|
197
|
+
3. Index renders the chain: "v3 of auth design (revises v2, v1)".
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Interactive artifacts (v0.3.0)
|
|
202
|
+
|
|
203
|
+
### The artifact-as-UI insight
|
|
204
|
+
|
|
205
|
+
In v0.3.0, `ask`-kind artifacts collapse the "publish" and "interactive UI" pipelines
|
|
206
|
+
into one. The artifact file IS the form. Inline JS POSTs individual answers to the
|
|
207
|
+
cesium HTTP server; the server mutates the file on disk atomically; once all required
|
|
208
|
+
questions are answered the status transitions to `"complete"` and the controls freeze
|
|
209
|
+
into a static answered record. The same `.html` file is the form, the live conversation,
|
|
210
|
+
and the permanent record — no separate UI, no database, no websocket.
|
|
211
|
+
|
|
212
|
+
### Storage
|
|
213
|
+
|
|
214
|
+
`ask`-kind artifacts carry an `interactive` field in the embedded
|
|
215
|
+
`<script type="application/json" id="cesium-meta">` block. Shape:
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
type InteractiveData = {
|
|
219
|
+
status: "open" | "complete" | "expired" | "cancelled";
|
|
220
|
+
requireAll: boolean;
|
|
221
|
+
expiresAt: string; // ISO-8601
|
|
222
|
+
questions: Question[];
|
|
223
|
+
answers: Record<string, { value: AnswerValue; answeredAt: string }>;
|
|
224
|
+
completedAt?: string;
|
|
225
|
+
};
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The same atomic-write + `index.json` cache pattern as publish artifacts applies.
|
|
229
|
+
`src/storage/mutate.ts` owns the read-mutate-write cycle for interactive artifacts.
|
|
230
|
+
|
|
231
|
+
### Transport
|
|
232
|
+
|
|
233
|
+
Answer submission:
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
POST /api/sessions/<projectSlug>/<filename>/answers/<questionId>
|
|
237
|
+
Body: { "value": <AnswerValue> }
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
State query:
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
GET /api/sessions/<projectSlug>/<filename>/state
|
|
244
|
+
Response: { status, remaining, answers }
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The server uses `withLock` on `<artifactPath>.lock` for all read-mutate-write
|
|
248
|
+
operations — the same lock primitive used by the index.
|
|
249
|
+
|
|
250
|
+
### Tools
|
|
251
|
+
|
|
252
|
+
- **`cesium_ask`** — validates input, builds the interactive artifact, writes it to
|
|
253
|
+
disk, starts the server, and returns `{ id, filePath, fileUrl, httpUrl }`.
|
|
254
|
+
- **`cesium_wait`** — polls disk every 500 ms, reading the artifact's embedded
|
|
255
|
+
`interactive.status`. Returns the full `answers` map once status is non-`"open"`.
|
|
256
|
+
No subagents, no WebSockets — pure polling, pure HTTP.
|
|
257
|
+
|
|
258
|
+
### Question types (v0.3.0)
|
|
259
|
+
|
|
260
|
+
Six types ship in v0.3.0: `pick_one`, `pick_many`, `confirm`, `ask_text`, `slider`,
|
|
261
|
+
`react`. Branching logic, ranking, and file/image inputs are deferred.
|
|
262
|
+
|
|
263
|
+
Each type has a corresponding control renderer in `src/render/controls.ts` that
|
|
264
|
+
produces the interactive HTML, and an answered renderer (`renderAnswered`) that
|
|
265
|
+
produces the frozen read-only record once an answer is recorded.
|
|
266
|
+
|
|
267
|
+
### Lifecycle
|
|
268
|
+
|
|
269
|
+
Status transitions: `open` → `complete` (all required answers received) or
|
|
270
|
+
`open` → `expired` (server-side check on `expiresAt`) or `open` → `cancelled`
|
|
271
|
+
(explicit cancellation via API).
|
|
272
|
+
|
|
273
|
+
Once status is non-`"open"`, `wrapDocument` omits the inline
|
|
274
|
+
`<script data-cesium-client>` tag entirely, so the file loads without any interactive
|
|
275
|
+
overhead. Controls render as `.cs-answered` read-only markup.
|
|
276
|
+
|
|
277
|
+
### CSS additions
|
|
278
|
+
|
|
279
|
+
`src/render/theme.ts` → `frameworkRulesCss()` gained ~210 lines of `.cs-*` rules:
|
|
280
|
+
|
|
281
|
+
- `.cs-questions` — container
|
|
282
|
+
- `.cs-question` — individual question block
|
|
283
|
+
- `.cs-control` — wraps each input widget
|
|
284
|
+
- `.cs-answered` — frozen answer display
|
|
285
|
+
- `.cs-banner` / `.cs-banner-offline` / `.cs-banner-ended` — status banners
|
|
286
|
+
- Per-type modifiers: `.cs-pick`, `.cs-confirm`, `.cs-slider`, `.cs-text`, `.cs-react`
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## v1 build phases
|
|
291
|
+
|
|
292
|
+
| Phase | Scope | Status |
|
|
293
|
+
| ----- | ---------------------------------------------------------------------------------- | ------- |
|
|
294
|
+
| 0 | Scaffolding, configs, docs, empty stubs | shipped |
|
|
295
|
+
| 1 | Storage + render core (paths, write, theme, wrap, scrub, validate) | shipped |
|
|
296
|
+
| 2 | `cesium_publish` + `cesium_styleguide` tools, plugin entry, system prompt fragment | shipped |
|
|
297
|
+
| 3 | Per-project + global `index.html` generation, file lock, revision chains | shipped |
|
|
298
|
+
| 4 | Lazy auto-server, port-scan, idle shutdown, SSH detection | shipped |
|
|
299
|
+
| 5 | Reference examples, dedicated agent definition, release polish | shipped |
|
|
300
|
+
| A | Interactive artifact types + `cesium_ask` tool | shipped |
|
|
301
|
+
| B | Answer submission API (`/api/sessions/…/answers/:qid`) + per-artifact file lock | shipped |
|
|
302
|
+
| C | `cesium_wait` polling tool + client JS answer submission | shipped |
|
|
303
|
+
| D | Interactive lifecycle (status transitions, expiry, freeze) | shipped |
|
|
304
|
+
| E | `buildProjectSummaries` refactor, `examples/ask.html`, docs, v0.3.0 release | shipped |
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## v0.3.5 — 2026-05-11
|
|
4
|
+
|
|
5
|
+
Fixes the `Publish to npm` GitHub Action.
|
|
6
|
+
|
|
7
|
+
- **fix:** Workflow now uses Node 24 (which ships with npm 11+, required for
|
|
8
|
+
the OIDC trusted-publisher flow). The previous attempt used Node 22 plus an
|
|
9
|
+
explicit `npm install -g npm@latest` step, which hit a `MODULE_NOT_FOUND`
|
|
10
|
+
on `promise-retry` in the runner's pre-cached npm. Bundled npm 11 from
|
|
11
|
+
Node 24 sidesteps the upgrade step entirely.
|
|
12
|
+
|
|
13
|
+
## v0.3.4 — 2026-05-11
|
|
14
|
+
|
|
15
|
+
Smoke test for the npm publish GitHub Action (OIDC trusted-publisher flow).
|
|
16
|
+
First release published from CI.
|
|
17
|
+
|
|
18
|
+
- **fix:** Removed `publishConfig.provenance: true` from `package.json`. The
|
|
19
|
+
field forces `--provenance` even on local publishes, where it fails with
|
|
20
|
+
`Automatic provenance generation not supported for provider: null`. The
|
|
21
|
+
GitHub Action passes `--provenance` explicitly, so CI publishes still
|
|
22
|
+
ship with an npm provenance attestation.
|
|
23
|
+
- **docs:** Bootstrap step in README "Releasing" no longer passes
|
|
24
|
+
`--provenance` (it can't work locally).
|
|
25
|
+
|
|
26
|
+
## v0.3.3 — 2026-05-11
|
|
27
|
+
|
|
28
|
+
First release published to npm as **`@cfbender/cesium`**. No runtime behavior
|
|
29
|
+
changes; only packaging and release infrastructure.
|
|
30
|
+
|
|
31
|
+
- **packaging:** Renamed package from `cesium` to `@cfbender/cesium` (scoped,
|
|
32
|
+
public). Install with `bun install -g @cfbender/cesium`. Old git-URL installs
|
|
33
|
+
still work but will fall behind.
|
|
34
|
+
- **packaging:** Added explicit `files` allowlist to package.json — the
|
|
35
|
+
published tarball ships `src/`, `assets/styleguide.html`, `agents/`, and
|
|
36
|
+
`ARCHITECTURE.md` only. Tests, examples, scripts, design specs, and the
|
|
37
|
+
README demo video are excluded.
|
|
38
|
+
- **packaging:** `engines.bun >= 1.0.0` declared (cesium runs TS directly via
|
|
39
|
+
Bun; the CLI's `#!/usr/bin/env bun` shebang requires Bun on `PATH`).
|
|
40
|
+
- **packaging:** `prepublishOnly` runs `typecheck` + `test` before publish.
|
|
41
|
+
- **packaging:** `publishConfig.access = "public"` and
|
|
42
|
+
`publishConfig.provenance = true` so scoped publishes work and ship with
|
|
43
|
+
npm provenance attestations.
|
|
44
|
+
- **ci:** New `.github/workflows/publish.yml`. Triggers on `v*` tag push,
|
|
45
|
+
runs typecheck + tests, verifies tag-vs-package-version match, then
|
|
46
|
+
`npm publish --access public --provenance` via npm's **Trusted Publisher
|
|
47
|
+
OIDC flow** — no `NPM_TOKEN` secret required. The first release is
|
|
48
|
+
published manually so the package exists on the registry; subsequent
|
|
49
|
+
releases are tag-triggered. See README "Releasing" for the bootstrap.
|
|
50
|
+
- **docs:** README install section rewritten around the npm package; mise /
|
|
51
|
+
`bun update -g` upgrade flows documented; trusted-publisher bootstrap +
|
|
52
|
+
release-via-tag flow documented.
|
|
53
|
+
|
|
54
|
+
## v0.3.2 — 2026-05-11
|
|
55
|
+
|
|
56
|
+
Quality-of-life patch focused on `cesium serve` reliability and README polish.
|
|
57
|
+
|
|
58
|
+
- **fix:** `cesium serve` no longer auto-shuts-down on idle. The configured
|
|
59
|
+
`idleTimeoutMs` exists for the plugin's lazy-started server and was being
|
|
60
|
+
unintentionally applied to foreground `cesium serve`, killing the process
|
|
61
|
+
unexpectedly. Foreground serve now runs until SIGINT/SIGTERM by default.
|
|
62
|
+
- **new:** `cesium serve --idle-timeout DUR` opts back into auto-shutdown.
|
|
63
|
+
Accepts plain milliseconds or a suffixed duration (`90s`, `30m`, `2h`).
|
|
64
|
+
Use `0`, `never`, or `off` to disable explicitly.
|
|
65
|
+
- **internal:** `lifecycle.startIdleTimer` now treats `idleTimeoutMs <= 0` as
|
|
66
|
+
"never time out" and skips creating the interval.
|
|
67
|
+
- **docs:** README demo asset (`assets/cesium.mp4`, ~600 KB, 720px wide)
|
|
68
|
+
embedded near the top via a `<video>` tag.
|
|
69
|
+
- **docs:** New "Common workflows" section in the README covering forced
|
|
70
|
+
publish, finding/opening artifacts, sharing, pruning, theme changes,
|
|
71
|
+
server restart, and Q&A loops.
|
|
72
|
+
- **docs:** Acknowledgements section added.
|
|
73
|
+
- **tests:** 889 → 906 (+9 serve-arg parser tests, +2 lifecycle tests for
|
|
74
|
+
the `idleTimeoutMs <= 0` path; the previously-skipped flaky idle-timer
|
|
75
|
+
test was preserved).
|
|
76
|
+
|
|
77
|
+
## v0.3.1 — 2026-05-11
|
|
78
|
+
|
|
79
|
+
Small quality-of-life patch. The only user-visible change is the Skip button on
|
|
80
|
+
optional `ask_text` questions; all other v0.3.0 behavior is unchanged.
|
|
81
|
+
|
|
82
|
+
- **new:** `optional?: boolean` field on `ask_text` questions (default `false`).
|
|
83
|
+
When `true`, the server accepts an empty-string answer (skipped), and the
|
|
84
|
+
answered section renders a muted "(skipped)" placeholder instead of a blockquote.
|
|
85
|
+
- **new:** Skip button rendered alongside Submit for optional ask_text controls
|
|
86
|
+
(`class="cs-skip"`), wrapped in a `class="cs-button-row"` flex container.
|
|
87
|
+
- **new:** Client JS `cs-skip` click handler — POSTs `{ type: "ask_text", text: "" }`
|
|
88
|
+
via the same `submitAnswer` path as Submit.
|
|
89
|
+
- **examples:** `ask.html` "constraints" question is now `optional: true` — showcases
|
|
90
|
+
the Skip button.
|
|
91
|
+
- **tests:** 870 → 889 (+19 new tests across validate, mutate, controls, client-js,
|
|
92
|
+
theme, system-fragment).
|
|
93
|
+
|
|
94
|
+
## v0.3.0 — 2026-05-11
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
|
|
98
|
+
- **`cesium_ask`** — publish an interactive Q&A artifact and return its URL. The
|
|
99
|
+
agent calls this when it needs structured input before producing a final artifact:
|
|
100
|
+
design tradeoffs, plan choices, confirmation gates. Returns `{ id, filePath, fileUrl, httpUrl }`.
|
|
101
|
+
|
|
102
|
+
- **`cesium_wait`** — block until the user finishes answering all required questions.
|
|
103
|
+
Polls disk every 500 ms reading the artifact's embedded `interactive.status`. Returns
|
|
104
|
+
the full `answers` map once complete, expired, or cancelled.
|
|
105
|
+
|
|
106
|
+
- **New artifact kind: `"ask"`** — interactive Q&A artifacts. A single self-contained
|
|
107
|
+
`.html` file that embeds the question form, client JS, and answers. Server-mutated
|
|
108
|
+
atomically on each answer; crystallizes into a permanent static record once complete.
|
|
109
|
+
The same file is the form, the live session, and the archive.
|
|
110
|
+
|
|
111
|
+
- **Six question types:** `pick_one` (radio group + recommended), `pick_many`
|
|
112
|
+
(checkbox group + min/max), `confirm` (yes/no with custom labels), `ask_text`
|
|
113
|
+
(free-text, optional multiline), `slider` (numeric range), `react` (thumbs reaction
|
|
114
|
+
with optional comment).
|
|
115
|
+
|
|
116
|
+
- **Server: new `/api/*` routes** — `POST /api/sessions/<slug>/<file>/answers/<qid>`
|
|
117
|
+
submits an individual answer; `GET /api/sessions/<slug>/<file>/state` returns current
|
|
118
|
+
status and remaining question ids. Per-artifact file lock (`<artifactPath>.lock`).
|
|
119
|
+
|
|
120
|
+
- **`examples/ask.html`** — baked demo artifact demonstrating all six question types
|
|
121
|
+
in `status: "open"` state. Open in browser to see the controls.
|
|
122
|
+
|
|
123
|
+
### Changed
|
|
124
|
+
|
|
125
|
+
- **Storage:** new `src/storage/mutate.ts` — atomic read-mutate-write for interactive
|
|
126
|
+
artifacts. New `src/storage/project-summaries.ts` — `buildProjectSummaries` extracted
|
|
127
|
+
from `publish.ts` and `ask.ts` into a shared module (no behavior change).
|
|
128
|
+
|
|
129
|
+
- **Render:** new `src/render/controls.ts` (question control + answered renderers) and
|
|
130
|
+
`src/render/client-js.ts` (~309-line inline JS bundle for answer POSTing and UI state).
|
|
131
|
+
~210 new `.cs-*` CSS rules in `frameworkRulesCss()`.
|
|
132
|
+
|
|
133
|
+
- **Tests:** 863 → 870 (commit 1 refactor: +7 project-summaries tests). Full suite: 870
|
|
134
|
+
pass (+281 new tests since v0.2.4).
|
|
135
|
+
|
|
136
|
+
## v0.2.4 — 2026-05-11
|
|
137
|
+
|
|
138
|
+
### Added
|
|
139
|
+
|
|
140
|
+
- `cesium --version` / `cesium -v` / `cesium version` — print the installed
|
|
141
|
+
version. Useful for confirming what's actually running after an upgrade.
|
|
142
|
+
|
|
143
|
+
### Changed
|
|
144
|
+
|
|
145
|
+
- `claret-dark` code panels now render at `surface2` (`#2B1F22`) instead of
|
|
146
|
+
recessed `#0F0509`. The recessed value gave only ~9 luminance points of
|
|
147
|
+
contrast against the page bg; the elevated value reads cleanly.
|
|
148
|
+
|
|
149
|
+
## v0.2.3 — 2026-05-11
|
|
150
|
+
|
|
151
|
+
### Added
|
|
152
|
+
|
|
153
|
+
- `cesium_stop` tool. The agent can now stop the running cesium HTTP server
|
|
154
|
+
from inside an opencode session via a tool call. Useful for cycling the
|
|
155
|
+
server after a config change, or cleaning up at session end. Idempotent.
|
|
156
|
+
- `claret-dark` theme preset — dark wine background with bright rose and sage
|
|
157
|
+
accents, sourced from `claret.nvim`'s dark palette.
|
|
158
|
+
- `claret-light` theme preset — the previous `claret` palette, renamed.
|
|
159
|
+
|
|
160
|
+
### Changed
|
|
161
|
+
|
|
162
|
+
- **Default theme is now `claret-dark`.** If you have `themePreset: "claret"`
|
|
163
|
+
in `~/.config/opencode/cesium.json`, you'll now see the dark variant. Set
|
|
164
|
+
`themePreset: "claret-light"` to keep the old look. The bare `"claret"` name
|
|
165
|
+
is preserved as an alias for `"claret-dark"`.
|
|
166
|
+
- Refactored cross-process server-stop logic into `src/server/stop.ts` so the
|
|
167
|
+
CLI's `cesium stop` and the new `cesium_stop` tool share the same code path.
|
|
168
|
+
|
|
169
|
+
## v0.2.2 — 2026-05-11
|
|
170
|
+
|
|
171
|
+
### Added
|
|
172
|
+
|
|
173
|
+
- `cesium stop` — kills the running cesium server cross-process via its PID
|
|
174
|
+
file. Sends SIGTERM with a configurable grace period (`--timeout`, default
|
|
175
|
+
3000 ms), then SIGKILL. `--force` skips the grace. Idempotent: safe when no
|
|
176
|
+
server is running.
|
|
177
|
+
- `cesium restart` — stops then re-starts the server. Replaces the calling
|
|
178
|
+
terminal with the new server (foreground, like `cesium serve`). Inherits
|
|
179
|
+
serve's `--port` / `--hostname` flags.
|
|
180
|
+
|
|
181
|
+
## v0.2.1 — 2026-05-11
|
|
182
|
+
|
|
183
|
+
### Changed
|
|
184
|
+
|
|
185
|
+
- **Default theme is now `claret`** — a deep-rose-on-warm-cream palette derived
|
|
186
|
+
from the claret.nvim color scheme. The previous default (`warm`) is still
|
|
187
|
+
available as a preset; set `themePreset: "warm"` in `cesium.json` to keep the
|
|
188
|
+
old look.
|
|
189
|
+
|
|
190
|
+
### Added
|
|
191
|
+
|
|
192
|
+
- Dynamic theme via `<stateDir>/theme.css`. Each artifact (and index page) now
|
|
193
|
+
references this file via a relative `<link rel="stylesheet">`. Changing the
|
|
194
|
+
configured theme and running `cesium theme apply` re-skins all linked
|
|
195
|
+
artifacts on disk — file://-served artifacts fall back to their original
|
|
196
|
+
inline tokens, preserving offline portability.
|
|
197
|
+
- `claret` theme preset.
|
|
198
|
+
- `cesium theme show` — print resolved theme tokens, indicate when on-disk
|
|
199
|
+
theme.css is out of date.
|
|
200
|
+
- `cesium theme apply` — write theme.css from current config.
|
|
201
|
+
- `cesium theme apply --rewrite-artifacts` — retrofit existing artifacts and
|
|
202
|
+
index pages on disk to reference theme.css. Adds the `<link>` tag idempotently
|
|
203
|
+
to files that don't already have one.
|
|
204
|
+
|
|
205
|
+
### Architectural notes
|
|
206
|
+
|
|
207
|
+
- Inline `<style>` blocks now contain framework rules + a _fallback_ token set
|
|
208
|
+
baked at publish time. The external `theme.css` overrides the fallback when
|
|
209
|
+
present (CSS cascade). Standalone `.html` files still render correctly when
|
|
210
|
+
opened via `file://` without the surrounding state dir.
|
|
211
|
+
|
|
212
|
+
## v0.2.0 — 2026-05-11
|
|
213
|
+
|
|
214
|
+
This is the v0.2.0 polish release. Three smaller features shipped as 0.1.3–0.1.5
|
|
215
|
+
(theme presets, cesium_critique, full-text search) and the standalone CLI lands
|
|
216
|
+
here. Use `cesium <subcommand>` from any shell.
|
|
217
|
+
|
|
218
|
+
### Added
|
|
219
|
+
|
|
220
|
+
- Standalone `cesium` CLI with subcommands:
|
|
221
|
+
- `cesium ls [--all] [--json] [--limit N]` — list artifacts
|
|
222
|
+
- `cesium open <id-prefix> [--print]` — open an artifact in the browser
|
|
223
|
+
- `cesium serve [--port N] [--hostname H]` — run the local server in foreground
|
|
224
|
+
- `cesium prune --older-than <duration> [--yes]` — delete old artifacts
|
|
225
|
+
- `package.json` `bin` field exposes the CLI when the plugin is installed via
|
|
226
|
+
bun/opencode (linked into `node_modules/.bin/cesium`).
|
|
227
|
+
|
|
228
|
+
## v0.1.5 — 2026-05-11
|
|
229
|
+
|
|
230
|
+
### Added
|
|
231
|
+
|
|
232
|
+
- Index search now matches body text in addition to titles. Each artifact's
|
|
233
|
+
rendered card carries a `data-body-text` attribute (capped at 5000 chars,
|
|
234
|
+
lowercased) and the inline filter checks both fields.
|
|
235
|
+
- Body text is extracted at publish time via parse5 and stored on the
|
|
236
|
+
`IndexEntry` shape.
|
|
237
|
+
|
|
238
|
+
### Changed
|
|
239
|
+
|
|
240
|
+
- `IndexEntry` gained a `bodyText: string` field. Existing `index.json` files
|
|
241
|
+
without this field are loaded with an empty string; republishing populates it.
|
|
242
|
+
- Search input placeholder updated from "Filter by title…" to
|
|
243
|
+
"Filter by title or content…".
|
|
244
|
+
|
|
245
|
+
## v0.1.4 — 2026-05-11
|
|
246
|
+
|
|
247
|
+
### Added
|
|
248
|
+
|
|
249
|
+
- `cesium_critique` tool. Agent can call this before publishing to get a 0-100
|
|
250
|
+
score and structured findings (warn/suggest/info) about how well the body
|
|
251
|
+
adheres to the design system. The system-prompt fragment now instructs
|
|
252
|
+
agents to self-check on complex artifacts.
|
|
253
|
+
|
|
254
|
+
## v0.1.3 — 2026-05-11
|
|
255
|
+
|
|
256
|
+
### Added
|
|
257
|
+
|
|
258
|
+
- Four theme presets (`warm`, `cool`, `mono`, `paper`) selectable via `themePreset`
|
|
259
|
+
in `~/.config/opencode/cesium.json`. `CESIUM_THEME_PRESET` env honored.
|
|
260
|
+
- Per-token `theme: {...}` overrides now stack on top of the chosen preset.
|
|
261
|
+
|
|
262
|
+
## v0.1.2 — 2026-05-11
|
|
263
|
+
|
|
264
|
+
### Added
|
|
265
|
+
|
|
266
|
+
- Each artifact now renders a small back-nav at the top of the body linking to
|
|
267
|
+
its project's `index.html` and to the global `index.html`. Uses relative
|
|
268
|
+
paths so it works the same over `http://` and `file://`.
|
|
269
|
+
|
|
270
|
+
## v0.1.1 — 2026-05-11
|
|
271
|
+
|
|
272
|
+
### Added
|
|
273
|
+
|
|
274
|
+
- `hostname` config field (default `127.0.0.1`) lets the local HTTP server bind
|
|
275
|
+
to any address, including `0.0.0.0` for LAN access. `CESIUM_HOSTNAME` env var
|
|
276
|
+
is honored as an override.
|
|
277
|
+
- Display URLs in `terminalSummary` now resolve sensibly: `127.0.0.1` becomes
|
|
278
|
+
`localhost`, `0.0.0.0` becomes the first non-loopback IPv4 interface address,
|
|
279
|
+
named hosts pass through verbatim. Generated http URLs are always reachable.
|
|
280
|
+
|
|
281
|
+
### Changed
|
|
282
|
+
|
|
283
|
+
- `terminalSummary` URLs now show `http://localhost:3030/...` by default
|
|
284
|
+
(previously `http://127.0.0.1:3030/...`). Functionally equivalent on a single
|
|
285
|
+
machine; consistent with how URLs are rendered when binding to other hosts.
|
|
286
|
+
|
|
287
|
+
## v0.1.0 — 2026-05-11
|
|
288
|
+
|
|
289
|
+
Initial release.
|
|
290
|
+
|
|
291
|
+
### Tools
|
|
292
|
+
|
|
293
|
+
- `cesium_publish` — agent-decided HTML artifact publishing with strict portability
|
|
294
|
+
(no external resources), input validation, embedded JSON metadata, atomic writes,
|
|
295
|
+
and revision chains via `supersedes`.
|
|
296
|
+
- `cesium_styleguide` — on-demand design system reference for the agent.
|
|
297
|
+
|
|
298
|
+
### Storage
|
|
299
|
+
|
|
300
|
+
- Artifacts written to `~/.local/state/cesium/projects/<project-slug>/artifacts/`.
|
|
301
|
+
- Project slug derived from git remote when available, else `<basename>-<6char hash>`.
|
|
302
|
+
- Embedded `<script type="application/json" id="cesium-meta">` is the source of truth;
|
|
303
|
+
`index.json` per-project + global is a regenerated cache.
|
|
304
|
+
- Revision chains: `supersedes` field links a new artifact to its predecessor; the
|
|
305
|
+
predecessor's metadata is patched in-place with `supersededBy`.
|
|
306
|
+
|
|
307
|
+
### Index pages
|
|
308
|
+
|
|
309
|
+
- Per-project and global `index.html` regenerated atomically on every publish.
|
|
310
|
+
- Inline JS for kind-filter chips, title search, and revision-chain collapsing.
|
|
311
|
+
- File lock at `<stateDir>/.index.lock` serializes concurrent publishes.
|
|
312
|
+
|
|
313
|
+
### Server
|
|
314
|
+
|
|
315
|
+
- Lazy-start Bun HTTP server on port 3030 (configurable). Scans 3030–3050 on conflict.
|
|
316
|
+
- Static file serving with proper MIME types and path-traversal defense in depth.
|
|
317
|
+
- Idle shutdown after 30 minutes of no requests.
|
|
318
|
+
- SSH detection (`$SSH_CONNECTION`) emits a `ssh -L` port-forward hint in the publish
|
|
319
|
+
output.
|
|
320
|
+
- PID file at `<stateDir>/.server.pid` with stale-process detection.
|
|
321
|
+
|
|
322
|
+
### Design system
|
|
323
|
+
|
|
324
|
+
- Warm ivory / clay / oat palette inspired by the html-effectiveness reference.
|
|
325
|
+
- 16 named component classes covering typography, cards, callouts, code panels,
|
|
326
|
+
timelines, diagrams, comparison and risk tables, and inline chips.
|
|
327
|
+
- System fonts only — no remote resources. Files are fully self-contained.
|
|
328
|
+
|
|
329
|
+
### Agent steering
|
|
330
|
+
|
|
331
|
+
- `experimental.chat.system.transform` hook injects a ~600-token system fragment
|
|
332
|
+
describing the trigger heuristic (≥ 400 word threshold) and the component-class
|
|
333
|
+
cheatsheet.
|
|
334
|
+
- Optional dedicated `@cesium` agent definition shipped at `agents/cesium.md` —
|
|
335
|
+
copy into `~/.config/opencode/agents/` to invoke explicit-publish sessions.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 cfb
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|