super-dsh 0.1.12 → 0.3.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.
Files changed (856) hide show
  1. package/README.md +50 -13
  2. package/agent-agy/dist/world-plugin.d.ts +1 -1
  3. package/agent-agy/dist/world-plugin.js +14 -27
  4. package/agent-agy-sdk/dist/world-plugin.d.ts +1 -1
  5. package/agent-agy-sdk/dist/world-plugin.js +14 -27
  6. package/agent-codex/dist/world-plugin.js +14 -27
  7. package/agent-codex-sdk/dist/world-plugin.js +14 -43
  8. package/agent-hermes/dist/world-plugin.js +14 -27
  9. package/agent-omp/dist/world-plugin.js +14 -39
  10. package/agent-omp/lib/client/index.js +258 -0
  11. package/agent-omp-sdk/dist/world-plugin.d.ts +1 -1
  12. package/agent-omp-sdk/dist/world-plugin.js +14 -43
  13. package/agent-pi/dist/world-plugin.js +14 -27
  14. package/bundles/better-dsh.tgz +0 -0
  15. package/bundles/manifest.json +10 -0
  16. package/client/index.js +434 -307
  17. package/cordis.patch.yml +7 -16
  18. package/node_modules/better-dsh/LICENSE +24 -0
  19. package/node_modules/better-dsh/README.md +323 -0
  20. package/node_modules/better-dsh/THIRD_PARTY_NOTICES.md +52 -0
  21. package/node_modules/better-dsh/cordis.patch.yml +139 -0
  22. package/node_modules/better-dsh/docs/00_adr/0001-bridge-tool-layer-not-service-layer.md +14 -0
  23. package/node_modules/better-dsh/docs/00_adr/0002-masking-is-presentation-only.md +15 -0
  24. package/node_modules/better-dsh/docs/10_plans/2026-09-23-remote-execution-framework.md +236 -0
  25. package/node_modules/better-dsh/docs/10_plans/2026-09-23-remote-framework-impl.md +2083 -0
  26. package/node_modules/better-dsh/docs/10_plans/2026-09-26-lsp-ast-reminder.md +64 -0
  27. package/node_modules/better-dsh/docs/10_plans/A2A-messaging-channel-test-archive.md +256 -0
  28. package/node_modules/better-dsh/docs/10_plans/code-mode-vs-rlm-ipython-comparison.md +137 -0
  29. package/node_modules/better-dsh/docs/10_plans/dashr-blueprint-review.md +201 -0
  30. package/node_modules/better-dsh/docs/10_plans/dashr-blueprint.md +561 -0
  31. package/node_modules/better-dsh/docs/10_plans/dashr-compaction-window-and-archive.md +307 -0
  32. package/node_modules/better-dsh/docs/10_plans/dashr-profile-layer-feasibility.md +367 -0
  33. package/node_modules/better-dsh/docs/10_plans/dashr-sandbox-escalation-semantics-gap.md +171 -0
  34. package/node_modules/better-dsh/docs/10_plans/dashr-security-sandbox-analysis.md +187 -0
  35. package/node_modules/better-dsh/docs/10_plans/dashr-surface-invariant-and-omp-imports.md +97 -0
  36. package/node_modules/better-dsh/docs/10_plans/ipython-kernel-interactive-interface-test-report.md +152 -0
  37. package/node_modules/better-dsh/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +146 -0
  38. package/node_modules/better-dsh/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +50 -0
  39. package/node_modules/better-dsh/docs/10_plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +79 -0
  40. package/node_modules/better-dsh/docs/10_plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +138 -0
  41. package/node_modules/better-dsh/docs/10_plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +161 -0
  42. package/node_modules/better-dsh/docs/10_plans/kernel-refactoring/V0.1.5-development-plan.md +109 -0
  43. package/node_modules/better-dsh/docs/10_plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +50 -0
  44. package/node_modules/better-dsh/docs/10_plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +113 -0
  45. package/node_modules/better-dsh/docs/10_plans/recallable-compaction.md +147 -0
  46. package/node_modules/better-dsh/docs/10_plans/spike-tag-repro.mjs +102 -0
  47. package/node_modules/better-dsh/docs/10_plans/upstream-analysis.md +128 -0
  48. package/node_modules/better-dsh/docs/20_specs/agent/spec.md +54 -0
  49. package/node_modules/better-dsh/docs/20_specs/ast/spec.md +57 -0
  50. package/node_modules/better-dsh/docs/20_specs/compaction-recall/spec.md +46 -0
  51. package/node_modules/better-dsh/docs/20_specs/ctx/spec.md +107 -0
  52. package/node_modules/better-dsh/docs/20_specs/dsh/spec.md +47 -0
  53. package/node_modules/better-dsh/docs/20_specs/dvc/spec.md +106 -0
  54. package/node_modules/better-dsh/docs/20_specs/escalation-guidance/spec.md +44 -0
  55. package/node_modules/better-dsh/docs/20_specs/fs-scheme-resolution/spec.md +37 -0
  56. package/node_modules/better-dsh/docs/20_specs/hash-edit/spec.md +41 -0
  57. package/node_modules/better-dsh/docs/20_specs/http-read/spec.md +73 -0
  58. package/node_modules/better-dsh/docs/20_specs/kernel-provisioning/spec.md +53 -0
  59. package/node_modules/better-dsh/docs/20_specs/lsp/spec.md +121 -0
  60. package/node_modules/better-dsh/docs/20_specs/mobile-layout/spec.md +108 -0
  61. package/node_modules/better-dsh/docs/20_specs/model-failover/spec.md +20 -0
  62. package/node_modules/better-dsh/docs/20_specs/plugins-page-components/spec.md +79 -0
  63. package/node_modules/better-dsh/docs/20_specs/preact-ui-shell/spec.md +22 -0
  64. package/node_modules/better-dsh/docs/20_specs/repl-dispatch-resilience/spec.md +21 -0
  65. package/node_modules/better-dsh/docs/20_specs/skill/spec.md +58 -0
  66. package/node_modules/better-dsh/docs/20_specs/tool-surface/spec.md +222 -0
  67. package/node_modules/better-dsh/docs/20_specs/url-schema/spec.md +148 -0
  68. package/node_modules/better-dsh/docs/20_specs/web-trust-fence/spec.md +43 -0
  69. package/node_modules/better-dsh/docs/50_test-reports/2026-09-06-write/345/267/245/345/205/267sandbox/345/215/207/347/272/247/351/200/217/344/274/240bug/345/244/215/345/217/221/345/217/212/346/214/202/350/265/267-/344/272/213/344/273/266/346/212/245/345/221/212.md +176 -0
  70. package/node_modules/better-dsh/docs/50_test-reports/2026-09-08-hashline-edit-E_RANGE_UNVERIFIED/350/267/250/350/275/256/344/274/232/350/257/235/351/224/256/345/244/261/346/225/210-/350/257/212/346/226/255/346/212/245/345/221/212.md +226 -0
  71. package/node_modules/better-dsh/docs/50_test-reports/2026-09-11-control-prompt-into-eval-description/345/256/236/346/265/213/346/212/245/345/221/212.md +222 -0
  72. package/node_modules/better-dsh/docs/50_test-reports/2026-09-12-fs-scheme-resolution-/345/256/236/346/265/213/346/212/245/345/221/212.md +81 -0
  73. package/node_modules/better-dsh/docs/50_test-reports/2026-09-12-url-schemes-grammar-matrix/344/270/216catalog-centralize-/345/256/236/346/265/213/346/212/245/345/221/212.md +234 -0
  74. package/node_modules/better-dsh/docs/50_test-reports/2026-09-12-url-schemes-recallable-context-design/351/252/214/350/257/201/346/212/245/345/221/212.md +160 -0
  75. package/node_modules/better-dsh/docs/50_test-reports/2026-09-12-url-schemes-recallable-context-/345/256/236/346/265/213/345/211/247/346/234/254.md +44 -0
  76. package/node_modules/better-dsh/docs/50_test-reports/2026-09-12-url-schemes-recallable-context-/345/256/236/346/265/213/346/212/245/345/221/212.md +89 -0
  77. package/node_modules/better-dsh/docs/50_test-reports/2026-09-12-url-schemes-/345/205/255scheme/345/206/222/347/203/237/344/270/216/350/276/271/347/225/214/345/256/236/346/265/213/346/212/245/345/221/212.md +198 -0
  78. package/node_modules/better-dsh/docs/50_test-reports/2026-09-13-hashline-off/344/270/213scheme/345/217/257/350/276/276/346/200/247/345/267/245/345/205/267/351/235/242/344/270/215/345/257/271/347/247/260-/345/256/236/346/265/213/346/212/245/345/221/212.md +246 -0
  79. package/node_modules/better-dsh/docs/50_test-reports/2026-09-13-preact-ui-shell/345/256/236/346/265/213/346/212/245/345/221/212.md +50 -0
  80. package/node_modules/better-dsh/docs/50_test-reports/2026-09-14-4999-skill/346/270/205/345/215/225/344/270/216lsp-gate/345/256/236/346/265/213/346/212/245/345/221/212.md +63 -0
  81. package/node_modules/better-dsh/docs/50_test-reports/2026-09-17-plugins/351/241/265/345/205/255/347/273/204/344/273/266/346/213/206/345/210/206/345/256/236/346/265/213/346/212/245/345/221/212.md +76 -0
  82. package/node_modules/better-dsh/docs/50_test-reports/2026-09-22-4988/345/217/214/345/271/263/351/235/242/345/220/257/345/212/250/344/277/256/345/244/215/345/256/236/346/265/213/346/212/245/345/221/212.md +76 -0
  83. package/node_modules/better-dsh/docs/50_test-reports/2026-09-22-better-dsh/347/273/204/344/273/266/347/203/255/346/217/222/346/213/224/344/270/216/344/276/235/350/265/226/347/272/247/350/201/224/345/256/236/346/265/213/346/212/245/345/221/212.md +134 -0
  84. package/node_modules/better-dsh/docs/50_test-reports/2026-09-23-remote-framework/345/256/236/346/265/213/346/212/245/345/221/212.md +92 -0
  85. package/node_modules/better-dsh/docs/50_test-reports/2026-09-23-remote-framework/347/254/254/344/270/200/344/272/272/347/247/260/345/244/215/346/265/213/346/212/245/345/221/212.md +125 -0
  86. package/node_modules/better-dsh/docs/50_test-reports/2026-09-23-ssh/345/267/245/345/205/267assisted-pty/344/274/232/350/257/235framing/345/256/236/346/265/213/346/212/245/345/221/212.md +207 -0
  87. package/node_modules/better-dsh/docs/50_test-reports/2026-09-24-v0.1.7-rc.1/345/257/271/351/275/220/350/275/256-compaction/344/270/216failover/350/256/276/347/275/256/351/235/242/344/277/256/345/244/215/345/256/236/346/265/213/346/212/245/345/221/212.md +65 -0
  88. package/node_modules/better-dsh/docs/50_test-reports/2026-09-27-lsp-ast-reminder-4999/345/256/236/346/265/213/346/212/245/345/221/212.md +53 -0
  89. package/node_modules/better-dsh/docs/50_test-reports/2026-09-28-ctx-scheme/351/225/277/344/274/232/350/257/235utility/345/256/236/346/265/213/346/212/245/345/221/212.md +155 -0
  90. package/node_modules/better-dsh/docs/50_test-reports/2026-10-01-v0.2.4d-web-password-gate/345/256/236/346/265/213/346/212/245/345/221/212.md +105 -0
  91. package/node_modules/better-dsh/docs/50_test-reports/2026-10-02-better-dsh-schemastery/344/276/235/350/265/226/345/243/260/346/230/216/344/277/256/345/244/215/345/256/236/346/265/213/346/212/245/345/221/212.md +62 -0
  92. package/node_modules/better-dsh/docs/50_test-reports/2026-10-02-ctx-navigation/345/256/236/346/265/213/346/212/245/345/221/212.md +137 -0
  93. package/node_modules/better-dsh/docs/50_test-reports/2026-10-02-v0.2.0-rc.2/345/257/271/351/275/220/350/275/256/345/256/236/346/265/213/346/212/245/345/221/212.md +38 -0
  94. package/node_modules/better-dsh/docs/50_test-reports/2026-10-03-ast-engine-deomp-4999/345/256/236/346/265/213/346/212/245/345/221/212.md +325 -0
  95. package/node_modules/better-dsh/docs/50_test-reports/2026-10-03-better-dsh-tool-surface-repl-dvc-browser-ast-lsp-4999/345/256/236/346/265/213/346/212/245/345/221/212.md +185 -0
  96. package/node_modules/better-dsh/docs/50_test-reports/2026-10-03-docs-packaging-trim/345/256/236/346/265/213/346/212/245/345/221/212.md +82 -0
  97. package/node_modules/better-dsh/docs/50_test-reports/2026-10-03-physical-import/344/270/216llm-completion-ast/347/233/270/345/257/271/350/267/257/345/276/204/344/277/256/345/244/215/345/256/236/346/265/213/346/212/245/345/221/212.md +101 -0
  98. package/node_modules/better-dsh/docs/50_test-reports/2026-10-03-pnpm11/345/271/264/351/276/204/351/227/250/351/224/201/346/226/207/344/273/266/347/233/270/344/275/215/345/256/236/350/257/201.md +54 -0
  99. package/node_modules/better-dsh/docs/50_test-reports/2026-10-03-remote-BYO-PTY-label/351/207/215/346/236/204/347/254/254/344/270/200/344/272/272/347/247/260/345/256/236/346/265/213/346/212/245/345/221/212.md +447 -0
  100. package/node_modules/better-dsh/docs/50_test-reports/2026-10-03-schemastery-cosmokit/346/272/220/347/240/201/345/206/205/350/201/224/345/256/236/346/265/213/346/212/245/345/221/212.md +63 -0
  101. package/node_modules/better-dsh/docs/50_test-reports/2026-10-03-zero-npm-runtime-deps/345/256/236/346/265/213/346/212/245/345/221/212.md +82 -0
  102. package/node_modules/better-dsh/docs/50_test-reports/2026-10-04-ast-engine-deomp-0.2.5-d/345/217/221/345/270/203/351/252/214/346/224/266/346/212/245/345/221/212.md +220 -0
  103. package/node_modules/better-dsh/docs/50_test-reports/2026-10-04-ast_grep/344/270/216ast_edit/345/245/221/347/272/246/344/270/216/350/276/271/347/225/214/345/256/236/346/265/213/346/212/245/345/221/212.md +151 -0
  104. package/node_modules/better-dsh/docs/50_test-reports/2026-10-06-authentication-only-web-admission-4999.md +63 -0
  105. package/node_modules/better-dsh/docs/50_test-reports/2026-10-07-better-dsh-welcome-self-contained-4999.md +52 -0
  106. package/node_modules/better-dsh/docs/50_test-reports/REPL-/345/267/245/345/205/267/350/260/203/347/224/250-/346/210/252/346/226/255/350/257/212/346/226/255.md +110 -0
  107. package/node_modules/better-dsh/docs/50_test-reports/kernel-provisioning.md +44 -0
  108. package/node_modules/better-dsh/docs/50_test-reports/repl-kernel-provisioning-test-report.md +87 -0
  109. package/node_modules/better-dsh/docs/50_test-reports/upstream-dsh-0.1.2-alpha.5-local-test-report.md +81 -0
  110. package/node_modules/better-dsh/docs/50_test-reports/upstream-dsh-0.1.2-alpha.5-report.md +93 -0
  111. package/node_modules/better-dsh/docs/50_test-reports/upstream-dsh-0.1.3-alpha.2-local-test-report.md +44 -0
  112. package/node_modules/better-dsh/docs/50_test-reports/upstream-dsh-0.1.3-alpha.2-report.md +110 -0
  113. package/node_modules/better-dsh/docs/50_test-reports/upstream-dsh-0.1.5-rc.2-local-test-report.md +79 -0
  114. package/node_modules/better-dsh/docs/50_test-reports/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +142 -0
  115. package/node_modules/better-dsh/docs/50_test-reports/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +193 -0
  116. package/node_modules/better-dsh/docs/50_test-reports/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +96 -0
  117. package/node_modules/better-dsh/docs/50_test-reports/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +127 -0
  118. package/node_modules/better-dsh/docs/50_test-reports/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +150 -0
  119. package/node_modules/better-dsh/docs/50_test-reports/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +224 -0
  120. package/node_modules/better-dsh/docs/50_test-reports/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +168 -0
  121. package/node_modules/better-dsh/docs/50_test-reports/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +123 -0
  122. package/node_modules/better-dsh/docs/50_test-reports/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +110 -0
  123. package/node_modules/better-dsh/docs/50_test-reports/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +86 -0
  124. package/node_modules/better-dsh/docs/50_test-reports/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +66 -0
  125. package/node_modules/better-dsh/docs/50_test-reports/v0.2.1d-/345/256/236/346/265/213/346/212/245/345/221/212.md +67 -0
  126. package/node_modules/better-dsh/docs/50_test-reports/v0.2.1e-P1-/345/256/236/346/265/213/346/212/245/345/221/212.md +136 -0
  127. package/node_modules/better-dsh/docs/50_test-reports/v0.2.1ef-dev-audit-report.md +73 -0
  128. package/node_modules/better-dsh/docs/50_test-reports/v0.2.1f-plugin-shipped-ui-patches/345/256/236/346/265/213/346/212/245/345/221/212.md +102 -0
  129. package/node_modules/better-dsh/docs/50_test-reports/v0.2.3b-hashline-content-locator/345/256/236/346/265/213/346/212/245/345/221/212.md +73 -0
  130. package/node_modules/better-dsh/docs/50_test-reports/v0.2.3c-mobile-wave/345/256/236/346/265/213/346/212/245/345/221/212.md +47 -0
  131. package/node_modules/better-dsh/docs/50_test-reports/v0.2.4-ios-focus-zoom-suppression/345/256/236/346/265/213/346/212/245/345/221/212.md +158 -0
  132. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/SKILL.md +147 -0
  133. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch01-user-guide.md +123 -0
  134. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch02-plugin-basics.md +127 -0
  135. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch03-plugin-framework-practice.md +120 -0
  136. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch04-cordis-fundamentals.md +129 -0
  137. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch05-cordis-api.md +115 -0
  138. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch06-architecture.md +109 -0
  139. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch07-capability-seams.md +97 -0
  140. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch08-internals-pipelines.md +111 -0
  141. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch09-api-gateway.md +106 -0
  142. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch10-config-catalog.md +97 -0
  143. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch11-tool-catalog.md +121 -0
  144. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch12-persistence-catalog.md +109 -0
  145. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch13-subsystems-core-session.md +106 -0
  146. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch14-subsystems-agent-loop.md +111 -0
  147. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch15-subsystems-tool-execution.md +106 -0
  148. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch16-subsystems-session-data.md +132 -0
  149. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch17-subsystems-llm-streaming.md +128 -0
  150. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch18-subsystems-web-ui.md +142 -0
  151. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch19-cookbook.md +149 -0
  152. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch20-development-testing.md +87 -0
  153. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch21-postmortems.md +82 -0
  154. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/chapters/ch22-i18n.md +86 -0
  155. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/cheatsheet.md +67 -0
  156. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/glossary.md +57 -0
  157. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/skill/patterns.md +88 -0
  158. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/AGENTS.md +75 -0
  159. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/agent-lifecycle.md +84 -0
  160. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/agent-lifecycle.zh.md +86 -0
  161. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/api-gateway.md +164 -0
  162. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/api-gateway.zh.md +164 -0
  163. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/architecture.md +150 -0
  164. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/architecture.zh.md +154 -0
  165. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/capability-seams.md +543 -0
  166. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/capability-seams.zh.md +545 -0
  167. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/config-catalog.md +3473 -0
  168. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/config-catalog.zh.md +3474 -0
  169. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-package.md +117 -0
  170. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-package.zh.md +119 -0
  171. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-remote-api.md +197 -0
  172. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-remote-api.zh.md +197 -0
  173. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-settings-card.md +102 -0
  174. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-settings-card.zh.md +102 -0
  175. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-tool.md +101 -0
  176. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-tool.zh.md +103 -0
  177. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-vendored-package.md +59 -0
  178. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-a-vendored-package.zh.md +59 -0
  179. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-an-llm-adapter.md +43 -0
  180. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/adding-an-llm-adapter.zh.md +43 -0
  181. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/extension-cookbook.md +132 -0
  182. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/extension-cookbook.zh.md +136 -0
  183. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/maintaining-dsh-code-review.md +64 -0
  184. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/maintaining-dsh-code-review.zh.md +64 -0
  185. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
  186. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
  187. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/context.md +364 -0
  188. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/context.zh.md +366 -0
  189. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/events.md +207 -0
  190. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/events.zh.md +209 -0
  191. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/fiber.md +375 -0
  192. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/fiber.zh.md +377 -0
  193. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/inherited.md +39 -0
  194. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/registry.md +152 -0
  195. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/registry.zh.md +154 -0
  196. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/service.md +102 -0
  197. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-api/service.zh.md +104 -0
  198. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-primer.md +45 -0
  199. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-primer.zh.md +51 -0
  200. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/01-first-plugin.md +95 -0
  201. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/01-first-plugin.zh.md +95 -0
  202. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  203. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/02-lifecycle-and-effects.zh.md +98 -0
  204. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/03-services.md +98 -0
  205. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/03-services.zh.md +98 -0
  206. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/04-events.md +144 -0
  207. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/04-events.zh.md +144 -0
  208. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/05-config.md +84 -0
  209. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/05-config.zh.md +84 -0
  210. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/06-composition-and-hmr.md +113 -0
  211. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/06-composition-and-hmr.zh.md +113 -0
  212. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/07-into-the-harness.md +108 -0
  213. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/07-into-the-harness.zh.md +108 -0
  214. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/index.md +60 -0
  215. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/cordis-tutorial/index.zh.md +62 -0
  216. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/deepseek-llm-api-wire-extensions.md +163 -0
  217. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/deepseek-llm-api-wire-extensions.zh.md +163 -0
  218. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/defensive-patterns.md +33 -0
  219. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/defensive-patterns.zh.md +35 -0
  220. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/development.md +167 -0
  221. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/development.zh.md +173 -0
  222. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/event-producer-consumer.md +86 -0
  223. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/event-producer-consumer.zh.md +88 -0
  224. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/glossary.md +45 -0
  225. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/glossary.zh.md +45 -0
  226. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/graph-atlas.md +22 -0
  227. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/graph-atlas.zh.md +24 -0
  228. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/README.md +60 -0
  229. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/README.zh.md +62 -0
  230. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/style-samples.md +87 -0
  231. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/terminology.md +214 -0
  232. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/translation-prompt.md +263 -0
  233. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/translation-rules.md +69 -0
  234. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/i18n/translation-rules.zh.md +69 -0
  235. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/module-graph.md +1411 -0
  236. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/module-graph.zh.md +1413 -0
  237. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/persistence-catalog.md +1075 -0
  238. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/persistence-catalog.zh.md +1077 -0
  239. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0001-acp-default-export-drops-inject.md +113 -0
  240. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
  241. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
  242. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
  243. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
  244. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
  245. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
  246. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
  247. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/README.md +18 -0
  248. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/postmortem/README.zh.md +18 -0
  249. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/rescope.md +53 -0
  250. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/rescope.zh.md +53 -0
  251. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/README.md +61 -0
  252. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/README.zh.md +61 -0
  253. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/agent-team.md +207 -0
  254. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/agent-team.zh.md +207 -0
  255. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/approval.md +170 -0
  256. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/approval.zh.md +170 -0
  257. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/attachment.md +351 -0
  258. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/attachment.zh.md +351 -0
  259. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/client-modules.md +168 -0
  260. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/client-modules.zh.md +168 -0
  261. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/code-runtime.md +195 -0
  262. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/code-runtime.zh.md +195 -0
  263. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/commands.md +219 -0
  264. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/commands.zh.md +219 -0
  265. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/compaction.md +238 -0
  266. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/compaction.zh.md +238 -0
  267. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/conversation.md +258 -0
  268. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/conversation.zh.md +258 -0
  269. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/core.md +1209 -0
  270. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/core.zh.md +1219 -0
  271. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/credentials.md +329 -0
  272. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/credentials.zh.md +329 -0
  273. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/extensions.md +382 -0
  274. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/extensions.zh.md +382 -0
  275. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/feedback.md +266 -0
  276. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/feedback.zh.md +266 -0
  277. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/filesystem.md +505 -0
  278. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/filesystem.zh.md +505 -0
  279. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/goal.md +277 -0
  280. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/goal.zh.md +277 -0
  281. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/invariants.md +88 -0
  282. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/invariants.zh.md +88 -0
  283. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/jobs.md +290 -0
  284. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/jobs.zh.md +290 -0
  285. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/llm-streaming.md +1080 -0
  286. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/llm-streaming.zh.md +1086 -0
  287. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/lsp.md +202 -0
  288. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/lsp.zh.md +202 -0
  289. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/permission-presets.md +131 -0
  290. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/permission-presets.zh.md +131 -0
  291. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/persistence.md +395 -0
  292. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/persistence.zh.md +395 -0
  293. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/plan.md +87 -0
  294. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/plan.zh.md +87 -0
  295. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/sandbox.md +220 -0
  296. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/sandbox.zh.md +220 -0
  297. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/schedule.md +192 -0
  298. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/schedule.zh.md +192 -0
  299. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/scope.md +59 -0
  300. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/scope.zh.md +59 -0
  301. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-projection.md +354 -0
  302. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-projection.zh.md +354 -0
  303. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-query.md +509 -0
  304. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-query.zh.md +509 -0
  305. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-reference.md +219 -0
  306. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-reference.zh.md +219 -0
  307. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-telemetry.md +194 -0
  308. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-telemetry.zh.md +194 -0
  309. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-title.md +204 -0
  310. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session-title.zh.md +204 -0
  311. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session.md +1155 -0
  312. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/session.zh.md +1159 -0
  313. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/settings.md +405 -0
  314. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/settings.zh.md +405 -0
  315. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/shell.md +303 -0
  316. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/shell.zh.md +303 -0
  317. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/skills.md +354 -0
  318. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/skills.zh.md +354 -0
  319. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/slots.md +175 -0
  320. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/slots.zh.md +175 -0
  321. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/spill.md +117 -0
  322. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/spill.zh.md +117 -0
  323. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/storage.md +260 -0
  324. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/storage.zh.md +260 -0
  325. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/subagent.md +766 -0
  326. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/subagent.zh.md +770 -0
  327. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/subprocess.md +324 -0
  328. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/subprocess.zh.md +324 -0
  329. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/system-prompt.md +220 -0
  330. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/system-prompt.zh.md +220 -0
  331. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/terminal.md +184 -0
  332. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/terminal.zh.md +184 -0
  333. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/todo.md +32 -0
  334. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/todo.zh.md +32 -0
  335. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/token-meter.md +105 -0
  336. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/token-meter.zh.md +105 -0
  337. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/tools.md +720 -0
  338. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/tools.zh.md +720 -0
  339. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/typert.md +343 -0
  340. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/typert.zh.md +343 -0
  341. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/user-questions.md +178 -0
  342. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/user-questions.zh.md +178 -0
  343. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web-client.md +95 -0
  344. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web-client.zh.md +95 -0
  345. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web-server.md +154 -0
  346. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web-server.zh.md +154 -0
  347. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web.md +206 -0
  348. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/web.zh.md +206 -0
  349. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/webhook.md +70 -0
  350. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/webhook.zh.md +70 -0
  351. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/workflow.md +278 -0
  352. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/workflow.zh.md +278 -0
  353. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/workspace.md +321 -0
  354. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/subsystems/workspace.zh.md +321 -0
  355. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/testing.md +54 -0
  356. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/testing.zh.md +54 -0
  357. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/tool-catalog.md +2225 -0
  358. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/tool-catalog.zh.md +2233 -0
  359. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/tool-execution-pipeline.md +62 -0
  360. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/tool-execution-pipeline.zh.md +64 -0
  361. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/config.md +106 -0
  362. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/config.zh.md +106 -0
  363. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/index.md +144 -0
  364. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/index.zh.md +144 -0
  365. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/publish.md +183 -0
  366. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/publish.zh.md +183 -0
  367. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/tool.md +52 -0
  368. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/basic/tool.zh.md +52 -0
  369. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/events.md +143 -0
  370. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/events.zh.md +143 -0
  371. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/index.md +137 -0
  372. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/index.zh.md +137 -0
  373. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/service.md +148 -0
  374. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/framework/service.zh.md +150 -0
  375. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/dynamic-cordis.md +15 -0
  376. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/dynamic-cordis.zh.md +15 -0
  377. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/index.md +155 -0
  378. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/index.zh.md +155 -0
  379. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/llm-adapter.md +189 -0
  380. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/develop/practice/llm-adapter.zh.md +189 -0
  381. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/github-review.md +102 -0
  382. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/github-review.zh.md +102 -0
  383. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/index.md +30 -0
  384. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/index.zh.md +30 -0
  385. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/mcp-memory.md +101 -0
  386. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/mcp-memory.zh.md +101 -0
  387. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/network-proxy.md +85 -0
  388. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/network-proxy.zh.md +85 -0
  389. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/providers.md +190 -0
  390. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/providers.zh.md +190 -0
  391. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/python-sdk.md +150 -0
  392. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/python-sdk.zh.md +150 -0
  393. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/schedule.md +21 -0
  394. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/guide/schedule.zh.md +21 -0
  395. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/index.md +11 -0
  396. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/user/index.zh.md +11 -0
  397. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/web-styling.md +29 -0
  398. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/docs/web-styling.zh.md +29 -0
  399. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/site-pages-map.txt +234 -0
  400. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src/site-pages.json +232 -0
  401. package/node_modules/better-dsh/docs/80_upstream-docs-and-skills/dsh-dev-skill/src-README.md +63 -0
  402. package/node_modules/better-dsh/docs/dev-test-environment-notes.md +137 -0
  403. package/node_modules/better-dsh/docs/distro-blueprint.md +81 -0
  404. package/node_modules/better-dsh/docs/dsh-webUI-with-rlm-mode.png +0 -0
  405. package/node_modules/better-dsh/docs/repositioning-and-rebranding.md +102 -0
  406. package/node_modules/better-dsh/docs/specs/agent/spec.md +54 -0
  407. package/node_modules/better-dsh/docs/specs/ast/spec.md +57 -0
  408. package/node_modules/better-dsh/docs/specs/ast-engine-deomp/spec.md +170 -0
  409. package/node_modules/better-dsh/docs/specs/authentication-only-web-admission/spec.md +51 -0
  410. package/node_modules/better-dsh/docs/specs/compaction-recall/spec.md +46 -0
  411. package/node_modules/better-dsh/docs/specs/ctx/spec.md +179 -0
  412. package/node_modules/better-dsh/docs/specs/docs-packaging-trim/spec.md +110 -0
  413. package/node_modules/better-dsh/docs/specs/dsh/spec.md +47 -0
  414. package/node_modules/better-dsh/docs/specs/dvc/spec.md +106 -0
  415. package/node_modules/better-dsh/docs/specs/escalation-guidance/spec.md +44 -0
  416. package/node_modules/better-dsh/docs/specs/fs-scheme-resolution/spec.md +37 -0
  417. package/node_modules/better-dsh/docs/specs/hash-edit/spec.md +41 -0
  418. package/node_modules/better-dsh/docs/specs/http-read/spec.md +73 -0
  419. package/node_modules/better-dsh/docs/specs/kernel-provisioning/spec.md +53 -0
  420. package/node_modules/better-dsh/docs/specs/lsp/spec.md +121 -0
  421. package/node_modules/better-dsh/docs/specs/mobile-layout/spec.md +108 -0
  422. package/node_modules/better-dsh/docs/specs/model-failover/spec.md +20 -0
  423. package/node_modules/better-dsh/docs/specs/model-picker-ios-blur/spec.md +168 -0
  424. package/node_modules/better-dsh/docs/specs/plugins-page-components/spec.md +79 -0
  425. package/node_modules/better-dsh/docs/specs/preact-ui-shell/spec.md +22 -0
  426. package/node_modules/better-dsh/docs/specs/remote-pty-label/spec.md +126 -0
  427. package/node_modules/better-dsh/docs/specs/repl-dispatch-resilience/spec.md +21 -0
  428. package/node_modules/better-dsh/docs/specs/skill/spec.md +58 -0
  429. package/node_modules/better-dsh/docs/specs/tool-surface/spec.md +222 -0
  430. package/node_modules/better-dsh/docs/specs/url-schema/spec.md +148 -0
  431. package/node_modules/better-dsh/docs/specs/web-trust-fence/spec.md +43 -0
  432. package/node_modules/better-dsh/docs/specs/welcome-self-contained/spec.md +13 -0
  433. package/node_modules/better-dsh/docs/specs/zero-npm-runtime-deps/spec.md +85 -0
  434. package/node_modules/better-dsh/docs/superpowers/plans/2026-10-02-ctx-navigation.md +319 -0
  435. package/node_modules/better-dsh/docs/superpowers/plans/2026-10-03-ast-engine-deomp.md +1214 -0
  436. package/node_modules/better-dsh/docs/superpowers/plans/2026-10-03-docs-packaging-trim.md +181 -0
  437. package/node_modules/better-dsh/docs/superpowers/specs/2026-10-02-ctx-navigation-design.md +209 -0
  438. package/node_modules/better-dsh/docs/upstream-dsh-0.1.5-rc.2-report.md +156 -0
  439. package/node_modules/better-dsh/dsh-docs/AGENTS.md +75 -0
  440. package/node_modules/better-dsh/dsh-docs/agent-lifecycle.md +84 -0
  441. package/node_modules/better-dsh/dsh-docs/agent-lifecycle.zh.md +86 -0
  442. package/node_modules/better-dsh/dsh-docs/api-gateway.md +164 -0
  443. package/node_modules/better-dsh/dsh-docs/api-gateway.zh.md +164 -0
  444. package/node_modules/better-dsh/dsh-docs/architecture.md +150 -0
  445. package/node_modules/better-dsh/dsh-docs/architecture.zh.md +154 -0
  446. package/node_modules/better-dsh/dsh-docs/capability-seams.md +543 -0
  447. package/node_modules/better-dsh/dsh-docs/capability-seams.zh.md +545 -0
  448. package/node_modules/better-dsh/dsh-docs/config-catalog.md +3473 -0
  449. package/node_modules/better-dsh/dsh-docs/config-catalog.zh.md +3474 -0
  450. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-package.md +117 -0
  451. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-package.zh.md +119 -0
  452. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-remote-api.md +197 -0
  453. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-remote-api.zh.md +197 -0
  454. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-session-format-version.md +109 -0
  455. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-session-format-version.zh.md +109 -0
  456. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-settings-card.md +102 -0
  457. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-settings-card.zh.md +102 -0
  458. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-tool.md +101 -0
  459. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-tool.zh.md +103 -0
  460. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-vendored-package.md +59 -0
  461. package/node_modules/better-dsh/dsh-docs/cookbook/adding-a-vendored-package.zh.md +59 -0
  462. package/node_modules/better-dsh/dsh-docs/cookbook/adding-an-llm-adapter.md +43 -0
  463. package/node_modules/better-dsh/dsh-docs/cookbook/adding-an-llm-adapter.zh.md +43 -0
  464. package/node_modules/better-dsh/dsh-docs/cookbook/extension-cookbook.md +132 -0
  465. package/node_modules/better-dsh/dsh-docs/cookbook/extension-cookbook.zh.md +136 -0
  466. package/node_modules/better-dsh/dsh-docs/cookbook/maintaining-dsh-code-review.md +64 -0
  467. package/node_modules/better-dsh/dsh-docs/cookbook/maintaining-dsh-code-review.zh.md +64 -0
  468. package/node_modules/better-dsh/dsh-docs/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
  469. package/node_modules/better-dsh/dsh-docs/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
  470. package/node_modules/better-dsh/dsh-docs/cordis-api/context.md +364 -0
  471. package/node_modules/better-dsh/dsh-docs/cordis-api/context.zh.md +366 -0
  472. package/node_modules/better-dsh/dsh-docs/cordis-api/events.md +207 -0
  473. package/node_modules/better-dsh/dsh-docs/cordis-api/events.zh.md +209 -0
  474. package/node_modules/better-dsh/dsh-docs/cordis-api/fiber.md +375 -0
  475. package/node_modules/better-dsh/dsh-docs/cordis-api/fiber.zh.md +377 -0
  476. package/node_modules/better-dsh/dsh-docs/cordis-api/inherited.md +39 -0
  477. package/node_modules/better-dsh/dsh-docs/cordis-api/registry.md +152 -0
  478. package/node_modules/better-dsh/dsh-docs/cordis-api/registry.zh.md +154 -0
  479. package/node_modules/better-dsh/dsh-docs/cordis-api/service.md +102 -0
  480. package/node_modules/better-dsh/dsh-docs/cordis-api/service.zh.md +104 -0
  481. package/node_modules/better-dsh/dsh-docs/cordis-primer.md +45 -0
  482. package/node_modules/better-dsh/dsh-docs/cordis-primer.zh.md +51 -0
  483. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/01-first-plugin.md +95 -0
  484. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/01-first-plugin.zh.md +95 -0
  485. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  486. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/02-lifecycle-and-effects.zh.md +98 -0
  487. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/03-services.md +98 -0
  488. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/03-services.zh.md +98 -0
  489. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/04-events.md +144 -0
  490. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/04-events.zh.md +144 -0
  491. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/05-config.md +84 -0
  492. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/05-config.zh.md +84 -0
  493. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/06-composition-and-hmr.md +113 -0
  494. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/06-composition-and-hmr.zh.md +113 -0
  495. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/07-into-the-harness.md +108 -0
  496. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/07-into-the-harness.zh.md +108 -0
  497. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/index.md +60 -0
  498. package/node_modules/better-dsh/dsh-docs/cordis-tutorial/index.zh.md +62 -0
  499. package/node_modules/better-dsh/dsh-docs/deepseek-llm-api-wire-extensions.md +163 -0
  500. package/node_modules/better-dsh/dsh-docs/deepseek-llm-api-wire-extensions.zh.md +163 -0
  501. package/node_modules/better-dsh/dsh-docs/defensive-patterns.md +33 -0
  502. package/node_modules/better-dsh/dsh-docs/defensive-patterns.zh.md +35 -0
  503. package/node_modules/better-dsh/dsh-docs/development.md +167 -0
  504. package/node_modules/better-dsh/dsh-docs/development.zh.md +173 -0
  505. package/node_modules/better-dsh/dsh-docs/event-producer-consumer.md +86 -0
  506. package/node_modules/better-dsh/dsh-docs/event-producer-consumer.zh.md +88 -0
  507. package/node_modules/better-dsh/dsh-docs/glossary.md +45 -0
  508. package/node_modules/better-dsh/dsh-docs/glossary.zh.md +45 -0
  509. package/node_modules/better-dsh/dsh-docs/graph-atlas.md +22 -0
  510. package/node_modules/better-dsh/dsh-docs/graph-atlas.zh.md +24 -0
  511. package/node_modules/better-dsh/dsh-docs/i18n/README.md +60 -0
  512. package/node_modules/better-dsh/dsh-docs/i18n/README.zh.md +62 -0
  513. package/node_modules/better-dsh/dsh-docs/i18n/style-samples.md +87 -0
  514. package/node_modules/better-dsh/dsh-docs/i18n/terminology.md +214 -0
  515. package/node_modules/better-dsh/dsh-docs/i18n/translation-prompt.md +263 -0
  516. package/node_modules/better-dsh/dsh-docs/i18n/translation-rules.md +69 -0
  517. package/node_modules/better-dsh/dsh-docs/i18n/translation-rules.zh.md +69 -0
  518. package/node_modules/better-dsh/dsh-docs/module-graph.md +1411 -0
  519. package/node_modules/better-dsh/dsh-docs/module-graph.zh.md +1413 -0
  520. package/node_modules/better-dsh/dsh-docs/persistence-catalog.md +1075 -0
  521. package/node_modules/better-dsh/dsh-docs/persistence-catalog.zh.md +1077 -0
  522. package/node_modules/better-dsh/dsh-docs/postmortem/0001-acp-default-export-drops-inject.md +113 -0
  523. package/node_modules/better-dsh/dsh-docs/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
  524. package/node_modules/better-dsh/dsh-docs/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
  525. package/node_modules/better-dsh/dsh-docs/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
  526. package/node_modules/better-dsh/dsh-docs/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
  527. package/node_modules/better-dsh/dsh-docs/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
  528. package/node_modules/better-dsh/dsh-docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
  529. package/node_modules/better-dsh/dsh-docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
  530. package/node_modules/better-dsh/dsh-docs/postmortem/README.md +18 -0
  531. package/node_modules/better-dsh/dsh-docs/postmortem/README.zh.md +18 -0
  532. package/node_modules/better-dsh/dsh-docs/rescope.md +53 -0
  533. package/node_modules/better-dsh/dsh-docs/rescope.zh.md +53 -0
  534. package/node_modules/better-dsh/dsh-docs/session-format-status.md +47 -0
  535. package/node_modules/better-dsh/dsh-docs/session-format-status.zh.md +47 -0
  536. package/node_modules/better-dsh/dsh-docs/subsystems/README.md +61 -0
  537. package/node_modules/better-dsh/dsh-docs/subsystems/README.zh.md +61 -0
  538. package/node_modules/better-dsh/dsh-docs/subsystems/agent-team.md +207 -0
  539. package/node_modules/better-dsh/dsh-docs/subsystems/agent-team.zh.md +207 -0
  540. package/node_modules/better-dsh/dsh-docs/subsystems/approval.md +170 -0
  541. package/node_modules/better-dsh/dsh-docs/subsystems/approval.zh.md +170 -0
  542. package/node_modules/better-dsh/dsh-docs/subsystems/attachment.md +351 -0
  543. package/node_modules/better-dsh/dsh-docs/subsystems/attachment.zh.md +351 -0
  544. package/node_modules/better-dsh/dsh-docs/subsystems/client-modules.md +168 -0
  545. package/node_modules/better-dsh/dsh-docs/subsystems/client-modules.zh.md +168 -0
  546. package/node_modules/better-dsh/dsh-docs/subsystems/client-resources.md +91 -0
  547. package/node_modules/better-dsh/dsh-docs/subsystems/client-resources.zh.md +91 -0
  548. package/node_modules/better-dsh/dsh-docs/subsystems/code-runtime.md +195 -0
  549. package/node_modules/better-dsh/dsh-docs/subsystems/code-runtime.zh.md +195 -0
  550. package/node_modules/better-dsh/dsh-docs/subsystems/commands.md +219 -0
  551. package/node_modules/better-dsh/dsh-docs/subsystems/commands.zh.md +219 -0
  552. package/node_modules/better-dsh/dsh-docs/subsystems/compaction.md +238 -0
  553. package/node_modules/better-dsh/dsh-docs/subsystems/compaction.zh.md +238 -0
  554. package/node_modules/better-dsh/dsh-docs/subsystems/conversation.md +258 -0
  555. package/node_modules/better-dsh/dsh-docs/subsystems/conversation.zh.md +258 -0
  556. package/node_modules/better-dsh/dsh-docs/subsystems/core.md +1209 -0
  557. package/node_modules/better-dsh/dsh-docs/subsystems/core.zh.md +1219 -0
  558. package/node_modules/better-dsh/dsh-docs/subsystems/credentials.md +329 -0
  559. package/node_modules/better-dsh/dsh-docs/subsystems/credentials.zh.md +329 -0
  560. package/node_modules/better-dsh/dsh-docs/subsystems/extensions.md +382 -0
  561. package/node_modules/better-dsh/dsh-docs/subsystems/extensions.zh.md +382 -0
  562. package/node_modules/better-dsh/dsh-docs/subsystems/feedback.md +266 -0
  563. package/node_modules/better-dsh/dsh-docs/subsystems/feedback.zh.md +266 -0
  564. package/node_modules/better-dsh/dsh-docs/subsystems/filesystem.md +505 -0
  565. package/node_modules/better-dsh/dsh-docs/subsystems/filesystem.zh.md +505 -0
  566. package/node_modules/better-dsh/dsh-docs/subsystems/goal.md +277 -0
  567. package/node_modules/better-dsh/dsh-docs/subsystems/goal.zh.md +277 -0
  568. package/node_modules/better-dsh/dsh-docs/subsystems/invariants.md +88 -0
  569. package/node_modules/better-dsh/dsh-docs/subsystems/invariants.zh.md +88 -0
  570. package/node_modules/better-dsh/dsh-docs/subsystems/jobs.md +290 -0
  571. package/node_modules/better-dsh/dsh-docs/subsystems/jobs.zh.md +290 -0
  572. package/node_modules/better-dsh/dsh-docs/subsystems/llm-streaming.md +1080 -0
  573. package/node_modules/better-dsh/dsh-docs/subsystems/llm-streaming.zh.md +1086 -0
  574. package/node_modules/better-dsh/dsh-docs/subsystems/lsp.md +202 -0
  575. package/node_modules/better-dsh/dsh-docs/subsystems/lsp.zh.md +202 -0
  576. package/node_modules/better-dsh/dsh-docs/subsystems/permission-presets.md +131 -0
  577. package/node_modules/better-dsh/dsh-docs/subsystems/permission-presets.zh.md +131 -0
  578. package/node_modules/better-dsh/dsh-docs/subsystems/persistence.md +395 -0
  579. package/node_modules/better-dsh/dsh-docs/subsystems/persistence.zh.md +395 -0
  580. package/node_modules/better-dsh/dsh-docs/subsystems/plan.md +87 -0
  581. package/node_modules/better-dsh/dsh-docs/subsystems/plan.zh.md +87 -0
  582. package/node_modules/better-dsh/dsh-docs/subsystems/sandbox.md +220 -0
  583. package/node_modules/better-dsh/dsh-docs/subsystems/sandbox.zh.md +220 -0
  584. package/node_modules/better-dsh/dsh-docs/subsystems/schedule.md +192 -0
  585. package/node_modules/better-dsh/dsh-docs/subsystems/schedule.zh.md +192 -0
  586. package/node_modules/better-dsh/dsh-docs/subsystems/scope.md +59 -0
  587. package/node_modules/better-dsh/dsh-docs/subsystems/scope.zh.md +59 -0
  588. package/node_modules/better-dsh/dsh-docs/subsystems/session-projection.md +354 -0
  589. package/node_modules/better-dsh/dsh-docs/subsystems/session-projection.zh.md +354 -0
  590. package/node_modules/better-dsh/dsh-docs/subsystems/session-query.md +509 -0
  591. package/node_modules/better-dsh/dsh-docs/subsystems/session-query.zh.md +509 -0
  592. package/node_modules/better-dsh/dsh-docs/subsystems/session-reference.md +219 -0
  593. package/node_modules/better-dsh/dsh-docs/subsystems/session-reference.zh.md +219 -0
  594. package/node_modules/better-dsh/dsh-docs/subsystems/session-telemetry.md +194 -0
  595. package/node_modules/better-dsh/dsh-docs/subsystems/session-telemetry.zh.md +194 -0
  596. package/node_modules/better-dsh/dsh-docs/subsystems/session-title.md +204 -0
  597. package/node_modules/better-dsh/dsh-docs/subsystems/session-title.zh.md +204 -0
  598. package/node_modules/better-dsh/dsh-docs/subsystems/session.md +1155 -0
  599. package/node_modules/better-dsh/dsh-docs/subsystems/session.zh.md +1159 -0
  600. package/node_modules/better-dsh/dsh-docs/subsystems/settings.md +405 -0
  601. package/node_modules/better-dsh/dsh-docs/subsystems/settings.zh.md +405 -0
  602. package/node_modules/better-dsh/dsh-docs/subsystems/shell.md +303 -0
  603. package/node_modules/better-dsh/dsh-docs/subsystems/shell.zh.md +303 -0
  604. package/node_modules/better-dsh/dsh-docs/subsystems/sidebar-right.md +148 -0
  605. package/node_modules/better-dsh/dsh-docs/subsystems/sidebar-right.zh.md +148 -0
  606. package/node_modules/better-dsh/dsh-docs/subsystems/skills.md +354 -0
  607. package/node_modules/better-dsh/dsh-docs/subsystems/skills.zh.md +354 -0
  608. package/node_modules/better-dsh/dsh-docs/subsystems/slots.md +175 -0
  609. package/node_modules/better-dsh/dsh-docs/subsystems/slots.zh.md +175 -0
  610. package/node_modules/better-dsh/dsh-docs/subsystems/spill.md +117 -0
  611. package/node_modules/better-dsh/dsh-docs/subsystems/spill.zh.md +117 -0
  612. package/node_modules/better-dsh/dsh-docs/subsystems/storage.md +260 -0
  613. package/node_modules/better-dsh/dsh-docs/subsystems/storage.zh.md +260 -0
  614. package/node_modules/better-dsh/dsh-docs/subsystems/subagent.md +766 -0
  615. package/node_modules/better-dsh/dsh-docs/subsystems/subagent.zh.md +770 -0
  616. package/node_modules/better-dsh/dsh-docs/subsystems/subprocess.md +324 -0
  617. package/node_modules/better-dsh/dsh-docs/subsystems/subprocess.zh.md +324 -0
  618. package/node_modules/better-dsh/dsh-docs/subsystems/system-prompt.md +220 -0
  619. package/node_modules/better-dsh/dsh-docs/subsystems/system-prompt.zh.md +220 -0
  620. package/node_modules/better-dsh/dsh-docs/subsystems/terminal.md +184 -0
  621. package/node_modules/better-dsh/dsh-docs/subsystems/terminal.zh.md +184 -0
  622. package/node_modules/better-dsh/dsh-docs/subsystems/todo.md +32 -0
  623. package/node_modules/better-dsh/dsh-docs/subsystems/todo.zh.md +32 -0
  624. package/node_modules/better-dsh/dsh-docs/subsystems/token-meter.md +105 -0
  625. package/node_modules/better-dsh/dsh-docs/subsystems/token-meter.zh.md +105 -0
  626. package/node_modules/better-dsh/dsh-docs/subsystems/tools.md +720 -0
  627. package/node_modules/better-dsh/dsh-docs/subsystems/tools.zh.md +720 -0
  628. package/node_modules/better-dsh/dsh-docs/subsystems/typert.md +343 -0
  629. package/node_modules/better-dsh/dsh-docs/subsystems/typert.zh.md +343 -0
  630. package/node_modules/better-dsh/dsh-docs/subsystems/user-questions.md +178 -0
  631. package/node_modules/better-dsh/dsh-docs/subsystems/user-questions.zh.md +178 -0
  632. package/node_modules/better-dsh/dsh-docs/subsystems/web-client.md +95 -0
  633. package/node_modules/better-dsh/dsh-docs/subsystems/web-client.zh.md +95 -0
  634. package/node_modules/better-dsh/dsh-docs/subsystems/web-server.md +154 -0
  635. package/node_modules/better-dsh/dsh-docs/subsystems/web-server.zh.md +154 -0
  636. package/node_modules/better-dsh/dsh-docs/subsystems/web.md +206 -0
  637. package/node_modules/better-dsh/dsh-docs/subsystems/web.zh.md +206 -0
  638. package/node_modules/better-dsh/dsh-docs/subsystems/webhook.md +70 -0
  639. package/node_modules/better-dsh/dsh-docs/subsystems/webhook.zh.md +70 -0
  640. package/node_modules/better-dsh/dsh-docs/subsystems/workflow.md +278 -0
  641. package/node_modules/better-dsh/dsh-docs/subsystems/workflow.zh.md +278 -0
  642. package/node_modules/better-dsh/dsh-docs/subsystems/workspace.md +321 -0
  643. package/node_modules/better-dsh/dsh-docs/subsystems/workspace.zh.md +321 -0
  644. package/node_modules/better-dsh/dsh-docs/testing.md +54 -0
  645. package/node_modules/better-dsh/dsh-docs/testing.zh.md +54 -0
  646. package/node_modules/better-dsh/dsh-docs/tool-catalog.md +2225 -0
  647. package/node_modules/better-dsh/dsh-docs/tool-catalog.zh.md +2233 -0
  648. package/node_modules/better-dsh/dsh-docs/tool-execution-pipeline.md +62 -0
  649. package/node_modules/better-dsh/dsh-docs/tool-execution-pipeline.zh.md +64 -0
  650. package/node_modules/better-dsh/dsh-docs/user/develop/basic/config.md +106 -0
  651. package/node_modules/better-dsh/dsh-docs/user/develop/basic/config.zh.md +106 -0
  652. package/node_modules/better-dsh/dsh-docs/user/develop/basic/index.md +144 -0
  653. package/node_modules/better-dsh/dsh-docs/user/develop/basic/index.zh.md +144 -0
  654. package/node_modules/better-dsh/dsh-docs/user/develop/basic/publish.md +183 -0
  655. package/node_modules/better-dsh/dsh-docs/user/develop/basic/publish.zh.md +183 -0
  656. package/node_modules/better-dsh/dsh-docs/user/develop/basic/tool.md +52 -0
  657. package/node_modules/better-dsh/dsh-docs/user/develop/basic/tool.zh.md +52 -0
  658. package/node_modules/better-dsh/dsh-docs/user/develop/framework/events.md +143 -0
  659. package/node_modules/better-dsh/dsh-docs/user/develop/framework/events.zh.md +143 -0
  660. package/node_modules/better-dsh/dsh-docs/user/develop/framework/index.md +137 -0
  661. package/node_modules/better-dsh/dsh-docs/user/develop/framework/index.zh.md +137 -0
  662. package/node_modules/better-dsh/dsh-docs/user/develop/framework/service.md +148 -0
  663. package/node_modules/better-dsh/dsh-docs/user/develop/framework/service.zh.md +150 -0
  664. package/node_modules/better-dsh/dsh-docs/user/develop/practice/dynamic-cordis.md +15 -0
  665. package/node_modules/better-dsh/dsh-docs/user/develop/practice/dynamic-cordis.zh.md +15 -0
  666. package/node_modules/better-dsh/dsh-docs/user/develop/practice/index.md +155 -0
  667. package/node_modules/better-dsh/dsh-docs/user/develop/practice/index.zh.md +155 -0
  668. package/node_modules/better-dsh/dsh-docs/user/develop/practice/llm-adapter.md +189 -0
  669. package/node_modules/better-dsh/dsh-docs/user/develop/practice/llm-adapter.zh.md +189 -0
  670. package/node_modules/better-dsh/dsh-docs/user/guide/github-review.md +102 -0
  671. package/node_modules/better-dsh/dsh-docs/user/guide/github-review.zh.md +102 -0
  672. package/node_modules/better-dsh/dsh-docs/user/guide/index.md +30 -0
  673. package/node_modules/better-dsh/dsh-docs/user/guide/index.zh.md +30 -0
  674. package/node_modules/better-dsh/dsh-docs/user/guide/mcp-memory.md +101 -0
  675. package/node_modules/better-dsh/dsh-docs/user/guide/mcp-memory.zh.md +101 -0
  676. package/node_modules/better-dsh/dsh-docs/user/guide/network-proxy.md +85 -0
  677. package/node_modules/better-dsh/dsh-docs/user/guide/network-proxy.zh.md +85 -0
  678. package/node_modules/better-dsh/dsh-docs/user/guide/providers.md +190 -0
  679. package/node_modules/better-dsh/dsh-docs/user/guide/providers.zh.md +190 -0
  680. package/node_modules/better-dsh/dsh-docs/user/guide/python-sdk.md +150 -0
  681. package/node_modules/better-dsh/dsh-docs/user/guide/python-sdk.zh.md +150 -0
  682. package/node_modules/better-dsh/dsh-docs/user/guide/schedule.md +21 -0
  683. package/node_modules/better-dsh/dsh-docs/user/guide/schedule.zh.md +21 -0
  684. package/node_modules/better-dsh/dsh-docs/user/index.md +11 -0
  685. package/node_modules/better-dsh/dsh-docs/user/index.zh.md +11 -0
  686. package/node_modules/better-dsh/dsh-docs/web-styling.md +29 -0
  687. package/node_modules/better-dsh/dsh-docs/web-styling.zh.md +29 -0
  688. package/node_modules/better-dsh/eval-description.md +33 -0
  689. package/node_modules/better-dsh/lib/BrowserWebSocketTransport-D1aFReu_.js +4 -0
  690. package/node_modules/better-dsh/lib/BrowserWebSocketTransport-wm99h94r.js +39 -0
  691. package/node_modules/better-dsh/lib/LaunchOptions-B874eBu2.js +4 -0
  692. package/node_modules/better-dsh/lib/LaunchOptions-kGXcZOe0.js +17 -0
  693. package/node_modules/better-dsh/lib/NodeWebSocketTransport-BRLjmu2R.js +4 -0
  694. package/node_modules/better-dsh/lib/NodeWebSocketTransport-D9ysYGLM.js +3634 -0
  695. package/node_modules/better-dsh/lib/ast-assets/ast-grep.wasm +0 -0
  696. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-bash.wasm +0 -0
  697. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-c.wasm +0 -0
  698. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-cpp.wasm +0 -0
  699. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-css.wasm +0 -0
  700. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-go.wasm +0 -0
  701. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-html.wasm +0 -0
  702. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-javascript.wasm +0 -0
  703. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-json.wasm +0 -0
  704. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-python.wasm +0 -0
  705. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-ruby.wasm +0 -0
  706. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-rust.wasm +0 -0
  707. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-tsx.wasm +0 -0
  708. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-typescript.wasm +0 -0
  709. package/node_modules/better-dsh/lib/ast-assets/tree-sitter-yaml.wasm +0 -0
  710. package/node_modules/better-dsh/lib/ast-assets/tree-sitter.wasm +0 -0
  711. package/node_modules/better-dsh/lib/bidi-BalpKaJc.js +16106 -0
  712. package/node_modules/better-dsh/lib/bundle-delivery.d.ts +20 -0
  713. package/node_modules/better-dsh/lib/bundle-delivery.js +209 -0
  714. package/node_modules/better-dsh/lib/chunk-DQxbwPpZ.js +30 -0
  715. package/node_modules/better-dsh/lib/client/index.js +712 -0
  716. package/node_modules/better-dsh/lib/compaction/index.d.ts +57 -0
  717. package/node_modules/better-dsh/lib/compaction/index.js +145 -0
  718. package/node_modules/better-dsh/lib/failover/index.d.ts +59 -0
  719. package/node_modules/better-dsh/lib/failover/index.js +147 -0
  720. package/node_modules/better-dsh/lib/fs-aware/sandbox-plugin.d.ts +71 -0
  721. package/node_modules/better-dsh/lib/fs-aware/sandbox-plugin.js +249 -0
  722. package/node_modules/better-dsh/lib/hmr.d.ts +32 -0
  723. package/node_modules/better-dsh/lib/hmr.js +49 -0
  724. package/node_modules/better-dsh/lib/index-DTDXUe6m.d.ts +208 -0
  725. package/node_modules/better-dsh/lib/index-browser-CysrjMyM.js +21061 -0
  726. package/node_modules/better-dsh/lib/index.d.ts +705 -0
  727. package/node_modules/better-dsh/lib/index.js +3816 -0
  728. package/node_modules/better-dsh/lib/kernel-bridge.py +172 -0
  729. package/node_modules/better-dsh/lib/kernel-env-D8UOWeji.js +195 -0
  730. package/node_modules/better-dsh/lib/kernel-env.d.ts +80 -0
  731. package/node_modules/better-dsh/lib/kernel-env.js +3 -0
  732. package/node_modules/better-dsh/lib/lib-C8_jXvwA.js +894 -0
  733. package/node_modules/better-dsh/lib/lsp-server-registry-BXvUTBY7.js +3 -0
  734. package/node_modules/better-dsh/lib/lsp-server-registry-CH9WNFFt.js +972 -0
  735. package/node_modules/better-dsh/lib/main-BQeFrBM1.js +3 -0
  736. package/node_modules/better-dsh/lib/main-CupOhMp5.js +1432 -0
  737. package/node_modules/better-dsh/lib/mobile/plugin.d.ts +29 -0
  738. package/node_modules/better-dsh/lib/mobile/plugin.js +54 -0
  739. package/node_modules/better-dsh/lib/native-capture-BEByDXYM.js +68 -0
  740. package/node_modules/better-dsh/lib/puppeteer-core-CSk2PtSm.js +1136 -0
  741. package/node_modules/better-dsh/lib/py-sdk-D7klhpWb.js +178 -0
  742. package/node_modules/better-dsh/lib/py-sdk.d.ts +19 -0
  743. package/node_modules/better-dsh/lib/py-sdk.js +3 -0
  744. package/node_modules/better-dsh/lib/remote/plugin.d.ts +24 -0
  745. package/node_modules/better-dsh/lib/remote/plugin.js +1190 -0
  746. package/node_modules/better-dsh/lib/url-schemes/index.d.ts +88 -0
  747. package/node_modules/better-dsh/lib/url-schemes/index.js +12229 -0
  748. package/node_modules/better-dsh/lib/util-BHL_dfV_.js +2953 -0
  749. package/node_modules/better-dsh/lib/wasm_bg-CNXhHjVg.js +1291 -0
  750. package/node_modules/better-dsh/lib/web-password.d.ts +156 -0
  751. package/node_modules/better-dsh/lib/web-password.js +562 -0
  752. package/node_modules/better-dsh/lib/web-tree-sitter-CPrPD4J2.js +3440 -0
  753. package/node_modules/better-dsh/lib/web-trust-D6gJpUMf.js +393 -0
  754. package/node_modules/better-dsh/lib/web-trust-Dej_RI2B.d.ts +113 -0
  755. package/node_modules/better-dsh/lib/web-trust.d.ts +3 -0
  756. package/node_modules/better-dsh/lib/web-trust.js +4 -0
  757. package/node_modules/better-dsh/lib/webserver.d.ts +10 -0
  758. package/node_modules/better-dsh/lib/webserver.js +19 -0
  759. package/node_modules/better-dsh/lib/welcome-notice.d.ts +18 -0
  760. package/node_modules/better-dsh/lib/welcome-notice.js +59 -0
  761. package/node_modules/better-dsh/lib/wrap-T4I0nfPM.js +750 -0
  762. package/node_modules/better-dsh/package.json +430 -0
  763. package/node_modules/better-dsh/scripts/kernel-provision.mjs +35 -0
  764. package/node_modules/better-dsh/scripts/register-bundle.mjs +80 -0
  765. package/node_modules/better-dsh/url-schemes-instruction.md +22 -0
  766. package/package.json +21 -6
  767. package/superd-hub/assets/icons/README.md +20 -0
  768. package/superd-hub/assets/icons/amp.png +0 -0
  769. package/superd-hub/assets/icons/ante.png +0 -0
  770. package/superd-hub/assets/icons/antigravity.png +0 -0
  771. package/superd-hub/assets/icons/aug.png +0 -0
  772. package/superd-hub/assets/icons/autohand.png +0 -0
  773. package/superd-hub/assets/icons/claude.svg +1 -0
  774. package/superd-hub/assets/icons/cline.png +0 -0
  775. package/superd-hub/assets/icons/codebuddy.png +0 -0
  776. package/superd-hub/assets/icons/codebuff.png +0 -0
  777. package/superd-hub/assets/icons/codex.svg +1 -0
  778. package/superd-hub/assets/icons/command-code.png +0 -0
  779. package/superd-hub/assets/icons/continue.png +0 -0
  780. package/superd-hub/assets/icons/copilot.png +0 -0
  781. package/superd-hub/assets/icons/crush.png +0 -0
  782. package/superd-hub/assets/icons/cursor.png +0 -0
  783. package/superd-hub/assets/icons/devin.png +0 -0
  784. package/superd-hub/assets/icons/droid.png +0 -0
  785. package/superd-hub/assets/icons/dsh-fish.svg +3 -0
  786. package/superd-hub/assets/icons/dsh.png +0 -0
  787. package/superd-hub/assets/icons/freebuff.png +0 -0
  788. package/superd-hub/assets/icons/gemini.png +0 -0
  789. package/superd-hub/assets/icons/goose.png +0 -0
  790. package/superd-hub/assets/icons/grok.png +0 -0
  791. package/superd-hub/assets/icons/hermes.png +0 -0
  792. package/superd-hub/assets/icons/jcode.png +0 -0
  793. package/superd-hub/assets/icons/kilo.png +0 -0
  794. package/superd-hub/assets/icons/kimi.png +0 -0
  795. package/superd-hub/assets/icons/kiro.png +0 -0
  796. package/superd-hub/assets/icons/manifest.json +20 -0
  797. package/superd-hub/assets/icons/mimo-code.png +0 -0
  798. package/superd-hub/assets/icons/mistral-vibe.png +0 -0
  799. package/superd-hub/assets/icons/muse.png +0 -0
  800. package/superd-hub/assets/icons/omp.svg +1 -0
  801. package/superd-hub/assets/icons/openclaude.png +0 -0
  802. package/superd-hub/assets/icons/openclaw.png +0 -0
  803. package/superd-hub/assets/icons/opencode.png +0 -0
  804. package/superd-hub/assets/icons/pi.svg +1 -0
  805. package/superd-hub/assets/icons/prime-agent.png +0 -0
  806. package/superd-hub/assets/icons/qoder-cn.png +0 -0
  807. package/superd-hub/assets/icons/qoder.png +0 -0
  808. package/superd-hub/assets/icons/qwen-code.png +0 -0
  809. package/superd-hub/assets/icons/rovo.png +0 -0
  810. package/superd-hub/assets/icons/trae.png +0 -0
  811. package/superd-hub/assets/icons/zcode.png +0 -0
  812. package/superd-hub/dist/a2a-row.js +1 -1
  813. package/superd-hub/dist/agent-roster.d.ts +8 -3
  814. package/superd-hub/dist/agent-roster.js +19 -7
  815. package/superd-hub/dist/bundle-setup.d.ts +2 -0
  816. package/superd-hub/dist/bundle-setup.js +2 -0
  817. package/superd-hub/dist/client/icon-assets.gen.d.ts +16 -0
  818. package/superd-hub/dist/client/icon-assets.gen.js +54 -0
  819. package/superd-hub/dist/client/mesh-api.d.ts +28 -17
  820. package/superd-hub/dist/client/mesh-api.js +44 -31
  821. package/superd-hub/dist/client/mesh-groups.d.ts +13 -11
  822. package/superd-hub/dist/client/mesh-groups.js +30 -10
  823. package/superd-hub/dist/client/roster.d.ts +7 -16
  824. package/superd-hub/dist/client/roster.js +5 -3
  825. package/superd-hub/dist/fusion-transport.d.ts +11 -10
  826. package/superd-hub/dist/fusion-transport.js +21 -11
  827. package/superd-hub/dist/index.d.ts +0 -1
  828. package/superd-hub/dist/index.js +0 -1
  829. package/superd-hub/dist/machines.d.ts +6 -3
  830. package/superd-hub/dist/machines.js +15 -3
  831. package/superd-hub/dist/mesh-federate.d.ts +18 -8
  832. package/superd-hub/dist/mesh-federate.js +14 -9
  833. package/superd-hub/dist/mesh-link.d.ts +37 -3
  834. package/superd-hub/dist/mesh-link.js +49 -4
  835. package/superd-hub/dist/mesh-rpc.d.ts +48 -16
  836. package/superd-hub/dist/mesh-rpc.js +139 -14
  837. package/superd-hub/dist/roster.d.ts +20 -0
  838. package/superd-hub/dist/roster.js +24 -0
  839. package/superd-hub/dist/switch-core.d.ts +3 -2
  840. package/superd-hub/dist/switch-core.js +1 -1
  841. package/superd-hub/dist/world-entry.d.ts +3 -0
  842. package/superd-hub/dist/world-entry.js +4 -1
  843. package/superd-hub/dist/world-host.d.ts +5 -2
  844. package/superd-hub/dist/world-host.js +6 -2
  845. package/superd-hub/dist/world-join.d.ts +1 -1
  846. package/superd-hub/dist/world-join.js +14 -32
  847. package/superd-hub/dist/world-lifecycle.d.ts +20 -0
  848. package/superd-hub/dist/world-lifecycle.js +69 -0
  849. package/superd-hub/dist/world-mount.d.ts +1 -1
  850. package/superd-hub/dist/world-mount.js +2 -2
  851. package/superd-hub/lib/client/index.js +434 -307
  852. package/superd-hub/package.json +3 -2
  853. package/superd-hub/dist/connection-trust.d.ts +0 -8
  854. package/superd-hub/dist/connection-trust.js +0 -16
  855. package/superd-hub/dist/web-trust.d.ts +0 -84
  856. package/superd-hub/dist/web-trust.js +0 -101
@@ -0,0 +1,3816 @@
1
+ import { t as Schema } from "./lib-C8_jXvwA.js";
2
+ import { a as RESERVED_ERROR_MEMBERS, i as RESERVED_BINDING_GLOBALS, n as DUNDER_MEMBER, o as ReplRuntime, r as PORTABLE_RESERVED_WORDS, t as isFlatBindableName } from "./py-sdk-D7klhpWb.js";
3
+ import { s as resolveKernelEnv } from "./kernel-env-D8UOWeji.js";
4
+ import { t as captureAllTools } from "./native-capture-BEByDXYM.js";
5
+ import { createRequire } from "node:module";
6
+ import { randomBytes, randomUUID } from "node:crypto";
7
+ import { spawn } from "node:child_process";
8
+ import { join } from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import { Context } from "@deepseek-ai/cordis";
11
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
12
+ import { tmpdir } from "node:os";
13
+ import { setTimeout as setTimeout$1 } from "node:timers/promises";
14
+ import { createInterface } from "node:readline";
15
+ import { TOOL_RUNTIME_SCHEDULER, defineTool } from "@deepseek-ai/dsh-tools";
16
+ import * as dshLlm from "@deepseek-ai/dsh-llm";
17
+ import { BlockAssembler, HarnessError, createUserMessage } from "@deepseek-ai/dsh-llm";
18
+ import { scopeTarget } from "@deepseek-ai/dsh-scope";
19
+
20
+ //#region src/snapshot-json.ts
21
+ /** Whether a realm-owned intrinsic prototype is backed by its native constructor. */
22
+ function hasIntrinsicConstructor(prototype, name$1) {
23
+ const constructor = Object.getOwnPropertyDescriptor(prototype, "constructor")?.value;
24
+ if (typeof constructor !== "function") return false;
25
+ try {
26
+ return constructor.name === name$1 && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === `function ${name$1}() { [native code] }`;
27
+ } catch {
28
+ return false;
29
+ }
30
+ }
31
+ /** Whether a candidate is one realm's intrinsic `Object.prototype`. */
32
+ function isIntrinsicObjectPrototype(value) {
33
+ return Object.getPrototypeOf(value) === null && hasIntrinsicConstructor(value, "Object");
34
+ }
35
+ /** Whether an array uses one realm's intrinsic `Array.prototype`, not a subclass or forged prototype. */
36
+ function hasPlainArrayPrototype(value) {
37
+ const prototype = Object.getPrototypeOf(value);
38
+ if (!Array.isArray(prototype) || !hasIntrinsicConstructor(prototype, "Array")) return false;
39
+ const objectPrototype = Object.getPrototypeOf(prototype);
40
+ return typeof objectPrototype === "object" && objectPrototype !== null && isIntrinsicObjectPrototype(objectPrototype);
41
+ }
42
+ /** Whether an object is a plain or null-prototype record from any JavaScript realm. */
43
+ function hasPlainObjectPrototype(value) {
44
+ const prototype = Object.getPrototypeOf(value);
45
+ return prototype === null || typeof prototype === "object" && isIntrinsicObjectPrototype(prototype);
46
+ }
47
+ /** Return every JSON-visible object key, or reject own data JSON would discard. */
48
+ function enumerableStringKeys(value) {
49
+ const keys = Reflect.ownKeys(value);
50
+ if (keys.some((key) => typeof key !== "string" || !Object.prototype.propertyIsEnumerable.call(value, key))) return void 0;
51
+ return keys;
52
+ }
53
+ /** Validate lossless JSON iteratively, optionally materializing a detached snapshot. */
54
+ function walkJsonValue(value, detach) {
55
+ const ancestors = /* @__PURE__ */ new Set();
56
+ let root;
57
+ const assign = (destination, item) => {
58
+ if (destination === void 0) return;
59
+ if (destination.kind === "root") root = item;
60
+ else if (destination.kind === "array") destination.target[destination.index] = item;
61
+ else Object.defineProperty(destination.target, destination.key, {
62
+ value: item,
63
+ enumerable: true,
64
+ configurable: true,
65
+ writable: true
66
+ });
67
+ };
68
+ const tasks = [{
69
+ kind: "visit",
70
+ value,
71
+ ...detach ? { destination: { kind: "root" } } : {}
72
+ }];
73
+ for (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {
74
+ if (task.kind === "leave") {
75
+ ancestors.delete(task.source);
76
+ continue;
77
+ }
78
+ if (task.kind === "array-item") {
79
+ if (!Object.prototype.hasOwnProperty.call(task.source, task.index)) return void 0;
80
+ tasks.push({
81
+ kind: "visit",
82
+ value: task.source[task.index],
83
+ ...task.target === void 0 ? {} : { destination: {
84
+ kind: "array",
85
+ target: task.target,
86
+ index: task.index
87
+ } }
88
+ });
89
+ continue;
90
+ }
91
+ if (task.kind === "object-property") {
92
+ tasks.push({
93
+ kind: "visit",
94
+ value: task.source[task.key],
95
+ ...task.target === void 0 ? {} : { destination: {
96
+ kind: "object",
97
+ target: task.target,
98
+ key: task.key
99
+ } }
100
+ });
101
+ continue;
102
+ }
103
+ const current = task.value;
104
+ if (current === null) {
105
+ assign(task.destination, null);
106
+ continue;
107
+ }
108
+ if (typeof current === "boolean" || typeof current === "string") {
109
+ assign(task.destination, current);
110
+ continue;
111
+ }
112
+ if (typeof current === "number") {
113
+ if (!Number.isFinite(current) || Object.is(current, -0)) return void 0;
114
+ assign(task.destination, current);
115
+ continue;
116
+ }
117
+ if (typeof current !== "object") return void 0;
118
+ if (ancestors.has(current)) return void 0;
119
+ if (Array.isArray(current)) {
120
+ if (!hasPlainArrayPrototype(current)) return void 0;
121
+ const length = current.length;
122
+ if (Reflect.ownKeys(current).length !== length + 1) return void 0;
123
+ const target$1 = detach ? [] : void 0;
124
+ if (target$1 !== void 0) assign(task.destination, target$1);
125
+ ancestors.add(current);
126
+ tasks.push({
127
+ kind: "leave",
128
+ source: current
129
+ });
130
+ for (let index = length - 1; index >= 0; index--) tasks.push({
131
+ kind: "array-item",
132
+ source: current,
133
+ index,
134
+ ...target$1 === void 0 ? {} : { target: target$1 }
135
+ });
136
+ continue;
137
+ }
138
+ if (!hasPlainObjectPrototype(current)) return void 0;
139
+ const keys = enumerableStringKeys(current);
140
+ if (keys === void 0) return void 0;
141
+ const target = detach ? {} : void 0;
142
+ if (target !== void 0) assign(task.destination, target);
143
+ ancestors.add(current);
144
+ tasks.push({
145
+ kind: "leave",
146
+ source: current
147
+ });
148
+ for (let index = keys.length - 1; index >= 0; index--) {
149
+ const key = keys[index];
150
+ /* v8 ignore next -- the loop is bounded by the captured key count. */
151
+ if (key === void 0) return void 0;
152
+ tasks.push({
153
+ kind: "object-property",
154
+ source: current,
155
+ key,
156
+ ...target === void 0 ? {} : { target }
157
+ });
158
+ }
159
+ }
160
+ return detach ? root : true;
161
+ }
162
+ /**
163
+ * Validate and detach lossless JSON in one read per property, so a stateful
164
+ * getter cannot change between validation and copying. Traversal is iterative,
165
+ * so valid nesting is bounded by available memory rather than the JavaScript
166
+ * call stack. Accepts ordinary arrays, plain or null-prototype objects, and JSON
167
+ * scalars; rejects sparse, cyclic, exotic, negative-zero, and non-finite values.
168
+ * Getter throws propagate.
169
+ *
170
+ * @param value - the candidate value to validate and detach.
171
+ * @returns the detached snapshot, or `undefined` when the value is not
172
+ * losslessly JSON-serializable.
173
+ */
174
+ function snapshotJsonValue(value) {
175
+ return walkJsonValue(value, true);
176
+ }
177
+
178
+ //#endregion
179
+ //#region src/kernel-transport.ts
180
+ /** The bridge script shipped beside the built entry (`lib/kernel-bridge.py`). */
181
+ const BRIDGE_SCRIPT = fileURLToPath(new URL("./kernel-bridge.py", import.meta.url));
182
+ /**
183
+ * One bridge subprocess speaking JSON lines. Lifecycle is owned by the caller
184
+ * (the kernel bridge registers it as an `ctx.effect`); this type installs no
185
+ * process-level signal handlers.
186
+ */
187
+ var KernelTransport = class {
188
+ child;
189
+ reader;
190
+ startup = false;
191
+ closed = false;
192
+ readySettled = false;
193
+ readyResolve;
194
+ readyReject;
195
+ bridgeStderr = "";
196
+ handlers = /* @__PURE__ */ new Set();
197
+ waiters = /* @__PURE__ */ new Set();
198
+ constructor(options) {
199
+ this.options = options;
200
+ }
201
+ /** Spawn the bridge and resolve once it reports the channels are up. */
202
+ async start() {
203
+ if (this.reader !== void 0) return;
204
+ if (this.closed) throw new Error("kernel transport is closed");
205
+ const child = spawn(this.options.python, [BRIDGE_SCRIPT, this.options.connectionFile], {
206
+ ...this.options.cwd === void 0 ? {} : { cwd: this.options.cwd },
207
+ env: {
208
+ PATH: process.env.PATH ?? "/usr/local/bin:/usr/bin:/bin",
209
+ LANG: "C.UTF-8",
210
+ HOME: process.env.HOME ?? tmpdir(),
211
+ PYTHONUNBUFFERED: "1"
212
+ },
213
+ stdio: [
214
+ "pipe",
215
+ "pipe",
216
+ "pipe"
217
+ ]
218
+ });
219
+ this.child = child;
220
+ this.startup = true;
221
+ const ready = new Promise((resolve$1, reject) => {
222
+ this.readyResolve = resolve$1;
223
+ this.readyReject = reject;
224
+ });
225
+ const timer = setTimeout(() => {
226
+ this.failReady(/* @__PURE__ */ new Error(`kernel bridge did not report ready within ${this.options.readyTimeoutMs}ms; stderr tail:\n${this.stderrTail()}`));
227
+ }, this.options.readyTimeoutMs);
228
+ timer.unref?.();
229
+ child.stderr?.on("data", (buffer) => {
230
+ this.bridgeStderr += buffer.toString();
231
+ });
232
+ child.stdin?.on("error", (error) => {
233
+ this.bridgeStderr += `stdin error: ${error.code ?? error.message}\n`;
234
+ this.closed = true;
235
+ this.failWaiters();
236
+ });
237
+ child.stdout?.on("error", (error) => {
238
+ this.bridgeStderr += `stdout error: ${error.code ?? error.message}\n`;
239
+ });
240
+ child.on("error", (error) => {
241
+ this.bridgeStderr += `spawn error: ${error.message}\n`;
242
+ this.failReady(/* @__PURE__ */ new Error(`kernel bridge failed to spawn: ${error.message}`));
243
+ this.failWaiters();
244
+ this.failExit();
245
+ });
246
+ child.on("exit", (code, signal) => {
247
+ const detail = `kernel bridge exited (code=${String(code)} signal=${String(signal)})`;
248
+ this.bridgeStderr += `${detail}\n`;
249
+ this.closed = true;
250
+ this.failReady(/* @__PURE__ */ new Error(`${detail}; stderr tail:\n${this.stderrTail()}`));
251
+ this.failWaiters();
252
+ this.failExit();
253
+ });
254
+ if (child.stdout) {
255
+ this.reader = createInterface({ input: child.stdout });
256
+ this.reader.on("line", (line) => {
257
+ this.accept(line);
258
+ });
259
+ }
260
+ try {
261
+ await ready;
262
+ } finally {
263
+ clearTimeout(timer);
264
+ this.startup = false;
265
+ }
266
+ }
267
+ /** Whether the bridge process is still live. */
268
+ get alive() {
269
+ return this.child !== void 0 && this.child.exitCode === null && !this.closed;
270
+ }
271
+ /** The bridge's stderr tail, for startup and crash diagnostics. */
272
+ stderrTail() {
273
+ return this.bridgeStderr.slice(-1024) || "(empty)";
274
+ }
275
+ /** Register a message handler; the returned function removes it. */
276
+ onMessage(handler) {
277
+ this.handlers.add(handler);
278
+ return () => {
279
+ this.handlers.delete(handler);
280
+ };
281
+ }
282
+ /**
283
+ * Register a bridge-exit handler; the returned function removes it. A bridge
284
+ * that dies mid-cell must settle the active execution at once rather than at
285
+ * the cell budget.
286
+ */
287
+ onExit(handler) {
288
+ this.exitHandlers.add(handler);
289
+ return () => {
290
+ this.exitHandlers.delete(handler);
291
+ };
292
+ }
293
+ exitHandlers = /* @__PURE__ */ new Set();
294
+ /** Notify exit handlers once per bridge process end. */
295
+ failExit() {
296
+ const handlers = [...this.exitHandlers];
297
+ this.exitHandlers.clear();
298
+ for (const handler of handlers) handler();
299
+ }
300
+ /** Send one message on the shell or control channel. */
301
+ send(channel, message) {
302
+ this.writeLine({
303
+ op: "send",
304
+ channel,
305
+ header: message.header,
306
+ content: message.content
307
+ });
308
+ }
309
+ /** Ask the kernel to interrupt the running cell (control channel). */
310
+ interrupt() {
311
+ this.writeLine({ op: "interrupt" });
312
+ }
313
+ /** Write one protocol line, refusing instead of throwing when the pipe is gone. */
314
+ writeLine(payload) {
315
+ const stdin = this.child?.stdin;
316
+ if (stdin === null || stdin === void 0 || this.closed || !stdin.writable) throw new Error("kernel bridge is not connected");
317
+ stdin.write(`${JSON.stringify(payload)}\n`);
318
+ }
319
+ /**
320
+ * Wait for the next message on `channel` matching `match`.
321
+ * @returns The message, or null when the budget expires or the bridge dies.
322
+ */
323
+ waitFor(channel, match, timeoutMs) {
324
+ if (this.closed) return Promise.resolve(null);
325
+ return new Promise((resolve$1) => {
326
+ const waiter = {
327
+ channel,
328
+ match,
329
+ settle: (message) => {
330
+ clearTimeout(waiter.timer);
331
+ this.waiters.delete(waiter);
332
+ resolve$1(message);
333
+ },
334
+ timer: setTimeout(() => {
335
+ this.waiters.delete(waiter);
336
+ resolve$1(null);
337
+ }, timeoutMs)
338
+ };
339
+ waiter.timer.unref?.();
340
+ this.waiters.add(waiter);
341
+ });
342
+ }
343
+ /** Stop the bridge (graceful shutdown note, then kill). */
344
+ async dispose() {
345
+ const child = this.child;
346
+ this.closed = true;
347
+ this.failWaiters();
348
+ this.reader?.close();
349
+ this.reader = void 0;
350
+ if (child === void 0) return;
351
+ try {
352
+ if (child.stdin?.writable === true) child.stdin.write(`${JSON.stringify({ op: "shutdown" })}\n`);
353
+ } catch {}
354
+ try {
355
+ child.stdin?.end();
356
+ } catch {}
357
+ if (child.exitCode !== null) return;
358
+ await new Promise((resolve$1) => {
359
+ const timer = setTimeout(() => {
360
+ try {
361
+ child.kill("SIGKILL");
362
+ } catch {}
363
+ resolve$1();
364
+ }, 500);
365
+ timer.unref?.();
366
+ child.once("exit", () => {
367
+ clearTimeout(timer);
368
+ resolve$1();
369
+ });
370
+ });
371
+ }
372
+ failReady(error) {
373
+ if (this.readySettled) return;
374
+ this.readySettled = true;
375
+ this.readyReject?.(error);
376
+ }
377
+ failWaiters() {
378
+ for (const waiter of [...this.waiters]) waiter.settle(null);
379
+ }
380
+ /** Route one decoded line; unknown events are ignored. */
381
+ accept(line) {
382
+ let event;
383
+ try {
384
+ event = JSON.parse(line);
385
+ } catch {
386
+ return;
387
+ }
388
+ if (event.ev === "ready") {
389
+ if (!this.readySettled) {
390
+ this.readySettled = true;
391
+ this.readyResolve?.();
392
+ }
393
+ return;
394
+ }
395
+ if (event.ev === "msg") {
396
+ const channel = event.channel;
397
+ const raw = event.msg;
398
+ if (typeof channel !== "string" || raw === void 0 || typeof raw.header !== "object" || raw.header === null) return;
399
+ const message = {
400
+ header: raw.header,
401
+ parent_header: raw.parent_header ?? {},
402
+ content: raw.content ?? {}
403
+ };
404
+ for (const waiter of [...this.waiters]) if (waiter.channel === channel && waiter.match(message)) waiter.settle(message);
405
+ for (const handler of this.handlers) handler(channel, message);
406
+ return;
407
+ }
408
+ if (event.ev === "fatal") this.bridgeStderr += `fatal: ${String(event.message ?? "unknown")}\n`;
409
+ }
410
+ };
411
+
412
+ //#endregion
413
+ //#region src/bootstrap.ts
414
+ /**
415
+ * Python-side bootstrap executed once as an internal cell right after kernel
416
+ * startup. Seeds the user namespace with the host-request comm bridge
417
+ * (`dashr.host` target, the PA `host_request()` pattern), the binding-proxy
418
+ * factories, the typed rejection classes, and the lossless-JSON completion
419
+ * encoder. Names are `_dashr`/`__dashr` prefixed (any case) so they are
420
+ * excluded from namespace snapshots and never leak into user state.
421
+ * @module dashr/bootstrap
422
+ */
423
+ /** Comm target the kernel-side shim opens for typed host requests. */
424
+ const HOST_COMM_TARGET = "dashr.host";
425
+ /**
426
+ * The bootstrap source. Kept dependency-free apart from `ast`, `asyncio`,
427
+ * `json`, and `comm` (present by construction — it IS the kernel).
428
+ */
429
+ const KERNEL_BOOTSTRAP = `
430
+ import ast as _dashr_ast
431
+ import json as _dashr_json
432
+
433
+
434
+ def _dashr_install_control_comm_handlers():
435
+ # Host replies arrive as comm_msg on the CONTROL channel while the shell
436
+ # channel is busy executing our cell; teach the kernel to route them.
437
+ try:
438
+ from IPython import get_ipython
439
+ except Exception:
440
+ return
441
+ shell = get_ipython()
442
+ kernel = getattr(shell, 'kernel', None)
443
+ comm_manager = getattr(kernel, 'comm_manager', None)
444
+ control_handlers = getattr(kernel, 'control_handlers', None)
445
+ if comm_manager is None or not isinstance(control_handlers, dict):
446
+ return
447
+ control_handlers.setdefault('comm_msg', comm_manager.comm_msg)
448
+ control_handlers.setdefault('comm_close', comm_manager.comm_close)
449
+
450
+
451
+ def _dashr_install_interrupt():
452
+ # ipykernel's async-cell SIGINT handling only schedules a callback on the
453
+ # kernel event loop, and a non-yielding cell ('while True: pass') blocks
454
+ # that very loop, so the control-channel interrupt can never break it.
455
+ # SIGALRM is untouched by ipykernel: raising KeyboardInterrupt from its
456
+ # handler breaks any cell, and the host sends it (after a confirm window,
457
+ # see the bridge) on timeout/abort. Best effort — where SIGALRM is
458
+ # unavailable the control-channel interrupt is all there is.
459
+ #
460
+ # The busy guard is load-bearing (M3-A, blueprint §5 "SIGALRM-at-idle 双重
461
+ # 窗口"): a KeyboardInterrupt raised OUTSIDE cell execution — while the
462
+ # kernel boots, idles between cells, or unwinds a finished one — escapes
463
+ # the shell's containment and terminates the process cleanly, which used
464
+ # to kill the kernel deterministically (10/10 same-tick aborts, 40/40
465
+ # during cold boot; dev/m2a-report.md §5.1). The handler therefore only
466
+ # raises while a dashr cell is actually executing, tracked by the
467
+ # module-level _dashr_state dict below and set/cleared by the run/snapshot
468
+ # cell scaffolds around their whole body. A stray SIGALRM outside that
469
+ # window is swallowed — the host's force-settle already resolves the run,
470
+ # and the kernel lives. The dict (not a bare flag) is captured by the
471
+ # handler closure, so user code rebinding the NAME cannot disarm the
472
+ # guard; mutating the dict itself stays possible and accepted — this shim
473
+ # is a capability seam, not a security boundary.
474
+ try:
475
+ import signal as _dashr_signal
476
+
477
+ def _dashr_on_sigalrm(_signum, _frame):
478
+ if not _dashr_state['executing']:
479
+ return
480
+ raise KeyboardInterrupt
481
+
482
+ _dashr_signal.signal(_dashr_signal.SIGALRM, _dashr_on_sigalrm)
483
+ except (ImportError, AttributeError, OSError, ValueError):
484
+ pass
485
+
486
+
487
+ # The dashr busy-guard flag (see _dashr_install_interrupt): True for the whole
488
+ # duration of a run or snapshot cell — the only window in which a SIGALRM may
489
+ # raise KeyboardInterrupt. Lives at module (user-namespace) level so the cell
490
+ # scaffolds can flip it; excluded from snapshots by the _dashr prefix rule.
491
+ _dashr_state = {'executing': False}
492
+
493
+
494
+ _dashr_install_interrupt()
495
+
496
+
497
+ class _DashrRejected(Exception):
498
+ def __init__(self, message):
499
+ Exception.__init__(self, message)
500
+
501
+
502
+ def _dashr_host_request(payload):
503
+ from comm import create_comm
504
+ import asyncio
505
+ _dashr_install_control_comm_handlers()
506
+ loop = asyncio.get_running_loop()
507
+ future = loop.create_future()
508
+ # primary=True publishes comm_open so the host learns this comm_id; the
509
+ # request itself travels as the first comm_msg.
510
+ comm = create_comm(target_name=${JSON.stringify(HOST_COMM_TARGET)})
511
+
512
+ def _resolve(action):
513
+ def _apply():
514
+ if future.done():
515
+ return
516
+ action()
517
+ comm.close()
518
+ # Replies arrive on the kernel's control channel, which may run off
519
+ # the event-loop thread; only call_soon_threadsafe may touch the
520
+ # future from there.
521
+ loop.call_soon_threadsafe(_apply)
522
+
523
+ def _on_msg(msg):
524
+ content = msg.get('content', {})
525
+ reply = content.get('data', {}) if isinstance(content, dict) else {}
526
+ if not isinstance(reply, dict) or future.done():
527
+ return
528
+ status = reply.get('status')
529
+ if status == 'ok':
530
+ _resolve(lambda: future.set_result(reply.get('result')))
531
+ elif status == 'error':
532
+ _resolve(lambda: future.set_exception(_DashrRejected(reply.get('error') or 'host request failed')))
533
+
534
+ comm.on_msg(_on_msg)
535
+ comm.send(dict(payload))
536
+ return future
537
+
538
+
539
+ def _dashr_make_error_class(name, member_property):
540
+ def _init(self, message, member=None):
541
+ Exception.__init__(self, message)
542
+ if member is not None:
543
+ setattr(self, member_property, member)
544
+ return type(name, (Exception,), {'__init__': _init})
545
+
546
+
547
+ def _dashr_make_proxy(global_name, function_name, error_class_name, member_property):
548
+ async def _dashr_proxy(*args, **kwargs):
549
+ if kwargs:
550
+ raise TypeError('dashr binding calls do not accept keyword arguments')
551
+ if len(args) == 1:
552
+ call_args = args[0]
553
+ elif len(args) == 0:
554
+ call_args = None
555
+ else:
556
+ call_args = list(args)
557
+ payload = {
558
+ 'type': 'binding.call',
559
+ 'global': global_name,
560
+ 'name': function_name,
561
+ 'args': call_args,
562
+ }
563
+ try:
564
+ return await _dashr_host_request(payload)
565
+ except _DashrRejected as rejected:
566
+ cls = globals().get(error_class_name) if error_class_name else None
567
+ if cls is None:
568
+ raise
569
+ raise cls(str(rejected), function_name) from None
570
+ return _dashr_proxy
571
+
572
+
573
+ def _dashr_make_holder(global_name, error_class_name, member_property, members):
574
+ # Attribute misses travel to the host instead of raising AttributeError
575
+ # here: the host owns the namespace, so IT rejects an unknown member as an
576
+ # unknown binding rather than the kernel inventing a local error class.
577
+ class _DashrBindingHolder:
578
+ def __dir__(self):
579
+ # F9 (v0.2.0-a): introspection tells the truth — dir(tool) lists
580
+ # exactly the bound names. A custom __dir__ fully replaces the
581
+ # default object.__dir__, so no dunder noise leaks in.
582
+ return list(members)
583
+
584
+ def __getattr__(self, function_name):
585
+ return _dashr_make_proxy(
586
+ global_name,
587
+ function_name,
588
+ error_class_name,
589
+ member_property,
590
+ )
591
+
592
+ return _DashrBindingHolder()
593
+
594
+
595
+ def _dashr_make_callable(global_name, function_name, error_class_name, member_property):
596
+ # A BARE callable global (the flat per-tool bindings AND the bridge
597
+ # tools: 'callable: true' on the namespace) instead of an object
598
+ # holder. The one-object form is the single convention: every callable
599
+ # takes exactly one positional arguments object (e.g.
600
+ # agent_message({'receiver': 'child', ...})), and keyword / multi-positional forms are
601
+ # rejected HERE, at the Python call boundary, so the introspectable
602
+ # signature tells the truth and a TypeError names the binding global
603
+ # (read(...) got an unexpected keyword argument ...). The wire envelope
604
+ # keeps the historical {'args': [...], 'kwargs': {}} shape so the host's
605
+ # parseReplCall / flatToolArgs / flatBridgeToolArgs validation layers stay
606
+ # authoritative and unchanged. The single functions-entry name is
607
+ # transport-only: the program never sees it, and a typed rejection
608
+ # carries the GLOBAL name as its member (for a flat tool binding the
609
+ # global IS the tool name the program knows). __name__/__qualname__ are
610
+ # pinned to the global name so introspection shows the binding's name,
611
+ # not the factory-local _dashr_callable.
612
+ async def _dashr_callable(args=None, /):
613
+ payload = {
614
+ 'type': 'binding.call',
615
+ 'global': global_name,
616
+ 'name': function_name,
617
+ 'args': {'args': [] if args is None else [args], 'kwargs': {}},
618
+ }
619
+ try:
620
+ return await _dashr_host_request(payload)
621
+ except _DashrRejected as rejected:
622
+ cls = globals().get(error_class_name) if error_class_name else None
623
+ if cls is None:
624
+ raise
625
+ raise cls(str(rejected), global_name) from None
626
+
627
+ _dashr_callable.__name__ = global_name
628
+ _dashr_callable.__qualname__ = global_name
629
+ return _dashr_callable
630
+
631
+
632
+ class _DashrNoValue:
633
+ # Marks 'no completion value': a cell whose last statement is not an
634
+ # expression, or whose last expression evaluates to None — the REPL
635
+ # displayhook suppresses None (IPython behavior), so no value crosses.
636
+ __slots__ = ()
637
+
638
+
639
+ _DASHR_NO_VALUE = _DashrNoValue()
640
+
641
+
642
+ class _DashrTopLevelReturnChecker(_dashr_ast.NodeVisitor):
643
+ # A cell runs at module scope, like any native IPython cell: a top-level
644
+ # 'return'/'yield' is a SyntaxError decided by the kernel itself, exactly
645
+ # as in a real REPL. Nested scopes (functions, lambdas, classes) keep
646
+ # their own return semantics.
647
+ def visit_FunctionDef(self, node):
648
+ return
649
+
650
+ def visit_AsyncFunctionDef(self, node):
651
+ return
652
+
653
+ def visit_ClassDef(self, node):
654
+ return
655
+
656
+ def visit_Lambda(self, node):
657
+ return
658
+
659
+ def visit_Return(self, node):
660
+ raise SyntaxError("'return' outside function")
661
+
662
+ def visit_Yield(self, node):
663
+ raise SyntaxError("'yield' outside function")
664
+
665
+
666
+ async def _dashr_run_program(source):
667
+ # Run one cell with the user namespace as BOTH globals and locals —
668
+ # module-scope REPL semantics: state persists across cells, top-level
669
+ # 'await' is legal (PyCF_ALLOW_TOP_LEVEL_AWAIT, the same mechanism IPython
670
+ # uses), a top-level 'return'/'yield' is a SyntaxError decided here by the
671
+ # kernel — exactly as in a native IPython cell — and the last expression's
672
+ # value is the cell's result (the REPL displayhook handoff).
673
+ import inspect as _dashr_inspect
674
+ user_ns = globals()
675
+ if not source.strip():
676
+ source = 'pass'
677
+ parsed = _dashr_ast.parse(source, '<dashr program>', 'exec')
678
+ _DashrTopLevelReturnChecker().visit(parsed)
679
+ body = parsed.body
680
+ if body and isinstance(body[-1], _dashr_ast.Expr):
681
+ # Capture the last expression the way a REPL's displayhook shows it:
682
+ # its value feeds the completion envelope instead of being discarded.
683
+ # The name is distinct from the scaffold's __dashr_completion__ (the
684
+ # envelope holder) so a statement-ending cell can never pop a stale
685
+ # envelope left by an earlier run.
686
+ last = body[-1]
687
+ body[-1] = _dashr_ast.Assign(
688
+ targets=[_dashr_ast.Name(id='__dashr_cell_value__', ctx=_dashr_ast.Store())],
689
+ value=last.value,
690
+ )
691
+ _dashr_ast.fix_missing_locations(body[-1])
692
+ code = compile(
693
+ parsed,
694
+ '<dashr program>',
695
+ 'exec',
696
+ flags=_dashr_ast.PyCF_ALLOW_TOP_LEVEL_AWAIT,
697
+ )
698
+ # IPython's own run_code pattern: with PyCF_ALLOW_TOP_LEVEL_AWAIT, plain
699
+ # exec() DISCARDS the module coroutine silently; eval() under await
700
+ # returns it and runs the code (IPython InteractiveShell.run_code does
701
+ # exactly 'await eval(code_obj, user_global_ns, user_ns)').
702
+ result = eval(code, user_ns, user_ns)
703
+ if _dashr_inspect.iscoroutine(result):
704
+ await result
705
+ value = user_ns.pop('__dashr_cell_value__', _DASHR_NO_VALUE)
706
+ if value is None:
707
+ return _DASHR_NO_VALUE
708
+ return value
709
+
710
+
711
+ def _dashr_install_bindings(spec_json):
712
+ spec = _dashr_json.loads(spec_json)
713
+ user_ns = globals()
714
+ injected = user_ns.get('__dashr_injected__', {})
715
+ for old_name, old_spec in list(injected.items()):
716
+ if old_name not in spec:
717
+ user_ns.pop(old_name, None)
718
+ if old_spec.get('errorClass'):
719
+ user_ns.pop(old_spec['errorClass']['name'], None)
720
+ fresh = {}
721
+ # The flat per-tool shape declares the SAME error class on many
722
+ # namespaces: materialize each DISTINCT name once, so every proxy's
723
+ # raise-time globals() lookup finds ONE class and a single
724
+ # 'except ToolCallError' catches failures from every binding.
725
+ error_classes = {}
726
+ for global_name, namespace in spec.items():
727
+ error_class = namespace.get('errorClass')
728
+ if namespace.get('callable'):
729
+ # Exactly one function entry was validated by the host; its key is
730
+ # the transport name, the bare global itself is the callable.
731
+ function_name = next(iter(namespace['functions']))
732
+ user_ns[global_name] = _dashr_make_callable(
733
+ global_name,
734
+ function_name,
735
+ error_class['name'] if error_class else None,
736
+ error_class['memberNameProperty'] if error_class else None,
737
+ )
738
+ else:
739
+ user_ns[global_name] = _dashr_make_holder(
740
+ global_name,
741
+ error_class['name'] if error_class else None,
742
+ error_class['memberNameProperty'] if error_class else None,
743
+ sorted(namespace['functions']),
744
+ )
745
+ if error_class and error_class['name'] not in error_classes:
746
+ cls = _dashr_make_error_class(
747
+ error_class['name'],
748
+ error_class['memberNameProperty'],
749
+ )
750
+ error_classes[error_class['name']] = cls
751
+ user_ns[error_class['name']] = cls
752
+ fresh[global_name] = namespace
753
+ user_ns['__dashr_injected__'] = fresh
754
+
755
+
756
+ def _dashr_encode(value):
757
+ if value is _DASHR_NO_VALUE:
758
+ return {'ok': True}
759
+ try:
760
+ return {'ok': True, 'json': _dashr_json.dumps(value, allow_nan=False)}
761
+ except (TypeError, ValueError, OverflowError):
762
+ # Not lossless JSON: pass its repr TEXT through instead of failing
763
+ # the cell. The upstream renders the tool result as text either way,
764
+ # so a non-JSON value costs the model nothing; the host keeps a
765
+ # plain string it forwards untouched. The envelope itself never
766
+ # fails, so the completion never gate-rejects a return value.
767
+ return {'ok': True, 'json': _dashr_json.dumps(repr(value))}
768
+ `;
769
+
770
+ //#endregion
771
+ //#region src/python.ts
772
+ /**
773
+ * Build the single cell for one run.
774
+ * @param program - the model's cell program, executed at module scope.
775
+ * @param specJson - the JSON-encoded {@link NamespaceSpecs} map.
776
+ * @param sentinel - per-run nonce prefix; the envelope line starts with it.
777
+ * @returns the complete cell source.
778
+ */
779
+ function buildRunCell(program, specJson, sentinel) {
780
+ return [
781
+ `_dashr_state['executing'] = True`,
782
+ `try:`,
783
+ ` _dashr_install_bindings(${JSON.stringify(specJson)})`,
784
+ ` __dashr_completion__ = _dashr_encode(await _dashr_run_program(${JSON.stringify(program)}))`,
785
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps(__dashr_completion__))`,
786
+ `finally:`,
787
+ ` _dashr_state['executing'] = False`
788
+ ].join("\n");
789
+ }
790
+ /**
791
+ * Build the internal cell that dumps the user namespace to a dill snapshot and
792
+ * writes a JSON manifest next to it. Only USER state is captured: IPython's
793
+ * own session plumbing (`exit`, `quit`, `get_ipython`, … tracked in the
794
+ * shell's `user_ns_hidden` and still bound to the object IPython installed)
795
+ * reaches unpicklable kernel machinery — e.g. the history manager's
796
+ * sqlite3.Connection — and is never restored as program state anyway. Shim
797
+ * names (any `_dashr`/`__dashr` spelling) are excluded by prefix.
798
+ *
799
+ * Size-cap policy (M3-B, blueprint §8.3): dill cannot report a serialized
800
+ * size before dumping, and a GB-sized `DataFrame` dumped EVERY turn is the IO
801
+ * storm the cap exists to stop. The cell therefore gates in two tiers:
802
+ * first a bounded-depth namespace walk estimates the footprint (counting
803
+ * container lengths and reading `nbytes` / `memory_usage(deep=True)` for
804
+ * numpy/pandas objects — the stated pathological case — so the dump is
805
+ * skipped BEFORE any dill IO), then the actual dump goes to a sibling
806
+ * `.part` file whose true byte size is measured before it replaces the
807
+ * previous good snapshot. Skipped snapshots leave the previous
808
+ * `state.dill` + manifest untouched, so a revive restores the last good turn.
809
+ * @param payloadPath - absolute path for the dill payload.
810
+ * @param manifestPath - absolute path for the JSON manifest.
811
+ * @param spec - turn counter, skills list, and the size cap.
812
+ * @param sentinel - per-cell nonce prefix for the outcome envelope.
813
+ * @returns the complete cell source.
814
+ */
815
+ function buildSnapshotCell(payloadPath, manifestPath, spec, sentinel) {
816
+ return [
817
+ `_dashr_state['executing'] = True`,
818
+ `try:`,
819
+ ` import dill as _dashr_dill, json as _dashr_json, platform as _dashr_platform`,
820
+ ` import os as _dashr_os, sys as _dashr_sys, datetime as _dashr_dt`,
821
+ ` _dashr_shell = globals().get('get_ipython', lambda: None)()`,
822
+ ` _dashr_hidden = getattr(_dashr_shell, 'user_ns_hidden', None) or {}`,
823
+ ` _dashr_user_ns = {`,
824
+ ` name: value`,
825
+ ` for name, value in globals().items()`,
826
+ ` if not name.lower().startswith(('_dashr', '__dashr'))`,
827
+ ` and (name not in _dashr_hidden or _dashr_hidden[name] is not value)`,
828
+ ` }`,
829
+ ` _dashr_cap = ${JSON.stringify(spec.sizeCapBytes)}`,
830
+ ` def _dashr_estimate(value, depth):`,
831
+ ` if value is None or isinstance(value, (bool, int, float, complex)):`,
832
+ ` return 32`,
833
+ ` if isinstance(value, (str, bytes, bytearray)):`,
834
+ ` return len(value) + 64`,
835
+ ` if isinstance(value, (list, tuple, set, frozenset)):`,
836
+ ` if depth <= 0:`,
837
+ ` return 4096`,
838
+ ` return 64 + sum(_dashr_estimate(item, depth - 1) for item in value)`,
839
+ ` if isinstance(value, dict):`,
840
+ ` if depth <= 0:`,
841
+ ` return 4096`,
842
+ ` total = 64`,
843
+ ` for key, item in value.items():`,
844
+ ` total += _dashr_estimate(key, depth - 1)`,
845
+ ` total += _dashr_estimate(item, depth - 1)`,
846
+ ` if total > _dashr_cap:`,
847
+ ` return total`,
848
+ ` return total`,
849
+ ` _dashr_nbytes = getattr(value, 'nbytes', None)`,
850
+ ` if isinstance(_dashr_nbytes, int) and _dashr_nbytes > 0:`,
851
+ ` return _dashr_nbytes + 128`,
852
+ ` _dashr_mem = getattr(value, 'memory_usage', None)`,
853
+ ` if callable(_dashr_mem):`,
854
+ ` try:`,
855
+ ` _dashr_usage = _dashr_mem(deep=True)`,
856
+ ` _dashr_sum = getattr(_dashr_usage, 'sum', None)`,
857
+ ` if callable(_dashr_sum):`,
858
+ ` # pandas returns a numpy scalar (np.int64), which is`,
859
+ ` # not a Python int subclass; coerce, don't isinstance.`,
860
+ ` _dashr_n = int(_dashr_sum())`,
861
+ ` if _dashr_n > 0:`,
862
+ ` return _dashr_n + 128`,
863
+ ` except Exception:`,
864
+ ` pass`,
865
+ ` return 4096`,
866
+ ` _dashr_estimate_bytes = sum(_dashr_estimate(value, 4) for value in _dashr_user_ns.values())`,
867
+ ` if _dashr_estimate_bytes > _dashr_cap:`,
868
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({`,
869
+ ` 'ok': False, 'skipped': True, 'reason': 'estimate',`,
870
+ ` 'estimateBytes': _dashr_estimate_bytes, 'capBytes': _dashr_cap,`,
871
+ ` }))`,
872
+ ` else:`,
873
+ ` _dashr_part = ${JSON.stringify(payloadPath)} + '.part'`,
874
+ ` try:`,
875
+ ` with open(_dashr_part, 'wb') as _dashr_f:`,
876
+ ` _dashr_dill.dump(_dashr_user_ns, _dashr_f)`,
877
+ ` _dashr_size = _dashr_os.path.getsize(_dashr_part)`,
878
+ ` if _dashr_size > _dashr_cap:`,
879
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({`,
880
+ ` 'ok': False, 'skipped': True, 'reason': 'actual',`,
881
+ ` 'sizeBytes': _dashr_size, 'capBytes': _dashr_cap,`,
882
+ ` }))`,
883
+ ` else:`,
884
+ ` _dashr_os.replace(_dashr_part, ${JSON.stringify(payloadPath)})`,
885
+ ` _dashr_manifest = {`,
886
+ ` 'snapshotFormat': 1,`,
887
+ ` 'turn': ${JSON.stringify(spec.turn)},`,
888
+ ` 'pythonVersion': _dashr_platform.python_version(),`,
889
+ ` 'venvPath': _dashr_sys.executable,`,
890
+ ` 'skills': ${JSON.stringify(spec.skills)},`,
891
+ ` 'names': sorted(_dashr_user_ns),`,
892
+ ` 'sizeBytes': _dashr_size,`,
893
+ ` 'skipped': False,`,
894
+ ` 'createdAt': _dashr_dt.datetime.now(_dashr_dt.timezone.utc).isoformat(),`,
895
+ ` }`,
896
+ ` with open(${JSON.stringify(manifestPath)}, 'w', encoding='utf-8') as _dashr_f:`,
897
+ ` _dashr_json.dump(_dashr_manifest, _dashr_f)`,
898
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({`,
899
+ ` 'ok': True, 'sizeBytes': _dashr_size, 'names': len(_dashr_user_ns),`,
900
+ ` }))`,
901
+ ` finally:`,
902
+ ` if _dashr_os.path.exists(_dashr_part):`,
903
+ ` try:`,
904
+ ` _dashr_os.unlink(_dashr_part)`,
905
+ ` except OSError:`,
906
+ ` pass`,
907
+ `finally:`,
908
+ ` _dashr_state['executing'] = False`
909
+ ].join("\n");
910
+ }
911
+ /**
912
+ * Build the internal cell that restores a dill snapshot into the user
913
+ * namespace. The kernel validates the manifest ITSELF (it is the only party
914
+ * that knows its own python version and `sys.executable`): a python-version
915
+ * mismatch, a different interpreter (`venvPath`), a non-empty skills list, or
916
+ * an unreadable/corrupt payload degrades to an empty namespace WITHOUT
917
+ * touching globals, and reports the reason through the envelope so the host
918
+ * can tell the model "snapshot not replayable, started from empty". Shim and
919
+ * IPython-hidden names are re-filtered on the way in — the same exclusion the
920
+ * snapshot applied on the way out, applied again defensively.
921
+ * @param payloadPath - absolute path of the dill payload.
922
+ * @param manifestPath - absolute path of the JSON manifest.
923
+ * @param sentinel - per-cell nonce prefix for the outcome envelope.
924
+ * @returns the complete cell source.
925
+ */
926
+ function buildRestoreCell(payloadPath, manifestPath, sentinel) {
927
+ return [
928
+ `_dashr_state['executing'] = True`,
929
+ `try:`,
930
+ ` import dill as _dashr_dill, json as _dashr_json, platform as _dashr_platform`,
931
+ ` import os as _dashr_os, sys as _dashr_sys`,
932
+ ` _dashr_manifest = None`,
933
+ ` _dashr_reason = 'snapshot manifest could not be read'`,
934
+ ` try:`,
935
+ ` with open(${JSON.stringify(manifestPath)}, 'r', encoding='utf-8') as _dashr_f:`,
936
+ ` _dashr_manifest = _dashr_json.load(_dashr_f)`,
937
+ ` except Exception as _dashr_err:`,
938
+ ` _dashr_reason = 'snapshot manifest could not be read: ' + repr(_dashr_err)`,
939
+ ` if _dashr_manifest is None:`,
940
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': False, 'reason': _dashr_reason}))`,
941
+ ` elif _dashr_manifest.get('snapshotFormat') != 1:`,
942
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': False, 'reason': 'snapshot format is not replayable'}))`,
943
+ ` elif _dashr_manifest.get('skipped'):`,
944
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': False, 'reason': 'snapshot was skipped (namespace exceeded the size cap)'}))`,
945
+ ` elif _dashr_manifest.get('pythonVersion') != _dashr_platform.python_version():`,
946
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': False, 'reason': 'python version mismatch: snapshot ' + str(_dashr_manifest.get('pythonVersion')) + ' vs kernel ' + _dashr_platform.python_version()}))`,
947
+ ` elif _dashr_os.path.realpath(_dashr_manifest.get('venvPath') or '') != _dashr_os.path.realpath(_dashr_sys.executable):`,
948
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': False, 'reason': 'kernel interpreter differs from the snapshot venv'}))`,
949
+ ` elif _dashr_manifest.get('skills'):`,
950
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': False, 'reason': 'snapshot skills are not replayable in this provider'}))`,
951
+ ` else:`,
952
+ ` try:`,
953
+ ` with open(${JSON.stringify(payloadPath)}, 'rb') as _dashr_f:`,
954
+ ` _dashr_restored = _dashr_dill.load(_dashr_f)`,
955
+ ` except Exception as _dashr_err:`,
956
+ ` _dashr_restored = None`,
957
+ ` _dashr_reason = 'snapshot payload could not be loaded: ' + repr(_dashr_err)`,
958
+ ` if not isinstance(_dashr_restored, dict):`,
959
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': False, 'reason': _dashr_reason if _dashr_restored is None else 'snapshot payload is not a namespace dict'}))`,
960
+ ` else:`,
961
+ ` _dashr_shell = globals().get('get_ipython', lambda: None)()`,
962
+ ` _dashr_hidden = getattr(_dashr_shell, 'user_ns_hidden', None) or {}`,
963
+ ` _dashr_user_ns = globals()`,
964
+ ` _dashr_restored_count = 0`,
965
+ ` for _dashr_name, _dashr_value in _dashr_restored.items():`,
966
+ ` if not isinstance(_dashr_name, str):`,
967
+ ` continue`,
968
+ ` if _dashr_name.lower().startswith(('_dashr', '__dashr')):`,
969
+ ` continue`,
970
+ ` if _dashr_name in _dashr_hidden and _dashr_hidden[_dashr_name] is _dashr_value:`,
971
+ ` continue`,
972
+ ` _dashr_user_ns[_dashr_name] = _dashr_value`,
973
+ ` _dashr_restored_count += 1`,
974
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': True, 'restored': _dashr_restored_count}))`,
975
+ `finally:`,
976
+ ` _dashr_state['executing'] = False`
977
+ ].join("\n");
978
+ }
979
+ /**
980
+ * Build the internal cell that reads ONE user-namespace variable by name, or
981
+ * — when `name` is `null` — lists the namespace's user-variable names. The
982
+ * same exclusion the snapshot applies on the way out (any `_dashr`/`__dashr`
983
+ * spelling plus IPython's `user_ns_hidden`) defines what "user variable"
984
+ * means here, so `ctx://` sees exactly the namespace a revive would restore.
985
+ *
986
+ * Serialization boundary (design.md D4): a value that survives
987
+ * `json.dumps(…, allow_nan=False)` crosses as `kind: 'json'` text; anything
988
+ * else falls back to `repr` text (`kind: 'repr'`) so a non-JSON variable
989
+ * (the reason the snapshot uses dill at all) is still readable as text. The
990
+ * host keeps the `kind` so the presentation can annotate a repr as "this is
991
+ * repr text, not a JSON value".
992
+ * @param name - the exact variable name, or `null` to list namespace names.
993
+ * @param sentinel - per-cell nonce prefix for the outcome envelope.
994
+ * @returns the complete cell source.
995
+ */
996
+ function buildQueryVarCell(name$1, sentinel) {
997
+ const lines = [
998
+ `_dashr_state['executing'] = True`,
999
+ `try:`,
1000
+ ` import json as _dashr_json`,
1001
+ ` _dashr_shell = globals().get('get_ipython', lambda: None)()`,
1002
+ ` _dashr_hidden = getattr(_dashr_shell, 'user_ns_hidden', None) or {}`,
1003
+ ` _dashr_user_ns = {`,
1004
+ ` _name: _value`,
1005
+ ` for _name, _value in globals().items()`,
1006
+ ` if not _name.lower().startswith(('_dashr', '__dashr'))`,
1007
+ ` and (_name not in _dashr_hidden or _dashr_hidden[_name] is not _value)`,
1008
+ ` }`
1009
+ ];
1010
+ if (name$1 === null) lines.push(` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': True, 'kind': 'names', 'names': sorted(_dashr_user_ns)}))`);
1011
+ else lines.push(` _dashr_name = ${JSON.stringify(name$1)}`, ` if _dashr_name not in _dashr_user_ns:`, ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': True, 'kind': 'missing'}))`, ` else:`, ` _dashr_value = _dashr_user_ns[_dashr_name]`, ` try:`, ` _dashr_text = _dashr_json.dumps(_dashr_value, allow_nan=False)`, ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': True, 'kind': 'json', 'text': _dashr_text}))`, ` except (TypeError, ValueError, OverflowError):`, ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': True, 'kind': 'repr', 'text': repr(_dashr_value)}))`);
1012
+ lines.push(`finally:`, ` _dashr_state['executing'] = False`);
1013
+ return lines.join("\n");
1014
+ }
1015
+ /**
1016
+ * Build the internal cell that assigns one JSON value into the user
1017
+ * namespace under `name`. The value is carried as pre-serialized JSON text
1018
+ * (the host validated it as lossless JSON and the name as a usable
1019
+ * identifier), so the cell only decodes and binds — no arbitrary object can
1020
+ * cross the wire. Bracketed by the same SIGALRM busy guard as a run cell.
1021
+ * @param name - the validated identifier to assign under.
1022
+ * @param valueJson - the lossless-JSON text to decode and bind.
1023
+ * @param sentinel - per-cell nonce prefix for the outcome envelope.
1024
+ * @returns the complete cell source.
1025
+ */
1026
+ function buildSetVarCell(name$1, valueJson, sentinel) {
1027
+ return [
1028
+ `_dashr_state['executing'] = True`,
1029
+ `try:`,
1030
+ ` import json as _dashr_json`,
1031
+ ` _dashr_value = _dashr_json.loads(${JSON.stringify(valueJson)})`,
1032
+ ` globals()[${JSON.stringify(name$1)}] = _dashr_value`,
1033
+ ` print(${JSON.stringify(sentinel)} + _dashr_json.dumps({'ok': True}))`,
1034
+ `finally:`,
1035
+ ` _dashr_state['executing'] = False`
1036
+ ].join("\n");
1037
+ }
1038
+
1039
+ //#endregion
1040
+ //#region src/output.ts
1041
+ /** ANSI color escapes, which ipykernel embeds in published tracebacks. */
1042
+ const ANSI_ESCAPE = /\x1b\[[0-9;]*[A-Za-z]/g;
1043
+ /** Smallest cap that can represent an empty logs array plus a quoted message. */
1044
+ const MIN_OUTPUT_BYTES = 4;
1045
+ /**
1046
+ * Split captured stream text into log lines and the completion envelope.
1047
+ * Tolerates a sentinel that landed mid-line after an emission without a
1048
+ * trailing newline (the prefix stays in the logs).
1049
+ * @param streamText - concatenated iopub stream text for one cell.
1050
+ * @param sentinel - per-run nonce prefix of the envelope line.
1051
+ */
1052
+ function extractStream(streamText, sentinel) {
1053
+ const logs = [];
1054
+ let envelope;
1055
+ for (const line of streamText.split("\n")) {
1056
+ const at = line.indexOf(sentinel);
1057
+ if (at === -1) {
1058
+ logs.push(line);
1059
+ continue;
1060
+ }
1061
+ if (at > 0) logs.push(line.slice(0, at));
1062
+ envelope = line.slice(at + sentinel.length);
1063
+ }
1064
+ if (logs.length > 0 && logs.at(-1) === "") logs.pop();
1065
+ return {
1066
+ logs,
1067
+ envelope: envelope === "" ? void 0 : envelope
1068
+ };
1069
+ }
1070
+ /** Strip ANSI escapes from an ipykernel traceback for a model-facing message. */
1071
+ function plainTraceback(ename, evalue, traceback) {
1072
+ const body = traceback.map((line) => line.replace(ANSI_ESCAPE, "")).join("\n");
1073
+ return body.length > 0 ? `${ename}: ${evalue}\n${body}` : `${ename}: ${evalue}`;
1074
+ }
1075
+ function byteLength(text) {
1076
+ return Buffer.byteLength(text, "utf8");
1077
+ }
1078
+ /** Serialized size of the counted payloads: logs array, value, failure message. */
1079
+ function payloadBytes(logs, value, errorMessage) {
1080
+ let total = 2;
1081
+ for (const [i, text] of logs.entries()) total += (i > 0 ? 1 : 0) + byteLength(JSON.stringify(text));
1082
+ if (value !== void 0) total += byteLength(JSON.stringify(value));
1083
+ if (errorMessage !== void 0) total += byteLength(JSON.stringify(errorMessage));
1084
+ return total;
1085
+ }
1086
+ /**
1087
+ * Apply the outer-output ledger: admit the result when the combined serialized
1088
+ * payloads fit, otherwise retain a fitting log prefix and report an explicit
1089
+ * `output-limit` failure. Conservative accounting — it may underuse the cap,
1090
+ * never exceed it.
1091
+ * @param logs - captured emission lines.
1092
+ * @param value - the completion value, when one crossed the JSON boundary.
1093
+ * @param error - the failure, when the run failed.
1094
+ * @param maxBytes - the configured cap for the combined counted payloads.
1095
+ */
1096
+ function finalizeOutput(logs, value, error, maxBytes) {
1097
+ if (payloadBytes(logs, value, error?.message) <= maxBytes) return {
1098
+ logs,
1099
+ ...value !== void 0 ? { value } : {},
1100
+ ...error ? { error } : {}
1101
+ };
1102
+ const limitMessage = `outer output exceeded ${maxBytes} bytes`;
1103
+ const messageBytes = byteLength(JSON.stringify(limitMessage)) + 4;
1104
+ const budget = Math.max(0, maxBytes - 2 - messageBytes);
1105
+ const retained = [];
1106
+ let used = 0;
1107
+ for (const text of logs) {
1108
+ const serialized = byteLength(JSON.stringify(text));
1109
+ const separator = retained.length > 0 ? 1 : 0;
1110
+ if (used + separator + serialized > budget) break;
1111
+ retained.push(text);
1112
+ used += separator + serialized;
1113
+ }
1114
+ return {
1115
+ logs: retained,
1116
+ error: {
1117
+ kind: "output-limit",
1118
+ message: limitMessage
1119
+ }
1120
+ };
1121
+ }
1122
+
1123
+ //#endregion
1124
+ //#region src/kernel.ts
1125
+ const PROTOCOL_VERSION = "5.3";
1126
+ /** Loopback PUB/SUB subscription propagation guard before the first execute. */
1127
+ const IOPUB_SUBSCRIBE_DELAY_MS = 50;
1128
+ const CONNECT_POLL_MS = 25;
1129
+ const SHUTDOWN_DRAIN_MS = 200;
1130
+ function isRecord(value) {
1131
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1132
+ }
1133
+ function buildMessage(msgType, content, session, username) {
1134
+ return {
1135
+ header: {
1136
+ msg_id: randomUUID(),
1137
+ session,
1138
+ username,
1139
+ date: (/* @__PURE__ */ new Date()).toISOString(),
1140
+ msg_type: msgType,
1141
+ version: PROTOCOL_VERSION
1142
+ },
1143
+ parent_header: {},
1144
+ content
1145
+ };
1146
+ }
1147
+ function makeConnection() {
1148
+ const info = {
1149
+ ip: "127.0.0.1",
1150
+ transport: "tcp",
1151
+ shell_port: 0,
1152
+ iopub_port: 0,
1153
+ stdin_port: 0,
1154
+ control_port: 0,
1155
+ hb_port: 0,
1156
+ signature_scheme: "hmac-sha256",
1157
+ key: randomBytes(16).toString("hex"),
1158
+ kernel_name: "python3"
1159
+ };
1160
+ const tempDir = mkdtempSync(join(tmpdir(), "dashr-kernel-"));
1161
+ const path$1 = join(tempDir, "connection.json");
1162
+ writeFileSync(path$1, JSON.stringify(info, null, 2), { mode: 384 });
1163
+ return {
1164
+ path: path$1,
1165
+ tempDir
1166
+ };
1167
+ }
1168
+ function readResolvedConnection(path$1) {
1169
+ try {
1170
+ const parsed = JSON.parse(readFileSync(path$1, "utf8"));
1171
+ if (!isRecord(parsed) || parsed.ip !== "127.0.0.1" || parsed.transport !== "tcp" || parsed.signature_scheme !== "hmac-sha256" || typeof parsed.key !== "string") return null;
1172
+ for (const port of [
1173
+ "shell_port",
1174
+ "iopub_port",
1175
+ "stdin_port",
1176
+ "control_port",
1177
+ "hb_port"
1178
+ ]) {
1179
+ const value = parsed[port];
1180
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) return null;
1181
+ }
1182
+ return parsed;
1183
+ } catch {
1184
+ return null;
1185
+ }
1186
+ }
1187
+ /**
1188
+ * One persistent IPython kernel subprocess with its ZeroMQ channels. Cell
1189
+ * execution is serialized on an internal queue (the Jupyter shell channel is
1190
+ * request/reply).
1191
+ */
1192
+ var IpyKernelBridge = class {
1193
+ session = randomUUID();
1194
+ state = "idle";
1195
+ startPromise;
1196
+ kernel;
1197
+ transport;
1198
+ connection;
1199
+ tempDir;
1200
+ kernelStderr = "";
1201
+ executionQueue = Promise.resolve();
1202
+ activeExec;
1203
+ commTargets = /* @__PURE__ */ new Map();
1204
+ servedComms = /* @__PURE__ */ new Set();
1205
+ constructor(options) {
1206
+ this.options = options;
1207
+ }
1208
+ /** The kernel subprocess pid, for lifecycle assertions; absent before spawn. */
1209
+ get pid() {
1210
+ return this.kernel?.pid;
1211
+ }
1212
+ get isRunning() {
1213
+ return this.state === "running";
1214
+ }
1215
+ /**
1216
+ * Whether the subprocess is gone (crashed or disposed). A dead bridge is
1217
+ * never resurrected — the owning provider replaces it with a fresh one
1218
+ * (respawn, M3-A), because kernel state is unrecoverable in-process.
1219
+ */
1220
+ get isDead() {
1221
+ return this.state === "shutdown";
1222
+ }
1223
+ /**
1224
+ * Start the kernel (idempotent; concurrent callers share one startup).
1225
+ * @throws when the subprocess cannot spawn, ports never resolve, the
1226
+ * kernel_info probe times out, or the bootstrap cell fails.
1227
+ */
1228
+ async start() {
1229
+ if (!this.startPromise) this.startPromise = this.doStart().catch((error) => {
1230
+ this.startPromise = void 0;
1231
+ throw error;
1232
+ });
1233
+ return this.startPromise;
1234
+ }
1235
+ stderrTail() {
1236
+ return this.kernelStderr.slice(-1024) || "(empty)";
1237
+ }
1238
+ async doStart() {
1239
+ if (this.state !== "idle") return;
1240
+ this.state = "starting";
1241
+ const { path: path$1, tempDir } = makeConnection();
1242
+ this.tempDir = tempDir;
1243
+ const kernel = spawn(this.options.python, [
1244
+ "-m",
1245
+ "ipykernel_launcher",
1246
+ "-f",
1247
+ path$1
1248
+ ], {
1249
+ cwd: this.options.cwd,
1250
+ env: {
1251
+ PATH: process.env.PATH ?? "/usr/local/bin:/usr/bin:/bin",
1252
+ LANG: "C.UTF-8",
1253
+ HOME: process.env.HOME ?? tmpdir()
1254
+ },
1255
+ stdio: [
1256
+ "ignore",
1257
+ "pipe",
1258
+ "pipe"
1259
+ ]
1260
+ });
1261
+ this.kernel = kernel;
1262
+ kernel.stderr?.on("data", (buf) => {
1263
+ this.kernelStderr += buf.toString();
1264
+ });
1265
+ kernel.on("error", (error) => {
1266
+ this.kernelStderr += `spawn error: ${error.message}\n`;
1267
+ this.onKernelDeath();
1268
+ });
1269
+ kernel.on("exit", (code, signal) => {
1270
+ if (this.state !== "shutdown") this.kernelStderr += `unexpected exit code=${code} signal=${signal}\n`;
1271
+ this.onKernelDeath();
1272
+ });
1273
+ let conn;
1274
+ try {
1275
+ conn = await this.waitForConnection(path$1);
1276
+ this.connection = conn;
1277
+ } catch (error) {
1278
+ this.cleanupResources();
1279
+ this.state = "idle";
1280
+ throw error;
1281
+ }
1282
+ const transport = new KernelTransport({
1283
+ python: this.options.python,
1284
+ connectionFile: path$1,
1285
+ ...this.options.cwd === void 0 ? {} : { cwd: this.options.cwd },
1286
+ readyTimeoutMs: this.options.startupTimeoutMs
1287
+ });
1288
+ this.transport = transport;
1289
+ transport.onMessage((channel, message) => {
1290
+ this.handleTransportMessage(channel, message);
1291
+ });
1292
+ transport.onExit(() => {
1293
+ if (this.state !== "shutdown") this.forceSettleActive({
1294
+ kind: "worker-exit",
1295
+ message: `kernel bridge died. stderr tail:\n${transport.stderrTail()}`
1296
+ });
1297
+ });
1298
+ try {
1299
+ await transport.start();
1300
+ } catch (error) {
1301
+ this.cleanupResources();
1302
+ this.state = "idle";
1303
+ throw error;
1304
+ }
1305
+ await setTimeout$1(IOPUB_SUBSCRIBE_DELAY_MS);
1306
+ try {
1307
+ await this.probeReady();
1308
+ } catch (error) {
1309
+ this.cleanupResources();
1310
+ this.state = "idle";
1311
+ throw error;
1312
+ }
1313
+ const bootstrap = await this.executeCell(KERNEL_BOOTSTRAP, {
1314
+ timeoutMs: this.options.startupTimeoutMs,
1315
+ interruptGraceMs: 1e3,
1316
+ interruptConfirmMs: Math.min(this.options.interruptConfirmMs, 500)
1317
+ });
1318
+ if (bootstrap.outcome !== "completed" || bootstrap.status !== "ok") {
1319
+ const detail = bootstrap.outcome === "completed" && bootstrap.cellError ? `${bootstrap.cellError.ename}: ${bootstrap.cellError.evalue}` : "bootstrap cell failed";
1320
+ this.cleanupResources();
1321
+ this.state = "idle";
1322
+ throw new Error(`dashr kernel bootstrap failed: ${detail}`);
1323
+ }
1324
+ this.state = "running";
1325
+ }
1326
+ async waitForConnection(path$1) {
1327
+ const deadline = Date.now() + this.options.startupTimeoutMs;
1328
+ while (Date.now() < deadline) {
1329
+ if (this.state === "shutdown") throw new Error(`kernel exited before resolving ports. stderr:\n${this.stderrTail()}`);
1330
+ const info = readResolvedConnection(path$1);
1331
+ if (info) return info;
1332
+ await setTimeout$1(CONNECT_POLL_MS);
1333
+ }
1334
+ throw new Error(`kernel did not resolve connection ports within ${this.options.startupTimeoutMs}ms. stderr tail:\n${this.stderrTail()}`);
1335
+ }
1336
+ async probeReady() {
1337
+ const transport = this.transport;
1338
+ if (!transport) throw new Error("kernel channels are not connected");
1339
+ const msg = buildMessage("kernel_info_request", {}, this.session, this.options.username);
1340
+ const requestMsgId = msg.header.msg_id;
1341
+ transport.send("shell", msg);
1342
+ if (await transport.waitFor("shell", (incoming) => incoming.header.msg_type === "kernel_info_reply" && incoming.parent_header.msg_id === requestMsgId, this.options.startupTimeoutMs)) return;
1343
+ const bridgeTail = transport.stderrTail();
1344
+ if (this.state === "shutdown") throw new Error(`kernel exited during startup. kernel stderr:\n${this.stderrTail()}\nbridge stderr:\n${bridgeTail}`);
1345
+ throw new Error(`kernel did not answer kernel_info_request within ${this.options.startupTimeoutMs}ms. kernel stderr:\n${this.stderrTail()}\nbridge stderr:\n${bridgeTail}`);
1346
+ }
1347
+ /**
1348
+ * Execute one cell on the persistent kernel, serialized against all other
1349
+ * executions. Resolves with the cell's outcome — never rejects for
1350
+ * cell-level failures (program errors, timeouts, aborts, kernel death).
1351
+ * @param code - complete cell source.
1352
+ * @param opts - budgets, abort signal, and the host-request dispatcher.
1353
+ */
1354
+ async executeCell(code, opts) {
1355
+ const prev = this.executionQueue;
1356
+ let releaseQueue;
1357
+ this.executionQueue = new Promise((resolve$1) => {
1358
+ releaseQueue = resolve$1;
1359
+ });
1360
+ await prev;
1361
+ try {
1362
+ if (this.state === "shutdown" || this.state === "idle") return {
1363
+ outcome: "forced",
1364
+ failure: {
1365
+ kind: "worker-exit",
1366
+ message: "kernel has been shut down"
1367
+ },
1368
+ streamText: ""
1369
+ };
1370
+ return await this.executeInner(code, opts);
1371
+ } finally {
1372
+ releaseQueue();
1373
+ }
1374
+ }
1375
+ executeInner(code, opts) {
1376
+ const transport = this.transport;
1377
+ if (!transport) return Promise.resolve({
1378
+ outcome: "forced",
1379
+ failure: {
1380
+ kind: "worker-exit",
1381
+ message: "kernel channels are not connected"
1382
+ },
1383
+ streamText: ""
1384
+ });
1385
+ const msg = buildMessage("execute_request", {
1386
+ code,
1387
+ silent: false,
1388
+ store_history: false,
1389
+ user_expressions: {},
1390
+ allow_stdin: false,
1391
+ stop_on_error: true
1392
+ }, this.session, this.options.username);
1393
+ return new Promise((resolve$1) => {
1394
+ const execution = {
1395
+ requestMsgId: msg.header.msg_id,
1396
+ opts,
1397
+ streamText: "",
1398
+ status: "ok",
1399
+ settled: false,
1400
+ resolve: resolve$1
1401
+ };
1402
+ this.activeExec = execution;
1403
+ const settle = (outcome) => {
1404
+ if (execution.settled) return;
1405
+ execution.settled = true;
1406
+ if (execution.forceTimer) clearTimeout(execution.forceTimer);
1407
+ if (execution.timeoutTimer) clearTimeout(execution.timeoutTimer);
1408
+ if (execution.alarmTimer) clearTimeout(execution.alarmTimer);
1409
+ execution.detachSignal?.();
1410
+ if (this.activeExec === execution) this.activeExec = void 0;
1411
+ resolve$1(outcome);
1412
+ };
1413
+ const interruptAndForce = (failure) => {
1414
+ if (this.activeExec !== execution) return;
1415
+ if (execution.pendingForce === void 0) execution.pendingForce = failure;
1416
+ this.sendInterrupt(execution);
1417
+ execution.forceTimer = setTimeout(() => {
1418
+ settle({
1419
+ outcome: "forced",
1420
+ failure,
1421
+ streamText: execution.streamText
1422
+ });
1423
+ }, opts.interruptGraceMs);
1424
+ execution.forceTimer.unref?.();
1425
+ };
1426
+ const onAbort = () => {
1427
+ interruptAndForce({
1428
+ kind: "abort",
1429
+ message: String(opts.signal?.reason)
1430
+ });
1431
+ };
1432
+ execution.timeoutTimer = setTimeout(() => {
1433
+ interruptAndForce({
1434
+ kind: "timeout",
1435
+ message: `cell exceeded ${opts.timeoutMs}ms wall budget`
1436
+ });
1437
+ }, opts.timeoutMs);
1438
+ execution.timeoutTimer.unref?.();
1439
+ opts.signal?.addEventListener("abort", onAbort, { once: true });
1440
+ execution.detachSignal = () => opts.signal?.removeEventListener("abort", onAbort);
1441
+ if (opts.signal?.aborted) onAbort();
1442
+ try {
1443
+ transport.send("shell", msg);
1444
+ } catch {
1445
+ settle({
1446
+ outcome: "forced",
1447
+ failure: {
1448
+ kind: "worker-exit",
1449
+ message: "shell channel send failed"
1450
+ },
1451
+ streamText: execution.streamText
1452
+ });
1453
+ }
1454
+ });
1455
+ }
1456
+ /**
1457
+ * Route one relayed message. Only iopub drives executions and comms; shell
1458
+ * replies serve the startup probe (via `waitFor`), and control is inbound
1459
+ * for host replies.
1460
+ */
1461
+ handleTransportMessage(channel, incoming) {
1462
+ if (channel !== "iopub") return;
1463
+ const msgType = incoming.header.msg_type;
1464
+ if (msgType === "comm_open" || msgType === "comm_msg" || msgType === "comm_close") {
1465
+ this.handleCommMessage(incoming);
1466
+ return;
1467
+ }
1468
+ this.handleExecutionMessage(incoming);
1469
+ }
1470
+ forceSettleActive(failure) {
1471
+ const execution = this.activeExec;
1472
+ if (!execution || execution.settled) return;
1473
+ execution.settled = true;
1474
+ if (execution.forceTimer) clearTimeout(execution.forceTimer);
1475
+ if (execution.timeoutTimer) clearTimeout(execution.timeoutTimer);
1476
+ if (execution.alarmTimer) clearTimeout(execution.alarmTimer);
1477
+ execution.detachSignal?.();
1478
+ this.activeExec = void 0;
1479
+ execution.resolve({
1480
+ outcome: "forced",
1481
+ failure,
1482
+ streamText: execution.streamText
1483
+ });
1484
+ }
1485
+ handleExecutionMessage(incoming) {
1486
+ const execution = this.activeExec;
1487
+ if (!execution || execution.settled) return;
1488
+ if (incoming.parent_header.msg_id !== execution.requestMsgId) return;
1489
+ const msgType = incoming.header.msg_type;
1490
+ if (msgType === "stream") {
1491
+ const content = incoming.content;
1492
+ if (typeof content.text === "string") execution.streamText += content.text;
1493
+ } else if (msgType === "error") {
1494
+ const content = incoming.content;
1495
+ execution.cellError = {
1496
+ ename: typeof content.ename === "string" ? content.ename : "Error",
1497
+ evalue: typeof content.evalue === "string" ? content.evalue : "",
1498
+ traceback: Array.isArray(content.traceback) ? content.traceback : []
1499
+ };
1500
+ execution.status = "error";
1501
+ } else if (msgType === "status") {
1502
+ if (incoming.content.execution_state === "idle") this.settleCompleted(execution);
1503
+ }
1504
+ }
1505
+ settleCompleted(execution) {
1506
+ if (execution.settled) return;
1507
+ execution.settled = true;
1508
+ if (execution.forceTimer) clearTimeout(execution.forceTimer);
1509
+ if (execution.timeoutTimer) clearTimeout(execution.timeoutTimer);
1510
+ if (execution.alarmTimer) clearTimeout(execution.alarmTimer);
1511
+ execution.detachSignal?.();
1512
+ if (this.activeExec === execution) this.activeExec = void 0;
1513
+ if (execution.pendingForce !== void 0) {
1514
+ execution.resolve({
1515
+ outcome: "forced",
1516
+ failure: execution.pendingForce,
1517
+ streamText: execution.streamText
1518
+ });
1519
+ return;
1520
+ }
1521
+ execution.resolve({
1522
+ outcome: "completed",
1523
+ status: execution.status,
1524
+ streamText: execution.streamText,
1525
+ ...execution.cellError ? { cellError: execution.cellError } : {}
1526
+ });
1527
+ }
1528
+ handleCommMessage(incoming) {
1529
+ const content = incoming.content;
1530
+ const commId = content.comm_id;
1531
+ if (typeof commId !== "string") return;
1532
+ const msgType = incoming.header.msg_type;
1533
+ if (msgType === "comm_close") {
1534
+ this.commTargets.delete(commId);
1535
+ this.servedComms.delete(commId);
1536
+ return;
1537
+ }
1538
+ if (msgType === "comm_open") {
1539
+ const targetName = content.target_name;
1540
+ if (typeof targetName === "string") this.commTargets.set(commId, targetName);
1541
+ return;
1542
+ }
1543
+ if (msgType === "comm_msg" && this.commTargets.get(commId) === HOST_COMM_TARGET) this.serveHostRequest(commId, content.data);
1544
+ }
1545
+ serveHostRequest(commId, data) {
1546
+ if (this.servedComms.has(commId)) return;
1547
+ this.servedComms.add(commId);
1548
+ const handler = this.activeExec?.opts.hostRequestHandler;
1549
+ if (!handler) {
1550
+ this.replyComm(commId, {
1551
+ status: "error",
1552
+ error: "no host request handler is active"
1553
+ }).catch(() => void 0);
1554
+ return;
1555
+ }
1556
+ if (!isRecord(data)) {
1557
+ this.replyComm(commId, {
1558
+ status: "error",
1559
+ error: "host request payload must be an object"
1560
+ }).catch(() => void 0);
1561
+ return;
1562
+ }
1563
+ (async () => {
1564
+ try {
1565
+ const outcome = await handler(data);
1566
+ if (outcome.ok) await this.replyComm(commId, {
1567
+ status: "ok",
1568
+ result: outcome.result
1569
+ });
1570
+ else await this.replyComm(commId, {
1571
+ status: "error",
1572
+ error: outcome.message
1573
+ });
1574
+ } catch (error) {
1575
+ const message = error instanceof Error ? error.message : String(error);
1576
+ await this.replyComm(commId, {
1577
+ status: "error",
1578
+ error: message
1579
+ }).catch(() => void 0);
1580
+ }
1581
+ })().catch(() => void 0);
1582
+ }
1583
+ async replyComm(commId, data) {
1584
+ const transport = this.transport;
1585
+ if (!transport) throw new Error("kernel channels are not connected");
1586
+ transport.send("control", buildMessage("comm_msg", {
1587
+ comm_id: commId,
1588
+ data
1589
+ }, this.session, this.options.username));
1590
+ }
1591
+ /**
1592
+ * Phase one NOW, phase two on a timer: send the control-channel interrupt,
1593
+ * then — after the confirm window, and only if the execution has still not
1594
+ * settled — escalate to SIGALRM. The zmq interrupt only lands when the cell
1595
+ * yields to the kernel event loop; a busy sync cell ('while True: pass')
1596
+ * never does, which is why the escalation exists at all. Sending both
1597
+ * channels in the same tick (the M1 design) made SIGALRM the FIRST signal
1598
+ * an idle-or-booting kernel saw on timeout/abort: its handler raised
1599
+ * KeyboardInterrupt at the top level and the process exited cleanly — a
1600
+ * deterministic kill (10/10 same-tick aborts, 8/10 at +1-2ms, 40/40 during
1601
+ * cold boot; dev/m2a-report.md §5.1). Two-phase escalation plus the
1602
+ * kernel-side busy guard closes that window while keeping the hard-abort
1603
+ * contract: a busy loop still breaks, one confirm window later.
1604
+ */
1605
+ async sendInterrupt(execution) {
1606
+ const transport = this.transport;
1607
+ if (!transport) return;
1608
+ try {
1609
+ transport.interrupt();
1610
+ } catch {}
1611
+ execution.alarmTimer = setTimeout(() => {
1612
+ if (execution.settled) return;
1613
+ if (this.kernel?.exitCode === null) try {
1614
+ this.kernel.kill("SIGALRM");
1615
+ } catch {}
1616
+ }, execution.opts.interruptConfirmMs);
1617
+ execution.alarmTimer.unref?.();
1618
+ }
1619
+ /**
1620
+ * Snapshot the user namespace via an internal dill cell. Requires `dill` in
1621
+ * the kernel environment. The cell reports its outcome through a nonce
1622
+ * envelope (skipped-for-size vs written); a failed/skipped dump NEVER
1623
+ * replaces a previous good snapshot on disk.
1624
+ * @param payloadPath - dill payload destination.
1625
+ * @param manifestPath - JSON manifest destination (turn, names, python
1626
+ * version, venv path, skills, size).
1627
+ * @param spec - turn counter, skills list, and the size cap.
1628
+ */
1629
+ async snapshotState(payloadPath, manifestPath, spec) {
1630
+ if (!this.isRunning) return {
1631
+ kind: "failed",
1632
+ reason: "kernel is not running"
1633
+ };
1634
+ const sentinel = `__dashr_snapshot_${randomBytes(9).toString("hex")}__`;
1635
+ const outcome = await this.executeCell(buildSnapshotCell(payloadPath, manifestPath, spec, sentinel), {
1636
+ timeoutMs: this.options.snapshotTimeoutMs,
1637
+ interruptGraceMs: 1e3,
1638
+ interruptConfirmMs: Math.min(this.options.interruptConfirmMs, 500)
1639
+ });
1640
+ if (outcome.outcome !== "completed" || outcome.status !== "ok") return {
1641
+ kind: "failed",
1642
+ reason: "snapshot cell failed"
1643
+ };
1644
+ return this.parseSnapshotEnvelope(outcome.streamText, sentinel);
1645
+ }
1646
+ /** Parse one snapshot cell's nonce envelope into its outcome. */
1647
+ parseSnapshotEnvelope(streamText, sentinel) {
1648
+ const capture = extractStream(streamText, sentinel);
1649
+ if (capture.envelope === void 0) return {
1650
+ kind: "failed",
1651
+ reason: "snapshot cell produced no envelope"
1652
+ };
1653
+ let envelope;
1654
+ try {
1655
+ envelope = JSON.parse(capture.envelope);
1656
+ } catch {
1657
+ return {
1658
+ kind: "failed",
1659
+ reason: "snapshot envelope was not valid JSON"
1660
+ };
1661
+ }
1662
+ if (typeof envelope !== "object" || envelope === null) return {
1663
+ kind: "failed",
1664
+ reason: "snapshot envelope was not an object"
1665
+ };
1666
+ const record = envelope;
1667
+ if (record.ok === true) return {
1668
+ kind: "ok",
1669
+ sizeBytes: typeof record.sizeBytes === "number" ? record.sizeBytes : 0,
1670
+ names: typeof record.names === "number" ? record.names : 0
1671
+ };
1672
+ if (record.skipped === true) return {
1673
+ kind: "skipped",
1674
+ reason: typeof record.reason === "string" ? record.reason : "size cap",
1675
+ ...typeof record.estimateBytes === "number" ? { estimateBytes: record.estimateBytes } : {},
1676
+ ...typeof record.sizeBytes === "number" ? { sizeBytes: record.sizeBytes } : {},
1677
+ capBytes: typeof record.capBytes === "number" ? record.capBytes : 0
1678
+ };
1679
+ return {
1680
+ kind: "failed",
1681
+ reason: typeof record.reason === "string" ? record.reason : "snapshot failed"
1682
+ };
1683
+ }
1684
+ /**
1685
+ * Restore a dill snapshot into the user namespace via an internal cell. The
1686
+ * kernel validates the manifest (python version, interpreter identity,
1687
+ * skills) and reports restored vs degraded through a nonce envelope; a
1688
+ * degraded restore leaves the namespace empty.
1689
+ * @param payloadPath - dill payload source.
1690
+ * @param manifestPath - JSON manifest source.
1691
+ */
1692
+ async restoreState(payloadPath, manifestPath) {
1693
+ if (!this.isRunning) return {
1694
+ kind: "degraded",
1695
+ reason: "kernel is not running"
1696
+ };
1697
+ const sentinel = `__dashr_restore_${randomBytes(9).toString("hex")}__`;
1698
+ const outcome = await this.executeCell(buildRestoreCell(payloadPath, manifestPath, sentinel), {
1699
+ timeoutMs: this.options.snapshotTimeoutMs,
1700
+ interruptGraceMs: 1e3,
1701
+ interruptConfirmMs: Math.min(this.options.interruptConfirmMs, 500)
1702
+ });
1703
+ if (outcome.outcome !== "completed" || outcome.status !== "ok") return {
1704
+ kind: "degraded",
1705
+ reason: "restore cell failed"
1706
+ };
1707
+ const capture = extractStream(outcome.streamText, sentinel);
1708
+ if (capture.envelope === void 0) return {
1709
+ kind: "degraded",
1710
+ reason: "restore cell produced no envelope"
1711
+ };
1712
+ let envelope;
1713
+ try {
1714
+ envelope = JSON.parse(capture.envelope);
1715
+ } catch {
1716
+ return {
1717
+ kind: "degraded",
1718
+ reason: "restore envelope was not valid JSON"
1719
+ };
1720
+ }
1721
+ if (typeof envelope !== "object" || envelope === null) return {
1722
+ kind: "degraded",
1723
+ reason: "restore envelope was not an object"
1724
+ };
1725
+ const record = envelope;
1726
+ if (record.ok === true) return {
1727
+ kind: "restored",
1728
+ count: typeof record.restored === "number" ? record.restored : 0
1729
+ };
1730
+ return {
1731
+ kind: "degraded",
1732
+ reason: typeof record.reason === "string" ? record.reason : "snapshot not replayable"
1733
+ };
1734
+ }
1735
+ /**
1736
+ * Read one user-namespace variable by name (or list the namespace's user
1737
+ * names when `name` is `null`) via an internal cell. JSON-serializable
1738
+ * values cross as `kind: 'json'` text; anything else falls back to `repr`
1739
+ * text (`kind: 'repr'`) so a non-JSON variable is still readable. A missing
1740
+ * name reports `kind: 'missing'` rather than failing the cell.
1741
+ * @param name - the exact variable name, or `null` to list namespace names.
1742
+ */
1743
+ async queryVar(name$1) {
1744
+ if (!this.isRunning) return {
1745
+ kind: "failed",
1746
+ reason: "kernel is not running"
1747
+ };
1748
+ const sentinel = `__dashr_query_${randomBytes(9).toString("hex")}__`;
1749
+ const outcome = await this.executeCell(buildQueryVarCell(name$1, sentinel), {
1750
+ timeoutMs: this.options.snapshotTimeoutMs,
1751
+ interruptGraceMs: 1e3,
1752
+ interruptConfirmMs: Math.min(this.options.interruptConfirmMs, 500)
1753
+ });
1754
+ if (outcome.outcome !== "completed" || outcome.status !== "ok") return {
1755
+ kind: "failed",
1756
+ reason: "query cell failed"
1757
+ };
1758
+ const capture = extractStream(outcome.streamText, sentinel);
1759
+ if (capture.envelope === void 0) return {
1760
+ kind: "failed",
1761
+ reason: "query cell produced no envelope"
1762
+ };
1763
+ let envelope;
1764
+ try {
1765
+ envelope = JSON.parse(capture.envelope);
1766
+ } catch {
1767
+ return {
1768
+ kind: "failed",
1769
+ reason: "query envelope was not valid JSON"
1770
+ };
1771
+ }
1772
+ if (!isRecord(envelope)) return {
1773
+ kind: "failed",
1774
+ reason: "query envelope was not an object"
1775
+ };
1776
+ if (envelope.ok !== true) return {
1777
+ kind: "failed",
1778
+ reason: typeof envelope.reason === "string" ? envelope.reason : "query failed"
1779
+ };
1780
+ const kind = envelope.kind;
1781
+ if (kind === "names") return {
1782
+ kind: "names",
1783
+ names: Array.isArray(envelope.names) ? envelope.names.filter((name$2) => typeof name$2 === "string") : []
1784
+ };
1785
+ if (kind === "missing") return { kind: "missing" };
1786
+ if (kind === "json" || kind === "repr") return typeof envelope.text === "string" ? {
1787
+ kind,
1788
+ text: envelope.text
1789
+ } : {
1790
+ kind: "failed",
1791
+ reason: "query envelope carried no text"
1792
+ };
1793
+ return {
1794
+ kind: "failed",
1795
+ reason: `unknown query kind ${JSON.stringify(kind)}`
1796
+ };
1797
+ }
1798
+ /**
1799
+ * Assign one pre-serialized JSON value into the user namespace under
1800
+ * `name` via an internal cell. The host already validated the name and the
1801
+ * value; the cell only decodes and binds. Uses the same busy guard and
1802
+ * internal-cell budget as the snapshot cells.
1803
+ * @param name - the validated identifier to assign under.
1804
+ * @param valueJson - the lossless-JSON text to decode and bind.
1805
+ */
1806
+ async setVar(name$1, valueJson) {
1807
+ if (!this.isRunning) return {
1808
+ kind: "failed",
1809
+ reason: "kernel is not running"
1810
+ };
1811
+ const sentinel = `__dashr_set_${randomBytes(9).toString("hex")}__`;
1812
+ const outcome = await this.executeCell(buildSetVarCell(name$1, valueJson, sentinel), {
1813
+ timeoutMs: this.options.snapshotTimeoutMs,
1814
+ interruptGraceMs: 1e3,
1815
+ interruptConfirmMs: Math.min(this.options.interruptConfirmMs, 500)
1816
+ });
1817
+ if (outcome.outcome !== "completed" || outcome.status !== "ok") return {
1818
+ kind: "failed",
1819
+ reason: "set cell failed"
1820
+ };
1821
+ const capture = extractStream(outcome.streamText, sentinel);
1822
+ if (capture.envelope === void 0) return {
1823
+ kind: "failed",
1824
+ reason: "set cell produced no envelope"
1825
+ };
1826
+ let envelope;
1827
+ try {
1828
+ envelope = JSON.parse(capture.envelope);
1829
+ } catch {
1830
+ return {
1831
+ kind: "failed",
1832
+ reason: "set envelope was not valid JSON"
1833
+ };
1834
+ }
1835
+ if (!isRecord(envelope) || envelope.ok !== true) return {
1836
+ kind: "failed",
1837
+ reason: isRecord(envelope) && typeof envelope.reason === "string" ? envelope.reason : "set failed"
1838
+ };
1839
+ return { kind: "ok" };
1840
+ }
1841
+ onKernelDeath() {
1842
+ this.state = "shutdown";
1843
+ this.forceSettleActive({
1844
+ kind: "worker-exit",
1845
+ message: `kernel process died. stderr tail:\n${this.stderrTail()}`
1846
+ });
1847
+ this.cleanupResources();
1848
+ }
1849
+ cleanupResources() {
1850
+ this.transport?.dispose();
1851
+ this.transport = void 0;
1852
+ this.connection = void 0;
1853
+ try {
1854
+ this.kernel?.kill("SIGKILL");
1855
+ } catch {}
1856
+ this.kernel = void 0;
1857
+ if (this.tempDir) try {
1858
+ rmSync(this.tempDir, {
1859
+ recursive: true,
1860
+ force: true
1861
+ });
1862
+ } catch {}
1863
+ this.tempDir = void 0;
1864
+ }
1865
+ /** Graceful teardown: shutdown_request, then SIGKILL after the dispose budget. */
1866
+ async dispose() {
1867
+ if (this.state === "shutdown") {
1868
+ this.cleanupResources();
1869
+ return;
1870
+ }
1871
+ this.state = "shutdown";
1872
+ try {
1873
+ if (this.transport) {
1874
+ this.transport.send("control", buildMessage("shutdown_request", { restart: false }, this.session, this.options.username));
1875
+ await setTimeout$1(SHUTDOWN_DRAIN_MS);
1876
+ }
1877
+ } catch {}
1878
+ const kernel = this.kernel;
1879
+ this.cleanupResources();
1880
+ if (kernel && kernel.exitCode === null && kernel.signalCode === null) await new Promise((resolve$1) => {
1881
+ const timer = setTimeout(() => {
1882
+ kernel.removeListener("exit", onExit);
1883
+ try {
1884
+ kernel.kill("SIGKILL");
1885
+ } catch {}
1886
+ resolve$1();
1887
+ }, this.options.disposeTimeoutMs);
1888
+ timer.unref?.();
1889
+ const onExit = () => {
1890
+ clearTimeout(timer);
1891
+ resolve$1();
1892
+ };
1893
+ kernel.once("exit", onExit);
1894
+ });
1895
+ }
1896
+ };
1897
+
1898
+ //#endregion
1899
+ //#region src/runtime.ts
1900
+ const IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
1901
+ /**
1902
+ * Names the kernel-side shim owns (`_dashr`/`__dashr` prefixed, any case —
1903
+ * bootstrap helpers plus the per-run `__dashr_completion__` and
1904
+ * `__dashr_injected__`), refused as binding globals on top of the seam's
1905
+ * shared set.
1906
+ */
1907
+ const KERNEL_OWNED_NAME = /^_+dashr/i;
1908
+ /** Manifest format version; a snapshot written under a different version is not replayable. */
1909
+ const SNAPSHOT_FORMAT = 1;
1910
+ function messageOf(error) {
1911
+ return error instanceof Error ? error.message : String(error);
1912
+ }
1913
+ /** Key under which the per-session kernel map stores agentless runs. */
1914
+ const AGENTLESS_KEY = "(agentless)";
1915
+ /**
1916
+ * Encode one principal as a single path segment for its per-key snapshot
1917
+ * subdirectory: `encodeURIComponent` neutralizes separators and traversal,
1918
+ * and a leading run of dots (which would encode to itself, addressing `.` or
1919
+ * `..`) is re-escaped so every key lands strictly inside `snapshotDir`.
1920
+ */
1921
+ function keyDirectoryName(principal) {
1922
+ return encodeURIComponent(principal).replace(/^\.+/, (dots) => dots.replace(/\./g, "%2E"));
1923
+ }
1924
+ /**
1925
+ * The {@link ReplRuntime} backend this package registers (`ctx.replRuntime`)
1926
+ * — the standing-mount layer of the v0.1.5 architecture, the de facto daemon
1927
+ * while the profile-level DashrDaemon stays an empty shell. One service
1928
+ * instance per mount holds one lazily-spawned kernel per session principal;
1929
+ * each kernel's lifecycle — snapshot and shutdown on session end, snapshot
1930
+ * and shutdown of every key on plugin disposal — is effect-owned.
1931
+ */
1932
+ var DashrRuntime = class extends ReplRuntime {
1933
+ static Config = Schema.object({
1934
+ python: Schema.string().default("python3"),
1935
+ startupTimeoutMs: Schema.number().default(3e4),
1936
+ runTimeoutMs: Schema.number().default(12e4),
1937
+ interruptGraceMs: Schema.number().default(2e3),
1938
+ interruptConfirmMs: Schema.number().default(250),
1939
+ disposeTimeoutMs: Schema.number().default(5e3),
1940
+ snapshotTimeoutMs: Schema.number().default(3e4),
1941
+ maxOutputBytes: Schema.number().default(67108864),
1942
+ snapshotDir: Schema.string(),
1943
+ snapshotSizeCapBytes: Schema.number().default(268435456),
1944
+ kernelEnvDir: Schema.string(),
1945
+ kernelPythonVersion: Schema.string(),
1946
+ kernelAutoInstall: Schema.boolean().default(true),
1947
+ username: Schema.string().default("dashr")
1948
+ });
1949
+ language = "python";
1950
+ isolation = "process";
1951
+ config;
1952
+ logger;
1953
+ /** One entry per session principal that has run code (lazy — never pre-seeded). */
1954
+ kernels = /* @__PURE__ */ new Map();
1955
+ disposed = false;
1956
+ /** Lazily-resolved (and, when managed, provisioned) kernel interpreter. */
1957
+ kernelEnvPromise;
1958
+ constructor(ctx, config) {
1959
+ super(ctx);
1960
+ this.config = config;
1961
+ for (const key of [
1962
+ "startupTimeoutMs",
1963
+ "runTimeoutMs",
1964
+ "interruptGraceMs",
1965
+ "disposeTimeoutMs",
1966
+ "snapshotTimeoutMs"
1967
+ ]) {
1968
+ const value = this.config[key];
1969
+ if (!(Number.isFinite(value) && value > 0)) throw new Error(`dashr-repl: config.${key} must be a positive number, got ${String(value)}`);
1970
+ }
1971
+ if (!(this.config.interruptConfirmMs > 0 && this.config.interruptConfirmMs < this.config.interruptGraceMs)) throw new Error(`dashr-repl: config.interruptConfirmMs must be positive and below interruptGraceMs (${this.config.interruptGraceMs}), got ${String(this.config.interruptConfirmMs)}`);
1972
+ if (!Number.isSafeInteger(this.config.maxOutputBytes) || this.config.maxOutputBytes < MIN_OUTPUT_BYTES) throw new Error(`dashr-repl: config.maxOutputBytes must be a safe integer of at least ${MIN_OUTPUT_BYTES}, got ${String(this.config.maxOutputBytes)}`);
1973
+ if (!Number.isSafeInteger(this.config.snapshotSizeCapBytes) || this.config.snapshotSizeCapBytes < 1) throw new Error(`dashr-repl: config.snapshotSizeCapBytes must be a positive safe integer, got ${String(this.config.snapshotSizeCapBytes)}`);
1974
+ this.logger = ctx.logger("dashr-repl");
1975
+ ctx.effect(() => () => this.teardown(), "eval code-runtime teardown");
1976
+ ctx.events.on("agent/disposed", (payload) => {
1977
+ const principal = payload?.agent?.id;
1978
+ if (typeof principal === "string" && principal.length > 0) this.destroyKey(principal).catch(() => void 0);
1979
+ });
1980
+ }
1981
+ /**
1982
+ * The agentless-default kernel's pid, for lifecycle diagnostics; absent
1983
+ * before the first agentless run. Per-session pids: {@link kernelPids}.
1984
+ */
1985
+ get kernelPid() {
1986
+ return this.kernels.get(AGENTLESS_KEY)?.bridge.pid;
1987
+ }
1988
+ /** Every live kernel subprocess pid, one per session that has run code. */
1989
+ get kernelPids() {
1990
+ return [...this.kernels.values()].map((entry) => entry.bridge.pid).filter((pid) => pid !== void 0);
1991
+ }
1992
+ /**
1993
+ * Execute one program as one cell on the persistent kernel. Program
1994
+ * outcomes — including kernel startup failure — resolve with
1995
+ * `result.error`; the method rejects only for Service Definition contract
1996
+ * misuse (a disposed runtime, an invalid binding namespace).
1997
+ * @param request - the program, its bindings, and the abort signal.
1998
+ * @returns the run's outcome per the seam contract.
1999
+ */
2000
+ async run(request) {
2001
+ if (this.disposed) throw new Error("dashr-repl: run() after disposal");
2002
+ const bindings = this.validateBindings(request);
2003
+ if (request.signal?.aborted) return {
2004
+ logs: [],
2005
+ error: {
2006
+ kind: "abort",
2007
+ message: String(request.signal.reason)
2008
+ }
2009
+ };
2010
+ const key = request.principal && request.principal.length > 0 ? request.principal : AGENTLESS_KEY;
2011
+ if (request.reset) await this.resetKey(key);
2012
+ const dead = this.kernels.get(key);
2013
+ if (dead?.bridge.isDead) {
2014
+ this.kernels.delete(key);
2015
+ if (dead.ranCells) return await this.reviveAfterDeath(key, dead);
2016
+ }
2017
+ let entry;
2018
+ try {
2019
+ entry = await this.ensureKernel(key, request.cwd);
2020
+ } catch (error) {
2021
+ return finalizeOutput([], void 0, {
2022
+ kind: "worker-exit",
2023
+ message: `kernel failed to start: ${messageOf(error)}`
2024
+ }, this.config.maxOutputBytes);
2025
+ }
2026
+ if (!entry.restoreAttempted) {
2027
+ entry.restoreAttempted = true;
2028
+ const restore = await this.restoreEntry(entry);
2029
+ if (restore.kind === "restored") entry.pendingNotice = `namespace restored from the turn-${restore.turn} snapshot`;
2030
+ else if (restore.kind === "degraded") entry.pendingNotice = `snapshot not replayable (${restore.reason}); started from an EMPTY namespace — re-create any state you need`;
2031
+ }
2032
+ const kernel = entry.bridge;
2033
+ const specs = Object.fromEntries([...bindings.entries()].map(([global, namespace]) => [global, {
2034
+ functions: Object.keys(namespace.functions),
2035
+ ...namespace.callable ? { callable: true } : {},
2036
+ ...namespace.errorClass ? { errorClass: namespace.errorClass } : {}
2037
+ }]));
2038
+ const sentinel = `__dashr_${randomBytes(9).toString("hex")}__`;
2039
+ const cell = buildRunCell(request.program, JSON.stringify(specs), sentinel);
2040
+ const outcome = await kernel.executeCell(cell, {
2041
+ timeoutMs: request.timeoutMs ?? this.config.runTimeoutMs,
2042
+ interruptGraceMs: this.config.interruptGraceMs,
2043
+ interruptConfirmMs: this.config.interruptConfirmMs,
2044
+ ...request.signal ? { signal: request.signal } : {},
2045
+ hostRequestHandler: (data) => this.dispatchHostRequest(data, bindings)
2046
+ });
2047
+ if (outcome.outcome === "completed") {
2048
+ entry.ranCells = true;
2049
+ entry.turn += 1;
2050
+ } else if (outcome.outcome === "forced" && outcome.failure.kind === "worker-exit" && kernel.isDead && !this.disposed) {
2051
+ if (this.kernels.get(key) === entry) this.kernels.delete(key);
2052
+ if (entry.ranCells) return await this.reviveAfterDeath(key, entry);
2053
+ }
2054
+ let result = this.assembleResult(outcome, sentinel);
2055
+ if (outcome.outcome === "completed") {
2056
+ const snapshot = await this.snapshotTurnEnd(entry);
2057
+ const notices = [];
2058
+ if (snapshot.skipped && !entry.warnedSnapshotSkip) {
2059
+ entry.warnedSnapshotSkip = true;
2060
+ const detail = snapshot.estimateBytes !== void 0 ? `estimated ${snapshot.estimateBytes} bytes` : `${snapshot.sizeBytes ?? "unknown"} bytes serialized`;
2061
+ notices.push(`[dashr] namespace snapshot skipped: ${detail} exceeds snapshotSizeCapBytes (${this.config.snapshotSizeCapBytes}) — later turn-end snapshots are skipped while the namespace stays this large`);
2062
+ }
2063
+ if (entry.pendingNotice) {
2064
+ notices.push(`[dashr] ${entry.pendingNotice}`);
2065
+ entry.pendingNotice = void 0;
2066
+ }
2067
+ if (notices.length > 0) result = finalizeOutput([...result.logs, ...notices], result.value, result.error, this.config.maxOutputBytes);
2068
+ }
2069
+ return result;
2070
+ }
2071
+ /**
2072
+ * Read one user-namespace variable by name on the session's kernel. A
2073
+ * bare/empty name lists the namespace's user-variable names; a
2074
+ * JSON-serializable value resolves to its JSON text, any other value to its
2075
+ * `repr` text, and a missing name to `{ kind: 'missing' }`. When no live
2076
+ * kernel holds state for the key the namespace is empty (no spawn — this
2077
+ * channel never creates a kernel). Pure additive: the run/execute/snapshot
2078
+ * lifecycle is untouched.
2079
+ * @param name - the variable name, or empty to list namespace names.
2080
+ * @param principal - the session key (absent → the shared default).
2081
+ */
2082
+ async queryVar(name$1, principal) {
2083
+ if (this.disposed) throw new Error("dashr-repl: queryVar() after disposal");
2084
+ const key = principal && principal.length > 0 ? principal : AGENTLESS_KEY;
2085
+ const bridge = this.kernels.get(key)?.bridge;
2086
+ if (!bridge || !bridge.isRunning) return name$1.trim().length === 0 ? {
2087
+ kind: "names",
2088
+ names: []
2089
+ } : { kind: "missing" };
2090
+ const outcome = await bridge.queryVar(name$1.trim().length === 0 ? null : name$1);
2091
+ switch (outcome.kind) {
2092
+ case "json": return {
2093
+ kind: "json",
2094
+ text: outcome.text
2095
+ };
2096
+ case "repr": return {
2097
+ kind: "repr",
2098
+ text: outcome.text
2099
+ };
2100
+ case "names": return {
2101
+ kind: "names",
2102
+ names: outcome.names
2103
+ };
2104
+ case "missing": return { kind: "missing" };
2105
+ case "failed": throw new Error(`dashr-repl: queryVar(${JSON.stringify(name$1)}) failed: ${outcome.reason}`);
2106
+ }
2107
+ }
2108
+ /**
2109
+ * Assign one lossless-JSON value into the user namespace under `name` on
2110
+ * the session's kernel. `name` must be a usable identifier (and not a
2111
+ * kernel-shim name); `value` must be lossless JSON. Requires a live kernel
2112
+ * for the key — the channel never spawns one, so a session that has not yet
2113
+ * run a cell must `run` first. Pure additive to the existing lifecycle.
2114
+ * @param name - the identifier to assign under.
2115
+ * @param value - the lossless-JSON value to bind.
2116
+ * @param principal - the session key (absent → the shared default).
2117
+ */
2118
+ async setVar(name$1, value, principal) {
2119
+ if (this.disposed) throw new Error("dashr-repl: setVar() after disposal");
2120
+ const trimmed = name$1.trim();
2121
+ if (trimmed.length === 0) throw new Error("dashr-repl: setVar() requires a non-empty variable name");
2122
+ if (!IDENTIFIER.test(trimmed)) throw new Error(`dashr-repl: setVar() name ${JSON.stringify(trimmed)} is not a usable identifier`);
2123
+ if (KERNEL_OWNED_NAME.test(trimmed)) throw new Error(`dashr-repl: setVar() name ${JSON.stringify(trimmed)} is reserved by the kernel`);
2124
+ const jsonValue = snapshotJsonValue(value);
2125
+ if (jsonValue === void 0) throw new Error("dashr-repl: setVar() value must be lossless JSON");
2126
+ const key = principal && principal.length > 0 ? principal : AGENTLESS_KEY;
2127
+ const bridge = this.kernels.get(key)?.bridge;
2128
+ if (!bridge || !bridge.isRunning) throw new Error("dashr-repl: setVar() requires a live kernel for this session — run a cell first");
2129
+ const outcome = await bridge.setVar(trimmed, JSON.stringify(jsonValue));
2130
+ if (outcome.kind === "failed") throw new Error(`dashr-repl: setVar(${JSON.stringify(trimmed)}) failed: ${outcome.reason}`);
2131
+ }
2132
+ /** Map one cell outcome onto the seam's result shape under the output ledger. */
2133
+ assembleResult(outcome, sentinel) {
2134
+ const capture = extractStream(outcome.streamText, sentinel);
2135
+ const maxBytes = this.config.maxOutputBytes;
2136
+ if (outcome.outcome === "forced") return finalizeOutput(capture.logs, void 0, outcome.failure, maxBytes);
2137
+ if (outcome.status === "error") {
2138
+ const failure = outcome.cellError ? {
2139
+ kind: "exception",
2140
+ message: plainTraceback(outcome.cellError.ename, outcome.cellError.evalue, outcome.cellError.traceback)
2141
+ } : {
2142
+ kind: "exception",
2143
+ message: "the program failed without a traceback"
2144
+ };
2145
+ return finalizeOutput(capture.logs, void 0, failure, maxBytes);
2146
+ }
2147
+ if (capture.envelope === void 0) return finalizeOutput(capture.logs, void 0, void 0, maxBytes);
2148
+ let envelope;
2149
+ try {
2150
+ envelope = JSON.parse(capture.envelope);
2151
+ } catch {
2152
+ return finalizeOutput(capture.logs, void 0, {
2153
+ kind: "invalid-output",
2154
+ message: "completion envelope was not valid JSON"
2155
+ }, maxBytes);
2156
+ }
2157
+ if (typeof envelope !== "object" || envelope === null || envelope.ok !== true) return finalizeOutput(capture.logs, void 0, {
2158
+ kind: "invalid-output",
2159
+ message: "program completion must be lossless JSON"
2160
+ }, maxBytes);
2161
+ const json = envelope.json;
2162
+ if (typeof json !== "string") return finalizeOutput(capture.logs, void 0, void 0, maxBytes);
2163
+ return finalizeOutput(capture.logs, JSON.parse(json), void 0, maxBytes);
2164
+ }
2165
+ /** Reject malformed binding globals or typed-error declarations as contract misuse. */
2166
+ validateBindings(request) {
2167
+ const bindings = /* @__PURE__ */ new Map();
2168
+ for (const namespace of request.bindings) {
2169
+ if (!IDENTIFIER.test(namespace.global) || PORTABLE_RESERVED_WORDS.has(namespace.global)) throw new Error(`dashr-repl: binding global ${JSON.stringify(namespace.global)} is not a usable identifier`);
2170
+ if (RESERVED_BINDING_GLOBALS.has(namespace.global) || KERNEL_OWNED_NAME.test(namespace.global)) throw new Error(`dashr-repl: reserved binding global ${JSON.stringify(namespace.global)}`);
2171
+ if (bindings.has(namespace.global)) throw new Error(`dashr-repl: duplicate binding global ${JSON.stringify(namespace.global)}`);
2172
+ if (namespace.callable === true && Object.keys(namespace.functions).length !== 1) throw new Error(`dashr-repl: callable binding global ${JSON.stringify(namespace.global)} must declare exactly one function`);
2173
+ bindings.set(namespace.global, namespace);
2174
+ }
2175
+ const errorClasses = /* @__PURE__ */ new Map();
2176
+ for (const namespace of request.bindings) {
2177
+ const descriptor = namespace.errorClass;
2178
+ if (!descriptor) continue;
2179
+ if (!IDENTIFIER.test(descriptor.name) || PORTABLE_RESERVED_WORDS.has(descriptor.name)) throw new Error(`dashr-repl: binding error class ${JSON.stringify(descriptor.name)} is not a usable identifier`);
2180
+ if (RESERVED_BINDING_GLOBALS.has(descriptor.name) || KERNEL_OWNED_NAME.test(descriptor.name)) throw new Error(`dashr-repl: reserved binding global ${JSON.stringify(descriptor.name)}`);
2181
+ if (bindings.has(descriptor.name)) throw new Error(`dashr-repl: duplicate injected global ${JSON.stringify(descriptor.name)}`);
2182
+ const member = descriptor.memberNameProperty;
2183
+ if (member.length === 0 || RESERVED_ERROR_MEMBERS.has(member) || DUNDER_MEMBER.test(member)) throw new Error(`dashr-repl: binding error member property ${JSON.stringify(descriptor.memberNameProperty)} is not usable`);
2184
+ const declared = errorClasses.get(descriptor.name);
2185
+ if (declared !== void 0 && declared !== member) throw new Error(`dashr-repl: error class ${JSON.stringify(descriptor.name)} declared with conflicting member properties ${JSON.stringify(declared)} and ${JSON.stringify(member)}`);
2186
+ errorClasses.set(descriptor.name, member);
2187
+ }
2188
+ return bindings;
2189
+ }
2190
+ /** Dispatch one kernel-side host request; unknown types and bad payloads become error replies. */
2191
+ async dispatchHostRequest(data, bindings) {
2192
+ if (data.type !== "binding.call" || typeof data.global !== "string" || typeof data.name !== "string") return {
2193
+ ok: false,
2194
+ message: "host request must be a binding.call with global and name"
2195
+ };
2196
+ const record = bindings.get(data.global)?.functions;
2197
+ const fn = record && Object.hasOwn(record, data.name) ? record[data.name] : void 0;
2198
+ if (typeof fn !== "function") return {
2199
+ ok: false,
2200
+ message: `unknown binding ${JSON.stringify(`${data.global}.${data.name}`)}`
2201
+ };
2202
+ const args = snapshotJsonValue(data.args);
2203
+ if (args === void 0) return {
2204
+ ok: false,
2205
+ message: "binding arguments must be lossless JSON"
2206
+ };
2207
+ let resolved;
2208
+ try {
2209
+ resolved = await fn(args);
2210
+ } catch (error) {
2211
+ return {
2212
+ ok: false,
2213
+ message: messageOf(error)
2214
+ };
2215
+ }
2216
+ const value = snapshotJsonValue(resolved);
2217
+ if (value === void 0) return {
2218
+ ok: false,
2219
+ message: "binding resolution must be lossless JSON"
2220
+ };
2221
+ return {
2222
+ ok: true,
2223
+ result: value
2224
+ };
2225
+ }
2226
+ /** Resolve (and provision, when managed) the kernel interpreter once per runtime. */
2227
+ resolveKernelPython() {
2228
+ this.kernelEnvPromise ??= resolveKernelEnv({
2229
+ python: this.config.python,
2230
+ venvDir: this.config.kernelEnvDir,
2231
+ pythonVersion: this.config.kernelPythonVersion,
2232
+ autoInstall: this.config.kernelAutoInstall,
2233
+ log: (level, message) => {
2234
+ if (level === "warn") this.logger.warn(message);
2235
+ else this.logger.info(message);
2236
+ }
2237
+ }).catch((error) => {
2238
+ this.kernelEnvPromise = void 0;
2239
+ throw error;
2240
+ });
2241
+ return this.kernelEnvPromise;
2242
+ }
2243
+ /**
2244
+ * Spawn-or-reuse the kernel for one key. The lazy map guarantees one
2245
+ * entry is created here and nowhere else, so a key that never runs never
2246
+ * holds a subprocess — the subagent fan-out guarantee (blueprint §6:
2247
+ * subagent ×N spawns nothing until a child actually executes code).
2248
+ * @param key - the run principal (or the agentless default).
2249
+ */
2250
+ async ensureKernel(key, cwd) {
2251
+ let entry = this.kernels.get(key);
2252
+ if (!entry) {
2253
+ const kernelCwd = cwd && existsSync(cwd) ? cwd : void 0;
2254
+ entry = {
2255
+ key,
2256
+ cwd: kernelCwd,
2257
+ bridge: new IpyKernelBridge({
2258
+ python: (await this.resolveKernelPython()).python,
2259
+ ...kernelCwd ? { cwd: kernelCwd } : {},
2260
+ startupTimeoutMs: this.config.startupTimeoutMs,
2261
+ disposeTimeoutMs: this.config.disposeTimeoutMs,
2262
+ interruptConfirmMs: this.config.interruptConfirmMs,
2263
+ snapshotTimeoutMs: this.config.snapshotTimeoutMs,
2264
+ username: this.config.username
2265
+ }),
2266
+ ranCells: false,
2267
+ turn: 0
2268
+ };
2269
+ this.kernels.set(key, entry);
2270
+ }
2271
+ await entry.bridge.start();
2272
+ return entry;
2273
+ }
2274
+ /**
2275
+ * Restore a key's on-disk snapshot into a freshly booted kernel, when one
2276
+ * exists and its manifest is plausible. Called once per entry boot. The
2277
+ * kernel-side restore cell performs the authoritative environment checks
2278
+ * (python version, interpreter identity, skills); this method only gates on
2279
+ * the manifest the host can read cheaply, then records the turn so the
2280
+ * first-run notice and the revive chain can name it.
2281
+ */
2282
+ async restoreEntry(entry) {
2283
+ if (!this.config.snapshotDir) return { kind: "none" };
2284
+ const dir = join(this.config.snapshotDir, keyDirectoryName(entry.key));
2285
+ const payloadPath = join(dir, "state.dill");
2286
+ const manifestPath = join(dir, "manifest.json");
2287
+ const manifest = this.readSnapshotManifest(entry.key);
2288
+ if (manifest === void 0) return { kind: "none" };
2289
+ if (manifest.snapshotFormat !== SNAPSHOT_FORMAT) return {
2290
+ kind: "degraded",
2291
+ reason: `snapshot format ${String(manifest.snapshotFormat)} is not replayable`
2292
+ };
2293
+ if (manifest.skipped === true) return { kind: "none" };
2294
+ if (!existsSync(payloadPath)) return {
2295
+ kind: "degraded",
2296
+ reason: "snapshot payload is missing"
2297
+ };
2298
+ const restored = await entry.bridge.restoreState(payloadPath, manifestPath);
2299
+ if (restored.kind === "restored") {
2300
+ entry.turn = typeof manifest.turn === "number" && Number.isSafeInteger(manifest.turn) && manifest.turn >= 0 ? manifest.turn : 0;
2301
+ entry.lastSnapshotTurn = entry.turn;
2302
+ entry.ranCells = true;
2303
+ return {
2304
+ kind: "restored",
2305
+ turn: entry.turn
2306
+ };
2307
+ }
2308
+ return {
2309
+ kind: "degraded",
2310
+ reason: restored.reason
2311
+ };
2312
+ }
2313
+ /** Read the per-key manifest's host-relevant fields; absent when unreadable/missing. */
2314
+ readSnapshotManifest(key) {
2315
+ if (!this.config.snapshotDir) return void 0;
2316
+ try {
2317
+ return JSON.parse(readFileSync(join(this.config.snapshotDir, keyDirectoryName(key), "manifest.json"), "utf8"));
2318
+ } catch {
2319
+ return;
2320
+ }
2321
+ }
2322
+ /**
2323
+ * Revive one session's kernel after death: respawn a fresh kernel, restore
2324
+ * the nearest replayable snapshot onto it (the normal restore path), and
2325
+ * return the death-observing run's explicit error naming the turn. When no
2326
+ * replayable snapshot exists the message falls back to M3-A's fresh-empty
2327
+ * contract. The run itself does NOT execute — an error that lies about a
2328
+ * NameError costs the model more than one dropped cell (blueprint §8.3).
2329
+ * @param key - the run principal.
2330
+ * @param dead - the entry that died (its `turn` is the last completed turn).
2331
+ */
2332
+ async reviveAfterDeath(key, dead) {
2333
+ let entry;
2334
+ try {
2335
+ entry = await this.ensureKernel(key, dead.cwd);
2336
+ } catch (error) {
2337
+ return finalizeOutput([], void 0, {
2338
+ kind: "worker-exit",
2339
+ message: `kernel died and respawn failed (${messageOf(error)}); the next run will retry a fresh kernel`
2340
+ }, this.config.maxOutputBytes);
2341
+ }
2342
+ entry.restoreAttempted = true;
2343
+ const restore = await this.restoreEntry(entry);
2344
+ const observingTurn = dead.turn + 1;
2345
+ if (restore.kind === "restored") {
2346
+ const lost = observingTurn - restore.turn;
2347
+ const rounds = lost === 1 ? "round" : "rounds";
2348
+ return finalizeOutput([], void 0, {
2349
+ kind: "worker-exit",
2350
+ message: `the kernel for this session died; its namespace was restored from the turn-${restore.turn} snapshot — the last ${lost} ${rounds} of variable operations must be replayed. This run did not execute.`
2351
+ }, this.config.maxOutputBytes);
2352
+ }
2353
+ return finalizeOutput([], void 0, {
2354
+ kind: "worker-exit",
2355
+ message: `the kernel for this session died and no replayable snapshot was available${restore.kind === "degraded" ? ` (${restore.reason})` : ""}; the next run starts a fresh kernel with an EMPTY namespace — re-create any state you still need. This run did not execute.`
2356
+ }, this.config.maxOutputBytes);
2357
+ }
2358
+ /**
2359
+ * Write one key's turn-end snapshot, when a snapshot directory is
2360
+ * configured. A size-cap skip is reported (so the run can warn the model
2361
+ * once); other failures log without disturbing the run.
2362
+ */
2363
+ async snapshotTurnEnd(entry) {
2364
+ if (!this.config.snapshotDir) return { skipped: false };
2365
+ const kernel = entry.bridge;
2366
+ if (!kernel.isRunning) return { skipped: false };
2367
+ const dir = join(this.config.snapshotDir, keyDirectoryName(entry.key));
2368
+ mkdirSync(dir, { recursive: true });
2369
+ const spec = {
2370
+ turn: entry.turn,
2371
+ skills: [],
2372
+ sizeCapBytes: this.config.snapshotSizeCapBytes
2373
+ };
2374
+ const outcome = await kernel.snapshotState(join(dir, "state.dill"), join(dir, "manifest.json"), spec);
2375
+ if (outcome.kind === "ok") {
2376
+ entry.lastSnapshotTurn = entry.turn;
2377
+ return { skipped: false };
2378
+ }
2379
+ if (outcome.kind === "skipped") return {
2380
+ skipped: true,
2381
+ ...outcome.estimateBytes !== void 0 ? { estimateBytes: outcome.estimateBytes } : {},
2382
+ ...outcome.sizeBytes !== void 0 ? { sizeBytes: outcome.sizeBytes } : {}
2383
+ };
2384
+ this.logger.warn(`turn-end snapshot for ${JSON.stringify(entry.key)} failed: ${outcome.reason}`);
2385
+ return { skipped: false };
2386
+ }
2387
+ /**
2388
+ * Dispose to quiescence: snapshot every live key's namespace when a
2389
+ * snapshot directory is configured (each under its own per-key
2390
+ * subdirectory), then shut the subprocesses down. Registered as the
2391
+ * plugin's `ctx.effect` disposer.
2392
+ */
2393
+ async teardown() {
2394
+ this.disposed = true;
2395
+ const entries = [...this.kernels.values()];
2396
+ this.kernels.clear();
2397
+ await Promise.all(entries.map((entry) => this.teardownKernel(entry)));
2398
+ }
2399
+ /**
2400
+ * Tear one session's kernel down (session end via the `agent/disposed`
2401
+ * listener). A no-op for keys that never ran code through this instance —
2402
+ * which is what makes hearing every agent's disposal safe.
2403
+ */
2404
+ async destroyKey(key) {
2405
+ const entry = this.kernels.get(key);
2406
+ if (!entry) return;
2407
+ this.kernels.delete(key);
2408
+ await this.teardownKernel(entry);
2409
+ }
2410
+ /**
2411
+ * Reset one session's kernel to a fresh, empty namespace: dispose the live
2412
+ * subprocess WITHOUT a turn-end snapshot and clear its on-disk snapshot, so
2413
+ * the next ensureKernel spawns empty (restore finds nothing to replay).
2414
+ */
2415
+ async resetKey(key) {
2416
+ const entry = this.kernels.get(key);
2417
+ if (entry) {
2418
+ this.kernels.delete(key);
2419
+ await entry.bridge.dispose();
2420
+ }
2421
+ if (this.config.snapshotDir) rmSync(join(this.config.snapshotDir, keyDirectoryName(key)), {
2422
+ recursive: true,
2423
+ force: true
2424
+ });
2425
+ }
2426
+ /** Snapshot (when configured) then dispose one key's kernel; failures log, never throw into a listener. */
2427
+ async teardownKernel(entry) {
2428
+ const kernel = entry.bridge;
2429
+ if (this.config.snapshotDir && kernel.isRunning) try {
2430
+ const dir = join(this.config.snapshotDir, keyDirectoryName(entry.key));
2431
+ mkdirSync(dir, { recursive: true });
2432
+ const spec = {
2433
+ turn: entry.turn,
2434
+ skills: [],
2435
+ sizeCapBytes: this.config.snapshotSizeCapBytes
2436
+ };
2437
+ const saved = await kernel.snapshotState(join(dir, "state.dill"), join(dir, "manifest.json"), spec);
2438
+ if (saved.kind !== "ok" && saved.kind !== "skipped") this.logger.warn(`kernel namespace snapshot for ${JSON.stringify(entry.key)} failed: ${saved.reason}`);
2439
+ } catch (error) {
2440
+ this.logger.warn(`kernel namespace snapshot for ${JSON.stringify(entry.key)} failed: ${messageOf(error)}`);
2441
+ }
2442
+ await kernel.dispose();
2443
+ }
2444
+ };
2445
+
2446
+ //#endregion
2447
+ //#region src/tool-call-id.ts
2448
+ /** Brand a string as the host's tool-call id (identity at runtime). */
2449
+ const toolCallId = dshLlm.ToolCallId;
2450
+
2451
+ //#endregion
2452
+ //#region src/bridges/index.ts
2453
+ /**
2454
+ * Unwrap one bridge-tool {@link parseReplCall} packaging into its single
2455
+ * arguments object. Same one-object contract as a registry tool, but bridge
2456
+ * tools return a structured `{ error }` value instead of throwing, and a call
2457
+ * with no arguments reads as an empty object. Keyword and multi-positional
2458
+ * forms are rejected.
2459
+ */
2460
+ function flatBridgeToolArgs(rawArgs) {
2461
+ if (rawArgs === void 0 || rawArgs === null) return {
2462
+ ok: true,
2463
+ args: {}
2464
+ };
2465
+ if (Array.isArray(rawArgs)) return {
2466
+ ok: false,
2467
+ error: "tools take exactly one positional arguments object — call e.g. tool.name({\"field\": value})"
2468
+ };
2469
+ if (typeof rawArgs !== "object") return {
2470
+ ok: false,
2471
+ error: "tools take one positional arguments object, not a bare value — call e.g. tool.name({\"field\": value})"
2472
+ };
2473
+ return {
2474
+ ok: true,
2475
+ args: rawArgs
2476
+ };
2477
+ }
2478
+ /**
2479
+ * The wire layer delivers `type:'json'` parameters as JSON STRINGS (the cell
2480
+ * path delivers parsed objects); accept either form. An unparseable string
2481
+ * falls through untouched — the caller's object check turns it into the
2482
+ * structured error.
2483
+ */
2484
+ function coerceJsonField(value) {
2485
+ if (typeof value !== "string") return value;
2486
+ try {
2487
+ return JSON.parse(value);
2488
+ } catch {
2489
+ return value;
2490
+ }
2491
+ }
2492
+ /** Reject unexpected keys on one bridge call's arguments object. */
2493
+ function rejectUnknownKeys(tool, args, allowed) {
2494
+ const unknownKeys = Object.keys(args).filter((key) => !allowed.includes(key));
2495
+ if (unknownKeys.length > 0) return { error: `${tool}() got unexpected key(s): ${unknownKeys.join(", ")}` };
2496
+ }
2497
+ /** Human-readable reason for one non-`completed` subagent stop (native `stopReasonError`). */
2498
+ function stopReasonError(reason) {
2499
+ switch (reason) {
2500
+ case "completed": return "subagent run completed";
2501
+ case "aborted": return "subagent run was cancelled";
2502
+ case "error": return "subagent run failed";
2503
+ case "max-tokens": return "subagent run hit its token limit before finishing";
2504
+ case "refusal": return "subagent declined the task";
2505
+ default: return `subagent run ended abnormally (${reason})`;
2506
+ }
2507
+ }
2508
+ /** The native `dsh-tool-subagent` default delegation-depth cap (Config default `3`). */
2509
+ const NATIVE_MAX_DEPTH = 3;
2510
+ /** The fixed Ralph orchestration (deployment-owned, copied verbatim from `@deepseek-ai/dsh-tool-ralph`). */
2511
+ const RALPH_META = {
2512
+ name: "ralph-loop",
2513
+ description: "Iterate toward one objective with a fresh child and bounded structured handoff per round.",
2514
+ phases: [{
2515
+ title: "Fresh-agent rounds",
2516
+ detail: "One clean child context per Ralph round."
2517
+ }]
2518
+ };
2519
+ /** Native Ralph defaults (Config defaults). */
2520
+ const RALPH_SUBAGENT_PROVIDER = "spawn";
2521
+ const RALPH_MAX_ROUNDS = 256;
2522
+ const RALPH_MAX_HANDOFF_CHARS = 16384;
2523
+ /** The fixed, deployment-owned Ralph script, copied verbatim from `@deepseek-ai/dsh-tool-ralph`. */
2524
+ const RALPH_SCRIPT = String.raw`
2525
+ const reportSchema = {
2526
+ type: 'object',
2527
+ properties: {
2528
+ status: { type: 'string', enum: ['continue', 'complete', 'blocked'] },
2529
+ summary: { type: 'string' },
2530
+ evidence: { type: 'array', items: { type: 'string' } },
2531
+ nextSteps: { type: 'array', items: { type: 'string' } },
2532
+ blocker: { type: 'string' },
2533
+ },
2534
+ required: ['status', 'summary', 'evidence', 'nextSteps', 'blocker'],
2535
+ additionalProperties: false,
2536
+ }
2537
+
2538
+ function normalizedText(value) {
2539
+ return typeof value === 'string' && value.length > 0 && value === value.trim()
2540
+ }
2541
+
2542
+ function normalizedList(value) {
2543
+ return Array.isArray(value) && value.every(normalizedText)
2544
+ }
2545
+
2546
+ function validateReport(report) {
2547
+ if (report === null || typeof report !== 'object' || Array.isArray(report)) {
2548
+ throw new Error('Ralph child returned no structured round report')
2549
+ }
2550
+ if (!normalizedText(report.summary)) {
2551
+ throw new Error('Ralph round report summary must be non-empty and normalized')
2552
+ }
2553
+ if (!normalizedList(report.evidence) || !normalizedList(report.nextSteps)) {
2554
+ throw new Error('Ralph round report evidence and nextSteps must contain only non-empty normalized strings')
2555
+ }
2556
+ if (typeof report.blocker !== 'string' || report.blocker !== report.blocker.trim()) {
2557
+ throw new Error('Ralph round report blocker must be a normalized string')
2558
+ }
2559
+ switch (report.status) {
2560
+ case 'continue':
2561
+ if (report.nextSteps.length === 0 || report.blocker !== '') {
2562
+ throw new Error('a continuing Ralph report needs nextSteps and an empty blocker')
2563
+ }
2564
+ break
2565
+ case 'complete':
2566
+ if (report.evidence.length === 0 || report.nextSteps.length !== 0 || report.blocker !== '') {
2567
+ throw new Error('a complete Ralph report needs evidence, no nextSteps, and an empty blocker')
2568
+ }
2569
+ break
2570
+ case 'blocked':
2571
+ if (!normalizedText(report.blocker)) {
2572
+ throw new Error('a blocked Ralph report needs a concrete blocker')
2573
+ }
2574
+ break
2575
+ default:
2576
+ throw new Error('Ralph round report status is invalid')
2577
+ }
2578
+ const serialized = JSON.stringify(report)
2579
+ if (serialized.length > args.maxHandoffChars) {
2580
+ throw new Error('Ralph round report exceeds maxHandoffChars (' + serialized.length + ' > ' + args.maxHandoffChars + ')')
2581
+ }
2582
+ return report
2583
+ }
2584
+
2585
+ let previous
2586
+ phase('Fresh-agent rounds')
2587
+ for (let round = 1; round <= args.maxRounds; round += 1) {
2588
+ const prior = previous === undefined ? '(none — this is the first round)' : JSON.stringify(previous)
2589
+ const prompt = [
2590
+ 'You are one fresh worker in a foreground Ralph loop. You receive no parent conversation and no prior child session. Do not call the ralph tool: this round already is its worker.',
2591
+ 'Immutable objective:\n' + args.objective,
2592
+ 'Ralph round: ' + round + ' of ' + args.maxRounds + '.',
2593
+ 'The shared workspace and its current working tree are the long-term memory and source of truth. Inspect them before acting, preserve existing work, perform concrete in-scope work, and verify what you change. Treat the previous report only as a bounded handoff; confirm it against the workspace.',
2594
+ 'Previous structured handoff:\n' + prior,
2595
+ 'Return one report with exact normalized strings. Use status continue with at least one nextSteps entry while useful work remains; complete only with concrete evidence and no nextSteps; blocked only when no meaningful progress is possible without human input or an external-state change. blocker must be empty unless blocked.',
2596
+ ].join('\n\n')
2597
+ const rawReport = await agent(prompt, {
2598
+ label: 'Ralph round ' + round,
2599
+ phase: 'Fresh-agent rounds',
2600
+ schema: reportSchema,
2601
+ })
2602
+ if (rawReport === null) {
2603
+ return { status: 'round-failed', roundsStarted: round, lastReport: previous ?? null }
2604
+ }
2605
+ const report = validateReport(rawReport)
2606
+ if (report.status === 'complete') return { status: 'complete', roundsStarted: round, report }
2607
+ if (report.status === 'blocked') return { status: 'blocked', roundsStarted: round, report }
2608
+ previous = report
2609
+ }
2610
+ return { status: 'budget-limited', roundsStarted: args.maxRounds, report: previous }
2611
+ `;
2612
+ const agentExecutor = async (rawArgs, exec, deps) => {
2613
+ const parsed = flatBridgeToolArgs(rawArgs);
2614
+ if (!parsed.ok) return { error: parsed.error };
2615
+ const a = parsed.args;
2616
+ const unknown = rejectUnknownKeys("agent", a, [
2617
+ "description",
2618
+ "prompt",
2619
+ "run_in_background",
2620
+ "mode"
2621
+ ]);
2622
+ if (unknown !== void 0) return unknown;
2623
+ const description = a["description"];
2624
+ const prompt = a["prompt"];
2625
+ if (typeof description !== "string" || description.length === 0) return { error: "agent() requires {\"description\": \"...\"} — a short (3-5 word) display label" };
2626
+ if (typeof prompt !== "string" || prompt.length === 0) return { error: "agent() requires {\"prompt\": \"...\"} — the task for the child agent" };
2627
+ const mode = a["mode"] ?? "delegate";
2628
+ if (mode !== "delegate" && mode !== "fork") return { error: `agent() unknown mode ${JSON.stringify(mode)}: expected 'delegate' or 'fork'` };
2629
+ const provider = mode === "fork" ? "fork" : "spawn";
2630
+ if (!exec.agent) return { error: "agent() requires a calling agent (this run has no agent to delegate from)" };
2631
+ const subagents = deps.requireSubagents?.();
2632
+ if (!subagents) return { error: "agent() is unavailable: no ctx.subagents service is mounted in this composition" };
2633
+ const delegation = {
2634
+ label: description,
2635
+ prompt: [{
2636
+ type: "text",
2637
+ text: prompt
2638
+ }],
2639
+ parent: exec.agent,
2640
+ maxDepth: NATIVE_MAX_DEPTH
2641
+ };
2642
+ const runInBackground = a["run_in_background"] ?? true;
2643
+ try {
2644
+ if (runInBackground) return {
2645
+ kind: "continuable",
2646
+ subagentId: (await subagents.startContinuable({
2647
+ provider,
2648
+ label: description,
2649
+ request: delegation,
2650
+ signal: exec.signal
2651
+ })).childId
2652
+ };
2653
+ const run = await subagents.start(provider, {
2654
+ ...delegation,
2655
+ signal: exec.signal
2656
+ });
2657
+ try {
2658
+ const result = await run.result;
2659
+ if (result.stopReason !== "completed") return { error: `agent() ${stopReasonError(result.stopReason)}` };
2660
+ return {
2661
+ kind: "foreground",
2662
+ runId: run.id,
2663
+ output: result.output
2664
+ };
2665
+ } finally {
2666
+ await run.dispose();
2667
+ }
2668
+ } catch (error) {
2669
+ return { error: `agent() failed: ${error instanceof Error ? error.message : String(error)}` };
2670
+ }
2671
+ };
2672
+ const agentMessageExecutor = async (rawArgs, exec, deps) => {
2673
+ const parsed = flatBridgeToolArgs(rawArgs);
2674
+ if (!parsed.ok) return { error: parsed.error };
2675
+ const a = parsed.args;
2676
+ const unknown = rejectUnknownKeys("agent_message", a, [
2677
+ "receiver",
2678
+ "message",
2679
+ "subagent_id",
2680
+ "target_session_id"
2681
+ ]);
2682
+ if (unknown !== void 0) return unknown;
2683
+ const receiver = a["receiver"];
2684
+ if (typeof receiver !== "string") return { error: "agent_message() requires {\"receiver\": \"child\" | \"parent\" | \"interrupt\"}" };
2685
+ const message = a["message"];
2686
+ if (receiver === "child") {
2687
+ if (typeof message !== "string") return { error: "agent_message() receiver \"child\" requires {\"message\": \"...\"}" };
2688
+ const subagentId = a["subagent_id"];
2689
+ if (typeof subagentId !== "string" || subagentId.length === 0) return { error: "agent_message() receiver \"child\" requires {\"subagent_id\": \"...\"} — the durable subagent id a spawn returned" };
2690
+ if (!exec.agent) return { error: "agent_message(receiver='child') requires an agent session (this run has no agent to deliver from)" };
2691
+ const subagents = deps.requireSubagents?.();
2692
+ if (!subagents) return { error: "agent_message(receiver='child') is unavailable: no ctx.subagents service is mounted in this composition" };
2693
+ try {
2694
+ return { messageId: await subagents.sendMessage(exec.agent, subagentId, [{
2695
+ type: "text",
2696
+ text: message
2697
+ }], { signal: exec.signal }) };
2698
+ } catch (error) {
2699
+ return { error: `agent_message(receiver='child') failed: ${error instanceof Error ? error.message : String(error)}` };
2700
+ }
2701
+ }
2702
+ if (receiver === "parent") {
2703
+ if (typeof message !== "string") return { error: "agent_message() receiver \"parent\" requires {\"message\": \"...\"}" };
2704
+ if (!exec.agent) return { error: "agent_message(receiver='parent') requires an agent session (this run has no agent to report from)" };
2705
+ const subagents = deps.requireSubagents?.();
2706
+ if (!subagents) return { error: "agent_message(receiver='parent') is unavailable: no ctx.subagents service is mounted in this composition" };
2707
+ try {
2708
+ const parentId = exec.agent.session.header.parentSession;
2709
+ if (parentId === void 0) return { error: "agent_message(receiver='parent') rejected: only a live continuable child agent can report to its parent (a root agent has none)" };
2710
+ return {
2711
+ delivered: true,
2712
+ message_id: await subagents.sendMessage(exec.agent, parentId, [{
2713
+ type: "text",
2714
+ text: message
2715
+ }], { signal: exec.signal })
2716
+ };
2717
+ } catch (error) {
2718
+ if (error.code === "UNAUTHORIZED") return { error: `agent_message(receiver='parent') rejected: only a live continuable child agent can report to its parent (a root agent has none) — ${error instanceof Error ? error.message : String(error)}` };
2719
+ return { error: `agent_message(receiver='parent') failed: ${error instanceof Error ? error.message : String(error)}` };
2720
+ }
2721
+ }
2722
+ if (receiver === "interrupt") {
2723
+ const targetSessionId = a["target_session_id"];
2724
+ if (typeof targetSessionId !== "string" || targetSessionId.length === 0) return { error: "agent_message() receiver 'interrupt' requires {\"target_session_id\": \"...\"} — the target agent's session id" };
2725
+ if (!exec.agent) return { error: "agent_message(receiver='interrupt') requires a calling agent (this run has no agent to authorize the interrupt)" };
2726
+ const subagents = deps.requireSubagents?.();
2727
+ if (!subagents) return { error: "agent_message(receiver='interrupt') is unavailable: no ctx.subagents service is mounted in this composition" };
2728
+ try {
2729
+ subagents.interrupt(targetSessionId, {
2730
+ kind: "ancestor",
2731
+ agent: exec.agent
2732
+ });
2733
+ return { accepted: true };
2734
+ } catch (error) {
2735
+ return { error: `agent_message(receiver='interrupt') failed: ${error instanceof Error ? error.message : String(error)}` };
2736
+ }
2737
+ }
2738
+ return { error: `agent_message() unknown receiver ${JSON.stringify(receiver)}: expected 'child', 'parent', or 'interrupt'` };
2739
+ };
2740
+ const agentWorkflowExecutor = async (rawArgs, exec, deps) => {
2741
+ const parsed = flatBridgeToolArgs(rawArgs);
2742
+ if (!parsed.ok) return { error: parsed.error };
2743
+ const a = parsed.args;
2744
+ const unknown = rejectUnknownKeys("agent_workflow", a, [
2745
+ "mode",
2746
+ "script",
2747
+ "meta",
2748
+ "args",
2749
+ "objective",
2750
+ "maxRounds"
2751
+ ]);
2752
+ if (unknown !== void 0) return unknown;
2753
+ const mode = a["mode"] ?? "script";
2754
+ if (mode !== "script" && mode !== "rfc") return { error: `agent_workflow() unknown mode ${JSON.stringify(mode)}: expected 'script' or 'rfc'` };
2755
+ if (!exec.agent) return { error: "agent_workflow() requires a calling agent (this run has no agent to attribute the workflow to)" };
2756
+ const meta = coerceJsonField(a["meta"]);
2757
+ const argsField = coerceJsonField(a["args"]);
2758
+ if (mode === "script") {
2759
+ if (typeof a["script"] !== "string" || a["script"].length === 0) return { error: "agent_workflow() mode \"script\" requires {\"script\": \"...\"} — the plain-JS workflow script body" };
2760
+ if (typeof meta !== "object" || meta === null || Array.isArray(meta)) return { error: "agent_workflow() mode \"script\" requires {\"meta\": {...}} — the workflow identity block" };
2761
+ } else if (typeof a["objective"] !== "string" || a["objective"].trim().length === 0) return { error: "agent_workflow() mode \"rfc\" requires {\"objective\": \"...\"} — the immutable completion objective" };
2762
+ const engine = deps.requireWorkflowEngine?.(exec.agent);
2763
+ if (!engine) return { error: "agent_workflow() is unavailable: no workflowEngine service is mounted for this agent's preset" };
2764
+ const settle = async (run) => {
2765
+ const onAbort = () => {
2766
+ run.cancel("parent step aborted");
2767
+ };
2768
+ exec.signal.addEventListener("abort", onAbort, { once: true });
2769
+ try {
2770
+ const result = await run.result;
2771
+ if (result.stopReason !== "completed") return { error: `agent_workflow() did not finish cleanly: ${result.error ?? result.stopReason}` };
2772
+ return {
2773
+ runId: run.id,
2774
+ agentsStarted: result.agentsStarted,
2775
+ result: result.value
2776
+ };
2777
+ } catch (error) {
2778
+ return { error: `agent_workflow() failed: ${error instanceof Error ? error.message : String(error)}` };
2779
+ } finally {
2780
+ exec.signal.removeEventListener("abort", onAbort);
2781
+ await run.dispose();
2782
+ }
2783
+ };
2784
+ try {
2785
+ if (mode === "script") return await settle(engine.start({
2786
+ script: a["script"],
2787
+ meta,
2788
+ ...argsField !== void 0 ? { args: argsField } : {},
2789
+ parent: exec.agent,
2790
+ signal: exec.signal
2791
+ }));
2792
+ const maxRounds = a["maxRounds"] === void 0 ? RALPH_MAX_ROUNDS : a["maxRounds"];
2793
+ if (typeof maxRounds !== "number" || !Number.isSafeInteger(maxRounds) || maxRounds < 1) return { error: "agent_workflow() mode \"rfc\" maxRounds must be a positive safe integer" };
2794
+ if (maxRounds > RALPH_MAX_ROUNDS) return { error: `agent_workflow() mode "rfc" maxRounds ${maxRounds} exceeds the deployment ceiling ${RALPH_MAX_ROUNDS}` };
2795
+ return await settle(engine.start({
2796
+ script: RALPH_SCRIPT,
2797
+ meta: RALPH_META,
2798
+ args: {
2799
+ objective: a["objective"].trim(),
2800
+ maxRounds,
2801
+ maxHandoffChars: RALPH_MAX_HANDOFF_CHARS
2802
+ },
2803
+ subagentProvider: RALPH_SUBAGENT_PROVIDER,
2804
+ maxTotalAgents: maxRounds,
2805
+ parent: exec.agent,
2806
+ signal: exec.signal
2807
+ }));
2808
+ } catch (error) {
2809
+ return { error: `agent_workflow() failed: ${error instanceof Error ? error.message : String(error)}` };
2810
+ }
2811
+ };
2812
+ /**
2813
+ * Build the three delegation bridge TOOLS: real registry registrations whose
2814
+ * execute runs the pure executors with the host-level service resolvers.
2815
+ * Register once at the same host layer as `eval`; the registry projection is
2816
+ * then the single source for the wire tools array, the tool catalog, and the
2817
+ * REPL `tool.*` bindings (via the mechanical auto-bridge). Runtime argument
2818
+ * validation stays inside the executors; the schemas below are the declared
2819
+ * model-facing contract, and a structured `{ error }` value — not a thrown
2820
+ * exception — is the failure form.
2821
+ */
2822
+ function createAgentBridgeTools(deps) {
2823
+ const jsonRender = (_args, value) => [{
2824
+ type: "text",
2825
+ text: JSON.stringify(value, null, 2)
2826
+ }];
2827
+ const errorVariant = {
2828
+ type: "object",
2829
+ properties: { error: { type: "string" } },
2830
+ additionalProperties: false
2831
+ };
2832
+ return [
2833
+ defineTool({
2834
+ name: "agent",
2835
+ description: "Start a child agent. Runs in the background by default: returns a durable subagent id immediately and keeps the child conversation open for agent_message follow-ups. Set run_in_background false to run a ONE-SHOT child instead — the call waits for the result and the child ends with the run. mode \"delegate\" (default) starts a fresh child; mode \"fork\" seeds the child with this agent's completed conversation turns.",
2836
+ parameters: {
2837
+ description: {
2838
+ type: "string",
2839
+ description: "A short (3-5 word) description of the delegated task, for display."
2840
+ },
2841
+ prompt: {
2842
+ type: "string",
2843
+ description: "The task prompt for the child agent."
2844
+ },
2845
+ run_in_background: {
2846
+ type: "boolean",
2847
+ description: "Default true: return a durable subagent id immediately (continuable, agent_message can follow up). Explicit false: one-shot — wait for the child's result here."
2848
+ },
2849
+ mode: {
2850
+ type: "string",
2851
+ description: "'delegate' (default: a fresh child) or 'fork' (a child seeded with this agent's completed conversation turns)."
2852
+ }
2853
+ },
2854
+ output: {
2855
+ schema: { oneOf: [
2856
+ {
2857
+ type: "object",
2858
+ properties: {
2859
+ kind: {
2860
+ type: "string",
2861
+ enum: ["continuable"]
2862
+ },
2863
+ subagentId: { type: "string" }
2864
+ },
2865
+ additionalProperties: false
2866
+ },
2867
+ {
2868
+ type: "object",
2869
+ properties: {
2870
+ kind: {
2871
+ type: "string",
2872
+ enum: ["foreground"]
2873
+ },
2874
+ runId: { type: "string" },
2875
+ output: { type: "json" }
2876
+ },
2877
+ additionalProperties: false
2878
+ },
2879
+ errorVariant
2880
+ ] },
2881
+ render: jsonRender
2882
+ },
2883
+ execute: (args, exec) => agentExecutor(args, exec, deps)
2884
+ }),
2885
+ defineTool({
2886
+ name: "agent_message",
2887
+ description: "The single agent-to-agent channel, three ways: receiver \"child\" delivers a follow-up message down to a child (subagent_id required); receiver \"parent\" reports up to this agent's parent (live continuable children only; a root agent gets a structured UNAUTHORIZED instead); receiver \"interrupt\" stops a child's current turn (target_session_id required).",
2888
+ parameters: {
2889
+ receiver: {
2890
+ type: "string",
2891
+ description: "'child' (deliver down), 'parent' (report up), or 'interrupt' (stop a child's current turn)."
2892
+ },
2893
+ message: {
2894
+ type: "string",
2895
+ description: "The message text (required for receiver 'child' and 'parent')."
2896
+ },
2897
+ subagent_id: {
2898
+ type: "string",
2899
+ description: "The child's durable id (required when receiver is 'child')."
2900
+ },
2901
+ target_session_id: {
2902
+ type: "string",
2903
+ description: "The target agent's session id to interrupt (required when receiver is 'interrupt')."
2904
+ }
2905
+ },
2906
+ output: {
2907
+ schema: { oneOf: [
2908
+ {
2909
+ type: "object",
2910
+ properties: { messageId: { type: "string" } },
2911
+ additionalProperties: false
2912
+ },
2913
+ {
2914
+ type: "object",
2915
+ properties: {
2916
+ delivered: {
2917
+ type: "boolean",
2918
+ enum: [true]
2919
+ },
2920
+ message_id: { type: "string" }
2921
+ },
2922
+ additionalProperties: false
2923
+ },
2924
+ {
2925
+ type: "object",
2926
+ properties: { accepted: {
2927
+ type: "boolean",
2928
+ enum: [true]
2929
+ } },
2930
+ additionalProperties: false
2931
+ },
2932
+ errorVariant
2933
+ ] },
2934
+ render: jsonRender
2935
+ },
2936
+ execute: (args, exec) => agentMessageExecutor(args, exec, deps)
2937
+ }),
2938
+ defineTool({
2939
+ name: "agent_workflow",
2940
+ description: "Run a multi-agent orchestration: mode \"script\" runs a plain-JS orchestration script (script/meta required); mode \"rfc\" runs the fixed fresh-agent Ralph loop toward one objective (objective required, maxRounds optional).",
2941
+ parameters: {
2942
+ mode: {
2943
+ type: "string",
2944
+ description: "'script' (default: an orchestration script) or 'rfc' (a fixed fresh-agent Ralph loop)."
2945
+ },
2946
+ script: {
2947
+ type: "string",
2948
+ description: "The plain-JS workflow script body (required when mode is \"script\")."
2949
+ },
2950
+ meta: {
2951
+ type: "json",
2952
+ description: "The workflow identity block (required when mode is \"script\"); must carry non-empty name and description (host invariant)."
2953
+ },
2954
+ args: {
2955
+ type: "json",
2956
+ description: "Optional JSON input exposed to the script as the args global."
2957
+ },
2958
+ objective: {
2959
+ type: "string",
2960
+ description: "The immutable completion objective for the Ralph loop (required when mode is \"rfc\")."
2961
+ },
2962
+ maxRounds: {
2963
+ type: "number",
2964
+ description: "Optional round cap for the Ralph loop, bounded by the deployment ceiling."
2965
+ }
2966
+ },
2967
+ output: {
2968
+ schema: { oneOf: [{
2969
+ type: "object",
2970
+ properties: {
2971
+ runId: { type: "string" },
2972
+ agentsStarted: { type: "number" },
2973
+ result: { type: "json" }
2974
+ },
2975
+ additionalProperties: false
2976
+ }, errorVariant] },
2977
+ render: jsonRender
2978
+ },
2979
+ execute: (args, exec) => agentWorkflowExecutor(args, exec, deps)
2980
+ })
2981
+ ];
2982
+ }
2983
+
2984
+ //#endregion
2985
+ //#region src/llm-completion.ts
2986
+ /** Default output-token ceiling for one completion (cost guard; the caller may lower it, never raise past this). */
2987
+ const MAX_COMPLETION_TOKENS = 4096;
2988
+ /** Structured failure text for one non-`stop` finish (mirrors the session-title generator's finishError). */
2989
+ function finishError(finish) {
2990
+ switch (finish.kind) {
2991
+ case "stop": return "";
2992
+ case "error":
2993
+ case "aborted": return `llm_completion() call ${finish.kind}: ${String(finish.failure?.message ?? finish.kind)}`;
2994
+ case "max-tokens": return "llm_completion() output reached its maxTokens ceiling";
2995
+ case "tool-calls": return "llm_completion() model unexpectedly requested a tool (a bare call offers none)";
2996
+ default: return `llm_completion() unsupported finish reason ${JSON.stringify(finish.kind)}`;
2997
+ }
2998
+ }
2999
+ /**
3000
+ * Build the `llm_completion` tool. Input: `{ prompt, system?, maxTokens? }`;
3001
+ * output: the model's text (a bare string root), or a structured `{ error }`
3002
+ * object — never a thrown exception for bad input or a degraded finish.
3003
+ */
3004
+ /** Narrow a tool result to the success variant (for the model-facing render). */
3005
+ function isTextResult(value) {
3006
+ return typeof value === "object" && value !== null && value.ok === true && typeof value.text === "string";
3007
+ }
3008
+ function createLlmCompletionTool(deps) {
3009
+ return defineTool({
3010
+ name: "llm_completion",
3011
+ description: "One-shot stateless LLM call — no tools, no history, no agent. Give {prompt} (and optional {system}, {maxTokens}); get a discriminated result back: {ok:true,text} on success or {ok:false,error} on failure, so a programmatic caller can branch without shape guessing (a direct tool call renders just the text on success). For judge steps, extraction, and handoff compression inside one cell, without spawning a subagent.",
3012
+ parameters: {
3013
+ prompt: {
3014
+ type: "string",
3015
+ description: "The prompt for the one-shot call."
3016
+ },
3017
+ system: {
3018
+ type: "string",
3019
+ description: "Optional system prompt for the call."
3020
+ },
3021
+ maxTokens: {
3022
+ type: "integer",
3023
+ description: `Optional output-token ceiling for this call (default ${MAX_COMPLETION_TOKENS}, which is also the cap).`
3024
+ }
3025
+ },
3026
+ output: {
3027
+ schema: { oneOf: [{
3028
+ type: "object",
3029
+ properties: {
3030
+ ok: {
3031
+ type: "boolean",
3032
+ required: true
3033
+ },
3034
+ text: {
3035
+ type: "string",
3036
+ required: true
3037
+ }
3038
+ },
3039
+ additionalProperties: false
3040
+ }, {
3041
+ type: "object",
3042
+ properties: {
3043
+ ok: {
3044
+ type: "boolean",
3045
+ required: true
3046
+ },
3047
+ error: {
3048
+ type: "string",
3049
+ required: true
3050
+ }
3051
+ },
3052
+ additionalProperties: false
3053
+ }] },
3054
+ render: (_args, value) => [{
3055
+ type: "text",
3056
+ text: isTextResult(value) ? value.text : JSON.stringify(value, null, 2)
3057
+ }]
3058
+ },
3059
+ execute: async (args, exec) => {
3060
+ const a = args;
3061
+ const prompt = a["prompt"];
3062
+ if (typeof prompt !== "string" || prompt.length === 0) return {
3063
+ ok: false,
3064
+ error: "llm_completion() requires {\"prompt\": \"...\"} — the one-shot prompt"
3065
+ };
3066
+ const system = a["system"];
3067
+ if (system !== void 0 && typeof system !== "string") return {
3068
+ ok: false,
3069
+ error: "llm_completion() system must be a string"
3070
+ };
3071
+ const maxTokens = a["maxTokens"] === void 0 ? MAX_COMPLETION_TOKENS : a["maxTokens"];
3072
+ if (typeof maxTokens !== "number" || !Number.isSafeInteger(maxTokens) || maxTokens < 1 || maxTokens > MAX_COMPLETION_TOKENS) return {
3073
+ ok: false,
3074
+ error: `llm_completion() maxTokens must be a positive safe integer no greater than ${MAX_COMPLETION_TOKENS}`
3075
+ };
3076
+ const llm = deps.requireLlm();
3077
+ if (llm === void 0) return {
3078
+ ok: false,
3079
+ error: "llm_completion() is unavailable: no ctx.llm service is mounted in this composition"
3080
+ };
3081
+ const agent = exec.agent;
3082
+ const route = agent?.options;
3083
+ const provider = route?.provider;
3084
+ const model = route?.model;
3085
+ if (typeof provider !== "string" || provider.length === 0 || typeof model !== "string" || model.length === 0) return {
3086
+ ok: false,
3087
+ error: "llm_completion() requires a model route: the calling agent has no provider/model selected (a judge call runs on its caller's tier)"
3088
+ };
3089
+ const options = {
3090
+ provider,
3091
+ model,
3092
+ messages: [createUserMessage({
3093
+ content: [{
3094
+ type: "text",
3095
+ text: prompt
3096
+ }],
3097
+ source: { kind: "plugin:better-dsh" }
3098
+ })],
3099
+ maxTokens,
3100
+ ...system !== void 0 ? { system } : {},
3101
+ ...agent ? { sessionId: agent.session.id } : {},
3102
+ signal: exec.signal
3103
+ };
3104
+ const assembler = new BlockAssembler();
3105
+ try {
3106
+ for await (const chunk of llm.stream(options)) {
3107
+ exec.signal.throwIfAborted();
3108
+ assembler.push(chunk);
3109
+ }
3110
+ } catch (error) {
3111
+ return {
3112
+ ok: false,
3113
+ error: `llm_completion() failed: ${error instanceof Error ? error.message : String(error)}`
3114
+ };
3115
+ }
3116
+ const failure = finishError(assembler.finish);
3117
+ if (failure !== "") return {
3118
+ ok: false,
3119
+ error: failure
3120
+ };
3121
+ const blocks = assembler.blocks();
3122
+ if (blocks.some((block) => block.type === "tool-call")) return {
3123
+ ok: false,
3124
+ error: "llm_completion() output must contain text only"
3125
+ };
3126
+ const text = blocks.filter((block) => block.type === "text").map((block) => block.text).join(" ");
3127
+ if (text.trim().length === 0) return {
3128
+ ok: false,
3129
+ error: "llm_completion() produced no text"
3130
+ };
3131
+ return {
3132
+ ok: true,
3133
+ text
3134
+ };
3135
+ }
3136
+ });
3137
+ }
3138
+
3139
+ //#endregion
3140
+ //#region src/index.ts
3141
+ /** Cordis plugin name. */
3142
+ const name = "dashr-repl";
3143
+ /**
3144
+ * Required services. `replRuntime` is NOT listed: see the module doc — the
3145
+ * mode-dependent wait is declared inside {@link apply} instead, and the
3146
+ * execution path re-reads the service at use time with an actionable error.
3147
+ */
3148
+ const inject = ["tools"];
3149
+ /** Runtime schema. */
3150
+ const Config = Schema.intersect([DashrRuntime.Config, Schema.object({ maxParallelSubCalls: Schema.natural().min(1).default(10) })]);
3151
+ /** The model-facing name of the DASHR cell transport. */
3152
+ const EVAL_NAME = "eval";
3153
+ /**
3154
+ * The wire-mask deny list (design D1): the upstream delegation and
3155
+ * guidance tools DASHR displaces from the model's surface. The list feeds
3156
+ * ONE registry-level mechanism — `tools.restrict({deny})` on the agent's
3157
+ * own scope layer at session-start — which removes every name from ALL
3158
+ * registry projections at once (wire schemas, catalog, SDK, REPL bindings,
3159
+ * by-name dispatch): the restricted-away names are gone for the model on
3160
+ * every surface, not hidden per-presentation. Two exemptions are registry
3161
+ * facts, not list policy: a name the host never registered is skipped (a
3162
+ * restriction may only name inherited tools), and a name registered on the
3163
+ * agent's OWN layer (the child-scoped native `report`, this composition's
3164
+ * bridges below, never through the masked name. `subagent` is deliberately
3165
+ * NOT in this list (v0.2.1b): its standard-preset registration
3166
+ * (`modelSelectionSettings: true`) lands on the agent's OWN layer, outside
3167
+ * registry restriction reach, so it stays visible on every surface and the
3168
+ * control prompt annotates it as an alias of the `agent` delegation tool.
3169
+ * `skill` was REMOVED from this list (2026-09-12, user ruling): the native
3170
+ * skill tool stays visible and self-surfaces its session catalog
3171
+ * (`<available_skills>` is gated on the tool's registry visibility — masking
3172
+ * the tool silenced the catalog). dashr's dual pipeline keeps `read
3173
+ * skill://<name>` as the addressing form alongside native invocation.
3174
+ * own URL wrappers) is exempt from restrictions by construction — the
3175
+ * capability it carries stays reachable through the captured-definition
3176
+ * bridges below, never through the masked name.
3177
+ */
3178
+ const MASKED_TOOL_NAMES = new Set([
3179
+ "send_message",
3180
+ "report",
3181
+ "list_agents",
3182
+ "subagent_fork",
3183
+ "interrupt_agent",
3184
+ "workflow",
3185
+ "ralph"
3186
+ ]);
3187
+ /**
3188
+ * The effective deny list the session-start wiring restricts. An alias of
3189
+ * {@link MASKED_TOOL_NAMES} today; a config override (a deployment naming
3190
+ * its own mask) slots in HERE and nowhere else — the constant is the single
3191
+ * source, so the mask never drifts between capture, restrict, and the
3192
+ * bridges that read captured definitions.
3193
+ */
3194
+ const WIRE_MASKED_NAMES = MASKED_TOOL_NAMES;
3195
+ /**
3196
+ * The typed-rejection contract declared on EVERY flat tool namespace: a
3197
+ * failed tool call raises `ToolCallError` with `.toolName` set to the
3198
+ * binding global (= the tool name the model knows). Identical descriptors
3199
+ * may repeat across namespaces; the runtime materializes the class once.
3200
+ */
3201
+ const TOOL_CALL_ERROR_CLASS = {
3202
+ name: "ToolCallError",
3203
+ memberNameProperty: "toolName"
3204
+ };
3205
+ /**
3206
+ * The `dashr:escalation-guidance` CONTEXT order: sits inside the runtime-context snapshot
3207
+ * band between upstream `approval:policy` (115) and `subagent:delegation` (120) — the
3208
+ * sandbox policy statement is order 110, the approval policy 115. Re-check if upstream
3209
+ * adds context entries in this band (dsh-system-prompt CONTEXT_ORDERS).
3210
+ */
3211
+ const ESCALATION_GUIDANCE_ORDER = 116;
3212
+ /**
3213
+ * The `eval` tool's whole model-facing description, loaded at module time
3214
+ * from the sibling markdown file (editable without touching TS). It carries
3215
+ * ALL REPL guidance — cell semantics, the direct-vs-cell decision rule, the
3216
+ * delegation alias note, and the one-form bridge at the end.
3217
+ */
3218
+ const EVAL_DESCRIPTION = readFileSync(new URL("../eval-description.md", import.meta.url), "utf8");
3219
+ /** The `cell` parameter's model-facing description. */
3220
+ const EVAL_CELL_PARAM_DESCRIPTION = "The cell: one Python program body for the session-persistent scripting pad (top-level `await` works; top-level `return` is a SyntaxError — the cell runs in module scope).";
3221
+ /**
3222
+ * The `description` parameter's model-facing description: the UI label
3223
+ * contract, ported verbatim in shape from upstream `run_code` (the label
3224
+ * surfaces on the generic card as the call's always-visible title).
3225
+ */
3226
+ const EVAL_DESCRIPTION_PARAM_DESCRIPTION = "Clear, concise description of what this cell does in active voice, 5-10 words (shown in the UI). Examples: \"Load dataframe and summarize columns\"; \"Run test file and capture failures\"; \"Patch config key across cordis.yml files\".";
3227
+ /**
3228
+ * Thrown by `eval` when the cell itself failed — a program exception, a
3229
+ * budget expiry, an abort, or kernel death. Extends {@link HarnessError} with
3230
+ * the same `code: 'CODE_RUN_FAILED'` as upstream `CodeRunFailedError`, so
3231
+ * registry-side error taxonomy and session-log consumers see the shape they
3232
+ * already know; the registry's execution pipeline converts it into a
3233
+ * structured `isError` result whose text carries the failure kind plus the
3234
+ * captured logs, so the model can self-correct.
3235
+ */
3236
+ var DASHRRunFailedError = class extends HarnessError {
3237
+ constructor(message) {
3238
+ super(message, "CODE_RUN_FAILED");
3239
+ this.name = "DASHRRunFailedError";
3240
+ }
3241
+ };
3242
+ /**
3243
+ * Snapshot one binding call's argument as lossless JSON, then snapshot that
3244
+ * detached value again so dispatch and logging stay independent without
3245
+ * reintroducing structured-clone's platform-specific nesting limit. Ported
3246
+ * verbatim from upstream `code-mode.ts` (`jsonNormalizeArgs`).
3247
+ */
3248
+ function jsonNormalizeArgs(value) {
3249
+ let snapshot;
3250
+ try {
3251
+ snapshot = snapshotJsonValue(value);
3252
+ } catch (error) {
3253
+ throw new Error(`tool arguments must be lossless JSON: ${error instanceof Error ? error.message : String(error)}`);
3254
+ }
3255
+ if (snapshot === void 0) throw new Error("tool arguments must be lossless JSON (call the tool with an arguments object, e.g. `{}`)");
3256
+ const logged = snapshotJsonValue(snapshot);
3257
+ if (logged === void 0) throw new Error("tool arguments could not be detached for durable logging");
3258
+ return {
3259
+ dispatched: snapshot,
3260
+ logged
3261
+ };
3262
+ }
3263
+ /** Resolve the eval overlap cap at the config boundary (schemastery already validated the range; direct construction in tests bypasses it). */
3264
+ function resolveMaxParallelSubCalls(value) {
3265
+ const maxParallelSubCalls = value ?? 10;
3266
+ if (!Number.isInteger(maxParallelSubCalls) || maxParallelSubCalls < 1) throw new Error("dashr-repl: maxParallelSubCalls must be a positive integer");
3267
+ return maxParallelSubCalls;
3268
+ }
3269
+ /** Two-space JSON presentation, matching the shallow `eval` text contract (ported). */
3270
+ const JSON_INDENT = " ";
3271
+ /** ECMAScript caps `JSON.stringify`'s `space` string at ten characters; total indentation is capped there so formatted output stays linear (ported). */
3272
+ const MAX_JSON_INDENT_CHARS = 10;
3273
+ /** Render one non-string JSON root without recursive traversal or unbounded indentation growth (ported from upstream code-mode.ts). */
3274
+ function renderJsonValue(value) {
3275
+ const chunks = [];
3276
+ const tasks = [{
3277
+ kind: "value",
3278
+ value,
3279
+ depth: 0,
3280
+ compact: false
3281
+ }];
3282
+ for (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {
3283
+ if (task.kind === "text") {
3284
+ chunks.push(task.text);
3285
+ continue;
3286
+ }
3287
+ const current = task.value;
3288
+ if (current === null || typeof current === "boolean" || typeof current === "number") {
3289
+ chunks.push(String(current));
3290
+ continue;
3291
+ }
3292
+ if (typeof current === "string") {
3293
+ chunks.push(JSON.stringify(current));
3294
+ continue;
3295
+ }
3296
+ const compact = task.compact || (task.depth + 1) * 2 > MAX_JSON_INDENT_CHARS;
3297
+ const childDepth = task.depth + 1;
3298
+ if (Array.isArray(current)) {
3299
+ chunks.push("[");
3300
+ if (current.length === 0) {
3301
+ chunks.push("]");
3302
+ continue;
3303
+ }
3304
+ tasks.push({
3305
+ kind: "text",
3306
+ text: compact ? "]" : `\n${JSON_INDENT.repeat(task.depth)}]`
3307
+ });
3308
+ for (let index = current.length - 1; index >= 0; index--) {
3309
+ const item = current[index];
3310
+ if (item === void 0) throw new Error("dashr-repl: cannot render a sparse JSON array");
3311
+ tasks.push({
3312
+ kind: "value",
3313
+ value: item,
3314
+ depth: childDepth,
3315
+ compact
3316
+ });
3317
+ tasks.push({
3318
+ kind: "text",
3319
+ text: compact ? index === 0 ? "" : "," : `${index === 0 ? "\n" : ",\n"}${JSON_INDENT.repeat(childDepth)}`
3320
+ });
3321
+ }
3322
+ continue;
3323
+ }
3324
+ const keys = Object.keys(current);
3325
+ chunks.push("{");
3326
+ if (keys.length === 0) {
3327
+ chunks.push("}");
3328
+ continue;
3329
+ }
3330
+ tasks.push({
3331
+ kind: "text",
3332
+ text: compact ? "}" : `\n${JSON_INDENT.repeat(task.depth)}}`
3333
+ });
3334
+ for (let index = keys.length - 1; index >= 0; index--) {
3335
+ const key = keys[index];
3336
+ if (key === void 0) throw new Error("dashr-repl: cannot render a missing JSON object key");
3337
+ const item = current[key];
3338
+ if (item === void 0) throw new Error("dashr-repl: cannot render an undefined JSON object property");
3339
+ tasks.push({
3340
+ kind: "value",
3341
+ value: item,
3342
+ depth: childDepth,
3343
+ compact
3344
+ });
3345
+ tasks.push({
3346
+ kind: "text",
3347
+ text: compact ? `${index === 0 ? "" : ","}${JSON.stringify(key)}:` : `${index === 0 ? "\n" : ",\n"}${JSON_INDENT.repeat(childDepth)}${JSON.stringify(key)}: `
3348
+ });
3349
+ }
3350
+ }
3351
+ return chunks.join("");
3352
+ }
3353
+ /** Render one present cell completion value for the model-facing result text (ported). */
3354
+ function renderValue(value) {
3355
+ return typeof value === "string" ? value : renderJsonValue(value);
3356
+ }
3357
+ /**
3358
+ * Build the `eval` {@link ToolDefinition}: required `cell` and
3359
+ * `description` parameters, executed through the dispatch bridge described
3360
+ * in the module doc. Sub-calls ride the registry's exported staged scheduler
3361
+ * (`prepare`/`dispatch`/`finalize`/`finish`) under the native concurrency
3362
+ * contract; each sub-dispatch is logged for reconstruction
3363
+ * (`tool/ptc-dispatch-start` / `tool/ptc-dispatch`) while only the outer
3364
+ * curated result enters model history.
3365
+ * @param registry - the host tool registry (sub-calls go through its staged
3366
+ * scheduler, bindings cover its registered tools).
3367
+ * @param options - the bridge capabilities described above.
3368
+ * @returns the registry-ready definition.
3369
+ */
3370
+ function createRunCellTool(registry, options) {
3371
+ const { requireRuntime, maxParallel, shapeDispatchLog, warn } = options;
3372
+ return defineTool({
3373
+ name: EVAL_NAME,
3374
+ description: EVAL_DESCRIPTION,
3375
+ parameters: {
3376
+ cell: {
3377
+ type: "string",
3378
+ required: true,
3379
+ description: EVAL_CELL_PARAM_DESCRIPTION
3380
+ },
3381
+ description: {
3382
+ type: "string",
3383
+ required: true,
3384
+ description: EVAL_DESCRIPTION_PARAM_DESCRIPTION
3385
+ },
3386
+ timeout: {
3387
+ type: "number",
3388
+ description: "Optional wall-clock budget for this cell, in seconds; the cell is interrupted (then force-stopped) if it exceeds the budget. Omit to use the runtime default."
3389
+ },
3390
+ reset: {
3391
+ type: "boolean",
3392
+ description: "Optional: reset the persistent pad namespace to EMPTY before running — variables, imports, and definitions from earlier cells are discarded and the pad restarts fresh. Omit to keep the namespace."
3393
+ }
3394
+ },
3395
+ output: {
3396
+ schema: {
3397
+ type: "object",
3398
+ additionalProperties: false,
3399
+ properties: {
3400
+ logs: {
3401
+ type: "array",
3402
+ required: true,
3403
+ items: { type: "string" }
3404
+ },
3405
+ result: { type: "json" }
3406
+ }
3407
+ },
3408
+ render: (_args, value) => {
3409
+ const rendered = value.result === void 0 ? "" : renderValue(value.result);
3410
+ const parts = [value.logs.join("\n"), rendered].filter((part) => part.length > 0);
3411
+ return [{
3412
+ type: "text",
3413
+ text: parts.length > 0 ? parts.join("\n") : `(${EVAL_NAME} completed with no output)`
3414
+ }];
3415
+ }
3416
+ },
3417
+ async execute(args, exec) {
3418
+ if (args.description.trim().length === 0) throw new Error("dashr-repl: invalid description: expected a non-empty string");
3419
+ const runtime = requireRuntime();
3420
+ const runController = new AbortController();
3421
+ const onOuterAbort = () => {
3422
+ runController.abort(exec.signal.reason);
3423
+ };
3424
+ exec.signal.addEventListener("abort", onOuterAbort, { once: true });
3425
+ let dispatches = 0;
3426
+ const pendingQueue = [];
3427
+ const inFlight = /* @__PURE__ */ new Set();
3428
+ /** Tracked settle-event side work (log-content listener + append), drained at run settlement. */
3429
+ const logWork = /* @__PURE__ */ new Set();
3430
+ const commitQueue = [];
3431
+ let exclusiveActive = false;
3432
+ let driving = false;
3433
+ let driverRun = Promise.resolve();
3434
+ let wake;
3435
+ const wakeup = () => {
3436
+ const release = wake;
3437
+ wake = void 0;
3438
+ release?.();
3439
+ };
3440
+ /** The single ordered lane (ported; see the block comment above). */
3441
+ const drive = () => {
3442
+ if (driving) return driverRun;
3443
+ driving = true;
3444
+ driverRun = (async () => {
3445
+ try {
3446
+ for (;;) {
3447
+ const signal = new Promise((resolve$1) => {
3448
+ wake = resolve$1;
3449
+ });
3450
+ const commitHead = commitQueue[0];
3451
+ if (commitHead !== void 0 && commitHead.settled) {
3452
+ commitQueue.shift();
3453
+ await commitHead.commit();
3454
+ if (commitHead.mode === "exclusive") exclusiveActive = false;
3455
+ continue;
3456
+ }
3457
+ const head = pendingQueue[0];
3458
+ if (head !== void 0) {
3459
+ if (runController.signal.aborted) {
3460
+ pendingQueue.shift();
3461
+ head.abandon();
3462
+ continue;
3463
+ }
3464
+ const mode = head.classify();
3465
+ if (!exclusiveActive && (mode === "exclusive" ? inFlight.size === 0 : inFlight.size < maxParallel)) {
3466
+ if (mode === "exclusive") exclusiveActive = true;
3467
+ head.mode = mode;
3468
+ pendingQueue.shift();
3469
+ commitQueue.push(head);
3470
+ await head.start();
3471
+ const flight = head.flight.finally(() => {
3472
+ inFlight.delete(flight);
3473
+ wakeup();
3474
+ });
3475
+ inFlight.add(flight);
3476
+ continue;
3477
+ }
3478
+ }
3479
+ if (pendingQueue.length === 0 && commitQueue.length === 0 && inFlight.size === 0) return;
3480
+ await signal;
3481
+ }
3482
+ } catch (error) {
3483
+ warn(`dashr-repl: dispatch lane failed (${error instanceof Error ? error.message : String(error)}); settling queued dispatches as errors`);
3484
+ for (const entry of [...pendingQueue, ...commitQueue]) if (!entry.settled) entry.fail(error);
3485
+ pendingQueue.length = 0;
3486
+ commitQueue.length = 0;
3487
+ exclusiveActive = false;
3488
+ } finally {
3489
+ driving = false;
3490
+ wake = void 0;
3491
+ }
3492
+ })();
3493
+ return driverRun;
3494
+ };
3495
+ /** Every dispatch settled AND committed; nothing can start (the run is aborted at call time). */
3496
+ const drainDispatches = async () => {
3497
+ await drive();
3498
+ while (logWork.size > 0) await Promise.allSettled([...logWork]);
3499
+ };
3500
+ const runOver = () => runController.signal.aborted;
3501
+ const binding = (name$1) => async (rawArgs) => {
3502
+ if (runOver()) throw new Error(`${EVAL_NAME} run is over (${String(runController.signal.reason)}); ${name$1} not dispatched`);
3503
+ const normalized = jsonNormalizeArgs(rawArgs);
3504
+ const n = ++dispatches;
3505
+ const subCallId = toolCallId(`${String(exec.callId)}:code:${n}`);
3506
+ const input = {
3507
+ callId: subCallId,
3508
+ rootCallId: exec.rootCallId,
3509
+ name: name$1,
3510
+ arguments: normalized.dispatched,
3511
+ ...exec.agent ? { agent: exec.agent } : {},
3512
+ parent: exec.token,
3513
+ signal: runController.signal
3514
+ };
3515
+ const scheduler = registry[TOOL_RUNTIME_SCHEDULER];
3516
+ if (scheduler === void 0) {
3517
+ let resolvedFrom;
3518
+ try {
3519
+ resolvedFrom = createRequire(import.meta.url).resolve("@deepseek-ai/dsh-tools");
3520
+ } catch {
3521
+ resolvedFrom = "(unresolvable from the plugin position)";
3522
+ }
3523
+ throw new Error(`${EVAL_NAME}: the tools service mounted by this composition lacks the TOOL_RUNTIME_SCHEDULER symbol as this plugin sees it — REPL sub-dispatch cannot run. Most likely a dual-copy dsh-tools: the symbol keying the mounted ToolRuntime instance is not the symbol this plugin imported (named methods like executionMode keep working across copies; only the symbol-keyed field goes missing). This plugin resolves @deepseek-ai/dsh-tools from: ${resolvedFrom}. Check the deployed plugin's node_modules for stray @deepseek-ai entries (only schemastery and cosmokit belong there)`);
3524
+ }
3525
+ const outcome = await new Promise((resolve$1, reject) => {
3526
+ let parked;
3527
+ const settle = (result) => {
3528
+ resolve$1(result.isError ? {
3529
+ isError: true,
3530
+ message: result.error.message
3531
+ } : {
3532
+ isError: false,
3533
+ value: result.value
3534
+ });
3535
+ const agent = exec.agent;
3536
+ if (agent === void 0) return;
3537
+ const task = (async () => {
3538
+ const logged = await shapeDispatchLog({
3539
+ exec,
3540
+ agent,
3541
+ subCallId,
3542
+ name: name$1,
3543
+ isError: result.isError,
3544
+ content: result.content
3545
+ });
3546
+ agent.session.append("tool/ptc-dispatch", {
3547
+ rootCallId: exec.rootCallId,
3548
+ parentCallId: exec.callId,
3549
+ subCallId,
3550
+ name: name$1,
3551
+ arguments: normalized.logged,
3552
+ isError: result.isError,
3553
+ content: logged
3554
+ });
3555
+ })().finally(() => {
3556
+ logWork.delete(task);
3557
+ });
3558
+ logWork.add(task);
3559
+ };
3560
+ const settleError = (error) => {
3561
+ settle({
3562
+ isError: true,
3563
+ error: { message: error instanceof Error ? error.message : String(error) },
3564
+ content: []
3565
+ });
3566
+ };
3567
+ pendingQueue.push({
3568
+ flight: Promise.resolve(),
3569
+ settled: false,
3570
+ classify: () => registry.executionMode(input).kind,
3571
+ abandon: () => {
3572
+ reject(/* @__PURE__ */ new Error(`${EVAL_NAME} run is over (${String(runController.signal.reason)}); ${name$1} tool call abandoned`));
3573
+ },
3574
+ fail(error) {
3575
+ if (this.settled) return;
3576
+ this.settled = true;
3577
+ settleError(error);
3578
+ },
3579
+ async start() {
3580
+ exec.agent?.session.append("tool/ptc-dispatch-start", {
3581
+ rootCallId: exec.rootCallId,
3582
+ parentCallId: exec.callId,
3583
+ subCallId,
3584
+ name: name$1,
3585
+ arguments: normalized.logged
3586
+ });
3587
+ try {
3588
+ const prepared = await scheduler.prepare(input);
3589
+ if (prepared.kind === "dispatch") {
3590
+ this.flight = scheduler.dispatch(prepared.exec).then((dispatchOutcome) => {
3591
+ parked = {
3592
+ kind: dispatchOutcome.kind,
3593
+ exec: prepared.exec,
3594
+ result: dispatchOutcome.result
3595
+ };
3596
+ this.settled = true;
3597
+ }, (error) => {
3598
+ this.settled = true;
3599
+ settleError(error);
3600
+ });
3601
+ return;
3602
+ }
3603
+ parked = {
3604
+ kind: prepared.kind,
3605
+ exec: prepared.exec,
3606
+ result: prepared.result
3607
+ };
3608
+ this.settled = true;
3609
+ } catch (error) {
3610
+ this.settled = true;
3611
+ settleError(error);
3612
+ }
3613
+ },
3614
+ async commit() {
3615
+ if (parked === void 0) return;
3616
+ try {
3617
+ const result = parked.kind === "post-result" ? await scheduler.finalize(parked.exec, parked.result) : scheduler.finish(parked.exec, parked.result);
3618
+ for (const context of result.additionalContexts ?? []) exec.deferContext(context);
3619
+ if (result.concludesTurn) exec.concludeTurn();
3620
+ settle(result);
3621
+ while (logWork.size > maxParallel) await Promise.race(logWork);
3622
+ } catch (error) {
3623
+ settleError(error);
3624
+ }
3625
+ }
3626
+ });
3627
+ wakeup();
3628
+ drive();
3629
+ });
3630
+ if (runOver()) throw new Error(`${EVAL_NAME} run is over (${String(runController.signal.reason)}); ${name$1} result discarded`);
3631
+ if (outcome.isError) throw new Error(outcome.message);
3632
+ return outcome.value;
3633
+ };
3634
+ const toolFunctions = {};
3635
+ for (const schema of registry.schemas(exec.agent)) {
3636
+ if (schema.name === EVAL_NAME) continue;
3637
+ if (!isFlatBindableName(schema.name)) continue;
3638
+ toolFunctions[schema.name] = async (args$1) => binding(schema.name)(args$1);
3639
+ }
3640
+ try {
3641
+ let result;
3642
+ try {
3643
+ result = await runtime.run({
3644
+ program: args.cell,
3645
+ bindings: [{
3646
+ global: "tool",
3647
+ functions: { ...toolFunctions },
3648
+ errorClass: TOOL_CALL_ERROR_CLASS
3649
+ }],
3650
+ signal: runController.signal,
3651
+ ...exec.agent ? { principal: exec.agent.id } : {},
3652
+ ...exec.agent ? { cwd: exec.agent.session.header.cwd } : {},
3653
+ ...typeof args.timeout === "number" && Number.isFinite(args.timeout) && args.timeout > 0 ? { timeoutMs: Math.max(1, Math.floor(args.timeout * 1e3)) } : {},
3654
+ ...args.reset === true ? { reset: true } : {}
3655
+ });
3656
+ } finally {
3657
+ runController.abort(`${EVAL_NAME} settled`);
3658
+ await drainDispatches();
3659
+ }
3660
+ if (result.error) {
3661
+ const logsText = result.logs.length > 0 ? `\nCaptured output:\n${result.logs.join("\n")}` : "";
3662
+ throw new DASHRRunFailedError(`code run failed (${result.error.kind}): ${result.error.message}${logsText}`);
3663
+ }
3664
+ return {
3665
+ logs: result.logs,
3666
+ ...result.value !== void 0 ? { result: result.value } : {}
3667
+ };
3668
+ } finally {
3669
+ exec.signal.removeEventListener("abort", onOuterAbort);
3670
+ }
3671
+ },
3672
+ presentCall: (args) => ({
3673
+ card: "generic",
3674
+ title: args.description,
3675
+ kind: "execute",
3676
+ rawInput: args.cell
3677
+ })
3678
+ });
3679
+ }
3680
+ /**
3681
+ * Declare the DASHR cell presentation for every agent this composition
3682
+ * covers: the `eval` transport tool, the model-direct collapse guard, and the assembly filter that
3683
+ * leaves `eval` the only contributed tool schema.
3684
+ *
3685
+ * Mount through a preset's standing scope (`agent.cordis.yml` include row);
3686
+ * mounting unscoped is legal for a whole-process DASHR deployment and gives
3687
+ * the same shape at the global layer.
3688
+ * @param ctx - the mounting composition's context (a preset's standing scope).
3689
+ * @param config - the plugin config.
3690
+ */
3691
+ /** The runtime slice's config keys, mirrored from `DashrRuntime.Config` in `./runtime.ts`. */
3692
+ const RUNTIME_CONFIG_KEYS = [
3693
+ "python",
3694
+ "cwd",
3695
+ "startupTimeoutMs",
3696
+ "runTimeoutMs",
3697
+ "interruptGraceMs",
3698
+ "interruptConfirmMs",
3699
+ "disposeTimeoutMs",
3700
+ "snapshotTimeoutMs",
3701
+ "maxOutputBytes",
3702
+ "snapshotDir",
3703
+ "snapshotSizeCapBytes",
3704
+ "username",
3705
+ "kernelEnvDir",
3706
+ "kernelPythonVersion",
3707
+ "kernelAutoInstall"
3708
+ ];
3709
+ /** The runtime slice of the merged config — the keys `DashrRuntime` owns. */
3710
+ function pickRuntimeConfig(config) {
3711
+ const out = {};
3712
+ for (const key of RUNTIME_CONFIG_KEYS) out[key] = config[key];
3713
+ return out;
3714
+ }
3715
+ function apply(ctx, config) {
3716
+ ctx.plugin(DashrRuntime, pickRuntimeConfig(config));
3717
+ const logger = ctx.logger("dashr-repl");
3718
+ const maxParallel = resolveMaxParallelSubCalls(config.maxParallelSubCalls);
3719
+ {
3720
+ const kernelConfig = pickRuntimeConfig(config);
3721
+ resolveKernelEnv({
3722
+ python: kernelConfig.python,
3723
+ venvDir: kernelConfig.kernelEnvDir,
3724
+ pythonVersion: kernelConfig.kernelPythonVersion,
3725
+ autoInstall: kernelConfig.kernelAutoInstall ?? true,
3726
+ log: (level, message) => {
3727
+ logger[level](message);
3728
+ }
3729
+ }).catch((error) => {
3730
+ logger.error(`dashr-repl: spin-up kernel check failed (non-blocking): ${error instanceof Error ? error.message : String(error)}`);
3731
+ });
3732
+ }
3733
+ ctx.inject(["replRuntime"], (runtimeCtx) => {
3734
+ const requireRuntime = () => {
3735
+ const runtime = runtimeCtx.get("replRuntime");
3736
+ if (!runtime) throw new Error("dashr-repl: eval requires an replRuntime service — load a ctx.replRuntime implementation in this composition (dashr-repl mounts one at apply)");
3737
+ if (runtime.language !== "python") throw new Error(`dashr-repl: no cell SDK for runtime language ${JSON.stringify(runtime.language)} (dashr-repl presents Python only; got a ${JSON.stringify(runtime.language)} runtime under ctx.replRuntime)`);
3738
+ return runtime;
3739
+ };
3740
+ const registry = runtimeCtx.tools;
3741
+ const systemPrompt = runtimeCtx.get("systemPrompt");
3742
+ if (!systemPrompt) throw new Error("dashr-repl: ctx.systemPrompt is required beside ctx.tools (the tools service itself depends on it) — this composition mounted tools without a system prompt registry");
3743
+ const shapeDispatchLog = async (dispatch) => {
3744
+ try {
3745
+ const own = await runtimeCtx.waterfall(scopeTarget(registry, dispatch.agent), "dashr/repl-dispatch-log", dispatch, () => Promise.resolve(dispatch.content));
3746
+ return await runtimeCtx.waterfall(scopeTarget(registry, dispatch.agent), "tools/ptc-dispatch-log", dispatch, () => Promise.resolve(own));
3747
+ } catch (error) {
3748
+ logger.warn(`dashr-repl: dispatch-log listener failed for ${dispatch.name}: ${error instanceof Error ? error.message : String(error)}; logging the original settled content`);
3749
+ return dispatch.content;
3750
+ }
3751
+ };
3752
+ const requireSubagents = () => runtimeCtx.get("subagents");
3753
+ let serviceForAgent;
3754
+ import("@deepseek-ai/dsh-agent-presets").then((mod) => {
3755
+ serviceForAgent = mod.serviceForAgent;
3756
+ }, () => {});
3757
+ const requireWorkflowEngine = (agent) => {
3758
+ if (agent !== void 0 && serviceForAgent !== void 0) {
3759
+ const preset = serviceForAgent(runtimeCtx, agent, "workflowEngine");
3760
+ if (preset !== void 0) return preset;
3761
+ }
3762
+ return runtimeCtx.get("workflowEngine");
3763
+ };
3764
+ runtimeCtx.tools.register(createRunCellTool(registry, {
3765
+ requireRuntime,
3766
+ maxParallel,
3767
+ shapeDispatchLog,
3768
+ warn: (message) => logger.warn(message)
3769
+ }));
3770
+ for (const bridgeTool of createAgentBridgeTools({
3771
+ requireSubagents,
3772
+ requireWorkflowEngine
3773
+ })) runtimeCtx.tools.register(bridgeTool);
3774
+ runtimeCtx.tools.register(createLlmCompletionTool({ requireLlm: () => runtimeCtx.get("llm") }));
3775
+ const wireMasked = /* @__PURE__ */ new WeakSet();
3776
+ runtimeCtx.on("agent/created", ({ agent }) => {
3777
+ if (wireMasked.has(agent)) return void 0;
3778
+ wireMasked.add(agent);
3779
+ try {
3780
+ captureAllTools(runtimeCtx, agent);
3781
+ const visible = new Set(agent.ctx.tools.schemas(agent).map((schema) => schema.name));
3782
+ const deny = [...WIRE_MASKED_NAMES].filter((name$1) => visible.has(name$1));
3783
+ if (deny.length === 0) return void 0;
3784
+ try {
3785
+ agent.ctx.tools.restrict({ deny });
3786
+ return;
3787
+ } catch {}
3788
+ for (const name$1 of deny) try {
3789
+ agent.ctx.tools.restrict({ deny: [name$1] });
3790
+ } catch {}
3791
+ } catch (error) {
3792
+ logger.warn(`dashr-repl: wire mask failed for agent ${agent.id}: ${error instanceof Error ? error.message : String(error)}`);
3793
+ }
3794
+ });
3795
+ systemPrompt.context({
3796
+ name: "dashr:escalation-guidance",
3797
+ order: ESCALATION_GUIDANCE_ORDER,
3798
+ text: (context) => {
3799
+ const session = context.agent?.session;
3800
+ if (session === void 0) return "";
3801
+ const sandboxPolicy = runtimeCtx.get("sandboxPolicy");
3802
+ if (!sandboxPolicy) return "";
3803
+ return sandboxPolicy.resolve({ session }).mode === "workspace-write" ? "A sandbox-deniable/denied call may be escalated with `sandbox_permissions=\"danger-full-access\"` and a one-line `justification`; the runtime will prompt for user approval. Escalation and its approval/denial are per-call." : "";
3804
+ }
3805
+ });
3806
+ });
3807
+ }
3808
+ var src_default = {
3809
+ name,
3810
+ inject,
3811
+ Config,
3812
+ apply
3813
+ };
3814
+
3815
+ //#endregion
3816
+ export { Config, DASHRRunFailedError, DashrRuntime, ESCALATION_GUIDANCE_ORDER, EVAL_NAME, MASKED_TOOL_NAMES, ReplRuntime, WIRE_MASKED_NAMES, apply, createRunCellTool, src_default as default, inject, name, resolveMaxParallelSubCalls };