@fungi.computer/oyster 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +1134 -2
- package/dist/agents.d.ts +114 -0
- package/dist/agents.js +322 -0
- package/dist/app-builds.d.ts +210 -0
- package/dist/app-builds.js +499 -0
- package/dist/app-sandbox.d.ts +2 -0
- package/dist/app-sandbox.js +2 -0
- package/dist/app-sources.d.ts +31 -0
- package/dist/app-sources.js +370 -0
- package/dist/app-storage.d.ts +141 -0
- package/dist/app-storage.js +281 -0
- package/dist/apps/gate.d.ts +105 -0
- package/dist/apps/gate.js +273 -0
- package/dist/apps/index.d.ts +5 -0
- package/dist/apps/index.js +5 -0
- package/dist/apps/installation.d.ts +248 -0
- package/dist/apps/installation.js +307 -0
- package/dist/apps/operations.d.ts +8 -0
- package/dist/apps/operations.js +98 -0
- package/dist/apps/tools.d.ts +33 -0
- package/dist/apps/tools.js +17 -0
- package/dist/auth.d.ts +11 -0
- package/dist/auth.js +93 -0
- package/dist/backend-request.d.ts +3 -0
- package/dist/backend-request.js +53 -0
- package/dist/build/artifact-writer.d.ts +40 -0
- package/dist/build/artifact-writer.js +181 -0
- package/dist/build/build-jobs.d.ts +128 -0
- package/dist/build/build-jobs.js +203 -0
- package/dist/build/build-policy.d.ts +10 -0
- package/dist/build/build-policy.js +10 -0
- package/dist/build/build-step.d.ts +37 -0
- package/dist/build/build-step.js +28 -0
- package/dist/build/bundled-html.d.ts +7 -0
- package/dist/build/bundled-html.js +64 -0
- package/dist/build/candidate-builder.d.ts +68 -0
- package/dist/build/candidate-builder.js +91 -0
- package/dist/build/candidate-cli.d.ts +1 -0
- package/dist/build/candidate-cli.js +119 -0
- package/dist/build/candidate-cli.mjs +28170 -0
- package/dist/build/content-objects.d.ts +37 -0
- package/dist/build/content-objects.js +53 -0
- package/dist/build/definition-emission.d.ts +34 -0
- package/dist/build/definition-emission.js +201 -0
- package/dist/build/effect.d.ts +249 -0
- package/dist/build/effect.js +436 -0
- package/dist/build/git-environment.d.ts +9 -0
- package/dist/build/git-environment.js +60 -0
- package/dist/build/html-recipe.d.ts +20 -0
- package/dist/build/html-recipe.js +51 -0
- package/dist/build/local-build.d.ts +67 -0
- package/dist/build/local-build.js +1128 -0
- package/dist/build/snapshot-package-store.d.ts +12 -0
- package/dist/build/snapshot-package-store.js +36 -0
- package/dist/build/snapshot-program-scripts.d.ts +6 -0
- package/dist/build/snapshot-program-scripts.js +2 -0
- package/dist/build/snapshot-programs/snapshot-path.d.ts +2 -0
- package/dist/build/snapshot-programs/snapshot-path.js +6 -0
- package/dist/build/submission-contract.d.ts +828 -0
- package/dist/build/submission-contract.js +180 -0
- package/dist/build/workspace-build.d.ts +55 -0
- package/dist/build/workspace-build.js +200 -0
- package/dist/build-contract.d.ts +7 -0
- package/dist/build-contract.js +7 -0
- package/dist/build-egress.d.ts +62 -0
- package/dist/build-egress.js +148 -0
- package/dist/build-jobs.d.ts +2 -0
- package/dist/build-jobs.js +2 -0
- package/dist/build.d.ts +12 -0
- package/dist/build.js +14 -0
- package/dist/capability-descriptor.d.ts +46 -0
- package/dist/capability-descriptor.js +51 -0
- package/dist/catalog-frame.d.ts +39 -0
- package/dist/catalog-frame.js +72 -0
- package/dist/cause-class.d.ts +19 -0
- package/dist/cause-class.js +54 -0
- package/dist/cloudflare.d.ts +123 -0
- package/dist/cloudflare.js +391 -0
- package/dist/computer-terminal.d.ts +38 -0
- package/dist/computer-terminal.js +410 -0
- package/dist/computer.d.ts +60 -0
- package/dist/computer.js +33 -0
- package/dist/event-recipients.d.ts +57 -0
- package/dist/event-recipients.js +144 -0
- package/dist/facet-invocation.d.ts +4 -0
- package/dist/facet-invocation.js +45 -0
- package/dist/files.d.ts +42 -0
- package/dist/files.js +123 -0
- package/dist/frame-binding-wire-script.d.ts +2 -0
- package/dist/frame-binding-wire-script.js +1 -0
- package/dist/frame-binding-wire.d.ts +28 -0
- package/dist/frame-binding-wire.js +54 -0
- package/dist/git-admission.d.ts +52 -0
- package/dist/git-admission.js +188 -0
- package/dist/git-auth.d.ts +11 -0
- package/dist/git-auth.js +27 -0
- package/dist/git-door.d.ts +35 -0
- package/dist/git-door.js +108 -0
- package/dist/git-journal.d.ts +31 -0
- package/dist/git-journal.js +188 -0
- package/dist/git.d.ts +31 -0
- package/dist/git.js +64 -0
- package/dist/guest-policy.d.ts +9 -0
- package/dist/guest-policy.js +13 -0
- package/dist/host.d.ts +244 -0
- package/dist/host.js +1043 -0
- package/dist/index.d.ts +166 -0
- package/dist/index.js +320 -0
- package/dist/installation-consent.d.ts +79 -0
- package/dist/installation-consent.js +82 -0
- package/dist/internal/background-origins.d.ts +3 -0
- package/dist/internal/background-origins.js +8 -0
- package/dist/internal/delivery.d.ts +12 -0
- package/dist/internal/delivery.js +167 -0
- package/dist/internal/host-gate.d.ts +14 -0
- package/dist/internal/host-gate.js +62 -0
- package/dist/internal/registry-installations.d.ts +6 -0
- package/dist/internal/registry-installations.js +12 -0
- package/dist/invocation.d.ts +251 -0
- package/dist/invocation.js +377 -0
- package/dist/keys.d.ts +48 -0
- package/dist/keys.js +52 -0
- package/dist/mcp-owner.d.ts +27 -0
- package/dist/mcp-owner.js +155 -0
- package/dist/mcp.d.ts +89 -0
- package/dist/mcp.js +429 -0
- package/dist/media.d.ts +23 -0
- package/dist/media.js +12 -0
- package/dist/pack.d.ts +79 -0
- package/dist/pack.js +151 -0
- package/dist/page/capabilities.d.ts +23 -0
- package/dist/page/capabilities.js +256 -0
- package/dist/page/computer-handles.d.ts +79 -0
- package/dist/page/computer-handles.js +44 -0
- package/dist/page/gill-observation.d.ts +4 -0
- package/dist/page/gill-observation.js +31 -0
- package/dist/page/lifetime.d.ts +6 -0
- package/dist/page/lifetime.js +19 -0
- package/dist/page/mount.d.ts +163 -0
- package/dist/page/mount.js +390 -0
- package/dist/page/storage.d.ts +3 -0
- package/dist/page/storage.js +82 -0
- package/dist/page/terminal.d.ts +5 -0
- package/dist/page/terminal.js +7 -0
- package/dist/page/window-launch.d.ts +18 -0
- package/dist/page/window-launch.js +11 -0
- package/dist/page-script.d.ts +14 -0
- package/dist/page-script.js +5 -0
- package/dist/r2-files.d.ts +3 -0
- package/dist/r2-files.js +79 -0
- package/dist/release.d.ts +83 -0
- package/dist/release.js +167 -0
- package/dist/root-data.d.ts +86 -0
- package/dist/root-data.js +69 -0
- package/dist/shell/app-directory.d.ts +542 -0
- package/dist/shell/app-directory.js +199 -0
- package/dist/shell/browser-actions.d.ts +7 -0
- package/dist/shell/browser-actions.js +56 -0
- package/dist/shell/command-host.d.ts +112 -0
- package/dist/shell/command-host.js +502 -0
- package/dist/shell/commands.d.ts +25 -0
- package/dist/shell/commands.js +78 -0
- package/dist/shell/index.d.ts +8 -0
- package/dist/shell/index.js +8 -0
- package/dist/shell/keys.d.ts +41 -0
- package/dist/shell/keys.js +134 -0
- package/dist/shell/shell-module.d.ts +55 -0
- package/dist/shell/shell-module.js +86 -0
- package/dist/shell/window-manager.d.ts +124 -0
- package/dist/shell/window-manager.js +711 -0
- package/dist/shell/workbench-contract.d.ts +68 -0
- package/dist/shell/workbench-contract.js +1 -0
- package/dist/shell/workbench-directory.d.ts +332 -0
- package/dist/shell/workbench-directory.js +35 -0
- package/dist/shell/workbench-host-types.d.ts +96 -0
- package/dist/shell/workbench-host-types.js +1 -0
- package/dist/shell/workbench-host.d.ts +34 -0
- package/dist/shell/workbench-host.js +347 -0
- package/dist/shell/workbench-model.d.ts +192 -0
- package/dist/shell/workbench-model.js +53 -0
- package/dist/shell/workbench.d.ts +4 -0
- package/dist/shell/workbench.js +2 -0
- package/dist/source/fork.d.ts +27 -0
- package/dist/source/fork.js +46 -0
- package/dist/source/index.d.ts +10 -0
- package/dist/source/index.js +10 -0
- package/dist/source/seed-receipt.d.ts +53 -0
- package/dist/source/seed-receipt.js +18 -0
- package/dist/source/team-source.d.ts +32 -0
- package/dist/source/team-source.js +42 -0
- package/dist/source/template-push.d.ts +33 -0
- package/dist/source/template-push.js +223 -0
- package/dist/source/template-repository.d.ts +4 -0
- package/dist/source/template-repository.js +21 -0
- package/dist/source/template-seed.d.ts +68 -0
- package/dist/source/template-seed.js +80 -0
- package/dist/standalone/agent-directory.d.ts +4 -0
- package/dist/standalone/agent-directory.js +4 -0
- package/dist/standalone/agents.d.ts +220 -0
- package/dist/standalone/agents.js +795 -0
- package/dist/standalone/app-builds-binding.d.ts +36 -0
- package/dist/standalone/app-builds-binding.js +119 -0
- package/dist/standalone/app-set.d.ts +91 -0
- package/dist/standalone/app-set.js +395 -0
- package/dist/standalone/app-source.d.ts +41 -0
- package/dist/standalone/app-source.js +59 -0
- package/dist/standalone/builds.d.ts +18 -0
- package/dist/standalone/builds.js +101 -0
- package/dist/standalone/computer-egress.d.ts +37 -0
- package/dist/standalone/computer-egress.js +111 -0
- package/dist/standalone/computer.d.ts +122 -0
- package/dist/standalone/computer.js +714 -0
- package/dist/standalone/install-apps-cli.d.ts +2 -0
- package/dist/standalone/install-apps-cli.js +126 -0
- package/dist/standalone/instance.d.ts +35 -0
- package/dist/standalone/instance.js +74 -0
- package/dist/standalone/media.d.ts +76 -0
- package/dist/standalone/media.js +227 -0
- package/dist/standalone/preview.d.ts +51 -0
- package/dist/standalone/preview.js +167 -0
- package/dist/standalone/registry.d.ts +102 -0
- package/dist/standalone/registry.js +193 -0
- package/dist/standalone/tenancy.d.ts +42 -0
- package/dist/standalone/tenancy.js +241 -0
- package/dist/standalone/worker.d.ts +55 -0
- package/dist/standalone/worker.js +147 -0
- package/dist/standalone/workflow-authority-readers.d.ts +16 -0
- package/dist/standalone/workflow-authority-readers.js +35 -0
- package/dist/standalone/workflow-binding.d.ts +216 -0
- package/dist/standalone/workflow-binding.js +217 -0
- package/dist/standalone/workflow-events.d.ts +46 -0
- package/dist/standalone/workflow-events.js +39 -0
- package/dist/standalone/workflow-git-capture.d.ts +7 -0
- package/dist/standalone/workflow-git-capture.js +62 -0
- package/dist/standalone/workflow-host.d.ts +931 -0
- package/dist/standalone/workflow-host.js +751 -0
- package/dist/standalone/workflow-node-capture.d.ts +13 -0
- package/dist/standalone/workflow-node-capture.js +72 -0
- package/dist/standalone/workflow-root-authority.d.ts +27 -0
- package/dist/standalone/workflow-root-authority.js +87 -0
- package/dist/standalone/workflow-schedules.d.ts +52 -0
- package/dist/standalone/workflow-schedules.js +40 -0
- package/dist/standalone/workflow-trigger-host.d.ts +1694 -0
- package/dist/standalone/workflow-trigger-host.js +52 -0
- package/dist/standalone/workflows.d.ts +657 -0
- package/dist/standalone/workflows.js +554 -0
- package/dist/storage-frame.d.ts +64 -0
- package/dist/storage-frame.js +28 -0
- package/dist/tenancy/auth0.d.ts +64 -0
- package/dist/tenancy/auth0.js +198 -0
- package/dist/tenancy/cloudflare/rate-limit.d.ts +8 -0
- package/dist/tenancy/cloudflare/rate-limit.js +19 -0
- package/dist/tenancy/cloudflare/registry.d.ts +50 -0
- package/dist/tenancy/cloudflare/registry.js +301 -0
- package/dist/tenancy/cloudflare.d.ts +2 -0
- package/dist/tenancy/cloudflare.js +2 -0
- package/dist/tenancy/cold-directory.d.ts +13 -0
- package/dist/tenancy/cold-directory.js +43 -0
- package/dist/tenancy/contracts.d.ts +195 -0
- package/dist/tenancy/contracts.js +1 -0
- package/dist/tenancy/index.d.ts +19 -0
- package/dist/tenancy/index.js +156 -0
- package/dist/tenancy/owner-key.d.ts +26 -0
- package/dist/tenancy/owner-key.js +63 -0
- package/dist/tenancy/oyster.d.ts +4 -0
- package/dist/tenancy/oyster.js +25 -0
- package/dist/tenancy/registry-record.d.ts +7 -0
- package/dist/tenancy/registry-record.js +44 -0
- package/dist/tenancy/registry.d.ts +27 -0
- package/dist/tenancy/registry.js +138 -0
- package/dist/tenancy/resolve.d.ts +7 -0
- package/dist/tenancy/resolve.js +64 -0
- package/dist/tenant.d.ts +81 -0
- package/dist/tenant.js +71 -0
- package/dist/testing/capabilities.d.ts +29 -0
- package/dist/testing/capabilities.js +130 -0
- package/dist/testing/catalog.d.ts +3 -0
- package/dist/testing/catalog.js +53 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.js +10 -0
- package/dist/testing/installation.d.ts +11 -0
- package/dist/testing/installation.js +25 -0
- package/dist/testing/native-worker.d.ts +21 -0
- package/dist/testing/native-worker.js +106 -0
- package/dist/testing/worker.d.ts +18 -0
- package/dist/testing/worker.js +67 -0
- package/dist/testing/workers-runtime.d.ts +24 -0
- package/dist/testing/workers-runtime.js +33 -0
- package/dist/webhook-delivery.d.ts +14 -0
- package/dist/webhook-delivery.js +17 -0
- package/dist/workers-git.d.ts +285 -0
- package/dist/workers-git.js +1174 -0
- package/dist/workers.d.ts +352 -0
- package/dist/workers.js +868 -0
- package/docs/api/README.md +82 -0
- package/docs/api/agents.md +332 -0
- package/docs/api/app-storage.md +209 -0
- package/docs/api/apps.md +1375 -0
- package/docs/api/auth.md +63 -0
- package/docs/api/build-contract.md +1304 -0
- package/docs/api/build.md +1712 -0
- package/docs/api/cloudflare.md +421 -0
- package/docs/api/computer.md +203 -0
- package/docs/api/files.md +117 -0
- package/docs/api/git.md +470 -0
- package/docs/api/host.md +1328 -0
- package/docs/api/index.md +430 -0
- package/docs/api/invocation.md +738 -0
- package/docs/api/keys.md +175 -0
- package/docs/api/mcp.md +301 -0
- package/docs/api/media.md +40 -0
- package/docs/api/modules.md +50 -0
- package/docs/api/pack.md +141 -0
- package/docs/api/page/mount.md +298 -0
- package/docs/api/root-data.md +111 -0
- package/docs/api/shell/app-directory.md +599 -0
- package/docs/api/shell/command-host.md +224 -0
- package/docs/api/shell/commands.md +197 -0
- package/docs/api/shell/keys.md +183 -0
- package/docs/api/shell/shell-module.md +204 -0
- package/docs/api/shell/window-manager.md +267 -0
- package/docs/api/shell/workbench-directory.md +119 -0
- package/docs/api/shell/workbench.md +205 -0
- package/docs/api/shell.md +1915 -0
- package/docs/api/tenancy/auth0.md +110 -0
- package/docs/api/tenancy/cloudflare.md +221 -0
- package/docs/api/tenancy/cold-directory.md +46 -0
- package/docs/api/tenancy/owner-key.md +63 -0
- package/docs/api/tenancy/registry.md +77 -0
- package/docs/api/tenancy/resolve.md +69 -0
- package/docs/api/tenancy.md +430 -0
- package/docs/api/tenant.md +194 -0
- package/docs/api/workers-git.md +1646 -0
- package/docs/api/workers.md +1691 -0
- package/docs/site/agent-quickstart.mdx +346 -0
- package/examples/standalone/worker.ts +7 -0
- package/examples/standalone/wrangler.jsonc +82 -0
- package/package.json +300 -3
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Agent quick start
|
|
3
|
+
description:
|
|
4
|
+
Hand this guide to a coding agent to install Oyster from npm, run it locally,
|
|
5
|
+
install an App, connect over MCP and deploy.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are an agent setting up Oyster for a person. Follow these steps in order.
|
|
9
|
+
Run every command exactly as written, from the directory each step names.
|
|
10
|
+
Compare its output with the expected output before you go on. When a step fails,
|
|
11
|
+
read the "If it fails" notes under it before trying anything else.
|
|
12
|
+
|
|
13
|
+
## What Oyster is
|
|
14
|
+
|
|
15
|
+
- Oyster hosts Apps on one Cloudflare Worker, or on celld, a Workers-compatible
|
|
16
|
+
runtime you host yourself.
|
|
17
|
+
- Each App is an immutable Release built from an exact git commit. Its backend
|
|
18
|
+
runs in its own Durable Object with its own SQLite, and it gets only the
|
|
19
|
+
bindings it declares.
|
|
20
|
+
- People use Apps in a browser. Agents call the same App methods over HTTP or
|
|
21
|
+
through one MCP endpoint, `/mcp`.
|
|
22
|
+
|
|
23
|
+
## 1. Check prerequisites
|
|
24
|
+
|
|
25
|
+
You need Node 24 or newer, pnpm, Git, curl and openssl. You do not need a
|
|
26
|
+
Cloudflare account until step 7. Docker is needed only in step 7, where Wrangler
|
|
27
|
+
builds the Computer's container image.
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
node --version
|
|
31
|
+
pnpm --version
|
|
32
|
+
git --version
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Expected output: a `v24.` or later Node version, any pnpm version, then any
|
|
36
|
+
`git version 2.x` line.
|
|
37
|
+
|
|
38
|
+
If it fails:
|
|
39
|
+
|
|
40
|
+
- Wrong Node: install Node 24 with your version manager, for example
|
|
41
|
+
`mise use node@24` or `nvm install 24`.
|
|
42
|
+
- No pnpm: run `corepack enable`, or use `npm install` wherever this guide says
|
|
43
|
+
`pnpm add`.
|
|
44
|
+
|
|
45
|
+
## 2. Create a project
|
|
46
|
+
|
|
47
|
+
Make a new directory, install Oyster, its Computer and Wrangler, and copy the
|
|
48
|
+
example Worker out of the package:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
mkdir my-oyster
|
|
52
|
+
cd my-oyster
|
|
53
|
+
pnpm add @fungi.computer/oyster @fungi.computer/computer
|
|
54
|
+
pnpm add -D wrangler
|
|
55
|
+
cp node_modules/@fungi.computer/oyster/examples/standalone/worker.ts .
|
|
56
|
+
cp node_modules/@fungi.computer/oyster/examples/standalone/wrangler.jsonc .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Expected output: pnpm lists the added package after each `add`, and `ls` now
|
|
60
|
+
shows `node_modules`, `package.json`, `worker.ts` and `wrangler.jsonc`.
|
|
61
|
+
|
|
62
|
+
Every later command runs from this `my-oyster` directory unless the step says
|
|
63
|
+
otherwise.
|
|
64
|
+
|
|
65
|
+
If it fails:
|
|
66
|
+
|
|
67
|
+
- `ERR_PNPM_IGNORED_BUILDS` naming packages such as `esbuild`, `workerd` or
|
|
68
|
+
`protobufjs`: pnpm installed them without running their install scripts, and
|
|
69
|
+
nothing in this guide needs those scripts. Go on.
|
|
70
|
+
- `cp: cannot stat …/examples/standalone/…`: the install did not finish. Run
|
|
71
|
+
`pnpm add @fungi.computer/oyster @fungi.computer/computer` again and read its
|
|
72
|
+
first error.
|
|
73
|
+
|
|
74
|
+
## 3. Run a local Oyster
|
|
75
|
+
|
|
76
|
+
`worker.ts` and `wrangler.jsonc` are the whole Oyster. Run it under
|
|
77
|
+
`wrangler dev` on your machine, without its Computer container. Oyster serves an
|
|
78
|
+
HTTPS origin; `--local-upstream` presents your loopback requests to it at
|
|
79
|
+
`https://oyster.test`. Choose an owner key and keep this terminal open:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
export OYSTER_OWNER_KEY=$(openssl rand -hex 24)
|
|
83
|
+
export OYSTER_URL=http://127.0.0.1:8787
|
|
84
|
+
echo "$OYSTER_OWNER_KEY" > .oyster-owner-key
|
|
85
|
+
npx wrangler dev --local --enable-containers=false --ip 127.0.0.1 --port 8787 \
|
|
86
|
+
--local-upstream oyster.test --upstream-protocol https \
|
|
87
|
+
--var OYSTER_OWNER_KEY:$OYSTER_OWNER_KEY --var OYSTER_ORIGIN:https://oyster.test
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Expected output: warnings that the AI and Artifacts bindings reach remote
|
|
91
|
+
resources, a bindings table listing `env.REGISTRY (OysterRegistry)`,
|
|
92
|
+
`env.INSTANCES (StandaloneInstance)`, `env.COMPUTER (ComputerDO)` and the rest,
|
|
93
|
+
then `Ready on http://127.0.0.1:8787`. Locally there is no Computer, git storage
|
|
94
|
+
or Workers AI; steps 3 to 5 need none of them.
|
|
95
|
+
|
|
96
|
+
Keep it running. Open a second terminal in `my-oyster`, set the same two
|
|
97
|
+
variables there, and check that Oyster answers:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
export OYSTER_OWNER_KEY=$(cat .oyster-owner-key)
|
|
101
|
+
export OYSTER_URL=http://127.0.0.1:8787
|
|
102
|
+
curl -s -o /dev/null -w '%{http_code}\n' $OYSTER_URL/login
|
|
103
|
+
curl -s -o /dev/null -w '%{http_code}\n' $OYSTER_URL/api/installations
|
|
104
|
+
curl -s -H "Authorization: Bearer $OYSTER_OWNER_KEY" $OYSTER_URL/api/installations
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Expected output: `200`, then `401` (no key), then `[]` (no Apps installed yet).
|
|
108
|
+
|
|
109
|
+
If it fails:
|
|
110
|
+
|
|
111
|
+
- `Address already in use`: another process holds port 8787. Pick another port
|
|
112
|
+
and use it in both `--port` and `OYSTER_URL`.
|
|
113
|
+
- `curl` prints `000`: the server is not ready yet. Wait for the `Ready on`
|
|
114
|
+
line.
|
|
115
|
+
- `401` with the key: the two terminals hold different keys. Set
|
|
116
|
+
`OYSTER_OWNER_KEY` from `.oyster-owner-key` in both.
|
|
117
|
+
- An agent runtime that cannot keep a process in the foreground starts the same
|
|
118
|
+
command in the background with its output in a log, then waits until the
|
|
119
|
+
`/login` check prints `200`:
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
npx wrangler dev --local --enable-containers=false --ip 127.0.0.1 --port 8787 \
|
|
123
|
+
--local-upstream oyster.test --upstream-protocol https \
|
|
124
|
+
--var OYSTER_OWNER_KEY:$OYSTER_OWNER_KEY --var OYSTER_ORIGIN:https://oyster.test \
|
|
125
|
+
> oyster-dev.log 2>&1 &
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
To stop the server, press Ctrl-C in its terminal. A background server runs as
|
|
129
|
+
several processes (`npm exec`, `wrangler.js` and `workerd`); stop them all by
|
|
130
|
+
ending `wrangler.js`, then check that `/login` prints `000`:
|
|
131
|
+
|
|
132
|
+
```sh
|
|
133
|
+
pkill -f 'wrangler[.]js dev .*--port 8787'
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## 4. Add an App
|
|
137
|
+
|
|
138
|
+
An App is a git repository with a `package.json` that declares it under
|
|
139
|
+
`fungi.app`. Make the smallest one, a single committed HTML page:
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
mkdir -p hello-app/bundle
|
|
143
|
+
cat > hello-app/package.json <<'EOF'
|
|
144
|
+
{
|
|
145
|
+
"name": "hello-app",
|
|
146
|
+
"private": true,
|
|
147
|
+
"fungi": { "app": { "displayName": "Hello", "capabilities": [] } }
|
|
148
|
+
}
|
|
149
|
+
EOF
|
|
150
|
+
cat > hello-app/bundle/index.html <<'EOF'
|
|
151
|
+
<!doctype html>
|
|
152
|
+
<title>Hello</title>
|
|
153
|
+
<h1>Hello from my first Oyster App</h1>
|
|
154
|
+
EOF
|
|
155
|
+
git -C hello-app init -q
|
|
156
|
+
git -C hello-app add .
|
|
157
|
+
git -C hello-app -c user.name=Oyster -c user.email=oyster@example.invalid \
|
|
158
|
+
commit -qm "Hello App"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Then pack that commit into a Release and install it as installation `hello` with
|
|
162
|
+
`@fungi.computer/oyster/pack`:
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
cat > install-hello.mjs <<'EOF'
|
|
166
|
+
import { execFileSync } from "node:child_process";
|
|
167
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
168
|
+
import { tmpdir } from "node:os";
|
|
169
|
+
import { join, resolve } from "node:path";
|
|
170
|
+
import process from "node:process";
|
|
171
|
+
import { installRelease, packRelease } from "@fungi.computer/oyster/pack";
|
|
172
|
+
|
|
173
|
+
const source = resolve("hello-app");
|
|
174
|
+
const commit = execFileSync("git", ["-C", source, "rev-parse", "HEAD"], {
|
|
175
|
+
encoding: "utf8",
|
|
176
|
+
}).trim();
|
|
177
|
+
const out = await mkdtemp(join(tmpdir(), "oyster-hello-"));
|
|
178
|
+
try {
|
|
179
|
+
await packRelease({
|
|
180
|
+
appId: "app_hello",
|
|
181
|
+
sourceDirectory: source,
|
|
182
|
+
sourceRevision: `git:${commit}`,
|
|
183
|
+
recipe: {
|
|
184
|
+
kind: "bundled-html",
|
|
185
|
+
entry: "bundle/index.html",
|
|
186
|
+
assets: {
|
|
187
|
+
maxManifestBytes: 65_536,
|
|
188
|
+
maxObjects: 16,
|
|
189
|
+
maxObjectBytes: 1_048_576,
|
|
190
|
+
maxTotalBytes: 4_194_304,
|
|
191
|
+
},
|
|
192
|
+
assetBase: "./",
|
|
193
|
+
backend: null,
|
|
194
|
+
maxOutputBytes: 4_194_304,
|
|
195
|
+
},
|
|
196
|
+
outDirectory: join(out, "release"),
|
|
197
|
+
});
|
|
198
|
+
const response = await installRelease({
|
|
199
|
+
directory: join(out, "release"),
|
|
200
|
+
url: process.env.OYSTER_URL,
|
|
201
|
+
key: process.env.OYSTER_OWNER_KEY,
|
|
202
|
+
installationId: "hello",
|
|
203
|
+
});
|
|
204
|
+
console.log(`installed hello: ${response.status} ${await response.text()}`);
|
|
205
|
+
} finally {
|
|
206
|
+
await rm(out, { recursive: true, force: true });
|
|
207
|
+
}
|
|
208
|
+
EOF
|
|
209
|
+
node install-hello.mjs
|
|
210
|
+
curl -s -o /dev/null -w '%{http_code}\n' \
|
|
211
|
+
-H "Authorization: Bearer $OYSTER_OWNER_KEY" $OYSTER_URL/apps/hello/
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Expected output: one line starting
|
|
215
|
+
`installed hello: 201 {"installationId":"hello",` and containing
|
|
216
|
+
`"status":"enabled"`, then `200`. Running `node install-hello.mjs` again prints
|
|
217
|
+
`installed hello: 200`: the installation already exists, and Oyster switches it
|
|
218
|
+
to the Release just packed.
|
|
219
|
+
|
|
220
|
+
A person can open `$OYSTER_URL/login`, sign in with the owner key, and open
|
|
221
|
+
Hello from the installation list at `$OYSTER_URL/`.
|
|
222
|
+
|
|
223
|
+
If it fails:
|
|
224
|
+
|
|
225
|
+
- `installed hello: 401`: `OYSTER_OWNER_KEY` in this terminal differs from the
|
|
226
|
+
server's. Set it from `.oyster-owner-key`.
|
|
227
|
+
- `fetch failed` or `ECONNREFUSED`: the server from step 3 is not running.
|
|
228
|
+
- The build reads committed files only. To install an edit, commit it in
|
|
229
|
+
`hello-app` and run `node install-hello.mjs` again; Oyster switches the
|
|
230
|
+
installation to the new Release and keeps its data.
|
|
231
|
+
|
|
232
|
+
An App with a backend, typed methods and its own SQLite adds
|
|
233
|
+
`fungi.backendDefinition` and a `backend` entry to its recipe. The
|
|
234
|
+
[Notes example App](https://github.com/fungi-computer/oyster/tree/main/examples/notes-app)
|
|
235
|
+
is one, and the Oyster README's "Pack an App" and "Build App Releases" sections
|
|
236
|
+
describe the recipe.
|
|
237
|
+
|
|
238
|
+
## 5. Connect over MCP
|
|
239
|
+
|
|
240
|
+
`/mcp` serves every installed App to MCP clients through one `execute` tool, in
|
|
241
|
+
which each App's methods are `env.<APP>`. The owner key signs in. For Claude
|
|
242
|
+
Code:
|
|
243
|
+
|
|
244
|
+
```sh
|
|
245
|
+
claude mcp add --transport http oyster "$OYSTER_URL/mcp" \
|
|
246
|
+
--header "Authorization: Bearer $OYSTER_OWNER_KEY"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
To check `/mcp` without an MCP client, open a session and list its tools:
|
|
250
|
+
|
|
251
|
+
```sh
|
|
252
|
+
MCP=(-H "Authorization: Bearer $OYSTER_OWNER_KEY" -H 'content-type: application/json' -H 'accept: application/json, text/event-stream')
|
|
253
|
+
SESSION=$(curl -s "${MCP[@]}" -D - -o /dev/null \
|
|
254
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}' \
|
|
255
|
+
$OYSTER_URL/mcp | grep -i '^mcp-session-id' | cut -d' ' -f2 | tr -d '\r')
|
|
256
|
+
curl -s "${MCP[@]}" -H "mcp-session-id: $SESSION" -H 'mcp-protocol-version: 2025-11-25' \
|
|
257
|
+
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}' $OYSTER_URL/mcp
|
|
258
|
+
curl -s "${MCP[@]}" -H "mcp-session-id: $SESSION" -H 'mcp-protocol-version: 2025-11-25' \
|
|
259
|
+
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' $OYSTER_URL/mcp
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Expected output: the last command prints an `event: message` block whose `data:`
|
|
263
|
+
line contains `"name":"execute"`.
|
|
264
|
+
|
|
265
|
+
If it fails:
|
|
266
|
+
|
|
267
|
+
- `SESSION` is empty: the `initialize` call was refused. Check the key as in
|
|
268
|
+
step 3.
|
|
269
|
+
- Named keys for each agent (`POST /api/keys`) come with the Git worker in
|
|
270
|
+
step 6. The plain standalone Worker answers `404` there.
|
|
271
|
+
|
|
272
|
+
## 6. Add Git
|
|
273
|
+
|
|
274
|
+
Git is already part of the host: people and agents `clone`, `fetch` and `push`
|
|
275
|
+
App repositories with ordinary `git` at `/git/<installation>/<repo>.git`, with
|
|
276
|
+
repositories in Cloudflare Artifacts. Artifacts runs only once the Worker is
|
|
277
|
+
deployed in step 7. There, give each agent its own key:
|
|
278
|
+
|
|
279
|
+
```sh
|
|
280
|
+
curl -s -X POST -H "Authorization: Bearer $OYSTER_OWNER_KEY" \
|
|
281
|
+
-H 'content-type: application/json' \
|
|
282
|
+
-d '{"name":"morel","grants":[{"capability":"apps.use","targets":{"kind":"all"}}]}' \
|
|
283
|
+
$OYSTER_URL/api/keys
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Expected output: JSON with a `plaintext` field starting `oyk_`. Oyster shows it
|
|
287
|
+
once; that key signs in to `git` and to `/mcp`.
|
|
288
|
+
|
|
289
|
+
## 7. Deploy to Cloudflare Workers
|
|
290
|
+
|
|
291
|
+
This step needs a Cloudflare account on Workers Paid with Containers, Artifacts,
|
|
292
|
+
Workers AI and Workflows enabled, and Docker running on this machine. Ask the
|
|
293
|
+
person before you deploy anything.
|
|
294
|
+
|
|
295
|
+
`wrangler.jsonc` names the Worker `oyster`, its R2 bucket `oyster-releases` and
|
|
296
|
+
its Artifacts namespace `oyster`. The Worker's address is
|
|
297
|
+
`https://oyster.<your-subdomain>.workers.dev`, or a custom domain:
|
|
298
|
+
|
|
299
|
+
```sh
|
|
300
|
+
npx wrangler login
|
|
301
|
+
npx wrangler r2 bucket create oyster-releases
|
|
302
|
+
export OYSTER_URL=https://oyster.<your-subdomain>.workers.dev
|
|
303
|
+
npx wrangler deploy --var OYSTER_ORIGIN:$OYSTER_URL
|
|
304
|
+
printf '%s' "$OYSTER_OWNER_KEY" | npx wrangler secret put OYSTER_OWNER_KEY
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Expected output: `wrangler deploy` builds the Computer image, uploads it and
|
|
308
|
+
prints the deployed `https://` URL, and `wrangler secret put` reports the secret
|
|
309
|
+
uploaded.
|
|
310
|
+
|
|
311
|
+
Then install Fungi's seven starter Apps, each built on this Oyster's Computer
|
|
312
|
+
from its own repository:
|
|
313
|
+
|
|
314
|
+
```sh
|
|
315
|
+
npx oyster install-apps
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Expected output: a `source recorded` line per App, `Building … on the Computer`
|
|
319
|
+
and `Installed …` lines (two builds at a time, Tourtois first), a timing table,
|
|
320
|
+
and `Installed 7 Apps`. Open `$OYSTER_URL/login` with the owner key to see the
|
|
321
|
+
Tourtois desktop.
|
|
322
|
+
|
|
323
|
+
To keep `OYSTER_ORIGIN` across later deploys, set `vars.OYSTER_ORIGIN` in
|
|
324
|
+
`wrangler.jsonc`; every deploy replaces the Worker's variables.
|
|
325
|
+
|
|
326
|
+
If it fails:
|
|
327
|
+
|
|
328
|
+
- `R2 bucket … already exists`: use that bucket, or pick a new name and put it
|
|
329
|
+
in `wrangler.jsonc`.
|
|
330
|
+
- A secret prompt on stdin: pipe the key as shown; never type it into a log.
|
|
331
|
+
- Bindings or migrations refused: deploy the copied `wrangler.jsonc` unchanged
|
|
332
|
+
except for `vars` and the bucket name.
|
|
333
|
+
- `docker` not found or not running: start Docker; Wrangler builds the Computer
|
|
334
|
+
image from `node_modules/@fungi.computer/computer/Dockerfile`.
|
|
335
|
+
- A build `failed` in `install-apps`: run it again; finished Apps are kept and
|
|
336
|
+
replaced in place.
|
|
337
|
+
|
|
338
|
+
## Where to go next
|
|
339
|
+
|
|
340
|
+
- The Oyster README (`node_modules/@fungi.computer/oyster/README.md`) explains
|
|
341
|
+
the host, Apps, capabilities, MCP and the shell in depth.
|
|
342
|
+
- [oyster.shiit.app](https://oyster.shiit.app/) runs this same host with the
|
|
343
|
+
seven starter Apps.
|
|
344
|
+
- Oyster is built from the other Fungi packages, each its own repository under
|
|
345
|
+
[github.com/fungi-computer](https://github.com/fungi-computer) and on npm as
|
|
346
|
+
`@fungi.computer/<name>`. The README's "Part of Fungi" section lists them.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// The whole Oyster: Apps installed from Releases, each with its own Durable
|
|
2
|
+
// Object and SQLite; git through Artifacts; a Computer in a Cloudflare
|
|
3
|
+
// Container that builds App sources and runs terminals and files; Agents on
|
|
4
|
+
// Workers AI; Workflows; and media. Runs on Cloudflare Workers
|
|
5
|
+
// (`wrangler deploy`) and on celld from the same code.
|
|
6
|
+
export * from "@fungi.computer/oyster/standalone";
|
|
7
|
+
export { default } from "@fungi.computer/oyster/standalone";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/wrangler/config-schema.json",
|
|
3
|
+
// The whole Oyster. Copy it beside worker.ts, set OYSTER_ORIGIN, and deploy.
|
|
4
|
+
"name": "oyster",
|
|
5
|
+
"main": "worker.ts",
|
|
6
|
+
"compatibility_date": "2026-09-04",
|
|
7
|
+
"compatibility_flags": ["nodejs_compat"],
|
|
8
|
+
"workers_dev": true,
|
|
9
|
+
"preview_urls": false,
|
|
10
|
+
"observability": { "enabled": true },
|
|
11
|
+
"workflows": [
|
|
12
|
+
{
|
|
13
|
+
"binding": "GRAPH_WORKFLOWS",
|
|
14
|
+
"name": "oyster-graphs",
|
|
15
|
+
"class_name": "StandaloneGraphWorkflow",
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
"worker_loaders": [{ "binding": "LOADER" }],
|
|
19
|
+
"containers": [
|
|
20
|
+
{
|
|
21
|
+
"class_name": "ComputerDO",
|
|
22
|
+
"image": "./node_modules/@fungi.computer/computer/Dockerfile",
|
|
23
|
+
"instance_type": "standard-4",
|
|
24
|
+
"max_instances": 1,
|
|
25
|
+
"rollout_active_grace_period": 0,
|
|
26
|
+
"rollout_step_percentage": [100],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
"ai": { "binding": "AI" },
|
|
30
|
+
"images": { "binding": "IMAGES" },
|
|
31
|
+
"r2_buckets": [
|
|
32
|
+
{ "binding": "RELEASES", "bucket_name": "oyster-releases" },
|
|
33
|
+
{ "binding": "APP_ARTIFACTS", "bucket_name": "oyster-releases" },
|
|
34
|
+
],
|
|
35
|
+
"artifacts": [{ "binding": "ARTIFACTS", "namespace": "oyster" }],
|
|
36
|
+
"vars": {
|
|
37
|
+
"OYSTER_COMPUTER_ID": "workspace",
|
|
38
|
+
"OYSTER_HOME_INSTALLATION": "tourtois",
|
|
39
|
+
"OYSTER_ORIGIN": "https://oyster.example",
|
|
40
|
+
"OYSTER_OWNER_NAME": "owner",
|
|
41
|
+
// Names the AI Gateway that Prints' third-party models (GPT Image 2,
|
|
42
|
+
// Seedance, Veo) and the background media retry owner route through.
|
|
43
|
+
// Not a secret: Cloudflare creates the gateway by this id on first use.
|
|
44
|
+
"AI_GATEWAY_ID": "oyster",
|
|
45
|
+
},
|
|
46
|
+
"durable_objects": {
|
|
47
|
+
"bindings": [
|
|
48
|
+
{ "name": "TENANTS", "class_name": "StandaloneTenants" },
|
|
49
|
+
{ "name": "MCP", "class_name": "OysterMcp" },
|
|
50
|
+
|
|
51
|
+
{ "name": "REGISTRY", "class_name": "OysterRegistry" },
|
|
52
|
+
{ "name": "WORKFLOW_RUNS", "class_name": "StandaloneWorkflowRuns" },
|
|
53
|
+
{ "name": "INSTANCES", "class_name": "StandaloneInstance" },
|
|
54
|
+
{ "name": "COMPUTER", "class_name": "ComputerDO" },
|
|
55
|
+
{ "name": "KEYS", "class_name": "OysterKeys" },
|
|
56
|
+
{ "name": "WEBHOOKS", "class_name": "OysterWebhooks" },
|
|
57
|
+
{ "name": "AGENTS", "class_name": "StandaloneAgent" },
|
|
58
|
+
{ "name": "AGENT_DIRECTORY", "class_name": "AgentDirectory" },
|
|
59
|
+
{ "name": "MEDIA_OPERATION", "class_name": "MediaOperationDO" },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
// One initial tag: pre-launch history was collapsed (Levi 10-14, data wipe
|
|
63
|
+
// authorized), so a fresh Worker creates every bound class at once.
|
|
64
|
+
"migrations": [
|
|
65
|
+
{
|
|
66
|
+
"tag": "oyster-v1",
|
|
67
|
+
"new_sqlite_classes": [
|
|
68
|
+
"StandaloneTenants",
|
|
69
|
+
"OysterMcp",
|
|
70
|
+
"OysterRegistry",
|
|
71
|
+
"StandaloneWorkflowRuns",
|
|
72
|
+
"StandaloneInstance",
|
|
73
|
+
"ComputerDO",
|
|
74
|
+
"OysterKeys",
|
|
75
|
+
"OysterWebhooks",
|
|
76
|
+
"StandaloneAgent",
|
|
77
|
+
"AgentDirectory",
|
|
78
|
+
"MediaOperationDO",
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
}
|