@fungi.computer/oyster 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/README.md +376 -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 +210 -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/pack.d.ts +14 -3
  130. package/dist/pack.js +44 -19
  131. package/dist/page/app-access.d.ts +7 -0
  132. package/dist/page/app-access.js +75 -0
  133. package/dist/page/boot-host.js +57 -0
  134. package/dist/page/capabilities.d.ts +3 -3
  135. package/dist/page/capabilities.js +16 -12
  136. package/dist/page/computer-handles.d.ts +3 -3
  137. package/dist/page/computer-target.d.ts +3 -0
  138. package/dist/page/computer-target.js +9 -0
  139. package/dist/page/mount.d.ts +23 -3
  140. package/dist/page/mount.js +152 -16
  141. package/dist/page-assets.d.ts +22 -0
  142. package/dist/page-assets.js +28 -0
  143. package/dist/page-script.d.ts +3 -0
  144. package/dist/page-script.js +5 -4
  145. package/dist/release.d.ts +13 -6
  146. package/dist/release.js +10 -7
  147. package/dist/root-data.d.ts +16 -6
  148. package/dist/root-data.js +2 -2
  149. package/dist/source/index.d.ts +1 -1
  150. package/dist/source/team-source.d.ts +20 -8
  151. package/dist/source/team-source.js +39 -10
  152. package/dist/source/template-seed.d.ts +2 -2
  153. package/dist/standalone/agent-mail.d.ts +24 -0
  154. package/dist/standalone/agent-mail.js +62 -0
  155. package/dist/standalone/agent-store.d.ts +9 -0
  156. package/dist/standalone/agent-store.js +30 -0
  157. package/dist/standalone/agents.d.ts +68 -9
  158. package/dist/standalone/agents.js +428 -56
  159. package/dist/standalone/app-builds-binding.d.ts +20 -2
  160. package/dist/standalone/app-builds-binding.js +147 -23
  161. package/dist/standalone/app-set.d.ts +5 -2
  162. package/dist/standalone/app-set.js +174 -143
  163. package/dist/standalone/browser.d.ts +11 -0
  164. package/dist/standalone/browser.js +72 -0
  165. package/dist/standalone/builds.d.ts +13 -4
  166. package/dist/standalone/builds.js +28 -44
  167. package/dist/standalone/computer-egress.d.ts +2 -0
  168. package/dist/standalone/computer-egress.js +13 -4
  169. package/dist/standalone/computer-fleet.d.ts +43 -0
  170. package/dist/standalone/computer-fleet.js +200 -0
  171. package/dist/standalone/computer.d.ts +44 -9
  172. package/dist/standalone/computer.js +129 -22
  173. package/dist/standalone/install-apps-cli.js +43 -6
  174. package/dist/standalone/instance.d.ts +2 -2
  175. package/dist/standalone/instance.js +8 -11
  176. package/dist/standalone/machine-link.d.ts +354 -0
  177. package/dist/standalone/machine-link.js +368 -0
  178. package/dist/standalone/media.d.ts +2 -2
  179. package/dist/standalone/media.js +19 -16
  180. package/dist/standalone/preview.d.ts +2 -2
  181. package/dist/standalone/preview.js +37 -10
  182. package/dist/standalone/registry.d.ts +149 -9
  183. package/dist/standalone/registry.js +299 -8
  184. package/dist/standalone/worker.d.ts +19 -5
  185. package/dist/standalone/worker.js +90 -54
  186. package/dist/standalone/workflow-binding.d.ts +18 -22
  187. package/dist/standalone/workflow-binding.js +18 -18
  188. package/dist/standalone/workflow-control.d.ts +4 -0
  189. package/dist/standalone/workflow-control.js +40 -0
  190. package/dist/standalone/workflow-events.d.ts +2 -2
  191. package/dist/standalone/workflow-events.js +9 -10
  192. package/dist/standalone/workflow-git-capture.js +4 -3
  193. package/dist/standalone/workflow-host.d.ts +162 -161
  194. package/dist/standalone/workflow-host.js +101 -21
  195. package/dist/standalone/workflow-node-capture.js +11 -4
  196. package/dist/standalone/workflow-schedules.d.ts +5 -2
  197. package/dist/standalone/workflow-schedules.js +9 -10
  198. package/dist/standalone/workflow-trigger-host.d.ts +65 -5
  199. package/dist/standalone/workflow-trigger-host.js +2 -2
  200. package/dist/standalone/workflow-webhooks.d.ts +22 -0
  201. package/dist/standalone/workflow-webhooks.js +39 -0
  202. package/dist/standalone/workflows.d.ts +140 -43
  203. package/dist/standalone/workflows.js +198 -39
  204. package/dist/storage-frame.d.ts +6 -6
  205. package/dist/testing/capabilities.js +14 -3
  206. package/dist/testing/installation.js +26 -2
  207. package/dist/testing/worker.js +1 -1
  208. package/dist/testing/workers-runtime.d.ts +8 -2
  209. package/dist/testing/workers-runtime.js +20 -2
  210. package/dist/webhook-abuse.d.ts +25 -0
  211. package/dist/webhook-abuse.js +54 -0
  212. package/dist/webhook-custody.d.ts +144 -0
  213. package/dist/webhook-custody.js +222 -0
  214. package/dist/webhook-ingress.d.ts +36 -0
  215. package/dist/webhook-ingress.js +146 -0
  216. package/dist/webhooks.d.ts +111 -0
  217. package/dist/webhooks.js +189 -0
  218. package/dist/workers-git.d.ts +12 -17
  219. package/dist/workers-git.js +60 -52
  220. package/dist/workers.d.ts +224 -13
  221. package/dist/workers.js +351 -51
  222. package/dist/workflow-agent-authority.d.ts +8 -0
  223. package/dist/workflow-agent-authority.js +42 -0
  224. package/dist/workflows.d.ts +66 -0
  225. package/dist/workflows.js +97 -0
  226. package/docs/api/README.md +63 -37
  227. package/docs/api/agents.md +17 -0
  228. package/docs/api/app-storage.md +1 -1
  229. package/docs/api/apps.md +1394 -543
  230. package/docs/api/browser/boot.md +132 -0
  231. package/docs/api/browser.md +1440 -0
  232. package/docs/api/build-contract.md +38 -25
  233. package/docs/api/build.md +263 -84
  234. package/docs/api/cloudflare.md +93 -7
  235. package/docs/api/git.md +3 -13
  236. package/docs/api/host.md +944 -118
  237. package/docs/api/index.md +320 -18
  238. package/docs/api/keys.md +24 -1
  239. package/docs/api/mcp.md +59 -12
  240. package/docs/api/modules.md +33 -40
  241. package/docs/api/pack.md +57 -8
  242. package/docs/api/page/mount.md +92 -4
  243. package/docs/api/workers-git.md +103 -24
  244. package/docs/api/workers.md +1581 -244
  245. package/docs/site/agent-quickstart.mdx +28 -14
  246. package/examples/standalone/worker.ts +3 -1
  247. package/examples/standalone/wrangler.jsonc +2 -0
  248. package/package.json +73 -71
  249. package/dist/installation-consent.d.ts +0 -81
  250. package/dist/installation-consent.js +0 -84
  251. package/dist/shell/app-directory.d.ts +0 -542
  252. package/dist/shell/app-directory.js +0 -196
  253. package/dist/shell/browser-actions.d.ts +0 -7
  254. package/dist/shell/browser-actions.js +0 -56
  255. package/dist/shell/command-host.d.ts +0 -112
  256. package/dist/shell/command-host.js +0 -502
  257. package/dist/shell/commands.d.ts +0 -25
  258. package/dist/shell/commands.js +0 -78
  259. package/dist/shell/index.d.ts +0 -8
  260. package/dist/shell/index.js +0 -8
  261. package/dist/shell/keys.d.ts +0 -41
  262. package/dist/shell/keys.js +0 -134
  263. package/dist/shell/shell-module.d.ts +0 -55
  264. package/dist/shell/shell-module.js +0 -86
  265. package/dist/shell/window-manager.d.ts +0 -128
  266. package/dist/shell/window-manager.js +0 -730
  267. package/dist/shell/workbench-contract.d.ts +0 -68
  268. package/dist/shell/workbench-directory.d.ts +0 -332
  269. package/dist/shell/workbench-directory.js +0 -35
  270. package/dist/shell/workbench-host-types.d.ts +0 -96
  271. package/dist/shell/workbench-host-types.js +0 -1
  272. package/dist/shell/workbench-host.d.ts +0 -34
  273. package/dist/shell/workbench-host.js +0 -352
  274. package/dist/shell/workbench-model.d.ts +0 -194
  275. package/dist/shell/workbench-model.js +0 -53
  276. package/dist/shell/workbench.d.ts +0 -4
  277. package/dist/shell/workbench.js +0 -2
  278. package/docs/api/shell/app-directory.md +0 -599
  279. package/docs/api/shell/command-host.md +0 -224
  280. package/docs/api/shell/commands.md +0 -197
  281. package/docs/api/shell/keys.md +0 -183
  282. package/docs/api/shell/shell-module.md +0 -204
  283. package/docs/api/shell/window-manager.md +0 -267
  284. package/docs/api/shell/workbench-directory.md +0 -119
  285. package/docs/api/shell/workbench.md +0 -205
  286. package/docs/api/shell.md +0 -1915
  287. /package/dist/{shell/workbench-contract.js → page/boot-host.d.ts} +0 -0
@@ -0,0 +1,32 @@
1
+ import * as Data from "effect/Data";
2
+ /**
3
+ * The cloud-browser backend's closed, typed failure channel. Every backend
4
+ * (today only Cloudflare Browser Run) throws exclusively from this union;
5
+ * `agent-cloud-browser-source.ts` is the one place that maps it onto
6
+ * Mycelium's `CapabilityFailed`, so the model only ever sees a bounded,
7
+ * owner-admitted message (never a raw provider error body or stack).
8
+ */
9
+ /** The target URL failed policy before any provider call was made. */
10
+ export class CloudBrowserUrlDenied extends Data.TaggedError("CloudBrowserUrlDenied") {
11
+ }
12
+ /** The provider (Cloudflare Browser Run) answered with a failure. */
13
+ export class CloudBrowserUpstreamError extends Data.TaggedError("CloudBrowserUpstreamError") {
14
+ }
15
+ /** A call did not complete within its deadline. */
16
+ export class CloudBrowserTimeout extends Data.TaggedError("CloudBrowserTimeout") {
17
+ }
18
+ /** The named lease is not held by this (teamId, agentId, sessionId). */
19
+ export class CloudBrowserLeaseNotFound extends Data.TaggedError("CloudBrowserLeaseNotFound") {
20
+ }
21
+ /** A member was asked to take over; the Agent cannot drive it until "Done". */
22
+ export class CloudBrowserLeasePaused extends Data.TaggedError("CloudBrowserLeasePaused") {
23
+ }
24
+ /** The Team has no more concurrent leases available right now. */
25
+ export class CloudBrowserCapacityExceeded extends Data.TaggedError("CloudBrowserCapacityExceeded") {
26
+ }
27
+ /** The Team has no credit to start or continue a lease. */
28
+ export class CloudBrowserCreditDenied extends Data.TaggedError("CloudBrowserCreditDenied") {
29
+ }
30
+ /** No backend is configured (credentials absent, or the feature is paused). */
31
+ export class CloudBrowserUnavailable extends Data.TaggedError("CloudBrowserUnavailable") {
32
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `@fungi.computer/oyster/browser`: the one agent browser for the Hub and a
3
+ * standalone Oyster. A host builds the port from a provider (`browserRunSessions`
4
+ * or `bindingSessions`, plus Browser Run Quick Reads when it has them), its
5
+ * required metering owner and an event sink; `createBrowser` owns lease
6
+ * ownership, egress policy and billing order; `browserCapabilitySource` is
7
+ * the agent's `cloudBrowser` tool. Raw CDP stays internal to this directory.
8
+ */
9
+ export { createBrowser, type Browser, type BrowserEvent, type BrowserHost, type BrowserLimits, type BrowserMemberAction, type BrowserMeter, } from "./browser.js";
10
+ export { browserCapabilitySource, CLOUD_BROWSER_DESCRIPTIONS, type AgentBrowserDoor, type SaveBrowserFile, } from "./capability-source.js";
11
+ export { CloudBrowserCapacityExceeded, CloudBrowserCreditDenied, CloudBrowserLeaseNotFound, CloudBrowserLeasePaused, CloudBrowserTimeout, CloudBrowserUnavailable, CloudBrowserUpstreamError, CloudBrowserUrlDenied, type CloudBrowserFailure, } from "./errors.js";
12
+ export type { LeaseOwner } from "./lease-registry.js";
13
+ export { cloudBrowserBounds, extractInputSchema, extractResultSchema, linksResultSchema, markdownInputSchema, markdownResultSchema, navigateResultSchema, openResultSchema, scrapeInputSchema, scrapeResultSchema, snapshotResultSchema, type BinaryResult, type CloudBrowserAck, type CloudBrowserClosed, type CloudBrowserOperation, type CloudBrowserOperationResult, type ExtractInput, type ExtractResult, type LinksResult, type MarkdownInput, type MarkdownResult, type NavigateResult, type OpenResult, type ScrapeInput, type ScrapeResult, type SnapshotResult, } from "./operations.js";
14
+ export type { CdpSocket, HttpFetch } from "./cdp-client.js";
15
+ export { browserRunQuickReads, type BrowserRunQuickReadsConfig, type QuickRead, type QuickReads, } from "./quick-reads.js";
16
+ export { bindingSessions, browserRunSessions, type BrowserBinding, type BrowserSessions, type CdpConnect, } from "./sessions.js";
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `@fungi.computer/oyster/browser`: the one agent browser for the Hub and a
3
+ * standalone Oyster. A host builds the port from a provider (`browserRunSessions`
4
+ * or `bindingSessions`, plus Browser Run Quick Reads when it has them), its
5
+ * required metering owner and an event sink; `createBrowser` owns lease
6
+ * ownership, egress policy and billing order; `browserCapabilitySource` is
7
+ * the agent's `cloudBrowser` tool. Raw CDP stays internal to this directory.
8
+ */
9
+ export { createBrowser, } from "./browser.js";
10
+ export { browserCapabilitySource, CLOUD_BROWSER_DESCRIPTIONS, } from "./capability-source.js";
11
+ export { CloudBrowserCapacityExceeded, CloudBrowserCreditDenied, CloudBrowserLeaseNotFound, CloudBrowserLeasePaused, CloudBrowserTimeout, CloudBrowserUnavailable, CloudBrowserUpstreamError, CloudBrowserUrlDenied, } from "./errors.js";
12
+ export { cloudBrowserBounds, extractInputSchema, extractResultSchema, linksResultSchema, markdownInputSchema, markdownResultSchema, navigateResultSchema, openResultSchema, scrapeInputSchema, scrapeResultSchema, snapshotResultSchema, } from "./operations.js";
13
+ export { browserRunQuickReads, } from "./quick-reads.js";
14
+ export { bindingSessions, browserRunSessions, } from "./sessions.js";
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The one place that binds a cloud-browser lease to the (teamId, agentId,
3
+ * sessionId) that opened it, enforces the per-Team concurrent cap, and times
4
+ * leases out. The provider (`sessions.ts`) only knows CDP connections; it
5
+ * has no idea which Team or Session owns one.
6
+ * This registry is in-process (one Hub instance): see the report for why a
7
+ * durable, cross-instance counter (the `TeamDO`-backed shape Computer
8
+ * admission uses) is the better home for this long-term.
9
+ */
10
+ export type LeaseOwner = Readonly<{
11
+ teamId: string;
12
+ agentId: string;
13
+ sessionId: string;
14
+ }>;
15
+ export type LeaseRecord = LeaseOwner & {
16
+ leaseId: string;
17
+ openedAt: number;
18
+ lastActiveAt: number;
19
+ /** Set by `cloudBrowser.handoff`; cleared when a member presses "Done". */
20
+ paused: boolean;
21
+ };
22
+ export type LeaseRegistryConfig = Readonly<{
23
+ /** Concurrent open leases one Team may hold. LIMIT DECISION PENDING (Levi). */
24
+ maxConcurrentPerTeam: number;
25
+ /** A lease older than this is reaped even if active. */
26
+ maxLifetimeMs: number;
27
+ /** A lease idle this long is reaped. */
28
+ idleTimeoutMs: number;
29
+ now?: () => number;
30
+ }>;
31
+ export type LeaseRegistry = Readonly<{
32
+ /**
33
+ * Reserve one of the Team's slots for an open still in flight. Throws
34
+ * `CloudBrowserCapacityExceeded` when registered leases plus reservations
35
+ * already fill the cap, so concurrent opens cannot overshoot it.
36
+ */
37
+ reserve: (leaseId: string, owner: LeaseOwner) => void;
38
+ /** Give back a reservation whose open failed. */
39
+ abandon: (leaseId: string) => void;
40
+ /** Turn a reservation into an open lease. */
41
+ /** `openedAt` is when the provider session was requested: lifetime and billing start there. */
42
+ register: (leaseId: string, owner: LeaseOwner, openedAt: number) => void;
43
+ /** Throws `CloudBrowserLeaseNotFound` for a wrong owner, unknown, or expired lease. */
44
+ touch: (leaseId: string, owner: LeaseOwner) => void;
45
+ release: (leaseId: string) => void;
46
+ /** Leases past their idle timeout or max lifetime, for a reap sweep. */
47
+ expired: () => readonly string[];
48
+ /** Read-only lookup, e.g. to bill a closing lease's real elapsed time. */
49
+ get: (leaseId: string) => Readonly<LeaseRecord> | undefined;
50
+ count: (teamId: string) => number;
51
+ /** `cloudBrowser.handoff`: the Agent cannot drive the lease until `resume`. */
52
+ pause: (leaseId: string) => void;
53
+ /** The member's "Done": the Agent may drive the lease again. */
54
+ resume: (leaseId: string, teamId: string) => void;
55
+ /**
56
+ * The live view's own admission: Team membership, not Agent identity.
57
+ * Throws `CloudBrowserLeaseNotFound` for a lease outside this Team.
58
+ */
59
+ touchAsMember: (leaseId: string, teamId: string) => void;
60
+ }>;
61
+ export declare function createLeaseRegistry(config: LeaseRegistryConfig): LeaseRegistry;
@@ -0,0 +1,101 @@
1
+ import { CloudBrowserCapacityExceeded, CloudBrowserLeaseNotFound, CloudBrowserLeasePaused, } from "./errors.js";
2
+ export function createLeaseRegistry(config) {
3
+ const now = config.now ?? Date.now;
4
+ const leases = new Map();
5
+ const reserved = new Map();
6
+ function countFor(teamId) {
7
+ let total = 0;
8
+ for (const lease of leases.values())
9
+ if (lease.teamId === teamId)
10
+ total += 1;
11
+ for (const reservedTeam of reserved.values())
12
+ if (reservedTeam === teamId)
13
+ total += 1;
14
+ return total;
15
+ }
16
+ function isExpired(lease, at) {
17
+ return (at - lease.openedAt > config.maxLifetimeMs ||
18
+ at - lease.lastActiveAt > config.idleTimeoutMs);
19
+ }
20
+ function ownedBy(lease, owner) {
21
+ return (lease.teamId === owner.teamId &&
22
+ lease.agentId === owner.agentId &&
23
+ lease.sessionId === owner.sessionId);
24
+ }
25
+ return {
26
+ reserve: (leaseId, owner) => {
27
+ if (countFor(owner.teamId) >= config.maxConcurrentPerTeam)
28
+ throw new CloudBrowserCapacityExceeded({
29
+ teamId: owner.teamId,
30
+ limit: config.maxConcurrentPerTeam,
31
+ });
32
+ reserved.set(leaseId, owner.teamId);
33
+ },
34
+ abandon: (leaseId) => {
35
+ reserved.delete(leaseId);
36
+ },
37
+ register: (leaseId, owner, openedAt) => {
38
+ reserved.delete(leaseId);
39
+ leases.set(leaseId, {
40
+ ...owner,
41
+ leaseId,
42
+ openedAt,
43
+ lastActiveAt: now(),
44
+ paused: false,
45
+ });
46
+ },
47
+ touch: (leaseId, owner) => {
48
+ const lease = leases.get(leaseId);
49
+ if (lease === undefined)
50
+ throw new CloudBrowserLeaseNotFound({ leaseId });
51
+ const at = now();
52
+ if (isExpired(lease, at)) {
53
+ leases.delete(leaseId);
54
+ throw new CloudBrowserLeaseNotFound({ leaseId });
55
+ }
56
+ if (!ownedBy(lease, owner))
57
+ throw new CloudBrowserLeaseNotFound({ leaseId });
58
+ if (lease.paused)
59
+ throw new CloudBrowserLeasePaused({ leaseId });
60
+ lease.lastActiveAt = at;
61
+ },
62
+ touchAsMember: (leaseId, teamId) => {
63
+ const lease = leases.get(leaseId);
64
+ if (lease === undefined)
65
+ throw new CloudBrowserLeaseNotFound({ leaseId });
66
+ const at = now();
67
+ if (isExpired(lease, at)) {
68
+ leases.delete(leaseId);
69
+ throw new CloudBrowserLeaseNotFound({ leaseId });
70
+ }
71
+ if (lease.teamId !== teamId)
72
+ throw new CloudBrowserLeaseNotFound({ leaseId });
73
+ lease.lastActiveAt = at;
74
+ },
75
+ release: (leaseId) => {
76
+ leases.delete(leaseId);
77
+ },
78
+ expired: () => {
79
+ const at = now();
80
+ const ids = [];
81
+ for (const lease of leases.values())
82
+ if (isExpired(lease, at))
83
+ ids.push(lease.leaseId);
84
+ return ids;
85
+ },
86
+ get: (leaseId) => leases.get(leaseId),
87
+ count: countFor,
88
+ pause: (leaseId) => {
89
+ const lease = leases.get(leaseId);
90
+ if (lease !== undefined)
91
+ lease.paused = true;
92
+ },
93
+ resume: (leaseId, teamId) => {
94
+ const lease = leases.get(leaseId);
95
+ if (lease?.teamId !== teamId)
96
+ return;
97
+ lease.paused = false;
98
+ lease.lastActiveAt = now();
99
+ },
100
+ };
101
+ }
@@ -0,0 +1,225 @@
1
+ import { z } from "zod";
2
+ /** The module's fixed output bounds (characters, links, selectors, bytes). */
3
+ export declare const cloudBrowserBounds: Readonly<{
4
+ maxChars: 50000;
5
+ defaultMarkdownChars: 20000;
6
+ maxLinks: 500;
7
+ maxSelectors: 10;
8
+ maxScrapeBytes: number;
9
+ maxSnapshotBytes: number;
10
+ maxScreenshotBytes: number;
11
+ maxPdfBytes: number;
12
+ }>;
13
+ /** Input of a URL-only Quick Read (`links`). */
14
+ export declare const urlInputSchema: z.ZodObject<{
15
+ url: z.ZodURL;
16
+ }, z.core.$strict>;
17
+ /** Input of `markdown`: a URL and a character bound. */
18
+ export declare const markdownInputSchema: z.ZodObject<{
19
+ url: z.ZodURL;
20
+ maxChars: z.ZodDefault<z.ZodNumber>;
21
+ }, z.core.$strict>;
22
+ /** Output of `markdown`: the page text, possibly truncated. */
23
+ export declare const markdownResultSchema: z.ZodObject<{
24
+ url: z.ZodString;
25
+ text: z.ZodString;
26
+ truncated: z.ZodBoolean;
27
+ }, z.core.$strict>;
28
+ /** Output of `links`: bare URL strings, bounded. */
29
+ export declare const linksResultSchema: z.ZodObject<{
30
+ url: z.ZodString;
31
+ links: z.ZodArray<z.ZodString>;
32
+ truncated: z.ZodBoolean;
33
+ }, z.core.$strict>;
34
+ /** Input of `scrape`: a URL and up to ten CSS selectors. */
35
+ export declare const scrapeInputSchema: z.ZodObject<{
36
+ url: z.ZodURL;
37
+ selectors: z.ZodArray<z.ZodString>;
38
+ }, z.core.$strict>;
39
+ /** Output of `scrape`: matched elements per selector, bounded. */
40
+ export declare const scrapeResultSchema: z.ZodObject<{
41
+ url: z.ZodString;
42
+ result: z.ZodArray<z.ZodObject<{
43
+ selector: z.ZodString;
44
+ elements: z.ZodArray<z.ZodObject<{
45
+ text: z.ZodString;
46
+ html: z.ZodString;
47
+ }, z.core.$strict>>;
48
+ }, z.core.$strict>>;
49
+ truncated: z.ZodBoolean;
50
+ }, z.core.$strict>;
51
+ /** Input of `extract`: a URL and a prompt. */
52
+ export declare const extractInputSchema: z.ZodObject<{
53
+ url: z.ZodURL;
54
+ prompt: z.ZodString;
55
+ }, z.core.$strict>;
56
+ /** Output of `extract`: JSON-safe structured data. */
57
+ export declare const extractResultSchema: z.ZodObject<{
58
+ url: z.ZodString;
59
+ result: z.ZodJSONSchema;
60
+ }, z.core.$strict>;
61
+ /** Input of `open`: an optional first URL. */
62
+ export declare const openInputSchema: z.ZodObject<{
63
+ url: z.ZodDefault<z.ZodNullable<z.ZodURL>>;
64
+ }, z.core.$strict>;
65
+ /** Output of `open`: the new lease and its first URL. */
66
+ export declare const openResultSchema: z.ZodObject<{
67
+ leaseId: z.ZodString;
68
+ url: z.ZodNullable<z.ZodString>;
69
+ }, z.core.$strict>;
70
+ /** Input of `navigate`: a lease and a URL. */
71
+ export declare const navigateInputSchema: z.ZodObject<{
72
+ leaseId: z.ZodString;
73
+ url: z.ZodURL;
74
+ }, z.core.$strict>;
75
+ /** Output of `navigate`: the page's location after load. */
76
+ export declare const navigateResultSchema: z.ZodObject<{
77
+ leaseId: z.ZodString;
78
+ url: z.ZodString;
79
+ status: z.ZodNullable<z.ZodNumber>;
80
+ title: z.ZodNullable<z.ZodString>;
81
+ }, z.core.$strict>;
82
+ /** Input of `snapshot`: a lease. */
83
+ export declare const snapshotInputSchema: z.ZodObject<{
84
+ leaseId: z.ZodString;
85
+ }, z.core.$strict>;
86
+ /** Output of `snapshot`: a bounded accessibility-tree summary. */
87
+ export declare const snapshotResultSchema: z.ZodObject<{
88
+ leaseId: z.ZodString;
89
+ tree: z.ZodString;
90
+ truncated: z.ZodBoolean;
91
+ }, z.core.$strict>;
92
+ /** Input of `click`: a lease and a viewport coordinate. */
93
+ export declare const clickInputSchema: z.ZodObject<{
94
+ leaseId: z.ZodString;
95
+ x: z.ZodNumber;
96
+ y: z.ZodNumber;
97
+ }, z.core.$strict>;
98
+ /** Input of `type`: a lease and text to insert. */
99
+ export declare const typeInputSchema: z.ZodObject<{
100
+ leaseId: z.ZodString;
101
+ text: z.ZodString;
102
+ }, z.core.$strict>;
103
+ /** Input of `press`: a lease and one key name. */
104
+ export declare const pressInputSchema: z.ZodObject<{
105
+ leaseId: z.ZodString;
106
+ key: z.ZodString;
107
+ }, z.core.$strict>;
108
+ /** Input of `scroll`: a lease and a pixel delta. */
109
+ export declare const scrollInputSchema: z.ZodObject<{
110
+ leaseId: z.ZodString;
111
+ deltaX: z.ZodDefault<z.ZodNumber>;
112
+ deltaY: z.ZodDefault<z.ZodNumber>;
113
+ }, z.core.$strict>;
114
+ /** Output of a driven input step: the lease it acted on. */
115
+ export declare const leaseAckSchema: z.ZodObject<{
116
+ leaseId: z.ZodString;
117
+ }, z.core.$strict>;
118
+ /** Input of `close`: a lease. */
119
+ export declare const closeInputSchema: z.ZodObject<{
120
+ leaseId: z.ZodString;
121
+ }, z.core.$strict>;
122
+ /** Output of `close`: the closed lease. */
123
+ export declare const closeResultSchema: z.ZodObject<{
124
+ leaseId: z.ZodString;
125
+ closed: z.ZodLiteral<true>;
126
+ provider: z.ZodEnum<{
127
+ closed: "closed";
128
+ closing: "closing";
129
+ }>;
130
+ }, z.core.$strict>;
131
+ /** Parsed `markdown` input. */
132
+ export type MarkdownInput = z.output<typeof markdownInputSchema>;
133
+ /** Parsed `markdown` output. */
134
+ export type MarkdownResult = z.output<typeof markdownResultSchema>;
135
+ /** Parsed `links` output. */
136
+ export type LinksResult = z.output<typeof linksResultSchema>;
137
+ /** Parsed `scrape` input. */
138
+ export type ScrapeInput = z.output<typeof scrapeInputSchema>;
139
+ /** Parsed `scrape` output. */
140
+ export type ScrapeResult = z.output<typeof scrapeResultSchema>;
141
+ /** Parsed `extract` input. */
142
+ export type ExtractInput = z.output<typeof extractInputSchema>;
143
+ /** Parsed `extract` output. */
144
+ export type ExtractResult = z.output<typeof extractResultSchema>;
145
+ /** Parsed `open` output. */
146
+ export type OpenResult = z.output<typeof openResultSchema>;
147
+ /** Parsed `navigate` output. */
148
+ export type NavigateResult = z.output<typeof navigateResultSchema>;
149
+ /** Parsed `snapshot` output. */
150
+ export type SnapshotResult = z.output<typeof snapshotResultSchema>;
151
+ /** Raw bytes never cross the Mycelium boundary; only a byte count does. */
152
+ export type BinaryResult = Readonly<{
153
+ leaseId: string;
154
+ bytes: Uint8Array;
155
+ contentType: string;
156
+ }>;
157
+ /**
158
+ * Every call the agent tool can make. `markdown`/`links`/`scrape`/`extract`
159
+ * are stateless Quick Reads (absent on a host without them); `open`..`close`
160
+ * share one driven session keyed by `leaseId`. "screenshot"/"pdf" return raw
161
+ * bytes here; `capability-source.ts` saves them through the host's door and
162
+ * hands the model only a byte count.
163
+ */
164
+ export type CloudBrowserOperation = Readonly<{
165
+ kind: "markdown";
166
+ input: MarkdownInput;
167
+ }> | Readonly<{
168
+ kind: "links";
169
+ url: string;
170
+ }> | Readonly<{
171
+ kind: "scrape";
172
+ input: ScrapeInput;
173
+ }> | Readonly<{
174
+ kind: "extract";
175
+ input: ExtractInput;
176
+ }> | Readonly<{
177
+ kind: "open";
178
+ url: string | null;
179
+ }> | Readonly<{
180
+ kind: "navigate";
181
+ leaseId: string;
182
+ url: string;
183
+ }> | Readonly<{
184
+ kind: "snapshot";
185
+ leaseId: string;
186
+ }> | Readonly<{
187
+ kind: "click";
188
+ leaseId: string;
189
+ x: number;
190
+ y: number;
191
+ }> | Readonly<{
192
+ kind: "type";
193
+ leaseId: string;
194
+ text: string;
195
+ }> | Readonly<{
196
+ kind: "press";
197
+ leaseId: string;
198
+ key: string;
199
+ }> | Readonly<{
200
+ kind: "scroll";
201
+ leaseId: string;
202
+ deltaX: number;
203
+ deltaY: number;
204
+ }> | Readonly<{
205
+ kind: "screenshot";
206
+ leaseId: string;
207
+ }> | Readonly<{
208
+ kind: "pdf";
209
+ leaseId: string;
210
+ }> | Readonly<{
211
+ kind: "close";
212
+ leaseId: string;
213
+ }>;
214
+ /** Acknowledgement of one driven input step. */
215
+ export type CloudBrowserAck = Readonly<{
216
+ leaseId: string;
217
+ }>;
218
+ /** Acknowledgement that a lease closed. */
219
+ export type CloudBrowserClosed = Readonly<{
220
+ leaseId: string;
221
+ closed: true;
222
+ provider: "closed" | "closing";
223
+ }>;
224
+ /** What one `CloudBrowserOperation` returns, before the agent tool shapes it. */
225
+ export type CloudBrowserOperationResult = MarkdownResult | LinksResult | ScrapeResult | ExtractResult | OpenResult | NavigateResult | SnapshotResult | CloudBrowserAck | BinaryResult | CloudBrowserClosed;
@@ -0,0 +1,137 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * The agent browser's closed operation vocabulary: input/output schemas,
4
+ * bounds and the one discriminated union `browser.ts` pattern-matches.
5
+ * There is deliberately no `send`/`execute`/`evaluate` member: the Agent
6
+ * can never reach raw CDP or run script in the page, only this typed set.
7
+ * Every failure comes from `./errors.js`'s `CloudBrowserFailure` union.
8
+ */
9
+ const maxChars = 50_000;
10
+ const defaultMarkdownChars = 20_000;
11
+ const maxLinks = 500;
12
+ const maxSelectors = 10;
13
+ const maxScrapeBytes = 64 * 1024;
14
+ const maxSnapshotBytes = 64 * 1024;
15
+ const maxScreenshotBytes = 8 * 1024 * 1024;
16
+ const maxPdfBytes = 8 * 1024 * 1024;
17
+ /** The module's fixed output bounds (characters, links, selectors, bytes). */
18
+ export const cloudBrowserBounds = Object.freeze({
19
+ maxChars,
20
+ defaultMarkdownChars,
21
+ maxLinks,
22
+ maxSelectors,
23
+ maxScrapeBytes,
24
+ maxSnapshotBytes,
25
+ maxScreenshotBytes,
26
+ maxPdfBytes,
27
+ });
28
+ /** Input of a URL-only Quick Read (`links`). */
29
+ export const urlInputSchema = z.strictObject({ url: z.url().max(2_048) });
30
+ /** Input of `markdown`: a URL and a character bound. */
31
+ export const markdownInputSchema = z.strictObject({
32
+ url: z.url().max(2_048),
33
+ maxChars: z.number().int().min(1).max(maxChars).default(defaultMarkdownChars),
34
+ });
35
+ /** Output of `markdown`: the page text, possibly truncated. */
36
+ export const markdownResultSchema = z.strictObject({
37
+ url: z.string(),
38
+ text: z.string(),
39
+ truncated: z.boolean(),
40
+ });
41
+ /** Output of `links`: bare URL strings, bounded. */
42
+ export const linksResultSchema = z.strictObject({
43
+ url: z.string(),
44
+ /** Cloudflare's `/links` Quick Action returns bare URL strings, not anchor text. */
45
+ links: z.array(z.string()).max(maxLinks),
46
+ truncated: z.boolean(),
47
+ });
48
+ /** Input of `scrape`: a URL and up to ten CSS selectors. */
49
+ export const scrapeInputSchema = z.strictObject({
50
+ url: z.url().max(2_048),
51
+ selectors: z.array(z.string().min(1).max(256)).min(1).max(maxSelectors),
52
+ });
53
+ /** Output of `scrape`: matched elements per selector, bounded. */
54
+ export const scrapeResultSchema = z.strictObject({
55
+ url: z.string(),
56
+ result: z.array(z.strictObject({
57
+ selector: z.string(),
58
+ elements: z.array(z.strictObject({ text: z.string(), html: z.string() })),
59
+ })),
60
+ truncated: z.boolean(),
61
+ });
62
+ /** Input of `extract`: a URL and a prompt. */
63
+ export const extractInputSchema = z.strictObject({
64
+ url: z.url().max(2_048),
65
+ prompt: z.string().min(1).max(2_000),
66
+ });
67
+ /** Output of `extract`: JSON-safe structured data. */
68
+ export const extractResultSchema = z.strictObject({
69
+ url: z.string(),
70
+ // `z.json()`, not `z.unknown()`: Mycelium-facing schemas must stay JSON-safe.
71
+ result: z.json(),
72
+ });
73
+ const leaseIdSchema = z.string().min(1).max(128);
74
+ /** Input of `open`: an optional first URL. */
75
+ export const openInputSchema = z.strictObject({
76
+ // `.nullable().default(null)`, not `.optional()`: every Mycelium-facing
77
+ // schema's parsed output must stay JSON-safe (no `undefined`).
78
+ url: z.url().max(2_048).nullable().default(null),
79
+ });
80
+ /** Output of `open`: the new lease and its first URL. */
81
+ export const openResultSchema = z.strictObject({
82
+ leaseId: leaseIdSchema,
83
+ url: z.string().nullable(),
84
+ });
85
+ /** Input of `navigate`: a lease and a URL. */
86
+ export const navigateInputSchema = z.strictObject({
87
+ leaseId: leaseIdSchema,
88
+ url: z.url().max(2_048),
89
+ });
90
+ /** Output of `navigate`: the page's location after load. */
91
+ export const navigateResultSchema = z.strictObject({
92
+ leaseId: leaseIdSchema,
93
+ url: z.string(),
94
+ status: z.number().int().nullable(),
95
+ title: z.string().nullable(),
96
+ });
97
+ /** Input of `snapshot`: a lease. */
98
+ export const snapshotInputSchema = z.strictObject({ leaseId: leaseIdSchema });
99
+ /** Output of `snapshot`: a bounded accessibility-tree summary. */
100
+ export const snapshotResultSchema = z.strictObject({
101
+ leaseId: leaseIdSchema,
102
+ tree: z.string(),
103
+ truncated: z.boolean(),
104
+ });
105
+ /** Input of `click`: a lease and a viewport coordinate. */
106
+ export const clickInputSchema = z.strictObject({
107
+ leaseId: leaseIdSchema,
108
+ x: z.number().int().min(0).max(20_000),
109
+ y: z.number().int().min(0).max(20_000),
110
+ });
111
+ /** Input of `type`: a lease and text to insert. */
112
+ export const typeInputSchema = z.strictObject({
113
+ leaseId: leaseIdSchema,
114
+ text: z.string().max(10_000),
115
+ });
116
+ /** Input of `press`: a lease and one key name. */
117
+ export const pressInputSchema = z.strictObject({
118
+ leaseId: leaseIdSchema,
119
+ key: z.string().min(1).max(64),
120
+ });
121
+ /** Input of `scroll`: a lease and a pixel delta. */
122
+ export const scrollInputSchema = z.strictObject({
123
+ leaseId: leaseIdSchema,
124
+ deltaX: z.number().int().min(-100_000).max(100_000).default(0),
125
+ deltaY: z.number().int().min(-100_000).max(100_000).default(0),
126
+ });
127
+ /** Output of a driven input step: the lease it acted on. */
128
+ export const leaseAckSchema = z.strictObject({ leaseId: leaseIdSchema });
129
+ /** Input of `close`: a lease. */
130
+ export const closeInputSchema = z.strictObject({ leaseId: leaseIdSchema });
131
+ /** Output of `close`: the closed lease. */
132
+ export const closeResultSchema = z.strictObject({
133
+ leaseId: leaseIdSchema,
134
+ closed: z.literal(true),
135
+ /** "closing" when the provider acknowledged but has not yet confirmed the end. */
136
+ provider: z.enum(["closed", "closing"]),
137
+ });
@@ -0,0 +1,25 @@
1
+ import { type BinaryResult, type SnapshotResult } from "./operations.js";
2
+ import type { CdpClient } from "./cdp-client.js";
3
+ export type Page = Readonly<{
4
+ client: CdpClient;
5
+ cdpSessionId: string;
6
+ /** The attached page target, so observers can tell it from pages it opens. */
7
+ targetId: string;
8
+ }>;
9
+ /** Attach to the session's first page target (or a new blank one). */
10
+ export declare function attachPage(client: CdpClient): Promise<Page>;
11
+ export type PageLocation = Readonly<{
12
+ url: string;
13
+ title: string | null;
14
+ }>;
15
+ /** The page's current history entry. */
16
+ export declare function pageLocation({ client, cdpSessionId }: Page, fallbackUrl: string): Promise<PageLocation>;
17
+ /** Navigate to an already policy-checked URL and wait for its load event. */
18
+ export declare function navigatePage(page: Page, url: URL, timeoutMs: number): Promise<PageLocation>;
19
+ export declare function snapshotPage({ client, cdpSessionId }: Page, leaseId: string, signal: AbortSignal): Promise<SnapshotResult>;
20
+ export declare function clickPage({ client, cdpSessionId }: Page, x: number, y: number, signal: AbortSignal): Promise<void>;
21
+ export declare function typePage({ client, cdpSessionId }: Page, text: string, signal: AbortSignal): Promise<void>;
22
+ export declare function pressPage({ client, cdpSessionId }: Page, key: string, signal: AbortSignal): Promise<void>;
23
+ export declare function scrollPage({ client, cdpSessionId }: Page, deltaX: number, deltaY: number, signal: AbortSignal): Promise<void>;
24
+ export declare function screenshotPage(page: Page, leaseId: string, signal: AbortSignal): Promise<BinaryResult>;
25
+ export declare function pdfPage(page: Page, leaseId: string, signal: AbortSignal): Promise<BinaryResult>;