@mastra/modal 0.2.0 → 0.2.1-alpha.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/CHANGELOG.md +9 -0
- package/dist/index.cjs +6 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/sandbox/process-manager.d.ts.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @mastra/modal
|
|
2
2
|
|
|
3
|
+
## 0.2.1-alpha.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed sandbox execution results to report killed and timed out commands. ([#17281](https://github.com/mastra-ai/mastra/pull/17281))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`8ace89d`](https://github.com/mastra-ai/mastra/commit/8ace89df77f762e622d3b9f7f65ad7524350d050), [`fa63872`](https://github.com/mastra-ai/mastra/commit/fa6387280954e6b667bec5714b55ba082bc627ff), [`f07b646`](https://github.com/mastra-ai/mastra/commit/f07b64604ab7d25391179790b7fd4823df9e2dff), [`d8838ae`](https://github.com/mastra-ai/mastra/commit/d8838ae80b69780361693d27098f7f6684af12fe), [`40f9297`](https://github.com/mastra-ai/mastra/commit/40f9297003b921c62373d3e8d3a4bda76c9f6de3), [`0f0d1ba`](https://github.com/mastra-ai/mastra/commit/0f0d1ba67bfcb2204e571401662f1eceefc03357), [`8c31bcd`](https://github.com/mastra-ai/mastra/commit/8c31bcdb00e597880d5939b1b7d7566fbe5dacae), [`95b14cd`](https://github.com/mastra-ai/mastra/commit/95b14cdd820e86d97ac05fe568424c513a252e31), [`aa36be2`](https://github.com/mastra-ai/mastra/commit/aa36be23aa513b7dc53cb8ca16b7fab8f20e43ad), [`212c635`](https://github.com/mastra-ai/mastra/commit/212c635203e61d036ab41db8ff86c3893dc795b3), [`d8838ae`](https://github.com/mastra-ai/mastra/commit/d8838ae80b69780361693d27098f7f6684af12fe), [`9aa5a73`](https://github.com/mastra-ai/mastra/commit/9aa5a73e7e110f6e9365eec69364a33d5f03bb56), [`f73c789`](https://github.com/mastra-ai/mastra/commit/f73c789e8ef21561580395d2c410119cab5848c8), [`8bd16da`](https://github.com/mastra-ai/mastra/commit/8bd16da73a4cb874d739373643dbd6a6e7f88684), [`c8630f8`](https://github.com/mastra-ai/mastra/commit/c8630f80d4f40cb5d22e60ab162b618b1907167a), [`47f71dc`](https://github.com/mastra-ai/mastra/commit/47f71dc6fbcbd12d71e21a979e676e20a02bd77d), [`50ceae2`](https://github.com/mastra-ai/mastra/commit/50ceae270878e2f8fb2b2c6c2faab09df0007c8a), [`8cdde58`](https://github.com/mastra-ai/mastra/commit/8cdde5875bbba6702d9df226f2b20232b8d75d6c), [`847ff1e`](https://github.com/mastra-ai/mastra/commit/847ff1e0d94368d94b2e173e4e0908e115568ef3), [`259d409`](https://github.com/mastra-ai/mastra/commit/259d409a514174299dbde1ff5e1121209b3ba850), [`9e16c68`](https://github.com/mastra-ai/mastra/commit/9e16c6818b6485ccb43df28aba6f3a2219d28662), [`cefca33`](https://github.com/mastra-ai/mastra/commit/cefca33ae666e69810c935fedf95a929c173d1d7), [`d00e8c5`](https://github.com/mastra-ai/mastra/commit/d00e8c50daebe5bce5bf2f48bde39c86fc3d2fe4), [`36fa7e2`](https://github.com/mastra-ai/mastra/commit/36fa7e24d14e58a1eb46147097b32f583e5b8775), [`87e9774`](https://github.com/mastra-ai/mastra/commit/87e97741c1e493cd6d62f478eb810b49bda4d57c), [`65a72e7`](https://github.com/mastra-ai/mastra/commit/65a72e70c25eedea8ff985a6624b96be2850236b), [`0f77241`](https://github.com/mastra-ai/mastra/commit/0f7724108806703799a8ba80ad0f09414afd5066), [`92ff509`](https://github.com/mastra-ai/mastra/commit/92ff5098ef8a990438ca038077021a5f7541ec1d), [`3fce5e7`](https://github.com/mastra-ai/mastra/commit/3fce5e70d011d289043e75003ef3336ed4aa43c3), [`a763592`](https://github.com/mastra-ai/mastra/commit/a763592c3db46963ef1011cfe16fe372816e775e), [`80c7737`](https://github.com/mastra-ai/mastra/commit/80c7737e32d7917b5f356957d67c169d01744fd3), [`3f1cf47`](https://github.com/mastra-ai/mastra/commit/3f1cf476f74c1e4cc2df908837e05853a5347e31)]:
|
|
10
|
+
- @mastra/core@1.38.0-alpha.3
|
|
11
|
+
|
|
3
12
|
## 0.2.0
|
|
4
13
|
|
|
5
14
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -70,7 +70,9 @@ var ModalProcessHandle = class extends workspace.ProcessHandle {
|
|
|
70
70
|
exitCode: 124,
|
|
71
71
|
stdout: this.stdout,
|
|
72
72
|
stderr: this.stderr || error.message,
|
|
73
|
-
executionTimeMs: Date.now() - this._startTime
|
|
73
|
+
executionTimeMs: Date.now() - this._startTime,
|
|
74
|
+
killed: true,
|
|
75
|
+
timedOut: true
|
|
74
76
|
};
|
|
75
77
|
}
|
|
76
78
|
throw error;
|
|
@@ -87,7 +89,9 @@ var ModalProcessHandle = class extends workspace.ProcessHandle {
|
|
|
87
89
|
exitCode: this._exitCode ?? 137,
|
|
88
90
|
stdout: this.stdout,
|
|
89
91
|
stderr: this.stderr,
|
|
90
|
-
executionTimeMs: Date.now() - this._startTime
|
|
92
|
+
executionTimeMs: Date.now() - this._startTime,
|
|
93
|
+
killed: true,
|
|
94
|
+
timedOut: false
|
|
91
95
|
};
|
|
92
96
|
}
|
|
93
97
|
await this._resolveExitCode();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sandbox/process-manager.ts","../src/sandbox/index.ts"],"names":["ProcessHandle","SandboxProcessManager","MastraSandbox","SandboxNotReadyError","NotFoundError","ClientClosedError","ModalClient"],"mappings":";;;;;;AAkBA,IAAM,kBAAA,GAAN,cAAiCA,uBAAA,CAAc;AAAA,EACpC,GAAA;AAAA,EAEQ,KAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EAET,SAAA;AAAA,EACA,YAAA,GAA8C,IAAA;AAAA,EAC9C,iBAAA,GAA0C,IAAA;AAAA,EAC1C,OAAA,GAAU,KAAA;AAAA,EACV,aAAA,GAA4D,IAAA;AAAA,EAC5D,aAAA,GAA4D,IAAA;AAAA,EAEpE,WAAA,CAAY,GAAA,EAAa,IAAA,EAAgC,SAAA,EAAmB,OAAA,EAA+B;AACzG,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAClB,IAAA,IAAA,CAAK,WAAW,OAAA,EAAS,OAAA;AAAA,EAC3B;AAAA,EAEA,IAAI,QAAA,GAA+B;AACjC,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,iBAAiB,CAAA,EAAkB;AACrC,IAAA,IAAA,CAAK,iBAAA,GAAoB,CAAA;AAGzB,IAAA,CAAA,CAAE,IAAA,CAAK,MAAM,IAAA,CAAK,gBAAA,EAAkB,EAAE,KAAA,CAAM,MAAM,IAAA,CAAK,gBAAA,EAAkB,CAAA;AAAA,EAC3E;AAAA;AAAA,EAGA,UAAA,CACE,cACA,YAAA,EACM;AACN,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AACrB,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,EACvB;AAAA;AAAA,EAGA,MAAc,gBAAA,GAAkC;AAC9C,IAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAW;AAClC,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,SAAA,GAAY,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,EAAK;AAAA,IACzC,CAAA,CAAA,MAAQ;AACN,MAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAW;AAChC,QAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,IAAA,GAA+B;AACnC,IAAA,IAAI,CAAC,KAAK,YAAA,EAAc;AACtB,MAAA,IAAA,CAAK,YAAA,GAAe,KAAK,OAAA,EAAQ;AAAA,IACnC;AACA,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA,EAEA,MAAc,OAAA,GAAkC;AAC9C,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,iBAAA,IAAqB,OAAA,CAAQ,OAAA,EAAQ;AAE7D,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,IAAI,SAAA;AACJ,MAAA,MAAM,cAAA,GAAiB,IAAI,OAAA,CAAe,CAAC,GAAG,MAAA,KAAW;AACvD,QAAA,SAAA,GAAY,UAAA,CAAW,MAAM,MAAA,CAAO,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,IAAA,CAAK,QAAQ,CAAA,EAAA,CAAI,CAAC,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA;AAAA,MAC7G,CAAC,CAAA;AAED,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,CAAQ,IAAA,CAAK,CAAC,UAAA,EAAY,cAAc,CAAC,CAAA;AAAA,MACjD,SAAS,KAAA,EAAO;AACd,QAAA,IAAI,iBAAiB,KAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA,EAAG;AACjE,UAAA,MAAM,KAAK,IAAA,EAAK;AAChB,UAAA,IAAA,CAAK,SAAA,GAAY,GAAA;AACjB,UAAA,OAAO;AAAA,YACL,OAAA,EAAS,KAAA;AAAA,YACT,QAAA,EAAU,GAAA;AAAA,YACV,QAAQ,IAAA,CAAK,MAAA;AAAA,YACb,MAAA,EAAQ,IAAA,CAAK,MAAA,IAAU,KAAA,CAAM,OAAA;AAAA,YAC7B,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK;AAAA,WACrC;AAAA,QACF;AACA,QAAA,MAAM,KAAA;AAAA,MACR,CAAA,SAAE;AACA,QAAA,YAAA,CAAa,SAAS,CAAA;AAAA,MACxB;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAAM,UAAA,CAAW,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACjC;AAEA,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,QAAA,EAAU,KAAK,SAAA,IAAa,GAAA;AAAA,QAC5B,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK;AAAA,OACrC;AAAA,IACF;AAEA,IAAA,MAAM,KAAK,gBAAA,EAAiB;AAE5B,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAK,SAAA,KAAc,CAAA;AAAA,MAC5B,QAAA,EAAU,KAAK,SAAA,IAAa,CAAA;AAAA,MAC5B,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK;AAAA,KACrC;AAAA,EACF;AAAA,EAEA,MAAM,IAAA,GAAyB;AAC7B,IAAA,IAAI,IAAA,CAAK,SAAA,KAAc,MAAA,EAAW,OAAO,KAAA;AACzC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,SAAA,GAAY,GAAA;AAEjB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,eAAe,MAAA,EAAO;AAAA,IACnC,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,eAAe,MAAA,EAAO;AAAA,IACnC,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,KAAA,EAA8B;AAC5C,IAAA,MAAM,IAAI,MAAM,kFAA6E,CAAA;AAAA,EAC/F;AACF,CAAA;AAcO,IAAM,mBAAA,GAAN,cAAkCC,+BAAA,CAAoC;AAAA,EACnE,aAAA,GAAgB,CAAA;AAAA,EAExB,WAAA,CAAY,IAAA,GAAmC,EAAC,EAAG;AACjD,IAAA,KAAA,CAAM,EAAE,GAAA,EAAK,IAAA,CAAK,GAAA,EAAK,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,KAAA,CAAM,OAAA,EAAiB,OAAA,GAA+B,EAAC,EAA2B;AACtF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,WAAA,CAAY,YAAY;AAC1C,MAAA,MAAM,EAAA,GAAK,KAAK,OAAA,CAAQ,KAAA;AAExB,MAAA,MAAM,YAAY,EAAE,GAAG,KAAK,GAAA,EAAK,GAAG,QAAQ,GAAA,EAAI;AAChD,MAAA,MAAM,MAAM,MAAA,CAAO,WAAA;AAAA,QACjB,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,CAAE,MAAA,CAAO,CAAC,KAAA,KAAqC,KAAA,CAAM,CAAC,CAAA,KAAM,MAAS;AAAA,OAC/F;AAGA,MAAA,MAAM,IAAA,GAAO,CAAC,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA;AAEjC,MAAA,MAAM,IAAA,GAAO,MAAM,EAAA,CAAG,IAAA,CAAK,IAAA,EAAM;AAAA,QAC/B,KAAK,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,GAAS,IAAI,GAAA,GAAM,MAAA;AAAA,QACzC,SAAS,OAAA,CAAQ,GAAA;AAAA,QACjB,WAAW,OAAA,CAAQ;AAAA,OACpB,CAAA;AAED,MAAA,MAAM,GAAA,GAAM,CAAA,WAAA,EAAc,IAAA,CAAK,GAAA,EAAI,CAAE,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA,EAAI,EAAE,IAAA,CAAK,aAAa,CAAA,CAAA;AACzE,MAAA,MAAM,MAAA,GAAS,IAAI,kBAAA,CAAmB,GAAA,EAAK,MAAM,IAAA,CAAK,GAAA,IAAO,OAAO,CAAA;AAEpE,MAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,SAAA,EAAU;AAC3C,MAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,SAAA,EAAU;AAC3C,MAAA,MAAA,CAAO,UAAA,CAAW,cAAc,YAAY,CAAA;AAE5C,MAAA,MAAM,gBAAA,GAAmB,QAAQ,GAAA,CAAI;AAAA,QACnC,YAAY,YAAA,EAAc,CAAA,KAAA,KAAS,MAAA,CAAO,UAAA,CAAW,KAAK,CAAC,CAAA;AAAA,QAC3D,YAAY,YAAA,EAAc,CAAA,KAAA,KAAS,MAAA,CAAO,UAAA,CAAW,KAAK,CAAC;AAAA,OAC5D,CAAA,CAAE,IAAA,CAAK,MAAM;AAAA,MAAC,CAAC,CAAA;AAEhB,MAAA,MAAA,CAAO,gBAAA,GAAmB,gBAAA;AAE1B,MAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,GAAA,EAAK,MAAM,CAAA;AAC7B,MAAA,OAAO,MAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,IAAA,GAA+B;AACnC,IAAA,MAAM,SAAwB,EAAC;AAC/B,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,MAAM,CAAA,IAAK,KAAK,QAAA,EAAU;AACzC,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,GAAA;AAAA,QACA,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,OAAA,EAAS,OAAO,QAAA,KAAa,MAAA;AAAA,QAC7B,UAAU,MAAA,CAAO;AAAA,OAClB,CAAA;AAAA,IACH;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAOA,eAAe,WAAA,CAAY,QAA6C,IAAA,EAA8C;AACpH,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,MAAA,IAAI,IAAA,EAAM;AACV,MAAA,IAAA,CAAK,KAAK,CAAA;AAAA,IACZ;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;;;ACtOA,IAAM,UAAA,GAAa,gBAAA;AAkEZ,IAAM,YAAA,GAAN,cAA2BC,uBAAA,CAAc;AAAA,EACrC,EAAA;AAAA,EACA,IAAA,GAAO,cAAA;AAAA,EACP,QAAA,GAAW,OAAA;AAAA,EACpB,MAAA,GAAyB,SAAA;AAAA,EAIjB,GAAA,GAAsB,IAAA;AAAA,EACtB,cAAA,GAA+B,IAAA;AAAA;AAAA,EAC/B,OAAA,GAA8B,IAAA;AAAA,EAC9B,UAAA,GAA0B,IAAA;AAAA,EAC1B,WAAA,GAAc,KAAA;AAAA,EAEL,OAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,qBAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAA+B,EAAC,EAAG;AAC7C,IAAA,KAAA,CAAM;AAAA,MACJ,GAAG,OAAA;AAAA,MACH,IAAA,EAAM,cAAA;AAAA,MACN,SAAA,EAAW,IAAI,mBAAA,CAAoB,EAAE,KAAK,OAAA,CAAQ,GAAA,IAAO,EAAC,EAAG;AAAA,KAC9D,CAAA;AAED,IAAA,IAAA,CAAK,EAAA,GAAK,OAAA,CAAQ,EAAA,IAAM,IAAA,CAAK,WAAA,EAAY;AACzC,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW,QAAA;AAClC,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,SAAA,IAAa,cAAA;AACtC,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,SAAA,IAAa,GAAA;AACtC,IAAA,IAAA,CAAK,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,EAAC;AAC3B,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AACvB,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AACvB,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,WAAA;AAC3B,IAAA,IAAA,CAAK,wBAAwB,OAAA,CAAQ,YAAA;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,KAAA,GAAiB;AACnB,IAAA,IAAI,CAAC,KAAK,GAAA,EAAK;AACb,MAAA,MAAM,IAAIC,8BAAA,CAAqB,IAAA,CAAK,EAAE,CAAA;AAAA,IACxC;AACA,IAAA,OAAO,IAAA,CAAK,GAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,KAAK,GAAA,EAAK;AACZ,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,KAAK,UAAA,EAAW;AAE/B,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,GAAA,GAAM,MAAM,MAAA,CAAO,SAAA,CAAU,SAAS,IAAA,CAAK,OAAA,EAAS,KAAK,EAAE,CAAA;AAChE,MAAA,IAAA,CAAK,UAAA,uBAAiB,IAAA,EAAK;AAC3B,MAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,iCAAA,EAAoC,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AAC5E,MAAA;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,EAAE,iBAAiBC,mBAAA,CAAA,EAAgB;AACrC,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF;AAEA,IAAA,MAAM,GAAA,GAAW,MAAM,MAAA,CAAO,IAAA,CAAK,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,eAAA,EAAiB,IAAA,EAAM,CAAA;AAEnF,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,0BAAA,EAA6B,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AACrE,MAAA,IAAA,CAAK,MAAM,MAAM,MAAA,CAAO,UAAU,MAAA,CAAO,GAAA,EAAK,KAAK,cAAA,EAAgB;AAAA,QACjE,MAAM,IAAA,CAAK,EAAA;AAAA,QACX,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB,GAAA,EAAK,OAAO,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,GAAA,GAAM,MAAA;AAAA,QACnD,SAAS,IAAA,CAAK;AAAA,OACf,CAAA;AACD,MAAA,IAAA,CAAK,UAAA,uBAAiB,IAAA,EAAK;AAC3B,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,uCAAuC,IAAA,CAAK,GAAA,EAAK,SAAS,CAAA,CAAE,CAAA;AAC3F,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAe,MAAA,CAAO,MAAA,CAAO,YAAA,CAAa,KAAK,SAAS,CAAA;AAC9D,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,mBAAA,EAAsB,KAAK,EAAE,CAAA,aAAA,EAAgB,IAAA,CAAK,SAAS,CAAA,CAAA,CAAG,CAAA;AAC7F,IAAA,IAAA,CAAK,MAAM,MAAM,MAAA,CAAO,SAAA,CAAU,MAAA,CAAO,KAAK,KAAA,EAAO;AAAA,MACnD,MAAM,IAAA,CAAK,EAAA;AAAA,MACX,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,GAAA,EAAK,OAAO,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,GAAA,GAAM,MAAA;AAAA,MACnD,SAAS,IAAA,CAAK;AAAA,KACf,CAAA;AACD,IAAA,IAAA,CAAK,UAAA,uBAAiB,IAAA,EAAK;AAC3B,IAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,qBAAqB,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,CAAE,CAAA;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,IAAA,GAAsB;AAC1B,IAAA,IAAI,CAAC,KAAK,GAAA,EAAK;AAEf,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,SAAA,CAAU,IAAA,EAAK;AACxC,MAAA,MAAM,QAAQ,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,KAAK,SAAA,CAAU,IAAA,CAAK,CAAA,CAAE,GAAG,CAAC,CAAC,CAAA;AAAA,IACrF,CAAA,CAAA,MAAQ;AAAA,IAER;AAEA,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,cAAA,GAAiB,MAAM,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAmB;AACxD,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,sBAAsB,IAAA,CAAK,cAAA,CAAe,OAAO,CAAA,CAAE,CAAA;AAAA,IACpF,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,mDAAmD,KAAK,CAAA;AAAA,IACzF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,GAAA,CAAI,SAAA,CAAU,EAAE,IAAA,EAAM,MAAM,CAAA;AACvC,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,wBAAwB,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,CAAE,CAAA;AAC3E,MAAA,IAAA,CAAK,GAAA,GAAM,IAAA;AAAA,IACb,SAAS,KAAA,EAAO;AAEd,MAAA,IAAI,IAAA,CAAK,kBAAA,CAAmB,KAAK,CAAA,EAAG;AAClC,QAAA,IAAA,CAAK,GAAA,GAAM,IAAA;AAAA,MACb,CAAA,MAAO;AACL,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,OAAA,GAAyB;AAC7B,IAAA,IAAI,KAAK,GAAA,EAAK;AACZ,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,SAAA,CAAU,IAAA,EAAK;AACxC,QAAA,MAAM,QAAQ,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,KAAK,SAAA,CAAU,IAAA,CAAK,CAAA,CAAE,GAAG,CAAC,CAAC,CAAA;AAAA,MACrF,CAAA,CAAA,MAAQ;AAAA,MAER;AAEA,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,IAAI,SAAA,EAAU;AACzB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,wBAAwB,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,CAAE,CAAA;AAAA,MAC7E,CAAA,CAAA,MAAQ;AAAA,MAER;AAEA,MAAA,IAAA,CAAK,GAAA,GAAM,IAAA;AAAA,IACb;AAEA,IAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AAAA,EACxB;AAAA,EAEA,MAAM,OAAA,GAAgC;AACpC,IAAA,OAAO;AAAA,MACL,IAAI,IAAA,CAAK,EAAA;AAAA,MACT,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAA,EAAW,IAAA,CAAK,UAAA,oBAAc,IAAI,IAAA,EAAK;AAAA,MACvC,QAAA,EAAU;AAAA,QACR,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,KAAA,EAAO,IAAA,CAAK,cAAA,EAAgB,OAAA,IAAW,IAAA,CAAK,SAAA;AAAA,QAC5C,WAAW,IAAA,CAAK;AAAA;AAClB,KACF;AAAA,EACF;AAAA,EAEA,eAAA,GAA0B;AACxB,IAAA,MAAM,mBAAA,GAAsB,KAAK,uBAAA,EAAwB;AACzD,IAAA,IAAI,IAAA,CAAK,qBAAA,KAA0B,MAAA,EAAW,OAAO,mBAAA;AACrD,IAAA,IAAI,OAAO,IAAA,CAAK,qBAAA,KAA0B,QAAA,SAAiB,IAAA,CAAK,qBAAA;AAChE,IAAA,OAAO,IAAA,CAAK,qBAAA,CAAsB,EAAE,mBAAA,EAAqB,CAAA;AAAA,EAC3D;AAAA,EAEQ,uBAAA,GAAkC;AACxC,IAAA,OAAO,CAAA,4BAAA,EAA+B,KAAK,SAAS,CAAA,6CAAA,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,KAAA,EAAyB;AAClD,IAAA,IAAI,CAAC,OAAO,OAAO,KAAA;AACnB,IAAA,IAAI,KAAA,YAAiBC,yBAAmB,OAAO,IAAA;AAC/C,IAAA,IAAI,KAAA,YAAiBD,qBAAe,OAAO,IAAA;AAC3C,IAAA,MAAM,QAAA,GAAW,OAAO,KAAK,CAAA;AAC7B,IAAA,OACE,QAAA,CAAS,QAAA,CAAS,mBAAmB,CAAA,IACrC,SAAS,QAAA,CAAS,qBAAqB,CAAA,IACvC,QAAA,CAAS,QAAA,CAAS,mBAAmB,CAAA,IACrC,QAAA,CAAS,SAAS,eAAe,CAAA;AAAA,IAEjC,kBAAkB,IAAA,CAAK,QAAQ,CAAA,IAC/B,QAAA,CAAS,SAAS,WAAW,CAAA;AAAA,EAEjC;AAAA,EAEQ,iBAAA,GAA0B;AAChC,IAAA,IAAA,CAAK,GAAA,GAAM,IAAA;AACX,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA;AAAA,EAChB;AAAA;AAAA,EAGA,MAAM,YAAe,EAAA,EAAkC;AACrD,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,EAAA,EAAG;AAAA,IAClB,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,KAAK,kBAAA,CAAmB,KAAK,CAAA,IAAK,CAAC,KAAK,WAAA,EAAa;AACvD,QAAA,IAAA,CAAK,iBAAA,EAAkB;AACvB,QAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,QAAA,IAAI;AACF,UAAA,MAAM,KAAK,aAAA,EAAc;AACzB,UAAA,OAAO,MAAM,EAAA,EAAG;AAAA,QAClB,CAAA,SAAE;AACA,UAAA,IAAA,CAAK,WAAA,GAAc,KAAA;AAAA,QACrB;AAAA,MACF;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAA,GAAsB;AAC5B,IAAA,OAAO,iBAAiB,IAAA,CAAK,GAAA,EAAI,CAAE,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,EAAE,EAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAAA,EAC3F;AAAA,EAEQ,UAAA,GAA0B;AAChC,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,MAAA,IAAA,CAAK,OAAA,GAAU,IAAIE,iBAAA,CAAY;AAAA,QAC7B,GAAI,IAAA,CAAK,OAAA,IAAW,EAAE,OAAA,EAAS,KAAK,OAAA,EAAQ;AAAA,QAC5C,GAAI,IAAA,CAAK,WAAA,IAAe,EAAE,WAAA,EAAa,KAAK,WAAA;AAAY,OACzD,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AACF","file":"index.cjs","sourcesContent":["/**\n * Modal process manager. Each spawn() creates a ContainerProcess via exec().\n * kill() has no SDK equivalent — it cancels stream readers locally; the remote\n * process runs until the sandbox timeout.\n */\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { ContainerProcess } from 'modal';\nimport type { ModalSandbox } from './index';\n\n// =============================================================================\n// Modal Process Handle\n// =============================================================================\n\n/**\n * Wraps a Modal ContainerProcess to conform to Mastra's ProcessHandle.\n */\nclass ModalProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _proc: ContainerProcess<string>;\n private readonly _startTime: number;\n private readonly _timeout?: number;\n\n private _exitCode: number | undefined;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _streamingPromise: Promise<void> | null = null;\n private _killed = false;\n private _stdoutReader: ReadableStreamDefaultReader<string> | null = null;\n private _stderrReader: ReadableStreamDefaultReader<string> | null = null;\n\n constructor(pid: string, proc: ContainerProcess<string>, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = pid;\n this._proc = proc;\n this._startTime = startTime;\n this._timeout = options?.timeout;\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n /** @internal Set by the process manager after streaming starts. */\n set streamingPromise(p: Promise<void>) {\n this._streamingPromise = p;\n\n // Resolve exit code when streaming ends so exitCode is available without calling wait()\n p.then(() => this._resolveExitCode()).catch(() => this._resolveExitCode());\n }\n\n /** @internal Set by the process manager so kill() can cancel the readers. */\n setReaders(\n stdoutReader: ReadableStreamDefaultReader<string>,\n stderrReader: ReadableStreamDefaultReader<string>,\n ): void {\n this._stdoutReader = stdoutReader;\n this._stderrReader = stderrReader;\n }\n\n /** Fetch the exit code from the Modal process. No-op if already set. */\n private async _resolveExitCode(): Promise<void> {\n if (this._exitCode !== undefined) return;\n try {\n this._exitCode = await this._proc.wait();\n } catch {\n if (this._exitCode === undefined) {\n this._exitCode = 1;\n }\n }\n }\n\n async wait(): Promise<CommandResult> {\n if (!this._waitPromise) {\n this._waitPromise = this._doWait();\n }\n return this._waitPromise;\n }\n\n private async _doWait(): Promise<CommandResult> {\n const streamDone = this._streamingPromise ?? Promise.resolve();\n\n if (this._timeout) {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error(`Command timed out after ${this._timeout}ms`)), this._timeout);\n });\n\n try {\n await Promise.race([streamDone, timeoutPromise]);\n } catch (error) {\n if (error instanceof Error && error.message.includes('timed out')) {\n await this.kill();\n this._exitCode = 124; // conventional timeout exit code\n return {\n success: false,\n exitCode: 124,\n stdout: this.stdout,\n stderr: this.stderr || error.message,\n executionTimeMs: Date.now() - this._startTime,\n };\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n } else {\n await streamDone.catch(() => {});\n }\n\n if (this._killed) {\n return {\n success: false,\n exitCode: this._exitCode ?? 137,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n };\n }\n\n await this._resolveExitCode();\n\n return {\n success: this._exitCode === 0,\n exitCode: this._exitCode ?? 1,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n };\n }\n\n async kill(): Promise<boolean> {\n if (this._exitCode !== undefined) return false;\n this._killed = true;\n this._exitCode = 137; // SIGKILL\n // The remote process may continue running; Modal JS SDK has no per-exec kill.\n try {\n await this._stdoutReader?.cancel();\n } catch {\n // Ignore cancellation errors\n }\n try {\n await this._stderrReader?.cancel();\n } catch {\n // Ignore cancellation errors\n }\n return true;\n }\n\n async sendStdin(_data: string): Promise<void> {\n throw new Error('Modal JS SDK does not expose stdin on exec() — sendStdin() is not supported');\n }\n}\n\n// =============================================================================\n// Modal Process Manager\n// =============================================================================\n\nexport interface ModalProcessManagerOptions {\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Modal implementation of SandboxProcessManager.\n * Uses the Modal SDK's exec() API with one ContainerProcess per spawn.\n */\nexport class ModalProcessManager extends SandboxProcessManager<ModalSandbox> {\n private _spawnCounter = 0;\n\n constructor(opts: ModalProcessManagerOptions = {}) {\n super({ env: opts.env });\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n return this.sandbox.retryOnDead(async () => {\n const sb = this.sandbox.modal;\n\n const mergedEnv = { ...this.env, ...options.env };\n const env = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n // exec() takes string[] — wrap in sh -c to support pipes, redirects, etc.\n const argv = ['sh', '-c', command];\n\n const proc = await sb.exec(argv, {\n env: Object.keys(env).length > 0 ? env : undefined,\n workdir: options.cwd,\n timeoutMs: options.timeout,\n });\n\n const pid = `modal-proc-${Date.now().toString(36)}-${++this._spawnCounter}`;\n const handle = new ModalProcessHandle(pid, proc, Date.now(), options);\n\n const stdoutReader = proc.stdout.getReader();\n const stderrReader = proc.stderr.getReader();\n handle.setReaders(stdoutReader, stderrReader);\n\n const streamingPromise = Promise.all([\n drainReader(stdoutReader, chunk => handle.emitStdout(chunk)),\n drainReader(stderrReader, chunk => handle.emitStderr(chunk)),\n ]).then(() => {});\n\n handle.streamingPromise = streamingPromise;\n\n this._tracked.set(pid, handle);\n return handle;\n });\n }\n\n async list(): Promise<ProcessInfo[]> {\n const result: ProcessInfo[] = [];\n for (const [pid, handle] of this._tracked) {\n result.push({\n pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n exitCode: handle.exitCode,\n });\n }\n return result;\n }\n}\n\n// =============================================================================\n// Stream Helpers\n// =============================================================================\n\n/** Reads chunks from a stream until done or cancelled. */\nasync function drainReader(reader: ReadableStreamDefaultReader<string>, emit: (chunk: string) => void): Promise<void> {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n emit(value);\n }\n } catch {\n // cancelled or network error\n }\n}\n","/**\n * @see https://modal.com/docs/reference/modal.Sandbox\n */\n\nimport type { MastraSandboxOptions, ProviderStatus, SandboxInfo } from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { ClientClosedError, ModalClient, NotFoundError } from 'modal';\nimport type { App, Image, Sandbox } from 'modal';\nimport { ModalProcessManager } from './process-manager';\n\nconst LOG_PREFIX = '[ModalSandbox]';\n\n// =============================================================================\n// Options\n// =============================================================================\n\ntype InstructionsOption = string | ((opts: { defaultInstructions: string }) => string);\n\n/**\n * Modal sandbox provider configuration.\n */\nexport interface ModalSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Stable name for this sandbox. Reusing the same id reconnects to a running sandbox. */\n id?: string;\n /**\n * Modal App name to associate sandboxes with.\n *\n * @default 'mastra'\n */\n appName?: string;\n /**\n * Docker image to use for the sandbox.\n *\n * @default 'ubuntu:22.04'\n */\n baseImage?: string;\n /**\n * Wall-clock max lifetime in milliseconds. The sandbox is terminated when this expires,\n * regardless of activity. Modal's maximum is 24 hours (86_400_000).\n *\n * @default 300_000 // 5 minutes\n */\n timeoutMs?: number;\n /** Environment variables baked into the sandbox at create time. */\n env?: Record<string, string>;\n /** Default working directory inside the sandbox. */\n workdir?: string;\n /** Modal token ID. Falls back to MODAL_TOKEN_ID env var. */\n tokenId?: string;\n /** Modal token secret. Falls back to MODAL_TOKEN_SECRET env var. */\n tokenSecret?: string;\n /** Custom instructions for getInstructions(). String replaces the default; function receives it. */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// ModalSandbox\n// =============================================================================\n\n/**\n * Modal cloud sandbox provider for Mastra workspaces.\n *\n * @example\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { ModalSandbox } from '@mastra/modal';\n *\n * const sandbox = new ModalSandbox({\n * baseImage: 'ubuntu:22.04',\n * timeoutMs: 60_000,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCommand('echo hello');\n * ```\n */\nexport class ModalSandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'ModalSandbox';\n readonly provider = 'modal';\n status: ProviderStatus = 'pending';\n\n declare readonly processes: ModalProcessManager;\n\n private _sb: Sandbox | null = null;\n private _imageSnapshot: Image | null = null; // for stop-and-resume\n private _client: ModalClient | null = null;\n private _createdAt: Date | null = null;\n private _isRetrying = false;\n\n private readonly appName: string;\n private readonly baseImage: string;\n private readonly timeoutMs: number;\n private readonly env: Record<string, string>;\n private readonly workdir?: string;\n private readonly tokenId?: string;\n private readonly tokenSecret?: string;\n private readonly _instructionsOverride?: InstructionsOption;\n\n constructor(options: ModalSandboxOptions = {}) {\n super({\n ...options,\n name: 'ModalSandbox',\n processes: new ModalProcessManager({ env: options.env ?? {} }),\n });\n\n this.id = options.id ?? this._generateId();\n this.appName = options.appName ?? 'mastra';\n this.baseImage = options.baseImage ?? 'ubuntu:22.04';\n this.timeoutMs = options.timeoutMs ?? 300_000;\n this.env = options.env ?? {};\n this.workdir = options.workdir;\n this.tokenId = options.tokenId;\n this.tokenSecret = options.tokenSecret;\n this._instructionsOverride = options.instructions;\n }\n\n /**\n * Get the underlying Modal Sandbox instance for direct SDK access.\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n */\n get modal(): Sandbox {\n if (!this._sb) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._sb;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /** Reconnects to a running sandbox with this id if one exists, otherwise creates a new one. */\n async start(): Promise<void> {\n if (this._sb) {\n return;\n }\n\n const client = this._getClient();\n\n try {\n this._sb = await client.sandboxes.fromName(this.appName, this.id);\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Reconnected to running sandbox: ${this.id}`);\n return;\n } catch (error) {\n if (!(error instanceof NotFoundError)) {\n throw error;\n }\n }\n\n const app: App = await client.apps.fromName(this.appName, { createIfMissing: true });\n\n if (this._imageSnapshot) {\n this.logger.debug(`${LOG_PREFIX} Rebooting from snapshot: ${this.id}`);\n this._sb = await client.sandboxes.create(app, this._imageSnapshot, {\n name: this.id,\n timeoutMs: this.timeoutMs,\n env: Object.keys(this.env).length > 0 ? this.env : undefined,\n workdir: this.workdir,\n });\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Created new sandbox from snapshot: ${this._sb?.sandboxId}`);\n return;\n }\n\n const image: Image = client.images.fromRegistry(this.baseImage);\n this.logger.debug(`${LOG_PREFIX} Creating sandbox: ${this.id} (baseImage: ${this.baseImage})`);\n this._sb = await client.sandboxes.create(app, image, {\n name: this.id,\n timeoutMs: this.timeoutMs,\n env: Object.keys(this.env).length > 0 ? this.env : undefined,\n workdir: this.workdir,\n });\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Created sandbox: ${this._sb.sandboxId}`);\n }\n\n /**\n * Snapshot the sandbox filesystem before terminating it.\n * Future starts will create net-new sandboxes from the snapshot.\n */\n async stop(): Promise<void> {\n if (!this._sb) return;\n\n try {\n const procs = await this.processes.list();\n await Promise.all(procs.filter(p => p.running).map(p => this.processes.kill(p.pid)));\n } catch {\n // Best-effort: sandbox may already be dead\n }\n\n try {\n this._imageSnapshot = await this._sb.snapshotFilesystem();\n this.logger.debug(`${LOG_PREFIX} Snapshot created: ${this._imageSnapshot.imageId}`);\n } catch (error) {\n this.logger.debug(`${LOG_PREFIX} Snapshot failed, terminating without snapshot:`, error);\n }\n\n try {\n await this._sb.terminate({ wait: true });\n this.logger.debug(`${LOG_PREFIX} Sandbox terminated: ${this._sb.sandboxId}`);\n this._sb = null;\n } catch (error) {\n // Best-effort: sandbox may already be dead\n if (this.isSandboxDeadError(error)) {\n this._sb = null;\n } else {\n throw error;\n }\n }\n }\n\n /** Terminates the sandbox, ending its lifetime. Unlike stop(), no snapshot is preserved. */\n async destroy(): Promise<void> {\n if (this._sb) {\n try {\n const procs = await this.processes.list();\n await Promise.all(procs.filter(p => p.running).map(p => this.processes.kill(p.pid)));\n } catch {\n // Best-effort: sandbox may already be dead\n }\n\n try {\n await this._sb.terminate();\n this.logger.debug(`${LOG_PREFIX} Sandbox terminated: ${this._sb.sandboxId}`);\n } catch {\n // Ignore errors during destroy\n }\n\n this._sb = null;\n }\n\n this._imageSnapshot = null;\n }\n\n async getInfo(): Promise<SandboxInfo> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: this._createdAt ?? new Date(),\n metadata: {\n appName: this.appName,\n image: this._imageSnapshot?.imageId ?? this.baseImage,\n timeoutMs: this.timeoutMs,\n },\n };\n }\n\n getInstructions(): string {\n const defaultInstructions = this._getDefaultInstructions();\n if (this._instructionsOverride === undefined) return defaultInstructions;\n if (typeof this._instructionsOverride === 'string') return this._instructionsOverride;\n return this._instructionsOverride({ defaultInstructions });\n }\n\n private _getDefaultInstructions(): string {\n return `Modal cloud sandbox running ${this.baseImage}. Use executeCommand() to run shell commands.`;\n }\n\n // ---------------------------------------------------------------------------\n // Dead-sandbox Retry\n // ---------------------------------------------------------------------------\n\n private isSandboxDeadError(error: unknown): boolean {\n if (!error) return false;\n if (error instanceof ClientClosedError) return true;\n if (error instanceof NotFoundError) return true;\n const errorStr = String(error);\n return (\n errorStr.includes('sandbox not found') ||\n errorStr.includes('has been terminated') ||\n errorStr.includes('already completed') ||\n errorStr.includes('was cancelled') ||\n // gRPC NOT_FOUND (code 5)\n /status[:\\s]+5\\b/.test(errorStr) ||\n errorStr.includes('NOT_FOUND')\n );\n }\n\n private handleSandboxDead(): void {\n this._sb = null;\n this.status = 'stopped';\n }\n\n /** @internal Retries fn() once after restarting if the sandbox is dead. */\n async retryOnDead<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (this.isSandboxDeadError(error) && !this._isRetrying) {\n this.handleSandboxDead();\n this._isRetrying = true;\n try {\n await this.ensureRunning();\n return await fn();\n } finally {\n this._isRetrying = false;\n }\n }\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Internal Helpers\n // ---------------------------------------------------------------------------\n\n private _generateId(): string {\n return `modal-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n private _getClient(): ModalClient {\n if (!this._client) {\n this._client = new ModalClient({\n ...(this.tokenId && { tokenId: this.tokenId }),\n ...(this.tokenSecret && { tokenSecret: this.tokenSecret }),\n });\n }\n return this._client;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/sandbox/process-manager.ts","../src/sandbox/index.ts"],"names":["ProcessHandle","SandboxProcessManager","MastraSandbox","SandboxNotReadyError","NotFoundError","ClientClosedError","ModalClient"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Modal process manager. Each spawn() creates a ContainerProcess via exec().\n * kill() has no SDK equivalent — it cancels stream readers locally; the remote\n * process runs until the sandbox timeout.\n */\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { ContainerProcess } from 'modal';\nimport type { ModalSandbox } from './index';\n\n// =============================================================================\n// Modal Process Handle\n// =============================================================================\n\n/**\n * Wraps a Modal ContainerProcess to conform to Mastra's ProcessHandle.\n */\nclass ModalProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _proc: ContainerProcess<string>;\n private readonly _startTime: number;\n private readonly _timeout?: number;\n\n private _exitCode: number | undefined;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _streamingPromise: Promise<void> | null = null;\n private _killed = false;\n private _stdoutReader: ReadableStreamDefaultReader<string> | null = null;\n private _stderrReader: ReadableStreamDefaultReader<string> | null = null;\n\n constructor(pid: string, proc: ContainerProcess<string>, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = pid;\n this._proc = proc;\n this._startTime = startTime;\n this._timeout = options?.timeout;\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n /** @internal Set by the process manager after streaming starts. */\n set streamingPromise(p: Promise<void>) {\n this._streamingPromise = p;\n\n // Resolve exit code when streaming ends so exitCode is available without calling wait()\n p.then(() => this._resolveExitCode()).catch(() => this._resolveExitCode());\n }\n\n /** @internal Set by the process manager so kill() can cancel the readers. */\n setReaders(\n stdoutReader: ReadableStreamDefaultReader<string>,\n stderrReader: ReadableStreamDefaultReader<string>,\n ): void {\n this._stdoutReader = stdoutReader;\n this._stderrReader = stderrReader;\n }\n\n /** Fetch the exit code from the Modal process. No-op if already set. */\n private async _resolveExitCode(): Promise<void> {\n if (this._exitCode !== undefined) return;\n try {\n this._exitCode = await this._proc.wait();\n } catch {\n if (this._exitCode === undefined) {\n this._exitCode = 1;\n }\n }\n }\n\n async wait(): Promise<CommandResult> {\n if (!this._waitPromise) {\n this._waitPromise = this._doWait();\n }\n return this._waitPromise;\n }\n\n private async _doWait(): Promise<CommandResult> {\n const streamDone = this._streamingPromise ?? Promise.resolve();\n\n if (this._timeout) {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error(`Command timed out after ${this._timeout}ms`)), this._timeout);\n });\n\n try {\n await Promise.race([streamDone, timeoutPromise]);\n } catch (error) {\n if (error instanceof Error && error.message.includes('timed out')) {\n await this.kill();\n this._exitCode = 124; // conventional timeout exit code\n return {\n success: false,\n exitCode: 124,\n stdout: this.stdout,\n stderr: this.stderr || error.message,\n executionTimeMs: Date.now() - this._startTime,\n killed: true,\n timedOut: true,\n };\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n } else {\n await streamDone.catch(() => {});\n }\n\n if (this._killed) {\n return {\n success: false,\n exitCode: this._exitCode ?? 137,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n killed: true,\n timedOut: false,\n };\n }\n\n await this._resolveExitCode();\n\n return {\n success: this._exitCode === 0,\n exitCode: this._exitCode ?? 1,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n };\n }\n\n async kill(): Promise<boolean> {\n if (this._exitCode !== undefined) return false;\n this._killed = true;\n this._exitCode = 137; // SIGKILL\n // The remote process may continue running; Modal JS SDK has no per-exec kill.\n try {\n await this._stdoutReader?.cancel();\n } catch {\n // Ignore cancellation errors\n }\n try {\n await this._stderrReader?.cancel();\n } catch {\n // Ignore cancellation errors\n }\n return true;\n }\n\n async sendStdin(_data: string): Promise<void> {\n throw new Error('Modal JS SDK does not expose stdin on exec() — sendStdin() is not supported');\n }\n}\n\n// =============================================================================\n// Modal Process Manager\n// =============================================================================\n\nexport interface ModalProcessManagerOptions {\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Modal implementation of SandboxProcessManager.\n * Uses the Modal SDK's exec() API with one ContainerProcess per spawn.\n */\nexport class ModalProcessManager extends SandboxProcessManager<ModalSandbox> {\n private _spawnCounter = 0;\n\n constructor(opts: ModalProcessManagerOptions = {}) {\n super({ env: opts.env });\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n return this.sandbox.retryOnDead(async () => {\n const sb = this.sandbox.modal;\n\n const mergedEnv = { ...this.env, ...options.env };\n const env = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n // exec() takes string[] — wrap in sh -c to support pipes, redirects, etc.\n const argv = ['sh', '-c', command];\n\n const proc = await sb.exec(argv, {\n env: Object.keys(env).length > 0 ? env : undefined,\n workdir: options.cwd,\n timeoutMs: options.timeout,\n });\n\n const pid = `modal-proc-${Date.now().toString(36)}-${++this._spawnCounter}`;\n const handle = new ModalProcessHandle(pid, proc, Date.now(), options);\n\n const stdoutReader = proc.stdout.getReader();\n const stderrReader = proc.stderr.getReader();\n handle.setReaders(stdoutReader, stderrReader);\n\n const streamingPromise = Promise.all([\n drainReader(stdoutReader, chunk => handle.emitStdout(chunk)),\n drainReader(stderrReader, chunk => handle.emitStderr(chunk)),\n ]).then(() => {});\n\n handle.streamingPromise = streamingPromise;\n\n this._tracked.set(pid, handle);\n return handle;\n });\n }\n\n async list(): Promise<ProcessInfo[]> {\n const result: ProcessInfo[] = [];\n for (const [pid, handle] of this._tracked) {\n result.push({\n pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n exitCode: handle.exitCode,\n });\n }\n return result;\n }\n}\n\n// =============================================================================\n// Stream Helpers\n// =============================================================================\n\n/** Reads chunks from a stream until done or cancelled. */\nasync function drainReader(reader: ReadableStreamDefaultReader<string>, emit: (chunk: string) => void): Promise<void> {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n emit(value);\n }\n } catch {\n // cancelled or network error\n }\n}\n","/**\n * @see https://modal.com/docs/reference/modal.Sandbox\n */\n\nimport type { MastraSandboxOptions, ProviderStatus, SandboxInfo } from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { ClientClosedError, ModalClient, NotFoundError } from 'modal';\nimport type { App, Image, Sandbox } from 'modal';\nimport { ModalProcessManager } from './process-manager';\n\nconst LOG_PREFIX = '[ModalSandbox]';\n\n// =============================================================================\n// Options\n// =============================================================================\n\ntype InstructionsOption = string | ((opts: { defaultInstructions: string }) => string);\n\n/**\n * Modal sandbox provider configuration.\n */\nexport interface ModalSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Stable name for this sandbox. Reusing the same id reconnects to a running sandbox. */\n id?: string;\n /**\n * Modal App name to associate sandboxes with.\n *\n * @default 'mastra'\n */\n appName?: string;\n /**\n * Docker image to use for the sandbox.\n *\n * @default 'ubuntu:22.04'\n */\n baseImage?: string;\n /**\n * Wall-clock max lifetime in milliseconds. The sandbox is terminated when this expires,\n * regardless of activity. Modal's maximum is 24 hours (86_400_000).\n *\n * @default 300_000 // 5 minutes\n */\n timeoutMs?: number;\n /** Environment variables baked into the sandbox at create time. */\n env?: Record<string, string>;\n /** Default working directory inside the sandbox. */\n workdir?: string;\n /** Modal token ID. Falls back to MODAL_TOKEN_ID env var. */\n tokenId?: string;\n /** Modal token secret. Falls back to MODAL_TOKEN_SECRET env var. */\n tokenSecret?: string;\n /** Custom instructions for getInstructions(). String replaces the default; function receives it. */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// ModalSandbox\n// =============================================================================\n\n/**\n * Modal cloud sandbox provider for Mastra workspaces.\n *\n * @example\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { ModalSandbox } from '@mastra/modal';\n *\n * const sandbox = new ModalSandbox({\n * baseImage: 'ubuntu:22.04',\n * timeoutMs: 60_000,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCommand('echo hello');\n * ```\n */\nexport class ModalSandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'ModalSandbox';\n readonly provider = 'modal';\n status: ProviderStatus = 'pending';\n\n declare readonly processes: ModalProcessManager;\n\n private _sb: Sandbox | null = null;\n private _imageSnapshot: Image | null = null; // for stop-and-resume\n private _client: ModalClient | null = null;\n private _createdAt: Date | null = null;\n private _isRetrying = false;\n\n private readonly appName: string;\n private readonly baseImage: string;\n private readonly timeoutMs: number;\n private readonly env: Record<string, string>;\n private readonly workdir?: string;\n private readonly tokenId?: string;\n private readonly tokenSecret?: string;\n private readonly _instructionsOverride?: InstructionsOption;\n\n constructor(options: ModalSandboxOptions = {}) {\n super({\n ...options,\n name: 'ModalSandbox',\n processes: new ModalProcessManager({ env: options.env ?? {} }),\n });\n\n this.id = options.id ?? this._generateId();\n this.appName = options.appName ?? 'mastra';\n this.baseImage = options.baseImage ?? 'ubuntu:22.04';\n this.timeoutMs = options.timeoutMs ?? 300_000;\n this.env = options.env ?? {};\n this.workdir = options.workdir;\n this.tokenId = options.tokenId;\n this.tokenSecret = options.tokenSecret;\n this._instructionsOverride = options.instructions;\n }\n\n /**\n * Get the underlying Modal Sandbox instance for direct SDK access.\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n */\n get modal(): Sandbox {\n if (!this._sb) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._sb;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /** Reconnects to a running sandbox with this id if one exists, otherwise creates a new one. */\n async start(): Promise<void> {\n if (this._sb) {\n return;\n }\n\n const client = this._getClient();\n\n try {\n this._sb = await client.sandboxes.fromName(this.appName, this.id);\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Reconnected to running sandbox: ${this.id}`);\n return;\n } catch (error) {\n if (!(error instanceof NotFoundError)) {\n throw error;\n }\n }\n\n const app: App = await client.apps.fromName(this.appName, { createIfMissing: true });\n\n if (this._imageSnapshot) {\n this.logger.debug(`${LOG_PREFIX} Rebooting from snapshot: ${this.id}`);\n this._sb = await client.sandboxes.create(app, this._imageSnapshot, {\n name: this.id,\n timeoutMs: this.timeoutMs,\n env: Object.keys(this.env).length > 0 ? this.env : undefined,\n workdir: this.workdir,\n });\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Created new sandbox from snapshot: ${this._sb?.sandboxId}`);\n return;\n }\n\n const image: Image = client.images.fromRegistry(this.baseImage);\n this.logger.debug(`${LOG_PREFIX} Creating sandbox: ${this.id} (baseImage: ${this.baseImage})`);\n this._sb = await client.sandboxes.create(app, image, {\n name: this.id,\n timeoutMs: this.timeoutMs,\n env: Object.keys(this.env).length > 0 ? this.env : undefined,\n workdir: this.workdir,\n });\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Created sandbox: ${this._sb.sandboxId}`);\n }\n\n /**\n * Snapshot the sandbox filesystem before terminating it.\n * Future starts will create net-new sandboxes from the snapshot.\n */\n async stop(): Promise<void> {\n if (!this._sb) return;\n\n try {\n const procs = await this.processes.list();\n await Promise.all(procs.filter(p => p.running).map(p => this.processes.kill(p.pid)));\n } catch {\n // Best-effort: sandbox may already be dead\n }\n\n try {\n this._imageSnapshot = await this._sb.snapshotFilesystem();\n this.logger.debug(`${LOG_PREFIX} Snapshot created: ${this._imageSnapshot.imageId}`);\n } catch (error) {\n this.logger.debug(`${LOG_PREFIX} Snapshot failed, terminating without snapshot:`, error);\n }\n\n try {\n await this._sb.terminate({ wait: true });\n this.logger.debug(`${LOG_PREFIX} Sandbox terminated: ${this._sb.sandboxId}`);\n this._sb = null;\n } catch (error) {\n // Best-effort: sandbox may already be dead\n if (this.isSandboxDeadError(error)) {\n this._sb = null;\n } else {\n throw error;\n }\n }\n }\n\n /** Terminates the sandbox, ending its lifetime. Unlike stop(), no snapshot is preserved. */\n async destroy(): Promise<void> {\n if (this._sb) {\n try {\n const procs = await this.processes.list();\n await Promise.all(procs.filter(p => p.running).map(p => this.processes.kill(p.pid)));\n } catch {\n // Best-effort: sandbox may already be dead\n }\n\n try {\n await this._sb.terminate();\n this.logger.debug(`${LOG_PREFIX} Sandbox terminated: ${this._sb.sandboxId}`);\n } catch {\n // Ignore errors during destroy\n }\n\n this._sb = null;\n }\n\n this._imageSnapshot = null;\n }\n\n async getInfo(): Promise<SandboxInfo> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: this._createdAt ?? new Date(),\n metadata: {\n appName: this.appName,\n image: this._imageSnapshot?.imageId ?? this.baseImage,\n timeoutMs: this.timeoutMs,\n },\n };\n }\n\n getInstructions(): string {\n const defaultInstructions = this._getDefaultInstructions();\n if (this._instructionsOverride === undefined) return defaultInstructions;\n if (typeof this._instructionsOverride === 'string') return this._instructionsOverride;\n return this._instructionsOverride({ defaultInstructions });\n }\n\n private _getDefaultInstructions(): string {\n return `Modal cloud sandbox running ${this.baseImage}. Use executeCommand() to run shell commands.`;\n }\n\n // ---------------------------------------------------------------------------\n // Dead-sandbox Retry\n // ---------------------------------------------------------------------------\n\n private isSandboxDeadError(error: unknown): boolean {\n if (!error) return false;\n if (error instanceof ClientClosedError) return true;\n if (error instanceof NotFoundError) return true;\n const errorStr = String(error);\n return (\n errorStr.includes('sandbox not found') ||\n errorStr.includes('has been terminated') ||\n errorStr.includes('already completed') ||\n errorStr.includes('was cancelled') ||\n // gRPC NOT_FOUND (code 5)\n /status[:\\s]+5\\b/.test(errorStr) ||\n errorStr.includes('NOT_FOUND')\n );\n }\n\n private handleSandboxDead(): void {\n this._sb = null;\n this.status = 'stopped';\n }\n\n /** @internal Retries fn() once after restarting if the sandbox is dead. */\n async retryOnDead<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (this.isSandboxDeadError(error) && !this._isRetrying) {\n this.handleSandboxDead();\n this._isRetrying = true;\n try {\n await this.ensureRunning();\n return await fn();\n } finally {\n this._isRetrying = false;\n }\n }\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Internal Helpers\n // ---------------------------------------------------------------------------\n\n private _generateId(): string {\n return `modal-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n private _getClient(): ModalClient {\n if (!this._client) {\n this._client = new ModalClient({\n ...(this.tokenId && { tokenId: this.tokenId }),\n ...(this.tokenSecret && { tokenSecret: this.tokenSecret }),\n });\n }\n return this._client;\n }\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -68,7 +68,9 @@ var ModalProcessHandle = class extends ProcessHandle {
|
|
|
68
68
|
exitCode: 124,
|
|
69
69
|
stdout: this.stdout,
|
|
70
70
|
stderr: this.stderr || error.message,
|
|
71
|
-
executionTimeMs: Date.now() - this._startTime
|
|
71
|
+
executionTimeMs: Date.now() - this._startTime,
|
|
72
|
+
killed: true,
|
|
73
|
+
timedOut: true
|
|
72
74
|
};
|
|
73
75
|
}
|
|
74
76
|
throw error;
|
|
@@ -85,7 +87,9 @@ var ModalProcessHandle = class extends ProcessHandle {
|
|
|
85
87
|
exitCode: this._exitCode ?? 137,
|
|
86
88
|
stdout: this.stdout,
|
|
87
89
|
stderr: this.stderr,
|
|
88
|
-
executionTimeMs: Date.now() - this._startTime
|
|
90
|
+
executionTimeMs: Date.now() - this._startTime,
|
|
91
|
+
killed: true,
|
|
92
|
+
timedOut: false
|
|
89
93
|
};
|
|
90
94
|
}
|
|
91
95
|
await this._resolveExitCode();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sandbox/process-manager.ts","../src/sandbox/index.ts"],"names":[],"mappings":";;;;AAkBA,IAAM,kBAAA,GAAN,cAAiC,aAAA,CAAc;AAAA,EACpC,GAAA;AAAA,EAEQ,KAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EAET,SAAA;AAAA,EACA,YAAA,GAA8C,IAAA;AAAA,EAC9C,iBAAA,GAA0C,IAAA;AAAA,EAC1C,OAAA,GAAU,KAAA;AAAA,EACV,aAAA,GAA4D,IAAA;AAAA,EAC5D,aAAA,GAA4D,IAAA;AAAA,EAEpE,WAAA,CAAY,GAAA,EAAa,IAAA,EAAgC,SAAA,EAAmB,OAAA,EAA+B;AACzG,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAClB,IAAA,IAAA,CAAK,WAAW,OAAA,EAAS,OAAA;AAAA,EAC3B;AAAA,EAEA,IAAI,QAAA,GAA+B;AACjC,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,iBAAiB,CAAA,EAAkB;AACrC,IAAA,IAAA,CAAK,iBAAA,GAAoB,CAAA;AAGzB,IAAA,CAAA,CAAE,IAAA,CAAK,MAAM,IAAA,CAAK,gBAAA,EAAkB,EAAE,KAAA,CAAM,MAAM,IAAA,CAAK,gBAAA,EAAkB,CAAA;AAAA,EAC3E;AAAA;AAAA,EAGA,UAAA,CACE,cACA,YAAA,EACM;AACN,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AACrB,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,EACvB;AAAA;AAAA,EAGA,MAAc,gBAAA,GAAkC;AAC9C,IAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAW;AAClC,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,SAAA,GAAY,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,EAAK;AAAA,IACzC,CAAA,CAAA,MAAQ;AACN,MAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAW;AAChC,QAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,IAAA,GAA+B;AACnC,IAAA,IAAI,CAAC,KAAK,YAAA,EAAc;AACtB,MAAA,IAAA,CAAK,YAAA,GAAe,KAAK,OAAA,EAAQ;AAAA,IACnC;AACA,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA,EAEA,MAAc,OAAA,GAAkC;AAC9C,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,iBAAA,IAAqB,OAAA,CAAQ,OAAA,EAAQ;AAE7D,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,IAAI,SAAA;AACJ,MAAA,MAAM,cAAA,GAAiB,IAAI,OAAA,CAAe,CAAC,GAAG,MAAA,KAAW;AACvD,QAAA,SAAA,GAAY,UAAA,CAAW,MAAM,MAAA,CAAO,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,IAAA,CAAK,QAAQ,CAAA,EAAA,CAAI,CAAC,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA;AAAA,MAC7G,CAAC,CAAA;AAED,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,CAAQ,IAAA,CAAK,CAAC,UAAA,EAAY,cAAc,CAAC,CAAA;AAAA,MACjD,SAAS,KAAA,EAAO;AACd,QAAA,IAAI,iBAAiB,KAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA,EAAG;AACjE,UAAA,MAAM,KAAK,IAAA,EAAK;AAChB,UAAA,IAAA,CAAK,SAAA,GAAY,GAAA;AACjB,UAAA,OAAO;AAAA,YACL,OAAA,EAAS,KAAA;AAAA,YACT,QAAA,EAAU,GAAA;AAAA,YACV,QAAQ,IAAA,CAAK,MAAA;AAAA,YACb,MAAA,EAAQ,IAAA,CAAK,MAAA,IAAU,KAAA,CAAM,OAAA;AAAA,YAC7B,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK;AAAA,WACrC;AAAA,QACF;AACA,QAAA,MAAM,KAAA;AAAA,MACR,CAAA,SAAE;AACA,QAAA,YAAA,CAAa,SAAS,CAAA;AAAA,MACxB;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAAM,UAAA,CAAW,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACjC;AAEA,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,QAAA,EAAU,KAAK,SAAA,IAAa,GAAA;AAAA,QAC5B,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK;AAAA,OACrC;AAAA,IACF;AAEA,IAAA,MAAM,KAAK,gBAAA,EAAiB;AAE5B,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAK,SAAA,KAAc,CAAA;AAAA,MAC5B,QAAA,EAAU,KAAK,SAAA,IAAa,CAAA;AAAA,MAC5B,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK;AAAA,KACrC;AAAA,EACF;AAAA,EAEA,MAAM,IAAA,GAAyB;AAC7B,IAAA,IAAI,IAAA,CAAK,SAAA,KAAc,MAAA,EAAW,OAAO,KAAA;AACzC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,SAAA,GAAY,GAAA;AAEjB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,eAAe,MAAA,EAAO;AAAA,IACnC,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,eAAe,MAAA,EAAO;AAAA,IACnC,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,KAAA,EAA8B;AAC5C,IAAA,MAAM,IAAI,MAAM,kFAA6E,CAAA;AAAA,EAC/F;AACF,CAAA;AAcO,IAAM,mBAAA,GAAN,cAAkC,qBAAA,CAAoC;AAAA,EACnE,aAAA,GAAgB,CAAA;AAAA,EAExB,WAAA,CAAY,IAAA,GAAmC,EAAC,EAAG;AACjD,IAAA,KAAA,CAAM,EAAE,GAAA,EAAK,IAAA,CAAK,GAAA,EAAK,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,KAAA,CAAM,OAAA,EAAiB,OAAA,GAA+B,EAAC,EAA2B;AACtF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,WAAA,CAAY,YAAY;AAC1C,MAAA,MAAM,EAAA,GAAK,KAAK,OAAA,CAAQ,KAAA;AAExB,MAAA,MAAM,YAAY,EAAE,GAAG,KAAK,GAAA,EAAK,GAAG,QAAQ,GAAA,EAAI;AAChD,MAAA,MAAM,MAAM,MAAA,CAAO,WAAA;AAAA,QACjB,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,CAAE,MAAA,CAAO,CAAC,KAAA,KAAqC,KAAA,CAAM,CAAC,CAAA,KAAM,MAAS;AAAA,OAC/F;AAGA,MAAA,MAAM,IAAA,GAAO,CAAC,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA;AAEjC,MAAA,MAAM,IAAA,GAAO,MAAM,EAAA,CAAG,IAAA,CAAK,IAAA,EAAM;AAAA,QAC/B,KAAK,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,GAAS,IAAI,GAAA,GAAM,MAAA;AAAA,QACzC,SAAS,OAAA,CAAQ,GAAA;AAAA,QACjB,WAAW,OAAA,CAAQ;AAAA,OACpB,CAAA;AAED,MAAA,MAAM,GAAA,GAAM,CAAA,WAAA,EAAc,IAAA,CAAK,GAAA,EAAI,CAAE,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA,EAAI,EAAE,IAAA,CAAK,aAAa,CAAA,CAAA;AACzE,MAAA,MAAM,MAAA,GAAS,IAAI,kBAAA,CAAmB,GAAA,EAAK,MAAM,IAAA,CAAK,GAAA,IAAO,OAAO,CAAA;AAEpE,MAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,SAAA,EAAU;AAC3C,MAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,SAAA,EAAU;AAC3C,MAAA,MAAA,CAAO,UAAA,CAAW,cAAc,YAAY,CAAA;AAE5C,MAAA,MAAM,gBAAA,GAAmB,QAAQ,GAAA,CAAI;AAAA,QACnC,YAAY,YAAA,EAAc,CAAA,KAAA,KAAS,MAAA,CAAO,UAAA,CAAW,KAAK,CAAC,CAAA;AAAA,QAC3D,YAAY,YAAA,EAAc,CAAA,KAAA,KAAS,MAAA,CAAO,UAAA,CAAW,KAAK,CAAC;AAAA,OAC5D,CAAA,CAAE,IAAA,CAAK,MAAM;AAAA,MAAC,CAAC,CAAA;AAEhB,MAAA,MAAA,CAAO,gBAAA,GAAmB,gBAAA;AAE1B,MAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,GAAA,EAAK,MAAM,CAAA;AAC7B,MAAA,OAAO,MAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,IAAA,GAA+B;AACnC,IAAA,MAAM,SAAwB,EAAC;AAC/B,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,MAAM,CAAA,IAAK,KAAK,QAAA,EAAU;AACzC,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,GAAA;AAAA,QACA,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,OAAA,EAAS,OAAO,QAAA,KAAa,MAAA;AAAA,QAC7B,UAAU,MAAA,CAAO;AAAA,OAClB,CAAA;AAAA,IACH;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAOA,eAAe,WAAA,CAAY,QAA6C,IAAA,EAA8C;AACpH,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,MAAA,IAAI,IAAA,EAAM;AACV,MAAA,IAAA,CAAK,KAAK,CAAA;AAAA,IACZ;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;;;ACtOA,IAAM,UAAA,GAAa,gBAAA;AAkEZ,IAAM,YAAA,GAAN,cAA2B,aAAA,CAAc;AAAA,EACrC,EAAA;AAAA,EACA,IAAA,GAAO,cAAA;AAAA,EACP,QAAA,GAAW,OAAA;AAAA,EACpB,MAAA,GAAyB,SAAA;AAAA,EAIjB,GAAA,GAAsB,IAAA;AAAA,EACtB,cAAA,GAA+B,IAAA;AAAA;AAAA,EAC/B,OAAA,GAA8B,IAAA;AAAA,EAC9B,UAAA,GAA0B,IAAA;AAAA,EAC1B,WAAA,GAAc,KAAA;AAAA,EAEL,OAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,qBAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAA+B,EAAC,EAAG;AAC7C,IAAA,KAAA,CAAM;AAAA,MACJ,GAAG,OAAA;AAAA,MACH,IAAA,EAAM,cAAA;AAAA,MACN,SAAA,EAAW,IAAI,mBAAA,CAAoB,EAAE,KAAK,OAAA,CAAQ,GAAA,IAAO,EAAC,EAAG;AAAA,KAC9D,CAAA;AAED,IAAA,IAAA,CAAK,EAAA,GAAK,OAAA,CAAQ,EAAA,IAAM,IAAA,CAAK,WAAA,EAAY;AACzC,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW,QAAA;AAClC,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,SAAA,IAAa,cAAA;AACtC,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,SAAA,IAAa,GAAA;AACtC,IAAA,IAAA,CAAK,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,EAAC;AAC3B,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AACvB,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AACvB,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,WAAA;AAC3B,IAAA,IAAA,CAAK,wBAAwB,OAAA,CAAQ,YAAA;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,KAAA,GAAiB;AACnB,IAAA,IAAI,CAAC,KAAK,GAAA,EAAK;AACb,MAAA,MAAM,IAAI,oBAAA,CAAqB,IAAA,CAAK,EAAE,CAAA;AAAA,IACxC;AACA,IAAA,OAAO,IAAA,CAAK,GAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,KAAK,GAAA,EAAK;AACZ,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,KAAK,UAAA,EAAW;AAE/B,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,GAAA,GAAM,MAAM,MAAA,CAAO,SAAA,CAAU,SAAS,IAAA,CAAK,OAAA,EAAS,KAAK,EAAE,CAAA;AAChE,MAAA,IAAA,CAAK,UAAA,uBAAiB,IAAA,EAAK;AAC3B,MAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,iCAAA,EAAoC,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AAC5E,MAAA;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,EAAE,iBAAiB,aAAA,CAAA,EAAgB;AACrC,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF;AAEA,IAAA,MAAM,GAAA,GAAW,MAAM,MAAA,CAAO,IAAA,CAAK,QAAA,CAAS,KAAK,OAAA,EAAS,EAAE,eAAA,EAAiB,IAAA,EAAM,CAAA;AAEnF,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,IAAA,CAAK,OAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,0BAAA,EAA6B,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AACrE,MAAA,IAAA,CAAK,MAAM,MAAM,MAAA,CAAO,UAAU,MAAA,CAAO,GAAA,EAAK,KAAK,cAAA,EAAgB;AAAA,QACjE,MAAM,IAAA,CAAK,EAAA;AAAA,QACX,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB,GAAA,EAAK,OAAO,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,GAAA,GAAM,MAAA;AAAA,QACnD,SAAS,IAAA,CAAK;AAAA,OACf,CAAA;AACD,MAAA,IAAA,CAAK,UAAA,uBAAiB,IAAA,EAAK;AAC3B,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,uCAAuC,IAAA,CAAK,GAAA,EAAK,SAAS,CAAA,CAAE,CAAA;AAC3F,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAe,MAAA,CAAO,MAAA,CAAO,YAAA,CAAa,KAAK,SAAS,CAAA;AAC9D,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA,mBAAA,EAAsB,KAAK,EAAE,CAAA,aAAA,EAAgB,IAAA,CAAK,SAAS,CAAA,CAAA,CAAG,CAAA;AAC7F,IAAA,IAAA,CAAK,MAAM,MAAM,MAAA,CAAO,SAAA,CAAU,MAAA,CAAO,KAAK,KAAA,EAAO;AAAA,MACnD,MAAM,IAAA,CAAK,EAAA;AAAA,MACX,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,GAAA,EAAK,OAAO,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,GAAA,GAAM,MAAA;AAAA,MACnD,SAAS,IAAA,CAAK;AAAA,KACf,CAAA;AACD,IAAA,IAAA,CAAK,UAAA,uBAAiB,IAAA,EAAK;AAC3B,IAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,qBAAqB,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,CAAE,CAAA;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,IAAA,GAAsB;AAC1B,IAAA,IAAI,CAAC,KAAK,GAAA,EAAK;AAEf,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,SAAA,CAAU,IAAA,EAAK;AACxC,MAAA,MAAM,QAAQ,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,KAAK,SAAA,CAAU,IAAA,CAAK,CAAA,CAAE,GAAG,CAAC,CAAC,CAAA;AAAA,IACrF,CAAA,CAAA,MAAQ;AAAA,IAER;AAEA,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,cAAA,GAAiB,MAAM,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAmB;AACxD,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,sBAAsB,IAAA,CAAK,cAAA,CAAe,OAAO,CAAA,CAAE,CAAA;AAAA,IACpF,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,mDAAmD,KAAK,CAAA;AAAA,IACzF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,GAAA,CAAI,SAAA,CAAU,EAAE,IAAA,EAAM,MAAM,CAAA;AACvC,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,wBAAwB,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,CAAE,CAAA;AAC3E,MAAA,IAAA,CAAK,GAAA,GAAM,IAAA;AAAA,IACb,SAAS,KAAA,EAAO;AAEd,MAAA,IAAI,IAAA,CAAK,kBAAA,CAAmB,KAAK,CAAA,EAAG;AAClC,QAAA,IAAA,CAAK,GAAA,GAAM,IAAA;AAAA,MACb,CAAA,MAAO;AACL,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,OAAA,GAAyB;AAC7B,IAAA,IAAI,KAAK,GAAA,EAAK;AACZ,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,SAAA,CAAU,IAAA,EAAK;AACxC,QAAA,MAAM,QAAQ,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,KAAK,SAAA,CAAU,IAAA,CAAK,CAAA,CAAE,GAAG,CAAC,CAAC,CAAA;AAAA,MACrF,CAAA,CAAA,MAAQ;AAAA,MAER;AAEA,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,IAAI,SAAA,EAAU;AACzB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,UAAU,wBAAwB,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,CAAE,CAAA;AAAA,MAC7E,CAAA,CAAA,MAAQ;AAAA,MAER;AAEA,MAAA,IAAA,CAAK,GAAA,GAAM,IAAA;AAAA,IACb;AAEA,IAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AAAA,EACxB;AAAA,EAEA,MAAM,OAAA,GAAgC;AACpC,IAAA,OAAO;AAAA,MACL,IAAI,IAAA,CAAK,EAAA;AAAA,MACT,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAA,EAAW,IAAA,CAAK,UAAA,oBAAc,IAAI,IAAA,EAAK;AAAA,MACvC,QAAA,EAAU;AAAA,QACR,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,KAAA,EAAO,IAAA,CAAK,cAAA,EAAgB,OAAA,IAAW,IAAA,CAAK,SAAA;AAAA,QAC5C,WAAW,IAAA,CAAK;AAAA;AAClB,KACF;AAAA,EACF;AAAA,EAEA,eAAA,GAA0B;AACxB,IAAA,MAAM,mBAAA,GAAsB,KAAK,uBAAA,EAAwB;AACzD,IAAA,IAAI,IAAA,CAAK,qBAAA,KAA0B,MAAA,EAAW,OAAO,mBAAA;AACrD,IAAA,IAAI,OAAO,IAAA,CAAK,qBAAA,KAA0B,QAAA,SAAiB,IAAA,CAAK,qBAAA;AAChE,IAAA,OAAO,IAAA,CAAK,qBAAA,CAAsB,EAAE,mBAAA,EAAqB,CAAA;AAAA,EAC3D;AAAA,EAEQ,uBAAA,GAAkC;AACxC,IAAA,OAAO,CAAA,4BAAA,EAA+B,KAAK,SAAS,CAAA,6CAAA,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,KAAA,EAAyB;AAClD,IAAA,IAAI,CAAC,OAAO,OAAO,KAAA;AACnB,IAAA,IAAI,KAAA,YAAiB,mBAAmB,OAAO,IAAA;AAC/C,IAAA,IAAI,KAAA,YAAiB,eAAe,OAAO,IAAA;AAC3C,IAAA,MAAM,QAAA,GAAW,OAAO,KAAK,CAAA;AAC7B,IAAA,OACE,QAAA,CAAS,QAAA,CAAS,mBAAmB,CAAA,IACrC,SAAS,QAAA,CAAS,qBAAqB,CAAA,IACvC,QAAA,CAAS,QAAA,CAAS,mBAAmB,CAAA,IACrC,QAAA,CAAS,SAAS,eAAe,CAAA;AAAA,IAEjC,kBAAkB,IAAA,CAAK,QAAQ,CAAA,IAC/B,QAAA,CAAS,SAAS,WAAW,CAAA;AAAA,EAEjC;AAAA,EAEQ,iBAAA,GAA0B;AAChC,IAAA,IAAA,CAAK,GAAA,GAAM,IAAA;AACX,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA;AAAA,EAChB;AAAA;AAAA,EAGA,MAAM,YAAe,EAAA,EAAkC;AACrD,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,EAAA,EAAG;AAAA,IAClB,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,KAAK,kBAAA,CAAmB,KAAK,CAAA,IAAK,CAAC,KAAK,WAAA,EAAa;AACvD,QAAA,IAAA,CAAK,iBAAA,EAAkB;AACvB,QAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,QAAA,IAAI;AACF,UAAA,MAAM,KAAK,aAAA,EAAc;AACzB,UAAA,OAAO,MAAM,EAAA,EAAG;AAAA,QAClB,CAAA,SAAE;AACA,UAAA,IAAA,CAAK,WAAA,GAAc,KAAA;AAAA,QACrB;AAAA,MACF;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAA,GAAsB;AAC5B,IAAA,OAAO,iBAAiB,IAAA,CAAK,GAAA,EAAI,CAAE,QAAA,CAAS,EAAE,CAAC,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,EAAE,EAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAAA,EAC3F;AAAA,EAEQ,UAAA,GAA0B;AAChC,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,MAAA,IAAA,CAAK,OAAA,GAAU,IAAI,WAAA,CAAY;AAAA,QAC7B,GAAI,IAAA,CAAK,OAAA,IAAW,EAAE,OAAA,EAAS,KAAK,OAAA,EAAQ;AAAA,QAC5C,GAAI,IAAA,CAAK,WAAA,IAAe,EAAE,WAAA,EAAa,KAAK,WAAA;AAAY,OACzD,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AACF","file":"index.js","sourcesContent":["/**\n * Modal process manager. Each spawn() creates a ContainerProcess via exec().\n * kill() has no SDK equivalent — it cancels stream readers locally; the remote\n * process runs until the sandbox timeout.\n */\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { ContainerProcess } from 'modal';\nimport type { ModalSandbox } from './index';\n\n// =============================================================================\n// Modal Process Handle\n// =============================================================================\n\n/**\n * Wraps a Modal ContainerProcess to conform to Mastra's ProcessHandle.\n */\nclass ModalProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _proc: ContainerProcess<string>;\n private readonly _startTime: number;\n private readonly _timeout?: number;\n\n private _exitCode: number | undefined;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _streamingPromise: Promise<void> | null = null;\n private _killed = false;\n private _stdoutReader: ReadableStreamDefaultReader<string> | null = null;\n private _stderrReader: ReadableStreamDefaultReader<string> | null = null;\n\n constructor(pid: string, proc: ContainerProcess<string>, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = pid;\n this._proc = proc;\n this._startTime = startTime;\n this._timeout = options?.timeout;\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n /** @internal Set by the process manager after streaming starts. */\n set streamingPromise(p: Promise<void>) {\n this._streamingPromise = p;\n\n // Resolve exit code when streaming ends so exitCode is available without calling wait()\n p.then(() => this._resolveExitCode()).catch(() => this._resolveExitCode());\n }\n\n /** @internal Set by the process manager so kill() can cancel the readers. */\n setReaders(\n stdoutReader: ReadableStreamDefaultReader<string>,\n stderrReader: ReadableStreamDefaultReader<string>,\n ): void {\n this._stdoutReader = stdoutReader;\n this._stderrReader = stderrReader;\n }\n\n /** Fetch the exit code from the Modal process. No-op if already set. */\n private async _resolveExitCode(): Promise<void> {\n if (this._exitCode !== undefined) return;\n try {\n this._exitCode = await this._proc.wait();\n } catch {\n if (this._exitCode === undefined) {\n this._exitCode = 1;\n }\n }\n }\n\n async wait(): Promise<CommandResult> {\n if (!this._waitPromise) {\n this._waitPromise = this._doWait();\n }\n return this._waitPromise;\n }\n\n private async _doWait(): Promise<CommandResult> {\n const streamDone = this._streamingPromise ?? Promise.resolve();\n\n if (this._timeout) {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error(`Command timed out after ${this._timeout}ms`)), this._timeout);\n });\n\n try {\n await Promise.race([streamDone, timeoutPromise]);\n } catch (error) {\n if (error instanceof Error && error.message.includes('timed out')) {\n await this.kill();\n this._exitCode = 124; // conventional timeout exit code\n return {\n success: false,\n exitCode: 124,\n stdout: this.stdout,\n stderr: this.stderr || error.message,\n executionTimeMs: Date.now() - this._startTime,\n };\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n } else {\n await streamDone.catch(() => {});\n }\n\n if (this._killed) {\n return {\n success: false,\n exitCode: this._exitCode ?? 137,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n };\n }\n\n await this._resolveExitCode();\n\n return {\n success: this._exitCode === 0,\n exitCode: this._exitCode ?? 1,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n };\n }\n\n async kill(): Promise<boolean> {\n if (this._exitCode !== undefined) return false;\n this._killed = true;\n this._exitCode = 137; // SIGKILL\n // The remote process may continue running; Modal JS SDK has no per-exec kill.\n try {\n await this._stdoutReader?.cancel();\n } catch {\n // Ignore cancellation errors\n }\n try {\n await this._stderrReader?.cancel();\n } catch {\n // Ignore cancellation errors\n }\n return true;\n }\n\n async sendStdin(_data: string): Promise<void> {\n throw new Error('Modal JS SDK does not expose stdin on exec() — sendStdin() is not supported');\n }\n}\n\n// =============================================================================\n// Modal Process Manager\n// =============================================================================\n\nexport interface ModalProcessManagerOptions {\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Modal implementation of SandboxProcessManager.\n * Uses the Modal SDK's exec() API with one ContainerProcess per spawn.\n */\nexport class ModalProcessManager extends SandboxProcessManager<ModalSandbox> {\n private _spawnCounter = 0;\n\n constructor(opts: ModalProcessManagerOptions = {}) {\n super({ env: opts.env });\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n return this.sandbox.retryOnDead(async () => {\n const sb = this.sandbox.modal;\n\n const mergedEnv = { ...this.env, ...options.env };\n const env = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n // exec() takes string[] — wrap in sh -c to support pipes, redirects, etc.\n const argv = ['sh', '-c', command];\n\n const proc = await sb.exec(argv, {\n env: Object.keys(env).length > 0 ? env : undefined,\n workdir: options.cwd,\n timeoutMs: options.timeout,\n });\n\n const pid = `modal-proc-${Date.now().toString(36)}-${++this._spawnCounter}`;\n const handle = new ModalProcessHandle(pid, proc, Date.now(), options);\n\n const stdoutReader = proc.stdout.getReader();\n const stderrReader = proc.stderr.getReader();\n handle.setReaders(stdoutReader, stderrReader);\n\n const streamingPromise = Promise.all([\n drainReader(stdoutReader, chunk => handle.emitStdout(chunk)),\n drainReader(stderrReader, chunk => handle.emitStderr(chunk)),\n ]).then(() => {});\n\n handle.streamingPromise = streamingPromise;\n\n this._tracked.set(pid, handle);\n return handle;\n });\n }\n\n async list(): Promise<ProcessInfo[]> {\n const result: ProcessInfo[] = [];\n for (const [pid, handle] of this._tracked) {\n result.push({\n pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n exitCode: handle.exitCode,\n });\n }\n return result;\n }\n}\n\n// =============================================================================\n// Stream Helpers\n// =============================================================================\n\n/** Reads chunks from a stream until done or cancelled. */\nasync function drainReader(reader: ReadableStreamDefaultReader<string>, emit: (chunk: string) => void): Promise<void> {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n emit(value);\n }\n } catch {\n // cancelled or network error\n }\n}\n","/**\n * @see https://modal.com/docs/reference/modal.Sandbox\n */\n\nimport type { MastraSandboxOptions, ProviderStatus, SandboxInfo } from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { ClientClosedError, ModalClient, NotFoundError } from 'modal';\nimport type { App, Image, Sandbox } from 'modal';\nimport { ModalProcessManager } from './process-manager';\n\nconst LOG_PREFIX = '[ModalSandbox]';\n\n// =============================================================================\n// Options\n// =============================================================================\n\ntype InstructionsOption = string | ((opts: { defaultInstructions: string }) => string);\n\n/**\n * Modal sandbox provider configuration.\n */\nexport interface ModalSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Stable name for this sandbox. Reusing the same id reconnects to a running sandbox. */\n id?: string;\n /**\n * Modal App name to associate sandboxes with.\n *\n * @default 'mastra'\n */\n appName?: string;\n /**\n * Docker image to use for the sandbox.\n *\n * @default 'ubuntu:22.04'\n */\n baseImage?: string;\n /**\n * Wall-clock max lifetime in milliseconds. The sandbox is terminated when this expires,\n * regardless of activity. Modal's maximum is 24 hours (86_400_000).\n *\n * @default 300_000 // 5 minutes\n */\n timeoutMs?: number;\n /** Environment variables baked into the sandbox at create time. */\n env?: Record<string, string>;\n /** Default working directory inside the sandbox. */\n workdir?: string;\n /** Modal token ID. Falls back to MODAL_TOKEN_ID env var. */\n tokenId?: string;\n /** Modal token secret. Falls back to MODAL_TOKEN_SECRET env var. */\n tokenSecret?: string;\n /** Custom instructions for getInstructions(). String replaces the default; function receives it. */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// ModalSandbox\n// =============================================================================\n\n/**\n * Modal cloud sandbox provider for Mastra workspaces.\n *\n * @example\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { ModalSandbox } from '@mastra/modal';\n *\n * const sandbox = new ModalSandbox({\n * baseImage: 'ubuntu:22.04',\n * timeoutMs: 60_000,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCommand('echo hello');\n * ```\n */\nexport class ModalSandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'ModalSandbox';\n readonly provider = 'modal';\n status: ProviderStatus = 'pending';\n\n declare readonly processes: ModalProcessManager;\n\n private _sb: Sandbox | null = null;\n private _imageSnapshot: Image | null = null; // for stop-and-resume\n private _client: ModalClient | null = null;\n private _createdAt: Date | null = null;\n private _isRetrying = false;\n\n private readonly appName: string;\n private readonly baseImage: string;\n private readonly timeoutMs: number;\n private readonly env: Record<string, string>;\n private readonly workdir?: string;\n private readonly tokenId?: string;\n private readonly tokenSecret?: string;\n private readonly _instructionsOverride?: InstructionsOption;\n\n constructor(options: ModalSandboxOptions = {}) {\n super({\n ...options,\n name: 'ModalSandbox',\n processes: new ModalProcessManager({ env: options.env ?? {} }),\n });\n\n this.id = options.id ?? this._generateId();\n this.appName = options.appName ?? 'mastra';\n this.baseImage = options.baseImage ?? 'ubuntu:22.04';\n this.timeoutMs = options.timeoutMs ?? 300_000;\n this.env = options.env ?? {};\n this.workdir = options.workdir;\n this.tokenId = options.tokenId;\n this.tokenSecret = options.tokenSecret;\n this._instructionsOverride = options.instructions;\n }\n\n /**\n * Get the underlying Modal Sandbox instance for direct SDK access.\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n */\n get modal(): Sandbox {\n if (!this._sb) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._sb;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /** Reconnects to a running sandbox with this id if one exists, otherwise creates a new one. */\n async start(): Promise<void> {\n if (this._sb) {\n return;\n }\n\n const client = this._getClient();\n\n try {\n this._sb = await client.sandboxes.fromName(this.appName, this.id);\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Reconnected to running sandbox: ${this.id}`);\n return;\n } catch (error) {\n if (!(error instanceof NotFoundError)) {\n throw error;\n }\n }\n\n const app: App = await client.apps.fromName(this.appName, { createIfMissing: true });\n\n if (this._imageSnapshot) {\n this.logger.debug(`${LOG_PREFIX} Rebooting from snapshot: ${this.id}`);\n this._sb = await client.sandboxes.create(app, this._imageSnapshot, {\n name: this.id,\n timeoutMs: this.timeoutMs,\n env: Object.keys(this.env).length > 0 ? this.env : undefined,\n workdir: this.workdir,\n });\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Created new sandbox from snapshot: ${this._sb?.sandboxId}`);\n return;\n }\n\n const image: Image = client.images.fromRegistry(this.baseImage);\n this.logger.debug(`${LOG_PREFIX} Creating sandbox: ${this.id} (baseImage: ${this.baseImage})`);\n this._sb = await client.sandboxes.create(app, image, {\n name: this.id,\n timeoutMs: this.timeoutMs,\n env: Object.keys(this.env).length > 0 ? this.env : undefined,\n workdir: this.workdir,\n });\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Created sandbox: ${this._sb.sandboxId}`);\n }\n\n /**\n * Snapshot the sandbox filesystem before terminating it.\n * Future starts will create net-new sandboxes from the snapshot.\n */\n async stop(): Promise<void> {\n if (!this._sb) return;\n\n try {\n const procs = await this.processes.list();\n await Promise.all(procs.filter(p => p.running).map(p => this.processes.kill(p.pid)));\n } catch {\n // Best-effort: sandbox may already be dead\n }\n\n try {\n this._imageSnapshot = await this._sb.snapshotFilesystem();\n this.logger.debug(`${LOG_PREFIX} Snapshot created: ${this._imageSnapshot.imageId}`);\n } catch (error) {\n this.logger.debug(`${LOG_PREFIX} Snapshot failed, terminating without snapshot:`, error);\n }\n\n try {\n await this._sb.terminate({ wait: true });\n this.logger.debug(`${LOG_PREFIX} Sandbox terminated: ${this._sb.sandboxId}`);\n this._sb = null;\n } catch (error) {\n // Best-effort: sandbox may already be dead\n if (this.isSandboxDeadError(error)) {\n this._sb = null;\n } else {\n throw error;\n }\n }\n }\n\n /** Terminates the sandbox, ending its lifetime. Unlike stop(), no snapshot is preserved. */\n async destroy(): Promise<void> {\n if (this._sb) {\n try {\n const procs = await this.processes.list();\n await Promise.all(procs.filter(p => p.running).map(p => this.processes.kill(p.pid)));\n } catch {\n // Best-effort: sandbox may already be dead\n }\n\n try {\n await this._sb.terminate();\n this.logger.debug(`${LOG_PREFIX} Sandbox terminated: ${this._sb.sandboxId}`);\n } catch {\n // Ignore errors during destroy\n }\n\n this._sb = null;\n }\n\n this._imageSnapshot = null;\n }\n\n async getInfo(): Promise<SandboxInfo> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: this._createdAt ?? new Date(),\n metadata: {\n appName: this.appName,\n image: this._imageSnapshot?.imageId ?? this.baseImage,\n timeoutMs: this.timeoutMs,\n },\n };\n }\n\n getInstructions(): string {\n const defaultInstructions = this._getDefaultInstructions();\n if (this._instructionsOverride === undefined) return defaultInstructions;\n if (typeof this._instructionsOverride === 'string') return this._instructionsOverride;\n return this._instructionsOverride({ defaultInstructions });\n }\n\n private _getDefaultInstructions(): string {\n return `Modal cloud sandbox running ${this.baseImage}. Use executeCommand() to run shell commands.`;\n }\n\n // ---------------------------------------------------------------------------\n // Dead-sandbox Retry\n // ---------------------------------------------------------------------------\n\n private isSandboxDeadError(error: unknown): boolean {\n if (!error) return false;\n if (error instanceof ClientClosedError) return true;\n if (error instanceof NotFoundError) return true;\n const errorStr = String(error);\n return (\n errorStr.includes('sandbox not found') ||\n errorStr.includes('has been terminated') ||\n errorStr.includes('already completed') ||\n errorStr.includes('was cancelled') ||\n // gRPC NOT_FOUND (code 5)\n /status[:\\s]+5\\b/.test(errorStr) ||\n errorStr.includes('NOT_FOUND')\n );\n }\n\n private handleSandboxDead(): void {\n this._sb = null;\n this.status = 'stopped';\n }\n\n /** @internal Retries fn() once after restarting if the sandbox is dead. */\n async retryOnDead<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (this.isSandboxDeadError(error) && !this._isRetrying) {\n this.handleSandboxDead();\n this._isRetrying = true;\n try {\n await this.ensureRunning();\n return await fn();\n } finally {\n this._isRetrying = false;\n }\n }\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Internal Helpers\n // ---------------------------------------------------------------------------\n\n private _generateId(): string {\n return `modal-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n private _getClient(): ModalClient {\n if (!this._client) {\n this._client = new ModalClient({\n ...(this.tokenId && { tokenId: this.tokenId }),\n ...(this.tokenSecret && { tokenSecret: this.tokenSecret }),\n });\n }\n return this._client;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/sandbox/process-manager.ts","../src/sandbox/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Modal process manager. Each spawn() creates a ContainerProcess via exec().\n * kill() has no SDK equivalent — it cancels stream readers locally; the remote\n * process runs until the sandbox timeout.\n */\n\nimport { ProcessHandle, SandboxProcessManager } from '@mastra/core/workspace';\nimport type { CommandResult, ProcessInfo, SpawnProcessOptions } from '@mastra/core/workspace';\nimport type { ContainerProcess } from 'modal';\nimport type { ModalSandbox } from './index';\n\n// =============================================================================\n// Modal Process Handle\n// =============================================================================\n\n/**\n * Wraps a Modal ContainerProcess to conform to Mastra's ProcessHandle.\n */\nclass ModalProcessHandle extends ProcessHandle {\n readonly pid: string;\n\n private readonly _proc: ContainerProcess<string>;\n private readonly _startTime: number;\n private readonly _timeout?: number;\n\n private _exitCode: number | undefined;\n private _waitPromise: Promise<CommandResult> | null = null;\n private _streamingPromise: Promise<void> | null = null;\n private _killed = false;\n private _stdoutReader: ReadableStreamDefaultReader<string> | null = null;\n private _stderrReader: ReadableStreamDefaultReader<string> | null = null;\n\n constructor(pid: string, proc: ContainerProcess<string>, startTime: number, options?: SpawnProcessOptions) {\n super(options);\n this.pid = pid;\n this._proc = proc;\n this._startTime = startTime;\n this._timeout = options?.timeout;\n }\n\n get exitCode(): number | undefined {\n return this._exitCode;\n }\n\n /** @internal Set by the process manager after streaming starts. */\n set streamingPromise(p: Promise<void>) {\n this._streamingPromise = p;\n\n // Resolve exit code when streaming ends so exitCode is available without calling wait()\n p.then(() => this._resolveExitCode()).catch(() => this._resolveExitCode());\n }\n\n /** @internal Set by the process manager so kill() can cancel the readers. */\n setReaders(\n stdoutReader: ReadableStreamDefaultReader<string>,\n stderrReader: ReadableStreamDefaultReader<string>,\n ): void {\n this._stdoutReader = stdoutReader;\n this._stderrReader = stderrReader;\n }\n\n /** Fetch the exit code from the Modal process. No-op if already set. */\n private async _resolveExitCode(): Promise<void> {\n if (this._exitCode !== undefined) return;\n try {\n this._exitCode = await this._proc.wait();\n } catch {\n if (this._exitCode === undefined) {\n this._exitCode = 1;\n }\n }\n }\n\n async wait(): Promise<CommandResult> {\n if (!this._waitPromise) {\n this._waitPromise = this._doWait();\n }\n return this._waitPromise;\n }\n\n private async _doWait(): Promise<CommandResult> {\n const streamDone = this._streamingPromise ?? Promise.resolve();\n\n if (this._timeout) {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error(`Command timed out after ${this._timeout}ms`)), this._timeout);\n });\n\n try {\n await Promise.race([streamDone, timeoutPromise]);\n } catch (error) {\n if (error instanceof Error && error.message.includes('timed out')) {\n await this.kill();\n this._exitCode = 124; // conventional timeout exit code\n return {\n success: false,\n exitCode: 124,\n stdout: this.stdout,\n stderr: this.stderr || error.message,\n executionTimeMs: Date.now() - this._startTime,\n killed: true,\n timedOut: true,\n };\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n } else {\n await streamDone.catch(() => {});\n }\n\n if (this._killed) {\n return {\n success: false,\n exitCode: this._exitCode ?? 137,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n killed: true,\n timedOut: false,\n };\n }\n\n await this._resolveExitCode();\n\n return {\n success: this._exitCode === 0,\n exitCode: this._exitCode ?? 1,\n stdout: this.stdout,\n stderr: this.stderr,\n executionTimeMs: Date.now() - this._startTime,\n };\n }\n\n async kill(): Promise<boolean> {\n if (this._exitCode !== undefined) return false;\n this._killed = true;\n this._exitCode = 137; // SIGKILL\n // The remote process may continue running; Modal JS SDK has no per-exec kill.\n try {\n await this._stdoutReader?.cancel();\n } catch {\n // Ignore cancellation errors\n }\n try {\n await this._stderrReader?.cancel();\n } catch {\n // Ignore cancellation errors\n }\n return true;\n }\n\n async sendStdin(_data: string): Promise<void> {\n throw new Error('Modal JS SDK does not expose stdin on exec() — sendStdin() is not supported');\n }\n}\n\n// =============================================================================\n// Modal Process Manager\n// =============================================================================\n\nexport interface ModalProcessManagerOptions {\n env?: Record<string, string | undefined>;\n}\n\n/**\n * Modal implementation of SandboxProcessManager.\n * Uses the Modal SDK's exec() API with one ContainerProcess per spawn.\n */\nexport class ModalProcessManager extends SandboxProcessManager<ModalSandbox> {\n private _spawnCounter = 0;\n\n constructor(opts: ModalProcessManagerOptions = {}) {\n super({ env: opts.env });\n }\n\n async spawn(command: string, options: SpawnProcessOptions = {}): Promise<ProcessHandle> {\n return this.sandbox.retryOnDead(async () => {\n const sb = this.sandbox.modal;\n\n const mergedEnv = { ...this.env, ...options.env };\n const env = Object.fromEntries(\n Object.entries(mergedEnv).filter((entry): entry is [string, string] => entry[1] !== undefined),\n );\n\n // exec() takes string[] — wrap in sh -c to support pipes, redirects, etc.\n const argv = ['sh', '-c', command];\n\n const proc = await sb.exec(argv, {\n env: Object.keys(env).length > 0 ? env : undefined,\n workdir: options.cwd,\n timeoutMs: options.timeout,\n });\n\n const pid = `modal-proc-${Date.now().toString(36)}-${++this._spawnCounter}`;\n const handle = new ModalProcessHandle(pid, proc, Date.now(), options);\n\n const stdoutReader = proc.stdout.getReader();\n const stderrReader = proc.stderr.getReader();\n handle.setReaders(stdoutReader, stderrReader);\n\n const streamingPromise = Promise.all([\n drainReader(stdoutReader, chunk => handle.emitStdout(chunk)),\n drainReader(stderrReader, chunk => handle.emitStderr(chunk)),\n ]).then(() => {});\n\n handle.streamingPromise = streamingPromise;\n\n this._tracked.set(pid, handle);\n return handle;\n });\n }\n\n async list(): Promise<ProcessInfo[]> {\n const result: ProcessInfo[] = [];\n for (const [pid, handle] of this._tracked) {\n result.push({\n pid,\n command: handle.command,\n running: handle.exitCode === undefined,\n exitCode: handle.exitCode,\n });\n }\n return result;\n }\n}\n\n// =============================================================================\n// Stream Helpers\n// =============================================================================\n\n/** Reads chunks from a stream until done or cancelled. */\nasync function drainReader(reader: ReadableStreamDefaultReader<string>, emit: (chunk: string) => void): Promise<void> {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n emit(value);\n }\n } catch {\n // cancelled or network error\n }\n}\n","/**\n * @see https://modal.com/docs/reference/modal.Sandbox\n */\n\nimport type { MastraSandboxOptions, ProviderStatus, SandboxInfo } from '@mastra/core/workspace';\nimport { MastraSandbox, SandboxNotReadyError } from '@mastra/core/workspace';\nimport { ClientClosedError, ModalClient, NotFoundError } from 'modal';\nimport type { App, Image, Sandbox } from 'modal';\nimport { ModalProcessManager } from './process-manager';\n\nconst LOG_PREFIX = '[ModalSandbox]';\n\n// =============================================================================\n// Options\n// =============================================================================\n\ntype InstructionsOption = string | ((opts: { defaultInstructions: string }) => string);\n\n/**\n * Modal sandbox provider configuration.\n */\nexport interface ModalSandboxOptions extends Omit<MastraSandboxOptions, 'processes'> {\n /** Stable name for this sandbox. Reusing the same id reconnects to a running sandbox. */\n id?: string;\n /**\n * Modal App name to associate sandboxes with.\n *\n * @default 'mastra'\n */\n appName?: string;\n /**\n * Docker image to use for the sandbox.\n *\n * @default 'ubuntu:22.04'\n */\n baseImage?: string;\n /**\n * Wall-clock max lifetime in milliseconds. The sandbox is terminated when this expires,\n * regardless of activity. Modal's maximum is 24 hours (86_400_000).\n *\n * @default 300_000 // 5 minutes\n */\n timeoutMs?: number;\n /** Environment variables baked into the sandbox at create time. */\n env?: Record<string, string>;\n /** Default working directory inside the sandbox. */\n workdir?: string;\n /** Modal token ID. Falls back to MODAL_TOKEN_ID env var. */\n tokenId?: string;\n /** Modal token secret. Falls back to MODAL_TOKEN_SECRET env var. */\n tokenSecret?: string;\n /** Custom instructions for getInstructions(). String replaces the default; function receives it. */\n instructions?: InstructionsOption;\n}\n\n// =============================================================================\n// ModalSandbox\n// =============================================================================\n\n/**\n * Modal cloud sandbox provider for Mastra workspaces.\n *\n * @example\n * ```typescript\n * import { Workspace } from '@mastra/core/workspace';\n * import { ModalSandbox } from '@mastra/modal';\n *\n * const sandbox = new ModalSandbox({\n * baseImage: 'ubuntu:22.04',\n * timeoutMs: 60_000,\n * });\n *\n * const workspace = new Workspace({ sandbox });\n * const result = await workspace.executeCommand('echo hello');\n * ```\n */\nexport class ModalSandbox extends MastraSandbox {\n readonly id: string;\n readonly name = 'ModalSandbox';\n readonly provider = 'modal';\n status: ProviderStatus = 'pending';\n\n declare readonly processes: ModalProcessManager;\n\n private _sb: Sandbox | null = null;\n private _imageSnapshot: Image | null = null; // for stop-and-resume\n private _client: ModalClient | null = null;\n private _createdAt: Date | null = null;\n private _isRetrying = false;\n\n private readonly appName: string;\n private readonly baseImage: string;\n private readonly timeoutMs: number;\n private readonly env: Record<string, string>;\n private readonly workdir?: string;\n private readonly tokenId?: string;\n private readonly tokenSecret?: string;\n private readonly _instructionsOverride?: InstructionsOption;\n\n constructor(options: ModalSandboxOptions = {}) {\n super({\n ...options,\n name: 'ModalSandbox',\n processes: new ModalProcessManager({ env: options.env ?? {} }),\n });\n\n this.id = options.id ?? this._generateId();\n this.appName = options.appName ?? 'mastra';\n this.baseImage = options.baseImage ?? 'ubuntu:22.04';\n this.timeoutMs = options.timeoutMs ?? 300_000;\n this.env = options.env ?? {};\n this.workdir = options.workdir;\n this.tokenId = options.tokenId;\n this.tokenSecret = options.tokenSecret;\n this._instructionsOverride = options.instructions;\n }\n\n /**\n * Get the underlying Modal Sandbox instance for direct SDK access.\n *\n * @throws {SandboxNotReadyError} If the sandbox has not been started.\n */\n get modal(): Sandbox {\n if (!this._sb) {\n throw new SandboxNotReadyError(this.id);\n }\n return this._sb;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /** Reconnects to a running sandbox with this id if one exists, otherwise creates a new one. */\n async start(): Promise<void> {\n if (this._sb) {\n return;\n }\n\n const client = this._getClient();\n\n try {\n this._sb = await client.sandboxes.fromName(this.appName, this.id);\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Reconnected to running sandbox: ${this.id}`);\n return;\n } catch (error) {\n if (!(error instanceof NotFoundError)) {\n throw error;\n }\n }\n\n const app: App = await client.apps.fromName(this.appName, { createIfMissing: true });\n\n if (this._imageSnapshot) {\n this.logger.debug(`${LOG_PREFIX} Rebooting from snapshot: ${this.id}`);\n this._sb = await client.sandboxes.create(app, this._imageSnapshot, {\n name: this.id,\n timeoutMs: this.timeoutMs,\n env: Object.keys(this.env).length > 0 ? this.env : undefined,\n workdir: this.workdir,\n });\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Created new sandbox from snapshot: ${this._sb?.sandboxId}`);\n return;\n }\n\n const image: Image = client.images.fromRegistry(this.baseImage);\n this.logger.debug(`${LOG_PREFIX} Creating sandbox: ${this.id} (baseImage: ${this.baseImage})`);\n this._sb = await client.sandboxes.create(app, image, {\n name: this.id,\n timeoutMs: this.timeoutMs,\n env: Object.keys(this.env).length > 0 ? this.env : undefined,\n workdir: this.workdir,\n });\n this._createdAt = new Date();\n this.logger.debug(`${LOG_PREFIX} Created sandbox: ${this._sb.sandboxId}`);\n }\n\n /**\n * Snapshot the sandbox filesystem before terminating it.\n * Future starts will create net-new sandboxes from the snapshot.\n */\n async stop(): Promise<void> {\n if (!this._sb) return;\n\n try {\n const procs = await this.processes.list();\n await Promise.all(procs.filter(p => p.running).map(p => this.processes.kill(p.pid)));\n } catch {\n // Best-effort: sandbox may already be dead\n }\n\n try {\n this._imageSnapshot = await this._sb.snapshotFilesystem();\n this.logger.debug(`${LOG_PREFIX} Snapshot created: ${this._imageSnapshot.imageId}`);\n } catch (error) {\n this.logger.debug(`${LOG_PREFIX} Snapshot failed, terminating without snapshot:`, error);\n }\n\n try {\n await this._sb.terminate({ wait: true });\n this.logger.debug(`${LOG_PREFIX} Sandbox terminated: ${this._sb.sandboxId}`);\n this._sb = null;\n } catch (error) {\n // Best-effort: sandbox may already be dead\n if (this.isSandboxDeadError(error)) {\n this._sb = null;\n } else {\n throw error;\n }\n }\n }\n\n /** Terminates the sandbox, ending its lifetime. Unlike stop(), no snapshot is preserved. */\n async destroy(): Promise<void> {\n if (this._sb) {\n try {\n const procs = await this.processes.list();\n await Promise.all(procs.filter(p => p.running).map(p => this.processes.kill(p.pid)));\n } catch {\n // Best-effort: sandbox may already be dead\n }\n\n try {\n await this._sb.terminate();\n this.logger.debug(`${LOG_PREFIX} Sandbox terminated: ${this._sb.sandboxId}`);\n } catch {\n // Ignore errors during destroy\n }\n\n this._sb = null;\n }\n\n this._imageSnapshot = null;\n }\n\n async getInfo(): Promise<SandboxInfo> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n createdAt: this._createdAt ?? new Date(),\n metadata: {\n appName: this.appName,\n image: this._imageSnapshot?.imageId ?? this.baseImage,\n timeoutMs: this.timeoutMs,\n },\n };\n }\n\n getInstructions(): string {\n const defaultInstructions = this._getDefaultInstructions();\n if (this._instructionsOverride === undefined) return defaultInstructions;\n if (typeof this._instructionsOverride === 'string') return this._instructionsOverride;\n return this._instructionsOverride({ defaultInstructions });\n }\n\n private _getDefaultInstructions(): string {\n return `Modal cloud sandbox running ${this.baseImage}. Use executeCommand() to run shell commands.`;\n }\n\n // ---------------------------------------------------------------------------\n // Dead-sandbox Retry\n // ---------------------------------------------------------------------------\n\n private isSandboxDeadError(error: unknown): boolean {\n if (!error) return false;\n if (error instanceof ClientClosedError) return true;\n if (error instanceof NotFoundError) return true;\n const errorStr = String(error);\n return (\n errorStr.includes('sandbox not found') ||\n errorStr.includes('has been terminated') ||\n errorStr.includes('already completed') ||\n errorStr.includes('was cancelled') ||\n // gRPC NOT_FOUND (code 5)\n /status[:\\s]+5\\b/.test(errorStr) ||\n errorStr.includes('NOT_FOUND')\n );\n }\n\n private handleSandboxDead(): void {\n this._sb = null;\n this.status = 'stopped';\n }\n\n /** @internal Retries fn() once after restarting if the sandbox is dead. */\n async retryOnDead<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (this.isSandboxDeadError(error) && !this._isRetrying) {\n this.handleSandboxDead();\n this._isRetrying = true;\n try {\n await this.ensureRunning();\n return await fn();\n } finally {\n this._isRetrying = false;\n }\n }\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Internal Helpers\n // ---------------------------------------------------------------------------\n\n private _generateId(): string {\n return `modal-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n private _getClient(): ModalClient {\n if (!this._client) {\n this._client = new ModalClient({\n ...(this.tokenId && { tokenId: this.tokenId }),\n ...(this.tokenSecret && { tokenSecret: this.tokenSecret }),\n });\n }\n return this._client;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../src/sandbox/process-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAiB,WAAW,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE9F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../src/sandbox/process-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAiB,WAAW,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE9F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA0J5C,MAAM,WAAW,0BAA0B;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,qBAAqB,CAAC,YAAY,CAAC;IAC1E,OAAO,CAAC,aAAa,CAAK;gBAEd,IAAI,GAAE,0BAA+B;IAI3C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,aAAa,CAAC;IAqCjF,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;CAYrC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/modal",
|
|
3
|
-
"version": "0.2.0",
|
|
3
|
+
"version": "0.2.1-alpha.0",
|
|
4
4
|
"description": "Modal cloud sandbox provider for Mastra workspaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
"dotenv": "^17.3.1",
|
|
30
30
|
"eslint": "^10.2.1",
|
|
31
31
|
"tsup": "^8.5.1",
|
|
32
|
-
"typescript": "^
|
|
32
|
+
"typescript": "^6.0.3",
|
|
33
33
|
"vitest": "4.1.5",
|
|
34
|
-
"@internal/
|
|
35
|
-
"@internal/
|
|
36
|
-
"@internal/
|
|
37
|
-
"@mastra/core": "1.
|
|
34
|
+
"@internal/lint": "0.0.99",
|
|
35
|
+
"@internal/types-builder": "0.0.74",
|
|
36
|
+
"@internal/workspace-test-utils": "0.0.43",
|
|
37
|
+
"@mastra/core": "1.38.0-alpha.3"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@mastra/core": ">=1.12.0-0 <2.0.0-0"
|