@namzu/sdk 33.1.1 → 34.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +22 -16
  3. package/dist/agents/PipelineAgent.d.ts.map +1 -1
  4. package/dist/agents/PipelineAgent.js +3 -0
  5. package/dist/agents/PipelineAgent.js.map +1 -1
  6. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  7. package/dist/agents/ReactiveAgent.js +1 -0
  8. package/dist/agents/ReactiveAgent.js.map +1 -1
  9. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  10. package/dist/agents/SupervisorAgent.js +1 -0
  11. package/dist/agents/SupervisorAgent.js.map +1 -1
  12. package/dist/agents/runAgent.d.ts +2 -0
  13. package/dist/agents/runAgent.d.ts.map +1 -1
  14. package/dist/agents/runAgent.js +1 -0
  15. package/dist/agents/runAgent.js.map +1 -1
  16. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  17. package/dist/manager/agent/lifecycle.js +7 -0
  18. package/dist/manager/agent/lifecycle.js.map +1 -1
  19. package/dist/plugin/loader.d.ts.map +1 -1
  20. package/dist/plugin/loader.js +28 -4
  21. package/dist/plugin/loader.js.map +1 -1
  22. package/dist/runtime/query/index.d.ts.map +1 -1
  23. package/dist/runtime/query/index.js +10 -0
  24. package/dist/runtime/query/index.js.map +1 -1
  25. package/dist/sandbox/provider/local.d.ts +1 -0
  26. package/dist/sandbox/provider/local.d.ts.map +1 -1
  27. package/dist/sandbox/provider/local.js +79 -35
  28. package/dist/sandbox/provider/local.js.map +1 -1
  29. package/dist/scheduler/local.d.ts +12 -0
  30. package/dist/scheduler/local.d.ts.map +1 -1
  31. package/dist/scheduler/local.js +69 -1
  32. package/dist/scheduler/local.js.map +1 -1
  33. package/dist/types/agent/base.d.ts +8 -0
  34. package/dist/types/agent/base.d.ts.map +1 -1
  35. package/dist/types/agent/factory.d.ts +1 -0
  36. package/dist/types/agent/factory.d.ts.map +1 -1
  37. package/dist/types/agent/scheduler.d.ts +12 -0
  38. package/dist/types/agent/scheduler.d.ts.map +1 -1
  39. package/dist/types/sandbox/index.d.ts +11 -0
  40. package/dist/types/sandbox/index.d.ts.map +1 -1
  41. package/dist/types/sandbox/index.js.map +1 -1
  42. package/package.json +1 -1
  43. package/src/agents/PipelineAgent.ts +5 -0
  44. package/src/agents/ReactiveAgent.ts +1 -0
  45. package/src/agents/SupervisorAgent.ts +1 -0
  46. package/src/agents/runAgent.ts +3 -0
  47. package/src/manager/agent/lifecycle.ts +7 -0
  48. package/src/plugin/loader.ts +28 -4
  49. package/src/runtime/query/index.ts +10 -0
  50. package/src/sandbox/provider/local.ts +77 -38
  51. package/src/scheduler/local.ts +87 -1
  52. package/src/types/agent/base.ts +9 -0
  53. package/src/types/agent/factory.ts +1 -0
  54. package/src/types/agent/scheduler.ts +13 -0
  55. package/src/types/sandbox/index.ts +12 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/sandbox/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/sandbox/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AACrF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAMhD,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,CAAA;AAEvE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAY/D;AAMD,MAAM,MAAM,kBAAkB,GAAG,aAAa,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,OAAO,CAAA;AAE/F;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,kBAAkB,EAK7D,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,uBAAuB,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAA;AAE1E,eAAO,MAAM,0BAA0B,EAAE,SAAS,uBAAuB,EAIxE,CAAA;AAED,kDAAkD;AAClD,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC,MAAM,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC,CAAA;AAEvF,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI,CAMtE;AAMD,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAClC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;CAClC;AAMD,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAC3B,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAA;QACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KACrB,KAAK,IAAI,CAAA;IACV;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC7B;AAOD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACrB;AAMD;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;;;;;OAOG;IACH,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;CACxC;AAED,MAAM,WAAW,OAAO;IACvB,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAA;IACxC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAE7F;;;;;;;;OAQG;IACH,gBAAgB,CAAC,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE9D;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,YAAY,CAAC,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IACrE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACvC;;;;;;;;;;;;;;;;;;OAkBG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAAA;IACjE;;;;;;;OAOG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvD;AAED,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC7B;AAmBD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,2BAA2B,GACpC;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD;IACA,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;CACjC,GACD;IACA;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CACvB,CAAA;AAEJ;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;IAC5C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;IAC5C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,OAAO,EAAE,2BAA2B,CAAA;IAC7C,QAAQ,CAAC,OAAO,CAAC,EAAE,2BAA2B,CAAA;IAC9C;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,2BAA2B,CAAA;IAC9C,QAAQ,CAAC,WAAW,CAAC,EAAE,2BAA2B,CAAA;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,0BAA0B,EAAE,CAAA;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,2BAA2B,CAAA;CAClD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;QAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAA;IAClG,QAAQ,CAAC,OAAO,CAAC,EAAE;QAClB,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;QAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;KAC9B,CAAA;IACD,QAAQ,CAAC,OAAO,CAAC,EAAE;QAClB,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;QAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;KAC9B,CAAA;IACD,QAAQ,CAAC,WAAW,CAAC,EAAE;QACtB,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;QAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;KAC9B,CAAA;IACD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS;QAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;QACnB,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;QAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;KAC9B,EAAE,CAAA;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE;QACtB,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;QAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;KAC9B,CAAA;CACD;AAMD,MAAM,WAAW,mBAAmB;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,gEAAgE;AAChE,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,mBAAmB,CAAA;AAEpE;;;;;;;;;;;;;;GAcG;AAMH,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAA;IACxC;;;;;;;OAOG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAA;IACzD,MAAM,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACtD;AAMD,eAAO,MAAM,mBAAmB;;;;;;IAM/B;;;;;;OAMG;;IAEH;;;;;;;;;;;;;;;;;;;OAmBG;;;;;;;;;;;;;;;;;;EAEF,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/sandbox/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EACN,6BAA6B,EAC7B,+BAA+B,EAC/B,0BAA0B,GAC1B,MAAM,kCAAkC,CAAA;AAUzC,MAAM,UAAU,mBAAmB,CAAC,MAAqB;IACxD,QAAQ,MAAM,EAAE,CAAC;QAChB,KAAK,UAAU,CAAC;QAChB,KAAK,OAAO,CAAC;QACb,KAAK,MAAM,CAAC;QACZ,KAAK,WAAW;YACf,OAAM;QACP,OAAO,CAAC,CAAC,CAAC;YACT,MAAM,WAAW,GAAU,MAAM,CAAA;YACjC,MAAM,IAAI,KAAK,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAA;QACzD,CAAC;IACF,CAAC;AACF,CAAC;AAQD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAkC;IAClE,aAAa;IACb,gBAAgB;IAChB,iBAAiB;IACjB,OAAO;CACP,CAAA;AAmBD,MAAM,CAAC,MAAM,0BAA0B,GAAuC;IAC7E,YAAY;IACZ,SAAS;IACT,SAAS;CACT,CAAA;AAKD,MAAM,UAAU,wBAAwB,CAAC,GAAuB;IAC/D,0EAA0E;IAC1E,wEAAwE;IACxE,iEAAiE;IACjE,IAAI,oBAAoB,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAM;IAC9C,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAA;AACtD,CAAC;AAiaD,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACnC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC5C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,0BAA0B,CAAC;IACpE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,+BAA+B,CAAC;IAC7E,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,6BAA6B,CAAC;IAC1E;;;;;;OAMG;IACH,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACnF;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;CAC1E,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/sandbox/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EACN,6BAA6B,EAC7B,+BAA+B,EAC/B,0BAA0B,GAC1B,MAAM,kCAAkC,CAAA;AAUzC,MAAM,UAAU,mBAAmB,CAAC,MAAqB;IACxD,QAAQ,MAAM,EAAE,CAAC;QAChB,KAAK,UAAU,CAAC;QAChB,KAAK,OAAO,CAAC;QACb,KAAK,MAAM,CAAC;QACZ,KAAK,WAAW;YACf,OAAM;QACP,OAAO,CAAC,CAAC,CAAC;YACT,MAAM,WAAW,GAAU,MAAM,CAAA;YACjC,MAAM,IAAI,KAAK,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAA;QACzD,CAAC;IACF,CAAC;AACF,CAAC;AAQD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAkC;IAClE,aAAa;IACb,gBAAgB;IAChB,iBAAiB;IACjB,OAAO;CACP,CAAA;AAmBD,MAAM,CAAC,MAAM,0BAA0B,GAAuC;IAC7E,YAAY;IACZ,SAAS;IACT,SAAS;CACT,CAAA;AAKD,MAAM,UAAU,wBAAwB,CAAC,GAAuB;IAC/D,0EAA0E;IAC1E,wEAAwE;IACxE,iEAAiE;IACjE,IAAI,oBAAoB,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAM;IAC9C,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAA;AACtD,CAAC;AA6aD,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACnC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC5C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,0BAA0B,CAAC;IACpE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,+BAA+B,CAAC;IAC7E,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,6BAA6B,CAAC;IAC1E;;;;;;OAMG;IACH,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACnF;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;CAC1E,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namzu/sdk",
3
- "version": "33.1.1",
3
+ "version": "34.0.1",
4
4
  "description": "Open-source AI agent SDK with a built-in runtime. Nothing between you and your agents.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "engines": {
@@ -84,6 +84,11 @@ export class PipelineAgent extends AbstractAgent<PipelineAgentConfig, PipelineAg
84
84
  config: PipelineAgentConfig,
85
85
  listener?: RunEventListener,
86
86
  ): Promise<PipelineAgentResult> {
87
+ if (config.sandbox) {
88
+ throw new Error(
89
+ 'PipelineAgent cannot enforce a run-level sandbox around developer-authored step callbacks. Configure confinement inside each step or use a tool-running agent.',
90
+ )
91
+ }
87
92
  const startTime = Date.now()
88
93
  const runId = this.createRunId()
89
94
  this.bindRun(runId, config.logger)
@@ -128,6 +128,7 @@ export class ReactiveAgent extends AbstractAgent<ReactiveAgentConfig, ReactiveAg
128
128
  model: config.model,
129
129
  tokenBudget: config.tokenBudget,
130
130
  timeoutMs: config.timeoutMs,
131
+ ...(config.sandbox ? { sandbox: config.sandbox } : {}),
131
132
  ...(config.streamIdleTimeoutMs !== undefined
132
133
  ? { streamIdleTimeoutMs: config.streamIdleTimeoutMs }
133
134
  : {}),
@@ -319,6 +319,7 @@ export class SupervisorAgent extends AbstractAgent<SupervisorAgentConfig, Superv
319
319
  model: config.model,
320
320
  tokenBudget: config.tokenBudget,
321
321
  timeoutMs: config.timeoutMs,
322
+ ...(config.sandbox ? { sandbox: config.sandbox } : {}),
322
323
  ...(config.streamIdleTimeoutMs !== undefined
323
324
  ? { streamIdleTimeoutMs: config.streamIdleTimeoutMs }
324
325
  : {}),
@@ -66,6 +66,8 @@ export interface RunAgentOptions extends AgentIdentity {
66
66
  tools?: ToolRegistryContract
67
67
  /** Execute sandbox-aware tools inside this provider's boundary. */
68
68
  sandboxProvider?: SandboxProvider
69
+ /** What a supplied sandbox is rooted at and its per-run limits. */
70
+ sandbox?: import('../types/run/config.js').AgentRunConfig['sandbox']
69
71
  /** Sandbox teardown wait; defaults to 30 seconds and `0` is unbounded. */
70
72
  sandboxTeardownTimeoutMs?: number
71
73
 
@@ -266,6 +268,7 @@ export async function runAgent(options: RunAgentOptions): Promise<RunAgentResult
266
268
  workingDirectory: options.workingDirectory ?? process.cwd(),
267
269
  runConfig: {
268
270
  model: options.model,
271
+ ...(options.sandbox ? { sandbox: options.sandbox } : {}),
269
272
  maxIterations: options.maxIterations ?? DEFAULT_MAX_ITERATIONS,
270
273
  tokenBudget: options.tokenBudget ?? DEFAULT_TOKEN_BUDGET,
271
274
  timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
@@ -386,6 +386,12 @@ export class AgentManager {
386
386
  // key, the same direction it already wins for `model` and `effort`.
387
387
  const inheritedEnv = mergeEnv(childConfig.env, options.configOverrides?.env)
388
388
  if (inheritedEnv) childConfig.env = inheritedEnv
389
+ // A builder may ignore a newly-added factory option. The requested root
390
+ // policy is an execution boundary, so stamp an explicit child override
391
+ // after the builder rather than silently falling back to ephemeral.
392
+ if (options.configOverrides?.sandbox) {
393
+ childConfig.sandbox = options.configOverrides.sandbox
394
+ }
389
395
  } else {
390
396
  this.log.warn('No configBuilder, using bare config', {
391
397
  [GENAI.AGENT_ID]: options.agentId,
@@ -408,6 +414,7 @@ export class AgentManager {
408
414
  thinking: options.configOverrides?.thinking,
409
415
  effort: options.configOverrides?.effort,
410
416
  env: options.configOverrides?.env,
417
+ sandbox: options.configOverrides?.sandbox,
411
418
  sessionId: spawnRecord.childSessionId,
412
419
  topicId: context.topicId,
413
420
  projectId: context.projectId,
@@ -1,6 +1,6 @@
1
- import { lstat, readFile, readdir } from 'node:fs/promises'
2
- import { homedir } from 'node:os'
3
- import { join } from 'node:path'
1
+ import { lstat, readFile, readdir, realpath } from 'node:fs/promises'
2
+ import { homedir, platform } from 'node:os'
3
+ import { join, resolve } from 'node:path'
4
4
  import {
5
5
  PLUGIN_MANIFEST_FILENAME,
6
6
  PROJECT_PLUGIN_DIR,
@@ -261,9 +261,10 @@ export async function discoverAllPluginDirs(
261
261
 
262
262
  const projectRoot = workingDirectory ?? process.cwd()
263
263
  const userRoot = homedir()
264
+ const sharedRoot = await samePhysicalDirectory(projectRoot, userRoot)
264
265
 
265
266
  const [project, user] = await Promise.all([
266
- mayScan('project')
267
+ mayScan('project') && !sharedRoot
267
268
  ? discoverScopedPlugins(projectRoot, PROJECT_PLUGIN_DIR, 'project', options?.log)
268
269
  : Promise.resolve([]),
269
270
  mayScan('user')
@@ -275,7 +276,30 @@ export async function discoverAllPluginDirs(
275
276
  'namzu.plugin.project_count': project.length,
276
277
  'namzu.plugin.user_count': user.length,
277
278
  ...(scopes ? { 'namzu.plugin.allowed_scopes': scopes } : {}),
279
+ ...(sharedRoot ? { 'namzu.plugin.shared_user_project_root': true } : {}),
278
280
  })
279
281
 
280
282
  return { project, user }
281
283
  }
284
+
285
+ /**
286
+ * Whether two scope roots name the same directory, including through a
287
+ * symlink. When home is the working directory, `.namzu/plugins` is user state:
288
+ * treating the same bytes as project state would let a project-only trust
289
+ * policy admit user-owned executable code, while scanning both installs it
290
+ * twice. Missing roots fall back to normalized absolute names; discovery will
291
+ * independently report them empty.
292
+ */
293
+ async function samePhysicalDirectory(left: string, right: string): Promise<boolean> {
294
+ const canonical = async (path: string): Promise<string> => {
295
+ let value: string
296
+ try {
297
+ value = await realpath(path)
298
+ } catch {
299
+ value = resolve(path)
300
+ }
301
+ return platform() === 'win32' ? value.toLocaleLowerCase('en-US') : value
302
+ }
303
+ const [a, b] = await Promise.all([canonical(left), canonical(right)])
304
+ return a === b
305
+ }
@@ -2396,6 +2396,16 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
2396
2396
  details: { workspace: 'working-directory' },
2397
2397
  })
2398
2398
  }
2399
+ if (rootAtCwd && !params.sandboxProvider.workspaceModes?.includes('working-directory')) {
2400
+ throw new NamzuError({
2401
+ code: 'invalid_config',
2402
+ message: `Sandbox provider '${params.sandboxProvider.id}' does not advertise working-directory workspace support. Refusing instead of passing a project path the provider may ignore.`,
2403
+ details: {
2404
+ providerId: params.sandboxProvider.id,
2405
+ workspace: 'working-directory',
2406
+ },
2407
+ })
2408
+ }
2399
2409
  const acquisition = await acquireSandbox({
2400
2410
  provider: params.sandboxProvider,
2401
2411
  config: {
@@ -10,7 +10,7 @@ import {
10
10
  stat,
11
11
  } from 'node:fs/promises'
12
12
  import { tmpdir } from 'node:os'
13
- import { dirname, isAbsolute, join, relative, resolve } from 'node:path'
13
+ import { dirname, isAbsolute, join, parse, resolve } from 'node:path'
14
14
  import { NAMZU } from '../../constants/telemetry/index.js'
15
15
  import { SCOPE_ATTRIBUTE } from '../../utils/log/types.js'
16
16
 
@@ -25,6 +25,7 @@ import {
25
25
  // registry needs the same one, and a near-copy would reproduce in the copy
26
26
  // every bug the original's comment was written to record.
27
27
  import { killTree } from '../../process/kill-tree.js'
28
+ import { resolveWithinReal } from '../../tools/paths.js'
28
29
  import type { SandboxId } from '../../types/ids/index.js'
29
30
  import type {
30
31
  Sandbox,
@@ -49,19 +50,6 @@ import {
49
50
  import { assertIsolation, describeIsolation } from '../isolation.js'
50
51
  import type { PtyLoader } from '../terminal.js'
51
52
 
52
- // ---------------------------------------------------------------------------
53
- // Path safety
54
- // ---------------------------------------------------------------------------
55
-
56
- function assertInsideSandbox(sandboxRoot: string, targetPath: string): string {
57
- const resolved = resolve(sandboxRoot, targetPath)
58
- const rel = relative(sandboxRoot, resolved)
59
- if (rel.startsWith('..') || isAbsolute(rel)) {
60
- throw new Error(`Path escapes sandbox: ${targetPath}`)
61
- }
62
- return resolved
63
- }
64
-
65
53
  // ---------------------------------------------------------------------------
66
54
  // Platform detection
67
55
  // ---------------------------------------------------------------------------
@@ -289,7 +277,7 @@ export function buildLimitedSpawn(request: LimitedSpawnRequest): {
289
277
  case 'macos-seatbelt':
290
278
  return {
291
279
  spawnCommand: requiredWrapper(request),
292
- spawnArgs: ['-p', buildSeatbeltProfile(rootDir), '--', ...inner],
280
+ spawnArgs: [...buildSeatbeltArgs(rootDir), '--', ...inner],
293
281
  }
294
282
 
295
283
  case 'basic': {
@@ -332,10 +320,7 @@ function detectEnvironment(): DetectedEnvironment {
332
320
 
333
321
  if (platform === 'darwin') {
334
322
  const seatbelt = resolveTrustedWrapper('sandbox-exec')
335
- if (
336
- seatbelt !== undefined &&
337
- probeSandboxSpawn(seatbelt, ['-p', buildSeatbeltProfile(tmpdir())])
338
- ) {
323
+ if (seatbelt !== undefined && probeSandboxSpawn(seatbelt, buildSeatbeltArgs(tmpdir()))) {
339
324
  return { environment: 'macos-seatbelt', wrapperCommand: seatbelt }
340
325
  }
341
326
  }
@@ -465,9 +450,7 @@ const BWRAP_SYSTEM_PATHS: readonly string[] = [
465
450
  '/opt',
466
451
  ]
467
452
 
468
- function buildSeatbeltProfile(sandboxRoot: string): string {
469
- const root = canonicalizePath(sandboxRoot)
470
-
453
+ function buildSeatbeltProfile(): string {
471
454
  return [
472
455
  '(version 1)',
473
456
  '(deny default)',
@@ -479,8 +462,8 @@ function buildSeatbeltProfile(sandboxRoot: string): string {
479
462
  '(allow signal (target same-sandbox))',
480
463
 
481
464
  // --- Sandbox workspace — full read/write ---
482
- `(allow file-read* (subpath "${root}"))`,
483
- `(allow file-write* (subpath "${root}"))`,
465
+ '(allow file-read* (subpath (param "NAMZU_SANDBOX_ROOT")))',
466
+ '(allow file-write* (subpath (param "NAMZU_SANDBOX_ROOT")))',
484
467
 
485
468
  // --- Root path literal — dyld needs this for path resolution ---
486
469
  '(allow file-read* (literal "/"))',
@@ -547,6 +530,18 @@ function buildSeatbeltProfile(sandboxRoot: string): string {
547
530
  ].join('\n')
548
531
  }
549
532
 
533
+ /**
534
+ * Keep caller-controlled paths out of SBPL source entirely.
535
+ *
536
+ * `sandbox-exec -Dname=value` binds an opaque argv value to `(param "name")`;
537
+ * quotes, newlines, and parentheses in a legal Unix directory name therefore
538
+ * remain path bytes instead of becoming policy syntax. This is the same
539
+ * parameter boundary used by Codex's seatbelt builder.
540
+ */
541
+ function buildSeatbeltArgs(sandboxRoot: string): string[] {
542
+ return ['-p', buildSeatbeltProfile(), `-DNAMZU_SANDBOX_ROOT=${canonicalizePath(sandboxRoot)}`]
543
+ }
544
+
550
545
  // ---------------------------------------------------------------------------
551
546
  // Environment building
552
547
  // ---------------------------------------------------------------------------
@@ -610,6 +605,7 @@ class LocalSandbox implements Sandbox {
610
605
  rootDir: string,
611
606
  environment: SandboxEnvironment,
612
607
  private readonly wrapperCommand: string | undefined,
608
+ private readonly removeRootOnDestroy: boolean,
613
609
  config: SandboxCreateConfig,
614
610
  log: Logger,
615
611
  ) {
@@ -618,7 +614,10 @@ class LocalSandbox implements Sandbox {
618
614
  this.environment = environment
619
615
  this.config = config
620
616
  this._status = 'ready'
621
- this.log = log.child({ [SCOPE_ATTRIBUTE]: 'sandbox/provider/local', [NAMZU.SANDBOX_ID]: id })
617
+ this.log = log.child({
618
+ [SCOPE_ATTRIBUTE]: 'sandbox/provider/local',
619
+ [NAMZU.SANDBOX_ID]: id,
620
+ })
622
621
 
623
622
  this.log.info('Sandbox created', {
624
623
  'namzu.sandbox.root_dir': rootDir,
@@ -641,7 +640,7 @@ class LocalSandbox implements Sandbox {
641
640
  const env = buildSafeEnv(this.config.env, opts?.env)
642
641
  const timeout = opts?.timeout ?? this.config.timeoutMs ?? SANDBOX_DEFAULT_TIMEOUT_MS
643
642
 
644
- const cwd = opts?.cwd ? assertInsideSandbox(this.rootDir, opts.cwd) : this.rootDir
643
+ const cwd = opts?.cwd ? await resolveWithinReal(this.rootDir, opts.cwd) : this.rootDir
645
644
 
646
645
  const { spawnCommand, spawnArgs, bwrapInfoFd, bwrapBlockFd } = this.buildSpawnArgs(
647
646
  command,
@@ -690,7 +689,7 @@ class LocalSandbox implements Sandbox {
690
689
  throw new Error(`Sandbox ${this.id} is destroyed`)
691
690
  }
692
691
 
693
- const resolved = assertInsideSandbox(this.rootDir, path)
692
+ const resolved = await resolveWithinReal(this.rootDir, path)
694
693
  await mkdir(dirname(resolved), { recursive: true })
695
694
 
696
695
  // Convention 8: Atomic write (write-tmp-rename)
@@ -706,7 +705,7 @@ class LocalSandbox implements Sandbox {
706
705
  throw new Error(`Sandbox ${this.id} is destroyed`)
707
706
  }
708
707
 
709
- const resolved = assertInsideSandbox(this.rootDir, path)
708
+ const resolved = await resolveWithinReal(this.rootDir, path)
710
709
  return fsReadFile(resolved)
711
710
  }
712
711
 
@@ -715,7 +714,7 @@ class LocalSandbox implements Sandbox {
715
714
  throw new Error(`Sandbox ${this.id} is destroyed`)
716
715
  }
717
716
 
718
- const resolved = assertInsideSandbox(this.rootDir, rootPath)
717
+ const resolved = await resolveWithinReal(this.rootDir, rootPath)
719
718
  const root = await stat(resolved).catch(() => null)
720
719
  if (!root || !root.isDirectory()) return []
721
720
 
@@ -746,7 +745,12 @@ class LocalSandbox implements Sandbox {
746
745
  }
747
746
 
748
747
  this._status = 'destroyed'
749
- await rm(this.rootDir, { recursive: true, force: true })
748
+ // A generated temp root belongs to this allocation. A working-directory
749
+ // root belongs to the caller. Conflating those lifetimes turns normal run
750
+ // teardown into recursive deletion of the project the run just edited.
751
+ if (this.removeRootOnDestroy) {
752
+ await rm(this.rootDir, { recursive: true, force: true })
753
+ }
750
754
 
751
755
  this.log.info('Sandbox destroyed', { 'namzu.sandbox.id': this.id })
752
756
  }
@@ -974,6 +978,7 @@ export interface LocalSandboxProviderOptions {
974
978
  export class LocalSandboxProvider implements SandboxProvider {
975
979
  readonly id = 'local'
976
980
  readonly name = 'Local Sandbox'
981
+ readonly workspaceModes = ['ephemeral', 'working-directory'] as const
977
982
  readonly environment: SandboxEnvironment
978
983
 
979
984
  private readonly log: Logger
@@ -1016,25 +1021,59 @@ export class LocalSandboxProvider implements SandboxProvider {
1016
1021
  async create(config?: SandboxCreateConfig): Promise<Sandbox> {
1017
1022
  config?.signal?.throwIfAborted()
1018
1023
  const id = generateSandboxId()
1024
+ let rootDir: string
1025
+ let removeRootOnDestroy: boolean
1019
1026
 
1020
- // mkdtemp is in node:fs/promises but requires an async import-style usage.
1021
- // We use the same pattern: create a unique dir under os.tmpdir().
1022
- const { mkdtemp } = await import('node:fs/promises')
1023
- const rawDir = await mkdtemp(join(tmpdir(), SANDBOX_TEMP_DIR_PREFIX))
1027
+ if (config?.workingDirectory !== undefined) {
1028
+ const requested = resolve(config.workingDirectory)
1029
+ let entry: Awaited<ReturnType<typeof stat>>
1030
+ try {
1031
+ entry = await stat(requested)
1032
+ } catch (error) {
1033
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
1034
+ throw new Error(`Sandbox workingDirectory does not exist: ${requested}`, {
1035
+ cause: error,
1036
+ })
1037
+ }
1038
+ throw new Error(`Sandbox workingDirectory could not be inspected: ${requested}`, {
1039
+ cause: error,
1040
+ })
1041
+ }
1042
+ if (!entry.isDirectory()) {
1043
+ throw new Error(`Sandbox workingDirectory is not a directory: ${requested}`)
1044
+ }
1045
+ // The caller owns this tree. The sandbox handle may be per run, but the
1046
+ // workspace survives every handle created for the session.
1047
+ rootDir = canonicalizePath(requested)
1048
+ if (rootDir === parse(rootDir).root) {
1049
+ throw new Error(
1050
+ `Sandbox workingDirectory cannot be a filesystem root: ${rootDir}. Choose a project directory so filesystem confinement has a boundary.`,
1051
+ )
1052
+ }
1053
+ removeRootOnDestroy = false
1054
+ } else {
1055
+ // No workspace was named: this allocation owns a fresh temporary root.
1056
+ const { mkdtemp } = await import('node:fs/promises')
1057
+ const rawDir = await mkdtemp(join(tmpdir(), SANDBOX_TEMP_DIR_PREFIX))
1058
+ rootDir = canonicalizePath(rawDir)
1059
+ removeRootOnDestroy = true
1060
+ }
1024
1061
  if (config?.signal?.aborted) {
1025
- await rm(rawDir, { recursive: true, force: true })
1062
+ if (removeRootOnDestroy) await rm(rootDir, { recursive: true, force: true })
1026
1063
  throw config.signal.reason
1027
1064
  }
1028
- // Canonicalize — macOS symlinks like /var → /private/var must be resolved
1029
- const rootDir = canonicalizePath(rawDir)
1030
1065
 
1031
- this.log.info('Creating sandbox', { 'namzu.sandbox.id': id, 'namzu.sandbox.root_dir': rootDir })
1066
+ this.log.info('Creating sandbox', {
1067
+ 'namzu.sandbox.id': id,
1068
+ 'namzu.sandbox.root_dir': rootDir,
1069
+ })
1032
1070
 
1033
1071
  return new LocalSandbox(
1034
1072
  id,
1035
1073
  rootDir,
1036
1074
  this.environment,
1037
1075
  this.wrapperCommand,
1076
+ removeRootOnDestroy,
1038
1077
  config ?? {},
1039
1078
  this.log,
1040
1079
  )
@@ -28,6 +28,14 @@ import { type Logger, resolveLogger } from '../utils/logger.js'
28
28
  */
29
29
  const GATEWAY_TASK_LEDGER_CAP = 1_000
30
30
 
31
+ interface ObserverDelivery {
32
+ busy: boolean
33
+ readonly queue: Array<{
34
+ readonly event: Parameters<RunEventListener>[0]
35
+ readonly observer: 'scheduler' | 'task'
36
+ }>
37
+ }
38
+
31
39
  export class LocalTaskScheduler implements TaskScheduler {
32
40
  private agentManager: AgentManagerContract
33
41
  private taskContext: AgentTaskContext
@@ -56,6 +64,15 @@ export class LocalTaskScheduler implements TaskScheduler {
56
64
  private siblingFailurePolicy: SiblingFailurePolicy = 'continue'
57
65
  /** See {@link onTaskProgress}. */
58
66
  private readonly progressListeners = new Set<(taskId: TaskId) => void>()
67
+ /**
68
+ * One non-blocking delivery chain per observer.
69
+ *
70
+ * Child streaming never awaits these promises, but a listener still sees
71
+ * its own events in source order. Keeping the chains separate also means a
72
+ * slow exporter cannot hold up a task-specific screen (or another task's
73
+ * screen) that uses a different callback.
74
+ */
75
+ private readonly observerDeliveries = new WeakMap<RunEventListener, ObserverDelivery>()
59
76
  /** Raw, unresolved — kept as the caller handed it so each of the two log
60
77
  * sites below resolves it independently via `resolveLogger`, rather than
61
78
  * this constructor baking in ONE `.child()` binding both would then share
@@ -150,7 +167,15 @@ export class LocalTaskScheduler implements TaskScheduler {
150
167
  // tool's own description tells the model to use — the event loop
151
168
  // interleaves and three of the four died. Found by running one.
152
169
  (event) => {
153
- this.listener?.(event)
170
+ // A scheduler-wide observer and this task's observer are independent.
171
+ // Either may throw or reject: observation is not authority over the
172
+ // child, and one broken screen/export must neither stop the run nor
173
+ // suppress the other observer. Async listeners are deliberately not
174
+ // awaited, so a slow renderer cannot backpressure model streaming.
175
+ this.deliverEvent(this.listener, event, 'scheduler')
176
+ if (options.onEvent !== this.listener) {
177
+ this.deliverEvent(options.onEvent, event, 'task')
178
+ }
154
179
  // No id yet means nothing is waiting on this task: the caller
155
180
  // does not hold the handle, so an idle bound cannot be running
156
181
  // against it. There is no progress to report to anyone.
@@ -190,6 +215,67 @@ export class LocalTaskScheduler implements TaskScheduler {
190
215
  return toHandle(task)
191
216
  }
192
217
 
218
+ private deliverEvent(
219
+ listener: RunEventListener | undefined,
220
+ event: Parameters<RunEventListener>[0],
221
+ observer: 'scheduler' | 'task',
222
+ ): void {
223
+ if (!listener) return
224
+
225
+ // Each observer receives its own value graph. RunEvent is readonly at the
226
+ // type boundary, but a JavaScript consumer can still mutate an object it
227
+ // was handed; that must not forge what the next independent observer sees.
228
+ const snapshot = structuredClone(event)
229
+ let delivery = this.observerDeliveries.get(listener)
230
+ if (!delivery) {
231
+ delivery = { busy: false, queue: [] }
232
+ this.observerDeliveries.set(listener, delivery)
233
+ }
234
+ delivery.queue.push({ event: snapshot, observer })
235
+ this.drainObserver(listener, delivery)
236
+ }
237
+
238
+ private drainObserver(listener: RunEventListener, delivery: ObserverDelivery): void {
239
+ if (delivery.busy) return
240
+ while (delivery.queue.length > 0) {
241
+ const next = delivery.queue.shift()
242
+ if (!next) return
243
+ try {
244
+ const pending = listener(next.event)
245
+ if (!pending) continue
246
+ delivery.busy = true
247
+ void pending.then(
248
+ () => {
249
+ delivery.busy = false
250
+ this.drainObserver(listener, delivery)
251
+ },
252
+ (error) => {
253
+ this.reportObserverFailure(next.event.type, next.observer, error)
254
+ delivery.busy = false
255
+ this.drainObserver(listener, delivery)
256
+ },
257
+ )
258
+ return
259
+ } catch (error) {
260
+ this.reportObserverFailure(next.event.type, next.observer, error)
261
+ }
262
+ }
263
+ }
264
+
265
+ private reportObserverFailure(
266
+ eventType: Parameters<RunEventListener>[0]['type'],
267
+ observer: 'scheduler' | 'task',
268
+ error: unknown,
269
+ ): void {
270
+ resolveLogger(this.log)
271
+ .child({ [SCOPE_ATTRIBUTE]: 'scheduler/local' })
272
+ .warn('Task event observer failed', {
273
+ 'namzu.event.type': eventType,
274
+ 'namzu.scheduler.observer': observer,
275
+ 'exception.message': toErrorMessage(error),
276
+ })
277
+ }
278
+
193
279
  /**
194
280
  * Decide what a failed child means for the ones still running.
195
281
  *
@@ -31,6 +31,15 @@ export interface BaseAgentConfig {
31
31
  costLimitUsd?: number
32
32
  permissionMode?: PermissionMode
33
33
 
34
+ /**
35
+ * Run-level sandbox limits and workspace ownership.
36
+ *
37
+ * A provider alone only says HOW commands are confined. This field says
38
+ * WHAT it is rooted at; `working-directory` makes sandbox-aware tools act
39
+ * on the run's declared workspace instead of a disposable empty tree.
40
+ */
41
+ sandbox?: import('../run/config.js').AgentRunConfig['sandbox']
42
+
34
43
  /**
35
44
  * The tools this run may use, narrowing whatever its registry holds.
36
45
  *
@@ -53,6 +53,7 @@ export interface AgentFactoryOptions {
53
53
  maxResponseTokens?: number
54
54
  env?: Record<string, string>
55
55
  permissionMode?: 'plan' | 'auto'
56
+ sandbox?: BaseAgentConfig['sandbox']
56
57
 
57
58
  systemPrompt?: string
58
59
 
@@ -1,6 +1,7 @@
1
1
  import type { TaskId } from '../ids/index.js'
2
2
  import type { AgentPersona } from '../persona/index.js'
3
3
  import type { CancelCause } from '../run/cancel-cause.js'
4
+ import type { RunEventListener } from '../run/events.js'
4
5
  import type { AgentRuntimeContext, BaseAgentConfig, BaseAgentResult } from './base.js'
5
6
  import type { AgentTaskState } from './task.js'
6
7
 
@@ -27,6 +28,18 @@ export interface TaskHandle {
27
28
  export type SiblingFailurePolicy = 'continue' | 'cancel-siblings'
28
29
 
29
30
  export interface CreateTaskOptions {
31
+ /**
32
+ * Observe events from this one delegated run when the scheduler can expose
33
+ * them.
34
+ *
35
+ * The built-in local scheduler supports this without replacing its
36
+ * scheduler-wide listener. Delivery is observational and must not
37
+ * backpressure or decide the child run; a remote/custom scheduler may omit
38
+ * it when that transport has no event stream. Callers must therefore settle
39
+ * their task view from the returned {@link TaskHandle} as well.
40
+ */
41
+ readonly onEvent?: RunEventListener
42
+
30
43
  /**
31
44
  * Span the spawned run should hang off — normally the executing tool's
32
45
  * own span, so the delegation shows up inside the turn that asked for
@@ -473,6 +473,9 @@ export interface SandboxCreateConfig {
473
473
  readonly maxProcesses?: number
474
474
  }
475
475
 
476
+ /** Workspace-root contracts a provider can enforce honestly. */
477
+ export type SandboxWorkspaceMode = 'ephemeral' | 'working-directory'
478
+
476
479
  /**
477
480
  * Tier-specific layout types ({@link ContainerSandboxLayout}, future
478
481
  * `MicroVMSandboxLayout`, etc.) are intentionally NOT fields on
@@ -497,6 +500,15 @@ export interface SandboxProvider {
497
500
  readonly id: string
498
501
  readonly name: string
499
502
  readonly environment: SandboxEnvironment
503
+ /**
504
+ * Root modes this provider actually implements.
505
+ *
506
+ * Optional for legacy providers using the ephemeral default. The kernel
507
+ * refuses an explicit `working-directory` request unless that mode is
508
+ * advertised; accepting `workingDirectory` and ignoring it would report a
509
+ * boundary around a project the provider never mounted.
510
+ */
511
+ readonly workspaceModes?: readonly SandboxWorkspaceMode[]
500
512
  create(config?: SandboxCreateConfig): Promise<Sandbox>
501
513
  }
502
514