@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.
Files changed (86) hide show
  1. package/dist/agent-computer-source.d.ts +42 -0
  2. package/dist/agent-computer-source.js +88 -0
  3. package/dist/agent-computers.d.ts +104 -0
  4. package/dist/agent-computers.js +227 -0
  5. package/dist/agents.d.ts +10 -0
  6. package/dist/agents.js +33 -0
  7. package/dist/app-builds.d.ts +1 -1
  8. package/dist/app-builds.js +16 -6
  9. package/dist/boot-capability.d.ts +2 -1
  10. package/dist/boot-capability.js +7 -5
  11. package/dist/browser/boot.d.ts +2 -2
  12. package/dist/browser/boot.js +10 -3
  13. package/dist/browser/browser.d.ts +1 -1
  14. package/dist/browser/browser.js +2 -1
  15. package/dist/browser/cdp-client.d.ts +2 -0
  16. package/dist/browser/errors.d.ts +2 -2
  17. package/dist/browser/errors.js +2 -2
  18. package/dist/browser/index.d.ts +3 -2
  19. package/dist/browser/index.js +3 -2
  20. package/dist/browser/page.js +11 -4
  21. package/dist/browser/sessions.d.ts +7 -4
  22. package/dist/browser/sessions.js +159 -0
  23. package/dist/browser/url-policy.d.ts +4 -2
  24. package/dist/browser/url-policy.js +4 -2
  25. package/dist/build/build-jobs.d.ts +3 -3
  26. package/dist/build/build-jobs.js +10 -5
  27. package/dist/build/candidate-cli.js +5 -3
  28. package/dist/build/candidate-cli.mjs +223 -5
  29. package/dist/build/candidate-diagnostic.d.ts +2 -0
  30. package/dist/build/candidate-diagnostic.js +16 -0
  31. package/dist/computer-control-port.d.ts +26 -0
  32. package/dist/computer-control-port.js +1 -0
  33. package/dist/host.d.ts +3 -0
  34. package/dist/machine-link/delivery.d.ts +1 -1
  35. package/dist/machine-link/delivery.js +2 -3
  36. package/dist/machine-link/host.d.ts +37 -6
  37. package/dist/machine-link/host.js +209 -14
  38. package/dist/machine-link/link.d.ts +13 -1
  39. package/dist/machine-link/link.js +20 -7
  40. package/dist/mcp.d.ts +144 -10
  41. package/dist/mcp.js +130 -13
  42. package/dist/page/computer-handles.d.ts +3 -3
  43. package/dist/page-script.js +1 -1
  44. package/dist/standalone/agent-computers.d.ts +29 -0
  45. package/dist/standalone/agent-computers.js +101 -0
  46. package/dist/standalone/agent-mail.d.ts +41 -18
  47. package/dist/standalone/agent-model-choice.d.ts +29 -0
  48. package/dist/standalone/agent-model-choice.js +72 -0
  49. package/dist/standalone/agents.d.ts +44 -4
  50. package/dist/standalone/agents.js +502 -46
  51. package/dist/standalone/app-set.d.ts +8 -1
  52. package/dist/standalone/app-set.js +46 -31
  53. package/dist/standalone/computer-control.d.ts +4 -0
  54. package/dist/standalone/computer-control.js +62 -0
  55. package/dist/standalone/computer-fleet.d.ts +1 -0
  56. package/dist/standalone/computer-fleet.js +1 -1
  57. package/dist/standalone/computer.d.ts +21 -2
  58. package/dist/standalone/computer.js +12 -0
  59. package/dist/standalone/install-apps-bin.d.ts +2 -0
  60. package/dist/standalone/install-apps-bin.js +3 -0
  61. package/dist/standalone/install-apps-cli.d.ts +3 -1
  62. package/dist/standalone/install-apps-cli.js +27 -17
  63. package/dist/standalone/machine-link.d.ts +10 -0
  64. package/dist/standalone/machine-link.js +6 -0
  65. package/dist/standalone/registry.d.ts +10 -1
  66. package/dist/standalone/registry.js +9 -0
  67. package/dist/standalone/worker.js +12 -0
  68. package/dist/standalone/workflow-binding.d.ts +2 -2
  69. package/dist/standalone/workflow-host.d.ts +11 -11
  70. package/dist/standalone/workflows.d.ts +22 -22
  71. package/dist/storage-frame.d.ts +3 -3
  72. package/dist/workers-git.d.ts +2 -0
  73. package/dist/workers-git.js +2 -0
  74. package/dist/workers.d.ts +8 -8
  75. package/dist/workers.js +9 -1
  76. package/docs/api/agents.md +66 -0
  77. package/docs/api/apps.md +104 -104
  78. package/docs/api/build-contract.md +35 -35
  79. package/docs/api/build.md +12 -12
  80. package/docs/api/host.md +61 -61
  81. package/docs/api/mcp.md +127 -13
  82. package/docs/api/root-data.md +1 -1
  83. package/docs/api/tenancy.md +1 -1
  84. package/docs/api/workers-git.md +3 -2
  85. package/docs/api/workers.md +81 -83
  86. package/package.json +26 -18
package/dist/mcp.js CHANGED
@@ -15,8 +15,86 @@ import { appToolSchemas, appToolFamilySchemas } from "@fungi.computer/forage";
15
15
  import { Knapsack } from "@fungi.computer/knapsack";
16
16
  import * as Schema from "effect/Schema";
17
17
  import { defineIdFamily } from "@fungi.computer/cairn/id";
18
+ import { computerCreateRequestSchema, computerPageSchema, } from "@fungi.computer/computer/fleet/inventory-wire";
19
+ import { computerStateSchema } from "@fungi.computer/computer/fleet/wire";
20
+ import { teamComputerDirectorySchema } from "@fungi.computer/nacre/workbench";
18
21
  import { keyAppAccess } from "./keys.js";
19
22
  import { defaultAssetPolicy, sha256, verifyRelease, } from "./release.js";
23
+ const fleetIds = defineIdFamily({
24
+ family: "mcp-computer-control",
25
+ version: 1,
26
+ kinds: { request: { prefix: "computer_request" } },
27
+ });
28
+ const fleetComputerId = z.strictObject({
29
+ computerId: z.string().min(1).max(256),
30
+ });
31
+ const fleetCreate = z.strictObject({
32
+ name: computerCreateRequestSchema.shape.name
33
+ .unwrap()
34
+ .nullable()
35
+ .default(null),
36
+ requestId: computerCreateRequestSchema.shape.requestId
37
+ .nullable()
38
+ .default(null),
39
+ });
40
+ const fleetComputer = z.strictObject({
41
+ computerId: z.string(),
42
+ name: z.string(),
43
+ });
44
+ const fleetCreation = z.discriminatedUnion("kind", [
45
+ z.strictObject({
46
+ kind: z.literal("created"),
47
+ requestId: z.string(),
48
+ computer: fleetComputer,
49
+ }),
50
+ z.strictObject({
51
+ kind: z.enum(["uncertain", "denied", "conflict", "invalid"]),
52
+ requestId: z.string(),
53
+ }),
54
+ ]);
55
+ /** One set of schemas and operations for MCP and direct broker invocation. */
56
+ export function computerControlSpecs(port) {
57
+ return {
58
+ list: {
59
+ replay: "safe",
60
+ access: "read",
61
+ description: "List a page of permitted Computers. Follow nextOffset for another page.",
62
+ input: computerPageSchema,
63
+ output: teamComputerDirectorySchema,
64
+ /** Return an admitted inventory page to MCP or the retained broker. */
65
+ execute: (input, context) => port.list(input, context),
66
+ },
67
+ state: {
68
+ replay: "safe",
69
+ access: "read",
70
+ description: "Read runtime state without waking a Computer, including its live admission queue position.",
71
+ input: fleetComputerId,
72
+ output: computerStateSchema,
73
+ /** Return liveness without waking the runtime. */
74
+ execute: (input, context) => port.state(input.computerId, context),
75
+ },
76
+ start: {
77
+ replay: "unsafe",
78
+ description: "Start a hosted Computer through ordinary admission. Waits until connected; poll computers.state while queued. Safe to retry.",
79
+ input: fleetComputerId,
80
+ output: computerStateSchema,
81
+ /** Admit and start this Computer. */
82
+ execute: (input, context) => port.start(input.computerId, context),
83
+ },
84
+ create: {
85
+ replay: "unsafe",
86
+ description: "Create a Computer with an optional friendly name. Request identity is generated automatically. If the outcome is uncertain, retry with its returned requestId and the original name input; do not start a second creation.",
87
+ input: fleetCreate,
88
+ output: fleetCreation,
89
+ /** Mint one identity or preserve the requestId for an uncertain retry. */
90
+ execute: async (input, context) => {
91
+ const requestId = input.requestId ?? fleetIds.request.generate();
92
+ const result = await port.create({ name: input.name ?? undefined, requestId }, context);
93
+ return { ...result, requestId };
94
+ },
95
+ },
96
+ };
97
+ }
20
98
  /** Mints the requestId a tool family tool sends on the caller's behalf to its
21
99
  * declared `call` method: each MCP call is its own independent run, never a
22
100
  * replay the caller controls. */
@@ -372,9 +450,9 @@ export async function oysterAppMethods(host, principal, access, surfaces, preloa
372
450
  }
373
451
  /**
374
452
  * Capture the host's fixed Computer for one caller as a Knapsack source.
375
- * The host decides whether the caller holds Computer access; the Computer
376
- * owner accepts every call. Null when the host has no Computer or the caller
377
- * has no access. Grants name exactly the one captured module.
453
+ * The host decides whether the caller holds Computer access; the ComputerDO
454
+ * still checks its host-issued grant on every call. Null when the host has no
455
+ * Computer or the caller has no access. Grants name the captured module.
378
456
  */
379
457
  export async function oysterComputerTools(host, principal) {
380
458
  if (host.computerId === undefined || host.computer === undefined)
@@ -399,12 +477,12 @@ export async function oysterComputerTools(host, principal) {
399
477
  * methods, plus the host's Computer when the caller holds Computer access.
400
478
  * A key sees exactly the installations and levels its own grants admit, and
401
479
  * the Computer only with its own `computer.use` grant; each App retains its
402
- * own caller checks regardless. The owner's stored write approval of an
403
- * Agent's App tools is that principal's confirmation for App writes, so a
404
- * headless client can write; the shared MCP server asks the client to
405
- * approve every other write (an owner's own calls, the Computer). Each call
406
- * still re-admits the key, rechecks that same stored approval, and passes
407
- * the App's gate.
480
+ * own caller checks regardless. App writes use the host's approval record;
481
+ * stored approval of an Agent's App tools can permit headless App writes.
482
+ * The shared MCP server elicits consent for explicitly confirmed operations,
483
+ * including every advertised Workspace Computer call, even reads. Each call
484
+ * still re-admits the key, checks current App approval and passes the App's
485
+ * gate.
408
486
  */
409
487
  export function oysterMcpCatalogLoad(host) {
410
488
  const surfaces = appSurfaceCache(host);
@@ -435,6 +513,40 @@ export function oysterMcpCatalogLoad(host) {
435
513
  }
436
514
  const apps = await oysterAppMethods(host, principal, access, surfaces, installations);
437
515
  const computer = await oysterComputerTools(host, principal);
516
+ const fleet = host.computerControl?.(principal) ?? null;
517
+ const fleetSpecs = fleet === null ? null : computerControlSpecs(fleet);
518
+ const fleetSource = fleetSpecs === null
519
+ ? []
520
+ : [
521
+ {
522
+ id: "oyster-computer-control",
523
+ acquire: () => Promise.resolve({
524
+ snapshot: {
525
+ version: "team-computer-control",
526
+ modules: [
527
+ Mycelium.module({
528
+ id: "team-computer-control",
529
+ name: "computers",
530
+ operations: {
531
+ list: Mycelium.operation(fleetSpecs.list),
532
+ state: Mycelium.operation(fleetSpecs.state),
533
+ start: Mycelium.operation({
534
+ ...fleetSpecs.start,
535
+ confirm: true,
536
+ }),
537
+ create: Mycelium.operation({
538
+ ...fleetSpecs.create,
539
+ confirm: true,
540
+ }),
541
+ },
542
+ }),
543
+ ],
544
+ },
545
+ release: () => Promise.resolve(),
546
+ }),
547
+ },
548
+ ];
549
+ const fleetGrants = fleet === null ? {} : { "team-computer-control": "write" };
438
550
  const control = await host.workflows?.(principal);
439
551
  const workflowSources = control == null
440
552
  ? []
@@ -454,13 +566,18 @@ export function oysterMcpCatalogLoad(host) {
454
566
  if (computer === null)
455
567
  return {
456
568
  instructions: "Installed Apps on this Oyster. Each App is env.<APP>; dotted method names are nested properties, e.g. env.BONSAI.repos.list({}). Use forage.search / forage.describe to find methods.",
457
- grants: { ...apps.grants, ...workflowGrants },
458
- sources: [apps, ...workflowSources],
569
+ grants: { ...apps.grants, ...workflowGrants, ...fleetGrants },
570
+ sources: [apps, ...workflowSources, ...fleetSource],
459
571
  };
460
572
  return {
461
573
  instructions: 'Installed Apps and this Oyster\'s Computer. Each App is env.<APP>; dotted method names are nested properties, e.g. env.BONSAI.repos.list({}). The Computer is env.computers.workspace, e.g. env.computers.workspace.exec({command: "ls"}). Use forage.search / forage.describe to find methods.',
462
- grants: { ...apps.grants, ...computer.grants, ...workflowGrants },
463
- sources: [apps, computer, ...workflowSources],
574
+ grants: {
575
+ ...apps.grants,
576
+ ...computer.grants,
577
+ ...workflowGrants,
578
+ ...fleetGrants,
579
+ },
580
+ sources: [apps, computer, ...workflowSources, ...fleetSource],
464
581
  };
465
582
  };
466
583
  }
@@ -44,7 +44,7 @@ export declare class ComputerProcessesHandle extends RpcTarget implements Handle
44
44
  readonly command: string;
45
45
  readonly cwd: string | null;
46
46
  readonly startedAt: number;
47
- readonly state: "running" | "exited" | "uncertain";
47
+ readonly state: "running" | "uncertain" | "exited";
48
48
  readonly exitCode: number | null;
49
49
  readonly sync: "unknown" | "pending" | "synced";
50
50
  readonly endedAt: number | null;
@@ -56,7 +56,7 @@ export declare class ComputerProcessesHandle extends RpcTarget implements Handle
56
56
  readonly command: string;
57
57
  readonly cwd: string | null;
58
58
  readonly startedAt: number;
59
- readonly state: "running" | "exited" | "uncertain";
59
+ readonly state: "running" | "uncertain" | "exited";
60
60
  readonly exitCode: number | null;
61
61
  readonly sync: "unknown" | "pending" | "synced";
62
62
  readonly endedAt: number | null;
@@ -69,7 +69,7 @@ export declare class ComputerProcessesHandle extends RpcTarget implements Handle
69
69
  readonly command: string;
70
70
  readonly cwd: string | null;
71
71
  readonly startedAt: number;
72
- readonly state: "running" | "exited" | "uncertain";
72
+ readonly state: "running" | "uncertain" | "exited";
73
73
  readonly exitCode: number | null;
74
74
  readonly sync: "unknown" | "pending" | "synced";
75
75
  readonly endedAt: number | null;