@fungi.computer/oyster 0.5.0 → 0.7.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/README.md +155 -63
- package/dist/agent-archive-projection.d.ts +8 -0
- package/dist/agent-archive-projection.js +49 -0
- package/dist/agent-schedules.d.ts +50 -0
- package/dist/agent-schedules.js +17 -0
- package/dist/agents.d.ts +35 -14
- package/dist/agents.js +97 -144
- package/dist/app-builds.d.ts +7 -2
- package/dist/app-builds.js +19 -2
- package/dist/approval-capability.d.ts +1 -1
- package/dist/approval-capability.js +11 -16
- package/dist/approval-home.d.ts +2 -1
- package/dist/approval-home.js +5 -3
- package/dist/apps/catalog.js +1 -1
- package/dist/apps/gate.d.ts +4 -7
- package/dist/apps/gate.js +14 -29
- package/dist/apps/index.d.ts +1 -1
- package/dist/apps/installation.d.ts +4 -42
- package/dist/apps/installation.js +7 -75
- package/dist/apps/operations.js +0 -10
- package/dist/apps/permissions.d.ts +18 -8
- package/dist/apps/permissions.js +7 -1
- package/dist/auth.js +9 -1
- package/dist/authorization.d.ts +307 -0
- package/dist/authorization.js +542 -0
- package/dist/boot-host-script.js +1 -1
- package/dist/build/build-jobs.d.ts +2 -2
- package/dist/build/candidate-builder.d.ts +2 -0
- package/dist/build/candidate-builder.js +5 -1
- package/dist/build/candidate-cli.js +3 -0
- package/dist/build/candidate-cli.mjs +67 -22
- package/dist/build/job-log.d.ts +23 -0
- package/dist/build/job-log.js +88 -0
- package/dist/build/local-build.d.ts +2 -0
- package/dist/build/local-build.js +11 -9
- package/dist/channels/binding.d.ts +8 -1
- package/dist/channels/binding.js +12 -0
- package/dist/channels/conversations.d.ts +16 -5
- package/dist/channels/visitor-channel.d.ts +53 -0
- package/dist/channels/visitor-channel.js +124 -0
- package/dist/channels/visitor-edge.d.ts +115 -0
- package/dist/channels/visitor-edge.js +582 -0
- package/dist/channels/visitor-request.d.ts +7 -0
- package/dist/channels/visitor-request.js +17 -0
- package/dist/channels/visitor-stream-slots.d.ts +2 -0
- package/dist/channels/visitor-stream-slots.js +33 -0
- package/dist/channels/visitors.d.ts +47 -0
- package/dist/channels/visitors.js +181 -0
- package/dist/cloudflare.d.ts +11 -2
- package/dist/cloudflare.js +27 -1
- package/dist/{page/computer-target.d.ts → computer-target.d.ts} +2 -0
- package/dist/{page/computer-target.js → computer-target.js} +3 -1
- package/dist/files.js +9 -8
- package/dist/git-admission.d.ts +3 -3
- package/dist/git-admission.js +4 -6
- package/dist/git-door.d.ts +8 -7
- package/dist/git-door.js +18 -17
- package/dist/git.d.ts +1 -1
- package/dist/host.d.ts +38 -42
- package/dist/host.js +182 -239
- package/dist/installation-execution.js +10 -5
- package/dist/installation-operations.d.ts +4 -180
- package/dist/installation-operations.js +1 -5
- package/dist/installation-store-generation.d.ts +4 -1
- package/dist/installation-store-generation.js +59 -6
- package/dist/internal/delivery.js +0 -1
- package/dist/internal/host-gate.d.ts +9 -6
- package/dist/internal/host-gate.js +19 -25
- package/dist/internal/invocation-timing.d.ts +16 -0
- package/dist/internal/invocation-timing.js +23 -0
- package/dist/internal/registry-installations.js +1 -0
- package/dist/invocation.d.ts +19 -11
- package/dist/invocation.js +171 -96
- package/dist/keys.d.ts +2 -19
- package/dist/keys.js +1 -37
- package/dist/mcp.d.ts +15 -27
- package/dist/mcp.js +105 -155
- package/dist/page/agent-browser.d.ts +15 -0
- package/dist/page/agent-browser.js +162 -0
- package/dist/page/app-permissions-port.d.ts +3 -0
- package/dist/page/app-permissions-port.js +43 -0
- package/dist/page/app-permissions.d.ts +11 -0
- package/dist/page/app-permissions.js +296 -0
- package/dist/page/capabilities.js +1 -1
- package/dist/page/child-selection.d.ts +27 -0
- package/dist/page/child-selection.js +38 -0
- package/dist/page/isolated-page-theme.d.ts +2 -0
- package/dist/page/isolated-page-theme.js +11 -0
- package/dist/page/mount.d.ts +2 -13
- package/dist/page/mount.js +8 -94
- package/dist/page-script.d.ts +0 -3
- package/dist/page-script.js +3 -4
- package/dist/release.d.ts +13 -0
- package/dist/release.js +10 -0
- package/dist/request-origin.d.ts +4 -0
- package/dist/request-origin.js +10 -0
- package/dist/standalone/agent-archive-owner.d.ts +42 -0
- package/dist/standalone/agent-archive-owner.js +116 -0
- package/dist/standalone/agent-archive-schedules.d.ts +6 -0
- package/dist/standalone/agent-archive-schedules.js +76 -0
- package/dist/standalone/agent-archive.d.ts +31 -0
- package/dist/standalone/agent-archive.js +67 -0
- package/dist/standalone/agent-computers.d.ts +7 -6
- package/dist/standalone/agent-computers.js +4 -7
- package/dist/standalone/agent-mail.d.ts +2 -2
- package/dist/standalone/agents.d.ts +157 -20
- package/dist/standalone/agents.js +242 -38
- package/dist/standalone/app-builds-binding.js +1 -1
- package/dist/standalone/app-set.js +2 -54
- package/dist/standalone/app-source.d.ts +3 -4
- package/dist/standalone/app-source.js +12 -9
- package/dist/standalone/builds.d.ts +2 -14
- package/dist/standalone/builds.js +15 -13
- package/dist/standalone/computer-fleet.d.ts +4 -4
- package/dist/standalone/computer-fleet.js +20 -43
- package/dist/standalone/computer.d.ts +4 -3
- package/dist/standalone/computer.js +52 -53
- package/dist/standalone/dashboard-approval.d.ts +10 -0
- package/dist/standalone/dashboard-approval.js +66 -0
- package/dist/standalone/machine-link.d.ts +4 -221
- package/dist/standalone/machine-link.js +21 -15
- package/dist/standalone/media.d.ts +1 -0
- package/dist/standalone/media.js +20 -14
- package/dist/standalone/owner-routes.d.ts +16 -0
- package/dist/standalone/owner-routes.js +21 -0
- package/dist/standalone/permission-resources.d.ts +5 -0
- package/dist/standalone/permission-resources.js +31 -0
- package/dist/standalone/registry.d.ts +7 -0
- package/dist/standalone/registry.js +3 -0
- package/dist/standalone/tenancy.js +3 -1
- package/dist/standalone/worker-routes.d.ts +19 -0
- package/dist/standalone/worker-routes.js +9 -0
- package/dist/standalone/worker.d.ts +1 -1
- package/dist/standalone/worker.js +27 -35
- package/dist/standalone/workflow-binding.d.ts +8 -3
- package/dist/standalone/workflow-binding.js +14 -5
- package/dist/standalone/workflow-git-capture.js +2 -1
- package/dist/standalone/workflow-host.d.ts +8 -103
- package/dist/standalone/workflow-host.js +1 -1
- package/dist/standalone/workflow-node-capture.js +2 -2
- package/dist/standalone/workflow-root-authority.d.ts +1 -1
- package/dist/standalone/workflow-root-authority.js +1 -1
- package/dist/standalone/workflow-schedules.d.ts +14 -5
- package/dist/standalone/workflow-schedules.js +11 -5
- package/dist/standalone/workflow-webhooks.d.ts +4 -18
- package/dist/standalone/workflow-webhooks.js +5 -5
- package/dist/standalone/workflows.d.ts +36 -28
- package/dist/standalone/workflows.js +6 -3
- package/dist/storage-frame.d.ts +6 -6
- package/dist/testing/capabilities.d.ts +7 -6
- package/dist/testing/capabilities.js +3 -6
- package/dist/testing/installation.d.ts +0 -1
- package/dist/testing/installation.js +2 -5
- package/dist/turnstile.d.ts +27 -0
- package/dist/turnstile.js +51 -0
- package/dist/workers-git.d.ts +12 -4
- package/dist/workers-git.js +58 -36
- package/dist/workers.d.ts +9 -1
- package/dist/workers.js +59 -20
- package/dist/workflows.d.ts +2 -0
- package/dist/workflows.js +1 -0
- package/docs/api/README.md +7 -0
- package/docs/api/agent-schedules.md +175 -0
- package/docs/api/agents.md +34 -13
- package/docs/api/app-storage.md +1 -1
- package/docs/api/apps.md +323 -225
- package/docs/api/authorization.md +1300 -0
- package/docs/api/build-contract.md +2 -2
- package/docs/api/build.md +40 -37
- package/docs/api/cloudflare.md +27 -2
- package/docs/api/git.md +20 -11
- package/docs/api/host.md +80 -199
- package/docs/api/index.md +1 -1
- package/docs/api/invocation.md +15 -11
- package/docs/api/keys.md +1 -98
- package/docs/api/mcp.md +43 -40
- package/docs/api/modules.md +2 -0
- package/docs/api/page/mount.md +16 -19
- package/docs/api/workers-git.md +46 -12
- package/docs/api/workers.md +125 -235
- package/docs/site/agent-quickstart.mdx +6 -2
- package/examples/standalone/wrangler.celld.jsonc +66 -0
- package/package.json +64 -21
- package/dist/standalone/channel-session-door.d.ts +0 -4
- package/dist/standalone/channel-session-door.js +0 -42
package/README.md
CHANGED
|
@@ -4,6 +4,12 @@ Oyster puts a desktop of Apps on your own Cloudflare account: a git platform,
|
|
|
4
4
|
agents, a terminal, an editor, workflows and image generation, each built from a
|
|
5
5
|
git commit on your own Computer.
|
|
6
6
|
|
|
7
|
+
The owner can read a build's status at `GET /api/builds/:jobId` and its combined
|
|
8
|
+
stdout/stderr at `GET /api/builds/:jobId?log`. The status diagnostic stays
|
|
9
|
+
within 200 characters and points to the log. The log returns base64url-encoded
|
|
10
|
+
raw bytes; if output exceeds 2 MiB it retains the head and tail and reports
|
|
11
|
+
`truncated.droppedBytes`. Both reads use the same owner authorization.
|
|
12
|
+
|
|
7
13
|
<picture>
|
|
8
14
|
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/fungi-computer/oyster/main/docs/media/desktop-light.png">
|
|
9
15
|
<img alt="The Tourtois desktop on Oyster with three Apps tiled: Trellis editing the Bonsai checks graph, Bonsai drawing a repository's network of agent forks, and Shed's terminal on the Computer" src="https://raw.githubusercontent.com/fungi-computer/oyster/main/docs/media/desktop-dark.png">
|
|
@@ -62,6 +68,10 @@ Workers AI, Workflows and media.
|
|
|
62
68
|
|
|
63
69
|
## Quick start: deploy your own Oyster
|
|
64
70
|
|
|
71
|
+
Deciding what to run?
|
|
72
|
+
[Is Oyster for you?](https://docs.fungi.computer/is-oyster-for-you/) compares
|
|
73
|
+
agent Computers and App builds with Cloudflare Workers Builds.
|
|
74
|
+
|
|
65
75
|
You need:
|
|
66
76
|
|
|
67
77
|
- a Cloudflare account on Workers Paid, with Containers, Artifacts, Workers AI,
|
|
@@ -69,11 +79,12 @@ You need:
|
|
|
69
79
|
- Docker, which Wrangler uses to build the Computer's container image;
|
|
70
80
|
- Node 24, pnpm 11 or newer and Git.
|
|
71
81
|
|
|
72
|
-
The first install takes about 15 to 20 minutes,
|
|
73
|
-
on the Computer,
|
|
74
|
-
and Wrangler, and copy the example Worker out of the
|
|
75
|
-
policy allows esbuild and workerd to install their
|
|
76
|
-
unneeded optional dependency scripts, so a fresh
|
|
82
|
+
The first install takes about 15 to 20 minutes, mostly building the seven Apps
|
|
83
|
+
on the Computer. By default, Oyster builds two Apps at a time. Start a project,
|
|
84
|
+
add Oyster, its Computer and Wrangler, and copy the example Worker out of the
|
|
85
|
+
package. The local pnpm policy allows esbuild and workerd to install their
|
|
86
|
+
native binaries and disables unneeded optional dependency scripts, so a fresh
|
|
87
|
+
install exits successfully:
|
|
77
88
|
|
|
78
89
|
```sh
|
|
79
90
|
mkdir my-oyster && cd my-oyster
|
|
@@ -173,6 +184,42 @@ repositories and namespace. Use the configured resource names and confirm each
|
|
|
173
184
|
is gone through Cloudflare's dashboard or API. Capture teardown errors and the
|
|
174
185
|
Wrangler version rather than silently adding unrelated token permissions.
|
|
175
186
|
|
|
187
|
+
### Upgrading to owner-only Oyster
|
|
188
|
+
|
|
189
|
+
Upgrading to 0.7.0 resets the installed Apps when the registry contains the
|
|
190
|
+
pre-owner-only `visibility`, `approvedAnonymousMethods` or `anonymousApproval`
|
|
191
|
+
fields. This clears all installation rows and their installation command journal
|
|
192
|
+
once, renews the store incarnation, and permanently records the reset time and
|
|
193
|
+
row count. It does not uninstall Apps through their storage-purging delete path.
|
|
194
|
+
Agents, Sessions, files, keys, source and release data, tenancy, approval
|
|
195
|
+
records and Computer state are retained.
|
|
196
|
+
|
|
197
|
+
While no App is enabled, Oyster Home shows:
|
|
198
|
+
|
|
199
|
+
> This update reset your installed Apps. Reinstall them with npx oyster
|
|
200
|
+
> install-apps.
|
|
201
|
+
|
|
202
|
+
Run `npx oyster install-apps` to reinstall. The notice disappears when an App is
|
|
203
|
+
enabled; the audit fact remains. This is not a compatibility reader or a reset
|
|
204
|
+
on arbitrary corruption. The separate pre-0.3 refusal below is unchanged.
|
|
205
|
+
|
|
206
|
+
Same-ID App settings: kept and back after reinstall; backend SQLite: kept but
|
|
207
|
+
not reachable.
|
|
208
|
+
|
|
209
|
+
Each installed App's own backend database (for example saved Notes) stays in
|
|
210
|
+
storage but is no longer reachable; reinstalling creates a new App Instance that
|
|
211
|
+
starts empty. There is no recovery for App backend data in 0.7.0; reinstalling
|
|
212
|
+
with `npx oyster install-apps` restores the Apps and their same-ID App settings,
|
|
213
|
+
and Agents, Sessions, files and keys are retained.
|
|
214
|
+
|
|
215
|
+
These are different stores. Backend SQLite belongs to the Instance's `app`
|
|
216
|
+
facet. Host `APP_STORAGE` settings instead belong to the installation address
|
|
217
|
+
plus App ID, key, scope and member membership version; the starter installer
|
|
218
|
+
reuses the same installation IDs, so the same App reconnects to those settings.
|
|
219
|
+
There is no automatic backend-data reattachment or change to either keying
|
|
220
|
+
scheme. Files on Computers and Agent/Session data have their own retained
|
|
221
|
+
owners.
|
|
222
|
+
|
|
176
223
|
### Upgrading from Oyster 0.2 or earlier
|
|
177
224
|
|
|
178
225
|
Oyster 0.3 does not read data created by Oyster 0.1 or 0.2, and it does not
|
|
@@ -418,16 +465,16 @@ can host yourself.
|
|
|
418
465
|
|
|
419
466
|

|
|
420
467
|
|
|
421
|
-
| Piece | Owns
|
|
422
|
-
| ----------------- |
|
|
423
|
-
| Router |
|
|
424
|
-
| `OysterRegistry` | The installation list: which Release each installation runs
|
|
425
|
-
| R2 | Release artifacts, stored by digest.
|
|
426
|
-
| App Instance | One Durable Object per installation: lifecycle, owner state and the backend facet.
|
|
427
|
-
| Backend facet | The App's own code and SQLite database, loaded through the Worker Loader.
|
|
428
|
-
| git door | Smart-HTTP `clone`, `fetch` and `push`, admitted per key and forwarded to Artifacts.
|
|
429
|
-
| Tourtois | The trusted shell: launcher, windows, menus and settings, rendered as the top-level page.
|
|
430
|
-
| Platform bindings | Workflows, Computers, Agents and Workers AI, offered only to Apps that declare them.
|
|
468
|
+
| Piece | Owns |
|
|
469
|
+
| ----------------- | ---------------------------------------------------------------------------------------------------- |
|
|
470
|
+
| Router | One declared route table (`authorization.ts`): sign-in, App pages and methods, owner routes, `/mcp`. |
|
|
471
|
+
| `OysterRegistry` | The installation list: which Release each installation runs. |
|
|
472
|
+
| R2 | Release artifacts, stored by digest. |
|
|
473
|
+
| App Instance | One Durable Object per installation: lifecycle, owner state and the backend facet. |
|
|
474
|
+
| Backend facet | The App's own code and SQLite database, loaded through the Worker Loader. |
|
|
475
|
+
| git door | Smart-HTTP `clone`, `fetch` and `push`, admitted per key and forwarded to Artifacts. |
|
|
476
|
+
| Tourtois | The trusted shell: launcher, windows, menus and settings, rendered as the top-level page. |
|
|
477
|
+
| Platform bindings | Workflows, Computers, Agents and Workers AI, offered only to Apps that declare them. |
|
|
431
478
|
|
|
432
479
|
The diagram source is
|
|
433
480
|
[`docs/media/architecture.mmd`](https://github.com/fungi-computer/oyster/blob/main/docs/media/architecture.mmd).
|
|
@@ -462,10 +509,29 @@ the Computer. `examples/standalone/wrangler.jsonc` declares every binding it
|
|
|
462
509
|
uses. Set the owner key as a secret (`OYSTER_OWNER_KEY`, 24+ characters) and
|
|
463
510
|
deploy with `wrangler deploy`. Sign in at `/login`.
|
|
464
511
|
|
|
512
|
+
Oyster is owner-only. A browser signs in only with the owner key, through
|
|
513
|
+
`/login` and its `SameSite=Strict` session cookie. Named keys sign in only by
|
|
514
|
+
header (`Authorization`), for MCP, Git and the API; no cookie admits a named
|
|
515
|
+
key. Anonymous requests reach only `/login`, `robots.txt` and digest-pinned
|
|
516
|
+
shell and App UI bytes.
|
|
517
|
+
|
|
518
|
+
The celld example is a limited trial, not the full Cloudflare setup above. It
|
|
519
|
+
requires access to Fungi's private celld fork. Use
|
|
520
|
+
`examples/standalone/wrangler.celld.jsonc` beside `worker.ts`, not the
|
|
521
|
+
Cloudflare-only config. Oyster `0.6.0` includes both files under
|
|
522
|
+
`examples/standalone` in the installed package.
|
|
523
|
+
|
|
465
524
|
The layers it is built from stay exported for hosts that compose their own:
|
|
466
|
-
`@fungi.computer/oyster/
|
|
467
|
-
|
|
468
|
-
|
|
525
|
+
`@fungi.computer/oyster/turnstile` owns Cloudflare challenge configuration and
|
|
526
|
+
token verification. Hosts supply their origin, verification timeout and safe
|
|
527
|
+
error reporter; they retain their own challenged routes and HTTP responses.
|
|
528
|
+
Configuration keeps the explicit `TURNSTILE=off` opt-out and fails closed on
|
|
529
|
+
HTTPS hosts without both keys. Hub retains its five-second verification policy.
|
|
530
|
+
|
|
531
|
+
Other host building blocks: `@fungi.computer/oyster/workers` (Releases,
|
|
532
|
+
Instances, MCP and App storage) and `@fungi.computer/oyster/workers-git` (the
|
|
533
|
+
git door), with `oysterAppMethods` supplying the installed App catalog to an
|
|
534
|
+
Agent runtime.
|
|
469
535
|
|
|
470
536
|
Pack and install an App with `@fungi.computer/oyster/pack`: `packRelease` turns
|
|
471
537
|
an exact Git commit and a canonical build recipe into a Release with immutable
|
|
@@ -559,7 +625,7 @@ flowchart LR
|
|
|
559
625
|
a named key may also be the Basic password from a git credential helper. A
|
|
560
626
|
Workflow Git pass (a `wgp.` Bearer header, never in a URL) goes only to
|
|
561
627
|
`host.git.workflowPass`; without that port it admits nothing. Anonymous
|
|
562
|
-
requests
|
|
628
|
+
requests never clone or push.
|
|
563
629
|
- **Git admission** reopens the live installation before every provider call: it
|
|
564
630
|
must be enabled and its Release must declare `git.repository`. The tenant
|
|
565
631
|
scope prefixes every repository name (`<installation>--<repo>` for the default
|
|
@@ -621,7 +687,9 @@ and the exact installation, repository and read/write scope it names. The last
|
|
|
621
687
|
returns an `AdmittedGit`; the door forwards reads to `.read` and pushes to
|
|
622
688
|
`.push`. Provider credentials stay inside the storage adapter. `createOyster`
|
|
623
689
|
builds these ports from `host.auth`, `host.installations` and `host.git`, so
|
|
624
|
-
most hosts set `host.git` and never call `createGitDoor` directly.
|
|
690
|
+
most hosts set `host.git` and never call `createGitDoor` directly. There a named
|
|
691
|
+
key signs Git in only for installations its own grants reach: a clone needs App
|
|
692
|
+
read and a push needs App use; otherwise the door refuses it.
|
|
625
693
|
|
|
626
694
|
A host whose Workflow run owner issues Workflow Git credentials supplies
|
|
627
695
|
`workflowGitPass` in `oysterGitRoot` or `oysterWorkerGit` options. The run owner
|
|
@@ -637,11 +705,13 @@ branches are refused before the App's push policy runs.
|
|
|
637
705
|
### Provide App capabilities
|
|
638
706
|
|
|
639
707
|
Each `OysterCapability` supplies its Agar `id` and `version`, a mount `base`,
|
|
640
|
-
relative
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
708
|
+
relative declared `routes` (a `routes()` table from
|
|
709
|
+
`@fungi.computer/oyster/authorization`, where every route names its requirement:
|
|
710
|
+
`owner`, `agent`, `computer`, `member`...), and `methods`. Each method
|
|
711
|
+
descriptor has `kind`, `method` (HTTP method), and `path` (relative route).
|
|
712
|
+
`CapabilityMethodKind` is `json | transport | read | write`: JSON calls return
|
|
713
|
+
decoded data, transports return Fetch handles, and reads/writes return Agar's
|
|
714
|
+
stream handles.
|
|
645
715
|
|
|
646
716
|
Method paths may contain named parameters, such as `:agentId/sessions`. Oyster
|
|
647
717
|
uses `path-to-regexp` to compile input fields into those parameters; remaining
|
|
@@ -659,10 +729,9 @@ from `@fungi.computer/oyster/files` supplies the three file contracts over the
|
|
|
659
729
|
existing `/files/` GET, PUT and POST routes.
|
|
660
730
|
|
|
661
731
|
The page offers a capability only when the installed Release declares its ID and
|
|
662
|
-
`admits` allows the principal.
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
file mount.
|
|
732
|
+
`admits` allows the principal. Every route request also rechecks that
|
|
733
|
+
declaration and admission using the `X-Oyster-Installation` header set by the
|
|
734
|
+
page; a read grant does not authorize the write route sharing its file mount.
|
|
666
735
|
|
|
667
736
|
Consent approves capabilities, like OAuth scopes. An App upgrade may add a
|
|
668
737
|
method that uses an already-approved capability without asking again. A new
|
|
@@ -677,10 +746,9 @@ your approval.**
|
|
|
677
746
|
The `apps.call` permission also shows the declared target Apps and methods. Its
|
|
678
747
|
route approvals retain those exact pairs: adding or renaming a target method
|
|
679
748
|
needs owner approval. On Oyster these page calls run as the signed-in member
|
|
680
|
-
through the target App's ordinary method gate; Agents
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
capability.
|
|
749
|
+
through the target App's ordinary method gate; Agents and keys cannot use this
|
|
750
|
+
path. The target receives its own grants, never the caller App's grants. The Hub
|
|
751
|
+
shows the same consent list but does not offer this page capability.
|
|
684
752
|
|
|
685
753
|
### Connect an agent over MCP
|
|
686
754
|
|
|
@@ -705,8 +773,8 @@ operations are the ones every Computer advertises (`read`, `list`, `write`,
|
|
|
705
773
|
The host supplies `computer(principal)` on its workspace: it returns the
|
|
706
774
|
Computer's calls for a caller with Computer access and `null` otherwise. The
|
|
707
775
|
standalone host gives an owner, key or member the same Computer grant its
|
|
708
|
-
`/computer` routes use;
|
|
709
|
-
|
|
776
|
+
`/computer` routes use; Agents get none. The Computer accepts every call against
|
|
777
|
+
that grant. `oysterComputerTools(host, principal)` from
|
|
710
778
|
`@fungi.computer/oyster/mcp` returns this Knapsack source and its `grants`.
|
|
711
779
|
|
|
712
780
|
Workers route every MCP request to the tenant's `MCP` Durable Object. Export
|
|
@@ -731,15 +799,15 @@ module's own grant is `read`. For an Agent, `access` is
|
|
|
731
799
|
`{level, revision, grantedBy}` approval; missing it grants no tool access. For a
|
|
732
800
|
named key, `access` is `{kind: "key", keyId, byInstallation}`, one
|
|
733
801
|
`{level, revision, grantedBy}` per installation the key's own Ear Tag grants
|
|
734
|
-
admit (`
|
|
735
|
-
`byInstallation` and never listed at all, not merely
|
|
736
|
-
set once, at `POST /api/keys`, and never edited: to
|
|
737
|
-
revokes the key (`POST /api/keys/revoke`) and issues a new
|
|
738
|
-
does not approve an App operation. The gate also intersects
|
|
739
|
-
explicit approvals with its verified Release; `external`
|
|
740
|
-
with `approval_required`. MCP uses this same projection.
|
|
741
|
-
policy, installation authority, a key's own grants or a
|
|
742
|
-
source represents one immutable catalog snapshot.
|
|
802
|
+
admit (`appToolAccess` in `authorization.ts`); an installation the key has no
|
|
803
|
+
grant for is absent from `byInstallation` and never listed at all, not merely
|
|
804
|
+
refused. A key's grants are set once, at `POST /api/keys`, and never edited: to
|
|
805
|
+
change them the owner revokes the key (`POST /api/keys/revoke`) and issues a new
|
|
806
|
+
one. A module grant does not approve an App operation. The gate also intersects
|
|
807
|
+
the installation's explicit approvals with its verified Release; `external`
|
|
808
|
+
methods are refused with `approval_required`. MCP uses this same projection.
|
|
809
|
+
Capture again when tool policy, installation authority, a key's own grants or a
|
|
810
|
+
Release changes; the source represents one immutable catalog snapshot.
|
|
743
811
|
|
|
744
812
|
### Approve an Agent's App tools
|
|
745
813
|
|
|
@@ -942,6 +1010,20 @@ that read when host settings change. Account writes remain Hub-owned.
|
|
|
942
1010
|
|
|
943
1011
|
## Core concepts
|
|
944
1012
|
|
|
1013
|
+
### Authorization
|
|
1014
|
+
|
|
1015
|
+
`@fungi.computer/oyster/authorization` is Oyster's one authorization owner.
|
|
1016
|
+
Every route is registered through `routes()` with a typed requirement
|
|
1017
|
+
(`publicRoute`, `door`, `owner`, `member`, `app`, `apps`, `agent`, `agents`,
|
|
1018
|
+
`computer`), and a table's `serve` is the only router the host builds: an
|
|
1019
|
+
undeclared route is not served, and a handler receives only what its requirement
|
|
1020
|
+
admitted. The owner reaches everything. A named key reaches exactly its Ear Tag
|
|
1021
|
+
grants: `apps.read`/`apps.use` per installation (including that App's Git
|
|
1022
|
+
repositories), `agents.use` per Agent, and `computer.use` for the Computer, its
|
|
1023
|
+
workspace files and media. An Agent reaches its approved App tool policy;
|
|
1024
|
+
nothing anonymous reaches an App. `owner("direct")` refuses App-mediated
|
|
1025
|
+
requests, so consent, keys and secrets never ride an App.
|
|
1026
|
+
|
|
945
1027
|
### Owner state and selection
|
|
946
1028
|
|
|
947
1029
|
The host calls `apply` with the complete owner-issued state, then `fetch` or
|
|
@@ -1060,6 +1142,17 @@ Guest code receives only the `bindings()` its host builds, no ambient outbound
|
|
|
1060
1142
|
access, and requests carry only `Content-Type` and the host-admitted actor,
|
|
1061
1143
|
Computer and resource headers.
|
|
1062
1144
|
|
|
1145
|
+
One Instance shares its guest between up to eight verified foreground reads.
|
|
1146
|
+
Writes, raw backend requests, Gills, replay and supervisor-exclusive work run
|
|
1147
|
+
alone; a waiting exclusive caller holds back later reads. Every completed frame
|
|
1148
|
+
closes its own authority, and packets naming that finished frame refuse. Guest
|
|
1149
|
+
work runs only while at least one frame on that Instance remains admitted: the
|
|
1150
|
+
last frame stops the guest, then closes its authority, then releases admission.
|
|
1151
|
+
Arrivals wait while that stop is in flight. Once the opening frame's deadline
|
|
1152
|
+
passes, new reads wait for the cohort to drain rather than prolonging the guest.
|
|
1153
|
+
Revocation, expiry and a verified write preempting replay still stop it at once.
|
|
1154
|
+
Stopping the guest does not erase the facet's durable database.
|
|
1155
|
+
|
|
1063
1156
|
## API reference
|
|
1064
1157
|
|
|
1065
1158
|
The core is `@fungi.computer/oyster`; the Durable Object adapter is
|
|
@@ -1279,15 +1372,14 @@ returns typed no_backend before creating a new job or starting a machine.
|
|
|
1279
1372
|
Only an admitted Workflow-node APPS call can install its matching successful
|
|
1280
1373
|
build's recorded Release at the recorded target. Ordinary App-origin
|
|
1281
1374
|
installation remains refused. Existing grants may be reused, but new permissions
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
Workflow-created installation
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
configuration or separate consent ledger.
|
|
1375
|
+
return needs_consent without changing the running Release. Registering a
|
|
1376
|
+
repository as an App (**Make this an App**) is the owner's consent for its merge
|
|
1377
|
+
Workflow to create that App's installation when none exists yet. A
|
|
1378
|
+
Workflow-created installation has no grants. Later Workflows reuse exactly that
|
|
1379
|
+
approval and can never widen it; every grant still needs the owner's explicit
|
|
1380
|
+
consent. The build row records the outcome; status reads are read-only and no
|
|
1381
|
+
native alarm resumes installation. Workflow execution owns retries. This
|
|
1382
|
+
template has no review step, review configuration or separate consent ledger.
|
|
1291
1383
|
|
|
1292
1384
|
**Breaking installation contract:** Bonsai apps.install and APPS.select require
|
|
1293
1385
|
the successful build's jobId alongside installationId and release. The host
|
|
@@ -1399,8 +1491,9 @@ tenant from the request origin before sign-in and returns that tenant's
|
|
|
1399
1491
|
or `null` to refuse an unknown origin. Oyster uses the scope for registry,
|
|
1400
1492
|
workspace, keys, webhooks and repository names, and pins each Instance to its
|
|
1401
1493
|
selected tenant. Canonical member roles remain distinct from owner authority.
|
|
1402
|
-
|
|
1403
|
-
|
|
1494
|
+
Anonymous requests reach only sign-in, `robots.txt` and the digest-pinned shell
|
|
1495
|
+
and App UI bytes; unknown origins and policy refusals fail closed.
|
|
1496
|
+
`ownerOrKeyTenancy` is the single-tenant case.
|
|
1404
1497
|
|
|
1405
1498
|
## Machine link protocol
|
|
1406
1499
|
|
|
@@ -1442,14 +1535,13 @@ The page sends an owner-only `PUT` to the same path, carrying the captured
|
|
|
1442
1535
|
`storeGeneration`, `authorityVersion`, Release `artifactDigest`, and a bounded
|
|
1443
1536
|
`{kind:"change-grants",changes:[{capability,grant}]}` command. Each grant
|
|
1444
1537
|
contains `operations` and `resources`; `null` revokes that capability. Unnamed
|
|
1445
|
-
approvals retain their existing operation and resource ceilings. Agents, keys
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
pins in the existing commit transaction.
|
|
1538
|
+
approvals retain their existing operation and resource ceilings. Agents, keys
|
|
1539
|
+
and App-origin requests cannot approve. A replaced store, stale Release/version
|
|
1540
|
+
or concurrent approval returns `409`; the page refreshes the facts and rebases
|
|
1541
|
+
touched edits for review. The required `InstallationStore` exposes its durable
|
|
1542
|
+
`generation()` and `compareAndPut(record, expectedVersion, expectedGeneration)`.
|
|
1543
|
+
The latter returns a serializable commit/refusal result across Durable Object
|
|
1544
|
+
RPC and checks both pins in the existing commit transaction.
|
|
1453
1545
|
|
|
1454
1546
|
## Breaking App send contract
|
|
1455
1547
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { WatchdogSqliteOwner } from "@fungi.computer/watchdog";
|
|
2
|
+
/** Revisioned, bounded-stale directory view; never the Agent's flag authority. */
|
|
3
|
+
export declare function agentArchiveProjection(sql: WatchdogSqliteOwner["sql"]): {
|
|
4
|
+
/** Only an advanced fact changes the view; replay can still be acked. */
|
|
5
|
+
record(agentId: string, archived: boolean, revision: number): "advanced" | "replayed" | "stale";
|
|
6
|
+
archived(agentId: string): boolean;
|
|
7
|
+
archivedIds(): ReadonlySet<string>;
|
|
8
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const archivedRow = z.strictObject({
|
|
3
|
+
archived: z.union([z.literal(0), z.literal(1)]),
|
|
4
|
+
revision: z.number().int().nonnegative(),
|
|
5
|
+
});
|
|
6
|
+
const agentRow = z.strictObject({ agent_id: z.string() });
|
|
7
|
+
const changesRow = z.strictObject({ count: z.number() });
|
|
8
|
+
/** Revisioned, bounded-stale directory view; never the Agent's flag authority. */
|
|
9
|
+
export function agentArchiveProjection(sql) {
|
|
10
|
+
sql.exec(`CREATE TABLE IF NOT EXISTS oyster_archive_projection (
|
|
11
|
+
agent_id TEXT PRIMARY KEY,
|
|
12
|
+
archived INTEGER NOT NULL CHECK(archived IN (0, 1)),
|
|
13
|
+
revision INTEGER NOT NULL
|
|
14
|
+
) STRICT`);
|
|
15
|
+
return {
|
|
16
|
+
/** Only an advanced fact changes the view; replay can still be acked. */
|
|
17
|
+
record(agentId, archived, revision) {
|
|
18
|
+
sql.exec(`INSERT INTO oyster_archive_projection(agent_id,archived,revision)
|
|
19
|
+
VALUES(?,?,?)
|
|
20
|
+
ON CONFLICT(agent_id) DO UPDATE SET
|
|
21
|
+
archived=excluded.archived, revision=excluded.revision
|
|
22
|
+
WHERE oyster_archive_projection.revision < excluded.revision`, agentId, archived ? 1 : 0, revision);
|
|
23
|
+
if (changesRow.parse(sql.exec("SELECT changes() AS count").toArray()[0])
|
|
24
|
+
.count > 0)
|
|
25
|
+
return "advanced";
|
|
26
|
+
const row = sql
|
|
27
|
+
.exec("SELECT archived, revision FROM oyster_archive_projection WHERE agent_id=?", agentId)
|
|
28
|
+
.toArray()[0];
|
|
29
|
+
const current = row === undefined ? null : archivedRow.parse(row);
|
|
30
|
+
return current !== null &&
|
|
31
|
+
current.revision === revision &&
|
|
32
|
+
current.archived === (archived ? 1 : 0)
|
|
33
|
+
? "replayed"
|
|
34
|
+
: "stale";
|
|
35
|
+
},
|
|
36
|
+
archived(agentId) {
|
|
37
|
+
const row = sql
|
|
38
|
+
.exec("SELECT archived, revision FROM oyster_archive_projection WHERE agent_id=?", agentId)
|
|
39
|
+
.toArray()[0];
|
|
40
|
+
return row === undefined ? false : archivedRow.parse(row).archived === 1;
|
|
41
|
+
},
|
|
42
|
+
archivedIds() {
|
|
43
|
+
return new Set(sql
|
|
44
|
+
.exec("SELECT agent_id FROM oyster_archive_projection WHERE archived=1")
|
|
45
|
+
.toArray()
|
|
46
|
+
.map((row) => agentRow.parse(row).agent_id));
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export { agentSchedulePageSchema, agentScheduleControlReceiptSchema, } from "@fungi.computer/shiitake-extensions/schedules";
|
|
3
|
+
export type { AgentSchedulePage, AgentScheduleTarget, AgentScheduleControlReceipt, } from "@fungi.computer/shiitake-extensions/schedules";
|
|
4
|
+
/** The App selects one Agent; its host must admit that target before opening it. */
|
|
5
|
+
export declare const appAgentScheduleListInputSchema: z.ZodObject<{
|
|
6
|
+
after: z.ZodOptional<z.ZodObject<{
|
|
7
|
+
agentId: z.ZodString;
|
|
8
|
+
kind: z.ZodUnion<readonly [z.ZodLiteral<"almanac">, z.ZodLiteral<"loop">]>;
|
|
9
|
+
after: z.ZodOptional<z.ZodString>;
|
|
10
|
+
}, z.core.$strict>>;
|
|
11
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
12
|
+
agentId: z.ZodString;
|
|
13
|
+
}, z.core.$strict>;
|
|
14
|
+
/** A single bounded native read, not an all-Agent inventory grant. */
|
|
15
|
+
export type AppAgentScheduleListInput = z.input<typeof appAgentScheduleListInputSchema>;
|
|
16
|
+
/** Both hosts decode the ordinary AGENTS packet with the native owner's grammar. */
|
|
17
|
+
export declare const agentScheduleBindingArgs: {
|
|
18
|
+
/** One bounded content-bearing read, admitted independently of manage. */
|
|
19
|
+
schedules: z.ZodTuple<[z.ZodObject<{
|
|
20
|
+
after: z.ZodOptional<z.ZodObject<{
|
|
21
|
+
agentId: z.ZodString;
|
|
22
|
+
kind: z.ZodUnion<readonly [z.ZodLiteral<"almanac">, z.ZodLiteral<"loop">]>;
|
|
23
|
+
after: z.ZodOptional<z.ZodString>;
|
|
24
|
+
}, z.core.$strict>>;
|
|
25
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
26
|
+
agentId: z.ZodString;
|
|
27
|
+
}, z.core.$strict>], null>;
|
|
28
|
+
/** Pause the exact listed schedule, retaining future resume and accepted work. */
|
|
29
|
+
pauseSchedule: z.ZodTuple<[z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
30
|
+
kind: z.ZodLiteral<"almanac">;
|
|
31
|
+
agentId: z.ZodString;
|
|
32
|
+
scheduleId: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
|
|
33
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
34
|
+
kind: z.ZodLiteral<"loop">;
|
|
35
|
+
agentId: z.ZodString;
|
|
36
|
+
sessionId: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
|
|
37
|
+
loopId: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
|
|
38
|
+
}, z.core.$strict>], "kind">], null>;
|
|
39
|
+
/** Cancel future occurrences of the exact identity without erasing history. */
|
|
40
|
+
deleteSchedule: z.ZodTuple<[z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
41
|
+
kind: z.ZodLiteral<"almanac">;
|
|
42
|
+
agentId: z.ZodString;
|
|
43
|
+
scheduleId: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
|
|
44
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
45
|
+
kind: z.ZodLiteral<"loop">;
|
|
46
|
+
agentId: z.ZodString;
|
|
47
|
+
sessionId: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
|
|
48
|
+
loopId: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
|
|
49
|
+
}, z.core.$strict>], "kind">], null>;
|
|
50
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { agentScheduleListInputSchema, agentScheduleTargetSchema, } from "@fungi.computer/shiitake-extensions/schedules";
|
|
3
|
+
export { agentSchedulePageSchema, agentScheduleControlReceiptSchema, } from "@fungi.computer/shiitake-extensions/schedules";
|
|
4
|
+
/** The App selects one Agent; its host must admit that target before opening it. */
|
|
5
|
+
export const appAgentScheduleListInputSchema = agentScheduleListInputSchema.extend({
|
|
6
|
+
/** The native directory identity whose owner the host must admit. */
|
|
7
|
+
agentId: z.string().min(1),
|
|
8
|
+
});
|
|
9
|
+
/** Both hosts decode the ordinary AGENTS packet with the native owner's grammar. */
|
|
10
|
+
export const agentScheduleBindingArgs = {
|
|
11
|
+
/** One bounded content-bearing read, admitted independently of manage. */
|
|
12
|
+
schedules: z.tuple([appAgentScheduleListInputSchema]),
|
|
13
|
+
/** Pause the exact listed schedule, retaining future resume and accepted work. */
|
|
14
|
+
pauseSchedule: z.tuple([agentScheduleTargetSchema]),
|
|
15
|
+
/** Cancel future occurrences of the exact identity without erasing history. */
|
|
16
|
+
deleteSchedule: z.tuple([agentScheduleTargetSchema]),
|
|
17
|
+
};
|
package/dist/agents.d.ts
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
* Shiitake's HTTP routes (`/sessions…`, `/acp`) and Knapsack's Session browser
|
|
7
7
|
* transport (`/browser/…`), served by the adapter behind the same App grants.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
10
|
-
import { type
|
|
9
|
+
import type { TenantPrincipal } from "./tenant.js";
|
|
10
|
+
import { type Routes } from "./authorization.js";
|
|
11
11
|
import type { AppToolPolicy } from "./apps/tools.js";
|
|
12
12
|
import * as Schema from "effect/Schema";
|
|
13
|
-
import { type OysterCapability, type OysterEnv
|
|
13
|
+
import { type OysterCapability, type OysterEnv } from "./host.js";
|
|
14
14
|
import type { HostActor } from "@fungi.computer/puffball/app";
|
|
15
15
|
import type { Avatar } from "@fungi.computer/sprite/avatar";
|
|
16
16
|
import type { AgentModelChoice, AgentModelRefusal } from "./standalone/agent-model-choice.js";
|
|
@@ -73,21 +73,42 @@ export type AgentToolPolicyStatus = Readonly<{
|
|
|
73
73
|
status: "pending" | "approved";
|
|
74
74
|
revision: string;
|
|
75
75
|
}>;
|
|
76
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* Where an Oyster's agents live and run. Archive is non-destructive: `list()`
|
|
78
|
+
* hides archived agents, and `list({ archived: true })` shows only archives.
|
|
79
|
+
* Archived agents keep existing reads, replays and settlements, but refuse new
|
|
80
|
+
* Sessions, prompts and steers with `contract/archived`. Archive refuses
|
|
81
|
+
* non-idle Session work or unsettled delegations; it pauses Almanac and Loop
|
|
82
|
+
* schedules and restores only archive-paused schedules on unarchive.
|
|
83
|
+
*/
|
|
77
84
|
export type OysterAgents = Readonly<{
|
|
78
|
-
/**
|
|
79
|
-
list(
|
|
85
|
+
/** Active agents by default; archived agents only by explicit selection. */
|
|
86
|
+
list(options?: Readonly<{
|
|
87
|
+
archived?: boolean;
|
|
88
|
+
}>): Promise<readonly OysterAgent[]>;
|
|
89
|
+
/** Owner-only HTTP transition; creator Agents use their own control tool. */
|
|
90
|
+
setArchived(agentId: string, archived: boolean, principal: TenantPrincipal): Promise<Readonly<{
|
|
91
|
+
archived: boolean;
|
|
92
|
+
revision: number;
|
|
93
|
+
}> | Readonly<{
|
|
94
|
+
error: "not_found" | "not_granted" | "self" | "not_creator" | "running" | "pending" | "unreadable" | "archived";
|
|
95
|
+
/** Safe refusal text; busy work names its command. */
|
|
96
|
+
message?: string;
|
|
97
|
+
/** A repair failure can follow an already-committed owner flag. */
|
|
98
|
+
archived?: boolean;
|
|
99
|
+
revision?: number;
|
|
100
|
+
}>>;
|
|
80
101
|
/**
|
|
81
102
|
* Create an agent; retrying with the same `requestId` returns the same one.
|
|
82
103
|
* With no `avatar` it wears its seeded default until the owner picks one.
|
|
83
104
|
*/
|
|
84
|
-
create(name: string, requestId: string, principal:
|
|
105
|
+
create(name: string, requestId: string, principal: TenantPrincipal, actor: AgentPolicyActor, avatar?: Avatar): Promise<OysterAgent>;
|
|
85
106
|
/** Owner-only rename; refuses a name already held by another Agent. */
|
|
86
|
-
rename(agentId: string, name: string, principal:
|
|
107
|
+
rename(agentId: string, name: string, principal: TenantPrincipal): Promise<OysterAgent | Readonly<{
|
|
87
108
|
error: "not_found" | "name_taken" | "not_granted";
|
|
88
109
|
}>>;
|
|
89
110
|
/** Owner-only avatar change for an existing Agent. */
|
|
90
|
-
setAvatar(agentId: string, avatar: Avatar, principal:
|
|
111
|
+
setAvatar(agentId: string, avatar: Avatar, principal: TenantPrincipal): Promise<OysterAgent | Readonly<{
|
|
91
112
|
error: "not_found" | "not_granted";
|
|
92
113
|
}>>;
|
|
93
114
|
/** Owner-only, secret-free Agent default; an unknown Agent cannot be configured. */
|
|
@@ -95,7 +116,7 @@ export type OysterAgents = Readonly<{
|
|
|
95
116
|
/** Parse the owner's JSON through the deployable Agent's model preference schema. */
|
|
96
117
|
decodeModelChoice(json: string): AgentModelChoice | null;
|
|
97
118
|
/** Persist a supported model and source reference for this Agent, or return an explicit refusal. */
|
|
98
|
-
setModelChoice(agentId: string, choice: AgentModelChoice, principal:
|
|
119
|
+
setModelChoice(agentId: string, choice: AgentModelChoice, principal: TenantPrincipal): Promise<AgentModelChoice | Readonly<{
|
|
99
120
|
error: "not_found" | "not_granted" | AgentModelRefusal;
|
|
100
121
|
}>>;
|
|
101
122
|
/** This Agent's App-tool policy status, or `null` for no such Agent. */
|
|
@@ -107,7 +128,7 @@ export type OysterAgents = Readonly<{
|
|
|
107
128
|
/** Read the current revision for direct owner approval. */
|
|
108
129
|
policyRevision(agentId: string): Promise<string | null>;
|
|
109
130
|
/** Replace an Agent's tool approval under its authenticated attaching human. */
|
|
110
|
-
approveAppToolPolicy(agentId: string, principal:
|
|
131
|
+
approveAppToolPolicy(agentId: string, principal: TenantPrincipal, level: AppToolPolicy["level"], expectedRevision: string | null, actor: AgentPolicyActor): Promise<AppToolPolicy | PendingAgentPolicy | Readonly<{
|
|
111
132
|
error: "not_found" | "revision_conflict" | "not_granted";
|
|
112
133
|
}>>;
|
|
113
134
|
/** An Agent's connected MCP servers, or `null` when there is no such Agent. */
|
|
@@ -126,11 +147,11 @@ export type OysterAgents = Readonly<{
|
|
|
126
147
|
visit(agentId: string, sessionId: string): Promise<boolean>;
|
|
127
148
|
}>;
|
|
128
149
|
/** Agent adapters admitted against each App's declared capabilities. */
|
|
129
|
-
export declare function agentCapabilities(agents: OysterAgents
|
|
150
|
+
export declare function agentCapabilities(agents: OysterAgents): readonly OysterCapability[];
|
|
130
151
|
/** Host-owned direct approval under the admitted owner; never an App capability. */
|
|
131
|
-
export declare function agentApprovalRoutes(agents: OysterAgents):
|
|
152
|
+
export declare function agentApprovalRoutes(agents: OysterAgents): Routes<OysterEnv>;
|
|
132
153
|
/**
|
|
133
154
|
* Host-owned Agent MCP server custody for the owner directly; never an App
|
|
134
155
|
* capability. Bearer tokens go in and never come back out.
|
|
135
156
|
*/
|
|
136
|
-
export declare function agentMcpServerRoutes(agents: OysterAgents):
|
|
157
|
+
export declare function agentMcpServerRoutes(agents: OysterAgents): Routes<OysterEnv>;
|