@fungi.computer/oyster 0.4.1 → 0.6.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 +46 -8
- package/dist/agents.d.ts +2 -1
- package/dist/agents.js +67 -8
- package/dist/apps/gate.d.ts +4 -0
- package/dist/apps/gate.js +3 -0
- package/dist/auth.d.ts +24 -1
- package/dist/auth.js +38 -0
- package/dist/boot-host-script.js +1 -1
- package/dist/build/candidate-cli.mjs +27 -5
- package/dist/channels/binding.d.ts +70 -0
- package/dist/channels/binding.js +97 -0
- package/dist/channels/conversations.d.ts +246 -0
- package/dist/channels/conversations.js +705 -0
- package/dist/channels/ids.d.ts +8 -0
- package/dist/channels/ids.js +15 -0
- 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 +8 -2
- package/dist/cloudflare.js +27 -1
- package/dist/computer-target.d.ts +5 -0
- package/dist/computer-target.js +11 -0
- package/dist/host.d.ts +7 -4
- package/dist/host.js +96 -17
- package/dist/internal/host-gate.d.ts +6 -4
- package/dist/internal/host-gate.js +14 -7
- package/dist/invocation.d.ts +11 -4
- package/dist/invocation.js +134 -91
- package/dist/keys.d.ts +4 -1
- package/dist/keys.js +15 -4
- package/dist/machine-link/authority.d.ts +7 -0
- package/dist/machine-link/delivery.d.ts +12 -0
- package/dist/machine-link/delivery.js +22 -1
- package/dist/machine-link/disposition.d.ts +16 -0
- package/dist/machine-link/disposition.js +65 -0
- package/dist/machine-link/host.d.ts +11 -2
- package/dist/machine-link/host.js +125 -5
- package/dist/machine-link/link.d.ts +4 -0
- package/dist/machine-link/link.js +47 -1
- 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/mount.js +1 -1
- package/dist/page-script.js +4 -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-mail.js +4 -1
- package/dist/standalone/agents.d.ts +8 -0
- package/dist/standalone/agents.js +30 -11
- package/dist/standalone/channel-session-door.d.ts +4 -0
- package/dist/standalone/channel-session-door.js +72 -0
- package/dist/standalone/computer-fleet.js +7 -1
- package/dist/standalone/machine-link.d.ts +2 -0
- package/dist/standalone/machine-link.js +34 -1
- package/dist/standalone/tenancy.d.ts +3 -0
- package/dist/standalone/tenancy.js +7 -2
- package/dist/testing/capabilities.d.ts +2 -0
- package/dist/testing/capabilities.js +3 -1
- package/dist/turnstile.d.ts +27 -0
- package/dist/turnstile.js +51 -0
- package/dist/workers-git.js +21 -2
- package/dist/workers.d.ts +3 -0
- package/dist/workers.js +15 -12
- package/docs/api/agents.md +8 -4
- package/docs/api/apps.md +8 -4
- package/docs/api/auth.md +55 -0
- package/docs/api/browser.md +40 -16
- package/docs/api/build-contract.md +2 -2
- package/docs/api/cloudflare.md +26 -1
- package/docs/api/host.md +22 -13
- package/docs/api/invocation.md +7 -3
- package/docs/api/keys.md +25 -3
- package/docs/api/workers.md +38 -30
- package/docs/site/agent-quickstart.mdx +29 -2
- package/examples/standalone/wrangler.celld.jsonc +66 -0
- package/examples/standalone/wrangler.jsonc +3 -4
- package/package.json +53 -17
package/dist/workers.js
CHANGED
|
@@ -35,10 +35,11 @@ import * as Schema from "effect/Schema";
|
|
|
35
35
|
import * as Stream from "effect/Stream";
|
|
36
36
|
import { releaseSchema } from "@fungi.computer/puffball/effect";
|
|
37
37
|
import { AppInstanceError, } from "./index.js";
|
|
38
|
-
import { createCloudflareAppInstance, r2ArtifactStore, createCloudflareInvocationGate, decodeFrameBindingProps, captureFrameBindingReply, frameBindingEntrypoint, backgroundFrameMethods, } from "./cloudflare.js";
|
|
38
|
+
import { createCloudflareAppInstance, r2ArtifactStore, createCloudflareInvocationGate, edgeVerifiedObjectCache, decodeFrameBindingProps, captureFrameBindingReply, frameBindingEntrypoint, backgroundFrameMethods, } from "./cloudflare.js";
|
|
39
39
|
import { invocationFactsSchema, assertBackgroundBinding, admitBackgroundFrame, } from "./invocation.js";
|
|
40
40
|
import { deliverBackground, deliverGitPush } from "./internal/delivery.js";
|
|
41
|
-
import {
|
|
41
|
+
import { releaseCache } from "./internal/host-gate.js";
|
|
42
|
+
import { createOyster, } from "./host.js";
|
|
42
43
|
import { createGitPushJournal } from "./git-journal.js";
|
|
43
44
|
import { AppStorageError, } from "@fungi.computer/agar/storage";
|
|
44
45
|
import { storageFrameMethods } from "./storage-frame.js";
|
|
@@ -148,6 +149,7 @@ export class OysterRegistry extends DurableObject {
|
|
|
148
149
|
return this.approvalHome(pin).capability(actor).setAutoApprove(input);
|
|
149
150
|
}
|
|
150
151
|
#rootData;
|
|
152
|
+
#releases = releaseCache(r2ArtifactStore(this.env.RELEASES));
|
|
151
153
|
/** Append-only App source seed receipts; a Git-capable subclass forks over these. */
|
|
152
154
|
appSourceReceipts;
|
|
153
155
|
/** Team-owned fork registrations, one App publisher record per App. */
|
|
@@ -196,7 +198,7 @@ export class OysterRegistry extends DurableObject {
|
|
|
196
198
|
installations: {
|
|
197
199
|
list: () => Promise.resolve(this.list()),
|
|
198
200
|
},
|
|
199
|
-
resolveRelease:
|
|
201
|
+
resolveRelease: this.#releases,
|
|
200
202
|
});
|
|
201
203
|
}
|
|
202
204
|
/** The installation owner's RPC: admit, read, load, plan or commit one
|
|
@@ -319,7 +321,7 @@ export class OysterRegistry extends DurableObject {
|
|
|
319
321
|
expected.selection.releaseId ||
|
|
320
322
|
installation.release.appId !== expected.selection.appId)))
|
|
321
323
|
throw new AppStorageError("unavailable");
|
|
322
|
-
const resolved = await
|
|
324
|
+
const resolved = await this.#releases(installation.release);
|
|
323
325
|
if (expected !== undefined &&
|
|
324
326
|
resolved.backend?.digest !== expected.artifactDigest)
|
|
325
327
|
throw new AppStorageError("unavailable");
|
|
@@ -756,9 +758,9 @@ export class OysterInstance extends DurableObject {
|
|
|
756
758
|
}
|
|
757
759
|
async executeBindingCall(raw, method, input) {
|
|
758
760
|
const props = decodeFrameBindingProps(raw);
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
761
|
+
// The packet's own frame: a closed or foreign frame id refuses.
|
|
762
|
+
const frame = this.frames.active(props.frameId);
|
|
763
|
+
if (props.instanceId !== frame.facts.instanceId)
|
|
762
764
|
throw new AppInstanceError("revoked");
|
|
763
765
|
assertBackgroundBinding(frame, props.binding);
|
|
764
766
|
// A guest packet is its own entry: exactly one registry read re-admits it.
|
|
@@ -787,7 +789,7 @@ export class OysterInstance extends DurableObject {
|
|
|
787
789
|
.every((operation) => granted.includes(operation)))
|
|
788
790
|
throw new AppInstanceError("binding_not_granted");
|
|
789
791
|
const result = await row.dispatch(this.#bindingContext, frame, props, method, args);
|
|
790
|
-
if (this.frames.active() !== frame)
|
|
792
|
+
if (this.frames.active(props.frameId) !== frame)
|
|
791
793
|
throw new AppInstanceError("revoked");
|
|
792
794
|
assertBackgroundBinding(frame, props.binding);
|
|
793
795
|
return descriptor.decodeResult(result);
|
|
@@ -1102,10 +1104,7 @@ export function oysterWorkerHost(env, auth, options = {}) {
|
|
|
1102
1104
|
},
|
|
1103
1105
|
auth,
|
|
1104
1106
|
workbench: {
|
|
1105
|
-
directory:
|
|
1106
|
-
await installations.list();
|
|
1107
|
-
return registry().directory();
|
|
1108
|
-
},
|
|
1107
|
+
directory: () => registry().directory(),
|
|
1109
1108
|
storage: (installationId, ownerId) => ({
|
|
1110
1109
|
read: (key) => registry().storageRead(installationId, ownerId, key),
|
|
1111
1110
|
write: (input) => registry().storageWrite(installationId, ownerId, input),
|
|
@@ -1115,6 +1114,10 @@ export function oysterWorkerHost(env, auth, options = {}) {
|
|
|
1115
1114
|
},
|
|
1116
1115
|
guestLimits: guestLimits(options.guestLimits),
|
|
1117
1116
|
artifacts,
|
|
1117
|
+
// Workers and workerd keep a zone cache; a runtime without one reads R2.
|
|
1118
|
+
...("caches" in globalThis && {
|
|
1119
|
+
uiCache: edgeVerifiedObjectCache(caches.default, scope.origin),
|
|
1120
|
+
}),
|
|
1118
1121
|
bootUi: oysterBootUi(env, scope),
|
|
1119
1122
|
// File-only hosts may keep workspace files beside their Release artifacts.
|
|
1120
1123
|
capabilities: [
|
package/docs/api/agents.md
CHANGED
|
@@ -358,16 +358,20 @@ optional bearer.
|
|
|
358
358
|
### agentCapabilities()
|
|
359
359
|
|
|
360
360
|
```ts
|
|
361
|
-
function agentCapabilities(
|
|
361
|
+
function agentCapabilities(
|
|
362
|
+
agents,
|
|
363
|
+
liveKey,
|
|
364
|
+
): readonly Readonly<object & object>[];
|
|
362
365
|
```
|
|
363
366
|
|
|
364
367
|
Agent adapters admitted against each App's declared capabilities.
|
|
365
368
|
|
|
366
369
|
#### Parameters
|
|
367
370
|
|
|
368
|
-
| Parameter | Type
|
|
369
|
-
| --------- |
|
|
370
|
-
| `agents` | [`OysterAgents`](#oysteragents)
|
|
371
|
+
| Parameter | Type |
|
|
372
|
+
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
373
|
+
| `agents` | [`OysterAgents`](#oysteragents) |
|
|
374
|
+
| `liveKey` | (`keyId`) => `Promise`\< \| `Readonly`\<\{ `keyId`: `string`; `owner`: `string`; `grantVersion`: `number`; `grants`: readonly `Readonly`\<\{ `capability`: [`OysterKeyCapability`](keys.md#oysterkeycapability); `targets`: `GrantTargets`; \}\>[]; \}\> \| `null`\> |
|
|
371
375
|
|
|
372
376
|
#### Returns
|
|
373
377
|
|
package/docs/api/apps.md
CHANGED
|
@@ -852,6 +852,10 @@ const gateRequestSchema: ZodLazy<ZodDiscriminatedUnion<[ZodObject<{
|
|
|
852
852
|
| "channels.read"
|
|
853
853
|
| "channels.personal.manage", unknown>>;
|
|
854
854
|
operation: ZodString;
|
|
855
|
+
effect: ZodEnum<{
|
|
856
|
+
read: "read";
|
|
857
|
+
write: "write";
|
|
858
|
+
}>;
|
|
855
859
|
}, $strict>], "kind">>;
|
|
856
860
|
```
|
|
857
861
|
|
|
@@ -1676,10 +1680,10 @@ stay outside this pure gate.
|
|
|
1676
1680
|
|
|
1677
1681
|
#### Parameters
|
|
1678
1682
|
|
|
1679
|
-
| Parameter | Type
|
|
1680
|
-
| ------------ |
|
|
1681
|
-
| `facts` | [`GateFacts`](#gatefacts)
|
|
1682
|
-
| `rawRequest` | \| \{ `kind`: `"method"`; `name`: `string`; `input`: `unknown`; `via`: `"ui"` \| `"agent"` \| `"mcp"` \| `"workflow"`; `resource?`: `Readonly`\<\{ `kind`: `string`; `id`: `string`; \}\>; \} \| \{ `kind`: `"capability"`; `capability`: \| `"computer.list"` \| `"computer.readFile"` \| `"computer.writeFile"` \| `"computer.execute"` \| `"approvals"` \| `"agent.list"` \| `"agent.manage"` \| `"agent.rename"` \| `"agent.avatar"` \| `"agent.toolPolicy"` \| `"agent.read"` \| `"agent.send"` \| `"llm.generation"` \| `"media.generation"` \| `"games:servers"` \| `"git.repository"` \| `"apps.open"` \| `"apps.call"` \| `"app.storage"` \| `"app.events.emit"` \| `"team.workbenchHost"` \| `"marketplace.browse"` \| `"marketplace.purchase"` \| `"workflow.run"` \| `"workflow.publish"` \| `"workflow.arm"` \| `"world"` \| `"channels.read"` \| `"channels.personal.manage"`; `operation?`: `string`; `resource`: \| `"any"` \| `Readonly`\<\{ `kind`: `string`; `id`: `string`; \}\>; \} \| \{ `kind`: `"capability-route"`; `capability`: \| `"computer.list"` \| `"computer.readFile"` \| `"computer.writeFile"` \| `"computer.execute"` \| `"approvals"` \| `"agent.list"` \| `"agent.manage"` \| `"agent.rename"` \| `"agent.avatar"` \| `"agent.toolPolicy"` \| `"agent.read"` \| `"agent.send"` \| `"llm.generation"` \| `"media.generation"` \| `"games:servers"` \| `"git.repository"` \| `"apps.open"` \| `"apps.call"` \| `"app.storage"` \| `"app.events.emit"` \| `"team.workbenchHost"` \| `"marketplace.browse"` \| `"marketplace.purchase"` \| `"workflow.run"` \| `"workflow.publish"` \| `"workflow.arm"` \| `"world"` \| `"channels.read"` \| `"channels.personal.manage"`; `operation`: `string`; \} \| \{ `kind`: `"binding"`; `binding`: \| `"BACKGROUND"` \| `"GIT"` \| `"EVENTS"` \| `"APPS"` \| `"WORKFLOWS"` \| `"APP_STORAGE"` \| `"MEDIA"` \| `"COMPUTER"` \| `"INBOX"` \| `"AGENTS"`; `operation`: `string`; \} \| \{ `kind`: `"list-tools"`; \} \| \{ `kind`: `"backend"`; \} |
|
|
1683
|
+
| Parameter | Type |
|
|
1684
|
+
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1685
|
+
| `facts` | [`GateFacts`](#gatefacts) |
|
|
1686
|
+
| `rawRequest` | \| \{ `kind`: `"method"`; `name`: `string`; `input`: `unknown`; `via`: `"ui"` \| `"agent"` \| `"mcp"` \| `"workflow"`; `resource?`: `Readonly`\<\{ `kind`: `string`; `id`: `string`; \}\>; \} \| \{ `kind`: `"capability"`; `capability`: \| `"computer.list"` \| `"computer.readFile"` \| `"computer.writeFile"` \| `"computer.execute"` \| `"approvals"` \| `"agent.list"` \| `"agent.manage"` \| `"agent.rename"` \| `"agent.avatar"` \| `"agent.toolPolicy"` \| `"agent.read"` \| `"agent.send"` \| `"llm.generation"` \| `"media.generation"` \| `"games:servers"` \| `"git.repository"` \| `"apps.open"` \| `"apps.call"` \| `"app.storage"` \| `"app.events.emit"` \| `"team.workbenchHost"` \| `"marketplace.browse"` \| `"marketplace.purchase"` \| `"workflow.run"` \| `"workflow.publish"` \| `"workflow.arm"` \| `"world"` \| `"channels.read"` \| `"channels.personal.manage"`; `operation?`: `string`; `resource`: \| `"any"` \| `Readonly`\<\{ `kind`: `string`; `id`: `string`; \}\>; \} \| \{ `kind`: `"capability-route"`; `capability`: \| `"computer.list"` \| `"computer.readFile"` \| `"computer.writeFile"` \| `"computer.execute"` \| `"approvals"` \| `"agent.list"` \| `"agent.manage"` \| `"agent.rename"` \| `"agent.avatar"` \| `"agent.toolPolicy"` \| `"agent.read"` \| `"agent.send"` \| `"llm.generation"` \| `"media.generation"` \| `"games:servers"` \| `"git.repository"` \| `"apps.open"` \| `"apps.call"` \| `"app.storage"` \| `"app.events.emit"` \| `"team.workbenchHost"` \| `"marketplace.browse"` \| `"marketplace.purchase"` \| `"workflow.run"` \| `"workflow.publish"` \| `"workflow.arm"` \| `"world"` \| `"channels.read"` \| `"channels.personal.manage"`; `operation`: `string`; `effect`: `"read"` \| `"write"`; \} \| \{ `kind`: `"binding"`; `binding`: \| `"BACKGROUND"` \| `"GIT"` \| `"EVENTS"` \| `"APPS"` \| `"WORKFLOWS"` \| `"APP_STORAGE"` \| `"MEDIA"` \| `"COMPUTER"` \| `"INBOX"` \| `"AGENTS"`; `operation`: `string`; \} \| \{ `kind`: `"list-tools"`; \} \| \{ `kind`: `"backend"`; \} |
|
|
1683
1687
|
|
|
1684
1688
|
#### Returns
|
|
1685
1689
|
|
package/docs/api/auth.md
CHANGED
|
@@ -8,6 +8,26 @@
|
|
|
8
8
|
|
|
9
9
|
# auth
|
|
10
10
|
|
|
11
|
+
## Type Aliases
|
|
12
|
+
|
|
13
|
+
### OysterKeySessionResolver
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
type OysterKeySessionResolver = Readonly<{
|
|
17
|
+
resolve: (value) => Promise<Readonly<{
|
|
18
|
+
keyId: string;
|
|
19
|
+
}> | null>;
|
|
20
|
+
}>;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The host owns session minting, hashing/storage and expiry. A session resolves
|
|
24
|
+
only to a key id, never to owner or grant authority. Hosts should use Path=/,
|
|
25
|
+
HttpOnly, Secure and SameSite=Lax (or stricter) as defense in depth; Oyster
|
|
26
|
+
independently checks request provenance. Cookie-only admission allows GET/HEAD
|
|
27
|
+
navigation. Every other method requires Origin to be present and equal the
|
|
28
|
+
request URL's origin, and Sec-Fetch-Site not to be cross-site. Missing Origin is
|
|
29
|
+
refused.
|
|
30
|
+
|
|
11
31
|
## Variables
|
|
12
32
|
|
|
13
33
|
### ownerKeyCookieName
|
|
@@ -18,6 +38,16 @@ const ownerKeyCookieName: "oyster_session" = "oyster_session";
|
|
|
18
38
|
|
|
19
39
|
Cookie emitted by ownerKeyAuth, for composing credential-specific adapters.
|
|
20
40
|
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### keySessionCookieName
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
const keySessionCookieName: "oyster_key_session" = "oyster_key_session";
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Host-minted opaque sessions for named keys, separate from the owner cookie.
|
|
50
|
+
|
|
21
51
|
## Functions
|
|
22
52
|
|
|
23
53
|
### ownerKeyAuth()
|
|
@@ -61,3 +91,28 @@ The owner key, or a named key admitted as its canonical Team-key actor.
|
|
|
61
91
|
#### Returns
|
|
62
92
|
|
|
63
93
|
[`OysterAuth`](host.md#oysterauth)
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### keySessionAuth()
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
function keySessionAuth(auth, ownerId, keys, sessions): OysterAuth;
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Add host-owned browser sessions to ownerOrKeyAuth. Explicit credentials and
|
|
104
|
+
non-401 refusals keep their ordinary result; ambient cookies cannot undo them.
|
|
105
|
+
Every cookie admission rechecks the key's liveness and canonical owner.
|
|
106
|
+
|
|
107
|
+
#### Parameters
|
|
108
|
+
|
|
109
|
+
| Parameter | Type |
|
|
110
|
+
| ---------- | --------------------------------------------------------------------- |
|
|
111
|
+
| `auth` | [`OysterAuth`](host.md#oysterauth) |
|
|
112
|
+
| `ownerId` | `string` |
|
|
113
|
+
| `keys` | () => `NonNullable`\<[`OysterHost`](host.md#oysterhost)\[`"keys"`\]\> |
|
|
114
|
+
| `sessions` | [`OysterKeySessionResolver`](#oysterkeysessionresolver) |
|
|
115
|
+
|
|
116
|
+
#### Returns
|
|
117
|
+
|
|
118
|
+
[`OysterAuth`](host.md#oysterauth)
|
package/docs/api/browser.md
CHANGED
|
@@ -91,7 +91,7 @@ Data.TaggedError("CloudBrowserUrlDenied").message;
|
|
|
91
91
|
|
|
92
92
|
### CloudBrowserUpstreamError
|
|
93
93
|
|
|
94
|
-
The provider
|
|
94
|
+
The configured provider answered with a failure or is unreachable.
|
|
95
95
|
|
|
96
96
|
#### Extends
|
|
97
97
|
|
|
@@ -593,10 +593,11 @@ type BrowserLimits = Readonly<{
|
|
|
593
593
|
|
|
594
594
|
`@fungi.computer/oyster/browser`: the one agent browser for the Hub and a
|
|
595
595
|
standalone Oyster. A host builds the port from a provider (`browserRunSessions`
|
|
596
|
-
or `bindingSessions
|
|
597
|
-
required metering owner and an event sink;
|
|
598
|
-
egress policy and billing order;
|
|
599
|
-
`cloudBrowser` tool. Raw CDP stays
|
|
596
|
+
or `bindingSessions` or `onboxBrowserSessions` on staging, plus Browser Run
|
|
597
|
+
Quick Reads when it has them), its required metering owner and an event sink;
|
|
598
|
+
`createBrowser` owns lease ownership, egress policy and billing order;
|
|
599
|
+
`browserCapabilitySource` is the agent's `cloudBrowser` tool. Raw CDP stays
|
|
600
|
+
internal to this directory.
|
|
600
601
|
|
|
601
602
|
---
|
|
602
603
|
|
|
@@ -643,10 +644,11 @@ type Browser = Readonly<{
|
|
|
643
644
|
|
|
644
645
|
`@fungi.computer/oyster/browser`: the one agent browser for the Hub and a
|
|
645
646
|
standalone Oyster. A host builds the port from a provider (`browserRunSessions`
|
|
646
|
-
or `bindingSessions
|
|
647
|
-
required metering owner and an event sink;
|
|
648
|
-
egress policy and billing order;
|
|
649
|
-
`cloudBrowser` tool. Raw CDP stays
|
|
647
|
+
or `bindingSessions` or `onboxBrowserSessions` on staging, plus Browser Run
|
|
648
|
+
Quick Reads when it has them), its required metering owner and an event sink;
|
|
649
|
+
`createBrowser` owns lease ownership, egress policy and billing order;
|
|
650
|
+
`browserCapabilitySource` is the agent's `cloudBrowser` tool. Raw CDP stays
|
|
651
|
+
internal to this directory.
|
|
650
652
|
|
|
651
653
|
---
|
|
652
654
|
|
|
@@ -1058,9 +1060,9 @@ caller (`browser.ts`) owns the deadline through `signal`.
|
|
|
1058
1060
|
type BrowserSessions = Readonly<{}>;
|
|
1059
1061
|
```
|
|
1060
1062
|
|
|
1061
|
-
The provider half of the host port.
|
|
1062
|
-
|
|
1063
|
-
|
|
1063
|
+
The provider half of the host port. Each step is separate so `createBrowser`
|
|
1064
|
+
owns a provider session id from the moment it exists, including when its CDP
|
|
1065
|
+
connect then fails.
|
|
1064
1066
|
|
|
1065
1067
|
---
|
|
1066
1068
|
|
|
@@ -1338,10 +1340,11 @@ function createBrowser(host, limits): Browser;
|
|
|
1338
1340
|
|
|
1339
1341
|
`@fungi.computer/oyster/browser`: the one agent browser for the Hub and a
|
|
1340
1342
|
standalone Oyster. A host builds the port from a provider (`browserRunSessions`
|
|
1341
|
-
or `bindingSessions
|
|
1342
|
-
required metering owner and an event sink;
|
|
1343
|
-
egress policy and billing order;
|
|
1344
|
-
`cloudBrowser` tool. Raw CDP stays
|
|
1343
|
+
or `bindingSessions` or `onboxBrowserSessions` on staging, plus Browser Run
|
|
1344
|
+
Quick Reads when it has them), its required metering owner and an event sink;
|
|
1345
|
+
`createBrowser` owns lease ownership, egress policy and billing order;
|
|
1346
|
+
`browserCapabilitySource` is the agent's `cloudBrowser` tool. Raw CDP stays
|
|
1347
|
+
internal to this directory.
|
|
1345
1348
|
|
|
1346
1349
|
#### Parameters
|
|
1347
1350
|
|
|
@@ -1438,3 +1441,24 @@ A standalone Oyster's own Workers BROWSER binding.
|
|
|
1438
1441
|
#### Returns
|
|
1439
1442
|
|
|
1440
1443
|
[`BrowserSessions`](#browsersessions)
|
|
1444
|
+
|
|
1445
|
+
---
|
|
1446
|
+
|
|
1447
|
+
### onboxBrowserSessions()
|
|
1448
|
+
|
|
1449
|
+
```ts
|
|
1450
|
+
function onboxBrowserSessions(origin, fetcher?): BrowserSessions;
|
|
1451
|
+
```
|
|
1452
|
+
|
|
1453
|
+
Staging uses Chromium's native CDP browser contexts; no session store.
|
|
1454
|
+
|
|
1455
|
+
#### Parameters
|
|
1456
|
+
|
|
1457
|
+
| Parameter | Type |
|
|
1458
|
+
| --------- | ------------------------- |
|
|
1459
|
+
| `origin` | `string` |
|
|
1460
|
+
| `fetcher` | [`HttpFetch`](#httpfetch) |
|
|
1461
|
+
|
|
1462
|
+
#### Returns
|
|
1463
|
+
|
|
1464
|
+
[`BrowserSessions`](#browsersessions)
|
|
@@ -966,7 +966,7 @@ function putContentObject(
|
|
|
966
966
|
object,
|
|
967
967
|
body,
|
|
968
968
|
mediaType,
|
|
969
|
-
): Promise<"
|
|
969
|
+
): Promise<"stored" | "refused">;
|
|
970
970
|
```
|
|
971
971
|
|
|
972
972
|
Stream one object into the store under its digest. The store refuses a body
|
|
@@ -987,7 +987,7 @@ the body is discarded, never stored.
|
|
|
987
987
|
|
|
988
988
|
#### Returns
|
|
989
989
|
|
|
990
|
-
`Promise`\<`"
|
|
990
|
+
`Promise`\<`"stored"` \| `"refused"`\>
|
|
991
991
|
|
|
992
992
|
---
|
|
993
993
|
|
package/docs/api/cloudflare.md
CHANGED
|
@@ -305,6 +305,30 @@ frame or guestEnv factory is accepted.
|
|
|
305
305
|
|
|
306
306
|
---
|
|
307
307
|
|
|
308
|
+
### edgeVerifiedObjectCache()
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
function edgeVerifiedObjectCache(cache, origin): VerifiedObjectCache;
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
The zone's edge cache as a [VerifiedObjectCache](host.md#verifiedobjectcache):
|
|
315
|
+
each verified object under a digest-named key on `origin` that no route serves.
|
|
316
|
+
A failed write is logged and answers `unstored`; the next reader verifies from
|
|
317
|
+
the store again.
|
|
318
|
+
|
|
319
|
+
#### Parameters
|
|
320
|
+
|
|
321
|
+
| Parameter | Type |
|
|
322
|
+
| --------- | --------------------------------------- |
|
|
323
|
+
| `cache` | `Pick`\<`Cache`, `"match"` \| `"put"`\> |
|
|
324
|
+
| `origin` | `string` |
|
|
325
|
+
|
|
326
|
+
#### Returns
|
|
327
|
+
|
|
328
|
+
[`VerifiedObjectCache`](host.md#verifiedobjectcache)
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
308
332
|
### r2ArtifactStore()
|
|
309
333
|
|
|
310
334
|
```ts
|
|
@@ -435,7 +459,8 @@ function createCloudflareInvocationGate<Host, FacetClass>(
|
|
|
435
459
|
): InvocationGate<Host>;
|
|
436
460
|
```
|
|
437
461
|
|
|
438
|
-
End the native App facet
|
|
462
|
+
End the native App facet when live authority closes early, before the gate
|
|
463
|
+
admits again.
|
|
439
464
|
|
|
440
465
|
#### Type Parameters
|
|
441
466
|
|
package/docs/api/host.md
CHANGED
|
@@ -375,24 +375,17 @@ A capability adapter whose routes require live installation admission.
|
|
|
375
375
|
### OysterVariables
|
|
376
376
|
|
|
377
377
|
```ts
|
|
378
|
-
type OysterVariables = object;
|
|
378
|
+
type OysterVariables = TimingVariables & object;
|
|
379
379
|
```
|
|
380
380
|
|
|
381
381
|
What the host stamps once per request; inner routes read it with `c.get`.
|
|
382
382
|
|
|
383
|
-
####
|
|
384
|
-
|
|
385
|
-
##### principal
|
|
386
|
-
|
|
387
|
-
```ts
|
|
388
|
-
principal: OysterPrincipal;
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
##### installation?
|
|
383
|
+
#### Type Declaration
|
|
392
384
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
385
|
+
| Name | Type |
|
|
386
|
+
| --------------- | -------------------------------------- |
|
|
387
|
+
| `principal` | [`OysterPrincipal`](#oysterprincipal) |
|
|
388
|
+
| `installation?` | [`Installation`](apps.md#installation) |
|
|
396
389
|
|
|
397
390
|
---
|
|
398
391
|
|
|
@@ -473,6 +466,7 @@ type OysterHost = Readonly<{
|
|
|
473
466
|
auth: OysterAuth;
|
|
474
467
|
backgroundOriginKey?: () => Promise<CryptoKey>;
|
|
475
468
|
artifacts: ArtifactStore;
|
|
469
|
+
uiCache?: VerifiedObjectCache;
|
|
476
470
|
installations: InstallationStore;
|
|
477
471
|
instances: InstanceDirectory;
|
|
478
472
|
bootUi: (release) => Promise<UiBootCheckOutcome>;
|
|
@@ -1309,6 +1303,21 @@ type VerifiedRelease = Readonly<{
|
|
|
1309
1303
|
|
|
1310
1304
|
A Release whose root, UI and backend artifacts were read and verified.
|
|
1311
1305
|
|
|
1306
|
+
---
|
|
1307
|
+
|
|
1308
|
+
### VerifiedObjectCache
|
|
1309
|
+
|
|
1310
|
+
```ts
|
|
1311
|
+
type VerifiedObjectCache = Readonly<{
|
|
1312
|
+
match: (digest) => Promise<ReadableStream<Uint8Array> | null>;
|
|
1313
|
+
put: (digest, bytes) => Promise<"stored" | "unstored">;
|
|
1314
|
+
}>;
|
|
1315
|
+
```
|
|
1316
|
+
|
|
1317
|
+
Copies of verified artifacts near the reader, keyed by content digest. An entry
|
|
1318
|
+
holds only bytes that already matched its digest, so a hit is served without
|
|
1319
|
+
another store read or hash.
|
|
1320
|
+
|
|
1312
1321
|
## Variables
|
|
1313
1322
|
|
|
1314
1323
|
### capabilityMethodKindSchema
|
package/docs/api/invocation.md
CHANGED
|
@@ -122,7 +122,7 @@ The host's native guest-abort and authority-close hooks.
|
|
|
122
122
|
```ts
|
|
123
123
|
type InvocationGate<Host> = Readonly<{
|
|
124
124
|
run: <A>(facts, host, work) => Promise<A>;
|
|
125
|
-
active: () => InvocationFrame<Host>;
|
|
125
|
+
active: (frameId) => InvocationFrame<Host>;
|
|
126
126
|
revoke: (reason?, target?) => Promise<void>;
|
|
127
127
|
exclusive: <A>(work) => Promise<A>;
|
|
128
128
|
}>;
|
|
@@ -412,8 +412,12 @@ only its decision.
|
|
|
412
412
|
function createInvocationGate<Host>(ports): InvocationGate<Host>;
|
|
413
413
|
```
|
|
414
414
|
|
|
415
|
-
|
|
416
|
-
|
|
415
|
+
Admit frames against one guest. Verified foreground reads share it, up to eight
|
|
416
|
+
at once; writes, raw backend requests, Gills and replay run alone. Every guest
|
|
417
|
+
binding packet names its frame, so a finished frame's leftover timers cannot
|
|
418
|
+
borrow a later frame's authority and a normal finish keeps the guest warm.
|
|
419
|
+
Closing authority early (revocation, expiry, a write preempting replay) aborts
|
|
420
|
+
the guest and so every frame sharing it; replay only yields to a verified write.
|
|
417
421
|
|
|
418
422
|
#### Type Parameters
|
|
419
423
|
|
package/docs/api/keys.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
```ts
|
|
16
16
|
type OysterKeyCapability =
|
|
17
|
-
"apps.read" | "apps.use" | "computer.use" | "machine.enroll";
|
|
17
|
+
"apps.read" | "apps.use" | "agents.use" | "computer.use" | "machine.enroll";
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
Every capability an Oyster key may carry.
|
|
@@ -88,8 +88,9 @@ const oysterKeyVocabulary: GrantVocabulary<OysterKeyCapability>;
|
|
|
88
88
|
`apps.use` also reaches `apps.read` (one level, per `defineGrants`'s own
|
|
89
89
|
`implies`): a key that may change an App's data may also read it. `computer.use`
|
|
90
90
|
has no narrower capability under it; the Computer is on or off, host-wide.
|
|
91
|
-
`
|
|
92
|
-
|
|
91
|
+
`agents.use` selects Agent ids independently of App grants. `machine.enroll`
|
|
92
|
+
admits enrollment only; it implies no App or Computer access. The enrollment
|
|
93
|
+
owner, not this vocabulary, owns one-use consumption.
|
|
93
94
|
|
|
94
95
|
---
|
|
95
96
|
|
|
@@ -159,6 +160,27 @@ name for MCP) to reach the full `AppToolAccess`.
|
|
|
159
160
|
|
|
160
161
|
---
|
|
161
162
|
|
|
163
|
+
### keyAgentAccess()
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
function keyAgentAccess(key, agentId): boolean;
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Agent access is scoped to the granted Agent ids, never inferred from App grants.
|
|
170
|
+
|
|
171
|
+
#### Parameters
|
|
172
|
+
|
|
173
|
+
| Parameter | Type |
|
|
174
|
+
| --------- | --------------------------------- |
|
|
175
|
+
| `key` | [`LiveOysterKey`](#liveoysterkey) |
|
|
176
|
+
| `agentId` | `string` |
|
|
177
|
+
|
|
178
|
+
#### Returns
|
|
179
|
+
|
|
180
|
+
`boolean`
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
162
184
|
### keyAllowsComputerUse()
|
|
163
185
|
|
|
164
186
|
```ts
|