From d1bf9c2343d790b4d90d8a1e5e1dd498c16a407f Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 28 Oct 2026 06:06:17 +0000 Subject: [PATCH 1/2] Examples move to examples/; the root README gets the comparison with celld MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - packages/flue-example → examples/flue, packages/agent-examples → examples/agents: `examples/*` is a pnpm workspace, the examples keep depending on @statewalker/cellb and @statewalker/fake-openai through workspace:*. packages/ holds the libraries. - CI, docs and the examples' own relative paths follow the move. - README: what cellb does next to celld, with the feature table (WebSockets, Workers AI, Python, containers, agent frameworks), the new layout and how to run each part. - Biome formatting of node-compat/async_hooks.ts. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01SXJQA3LbggJHi5qZBpUKe8 --- .github/workflows/interop.yml | 6 +- README.md | 58 ++++- .../agents}/README.md | 4 +- .../agents}/opencode/index.js | 0 .../agents}/opencode/wrangler.jsonc | 0 .../agents}/package.json | 0 .../agents}/pi/index.js | 0 .../agents}/pi/wrangler.jsonc | 0 .../agents}/test/load-example.ts | 0 .../agents}/test/opencode.test.ts | 0 .../agents}/test/pi.test.ts | 0 .../agents}/tsconfig.json | 0 .../agents}/vitest.config.ts | 0 .../flue-example => examples/flue}/.gitignore | 0 .../flue-example => examples/flue}/README.md | 4 +- .../flue}/browser/flue-shard-worker.ts | 0 .../flue}/browser/flue-worker.ts | 0 .../flue}/browser/index.html | 0 .../flue}/browser/sw.ts | 0 .../flue}/browser/tabs.html | 0 .../flue}/browser/tabs.ts | 0 .../flue}/browser/vite.config.ts | 0 .../flue}/package.json | 0 .../flue}/playwright.config.ts | 0 .../flue}/src/agents/assistant.ts | 0 .../flue}/src/agents/cloud.ts | 0 .../flue-example => examples/flue}/src/app.ts | 0 .../flue}/src/cloudflare-workers.d.ts | 0 .../flue}/test/agents-websocket.test.ts | 0 .../flue}/test/agents/chat-agent.ts | 0 .../flue}/test/agents/wrangler.json | 0 .../test/browser/flue-in-browser.spec.ts | 2 +- .../flue}/test/fake-llm.ts | 0 .../flue}/test/flue-on-cellb.test.ts | 0 .../flue}/test/whoami.ts | 0 .../flue}/tsconfig.json | 0 .../flue}/vite.config.ts | 0 .../flue}/vitest.config.ts | 0 .../flue}/wrangler.jsonc | 0 packages/cellb/docs/browser-host.md | 2 +- packages/cellb/docs/celld-compatibility.md | 2 +- packages/cellb/docs/gaps.md | 2 +- .../cellb/e2e-browser/agents-sdk-host.spec.ts | 2 +- packages/cellb/src/node-compat/async_hooks.ts | 6 +- .../cellb/test/p13-agents-sdk-host.test.ts | 2 +- pnpm-lock.yaml | 206 ++++++++---------- pnpm-workspace.yaml | 1 + 47 files changed, 158 insertions(+), 139 deletions(-) rename {packages/agent-examples => examples/agents}/README.md (95%) rename {packages/agent-examples => examples/agents}/opencode/index.js (100%) rename {packages/agent-examples => examples/agents}/opencode/wrangler.jsonc (100%) rename {packages/agent-examples => examples/agents}/package.json (100%) rename {packages/agent-examples => examples/agents}/pi/index.js (100%) rename {packages/agent-examples => examples/agents}/pi/wrangler.jsonc (100%) rename {packages/agent-examples => examples/agents}/test/load-example.ts (100%) rename {packages/agent-examples => examples/agents}/test/opencode.test.ts (100%) rename {packages/agent-examples => examples/agents}/test/pi.test.ts (100%) rename {packages/agent-examples => examples/agents}/tsconfig.json (100%) rename {packages/agent-examples => examples/agents}/vitest.config.ts (100%) rename {packages/flue-example => examples/flue}/.gitignore (100%) rename {packages/flue-example => examples/flue}/README.md (98%) rename {packages/flue-example => examples/flue}/browser/flue-shard-worker.ts (100%) rename {packages/flue-example => examples/flue}/browser/flue-worker.ts (100%) rename {packages/flue-example => examples/flue}/browser/index.html (100%) rename {packages/flue-example => examples/flue}/browser/sw.ts (100%) rename {packages/flue-example => examples/flue}/browser/tabs.html (100%) rename {packages/flue-example => examples/flue}/browser/tabs.ts (100%) rename {packages/flue-example => examples/flue}/browser/vite.config.ts (100%) rename {packages/flue-example => examples/flue}/package.json (100%) rename {packages/flue-example => examples/flue}/playwright.config.ts (100%) rename {packages/flue-example => examples/flue}/src/agents/assistant.ts (100%) rename {packages/flue-example => examples/flue}/src/agents/cloud.ts (100%) rename {packages/flue-example => examples/flue}/src/app.ts (100%) rename {packages/flue-example => examples/flue}/src/cloudflare-workers.d.ts (100%) rename {packages/flue-example => examples/flue}/test/agents-websocket.test.ts (100%) rename {packages/flue-example => examples/flue}/test/agents/chat-agent.ts (100%) rename {packages/flue-example => examples/flue}/test/agents/wrangler.json (100%) rename {packages/flue-example => examples/flue}/test/browser/flue-in-browser.spec.ts (99%) rename {packages/flue-example => examples/flue}/test/fake-llm.ts (100%) rename {packages/flue-example => examples/flue}/test/flue-on-cellb.test.ts (100%) rename {packages/flue-example => examples/flue}/test/whoami.ts (100%) rename {packages/flue-example => examples/flue}/tsconfig.json (100%) rename {packages/flue-example => examples/flue}/vite.config.ts (100%) rename {packages/flue-example => examples/flue}/vitest.config.ts (100%) rename {packages/flue-example => examples/flue}/wrangler.jsonc (100%) diff --git a/.github/workflows/interop.yml b/.github/workflows/interop.yml index e8089e0..c78f9ec 100644 --- a/.github/workflows/interop.yml +++ b/.github/workflows/interop.yml @@ -35,18 +35,18 @@ jobs: key: interop-bin-celld-0.6.3-rustfs-1.0.3 - run: pnpm run typecheck - name: Node — a Flue agent app on cellb - run: pnpm --dir ../flue-example test + run: pnpm --dir ../../examples/flue test - name: Node — the fake OpenAI-compatible model run: pnpm --dir ../fake-openai test - name: Node — pi and opencode agents on cellb, against the fake model - run: pnpm --dir ../agent-examples test + run: pnpm --dir ../../examples/agents test - name: Node — celld conformance and interop run: pnpm run interop - run: pnpm exec playwright install --with-deps chromium - name: Chromium — browser hosts on the shared bucket run: pnpm run interop:browser - name: Chromium — a Flue agent app on cellb in a browser - run: pnpm --dir ../flue-example test:browser + run: pnpm --dir ../../examples/flue test:browser - if: failure() uses: actions/upload-artifact@v4 with: diff --git a/README.md b/README.md index 4c7c5f4..810a848 100644 --- a/README.md +++ b/README.md @@ -4,26 +4,70 @@ The monorepo of **cellb** (`@statewalker/cellb`): an isomorphic Durable Objects celld/Cloudflare-compatible surface. The same cells run in a browser (OPFS, ServiceWorker ingress), in Node, and alongside celld on one shared bucket. +## What cellb does, next to celld + +[celld](https://github.com/denoland/celld) runs Cloudflare Workers projects on a fleet of servers +that share one bucket. cellb runs the same projects unchanged, in Node and in browsers, answers the +same requests the same way, and stores cells in celld's format, so one cell can be served by celld, +then by cellb, then by celld again. celld is the judge: its examples, cellb's own probe projects and +workerd's Durable Object tests run on the real celld, are recorded, and are replayed against cellb in +Node and in Chromium (70 scenarios; 5 are judged by workerd instead, where cellb passes stubs by +reference as workerd does, and 6 are known differences, listed in +[`packages/cellb/docs/gaps.md`](packages/cellb/docs/gaps.md)). + +| Feature | celld 0.6.3 | cellb, Node | cellb, browsers | How cellb is checked | +|---|---|---|---|---| +| Workers (stateless handlers) | supported | yes | yes | `hello`, `webapi`, `router`, `body` | +| Durable Objects / cells | supported | yes, same storage format | yes, same storage format | `counter`, `rpc`, `alarm`, workerd's tests; cells cross celld ↔ cellb | +| Durable Object facets | supported | yes | yes | `facets`, `facets-api` | +| KV | supported | yes (celld's code) | yes | `kv`, `kv-values` | +| Queues | supported | yes (celld's code) | yes | `queues`, `queues-api` | +| D1 | supported | yes (Miniflare's simulator) | yes | `d1`, D1 migrations | +| R2 | supported | yes, celld's bucket layout | yes | `r2`, `r2-api`, `r2-advanced` | +| Workflows | supported | yes (celld's engine) | yes | `workflow`, `workflow-api` | +| Cron triggers | supported | yes | yes | `cron` | +| Static assets | supported | yes (with Cloudflare's behaviour where celld has bugs) | yes | `static-assets`, `assets-api` | +| Dynamic Workers (Worker Loader) | supported | yes, a worker thread each | yes, a Dedicated Worker each | `dynamic-worker-tails`, the Worker Loader scenarios | +| WebSockets, hibernation | supported | yes | yes, over MessagePorts | `wsecho`, `wsclient`, `wd-websocket-*` (celld fails `wd-websocket-hibernation`, cellb passes it) | +| Vectorize-style search | example | yes | yes | `vectordb` | +| Workers AI (`ai` binding) | no binding | yes, on an OpenAI-compatible endpoint the host names | yes | `p14-workers-ai`, Flue's `cloud` agent | +| Python Workers (Pyodide) | supported | no, out of scope | no | not run | +| Containers | experimental (Docker or Podman) | no; reported in `unsupported` | no | not run | +| Agent frameworks: Flue, pi, opencode | examples (`pi`, `opencode` need the network) | yes, offline against a fake model | Flue | [`examples/flue`](examples/flue), [`examples/agents`](examples/agents) | + +Where cellb follows Cloudflare or workerd instead of celld, and what still differs, is in +[`packages/cellb/docs/celld-compatibility.md`](packages/cellb/docs/celld-compatibility.md). + ## Layout ``` packages/cellb/ the runtime, its browser host, conformance corpus and docs (see its README) -packages/flue-example/ a Flue agent app (Cloudflare target, Agents SDK) run on cellb +packages/fake-openai/ a scripted OpenAI-compatible model endpoint, for testing agents offline +examples/flue/ a Flue agent app (Cloudflare target, Agents SDK) on cellb, in Node and Chromium +examples/agents/ pi and opencode in Durable Objects on cellb, against the fake model docs/superpowers/ plans for work on the repository .github/workflows/ interop CI against the real celld and RustFS ``` +`packages/*` are libraries; `examples/*` are private apps that use them. Both are workspaces +(`pnpm-workspace.yaml`), so an example depends on `@statewalker/cellb` and +`@statewalker/fake-openai` through `workspace:*`. + ## How to run it 1. `pnpm install` 2. `cd packages/cellb && pnpm test`: the unit tests (`test/`) and the celld end-to-end tests (`e2e/`), which skip without `CELLD_BIN`. 3. `pnpm exec playwright test`: the Chromium end-to-end suite. -4. `cd packages/flue-example && pnpm test`: builds a Flue app with Flue's own Cloudflare build and +4. `cd examples/flue && pnpm test`: builds a Flue app with Flue's own Cloudflare build and runs it on cellb against a fake model endpoint; `pnpm test:browser` runs the same app in Chromium. -5. `pnpm run interop`: the celld interop suite. `scripts/interop-env.sh` downloads the pinned celld +5. `cd examples/agents && pnpm test`: pi and opencode, each in a Durable Object on cellb, against + the fake model. +6. `pnpm run interop`: the celld interop suite. `scripts/interop-env.sh` downloads the pinned celld and RustFS releases and starts RustFS on `127.0.0.1:9200`. +`pnpm test` at the root runs every workspace's tests, and stops at the first one that fails. + ## Why it is the way it is - **One package, three entry points.** Callers differ by platform (isomorphic, Node, browser), not @@ -31,7 +75,15 @@ docs/superpowers/ plans for work on the repository - **CI runs against the real celld.** celld is the conformance judge, so the interop workflow downloads the pinned celld and RustFS and runs the Node and Chromium interop suites on every pull request. +- **Examples run offline.** Agent frameworks need a model; the examples point theirs at + `@statewalker/fake-openai`, so CI needs no key and no network beyond the package registry. ## What will surprise you - A green `pnpm test` without `CELLD_BIN` says nothing about celld compatibility: those tests skip. +- **cellb's `pnpm test` passes every test and still exits 1**: workerd's vendored Durable Object + tests leave `assert.rejects(…)` unawaited, and the rejections reach the Node process the Worker + shares (`test/p09-celld-conformance.test.ts`). The root `pnpm test` stops there; run an example's + tests from its own directory. +- The opencode example's first load takes about half a minute: its SDK bundles to about 430,000 + lines. diff --git a/packages/agent-examples/README.md b/examples/agents/README.md similarity index 95% rename from packages/agent-examples/README.md rename to examples/agents/README.md index 3667414..2edbb7a 100644 --- a/packages/agent-examples/README.md +++ b/examples/agents/README.md @@ -7,7 +7,7 @@ model (`@statewalker/fake-openai`), so the whole thing runs offline once the pac |---|---|---| | `pi/` | [pi](https://pi.dev)'s agent loop (`@earendil-works/pi-agent-core`, `@earendil-works/pi-ai`) | a prompt runs a tool call and its follow-up; the transcript persists in the object's storage | | `opencode/` | opencode's workerd SDK (`@opencode-ai/sdk/workerd`) | celld's opencode example: the SDK boots on the object's SQLite, creates a session, and the model answers a prompt | -| `../flue-example` | Flue (`@flue/runtime`) | a whole Flue app, built for Cloudflare, on Node and in browsers | +| `../flue` | Flue (`@flue/runtime`) | a whole Flue app, built for Cloudflare, on Node and in browsers | The package is private: it is a test of cellb, not a library. @@ -30,7 +30,7 @@ To run one against a real endpoint, set its vars (`PI_BASE_URL`, `PI_MODEL`, `PI start it with `celld dev pi` or load it with `loadNodeProject`. Against the fake model: ```sh -node ../fake-openai/src/cli.ts 8787 # the vars' defaults point here +node ../../packages/fake-openai/src/cli.ts 8787 # the vars' defaults point here ``` ## Examples diff --git a/packages/agent-examples/opencode/index.js b/examples/agents/opencode/index.js similarity index 100% rename from packages/agent-examples/opencode/index.js rename to examples/agents/opencode/index.js diff --git a/packages/agent-examples/opencode/wrangler.jsonc b/examples/agents/opencode/wrangler.jsonc similarity index 100% rename from packages/agent-examples/opencode/wrangler.jsonc rename to examples/agents/opencode/wrangler.jsonc diff --git a/packages/agent-examples/package.json b/examples/agents/package.json similarity index 100% rename from packages/agent-examples/package.json rename to examples/agents/package.json diff --git a/packages/agent-examples/pi/index.js b/examples/agents/pi/index.js similarity index 100% rename from packages/agent-examples/pi/index.js rename to examples/agents/pi/index.js diff --git a/packages/agent-examples/pi/wrangler.jsonc b/examples/agents/pi/wrangler.jsonc similarity index 100% rename from packages/agent-examples/pi/wrangler.jsonc rename to examples/agents/pi/wrangler.jsonc diff --git a/packages/agent-examples/test/load-example.ts b/examples/agents/test/load-example.ts similarity index 100% rename from packages/agent-examples/test/load-example.ts rename to examples/agents/test/load-example.ts diff --git a/packages/agent-examples/test/opencode.test.ts b/examples/agents/test/opencode.test.ts similarity index 100% rename from packages/agent-examples/test/opencode.test.ts rename to examples/agents/test/opencode.test.ts diff --git a/packages/agent-examples/test/pi.test.ts b/examples/agents/test/pi.test.ts similarity index 100% rename from packages/agent-examples/test/pi.test.ts rename to examples/agents/test/pi.test.ts diff --git a/packages/agent-examples/tsconfig.json b/examples/agents/tsconfig.json similarity index 100% rename from packages/agent-examples/tsconfig.json rename to examples/agents/tsconfig.json diff --git a/packages/agent-examples/vitest.config.ts b/examples/agents/vitest.config.ts similarity index 100% rename from packages/agent-examples/vitest.config.ts rename to examples/agents/vitest.config.ts diff --git a/packages/flue-example/.gitignore b/examples/flue/.gitignore similarity index 100% rename from packages/flue-example/.gitignore rename to examples/flue/.gitignore diff --git a/packages/flue-example/README.md b/examples/flue/README.md similarity index 98% rename from packages/flue-example/README.md rename to examples/flue/README.md index d79d864..c562358 100644 --- a/packages/flue-example/README.md +++ b/examples/flue/README.md @@ -80,7 +80,7 @@ module, and a Dedicated Worker (`browser/flue-worker.ts`) hosts it with `browser Concurrent conversations in one browser runtime take turns: it is one thread, and each Flue turn makes 21 SQLite commits on OPFS there. Spreading them over workers runs them in parallel (see -`../cellb/docs/gaps.md` for the numbers). +`../../packages/cellb/docs/gaps.md` for the numbers). The core of it, against the build: @@ -128,7 +128,7 @@ CORS preflights, since the worker's origin is the Vite server's) and a fresh OPF - **`run vite build first (pnpm test does)`** is what `vitest run` alone says without `dist/`. - **The browser test's Chromium** is `PW_CHROMIUM`, else Playwright's own, else the one `@sparticuz/chromium` unpacks (as in `packages/cellb`). -- What cellb still lacks for Agents SDK apps is in `../cellb/docs/gaps.md`. +- What cellb still lacks for Agents SDK apps is in `../../packages/cellb/docs/gaps.md`. ### Dependencies diff --git a/packages/flue-example/browser/flue-shard-worker.ts b/examples/flue/browser/flue-shard-worker.ts similarity index 100% rename from packages/flue-example/browser/flue-shard-worker.ts rename to examples/flue/browser/flue-shard-worker.ts diff --git a/packages/flue-example/browser/flue-worker.ts b/examples/flue/browser/flue-worker.ts similarity index 100% rename from packages/flue-example/browser/flue-worker.ts rename to examples/flue/browser/flue-worker.ts diff --git a/packages/flue-example/browser/index.html b/examples/flue/browser/index.html similarity index 100% rename from packages/flue-example/browser/index.html rename to examples/flue/browser/index.html diff --git a/packages/flue-example/browser/sw.ts b/examples/flue/browser/sw.ts similarity index 100% rename from packages/flue-example/browser/sw.ts rename to examples/flue/browser/sw.ts diff --git a/packages/flue-example/browser/tabs.html b/examples/flue/browser/tabs.html similarity index 100% rename from packages/flue-example/browser/tabs.html rename to examples/flue/browser/tabs.html diff --git a/packages/flue-example/browser/tabs.ts b/examples/flue/browser/tabs.ts similarity index 100% rename from packages/flue-example/browser/tabs.ts rename to examples/flue/browser/tabs.ts diff --git a/packages/flue-example/browser/vite.config.ts b/examples/flue/browser/vite.config.ts similarity index 100% rename from packages/flue-example/browser/vite.config.ts rename to examples/flue/browser/vite.config.ts diff --git a/packages/flue-example/package.json b/examples/flue/package.json similarity index 100% rename from packages/flue-example/package.json rename to examples/flue/package.json diff --git a/packages/flue-example/playwright.config.ts b/examples/flue/playwright.config.ts similarity index 100% rename from packages/flue-example/playwright.config.ts rename to examples/flue/playwright.config.ts diff --git a/packages/flue-example/src/agents/assistant.ts b/examples/flue/src/agents/assistant.ts similarity index 100% rename from packages/flue-example/src/agents/assistant.ts rename to examples/flue/src/agents/assistant.ts diff --git a/packages/flue-example/src/agents/cloud.ts b/examples/flue/src/agents/cloud.ts similarity index 100% rename from packages/flue-example/src/agents/cloud.ts rename to examples/flue/src/agents/cloud.ts diff --git a/packages/flue-example/src/app.ts b/examples/flue/src/app.ts similarity index 100% rename from packages/flue-example/src/app.ts rename to examples/flue/src/app.ts diff --git a/packages/flue-example/src/cloudflare-workers.d.ts b/examples/flue/src/cloudflare-workers.d.ts similarity index 100% rename from packages/flue-example/src/cloudflare-workers.d.ts rename to examples/flue/src/cloudflare-workers.d.ts diff --git a/packages/flue-example/test/agents-websocket.test.ts b/examples/flue/test/agents-websocket.test.ts similarity index 100% rename from packages/flue-example/test/agents-websocket.test.ts rename to examples/flue/test/agents-websocket.test.ts diff --git a/packages/flue-example/test/agents/chat-agent.ts b/examples/flue/test/agents/chat-agent.ts similarity index 100% rename from packages/flue-example/test/agents/chat-agent.ts rename to examples/flue/test/agents/chat-agent.ts diff --git a/packages/flue-example/test/agents/wrangler.json b/examples/flue/test/agents/wrangler.json similarity index 100% rename from packages/flue-example/test/agents/wrangler.json rename to examples/flue/test/agents/wrangler.json diff --git a/packages/flue-example/test/browser/flue-in-browser.spec.ts b/examples/flue/test/browser/flue-in-browser.spec.ts similarity index 99% rename from packages/flue-example/test/browser/flue-in-browser.spec.ts rename to examples/flue/test/browser/flue-in-browser.spec.ts index 5fa0ab0..05a622f 100644 --- a/packages/flue-example/test/browser/flue-in-browser.spec.ts +++ b/examples/flue/test/browser/flue-in-browser.spec.ts @@ -4,7 +4,7 @@ import { expect, type Page, test } from "@playwright/test"; import { shardOf } from "@statewalker/cellb"; import { bundleWorkerForBrowser } from "@statewalker/cellb/node"; // Not exported: where a Durable Object id lands decides which tab's shard runs it. -import { idFromName, namespaceKey } from "../../../cellb/src/core/id.ts"; +import { idFromName, namespaceKey } from "../../../../packages/cellb/src/core/id.ts"; import { startFakeLlm } from "../fake-llm.ts"; import { whoamiScript, wrongIdentities } from "../whoami.ts"; diff --git a/packages/flue-example/test/fake-llm.ts b/examples/flue/test/fake-llm.ts similarity index 100% rename from packages/flue-example/test/fake-llm.ts rename to examples/flue/test/fake-llm.ts diff --git a/packages/flue-example/test/flue-on-cellb.test.ts b/examples/flue/test/flue-on-cellb.test.ts similarity index 100% rename from packages/flue-example/test/flue-on-cellb.test.ts rename to examples/flue/test/flue-on-cellb.test.ts diff --git a/packages/flue-example/test/whoami.ts b/examples/flue/test/whoami.ts similarity index 100% rename from packages/flue-example/test/whoami.ts rename to examples/flue/test/whoami.ts diff --git a/packages/flue-example/tsconfig.json b/examples/flue/tsconfig.json similarity index 100% rename from packages/flue-example/tsconfig.json rename to examples/flue/tsconfig.json diff --git a/packages/flue-example/vite.config.ts b/examples/flue/vite.config.ts similarity index 100% rename from packages/flue-example/vite.config.ts rename to examples/flue/vite.config.ts diff --git a/packages/flue-example/vitest.config.ts b/examples/flue/vitest.config.ts similarity index 100% rename from packages/flue-example/vitest.config.ts rename to examples/flue/vitest.config.ts diff --git a/packages/flue-example/wrangler.jsonc b/examples/flue/wrangler.jsonc similarity index 100% rename from packages/flue-example/wrangler.jsonc rename to examples/flue/wrangler.jsonc diff --git a/packages/cellb/docs/browser-host.md b/packages/cellb/docs/browser-host.md index 8cc384d..eddd974 100644 --- a/packages/cellb/docs/browser-host.md +++ b/packages/cellb/docs/browser-host.md @@ -57,7 +57,7 @@ code and builds the runtime from the wrangler configuration. The code is either: globals read what the runtime installs. `bundleWorkerForBrowser(entry, { nodeCompat })` from `@statewalker/cellb/node` builds it: `cloudflare:workers` with the project's own `env` and `exports`, `cloudflare:email`, and with nodejs_compat the `node:*` polyfills (bare names such as - `"path"` too). A Flue app built for Cloudflare runs this way (packages/flue-example); or + `"path"` too). A Flue app built for Cloudflare runs this way (examples/flue); or - `{ site }` — the base URL of an in-browser HTTP server made by `createProjectSite` and hosted by `@statewalker/webrun-site-host`, which compiles the project's sources on request (`@statewalker/webrun-modules`). Loaded Workers' code is uploaded to it and imported from URLs. diff --git a/packages/cellb/docs/celld-compatibility.md b/packages/cellb/docs/celld-compatibility.md index ad3b833..b5313f9 100644 --- a/packages/cellb/docs/celld-compatibility.md +++ b/packages/cellb/docs/celld-compatibility.md @@ -25,7 +25,7 @@ identical, how it is checked, and where the two still differ. The pinned celld v | Workers AI (`ai` binding) | no binding (the `pi` example builds its own adapter) | yes, on an OpenAI-compatible endpoint the host names | yes | `p14-workers-ai`, Flue's `cloud` agent | | Python Workers (Pyodide) | supported | no, out of scope ([gaps.md](gaps.md)) | no | not run | | Containers | experimental (Docker or Podman) | no; reported in `unsupported` | no | not run | -| Agent frameworks: Flue, pi, opencode | examples (`pi`, `opencode` need the network) | yes, offline against a fake model | Flue | `packages/flue-example`, `packages/agent-examples` | +| Agent frameworks: Flue, pi, opencode | examples (`pi`, `opencode` need the network) | yes, offline against a fake model | Flue | `examples/flue`, `examples/agents` | ## The same request gets the same answer diff --git a/packages/cellb/docs/gaps.md b/packages/cellb/docs/gaps.md index cba42a9..1f79e51 100644 --- a/packages/cellb/docs/gaps.md +++ b/packages/cellb/docs/gaps.md @@ -143,7 +143,7 @@ Dedicated Workers all work in Firefox 157, and the whole suite passes there. Wha - **celld examples not run:** `python` (Pyodide Python Workers: cellb runs no Python), `wasm` (needs the Rust toolchain to build), `container` and `sandbox` (Docker or Podman; a `containers` config is reported in `unsupported`). `pi` and `opencode` need a model on the network as celld - ships them; `packages/agent-examples` runs both, adapted to take their model from an endpoint in + ships them; `examples/agents` runs both, adapted to take their model from an endpoint in their vars, against a fake OpenAI-compatible model. - **No build step.** The entry points are TypeScript sources. A bundler, Vite or vitest resolves them; plain `node` fails with `ERR_MODULE_NOT_FOUND` for `src/…/*.js`. diff --git a/packages/cellb/e2e-browser/agents-sdk-host.spec.ts b/packages/cellb/e2e-browser/agents-sdk-host.spec.ts index cdcb060..7c52f9c 100644 --- a/packages/cellb/e2e-browser/agents-sdk-host.spec.ts +++ b/packages/cellb/e2e-browser/agents-sdk-host.spec.ts @@ -21,7 +21,7 @@ import { // What the Agents SDK (and Flue, built on it) needs from a browser host, in one project: // `env` and `exports` of cloudflare:workers, cloudflare:email, and the nodejs_compat modules it -// imports (packages/flue-example runs a whole Flue app the same way). +// imports (examples/flue runs a whole Flue app the same way). const worker = ` import { DurableObject, env, exports } from "cloudflare:workers"; import { EmailMessage } from "cloudflare:email"; diff --git a/packages/cellb/src/node-compat/async_hooks.ts b/packages/cellb/src/node-compat/async_hooks.ts index 6d606d5..61b8ff1 100644 --- a/packages/cellb/src/node-compat/async_hooks.ts +++ b/packages/cellb/src/node-compat/async_hooks.ts @@ -121,11 +121,7 @@ export class AsyncLocalStorage { } exit(fn: (...args: unknown[]) => R, ...args: unknown[]): R { if (native) - return variableOf(this as AsyncLocalStorage, native).run( - undefined, - fn, - ...args, - ); + return variableOf(this as AsyncLocalStorage, native).run(undefined, fn, ...args); const frame = new Map(state.current); frame.delete(this as AsyncLocalStorage); return runIn(frame, fn, undefined, args); diff --git a/packages/cellb/test/p13-agents-sdk-host.test.ts b/packages/cellb/test/p13-agents-sdk-host.test.ts index 614f5f5..21efa68 100644 --- a/packages/cellb/test/p13-agents-sdk-host.test.ts +++ b/packages/cellb/test/p13-agents-sdk-host.test.ts @@ -31,7 +31,7 @@ import { } from "./loaded-scope-worker.js"; // What the Cloudflare Agents SDK (and Flue, built on it) needs from a host beyond the -// Durable Object API itself; packages/flue-example runs a whole Flue app. +// Durable Object API itself; examples/flue runs a whole Flue app. const worker = ` import { DurableObject, env, exports } from "cloudflare:workers"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0e06d42..dba8cf7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -63,7 +63,7 @@ importers: specifier: 'catalog:' version: 5.0.5(@opentelemetry/api@1.10.0)(@types/node@26.6.5)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1)) - packages/agent-examples: + examples/agents: dependencies: '@earendil-works/pi-agent-core': specifier: ^1.4.0 @@ -77,10 +77,10 @@ importers: devDependencies: '@statewalker/cellb': specifier: workspace:* - version: link:../cellb + version: link:../../packages/cellb '@statewalker/fake-openai': specifier: workspace:* - version: link:../fake-openai + version: link:../../packages/fake-openai '@statewalker/webrun-files-mem': specifier: ^0.10.0 version: 0.10.3 @@ -97,6 +97,67 @@ importers: specifier: 'catalog:' version: 5.0.5(@opentelemetry/api@1.9.0)(@types/node@26.6.5)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1)) + examples/flue: + dependencies: + '@earendil-works/pi-ai': + specifier: ^1.4.0 + version: 1.4.0(@aws-sdk/credential-provider-node@3.972.88)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.7))(@smithy/signature-v4@5.7.4)(undici@8.12.3)(ws@8.22.0)(zod@4.6.7) + '@flue/runtime': + specifier: 2.3.0 + version: 2.3.0(@aws-sdk/credential-provider-node@3.972.88)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.7))(@smithy/signature-v4@5.7.4)(typescript@7.0.2)(undici@8.12.3)(ws@8.22.0)(zod@4.6.7) + hono: + specifier: ^4.13.14 + version: 4.13.14 + devDependencies: + '@cloudflare/vite-plugin': + specifier: ^1.65.0 + version: 1.65.0(@types/node@26.6.5)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1))(workerd@1.20261023.1)(wrangler@4.153.0(@cloudflare/workers-types@5.20261026.1)(@types/node@26.6.5)) + '@flue/sdk': + specifier: 2.3.0 + version: 2.3.0 + '@flue/vite': + specifier: 2.3.0 + version: 2.3.0(@aws-sdk/credential-provider-node@3.972.88)(@babel/core@8.0.9)(@babel/runtime@7.29.10)(@cloudflare/workers-types@5.20261026.1)(@modelcontextprotocol/client@2.0.0)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.7))(@modelcontextprotocol/server@2.0.0)(@smithy/signature-v4@5.7.4)(ai@6.0.317(zod@4.6.7))(hono@4.13.14)(react@19.3.1)(rolldown@1.2.15)(typescript@7.0.2)(undici@8.12.3)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1))(ws@8.22.0)(zod@4.6.7) + '@playwright/test': + specifier: ^1.63.0 + version: 1.64.1 + '@sparticuz/chromium': + specifier: ^153.0.0 + version: 153.0.0 + '@sqlite.org/sqlite-wasm': + specifier: ^3.53.4-build1 + version: 3.53.4-build2 + '@statewalker/cellb': + specifier: workspace:* + version: link:../../packages/cellb + '@statewalker/fake-openai': + specifier: workspace:* + version: link:../../packages/fake-openai + '@statewalker/webrun-files-mem': + specifier: ^0.10.0 + version: 0.10.3 + '@types/node': + specifier: 'catalog:' + version: 26.6.5 + agents: + specifier: 0.20.1 + version: 0.20.1(@babel/core@8.0.9)(@babel/runtime@7.29.10)(@cloudflare/workers-types@5.20261026.1)(@modelcontextprotocol/client@2.0.0)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.7))(@modelcontextprotocol/server@2.0.0)(ai@6.0.317(zod@4.6.7))(react@19.3.1)(rolldown@1.2.15)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1))(zod@4.6.7) + esbuild: + specifier: 0.28.2 + version: 0.28.2 + typescript: + specifier: 'catalog:' + version: 7.0.2 + vite: + specifier: 'catalog:' + version: 8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1) + vitest: + specifier: 'catalog:' + version: 5.0.5(@opentelemetry/api@1.10.0)(@types/node@26.6.5)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1)) + wrangler: + specifier: ^4.152.0 + version: 4.153.0(@cloudflare/workers-types@5.20261026.1)(@types/node@26.6.5) + packages/cellb: dependencies: '@noble/hashes': @@ -212,67 +273,6 @@ importers: specifier: 'catalog:' version: 5.0.5(@opentelemetry/api@1.10.0)(@types/node@26.6.5)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1)) - packages/flue-example: - dependencies: - '@earendil-works/pi-ai': - specifier: ^1.4.0 - version: 1.4.0(@aws-sdk/credential-provider-node@3.972.88)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.7))(@smithy/signature-v4@5.7.4)(undici@8.12.3)(ws@8.22.0)(zod@4.6.7) - '@flue/runtime': - specifier: 2.3.0 - version: 2.3.0(@aws-sdk/credential-provider-node@3.972.88)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.7))(@smithy/signature-v4@5.7.4)(typescript@7.0.2)(undici@8.12.3)(ws@8.22.0)(zod@4.6.7) - hono: - specifier: ^4.13.14 - version: 4.13.14 - devDependencies: - '@cloudflare/vite-plugin': - specifier: ^1.65.0 - version: 1.65.0(@types/node@26.6.5)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1))(workerd@1.20261023.1)(wrangler@4.153.0(@cloudflare/workers-types@5.20261026.1)(@types/node@26.6.5)) - '@flue/sdk': - specifier: 2.3.0 - version: 2.3.0 - '@flue/vite': - specifier: 2.3.0 - version: 2.3.0(@aws-sdk/credential-provider-node@3.972.88)(@babel/core@8.0.9)(@babel/runtime@7.29.10)(@cloudflare/workers-types@5.20261026.1)(@modelcontextprotocol/client@2.0.0)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.7))(@modelcontextprotocol/server@2.0.0)(@smithy/signature-v4@5.7.4)(ai@6.0.317(zod@4.6.7))(hono@4.13.14)(react@19.3.1)(rolldown@1.2.15)(typescript@7.0.2)(undici@8.12.3)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1))(ws@8.22.0)(zod@4.6.7) - '@playwright/test': - specifier: ^1.63.0 - version: 1.64.1 - '@sparticuz/chromium': - specifier: ^153.0.0 - version: 153.0.0 - '@sqlite.org/sqlite-wasm': - specifier: ^3.53.4-build1 - version: 3.53.4-build2 - '@statewalker/cellb': - specifier: workspace:* - version: link:../cellb - '@statewalker/fake-openai': - specifier: workspace:* - version: link:../fake-openai - '@statewalker/webrun-files-mem': - specifier: ^0.10.0 - version: 0.10.3 - '@types/node': - specifier: 'catalog:' - version: 26.6.5 - agents: - specifier: 0.20.1 - version: 0.20.1(@babel/core@8.0.9)(@babel/runtime@7.29.10)(@cloudflare/workers-types@5.20261026.1)(@modelcontextprotocol/client@2.0.0)(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.6.7))(@modelcontextprotocol/server@2.0.0)(ai@6.0.317(zod@4.6.7))(react@19.3.1)(rolldown@1.2.15)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1))(zod@4.6.7) - esbuild: - specifier: 0.28.2 - version: 0.28.2 - typescript: - specifier: 'catalog:' - version: 7.0.2 - vite: - specifier: 'catalog:' - version: 8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1) - vitest: - specifier: 'catalog:' - version: 5.0.5(@opentelemetry/api@1.10.0)(@types/node@26.6.5)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1)) - wrangler: - specifier: ^4.152.0 - version: 4.153.0(@cloudflare/workers-types@5.20261026.1)(@types/node@26.6.5) - packages: '@ai-sdk/alibaba@1.0.17': @@ -555,10 +555,6 @@ packages: resolution: {integrity: sha512-5MliYkp2u0+2arTp5fZIaxl+xmm90LEKv/VeSxhfNQW4t0fvWJrNO429/jchWQenNoDRrOGE59VfbuZUfwFujg==} engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.978.5': - resolution: {integrity: sha512-ruI0AWqcrfL20XDS6SwZIJFPOBZ6N0ADa9nLzWlBhxk1aoUjbUX3JkTR9vEmk7o35XpAHi68ahZ4T6RE2U9XyA==} - engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.978.6': resolution: {integrity: sha512-ykF/MiYoM15dgZwF/WLgjJXVbAK2wU6vjPigeEnOHwyUJ0rdlraO5uekecKNVPkvOnz+oju/5zljViQs1nI1FQ==} engines: {node: '>=20.0.0'} @@ -615,10 +611,6 @@ packages: resolution: {integrity: sha512-/BvocdloKozx/zFr4benH+9J1ywB/2dYFHPWNUdo0CBCe00gTm0HPflOq8MH6cuCTbnywSrscGq0/LheN59teQ==} engines: {node: '>= 14.0.0'} - '@aws-sdk/nested-clients@3.997.50': - resolution: {integrity: sha512-nKb8qu4QsnpZTq/6JIXc72mzuzfh7BK4sUQkpQznPec2z4W7Ob2xYkcM4i5e1yGTBnbJVeFv/0sf3jcz85hclA==} - engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.997.51': resolution: {integrity: sha512-DJK4iGIHWU8Jh8ODMvqFYcX9yGBMXV4tSZAvqlHF5EDd8hbmF3eFO9KIWOnA7wcQjPzEkyMMW1/FgZ9RU8oimQ==} engines: {node: '>=20.0.0'} @@ -5233,7 +5225,7 @@ snapshots: '@aws-sdk/client-bedrock-runtime@3.1127.0': dependencies: - '@aws-sdk/core': 3.978.5 + '@aws-sdk/core': 3.978.6 '@aws-sdk/credential-provider-node': 3.972.88 '@aws-sdk/eventstream-handler-node': 3.972.38 '@aws-sdk/middleware-eventstream': 3.972.33 @@ -5242,7 +5234,7 @@ snapshots: '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/fetch-http-handler': 5.8.0 - '@smithy/node-http-handler': 4.12.1 + '@smithy/node-http-handler': 4.13.0 '@smithy/types': 4.19.0 tslib: 2.8.1 @@ -5250,24 +5242,13 @@ snapshots: dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.978.5 + '@aws-sdk/core': 3.978.6 '@aws-sdk/credential-provider-node': 3.972.88 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/fetch-http-handler': 5.8.0 - '@smithy/node-http-handler': 4.12.1 - '@smithy/types': 4.19.0 - tslib: 2.8.1 - - '@aws-sdk/core@3.978.5': - dependencies: - '@aws-sdk/types': 3.975.0 - '@aws-sdk/xml-builder': 3.972.41 - '@aws/lambda-invoke-store': 0.3.0 - '@smithy/core': 3.37.0 - '@smithy/signature-v4': 5.7.4 + '@smithy/node-http-handler': 4.13.0 '@smithy/types': 4.19.0 - bowser: 2.14.1 tslib: 2.8.1 '@aws-sdk/core@3.978.6': @@ -5291,7 +5272,7 @@ snapshots: '@aws-sdk/credential-provider-env@3.972.76': dependencies: - '@aws-sdk/core': 3.978.5 + '@aws-sdk/core': 3.978.6 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/types': 4.19.0 @@ -5299,24 +5280,24 @@ snapshots: '@aws-sdk/credential-provider-http@3.972.78': dependencies: - '@aws-sdk/core': 3.978.5 + '@aws-sdk/core': 3.978.6 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/fetch-http-handler': 5.8.0 - '@smithy/node-http-handler': 4.12.1 + '@smithy/node-http-handler': 4.13.0 '@smithy/types': 4.19.0 tslib: 2.8.1 '@aws-sdk/credential-provider-ini@3.973.21': dependencies: - '@aws-sdk/core': 3.978.5 + '@aws-sdk/core': 3.978.6 '@aws-sdk/credential-provider-env': 3.972.76 '@aws-sdk/credential-provider-http': 3.972.78 '@aws-sdk/credential-provider-login': 3.972.83 '@aws-sdk/credential-provider-process': 3.972.76 '@aws-sdk/credential-provider-sso': 3.973.20 '@aws-sdk/credential-provider-web-identity': 3.972.82 - '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/nested-clients': 3.997.51 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/credential-provider-imds': 4.5.2 @@ -5325,8 +5306,8 @@ snapshots: '@aws-sdk/credential-provider-login@3.972.83': dependencies: - '@aws-sdk/core': 3.978.5 - '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/core': 3.978.6 + '@aws-sdk/nested-clients': 3.997.51 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/types': 4.19.0 @@ -5348,7 +5329,7 @@ snapshots: '@aws-sdk/credential-provider-process@3.972.76': dependencies: - '@aws-sdk/core': 3.978.5 + '@aws-sdk/core': 3.978.6 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/types': 4.19.0 @@ -5356,8 +5337,8 @@ snapshots: '@aws-sdk/credential-provider-sso@3.973.20': dependencies: - '@aws-sdk/core': 3.978.5 - '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/core': 3.978.6 + '@aws-sdk/nested-clients': 3.997.51 '@aws-sdk/token-providers': 3.1155.0 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 @@ -5366,8 +5347,8 @@ snapshots: '@aws-sdk/credential-provider-web-identity@3.972.82': dependencies: - '@aws-sdk/core': 3.978.5 - '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/core': 3.978.6 + '@aws-sdk/nested-clients': 3.997.51 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/types': 4.19.0 @@ -5376,7 +5357,7 @@ snapshots: '@aws-sdk/credential-providers@3.1057.0': dependencies: '@aws-sdk/client-cognito-identity': 3.1057.0 - '@aws-sdk/core': 3.978.5 + '@aws-sdk/core': 3.978.6 '@aws-sdk/credential-provider-cognito-identity': 3.972.76 '@aws-sdk/credential-provider-env': 3.972.76 '@aws-sdk/credential-provider-http': 3.972.78 @@ -5386,7 +5367,7 @@ snapshots: '@aws-sdk/credential-provider-process': 3.972.76 '@aws-sdk/credential-provider-sso': 3.973.20 '@aws-sdk/credential-provider-web-identity': 3.972.82 - '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/nested-clients': 3.997.51 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/credential-provider-imds': 4.5.2 @@ -5409,7 +5390,7 @@ snapshots: '@aws-sdk/middleware-websocket@3.972.58': dependencies: - '@aws-sdk/core': 3.978.5 + '@aws-sdk/core': 3.978.6 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/fetch-http-handler': 5.8.0 @@ -5417,17 +5398,6 @@ snapshots: '@smithy/types': 4.19.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.997.50': - dependencies: - '@aws-sdk/core': 3.978.5 - '@aws-sdk/signature-v4-multi-region': 3.996.49 - '@aws-sdk/types': 3.975.0 - '@smithy/core': 3.37.0 - '@smithy/fetch-http-handler': 5.8.0 - '@smithy/node-http-handler': 4.12.1 - '@smithy/types': 4.19.0 - tslib: 2.8.1 - '@aws-sdk/nested-clients@3.997.51': dependencies: '@aws-sdk/core': 3.978.6 @@ -5448,8 +5418,8 @@ snapshots: '@aws-sdk/token-providers@3.1127.0': dependencies: - '@aws-sdk/core': 3.978.5 - '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/core': 3.978.6 + '@aws-sdk/nested-clients': 3.997.51 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/types': 4.19.0 @@ -5457,8 +5427,8 @@ snapshots: '@aws-sdk/token-providers@3.1155.0': dependencies: - '@aws-sdk/core': 3.978.5 - '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/core': 3.978.6 + '@aws-sdk/nested-clients': 3.997.51 '@aws-sdk/types': 3.975.0 '@smithy/core': 3.37.0 '@smithy/types': 4.19.0 @@ -7221,7 +7191,7 @@ snapshots: '@opentelemetry/api-logs@0.214.0': dependencies: - '@opentelemetry/api': 1.9.0 + '@opentelemetry/api': 1.10.0 '@opentelemetry/api@1.10.0': {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4265e7b..eea1774 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,6 @@ packages: - "packages/*" + - "examples/*" catalog: "@biomejs/biome": 2.5.15 From 30a27ef96212ead1e15d865e35c6e68ab7a0ee2e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 28 Oct 2026 06:37:31 +0000 Subject: [PATCH 2/2] fake-openai moves to examples/: only the examples use it cellb's own tests do not; the Flue and agent examples test against it. CI, READMEs and the CLI's usage line follow the move. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01SXJQA3LbggJHi5qZBpUKe8 --- .github/workflows/interop.yml | 2 +- README.md | 5 ++-- examples/agents/README.md | 2 +- {packages => examples}/fake-openai/README.md | 5 ++-- .../fake-openai/package.json | 0 {packages => examples}/fake-openai/src/cli.ts | 2 +- .../fake-openai/src/index.ts | 0 .../fake-openai/test/fake-openai.test.ts | 0 .../fake-openai/tsconfig.json | 0 pnpm-lock.yaml | 28 +++++++++---------- 10 files changed, 23 insertions(+), 21 deletions(-) rename {packages => examples}/fake-openai/README.md (95%) rename {packages => examples}/fake-openai/package.json (100%) rename {packages => examples}/fake-openai/src/cli.ts (92%) rename {packages => examples}/fake-openai/src/index.ts (100%) rename {packages => examples}/fake-openai/test/fake-openai.test.ts (100%) rename {packages => examples}/fake-openai/tsconfig.json (100%) diff --git a/.github/workflows/interop.yml b/.github/workflows/interop.yml index c78f9ec..1b9f29c 100644 --- a/.github/workflows/interop.yml +++ b/.github/workflows/interop.yml @@ -37,7 +37,7 @@ jobs: - name: Node — a Flue agent app on cellb run: pnpm --dir ../../examples/flue test - name: Node — the fake OpenAI-compatible model - run: pnpm --dir ../fake-openai test + run: pnpm --dir ../../examples/fake-openai test - name: Node — pi and opencode agents on cellb, against the fake model run: pnpm --dir ../../examples/agents test - name: Node — celld conformance and interop diff --git a/README.md b/README.md index 810a848..1b18221 100644 --- a/README.md +++ b/README.md @@ -42,14 +42,15 @@ Where cellb follows Cloudflare or workerd instead of celld, and what still diffe ``` packages/cellb/ the runtime, its browser host, conformance corpus and docs (see its README) -packages/fake-openai/ a scripted OpenAI-compatible model endpoint, for testing agents offline examples/flue/ a Flue agent app (Cloudflare target, Agents SDK) on cellb, in Node and Chromium examples/agents/ pi and opencode in Durable Objects on cellb, against the fake model +examples/fake-openai/ a scripted OpenAI-compatible model endpoint the examples test against docs/superpowers/ plans for work on the repository .github/workflows/ interop CI against the real celld and RustFS ``` -`packages/*` are libraries; `examples/*` are private apps that use them. Both are workspaces +`packages/*` are libraries; `examples/*` are private apps that use them, with the test tools only +they use. Both are workspaces (`pnpm-workspace.yaml`), so an example depends on `@statewalker/cellb` and `@statewalker/fake-openai` through `workspace:*`. diff --git a/examples/agents/README.md b/examples/agents/README.md index 2edbb7a..01f06a5 100644 --- a/examples/agents/README.md +++ b/examples/agents/README.md @@ -30,7 +30,7 @@ To run one against a real endpoint, set its vars (`PI_BASE_URL`, `PI_MODEL`, `PI start it with `celld dev pi` or load it with `loadNodeProject`. Against the fake model: ```sh -node ../../packages/fake-openai/src/cli.ts 8787 # the vars' defaults point here +node ../fake-openai/src/cli.ts 8787 # the vars' defaults point here ``` ## Examples diff --git a/packages/fake-openai/README.md b/examples/fake-openai/README.md similarity index 95% rename from packages/fake-openai/README.md rename to examples/fake-openai/README.md index 6f8b182..29791eb 100644 --- a/packages/fake-openai/README.md +++ b/examples/fake-openai/README.md @@ -2,7 +2,8 @@ A scripted OpenAI-compatible model endpoint for running agents offline: `POST /v1/chat/completions` (streamed or not, text or tool calls), `POST /v1/embeddings` and `GET /v1/models`. The package is -private: the agent examples and the Flue example test against it. +private: the agent examples and the Flue example test against it, so it lives with them in +`examples/`. ## Why it exists @@ -28,7 +29,7 @@ await fake.close(); From a shell, for `celld dev` or a manual try (Node 22.18 or later runs the TypeScript directly): ```sh -node packages/fake-openai/src/cli.ts 8787 # http://127.0.0.1:8787/v1 +node examples/fake-openai/src/cli.ts 8787 # http://127.0.0.1:8787/v1 ``` ## Examples diff --git a/packages/fake-openai/package.json b/examples/fake-openai/package.json similarity index 100% rename from packages/fake-openai/package.json rename to examples/fake-openai/package.json diff --git a/packages/fake-openai/src/cli.ts b/examples/fake-openai/src/cli.ts similarity index 92% rename from packages/fake-openai/src/cli.ts rename to examples/fake-openai/src/cli.ts index 95bfea5..2d350bb 100755 --- a/packages/fake-openai/src/cli.ts +++ b/examples/fake-openai/src/cli.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node // Runs the fake model on its own, for `celld dev` or a manual try: -// node packages/fake-openai/src/cli.ts [port] +// node examples/fake-openai/src/cli.ts [port] // It answers with the default script (see `defaultReply`) and logs each request. import { defaultReply, lastUserText, startFakeOpenAi } from "./index.ts"; diff --git a/packages/fake-openai/src/index.ts b/examples/fake-openai/src/index.ts similarity index 100% rename from packages/fake-openai/src/index.ts rename to examples/fake-openai/src/index.ts diff --git a/packages/fake-openai/test/fake-openai.test.ts b/examples/fake-openai/test/fake-openai.test.ts similarity index 100% rename from packages/fake-openai/test/fake-openai.test.ts rename to examples/fake-openai/test/fake-openai.test.ts diff --git a/packages/fake-openai/tsconfig.json b/examples/fake-openai/tsconfig.json similarity index 100% rename from packages/fake-openai/tsconfig.json rename to examples/fake-openai/tsconfig.json diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dba8cf7..96a0d9c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -80,7 +80,7 @@ importers: version: link:../../packages/cellb '@statewalker/fake-openai': specifier: workspace:* - version: link:../../packages/fake-openai + version: link:../fake-openai '@statewalker/webrun-files-mem': specifier: ^0.10.0 version: 0.10.3 @@ -97,6 +97,18 @@ importers: specifier: 'catalog:' version: 5.0.5(@opentelemetry/api@1.9.0)(@types/node@26.6.5)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1)) + examples/fake-openai: + devDependencies: + '@types/node': + specifier: 'catalog:' + version: 26.6.5 + typescript: + specifier: 'catalog:' + version: 7.0.2 + vitest: + specifier: 'catalog:' + version: 5.0.5(@opentelemetry/api@1.10.0)(@types/node@26.6.5)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1)) + examples/flue: dependencies: '@earendil-works/pi-ai': @@ -132,7 +144,7 @@ importers: version: link:../../packages/cellb '@statewalker/fake-openai': specifier: workspace:* - version: link:../../packages/fake-openai + version: link:../fake-openai '@statewalker/webrun-files-mem': specifier: ^0.10.0 version: 0.10.3 @@ -261,18 +273,6 @@ importers: specifier: ^3.25.0 version: 3.25.76 - packages/fake-openai: - devDependencies: - '@types/node': - specifier: 'catalog:' - version: 26.6.5 - typescript: - specifier: 'catalog:' - version: 7.0.2 - vitest: - specifier: 'catalog:' - version: 5.0.5(@opentelemetry/api@1.10.0)(@types/node@26.6.5)(vite@8.3.5(@types/node@26.6.5)(esbuild@0.28.2)(yaml@2.9.1)) - packages: '@ai-sdk/alibaba@1.0.17':