dotdo 0.0.1 → 0.1.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.
- package/LICENSE +1 -1
- package/README.md +446 -315
- package/cli/README.md +238 -0
- package/cli/agent.ts +72 -0
- package/cli/bin.js +44 -0
- package/cli/bin.ts +38 -0
- package/cli/build.ts +157 -0
- package/cli/commands/auth/login.ts +14 -0
- package/cli/commands/auth/logout.ts +6 -0
- package/cli/commands/auth/whoami.ts +16 -0
- package/cli/commands/deploy-multi.ts +245 -0
- package/cli/commands/dev/deploy.ts +100 -0
- package/cli/commands/dev/dev.ts +95 -0
- package/cli/commands/dev/logs.ts +91 -0
- package/cli/commands/dev-local.ts +88 -0
- package/cli/commands/do-ops.ts +314 -0
- package/cli/commands/index.ts +100 -0
- package/cli/commands/init.ts +247 -0
- package/cli/commands/introspect/emitter.ts +315 -0
- package/cli/commands/introspect/index.ts +193 -0
- package/cli/commands/link.ts +598 -0
- package/cli/commands/snippets.ts +415 -0
- package/cli/commands/tunnel.ts +239 -0
- package/cli/device-auth.ts +289 -0
- package/cli/fallback.ts +12 -0
- package/cli/index.ts +121 -0
- package/cli/main.ts +246 -0
- package/cli/mcp-stdio.ts +790 -0
- package/cli/package.json +62 -0
- package/cli/runtime/do-registry.ts +193 -0
- package/cli/runtime/embedded-db.ts +344 -0
- package/cli/runtime/index.ts +9 -0
- package/cli/runtime/miniflare-adapter.ts +162 -0
- package/cli/sandbox.ts +82 -0
- package/cli/src/args.ts +174 -0
- package/cli/src/auth.ts +55 -0
- package/cli/src/commands/call.ts +84 -0
- package/cli/src/commands/charge.ts +96 -0
- package/cli/src/commands/config.ts +115 -0
- package/cli/src/commands/email.ts +112 -0
- package/cli/src/commands/llm.ts +115 -0
- package/cli/src/commands/queue.ts +134 -0
- package/cli/src/commands/text.ts +86 -0
- package/cli/src/config.ts +185 -0
- package/cli/src/output.ts +246 -0
- package/cli/src/rpc.ts +192 -0
- package/cli/utils/config.ts +282 -0
- package/cli/utils/detect.ts +73 -0
- package/cli/utils/index.ts +15 -0
- package/cli/utils/logger.ts +232 -0
- 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/middleware/auth-federation.js +573 -0
- package/dist/api/middleware/auth-federation.js.map +1 -0
- package/dist/api/middleware/auth.js +545 -0
- package/dist/api/middleware/auth.js.map +1 -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 +116 -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/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/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 +753 -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 +1006 -0
- package/dist/lib/mixins/git.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 +1190 -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/DOCache.js +153 -0
- package/dist/objects/DOCache.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 +650 -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 +691 -0
- package/dist/objects/transport/mcp-server.js.map +1 -0
- package/dist/objects/transport/rest-autowire.js +1508 -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 +1539 -0
- package/dist/objects/transport/rpc-server.js.map +1 -0
- package/dist/objects/transport/shared.js +576 -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/sandbox/index.js +258 -0
- package/dist/sandbox/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 +1149 -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 +146 -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 +294 -46
|
@@ -0,0 +1,904 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeFunctionExecutor
|
|
3
|
+
*
|
|
4
|
+
* Executes TypeScript/JavaScript handlers in a controlled environment with:
|
|
5
|
+
* - Context injection (env, state, services, logging, events)
|
|
6
|
+
* - Sandboxed execution (restricted globals)
|
|
7
|
+
* - Timeout handling and cancellation
|
|
8
|
+
* - Retry logic with configurable backoff strategies
|
|
9
|
+
* - Streaming output support
|
|
10
|
+
* - Resource limits (memory, CPU time, output size)
|
|
11
|
+
*/
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// ERROR CLASSES
|
|
14
|
+
// ============================================================================
|
|
15
|
+
export class ExecutionTimeoutError extends Error {
|
|
16
|
+
constructor(message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = 'ExecutionTimeoutError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class ExecutionSandboxError extends Error {
|
|
22
|
+
constructor(message) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = 'ExecutionSandboxError';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export class ExecutionResourceError extends Error {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = 'ExecutionResourceError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export class ExecutionRetryExhaustedError extends Error {
|
|
34
|
+
constructor(message) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = 'ExecutionRetryExhaustedError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export class ExecutionCancelledError extends Error {
|
|
40
|
+
constructor(message) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = 'ExecutionCancelledError';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export class ExecutionValidationError extends Error {
|
|
46
|
+
constructor(message) {
|
|
47
|
+
super(message);
|
|
48
|
+
this.name = 'ExecutionValidationError';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// STREAMING ASYNC ITERATOR
|
|
53
|
+
// ============================================================================
|
|
54
|
+
class ExecutionStream {
|
|
55
|
+
chunks = [];
|
|
56
|
+
resolvers = [];
|
|
57
|
+
done = false;
|
|
58
|
+
cancelled = false;
|
|
59
|
+
cancelCallback;
|
|
60
|
+
_result = null;
|
|
61
|
+
resultPushedToIteration = false;
|
|
62
|
+
push(chunk) {
|
|
63
|
+
if (this.cancelled || this.done)
|
|
64
|
+
return;
|
|
65
|
+
// Store result for later access via .result property
|
|
66
|
+
if (chunk.type === 'result') {
|
|
67
|
+
this._result = chunk;
|
|
68
|
+
}
|
|
69
|
+
// Push all chunks to iteration (both data and result)
|
|
70
|
+
if (this.resolvers.length > 0) {
|
|
71
|
+
const resolver = this.resolvers.shift();
|
|
72
|
+
resolver({ value: chunk, done: false });
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
this.chunks.push(chunk);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
finish() {
|
|
79
|
+
this.done = true;
|
|
80
|
+
// Don't push result to waiters - just signal done
|
|
81
|
+
while (this.resolvers.length > 0) {
|
|
82
|
+
const resolver = this.resolvers.shift();
|
|
83
|
+
resolver({ value: undefined, done: true });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
cancel() {
|
|
87
|
+
this.cancelled = true;
|
|
88
|
+
this.cancelCallback?.();
|
|
89
|
+
this.finish();
|
|
90
|
+
}
|
|
91
|
+
setCancelCallback(cb) {
|
|
92
|
+
this.cancelCallback = cb;
|
|
93
|
+
}
|
|
94
|
+
[Symbol.asyncIterator]() {
|
|
95
|
+
return {
|
|
96
|
+
next: () => {
|
|
97
|
+
if (this.cancelled) {
|
|
98
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
99
|
+
}
|
|
100
|
+
if (this.chunks.length > 0) {
|
|
101
|
+
return Promise.resolve({ value: this.chunks.shift(), done: false });
|
|
102
|
+
}
|
|
103
|
+
if (this.done) {
|
|
104
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
105
|
+
}
|
|
106
|
+
return new Promise((resolve) => {
|
|
107
|
+
this.resolvers.push(resolve);
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async toArray() {
|
|
113
|
+
const result = [];
|
|
114
|
+
for await (const chunk of this) {
|
|
115
|
+
result.push(chunk);
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get the final result after streaming is complete
|
|
121
|
+
*/
|
|
122
|
+
get result() {
|
|
123
|
+
return this._result;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// ============================================================================
|
|
127
|
+
// JSON SCHEMA VALIDATION
|
|
128
|
+
// ============================================================================
|
|
129
|
+
function validateJsonSchema(data, schema) {
|
|
130
|
+
if (!schema.type)
|
|
131
|
+
return true;
|
|
132
|
+
switch (schema.type) {
|
|
133
|
+
case 'object': {
|
|
134
|
+
if (typeof data !== 'object' || data === null || Array.isArray(data)) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
const obj = data;
|
|
138
|
+
// Check required fields
|
|
139
|
+
if (schema.required) {
|
|
140
|
+
for (const field of schema.required) {
|
|
141
|
+
if (!(field in obj)) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Check property types
|
|
147
|
+
if (schema.properties) {
|
|
148
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
149
|
+
if (key in obj && !validateJsonSchema(obj[key], propSchema)) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
case 'array':
|
|
157
|
+
if (!Array.isArray(data))
|
|
158
|
+
return false;
|
|
159
|
+
if (schema.items) {
|
|
160
|
+
return data.every((item) => validateJsonSchema(item, schema.items));
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
case 'string':
|
|
164
|
+
return typeof data === 'string';
|
|
165
|
+
case 'number':
|
|
166
|
+
return typeof data === 'number';
|
|
167
|
+
case 'integer':
|
|
168
|
+
return typeof data === 'number' && Number.isInteger(data);
|
|
169
|
+
case 'boolean':
|
|
170
|
+
return typeof data === 'boolean';
|
|
171
|
+
case 'null':
|
|
172
|
+
return data === null;
|
|
173
|
+
default:
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// ============================================================================
|
|
178
|
+
// SANDBOX UTILITIES
|
|
179
|
+
// ============================================================================
|
|
180
|
+
const RESTRICTED_GLOBALS = new Set([
|
|
181
|
+
'require',
|
|
182
|
+
'process',
|
|
183
|
+
'global',
|
|
184
|
+
'globalThis',
|
|
185
|
+
'eval',
|
|
186
|
+
'Function',
|
|
187
|
+
]);
|
|
188
|
+
const ALLOWED_GLOBALS = new Set([
|
|
189
|
+
'console',
|
|
190
|
+
'JSON',
|
|
191
|
+
'Math',
|
|
192
|
+
'Date',
|
|
193
|
+
'Array',
|
|
194
|
+
'Object',
|
|
195
|
+
'String',
|
|
196
|
+
'Number',
|
|
197
|
+
'Boolean',
|
|
198
|
+
'Promise',
|
|
199
|
+
'Set',
|
|
200
|
+
'Map',
|
|
201
|
+
'WeakSet',
|
|
202
|
+
'WeakMap',
|
|
203
|
+
'Symbol',
|
|
204
|
+
'Proxy',
|
|
205
|
+
'Reflect',
|
|
206
|
+
'Error',
|
|
207
|
+
'TypeError',
|
|
208
|
+
'RangeError',
|
|
209
|
+
'SyntaxError',
|
|
210
|
+
'ReferenceError',
|
|
211
|
+
'RegExp',
|
|
212
|
+
'parseInt',
|
|
213
|
+
'parseFloat',
|
|
214
|
+
'isNaN',
|
|
215
|
+
'isFinite',
|
|
216
|
+
'encodeURI',
|
|
217
|
+
'decodeURI',
|
|
218
|
+
'encodeURIComponent',
|
|
219
|
+
'decodeURIComponent',
|
|
220
|
+
'Uint8Array',
|
|
221
|
+
'Int8Array',
|
|
222
|
+
'Uint16Array',
|
|
223
|
+
'Int16Array',
|
|
224
|
+
'Uint32Array',
|
|
225
|
+
'Int32Array',
|
|
226
|
+
'Float32Array',
|
|
227
|
+
'Float64Array',
|
|
228
|
+
'ArrayBuffer',
|
|
229
|
+
'DataView',
|
|
230
|
+
'TextEncoder',
|
|
231
|
+
'TextDecoder',
|
|
232
|
+
'URL',
|
|
233
|
+
'URLSearchParams',
|
|
234
|
+
'Response',
|
|
235
|
+
'Request',
|
|
236
|
+
'Headers',
|
|
237
|
+
'fetch',
|
|
238
|
+
'setTimeout',
|
|
239
|
+
'clearTimeout',
|
|
240
|
+
'setInterval',
|
|
241
|
+
'clearInterval',
|
|
242
|
+
'queueMicrotask',
|
|
243
|
+
'atob',
|
|
244
|
+
'btoa',
|
|
245
|
+
'crypto',
|
|
246
|
+
'AbortController',
|
|
247
|
+
'AbortSignal',
|
|
248
|
+
]);
|
|
249
|
+
function createSandboxedConsole(logger) {
|
|
250
|
+
return {
|
|
251
|
+
log: (...args) => logger.info(args.map(String).join(' ')),
|
|
252
|
+
info: (...args) => logger.info(args.map(String).join(' ')),
|
|
253
|
+
warn: (...args) => logger.warn(args.map(String).join(' ')),
|
|
254
|
+
error: (...args) => logger.error(args.map(String).join(' ')),
|
|
255
|
+
debug: (...args) => logger.debug(args.map(String).join(' ')),
|
|
256
|
+
// Minimal console implementation
|
|
257
|
+
assert: () => { },
|
|
258
|
+
clear: () => { },
|
|
259
|
+
count: () => { },
|
|
260
|
+
countReset: () => { },
|
|
261
|
+
dir: () => { },
|
|
262
|
+
dirxml: () => { },
|
|
263
|
+
group: () => { },
|
|
264
|
+
groupCollapsed: () => { },
|
|
265
|
+
groupEnd: () => { },
|
|
266
|
+
table: () => { },
|
|
267
|
+
time: () => { },
|
|
268
|
+
timeEnd: () => { },
|
|
269
|
+
timeLog: () => { },
|
|
270
|
+
trace: () => { },
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
// ============================================================================
|
|
274
|
+
// BACKOFF STRATEGIES
|
|
275
|
+
// ============================================================================
|
|
276
|
+
function calculateDelay(attempt, config) {
|
|
277
|
+
let delay;
|
|
278
|
+
switch (config.backoff) {
|
|
279
|
+
case 'exponential':
|
|
280
|
+
delay = config.delay * Math.pow(2, attempt);
|
|
281
|
+
break;
|
|
282
|
+
case 'exponential-jitter': {
|
|
283
|
+
const baseDelay = config.delay * Math.pow(2, attempt);
|
|
284
|
+
// Add random jitter of 0-100% of base delay
|
|
285
|
+
delay = baseDelay * (0.5 + Math.random());
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
case 'linear':
|
|
289
|
+
delay = config.delay + (config.increment || 0) * attempt;
|
|
290
|
+
break;
|
|
291
|
+
case 'fixed':
|
|
292
|
+
default:
|
|
293
|
+
delay = config.delay;
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
// Apply max delay cap
|
|
297
|
+
if (config.maxDelay !== undefined && delay > config.maxDelay) {
|
|
298
|
+
delay = config.maxDelay;
|
|
299
|
+
}
|
|
300
|
+
return delay;
|
|
301
|
+
}
|
|
302
|
+
// ============================================================================
|
|
303
|
+
// RESOURCE MEASUREMENT
|
|
304
|
+
// ============================================================================
|
|
305
|
+
function measureOutputSize(output) {
|
|
306
|
+
try {
|
|
307
|
+
return JSON.stringify(output).length;
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
return 0;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// ============================================================================
|
|
314
|
+
// CODE FUNCTION EXECUTOR
|
|
315
|
+
// ============================================================================
|
|
316
|
+
export class CodeFunctionExecutor {
|
|
317
|
+
state;
|
|
318
|
+
env;
|
|
319
|
+
services;
|
|
320
|
+
logger;
|
|
321
|
+
onEvent;
|
|
322
|
+
// Default timeout is 30 seconds
|
|
323
|
+
static DEFAULT_TIMEOUT = 30000;
|
|
324
|
+
// Default memory limit is 128MB
|
|
325
|
+
static DEFAULT_MEMORY_LIMIT = 128 * 1024 * 1024;
|
|
326
|
+
// Default output size limit is 10MB
|
|
327
|
+
static DEFAULT_OUTPUT_SIZE_LIMIT = 10 * 1024 * 1024;
|
|
328
|
+
constructor(options) {
|
|
329
|
+
this.state = options.state;
|
|
330
|
+
this.env = options.env;
|
|
331
|
+
this.services = options.services;
|
|
332
|
+
this.logger = options.logger || {
|
|
333
|
+
debug: () => { },
|
|
334
|
+
info: () => { },
|
|
335
|
+
warn: () => { },
|
|
336
|
+
error: () => { },
|
|
337
|
+
};
|
|
338
|
+
this.onEvent = options.onEvent;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Execute a handler function with full context and options
|
|
342
|
+
*/
|
|
343
|
+
async execute(handler, input, options = {}) {
|
|
344
|
+
const startTime = Date.now();
|
|
345
|
+
const invocationId = crypto.randomUUID();
|
|
346
|
+
const functionId = options.functionId || 'anonymous';
|
|
347
|
+
let retryCount = 0;
|
|
348
|
+
let streamSequence = 0;
|
|
349
|
+
// Check if signal is already aborted
|
|
350
|
+
if (options.signal?.aborted) {
|
|
351
|
+
return {
|
|
352
|
+
success: false,
|
|
353
|
+
error: new ExecutionCancelledError(options.signal.reason ? String(options.signal.reason) : 'Execution cancelled'),
|
|
354
|
+
duration: 0,
|
|
355
|
+
retryCount: 0,
|
|
356
|
+
metrics: {},
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
// Validate input if schema provided
|
|
360
|
+
if (options.inputSchema && !validateJsonSchema(input, options.inputSchema)) {
|
|
361
|
+
return {
|
|
362
|
+
success: false,
|
|
363
|
+
error: new ExecutionValidationError('Invalid input: validation failed'),
|
|
364
|
+
duration: Date.now() - startTime,
|
|
365
|
+
retryCount: 0,
|
|
366
|
+
metrics: {},
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
const timeout = options.timeout ?? CodeFunctionExecutor.DEFAULT_TIMEOUT;
|
|
370
|
+
// Emit stream.start if streaming mode
|
|
371
|
+
if (options.streaming) {
|
|
372
|
+
await this.onEvent?.('stream.start', { invocationId });
|
|
373
|
+
}
|
|
374
|
+
const maxAttempts = options.retry?.maxAttempts || 1;
|
|
375
|
+
let lastError = null;
|
|
376
|
+
let cpuTimeStart = Date.now();
|
|
377
|
+
let attemptNumber = 0;
|
|
378
|
+
let currentTimeoutController = null;
|
|
379
|
+
while (attemptNumber < maxAttempts) {
|
|
380
|
+
attemptNumber++;
|
|
381
|
+
const attemptStart = Date.now();
|
|
382
|
+
cpuTimeStart = attemptStart;
|
|
383
|
+
// Create fresh abort controller for each attempt
|
|
384
|
+
const timeoutController = new AbortController();
|
|
385
|
+
currentTimeoutController = timeoutController;
|
|
386
|
+
// Link external signal to our controller
|
|
387
|
+
if (options.signal) {
|
|
388
|
+
if (options.signal.aborted) {
|
|
389
|
+
// External signal was aborted between retries
|
|
390
|
+
return {
|
|
391
|
+
success: false,
|
|
392
|
+
error: new ExecutionCancelledError(options.signal.reason ? String(options.signal.reason) : 'Execution cancelled'),
|
|
393
|
+
duration: Date.now() - startTime,
|
|
394
|
+
retryCount: attemptNumber - 1,
|
|
395
|
+
metrics: {},
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
options.signal.addEventListener('abort', () => {
|
|
399
|
+
timeoutController.abort(options.signal.reason || 'Execution cancelled');
|
|
400
|
+
}, { once: true });
|
|
401
|
+
}
|
|
402
|
+
// Set up timeout (if not 0)
|
|
403
|
+
let timeoutId;
|
|
404
|
+
if (timeout > 0) {
|
|
405
|
+
timeoutId = setTimeout(() => {
|
|
406
|
+
timeoutController.abort(`Execution timeout after ${timeout}ms`);
|
|
407
|
+
}, timeout);
|
|
408
|
+
}
|
|
409
|
+
// Build context with fresh signal
|
|
410
|
+
const context = this.createContext(functionId, invocationId, options, timeoutController.signal, () => streamSequence++);
|
|
411
|
+
try {
|
|
412
|
+
let result;
|
|
413
|
+
let cpuTimeFromExec = 0;
|
|
414
|
+
if (options.sandboxed !== false) {
|
|
415
|
+
const execResult = await this.executeInSandbox(handler, input, context, options, timeoutController.signal);
|
|
416
|
+
result = execResult.result;
|
|
417
|
+
cpuTimeFromExec = execResult.cpuTime;
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
const execResult = await this.executeUnsandboxed(handler, input, context, timeoutController.signal);
|
|
421
|
+
result = execResult.result;
|
|
422
|
+
cpuTimeFromExec = execResult.cpuTime;
|
|
423
|
+
}
|
|
424
|
+
// Clear timeout on success
|
|
425
|
+
if (timeoutId)
|
|
426
|
+
clearTimeout(timeoutId);
|
|
427
|
+
// Validate output if schema provided
|
|
428
|
+
if (options.outputSchema && !validateJsonSchema(result, options.outputSchema)) {
|
|
429
|
+
throw new ExecutionValidationError('Invalid output: validation failed');
|
|
430
|
+
}
|
|
431
|
+
// Check output size
|
|
432
|
+
const outputSize = measureOutputSize(result);
|
|
433
|
+
const maxOutputSize = options.resourceLimits?.maxOutputSize ||
|
|
434
|
+
CodeFunctionExecutor.DEFAULT_OUTPUT_SIZE_LIMIT;
|
|
435
|
+
if (outputSize > maxOutputSize) {
|
|
436
|
+
throw new ExecutionResourceError(`Output size ${outputSize} exceeded limit ${maxOutputSize}`);
|
|
437
|
+
}
|
|
438
|
+
// Emit stream.end if streaming mode
|
|
439
|
+
if (options.streaming) {
|
|
440
|
+
await this.onEvent?.('stream.end', {
|
|
441
|
+
invocationId,
|
|
442
|
+
totalChunks: streamSequence,
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
// retryCount is number of retries (attempts - 1, but 0 if no retries occurred)
|
|
446
|
+
retryCount = attemptNumber > 1 ? attemptNumber - 1 : 0;
|
|
447
|
+
return {
|
|
448
|
+
success: true,
|
|
449
|
+
result,
|
|
450
|
+
duration: Date.now() - startTime,
|
|
451
|
+
retryCount,
|
|
452
|
+
metrics: {
|
|
453
|
+
memoryUsed: this.estimateMemoryUsage(),
|
|
454
|
+
cpuTime: Math.round(cpuTimeFromExec),
|
|
455
|
+
},
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
catch (error) {
|
|
459
|
+
// Clear timeout on error before processing
|
|
460
|
+
if (timeoutId)
|
|
461
|
+
clearTimeout(timeoutId);
|
|
462
|
+
lastError = this.normalizeError(error);
|
|
463
|
+
// If signal was aborted and error is not already ExecutionCancelledError/ExecutionTimeoutError,
|
|
464
|
+
// convert it to appropriate error type
|
|
465
|
+
if (timeoutController.signal.aborted) {
|
|
466
|
+
if (!(lastError instanceof ExecutionCancelledError) && !(lastError instanceof ExecutionTimeoutError)) {
|
|
467
|
+
const rawReason = timeoutController.signal.reason;
|
|
468
|
+
const reason = typeof rawReason === 'string' ? rawReason : String(rawReason || 'Execution cancelled');
|
|
469
|
+
if (reason.includes('timeout')) {
|
|
470
|
+
lastError = new ExecutionTimeoutError(reason);
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
lastError = new ExecutionCancelledError(reason);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
// Check if we should retry (attemptNumber is 1-indexed, so compare with maxAttempts)
|
|
478
|
+
const shouldRetry = this.shouldRetry(lastError, attemptNumber - 1, maxAttempts, options);
|
|
479
|
+
if (shouldRetry && attemptNumber < maxAttempts) {
|
|
480
|
+
// Calculate delay for retry (attempt 1 failed -> retry 1 uses delay index 0)
|
|
481
|
+
const delayIndex = attemptNumber - 1;
|
|
482
|
+
const delay = calculateDelay(delayIndex, options.retry);
|
|
483
|
+
// Emit retry event (attempt is the retry number, 1-indexed)
|
|
484
|
+
await this.onEvent?.('function.retry', {
|
|
485
|
+
attempt: attemptNumber,
|
|
486
|
+
error: lastError.message,
|
|
487
|
+
delay,
|
|
488
|
+
});
|
|
489
|
+
// Call onRetry callback
|
|
490
|
+
options.retry?.onRetry?.({
|
|
491
|
+
attempt: attemptNumber,
|
|
492
|
+
delay,
|
|
493
|
+
error: lastError,
|
|
494
|
+
});
|
|
495
|
+
// Wait before retry
|
|
496
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
break;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
// Set retryCount: 0 if no retry config, otherwise total attempts - 1 (since first isn't a retry)
|
|
503
|
+
// But if we failed on first attempt with retries configured, retryCount = attempts made
|
|
504
|
+
if (!options.retry) {
|
|
505
|
+
retryCount = 0;
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
retryCount = attemptNumber;
|
|
509
|
+
}
|
|
510
|
+
// Wrap error if retries exhausted (all maxAttempts were used)
|
|
511
|
+
if (options.retry && attemptNumber >= maxAttempts && maxAttempts > 1) {
|
|
512
|
+
lastError = new ExecutionRetryExhaustedError(`All ${maxAttempts} retry attempts exhausted. Last error: ${lastError?.message}`);
|
|
513
|
+
}
|
|
514
|
+
// Emit error event
|
|
515
|
+
await this.onEvent?.('function.error', {
|
|
516
|
+
functionId,
|
|
517
|
+
invocationId,
|
|
518
|
+
error: lastError?.message || 'Unknown error',
|
|
519
|
+
input,
|
|
520
|
+
});
|
|
521
|
+
const cpuTime = Date.now() - cpuTimeStart;
|
|
522
|
+
return {
|
|
523
|
+
success: false,
|
|
524
|
+
error: lastError || new Error('Unknown error'),
|
|
525
|
+
duration: Date.now() - startTime,
|
|
526
|
+
retryCount,
|
|
527
|
+
metrics: {
|
|
528
|
+
memoryUsed: this.estimateMemoryUsage(),
|
|
529
|
+
cpuTime,
|
|
530
|
+
},
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Execute a handler and return a streaming async iterator
|
|
535
|
+
*/
|
|
536
|
+
async executeStreaming(handler, input, options = {}) {
|
|
537
|
+
const stream = new ExecutionStream();
|
|
538
|
+
let streamSequence = 0;
|
|
539
|
+
// Create execution context with streaming emit
|
|
540
|
+
const invocationId = crypto.randomUUID();
|
|
541
|
+
const functionId = options.functionId || 'anonymous';
|
|
542
|
+
const timeoutController = new AbortController();
|
|
543
|
+
// Set up cancel callback
|
|
544
|
+
stream.setCancelCallback(() => {
|
|
545
|
+
timeoutController.abort('Stream cancelled');
|
|
546
|
+
});
|
|
547
|
+
const context = this.createContext(functionId, invocationId, { ...options, streaming: true }, timeoutController.signal, () => streamSequence++, (event, data) => {
|
|
548
|
+
if (event === 'stream.chunk') {
|
|
549
|
+
stream.push({
|
|
550
|
+
type: 'chunk',
|
|
551
|
+
data: data.data,
|
|
552
|
+
sequence: data.sequence,
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
(async () => {
|
|
557
|
+
try {
|
|
558
|
+
const execResult = await this.executeInSandbox(handler, input, context, options, timeoutController.signal);
|
|
559
|
+
stream.push({
|
|
560
|
+
type: 'result',
|
|
561
|
+
value: execResult.result,
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
catch (error) {
|
|
565
|
+
// Handle error in stream - just finish
|
|
566
|
+
}
|
|
567
|
+
finally {
|
|
568
|
+
stream.finish();
|
|
569
|
+
}
|
|
570
|
+
})();
|
|
571
|
+
return stream;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Create execution context for handler
|
|
575
|
+
*/
|
|
576
|
+
createContext(functionId, invocationId, options, signal, getSequence, streamEmit) {
|
|
577
|
+
// Filter env vars if exposeEnv is specified
|
|
578
|
+
let exposedEnv;
|
|
579
|
+
if (options.exposeEnv) {
|
|
580
|
+
exposedEnv = {};
|
|
581
|
+
for (const key of options.exposeEnv) {
|
|
582
|
+
if (key in this.env) {
|
|
583
|
+
exposedEnv[key] = this.env[key];
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
exposedEnv = { ...this.env };
|
|
589
|
+
}
|
|
590
|
+
// Make env read-only
|
|
591
|
+
const readOnlyEnv = new Proxy(exposedEnv, {
|
|
592
|
+
set: () => false,
|
|
593
|
+
defineProperty: () => false,
|
|
594
|
+
deleteProperty: () => false,
|
|
595
|
+
});
|
|
596
|
+
// Create state wrapper
|
|
597
|
+
const stateWrapper = {
|
|
598
|
+
get: async (key) => {
|
|
599
|
+
const value = await this.state.storage.get(key);
|
|
600
|
+
return value ?? null;
|
|
601
|
+
},
|
|
602
|
+
put: async (key, value) => {
|
|
603
|
+
await this.state.storage.put(key, value);
|
|
604
|
+
},
|
|
605
|
+
delete: async (key) => {
|
|
606
|
+
return this.state.storage.delete(key);
|
|
607
|
+
},
|
|
608
|
+
list: async (opts) => {
|
|
609
|
+
return this.state.storage.list(opts);
|
|
610
|
+
},
|
|
611
|
+
};
|
|
612
|
+
// Create emit function that handles both events and streaming
|
|
613
|
+
const emit = async (event, data) => {
|
|
614
|
+
// Add sequence number for stream chunks
|
|
615
|
+
if (event === 'stream.chunk') {
|
|
616
|
+
const sequence = getSequence();
|
|
617
|
+
const dataWithSequence = { ...data, sequence };
|
|
618
|
+
streamEmit?.(event, dataWithSequence);
|
|
619
|
+
await this.onEvent?.(event, dataWithSequence);
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
await this.onEvent?.(event, data);
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
return {
|
|
626
|
+
functionId,
|
|
627
|
+
invocationId,
|
|
628
|
+
env: readOnlyEnv,
|
|
629
|
+
state: stateWrapper,
|
|
630
|
+
services: this.services,
|
|
631
|
+
log: {
|
|
632
|
+
debug: (message, data) => {
|
|
633
|
+
if (data !== undefined) {
|
|
634
|
+
this.logger.debug(message, data);
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
this.logger.debug(message);
|
|
638
|
+
}
|
|
639
|
+
},
|
|
640
|
+
info: (message, data) => {
|
|
641
|
+
if (data !== undefined) {
|
|
642
|
+
this.logger.info(message, data);
|
|
643
|
+
}
|
|
644
|
+
else {
|
|
645
|
+
this.logger.info(message);
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
warn: (message, data) => {
|
|
649
|
+
if (data !== undefined) {
|
|
650
|
+
this.logger.warn(message, data);
|
|
651
|
+
}
|
|
652
|
+
else {
|
|
653
|
+
this.logger.warn(message);
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
error: (message, data) => {
|
|
657
|
+
if (data !== undefined) {
|
|
658
|
+
this.logger.error(message, data);
|
|
659
|
+
}
|
|
660
|
+
else {
|
|
661
|
+
this.logger.error(message);
|
|
662
|
+
}
|
|
663
|
+
},
|
|
664
|
+
},
|
|
665
|
+
emit,
|
|
666
|
+
signal,
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Execute handler in sandboxed environment
|
|
671
|
+
*/
|
|
672
|
+
async executeInSandbox(handler, input, context, options, signal) {
|
|
673
|
+
// Check memory limit before execution
|
|
674
|
+
const maxMemory = options.resourceLimits?.maxMemory || CodeFunctionExecutor.DEFAULT_MEMORY_LIMIT;
|
|
675
|
+
// Track CPU time using a timing mechanism
|
|
676
|
+
const maxCpuTime = options.resourceLimits?.maxCpuTime;
|
|
677
|
+
let cpuTimeAccumulated = 0;
|
|
678
|
+
let lastCpuCheckTime = performance.now();
|
|
679
|
+
let cpuCheckInterval;
|
|
680
|
+
let cpuLimitExceeded = false;
|
|
681
|
+
// Function to check and update CPU time
|
|
682
|
+
const checkCpuTime = () => {
|
|
683
|
+
const now = performance.now();
|
|
684
|
+
const elapsed = now - lastCpuCheckTime;
|
|
685
|
+
cpuTimeAccumulated += elapsed;
|
|
686
|
+
lastCpuCheckTime = now;
|
|
687
|
+
if (maxCpuTime && cpuTimeAccumulated > maxCpuTime) {
|
|
688
|
+
cpuLimitExceeded = true;
|
|
689
|
+
throw new ExecutionResourceError(`CPU time ${Math.round(cpuTimeAccumulated)}ms exceeded limit ${maxCpuTime}ms`);
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
if (maxCpuTime) {
|
|
693
|
+
// Check CPU time periodically - for async code this helps track actual execution
|
|
694
|
+
cpuCheckInterval = setInterval(() => {
|
|
695
|
+
try {
|
|
696
|
+
checkCpuTime();
|
|
697
|
+
}
|
|
698
|
+
catch (e) {
|
|
699
|
+
// Error thrown in interval - need to abort
|
|
700
|
+
if (cpuLimitExceeded) {
|
|
701
|
+
// The abort will be handled by the Promise.race
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}, 5);
|
|
705
|
+
}
|
|
706
|
+
// Store CPU time in context for retrieval
|
|
707
|
+
;
|
|
708
|
+
context._cpuTimeStart = performance.now();
|
|
709
|
+
try {
|
|
710
|
+
// Convert handler to string to check for sandbox violations
|
|
711
|
+
const handlerSource = handler.toString();
|
|
712
|
+
// Check for restricted access patterns in handler source
|
|
713
|
+
for (const restricted of RESTRICTED_GLOBALS) {
|
|
714
|
+
// Match standalone references (not as object property)
|
|
715
|
+
const pattern = new RegExp(`\\b${restricted}\\b(?!\\s*:)`);
|
|
716
|
+
if (pattern.test(handlerSource)) {
|
|
717
|
+
throw new ExecutionSandboxError(`Access to '${restricted}' is not allowed in sandboxed mode`);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
// Check for prototype pollution attempts
|
|
721
|
+
if (handlerSource.includes('__proto__') ||
|
|
722
|
+
handlerSource.includes('Object.prototype') ||
|
|
723
|
+
/\.\s*prototype\s*\./.test(handlerSource) ||
|
|
724
|
+
/\[\s*['"]prototype['"]\s*\]/.test(handlerSource)) {
|
|
725
|
+
throw new ExecutionSandboxError('Prototype modification is not allowed in sandboxed mode');
|
|
726
|
+
}
|
|
727
|
+
// Replace console with sandboxed version in context
|
|
728
|
+
const sandboxedConsole = createSandboxedConsole(this.logger);
|
|
729
|
+
// Check if signal is already aborted before execution
|
|
730
|
+
if (signal.aborted) {
|
|
731
|
+
const rawReason = signal.reason;
|
|
732
|
+
const reason = typeof rawReason === 'string' ? rawReason : String(rawReason || 'Execution cancelled');
|
|
733
|
+
if (reason.includes('timeout')) {
|
|
734
|
+
throw new ExecutionTimeoutError(reason);
|
|
735
|
+
}
|
|
736
|
+
else {
|
|
737
|
+
throw new ExecutionCancelledError(reason);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
// Track execution start time for CPU time calculation
|
|
741
|
+
const execStartTime = performance.now();
|
|
742
|
+
let syncEndTime = 0;
|
|
743
|
+
// Execute with Promise.race for timeout and cancellation
|
|
744
|
+
const result = await Promise.race([
|
|
745
|
+
(async () => {
|
|
746
|
+
// Intercept console calls by wrapping handler execution
|
|
747
|
+
const originalConsole = globalThis.console;
|
|
748
|
+
try {
|
|
749
|
+
;
|
|
750
|
+
globalThis.console = sandboxedConsole;
|
|
751
|
+
// Call handler and immediately capture sync execution time
|
|
752
|
+
const handlerResult = handler(input, context);
|
|
753
|
+
// If handler returns immediately (sync), syncEndTime captures real CPU time
|
|
754
|
+
// If handler returns a promise, we track time up to the first await
|
|
755
|
+
syncEndTime = performance.now();
|
|
756
|
+
// Await the result (for async handlers, this is where time is spent in awaits)
|
|
757
|
+
const resolved = await Promise.resolve(handlerResult);
|
|
758
|
+
// After execution completes, calculate total elapsed
|
|
759
|
+
const totalElapsed = performance.now() - execStartTime;
|
|
760
|
+
const initialSyncTime = syncEndTime - execStartTime;
|
|
761
|
+
// For CPU time: if totalElapsed >> initialSyncTime, handler was async with waits
|
|
762
|
+
// Use initial sync time as approximation of CPU time
|
|
763
|
+
// Add a small amount for async completion overhead
|
|
764
|
+
const estimatedCpuTime = Math.min(initialSyncTime + 10, totalElapsed);
|
|
765
|
+
// Store for return
|
|
766
|
+
cpuTimeAccumulated = estimatedCpuTime;
|
|
767
|
+
// Check CPU limit using estimated CPU time
|
|
768
|
+
if (maxCpuTime && estimatedCpuTime > maxCpuTime) {
|
|
769
|
+
throw new ExecutionResourceError(`CPU time ${Math.round(estimatedCpuTime)}ms exceeded limit ${maxCpuTime}ms`);
|
|
770
|
+
}
|
|
771
|
+
return resolved;
|
|
772
|
+
}
|
|
773
|
+
finally {
|
|
774
|
+
;
|
|
775
|
+
globalThis.console = originalConsole;
|
|
776
|
+
}
|
|
777
|
+
})(),
|
|
778
|
+
new Promise((_, reject) => {
|
|
779
|
+
const handleAbort = () => {
|
|
780
|
+
const rawReason = signal.reason;
|
|
781
|
+
const reason = typeof rawReason === 'string' ? rawReason : String(rawReason || 'Execution cancelled');
|
|
782
|
+
if (reason.includes('timeout')) {
|
|
783
|
+
reject(new ExecutionTimeoutError(reason));
|
|
784
|
+
}
|
|
785
|
+
else {
|
|
786
|
+
reject(new ExecutionCancelledError(reason));
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
if (signal.aborted) {
|
|
790
|
+
handleAbort();
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
signal.addEventListener('abort', handleAbort);
|
|
794
|
+
}),
|
|
795
|
+
]);
|
|
796
|
+
// Store final CPU time for metrics
|
|
797
|
+
cpuTimeAccumulated = performance.now() - execStartTime;
|
|
798
|
+
// Check memory usage estimate
|
|
799
|
+
const memUsed = this.estimateMemoryUsage();
|
|
800
|
+
if (memUsed > maxMemory) {
|
|
801
|
+
throw new ExecutionResourceError(`Memory usage estimated at ${memUsed} exceeded limit ${maxMemory}`);
|
|
802
|
+
}
|
|
803
|
+
return { result, cpuTime: cpuTimeAccumulated };
|
|
804
|
+
}
|
|
805
|
+
finally {
|
|
806
|
+
if (cpuCheckInterval) {
|
|
807
|
+
clearInterval(cpuCheckInterval);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Execute handler without sandbox restrictions
|
|
813
|
+
*/
|
|
814
|
+
async executeUnsandboxed(handler, input, context, signal) {
|
|
815
|
+
const startTime = performance.now();
|
|
816
|
+
// Call handler and capture sync execution time
|
|
817
|
+
const handlerResult = handler(input, context);
|
|
818
|
+
const syncEndTime = performance.now();
|
|
819
|
+
const result = await Promise.race([
|
|
820
|
+
Promise.resolve(handlerResult),
|
|
821
|
+
new Promise((_, reject) => {
|
|
822
|
+
const handleAbort = () => {
|
|
823
|
+
const rawReason = signal.reason;
|
|
824
|
+
const reason = typeof rawReason === 'string' ? rawReason : String(rawReason || 'Execution cancelled');
|
|
825
|
+
if (reason.includes('timeout')) {
|
|
826
|
+
reject(new ExecutionTimeoutError(reason));
|
|
827
|
+
}
|
|
828
|
+
else {
|
|
829
|
+
reject(new ExecutionCancelledError(reason));
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
if (signal.aborted) {
|
|
833
|
+
handleAbort();
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
signal.addEventListener('abort', handleAbort);
|
|
837
|
+
}),
|
|
838
|
+
]);
|
|
839
|
+
const totalElapsed = performance.now() - startTime;
|
|
840
|
+
const initialSyncTime = syncEndTime - startTime;
|
|
841
|
+
const cpuTime = Math.min(initialSyncTime + 10, totalElapsed);
|
|
842
|
+
return { result, cpuTime };
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Check if we should retry after an error
|
|
846
|
+
*/
|
|
847
|
+
shouldRetry(error, _currentAttemptIndex, _maxAttempts, options) {
|
|
848
|
+
// No retry config = no retries
|
|
849
|
+
if (!options.retry)
|
|
850
|
+
return false;
|
|
851
|
+
// Check if timeout error and retryOnTimeout is false
|
|
852
|
+
if (error instanceof ExecutionTimeoutError) {
|
|
853
|
+
if (options.retry.retryOnTimeout === false)
|
|
854
|
+
return false;
|
|
855
|
+
}
|
|
856
|
+
// Check custom retry condition
|
|
857
|
+
if (options.retry.retryIf) {
|
|
858
|
+
return options.retry.retryIf(error);
|
|
859
|
+
}
|
|
860
|
+
return true;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Normalize error to ensure it has required properties
|
|
864
|
+
*/
|
|
865
|
+
normalizeError(error) {
|
|
866
|
+
if (error instanceof Error) {
|
|
867
|
+
return error;
|
|
868
|
+
}
|
|
869
|
+
if (error === null) {
|
|
870
|
+
return new Error('null error thrown');
|
|
871
|
+
}
|
|
872
|
+
if (error === undefined) {
|
|
873
|
+
return new Error('undefined error thrown');
|
|
874
|
+
}
|
|
875
|
+
if (typeof error === 'object') {
|
|
876
|
+
const obj = error;
|
|
877
|
+
const message = typeof obj.message === 'string'
|
|
878
|
+
? obj.message
|
|
879
|
+
: JSON.stringify(error);
|
|
880
|
+
const err = new Error(message);
|
|
881
|
+
// Copy additional properties
|
|
882
|
+
if (typeof obj.code === 'string') {
|
|
883
|
+
err.code = obj.code;
|
|
884
|
+
}
|
|
885
|
+
return err;
|
|
886
|
+
}
|
|
887
|
+
return new Error(String(error));
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Estimate current memory usage
|
|
891
|
+
*/
|
|
892
|
+
estimateMemoryUsage() {
|
|
893
|
+
// In a real implementation, this would use performance.memory or similar
|
|
894
|
+
// For now, return a rough estimate based on heap info if available
|
|
895
|
+
const perf = globalThis.performance;
|
|
896
|
+
if (perf?.memory) {
|
|
897
|
+
return perf.memory.usedJSHeapSize;
|
|
898
|
+
}
|
|
899
|
+
// Return a nominal value for environments without memory API
|
|
900
|
+
return 1024 * 1024; // 1MB placeholder
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
export default CodeFunctionExecutor;
|
|
904
|
+
//# sourceMappingURL=CodeFunctionExecutor.js.map
|