@toddzheng024/dscode-desktop 0.0.0-stage → 0.7.33

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 (484) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +120 -2
  3. package/THIRD_PARTY_NOTICES.md +30 -0
  4. package/bin/apply_patch +9 -0
  5. package/cordis.patch.yml +433 -0
  6. package/docs/CHANGELOG.md +641 -0
  7. package/docs/account-login.md +44 -0
  8. package/docs/auto-review.md +128 -0
  9. package/docs/browser-use.md +783 -0
  10. package/docs/computer-use.md +81 -0
  11. package/docs/custom-providers.md +88 -0
  12. package/docs/demo.md +76 -0
  13. package/docs/distribution.md +58 -0
  14. package/docs/dscode-ultra.md +75 -0
  15. package/docs/email.md +296 -0
  16. package/docs/exec.md +40 -0
  17. package/docs/hub-distribution.md +190 -0
  18. package/docs/memory.md +121 -0
  19. package/docs/opencode-go.md +61 -0
  20. package/docs/plugin-hub.md +68 -0
  21. package/docs/releases/0.2.0.md +28 -0
  22. package/docs/releases/0.3.0.md +21 -0
  23. package/docs/releases/0.4.0.md +20 -0
  24. package/docs/releases/0.5.0.md +19 -0
  25. package/docs/releases/0.6.0.md +20 -0
  26. package/docs/releases/0.7.0.md +22 -0
  27. package/docs/releases/0.7.1.md +20 -0
  28. package/docs/releases/0.7.10.md +10 -0
  29. package/docs/releases/0.7.11.md +17 -0
  30. package/docs/releases/0.7.12.md +11 -0
  31. package/docs/releases/0.7.13.md +12 -0
  32. package/docs/releases/0.7.14.md +11 -0
  33. package/docs/releases/0.7.15.md +11 -0
  34. package/docs/releases/0.7.16.md +10 -0
  35. package/docs/releases/0.7.17.md +12 -0
  36. package/docs/releases/0.7.18.md +13 -0
  37. package/docs/releases/0.7.19.md +8 -0
  38. package/docs/releases/0.7.2.md +19 -0
  39. package/docs/releases/0.7.20.md +10 -0
  40. package/docs/releases/0.7.21.md +9 -0
  41. package/docs/releases/0.7.22.md +11 -0
  42. package/docs/releases/0.7.23.md +14 -0
  43. package/docs/releases/0.7.24.md +11 -0
  44. package/docs/releases/0.7.25.md +8 -0
  45. package/docs/releases/0.7.26.md +18 -0
  46. package/docs/releases/0.7.27.md +8 -0
  47. package/docs/releases/0.7.28.md +22 -0
  48. package/docs/releases/0.7.29.md +12 -0
  49. package/docs/releases/0.7.3.md +23 -0
  50. package/docs/releases/0.7.30.md +19 -0
  51. package/docs/releases/0.7.31.md +14 -0
  52. package/docs/releases/0.7.32.md +14 -0
  53. package/docs/releases/0.7.33.md +30 -0
  54. package/docs/releases/0.7.4.md +16 -0
  55. package/docs/releases/0.7.5.md +18 -0
  56. package/docs/releases/0.7.6.md +29 -0
  57. package/docs/releases/0.7.7.md +36 -0
  58. package/docs/releases/0.7.8.md +14 -0
  59. package/docs/releases/0.7.9.md +15 -0
  60. package/docs/session-bridge.md +80 -0
  61. package/docs/session-cards.md +53 -0
  62. package/docs/session-communication.md +186 -0
  63. package/docs/session-metrics.md +41 -0
  64. package/docs/skills.md +81 -0
  65. package/docs/triggers.md +338 -0
  66. package/docs/tui-commands.md +204 -0
  67. package/extensions/browser/manifest.json +22 -0
  68. package/extensions/browser/popup.css +6 -0
  69. package/extensions/browser/popup.html +11 -0
  70. package/extensions/browser/popup.mjs +47 -0
  71. package/extensions/browser/protocol.mjs +168 -0
  72. package/extensions/browser/worker.mjs +94 -0
  73. package/icon.svg +7 -0
  74. package/locale/en.json +6 -0
  75. package/locale/zh-cn.json +6 -0
  76. package/node_modules/@deepseek-ai/node-addon-system/LICENSE +21 -0
  77. package/node_modules/@deepseek-ai/node-addon-system/README.i18n.yaml +6 -0
  78. package/node_modules/@deepseek-ai/node-addon-system/README.md +15 -0
  79. package/node_modules/@deepseek-ai/node-addon-system/README.zh.md +15 -0
  80. package/node_modules/@deepseek-ai/node-addon-system/lib/flock.d.ts +13 -0
  81. package/node_modules/@deepseek-ai/node-addon-system/lib/flock.js +51 -0
  82. package/node_modules/@deepseek-ai/node-addon-system/lib/index.d.ts +73 -0
  83. package/node_modules/@deepseek-ai/node-addon-system/lib/index.js +98 -0
  84. package/node_modules/@deepseek-ai/node-addon-system/package.json +45 -0
  85. package/node_modules/@deepseek-ai/node-addon-system/src/flock.c +164 -0
  86. package/node_modules/@deepseek-ai/node-addon-system/src/main.c +298 -0
  87. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/LICENSE +28 -0
  88. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.i18n.yaml +6 -0
  89. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.md +9 -0
  90. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.zh.md +9 -0
  91. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/bin/system.node +0 -0
  92. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/package.json +31 -0
  93. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/prebuilds.json +6 -0
  94. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/LICENSE +28 -0
  95. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.i18n.yaml +6 -0
  96. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.md +9 -0
  97. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.zh.md +9 -0
  98. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/bin/system.node +0 -0
  99. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/package.json +31 -0
  100. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/prebuilds.json +6 -0
  101. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/LICENSE +28 -0
  102. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.i18n.yaml +6 -0
  103. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.md +11 -0
  104. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.zh.md +11 -0
  105. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/glibc/system.node +0 -0
  106. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/landlock-run +0 -0
  107. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/musl/system.node +0 -0
  108. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/package.json +31 -0
  109. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/prebuilds.json +24 -0
  110. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/LICENSE +28 -0
  111. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.i18n.yaml +6 -0
  112. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.md +11 -0
  113. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.zh.md +11 -0
  114. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/glibc/system.node +0 -0
  115. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/landlock-run +0 -0
  116. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/musl/system.node +0 -0
  117. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/package.json +31 -0
  118. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/prebuilds.json +24 -0
  119. package/package.json +156 -4
  120. package/plugins/account/index.mjs +178 -0
  121. package/plugins/account/state.mjs +123 -0
  122. package/plugins/auto-review/audit.mjs +24 -0
  123. package/plugins/auto-review/index.mjs +267 -0
  124. package/plugins/auto-review/policy.mjs +92 -0
  125. package/plugins/browser/SKILL.md +158 -0
  126. package/plugins/browser/access.mjs +143 -0
  127. package/plugins/browser/config.mjs +60 -0
  128. package/plugins/browser/connection.mjs +385 -0
  129. package/plugins/browser/desktop-client.mjs +282 -0
  130. package/plugins/browser/desktop-host.mjs +74 -0
  131. package/plugins/browser/document-identity.mjs +57 -0
  132. package/plugins/browser/extension-relay.mjs +66 -0
  133. package/plugins/browser/files.mjs +32 -0
  134. package/plugins/browser/index.mjs +235 -0
  135. package/plugins/browser/mcp-entry.mjs +18 -0
  136. package/plugins/browser/mcp-tools.mjs +21 -0
  137. package/plugins/browser/presentation.mjs +45 -0
  138. package/plugins/browser/preview.mjs +77 -0
  139. package/plugins/browser/review.mjs +20 -0
  140. package/plugins/browser/screenshots.mjs +35 -0
  141. package/plugins/clipboard-image/clipboard-image.swift +56 -0
  142. package/plugins/clipboard-image/index.mjs +70 -0
  143. package/plugins/code-review/baseline.mjs +143 -0
  144. package/plugins/code-review/git.mjs +163 -0
  145. package/plugins/code-review/index.mjs +236 -0
  146. package/plugins/compaction/engine.mjs +304 -0
  147. package/plugins/compaction/tetris.mjs +65 -0
  148. package/plugins/compaction/threshold.mjs +98 -0
  149. package/plugins/computer-use/DESKTOP-SKILL.md +64 -0
  150. package/plugins/computer-use/desktop-host.mjs +75 -0
  151. package/plugins/computer-use/desktop-skill.mjs +28 -0
  152. package/plugins/computer-use/desktop-upstream.mjs +3 -0
  153. package/plugins/computer-use/index.mjs +37 -0
  154. package/plugins/cordis-config/plain.mjs +31 -0
  155. package/plugins/credentials/index.mjs +73 -0
  156. package/plugins/custom/adapter.mjs +110 -0
  157. package/plugins/custom/config.mjs +85 -0
  158. package/plugins/custom/desktop-client.mjs +150 -0
  159. package/plugins/custom/desktop-host.mjs +78 -0
  160. package/plugins/custom/images.mjs +32 -0
  161. package/plugins/custom/index.mjs +145 -0
  162. package/plugins/custom/wire.mjs +179 -0
  163. package/plugins/desktop/client.mjs +1041 -0
  164. package/plugins/desktop/index.mjs +10 -0
  165. package/plugins/desktop/shell-environment.mjs +9 -0
  166. package/plugins/desktop-workspace/hooks.mjs +29 -0
  167. package/plugins/desktop-workspace/index.mjs +37 -0
  168. package/plugins/dscode/board.mjs +260 -0
  169. package/plugins/dscode/child-target.mjs +11 -0
  170. package/plugins/dscode/control.mjs +17 -0
  171. package/plugins/dscode/desktop-client.mjs +55 -0
  172. package/plugins/dscode/desktop-host.mjs +37 -0
  173. package/plugins/dscode/index.mjs +270 -0
  174. package/plugins/email/cli.mjs +32 -0
  175. package/plugins/email/contacts.mjs +36 -0
  176. package/plugins/email/desktop-client.mjs +117 -0
  177. package/plugins/email/desktop-host.mjs +54 -0
  178. package/plugins/email/desktop-service.mjs +106 -0
  179. package/plugins/email/gmail-oauth.mjs +69 -0
  180. package/plugins/email/gmail-store.mjs +2 -0
  181. package/plugins/email/gmail.mjs +194 -0
  182. package/plugins/email/imap.mjs +136 -0
  183. package/plugins/email/inbox.d.mts +25 -0
  184. package/plugins/email/inbox.mjs +76 -0
  185. package/plugins/email/smtp.mjs +70 -0
  186. package/plugins/email/store.mjs +32 -0
  187. package/plugins/email-tools/index.mjs +46 -0
  188. package/plugins/exec/cli.mjs +64 -0
  189. package/plugins/exec/index.mjs +112 -0
  190. package/plugins/grok/adapter.mjs +114 -0
  191. package/plugins/grok/auth.mjs +76 -0
  192. package/plugins/grok/billing.mjs +146 -0
  193. package/plugins/grok/index.mjs +122 -0
  194. package/plugins/grok/models.mjs +129 -0
  195. package/plugins/grok/status.mjs +28 -0
  196. package/plugins/grok/wire.mjs +268 -0
  197. package/plugins/hub/catalog.mjs +82 -0
  198. package/plugins/hub/desktop-client.mjs +114 -0
  199. package/plugins/hub/desktop-host.mjs +129 -0
  200. package/plugins/i18n/messages.d.mts +21 -0
  201. package/plugins/i18n/messages.mjs +537 -0
  202. package/plugins/jev/approval.mjs +131 -0
  203. package/plugins/jev/client.mjs +74 -0
  204. package/plugins/jev/index.mjs +99 -0
  205. package/plugins/memory/content.mjs +57 -0
  206. package/plugins/memory/desktop-host.mjs +3 -0
  207. package/plugins/memory/index.mjs +168 -0
  208. package/plugins/memory/pipeline.mjs +79 -0
  209. package/plugins/memory/store.mjs +93 -0
  210. package/plugins/message-source/kind.mjs +20 -0
  211. package/plugins/opencode-go/adapter.mjs +96 -0
  212. package/plugins/opencode-go/command.mjs +128 -0
  213. package/plugins/opencode-go/index.mjs +120 -0
  214. package/plugins/opencode-go/models.mjs +58 -0
  215. package/plugins/opencode-go/oauth.mjs +194 -0
  216. package/plugins/opencode-go/search.mjs +86 -0
  217. package/plugins/opencode-go/usage.mjs +119 -0
  218. package/plugins/opencode-go/version.mjs +10 -0
  219. package/plugins/opencode-go/wire.mjs +73 -0
  220. package/plugins/openrouter/adapter.mjs +232 -0
  221. package/plugins/openrouter/index.mjs +123 -0
  222. package/plugins/openrouter/models.mjs +157 -0
  223. package/plugins/openrouter/search.mjs +113 -0
  224. package/plugins/openrouter/wire.mjs +101 -0
  225. package/plugins/providers/catalog.mjs +160 -0
  226. package/plugins/providers/chat-messages.mjs +120 -0
  227. package/plugins/providers/chat-stream.mjs +174 -0
  228. package/plugins/providers/desktop-client.mjs +84 -0
  229. package/plugins/providers/desktop-host.mjs +63 -0
  230. package/plugins/providers/effort.mjs +35 -0
  231. package/plugins/providers/http-errors.mjs +50 -0
  232. package/plugins/providers/openrouter-account.mjs +171 -0
  233. package/plugins/session-bridge/client.mjs +106 -0
  234. package/plugins/session-bridge/communication.mjs +260 -0
  235. package/plugins/session-bridge/index.mjs +68 -0
  236. package/plugins/session-bridge/mailbox.mjs +267 -0
  237. package/plugins/session-bridge/paths.mjs +21 -0
  238. package/plugins/session-bridge/server.mjs +172 -0
  239. package/plugins/session-bridge/tasks.mjs +229 -0
  240. package/plugins/session-cards/content.mjs +64 -0
  241. package/plugins/session-cards/index.mjs +38 -0
  242. package/plugins/session-cards/manager.mjs +140 -0
  243. package/plugins/session-metrics/attribution.mjs +30 -0
  244. package/plugins/session-metrics/balance.mjs +81 -0
  245. package/plugins/session-metrics/desktop-client.mjs +62 -0
  246. package/plugins/session-metrics/desktop-host.mjs +46 -0
  247. package/plugins/session-metrics/index.mjs +96 -0
  248. package/plugins/session-metrics/pricing.mjs +84 -0
  249. package/plugins/session-metrics/rate.mjs +59 -0
  250. package/plugins/session-metrics/store.mjs +75 -0
  251. package/plugins/session-metrics/turns.mjs +134 -0
  252. package/plugins/session-metrics/view.mjs +271 -0
  253. package/plugins/time-marks/desktop-host.mjs +2 -0
  254. package/plugins/time-marks/index.mjs +116 -0
  255. package/plugins/time-marks/marks.mjs +152 -0
  256. package/plugins/triggers/cli.mjs +558 -0
  257. package/plugins/triggers/commands.mjs +143 -0
  258. package/plugins/triggers/config.mjs +264 -0
  259. package/plugins/triggers/desktop-client.mjs +155 -0
  260. package/plugins/triggers/desktop-host.mjs +88 -0
  261. package/plugins/triggers/desktop-management.mjs +97 -0
  262. package/plugins/triggers/desktop-scheduler.mjs +125 -0
  263. package/plugins/triggers/host.mjs +24 -0
  264. package/plugins/triggers/index.mjs +27 -0
  265. package/plugins/triggers/job-cli.mjs +110 -0
  266. package/plugins/triggers/jobs.mjs +156 -0
  267. package/plugins/triggers/launchd.mjs +101 -0
  268. package/plugins/triggers/lease.mjs +24 -0
  269. package/plugins/triggers/log.mjs +104 -0
  270. package/plugins/triggers/management.mjs +181 -0
  271. package/plugins/triggers/options.mjs +117 -0
  272. package/plugins/triggers/overlay.mjs +7 -0
  273. package/plugins/triggers/poll.mjs +65 -0
  274. package/plugins/triggers/run.mjs +157 -0
  275. package/plugins/triggers/schedule.mjs +40 -0
  276. package/plugins/triggers/scheduler-service.mjs +46 -0
  277. package/plugins/triggers/scheduler.mjs +92 -0
  278. package/plugins/triggers/session-run.mjs +125 -0
  279. package/plugins/triggers/session.mjs +48 -0
  280. package/plugins/triggers/source-emit.mjs +19 -0
  281. package/plugins/triggers/source-host.mjs +78 -0
  282. package/plugins/triggers/source-ingress.mjs +70 -0
  283. package/plugins/triggers/source-sandbox.mjs +35 -0
  284. package/plugins/triggers/sources.mjs +45 -0
  285. package/plugins/triggers/spool.mjs +145 -0
  286. package/plugins/triggers/tools.mjs +67 -0
  287. package/plugins/triggers/unattended.mjs +18 -0
  288. package/plugins/tui-tools/composition.mjs +28 -0
  289. package/plugins/tui-tools/desktop-host.mjs +2 -0
  290. package/plugins/tui-tools/doctor-cli.mjs +22 -0
  291. package/plugins/tui-tools/doctor.mjs +148 -0
  292. package/plugins/tui-tools/hook-sources.mjs +113 -0
  293. package/plugins/tui-tools/hooks.mjs +23 -0
  294. package/plugins/tui-tools/index.mjs +268 -0
  295. package/plugins/tui-tools/sandbox-runner.mjs +123 -0
  296. package/plugins/tui-tools/shell.mjs +27 -0
  297. package/plugins/tui-tools/update.mjs +111 -0
  298. package/plugins/tui-tools/workspace-discovery.mjs +129 -0
  299. package/plugins/ultra/policy.mjs +42 -0
  300. package/plugins/worktree-subagent/worktree.mjs +56 -0
  301. package/runtime-sources.json +94 -0
  302. package/vendor/bash/LICENSE +21 -0
  303. package/vendor/bash/index.js +717 -0
  304. package/vendor/bash/types/background.d.ts +50 -0
  305. package/vendor/bash/types/index.d.ts +38 -0
  306. package/vendor/bash/types/render.d.ts +57 -0
  307. package/vendor/command-goal/LICENSE +21 -0
  308. package/vendor/command-goal/index.js +210 -0
  309. package/vendor/command-goal/types/index.d.ts +10 -0
  310. package/vendor/computer-use/LICENSE +21 -0
  311. package/vendor/computer-use/lib/approval-policy.js +12 -0
  312. package/vendor/computer-use/lib/approval-policy.js.map +1 -0
  313. package/vendor/computer-use/lib/artifacts.js +79 -0
  314. package/vendor/computer-use/lib/artifacts.js.map +1 -0
  315. package/vendor/computer-use/lib/backend.js +3 -0
  316. package/vendor/computer-use/lib/backend.js.map +1 -0
  317. package/vendor/computer-use/lib/client.js +369 -0
  318. package/vendor/computer-use/lib/client.js.map +1 -0
  319. package/vendor/computer-use/lib/config.js +159 -0
  320. package/vendor/computer-use/lib/config.js.map +1 -0
  321. package/vendor/computer-use/lib/confirmations.js +99 -0
  322. package/vendor/computer-use/lib/confirmations.js.map +1 -0
  323. package/vendor/computer-use/lib/diff.js +58 -0
  324. package/vendor/computer-use/lib/diff.js.map +1 -0
  325. package/vendor/computer-use/lib/errors.js +22 -0
  326. package/vendor/computer-use/lib/errors.js.map +1 -0
  327. package/vendor/computer-use/lib/exposure.js +244 -0
  328. package/vendor/computer-use/lib/exposure.js.map +1 -0
  329. package/vendor/computer-use/lib/index.js +66 -0
  330. package/vendor/computer-use/lib/index.js.map +1 -0
  331. package/vendor/computer-use/lib/leases.js +262 -0
  332. package/vendor/computer-use/lib/leases.js.map +1 -0
  333. package/vendor/computer-use/lib/providers/macos.js +243 -0
  334. package/vendor/computer-use/lib/providers/macos.js.map +1 -0
  335. package/vendor/computer-use/lib/providers/native-helper.js +726 -0
  336. package/vendor/computer-use/lib/providers/native-helper.js.map +1 -0
  337. package/vendor/computer-use/lib/providers/unsupported.js +51 -0
  338. package/vendor/computer-use/lib/providers/unsupported.js.map +1 -0
  339. package/vendor/computer-use/lib/service.js +608 -0
  340. package/vendor/computer-use/lib/service.js.map +1 -0
  341. package/vendor/computer-use/lib/skill.js +136 -0
  342. package/vendor/computer-use/lib/skill.js.map +1 -0
  343. package/vendor/computer-use/lib/target-resolver.js +180 -0
  344. package/vendor/computer-use/lib/target-resolver.js.map +1 -0
  345. package/vendor/computer-use/lib/tools.js +511 -0
  346. package/vendor/computer-use/lib/tools.js.map +1 -0
  347. package/vendor/computer-use/lib/types/approval-policy.d.ts +13 -0
  348. package/vendor/computer-use/lib/types/approval-policy.d.ts.map +1 -0
  349. package/vendor/computer-use/lib/types/artifacts.d.ts +10 -0
  350. package/vendor/computer-use/lib/types/artifacts.d.ts.map +1 -0
  351. package/vendor/computer-use/lib/types/backend.d.ts +124 -0
  352. package/vendor/computer-use/lib/types/backend.d.ts.map +1 -0
  353. package/vendor/computer-use/lib/types/client/index.d.ts +83 -0
  354. package/vendor/computer-use/lib/types/client/index.d.ts.map +1 -0
  355. package/vendor/computer-use/lib/types/config.d.ts +94 -0
  356. package/vendor/computer-use/lib/types/config.d.ts.map +1 -0
  357. package/vendor/computer-use/lib/types/confirmations.d.ts +23 -0
  358. package/vendor/computer-use/lib/types/confirmations.d.ts.map +1 -0
  359. package/vendor/computer-use/lib/types/diff.d.ts +5 -0
  360. package/vendor/computer-use/lib/types/diff.d.ts.map +1 -0
  361. package/vendor/computer-use/lib/types/errors.d.ts +15 -0
  362. package/vendor/computer-use/lib/types/errors.d.ts.map +1 -0
  363. package/vendor/computer-use/lib/types/exposure.d.ts +30 -0
  364. package/vendor/computer-use/lib/types/exposure.d.ts.map +1 -0
  365. package/vendor/computer-use/lib/types/index.d.ts +21 -0
  366. package/vendor/computer-use/lib/types/index.d.ts.map +1 -0
  367. package/vendor/computer-use/lib/types/leases.d.ts +81 -0
  368. package/vendor/computer-use/lib/types/leases.d.ts.map +1 -0
  369. package/vendor/computer-use/lib/types/providers/macos.d.ts +39 -0
  370. package/vendor/computer-use/lib/types/providers/macos.d.ts.map +1 -0
  371. package/vendor/computer-use/lib/types/providers/native-helper.d.ts +48 -0
  372. package/vendor/computer-use/lib/types/providers/native-helper.d.ts.map +1 -0
  373. package/vendor/computer-use/lib/types/providers/unsupported.d.ts +23 -0
  374. package/vendor/computer-use/lib/types/providers/unsupported.d.ts.map +1 -0
  375. package/vendor/computer-use/lib/types/service.d.ts +58 -0
  376. package/vendor/computer-use/lib/types/service.d.ts.map +1 -0
  377. package/vendor/computer-use/lib/types/skill.d.ts +14 -0
  378. package/vendor/computer-use/lib/types/skill.d.ts.map +1 -0
  379. package/vendor/computer-use/lib/types/target-resolver.d.ts +38 -0
  380. package/vendor/computer-use/lib/types/target-resolver.d.ts.map +1 -0
  381. package/vendor/computer-use/lib/types/tools.d.ts +6 -0
  382. package/vendor/computer-use/lib/types/tools.d.ts.map +1 -0
  383. package/vendor/computer-use/lib/types/types.d.ts +270 -0
  384. package/vendor/computer-use/lib/types/types.d.ts.map +1 -0
  385. package/vendor/computer-use/lib/types/web.d.ts +33 -0
  386. package/vendor/computer-use/lib/types/web.d.ts.map +1 -0
  387. package/vendor/computer-use/lib/types.js +9 -0
  388. package/vendor/computer-use/lib/types.js.map +1 -0
  389. package/vendor/computer-use/lib/web.js +188 -0
  390. package/vendor/computer-use/lib/web.js.map +1 -0
  391. package/vendor/computer-use/native/macos/Sources/Fixture/main.swift +412 -0
  392. package/vendor/computer-use/native/macos/Sources/Helper/CursorImage.swift +11 -0
  393. package/vendor/computer-use/native/macos/Sources/Helper/CursorMotion.swift +67 -0
  394. package/vendor/computer-use/native/macos/Sources/Helper/CursorOverlay.swift +840 -0
  395. package/vendor/computer-use/native/macos/Sources/Helper/TargetedPointer.swift +327 -0
  396. package/vendor/computer-use/native/macos/Sources/Helper/WindowNumberMatcher.swift +29 -0
  397. package/vendor/computer-use/native/macos/Sources/Helper/main.swift +1244 -0
  398. package/vendor/computer-use/native/macos/Sources/Monitor/main.swift +153 -0
  399. package/vendor/computer-use/native/macos/bin/dsh-computer-use-helper +0 -0
  400. package/vendor/computer-use/native/macos/manifest.json +14 -0
  401. package/vendor/persistent/LICENSE +21 -0
  402. package/vendor/persistent/index.js +411 -0
  403. package/vendor/persistent/types/index.d.ts +24 -0
  404. package/vendor/subagent/LICENSE +21 -0
  405. package/vendor/subagent/index.js +694 -0
  406. package/vendor/subagent/invariant.js +52 -0
  407. package/vendor/subagent/model-selection-settings.js +68 -0
  408. package/vendor/subagent/types/index.d.ts +82 -0
  409. package/vendor/subagent/types/invariant.d.ts +16 -0
  410. package/vendor/subagent/types/list-models.d.ts +10 -0
  411. package/vendor/subagent/types/model-selection-settings.d.ts +45 -0
  412. package/vendor/subagent/types/model-selection-state.d.ts +48 -0
  413. package/vendor/subagent/types/model-selection.d.ts +81 -0
  414. package/vendor/subagent-core/LICENSE +21 -0
  415. package/vendor/subagent-core/index.js +3202 -0
  416. package/vendor/subagent-core/invariant.js +76 -0
  417. package/vendor/subagent-core/typert.host.d.ts +3 -0
  418. package/vendor/subagent-core/typert.host.js +978 -0
  419. package/vendor/subagent-core/typert.remote-client.d.ts +25 -0
  420. package/vendor/subagent-core/typert.remote-client.js +114 -0
  421. package/vendor/subagent-core/types/archive-admission.d.ts +16 -0
  422. package/vendor/subagent-core/types/archive-admission.js +151 -0
  423. package/vendor/subagent-core/types/assistant-output.d.ts +48 -0
  424. package/vendor/subagent-core/types/assistant-output.js +73 -0
  425. package/vendor/subagent-core/types/catalog.d.ts +84 -0
  426. package/vendor/subagent-core/types/catalog.js +109 -0
  427. package/vendor/subagent-core/types/child-agent.d.ts +156 -0
  428. package/vendor/subagent-core/types/child-agent.js +213 -0
  429. package/vendor/subagent-core/types/client.d.ts +8 -0
  430. package/vendor/subagent-core/types/client.js +7 -0
  431. package/vendor/subagent-core/types/continuation-activation.d.ts +267 -0
  432. package/vendor/subagent-core/types/continuation-activation.js +700 -0
  433. package/vendor/subagent-core/types/continuation-messages.d.ts +62 -0
  434. package/vendor/subagent-core/types/continuation-messages.js +106 -0
  435. package/vendor/subagent-core/types/continuation.d.ts +124 -0
  436. package/vendor/subagent-core/types/continuation.js +455 -0
  437. package/vendor/subagent-core/types/control-types.d.ts +135 -0
  438. package/vendor/subagent-core/types/control-types.js +8 -0
  439. package/vendor/subagent-core/types/control.d.ts +45 -0
  440. package/vendor/subagent-core/types/control.js +79 -0
  441. package/vendor/subagent-core/types/depth.d.ts +31 -0
  442. package/vendor/subagent-core/types/depth.js +39 -0
  443. package/vendor/subagent-core/types/descriptor.d.ts +144 -0
  444. package/vendor/subagent-core/types/descriptor.js +193 -0
  445. package/vendor/subagent-core/types/error.d.ts +11 -0
  446. package/vendor/subagent-core/types/error.js +14 -0
  447. package/vendor/subagent-core/types/inbox.d.ts +43 -0
  448. package/vendor/subagent-core/types/inbox.js +61 -0
  449. package/vendor/subagent-core/types/index.d.ts +320 -0
  450. package/vendor/subagent-core/types/index.js +475 -0
  451. package/vendor/subagent-core/types/internal.d.ts +58 -0
  452. package/vendor/subagent-core/types/internal.js +58 -0
  453. package/vendor/subagent-core/types/invariant.d.ts +13 -0
  454. package/vendor/subagent-core/types/invariant.js +91 -0
  455. package/vendor/subagent-core/types/lifecycle.d.ts +113 -0
  456. package/vendor/subagent-core/types/lifecycle.js +180 -0
  457. package/vendor/subagent-core/types/list-children.d.ts +36 -0
  458. package/vendor/subagent-core/types/list-children.js +166 -0
  459. package/vendor/subagent-core/types/out-of-process.d.ts +118 -0
  460. package/vendor/subagent-core/types/out-of-process.js +219 -0
  461. package/vendor/subagent-core/types/projection-types.d.ts +82 -0
  462. package/vendor/subagent-core/types/projection-types.js +7 -0
  463. package/vendor/subagent-core/types/projection.d.ts +100 -0
  464. package/vendor/subagent-core/types/projection.js +157 -0
  465. package/vendor/subagent-core/types/run-settlement.d.ts +17 -0
  466. package/vendor/subagent-core/types/run-settlement.js +70 -0
  467. package/vendor/subagent-core/types/types.d.ts +377 -0
  468. package/vendor/subagent-core/types/types.js +19 -0
  469. package/vendor/subagent-driver/LICENSE +21 -0
  470. package/vendor/subagent-driver/index.js +255 -0
  471. package/vendor/subagent-driver/types/index.d.ts +33 -0
  472. package/vendor/subagent-driver/types/structured.d.ts +42 -0
  473. package/vendor/subagent-fork/LICENSE +21 -0
  474. package/vendor/subagent-fork/index.js +61 -0
  475. package/vendor/subagent-fork/types/index.d.ts +20 -0
  476. package/vendor/subagent-spawn/LICENSE +21 -0
  477. package/vendor/subagent-spawn/index.js +45 -0
  478. package/vendor/subagent-spawn/types/index.d.ts +19 -0
  479. package/vendor/terminal/LICENSE +21 -0
  480. package/vendor/terminal/index.js +1093 -0
  481. package/vendor/terminal/types/config.d.ts +82 -0
  482. package/vendor/terminal/types/index.d.ts +36 -0
  483. package/vendor/terminal/types/sanitize.d.ts +47 -0
  484. package/vendor/terminal/types/session.d.ts +87 -0
@@ -0,0 +1,113 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { hookEvents, validateHooks } from './hooks.mjs';
4
+ import { enabledFlag } from './workspace-discovery.mjs';
5
+
6
+ // Project hook files layer on top of the installation file by default. They run as
7
+ // the OS user outside tool approval, so a cloned repository can install gates;
8
+ // DSCODE_PROJECT_HOOKS=0/off/false loads the installation file alone.
9
+ // `.codex/hooks.json` and `.dsh/hooks.json` are the bridge's own shape;
10
+ // `.claude/settings.json` keeps hooks under a top-level `hooks` key and is skipped
11
+ // when that key is absent.
12
+ export const projectHookFiles = Object.freeze([
13
+ { path: '.codex/hooks.json' },
14
+ { path: '.dsh/hooks.json' },
15
+ { path: '.claude/settings.json', nested: true },
16
+ ]);
17
+
18
+ export const resolvedHookFile = 'hooks.resolved.json';
19
+ export const hookReportFile = 'hooks.resolved.report.json';
20
+
21
+ export function projectHooksEnabled(env = process.env) {
22
+ const value = env.DSCODE_PROJECT_HOOKS;
23
+ return value === undefined ? true : enabledFlag(value);
24
+ }
25
+
26
+ function extractHooks(parsed, nested) {
27
+ const hooks = parsed?.hooks !== undefined ? parsed.hooks : (nested ? undefined : parsed);
28
+ if (hooks === undefined) return undefined;
29
+ if (!hooks || typeof hooks !== 'object' || Array.isArray(hooks)) throw new Error('hooks must be an event map');
30
+ return hooks;
31
+ }
32
+
33
+ // The installation file is trusted and must fail loudly on anything this bridge
34
+ // cannot run.
35
+ export function readInstallationHooks(path) {
36
+ return validateHooks(JSON.parse(readFileSync(path, 'utf8')));
37
+ }
38
+
39
+ // A project file is only filtered: a Claude Code settings.json routinely carries
40
+ // events this bridge does not implement, and skipping them must not stop dscode
41
+ // from starting. Every skip is reported so it is visible rather than silent.
42
+ export function readProjectHooks(path, { nested = false } = {}) {
43
+ const hooks = extractHooks(JSON.parse(readFileSync(path, 'utf8')), nested);
44
+ if (hooks === undefined) return undefined;
45
+ const kept = {};
46
+ const skipped = [];
47
+ for (const [event, groups] of Object.entries(hooks)) {
48
+ if (!hookEvents.includes(event)) { skipped.push(event); continue; }
49
+ // A project file is untrusted input: a gate this bridge cannot run is dropped
50
+ // with its reason rather than allowed to stop dscode from starting.
51
+ try {
52
+ validateHooks({ hooks: { [event]: groups } });
53
+ } catch (error) {
54
+ const reason = error.message.startsWith(`${event}: `) ? error.message.slice(event.length + 2) : error.message;
55
+ skipped.push(`${event} (${reason})`);
56
+ continue;
57
+ }
58
+ kept[event] = groups;
59
+ }
60
+ return { hooks: Object.keys(kept).length ? kept : undefined, skipped };
61
+ }
62
+
63
+ export function resolveHookSources({ root, cwd = root, env = process.env }) {
64
+ const installation = join(root, 'config/hooks.local.json');
65
+ const sources = [{ path: installation, hooks: readInstallationHooks(installation) }];
66
+ const skipped = [];
67
+ if (!projectHooksEnabled(env)) return { sources, skipped };
68
+ for (const file of projectHookFiles) {
69
+ const path = join(cwd, file.path);
70
+ if (!existsSync(path)) continue;
71
+ let parsed;
72
+ try {
73
+ parsed = readProjectHooks(path, file);
74
+ } catch (error) {
75
+ // Unreadable JSON (a Claude settings file may even carry comments) is a
76
+ // report, not a startup failure, for a file dscode did not write.
77
+ skipped.push({ path: file.path, events: [`(not loaded: ${error.message})`] });
78
+ continue;
79
+ }
80
+ if (!parsed) continue;
81
+ if (parsed.skipped.length) skipped.push({ path: file.path, events: parsed.skipped });
82
+ if (parsed.hooks) sources.push({ path, hooks: parsed.hooks });
83
+ }
84
+ return { sources, skipped };
85
+ }
86
+
87
+ export function mergeHooks(sources) {
88
+ const hooks = {};
89
+ for (const source of sources) {
90
+ for (const [event, groups] of Object.entries(source.hooks ?? {})) hooks[event] = [...(hooks[event] ?? []), ...groups];
91
+ }
92
+ return { hooks };
93
+ }
94
+
95
+ // The pinned bridge takes one config path for the whole process, so layered files
96
+ // are merged into a single resolved file. A single source stays where it is edited.
97
+ export function writeHookConfig({ root, cwd = root, home, env = process.env }) {
98
+ const { sources, skipped } = resolveHookSources({ root, cwd, env });
99
+ const paths = sources.map(source => source.path);
100
+ const resolved = join(home, resolvedHookFile);
101
+ const report = join(home, hookReportFile);
102
+ if (sources.length === 1) {
103
+ // A stale merge must not outlive the layers it came from: /hooks reads the
104
+ // report, and a leftover one would describe sources that are no longer loaded.
105
+ if (existsSync(resolved)) rmSync(resolved);
106
+ if (existsSync(report)) rmSync(report);
107
+ return { path: sources[0].path, sources: paths, skipped };
108
+ }
109
+ mkdirSync(home, { recursive: true });
110
+ writeFileSync(resolved, JSON.stringify(mergeHooks(sources), null, 2) + '\n', { mode: 0o600 });
111
+ writeFileSync(report, JSON.stringify({ sources: paths, skipped }, null, 2) + '\n', { mode: 0o600 });
112
+ return { path: resolved, sources: paths, skipped };
113
+ }
@@ -0,0 +1,23 @@
1
+ export const hookEvents = ['SessionStart', 'UserPromptSubmit', 'PreToolUse', 'PostToolUse', 'Stop'];
2
+ // Fail visibly instead of letting the upstream compatibility bridge silently skip gates.
3
+ export function validateHooks(raw) {
4
+ const hooks = raw?.hooks ?? raw;
5
+ if (!hooks || typeof hooks !== 'object' || Array.isArray(hooks)) throw new Error('hooks must be an event map');
6
+ for (const [event, groups] of Object.entries(hooks)) {
7
+ if (!hookEvents.includes(event)) throw new Error(`Unsupported hook event: ${event}`);
8
+ if (!Array.isArray(groups)) throw new Error(`${event}: expected matcher groups`);
9
+ for (const group of groups) {
10
+ if (!group || !Array.isArray(group.hooks)) throw new Error(`${event}: expected hooks array`);
11
+ if (group.matcher !== undefined) {
12
+ if (typeof group.matcher !== 'string') throw new Error(`${event}: matcher must be a regex string`);
13
+ new RegExp(group.matcher);
14
+ }
15
+ for (const hook of group.hooks) {
16
+ if (!hook || (hook.type !== undefined && hook.type !== 'command') || hook.async === true || typeof hook.command !== 'string' || !hook.command.trim()) throw new Error(`${event}: only synchronous command hooks are supported`);
17
+ const timeout = hook.timeout ?? hook.timeoutSec;
18
+ if (timeout !== undefined && (!Number.isFinite(timeout) || timeout <= 0 || timeout > 600)) throw new Error(`${event}: timeout must be 0–600 seconds, excluding zero`);
19
+ }
20
+ }
21
+ }
22
+ return hooks;
23
+ }
@@ -0,0 +1,268 @@
1
+ import { runShell } from './shell.mjs';
2
+ import { VERSION_PATTERN, scheduleUpdate } from './update.mjs';
3
+ import { readLanguage, t } from '../i18n/messages.mjs';
4
+ import { hookReportFile } from './hook-sources.mjs';
5
+ import { readFile, readdir, access, stat } from 'node:fs/promises';
6
+ import { dirname, join, resolve } from 'node:path';
7
+ import { parse } from 'yaml';
8
+ import { createUserMessage } from '@deepseek-ai/dsh-llm';
9
+ import { inspectComposition, presetInventoryLines, presetMcpNotice } from './composition.mjs';
10
+ import { hookEvents, validateHooks } from './hooks.mjs';
11
+ import { redact } from '../auto-review/policy.mjs';
12
+ import { plainConfig } from '../cordis-config/plain.mjs';
13
+ import { analyzeDoctorEvidence, collectDoctorEvidence, recordRuntimeLog } from './doctor.mjs';
14
+
15
+ export const name = 'dscode-tui-tools';
16
+ export const inject = ['commands', 'agents', 'tools', 'skills', 'permissionPresets', 'sessionPersistence', 'llm'];
17
+ const phases = ['pending', 'loading', 'active', 'failed', 'unavailable', 'unloading'];
18
+ const ok = text => ({ kind: 'success', text });
19
+ const fail = text => ({ kind: 'error', text });
20
+ const show = value => typeof value === 'string' ? value : JSON.stringify(value ?? null);
21
+ const exists = path => access(path).then(() => true, () => false);
22
+
23
+ /** Ancestor skill roots the preset's own expression reads, for a reader that cannot evaluate it. */
24
+ function ancestorDirsFrom(env) {
25
+ try {
26
+ const parsed = JSON.parse(env.DSCODE_SKILL_ANCESTOR_DIRS ?? '[]');
27
+ return Array.isArray(parsed) ? parsed : [];
28
+ } catch { return []; }
29
+ }
30
+
31
+ export async function findConflicts(cwd, configs, winners, env = process.env) {
32
+ let project = resolve(cwd);
33
+ while (!await exists(join(project, '.git')) && dirname(project) !== project) project = dirname(project);
34
+ if (!await exists(join(project, '.git'))) project = resolve(cwd);
35
+ const roots = [];
36
+ const skipSystemRoots = new Set();
37
+ for (const config of configs) {
38
+ if (config.includeDefaultRoots !== false) {
39
+ roots.push(join(project, '.dsh/skills'), join(project, '.agents/skills'));
40
+ const dshHome = config.dshHome ?? env.DSH_HOME;
41
+ const agentsHome = config.agentsHome ?? env.DSH_AGENTS_HOME;
42
+ if (typeof dshHome === 'string') { const path = resolve(dshHome, 'skills'); roots.push(path); skipSystemRoots.add(path); }
43
+ if (typeof agentsHome === 'string') roots.push(resolve(agentsHome, 'skills'));
44
+ }
45
+ // A preset declares its ancestor roots as a `!!js` expression over this variable, which
46
+ // a reader of the row cannot evaluate; the environment it reads is the same here.
47
+ const custom = Array.isArray(config.customSkillDirs) ? config.customSkillDirs : ancestorDirsFrom(env);
48
+ roots.push(...custom.filter(x => typeof x === 'string').map(x => resolve(x)));
49
+ const bundled = config.bundledSkillDir ?? (config.includeDefaultRoots !== false ? env.DSH_BUNDLED_SKILL_DIR : undefined);
50
+ if (typeof bundled === 'string') roots.push(resolve(bundled));
51
+ }
52
+ const candidates = new Map();
53
+ const errors = [];
54
+ for (const root of new Set(roots)) {
55
+ let entries;
56
+ try { entries = await readdir(root, { withFileTypes: true }); }
57
+ catch (e) { if (e.code !== 'ENOENT') errors.push(`${root}: ${e.code}`); continue; }
58
+ for (const entry of entries) {
59
+ if (entry.name === '.system' && skipSystemRoots.has(root)) continue;
60
+ const path = entry.isFile() && entry.name.endsWith('.md') ? join(root, entry.name) : join(root, entry.name, 'SKILL.md');
61
+ try {
62
+ const raw = await readFile(path, 'utf8');
63
+ const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
64
+ const meta = match && parse(match[1]);
65
+ if (typeof meta?.name !== 'string' || typeof meta.description !== 'string') continue;
66
+ const list = candidates.get(meta.name) ?? [];
67
+ list.push(path); candidates.set(meta.name, list);
68
+ } catch (e) { if (!['ENOENT', 'ENOTDIR'].includes(e.code)) errors.push(`${path}: invalid or unreadable`); }
69
+ }
70
+ }
71
+ const lines = [];
72
+ for (const [name, paths] of candidates) if (paths.length > 1) {
73
+ const winner = winners.find(s => s.name === name);
74
+ lines.push(`${name}: effective source=${winner?.source ?? 'not in catalog'} provider=${winner?.provider ?? '?'}\n${paths.map(p => ` ${p}`).join('\n')}`);
75
+ }
76
+ return [...lines, ...errors, 'Scope: filesystem roots only; runtime/remote provider shadowed candidates are not exposed by DSH.'].join('\n');
77
+ }
78
+
79
+ // The pinned bridge reads one merged file for the whole process, and /hooks reload
80
+ // remounts the plugin with the same path, so an edited layer is not picked up until
81
+ // dscode restarts. Report that instead of letting the user believe the edit is live.
82
+ export async function staleLayers(resolvedPath, sources = []) {
83
+ const mergedAt = await stat(resolvedPath).then(value => value.mtimeMs).catch(() => undefined);
84
+ if (mergedAt === undefined) return [];
85
+ const stale = [];
86
+ for (const source of sources) {
87
+ if (source === resolvedPath) continue;
88
+ const at = await stat(source).then(value => value.mtimeMs).catch(() => undefined);
89
+ if (at === undefined) stale.push(`${source} (missing)`);
90
+ else if (at > mergedAt) stale.push(`${source} (newer than the merge)`);
91
+ }
92
+ return stale;
93
+ }
94
+
95
+ export function apply(ctx) {
96
+ return install(ctx, false);
97
+ }
98
+
99
+ export function applyDesktop(ctx) {
100
+ return install(ctx, true);
101
+ }
102
+
103
+ function install(ctx, desktop) {
104
+ const diagnosticsHome = process.env.DSH_HOME ?? process.env.DSCODE_HOME;
105
+ // A minimal composition (and the unit fixtures) may mount no logger; diagnostics are best-effort.
106
+ if (diagnosticsHome) ctx.logger?.exporter?.({ levels: { default: 2 }, export: message => recordRuntimeLog(diagnosticsHome, message) });
107
+ const composition = agent => {
108
+ const inventory = inspectComposition(ctx, agent);
109
+ if (!desktop) return inventory;
110
+ // Older runtimes also expose mutable standing preset entries. Desktop keeps
111
+ // those out of process-wide controls on every supported runtime version.
112
+ return { ...inventory, hostOnly: true,
113
+ entries: [...(ctx.get('loader')?.entries() ?? [])].filter(entry => entry.options.group !== true) };
114
+ };
115
+ const entries = agent => composition(agent).entries;
116
+ const mcps = agent => entries(agent).filter(e => e.options.name === '@deepseek-ai/dsh-mcp-client');
117
+ const hook = () => entries().find(e => e.options.id === 'dscode-hooks');
118
+ const state = e => e.disabled ? 'disabled' : phases[e.fiber?.state] ?? 'unavailable';
119
+ let changing = false;
120
+ const commandName = name => desktop ? `dscode-${name}` : name;
121
+ const mutate = async fn => {
122
+ if (changing || ctx.agents.list().some(a => a.status === 'running')) return fail('Wait until all agents are idle before changing process-wide plugins.');
123
+ changing = true;
124
+ try { return await fn(); } finally { changing = false; }
125
+ };
126
+ const register = (name, description, handler) => {
127
+ // Desktop owns its updater and shell UI. Register diagnostics separately
128
+ // so the native commands and other presets retain their own handlers.
129
+ if (desktop && !['status', 'doctor', 'mcp', 'skills'].includes(name)) return;
130
+ const hint = { doctor: '[preview|local]', mcp: '[list|tools <id>|enable <id>|disable <id>|reconnect <id>]', skills: '[list|conflicts|<name>]' }[name];
131
+ return ctx.commands.register({ name: commandName(name), description, ...(hint ? { input: { hint } } : {}), handler: async inv => {
132
+ if (desktop && ctx.agentPresets.composedPreset(inv.agent.ctx) !== 'dscode') return fail('Choose a DSCODE session to use DSCODE diagnostics.');
133
+ try {
134
+ const result = await handler(inv);
135
+ return { ...result, text: redact(result.text ?? '') };
136
+ }
137
+ catch (e) { return fail(redact(`${name}: ${e.message}`)); }
138
+ }});
139
+ };
140
+ register('shell-exec', 'Run a user shell command (also !command)', async ({ rawInput, agent, signal }) => {
141
+ const result = await runShell(rawInput, { cwd: agent.session.header.cwd ?? process.cwd(), signal });
142
+ // What the user ran belongs to the conversation: the command and its (redacted) output
143
+ // are handed to the agent, which then gets a turn to react to them.
144
+ const handover = redact(`[shell] $ ${rawInput.trim()}\n${result.text}`).slice(0, 8000);
145
+ try {
146
+ agent.followup(createUserMessage({ content: [{ type: 'text', text: handover }], source: { kind: 'dscode-shell-exec' } }));
147
+ await ctx.get('sessions')?.flush?.(agent.session);
148
+ } catch (error) {
149
+ return fail(`shell: the command ran, but its output could not reach the agent (${error.message})`);
150
+ }
151
+ return { ...result, text: `${result.text}\n\n[output handed to the agent]` };
152
+ });
153
+ register('status', 'Session, model, permissions, usage and plugin health', ({ agent }) => {
154
+ const session = agent.session;
155
+ const route = session.requestHeader()?.config ?? agent.options;
156
+ const events = session.snapshotEvents();
157
+ const projections = ctx.get('sessionProjections');
158
+ const usage = projections?.stateOf(session, 'tokenUsage')?.totals;
159
+ const pressure = projections?.stateOf(session, 'contextPressure');
160
+ const inventory = composition(agent);
161
+ const hostOnly = inventory.hostOnly || inventory.inspections !== null;
162
+ return ok([
163
+ `Session: ${session.id}`, `Workspace: ${session.header.cwd ?? process.cwd()}`,
164
+ `Agent: ${agent.status} | preset: ${session.header.agentPreset ?? 'standard'}`,
165
+ `Model: ${route?.provider ?? 'default'} / ${route?.model ?? 'default'}`,
166
+ `Effort: ${route?.reasoningEffort ?? 'model default'}${route?.reasoningEffort === 'ultra' ? ` (${route.provider === 'deepseek-official' ? 'DeepSeek wire: max' : route.model?.startsWith('deepseek/') ? 'OpenRouter wire: xhigh' : "sent as the model's max level"}; collaboration enabled)` : ''}`,
167
+ `Permission: ${show(ctx.permissionPresets.current(session))}`,
168
+ `Tokens: ${show(usage ?? 'no provider usage yet')}`,
169
+ `Context: ${pressure?.pressureTokens ?? pressure?.surfaceTokens ?? '?'} / ${pressure?.contextWindow ?? '?'} tokens`,
170
+ `Events: ${events.length}; /review-usage shows reviewer tokens`,
171
+ `Tools: ${ctx.tools.schemas(agent).length}; ${hostOnly ? 'Host ' : ''}MCP entries: ${inventory.entries.filter(e => e.options.name === '@deepseek-ai/dsh-mcp-client').length}`,
172
+ `${hostOnly ? 'Host plugins' : 'Plugins'}: ${inventory.entries.filter(e => state(e) === 'active').length} active, ${inventory.entries.filter(e => state(e) === 'failed').length} failed`,
173
+ ...presetInventoryLines(inventory),
174
+ desktop ? 'Use /dscode-doctor for diagnostics; inspect execution details in Trajectory.' : 'Use /doctor for diagnostics; /statusline for live context/token display.',
175
+ ].join('\n'));
176
+ });
177
+ register('update', 'Upgrade DSCODE after this session exits', ({ rawInput }) => {
178
+ const version = rawInput.trim() || 'latest';
179
+ const locale = readLanguage();
180
+ if (version !== 'latest' && !VERSION_PATTERN.test(version)) return fail(t(locale, 'update.usage'));
181
+ const { log } = scheduleUpdate({ helperModuleUrl: new URL('./update.mjs', import.meta.url), pid: process.pid, version });
182
+ return ok(t(locale, 'update.scheduled', { version: version === 'latest' ? t(locale, 'update.newest') : version, log }));
183
+ });
184
+ register('doctor', 'Analyze recent runtime logs and session traces', async ({ agent, signal, rawInput }) => {
185
+ const action = rawInput.trim();
186
+ if (!['', 'preview', 'local'].includes(action)) return fail(`Usage: /${commandName('doctor')} [preview|local]`);
187
+ const tools = ctx.tools.schemas(agent).map(t => t.name);
188
+ const catalog = await ctx.skills.snapshot({ cwd: agent.session.header.cwd, scope: agent, signal });
189
+ const computer = ctx.get('computerUse');
190
+ const health = [
191
+ `Node: ${process.version}; platform: ${process.platform}/${process.arch}`,
192
+ ...entries(agent).filter(e => !e.disabled && state(e) !== 'active').map(e => `CHECK plugin ${e.id}: ${state(e)}`),
193
+ ...presetInventoryLines(composition(agent)),
194
+ `Skills: ${catalog.skills.length}; discovery ${catalog.complete ? 'complete' : 'incomplete'}`,
195
+ `Core tools: ${['bash', 'skill', 'computer_use_activate'].map(n => `${n}=${tools.includes(n)}`).join(', ')}`,
196
+ ...mcps(agent).map(e => `MCP ${e.id}: ${state(e)}; ${tools.filter(n => n.startsWith(`mcp__${e.options.config?.serverName}__`)).length} registered tools`),
197
+ `Computer Use: ${computer ? show(await computer.status()) : 'service unavailable'}`,
198
+ 'Credentials are not read or printed. Diagnostic metadata may be sent to the selected model.',
199
+ ].join('\n');
200
+ const evidence = await collectDoctorEvidence(ctx, { agent, signal, workspaceOnly: desktop });
201
+ if (action === 'preview') return ok(JSON.stringify(evidence, null, 2));
202
+ const route = agent.session.requestHeader()?.config ?? agent.options;
203
+ return ok(`${health}\n\n${await analyzeDoctorEvidence(ctx, evidence, route, signal, { model: action !== 'local', sessionId: agent.session.id })}`);
204
+ });
205
+ register('mcp', 'MCP list, tools <id>, enable/disable/reconnect <id>', async ({ agent, rawInput }) => {
206
+ const [action = 'list', id, extra] = rawInput.trim().split(/\s+/).filter(Boolean);
207
+ const list = mcps(agent);
208
+ const notice = presetMcpNotice(composition(agent), commandName('mcp'))
209
+ || (desktop ? 'Only Host MCP entries can be changed here. Change preset servers through their bundle configuration and restart.' : '');
210
+ if (action === 'list') return ok([...list.map(e => `${e.id}: ${state(e)} | server=${show(e.options.config?.serverName)} | transport=${show(e.options.config?.transport)}`), ...(notice ? [notice] : [])].join('\n') + `\n/${commandName('mcp')} tools|enable|disable|reconnect <entry-id> — changes last for this process.`);
211
+ const matches = list.filter(e => e.id === id || e.options.id === id);
212
+ const entry = matches.length === 1 ? matches[0] : undefined;
213
+ if (!entry || extra) return fail(`Usage: /${commandName('mcp')} [list | tools|enable|disable|reconnect <entry-id>]` + (notice ? `\n${notice}` : ''));
214
+ if (action === 'tools') return ok(ctx.tools.schemas(agent).filter(t => t.name.startsWith(`mcp__${entry.options.config?.serverName}__`)).map(t => t.name).join('\n') || 'No tools currently registered.');
215
+ if (!['enable', 'disable', 'reconnect'].includes(action)) return fail('Unknown MCP action.');
216
+ return mutate(async () => {
217
+ if (action === 'reconnect' && entry.disabled) return fail('Enable this server before reconnecting.');
218
+ if (action === 'reconnect') await entry.update({ disabled: true });
219
+ await entry.update({ disabled: action === 'disable' });
220
+ return ok(`${entry.id}: ${state(entry)}. Use /${commandName('mcp')} tools ${entry.id} to check discovery.`);
221
+ });
222
+ });
223
+ register('skills', 'Skill catalog, sources, details and filesystem conflicts', async ({ agent, rawInput, signal }) => {
224
+ const options = { cwd: agent.session.header.cwd ?? process.cwd(), scope: agent, signal };
225
+ const { skills, complete } = await ctx.skills.snapshot(options);
226
+ const arg = rawInput.trim();
227
+ if (arg === 'conflicts') {
228
+ const inventory = composition(agent);
229
+ const report = await findConflicts(options.cwd, inventory.entries.filter(e => !e.disabled && e.options.name === '@deepseek-ai/dsh-skill-filesystem').map(e => plainConfig(e.options.config)), skills);
230
+ const missingPresetConfig = inventory.inspections?.some(preset => preset.modules.some(module => module.moduleName === '@deepseek-ai/dsh-skill-filesystem'));
231
+ return ok(report + (desktop ? '\nIncomplete: per-agent Desktop filesystem roots are not exposed by the preset inventory; only Host filesystem roots were checked.'
232
+ : missingPresetConfig ? '\nIncomplete: this runtime does not expose preset filesystem configuration; only Host filesystem roots were checked.' : ''));
233
+ }
234
+ if (arg && arg !== 'list') {
235
+ const skill = await ctx.skills.get(arg, options);
236
+ return skill ? ok(`${skill.name}\n${skill.description}\nsource: ${skill.source}\nprovider: ${skill.provider}\npath: ${skill.path ?? '(provider managed)'}\ninvocation: ${show(skill.invocation)}`) : fail(`Unknown skill: ${arg}`);
237
+ }
238
+ return ok(`Discovery: ${complete ? 'complete' : 'incomplete'}\n${skills.map(s => `${s.name} [${s.source}; ${s.provider}] user=${s.invocation.userInvocable} model=${s.invocation.modelInvocable}\n ${s.description}`).join('\n')}\n/${commandName('skills')} <name> for details; /${commandName('skills')} conflicts for duplicate filesystem names.`);
239
+ });
240
+ const hookPaths = new WeakMap();
241
+ const hookPath = entry => {
242
+ const path = entry.fiber?.config?.configPath ?? entry.options.config?.configPath;
243
+ if (typeof path === 'string') { hookPaths.set(entry, path); return path; }
244
+ const cached = hookPaths.get(entry) ?? ctx.get('dscodePaths')?.hooks;
245
+ if (typeof cached !== 'string') throw new Error('Hook configuration path has not resolved');
246
+ return cached;
247
+ };
248
+ register('hooks', 'Hook status and reload/disable/enable (installation-owned config)', async ({ rawInput }) => {
249
+ const entry = hook();
250
+ if (!entry) return fail('Hooks plugin is not mounted. Restart dscode after setup.');
251
+ const action = rawInput.trim() || 'list';
252
+ if (action !== 'list') {
253
+ if (!['reload', 'disable', 'enable'].includes(action)) return fail('Usage: /hooks [list|reload|disable|enable]');
254
+ return mutate(async () => {
255
+ if (action !== 'disable') validateHooks(JSON.parse(await readFile(hookPath(entry), 'utf8')));
256
+ if (action === 'reload') await entry.update({ disabled: true });
257
+ await entry.update({ disabled: action === 'disable' });
258
+ return ok(`Hooks: ${state(entry)}. Configuration changes apply after reload or restart.`);
259
+ });
260
+ }
261
+ const path = hookPath(entry);
262
+ const raw = JSON.parse(await readFile(path, 'utf8'));
263
+ const hooks = raw.hooks ?? raw;
264
+ const report = await readFile(join(dirname(path), hookReportFile), 'utf8').then(JSON.parse).catch(() => undefined);
265
+ const stale = report ? await staleLayers(path, report.sources) : [];
266
+ return ok(`Hooks: ${state(entry)}\nConfig: ${path}\n${Object.entries(hooks).map(([event, groups]) => `${event}: ${hookEvents.includes(event) ? 'supported' : 'UNSUPPORTED'}; ${Array.isArray(groups) ? groups.length : 0} groups`).join('\n')}\nSupported: ${hookEvents.join(', ')}\nOnly synchronous command hooks. Runs as your OS user, outside tool approval. Edit only trusted installation-owned config; /hooks reload applies it. Project files (.codex/hooks.json, .dsh/hooks.json, .claude/settings.json) layer on top unless DSCODE_PROJECT_HOOKS=0; events this bridge does not support are skipped rather than fatal, and any edit to a layer needs a restart.${report ? `\nLayers: ${report.sources.join(', ')}${report.skipped.length ? `\nSkipped by this bridge: ${report.skipped.map(entry => `${entry.path}: ${entry.events.join(', ')}`).join('; ')}` : ''}` : ''}${stale.length ? `\nNeeds restart: ${stale.join('; ')} — /hooks reload re-reads the merged file, not its sources.` : ''}\nPreCompact/PostCompact, PermissionRequest and subagent events are not supported by this bridge.`);
267
+ });
268
+ }
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+ // A custom runner for @deepseek-ai/dsh-sandbox-local, selected through the `sandbox`
3
+ // row's `runnerCommand`. The provider appends a bwrap-compatible profile and then
4
+ // `--` and the command:
5
+ //
6
+ // dsh-sandbox-runner --ro-bind / / --dev /dev --unshare-pid --proc /proc
7
+ // --die-with-parent [--tmpfs /tmp] [--bind <root> <root>] -- <command...>
8
+ //
9
+ // We translate the profile into a Seatbelt one and add the single grant the built-in
10
+ // profile lacks: /dev/ptmx. Without it a confined command cannot allocate a PTY
11
+ // (posix_openpt returns EPERM), which silently breaks nested harnesses, tmux, expect
12
+ // and any node-pty based suite. When the kernel refuses to apply another profile —
13
+ // which is exactly what happens inside an already-confined process — the command
14
+ // inherits the enclosing profile instead of nesting a second one.
15
+ import { spawn, spawnSync } from 'node:child_process';
16
+ import { realpathSync } from 'node:fs';
17
+ import { tmpdir } from 'node:os';
18
+ import { resolve } from 'node:path';
19
+ import { fileURLToPath } from 'node:url';
20
+
21
+ export const NAME = 'dscode-sandbox-runner';
22
+ // Configure this string as runnerFailureSignatures so the provider recognises our
23
+ // own failures instead of reading them as a denied command.
24
+ export const FATAL_PREFIX = `${NAME}: fatal: `;
25
+ // Informational output must never carry the configured failure signature: the provider
26
+ // turns any non-zero exit whose stderr matches it into a sandbox failure, so a notice
27
+ // would misreport a failing command as a broken runner.
28
+ export const NOTICE_PREFIX = `${NAME}: notice: `;
29
+ export const SANDBOX_EXEC = '/usr/bin/sandbox-exec';
30
+
31
+ const OPERAND_FLAGS = new Map([['--ro-bind', 2], ['--bind', 2], ['--tmpfs', 1], ['--dev', 1], ['--proc', 1], ['--dir', 1]]);
32
+
33
+ const canonical = path => {
34
+ try { return realpathSync(path); } catch { return resolve(path); }
35
+ };
36
+
37
+ const sbpl = path => `"${String(path).replaceAll('\\', '\\\\').replaceAll('"', '\\"')}"`;
38
+
39
+ /** Split the appended bwrap-compatible profile from the command after `--`. */
40
+ export function parseProfile(argv) {
41
+ const writable = [];
42
+ let index = 0;
43
+ while (index < argv.length) {
44
+ const token = argv[index];
45
+ if (token === '--') { index += 1; break; }
46
+ if (!token.startsWith('--')) throw new Error(`unexpected profile argument ${JSON.stringify(token)}`);
47
+ const operands = OPERAND_FLAGS.get(token) ?? 0;
48
+ if (operands === 2) {
49
+ const [, destination] = [argv[index + 1], argv[index + 2]];
50
+ if (!destination) throw new Error(`${token} needs two operands`);
51
+ if (token === '--bind') writable.push(destination);
52
+ } else if (operands === 1 && !argv[index + 1]) throw new Error(`${token} needs an operand`);
53
+ index += operands + 1;
54
+ }
55
+ return { writable, command: argv.slice(index) };
56
+ }
57
+
58
+ /** Writable roots that mirror the provider's own Seatbelt grant, plus the temp areas. */
59
+ export function writableRoots(parsed, { temp = tmpdir() } = {}) {
60
+ return [...new Set([...parsed.writable, '/tmp', temp].map(canonical))];
61
+ }
62
+
63
+ /** The SBPL profile: upstream's deny-by-default write policy plus /dev/ptmx. */
64
+ export function seatbeltProfile(roots) {
65
+ const forms = [
66
+ '(version 1)',
67
+ '(allow default)',
68
+ '(deny file-write*)',
69
+ `(allow file-write* (literal ${sbpl('/dev/null')}))`,
70
+ `(allow file-write* (literal ${sbpl('/dev/ptmx')}))`,
71
+ ];
72
+ if (roots.length) forms.push(`(allow file-write* ${roots.map(root => `(subpath ${sbpl(root)})`).join(' ')})`);
73
+ return forms.join(' ');
74
+ }
75
+
76
+ /** Whether this process may apply a Seatbelt profile at all. */
77
+ export function seatbeltApplies(exec = SANDBOX_EXEC) {
78
+ const probe = spawnSync(exec, ['-p', '(version 1)(allow default)', '/usr/bin/true'], { stdio: ['ignore', 'ignore', 'pipe'], encoding: 'utf8' });
79
+ if (probe.error) return probe.error.code === 'ENOENT' ? { ok: false, reason: 'missing' } : { ok: false, reason: probe.error.message };
80
+ if (probe.status === 0) return { ok: true };
81
+ return { ok: false, reason: (probe.stderr ?? '').trim().split('\n').at(-1) || `exit ${probe.status}` };
82
+ }
83
+
84
+ const SIGNAL_CODES = { SIGHUP: 129, SIGINT: 130, SIGTERM: 143 };
85
+
86
+ function runUnder(program, args) {
87
+ return new Promise(resolvePromise => {
88
+ const child = spawn(program, args, { stdio: 'inherit' });
89
+ const forward = signal => () => { try { child.kill(signal); } catch { /* already gone */ } };
90
+ const handlers = Object.keys(SIGNAL_CODES).map(signal => [signal, forward(signal)]);
91
+ for (const [signal, handler] of handlers) process.on(signal, handler);
92
+ child.on('error', error => { process.stderr.write(`${FATAL_PREFIX}${error.message}\n`); resolvePromise(126); });
93
+ child.on('exit', (code, signal) => resolvePromise(code ?? SIGNAL_CODES[signal] ?? 1));
94
+ });
95
+ }
96
+
97
+ export async function run(argv, { exec = SANDBOX_EXEC, stderr = process.stderr } = {}) {
98
+ const parsed = parseProfile(argv);
99
+ if (parsed.command.length === 0) {
100
+ stderr.write(`${FATAL_PREFIX}no command after --\n`);
101
+ return 126;
102
+ }
103
+ const [program, ...args] = parsed.command;
104
+ const applies = seatbeltApplies(exec);
105
+ if (!applies.ok && applies.reason === 'missing') {
106
+ stderr.write(`${FATAL_PREFIX}${exec} is not available; refusing to run unconfined\n`);
107
+ return 126;
108
+ }
109
+ if (!applies.ok) {
110
+ // Applying a profile is what the kernel refuses inside an existing one, so this
111
+ // process is already confined: inherit that profile rather than nest a second.
112
+ stderr.write(`${NOTICE_PREFIX}inheriting the enclosing profile (${applies.reason})\n`);
113
+ return runUnder(program, args);
114
+ }
115
+ return runUnder(exec, ['-p', seatbeltProfile(writableRoots(parsed)), '--', program, ...args]);
116
+ }
117
+
118
+ if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
119
+ run(process.argv.slice(2)).then(code => { process.exitCode = code; }).catch(error => {
120
+ process.stderr.write(`${FATAL_PREFIX}${error.message}\n`);
121
+ process.exitCode = 126;
122
+ });
123
+ }
@@ -0,0 +1,27 @@
1
+ import { spawn } from 'node:child_process';
2
+
3
+ // User-authored shell commands only: never registered as an agent tool.
4
+ export function runShell(command, { cwd, signal, timeoutMs = 120000, maxBytes = 65536 } = {}) {
5
+ if (!command.trim()) return Promise.resolve({ kind: 'error', text: 'Usage: !<shell command>' });
6
+ if (signal?.aborted) return Promise.resolve({ kind: 'error', text: 'Shell command cancelled' });
7
+ return new Promise(resolve => {
8
+ const child = spawn(process.env.SHELL || '/bin/sh', ['-c', command], { cwd, detached: true, stdio: ['ignore', 'pipe', 'pipe'] });
9
+ let output = '', bytes = 0, stopped = '', failure;
10
+ const collect = chunk => {
11
+ if (bytes < maxBytes) output += chunk.subarray(0, maxBytes - bytes).toString();
12
+ bytes += chunk.length;
13
+ };
14
+ const kill = () => { try { process.kill(-child.pid, 'SIGKILL'); } catch {} };
15
+ const cancel = () => { stopped = 'cancelled'; kill(); };
16
+ const timer = setTimeout(() => { stopped = 'timed out'; kill(); }, timeoutMs);
17
+ signal?.addEventListener('abort', cancel, { once: true });
18
+ child.stdout.on('data', collect);
19
+ child.stderr.on('data', collect);
20
+ child.on('error', error => { failure = error.message; });
21
+ child.on('close', (code, exitSignal) => {
22
+ clearTimeout(timer);
23
+ signal?.removeEventListener('abort', cancel);
24
+ resolve({ kind: code === 0 && !stopped && !failure ? 'success' : 'error', text: [output.trimEnd(), bytes > maxBytes ? '[output truncated]' : '', failure || (stopped ? `Shell command ${stopped}` : `Exit ${code ?? exitSignal}`)].filter(Boolean).join('\n') });
25
+ });
26
+ });
27
+ }