@fungi.computer/oyster 0.0.0-stage → 0.0.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/LICENSE +21 -0
- package/README.md +1082 -2
- package/dist/agents.d.ts +114 -0
- package/dist/agents.js +322 -0
- package/dist/app-builds.d.ts +151 -0
- package/dist/app-builds.js +355 -0
- package/dist/app-sandbox.d.ts +2 -0
- package/dist/app-sandbox.js +2 -0
- package/dist/app-sources.d.ts +46 -0
- package/dist/app-sources.js +335 -0
- package/dist/app-storage.d.ts +141 -0
- package/dist/app-storage.js +281 -0
- package/dist/apps/gate.d.ts +105 -0
- package/dist/apps/gate.js +273 -0
- package/dist/apps/index.d.ts +5 -0
- package/dist/apps/index.js +5 -0
- package/dist/apps/installation.d.ts +248 -0
- package/dist/apps/installation.js +307 -0
- package/dist/apps/operations.d.ts +8 -0
- package/dist/apps/operations.js +98 -0
- package/dist/apps/tools.d.ts +33 -0
- package/dist/apps/tools.js +17 -0
- package/dist/auth.d.ts +11 -0
- package/dist/auth.js +93 -0
- package/dist/backend-request.d.ts +3 -0
- package/dist/backend-request.js +53 -0
- package/dist/build/build-jobs.d.ts +128 -0
- package/dist/build/build-jobs.js +197 -0
- package/dist/build/build-step.d.ts +26 -0
- package/dist/build/build-step.js +20 -0
- package/dist/build/bundled-html.d.ts +7 -0
- package/dist/build/bundled-html.js +64 -0
- package/dist/build/definition-emission.d.ts +34 -0
- package/dist/build/definition-emission.js +201 -0
- package/dist/build/effect.d.ts +231 -0
- package/dist/build/effect.js +396 -0
- package/dist/build/git-environment.d.ts +6 -0
- package/dist/build/git-environment.js +48 -0
- package/dist/build/html-recipe.d.ts +20 -0
- package/dist/build/html-recipe.js +51 -0
- package/dist/build/local-build.d.ts +57 -0
- package/dist/build/local-build.js +1078 -0
- package/dist/build/r2-artifact-writer.d.ts +31 -0
- package/dist/build/r2-artifact-writer.js +179 -0
- package/dist/build/snapshot-package-store.d.ts +2 -0
- package/dist/build/snapshot-package-store.js +21 -0
- package/dist/build/snapshot-program-scripts.d.ts +6 -0
- package/dist/build/snapshot-program-scripts.js +2 -0
- package/dist/build/submission-contract.d.ts +384 -0
- package/dist/build/submission-contract.js +70 -0
- package/dist/build/workspace-build.d.ts +50 -0
- package/dist/build/workspace-build.js +156 -0
- package/dist/build-contract.d.ts +4 -0
- package/dist/build-contract.js +4 -0
- package/dist/build-jobs.d.ts +2 -0
- package/dist/build-jobs.js +2 -0
- package/dist/build.d.ts +11 -0
- package/dist/build.js +13 -0
- package/dist/capability-descriptor.d.ts +46 -0
- package/dist/capability-descriptor.js +51 -0
- package/dist/catalog-frame.d.ts +39 -0
- package/dist/catalog-frame.js +72 -0
- package/dist/cause-class.d.ts +19 -0
- package/dist/cause-class.js +54 -0
- package/dist/cloudflare.d.ts +123 -0
- package/dist/cloudflare.js +391 -0
- package/dist/computer-terminal.d.ts +38 -0
- package/dist/computer-terminal.js +410 -0
- package/dist/computer.d.ts +60 -0
- package/dist/computer.js +33 -0
- package/dist/event-recipients.d.ts +57 -0
- package/dist/event-recipients.js +144 -0
- package/dist/facet-invocation.d.ts +4 -0
- package/dist/facet-invocation.js +45 -0
- package/dist/files.d.ts +42 -0
- package/dist/files.js +123 -0
- package/dist/frame-binding-wire-script.d.ts +2 -0
- package/dist/frame-binding-wire-script.js +1 -0
- package/dist/frame-binding-wire.d.ts +28 -0
- package/dist/frame-binding-wire.js +54 -0
- package/dist/git-admission.d.ts +52 -0
- package/dist/git-admission.js +188 -0
- package/dist/git-auth.d.ts +11 -0
- package/dist/git-auth.js +27 -0
- package/dist/git-door.d.ts +35 -0
- package/dist/git-door.js +108 -0
- package/dist/git-journal.d.ts +31 -0
- package/dist/git-journal.js +188 -0
- package/dist/git.d.ts +31 -0
- package/dist/git.js +64 -0
- package/dist/guest-policy.d.ts +9 -0
- package/dist/guest-policy.js +13 -0
- package/dist/host.d.ts +244 -0
- package/dist/host.js +1043 -0
- package/dist/index.d.ts +166 -0
- package/dist/index.js +320 -0
- package/dist/installation-consent.d.ts +79 -0
- package/dist/installation-consent.js +82 -0
- package/dist/internal/background-origins.d.ts +3 -0
- package/dist/internal/background-origins.js +8 -0
- package/dist/internal/delivery.d.ts +12 -0
- package/dist/internal/delivery.js +167 -0
- package/dist/internal/host-gate.d.ts +14 -0
- package/dist/internal/host-gate.js +62 -0
- package/dist/internal/registry-installations.d.ts +6 -0
- package/dist/internal/registry-installations.js +12 -0
- package/dist/invocation.d.ts +251 -0
- package/dist/invocation.js +377 -0
- package/dist/keys.d.ts +48 -0
- package/dist/keys.js +52 -0
- package/dist/mcp-owner.d.ts +27 -0
- package/dist/mcp-owner.js +143 -0
- package/dist/mcp.d.ts +89 -0
- package/dist/mcp.js +429 -0
- package/dist/media.d.ts +23 -0
- package/dist/media.js +12 -0
- package/dist/pack.d.ts +76 -0
- package/dist/pack.js +134 -0
- package/dist/page/capabilities.d.ts +23 -0
- package/dist/page/capabilities.js +256 -0
- package/dist/page/computer-handles.d.ts +79 -0
- package/dist/page/computer-handles.js +44 -0
- package/dist/page/lifetime.d.ts +6 -0
- package/dist/page/lifetime.js +19 -0
- package/dist/page/mount.d.ts +163 -0
- package/dist/page/mount.js +390 -0
- package/dist/page/storage.d.ts +3 -0
- package/dist/page/storage.js +82 -0
- package/dist/page/terminal.d.ts +5 -0
- package/dist/page/terminal.js +7 -0
- package/dist/page-script.d.ts +14 -0
- package/dist/page-script.js +5 -0
- package/dist/r2-files.d.ts +3 -0
- package/dist/r2-files.js +79 -0
- package/dist/release.d.ts +72 -0
- package/dist/release.js +164 -0
- package/dist/root-data.d.ts +86 -0
- package/dist/root-data.js +69 -0
- package/dist/shell/app-directory.d.ts +537 -0
- package/dist/shell/app-directory.js +195 -0
- package/dist/shell/browser-actions.d.ts +7 -0
- package/dist/shell/browser-actions.js +56 -0
- package/dist/shell/command-host.d.ts +112 -0
- package/dist/shell/command-host.js +502 -0
- package/dist/shell/commands.d.ts +25 -0
- package/dist/shell/commands.js +78 -0
- package/dist/shell/index.d.ts +8 -0
- package/dist/shell/index.js +8 -0
- package/dist/shell/keys.d.ts +41 -0
- package/dist/shell/keys.js +134 -0
- package/dist/shell/shell-module.d.ts +31 -0
- package/dist/shell/shell-module.js +37 -0
- package/dist/shell/window-manager.d.ts +124 -0
- package/dist/shell/window-manager.js +711 -0
- package/dist/shell/workbench-contract.d.ts +68 -0
- package/dist/shell/workbench-contract.js +1 -0
- package/dist/shell/workbench-host-types.d.ts +96 -0
- package/dist/shell/workbench-host-types.js +1 -0
- package/dist/shell/workbench-host.d.ts +34 -0
- package/dist/shell/workbench-host.js +347 -0
- package/dist/shell/workbench-model.d.ts +192 -0
- package/dist/shell/workbench-model.js +53 -0
- package/dist/shell/workbench.d.ts +4 -0
- package/dist/shell/workbench.js +2 -0
- package/dist/source/fork.d.ts +27 -0
- package/dist/source/fork.js +46 -0
- package/dist/source/index.d.ts +11 -0
- package/dist/source/index.js +11 -0
- package/dist/source/seed-receipt.d.ts +53 -0
- package/dist/source/seed-receipt.js +18 -0
- package/dist/source/team-source.d.ts +32 -0
- package/dist/source/team-source.js +42 -0
- package/dist/source/template-repository.d.ts +2 -0
- package/dist/source/template-repository.js +8 -0
- package/dist/source/template-write.d.ts +69 -0
- package/dist/source/template-write.js +344 -0
- package/dist/storage-frame.d.ts +64 -0
- package/dist/storage-frame.js +28 -0
- package/dist/tenant.d.ts +81 -0
- package/dist/tenant.js +71 -0
- package/dist/testing/capabilities.d.ts +29 -0
- package/dist/testing/capabilities.js +130 -0
- package/dist/testing/catalog.d.ts +3 -0
- package/dist/testing/catalog.js +53 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.js +10 -0
- package/dist/testing/installation.d.ts +11 -0
- package/dist/testing/installation.js +25 -0
- package/dist/testing/native-worker.d.ts +21 -0
- package/dist/testing/native-worker.js +106 -0
- package/dist/testing/worker.d.ts +18 -0
- package/dist/testing/worker.js +67 -0
- package/dist/testing/workers-runtime.d.ts +24 -0
- package/dist/testing/workers-runtime.js +33 -0
- package/dist/webhook-delivery.d.ts +14 -0
- package/dist/webhook-delivery.js +17 -0
- package/dist/workers-git.d.ts +285 -0
- package/dist/workers-git.js +1174 -0
- package/dist/workers.d.ts +352 -0
- package/dist/workers.js +866 -0
- package/docs/api/README.md +82 -0
- package/docs/api/agents.md +332 -0
- package/docs/api/app-storage.md +209 -0
- package/docs/api/apps.md +1375 -0
- package/docs/api/auth.md +63 -0
- package/docs/api/build-contract.md +507 -0
- package/docs/api/build.md +1476 -0
- package/docs/api/cloudflare.md +421 -0
- package/docs/api/computer.md +203 -0
- package/docs/api/files.md +117 -0
- package/docs/api/git.md +470 -0
- package/docs/api/host.md +1328 -0
- package/docs/api/index.md +430 -0
- package/docs/api/invocation.md +738 -0
- package/docs/api/keys.md +175 -0
- package/docs/api/mcp.md +301 -0
- package/docs/api/media.md +40 -0
- package/docs/api/modules.md +42 -0
- package/docs/api/pack.md +138 -0
- package/docs/api/page/mount.md +298 -0
- package/docs/api/root-data.md +111 -0
- package/docs/api/shell/app-directory.md +332 -0
- package/docs/api/shell/command-host.md +224 -0
- package/docs/api/shell/commands.md +197 -0
- package/docs/api/shell/keys.md +183 -0
- package/docs/api/shell/shell-module.md +143 -0
- package/docs/api/shell/window-manager.md +267 -0
- package/docs/api/shell/workbench.md +186 -0
- package/docs/api/shell.md +1788 -0
- package/docs/api/tenant.md +194 -0
- package/docs/api/workers-git.md +1527 -0
- package/docs/api/workers.md +1678 -0
- package/docs/media/architecture.mmd +32 -0
- package/docs/media/architecture.png +0 -0
- package/docs/media/bonsai-network.png +0 -0
- package/docs/media/bonsai-repository.png +0 -0
- package/docs/site/agent-quickstart.mdx +349 -0
- package/examples/git/worker.ts +39 -0
- package/examples/git/wrangler.jsonc +32 -0
- package/examples/standalone/worker.ts +14 -0
- package/examples/standalone/wrangler.jsonc +21 -0
- package/package.json +249 -3
package/dist/build.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from "./build/effect.js";
|
|
2
|
+
export * from "./build/local-build.js";
|
|
3
|
+
export { createDefinitionEmission, type AppBackendOutput, type DefinitionEmission, } from "./build/definition-emission.js";
|
|
4
|
+
export { readBundledHtml } from "./build/bundled-html.js";
|
|
5
|
+
export { bundledHtmlRecipe, boundedBundlePolicy } from "./build/html-recipe.js";
|
|
6
|
+
export { resolveWorkspaceBuild, workspaceBuildPolicySchema, workspaceProjectsArguments, type WorkspaceBuild, type WorkspaceBuildPolicy, } from "./build/workspace-build.js";
|
|
7
|
+
export { workspaceBuildStepSchema, type WorkspaceBuildStep, } from "./build/build-step.js";
|
|
8
|
+
export { frozenSnapshotInstallArguments } from "./build/snapshot-package-store.js";
|
|
9
|
+
export { repositoryEnvironment, artifactsGitEnvironment, hostedArtifactsGitRemote, } from "./build/git-environment.js";
|
|
10
|
+
/** Captured-dependency build program with guarded filesystem access. */
|
|
11
|
+
export declare const dependencyBuildProgram: string;
|
package/dist/build.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Node-only App source capture, compilation and artifact writing. */
|
|
2
|
+
import { dependencyBuildProgram as bundledDependencyBuildProgram } from "#snapshot-program-scripts";
|
|
3
|
+
export * from "./build/effect.js";
|
|
4
|
+
export * from "./build/local-build.js";
|
|
5
|
+
export { createDefinitionEmission, } from "./build/definition-emission.js";
|
|
6
|
+
export { readBundledHtml } from "./build/bundled-html.js";
|
|
7
|
+
export { bundledHtmlRecipe, boundedBundlePolicy } from "./build/html-recipe.js";
|
|
8
|
+
export { resolveWorkspaceBuild, workspaceBuildPolicySchema, workspaceProjectsArguments, } from "./build/workspace-build.js";
|
|
9
|
+
export { workspaceBuildStepSchema, } from "./build/build-step.js";
|
|
10
|
+
export { frozenSnapshotInstallArguments } from "./build/snapshot-package-store.js";
|
|
11
|
+
export { repositoryEnvironment, artifactsGitEnvironment, hostedArtifactsGitRemote, } from "./build/git-environment.js";
|
|
12
|
+
/** Captured-dependency build program with guarded filesystem access. */
|
|
13
|
+
export const dependencyBuildProgram = bundledDependencyBuildProgram;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
/** How an admitted capability method is exposed to the App. */
|
|
3
|
+
export declare const capabilityMethodKindSchema: Schema.Literals<readonly ["json", "transport", "read", "write"]>;
|
|
4
|
+
/** The four supported capability method kinds. */
|
|
5
|
+
export type CapabilityMethodKind = Schema.Schema.Type<typeof capabilityMethodKindSchema>;
|
|
6
|
+
/** The HTTP operation exposed by one capability method on an Oyster page. */
|
|
7
|
+
export declare const capabilityMethodSchema: Schema.Union<readonly [Schema.Struct<{
|
|
8
|
+
readonly kind: Schema.Literal<"transport">;
|
|
9
|
+
readonly method: Schema.Literals<readonly ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "ANY"]>;
|
|
10
|
+
readonly path: Schema.String;
|
|
11
|
+
}>, Schema.Struct<{
|
|
12
|
+
readonly kind: Schema.Literals<readonly ["json", "read", "write"]>;
|
|
13
|
+
readonly method: Schema.Literals<readonly ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]>;
|
|
14
|
+
readonly path: Schema.String;
|
|
15
|
+
}>]>;
|
|
16
|
+
/** The serializable part of a capability admitted to an installation's page. */
|
|
17
|
+
export declare const capabilityDescriptorSchema: Schema.Struct<{
|
|
18
|
+
readonly id: Schema.String;
|
|
19
|
+
readonly version: Schema.Number;
|
|
20
|
+
readonly base: Schema.String;
|
|
21
|
+
readonly methods: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.Struct<{
|
|
22
|
+
readonly kind: Schema.Literal<"transport">;
|
|
23
|
+
readonly method: Schema.Literals<readonly ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "ANY"]>;
|
|
24
|
+
readonly path: Schema.String;
|
|
25
|
+
}>, Schema.Struct<{
|
|
26
|
+
readonly kind: Schema.Literals<readonly ["json", "read", "write"]>;
|
|
27
|
+
readonly method: Schema.Literals<readonly ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]>;
|
|
28
|
+
readonly path: Schema.String;
|
|
29
|
+
}>]>>;
|
|
30
|
+
}>;
|
|
31
|
+
/** A page descriptor carries routing, never the authority to use a capability. */
|
|
32
|
+
export type CapabilityDescriptor = Schema.Schema.Type<typeof capabilityDescriptorSchema>;
|
|
33
|
+
/** A UI-only member deputy. Its operation joins the ordinary installation consent owner. */
|
|
34
|
+
export declare const appCallsDescriptor: {
|
|
35
|
+
readonly id: "apps.call";
|
|
36
|
+
readonly permission: "apps.call";
|
|
37
|
+
readonly version: 1;
|
|
38
|
+
readonly base: "/apps/";
|
|
39
|
+
readonly methods: {
|
|
40
|
+
readonly call: {
|
|
41
|
+
readonly kind: "json";
|
|
42
|
+
readonly method: "POST";
|
|
43
|
+
readonly path: ":caller/calls/:appId/:method";
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
/** How an admitted capability method is exposed to the App. */
|
|
3
|
+
export const capabilityMethodKindSchema = Schema.Literals([
|
|
4
|
+
"json",
|
|
5
|
+
"transport",
|
|
6
|
+
"read",
|
|
7
|
+
"write",
|
|
8
|
+
]);
|
|
9
|
+
const httpMethods = [
|
|
10
|
+
"GET",
|
|
11
|
+
"POST",
|
|
12
|
+
"PUT",
|
|
13
|
+
"DELETE",
|
|
14
|
+
"PATCH",
|
|
15
|
+
"HEAD",
|
|
16
|
+
"OPTIONS",
|
|
17
|
+
];
|
|
18
|
+
/** The HTTP operation exposed by one capability method on an Oyster page. */
|
|
19
|
+
export const capabilityMethodSchema = Schema.Union([
|
|
20
|
+
Schema.Struct({
|
|
21
|
+
kind: Schema.Literal("transport"),
|
|
22
|
+
method: Schema.Literals([...httpMethods, "ANY"]),
|
|
23
|
+
path: Schema.String,
|
|
24
|
+
}),
|
|
25
|
+
Schema.Struct({
|
|
26
|
+
kind: Schema.Literals(["json", "read", "write"]),
|
|
27
|
+
method: Schema.Literals(httpMethods),
|
|
28
|
+
path: Schema.String,
|
|
29
|
+
}),
|
|
30
|
+
]);
|
|
31
|
+
/** The serializable part of a capability admitted to an installation's page. */
|
|
32
|
+
export const capabilityDescriptorSchema = Schema.Struct({
|
|
33
|
+
id: Schema.String,
|
|
34
|
+
version: Schema.Number,
|
|
35
|
+
base: Schema.String,
|
|
36
|
+
methods: Schema.Record(Schema.String, capabilityMethodSchema),
|
|
37
|
+
});
|
|
38
|
+
/** A UI-only member deputy. Its operation joins the ordinary installation consent owner. */
|
|
39
|
+
export const appCallsDescriptor = {
|
|
40
|
+
id: "apps.call",
|
|
41
|
+
permission: "apps.call",
|
|
42
|
+
version: 1,
|
|
43
|
+
base: "/apps/",
|
|
44
|
+
methods: {
|
|
45
|
+
call: {
|
|
46
|
+
kind: "json",
|
|
47
|
+
method: "POST",
|
|
48
|
+
path: ":caller/calls/:appId/:method",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
import type { OysterRootDirectory } from "./root-data.js";
|
|
3
|
+
import type { OysterBindingResult } from "./workers.js";
|
|
4
|
+
/** Guest input for `APPS.fork`: the platform App to fork and a chosen label. */
|
|
5
|
+
export declare const appForkInputSchema: Schema.Struct<{
|
|
6
|
+
readonly platformAppId: Schema.refine<import("@fungi.computer/puffball").AppId, Schema.String>;
|
|
7
|
+
readonly name: Schema.String;
|
|
8
|
+
}>;
|
|
9
|
+
export type AppForkInput = Schema.Schema.Type<typeof appForkInputSchema>;
|
|
10
|
+
/** The closed result union `forkAppSource` already returns. */
|
|
11
|
+
export declare const appForkResultSchema: Schema.Union<readonly [Schema.Struct<{
|
|
12
|
+
readonly kind: Schema.Literal<"forked">;
|
|
13
|
+
readonly appId: Schema.String;
|
|
14
|
+
readonly repository: Schema.String;
|
|
15
|
+
}>, Schema.Struct<{
|
|
16
|
+
readonly kind: Schema.Literals<readonly ["unauthorized", "conflict", "provider_unavailable"]>;
|
|
17
|
+
}>]>;
|
|
18
|
+
/** Canonical read-only App metadata, projected from the existing root
|
|
19
|
+
* directory. Typed as the binding's own result, so every consumer --
|
|
20
|
+
* in this package or across one -- gets the real return type directly. */
|
|
21
|
+
export declare function oysterAppCatalog(directory: OysterRootDirectory): OysterBindingResult;
|
|
22
|
+
/** The plain host exposes only `catalog`; a Git-capable host also wires `fork`. */
|
|
23
|
+
export declare const catalogFrameMethods: {
|
|
24
|
+
APPS: {
|
|
25
|
+
catalog: {
|
|
26
|
+
decodeArgs: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => readonly [{}];
|
|
27
|
+
decodeResult: (raw: unknown) => OysterBindingResult;
|
|
28
|
+
requiredOperations: () => string[];
|
|
29
|
+
};
|
|
30
|
+
fork: {
|
|
31
|
+
decodeArgs: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => readonly [{
|
|
32
|
+
readonly platformAppId: import("@fungi.computer/puffball").AppId;
|
|
33
|
+
readonly name: string;
|
|
34
|
+
}];
|
|
35
|
+
decodeResult: (raw: unknown) => OysterBindingResult;
|
|
36
|
+
requiredOperations: () => string[];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
import { appIdSchema } from "@fungi.computer/puffball/effect";
|
|
3
|
+
import { appCatalogResponseSchema, } from "./shell/app-directory.js";
|
|
4
|
+
/** Guest input for `APPS.fork`: the platform App to fork and a chosen label. */
|
|
5
|
+
export const appForkInputSchema = Schema.Struct({
|
|
6
|
+
platformAppId: appIdSchema,
|
|
7
|
+
name: Schema.String.pipe(Schema.check(Schema.isMinLength(1)), Schema.check(Schema.isMaxLength(63))),
|
|
8
|
+
});
|
|
9
|
+
/** The closed result union `forkAppSource` already returns. */
|
|
10
|
+
export const appForkResultSchema = Schema.Union([
|
|
11
|
+
Schema.Struct({
|
|
12
|
+
kind: Schema.Literal("forked"),
|
|
13
|
+
appId: Schema.String,
|
|
14
|
+
repository: Schema.String,
|
|
15
|
+
}),
|
|
16
|
+
Schema.Struct({
|
|
17
|
+
kind: Schema.Literals(["unauthorized", "conflict", "provider_unavailable"]),
|
|
18
|
+
}),
|
|
19
|
+
]);
|
|
20
|
+
/** Canonical read-only App metadata, projected from the existing root
|
|
21
|
+
* directory. Typed as the binding's own result, so every consumer --
|
|
22
|
+
* in this package or across one -- gets the real return type directly. */
|
|
23
|
+
export function oysterAppCatalog(directory) {
|
|
24
|
+
const roles = {};
|
|
25
|
+
if (directory.roles.inbox !== undefined)
|
|
26
|
+
roles.inbox = directory.roles.inbox;
|
|
27
|
+
return appCatalogResponseSchema.parse({
|
|
28
|
+
apps: directory.apps
|
|
29
|
+
.filter((app) => app.availability === "available" &&
|
|
30
|
+
app.surface !== null &&
|
|
31
|
+
app.releaseId !== null &&
|
|
32
|
+
!app.roles.includes("dashboard"))
|
|
33
|
+
.map((app) => {
|
|
34
|
+
const entry = {
|
|
35
|
+
surfaceId: app.surfaceId,
|
|
36
|
+
appId: app.appId,
|
|
37
|
+
gills: app.gills.map((gill) => {
|
|
38
|
+
const metadata = {
|
|
39
|
+
id: gill.id,
|
|
40
|
+
title: gill.title,
|
|
41
|
+
};
|
|
42
|
+
if (gill.desktop !== undefined)
|
|
43
|
+
metadata.desktop = { sizes: [...gill.desktop.sizes] };
|
|
44
|
+
return metadata;
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
if (app.displayName !== undefined)
|
|
48
|
+
entry.displayName = app.displayName;
|
|
49
|
+
return entry;
|
|
50
|
+
}),
|
|
51
|
+
roles,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** The plain host exposes only `catalog`; a Git-capable host also wires `fork`. */
|
|
55
|
+
export const catalogFrameMethods = {
|
|
56
|
+
APPS: {
|
|
57
|
+
catalog: {
|
|
58
|
+
decodeArgs: Schema.decodeUnknownSync(Schema.Tuple([Schema.Struct({})]), {
|
|
59
|
+
onExcessProperty: "error",
|
|
60
|
+
}),
|
|
61
|
+
decodeResult: (raw) => appCatalogResponseSchema.parse(raw),
|
|
62
|
+
requiredOperations: () => ["catalog"],
|
|
63
|
+
},
|
|
64
|
+
fork: {
|
|
65
|
+
decodeArgs: Schema.decodeUnknownSync(Schema.Tuple([appForkInputSchema]), {
|
|
66
|
+
onExcessProperty: "error",
|
|
67
|
+
}),
|
|
68
|
+
decodeResult: (raw) => Schema.decodeUnknownSync(appForkResultSchema)(raw),
|
|
69
|
+
requiredOperations: () => ["fork"],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Never copy a guest-controlled name, message or stack into host diagnostics. */
|
|
2
|
+
export declare function causeClass(cause: unknown): "TypeError" | "RangeError" | "SyntaxError" | "AbortError" | "TimeoutError" | "Other" | "Error";
|
|
3
|
+
/** Mark a failure that came back through the App facet so host logs keep only its class. */
|
|
4
|
+
export declare function guestFailure<E extends Error>(cause: E): E;
|
|
5
|
+
declare const platformFlags: readonly ["remote", "retryable", "overloaded", "durableObjectReset"];
|
|
6
|
+
export type PlatformFlag = (typeof platformFlags)[number];
|
|
7
|
+
/** A host-owned failure diagnostic; see {@link failureDiagnostic}. */
|
|
8
|
+
export type FailureDiagnostic = {
|
|
9
|
+
causeClass: ReturnType<typeof causeClass>;
|
|
10
|
+
platform?: PlatformFlag[];
|
|
11
|
+
message?: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* One host-owned failure diagnostic: the closed cause class, the workerd
|
|
15
|
+
* platform flags that are `true`, and, only when no guest produced the failure,
|
|
16
|
+
* its first message line bounded to {@link maxDiagnosticMessage} characters.
|
|
17
|
+
*/
|
|
18
|
+
export declare function failureDiagnostic(cause: unknown): FailureDiagnostic;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Never copy a guest-controlled name, message or stack into host diagnostics. */
|
|
2
|
+
export function causeClass(cause) {
|
|
3
|
+
if (cause instanceof TypeError)
|
|
4
|
+
return "TypeError";
|
|
5
|
+
if (cause instanceof RangeError)
|
|
6
|
+
return "RangeError";
|
|
7
|
+
if (cause instanceof SyntaxError)
|
|
8
|
+
return "SyntaxError";
|
|
9
|
+
if (cause instanceof DOMException) {
|
|
10
|
+
if (cause.name === "AbortError")
|
|
11
|
+
return "AbortError";
|
|
12
|
+
if (cause.name === "TimeoutError")
|
|
13
|
+
return "TimeoutError";
|
|
14
|
+
return "Other";
|
|
15
|
+
}
|
|
16
|
+
return cause instanceof Error ? "Error" : "Other";
|
|
17
|
+
}
|
|
18
|
+
/** Failures that crossed the App facet boundary; their text may be guest-authored. */
|
|
19
|
+
const guestCrossed = new WeakSet();
|
|
20
|
+
/** Mark a failure that came back through the App facet so host logs keep only its class. */
|
|
21
|
+
export function guestFailure(cause) {
|
|
22
|
+
guestCrossed.add(cause);
|
|
23
|
+
return cause;
|
|
24
|
+
}
|
|
25
|
+
const maxDiagnosticMessage = 240;
|
|
26
|
+
const platformFlags = [
|
|
27
|
+
"remote",
|
|
28
|
+
"retryable",
|
|
29
|
+
"overloaded",
|
|
30
|
+
"durableObjectReset",
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* One host-owned failure diagnostic: the closed cause class, the workerd
|
|
34
|
+
* platform flags that are `true`, and, only when no guest produced the failure,
|
|
35
|
+
* its first message line bounded to {@link maxDiagnosticMessage} characters.
|
|
36
|
+
*/
|
|
37
|
+
export function failureDiagnostic(cause) {
|
|
38
|
+
const diagnostic = { causeClass: causeClass(cause) };
|
|
39
|
+
if (!(cause instanceof Error))
|
|
40
|
+
return diagnostic;
|
|
41
|
+
const flags = platformFlags.filter((flag) => Object.getOwnPropertyDescriptor(cause, flag)?.value === true);
|
|
42
|
+
if (flags.length > 0)
|
|
43
|
+
diagnostic.platform = flags;
|
|
44
|
+
if (!guestCrossed.has(cause)) {
|
|
45
|
+
const [line = ""] = cause.message.split("\n", 1);
|
|
46
|
+
// Control characters become spaces so one failure stays one log line.
|
|
47
|
+
const message = line
|
|
48
|
+
.replace(/\p{Cc}/gu, " ")
|
|
49
|
+
.slice(0, maxDiagnosticMessage);
|
|
50
|
+
if (message.length > 0)
|
|
51
|
+
diagnostic.message = message;
|
|
52
|
+
}
|
|
53
|
+
return diagnostic;
|
|
54
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { type FrameBindingReply } from "./frame-binding-wire.js";
|
|
2
|
+
export type { FrameBindingReply, FrameBindingWire, } from "./frame-binding-wire.js";
|
|
3
|
+
export type { BackgroundFrameState } from "./invocation.js";
|
|
4
|
+
import { WorkerEntrypoint } from "cloudflare:workers";
|
|
5
|
+
import { type GuestLimits } from "./guest-policy.js";
|
|
6
|
+
export type { GuestLimits } from "./guest-policy.js";
|
|
7
|
+
import { type AppBackendBindingName } from "@fungi.computer/puffball/app";
|
|
8
|
+
import { type InvocationFrame, type InvocationGate } from "./invocation.js";
|
|
9
|
+
import * as Schema from "effect/Schema";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import type { WatchdogSqliteOwner } from "@fungi.computer/watchdog";
|
|
12
|
+
import { type AppInstance, type InstancePorts } from "./index.js";
|
|
13
|
+
/** Encode supervisor refusals before native RPC can discard Error properties. */
|
|
14
|
+
export declare function captureFrameBindingReply<Value>(run: () => Promise<Value>): Promise<FrameBindingReply<Value>>;
|
|
15
|
+
/** Retained shard reply ceiling; replies settle before the frame aborts its facet. */
|
|
16
|
+
export declare const MAX_APP_REPLY_BYTES: number;
|
|
17
|
+
/** Host-minted caller-frame routing props; never supplied by the App. */
|
|
18
|
+
export type FrameBindingProps = Readonly<{
|
|
19
|
+
instanceId: string;
|
|
20
|
+
binding: AppBackendBindingName;
|
|
21
|
+
frameId: string;
|
|
22
|
+
}>;
|
|
23
|
+
/** The host's maintained positional argument/result codecs and operation policy. */
|
|
24
|
+
export type FrameBindingMethod<Result> = Readonly<{
|
|
25
|
+
/** Decode the guest's positional arguments with the maintained method grammar. */
|
|
26
|
+
decodeArgs: (raw: readonly unknown[]) => readonly unknown[];
|
|
27
|
+
decodeResult: z.ZodType<Result>["parse"];
|
|
28
|
+
/** Determine the declared operations needed for these decoded arguments. */
|
|
29
|
+
requiredOperations: (args: readonly unknown[]) => readonly string[];
|
|
30
|
+
}>;
|
|
31
|
+
/** Method descriptors for the closed App binding vocabulary. */
|
|
32
|
+
export type FrameBindingMethods<Result> = Readonly<Partial<Record<AppBackendBindingName, Readonly<Record<string, FrameBindingMethod<Result>>>>>>;
|
|
33
|
+
/** Shared replay-only port codecs. Origin input is verified by the host and fails with a typed refusal. */
|
|
34
|
+
export declare const backgroundFrameMethods: {
|
|
35
|
+
BACKGROUND: {
|
|
36
|
+
admit: {
|
|
37
|
+
/** Malformed arity supplies invalid origin evidence for the host's typed refusal. */
|
|
38
|
+
decodeArgs: (raw: readonly unknown[]) => [unknown] | undefined[];
|
|
39
|
+
/** Preserve the host's closed admitted/refused result. */
|
|
40
|
+
decodeResult: (raw: unknown) => {
|
|
41
|
+
kind: "admitted";
|
|
42
|
+
} | {
|
|
43
|
+
kind: "refused";
|
|
44
|
+
code: "access_changed";
|
|
45
|
+
};
|
|
46
|
+
/** Only the host-minted replay grant supplies this operation. */
|
|
47
|
+
requiredOperations: () => string[];
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
/** The shared RPC boundary decoder for host-minted invocation binding props. */
|
|
52
|
+
export declare const frameBindingPropsSchema: Schema.Struct<{
|
|
53
|
+
readonly instanceId: Schema.Codec<import("./index.js").InstanceId, string, never, never>;
|
|
54
|
+
readonly frameId: Schema.String;
|
|
55
|
+
readonly binding: Schema.refine<"BACKGROUND" | "GIT" | "EVENTS" | "APPS" | "WORKFLOWS" | "APP_STORAGE" | "MEDIA" | "COMPUTER" | "INBOX" | "AGENTS", Schema.String>;
|
|
56
|
+
}>;
|
|
57
|
+
/** Decode a host routing packet or refuse it before any Instance lookup. */
|
|
58
|
+
export declare function decodeFrameBindingProps(raw: unknown): FrameBindingProps;
|
|
59
|
+
/** One native binding factory for both Hub and standalone, preserving RPC values. */
|
|
60
|
+
export declare function frameBindingEntrypoint<Env, Result>(methods: FrameBindingMethods<Result>, dispatch: (env: Env, props: FrameBindingProps, method: string, args: readonly unknown[]) => Promise<FrameBindingReply<unknown>>): typeof WorkerEntrypoint<Env, FrameBindingProps>;
|
|
61
|
+
/** Native facet handle; method RPCs are decoded at the invocation boundary. */
|
|
62
|
+
export type AppFacetStub = Readonly<{
|
|
63
|
+
/** Issue an HTTP request through the native facet handle. */
|
|
64
|
+
fetch: (request: Request) => Promise<Response>;
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* Only the native storage and facet capabilities used by an App Instance.
|
|
68
|
+
* `FacetClass` is the host's Durable Object class type (`DurableObjectClass`
|
|
69
|
+
* on workerd, celld and Cloudflare); Oyster passes it through unopened.
|
|
70
|
+
*/
|
|
71
|
+
export type AppInstanceContext<FacetClass> = Readonly<{
|
|
72
|
+
/** The Durable Object's ID; its `name` is the Instance ID. */
|
|
73
|
+
id: Readonly<{
|
|
74
|
+
name?: string | undefined;
|
|
75
|
+
}>;
|
|
76
|
+
/** The Durable Object's SQLite storage, used for supervisor state only. */
|
|
77
|
+
storage: WatchdogSqliteOwner;
|
|
78
|
+
/** The Durable Object's facets; the App backend runs in the `app` facet. */
|
|
79
|
+
facets: Readonly<{
|
|
80
|
+
/** Get or create the named facet from the class `prepare` returns. */
|
|
81
|
+
get: (name: string, prepare: () => {
|
|
82
|
+
class: FacetClass;
|
|
83
|
+
}) => AppFacetStub;
|
|
84
|
+
/** Abort the named facet's in-flight work with `reason`. */
|
|
85
|
+
abort: (name: string, reason: Error) => void;
|
|
86
|
+
/** Delete the named facet and its storage. */
|
|
87
|
+
delete: (name: string) => void;
|
|
88
|
+
}>;
|
|
89
|
+
}>;
|
|
90
|
+
/** The module set the Worker Loader runs for one App backend. */
|
|
91
|
+
export type AppWorkerCode = Readonly<{
|
|
92
|
+
compatibilityDate: string;
|
|
93
|
+
mainModule: string;
|
|
94
|
+
modules: Readonly<Record<string, string>>;
|
|
95
|
+
env: object;
|
|
96
|
+
globalOutbound: null;
|
|
97
|
+
/** Per-invocation guest budgets, enforced by the Worker Loader. */
|
|
98
|
+
limits: GuestLimits;
|
|
99
|
+
}>;
|
|
100
|
+
/** Loader memoization and class lookup; entrypoint access is not required. */
|
|
101
|
+
export type AppInstanceLoader<FacetClass> = Readonly<{
|
|
102
|
+
/** Get or load the Worker for `id`, calling `configure` only on a cache miss. */
|
|
103
|
+
get: (id: string, configure: () => AppWorkerCode) => Readonly<{
|
|
104
|
+
/** Look up the Durable Object class the backend exports as `exportName`. */
|
|
105
|
+
getDurableObjectClass: (exportName: string) => FacetClass;
|
|
106
|
+
}>;
|
|
107
|
+
}>;
|
|
108
|
+
/** End the native App facet before shared frame admission releases its permit. */
|
|
109
|
+
export declare function createCloudflareInvocationGate<Host, FacetClass>(ctx: Pick<AppInstanceContext<FacetClass>, "facets">, close: (frame: InvocationFrame<Host>) => Promise<void>): InvocationGate<Host>;
|
|
110
|
+
/**
|
|
111
|
+
* Run an App Instance inside a SQLite-backed Durable Object on workerd, celld
|
|
112
|
+
* or Cloudflare. Supervisor state lives in the Durable Object's own SQLite; the
|
|
113
|
+
* App backend runs in a named `app` facet loaded through the Worker Loader, so
|
|
114
|
+
* its database survives Release replacement and stays separate from the
|
|
115
|
+
* supervisor. Guest code gets only host gatekeeper bindings and no ambient outbound access.
|
|
116
|
+
*
|
|
117
|
+
* @param ctx - The Durable Object's name, storage and facets.
|
|
118
|
+
* @param loader - The Worker Loader binding; without it backend execution is unavailable.
|
|
119
|
+
* @param resolve - Resolves a Release ID to its verified durable backend.
|
|
120
|
+
* @param guestEnv - Mints loopbacks bound to the captured invocation frame.
|
|
121
|
+
* @param limits - Guest CPU and subrequest budgets; omitted fields use safe defaults.
|
|
122
|
+
*/
|
|
123
|
+
export declare function createCloudflareAppInstance<FacetClass, Host>(ctx: AppInstanceContext<FacetClass>, loader: AppInstanceLoader<FacetClass> | undefined, resolve: InstancePorts<Host>["resolve"], guestEnv: (frame: InvocationFrame<Host>) => object, limits?: Partial<GuestLimits>): AppInstance<Host>;
|