rivetkit 2.1.5 → 2.1.6-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/client.d.ts +593 -588
- package/dist/browser/client.js +215 -35
- package/dist/browser/client.js.map +1 -1
- package/dist/browser/inspector/client.js +109 -10
- package/dist/browser/inspector/client.js.map +1 -1
- package/dist/inspector.tar.gz +0 -0
- package/dist/tsup/actor/errors.cjs +2 -2
- package/dist/tsup/actor/errors.js +1 -1
- package/dist/tsup/{actor-router-consts-D29T1Z-K.d.cts → actor-router-consts-DU-1IdQj.d.cts} +1 -1
- package/dist/tsup/{actor-router-consts-D29T1Z-K.d.ts → actor-router-consts-DU-1IdQj.d.ts} +1 -1
- package/dist/tsup/chunk-2ELYUO6C.cjs +112 -0
- package/dist/tsup/chunk-2ELYUO6C.cjs.map +1 -0
- package/dist/tsup/chunk-2LY7RW3Y.cjs +2316 -0
- package/dist/tsup/chunk-2LY7RW3Y.cjs.map +1 -0
- package/dist/tsup/{chunk-L47L3ZWJ.cjs → chunk-6G7ZNM27.cjs} +11 -6
- package/dist/tsup/chunk-6G7ZNM27.cjs.map +1 -0
- package/dist/tsup/{chunk-PB5AEMKQ.cjs → chunk-A4KEUCB6.cjs} +84 -34
- package/dist/tsup/chunk-A4KEUCB6.cjs.map +1 -0
- package/dist/tsup/{chunk-7HTNH26M.js → chunk-AKUJ5OTO.js} +11 -6
- package/dist/tsup/chunk-AKUJ5OTO.js.map +1 -0
- package/dist/tsup/{chunk-TADUYCHF.js → chunk-C22JYHVT.js} +77 -27
- package/dist/tsup/chunk-C22JYHVT.js.map +1 -0
- package/dist/tsup/chunk-C4EB42ET.js +1459 -0
- package/dist/tsup/chunk-C4EB42ET.js.map +1 -0
- package/dist/tsup/chunk-CGGGBIDP.cjs +1459 -0
- package/dist/tsup/chunk-CGGGBIDP.cjs.map +1 -0
- package/dist/tsup/chunk-CMQPDBBR.cjs +1486 -0
- package/dist/tsup/chunk-CMQPDBBR.cjs.map +1 -0
- package/dist/tsup/{chunk-GQGRQDRL.cjs → chunk-DH6UINWA.cjs} +4 -4
- package/dist/tsup/{chunk-GQGRQDRL.cjs.map → chunk-DH6UINWA.cjs.map} +1 -1
- package/dist/tsup/chunk-DK46YYCJ.js +1486 -0
- package/dist/tsup/chunk-DK46YYCJ.js.map +1 -0
- package/dist/tsup/chunk-EGWXXBZV.js +2316 -0
- package/dist/tsup/chunk-EGWXXBZV.js.map +1 -0
- package/dist/tsup/{chunk-S662Y6ZU.js → chunk-EONWXYMN.js} +2 -2
- package/dist/tsup/{chunk-N4KRDJ56.js → chunk-GFGRBYO2.js} +35 -6
- package/dist/tsup/chunk-GFGRBYO2.js.map +1 -0
- package/dist/tsup/{chunk-IIJNPVPQ.cjs → chunk-GUHXWPGB.cjs} +1515 -1479
- package/dist/tsup/chunk-GUHXWPGB.cjs.map +1 -0
- package/dist/tsup/{chunk-TI5PXQGG.cjs → chunk-HNE2AK6C.cjs} +2375 -3713
- package/dist/tsup/chunk-HNE2AK6C.cjs.map +1 -0
- package/dist/tsup/{chunk-2OK7S6QF.js → chunk-I5I6OALK.js} +2 -2
- package/dist/tsup/chunk-IHQAF2HV.cjs +23 -0
- package/dist/tsup/chunk-IHQAF2HV.cjs.map +1 -0
- package/dist/tsup/{chunk-U5SMSA27.cjs → chunk-JJNZQDUN.cjs} +667 -2517
- package/dist/tsup/chunk-JJNZQDUN.cjs.map +1 -0
- package/dist/tsup/{chunk-ZPWOYQHN.js → chunk-JJSPHLJN.js} +219 -287
- package/dist/tsup/chunk-JJSPHLJN.js.map +1 -0
- package/dist/tsup/chunk-JRKPV5NJ.js +481 -0
- package/dist/tsup/chunk-JRKPV5NJ.js.map +1 -0
- package/dist/tsup/{chunk-VKVNIQRQ.js → chunk-K7MVU5SI.js} +36 -41
- package/dist/tsup/chunk-K7MVU5SI.js.map +1 -0
- package/dist/tsup/{chunk-KJSYAUOM.js → chunk-MLK3GY6P.js} +43 -27
- package/dist/tsup/chunk-MLK3GY6P.js.map +1 -0
- package/dist/tsup/{chunk-HYPIHCDT.cjs → chunk-MPLMTJY5.cjs} +123 -23
- package/dist/tsup/chunk-MPLMTJY5.cjs.map +1 -0
- package/dist/tsup/{chunk-MIX2KB6U.js → chunk-PQWI44WD.js} +1755 -3093
- package/dist/tsup/chunk-PQWI44WD.js.map +1 -0
- package/dist/tsup/{chunk-SR3KQE7Q.cjs → chunk-SQFCIDCG.cjs} +35 -6
- package/dist/tsup/chunk-SQFCIDCG.cjs.map +1 -0
- package/dist/tsup/{chunk-WY2SHWXQ.js → chunk-SVHJSM2E.js} +110 -24
- package/dist/tsup/chunk-SVHJSM2E.js.map +1 -0
- package/dist/tsup/chunk-T5KYKM6R.js +49 -0
- package/dist/tsup/chunk-T5KYKM6R.js.map +1 -0
- package/dist/tsup/{chunk-7WF2QSIC.cjs → chunk-TJ7DKW6F.cjs} +123 -37
- package/dist/tsup/chunk-TJ7DKW6F.cjs.map +1 -0
- package/dist/tsup/chunk-UQZRMTM3.js +23 -0
- package/dist/tsup/chunk-UQZRMTM3.js.map +1 -0
- package/dist/tsup/{chunk-JC6BEPE7.cjs → chunk-V3JSZR5P.cjs} +3 -3
- package/dist/tsup/{chunk-JC6BEPE7.cjs.map → chunk-V3JSZR5P.cjs.map} +1 -1
- package/dist/tsup/{chunk-OAXJWGMU.cjs → chunk-VBR35EQF.cjs} +271 -339
- package/dist/tsup/chunk-VBR35EQF.cjs.map +1 -0
- package/dist/tsup/{chunk-EIATSBYZ.js → chunk-VWYO36X4.js} +117 -17
- package/dist/tsup/chunk-VWYO36X4.js.map +1 -0
- package/dist/tsup/{chunk-JPXO2H55.js → chunk-WW27B6DM.js} +1452 -1416
- package/dist/tsup/chunk-WW27B6DM.js.map +1 -0
- package/dist/tsup/chunk-YAE3MEJM.cjs +49 -0
- package/dist/tsup/chunk-YAE3MEJM.cjs.map +1 -0
- package/dist/tsup/{chunk-SRIM3GHD.js → chunk-YGYGANCA.js} +473 -2323
- package/dist/tsup/chunk-YGYGANCA.js.map +1 -0
- package/dist/tsup/chunk-YZJWZBY5.cjs +481 -0
- package/dist/tsup/chunk-YZJWZBY5.cjs.map +1 -0
- package/dist/tsup/{chunk-ZFY5J2EP.cjs → chunk-ZZLJ5TSM.cjs} +39 -44
- package/dist/tsup/chunk-ZZLJ5TSM.cjs.map +1 -0
- package/dist/tsup/client/mod.cjs +10 -7
- package/dist/tsup/client/mod.cjs.map +1 -1
- package/dist/tsup/client/mod.d.cts +6 -6
- package/dist/tsup/client/mod.d.ts +6 -6
- package/dist/tsup/client/mod.js +11 -8
- package/dist/tsup/common/log.cjs +3 -3
- package/dist/tsup/common/log.js +2 -2
- package/dist/tsup/common/websocket.cjs +4 -4
- package/dist/tsup/common/websocket.js +3 -3
- package/dist/tsup/{config-Qj-zLJPc.d.ts → config-C2Wwnc69.d.ts} +142 -208
- package/dist/tsup/{config-BiNoIHRs.d.ts → config-DROwzBLT.d.cts} +82 -6
- package/dist/tsup/{config-BiNoIHRs.d.cts → config-DROwzBLT.d.ts} +82 -6
- package/dist/tsup/{config-iPj5l1bL.d.cts → config-ehT-_3BB.d.cts} +142 -208
- package/dist/tsup/{context-DzvH1PBK.d.cts → context-DGMJuAyc.d.ts} +16 -3
- package/dist/tsup/{context-CQCMuHND.d.ts → context-Dpp2RJbW.d.cts} +16 -3
- package/dist/tsup/db/drizzle/mod.cjs +3 -3
- package/dist/tsup/db/drizzle/mod.d.cts +1 -1
- package/dist/tsup/db/drizzle/mod.d.ts +1 -1
- package/dist/tsup/db/drizzle/mod.js +2 -2
- package/dist/tsup/db/mod.cjs +3 -3
- package/dist/tsup/db/mod.d.cts +1 -1
- package/dist/tsup/db/mod.d.ts +1 -1
- package/dist/tsup/db/mod.js +2 -2
- package/dist/tsup/{driver-Jo8v-kbU.d.ts → driver-CYZP9QYo.d.ts} +1 -1
- package/dist/tsup/{driver-iV8J-WMv.d.cts → driver-CoTFpipv.d.cts} +1 -1
- package/dist/tsup/driver-helpers/mod.cjs +7 -5
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -1
- package/dist/tsup/driver-helpers/mod.d.cts +17 -18
- package/dist/tsup/driver-helpers/mod.d.ts +17 -18
- package/dist/tsup/driver-helpers/mod.js +11 -9
- package/dist/tsup/driver-test-suite/mod.cjs +1275 -228
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/driver-test-suite/mod.d.cts +6 -5
- package/dist/tsup/driver-test-suite/mod.d.ts +6 -5
- package/dist/tsup/driver-test-suite/mod.js +1581 -534
- package/dist/tsup/driver-test-suite/mod.js.map +1 -1
- package/dist/tsup/inspector/mod.cjs +4 -4
- package/dist/tsup/inspector/mod.js +3 -3
- package/dist/tsup/mod.cjs +15 -9
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +9 -9
- package/dist/tsup/mod.d.ts +9 -9
- package/dist/tsup/mod.js +19 -13
- package/dist/tsup/sandbox/client.cjs +28 -0
- package/dist/tsup/sandbox/client.cjs.map +1 -0
- package/dist/tsup/sandbox/client.d.cts +88 -0
- package/dist/tsup/sandbox/client.d.ts +88 -0
- package/dist/tsup/sandbox/client.js +28 -0
- package/dist/tsup/sandbox/client.js.map +1 -0
- package/dist/tsup/sandbox/index.cjs +761 -0
- package/dist/tsup/sandbox/index.cjs.map +1 -0
- package/dist/tsup/sandbox/index.d.cts +120 -0
- package/dist/tsup/sandbox/index.d.ts +120 -0
- package/dist/tsup/sandbox/index.js +761 -0
- package/dist/tsup/sandbox/index.js.map +1 -0
- package/dist/tsup/sandbox/providers/computesdk.cjs +3 -0
- package/dist/tsup/sandbox/providers/computesdk.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/computesdk.d.cts +7 -0
- package/dist/tsup/sandbox/providers/computesdk.d.ts +7 -0
- package/dist/tsup/sandbox/providers/computesdk.js +3 -0
- package/dist/tsup/sandbox/providers/computesdk.js.map +1 -0
- package/dist/tsup/sandbox/providers/daytona.cjs +3 -0
- package/dist/tsup/sandbox/providers/daytona.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/daytona.d.cts +1 -0
- package/dist/tsup/sandbox/providers/daytona.d.ts +1 -0
- package/dist/tsup/sandbox/providers/daytona.js +3 -0
- package/dist/tsup/sandbox/providers/daytona.js.map +1 -0
- package/dist/tsup/sandbox/providers/docker.cjs +3 -0
- package/dist/tsup/sandbox/providers/docker.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/docker.d.cts +1 -0
- package/dist/tsup/sandbox/providers/docker.d.ts +1 -0
- package/dist/tsup/sandbox/providers/docker.js +3 -0
- package/dist/tsup/sandbox/providers/docker.js.map +1 -0
- package/dist/tsup/sandbox/providers/e2b.cjs +3 -0
- package/dist/tsup/sandbox/providers/e2b.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/e2b.d.cts +1 -0
- package/dist/tsup/sandbox/providers/e2b.d.ts +1 -0
- package/dist/tsup/sandbox/providers/e2b.js +3 -0
- package/dist/tsup/sandbox/providers/e2b.js.map +1 -0
- package/dist/tsup/sandbox/providers/local.cjs +3 -0
- package/dist/tsup/sandbox/providers/local.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/local.d.cts +1 -0
- package/dist/tsup/sandbox/providers/local.d.ts +1 -0
- package/dist/tsup/sandbox/providers/local.js +3 -0
- package/dist/tsup/sandbox/providers/local.js.map +1 -0
- package/dist/tsup/sandbox/providers/modal.cjs +3 -0
- package/dist/tsup/sandbox/providers/modal.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/modal.d.cts +1 -0
- package/dist/tsup/sandbox/providers/modal.d.ts +1 -0
- package/dist/tsup/sandbox/providers/modal.js +3 -0
- package/dist/tsup/sandbox/providers/modal.js.map +1 -0
- package/dist/tsup/sandbox/providers/vercel.cjs +3 -0
- package/dist/tsup/sandbox/providers/vercel.cjs.map +1 -0
- package/dist/tsup/sandbox/providers/vercel.d.cts +1 -0
- package/dist/tsup/sandbox/providers/vercel.d.ts +1 -0
- package/dist/tsup/sandbox/providers/vercel.js +3 -0
- package/dist/tsup/sandbox/providers/vercel.js.map +1 -0
- package/dist/tsup/serve-test-suite/mod.cjs +451 -327
- package/dist/tsup/serve-test-suite/mod.cjs.map +1 -1
- package/dist/tsup/serve-test-suite/mod.js +362 -238
- package/dist/tsup/serve-test-suite/mod.js.map +1 -1
- package/dist/tsup/test/mod.cjs +17 -14
- package/dist/tsup/test/mod.cjs.map +1 -1
- package/dist/tsup/test/mod.d.cts +4 -4
- package/dist/tsup/test/mod.d.ts +4 -4
- package/dist/tsup/test/mod.js +14 -11
- package/dist/tsup/test/mod.js.map +1 -1
- package/dist/tsup/utils.cjs +3 -3
- package/dist/tsup/utils.js +2 -2
- package/dist/tsup/workflow/mod.cjs +6 -6
- package/dist/tsup/workflow/mod.d.cts +13 -9
- package/dist/tsup/workflow/mod.d.ts +13 -9
- package/dist/tsup/workflow/mod.js +5 -5
- package/package.json +114 -15
- package/src/actor/config.ts +94 -88
- package/src/actor/conn/drivers/websocket.ts +2 -1
- package/src/actor/contexts/base/actor.ts +27 -4
- package/src/actor/database.ts +6 -1
- package/src/actor/driver.ts +27 -8
- package/src/actor/errors.ts +10 -5
- package/src/actor/instance/connection-manager.ts +4 -3
- package/src/actor/instance/kv.ts +52 -9
- package/src/actor/instance/mod.ts +135 -84
- package/src/actor/instance/queue-manager.ts +2 -5
- package/src/actor/instance/queue.ts +31 -29
- package/src/actor/instance/state-manager.ts +7 -1
- package/src/actor/instance/traces-driver.ts +34 -36
- package/src/actor/metrics.ts +137 -0
- package/src/actor/protocol/old.ts +9 -12
- package/src/actor/router-websocket-endpoints.ts +12 -6
- package/src/actor/router.ts +46 -9
- package/src/actor/schema.ts +14 -22
- package/src/client/actor-common.ts +65 -0
- package/src/client/actor-conn.ts +71 -9
- package/src/client/actor-handle.ts +22 -5
- package/src/client/client.ts +32 -6
- package/src/client/config.ts +18 -21
- package/src/client/mod.ts +1 -0
- package/src/client/queue.ts +8 -6
- package/src/common/inline-websocket-adapter.ts +8 -2
- package/src/common/router.ts +1 -4
- package/src/common/utils.ts +2 -5
- package/src/db/config.ts +10 -5
- package/src/db/drizzle/mod.ts +51 -41
- package/src/db/mod.ts +54 -29
- package/src/db/shared.ts +42 -8
- package/src/driver-helpers/mod.ts +2 -1
- package/src/driver-helpers/sqlite-pool.ts +42 -0
- package/src/driver-helpers/utils.ts +0 -20
- package/src/driver-test-suite/mod.ts +11 -1
- package/src/driver-test-suite/tests/access-control.ts +19 -12
- package/src/driver-test-suite/tests/action-features.ts +20 -8
- package/src/driver-test-suite/tests/actor-conn.ts +94 -8
- package/src/driver-test-suite/tests/actor-db-kv-stats.ts +282 -0
- package/src/driver-test-suite/tests/actor-db-raw.ts +6 -2
- package/src/driver-test-suite/tests/actor-db.ts +101 -31
- package/src/driver-test-suite/tests/actor-inspector.ts +174 -32
- package/src/driver-test-suite/tests/actor-kv.ts +79 -33
- package/src/driver-test-suite/tests/actor-lifecycle.ts +4 -12
- package/src/driver-test-suite/tests/actor-queue.ts +125 -17
- package/src/driver-test-suite/tests/actor-run.ts +59 -55
- package/src/driver-test-suite/tests/actor-sandbox.ts +78 -0
- package/src/driver-test-suite/tests/actor-schedule.ts +1 -4
- package/src/driver-test-suite/tests/actor-sleep.ts +111 -0
- package/src/driver-test-suite/tests/actor-workflow.ts +387 -3
- package/src/driver-test-suite/tests/conn-error-serialization.ts +3 -1
- package/src/driver-test-suite/tests/raw-websocket.ts +5 -1
- package/src/drivers/default.ts +1 -3
- package/src/drivers/engine/actor-driver.ts +94 -21
- package/src/drivers/engine/config.ts +4 -12
- package/src/drivers/engine/mod.ts +1 -5
- package/src/drivers/file-system/actor.ts +43 -8
- package/src/drivers/file-system/global-state.ts +180 -64
- package/src/drivers/file-system/kv-limits.ts +1 -1
- package/src/drivers/file-system/sqlite-runtime.ts +13 -4
- package/src/engine-process/mod.ts +5 -1
- package/src/inspector/actor-inspector.ts +47 -21
- package/src/inspector/config.ts +1 -4
- package/src/inspector/mod.browser.ts +2 -2
- package/src/inspector/mod.ts +4 -1
- package/src/inspector/serve-ui.ts +0 -1
- package/src/inspector/workflow-history-json.ts +309 -0
- package/src/manager/gateway.ts +6 -2
- package/src/manager/router.ts +3 -3
- package/src/registry/config/index.ts +65 -12
- package/src/registry/config/runner.ts +19 -4
- package/src/registry/index.ts +42 -89
- package/src/sandbox/actor/db.ts +36 -0
- package/src/sandbox/actor/index.ts +476 -0
- package/src/sandbox/actor/session.ts +350 -0
- package/src/sandbox/actor.test.ts +36 -0
- package/src/sandbox/client.test.ts +484 -0
- package/src/sandbox/client.ts +707 -0
- package/src/sandbox/config.ts +151 -0
- package/src/sandbox/index.ts +41 -0
- package/src/sandbox/providers/computesdk.ts +1 -0
- package/src/sandbox/providers/daytona.ts +1 -0
- package/src/sandbox/providers/docker.ts +1 -0
- package/src/sandbox/providers/e2b.ts +1 -0
- package/src/sandbox/providers/local.ts +1 -0
- package/src/sandbox/providers/modal.ts +1 -0
- package/src/sandbox/providers/vercel.ts +1 -0
- package/src/sandbox/session-persist-driver.ts +180 -0
- package/src/sandbox/types.ts +138 -0
- package/src/serverless/configure.ts +5 -3
- package/src/serverless/router.test.ts +17 -9
- package/src/serverless/router.ts +20 -13
- package/src/test/mod.ts +3 -4
- package/src/utils/endpoint-parser.test.ts +6 -2
- package/src/utils/endpoint-parser.ts +6 -2
- package/src/utils/env-vars.ts +0 -2
- package/src/utils/node.ts +1 -1
- package/src/utils/serve.ts +10 -5
- package/src/utils.ts +6 -1
- package/src/workflow/constants.ts +1 -2
- package/src/workflow/context.ts +42 -9
- package/src/workflow/driver.ts +57 -23
- package/src/workflow/inspector.ts +7 -13
- package/src/workflow/mod.ts +91 -4
- package/dist/tsup/chunk-6LJAZ5R4.cjs +0 -96
- package/dist/tsup/chunk-6LJAZ5R4.cjs.map +0 -1
- package/dist/tsup/chunk-7HTNH26M.js.map +0 -1
- package/dist/tsup/chunk-7WF2QSIC.cjs.map +0 -1
- package/dist/tsup/chunk-D2SPAJVT.cjs +0 -645
- package/dist/tsup/chunk-D2SPAJVT.cjs.map +0 -1
- package/dist/tsup/chunk-EIATSBYZ.js.map +0 -1
- package/dist/tsup/chunk-HYPIHCDT.cjs.map +0 -1
- package/dist/tsup/chunk-IIJNPVPQ.cjs.map +0 -1
- package/dist/tsup/chunk-JPXO2H55.js.map +0 -1
- package/dist/tsup/chunk-KJSYAUOM.js.map +0 -1
- package/dist/tsup/chunk-L47L3ZWJ.cjs.map +0 -1
- package/dist/tsup/chunk-MIX2KB6U.js.map +0 -1
- package/dist/tsup/chunk-N4KRDJ56.js.map +0 -1
- package/dist/tsup/chunk-OAXJWGMU.cjs.map +0 -1
- package/dist/tsup/chunk-PB5AEMKQ.cjs.map +0 -1
- package/dist/tsup/chunk-R5OQUSLN.js +0 -645
- package/dist/tsup/chunk-R5OQUSLN.js.map +0 -1
- package/dist/tsup/chunk-SR3KQE7Q.cjs.map +0 -1
- package/dist/tsup/chunk-SRIM3GHD.js.map +0 -1
- package/dist/tsup/chunk-TADUYCHF.js.map +0 -1
- package/dist/tsup/chunk-TI5PXQGG.cjs.map +0 -1
- package/dist/tsup/chunk-U5SMSA27.cjs.map +0 -1
- package/dist/tsup/chunk-VKVNIQRQ.js.map +0 -1
- package/dist/tsup/chunk-WY2SHWXQ.js.map +0 -1
- package/dist/tsup/chunk-ZFY5J2EP.cjs.map +0 -1
- package/dist/tsup/chunk-ZPWOYQHN.js.map +0 -1
- package/src/db/sqlite-vfs.ts +0 -12
- /package/dist/tsup/{chunk-S662Y6ZU.js.map → chunk-EONWXYMN.js.map} +0 -0
- /package/dist/tsup/{chunk-2OK7S6QF.js.map → chunk-I5I6OALK.js.map} +0 -0
package/src/registry/index.ts
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { createClient } from "@/client/mod";
|
|
3
|
-
import { getNodeEnv, isDev } from "@/utils/env-vars";
|
|
1
|
+
import { Runtime } from "../../runtime";
|
|
4
2
|
import {
|
|
5
3
|
type RegistryActors,
|
|
6
4
|
type RegistryConfig,
|
|
7
5
|
type RegistryConfigInput,
|
|
8
6
|
RegistryConfigSchema,
|
|
9
7
|
} from "./config";
|
|
10
|
-
import {
|
|
11
|
-
type LegacyRunnerConfig,
|
|
12
|
-
type LegacyRunnerConfigInput,
|
|
13
|
-
LegacyRunnerConfigSchema,
|
|
14
|
-
} from "./config/legacy-runner";
|
|
15
|
-
import { Runtime } from "../../runtime";
|
|
16
8
|
|
|
17
9
|
export type FetchHandler = (
|
|
18
10
|
request: Request,
|
|
@@ -23,13 +15,6 @@ export interface ServerlessHandler {
|
|
|
23
15
|
fetch: FetchHandler;
|
|
24
16
|
}
|
|
25
17
|
|
|
26
|
-
export interface LegacyStartServerOutput<A extends Registry<any>> {
|
|
27
|
-
/** Client to communicate with the actors. */
|
|
28
|
-
client: Client<A>;
|
|
29
|
-
/** Fetch handler to manually route requests to the Rivet manager API. */
|
|
30
|
-
fetch: FetchHandler;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
18
|
export class Registry<A extends RegistryActors> {
|
|
34
19
|
#config: RegistryConfigInput<A>;
|
|
35
20
|
|
|
@@ -48,13 +33,17 @@ export class Registry<A extends RegistryActors> {
|
|
|
48
33
|
constructor(config: RegistryConfigInput<A>) {
|
|
49
34
|
this.#config = config;
|
|
50
35
|
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
36
|
+
// Start the local manager or engine before /api/rivet is hit so clients can
|
|
37
|
+
// reach the public endpoint preemptively. This waits one tick because some
|
|
38
|
+
// integrations mutate registry config immediately after setup() returns.
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
const parsedConfig = this.parseConfig();
|
|
41
|
+
|
|
42
|
+
if (parsedConfig.serverless.spawnEngine || parsedConfig.serveManager) {
|
|
54
43
|
// biome-ignore lint/nursery/noFloatingPromises: fire-and-forget auto-prepare
|
|
55
44
|
this.#ensureRuntime();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
45
|
+
}
|
|
46
|
+
}, 0);
|
|
58
47
|
}
|
|
59
48
|
|
|
60
49
|
/** Creates runtime if not already created. Idempotent. */
|
|
@@ -105,82 +94,46 @@ export class Registry<A extends RegistryActors> {
|
|
|
105
94
|
this.#ensureRuntime().then((runtime) => runtime.startRunner());
|
|
106
95
|
}
|
|
107
96
|
|
|
108
|
-
// MARK: Legacy
|
|
109
97
|
/**
|
|
110
|
-
*
|
|
98
|
+
* Starts the server, serving both the actor API and static files.
|
|
99
|
+
*
|
|
100
|
+
* This is the simplest way to run RivetKit. It starts a local manager
|
|
101
|
+
* server, serves static files from the configured `publicDir` (default
|
|
102
|
+
* `"public"`), and starts the actor runner.
|
|
111
103
|
*
|
|
112
|
-
*
|
|
104
|
+
* When an endpoint is configured (via config or RIVET_ENDPOINT env var),
|
|
105
|
+
* operates in serverless mode connected to the remote engine instead.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* const registry = setup({ use: { counter } });
|
|
110
|
+
* registry.start();
|
|
111
|
+
* ```
|
|
113
112
|
*/
|
|
114
|
-
public start(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
// Validate autoConfigureServerless is only used with serverless runner
|
|
120
|
-
if (
|
|
121
|
-
config.autoConfigureServerless &&
|
|
122
|
-
config.runnerKind !== "serverless"
|
|
123
|
-
) {
|
|
124
|
-
throw new Error(
|
|
125
|
-
"autoConfigureServerless can only be configured when runnerKind is 'serverless'",
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Auto-configure serverless runner if not in prod
|
|
130
|
-
const isDevEnv = isDev();
|
|
131
|
-
if (isDevEnv && config.runnerKind === "serverless") {
|
|
132
|
-
if (inputConfig?.runEngine === undefined) config.runEngine = true;
|
|
133
|
-
if (inputConfig?.autoConfigureServerless === undefined)
|
|
134
|
-
config.autoConfigureServerless = true;
|
|
113
|
+
public start() {
|
|
114
|
+
// Default publicDir to "public" if not explicitly set
|
|
115
|
+
if (this.#config.publicDir === undefined) {
|
|
116
|
+
this.#config.publicDir = "public";
|
|
135
117
|
}
|
|
136
118
|
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
119
|
+
// Force serveManager when there's no remote endpoint so the
|
|
120
|
+
// manager server starts and serves the API + static files.
|
|
121
|
+
// When an endpoint IS configured, the config transform handles
|
|
122
|
+
// the mode (serveManager defaults to false, spawnEngine may be
|
|
123
|
+
// true, etc.) and we just start the runner.
|
|
124
|
+
if (this.#config.serveManager === undefined) {
|
|
125
|
+
const hasEndpoint = !!(
|
|
126
|
+
this.#config.endpoint ||
|
|
127
|
+
(typeof process !== "undefined" &&
|
|
128
|
+
(process.env.RIVET_ENGINE || process.env.RIVET_ENDPOINT))
|
|
129
|
+
);
|
|
130
|
+
if (!hasEndpoint) {
|
|
131
|
+
this.#config.serveManager = true;
|
|
132
|
+
}
|
|
142
133
|
}
|
|
143
|
-
}
|
|
144
134
|
|
|
145
|
-
|
|
146
|
-
config: LegacyRunnerConfig,
|
|
147
|
-
_inputConfig: LegacyRunnerConfigInput | undefined,
|
|
148
|
-
): LegacyStartServerOutput<this> {
|
|
149
|
-
// Create client for the legacy return value
|
|
150
|
-
// For serverless, we don't have an endpoint until /start is called,
|
|
151
|
-
// so we create a placeholder client
|
|
152
|
-
const client = createClient<this>({
|
|
153
|
-
endpoint: config.endpoint,
|
|
154
|
-
token: config.token,
|
|
155
|
-
namespace: config.namespace,
|
|
156
|
-
headers: config.headers,
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
return {
|
|
160
|
-
client,
|
|
161
|
-
fetch: this.handler.bind(this),
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
#legacyStartNormal(
|
|
166
|
-
config: LegacyRunnerConfig,
|
|
167
|
-
): LegacyStartServerOutput<this> {
|
|
168
|
-
// Start the runner (fire-and-forget to maintain sync API)
|
|
169
|
-
// biome-ignore lint/nursery/noFloatingPromises: legacy sync API
|
|
135
|
+
// biome-ignore lint/nursery/noFloatingPromises: fire-and-forget
|
|
170
136
|
this.#ensureRuntime().then((runtime) => runtime.startRunner());
|
|
171
|
-
|
|
172
|
-
// Create client for the legacy return value
|
|
173
|
-
const client = createClient<this>({
|
|
174
|
-
endpoint: config.endpoint,
|
|
175
|
-
token: config.token,
|
|
176
|
-
namespace: config.namespace,
|
|
177
|
-
headers: config.headers,
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
return {
|
|
181
|
-
client,
|
|
182
|
-
fetch: this.handler.bind(this),
|
|
183
|
-
};
|
|
184
137
|
}
|
|
185
138
|
}
|
|
186
139
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { RawAccess } from "@/db/config";
|
|
2
|
+
|
|
3
|
+
export async function migrateSandboxTables(db: RawAccess): Promise<void> {
|
|
4
|
+
// Legacy tables from an earlier naming convention. Safe to drop because
|
|
5
|
+
// they were never shipped in a release and contain no user data.
|
|
6
|
+
await db.execute(`
|
|
7
|
+
DROP TABLE IF EXISTS sandbox_actor_meta;
|
|
8
|
+
DROP TABLE IF EXISTS sandbox_actor_sessions;
|
|
9
|
+
`);
|
|
10
|
+
|
|
11
|
+
await db.execute(`
|
|
12
|
+
CREATE TABLE IF NOT EXISTS sandbox_agent_sessions (
|
|
13
|
+
id TEXT PRIMARY KEY,
|
|
14
|
+
created_at INTEGER NOT NULL,
|
|
15
|
+
record_json TEXT NOT NULL
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
CREATE TABLE IF NOT EXISTS sandbox_agent_events (
|
|
19
|
+
id TEXT PRIMARY KEY,
|
|
20
|
+
session_id TEXT NOT NULL,
|
|
21
|
+
event_index INTEGER NOT NULL,
|
|
22
|
+
created_at INTEGER NOT NULL,
|
|
23
|
+
connection_id TEXT NOT NULL,
|
|
24
|
+
sender TEXT NOT NULL,
|
|
25
|
+
payload_json TEXT NOT NULL,
|
|
26
|
+
raw_payload_json TEXT,
|
|
27
|
+
UNIQUE(session_id, event_index)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
CREATE INDEX IF NOT EXISTS sandbox_agent_sessions_created_at_idx
|
|
31
|
+
ON sandbox_agent_sessions (created_at DESC);
|
|
32
|
+
|
|
33
|
+
CREATE INDEX IF NOT EXISTS sandbox_agent_events_session_event_index_idx
|
|
34
|
+
ON sandbox_agent_events (session_id, event_index ASC);
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandbox actor — wraps a sandbox-agent as a RivetKit actor.
|
|
3
|
+
*
|
|
4
|
+
* ## Lifecycle
|
|
5
|
+
*
|
|
6
|
+
* The sandbox actor manages a remote sandbox environment (Docker container,
|
|
7
|
+
* E2B sandbox, Daytona workspace, or custom provider) and exposes every
|
|
8
|
+
* sandbox-agent SDK method as an actor action.
|
|
9
|
+
*
|
|
10
|
+
* **Creation:** On the first action call, `ensureAgent` lazily provisions
|
|
11
|
+
* the sandbox via `SandboxAgent.start()`, which calls `provider.create()`
|
|
12
|
+
* and connects to the running sandbox-agent server. The sandbox ID and
|
|
13
|
+
* provider name are persisted in state so subsequent wake cycles reconnect
|
|
14
|
+
* to the same sandbox.
|
|
15
|
+
*
|
|
16
|
+
* **Sleep/Wake:** When the actor sleeps, `onSleep` tears down the live
|
|
17
|
+
* agent WebSocket connection and clears all in-memory subscriptions and
|
|
18
|
+
* timers. Vars are ephemeral and recreated fresh on each wake cycle via
|
|
19
|
+
* `createVars`. On the next action call after wake, `ensureAgent` reconnects
|
|
20
|
+
* to the existing sandbox (identified by `state.sandboxId`) via
|
|
21
|
+
* `SandboxAgent.start()` with the persisted sandbox ID and re-subscribes
|
|
22
|
+
* to all sessions listed in `state.subscribedSessionIds`. The upstream
|
|
23
|
+
* provider's `ensureServer()` hook (if implemented) is called automatically
|
|
24
|
+
* by `SandboxAgent.start()` to ensure the sandbox-agent process is running.
|
|
25
|
+
*
|
|
26
|
+
* **Destroy:** `onDestroy` tears down the connection, then calls
|
|
27
|
+
* `provider.destroy()` to delete the sandbox environment. The custom
|
|
28
|
+
* `destroy` action allows users to destroy the sandbox without destroying
|
|
29
|
+
* the actor, setting `state.sandboxDestroyed = true`. After this, proxy
|
|
30
|
+
* actions that require a live sandbox throw, but read-only actions
|
|
31
|
+
* (`listSessions`, `getSession`, `getEvents`) fall back to the local
|
|
32
|
+
* SQLite persistence layer so transcripts remain accessible.
|
|
33
|
+
*
|
|
34
|
+
* ## Session management
|
|
35
|
+
*
|
|
36
|
+
* Session subscriptions and turn tracking are handled by `./session.ts`.
|
|
37
|
+
* The actor prevents sleep while any session has an active prompt turn
|
|
38
|
+
* or while user-provided hooks are executing. Idle timers warn and
|
|
39
|
+
* eventually force-clear stale turns to prevent the actor from staying
|
|
40
|
+
* awake indefinitely.
|
|
41
|
+
*
|
|
42
|
+
* ## Prevent-sleep coordination
|
|
43
|
+
*
|
|
44
|
+
* `setPreventSleep(true)` is set whenever:
|
|
45
|
+
* - A session has an active prompt turn (tracked via JSON-RPC id matching)
|
|
46
|
+
* - A user hook (onSessionEvent, onPermissionRequest) is executing
|
|
47
|
+
*
|
|
48
|
+
* It is cleared when all active turns complete and all hooks finish.
|
|
49
|
+
* To avoid a race between sending a prompt and receiving the first event,
|
|
50
|
+
* session-creating and message-sending actions immediately mark the session
|
|
51
|
+
* active with idle timers.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
import type { DatabaseProvider } from "@/actor/database";
|
|
55
|
+
import { actor } from "@/actor/mod";
|
|
56
|
+
import type { RawAccess } from "@/db/config";
|
|
57
|
+
import { db } from "@/db/mod";
|
|
58
|
+
import { SandboxAgent, type SandboxProvider } from "sandbox-agent";
|
|
59
|
+
import {
|
|
60
|
+
type SandboxActorConfig,
|
|
61
|
+
type SandboxActorConfigInput,
|
|
62
|
+
type SandboxActorOptionsRuntime,
|
|
63
|
+
SandboxActorConfigSchema,
|
|
64
|
+
} from "../config";
|
|
65
|
+
import { SqliteSessionPersistDriver } from "../session-persist-driver";
|
|
66
|
+
import {
|
|
67
|
+
type SandboxActionContext,
|
|
68
|
+
type SandboxActorActions,
|
|
69
|
+
type SandboxActorState,
|
|
70
|
+
type SandboxActorVars,
|
|
71
|
+
SANDBOX_AGENT_ACTION_METHODS,
|
|
72
|
+
} from "../types";
|
|
73
|
+
import { migrateSandboxTables } from "./db";
|
|
74
|
+
import {
|
|
75
|
+
addSubscribedSession,
|
|
76
|
+
clearAllActiveSessions,
|
|
77
|
+
clearAllSessionTimers,
|
|
78
|
+
markSessionActiveInMemory,
|
|
79
|
+
removeSubscribedSession,
|
|
80
|
+
subscribeToSession,
|
|
81
|
+
syncPreventSleep,
|
|
82
|
+
} from "./session";
|
|
83
|
+
|
|
84
|
+
// --- Proxy action type definitions ---
|
|
85
|
+
|
|
86
|
+
type SandboxProxyActionDefinitions<TConnParams> = {
|
|
87
|
+
[K in keyof SandboxActorActions]: (
|
|
88
|
+
c: SandboxActionContext<TConnParams>,
|
|
89
|
+
...args: Parameters<SandboxActorActions[K]>
|
|
90
|
+
) => ReturnType<SandboxActorActions[K]>;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// --- Agent runtime lifecycle ---
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Tears down the live sandbox-agent connection and all associated
|
|
97
|
+
* in-memory state (event subscriptions, timers, hook tracking).
|
|
98
|
+
* Does NOT destroy the sandbox itself.
|
|
99
|
+
*/
|
|
100
|
+
async function teardownAgentRuntime(
|
|
101
|
+
vars: SandboxActorVars,
|
|
102
|
+
): Promise<void> {
|
|
103
|
+
for (const subscription of vars.unsubscribeBySessionId.values()) {
|
|
104
|
+
subscription.event?.();
|
|
105
|
+
subscription.permission?.();
|
|
106
|
+
}
|
|
107
|
+
vars.unsubscribeBySessionId.clear();
|
|
108
|
+
clearAllSessionTimers(vars);
|
|
109
|
+
vars.activeHooks.clear();
|
|
110
|
+
|
|
111
|
+
if (vars.sandboxAgentClient) {
|
|
112
|
+
try {
|
|
113
|
+
await vars.sandboxAgentClient.dispose();
|
|
114
|
+
} finally {
|
|
115
|
+
vars.sandboxAgentClient = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
vars.provider = null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function resolveProvider<TConnParams>(
|
|
123
|
+
c: SandboxActionContext<TConnParams>,
|
|
124
|
+
config: SandboxActorConfig<TConnParams>,
|
|
125
|
+
): Promise<SandboxProvider> {
|
|
126
|
+
if (c.vars.provider) {
|
|
127
|
+
return c.vars.provider;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const provider =
|
|
131
|
+
config.provider !== undefined
|
|
132
|
+
? config.provider
|
|
133
|
+
: await config.createProvider(c);
|
|
134
|
+
|
|
135
|
+
if (c.state.providerName && c.state.providerName !== provider.name) {
|
|
136
|
+
throw new Error(
|
|
137
|
+
`sandbox actor provider mismatch: expected ${c.state.providerName}, received ${provider.name}`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!c.state.providerName) {
|
|
142
|
+
c.state.providerName = provider.name;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
c.vars.provider = provider;
|
|
146
|
+
return provider;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Lazily provisions and connects to the sandbox. On the first call, this
|
|
151
|
+
* creates the sandbox via the provider. On subsequent calls (e.g. after
|
|
152
|
+
* wake), it reconnects to the existing sandbox. Short-circuits if the
|
|
153
|
+
* agent client is already connected.
|
|
154
|
+
*
|
|
155
|
+
* Steps:
|
|
156
|
+
* 1. Resolve the provider (static or via createProvider callback)
|
|
157
|
+
* 2. Call `SandboxAgent.start()` which handles:
|
|
158
|
+
* - Creating the sandbox if no sandboxId is provided
|
|
159
|
+
* - Calling `ensureServer()` if the provider implements it
|
|
160
|
+
* - Connecting to the sandbox-agent server
|
|
161
|
+
* 3. Persist the sandbox ID from the started client
|
|
162
|
+
* 4. Re-subscribe to all persisted session IDs
|
|
163
|
+
*/
|
|
164
|
+
async function ensureAgent<TConnParams>(
|
|
165
|
+
c: SandboxActionContext<TConnParams>,
|
|
166
|
+
config: SandboxActorConfig<TConnParams>,
|
|
167
|
+
persistRawEvents: boolean,
|
|
168
|
+
): Promise<SandboxAgent> {
|
|
169
|
+
if (c.vars.sandboxAgentClient) {
|
|
170
|
+
return c.vars.sandboxAgentClient;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const provider = await resolveProvider(c, config);
|
|
174
|
+
|
|
175
|
+
c.vars.sandboxAgentClient = await SandboxAgent.start({
|
|
176
|
+
sandbox: provider,
|
|
177
|
+
sandboxId: c.state.sandboxId ?? undefined,
|
|
178
|
+
persist: new SqliteSessionPersistDriver(c.db, persistRawEvents),
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Persist the sandbox ID so future wake cycles reconnect to the same sandbox.
|
|
182
|
+
if (!c.state.sandboxId && c.vars.sandboxAgentClient.sandboxId) {
|
|
183
|
+
c.state.sandboxId = c.vars.sandboxAgentClient.sandboxId;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Re-subscribe to all sessions that were active before sleep.
|
|
187
|
+
for (const sessionId of c.state.subscribedSessionIds) {
|
|
188
|
+
subscribeToSession(c, config, sessionId);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return c.vars.sandboxAgentClient;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// --- Read-only fallback actions ---
|
|
195
|
+
|
|
196
|
+
// These actions can read from the local SQLite persistence layer even after
|
|
197
|
+
// the sandbox has been destroyed, allowing transcript access.
|
|
198
|
+
const READ_ONLY_ACTIONS = new Set([
|
|
199
|
+
"listSessions",
|
|
200
|
+
"getSession",
|
|
201
|
+
"getEvents",
|
|
202
|
+
]);
|
|
203
|
+
|
|
204
|
+
// --- Session-returning action detection ---
|
|
205
|
+
|
|
206
|
+
// Actions that return a session object. After these actions, the actor
|
|
207
|
+
// auto-subscribes to the returned session's event stream.
|
|
208
|
+
const SESSION_RETURNING_ACTIONS = new Set([
|
|
209
|
+
"createSession",
|
|
210
|
+
"resumeSession",
|
|
211
|
+
"resumeOrCreateSession",
|
|
212
|
+
"getSession",
|
|
213
|
+
]);
|
|
214
|
+
|
|
215
|
+
// Actions that send messages to a session. These immediately mark the
|
|
216
|
+
// session active to prevent a race between sending and receiving the
|
|
217
|
+
// first event.
|
|
218
|
+
const SESSION_SENDING_ACTIONS = new Set([
|
|
219
|
+
"rawSendSessionMethod",
|
|
220
|
+
"respondPermission",
|
|
221
|
+
"rawRespondPermission",
|
|
222
|
+
]);
|
|
223
|
+
|
|
224
|
+
function isSessionLike(value: unknown): value is { id: string } {
|
|
225
|
+
return (
|
|
226
|
+
typeof value === "object" &&
|
|
227
|
+
value !== null &&
|
|
228
|
+
"id" in value &&
|
|
229
|
+
typeof (value as Record<string, unknown>).id === "string"
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// --- Proxy action builder ---
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Generates an action for each sandbox-agent SDK method. Each proxy action:
|
|
237
|
+
*
|
|
238
|
+
* 1. Calls `ensureAgent()` to lazily connect to the sandbox
|
|
239
|
+
* 2. Forwards the call to the corresponding `SandboxAgent` method
|
|
240
|
+
* 3. Handles post-action side effects:
|
|
241
|
+
* - `dispose`: tears down the agent runtime
|
|
242
|
+
* - `destroySession`: unsubscribes from the destroyed session
|
|
243
|
+
* - Session-returning actions: auto-subscribes to the session
|
|
244
|
+
* - `listSessions`: auto-subscribes to all returned sessions
|
|
245
|
+
* - Session-sending actions: immediately marks the session active
|
|
246
|
+
* to prevent sleep before the first event arrives
|
|
247
|
+
*/
|
|
248
|
+
function buildProxyActions<TConnParams>(
|
|
249
|
+
config: SandboxActorConfig<TConnParams>,
|
|
250
|
+
): SandboxProxyActionDefinitions<TConnParams> {
|
|
251
|
+
const actions = {} as Record<
|
|
252
|
+
string,
|
|
253
|
+
(c: SandboxActionContext<TConnParams>, ...args: unknown[]) => Promise<unknown>
|
|
254
|
+
>;
|
|
255
|
+
|
|
256
|
+
for (const actionName of SANDBOX_AGENT_ACTION_METHODS) {
|
|
257
|
+
actions[actionName] = async (
|
|
258
|
+
c: SandboxActionContext<TConnParams>,
|
|
259
|
+
...args: unknown[]
|
|
260
|
+
) => {
|
|
261
|
+
// After sandbox destruction, only read-only actions are allowed.
|
|
262
|
+
// These fall back to the SQLite persistence layer.
|
|
263
|
+
if (c.state.sandboxDestroyed) {
|
|
264
|
+
if (READ_ONLY_ACTIONS.has(actionName)) {
|
|
265
|
+
const persist = new SqliteSessionPersistDriver(
|
|
266
|
+
c.db,
|
|
267
|
+
config.persistRawEvents ?? false,
|
|
268
|
+
);
|
|
269
|
+
if (actionName === "listSessions") {
|
|
270
|
+
return persist.listSessions(args[0] as any);
|
|
271
|
+
}
|
|
272
|
+
if (actionName === "getSession") {
|
|
273
|
+
return persist.getSession(args[0] as string);
|
|
274
|
+
}
|
|
275
|
+
if (actionName === "getEvents") {
|
|
276
|
+
return persist.listEvents(args[0] as any);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
throw new Error(
|
|
280
|
+
"sandbox has been destroyed; only read-only actions (listSessions, getSession, getEvents) are available",
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const options = config.options as SandboxActorOptionsRuntime;
|
|
285
|
+
|
|
286
|
+
// For session-sending actions, immediately mark the session
|
|
287
|
+
// active before dispatching to prevent the actor from sleeping
|
|
288
|
+
// between sending the message and receiving the first event.
|
|
289
|
+
if (
|
|
290
|
+
SESSION_SENDING_ACTIONS.has(actionName) &&
|
|
291
|
+
typeof args[0] === "string"
|
|
292
|
+
) {
|
|
293
|
+
markSessionActiveInMemory(c, options, args[0]);
|
|
294
|
+
syncPreventSleep(c);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Connect to the sandbox-agent and forward the method call.
|
|
298
|
+
const agent = await ensureAgent(
|
|
299
|
+
c,
|
|
300
|
+
config,
|
|
301
|
+
config.persistRawEvents ?? false,
|
|
302
|
+
);
|
|
303
|
+
const method = agent[actionName] as (
|
|
304
|
+
...innerArgs: unknown[]
|
|
305
|
+
) => unknown;
|
|
306
|
+
const result = await method.apply(agent, args);
|
|
307
|
+
|
|
308
|
+
// Post-action side effects: manage session subscriptions based
|
|
309
|
+
// on what the action returned.
|
|
310
|
+
if (actionName === "dispose") {
|
|
311
|
+
await teardownAgentRuntime(c.vars);
|
|
312
|
+
clearAllActiveSessions(c);
|
|
313
|
+
} else if (
|
|
314
|
+
actionName === "destroySession" &&
|
|
315
|
+
isSessionLike(result)
|
|
316
|
+
) {
|
|
317
|
+
const sub = c.vars.unsubscribeBySessionId.get(result.id);
|
|
318
|
+
sub?.event?.();
|
|
319
|
+
sub?.permission?.();
|
|
320
|
+
c.vars.unsubscribeBySessionId.delete(result.id);
|
|
321
|
+
removeSubscribedSession(c, result.id);
|
|
322
|
+
} else if (
|
|
323
|
+
SESSION_RETURNING_ACTIONS.has(actionName) &&
|
|
324
|
+
isSessionLike(result)
|
|
325
|
+
) {
|
|
326
|
+
addSubscribedSession(c, result.id);
|
|
327
|
+
subscribeToSession(c, config, result.id);
|
|
328
|
+
} else if (
|
|
329
|
+
actionName === "listSessions" &&
|
|
330
|
+
result &&
|
|
331
|
+
typeof result === "object"
|
|
332
|
+
) {
|
|
333
|
+
const items = (result as { items?: unknown }).items;
|
|
334
|
+
if (Array.isArray(items)) {
|
|
335
|
+
for (const item of items) {
|
|
336
|
+
if (isSessionLike(item)) {
|
|
337
|
+
addSubscribedSession(c, item.id);
|
|
338
|
+
subscribeToSession(c, config, item.id);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return result;
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return actions as unknown as SandboxProxyActionDefinitions<TConnParams>;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// --- Public API ---
|
|
352
|
+
|
|
353
|
+
export function sandboxActor<TConnParams = undefined>(
|
|
354
|
+
config: SandboxActorConfigInput<TConnParams>,
|
|
355
|
+
) {
|
|
356
|
+
const parsedConfig = SandboxActorConfigSchema.parse(
|
|
357
|
+
config,
|
|
358
|
+
) as SandboxActorConfig<TConnParams> & {
|
|
359
|
+
options: SandboxActorOptionsRuntime;
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
return actor<
|
|
363
|
+
SandboxActorState,
|
|
364
|
+
TConnParams,
|
|
365
|
+
undefined,
|
|
366
|
+
SandboxActorVars,
|
|
367
|
+
undefined,
|
|
368
|
+
DatabaseProvider<RawAccess>,
|
|
369
|
+
Record<never, never>,
|
|
370
|
+
Record<never, never>
|
|
371
|
+
>({
|
|
372
|
+
createState: async () => ({
|
|
373
|
+
sandboxId: null,
|
|
374
|
+
providerName: null,
|
|
375
|
+
subscribedSessionIds: [],
|
|
376
|
+
sandboxDestroyed: false,
|
|
377
|
+
}),
|
|
378
|
+
createVars: () => ({
|
|
379
|
+
sandboxAgentClient: null,
|
|
380
|
+
provider: null,
|
|
381
|
+
activeSessionIds: new Set<string>(),
|
|
382
|
+
activePromptRequestIdsBySessionId: new Map<string, string[]>(),
|
|
383
|
+
lastEventAtBySessionId: new Map<string, number>(),
|
|
384
|
+
unsubscribeBySessionId: new Map(),
|
|
385
|
+
activeHooks: new Set<Promise<void>>(),
|
|
386
|
+
warningTimeoutBySessionId: new Map(),
|
|
387
|
+
staleTimeoutBySessionId: new Map(),
|
|
388
|
+
}),
|
|
389
|
+
db: db({
|
|
390
|
+
onMigrate: migrateSandboxTables,
|
|
391
|
+
}),
|
|
392
|
+
onSleep: async (c) => {
|
|
393
|
+
await teardownAgentRuntime(c.vars);
|
|
394
|
+
},
|
|
395
|
+
onDestroy: async (c) => {
|
|
396
|
+
const sandboxContext =
|
|
397
|
+
c as SandboxActionContext<TConnParams>;
|
|
398
|
+
clearAllActiveSessions(sandboxContext);
|
|
399
|
+
await teardownAgentRuntime(sandboxContext.vars);
|
|
400
|
+
|
|
401
|
+
if (sandboxContext.state.sandboxId) {
|
|
402
|
+
try {
|
|
403
|
+
const provider = await resolveProvider(
|
|
404
|
+
sandboxContext,
|
|
405
|
+
parsedConfig,
|
|
406
|
+
);
|
|
407
|
+
await provider.destroy(sandboxContext.state.sandboxId);
|
|
408
|
+
} finally {
|
|
409
|
+
sandboxContext.state.sandboxId = null;
|
|
410
|
+
sandboxContext.state.providerName = null;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
sandboxContext.state.subscribedSessionIds = [];
|
|
415
|
+
},
|
|
416
|
+
onBeforeConnect: parsedConfig.onBeforeConnect,
|
|
417
|
+
actions: {
|
|
418
|
+
// Destroys the sandbox environment but keeps the actor alive so
|
|
419
|
+
// session transcripts remain accessible via read-only actions.
|
|
420
|
+
// If `destroyActor` is set in the config, the actor is also
|
|
421
|
+
// destroyed after the sandbox.
|
|
422
|
+
destroy: async (c: SandboxActionContext<TConnParams>) => {
|
|
423
|
+
if (c.state.sandboxDestroyed) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
clearAllActiveSessions(c);
|
|
428
|
+
await teardownAgentRuntime(c.vars);
|
|
429
|
+
|
|
430
|
+
if (c.state.sandboxId) {
|
|
431
|
+
const provider = await resolveProvider(c, parsedConfig);
|
|
432
|
+
await provider.destroy(c.state.sandboxId);
|
|
433
|
+
c.state.sandboxId = null;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
c.state.sandboxDestroyed = true;
|
|
437
|
+
|
|
438
|
+
if (parsedConfig.destroyActor) {
|
|
439
|
+
c.destroy();
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
getSandboxUrl: async (c: SandboxActionContext<TConnParams>) => {
|
|
443
|
+
if (c.state.sandboxDestroyed) {
|
|
444
|
+
throw new Error("sandbox has been destroyed");
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const provider = await resolveProvider(c, parsedConfig);
|
|
448
|
+
|
|
449
|
+
// Ensure the sandbox exists so we have a sandbox ID.
|
|
450
|
+
if (!c.state.sandboxId) {
|
|
451
|
+
const agent = await ensureAgent(
|
|
452
|
+
c,
|
|
453
|
+
parsedConfig,
|
|
454
|
+
parsedConfig.persistRawEvents ?? false,
|
|
455
|
+
);
|
|
456
|
+
if (!c.state.sandboxId && agent.sandboxId) {
|
|
457
|
+
c.state.sandboxId = agent.sandboxId;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (!c.state.sandboxId) {
|
|
462
|
+
throw new Error("sandbox ID is not available");
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (!provider.getUrl) {
|
|
466
|
+
throw new Error(
|
|
467
|
+
`provider "${provider.name}" does not support getUrl; direct sandbox URL access is not available for this provider`,
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
return { url: await provider.getUrl(c.state.sandboxId) };
|
|
472
|
+
},
|
|
473
|
+
...buildProxyActions(parsedConfig),
|
|
474
|
+
},
|
|
475
|
+
});
|
|
476
|
+
}
|