better-dsh 0.2.3 → 0.2.4-b

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 (406) hide show
  1. package/cordis.patch.yml +47 -16
  2. package/docs/10_plans/2026-09-23-remote-execution-framework.md +236 -0
  3. package/docs/10_plans/2026-09-23-remote-framework-impl.md +2083 -0
  4. package/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
  5. package/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
  6. package/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
  7. package/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
  8. package/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
  9. package/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
  10. package/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
  11. package/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
  12. package/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
  13. package/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
  14. package/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
  15. package/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
  16. package/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
  17. package/docs/50_test-reports/2026-09-23-remote-framework/345/256/236/346/265/213/346/212/245/345/221/212.md +92 -0
  18. package/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
  19. package/docs/50_test-reports/upstream-dsh-0.1.3-alpha.2-local-test-report.md +44 -0
  20. package/docs/50_test-reports/upstream-dsh-0.1.3-alpha.2-report.md +110 -0
  21. package/docs/50_test-reports/upstream-dsh-0.1.5-rc.2-local-test-report.md +79 -0
  22. package/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
  23. package/docs/50_test-reports/v0.2.3c-mobile-wave/345/256/236/346/265/213/346/212/245/345/221/212.md +47 -0
  24. package/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
  25. package/docs/specs/agent/spec.md +54 -0
  26. package/docs/specs/ast/spec.md +34 -0
  27. package/docs/specs/compaction-recall/spec.md +46 -0
  28. package/docs/specs/ctx/spec.md +107 -0
  29. package/docs/specs/dsh/spec.md +47 -0
  30. package/docs/specs/dvc/spec.md +87 -0
  31. package/docs/specs/escalation-guidance/spec.md +44 -0
  32. package/docs/specs/fs-scheme-resolution/spec.md +37 -0
  33. package/docs/specs/hash-edit/spec.md +41 -0
  34. package/docs/specs/http-read/spec.md +73 -0
  35. package/docs/specs/kernel-provisioning/spec.md +53 -0
  36. package/docs/specs/lsp/spec.md +121 -0
  37. package/docs/specs/mobile-layout/spec.md +108 -0
  38. package/docs/specs/model-failover/spec.md +20 -0
  39. package/docs/specs/plugins-page-components/spec.md +79 -0
  40. package/docs/specs/preact-ui-shell/spec.md +22 -0
  41. package/docs/specs/repl-dispatch-resilience/spec.md +21 -0
  42. package/docs/specs/skill/spec.md +58 -0
  43. package/docs/specs/tool-surface/spec.md +222 -0
  44. package/docs/specs/url-schema/spec.md +148 -0
  45. package/docs/specs/web-trust-fence/spec.md +43 -0
  46. package/docs/upstream-dsh-0.1.5-rc.2-report.md +156 -0
  47. package/dsh-docs/AGENTS.md +75 -0
  48. package/dsh-docs/agent-lifecycle.md +84 -0
  49. package/dsh-docs/agent-lifecycle.zh.md +86 -0
  50. package/dsh-docs/api-gateway.md +164 -0
  51. package/dsh-docs/api-gateway.zh.md +164 -0
  52. package/dsh-docs/architecture.md +150 -0
  53. package/dsh-docs/architecture.zh.md +154 -0
  54. package/dsh-docs/capability-seams.md +543 -0
  55. package/dsh-docs/capability-seams.zh.md +545 -0
  56. package/dsh-docs/config-catalog.md +3473 -0
  57. package/dsh-docs/config-catalog.zh.md +3474 -0
  58. package/dsh-docs/cookbook/adding-a-package.md +117 -0
  59. package/dsh-docs/cookbook/adding-a-package.zh.md +119 -0
  60. package/dsh-docs/cookbook/adding-a-remote-api.md +197 -0
  61. package/dsh-docs/cookbook/adding-a-remote-api.zh.md +197 -0
  62. package/dsh-docs/cookbook/adding-a-session-format-version.md +109 -0
  63. package/dsh-docs/cookbook/adding-a-session-format-version.zh.md +109 -0
  64. package/dsh-docs/cookbook/adding-a-settings-card.md +102 -0
  65. package/dsh-docs/cookbook/adding-a-settings-card.zh.md +102 -0
  66. package/dsh-docs/cookbook/adding-a-tool.md +101 -0
  67. package/dsh-docs/cookbook/adding-a-tool.zh.md +103 -0
  68. package/dsh-docs/cookbook/adding-a-vendored-package.md +59 -0
  69. package/dsh-docs/cookbook/adding-a-vendored-package.zh.md +59 -0
  70. package/dsh-docs/cookbook/adding-an-llm-adapter.md +43 -0
  71. package/dsh-docs/cookbook/adding-an-llm-adapter.zh.md +43 -0
  72. package/dsh-docs/cookbook/extension-cookbook.md +132 -0
  73. package/dsh-docs/cookbook/extension-cookbook.zh.md +136 -0
  74. package/dsh-docs/cookbook/maintaining-dsh-code-review.md +64 -0
  75. package/dsh-docs/cookbook/maintaining-dsh-code-review.zh.md +64 -0
  76. package/dsh-docs/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
  77. package/dsh-docs/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
  78. package/dsh-docs/cordis-api/context.md +364 -0
  79. package/dsh-docs/cordis-api/context.zh.md +366 -0
  80. package/dsh-docs/cordis-api/events.md +207 -0
  81. package/dsh-docs/cordis-api/events.zh.md +209 -0
  82. package/dsh-docs/cordis-api/fiber.md +375 -0
  83. package/dsh-docs/cordis-api/fiber.zh.md +377 -0
  84. package/dsh-docs/cordis-api/inherited.md +39 -0
  85. package/dsh-docs/cordis-api/registry.md +152 -0
  86. package/dsh-docs/cordis-api/registry.zh.md +154 -0
  87. package/dsh-docs/cordis-api/service.md +102 -0
  88. package/dsh-docs/cordis-api/service.zh.md +104 -0
  89. package/dsh-docs/cordis-primer.md +45 -0
  90. package/dsh-docs/cordis-primer.zh.md +51 -0
  91. package/dsh-docs/cordis-tutorial/01-first-plugin.md +95 -0
  92. package/dsh-docs/cordis-tutorial/01-first-plugin.zh.md +95 -0
  93. package/dsh-docs/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  94. package/dsh-docs/cordis-tutorial/02-lifecycle-and-effects.zh.md +98 -0
  95. package/dsh-docs/cordis-tutorial/03-services.md +98 -0
  96. package/dsh-docs/cordis-tutorial/03-services.zh.md +98 -0
  97. package/dsh-docs/cordis-tutorial/04-events.md +144 -0
  98. package/dsh-docs/cordis-tutorial/04-events.zh.md +144 -0
  99. package/dsh-docs/cordis-tutorial/05-config.md +84 -0
  100. package/dsh-docs/cordis-tutorial/05-config.zh.md +84 -0
  101. package/dsh-docs/cordis-tutorial/06-composition-and-hmr.md +113 -0
  102. package/dsh-docs/cordis-tutorial/06-composition-and-hmr.zh.md +113 -0
  103. package/dsh-docs/cordis-tutorial/07-into-the-harness.md +108 -0
  104. package/dsh-docs/cordis-tutorial/07-into-the-harness.zh.md +108 -0
  105. package/dsh-docs/cordis-tutorial/index.md +60 -0
  106. package/dsh-docs/cordis-tutorial/index.zh.md +62 -0
  107. package/dsh-docs/deepseek-llm-api-wire-extensions.md +163 -0
  108. package/dsh-docs/deepseek-llm-api-wire-extensions.zh.md +163 -0
  109. package/dsh-docs/defensive-patterns.md +33 -0
  110. package/dsh-docs/defensive-patterns.zh.md +35 -0
  111. package/dsh-docs/development.md +167 -0
  112. package/dsh-docs/development.zh.md +173 -0
  113. package/dsh-docs/event-producer-consumer.md +86 -0
  114. package/dsh-docs/event-producer-consumer.zh.md +88 -0
  115. package/dsh-docs/glossary.md +45 -0
  116. package/dsh-docs/glossary.zh.md +45 -0
  117. package/dsh-docs/graph-atlas.md +22 -0
  118. package/dsh-docs/graph-atlas.zh.md +24 -0
  119. package/dsh-docs/i18n/README.md +60 -0
  120. package/dsh-docs/i18n/README.zh.md +62 -0
  121. package/dsh-docs/i18n/style-samples.md +87 -0
  122. package/dsh-docs/i18n/terminology.md +214 -0
  123. package/dsh-docs/i18n/translation-prompt.md +263 -0
  124. package/dsh-docs/i18n/translation-rules.md +69 -0
  125. package/dsh-docs/i18n/translation-rules.zh.md +69 -0
  126. package/dsh-docs/module-graph.md +1411 -0
  127. package/dsh-docs/module-graph.zh.md +1413 -0
  128. package/dsh-docs/persistence-catalog.md +1075 -0
  129. package/dsh-docs/persistence-catalog.zh.md +1077 -0
  130. package/dsh-docs/postmortem/0001-acp-default-export-drops-inject.md +113 -0
  131. package/dsh-docs/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
  132. package/dsh-docs/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
  133. package/dsh-docs/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
  134. package/dsh-docs/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
  135. package/dsh-docs/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
  136. package/dsh-docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
  137. package/dsh-docs/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
  138. package/dsh-docs/postmortem/README.md +18 -0
  139. package/dsh-docs/postmortem/README.zh.md +18 -0
  140. package/dsh-docs/rescope.md +53 -0
  141. package/dsh-docs/rescope.zh.md +53 -0
  142. package/dsh-docs/session-format-status.md +47 -0
  143. package/dsh-docs/session-format-status.zh.md +47 -0
  144. package/dsh-docs/subsystems/README.md +61 -0
  145. package/dsh-docs/subsystems/README.zh.md +61 -0
  146. package/dsh-docs/subsystems/agent-team.md +207 -0
  147. package/dsh-docs/subsystems/agent-team.zh.md +207 -0
  148. package/dsh-docs/subsystems/approval.md +170 -0
  149. package/dsh-docs/subsystems/approval.zh.md +170 -0
  150. package/dsh-docs/subsystems/attachment.md +351 -0
  151. package/dsh-docs/subsystems/attachment.zh.md +351 -0
  152. package/dsh-docs/subsystems/client-modules.md +168 -0
  153. package/dsh-docs/subsystems/client-modules.zh.md +168 -0
  154. package/dsh-docs/subsystems/client-resources.md +91 -0
  155. package/dsh-docs/subsystems/client-resources.zh.md +91 -0
  156. package/dsh-docs/subsystems/code-runtime.md +195 -0
  157. package/dsh-docs/subsystems/code-runtime.zh.md +195 -0
  158. package/dsh-docs/subsystems/commands.md +219 -0
  159. package/dsh-docs/subsystems/commands.zh.md +219 -0
  160. package/dsh-docs/subsystems/compaction.md +238 -0
  161. package/dsh-docs/subsystems/compaction.zh.md +238 -0
  162. package/dsh-docs/subsystems/conversation.md +258 -0
  163. package/dsh-docs/subsystems/conversation.zh.md +258 -0
  164. package/dsh-docs/subsystems/core.md +1209 -0
  165. package/dsh-docs/subsystems/core.zh.md +1219 -0
  166. package/dsh-docs/subsystems/credentials.md +329 -0
  167. package/dsh-docs/subsystems/credentials.zh.md +329 -0
  168. package/dsh-docs/subsystems/extensions.md +382 -0
  169. package/dsh-docs/subsystems/extensions.zh.md +382 -0
  170. package/dsh-docs/subsystems/feedback.md +266 -0
  171. package/dsh-docs/subsystems/feedback.zh.md +266 -0
  172. package/dsh-docs/subsystems/filesystem.md +505 -0
  173. package/dsh-docs/subsystems/filesystem.zh.md +505 -0
  174. package/dsh-docs/subsystems/goal.md +277 -0
  175. package/dsh-docs/subsystems/goal.zh.md +277 -0
  176. package/dsh-docs/subsystems/invariants.md +88 -0
  177. package/dsh-docs/subsystems/invariants.zh.md +88 -0
  178. package/dsh-docs/subsystems/jobs.md +290 -0
  179. package/dsh-docs/subsystems/jobs.zh.md +290 -0
  180. package/dsh-docs/subsystems/llm-streaming.md +1080 -0
  181. package/dsh-docs/subsystems/llm-streaming.zh.md +1086 -0
  182. package/dsh-docs/subsystems/lsp.md +202 -0
  183. package/dsh-docs/subsystems/lsp.zh.md +202 -0
  184. package/dsh-docs/subsystems/permission-presets.md +131 -0
  185. package/dsh-docs/subsystems/permission-presets.zh.md +131 -0
  186. package/dsh-docs/subsystems/persistence.md +395 -0
  187. package/dsh-docs/subsystems/persistence.zh.md +395 -0
  188. package/dsh-docs/subsystems/plan.md +87 -0
  189. package/dsh-docs/subsystems/plan.zh.md +87 -0
  190. package/dsh-docs/subsystems/sandbox.md +220 -0
  191. package/dsh-docs/subsystems/sandbox.zh.md +220 -0
  192. package/dsh-docs/subsystems/schedule.md +192 -0
  193. package/dsh-docs/subsystems/schedule.zh.md +192 -0
  194. package/dsh-docs/subsystems/scope.md +59 -0
  195. package/dsh-docs/subsystems/scope.zh.md +59 -0
  196. package/dsh-docs/subsystems/session-projection.md +354 -0
  197. package/dsh-docs/subsystems/session-projection.zh.md +354 -0
  198. package/dsh-docs/subsystems/session-query.md +509 -0
  199. package/dsh-docs/subsystems/session-query.zh.md +509 -0
  200. package/dsh-docs/subsystems/session-reference.md +219 -0
  201. package/dsh-docs/subsystems/session-reference.zh.md +219 -0
  202. package/dsh-docs/subsystems/session-telemetry.md +194 -0
  203. package/dsh-docs/subsystems/session-telemetry.zh.md +194 -0
  204. package/dsh-docs/subsystems/session-title.md +204 -0
  205. package/dsh-docs/subsystems/session-title.zh.md +204 -0
  206. package/dsh-docs/subsystems/session.md +1155 -0
  207. package/dsh-docs/subsystems/session.zh.md +1159 -0
  208. package/dsh-docs/subsystems/settings.md +405 -0
  209. package/dsh-docs/subsystems/settings.zh.md +405 -0
  210. package/dsh-docs/subsystems/shell.md +303 -0
  211. package/dsh-docs/subsystems/shell.zh.md +303 -0
  212. package/dsh-docs/subsystems/sidebar-right.md +148 -0
  213. package/dsh-docs/subsystems/sidebar-right.zh.md +148 -0
  214. package/dsh-docs/subsystems/skills.md +354 -0
  215. package/dsh-docs/subsystems/skills.zh.md +354 -0
  216. package/dsh-docs/subsystems/slots.md +175 -0
  217. package/dsh-docs/subsystems/slots.zh.md +175 -0
  218. package/dsh-docs/subsystems/spill.md +117 -0
  219. package/dsh-docs/subsystems/spill.zh.md +117 -0
  220. package/dsh-docs/subsystems/storage.md +260 -0
  221. package/dsh-docs/subsystems/storage.zh.md +260 -0
  222. package/dsh-docs/subsystems/subagent.md +766 -0
  223. package/dsh-docs/subsystems/subagent.zh.md +770 -0
  224. package/dsh-docs/subsystems/subprocess.md +324 -0
  225. package/dsh-docs/subsystems/subprocess.zh.md +324 -0
  226. package/dsh-docs/subsystems/system-prompt.md +220 -0
  227. package/dsh-docs/subsystems/system-prompt.zh.md +220 -0
  228. package/dsh-docs/subsystems/terminal.md +184 -0
  229. package/dsh-docs/subsystems/terminal.zh.md +184 -0
  230. package/dsh-docs/subsystems/todo.md +32 -0
  231. package/dsh-docs/subsystems/todo.zh.md +32 -0
  232. package/dsh-docs/subsystems/token-meter.md +105 -0
  233. package/dsh-docs/subsystems/token-meter.zh.md +105 -0
  234. package/dsh-docs/subsystems/tools.md +720 -0
  235. package/dsh-docs/subsystems/tools.zh.md +720 -0
  236. package/dsh-docs/subsystems/typert.md +343 -0
  237. package/dsh-docs/subsystems/typert.zh.md +343 -0
  238. package/dsh-docs/subsystems/user-questions.md +178 -0
  239. package/dsh-docs/subsystems/user-questions.zh.md +178 -0
  240. package/dsh-docs/subsystems/web-client.md +95 -0
  241. package/dsh-docs/subsystems/web-client.zh.md +95 -0
  242. package/dsh-docs/subsystems/web-server.md +154 -0
  243. package/dsh-docs/subsystems/web-server.zh.md +154 -0
  244. package/dsh-docs/subsystems/web.md +206 -0
  245. package/dsh-docs/subsystems/web.zh.md +206 -0
  246. package/dsh-docs/subsystems/webhook.md +70 -0
  247. package/dsh-docs/subsystems/webhook.zh.md +70 -0
  248. package/dsh-docs/subsystems/workflow.md +278 -0
  249. package/dsh-docs/subsystems/workflow.zh.md +278 -0
  250. package/dsh-docs/subsystems/workspace.md +321 -0
  251. package/dsh-docs/subsystems/workspace.zh.md +321 -0
  252. package/dsh-docs/testing.md +54 -0
  253. package/dsh-docs/testing.zh.md +54 -0
  254. package/dsh-docs/tool-catalog.md +2225 -0
  255. package/dsh-docs/tool-catalog.zh.md +2233 -0
  256. package/dsh-docs/tool-execution-pipeline.md +62 -0
  257. package/dsh-docs/tool-execution-pipeline.zh.md +64 -0
  258. package/dsh-docs/user/develop/basic/config.md +106 -0
  259. package/dsh-docs/user/develop/basic/config.zh.md +106 -0
  260. package/dsh-docs/user/develop/basic/index.md +144 -0
  261. package/dsh-docs/user/develop/basic/index.zh.md +144 -0
  262. package/dsh-docs/user/develop/basic/publish.md +183 -0
  263. package/dsh-docs/user/develop/basic/publish.zh.md +183 -0
  264. package/dsh-docs/user/develop/basic/tool.md +52 -0
  265. package/dsh-docs/user/develop/basic/tool.zh.md +52 -0
  266. package/dsh-docs/user/develop/framework/events.md +143 -0
  267. package/dsh-docs/user/develop/framework/events.zh.md +143 -0
  268. package/dsh-docs/user/develop/framework/index.md +137 -0
  269. package/dsh-docs/user/develop/framework/index.zh.md +137 -0
  270. package/dsh-docs/user/develop/framework/service.md +148 -0
  271. package/dsh-docs/user/develop/framework/service.zh.md +150 -0
  272. package/dsh-docs/user/develop/practice/dynamic-cordis.md +15 -0
  273. package/dsh-docs/user/develop/practice/dynamic-cordis.zh.md +15 -0
  274. package/dsh-docs/user/develop/practice/index.md +155 -0
  275. package/dsh-docs/user/develop/practice/index.zh.md +155 -0
  276. package/dsh-docs/user/develop/practice/llm-adapter.md +189 -0
  277. package/dsh-docs/user/develop/practice/llm-adapter.zh.md +189 -0
  278. package/dsh-docs/user/guide/github-review.md +102 -0
  279. package/dsh-docs/user/guide/github-review.zh.md +102 -0
  280. package/dsh-docs/user/guide/index.md +30 -0
  281. package/dsh-docs/user/guide/index.zh.md +30 -0
  282. package/dsh-docs/user/guide/mcp-memory.md +101 -0
  283. package/dsh-docs/user/guide/mcp-memory.zh.md +101 -0
  284. package/dsh-docs/user/guide/network-proxy.md +85 -0
  285. package/dsh-docs/user/guide/network-proxy.zh.md +85 -0
  286. package/dsh-docs/user/guide/providers.md +190 -0
  287. package/dsh-docs/user/guide/providers.zh.md +190 -0
  288. package/dsh-docs/user/guide/python-sdk.md +150 -0
  289. package/dsh-docs/user/guide/python-sdk.zh.md +150 -0
  290. package/dsh-docs/user/guide/schedule.md +21 -0
  291. package/dsh-docs/user/guide/schedule.zh.md +21 -0
  292. package/dsh-docs/user/index.md +11 -0
  293. package/dsh-docs/user/index.zh.md +11 -0
  294. package/dsh-docs/web-styling.md +29 -0
  295. package/dsh-docs/web-styling.zh.md +29 -0
  296. package/eval-description.md +33 -0
  297. package/lib/client/index.js +328 -89
  298. package/lib/compaction/index.d.ts +47 -0
  299. package/lib/compaction/index.js +159 -0
  300. package/lib/failover/index.d.ts +35 -0
  301. package/lib/failover/index.js +141 -0
  302. package/lib/fs-aware/sandbox-plugin.d.ts +71 -0
  303. package/lib/fs-aware/sandbox-plugin.js +249 -0
  304. package/lib/index.d.ts +10 -41
  305. package/lib/index.js +226 -8173
  306. package/lib/lsp-server-registry-946ysdqg.js +972 -0
  307. package/lib/lsp-server-registry-XU6aHSqZ.js +3 -0
  308. package/lib/mobile/plugin.d.ts +29 -0
  309. package/lib/mobile/plugin.js +54 -0
  310. package/lib/native-capture-x_Hos2e8.js +68 -0
  311. package/lib/py-sdk-Chvy92MB.js +178 -0
  312. package/lib/py-sdk.d.ts +19 -2
  313. package/lib/py-sdk.js +2 -2
  314. package/lib/remote/plugin.d.ts +24 -0
  315. package/lib/remote/plugin.js +1095 -0
  316. package/lib/url-schemes/index.d.ts +88 -0
  317. package/lib/url-schemes/index.js +7200 -0
  318. package/lib/web-trust-BO66y72w.js +361 -0
  319. package/lib/web-trust-CgpBoFv3.d.ts +106 -0
  320. package/lib/web-trust.d.ts +2 -0
  321. package/lib/web-trust.js +3 -0
  322. package/lib/wrap-Dr8XtIak.js +747 -0
  323. package/package.json +87 -56
  324. package/url-schemes-instruction.md +22 -0
  325. package/control-prompt.md +0 -37
  326. package/docs/50_test-reports/v0.1.8d_artifacts/README.md +0 -138
  327. package/docs/50_test-reports/v0.1.8d_artifacts/code-mode-repl-only.observation.md +0 -74
  328. package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +0 -3890
  329. package/docs/50_test-reports/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +0 -544
  330. package/docs/50_test-reports/v0.1.8d_artifacts/functions.json +0 -592
  331. package/docs/50_test-reports/v0.1.8d_artifacts/skills-catalog.snapshot.md +0 -30
  332. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.output-schemas.json +0 -1236
  333. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.python.txt +0 -592
  334. package/docs/50_test-reports/v0.1.8d_artifacts/tools-sdk.typescript.txt +0 -516
  335. package/docs/50_test-reports/v0.1.8d_artifacts/wire-vs-transcription.diff.md +0 -54
  336. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.lock +0 -7
  337. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/Cargo.toml +0 -6
  338. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +0 -8
  339. package/docs/50_test-reports/v0.2.0b_artifacts/f2probe/src/main.rs +0 -4
  340. package/docs/50_test-reports/v0.2.0b_artifacts/hashline-probe.md +0 -5
  341. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.lock +0 -7
  342. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/Cargo.toml +0 -7
  343. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/build.rs +0 -4
  344. package/docs/50_test-reports/v0.2.0b_artifacts/slowprobe/src/main.rs +0 -13
  345. package/docs/60_exploration-and-research/cordis-research.md +0 -350
  346. package/docs/60_exploration-and-research/dsh-web-profile-package-map.md +0 -186
  347. package/docs/60_exploration-and-research/dsh-web-ui-slot-system-research.md +0 -310
  348. package/docs/60_exploration-and-research/dsh-webui-strip-boundary-research.md +0 -300
  349. package/docs/60_exploration-and-research/ios-chat-app-bridge-research.md +0 -324
  350. package/docs/60_exploration-and-research/web-frontend-composability-research.md +0 -191
  351. package/docs/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 +0 -110
  352. package/docs/adr/0001-bridge-tool-layer-not-service-layer.md +0 -14
  353. package/docs/adr/0002-masking-is-presentation-only.md +0 -15
  354. package/docs/plans/A2A-messaging-channel-test-archive.md +0 -256
  355. package/docs/plans/code-mode-vs-rlm-ipython-comparison.md +0 -137
  356. package/docs/plans/dashr-blueprint-review.md +0 -201
  357. package/docs/plans/dashr-blueprint.md +0 -561
  358. package/docs/plans/dashr-compaction-window-and-archive.md +0 -307
  359. package/docs/plans/dashr-profile-layer-feasibility.md +0 -367
  360. package/docs/plans/dashr-sandbox-escalation-semantics-gap.md +0 -171
  361. package/docs/plans/dashr-security-sandbox-analysis.md +0 -187
  362. package/docs/plans/dashr-surface-invariant-and-omp-imports.md +0 -97
  363. package/docs/plans/ipython-kernel-interactive-interface-test-report.md +0 -152
  364. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft.md +0 -146
  365. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v3.md +0 -50
  366. package/docs/plans/kernel-refactoring/Dash-IPython-Control-Prompt-draft_v4.md +0 -79
  367. package/docs/plans/kernel-refactoring/Dash-vs-PrimeAgent-systemprompt-toolcatalog-comparison.md +0 -138
  368. package/docs/plans/kernel-refactoring/RLM-system-prompt-injection-gap-report.md +0 -161
  369. package/docs/plans/kernel-refactoring/V0.1.5-development-plan.md +0 -109
  370. package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_dsh.md +0 -50
  371. package/docs/plans/kernel-refactoring/actinoable-surface-to-llm-in-agent-runtime_prime.md +0 -113
  372. package/docs/plans/recallable-compaction.md +0 -147
  373. package/docs/plans/spike-tag-repro.mjs +0 -102
  374. package/docs/plans/upstream-analysis.md +0 -128
  375. package/docs/v0.1.8-improved-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -142
  376. package/docs/v0.1.8-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -193
  377. package/docs/v0.1.8b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -96
  378. package/docs/v0.1.8c-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -127
  379. package/docs/v0.1.8d-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -150
  380. package/docs/v0.1.8d_artifacts/README.md +0 -138
  381. package/docs/v0.1.8d_artifacts/code-mode-repl-only.observation.md +0 -74
  382. package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.jsonl +0 -3890
  383. package/docs/v0.1.8d_artifacts/dsh-session-session-4a293388-9ae1-474b-87a0-9e17bb556d94.w-sample-0435.jsonl +0 -544
  384. package/docs/v0.1.8d_artifacts/functions.json +0 -592
  385. package/docs/v0.1.8d_artifacts/skills-catalog.snapshot.md +0 -30
  386. package/docs/v0.1.8d_artifacts/tools-sdk.output-schemas.json +0 -1236
  387. package/docs/v0.1.8d_artifacts/tools-sdk.python.txt +0 -592
  388. package/docs/v0.1.8d_artifacts/tools-sdk.typescript.txt +0 -516
  389. package/docs/v0.1.8d_artifacts/wire-vs-transcription.diff.md +0 -54
  390. package/docs/v0.1.8e-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -224
  391. package/docs/v0.1.9a-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -168
  392. package/docs/v0.2.0b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -123
  393. package/docs/v0.2.0b_artifacts/f2probe/Cargo.lock +0 -7
  394. package/docs/v0.2.0b_artifacts/f2probe/Cargo.toml +0 -6
  395. package/docs/v0.2.0b_artifacts/f2probe/src/bin/messy.rs +0 -8
  396. package/docs/v0.2.0b_artifacts/f2probe/src/main.rs +0 -4
  397. package/docs/v0.2.0b_artifacts/hashline-probe.md +0 -5
  398. package/docs/v0.2.0b_artifacts/slowprobe/Cargo.lock +0 -7
  399. package/docs/v0.2.0b_artifacts/slowprobe/Cargo.toml +0 -7
  400. package/docs/v0.2.0b_artifacts/slowprobe/build.rs +0 -4
  401. package/docs/v0.2.0b_artifacts/slowprobe/src/main.rs +0 -13
  402. package/docs/v0.2.1-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -110
  403. package/docs/v0.2.1b-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -86
  404. package/docs/v0.2.1c-/345/256/236/346/265/213/346/212/245/345/221/212.md +0 -66
  405. package/lib/py-sdk-BCaOGYz7.d.ts +0 -125
  406. package/lib/py-sdk-CbgYiX8O.js +0 -691
@@ -0,0 +1,747 @@
1
+ import { promises, statSync } from "node:fs";
2
+ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ //#region src/url-schemes/catalog.ts
6
+ /**
7
+ * The scheme set, in declaration order.
8
+ *
9
+ * `paths` mirrors each handler's own path parsing, not an idealised grammar:
10
+ * `dvc://` addresses a device by its FIRST segment only (a trailing `/sub` is
11
+ * parsed and then dropped), and `ctx://` addresses collection elements with a
12
+ * `[n]` bracket that lives in the *path*, not in the selector.
13
+ */
14
+ const SCHEME_CATALOGUE = [
15
+ {
16
+ names: ["skill"],
17
+ display: "skill://",
18
+ paths: "skill://<name>[/<file>]",
19
+ purpose: "a registered skill's files",
20
+ example: "skill://<name>/SKILL.md",
21
+ write: "read-only"
22
+ },
23
+ {
24
+ names: ["agent"],
25
+ display: "agent://",
26
+ paths: "agent://[<id>[/transcript]]",
27
+ purpose: "agent roster / a LIVE agent transcript",
28
+ example: "agent://<id>/transcript:1-40",
29
+ write: "read-only"
30
+ },
31
+ {
32
+ names: ["dsh"],
33
+ display: "dsh://",
34
+ paths: "dsh://docs[/<doc>] · dsh://config",
35
+ purpose: "harness docs / live resolved config",
36
+ example: "dsh://config:path/agent-loop.maxParallelToolCalls",
37
+ write: "read-only"
38
+ },
39
+ {
40
+ names: ["ctx"],
41
+ display: "ctx://",
42
+ paths: "ctx://session/<face>",
43
+ purpose: "THIS session's own log; face ∈ transcript, compactions, thinking, system, user_prompts[n], tool_calls[n], agent_responses[n]",
44
+ example: "ctx://session/tool_calls[0]",
45
+ write: "read-only",
46
+ selector: "`:raw` | `:N-M[,N2-M2]` | `:raw:N-M` (composite ≡ `:N-M`); `[n]` is path syntax (0-based ordinal or event seq)"
47
+ },
48
+ {
49
+ names: ["dvc"],
50
+ display: "dvc://",
51
+ paths: "dvc://[<device>]",
52
+ purpose: "device registry; `write dvc://<device>` with JSON args RUNS it",
53
+ example: "dvc://ast_grep",
54
+ write: "json-args"
55
+ },
56
+ {
57
+ names: ["http", "https"],
58
+ display: "http(s)://",
59
+ paths: "http(s)://<host>/<path>",
60
+ purpose: "plain fetch",
61
+ example: "https://example.com",
62
+ write: "read-only",
63
+ selector: "exempt — the whole remainder is the path (`:8443` port, `?x=1` query)"
64
+ }
65
+ ];
66
+ /** Every registered scheme token, sorted — the list error messages report. */
67
+ const SCHEME_NAMES = SCHEME_CATALOGUE.flatMap((doc) => doc.names).sort();
68
+ /** The schemes as display tokens (`skill://`, `http(s)://`, …) — prose + error messages. */
69
+ const SCHEME_DISPLAYS = SCHEME_CATALOGUE.map((doc) => doc.display);
70
+ /** Number of schemes with no write channel (every entry except `dvc://`). */
71
+ const READ_ONLY_SCHEME_COUNT = SCHEME_CATALOGUE.filter((doc) => doc.write === "read-only").length;
72
+
73
+ //#endregion
74
+ //#region src/url-schemes/selector.ts
75
+ /** Structured error thrown by the URL-schema layer. */
76
+ var UrlSchemesError = class extends Error {
77
+ code;
78
+ constructor(code, message) {
79
+ super(message);
80
+ this.name = "UrlSchemesError";
81
+ this.code = code;
82
+ }
83
+ };
84
+ /** Matches `scheme://rest` with a lowercase alphanumeric scheme. */
85
+ const SCHEME_RE = /^([a-z][a-z0-9]*):\/\/(.*)$/;
86
+ /** One line range token: `N`, `N-M`, or open `N-`. */
87
+ const RANGE_RE = /^(\d+)(?:-(\d*))?$/;
88
+ /**
89
+ * Schemes whose URL syntax reserves `:` and `?` (ports, query strings): the
90
+ * whole remainder is the path and NO selector is parsed. The http(s) handler
91
+ * is documented as selector-free for exactly this reason — `:8443` is a port
92
+ * and `?q=` a server query, never a line range or content filter.
93
+ */
94
+ const SELECTOR_EXEMPT = {
95
+ http: true,
96
+ https: true
97
+ };
98
+ /**
99
+ * Parse a `scheme://` URL into `{ scheme, path, selector }`.
100
+ *
101
+ * Throws a structured {@link UrlSchemesError} (code `URL_NO_SCHEME`) when the
102
+ * URL has no `scheme://` prefix. Any lowercase scheme is accepted here; the
103
+ * resolver rejects schemes with no registered handler. Selector-exempt
104
+ * schemes ({@link SELECTOR_EXEMPT}) return the whole remainder as the path.
105
+ */
106
+ function parseUrl(raw) {
107
+ const m = SCHEME_RE.exec(raw);
108
+ if (m === null) throw new UrlSchemesError("URL_NO_SCHEME", `URL "${raw}" has no scheme — expected "scheme://" (${SCHEME_DISPLAYS.join(", ")})`);
109
+ const scheme = m[1];
110
+ const rest = m[2];
111
+ if (SELECTOR_EXEMPT[scheme] === true) return {
112
+ scheme,
113
+ path: rest,
114
+ selector: null
115
+ };
116
+ const colon = rest.indexOf(":");
117
+ const question = rest.indexOf("?");
118
+ const hasColon = colon !== -1;
119
+ const hasQuestion = question !== -1;
120
+ if (!hasColon && !hasQuestion) return {
121
+ scheme,
122
+ path: rest,
123
+ selector: null
124
+ };
125
+ const isQuery = hasQuestion && (!hasColon || question < colon);
126
+ const marker = isQuery ? question : colon;
127
+ const path = rest.slice(0, marker);
128
+ const selPart = rest.slice(marker + 1);
129
+ return {
130
+ scheme,
131
+ path,
132
+ selector: isQuery ? {
133
+ kind: "query",
134
+ q: selPart.startsWith("q=") ? selPart.slice(2) : selPart
135
+ } : parseColonSelector(selPart)
136
+ };
137
+ }
138
+ /** `:raw`, composite `:raw:N-M`, `:path/<subpath>`, or a `:N-M` line range list. */
139
+ function parseColonSelector(selPart) {
140
+ if (selPart === "raw") return { kind: "raw" };
141
+ if (selPart.startsWith("raw:")) return {
142
+ kind: "lines",
143
+ ranges: parseRanges(selPart.slice(4))
144
+ };
145
+ if (selPart.startsWith("path/")) return {
146
+ kind: "path",
147
+ value: selPart.slice(5)
148
+ };
149
+ return {
150
+ kind: "lines",
151
+ ranges: parseRanges(selPart)
152
+ };
153
+ }
154
+ /** `N`, `N-M`, `N-`, comma-separated → `[[start, end], ...]` (1-based). */
155
+ function parseRanges(spec) {
156
+ return spec.split(",").map((part) => {
157
+ const token = part.trim();
158
+ const m = RANGE_RE.exec(token);
159
+ if (m === null) throw new UrlSchemesError("URL_BAD_SELECTOR", `invalid line selector ":${spec}" — expected N, N-M, or N-M,N2-M2`);
160
+ const start = Number(m[1]);
161
+ if (start < 1) throw new UrlSchemesError("URL_BAD_SELECTOR", `line numbers are 1-based — got ${start} in ":${spec}"`);
162
+ const end = m[2] === void 0 ? start : m[2] === "" ? Infinity : Number(m[2]);
163
+ if (end !== Infinity && end < start) throw new UrlSchemesError("URL_BAD_SELECTOR", `line range ${start}-${end} is empty — end must be >= start`);
164
+ return [start, end];
165
+ });
166
+ }
167
+ /**
168
+ * Apply a selector to already-resolved text.
169
+ *
170
+ * `null` and `{ kind: 'raw' }` return the text unchanged. `lines` performs a
171
+ * 1-based inclusive slice (open tail via `Infinity`). `path` navigates a JSON
172
+ * sub-resource by dot-path. `query` navigates JSON by dot-path when the text
173
+ * parses as JSON, and otherwise keeps the lines containing the query string.
174
+ */
175
+ function applySelector(text, sel) {
176
+ if (sel === null) return text;
177
+ switch (sel.kind) {
178
+ case "raw": return text;
179
+ case "lines": return applyLines(text, sel.ranges);
180
+ case "path": return applyPath(text, sel.value);
181
+ case "query": return applyQuery(text, sel.q);
182
+ }
183
+ }
184
+ /** 1-based inclusive line slicing; `Infinity` end = open tail. */
185
+ function applyLines(text, ranges) {
186
+ if (ranges.length === 0) return "";
187
+ const lines = text.split("\n");
188
+ const out = [];
189
+ for (const [startRaw, endRaw] of ranges) {
190
+ const start = Math.max(1, startRaw);
191
+ const end = endRaw === Infinity ? lines.length : Math.min(lines.length, endRaw);
192
+ if (start <= end) out.push(...lines.slice(start - 1, end));
193
+ }
194
+ return out.join("\n");
195
+ }
196
+ /** Navigate a JSON sub-resource by dot-path; non-JSON text passes through. */
197
+ function applyPath(text, value) {
198
+ if (value === "") return text;
199
+ const parsed = tryParseJson(text);
200
+ if (parsed === void 0) return text;
201
+ const node = navigate(parsed, value);
202
+ return node === void 0 ? text : stringifyNode(node);
203
+ }
204
+ /** JSON dot-path query when the text is JSON, else a substring line filter. */
205
+ function applyQuery(text, q) {
206
+ if (q === "") return text;
207
+ const parsed = tryParseJson(text);
208
+ if (parsed !== void 0) {
209
+ const node = navigate(parsed, q);
210
+ return node === void 0 ? text.split("\n").filter((line) => line.includes(q)).join("\n") : stringifyNode(node);
211
+ }
212
+ return text.split("\n").filter((line) => line.includes(q)).join("\n");
213
+ }
214
+ function tryParseJson(text) {
215
+ try {
216
+ return JSON.parse(text);
217
+ } catch {
218
+ return;
219
+ }
220
+ }
221
+ /** Walk a dot-path through a parsed JSON value (numeric segments index arrays). */
222
+ function navigate(node, path) {
223
+ let current = node;
224
+ for (const segment of path.split(".")) {
225
+ if (segment === "") return void 0;
226
+ if (Array.isArray(current)) {
227
+ const idx = Number(segment);
228
+ if (!Number.isInteger(idx) || idx < 0) return void 0;
229
+ current = current[idx];
230
+ } else if (current !== null && typeof current === "object") current = current[segment];
231
+ else return;
232
+ }
233
+ return current;
234
+ }
235
+ /** Render a navigated leaf as text. */
236
+ function stringifyNode(node) {
237
+ if (typeof node === "string") return node;
238
+ try {
239
+ return JSON.stringify(node) ?? "";
240
+ } catch {
241
+ return String(node);
242
+ }
243
+ }
244
+
245
+ //#endregion
246
+ //#region src/url-schemes/resolver.ts
247
+ /** Scheme→handler registry that resolves `scheme://` URLs end-to-end. */
248
+ var UrlResolver = class {
249
+ handlers = /* @__PURE__ */ new Map();
250
+ /** Register (or replace) the handler for `scheme`. */
251
+ register(scheme, handler) {
252
+ this.handlers.set(scheme, handler);
253
+ }
254
+ /**
255
+ * Resolve a `scheme://` URL to its selected text: parse the URL, dispatch
256
+ * to the registered handler for the scheme, then apply the selector.
257
+ *
258
+ * Throws a structured {@link UrlSchemesError} for a scheme-less URL
259
+ * (`URL_NO_SCHEME`, from {@link parseUrl}) or an unregistered scheme
260
+ * (`URL_UNREGISTERED_SCHEME`).
261
+ */
262
+ async resolve(env, url) {
263
+ const parsed = parseUrl(url);
264
+ const handler = this.handlers.get(parsed.scheme);
265
+ if (handler === void 0) {
266
+ const registered = [...this.handlers.keys()].sort().join(", ");
267
+ throw new UrlSchemesError("URL_UNREGISTERED_SCHEME", `no handler registered for scheme "${parsed.scheme}" (registered: ${registered || "none"})`);
268
+ }
269
+ if (handler.selectorAware === true) return handler.resolve(env, parsed.path, parsed.selector);
270
+ return applySelector(await handler.resolve(env, parsed.path), parsed.selector);
271
+ }
272
+ /**
273
+ * Resolve a `scheme://` URL to its on-disk path when its handler is
274
+ * path-backed: parse the URL, dispatch to the handler's optional
275
+ * `resolvePath`, and return the real disk location. Returns `undefined`
276
+ * for an unregistered scheme, a handler without `resolvePath`, or a path
277
+ * the handler cannot map — callers then fall back to text resolution
278
+ * (whose unregistered-scheme error is the structured generic one).
279
+ * Selectors are NOT applied: they operate on resolved text, not paths.
280
+ */
281
+ async resolvePath(env, url) {
282
+ const parsed = parseUrl(url);
283
+ const handler = this.handlers.get(parsed.scheme);
284
+ if (handler?.resolvePath === void 0) return void 0;
285
+ return await handler.resolvePath(env, parsed.path);
286
+ }
287
+ };
288
+
289
+ //#endregion
290
+ //#region src/url-schemes/handlers/dsh.ts
291
+ /** File extensions considered readable harness documentation. */
292
+ const DOC_EXTENSIONS = {
293
+ ".md": true,
294
+ ".markdown": true,
295
+ ".txt": true
296
+ };
297
+ /**
298
+ * Key-name patterns for the defensive secret denylist, matched against a
299
+ * normalized key (lowercased, separators removed). Complements schema-declared
300
+ * `role('secret')` redaction for fields a schema did not mark secret.
301
+ */
302
+ const SECRET_KEY_PATTERNS = [
303
+ /secret/,
304
+ /password/,
305
+ /passwd/,
306
+ /credential/,
307
+ /token/,
308
+ /apikey/,
309
+ /authorization/,
310
+ /privatekey/,
311
+ /accesskey/
312
+ ];
313
+ /** True when a settings field name names credentials/env/API-key material. */
314
+ function isSecretKey(key) {
315
+ const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
316
+ if (normalized === "env" || normalized === "environment") return true;
317
+ return SECRET_KEY_PATTERNS.some((re) => re.test(normalized));
318
+ }
319
+ /** Deep-copy a settings value, dropping every key the denylist names. */
320
+ function stripSecrets(value) {
321
+ if (Array.isArray(value)) return value.map(stripSecrets);
322
+ if (value !== null && typeof value === "object") {
323
+ const out = {};
324
+ for (const [key, item] of Object.entries(value)) {
325
+ if (isSecretKey(key)) continue;
326
+ out[key] = stripSecrets(item);
327
+ }
328
+ return out;
329
+ }
330
+ return value;
331
+ }
332
+ /** True when `name` has a doc extension (case-insensitive). */
333
+ function isDocFile(name) {
334
+ const dot = name.lastIndexOf(".");
335
+ if (dot === -1) return false;
336
+ return DOC_EXTENSIONS[name.slice(dot).toLowerCase()] === true;
337
+ }
338
+ /** Recursive, sorted list of readable doc paths relative to `dir`. */
339
+ async function listDocs(dir) {
340
+ const out = [];
341
+ const entries = await promises.readdir(dir, { withFileTypes: true });
342
+ entries.sort((a, b) => a.name.localeCompare(b.name));
343
+ for (const entry of entries) {
344
+ if (entry.name.startsWith(".")) continue;
345
+ const abs = join(dir, entry.name);
346
+ if (entry.isDirectory()) for (const child of await listDocs(abs)) out.push(join(entry.name, child));
347
+ else if (isDocFile(entry.name)) out.push(entry.name);
348
+ }
349
+ return out;
350
+ }
351
+ /** Read one `<doc>` path inside `dir`, guarding against path traversal. */
352
+ async function readDoc(dir, docPath) {
353
+ const abs = resolve(dir, docPath);
354
+ const rel = relative(dir, abs);
355
+ if (rel === "" || rel === ".." || rel.startsWith(".." + sep) || isAbsolute(rel)) throw new UrlSchemesError("URL_DOC_NOT_FOUND", `dsh://docs/${docPath}: path escapes the docs directory`);
356
+ let stat;
357
+ try {
358
+ stat = await promises.stat(abs);
359
+ } catch {
360
+ throw new UrlSchemesError("URL_DOC_NOT_FOUND", `dsh://docs/${docPath}: document not found`);
361
+ }
362
+ if (stat.isDirectory()) return JSON.stringify(await listDocs(abs), null, 2);
363
+ if (stat.isFile()) return await promises.readFile(abs, "utf8");
364
+ throw new UrlSchemesError("URL_DOC_NOT_FOUND", `dsh://docs/${docPath}: not a regular file`);
365
+ }
366
+ /** Create the `dsh://` scheme handler, capturing `deps` by closure. */
367
+ function createDshHandler(deps) {
368
+ const { settings, docsDir } = deps;
369
+ let docsDirPromise;
370
+ function findDocsDir() {
371
+ if (docsDirPromise === void 0) docsDirPromise = (async () => {
372
+ const candidates = [];
373
+ if (docsDir !== void 0) candidates.push(docsDir);
374
+ const pkgRoot = dirname(dirname(dirname(dirname(fileURLToPath(import.meta.url)))));
375
+ candidates.push(join(pkgRoot, "dsh-docs"), join(pkgRoot, "docs"), join(pkgRoot, "..", "docs"));
376
+ for (const dir of candidates) try {
377
+ if ((await promises.stat(dir)).isDirectory()) return dir;
378
+ } catch {}
379
+ })();
380
+ return docsDirPromise;
381
+ }
382
+ /**
383
+ * Path-backed view: `docs` and `docs/<sub>` map into the real docs tree, so
384
+ * the URL-aware `grep`/`glob` can hand the native tools a disk path instead
385
+ * of materializing the listing text. `config` is content-backed (resolved
386
+ * settings JSON) — never path-backed.
387
+ */
388
+ async function resolvePathDisk(path) {
389
+ if (path !== "docs" && !path.startsWith("docs/")) return void 0;
390
+ const dir = await findDocsDir();
391
+ if (dir === void 0) return void 0;
392
+ const abs = path === "docs" ? dir : join(dir, path.slice(5));
393
+ try {
394
+ await promises.stat(abs);
395
+ return abs;
396
+ } catch {
397
+ return;
398
+ }
399
+ }
400
+ return {
401
+ async resolvePath(_env, path) {
402
+ return resolvePathDisk(path);
403
+ },
404
+ async resolve(_env, path) {
405
+ const [root, ...rest] = path.split("/");
406
+ const restPath = rest.join("/");
407
+ if (root === "docs") {
408
+ const dir = await findDocsDir();
409
+ if (dir === void 0) throw new UrlSchemesError("URL_DOCS_UNAVAILABLE", "dsh://docs: no docs directory found (provide `docsDir` to createDshHandler)");
410
+ if (restPath === "") return JSON.stringify(await listDocs(dir), null, 2);
411
+ return await readDoc(dir, restPath);
412
+ }
413
+ if (root === "config") {
414
+ if (settings === void 0) throw new UrlSchemesError("URL_SETTINGS_UNAVAILABLE", "dsh://config: no ctx.settings service is mounted");
415
+ const descriptors = settings.describe({ redactSecrets: true });
416
+ if (restPath === "") {
417
+ const out = {};
418
+ for (const descriptor of descriptors) out[String(descriptor.ns)] = stripSecrets(descriptor.value);
419
+ return JSON.stringify(out, null, 2);
420
+ }
421
+ const found = descriptors.find((descriptor) => String(descriptor.ns) === restPath);
422
+ if (found === void 0) throw new UrlSchemesError("URL_UNKNOWN_SETTINGS_NAMESPACE", `dsh://config/${restPath}: unknown settings namespace`);
423
+ return JSON.stringify(stripSecrets(found.value), null, 2);
424
+ }
425
+ throw new UrlSchemesError("URL_UNKNOWN_RESOURCE", `dsh://: unknown resource "${root || "(empty)"}" — expected "docs" or "config"`);
426
+ }
427
+ };
428
+ }
429
+
430
+ //#endregion
431
+ //#region src/url-schemes/handlers/dvc.ts
432
+ /** Module-level device registry: insertion-ordered, shared by every handler instance. */
433
+ const devices = /* @__PURE__ */ new Map();
434
+ /** Register (or replace) the device mounted under `name`. */
435
+ function registerDvcDevice(name, device) {
436
+ devices.set(name, device);
437
+ }
438
+ /** Read-only view of the registered devices, in registration order. */
439
+ function listDvcDevices() {
440
+ return devices;
441
+ }
442
+ /**
443
+ * The first path segment is the device name (`dvc://name`, `dvc://name/sub`).
444
+ * A leading `dvc://` is tolerated so callers may pass either the parsed path
445
+ * (the write tool's contract) or the full URL.
446
+ */
447
+ /** Subpath after the device name (`status`, `diagnostics?file=…`), or undefined. */
448
+ function subpathOf(path) {
449
+ const trimmed = (path.startsWith("dvc://") ? path.slice(6) : path).replace(/^\/+/, "");
450
+ const slash = trimmed.indexOf("/");
451
+ if (slash === -1) return void 0;
452
+ const sub = trimmed.slice(slash + 1);
453
+ return sub === "" ? void 0 : sub;
454
+ }
455
+ function deviceNameFromPath(path) {
456
+ const trimmed = (path.startsWith("dvc://") ? path.slice(6) : path).replace(/^\/+/, "");
457
+ const slash = trimmed.indexOf("/");
458
+ return slash === -1 ? trimmed : trimmed.slice(0, slash);
459
+ }
460
+ /** Uniform `unknown`-error rendering for structured error messages. */
461
+ function messageOf(error) {
462
+ return error instanceof Error ? error.message : String(error);
463
+ }
464
+ /**
465
+ * Build the `dvc://` scheme handler over the module-level device registry.
466
+ * Bare `dvc://` yields the roster (`no devices mounted` while empty); a
467
+ * registered `<device>` yields its summary plus a usage hint; an unregistered
468
+ * name keeps the `unknown device` placeholder text.
469
+ */
470
+ function createDvcHandler(_deps = {}) {
471
+ return {
472
+ selectorAware: true,
473
+ async resolve(_env, path, selector) {
474
+ const name = deviceNameFromPath(path);
475
+ if (name === "") {
476
+ if (devices.size === 0) return "no devices mounted";
477
+ return applySelector([...devices].map(([n, device$1]) => `${n}\t${device$1.summary}`).join("\n"), selector ?? null);
478
+ }
479
+ const device = devices.get(name);
480
+ if (device === void 0) return `unknown device: ${name}`;
481
+ const subpath = subpathOf(path);
482
+ if (subpath !== void 0 && device.read !== void 0) {
483
+ const query = selector?.kind === "query" ? `?${selector.q}` : "";
484
+ let text;
485
+ try {
486
+ text = await device.read(`${subpath}${query}`, _env.agent?.id);
487
+ } catch (error) {
488
+ return `Error: ${error instanceof Error ? error.message : String(error)}`;
489
+ }
490
+ return selector !== void 0 && selector !== null && selector.kind !== "query" ? applySelector(text, selector) : text;
491
+ }
492
+ if (subpath !== void 0) return `unknown read path dvc://${name}/${subpath} (device serves doc only)`;
493
+ return applySelector(`${device.summary}\nusage: write dvc://${name} with a JSON args object to execute this device`, selector ?? null);
494
+ }
495
+ };
496
+ }
497
+ /**
498
+ * Write dispatch for `dvc://` URLs — called by the write tool's URL branch.
499
+ * `path` addresses the device (parsed path or full `dvc://` URL); `content`
500
+ * must be the JSON args payload.
501
+ *
502
+ * Routing and args failures (`DVC_NO_DEVICE`, `DVC_UNKNOWN_DEVICE`,
503
+ * `DVC_BAD_ARGS`) throw synchronously — the placeholder wave's observable
504
+ * contract — while a device-reported failure rejects the returned promise as
505
+ * `DVC_DEVICE_ERROR` carrying the device name.
506
+ */
507
+ function dispatchDvcWrite(path, content, session) {
508
+ if (devices.size === 0) throw new UrlSchemesError("DVC_NO_DEVICE", "dvc:// write dispatch: no devices mounted to route the write to");
509
+ const name = deviceNameFromPath(path);
510
+ const device = devices.get(name);
511
+ if (device === void 0) throw new UrlSchemesError("DVC_UNKNOWN_DEVICE", `dvc:// write dispatch: no device named "${name}" (registered: ${[...devices.keys()].sort().join(", ")})`);
512
+ let args;
513
+ try {
514
+ args = JSON.parse(content);
515
+ } catch (error) {
516
+ throw new UrlSchemesError("DVC_BAD_ARGS", `dvc:// write dispatch: device "${name}" requires a JSON args payload (${messageOf(error)})`);
517
+ }
518
+ if (session !== void 0 && args !== null && typeof args === "object" && !Array.isArray(args)) args = { ...args };
519
+ return Promise.resolve().then(() => device.execute(args, { session })).catch((error) => {
520
+ throw new UrlSchemesError("DVC_DEVICE_ERROR", `dvc:// device "${name}" execute failed: ${messageOf(error)}`);
521
+ });
522
+ }
523
+
524
+ //#endregion
525
+ //#region src/url-schemes/handlers/http.ts
526
+ /** The schemes one handler instance serves; register it under each of these. */
527
+ const HTTP_SCHEMES = ["http", "https"];
528
+ /** Hard cap on a fetched body: 2 MiB. */
529
+ const MAX_BODY_BYTES = 2 * 1024 * 1024;
530
+ /** Abort the GET after this many milliseconds. */
531
+ const TIMEOUT_MS = 2e4;
532
+ /** First line of every resolved http(s) URL: flags plain-fetch semantics. */
533
+ const DISCLAIMER = "[url-fetch] plain-text result of a direct HTTP GET (curl-equivalent). No JS execution or interaction — use browser tools, if any, for that.";
534
+ /** `application/` MIME types treated as text (any `text/*` also is). */
535
+ const APPLICATION_TEXT_TYPES = {
536
+ "application/json": true,
537
+ "application/xml": true,
538
+ "application/yaml": true,
539
+ "application/toml": true,
540
+ "application/xhtml+xml": true,
541
+ "application/javascript": true,
542
+ "application/plain": true
543
+ };
544
+ /** Strict whitelist: `text/*` or a known textual `application/*` MIME. A
545
+ * missing header fails the check — binary decoding is never guessed. */
546
+ function isTextContentType(headerValue) {
547
+ if (headerValue === null) return false;
548
+ const mime = headerValue.split(";", 1)[0].trim().toLowerCase();
549
+ return mime.startsWith("text/") || mime in APPLICATION_TEXT_TYPES;
550
+ }
551
+ /** Best-effort `err.cause` message — undici nests DNS/socket failures there. */
552
+ function causeMessageOf(err) {
553
+ const cause = err?.cause;
554
+ if (cause instanceof Error) return cause.message;
555
+ if (typeof cause === "string" && cause !== "") return cause;
556
+ return null;
557
+ }
558
+ /** Stream the body as UTF-8 text, throwing past the 2 MiB byte cap. */
559
+ async function readBodyCapped(body, href) {
560
+ const reader = body.getReader();
561
+ const decoder = new TextDecoder();
562
+ let received = 0;
563
+ let text = "";
564
+ try {
565
+ for (;;) {
566
+ const { done, value } = await reader.read().catch((err) => {
567
+ if (err instanceof Error && err.name === "AbortError") throw new UrlSchemesError("URL_HTTP_TIMEOUT", `HTTP GET ${href} aborted after the ${TIMEOUT_MS / 1e3} s deadline`);
568
+ throw err;
569
+ });
570
+ if (done) break;
571
+ received += value.byteLength;
572
+ if (received > MAX_BODY_BYTES) throw new UrlSchemesError("URL_HTTP_TOO_LARGE", `body of ${href} exceeded the ${MAX_BODY_BYTES}-byte (2 MiB) text limit after ${received} bytes`);
573
+ text += decoder.decode(value, { stream: true });
574
+ }
575
+ return text + decoder.decode();
576
+ } finally {
577
+ await reader.cancel().catch(() => {});
578
+ }
579
+ }
580
+ /** One capped, whitelisted GET of `url`; returns the decoded body text. */
581
+ async function getUrl(url) {
582
+ const controller = new AbortController();
583
+ let timedOut = false;
584
+ const timer = setTimeout(() => {
585
+ timedOut = true;
586
+ controller.abort();
587
+ }, TIMEOUT_MS);
588
+ try {
589
+ let response;
590
+ try {
591
+ response = await fetch(url, {
592
+ method: "GET",
593
+ redirect: "follow",
594
+ signal: controller.signal
595
+ });
596
+ } catch (err) {
597
+ if (timedOut || err instanceof Error && err.name === "AbortError") throw new UrlSchemesError("URL_HTTP_TIMEOUT", `HTTP GET ${url.href} aborted after the ${TIMEOUT_MS / 1e3} s deadline`);
598
+ const cause = causeMessageOf(err);
599
+ const message = err instanceof Error ? err.message : String(err);
600
+ throw new UrlSchemesError("URL_HTTP_FETCH_FAILED", `HTTP GET ${url.href} failed: ${message}${cause === null ? "" : ` (${cause})`}`);
601
+ }
602
+ if (!response.ok) {
603
+ const statusText = response.statusText === "" ? "" : ` ${response.statusText}`;
604
+ throw new UrlSchemesError("URL_HTTP_STATUS", `HTTP GET ${url.href} returned ${response.status}${statusText}`);
605
+ }
606
+ const declared = response.headers.get("content-length");
607
+ if (declared !== null) {
608
+ const bytes = Number(declared);
609
+ if (Number.isFinite(bytes) && bytes > MAX_BODY_BYTES) throw new UrlSchemesError("URL_HTTP_TOO_LARGE", `body of ${url.href} is ${bytes} bytes, over the ${MAX_BODY_BYTES}-byte (2 MiB) text limit`);
610
+ }
611
+ const contentType = response.headers.get("content-type");
612
+ if (!isTextContentType(contentType)) throw new UrlSchemesError("URL_HTTP_UNSUPPORTED_MEDIA", `content-type of ${url.href} is "${contentType ?? "(none)"}", outside the text whitelist (text/* or application/{json,xml,yaml,toml,xhtml+xml,javascript,plain}) — binary decoding is deliberately not guessed`);
613
+ if (response.body === null) {
614
+ const text = await response.text();
615
+ const bytes = Buffer.byteLength(text, "utf8");
616
+ if (bytes > MAX_BODY_BYTES) throw new UrlSchemesError("URL_HTTP_TOO_LARGE", `body of ${url.href} is ${bytes} bytes, over the ${MAX_BODY_BYTES}-byte (2 MiB) text limit`);
617
+ return text;
618
+ }
619
+ return await readBodyCapped(response.body, url.href);
620
+ } finally {
621
+ clearTimeout(timer);
622
+ }
623
+ }
624
+ /**
625
+ * Build the `http://`/`https://` handler. Register the returned instance
626
+ * under BOTH schemes ({@link HTTP_SCHEMES}); it is stateless and safe to
627
+ * share.
628
+ */
629
+ function createHttpHandler() {
630
+ return { async resolve(env, path) {
631
+ const raw = env.rawUrl ?? `https://${path}`;
632
+ let url;
633
+ try {
634
+ url = new URL(raw);
635
+ } catch (err) {
636
+ throw new UrlSchemesError("URL_INVALID", `invalid http(s) URL "${raw}": ${err instanceof Error ? err.message : String(err)}`);
637
+ }
638
+ if (url.protocol !== "http:" && url.protocol !== "https:") throw new UrlSchemesError("URL_INVALID", `not an http(s) URL: "${raw}"`);
639
+ return `${DISCLAIMER}\n\n${await getUrl(url)}`;
640
+ } };
641
+ }
642
+
643
+ //#endregion
644
+ //#region src/url-schemes/docs-dir.ts
645
+ function resolveDocsDir() {
646
+ let dir = dirname(fileURLToPath(import.meta.url));
647
+ for (;;) {
648
+ for (const name of ["dsh-docs", "docs"]) {
649
+ const candidate = join(dir, name);
650
+ try {
651
+ if (statSync(candidate).isDirectory()) return candidate;
652
+ } catch {}
653
+ }
654
+ const parent = dirname(dir);
655
+ if (parent === dir) return void 0;
656
+ dir = parent;
657
+ }
658
+ }
659
+
660
+ //#endregion
661
+ //#region src/fs-aware/wrap.ts
662
+ const WRAPPED = Symbol("dsh-url-schemes.fs-wrap");
663
+ function isSchemePath(path) {
664
+ return typeof path === "string" && /^[a-z][a-z0-9]*:\/\//.test(path);
665
+ }
666
+ function isSessionLayerScheme(path) {
667
+ return path.startsWith("ctx://") || path.startsWith("agent://") || path.startsWith("skill://");
668
+ }
669
+ function sessionLayerError(url) {
670
+ if (url.startsWith("skill://")) return new UrlSchemesError("CTX_SESSION_LAYER", `${url}: session-layer scheme — skill discovery (which roots load, scan depth, layered scope merge) is the host skill provider's business logic and resolves only against a calling agent, which the filesystem layer does not have. Load skills with the native \`skill\` tool; grep/glob with path=skill://… keep working through the tool layer`);
671
+ return new UrlSchemesError("CTX_SESSION_LAYER", `${url}: session-layer scheme — read it through the read tool (the session-layer resolver environment carries the live agent this filesystem layer does not have)`);
672
+ }
673
+ /** Build the FS-layer resolver: file-type schemes only (design D2). */
674
+ function buildFsLayerResolver(services, fsSelf) {
675
+ const resolver = new UrlResolver();
676
+ resolver.register("dsh", createDshHandler({
677
+ settings: services.settings,
678
+ docsDir: resolveDocsDir()
679
+ }));
680
+ resolver.register("dvc", createDvcHandler());
681
+ for (const scheme of HTTP_SCHEMES) resolver.register(scheme, createHttpHandler());
682
+ resolver.register("ctx", { async resolve(_env, path) {
683
+ throw sessionLayerError(`ctx://${path}`);
684
+ } });
685
+ resolver.register("agent", { async resolve(_env, path) {
686
+ throw sessionLayerError(`agent://${path}`);
687
+ } });
688
+ return resolver;
689
+ }
690
+ /**
691
+ * Wrap the mounted `ctx.fs` instance in place. Idempotent via a symbol flag.
692
+ * Returns the resolver used for scheme dereferencing (for diagnostics).
693
+ */
694
+ function wrapFsWithSchemes(fs, services) {
695
+ const holder = fs;
696
+ if (holder[WRAPPED] !== void 0) return holder[WRAPPED];
697
+ const resolver = buildFsLayerResolver(services, fs);
698
+ const envFor = (url) => ({
699
+ fs,
700
+ rawUrl: url
701
+ });
702
+ const bind = (fn) => typeof fn === "function" ? fn.bind(fs) : void 0;
703
+ const origResolve = bind(fs.resolve);
704
+ const origStat = bind(fs.stat);
705
+ const origReadText = bind(fs.readText);
706
+ const origWriteText = bind(fs.writeText);
707
+ const origEditText = bind(fs.editText);
708
+ const requireOrig = (orig, method) => {
709
+ if (orig === void 0) throw new UrlSchemesError("FS_BASE_UNSUPPORTED", `the mounted filesystem service exposes no "${method}" — scheme wrap is active but the base backend cannot serve real paths`);
710
+ return orig;
711
+ };
712
+ fs.resolve = async (path, opts) => {
713
+ if (!isSchemePath(path)) return requireOrig(origResolve, "resolve")(path, opts);
714
+ if (isSessionLayerScheme(path)) throw sessionLayerError(path);
715
+ await resolver.resolve(envFor(path), path);
716
+ return {
717
+ targetKey: path,
718
+ displayPath: path
719
+ };
720
+ };
721
+ fs.stat = async (target, signal) => {
722
+ if (!isSchemePath(target.targetKey)) return requireOrig(origStat, "stat")(target, signal);
723
+ if (isSessionLayerScheme(target.targetKey)) throw sessionLayerError(target.targetKey);
724
+ return {
725
+ type: "file",
726
+ size: (await resolver.resolve(envFor(target.targetKey), target.targetKey)).length
727
+ };
728
+ };
729
+ fs.readText = async (target, signal) => {
730
+ if (!isSchemePath(target.targetKey)) return requireOrig(origReadText, "readText")(target, signal);
731
+ if (isSessionLayerScheme(target.targetKey)) throw sessionLayerError(target.targetKey);
732
+ return resolver.resolve(envFor(target.targetKey), target.targetKey);
733
+ };
734
+ fs.writeText = async (target, ...rest) => {
735
+ if (isSchemePath(target.targetKey)) throw new UrlSchemesError("FS_VIRTUAL_READONLY", `cannot write "${target.targetKey}": scheme resources are read-only at the filesystem layer`);
736
+ return requireOrig(origWriteText, "writeText")(target, ...rest);
737
+ };
738
+ fs.editText = async (target, ...rest) => {
739
+ if (isSchemePath(target.targetKey)) throw new UrlSchemesError("FS_VIRTUAL_READONLY", `cannot edit "${target.targetKey}": scheme resources are read-only at the filesystem layer`);
740
+ return requireOrig(origEditText, "editText")(target, ...rest);
741
+ };
742
+ holder[WRAPPED] = resolver;
743
+ return resolver;
744
+ }
745
+
746
+ //#endregion
747
+ export { createHttpHandler as a, listDvcDevices as c, UrlResolver as d, UrlSchemesError as f, HTTP_SCHEMES as i, registerDvcDevice as l, SCHEME_NAMES as m, wrapFsWithSchemes as n, createDvcHandler as o, parseUrl as p, resolveDocsDir as r, dispatchDvcWrite as s, buildFsLayerResolver as t, createDshHandler as u };