@fungi.computer/oyster 0.2.0 → 0.3.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 (291) hide show
  1. package/README.md +396 -72
  2. package/dist/agents.d.ts +3 -2
  3. package/dist/agents.js +4 -2
  4. package/dist/app-builds.d.ts +81 -8
  5. package/dist/app-builds.js +213 -60
  6. package/dist/app-storage.d.ts +3 -3
  7. package/dist/approval-capability.d.ts +5 -0
  8. package/dist/approval-capability.js +46 -0
  9. package/dist/approval-home.d.ts +51 -0
  10. package/dist/approval-home.js +226 -0
  11. package/dist/apps/catalog.d.ts +335 -0
  12. package/dist/apps/catalog.js +46 -0
  13. package/dist/apps/gate.d.ts +20 -6
  14. package/dist/apps/gate.js +42 -16
  15. package/dist/apps/index.d.ts +3 -1
  16. package/dist/apps/index.js +3 -1
  17. package/dist/apps/installation.d.ts +132 -51
  18. package/dist/apps/installation.js +176 -70
  19. package/dist/apps/permissions.d.ts +247 -0
  20. package/dist/apps/permissions.js +255 -0
  21. package/dist/boot-capability-route.d.ts +15 -0
  22. package/dist/boot-capability-route.js +196 -0
  23. package/dist/boot-capability.d.ts +103 -0
  24. package/dist/boot-capability.js +141 -0
  25. package/dist/boot-construction.d.ts +12 -0
  26. package/dist/boot-construction.js +175 -0
  27. package/dist/boot-gate.d.ts +267 -0
  28. package/dist/boot-gate.js +236 -0
  29. package/dist/boot-host-script.d.ts +2 -0
  30. package/dist/boot-host-script.js +1 -0
  31. package/dist/boot-mount.d.ts +21 -0
  32. package/dist/boot-mount.js +65 -0
  33. package/dist/browser/boot.d.ts +73 -0
  34. package/dist/browser/boot.js +502 -0
  35. package/dist/browser/browser.d.ts +104 -0
  36. package/dist/browser/browser.js +374 -0
  37. package/dist/browser/capability-source.d.ts +76 -0
  38. package/dist/browser/capability-source.js +338 -0
  39. package/dist/browser/cdp-client.d.ts +56 -0
  40. package/dist/browser/cdp-client.js +184 -0
  41. package/dist/browser/errors.d.ts +79 -0
  42. package/dist/browser/errors.js +32 -0
  43. package/dist/browser/index.d.ts +16 -0
  44. package/dist/browser/index.js +14 -0
  45. package/dist/browser/lease-registry.d.ts +61 -0
  46. package/dist/browser/lease-registry.js +101 -0
  47. package/dist/browser/operations.d.ts +225 -0
  48. package/dist/browser/operations.js +137 -0
  49. package/dist/browser/page.d.ts +25 -0
  50. package/dist/browser/page.js +172 -0
  51. package/dist/browser/quick-reads.d.ts +29 -0
  52. package/dist/browser/quick-reads.js +160 -0
  53. package/dist/browser/sessions.d.ts +52 -0
  54. package/dist/browser/sessions.js +118 -0
  55. package/dist/browser/url-policy.d.ts +18 -0
  56. package/dist/browser/url-policy.js +58 -0
  57. package/dist/build/app-imports.d.ts +12 -0
  58. package/dist/build/app-imports.js +105 -0
  59. package/dist/build/build-policy.d.ts +5 -3
  60. package/dist/build/build-policy.js +5 -3
  61. package/dist/build/candidate-builder.d.ts +1 -1
  62. package/dist/build/candidate-cli.mjs +8375 -334
  63. package/dist/build/local-build.d.ts +2 -0
  64. package/dist/build/local-build.js +28 -6
  65. package/dist/build/snapshot-package-store.d.ts +1 -1
  66. package/dist/build/snapshot-package-store.js +7 -2
  67. package/dist/build/workspace-build.d.ts +92 -5
  68. package/dist/build/workspace-build.js +93 -19
  69. package/dist/build.d.ts +1 -1
  70. package/dist/build.js +1 -1
  71. package/dist/catalog-frame.js +1 -1
  72. package/dist/cloudflare.d.ts +13 -3
  73. package/dist/cloudflare.js +102 -4
  74. package/dist/frame-binding-wire-script.js +1 -1
  75. package/dist/frame-binding-wire.js +4 -2
  76. package/dist/git-auth.d.ts +0 -2
  77. package/dist/git-auth.js +0 -2
  78. package/dist/git.d.ts +0 -1
  79. package/dist/git.js +0 -2
  80. package/dist/host.d.ts +39 -13
  81. package/dist/host.js +268 -142
  82. package/dist/index.d.ts +25 -15
  83. package/dist/index.js +39 -16
  84. package/dist/install-release-cli.d.ts +2 -0
  85. package/dist/install-release-cli.js +46 -0
  86. package/dist/installation-client.d.ts +43 -0
  87. package/dist/installation-client.js +178 -0
  88. package/dist/installation-execution.d.ts +11 -0
  89. package/dist/installation-execution.js +184 -0
  90. package/dist/installation-operations.d.ts +1437 -0
  91. package/dist/installation-operations.js +664 -0
  92. package/dist/installation-store-generation.d.ts +3 -0
  93. package/dist/installation-store-generation.js +16 -0
  94. package/dist/instance-id.d.ts +10 -0
  95. package/dist/instance-id.js +10 -0
  96. package/dist/instance-refusal.d.ts +11 -0
  97. package/dist/instance-refusal.js +21 -0
  98. package/dist/internal/delivery.js +4 -2
  99. package/dist/internal/host-gate.js +7 -1
  100. package/dist/internal/registry-installations.js +4 -4
  101. package/dist/keys.d.ts +5 -1
  102. package/dist/keys.js +10 -2
  103. package/dist/machine-link/authority.d.ts +89 -0
  104. package/dist/machine-link/authority.js +37 -0
  105. package/dist/machine-link/client.d.ts +66 -0
  106. package/dist/machine-link/client.js +94 -0
  107. package/dist/machine-link/delivery.d.ts +18 -0
  108. package/dist/machine-link/delivery.js +55 -0
  109. package/dist/machine-link/enrollment.d.ts +111 -0
  110. package/dist/machine-link/enrollment.js +286 -0
  111. package/dist/machine-link/fences.d.ts +37 -0
  112. package/dist/machine-link/fences.js +166 -0
  113. package/dist/machine-link/home.d.ts +20 -0
  114. package/dist/machine-link/home.js +24 -0
  115. package/dist/machine-link/host.d.ts +43 -0
  116. package/dist/machine-link/host.js +189 -0
  117. package/dist/machine-link/index.d.ts +15 -0
  118. package/dist/machine-link/index.js +15 -0
  119. package/dist/machine-link/link.d.ts +48 -0
  120. package/dist/machine-link/link.js +223 -0
  121. package/dist/machine-link/presence.d.ts +10 -0
  122. package/dist/machine-link/presence.js +25 -0
  123. package/dist/machine-link/workers.d.ts +6 -0
  124. package/dist/machine-link/workers.js +6 -0
  125. package/dist/mcp-owner.d.ts +2 -2
  126. package/dist/mcp-owner.js +41 -33
  127. package/dist/mcp.d.ts +15 -3
  128. package/dist/mcp.js +146 -25
  129. package/dist/older-oyster-store-refusal.d.ts +4 -0
  130. package/dist/older-oyster-store-refusal.js +18 -0
  131. package/dist/older-oyster-store.d.ts +21 -0
  132. package/dist/older-oyster-store.js +43 -0
  133. package/dist/pack.d.ts +14 -3
  134. package/dist/pack.js +44 -19
  135. package/dist/page/app-access.d.ts +7 -0
  136. package/dist/page/app-access.js +75 -0
  137. package/dist/page/boot-host.js +57 -0
  138. package/dist/page/capabilities.d.ts +3 -3
  139. package/dist/page/capabilities.js +16 -12
  140. package/dist/page/computer-handles.d.ts +3 -3
  141. package/dist/page/computer-target.d.ts +3 -0
  142. package/dist/page/computer-target.js +9 -0
  143. package/dist/page/mount.d.ts +23 -3
  144. package/dist/page/mount.js +152 -16
  145. package/dist/page-assets.d.ts +22 -0
  146. package/dist/page-assets.js +28 -0
  147. package/dist/page-script.d.ts +3 -0
  148. package/dist/page-script.js +5 -4
  149. package/dist/release.d.ts +13 -6
  150. package/dist/release.js +10 -7
  151. package/dist/root-data.d.ts +16 -6
  152. package/dist/root-data.js +2 -2
  153. package/dist/source/index.d.ts +1 -1
  154. package/dist/source/team-source.d.ts +20 -8
  155. package/dist/source/team-source.js +39 -10
  156. package/dist/source/template-seed.d.ts +2 -2
  157. package/dist/standalone/agent-mail.d.ts +24 -0
  158. package/dist/standalone/agent-mail.js +62 -0
  159. package/dist/standalone/agent-store.d.ts +9 -0
  160. package/dist/standalone/agent-store.js +30 -0
  161. package/dist/standalone/agents.d.ts +68 -9
  162. package/dist/standalone/agents.js +428 -56
  163. package/dist/standalone/app-builds-binding.d.ts +20 -2
  164. package/dist/standalone/app-builds-binding.js +147 -23
  165. package/dist/standalone/app-set.d.ts +5 -2
  166. package/dist/standalone/app-set.js +186 -144
  167. package/dist/standalone/browser.d.ts +11 -0
  168. package/dist/standalone/browser.js +72 -0
  169. package/dist/standalone/builds.d.ts +13 -4
  170. package/dist/standalone/builds.js +28 -44
  171. package/dist/standalone/computer-egress.d.ts +2 -0
  172. package/dist/standalone/computer-egress.js +13 -4
  173. package/dist/standalone/computer-fleet.d.ts +43 -0
  174. package/dist/standalone/computer-fleet.js +200 -0
  175. package/dist/standalone/computer.d.ts +44 -9
  176. package/dist/standalone/computer.js +129 -22
  177. package/dist/standalone/install-apps-cli.js +43 -6
  178. package/dist/standalone/instance.d.ts +2 -2
  179. package/dist/standalone/instance.js +8 -11
  180. package/dist/standalone/machine-link.d.ts +354 -0
  181. package/dist/standalone/machine-link.js +368 -0
  182. package/dist/standalone/media.d.ts +2 -2
  183. package/dist/standalone/media.js +19 -16
  184. package/dist/standalone/preview.d.ts +2 -2
  185. package/dist/standalone/preview.js +37 -10
  186. package/dist/standalone/registry.d.ts +151 -9
  187. package/dist/standalone/registry.js +305 -8
  188. package/dist/standalone/worker.d.ts +19 -5
  189. package/dist/standalone/worker.js +90 -54
  190. package/dist/standalone/workflow-binding.d.ts +18 -22
  191. package/dist/standalone/workflow-binding.js +18 -18
  192. package/dist/standalone/workflow-control.d.ts +4 -0
  193. package/dist/standalone/workflow-control.js +40 -0
  194. package/dist/standalone/workflow-events.d.ts +2 -2
  195. package/dist/standalone/workflow-events.js +9 -10
  196. package/dist/standalone/workflow-git-capture.js +4 -3
  197. package/dist/standalone/workflow-host.d.ts +162 -161
  198. package/dist/standalone/workflow-host.js +101 -21
  199. package/dist/standalone/workflow-node-capture.js +11 -4
  200. package/dist/standalone/workflow-schedules.d.ts +5 -2
  201. package/dist/standalone/workflow-schedules.js +9 -10
  202. package/dist/standalone/workflow-trigger-host.d.ts +65 -5
  203. package/dist/standalone/workflow-trigger-host.js +2 -2
  204. package/dist/standalone/workflow-webhooks.d.ts +22 -0
  205. package/dist/standalone/workflow-webhooks.js +39 -0
  206. package/dist/standalone/workflows.d.ts +140 -43
  207. package/dist/standalone/workflows.js +198 -39
  208. package/dist/storage-frame.d.ts +6 -6
  209. package/dist/testing/capabilities.js +14 -3
  210. package/dist/testing/installation.js +26 -2
  211. package/dist/testing/worker.js +1 -1
  212. package/dist/testing/workers-runtime.d.ts +8 -2
  213. package/dist/testing/workers-runtime.js +20 -2
  214. package/dist/webhook-abuse.d.ts +25 -0
  215. package/dist/webhook-abuse.js +54 -0
  216. package/dist/webhook-custody.d.ts +144 -0
  217. package/dist/webhook-custody.js +222 -0
  218. package/dist/webhook-ingress.d.ts +36 -0
  219. package/dist/webhook-ingress.js +146 -0
  220. package/dist/webhooks.d.ts +111 -0
  221. package/dist/webhooks.js +189 -0
  222. package/dist/workers-git.d.ts +12 -17
  223. package/dist/workers-git.js +64 -52
  224. package/dist/workers.d.ts +226 -13
  225. package/dist/workers.js +363 -51
  226. package/dist/workflow-agent-authority.d.ts +8 -0
  227. package/dist/workflow-agent-authority.js +42 -0
  228. package/dist/workflows.d.ts +66 -0
  229. package/dist/workflows.js +97 -0
  230. package/docs/api/README.md +63 -37
  231. package/docs/api/agents.md +17 -0
  232. package/docs/api/app-storage.md +1 -1
  233. package/docs/api/apps.md +1394 -543
  234. package/docs/api/browser/boot.md +132 -0
  235. package/docs/api/browser.md +1440 -0
  236. package/docs/api/build-contract.md +38 -25
  237. package/docs/api/build.md +263 -84
  238. package/docs/api/cloudflare.md +93 -7
  239. package/docs/api/git.md +3 -13
  240. package/docs/api/host.md +944 -118
  241. package/docs/api/index.md +320 -18
  242. package/docs/api/keys.md +24 -1
  243. package/docs/api/mcp.md +59 -12
  244. package/docs/api/modules.md +33 -40
  245. package/docs/api/pack.md +57 -8
  246. package/docs/api/page/mount.md +92 -4
  247. package/docs/api/workers-git.md +103 -24
  248. package/docs/api/workers.md +1594 -244
  249. package/docs/site/agent-quickstart.mdx +28 -14
  250. package/examples/standalone/worker.ts +3 -1
  251. package/examples/standalone/wrangler.jsonc +2 -0
  252. package/package.json +73 -71
  253. package/dist/installation-consent.d.ts +0 -81
  254. package/dist/installation-consent.js +0 -84
  255. package/dist/shell/app-directory.d.ts +0 -542
  256. package/dist/shell/app-directory.js +0 -196
  257. package/dist/shell/browser-actions.d.ts +0 -7
  258. package/dist/shell/browser-actions.js +0 -56
  259. package/dist/shell/command-host.d.ts +0 -112
  260. package/dist/shell/command-host.js +0 -502
  261. package/dist/shell/commands.d.ts +0 -25
  262. package/dist/shell/commands.js +0 -78
  263. package/dist/shell/index.d.ts +0 -8
  264. package/dist/shell/index.js +0 -8
  265. package/dist/shell/keys.d.ts +0 -41
  266. package/dist/shell/keys.js +0 -134
  267. package/dist/shell/shell-module.d.ts +0 -55
  268. package/dist/shell/shell-module.js +0 -86
  269. package/dist/shell/window-manager.d.ts +0 -128
  270. package/dist/shell/window-manager.js +0 -730
  271. package/dist/shell/workbench-contract.d.ts +0 -68
  272. package/dist/shell/workbench-directory.d.ts +0 -332
  273. package/dist/shell/workbench-directory.js +0 -35
  274. package/dist/shell/workbench-host-types.d.ts +0 -96
  275. package/dist/shell/workbench-host-types.js +0 -1
  276. package/dist/shell/workbench-host.d.ts +0 -34
  277. package/dist/shell/workbench-host.js +0 -352
  278. package/dist/shell/workbench-model.d.ts +0 -194
  279. package/dist/shell/workbench-model.js +0 -53
  280. package/dist/shell/workbench.d.ts +0 -4
  281. package/dist/shell/workbench.js +0 -2
  282. package/docs/api/shell/app-directory.md +0 -599
  283. package/docs/api/shell/command-host.md +0 -224
  284. package/docs/api/shell/commands.md +0 -197
  285. package/docs/api/shell/keys.md +0 -183
  286. package/docs/api/shell/shell-module.md +0 -204
  287. package/docs/api/shell/window-manager.md +0 -267
  288. package/docs/api/shell/workbench-directory.md +0 -119
  289. package/docs/api/shell/workbench.md +0 -205
  290. package/docs/api/shell.md +0 -1915
  291. /package/dist/{shell/workbench-contract.js → page/boot-host.d.ts} +0 -0
@@ -1,19 +1,23 @@
1
1
  import { appOpenInputSchema, appsCall, appsOpen, } from "@fungi.computer/agar/apps";
2
2
  import { appApiMethodNameSchema } from "@fungi.computer/puffball/app";
3
3
  import { appIdSchema } from "@fungi.computer/puffball/effect";
4
- import { createBrowserActionHandler } from "../shell/browser-actions.js";
5
- import { createAppSurfaceCommandHost } from "../shell/command-host.js";
4
+ import { createBrowserActionHandler } from "@fungi.computer/nacre";
5
+ import { createAppSurfaceCommandHost } from "@fungi.computer/nacre/command-host";
6
6
  // App page: mounts one installed App's sandboxed frame and gives it the
7
7
  // capabilities this Oyster host provides. Bundled into `shellScript`.
8
- import { RpcTarget } from "@fungi.computer/capnweb";
8
+ import { RpcTarget, RpcStub } from "@fungi.computer/capnweb";
9
+ import { EventSource } from "eventsource";
10
+ import { connectBrowser, UiBrowserError, } from "@fungi.computer/knapsack/ui/browser";
9
11
  import { createPageLifetime } from "./lifetime.js";
12
+ import { computerTargetUrl } from "./computer-target.js";
10
13
  import * as Schema from "effect/Schema";
11
- import { AppError } from "@fungi.computer/agar";
14
+ import { AppError, createCapabilityRegistry, } from "@fungi.computer/agar";
12
15
  import { appStorage } from "@fungi.computer/agar/storage";
16
+ import { approvals } from "@fungi.computer/agar/approvals";
13
17
  import { oysterStorageHandle } from "./storage.js";
14
18
  import { appBackend, appMethods } from "@fungi.computer/agar/backend";
15
19
  import { computerList, computerPorts, computerProcesses, computerReadFile, computerTerminal, computerWriteFile, } from "@fungi.computer/agar/computer";
16
- import { agentList, agentManage, agentSessionRead, agentSessionWrite, } from "@fungi.computer/agar/agents";
20
+ import { agentList, agentManage, agentSessionRead, agentSessionWrite, openAppAgent, } from "@fungi.computer/agar/agents";
17
21
  import { mediaGeneration } from "@fungi.computer/agar/media";
18
22
  import { MediaGeneration, mediaGenerationDescriptionSchema, } from "@fungi.computer/agar/media-json";
19
23
  import { registeredCapabilityHandle, } from "./capabilities.js";
@@ -23,6 +27,105 @@ import { parseJsonValue } from "@fungi.computer/whistle/wire";
23
27
  import { appDeclaredCommandSchema } from "@fungi.computer/puffball/app";
24
28
  import { TerminalCapability } from "./terminal.js";
25
29
  import { ComputerPortsHandle, ComputerProcessesHandle, } from "./computer-handles.js";
30
+ /** One page-wide selected Session, using only its reporting App's admitted view. */
31
+ export class OysterAgentBrowserHost {
32
+ #active;
33
+ #disposed = false;
34
+ /** End the selected connection with the page's own lifetime. */
35
+ constructor(signal) {
36
+ if (signal.aborted)
37
+ this.dispose();
38
+ else
39
+ signal.addEventListener("abort", () => {
40
+ this.dispose();
41
+ }, { once: true });
42
+ }
43
+ /** A departing or deselecting mount cannot close a different active mount. */
44
+ release(frame) {
45
+ if (this.#active?.frame !== frame)
46
+ return;
47
+ const previous = this.#active;
48
+ this.#active = undefined;
49
+ previous.close();
50
+ }
51
+ /** Release the page's current selection; later reports cannot reconnect it. */
52
+ dispose() {
53
+ this.#disposed = true;
54
+ if (this.#active !== undefined)
55
+ this.release(this.#active.frame);
56
+ }
57
+ /** Bind the reporting mount's current command view to its explicitly selected Session. */
58
+ async report(frame, selection, capabilities, whistle) {
59
+ if (this.#disposed)
60
+ return;
61
+ if (selection === null) {
62
+ this.release(frame);
63
+ return;
64
+ }
65
+ if (this.#active !== undefined)
66
+ this.release(this.#active.frame);
67
+ // Read-only Apps may observe Sessions, but cannot claim or settle UI work.
68
+ if (!capabilities.has(agentSessionWrite) && !capabilities.has(agentManage))
69
+ return;
70
+ let transport;
71
+ let connection;
72
+ const failure = () => {
73
+ console.warn("Oyster Agent browser connection failed");
74
+ };
75
+ const active = {
76
+ frame,
77
+ close: () => {
78
+ connection?.close();
79
+ if (transport !== undefined)
80
+ void transport.close().catch(failure);
81
+ },
82
+ };
83
+ this.#active = active;
84
+ try {
85
+ transport = await openAppAgent(capabilities, {
86
+ agentId: selection.agentId,
87
+ });
88
+ if (this.#active !== active) {
89
+ await transport.close();
90
+ return;
91
+ }
92
+ const admitted = transport;
93
+ connection = connectBrowser({
94
+ baseUrl: `${admitted.baseUrl}/browser/sessions/${encodeURIComponent(selection.sessionId)}`,
95
+ whistle,
96
+ transport: {
97
+ fetch: admitted.fetch,
98
+ openEvents: (url) => new EventSource(url, { fetch: admitted.fetch }),
99
+ },
100
+ });
101
+ void connection.closed.catch((cause) => {
102
+ if (this.#active === active)
103
+ this.release(frame);
104
+ console.warn("Oyster Agent browser connection failed", cause instanceof UiBrowserError
105
+ ? cause.message
106
+ : "Transport unavailable");
107
+ });
108
+ }
109
+ catch (cause) {
110
+ if (this.#active === active)
111
+ this.release(frame);
112
+ throw cause;
113
+ }
114
+ }
115
+ }
116
+ function agentDirectory(capabilities) {
117
+ const directory = createCapabilityRegistry();
118
+ const read = capabilities.find(({ id, version }) => id === agentSessionRead.id && version === agentSessionRead.version);
119
+ const write = capabilities.find(({ id, version }) => id === agentSessionWrite.id && version === agentSessionWrite.version);
120
+ const manage = capabilities.find(({ id, version }) => id === agentManage.id && version === agentManage.version);
121
+ if (read !== undefined)
122
+ directory.provide(agentSessionRead, agentSessionRead.schema.parse(new RpcStub(read.handle)));
123
+ if (write !== undefined)
124
+ directory.provide(agentSessionWrite, agentSessionWrite.schema.parse(new RpcStub(write.handle)));
125
+ if (manage !== undefined)
126
+ directory.provide(agentManage, agentManage.schema.parse(new RpcStub(manage.handle)));
127
+ return directory;
128
+ }
26
129
  /** Current server-admitted configuration for one installed App page. */
27
130
  export const oysterAppConfigSchema = Schema.Struct({
28
131
  workbench: Schema.Boolean,
@@ -59,15 +162,17 @@ async function answer(response) {
59
162
  }
60
163
  /** The App's typed methods, reached through this host's method route. */
61
164
  class Methods extends RpcTarget {
165
+ computerTarget;
62
166
  #url;
63
- constructor(url) {
167
+ constructor(url, computerTarget) {
64
168
  super();
169
+ this.computerTarget = computerTarget;
65
170
  this.#url = url;
66
171
  }
67
172
  async call(method, input) {
68
173
  const name = Schema.decodeUnknownSync(Schema.String.check(Schema.isPattern(/^[A-Za-z][A-Za-z0-9_.]{0,79}$/u)))(method);
69
174
  const body = Schema.decodeUnknownSync(Schema.String)(input);
70
- return answer(await fetch(`${this.#url}${name}`, {
175
+ return answer(await fetch(computerTargetUrl(`${this.#url}${name}`, this.computerTarget), {
71
176
  method: "POST",
72
177
  headers: { "Content-Type": "application/json" },
73
178
  body,
@@ -81,10 +186,12 @@ class Methods extends RpcTarget {
81
186
  class Calls extends RpcTarget {
82
187
  base;
83
188
  signal;
84
- constructor(base, signal) {
189
+ computerTarget;
190
+ constructor(base, signal, computerTarget) {
85
191
  super();
86
192
  this.base = base;
87
193
  this.signal = signal;
194
+ this.computerTarget = computerTarget;
88
195
  }
89
196
  async call(appId, method, input) {
90
197
  const target = Schema.decodeUnknownSync(appIdSchema)(appId);
@@ -96,7 +203,7 @@ class Calls extends RpcTarget {
96
203
  retryable: false,
97
204
  });
98
205
  Schema.decodeUnknownSync(Schema.fromJsonString(Schema.Json))(body);
99
- return answer(await fetch(`${this.base}${encodeURIComponent(target)}/${encodeURIComponent(name)}`, {
206
+ return answer(await fetch(computerTargetUrl(`${this.base}${encodeURIComponent(target)}/${encodeURIComponent(name)}`, this.computerTarget), {
100
207
  method: "POST",
101
208
  headers: { "Content-Type": "application/json" },
102
209
  body,
@@ -205,11 +312,14 @@ export async function mountOysterPage() {
205
312
  // The App's commands are still admitted against its Release declaration.
206
313
  const commands = createAppSurfaceCommandHost();
207
314
  const mount = commands.mount(config.installationId, config.commands);
315
+ const agentBrowser = new OysterAgentBrowserHost(lifetime.signal);
208
316
  lifetime.own(() => {
209
317
  commands.dispose();
210
318
  });
211
319
  return connectOysterApp({
212
320
  config,
321
+ agentBrowser,
322
+ agentCommands: mount.agentCommands,
213
323
  frame,
214
324
  signal: lifetime.signal,
215
325
  reservedChords: [],
@@ -234,6 +344,11 @@ export async function connectOysterApp(options) {
234
344
  if (frame.contentWindow === null)
235
345
  throw new Error("App frame is unavailable");
236
346
  const capabilities = await oysterAppCapabilities(options);
347
+ const agents = agentDirectory(capabilities);
348
+ const releaseBrowser = () => {
349
+ options.agentBrowser.release(frame);
350
+ };
351
+ options.signal.addEventListener("abort", releaseBrowser, { once: true });
237
352
  const host = await connectAppHost({
238
353
  appWindow: frame.contentWindow,
239
354
  expectedAppOrigin: "null",
@@ -261,6 +376,14 @@ export async function connectOysterApp(options) {
261
376
  },
262
377
  handlers: {
263
378
  ...options.handlers,
379
+ reportAgentSessionSelection: async (selection) => {
380
+ await options.agentBrowser.report(frame, selection, agents, options.agentCommands);
381
+ await options.handlers.reportAgentSessionSelection(selection);
382
+ },
383
+ onDisconnect: async () => {
384
+ releaseBrowser();
385
+ await options.handlers.onDisconnect();
386
+ },
264
387
  requestBrowserAction: createBrowserActionHandler({
265
388
  frame,
266
389
  hostWindow: window,
@@ -305,11 +428,11 @@ export async function oysterAppCapabilities(options) {
305
428
  let leaseExpiresAt = 0;
306
429
  return new TerminalCapability((input) => transport("open", input), {
307
430
  computerId: config.computerId,
308
- terminalUrl: selected.terminalUrl,
431
+ terminalUrl: computerTargetUrl(selected.terminalUrl, options.computerTarget),
309
432
  hostWindow: window,
310
433
  mountSignal: options.signal,
311
434
  ensureAccess: Object.assign(async (signal) => {
312
- const response = await fetch(`/apps/${encodeURIComponent(config.installationId)}/`, {
435
+ const response = await fetch(computerTargetUrl(`/apps/${encodeURIComponent(config.installationId)}/`, options.computerTarget), {
313
436
  headers: { Accept: "application/json" },
314
437
  credentials: "same-origin",
315
438
  cache: "no-store",
@@ -325,11 +448,18 @@ export async function oysterAppCapabilities(options) {
325
448
  retryable: false,
326
449
  });
327
450
  leaseExpiresAt = Date.now() + 60_000;
328
- return terminalSelection(current);
451
+ const selected = terminalSelection(current);
452
+ return {
453
+ ...selected,
454
+ terminalUrl: selected.terminalUrl === null
455
+ ? null
456
+ : computerTargetUrl(selected.terminalUrl, options.computerTarget),
457
+ };
329
458
  }, { leaseExpiresAt: () => leaseExpiresAt }),
330
459
  });
331
460
  },
332
461
  },
462
+ { contract: approvals },
333
463
  { contract: agentList },
334
464
  { contract: agentManage },
335
465
  { contract: agentSessionRead },
@@ -357,7 +487,7 @@ export async function oysterAppCapabilities(options) {
357
487
  return [
358
488
  Promise.resolve({
359
489
  ...appsCall,
360
- handle: new Calls(base, options.signal),
490
+ handle: new Calls(base, options.signal, options.computerTarget),
361
491
  }),
362
492
  ];
363
493
  }
@@ -368,14 +498,20 @@ export async function oysterAppCapabilities(options) {
368
498
  return [];
369
499
  }
370
500
  return [
371
- registeredCapabilityHandle(registration, descriptor, config.installationId).then((handle) => ({ ...registration.contract, handle })),
501
+ registeredCapabilityHandle(registration, descriptor, config.installationId, options.computerTarget).then((handle) => ({ ...registration.contract, handle })),
372
502
  ];
373
503
  }));
374
504
  if (unknownCapabilities.length > 0)
375
505
  document.body.dataset.oysterCapability = unknownCapabilities.join(", ");
376
506
  const resolved = [
377
- { ...appBackend, handle: new Backend(config.backendUrl) },
378
- { ...appMethods, handle: new Methods(config.methodsUrl) },
507
+ {
508
+ ...appBackend,
509
+ handle: new Backend(computerTargetUrl(config.backendUrl, options.computerTarget)),
510
+ },
511
+ {
512
+ ...appMethods,
513
+ handle: new Methods(config.methodsUrl, options.computerTarget),
514
+ },
379
515
  ...capabilities,
380
516
  ...(config.appsOpen && options.appOpen
381
517
  ? [{ ...appsOpen, handle: new AppOpen(options.appOpen) }]
@@ -0,0 +1,22 @@
1
+ import { HTTPException } from "hono/http-exception";
2
+ /**
3
+ * Project the generated module's fields without exposing its private module name.
4
+ * The generated module remains the sole page-source contract.
5
+ * @inline
6
+ */
7
+ export type PageAssetSources = {
8
+ [Key in keyof typeof import("#page-script")]: (typeof import("#page-script"))[Key];
9
+ };
10
+ /**
11
+ * Acquire page sources only when a host page or asset request needs them.
12
+ */
13
+ export type PageAssetLoader = () => Promise<PageAssetSources>;
14
+ /** A failed acquisition refuses this request without exposing loader details. */
15
+ export declare class PageAssetsLoadError extends HTTPException {
16
+ constructor(cause: unknown);
17
+ getResponse(): Response;
18
+ }
19
+ /**
20
+ * Missing page sources must fail the request, never produce an empty script.
21
+ */
22
+ export declare const loadPageAssets: PageAssetLoader;
@@ -0,0 +1,28 @@
1
+ import { HTTPException } from "hono/http-exception";
2
+ /** A failed acquisition refuses this request without exposing loader details. */
3
+ export class PageAssetsLoadError extends HTTPException {
4
+ constructor(cause) {
5
+ super(503, { message: "Host page assets unavailable", cause });
6
+ }
7
+ getResponse() {
8
+ // Concurrent callers share the failure, not a one-use response body.
9
+ return new Response(this.message, {
10
+ status: this.status,
11
+ headers: {
12
+ "Content-Type": "text/plain; charset=utf-8",
13
+ "Cache-Control": "no-store",
14
+ },
15
+ });
16
+ }
17
+ }
18
+ /**
19
+ * Missing page sources must fail the request, never produce an empty script.
20
+ */
21
+ export const loadPageAssets = async () => {
22
+ try {
23
+ return await import("#page-script");
24
+ }
25
+ catch (cause) {
26
+ throw new PageAssetsLoadError(cause);
27
+ }
28
+ };
@@ -7,6 +7,9 @@ export declare const publicHomeScript: string;
7
7
  /** Shared host fonts, served once as a digest-pinned stylesheet. */
8
8
  export declare const fontStyles: string;
9
9
 
10
+ /** The sans family alone, for the sign-in page. */
11
+ export declare const loginFontStyles: string;
12
+
10
13
  /** Caps styles for server-rendered host pages. */
11
14
  export declare const shellStyles: string;
12
15