@fungi.computer/oyster 0.3.2 → 0.4.1
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/dist/agent-computer-source.d.ts +42 -0
- package/dist/agent-computer-source.js +88 -0
- package/dist/agent-computers.d.ts +104 -0
- package/dist/agent-computers.js +227 -0
- package/dist/agents.d.ts +10 -0
- package/dist/agents.js +33 -0
- package/dist/app-builds.d.ts +1 -1
- package/dist/app-builds.js +16 -6
- package/dist/boot-capability.d.ts +2 -1
- package/dist/boot-capability.js +7 -5
- package/dist/browser/boot.d.ts +2 -2
- package/dist/browser/boot.js +10 -3
- package/dist/browser/browser.d.ts +1 -1
- package/dist/browser/browser.js +2 -1
- package/dist/browser/cdp-client.d.ts +2 -0
- package/dist/browser/errors.d.ts +2 -2
- package/dist/browser/errors.js +2 -2
- package/dist/browser/index.d.ts +3 -2
- package/dist/browser/index.js +3 -2
- package/dist/browser/page.js +11 -4
- package/dist/browser/sessions.d.ts +7 -4
- package/dist/browser/sessions.js +159 -0
- package/dist/browser/url-policy.d.ts +4 -2
- package/dist/browser/url-policy.js +4 -2
- package/dist/build/build-jobs.d.ts +3 -3
- package/dist/build/build-jobs.js +10 -5
- package/dist/build/candidate-cli.js +5 -3
- package/dist/build/candidate-cli.mjs +223 -5
- package/dist/build/candidate-diagnostic.d.ts +2 -0
- package/dist/build/candidate-diagnostic.js +16 -0
- package/dist/computer-control-port.d.ts +26 -0
- package/dist/computer-control-port.js +1 -0
- package/dist/host.d.ts +3 -0
- package/dist/machine-link/delivery.d.ts +1 -1
- package/dist/machine-link/delivery.js +2 -3
- package/dist/machine-link/host.d.ts +37 -6
- package/dist/machine-link/host.js +209 -14
- package/dist/machine-link/link.d.ts +13 -1
- package/dist/machine-link/link.js +20 -7
- package/dist/mcp.d.ts +144 -10
- package/dist/mcp.js +130 -13
- package/dist/page/computer-handles.d.ts +3 -3
- package/dist/page-script.js +1 -1
- package/dist/standalone/agent-computers.d.ts +29 -0
- package/dist/standalone/agent-computers.js +101 -0
- package/dist/standalone/agent-mail.d.ts +41 -18
- package/dist/standalone/agent-model-choice.d.ts +29 -0
- package/dist/standalone/agent-model-choice.js +72 -0
- package/dist/standalone/agents.d.ts +44 -4
- package/dist/standalone/agents.js +502 -46
- package/dist/standalone/app-set.d.ts +8 -1
- package/dist/standalone/app-set.js +46 -31
- package/dist/standalone/computer-control.d.ts +4 -0
- package/dist/standalone/computer-control.js +62 -0
- package/dist/standalone/computer-fleet.d.ts +1 -0
- package/dist/standalone/computer-fleet.js +1 -1
- package/dist/standalone/computer.d.ts +21 -2
- package/dist/standalone/computer.js +12 -0
- package/dist/standalone/install-apps-bin.d.ts +2 -0
- package/dist/standalone/install-apps-bin.js +3 -0
- package/dist/standalone/install-apps-cli.d.ts +3 -1
- package/dist/standalone/install-apps-cli.js +27 -17
- package/dist/standalone/machine-link.d.ts +10 -0
- package/dist/standalone/machine-link.js +6 -0
- package/dist/standalone/registry.d.ts +10 -1
- package/dist/standalone/registry.js +9 -0
- package/dist/standalone/worker.js +12 -0
- package/dist/standalone/workflow-binding.d.ts +2 -2
- package/dist/standalone/workflow-host.d.ts +11 -11
- package/dist/standalone/workflows.d.ts +22 -22
- package/dist/storage-frame.d.ts +3 -3
- package/dist/workers-git.d.ts +2 -0
- package/dist/workers-git.js +2 -0
- package/dist/workers.d.ts +8 -8
- package/dist/workers.js +9 -1
- package/docs/api/agents.md +66 -0
- package/docs/api/apps.md +104 -104
- package/docs/api/build-contract.md +35 -35
- package/docs/api/build.md +12 -12
- package/docs/api/host.md +61 -61
- package/docs/api/mcp.md +127 -13
- package/docs/api/root-data.md +1 -1
- package/docs/api/tenancy.md +1 -1
- package/docs/api/workers-git.md +3 -2
- package/docs/api/workers.md +81 -83
- package/package.json +26 -18
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { type ComputerGrant } from "@fungi.computer/computer/fleet";
|
|
3
|
+
import { type AgentComputerProjection, type ComputerAttachmentInput } from "../agent-computers.js";
|
|
4
|
+
import type { AgentComputerConnection, AgentComputerPorts } from "../agent-computer-source.js";
|
|
5
|
+
import { type OysterEnv, type OysterPrincipal } from "../host.js";
|
|
6
|
+
import type { StandaloneAgentComputerRpc } from "./computer.js";
|
|
7
|
+
/** The directory supplies live authority; this adapter never invents a grant. */
|
|
8
|
+
export type StandaloneAgentComputerAccess = Readonly<{
|
|
9
|
+
admit: (connection: AgentComputerConnection) => Promise<ComputerGrant>;
|
|
10
|
+
computer: (computerId: string) => Rpc.Provider<StandaloneAgentComputerRpc>;
|
|
11
|
+
}>;
|
|
12
|
+
/** Native operations use the captured Computer, never the mutable workspace selection. */
|
|
13
|
+
export declare function standaloneAgentComputerPorts(access: StandaloneAgentComputerAccess, connection: AgentComputerConnection): AgentComputerPorts;
|
|
14
|
+
/** Persisted command outcome, with no fabricated attachment result on refusal. */
|
|
15
|
+
export type StandaloneAgentComputerReply = Readonly<{
|
|
16
|
+
kind: "ok";
|
|
17
|
+
projection: AgentComputerProjection;
|
|
18
|
+
}> | Readonly<{
|
|
19
|
+
kind: "refused";
|
|
20
|
+
error: "not_granted" | "not_found" | "request_conflict" | "attachment_identity_conflict";
|
|
21
|
+
}>;
|
|
22
|
+
/** Principal and persisted attachment transitions belong to the directory owner. */
|
|
23
|
+
export type StandaloneAgentComputerControl = Readonly<{
|
|
24
|
+
attach: (principal: OysterPrincipal, command: ComputerAttachmentInput) => Promise<StandaloneAgentComputerReply>;
|
|
25
|
+
detach: (principal: OysterPrincipal, command: ComputerAttachmentInput) => Promise<StandaloneAgentComputerReply>;
|
|
26
|
+
read: (principal: OysterPrincipal, agentId: string) => Promise<StandaloneAgentComputerReply>;
|
|
27
|
+
}>;
|
|
28
|
+
/** Owner HTTP transport over the retained attachment command grammar. */
|
|
29
|
+
export declare function standaloneAgentComputerRoutes(control: StandaloneAgentComputerControl): Hono<OysterEnv>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { createComputerFilesPort } from "@fungi.computer/computer";
|
|
3
|
+
import { checkComputerGrant, FleetGrantRefused, } from "@fungi.computer/computer/fleet";
|
|
4
|
+
import { computerCapabilities, computerValueSchema, } from "@fungi.computer/computer-contract";
|
|
5
|
+
import { attachComputerInputSchema, detachComputerInputSchema, readAgentComputersInputSchema, } from "../agent-computers.js";
|
|
6
|
+
import { oysterPrincipalIsOwner, } from "../host.js";
|
|
7
|
+
/** Native operations use the captured Computer, never the mutable workspace selection. */
|
|
8
|
+
export function standaloneAgentComputerPorts(access, connection) {
|
|
9
|
+
const { computerId } = connection.attachment;
|
|
10
|
+
async function authorized(action) {
|
|
11
|
+
const grant = await access.admit(connection);
|
|
12
|
+
if (checkComputerGrant(grant, {
|
|
13
|
+
computerId,
|
|
14
|
+
action,
|
|
15
|
+
now: Date.now(),
|
|
16
|
+
}).kind !== "admitted")
|
|
17
|
+
throw new FleetGrantRefused();
|
|
18
|
+
return grant;
|
|
19
|
+
}
|
|
20
|
+
// Constructing or advertising this port opens no native handle or Workspace.
|
|
21
|
+
async function withFiles(action, context, use) {
|
|
22
|
+
context.signal.throwIfAborted();
|
|
23
|
+
await authorized(action);
|
|
24
|
+
context.signal.throwIfAborted();
|
|
25
|
+
return use(createComputerFilesPort(access.computer(computerId)));
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
files: {
|
|
29
|
+
patch: async (input, context) => {
|
|
30
|
+
context.signal.throwIfAborted();
|
|
31
|
+
const grant = await authorized("files.edit");
|
|
32
|
+
context.signal.throwIfAborted();
|
|
33
|
+
return access.computer(computerId).filePatch(grant, input);
|
|
34
|
+
},
|
|
35
|
+
read: (input, context) => withFiles("files.readBytes", context, (files) => files.read(input, context)),
|
|
36
|
+
list: (input, context) => withFiles("files.list", context, (files) => files.list(input, context)),
|
|
37
|
+
glob: (input, context) => withFiles("files.glob", context, (files) => files.glob(input, context)),
|
|
38
|
+
grep: (input, context) => withFiles("files.grep", context, (files) => files.grep(input, context)),
|
|
39
|
+
replace: (input, context) => withFiles("files.edit", context, (files) => files.replace(input, context)),
|
|
40
|
+
},
|
|
41
|
+
computer: {
|
|
42
|
+
getCapabilities: (signal) => {
|
|
43
|
+
signal.throwIfAborted();
|
|
44
|
+
return Promise.resolve(computerValueSchema.parse(computerCapabilities()));
|
|
45
|
+
},
|
|
46
|
+
call: async (capabilityId, input, context) => {
|
|
47
|
+
context.signal.throwIfAborted();
|
|
48
|
+
// tool() retains the native advertised-operation/action mapping and decoders.
|
|
49
|
+
const grant = await access.admit(connection);
|
|
50
|
+
context.signal.throwIfAborted();
|
|
51
|
+
return computerValueSchema.parse(await access.computer(computerId).tool(grant, capabilityId, input));
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Owner HTTP transport over the retained attachment command grammar. */
|
|
57
|
+
export function standaloneAgentComputerRoutes(control) {
|
|
58
|
+
const routes = new Hono();
|
|
59
|
+
routes.post("/api/agents/:agentId/computers/:operation", async (context) => {
|
|
60
|
+
context.header("Cache-Control", "no-store");
|
|
61
|
+
const principal = context.get("principal");
|
|
62
|
+
if (!oysterPrincipalIsOwner(principal))
|
|
63
|
+
return context.json({ error: "not_granted" }, 403);
|
|
64
|
+
const operation = context.req.param("operation");
|
|
65
|
+
if (!["attach", "detach", "read"].includes(operation))
|
|
66
|
+
return context.json({ error: "not_found" }, 404);
|
|
67
|
+
let body;
|
|
68
|
+
try {
|
|
69
|
+
body = await context.req.json();
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (!(error instanceof SyntaxError))
|
|
73
|
+
throw error;
|
|
74
|
+
return context.json({ error: "invalid_input" }, 400);
|
|
75
|
+
}
|
|
76
|
+
const schema = operation === "attach"
|
|
77
|
+
? attachComputerInputSchema
|
|
78
|
+
: operation === "detach"
|
|
79
|
+
? detachComputerInputSchema
|
|
80
|
+
: readAgentComputersInputSchema;
|
|
81
|
+
const decoded = schema.safeParse(body);
|
|
82
|
+
if (!decoded.success)
|
|
83
|
+
return context.json({ error: "invalid_input" }, 400);
|
|
84
|
+
if (decoded.data.agentId !== context.req.param("agentId"))
|
|
85
|
+
return context.json({ error: "not_found" }, 404);
|
|
86
|
+
const result = operation === "read"
|
|
87
|
+
? await control.read(principal, decoded.data.agentId)
|
|
88
|
+
: operation === "attach"
|
|
89
|
+
? await control.attach(principal, attachComputerInputSchema.parse(decoded.data))
|
|
90
|
+
: await control.detach(principal, detachComputerInputSchema.parse(decoded.data));
|
|
91
|
+
if (result.kind === "ok")
|
|
92
|
+
return context.json(result.projection);
|
|
93
|
+
const status = result.error === "not_granted"
|
|
94
|
+
? 403
|
|
95
|
+
: result.error === "not_found"
|
|
96
|
+
? 404
|
|
97
|
+
: 409;
|
|
98
|
+
return context.json({ error: result.error }, status);
|
|
99
|
+
});
|
|
100
|
+
return routes;
|
|
101
|
+
}
|
|
@@ -1,24 +1,47 @@
|
|
|
1
|
+
import type { WatchdogTickResult } from "@fungi.computer/watchdog";
|
|
1
2
|
import { AgentMail, agentMailRoute } from "@fungi.computer/shiitake/delegation";
|
|
2
3
|
/** Standalone borrows Shiitake's one Watchdog and Carrier's ordinary durable lane. */
|
|
3
4
|
export declare function agentMail(options: Omit<ConstructorParameters<typeof AgentMail>[0], "post" | "drain"> & {
|
|
4
5
|
namespace: Parameters<typeof agentMailRoute>[0];
|
|
5
6
|
}): {
|
|
6
|
-
host:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
7
|
+
host: {
|
|
8
|
+
mailRoom: Readonly<{
|
|
9
|
+
fanOut: (settlement: import("@fungi.computer/bird-dog").BirdDogSettlement) => import("effect/Effect").Effect<void, import("@fungi.computer/bird-dog/effect").BirdDogError>;
|
|
10
|
+
postMail?: ((mail: import("@fungi.computer/bird-dog").BirdDogMail) => import("effect/Effect").Effect<void, import("@fungi.computer/bird-dog/effect").BirdDogError>) | undefined;
|
|
11
|
+
drainOutbox: () => import("effect/Effect").Effect<void, import("@fungi.computer/bird-dog/effect").BirdDogError>;
|
|
12
|
+
nextWakeAt: () => import("effect/Effect").Effect<number | undefined, import("@fungi.computer/bird-dog/effect").BirdDogError>;
|
|
13
|
+
}> & {
|
|
14
|
+
stageAcceptedNotice: (mail: import("@fungi.computer/bird-dog").BirdDogMail, scopeId: string) => void;
|
|
15
|
+
};
|
|
16
|
+
hostJobs: {
|
|
17
|
+
lane: string;
|
|
18
|
+
open: (owner: Readonly<{
|
|
19
|
+
transactional: import("@fungi.computer/watchdog").WatchdogTransactionalProjection;
|
|
20
|
+
readJob: (jobId: string) => Promise<import("@fungi.computer/watchdog").WatchdogReadResult>;
|
|
21
|
+
tickConcurrent: () => Promise<WatchdogTickResult>;
|
|
22
|
+
}>) => {
|
|
23
|
+
execute: (job: {
|
|
24
|
+
readonly queue: string;
|
|
25
|
+
readonly priority: number;
|
|
26
|
+
readonly payload: unknown;
|
|
27
|
+
readonly state: "running";
|
|
28
|
+
readonly lane: string;
|
|
29
|
+
readonly jobId: string;
|
|
30
|
+
readonly recovery?: {
|
|
31
|
+
readonly maxRecoveries: number;
|
|
32
|
+
} | undefined;
|
|
33
|
+
}) => Promise<Readonly<{
|
|
34
|
+
kind: "completed";
|
|
35
|
+
}>>;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
hostWork: {
|
|
39
|
+
pending: () => {
|
|
40
|
+
due: boolean;
|
|
41
|
+
nextWakeAt: number | null;
|
|
42
|
+
};
|
|
43
|
+
run: () => Promise<void>;
|
|
44
|
+
}[];
|
|
45
|
+
};
|
|
46
|
+
deliver: (value: Parameters<AgentMail["send"]>[0]) => Promise<import("@fungi.computer/shiitake").DelegationReceipt>;
|
|
24
47
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
2
|
+
import * as Schema from "effect/Schema";
|
|
3
|
+
/** A credential-source address, not credential material or a custodian locator. */
|
|
4
|
+
export declare const agentModelChoiceSchema: Schema.Struct<{
|
|
5
|
+
readonly keySource: Schema.Literals<readonly ["workers-ai", "ai-gateway", "byok"]>;
|
|
6
|
+
readonly model: Schema.Struct<{
|
|
7
|
+
readonly providerId: Schema.String;
|
|
8
|
+
readonly modelId: Schema.String;
|
|
9
|
+
readonly reasoning: Schema.optional<Schema.Literals<readonly ["minimal", "low", "medium", "high", "xhigh", "max"]>>;
|
|
10
|
+
}>;
|
|
11
|
+
}>;
|
|
12
|
+
/** The Agent's model preference and source reference, never credential material. */
|
|
13
|
+
export type AgentModelChoice = typeof agentModelChoiceSchema.Type;
|
|
14
|
+
/** Stable reason for rejecting a model or credential source before a run. */
|
|
15
|
+
export type AgentModelRefusal = "invalid_model_choice" | "unsupported_key_source" | "key_source_mismatch" | "model_unavailable" | "key_not_connected";
|
|
16
|
+
export declare class AgentModelRefused extends Error {
|
|
17
|
+
readonly reason: AgentModelRefusal;
|
|
18
|
+
constructor(reason: AgentModelRefusal);
|
|
19
|
+
}
|
|
20
|
+
/** Read the maintained Pi catalog; never accept a model from a different egress. */
|
|
21
|
+
export declare function selectAgentModel(choice: AgentModelChoice): Promise<Model<Api>>;
|
|
22
|
+
/** The Agent DO is the only durable owner. Absence is a new-format default, not an old-env reader. */
|
|
23
|
+
export declare function agentModelChoice(storage: Readonly<{
|
|
24
|
+
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
25
|
+
put(key: string, value: AgentModelChoice): Promise<void>;
|
|
26
|
+
}>, admit: (choice: AgentModelChoice) => void): {
|
|
27
|
+
read(): Promise<AgentModelChoice>;
|
|
28
|
+
set(input: AgentModelChoice): Promise<AgentModelChoice>;
|
|
29
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ModelPreferenceSchema } from "@fungi.computer/shiitake/model-preference";
|
|
2
|
+
import { cloudflareWorkersAIProvider } from "@earendil-works/pi-ai/providers/cloudflare-workers-ai";
|
|
3
|
+
import * as Schema from "effect/Schema";
|
|
4
|
+
/** A credential-source address, not credential material or a custodian locator. */
|
|
5
|
+
export const agentModelChoiceSchema = Schema.Struct({
|
|
6
|
+
keySource: Schema.Literals(["workers-ai", "ai-gateway", "byok"]),
|
|
7
|
+
model: ModelPreferenceSchema,
|
|
8
|
+
});
|
|
9
|
+
export class AgentModelRefused extends Error {
|
|
10
|
+
reason;
|
|
11
|
+
constructor(reason) {
|
|
12
|
+
super(reason);
|
|
13
|
+
this.reason = reason;
|
|
14
|
+
this.name = "AgentModelRefused";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const key = "agent-model-choice";
|
|
18
|
+
const defaultChoice = {
|
|
19
|
+
keySource: "workers-ai",
|
|
20
|
+
model: {
|
|
21
|
+
providerId: "cloudflare-workers-ai",
|
|
22
|
+
modelId: "@cf/moonshotai/kimi-k2.6",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
/** Read the maintained Pi catalog; never accept a model from a different egress. */
|
|
26
|
+
export async function selectAgentModel(choice) {
|
|
27
|
+
if (choice.keySource === "byok")
|
|
28
|
+
throw new AgentModelRefused("unsupported_key_source");
|
|
29
|
+
const { providerId, modelId, reasoning } = choice.model;
|
|
30
|
+
if ((choice.keySource === "workers-ai" &&
|
|
31
|
+
providerId !== "cloudflare-workers-ai") ||
|
|
32
|
+
(choice.keySource === "ai-gateway" &&
|
|
33
|
+
(providerId !== "openai" || modelId !== "openai/gpt-6-luna")))
|
|
34
|
+
throw new AgentModelRefused("key_source_mismatch");
|
|
35
|
+
// Pi's OpenAI provider is needed only when Luna is selected, not at boot.
|
|
36
|
+
const model = choice.keySource === "workers-ai"
|
|
37
|
+
? cloudflareWorkersAIProvider()
|
|
38
|
+
.getModels()
|
|
39
|
+
.find((item) => item.id === modelId)
|
|
40
|
+
: (await import("@earendil-works/pi-ai/providers/openai"))
|
|
41
|
+
.openaiProvider()
|
|
42
|
+
.getModels()
|
|
43
|
+
.find((item) => item.id === "gpt-6-luna");
|
|
44
|
+
if (model === undefined || (reasoning !== undefined && !model.reasoning))
|
|
45
|
+
throw new AgentModelRefused("model_unavailable");
|
|
46
|
+
return model;
|
|
47
|
+
}
|
|
48
|
+
/** The Agent DO is the only durable owner. Absence is a new-format default, not an old-env reader. */
|
|
49
|
+
export function agentModelChoice(storage, admit) {
|
|
50
|
+
return {
|
|
51
|
+
async read() {
|
|
52
|
+
const stored = await storage.get(key);
|
|
53
|
+
return stored === undefined
|
|
54
|
+
? defaultChoice
|
|
55
|
+
: Schema.decodeUnknownSync(agentModelChoiceSchema, {
|
|
56
|
+
onExcessProperty: "error",
|
|
57
|
+
})(stored);
|
|
58
|
+
},
|
|
59
|
+
async set(input) {
|
|
60
|
+
const parsed = Schema.decodeUnknownOption(agentModelChoiceSchema, {
|
|
61
|
+
onExcessProperty: "error",
|
|
62
|
+
})(input);
|
|
63
|
+
if (parsed._tag === "None")
|
|
64
|
+
throw new AgentModelRefused("invalid_model_choice");
|
|
65
|
+
const choice = parsed.value;
|
|
66
|
+
await selectAgentModel(choice);
|
|
67
|
+
admit(choice);
|
|
68
|
+
await storage.put(key, choice);
|
|
69
|
+
return choice;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -8,10 +8,15 @@ export type AiBinding = {
|
|
|
8
8
|
/** AI binding transport supplied by the Worker runtime. */
|
|
9
9
|
fetch?: (input: Request | string | URL, init?: RequestInit) => Promise<Response>;
|
|
10
10
|
};
|
|
11
|
+
import { type ComputerAttachmentInput } from "../agent-computers.js";
|
|
12
|
+
import { type AgentComputerSnapshot, type AgentComputerConnection } from "../agent-computer-source.js";
|
|
13
|
+
import { type StandaloneAgentComputerReply } from "./agent-computers.js";
|
|
14
|
+
import { type ComputerGrant } from "@fungi.computer/computer/fleet";
|
|
11
15
|
import { DurableObject } from "cloudflare:workers";
|
|
12
16
|
import type { StandaloneComputerEnv } from "./computer.js";
|
|
13
17
|
import { ShiitakeDO } from "@fungi.computer/shiitake/cloudflare";
|
|
14
18
|
import type { CloudflareShiitakeOptions } from "@fungi.computer/shiitake/cloudflare";
|
|
19
|
+
import { type AgentModelChoice, type AgentModelRefusal } from "./agent-model-choice.js";
|
|
15
20
|
import * as Schema from "effect/Schema";
|
|
16
21
|
import { type FrameBindingProps } from "../cloudflare.js";
|
|
17
22
|
import type { Avatar } from "@fungi.computer/sprite/avatar";
|
|
@@ -45,8 +50,6 @@ export type StandaloneAgentsEnv = Readonly<{
|
|
|
45
50
|
AI_GATEWAY_ID?: string;
|
|
46
51
|
/** Workers AI, the default model door. */
|
|
47
52
|
AI?: AiBinding;
|
|
48
|
-
/** The model: `@fungi/luna` via AI Gateway, or a Workers AI id (default {@link defaultAgentModel}). */
|
|
49
|
-
OYSTER_AGENT_MODEL?: string;
|
|
50
53
|
/** The AI Gateway the binding routes through (default `default`). */
|
|
51
54
|
OYSTER_AI_GATEWAY?: string;
|
|
52
55
|
/** Maintained current-member authority; absent means no nondefault-tenant policy admission. */
|
|
@@ -77,6 +80,18 @@ export declare abstract class StandaloneAgentBase<Env extends StandaloneAgentEnv
|
|
|
77
80
|
protected abstract hostFor(scope: TenantScope): Promise<OysterHost>;
|
|
78
81
|
private uiOwner;
|
|
79
82
|
private machineClient;
|
|
83
|
+
private computerSnapshot;
|
|
84
|
+
private computerSnapshotLoad;
|
|
85
|
+
private computerSnapshotGeneration;
|
|
86
|
+
private computerSnapshotRevision;
|
|
87
|
+
private readonly computerInvalidations;
|
|
88
|
+
/** Host invalidation drops captured discovery, not just its displayed names. */
|
|
89
|
+
invalidateComputerConnections(): void;
|
|
90
|
+
private computerConnections;
|
|
91
|
+
/** Revalidate the owner's generation before reusing a Home or tool snapshot. */
|
|
92
|
+
private preparedComputerSnapshot;
|
|
93
|
+
private readComputerGeneration;
|
|
94
|
+
private readComputerSnapshot;
|
|
80
95
|
private ui;
|
|
81
96
|
protected hostFetch(request: Request): Promise<Response> | undefined;
|
|
82
97
|
protected closeShiitake(): Promise<void>;
|
|
@@ -94,8 +109,15 @@ export declare abstract class StandaloneAgentBase<Env extends StandaloneAgentEnv
|
|
|
94
109
|
settlement(principal: MachineAgentSettlementPrincipal, sessionId: string, commandId: string): Promise<string | undefined>;
|
|
95
110
|
/** The root host for this Agent's pinned policy directory; unpinned Agents have no App tools. */
|
|
96
111
|
private appHost;
|
|
97
|
-
|
|
112
|
+
private choice;
|
|
113
|
+
/** Secret-free default of this Agent; stored separately from Session history. */
|
|
114
|
+
readModelChoice(): Promise<AgentModelChoice>;
|
|
115
|
+
setModelChoice(input: AgentModelChoice): Promise<AgentModelChoice | Readonly<{
|
|
116
|
+
error: AgentModelRefusal;
|
|
117
|
+
}>>;
|
|
118
|
+
/** Capture one model and credential source when the Agent's run acquires it. */
|
|
98
119
|
protected modelSource(): StandaloneModelSource;
|
|
120
|
+
private sourceFor;
|
|
99
121
|
/** Host-only initialization; Agent/App transports never receive this directory binding. */
|
|
100
122
|
usePolicyDirectory(input: {
|
|
101
123
|
directoryName: string;
|
|
@@ -127,6 +149,8 @@ export declare abstract class StandaloneAgentBase<Env extends StandaloneAgentEnv
|
|
|
127
149
|
}
|
|
128
150
|
/** Names this Oyster's agents and remembers which Sessions the member opened. */
|
|
129
151
|
export declare class AgentDirectory extends DurableObject<StandaloneAgentEnv> {
|
|
152
|
+
private readonly computers;
|
|
153
|
+
private readonly computerNames;
|
|
130
154
|
private readonly directory;
|
|
131
155
|
private readonly avatars;
|
|
132
156
|
private composedTenancy;
|
|
@@ -169,6 +193,21 @@ export declare class AgentDirectory extends DurableObject<StandaloneAgentEnv> {
|
|
|
169
193
|
alarm(): Promise<void>;
|
|
170
194
|
private grant;
|
|
171
195
|
constructor(ctx: DurableObjectState, env: StandaloneAgentEnv);
|
|
196
|
+
private computerOwner;
|
|
197
|
+
private loadComputerNames;
|
|
198
|
+
/** Check the existing transactional revision without resolving fleet names. */
|
|
199
|
+
agentComputerRevision(agentId: string, tenantId?: TenantId): Promise<number | null>;
|
|
200
|
+
/** Read the shared owner only after current membership and real fleet lookup. */
|
|
201
|
+
agentComputerSnapshot(agentId: string, tenantId?: TenantId): Promise<AgentComputerSnapshot | null>;
|
|
202
|
+
private computerCommand;
|
|
203
|
+
/** Owner attachment commands retain the shared owner's receipts and versions. */
|
|
204
|
+
attachComputer(command: ComputerAttachmentInput, principal: OysterPrincipal, tenantId?: TenantId): Promise<StandaloneAgentComputerReply>;
|
|
205
|
+
/** Detach advances the owner version and invalidates the Agent's held discovery. */
|
|
206
|
+
detachComputer(command: ComputerAttachmentInput, principal: OysterPrincipal, tenantId?: TenantId): Promise<StandaloneAgentComputerReply>;
|
|
207
|
+
/** The owner HTTP read uses the same projection as direct discovery. */
|
|
208
|
+
readAgentComputers(agentId: string, principal: OysterPrincipal, tenantId?: TenantId): Promise<StandaloneAgentComputerReply>;
|
|
209
|
+
/** Every captured native call rechecks the exact live attachment and credential owner. */
|
|
210
|
+
admitAgentComputer(captured: Pick<AgentComputerConnection, "scopeId" | "agentId" | "attachment">, tenantId: TenantId): Promise<Omit<ComputerGrant, "egress">>;
|
|
172
211
|
list(): readonly AgentEntry[];
|
|
173
212
|
has(agentId: string): boolean;
|
|
174
213
|
/** Resolve the existing recorded creator for host-side owner admission. */
|
|
@@ -241,9 +280,9 @@ export declare const agentFrameMethods: {
|
|
|
241
280
|
readonly nodeId: string;
|
|
242
281
|
readonly iteration: string;
|
|
243
282
|
};
|
|
283
|
+
readonly expiresAt: number;
|
|
244
284
|
readonly kind: "workflow-review";
|
|
245
285
|
readonly installationId: string;
|
|
246
|
-
readonly expiresAt: number;
|
|
247
286
|
readonly workflowId: string | null;
|
|
248
287
|
readonly state: "pending" | "delivered" | "answered" | "timed_out" | "closed";
|
|
249
288
|
readonly workflowTitle: string;
|
|
@@ -281,6 +320,7 @@ export declare const agentFrameMethods: {
|
|
|
281
320
|
decodeResult: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => Readonly<{
|
|
282
321
|
status: "accepted";
|
|
283
322
|
commandId: string;
|
|
323
|
+
sessionId?: string;
|
|
284
324
|
}>;
|
|
285
325
|
requiredOperations: () => string[];
|
|
286
326
|
};
|