dotdo 0.0.1 → 0.0.2
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 +1 -1
- package/README.md +446 -315
- package/dist/ai/index.js +19 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/template-literals.js +852 -0
- package/dist/ai/template-literals.js.map +1 -0
- package/dist/api/analytics/router.js +601 -0
- package/dist/api/analytics/router.js.map +1 -0
- package/dist/api/index.js +158 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/middleware/auth-federation.js +573 -0
- package/dist/api/middleware/auth-federation.js.map +1 -0
- package/dist/api/middleware/auth.js +544 -0
- package/dist/api/middleware/auth.js.map +1 -0
- package/dist/api/middleware/error-handling.js +176 -0
- package/dist/api/middleware/error-handling.js.map +1 -0
- package/dist/api/middleware/request-id.js +21 -0
- package/dist/api/middleware/request-id.js.map +1 -0
- package/dist/api/pages.js +1180 -0
- package/dist/api/pages.js.map +1 -0
- package/dist/api/routes/api.js +612 -0
- package/dist/api/routes/api.js.map +1 -0
- package/dist/api/routes/browsers.js +471 -0
- package/dist/api/routes/browsers.js.map +1 -0
- package/dist/api/routes/do.js +188 -0
- package/dist/api/routes/do.js.map +1 -0
- package/dist/api/routes/mcp.js +459 -0
- package/dist/api/routes/mcp.js.map +1 -0
- package/dist/api/routes/obs.js +445 -0
- package/dist/api/routes/obs.js.map +1 -0
- package/dist/api/routes/openapi.js +794 -0
- package/dist/api/routes/openapi.js.map +1 -0
- package/dist/api/routes/rpc.js +1103 -0
- package/dist/api/routes/rpc.js.map +1 -0
- package/dist/api/routes/sandboxes.js +389 -0
- package/dist/api/routes/sandboxes.js.map +1 -0
- package/dist/api/test-do.js +38 -0
- package/dist/api/test-do.js.map +1 -0
- package/dist/api/types.js +11 -0
- package/dist/api/types.js.map +1 -0
- package/dist/cli/bin.js +2 -0
- package/dist/cli/main.js +52342 -0
- package/dist/db/actions.js +212 -0
- package/dist/db/actions.js.map +1 -0
- package/dist/db/auth.js +506 -0
- package/dist/db/auth.js.map +1 -0
- package/dist/db/branches.js +65 -0
- package/dist/db/branches.js.map +1 -0
- package/dist/db/clickhouse.js +1074 -0
- package/dist/db/clickhouse.js.map +1 -0
- package/dist/db/dlq.js +39 -0
- package/dist/db/dlq.js.map +1 -0
- package/dist/db/events.js +28 -0
- package/dist/db/events.js.map +1 -0
- package/dist/db/exec.js +64 -0
- package/dist/db/exec.js.map +1 -0
- package/dist/db/files.js +85 -0
- package/dist/db/files.js.map +1 -0
- package/dist/db/flags.js +24 -0
- package/dist/db/flags.js.map +1 -0
- package/dist/db/git.js +116 -0
- package/dist/db/git.js.map +1 -0
- package/dist/db/iceberg/inverted-index.js +862 -0
- package/dist/db/iceberg/inverted-index.js.map +1 -0
- package/dist/db/iceberg/puffin.js +878 -0
- package/dist/db/iceberg/puffin.js.map +1 -0
- package/dist/db/iceberg/search-manifest.js +422 -0
- package/dist/db/iceberg/search-manifest.js.map +1 -0
- package/dist/db/iceberg/types.js +8 -0
- package/dist/db/iceberg/types.js.map +1 -0
- package/dist/db/index.js +121 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/integrations.js +368 -0
- package/dist/db/integrations.js.map +1 -0
- package/dist/db/json-indexes.js +332 -0
- package/dist/db/json-indexes.js.map +1 -0
- package/dist/db/linked-accounts.js +287 -0
- package/dist/db/linked-accounts.js.map +1 -0
- package/dist/db/nouns.js +183 -0
- package/dist/db/nouns.js.map +1 -0
- package/dist/db/objects.js +170 -0
- package/dist/db/objects.js.map +1 -0
- package/dist/db/primitives/dag-scheduler/index.js +869 -0
- package/dist/db/primitives/dag-scheduler/index.js.map +1 -0
- package/dist/db/primitives/exactly-once-context.js +237 -0
- package/dist/db/primitives/exactly-once-context.js.map +1 -0
- package/dist/db/primitives/index.js +62 -0
- package/dist/db/primitives/index.js.map +1 -0
- package/dist/db/primitives/keyed-router.js +145 -0
- package/dist/db/primitives/keyed-router.js.map +1 -0
- package/dist/db/primitives/observability.js +162 -0
- package/dist/db/primitives/observability.js.map +1 -0
- package/dist/db/primitives/schema-evolution.js +643 -0
- package/dist/db/primitives/schema-evolution.js.map +1 -0
- package/dist/db/primitives/stateful-operator/index.js +770 -0
- package/dist/db/primitives/stateful-operator/index.js.map +1 -0
- package/dist/db/primitives/temporal-store.js +306 -0
- package/dist/db/primitives/temporal-store.js.map +1 -0
- package/dist/db/primitives/typed-column-store.js +1229 -0
- package/dist/db/primitives/typed-column-store.js.map +1 -0
- package/dist/db/primitives/utils/duration.js +162 -0
- package/dist/db/primitives/utils/duration.js.map +1 -0
- package/dist/db/primitives/utils/murmur3.js +118 -0
- package/dist/db/primitives/utils/murmur3.js.map +1 -0
- package/dist/db/primitives/watermark-service.js +136 -0
- package/dist/db/primitives/watermark-service.js.map +1 -0
- package/dist/db/primitives/window-manager.js +764 -0
- package/dist/db/primitives/window-manager.js.map +1 -0
- package/dist/db/relationships.js +66 -0
- package/dist/db/relationships.js.map +1 -0
- package/dist/db/schema-minimal.js +61 -0
- package/dist/db/schema-minimal.js.map +1 -0
- package/dist/db/search.js +28 -0
- package/dist/db/search.js.map +1 -0
- package/dist/db/stores.js +1665 -0
- package/dist/db/stores.js.map +1 -0
- package/dist/db/things.js +297 -0
- package/dist/db/things.js.map +1 -0
- package/dist/db/vault.js +171 -0
- package/dist/db/vault.js.map +1 -0
- package/dist/db/verbs.js +102 -0
- package/dist/db/verbs.js.map +1 -0
- package/dist/do/base.js +48 -0
- package/dist/do/base.js.map +1 -0
- package/dist/do/bash.js +35 -0
- package/dist/do/bash.js.map +1 -0
- package/dist/do/fs.js +25 -0
- package/dist/do/fs.js.map +1 -0
- package/dist/do/full.js +61 -0
- package/dist/do/full.js.map +1 -0
- package/dist/do/git.js +28 -0
- package/dist/do/git.js.map +1 -0
- package/dist/do/index.js +52 -0
- package/dist/do/index.js.map +1 -0
- package/dist/do/tiny.js +31 -0
- package/dist/do/tiny.js.map +1 -0
- package/dist/lib/DOAuth.js +261 -0
- package/dist/lib/DOAuth.js.map +1 -0
- package/dist/lib/DODispatcher.js +72 -0
- package/dist/lib/DODispatcher.js.map +1 -0
- package/dist/lib/Modifier.js +189 -0
- package/dist/lib/Modifier.js.map +1 -0
- package/dist/lib/StateStorage.js +403 -0
- package/dist/lib/StateStorage.js.map +1 -0
- package/dist/lib/TypeRegistry.js +122 -0
- package/dist/lib/TypeRegistry.js.map +1 -0
- package/dist/lib/agent/tools/bash.js +336 -0
- package/dist/lib/agent/tools/bash.js.map +1 -0
- package/dist/lib/agent/tools/edit.js +157 -0
- package/dist/lib/agent/tools/edit.js.map +1 -0
- package/dist/lib/agent/tools/glob.js +137 -0
- package/dist/lib/agent/tools/glob.js.map +1 -0
- package/dist/lib/agent/tools/grep.js +315 -0
- package/dist/lib/agent/tools/grep.js.map +1 -0
- package/dist/lib/agent/tools/index.js +71 -0
- package/dist/lib/agent/tools/index.js.map +1 -0
- package/dist/lib/agent/tools/read.js +212 -0
- package/dist/lib/agent/tools/read.js.map +1 -0
- package/dist/lib/agent/tools/types.js +197 -0
- package/dist/lib/agent/tools/types.js.map +1 -0
- package/dist/lib/agent/tools/write.js +159 -0
- package/dist/lib/agent/tools/write.js.map +1 -0
- package/dist/lib/ai/gateway.js +247 -0
- package/dist/lib/ai/gateway.js.map +1 -0
- package/dist/lib/ai/tool-loop-agent.js +591 -0
- package/dist/lib/ai/tool-loop-agent.js.map +1 -0
- package/dist/lib/auto-wiring.js +439 -0
- package/dist/lib/auto-wiring.js.map +1 -0
- package/dist/lib/browse/browserbase.js +163 -0
- package/dist/lib/browse/browserbase.js.map +1 -0
- package/dist/lib/browse/cloudflare.js +144 -0
- package/dist/lib/browse/cloudflare.js.map +1 -0
- package/dist/lib/browse/index.js +62 -0
- package/dist/lib/browse/index.js.map +1 -0
- package/dist/lib/browse/types.js +13 -0
- package/dist/lib/browse/types.js.map +1 -0
- package/dist/lib/cache/index.js +37 -0
- package/dist/lib/cache/index.js.map +1 -0
- package/dist/lib/cache/visibility.js +638 -0
- package/dist/lib/cache/visibility.js.map +1 -0
- package/dist/lib/capabilities.js +268 -0
- package/dist/lib/capabilities.js.map +1 -0
- package/dist/lib/channels/base.js +106 -0
- package/dist/lib/channels/base.js.map +1 -0
- package/dist/lib/channels/discord.js +94 -0
- package/dist/lib/channels/discord.js.map +1 -0
- package/dist/lib/channels/email.js +204 -0
- package/dist/lib/channels/email.js.map +1 -0
- package/dist/lib/channels/index.js +90 -0
- package/dist/lib/channels/index.js.map +1 -0
- package/dist/lib/channels/mdxui-chat.js +95 -0
- package/dist/lib/channels/mdxui-chat.js.map +1 -0
- package/dist/lib/channels/slack-blockkit.js +121 -0
- package/dist/lib/channels/slack-blockkit.js.map +1 -0
- package/dist/lib/channels/types.js +7 -0
- package/dist/lib/channels/types.js.map +1 -0
- package/dist/lib/cloudflare/ai.js +654 -0
- package/dist/lib/cloudflare/ai.js.map +1 -0
- package/dist/lib/cloudflare/index.js +88 -0
- package/dist/lib/cloudflare/index.js.map +1 -0
- package/dist/lib/cloudflare/kv.js +342 -0
- package/dist/lib/cloudflare/kv.js.map +1 -0
- package/dist/lib/cloudflare/queues.js +434 -0
- package/dist/lib/cloudflare/queues.js.map +1 -0
- package/dist/lib/cloudflare/r2.js +604 -0
- package/dist/lib/cloudflare/r2.js.map +1 -0
- package/dist/lib/cloudflare/vectorize.js +494 -0
- package/dist/lib/cloudflare/vectorize.js.map +1 -0
- package/dist/lib/cloudflare/workflows.js +569 -0
- package/dist/lib/cloudflare/workflows.js.map +1 -0
- package/dist/lib/colo/caching.js +196 -0
- package/dist/lib/colo/caching.js.map +1 -0
- package/dist/lib/colo/detection.js +194 -0
- package/dist/lib/colo/detection.js.map +1 -0
- package/dist/lib/colo/external-data.js +219 -0
- package/dist/lib/colo/external-data.js.map +1 -0
- package/dist/lib/colo/globe-data.js +179 -0
- package/dist/lib/colo/globe-data.js.map +1 -0
- package/dist/lib/colo/index.js +16 -0
- package/dist/lib/colo/index.js.map +1 -0
- package/dist/lib/decorators.js +37 -0
- package/dist/lib/decorators.js.map +1 -0
- package/dist/lib/discovery.js +81 -0
- package/dist/lib/discovery.js.map +1 -0
- package/dist/lib/executors/AgenticFunctionExecutor.js +619 -0
- package/dist/lib/executors/AgenticFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/BaseFunctionExecutor.js +328 -0
- package/dist/lib/executors/BaseFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/CascadeExecutor.js +418 -0
- package/dist/lib/executors/CascadeExecutor.js.map +1 -0
- package/dist/lib/executors/CodeFunctionExecutor.js +904 -0
- package/dist/lib/executors/CodeFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/GenerativeFunctionExecutor.js +904 -0
- package/dist/lib/executors/GenerativeFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/HumanFunctionExecutor.js +884 -0
- package/dist/lib/executors/HumanFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/ParallelStepExecutor.js +308 -0
- package/dist/lib/executors/ParallelStepExecutor.js.map +1 -0
- package/dist/lib/executors/types.js +12 -0
- package/dist/lib/executors/types.js.map +1 -0
- package/dist/lib/experiments.js +89 -0
- package/dist/lib/experiments.js.map +1 -0
- package/dist/lib/flags/store.js +262 -0
- package/dist/lib/flags/store.js.map +1 -0
- package/dist/lib/functions/FunctionComposition.js +467 -0
- package/dist/lib/functions/FunctionComposition.js.map +1 -0
- package/dist/lib/functions/FunctionMiddleware.js +457 -0
- package/dist/lib/functions/FunctionMiddleware.js.map +1 -0
- package/dist/lib/functions/FunctionRegistry.js +426 -0
- package/dist/lib/functions/FunctionRegistry.js.map +1 -0
- package/dist/lib/functions/createFunction.js +1048 -0
- package/dist/lib/functions/createFunction.js.map +1 -0
- package/dist/lib/humans/index.js +68 -0
- package/dist/lib/humans/index.js.map +1 -0
- package/dist/lib/humans/templates.js +117 -0
- package/dist/lib/humans/templates.js.map +1 -0
- package/dist/lib/identity.js +98 -0
- package/dist/lib/identity.js.map +1 -0
- package/dist/lib/index.js +9 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/logging/error-logger.js +163 -0
- package/dist/lib/logging/error-logger.js.map +1 -0
- package/dist/lib/logging/index.js +160 -0
- package/dist/lib/logging/index.js.map +1 -0
- package/dist/lib/mixins/bash.js +825 -0
- package/dist/lib/mixins/bash.js.map +1 -0
- package/dist/lib/mixins/fs.js +648 -0
- package/dist/lib/mixins/fs.js.map +1 -0
- package/dist/lib/mixins/git.js +1011 -0
- package/dist/lib/mixins/git.js.map +1 -0
- package/dist/lib/mixins/index.js +29 -0
- package/dist/lib/mixins/index.js.map +1 -0
- package/dist/lib/mixins/npm.js +662 -0
- package/dist/lib/mixins/npm.js.map +1 -0
- package/dist/lib/noun-id.js +278 -0
- package/dist/lib/noun-id.js.map +1 -0
- package/dist/lib/rate-limit/sliding-window.js +148 -0
- package/dist/lib/rate-limit/sliding-window.js.map +1 -0
- package/dist/lib/rate-limit.js +110 -0
- package/dist/lib/rate-limit.js.map +1 -0
- package/dist/lib/rpc/bindings.js +548 -0
- package/dist/lib/rpc/bindings.js.map +1 -0
- package/dist/lib/rpc/index.js +64 -0
- package/dist/lib/rpc/index.js.map +1 -0
- package/dist/lib/safe-stringify.js +223 -0
- package/dist/lib/safe-stringify.js.map +1 -0
- package/dist/lib/sandbox/miniflare-sandbox.js +1007 -0
- package/dist/lib/sandbox/miniflare-sandbox.js.map +1 -0
- package/dist/lib/sqids.js +110 -0
- package/dist/lib/sqids.js.map +1 -0
- package/dist/lib/sql/adapters/index.js +10 -0
- package/dist/lib/sql/adapters/index.js.map +1 -0
- package/dist/lib/sql/adapters/node-sql-parser.js +552 -0
- package/dist/lib/sql/adapters/node-sql-parser.js.map +1 -0
- package/dist/lib/sql/adapters/pgsql-parser.js +1189 -0
- package/dist/lib/sql/adapters/pgsql-parser.js.map +1 -0
- package/dist/lib/sql/index.js +277 -0
- package/dist/lib/sql/index.js.map +1 -0
- package/dist/lib/sql/types.js +56 -0
- package/dist/lib/sql/types.js.map +1 -0
- package/dist/lib/type-classifier.js +126 -0
- package/dist/lib/type-classifier.js.map +1 -0
- package/dist/lib/utils/html.js +47 -0
- package/dist/lib/utils/html.js.map +1 -0
- package/dist/lib/validation.js +48 -0
- package/dist/lib/validation.js.map +1 -0
- package/dist/lib/vault/store.js +411 -0
- package/dist/lib/vault/store.js.map +1 -0
- package/dist/metrics/hunch.js +739 -0
- package/dist/metrics/hunch.js.map +1 -0
- package/dist/objects/API.js +302 -0
- package/dist/objects/API.js.map +1 -0
- package/dist/objects/Agent.js +179 -0
- package/dist/objects/Agent.js.map +1 -0
- package/dist/objects/AgenticFunctionExecutor.js +8 -0
- package/dist/objects/AgenticFunctionExecutor.js.map +1 -0
- package/dist/objects/App.js +83 -0
- package/dist/objects/App.js.map +1 -0
- package/dist/objects/Browser.js +884 -0
- package/dist/objects/Browser.js.map +1 -0
- package/dist/objects/Business.js +107 -0
- package/dist/objects/Business.js.map +1 -0
- package/dist/objects/CLI.js +221 -0
- package/dist/objects/CLI.js.map +1 -0
- package/dist/objects/CodeFunctionExecutor.js +8 -0
- package/dist/objects/CodeFunctionExecutor.js.map +1 -0
- package/dist/objects/Collection.js +161 -0
- package/dist/objects/Collection.js.map +1 -0
- package/dist/objects/DO.js +41 -0
- package/dist/objects/DO.js.map +1 -0
- package/dist/objects/DOBase.js +2309 -0
- package/dist/objects/DOBase.js.map +1 -0
- package/dist/objects/DOFull.js +1676 -0
- package/dist/objects/DOFull.js.map +1 -0
- package/dist/objects/DOTiny.js +207 -0
- package/dist/objects/DOTiny.js.map +1 -0
- package/dist/objects/Directory.js +199 -0
- package/dist/objects/Directory.js.map +1 -0
- package/dist/objects/Entity.js +413 -0
- package/dist/objects/Entity.js.map +1 -0
- package/dist/objects/Function.js +116 -0
- package/dist/objects/Function.js.map +1 -0
- package/dist/objects/Human.js +231 -0
- package/dist/objects/Human.js.map +1 -0
- package/dist/objects/HumanFunctionExecutor.js +8 -0
- package/dist/objects/HumanFunctionExecutor.js.map +1 -0
- package/dist/objects/IcebergMetadataDO.js +938 -0
- package/dist/objects/IcebergMetadataDO.js.map +1 -0
- package/dist/objects/IntegrationsDO.js +1174 -0
- package/dist/objects/IntegrationsDO.js.map +1 -0
- package/dist/objects/ObservabilityBroadcaster.js +149 -0
- package/dist/objects/ObservabilityBroadcaster.js.map +1 -0
- package/dist/objects/Package.js +154 -0
- package/dist/objects/Package.js.map +1 -0
- package/dist/objects/Product.js +193 -0
- package/dist/objects/Product.js.map +1 -0
- package/dist/objects/SDK.js +152 -0
- package/dist/objects/SDK.js.map +1 -0
- package/dist/objects/SaaS.js +235 -0
- package/dist/objects/SaaS.js.map +1 -0
- package/dist/objects/SandboxDO.js +759 -0
- package/dist/objects/SandboxDO.js.map +1 -0
- package/dist/objects/Service.js +337 -0
- package/dist/objects/Service.js.map +1 -0
- package/dist/objects/Site.js +80 -0
- package/dist/objects/Site.js.map +1 -0
- package/dist/objects/Startup.js +479 -0
- package/dist/objects/Startup.js.map +1 -0
- package/dist/objects/ThingsDO.js +170 -0
- package/dist/objects/ThingsDO.js.map +1 -0
- package/dist/objects/VectorShardDO.js +648 -0
- package/dist/objects/VectorShardDO.js.map +1 -0
- package/dist/objects/Worker.js +144 -0
- package/dist/objects/Worker.js.map +1 -0
- package/dist/objects/Workflow.js +196 -0
- package/dist/objects/Workflow.js.map +1 -0
- package/dist/objects/WorkflowFactory.js +313 -0
- package/dist/objects/WorkflowFactory.js.map +1 -0
- package/dist/objects/WorkflowRuntime.js +863 -0
- package/dist/objects/WorkflowRuntime.js.map +1 -0
- package/dist/objects/circuit-breaker-bulkhead.js +178 -0
- package/dist/objects/circuit-breaker-bulkhead.js.map +1 -0
- package/dist/objects/createFunction.js +934 -0
- package/dist/objects/createFunction.js.map +1 -0
- package/dist/objects/index.js +80 -0
- package/dist/objects/index.js.map +1 -0
- package/dist/objects/lifecycle/Branch.js +275 -0
- package/dist/objects/lifecycle/Branch.js.map +1 -0
- package/dist/objects/lifecycle/Clone.js +1499 -0
- package/dist/objects/lifecycle/Clone.js.map +1 -0
- package/dist/objects/lifecycle/Compact.js +237 -0
- package/dist/objects/lifecycle/Compact.js.map +1 -0
- package/dist/objects/lifecycle/Promote.js +476 -0
- package/dist/objects/lifecycle/Promote.js.map +1 -0
- package/dist/objects/lifecycle/Shard.js +560 -0
- package/dist/objects/lifecycle/Shard.js.map +1 -0
- package/dist/objects/lifecycle/index.js +15 -0
- package/dist/objects/lifecycle/index.js.map +1 -0
- package/dist/objects/lifecycle/types.js +33 -0
- package/dist/objects/lifecycle/types.js.map +1 -0
- package/dist/objects/mixins/infrastructure.js +171 -0
- package/dist/objects/mixins/infrastructure.js.map +1 -0
- package/dist/objects/modules/StoresModule.js +153 -0
- package/dist/objects/modules/StoresModule.js.map +1 -0
- package/dist/objects/persistence/checkpoint-manager.js +606 -0
- package/dist/objects/persistence/checkpoint-manager.js.map +1 -0
- package/dist/objects/persistence/index.js +72 -0
- package/dist/objects/persistence/index.js.map +1 -0
- package/dist/objects/persistence/migration-runner.js +562 -0
- package/dist/objects/persistence/migration-runner.js.map +1 -0
- package/dist/objects/persistence/replication-manager.js +501 -0
- package/dist/objects/persistence/replication-manager.js.map +1 -0
- package/dist/objects/persistence/tiered-storage-manager.js +595 -0
- package/dist/objects/persistence/tiered-storage-manager.js.map +1 -0
- package/dist/objects/persistence/types.js +14 -0
- package/dist/objects/persistence/types.js.map +1 -0
- package/dist/objects/persistence/wal-manager.js +653 -0
- package/dist/objects/persistence/wal-manager.js.map +1 -0
- package/dist/objects/presets/index.js +20 -0
- package/dist/objects/presets/index.js.map +1 -0
- package/dist/objects/presets/primitives.js +188 -0
- package/dist/objects/presets/primitives.js.map +1 -0
- package/dist/objects/primitives/alarm-adapter.js +141 -0
- package/dist/objects/primitives/alarm-adapter.js.map +1 -0
- package/dist/objects/primitives/index.js +337 -0
- package/dist/objects/primitives/index.js.map +1 -0
- package/dist/objects/primitives/storage-adapter.js +182 -0
- package/dist/objects/primitives/storage-adapter.js.map +1 -0
- package/dist/objects/primitives/with-primitives.js +102 -0
- package/dist/objects/primitives/with-primitives.js.map +1 -0
- package/dist/objects/services/StoreManager.js +227 -0
- package/dist/objects/services/StoreManager.js.map +1 -0
- package/dist/objects/services/index.js +13 -0
- package/dist/objects/services/index.js.map +1 -0
- package/dist/objects/transport/auth-layer.js +1451 -0
- package/dist/objects/transport/auth-layer.js.map +1 -0
- package/dist/objects/transport/capnweb-target.js +355 -0
- package/dist/objects/transport/capnweb-target.js.map +1 -0
- package/dist/objects/transport/chain.js +441 -0
- package/dist/objects/transport/chain.js.map +1 -0
- package/dist/objects/transport/handler.js +58 -0
- package/dist/objects/transport/handler.js.map +1 -0
- package/dist/objects/transport/index.js +53 -0
- package/dist/objects/transport/index.js.map +1 -0
- package/dist/objects/transport/mcp-server.js +690 -0
- package/dist/objects/transport/mcp-server.js.map +1 -0
- package/dist/objects/transport/rest-autowire.js +1507 -0
- package/dist/objects/transport/rest-autowire.js.map +1 -0
- package/dist/objects/transport/rest-router.js +440 -0
- package/dist/objects/transport/rest-router.js.map +1 -0
- package/dist/objects/transport/rpc-server.js +1536 -0
- package/dist/objects/transport/rpc-server.js.map +1 -0
- package/dist/objects/transport/shared.js +575 -0
- package/dist/objects/transport/shared.js.map +1 -0
- package/dist/objects/transport/sync-engine.js +291 -0
- package/dist/objects/transport/sync-engine.js.map +1 -0
- package/dist/objects/transport/types.js +8 -0
- package/dist/objects/transport/types.js.map +1 -0
- package/dist/primitives/bashx/src/ast/analyze.js +1472 -0
- package/dist/primitives/bashx/src/ast/analyze.js.map +1 -0
- package/dist/primitives/bashx/src/ast/parser.js +1488 -0
- package/dist/primitives/bashx/src/ast/parser.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/crypto.js +1954 -0
- package/dist/primitives/bashx/src/do/commands/crypto.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/data-processing.js +1812 -0
- package/dist/primitives/bashx/src/do/commands/data-processing.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/extended-utils.js +804 -0
- package/dist/primitives/bashx/src/do/commands/extended-utils.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/math-control.js +1122 -0
- package/dist/primitives/bashx/src/do/commands/math-control.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/posix-utils.js +1015 -0
- package/dist/primitives/bashx/src/do/commands/posix-utils.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/system-utils.js +687 -0
- package/dist/primitives/bashx/src/do/commands/system-utils.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/test-command.js +523 -0
- package/dist/primitives/bashx/src/do/commands/test-command.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/text-processing.js +1550 -0
- package/dist/primitives/bashx/src/do/commands/text-processing.js.map +1 -0
- package/dist/primitives/bashx/src/do/container-executor.js +429 -0
- package/dist/primitives/bashx/src/do/container-executor.js.map +1 -0
- package/dist/primitives/bashx/src/do/index.js +668 -0
- package/dist/primitives/bashx/src/do/index.js.map +1 -0
- package/dist/primitives/bashx/src/do/tiered-executor.js +2647 -0
- package/dist/primitives/bashx/src/do/tiered-executor.js.map +1 -0
- package/dist/primitives/bashx/src/do/worker.js +352 -0
- package/dist/primitives/bashx/src/do/worker.js.map +1 -0
- package/dist/primitives/bashx/src/types.js +10 -0
- package/dist/primitives/bashx/src/types.js.map +1 -0
- package/dist/primitives/fsx/core/backend.js +480 -0
- package/dist/primitives/fsx/core/backend.js.map +1 -0
- package/dist/primitives/fsx/core/constants.js +140 -0
- package/dist/primitives/fsx/core/constants.js.map +1 -0
- package/dist/primitives/fsx/core/fsx.js +1184 -0
- package/dist/primitives/fsx/core/fsx.js.map +1 -0
- package/dist/primitives/fsx/core/glob/glob.js +438 -0
- package/dist/primitives/fsx/core/glob/glob.js.map +1 -0
- package/dist/primitives/fsx/core/glob/index.js +8 -0
- package/dist/primitives/fsx/core/glob/index.js.map +1 -0
- package/dist/primitives/fsx/core/glob/match.js +392 -0
- package/dist/primitives/fsx/core/glob/match.js.map +1 -0
- package/dist/primitives/fsx/core/types.js +307 -0
- package/dist/primitives/fsx/core/types.js.map +1 -0
- package/dist/sandbox/index.js +258 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sdk/capnweb-compat.js +42 -0
- package/dist/sdk/capnweb-compat.js.map +1 -0
- package/dist/sdk/client.js +20 -0
- package/dist/sdk/client.js.map +1 -0
- package/dist/sdk/index.js +17 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/snippets/artifacts-config.js +241 -0
- package/dist/snippets/artifacts-config.js.map +1 -0
- package/dist/snippets/artifacts-ingest.js +832 -0
- package/dist/snippets/artifacts-ingest.js.map +1 -0
- package/dist/snippets/artifacts-serve.js +1035 -0
- package/dist/snippets/artifacts-serve.js.map +1 -0
- package/dist/snippets/artifacts-types.js +161 -0
- package/dist/snippets/artifacts-types.js.map +1 -0
- package/dist/snippets/cache-probe.js +376 -0
- package/dist/snippets/cache-probe.js.map +1 -0
- package/dist/snippets/cache.js +10 -0
- package/dist/snippets/cache.js.map +1 -0
- package/dist/snippets/events.js +469 -0
- package/dist/snippets/events.js.map +1 -0
- package/dist/snippets/index.js +7 -0
- package/dist/snippets/index.js.map +1 -0
- package/dist/snippets/proxy.js +495 -0
- package/dist/snippets/proxy.js.map +1 -0
- package/dist/snippets/search.js +1759 -0
- package/dist/snippets/search.js.map +1 -0
- package/dist/streams/index.js +30 -0
- package/dist/streams/index.js.map +1 -0
- package/dist/streams/observability.js +68 -0
- package/dist/streams/observability.js.map +1 -0
- package/dist/types/AI.js +92 -0
- package/dist/types/AI.js.map +1 -0
- package/dist/types/AIFunction.js +171 -0
- package/dist/types/AIFunction.js.map +1 -0
- package/dist/types/BrowseVerb.js +89 -0
- package/dist/types/BrowseVerb.js.map +1 -0
- package/dist/types/Browser.js +31 -0
- package/dist/types/Browser.js.map +1 -0
- package/dist/types/Chaos.js +15 -0
- package/dist/types/Chaos.js.map +1 -0
- package/dist/types/CloudflareBindings.js +109 -0
- package/dist/types/CloudflareBindings.js.map +1 -0
- package/dist/types/Collection.js +50 -0
- package/dist/types/Collection.js.map +1 -0
- package/dist/types/DO.js +2 -0
- package/dist/types/DO.js.map +1 -0
- package/dist/types/DOLocation.js +63 -0
- package/dist/types/DOLocation.js.map +1 -0
- package/dist/types/EventHandler.js +57 -0
- package/dist/types/EventHandler.js.map +1 -0
- package/dist/types/Experiment.js +33 -0
- package/dist/types/Experiment.js.map +1 -0
- package/dist/types/Flag.js +57 -0
- package/dist/types/Flag.js.map +1 -0
- package/dist/types/Lifecycle.js +13 -0
- package/dist/types/Lifecycle.js.map +1 -0
- package/dist/types/Location.js +169 -0
- package/dist/types/Location.js.map +1 -0
- package/dist/types/Noun.js +66 -0
- package/dist/types/Noun.js.map +1 -0
- package/dist/types/SessionEvent.js +194 -0
- package/dist/types/SessionEvent.js.map +1 -0
- package/dist/types/Thing.js +55 -0
- package/dist/types/Thing.js.map +1 -0
- package/dist/types/ThingDO.js +153 -0
- package/dist/types/ThingDO.js.map +1 -0
- package/dist/types/Things.js +2 -0
- package/dist/types/Things.js.map +1 -0
- package/dist/types/Verb.js +119 -0
- package/dist/types/Verb.js.map +1 -0
- package/dist/types/WorkflowContext.js +70 -0
- package/dist/types/WorkflowContext.js.map +1 -0
- package/dist/types/analytics-api.js +13 -0
- package/dist/types/analytics-api.js.map +1 -0
- package/dist/types/capabilities.js +135 -0
- package/dist/types/capabilities.js.map +1 -0
- package/dist/types/drizzle.js +12 -0
- package/dist/types/drizzle.js.map +1 -0
- package/dist/types/event.js +201 -0
- package/dist/types/event.js.map +1 -0
- package/dist/types/fn.js +12 -0
- package/dist/types/fn.js.map +1 -0
- package/dist/types/iceberg.js +48 -0
- package/dist/types/iceberg.js.map +1 -0
- package/dist/types/ids.js +170 -0
- package/dist/types/ids.js.map +1 -0
- package/dist/types/index.js +41 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/introspect.js +54 -0
- package/dist/types/introspect.js.map +1 -0
- package/dist/types/observability.js +124 -0
- package/dist/types/observability.js.map +1 -0
- package/dist/types/sync-protocol.js +175 -0
- package/dist/types/sync-protocol.js.map +1 -0
- package/dist/types/vector.js +13 -0
- package/dist/types/vector.js.map +1 -0
- package/dist/workflows/ScheduleManager.js +473 -0
- package/dist/workflows/ScheduleManager.js.map +1 -0
- package/dist/workflows/StepDOBridge.js +149 -0
- package/dist/workflows/StepDOBridge.js.map +1 -0
- package/dist/workflows/StepResultStorage.js +232 -0
- package/dist/workflows/StepResultStorage.js.map +1 -0
- package/dist/workflows/WaitForEventManager.js +461 -0
- package/dist/workflows/WaitForEventManager.js.map +1 -0
- package/dist/workflows/analyzer.js +332 -0
- package/dist/workflows/analyzer.js.map +1 -0
- package/dist/workflows/compat/activity-router.js +484 -0
- package/dist/workflows/compat/activity-router.js.map +1 -0
- package/dist/workflows/compat/backends/cloudflare-workflows.js +431 -0
- package/dist/workflows/compat/backends/cloudflare-workflows.js.map +1 -0
- package/dist/workflows/compat/backends/index.js +14 -0
- package/dist/workflows/compat/backends/index.js.map +1 -0
- package/dist/workflows/compat/errors/index.js +375 -0
- package/dist/workflows/compat/errors/index.js.map +1 -0
- package/dist/workflows/compat/index.js +79 -0
- package/dist/workflows/compat/index.js.map +1 -0
- package/dist/workflows/compat/inngest/index.js +989 -0
- package/dist/workflows/compat/inngest/index.js.map +1 -0
- package/dist/workflows/compat/qstash/index.js +1263 -0
- package/dist/workflows/compat/qstash/index.js.map +1 -0
- package/dist/workflows/compat/temporal/activities.js +739 -0
- package/dist/workflows/compat/temporal/activities.js.map +1 -0
- package/dist/workflows/compat/temporal/child-workflows.js +154 -0
- package/dist/workflows/compat/temporal/child-workflows.js.map +1 -0
- package/dist/workflows/compat/temporal/client.js +381 -0
- package/dist/workflows/compat/temporal/client.js.map +1 -0
- package/dist/workflows/compat/temporal/context.js +309 -0
- package/dist/workflows/compat/temporal/context.js.map +1 -0
- package/dist/workflows/compat/temporal/determinism.js +216 -0
- package/dist/workflows/compat/temporal/determinism.js.map +1 -0
- package/dist/workflows/compat/temporal/errors.js +128 -0
- package/dist/workflows/compat/temporal/errors.js.map +1 -0
- package/dist/workflows/compat/temporal/index.js +2464 -0
- package/dist/workflows/compat/temporal/index.js.map +1 -0
- package/dist/workflows/compat/temporal/saga.js +504 -0
- package/dist/workflows/compat/temporal/saga.js.map +1 -0
- package/dist/workflows/compat/temporal/signals.js +364 -0
- package/dist/workflows/compat/temporal/signals.js.map +1 -0
- package/dist/workflows/compat/temporal/storage.js +271 -0
- package/dist/workflows/compat/temporal/storage.js.map +1 -0
- package/dist/workflows/compat/temporal/timers.js +347 -0
- package/dist/workflows/compat/temporal/timers.js.map +1 -0
- package/dist/workflows/compat/temporal/types.js +7 -0
- package/dist/workflows/compat/temporal/types.js.map +1 -0
- package/dist/workflows/compat/temporal/unified-primitives.js +339 -0
- package/dist/workflows/compat/temporal/unified-primitives.js.map +1 -0
- package/dist/workflows/compat/trigger/index.js +468 -0
- package/dist/workflows/compat/trigger/index.js.map +1 -0
- package/dist/workflows/compat/utils/index.js +69 -0
- package/dist/workflows/compat/utils/index.js.map +1 -0
- package/dist/workflows/context/correlation-capability.js +266 -0
- package/dist/workflows/context/correlation-capability.js.map +1 -0
- package/dist/workflows/context/correlation.js +484 -0
- package/dist/workflows/context/correlation.js.map +1 -0
- package/dist/workflows/context/experiment.js +289 -0
- package/dist/workflows/context/experiment.js.map +1 -0
- package/dist/workflows/context/flag.js +244 -0
- package/dist/workflows/context/flag.js.map +1 -0
- package/dist/workflows/context/foundation.js +648 -0
- package/dist/workflows/context/foundation.js.map +1 -0
- package/dist/workflows/context/human-base.js +106 -0
- package/dist/workflows/context/human-base.js.map +1 -0
- package/dist/workflows/context/human.js +368 -0
- package/dist/workflows/context/human.js.map +1 -0
- package/dist/workflows/context/measure.js +354 -0
- package/dist/workflows/context/measure.js.map +1 -0
- package/dist/workflows/context/rate-limit.js +358 -0
- package/dist/workflows/context/rate-limit.js.map +1 -0
- package/dist/workflows/context/user.js +117 -0
- package/dist/workflows/context/user.js.map +1 -0
- package/dist/workflows/context/vault.js +360 -0
- package/dist/workflows/context/vault.js.map +1 -0
- package/dist/workflows/data/entity-events/entity-events.js +489 -0
- package/dist/workflows/data/entity-events/entity-events.js.map +1 -0
- package/dist/workflows/data/experiment/index.js +599 -0
- package/dist/workflows/data/experiment/index.js.map +1 -0
- package/dist/workflows/data/goal/context.js +558 -0
- package/dist/workflows/data/goal/context.js.map +1 -0
- package/dist/workflows/data/goal/index.js +32 -0
- package/dist/workflows/data/goal/index.js.map +1 -0
- package/dist/workflows/data/measure/index.js +840 -0
- package/dist/workflows/data/measure/index.js.map +1 -0
- package/dist/workflows/data/stream/index.js +1215 -0
- package/dist/workflows/data/stream/index.js.map +1 -0
- package/dist/workflows/data/track/context.js +883 -0
- package/dist/workflows/data/track/context.js.map +1 -0
- package/dist/workflows/data/track/index.js +15 -0
- package/dist/workflows/data/track/index.js.map +1 -0
- package/dist/workflows/data/view/context.js +864 -0
- package/dist/workflows/data/view/context.js.map +1 -0
- package/dist/workflows/domain.js +93 -0
- package/dist/workflows/domain.js.map +1 -0
- package/dist/workflows/flag.js +176 -0
- package/dist/workflows/flag.js.map +1 -0
- package/dist/workflows/flags.js +217 -0
- package/dist/workflows/flags.js.map +1 -0
- package/dist/workflows/hash.js +209 -0
- package/dist/workflows/hash.js.map +1 -0
- package/dist/workflows/index.js +50 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/on.js +378 -0
- package/dist/workflows/on.js.map +1 -0
- package/dist/workflows/pipeline-promise.js +481 -0
- package/dist/workflows/pipeline-promise.js.map +1 -0
- package/dist/workflows/pipeline-types.js +20 -0
- package/dist/workflows/pipeline-types.js.map +1 -0
- package/dist/workflows/proxy.js +76 -0
- package/dist/workflows/proxy.js.map +1 -0
- package/dist/workflows/runtime.js +310 -0
- package/dist/workflows/runtime.js.map +1 -0
- package/dist/workflows/schedule-builder.js +327 -0
- package/dist/workflows/schedule-builder.js.map +1 -0
- package/dist/workflows/visibility/index.js +148 -0
- package/dist/workflows/visibility/index.js.map +1 -0
- package/dist/workflows/visibility/query-parser.js +150 -0
- package/dist/workflows/visibility/query-parser.js.map +1 -0
- package/dist/workflows/visibility/store.js +223 -0
- package/dist/workflows/visibility/store.js.map +1 -0
- package/dist/workflows/visibility/types.js +30 -0
- package/dist/workflows/visibility/types.js.map +1 -0
- package/dist/workflows/workflow.js +53 -0
- package/dist/workflows/workflow.js.map +1 -0
- package/package.json +279 -46
|
@@ -0,0 +1,884 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser - Durable Object for browser automation session management
|
|
3
|
+
*
|
|
4
|
+
* Provides lifecycle management for browser automation sessions using
|
|
5
|
+
* the Browse library abstraction over Cloudflare Browser Rendering
|
|
6
|
+
* and Browserbase providers.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Session lifecycle: start(), stop(), alarm() for keepAlive
|
|
10
|
+
* - Provider abstraction: cloudflare and browserbase
|
|
11
|
+
* - Live view support for browserbase
|
|
12
|
+
* - Activity tracking with automatic timeout
|
|
13
|
+
* - Event emission for observability
|
|
14
|
+
* - AI operations: act, extract, observe
|
|
15
|
+
* - Autonomous agent execution
|
|
16
|
+
* - Screenshots
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Start a browser session with Cloudflare
|
|
21
|
+
* const result = await browserDO.start({
|
|
22
|
+
* provider: 'cloudflare',
|
|
23
|
+
* viewport: { width: 1920, height: 1080 },
|
|
24
|
+
* })
|
|
25
|
+
*
|
|
26
|
+
* // Start with Browserbase and live view
|
|
27
|
+
* const result = await browserDO.start({
|
|
28
|
+
* provider: 'browserbase',
|
|
29
|
+
* liveView: true,
|
|
30
|
+
* })
|
|
31
|
+
* console.log('Watch at:', result.liveViewUrl)
|
|
32
|
+
*
|
|
33
|
+
* // Perform operations
|
|
34
|
+
* await browserDO.goto('https://example.com.ai')
|
|
35
|
+
* await browserDO.act('Click the login button')
|
|
36
|
+
* const data = await browserDO.extract('Get the user profile')
|
|
37
|
+
*
|
|
38
|
+
* // Stop the session
|
|
39
|
+
* await browserDO.stop()
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
import { Hono } from 'hono';
|
|
43
|
+
import { DO } from './DO';
|
|
44
|
+
import { Browse } from '../lib/browse';
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// Browser Durable Object
|
|
47
|
+
// ============================================================================
|
|
48
|
+
export class Browser extends DO {
|
|
49
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
50
|
+
// TYPE DISCRIMINATOR
|
|
51
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
52
|
+
static $type = 'Browser';
|
|
53
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
54
|
+
// HONO HTTP APP
|
|
55
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
56
|
+
/**
|
|
57
|
+
* Hono app for HTTP route handling (overrides DO.app)
|
|
58
|
+
*/
|
|
59
|
+
app;
|
|
60
|
+
constructor(ctx, env) {
|
|
61
|
+
super(ctx, env);
|
|
62
|
+
this.app = this.createApp();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create the Hono app with all browser routes
|
|
66
|
+
*/
|
|
67
|
+
createApp() {
|
|
68
|
+
const app = new Hono();
|
|
69
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
70
|
+
// POST /start - Start browser session
|
|
71
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
72
|
+
app.post('/start', async (c) => {
|
|
73
|
+
try {
|
|
74
|
+
let body = {};
|
|
75
|
+
try {
|
|
76
|
+
body = await c.req.json();
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return c.json({ error: 'Invalid JSON body' }, 400);
|
|
80
|
+
}
|
|
81
|
+
const result = await this.start(body);
|
|
82
|
+
return c.json(result);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
86
|
+
if (message.includes('already active')) {
|
|
87
|
+
return c.json({ error: message }, 409);
|
|
88
|
+
}
|
|
89
|
+
if (message.includes('Invalid provider')) {
|
|
90
|
+
return c.json({ error: message }, 400);
|
|
91
|
+
}
|
|
92
|
+
return c.json({ error: message }, 500);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
96
|
+
// POST /goto - Navigate to URL
|
|
97
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
98
|
+
app.post('/goto', async (c) => {
|
|
99
|
+
try {
|
|
100
|
+
const body = await c.req.json().catch(() => ({}));
|
|
101
|
+
if (!body.url) {
|
|
102
|
+
return c.json({ error: 'Missing required field: url' }, 400);
|
|
103
|
+
}
|
|
104
|
+
await this.goto(body.url);
|
|
105
|
+
return c.json({ success: true });
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
109
|
+
if (message.includes('No active browser session')) {
|
|
110
|
+
return c.json({ error: 'No active browser session' }, 400);
|
|
111
|
+
}
|
|
112
|
+
if (message.includes('Invalid URL')) {
|
|
113
|
+
return c.json({ error: message }, 400);
|
|
114
|
+
}
|
|
115
|
+
return c.json({ error: message }, 500);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
119
|
+
// POST /act - Execute natural language action
|
|
120
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
121
|
+
app.post('/act', async (c) => {
|
|
122
|
+
try {
|
|
123
|
+
const body = await c.req.json().catch(() => ({}));
|
|
124
|
+
if (!body.instruction) {
|
|
125
|
+
return c.json({ error: 'Missing required field: instruction' }, 400);
|
|
126
|
+
}
|
|
127
|
+
const result = await this.act(body.instruction);
|
|
128
|
+
return c.json(result);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
132
|
+
if (message.includes('No active browser session')) {
|
|
133
|
+
return c.json({ error: 'No active browser session' }, 400);
|
|
134
|
+
}
|
|
135
|
+
return c.json({ error: message }, 500);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
139
|
+
// POST /extract - Extract structured data
|
|
140
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
141
|
+
app.post('/extract', async (c) => {
|
|
142
|
+
try {
|
|
143
|
+
const body = await c.req.json().catch(() => ({}));
|
|
144
|
+
if (!body.instruction) {
|
|
145
|
+
return c.json({ error: 'Missing required field: instruction' }, 400);
|
|
146
|
+
}
|
|
147
|
+
const result = await this.extract(body.instruction, body.schema);
|
|
148
|
+
return c.json(result);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
152
|
+
if (message.includes('No active browser session')) {
|
|
153
|
+
return c.json({ error: 'No active browser session' }, 400);
|
|
154
|
+
}
|
|
155
|
+
return c.json({ error: message }, 500);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
159
|
+
// POST /observe - Discover available actions
|
|
160
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
161
|
+
app.post('/observe', async (c) => {
|
|
162
|
+
try {
|
|
163
|
+
const body = await c.req.json().catch(() => ({}));
|
|
164
|
+
const result = await this.observe(body.instruction);
|
|
165
|
+
return c.json(result);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
169
|
+
if (message.includes('No active browser session')) {
|
|
170
|
+
return c.json({ error: 'No active browser session' }, 400);
|
|
171
|
+
}
|
|
172
|
+
return c.json({ error: message }, 500);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
176
|
+
// POST /agent - Run autonomous agent
|
|
177
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
178
|
+
app.post('/agent', async (c) => {
|
|
179
|
+
try {
|
|
180
|
+
const body = await c.req.json().catch(() => ({}));
|
|
181
|
+
if (!body.goal) {
|
|
182
|
+
return c.json({ error: 'Missing required field: goal' }, 400);
|
|
183
|
+
}
|
|
184
|
+
const result = await this.agent(body.goal);
|
|
185
|
+
return c.json(result);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
189
|
+
if (message.includes('No active browser session')) {
|
|
190
|
+
return c.json({ error: 'No active browser session' }, 400);
|
|
191
|
+
}
|
|
192
|
+
if (message.includes('Agent not available')) {
|
|
193
|
+
return c.json({ error: 'Agent not available on this browser session' }, 400);
|
|
194
|
+
}
|
|
195
|
+
return c.json({ error: message }, 500);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
199
|
+
// GET /state - Get browser state
|
|
200
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
201
|
+
app.get('/state', async (c) => {
|
|
202
|
+
const state = await this.getState();
|
|
203
|
+
return c.json(state);
|
|
204
|
+
});
|
|
205
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
206
|
+
// GET /screenshot - Capture page screenshot
|
|
207
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
208
|
+
app.get('/screenshot', async (c) => {
|
|
209
|
+
try {
|
|
210
|
+
const fullPage = c.req.query('fullPage') === 'true';
|
|
211
|
+
const selector = c.req.query('selector');
|
|
212
|
+
const options = {};
|
|
213
|
+
if (fullPage)
|
|
214
|
+
options.fullPage = true;
|
|
215
|
+
if (selector)
|
|
216
|
+
options.selector = selector;
|
|
217
|
+
const image = await this.screenshot(Object.keys(options).length > 0 ? options : undefined);
|
|
218
|
+
return c.json({ image });
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
222
|
+
if (message.includes('No active browser session')) {
|
|
223
|
+
return c.json({ error: 'No active browser session' }, 400);
|
|
224
|
+
}
|
|
225
|
+
return c.json({ error: message }, 500);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
229
|
+
// POST /stop - Stop browser session
|
|
230
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
231
|
+
app.post('/stop', async (c) => {
|
|
232
|
+
try {
|
|
233
|
+
await this.stop();
|
|
234
|
+
return c.json({ success: true });
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
238
|
+
if (message.includes('No active browser session')) {
|
|
239
|
+
return c.json({ error: 'No active browser session' }, 400);
|
|
240
|
+
}
|
|
241
|
+
return c.json({ error: message }, 500);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
245
|
+
// GET /live - Redirect to live view
|
|
246
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
247
|
+
app.get('/live', (c) => {
|
|
248
|
+
const liveViewUrl = this.session?.liveViewUrl;
|
|
249
|
+
if (!liveViewUrl) {
|
|
250
|
+
return c.json({ error: 'Live view not available' }, 404);
|
|
251
|
+
}
|
|
252
|
+
return c.redirect(liveViewUrl, 302);
|
|
253
|
+
});
|
|
254
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
255
|
+
// GET /screencast - WebSocket info (upgrade handled in fetch)
|
|
256
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
257
|
+
app.get('/screencast', (c) => {
|
|
258
|
+
// WebSocket upgrades are handled directly in fetch()
|
|
259
|
+
// This route is reached when no Upgrade header is present
|
|
260
|
+
return c.text('Use WebSocket upgrade', 400);
|
|
261
|
+
});
|
|
262
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
263
|
+
// POST /screencast/start - Start screencast streaming
|
|
264
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
265
|
+
app.post('/screencast/start', async (c) => {
|
|
266
|
+
try {
|
|
267
|
+
const body = await c.req.json().catch(() => ({}));
|
|
268
|
+
await this.startScreencast(body);
|
|
269
|
+
return c.json({ success: true });
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
273
|
+
if (message.includes('Browser session not started')) {
|
|
274
|
+
return c.json({ error: message }, 400);
|
|
275
|
+
}
|
|
276
|
+
return c.json({ error: message }, 500);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
280
|
+
// POST /screencast/stop - Stop screencast streaming
|
|
281
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
282
|
+
app.post('/screencast/stop', async (c) => {
|
|
283
|
+
try {
|
|
284
|
+
await this.stopScreencast();
|
|
285
|
+
return c.json({ success: true });
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
289
|
+
return c.json({ error: message }, 500);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
293
|
+
// Method not allowed handler
|
|
294
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
295
|
+
app.on(['GET'], ['/start', '/goto', '/act', '/extract', '/observe', '/agent', '/stop'], (c) => {
|
|
296
|
+
return c.json({ error: 'Method not allowed' }, 405);
|
|
297
|
+
});
|
|
298
|
+
app.on(['POST', 'PUT', 'DELETE', 'PATCH'], ['/state', '/screenshot', '/live'], (c) => {
|
|
299
|
+
return c.json({ error: 'Method not allowed' }, 405);
|
|
300
|
+
});
|
|
301
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
302
|
+
// 404 handler for unknown routes
|
|
303
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
304
|
+
app.all('*', (c) => {
|
|
305
|
+
return c.json({ error: 'Not found' }, 404);
|
|
306
|
+
});
|
|
307
|
+
return app;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Handle incoming HTTP requests via Hono
|
|
311
|
+
*
|
|
312
|
+
* Checks for WebSocket upgrade on /screencast path before
|
|
313
|
+
* delegating to Hono router.
|
|
314
|
+
*/
|
|
315
|
+
async fetch(request) {
|
|
316
|
+
// Check for WebSocket upgrade on /screencast path
|
|
317
|
+
const url = new URL(request.url);
|
|
318
|
+
if (url.pathname === '/screencast' && request.headers.get('Upgrade') === 'websocket') {
|
|
319
|
+
return this.handleScreencastWebSocket(request);
|
|
320
|
+
}
|
|
321
|
+
return this.handleFetch(request);
|
|
322
|
+
}
|
|
323
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
324
|
+
// SESSION STATE
|
|
325
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
326
|
+
/**
|
|
327
|
+
* Active browser session (null when stopped)
|
|
328
|
+
*/
|
|
329
|
+
session = null;
|
|
330
|
+
/**
|
|
331
|
+
* Browser configuration (stored version with sessionId)
|
|
332
|
+
*/
|
|
333
|
+
storedConfig = null;
|
|
334
|
+
/**
|
|
335
|
+
* Legacy config property for compatibility
|
|
336
|
+
*/
|
|
337
|
+
config = null;
|
|
338
|
+
/**
|
|
339
|
+
* Last activity timestamp for keep-alive
|
|
340
|
+
*/
|
|
341
|
+
lastActivity = 0;
|
|
342
|
+
/**
|
|
343
|
+
* Session timeout in milliseconds (5 minutes)
|
|
344
|
+
*/
|
|
345
|
+
SESSION_TIMEOUT = 5 * 60 * 1000;
|
|
346
|
+
/**
|
|
347
|
+
* Keep-alive timeout in milliseconds (default: 5 minutes)
|
|
348
|
+
* @deprecated Use SESSION_TIMEOUT instead
|
|
349
|
+
*/
|
|
350
|
+
keepAliveTimeout = 5 * 60 * 1000;
|
|
351
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
352
|
+
// SCREENCAST STATE
|
|
353
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
354
|
+
/**
|
|
355
|
+
* CDP session for screencast streaming
|
|
356
|
+
*/
|
|
357
|
+
cdpSession = null;
|
|
358
|
+
/**
|
|
359
|
+
* Set of connected WebSocket clients for screencast
|
|
360
|
+
*/
|
|
361
|
+
screencastClients = new Set();
|
|
362
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
363
|
+
// SESSION VALIDATION
|
|
364
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
365
|
+
/**
|
|
366
|
+
* Assert that a session is active, throw otherwise
|
|
367
|
+
*/
|
|
368
|
+
requireSession() {
|
|
369
|
+
if (!this.session) {
|
|
370
|
+
throw new Error('No active browser session');
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Check if a browser session is currently active
|
|
375
|
+
*/
|
|
376
|
+
isActive() {
|
|
377
|
+
return this.session !== null;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Get the current stored config
|
|
381
|
+
*/
|
|
382
|
+
getConfig() {
|
|
383
|
+
return this.storedConfig;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Get the last activity timestamp
|
|
387
|
+
*/
|
|
388
|
+
getLastActivity() {
|
|
389
|
+
return this.lastActivity;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Get the live view URL if available
|
|
393
|
+
*/
|
|
394
|
+
getLiveViewUrl() {
|
|
395
|
+
return this.session?.liveViewUrl;
|
|
396
|
+
}
|
|
397
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
398
|
+
// KEEP-ALIVE MANAGEMENT
|
|
399
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
400
|
+
/**
|
|
401
|
+
* Update last activity timestamp
|
|
402
|
+
*
|
|
403
|
+
* Called internally when browser operations are performed to
|
|
404
|
+
* prevent session timeout.
|
|
405
|
+
*/
|
|
406
|
+
async touch() {
|
|
407
|
+
this.lastActivity = Date.now();
|
|
408
|
+
await this.ctx.storage.put('browser:lastActivity', this.lastActivity);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Reset the keep-alive timer
|
|
412
|
+
* Called after each operation to extend session lifetime
|
|
413
|
+
* @deprecated Use touch() instead
|
|
414
|
+
*/
|
|
415
|
+
async resetKeepAlive() {
|
|
416
|
+
await this.touch();
|
|
417
|
+
}
|
|
418
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
419
|
+
// NAVIGATION OPERATIONS
|
|
420
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
421
|
+
/**
|
|
422
|
+
* Navigate to a URL
|
|
423
|
+
*
|
|
424
|
+
* @param url - The URL to navigate to
|
|
425
|
+
* @throws Error if session is not started or URL is invalid
|
|
426
|
+
*/
|
|
427
|
+
async goto(url) {
|
|
428
|
+
this.requireSession();
|
|
429
|
+
// Validate URL format
|
|
430
|
+
try {
|
|
431
|
+
new URL(url);
|
|
432
|
+
}
|
|
433
|
+
catch {
|
|
434
|
+
throw new Error(`Invalid URL: ${url}`);
|
|
435
|
+
}
|
|
436
|
+
// Navigate
|
|
437
|
+
await this.session.goto(url);
|
|
438
|
+
// Reset keep-alive
|
|
439
|
+
await this.resetKeepAlive();
|
|
440
|
+
// Log action
|
|
441
|
+
await this.logBrowserAction('goto', { url });
|
|
442
|
+
// Emit event
|
|
443
|
+
await this.emit('browser.navigated', { url });
|
|
444
|
+
}
|
|
445
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
446
|
+
// AI OPERATIONS
|
|
447
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
448
|
+
/**
|
|
449
|
+
* Execute a natural language action on the page
|
|
450
|
+
*
|
|
451
|
+
* @param instruction - Natural language instruction (e.g., "Click the submit button")
|
|
452
|
+
* @returns ActResult with success status and action details
|
|
453
|
+
* @throws Error if session is not started
|
|
454
|
+
*/
|
|
455
|
+
async act(instruction) {
|
|
456
|
+
this.requireSession();
|
|
457
|
+
// Execute action
|
|
458
|
+
const result = await this.session.act(instruction);
|
|
459
|
+
// Reset keep-alive
|
|
460
|
+
await this.resetKeepAlive();
|
|
461
|
+
// Log action with result
|
|
462
|
+
await this.logBrowserAction('act', { instruction, result });
|
|
463
|
+
// Emit event
|
|
464
|
+
await this.emit('browser.acted', { instruction, result });
|
|
465
|
+
return result;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Extract structured data from the page
|
|
469
|
+
*
|
|
470
|
+
* @param instruction - Natural language description of what to extract
|
|
471
|
+
* @param schema - Optional JSON schema for the extracted data
|
|
472
|
+
* @returns Extracted data matching the schema
|
|
473
|
+
* @throws Error if session is not started
|
|
474
|
+
*/
|
|
475
|
+
async extract(instruction, schema) {
|
|
476
|
+
this.requireSession();
|
|
477
|
+
// Extract data
|
|
478
|
+
const result = await this.session.extract(instruction, schema);
|
|
479
|
+
// Reset keep-alive
|
|
480
|
+
await this.resetKeepAlive();
|
|
481
|
+
// Log action with result
|
|
482
|
+
await this.logBrowserAction('extract', { instruction, schema, result });
|
|
483
|
+
// Emit event
|
|
484
|
+
await this.emit('browser.extracted', { instruction, result });
|
|
485
|
+
return result;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Observe available actions on the page
|
|
489
|
+
*
|
|
490
|
+
* @param instruction - Optional filter for what actions to observe
|
|
491
|
+
* @returns Array of available actions with selectors and descriptions
|
|
492
|
+
* @throws Error if session is not started
|
|
493
|
+
*/
|
|
494
|
+
async observe(instruction) {
|
|
495
|
+
this.requireSession();
|
|
496
|
+
// Observe page
|
|
497
|
+
const result = await this.session.observe(instruction);
|
|
498
|
+
// Reset keep-alive
|
|
499
|
+
await this.resetKeepAlive();
|
|
500
|
+
// Log action
|
|
501
|
+
await this.logBrowserAction('observe', { instruction, result });
|
|
502
|
+
// Emit event
|
|
503
|
+
await this.emit('browser.observed', { instruction, actions: result });
|
|
504
|
+
return result;
|
|
505
|
+
}
|
|
506
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
507
|
+
// AGENT OPERATIONS
|
|
508
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
509
|
+
/**
|
|
510
|
+
* Run an autonomous agent to accomplish a goal
|
|
511
|
+
*
|
|
512
|
+
* @param goal - The goal for the agent to accomplish
|
|
513
|
+
* @returns AgentResult with success status and steps taken
|
|
514
|
+
* @throws Error if session is not started or agent is not available
|
|
515
|
+
*/
|
|
516
|
+
async agent(goal) {
|
|
517
|
+
this.requireSession();
|
|
518
|
+
// Check if agent is available on the session
|
|
519
|
+
if (!this.session.agent) {
|
|
520
|
+
throw new Error('Agent not available on this browser session');
|
|
521
|
+
}
|
|
522
|
+
// Execute agent
|
|
523
|
+
const result = await this.session.agent.execute(goal);
|
|
524
|
+
// Reset keep-alive
|
|
525
|
+
await this.resetKeepAlive();
|
|
526
|
+
// Log action
|
|
527
|
+
await this.logBrowserAction('agent', { goal, result });
|
|
528
|
+
// Emit event
|
|
529
|
+
await this.emit('browser.agent.completed', { goal, result });
|
|
530
|
+
return result;
|
|
531
|
+
}
|
|
532
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
533
|
+
// SCREENSHOT OPERATIONS
|
|
534
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
535
|
+
/**
|
|
536
|
+
* Take a screenshot of the current page
|
|
537
|
+
*
|
|
538
|
+
* @param options - Screenshot options (fullPage, selector, type, quality)
|
|
539
|
+
* @returns Base64-encoded screenshot data
|
|
540
|
+
* @throws Error if session is not started
|
|
541
|
+
*/
|
|
542
|
+
async screenshot(options) {
|
|
543
|
+
this.requireSession();
|
|
544
|
+
// Take screenshot
|
|
545
|
+
const result = await this.session.screenshot(options);
|
|
546
|
+
// Reset keep-alive
|
|
547
|
+
await this.resetKeepAlive();
|
|
548
|
+
// Log action
|
|
549
|
+
await this.logBrowserAction('screenshot', { options });
|
|
550
|
+
// Emit event
|
|
551
|
+
await this.emit('browser.screenshot', { options });
|
|
552
|
+
return result;
|
|
553
|
+
}
|
|
554
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
555
|
+
// SCREENCAST OPERATIONS
|
|
556
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
557
|
+
/**
|
|
558
|
+
* Start CDP screencast streaming
|
|
559
|
+
*
|
|
560
|
+
* Creates a CDP session and begins streaming screencast frames.
|
|
561
|
+
* Frames are broadcast to all connected WebSocket clients.
|
|
562
|
+
*
|
|
563
|
+
* @param options - Screencast options (format, quality, dimensions)
|
|
564
|
+
* @throws Error if browser session not started
|
|
565
|
+
*
|
|
566
|
+
* @example
|
|
567
|
+
* ```typescript
|
|
568
|
+
* await browser.startScreencast({
|
|
569
|
+
* format: 'jpeg',
|
|
570
|
+
* quality: 60,
|
|
571
|
+
* maxWidth: 1280,
|
|
572
|
+
* maxHeight: 720,
|
|
573
|
+
* })
|
|
574
|
+
* ```
|
|
575
|
+
*/
|
|
576
|
+
async startScreencast(options = {}) {
|
|
577
|
+
if (!this.session?.page) {
|
|
578
|
+
throw new Error('Browser session not started');
|
|
579
|
+
}
|
|
580
|
+
// Create CDP session if not exists
|
|
581
|
+
if (!this.cdpSession) {
|
|
582
|
+
this.cdpSession = await this.session.page.createCDPSession();
|
|
583
|
+
// Listen for frames
|
|
584
|
+
this.cdpSession.on('Page.screencastFrame', async (event) => {
|
|
585
|
+
const { data, metadata, sessionId } = event;
|
|
586
|
+
// Broadcast to all connected clients
|
|
587
|
+
this.broadcastFrame(data, metadata);
|
|
588
|
+
// Acknowledge frame receipt
|
|
589
|
+
await this.cdpSession?.send('Page.screencastFrameAck', { sessionId });
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
// Start screencast with options
|
|
593
|
+
await this.cdpSession.send('Page.startScreencast', {
|
|
594
|
+
format: options.format || 'jpeg',
|
|
595
|
+
quality: options.quality ?? 60,
|
|
596
|
+
maxWidth: options.maxWidth ?? 1280,
|
|
597
|
+
maxHeight: options.maxHeight ?? 720,
|
|
598
|
+
everyNthFrame: options.everyNthFrame ?? 2,
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Stop CDP screencast streaming
|
|
603
|
+
*
|
|
604
|
+
* Sends stop command to CDP session if active.
|
|
605
|
+
*
|
|
606
|
+
* @example
|
|
607
|
+
* ```typescript
|
|
608
|
+
* await browser.stopScreencast()
|
|
609
|
+
* ```
|
|
610
|
+
*/
|
|
611
|
+
async stopScreencast() {
|
|
612
|
+
if (this.cdpSession) {
|
|
613
|
+
await this.cdpSession.send('Page.stopScreencast');
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Broadcast a screencast frame to all connected WebSocket clients
|
|
618
|
+
*
|
|
619
|
+
* @param data - Base64-encoded frame data
|
|
620
|
+
* @param metadata - Frame metadata from CDP
|
|
621
|
+
*/
|
|
622
|
+
broadcastFrame(data, metadata) {
|
|
623
|
+
const message = JSON.stringify({
|
|
624
|
+
type: 'frame',
|
|
625
|
+
data,
|
|
626
|
+
metadata,
|
|
627
|
+
timestamp: Date.now(),
|
|
628
|
+
});
|
|
629
|
+
for (const client of this.screencastClients) {
|
|
630
|
+
try {
|
|
631
|
+
client.send(message);
|
|
632
|
+
}
|
|
633
|
+
catch {
|
|
634
|
+
// Client disconnected, remove from set
|
|
635
|
+
this.screencastClients.delete(client);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Handle WebSocket upgrade for screencast streaming
|
|
641
|
+
*
|
|
642
|
+
* Creates a WebSocket pair and manages the screencast connection.
|
|
643
|
+
* Clients can send 'start' and 'stop' actions via messages.
|
|
644
|
+
*
|
|
645
|
+
* @param request - The incoming WebSocket upgrade request
|
|
646
|
+
* @returns Response with WebSocket upgrade (status 101)
|
|
647
|
+
*/
|
|
648
|
+
handleScreencastWebSocket(request) {
|
|
649
|
+
const pair = new WebSocketPair();
|
|
650
|
+
const [client, server] = Object.values(pair);
|
|
651
|
+
server.accept();
|
|
652
|
+
this.screencastClients.add(server);
|
|
653
|
+
server.addEventListener('message', async (event) => {
|
|
654
|
+
try {
|
|
655
|
+
const msg = JSON.parse(event.data);
|
|
656
|
+
if (msg.action === 'start') {
|
|
657
|
+
await this.startScreencast(msg.options);
|
|
658
|
+
}
|
|
659
|
+
else if (msg.action === 'stop') {
|
|
660
|
+
await this.stopScreencast();
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
catch (e) {
|
|
664
|
+
server.send(JSON.stringify({ type: 'error', message: e.message }));
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
server.addEventListener('close', () => {
|
|
668
|
+
this.screencastClients.delete(server);
|
|
669
|
+
// Stop screencast if no more clients
|
|
670
|
+
if (this.screencastClients.size === 0) {
|
|
671
|
+
this.stopScreencast().catch(() => { });
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
return new Response(null, {
|
|
675
|
+
status: 101,
|
|
676
|
+
webSocket: client,
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
680
|
+
// STATE OPERATIONS
|
|
681
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
682
|
+
/**
|
|
683
|
+
* Get the current URL from the browser session
|
|
684
|
+
*/
|
|
685
|
+
async getCurrentUrl() {
|
|
686
|
+
// This would typically get the URL from the page
|
|
687
|
+
// For now, return undefined if not implemented
|
|
688
|
+
return undefined;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Get the current browser state
|
|
692
|
+
*
|
|
693
|
+
* @returns BrowserState with status, provider, URLs
|
|
694
|
+
*/
|
|
695
|
+
async getState() {
|
|
696
|
+
const status = this.session ? 'active' : 'stopped';
|
|
697
|
+
const provider = this.config?.provider;
|
|
698
|
+
const currentUrl = await this.getCurrentUrl();
|
|
699
|
+
const liveViewUrl = this.session?.liveViewUrl;
|
|
700
|
+
return {
|
|
701
|
+
status,
|
|
702
|
+
provider,
|
|
703
|
+
currentUrl,
|
|
704
|
+
liveViewUrl,
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
708
|
+
// BROWSER ACTION LOGGING
|
|
709
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
710
|
+
/**
|
|
711
|
+
* Log a browser action
|
|
712
|
+
* Helper method that wraps parent logAction with 'do' durability
|
|
713
|
+
*/
|
|
714
|
+
async logBrowserAction(verb, data) {
|
|
715
|
+
// Call parent logAction with 'do' durability
|
|
716
|
+
return super.logAction('do', verb, data);
|
|
717
|
+
}
|
|
718
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
719
|
+
// LIFECYCLE METHODS
|
|
720
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
721
|
+
/**
|
|
722
|
+
* Start a new browser session
|
|
723
|
+
*
|
|
724
|
+
* @param options - Session configuration options
|
|
725
|
+
* @returns Session info including sessionId and optional liveViewUrl
|
|
726
|
+
* @throws If session already active or provider is invalid
|
|
727
|
+
*
|
|
728
|
+
* @example
|
|
729
|
+
* ```typescript
|
|
730
|
+
* // Start with Cloudflare (default)
|
|
731
|
+
* const result = await browser.start()
|
|
732
|
+
*
|
|
733
|
+
* // Start with Browserbase and live view
|
|
734
|
+
* const result = await browser.start({
|
|
735
|
+
* provider: 'browserbase',
|
|
736
|
+
* liveView: true,
|
|
737
|
+
* })
|
|
738
|
+
* ```
|
|
739
|
+
*/
|
|
740
|
+
async start(options = {}) {
|
|
741
|
+
const provider = options.provider ?? 'cloudflare';
|
|
742
|
+
const liveView = options.liveView ?? false;
|
|
743
|
+
// Validate provider
|
|
744
|
+
if (provider !== 'cloudflare' && provider !== 'browserbase') {
|
|
745
|
+
throw new Error(`Invalid provider: ${provider}`);
|
|
746
|
+
}
|
|
747
|
+
// Check if session already exists
|
|
748
|
+
if (this.session) {
|
|
749
|
+
throw new Error('Browser session already active');
|
|
750
|
+
}
|
|
751
|
+
// Prepare Browse.init config based on provider
|
|
752
|
+
const browseConfig = {
|
|
753
|
+
provider,
|
|
754
|
+
liveView,
|
|
755
|
+
env: provider === 'cloudflare'
|
|
756
|
+
? { BROWSER: this.env.BROWSER }
|
|
757
|
+
: {
|
|
758
|
+
BROWSERBASE_API_KEY: this.env.BROWSERBASE_API_KEY,
|
|
759
|
+
BROWSERBASE_PROJECT_ID: this.env.BROWSERBASE_PROJECT_ID,
|
|
760
|
+
},
|
|
761
|
+
};
|
|
762
|
+
if (options.viewport) {
|
|
763
|
+
browseConfig.viewport = options.viewport;
|
|
764
|
+
}
|
|
765
|
+
if (options.stealth) {
|
|
766
|
+
browseConfig.stealth = options.stealth;
|
|
767
|
+
}
|
|
768
|
+
// Initialize session via Browse.init()
|
|
769
|
+
this.session = await Browse.init(browseConfig);
|
|
770
|
+
// Generate session ID
|
|
771
|
+
const sessionId = crypto.randomUUID();
|
|
772
|
+
// Store config
|
|
773
|
+
this.storedConfig = {
|
|
774
|
+
provider,
|
|
775
|
+
liveView,
|
|
776
|
+
viewport: options.viewport,
|
|
777
|
+
stealth: options.stealth,
|
|
778
|
+
sessionId,
|
|
779
|
+
};
|
|
780
|
+
// Also set legacy config for compatibility
|
|
781
|
+
this.config = {
|
|
782
|
+
provider,
|
|
783
|
+
liveView,
|
|
784
|
+
viewport: options.viewport,
|
|
785
|
+
stealth: options.stealth,
|
|
786
|
+
};
|
|
787
|
+
await this.ctx.storage.put('browser:config', this.storedConfig);
|
|
788
|
+
// Update last activity
|
|
789
|
+
this.lastActivity = Date.now();
|
|
790
|
+
await this.ctx.storage.put('browser:lastActivity', this.lastActivity);
|
|
791
|
+
// Set alarm for keepAlive check (every minute)
|
|
792
|
+
const nextAlarm = Date.now() + 60_000;
|
|
793
|
+
await this.ctx.storage.setAlarm(nextAlarm);
|
|
794
|
+
// Emit 'browser.started' event
|
|
795
|
+
await this.emitEvent('browser.started', {
|
|
796
|
+
sessionId,
|
|
797
|
+
provider,
|
|
798
|
+
liveView,
|
|
799
|
+
liveViewUrl: this.session.liveViewUrl,
|
|
800
|
+
});
|
|
801
|
+
return {
|
|
802
|
+
sessionId,
|
|
803
|
+
provider,
|
|
804
|
+
liveViewUrl: this.session.liveViewUrl,
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Stop the browser session
|
|
809
|
+
*
|
|
810
|
+
* @throws If no active session
|
|
811
|
+
*
|
|
812
|
+
* @example
|
|
813
|
+
* ```typescript
|
|
814
|
+
* await browser.stop()
|
|
815
|
+
* ```
|
|
816
|
+
*/
|
|
817
|
+
async stop() {
|
|
818
|
+
if (!this.session) {
|
|
819
|
+
throw new Error('No active browser session');
|
|
820
|
+
}
|
|
821
|
+
// Get session ID before clearing
|
|
822
|
+
const sessionId = this.storedConfig?.sessionId;
|
|
823
|
+
// Stop screencast and cleanup CDP session
|
|
824
|
+
if (this.cdpSession) {
|
|
825
|
+
await this.stopScreencast().catch(() => { });
|
|
826
|
+
this.cdpSession = null;
|
|
827
|
+
}
|
|
828
|
+
// Close all screencast WebSocket clients
|
|
829
|
+
for (const client of this.screencastClients) {
|
|
830
|
+
try {
|
|
831
|
+
client.close();
|
|
832
|
+
}
|
|
833
|
+
catch {
|
|
834
|
+
// Ignore close errors
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
this.screencastClients.clear();
|
|
838
|
+
// Close session
|
|
839
|
+
await this.session.close();
|
|
840
|
+
// Clear alarm
|
|
841
|
+
await this.ctx.storage.deleteAlarm();
|
|
842
|
+
// Clear state
|
|
843
|
+
this.session = null;
|
|
844
|
+
this.storedConfig = null;
|
|
845
|
+
this.config = null;
|
|
846
|
+
this.lastActivity = 0;
|
|
847
|
+
// Clear stored config
|
|
848
|
+
await this.ctx.storage.delete('browser:config');
|
|
849
|
+
await this.ctx.storage.delete('browser:lastActivity');
|
|
850
|
+
// Emit 'browser.stopped' event
|
|
851
|
+
await this.emitEvent('browser.stopped', { sessionId });
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Alarm handler for session keepAlive and timeout
|
|
855
|
+
*
|
|
856
|
+
* Called periodically to check if the session should be kept alive
|
|
857
|
+
* or closed due to inactivity.
|
|
858
|
+
*/
|
|
859
|
+
async alarm() {
|
|
860
|
+
if (!this.session) {
|
|
861
|
+
// No session, nothing to do
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
const now = Date.now();
|
|
865
|
+
const storedLastActivity = await this.ctx.storage.get('browser:lastActivity');
|
|
866
|
+
const lastActivity = storedLastActivity ?? this.lastActivity;
|
|
867
|
+
// Check if session has been inactive too long
|
|
868
|
+
if (now - lastActivity > this.SESSION_TIMEOUT) {
|
|
869
|
+
// Session timed out - close it
|
|
870
|
+
await this.emitEvent('browser.timeout', {
|
|
871
|
+
sessionId: this.storedConfig?.sessionId,
|
|
872
|
+
inactiveMs: now - lastActivity,
|
|
873
|
+
});
|
|
874
|
+
await this.stop();
|
|
875
|
+
}
|
|
876
|
+
else {
|
|
877
|
+
// Session still active - reset alarm
|
|
878
|
+
const nextAlarm = now + 60_000; // Check again in 1 minute
|
|
879
|
+
await this.ctx.storage.setAlarm(nextAlarm);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
export default Browser;
|
|
884
|
+
//# sourceMappingURL=Browser.js.map
|