mixdog 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (404) hide show
  1. package/.claude-plugin/marketplace.json +31 -0
  2. package/.claude-plugin/plugin.json +20 -0
  3. package/.gitattributes +34 -0
  4. package/.mcp.json +14 -0
  5. package/ARCHITECTURE.md +77 -0
  6. package/CHANGELOG.md +7 -0
  7. package/CONTRIBUTING.md +45 -0
  8. package/DATA-FLOW.md +79 -0
  9. package/LICENSE +21 -0
  10. package/README.md +389 -0
  11. package/SECURITY.md +138 -0
  12. package/UNINSTALL.md +112 -0
  13. package/agents/maintenance.md +5 -0
  14. package/agents/memory-classification.md +30 -0
  15. package/agents/scheduler-task.md +18 -0
  16. package/agents/webhook-handler.md +27 -0
  17. package/agents/worker.md +24 -0
  18. package/bin/bridge +133 -0
  19. package/bin/statusline-launcher.mjs +78 -0
  20. package/bin/statusline-lib.mjs +550 -0
  21. package/bin/statusline.mjs +607 -0
  22. package/bun.lock +802 -0
  23. package/commands/config.md +16 -0
  24. package/commands/doctor.md +13 -0
  25. package/commands/setup.md +17 -0
  26. package/defaults/cycle3-review-prompt.md +90 -0
  27. package/defaults/hidden-roles.json +65 -0
  28. package/defaults/memory-chunk-prompt.md +63 -0
  29. package/defaults/memory-promote-prompt.md +135 -0
  30. package/defaults/mixdog-config.template.json +27 -0
  31. package/defaults/user-workflow.json +8 -0
  32. package/defaults/user-workflow.md +12 -0
  33. package/hooks/hooks.json +73 -0
  34. package/hooks/lib/active-instance.cjs +77 -0
  35. package/hooks/lib/permission-evaluator.cjs +411 -0
  36. package/hooks/lib/permission-route.cjs +63 -0
  37. package/hooks/lib/permission-rules.cjs +170 -0
  38. package/hooks/lib/settings-loader.cjs +116 -0
  39. package/hooks/post-tool-use.cjs +84 -0
  40. package/hooks/pre-mcp-sandbox.cjs +158 -0
  41. package/hooks/pre-tool-subagent.cjs +253 -0
  42. package/hooks/session-start.cjs +1372 -0
  43. package/hooks/turn-timer.cjs +82 -0
  44. package/lib/claude-md-writer.cjs +386 -0
  45. package/lib/config-cjs.cjs +61 -0
  46. package/lib/hook-pipe-path.cjs +10 -0
  47. package/lib/keychain-cjs.cjs +263 -0
  48. package/lib/plugin-paths.cjs +61 -0
  49. package/lib/rules-builder.cjs +241 -0
  50. package/lib/text-utils.cjs +61 -0
  51. package/native/README.md +117 -0
  52. package/native/prebuilt/linux-aarch64/mixdog-shim +0 -0
  53. package/native/prebuilt/linux-x86_64/mixdog-shim +0 -0
  54. package/native/prebuilt/macos-aarch64/mixdog-shim +0 -0
  55. package/native/prebuilt/macos-x86_64/mixdog-shim +0 -0
  56. package/native/prebuilt/windows-x86_64/mixdog-shim.exe +0 -0
  57. package/package.json +107 -0
  58. package/prompts/code-review.txt +16 -0
  59. package/prompts/security-audit.txt +17 -0
  60. package/rules/bridge/00-common.md +39 -0
  61. package/rules/bridge/20-skip-protocol.md +18 -0
  62. package/rules/bridge/30-explorer.md +33 -0
  63. package/rules/bridge/40-cycle1-agent.md +52 -0
  64. package/rules/bridge/41-cycle2-agent.md +62 -0
  65. package/rules/bridge/42-cycle3-agent.md +44 -0
  66. package/rules/lead/00-tool-lead.md +61 -0
  67. package/rules/lead/01-general.md +23 -0
  68. package/rules/lead/02-channels.md +49 -0
  69. package/rules/lead/03-team.md +27 -0
  70. package/rules/lead/04-workflow.md +20 -0
  71. package/rules/shared/00-language.md +14 -0
  72. package/rules/shared/01-tool.md +138 -0
  73. package/scripts/bootstrap.mjs +184 -0
  74. package/scripts/bridge-unify-smoke.mjs +308 -0
  75. package/scripts/build-runtime-linux.sh +348 -0
  76. package/scripts/build-runtime-macos.sh +217 -0
  77. package/scripts/build-runtime-windows.ps1 +242 -0
  78. package/scripts/builtin-utils-smoke.mjs +392 -0
  79. package/scripts/check-json.mjs +45 -0
  80. package/scripts/check-syntax-changed.mjs +102 -0
  81. package/scripts/check-syntax.mjs +58 -0
  82. package/scripts/code-graph-batch.test.mjs +33 -0
  83. package/scripts/config-preserve-smoke.mjs +180 -0
  84. package/scripts/doctor.mjs +484 -0
  85. package/scripts/edit-normalize-fuzz.mjs +130 -0
  86. package/scripts/edit-normalize-smoke.mjs +401 -0
  87. package/scripts/edit-operation-smoke.mjs +369 -0
  88. package/scripts/edit2-smoke.mjs +63 -0
  89. package/scripts/fuzzy-e2e.mjs +28 -0
  90. package/scripts/fuzzy-smoke.mjs +26 -0
  91. package/scripts/generate-runtime-manifest.mjs +166 -0
  92. package/scripts/guard-smoke.mjs +66 -0
  93. package/scripts/hidden-role-schema-smoke.mjs +162 -0
  94. package/scripts/hook-routing-smoke.mjs +29 -0
  95. package/scripts/inject-input.ps1 +204 -0
  96. package/scripts/io-complex-smoke.mjs +667 -0
  97. package/scripts/io-explore-bench.mjs +424 -0
  98. package/scripts/io-guardrails-smoke.mjs +205 -0
  99. package/scripts/io-mini-bench-baseline.json +11 -0
  100. package/scripts/io-mini-bench.mjs +216 -0
  101. package/scripts/io-route-harness.mjs +933 -0
  102. package/scripts/io-telemetry-report.mjs +691 -0
  103. package/scripts/mutation-bench.mjs +564 -0
  104. package/scripts/mutation-io-smoke.mjs +1081 -0
  105. package/scripts/native-patch-bridge-smoke.mjs +288 -0
  106. package/scripts/native-patch-smoke.mjs +304 -0
  107. package/scripts/patch-interior-context-smoke.mjs +49 -0
  108. package/scripts/patch-newline-utf8-smoke.mjs +157 -0
  109. package/scripts/perf-hook-smoke.mjs +71 -0
  110. package/scripts/permission-eval-smoke.mjs +426 -0
  111. package/scripts/prep-patch.mjs +53 -0
  112. package/scripts/prep-shim.mjs +96 -0
  113. package/scripts/provider-cache-smoke.mjs +687 -0
  114. package/scripts/report-runtime-health.mjs +132 -0
  115. package/scripts/run-mcp.mjs +1547 -0
  116. package/scripts/salvage-v4a-shatter.test.mjs +58 -0
  117. package/scripts/scoped-cache-io-smoke.mjs +103 -0
  118. package/scripts/shell-policy-round3-smoke.mjs +46 -0
  119. package/scripts/smoke-runtime-negative.ps1 +100 -0
  120. package/scripts/smoke-runtime-negative.sh +95 -0
  121. package/scripts/stall-policy-smoke.mjs +50 -0
  122. package/scripts/start-memory-worker.mjs +23 -0
  123. package/scripts/statusline-launcher-smoke.mjs +82 -0
  124. package/scripts/stress-atomic-write.mjs +1028 -0
  125. package/scripts/test-config-rmw-restore.mjs +122 -0
  126. package/scripts/test-fault-inject.mjs +164 -0
  127. package/scripts/test-large-file.mjs +174 -0
  128. package/scripts/tool-edge-smoke.mjs +209 -0
  129. package/scripts/uninstall.mjs +201 -0
  130. package/scripts/webhook-selfheal-smoke.mjs +29 -0
  131. package/scripts/write-overwrite-guard-smoke.mjs +56 -0
  132. package/server-main.mjs +3055 -0
  133. package/server.mjs +468 -0
  134. package/setup/config-merge.mjs +254 -0
  135. package/setup/install.mjs +120 -0
  136. package/setup/launch-core.mjs +507 -0
  137. package/setup/launch.mjs +101 -0
  138. package/setup/setup-server.mjs +3206 -0
  139. package/setup/setup.html +3693 -0
  140. package/skills/retro-skill-proposer/SKILL.md +92 -0
  141. package/skills/schedule-add/SKILL.md +77 -0
  142. package/skills/setup/SKILL.md +346 -0
  143. package/skills/webhook-add/SKILL.md +81 -0
  144. package/src/agent/bridge-stall-watchdog.mjs +337 -0
  145. package/src/agent/index.mjs +2138 -0
  146. package/src/agent/orchestrator/activity-bus.mjs +38 -0
  147. package/src/agent/orchestrator/ai-wrapped-dispatch.mjs +1010 -0
  148. package/src/agent/orchestrator/bridge-retry.mjs +220 -0
  149. package/src/agent/orchestrator/bridge-trace.mjs +583 -0
  150. package/src/agent/orchestrator/cache-mtime.mjs +58 -0
  151. package/src/agent/orchestrator/config.mjs +358 -0
  152. package/src/agent/orchestrator/context/collect.mjs +651 -0
  153. package/src/agent/orchestrator/dispatch-persist.mjs +549 -0
  154. package/src/agent/orchestrator/drain-registry.mjs +50 -0
  155. package/src/agent/orchestrator/explore-validator.mjs +8 -0
  156. package/src/agent/orchestrator/internal-roles.mjs +118 -0
  157. package/src/agent/orchestrator/internal-tools.mjs +88 -0
  158. package/src/agent/orchestrator/jobs.mjs +116 -0
  159. package/src/agent/orchestrator/mcp/client.mjs +364 -0
  160. package/src/agent/orchestrator/providers/anthropic-betas.mjs +21 -0
  161. package/src/agent/orchestrator/providers/anthropic-oauth.mjs +1745 -0
  162. package/src/agent/orchestrator/providers/anthropic.mjs +437 -0
  163. package/src/agent/orchestrator/providers/gemini.mjs +1175 -0
  164. package/src/agent/orchestrator/providers/grok-oauth.mjs +782 -0
  165. package/src/agent/orchestrator/providers/model-catalog.mjs +241 -0
  166. package/src/agent/orchestrator/providers/openai-compat.mjs +1467 -0
  167. package/src/agent/orchestrator/providers/openai-oauth-ws.mjs +1890 -0
  168. package/src/agent/orchestrator/providers/openai-oauth.mjs +1307 -0
  169. package/src/agent/orchestrator/providers/openai-ws.mjs +104 -0
  170. package/src/agent/orchestrator/providers/registry.mjs +192 -0
  171. package/src/agent/orchestrator/providers/retry-classifier.mjs +325 -0
  172. package/src/agent/orchestrator/session/abort-lookup.mjs +13 -0
  173. package/src/agent/orchestrator/session/cache/post-edit-marks.mjs +42 -0
  174. package/src/agent/orchestrator/session/cache/prefetch-cache.mjs +142 -0
  175. package/src/agent/orchestrator/session/cache/read-cache.mjs +319 -0
  176. package/src/agent/orchestrator/session/cache/scoped-cache-outcome.mjs +11 -0
  177. package/src/agent/orchestrator/session/cache/scoped-cache.mjs +361 -0
  178. package/src/agent/orchestrator/session/cache/util.mjs +49 -0
  179. package/src/agent/orchestrator/session/loop.mjs +1478 -0
  180. package/src/agent/orchestrator/session/manager.mjs +1975 -0
  181. package/src/agent/orchestrator/session/read-dedup.mjs +6 -0
  182. package/src/agent/orchestrator/session/result-classification.mjs +65 -0
  183. package/src/agent/orchestrator/session/save-session-worker.mjs +18 -0
  184. package/src/agent/orchestrator/session/store.mjs +624 -0
  185. package/src/agent/orchestrator/session/stream-watchdog.mjs +130 -0
  186. package/src/agent/orchestrator/session/tool-result-offload.mjs +166 -0
  187. package/src/agent/orchestrator/session/trim.mjs +491 -0
  188. package/src/agent/orchestrator/smart-bridge/CACHE-SHARD.md +115 -0
  189. package/src/agent/orchestrator/smart-bridge/bridge-llm.mjs +327 -0
  190. package/src/agent/orchestrator/smart-bridge/cache-obs.mjs +150 -0
  191. package/src/agent/orchestrator/smart-bridge/cache-strategy.mjs +228 -0
  192. package/src/agent/orchestrator/smart-bridge/index.mjs +215 -0
  193. package/src/agent/orchestrator/smart-bridge/profiles.mjs +37 -0
  194. package/src/agent/orchestrator/smart-bridge/registry.mjs +348 -0
  195. package/src/agent/orchestrator/smart-bridge/session-builder.mjs +116 -0
  196. package/src/agent/orchestrator/stall-policy.mjs +195 -0
  197. package/src/agent/orchestrator/tool-loop-guard.mjs +75 -0
  198. package/src/agent/orchestrator/tools/bash-policy-scan.mjs +77 -0
  199. package/src/agent/orchestrator/tools/bash-session.mjs +721 -0
  200. package/src/agent/orchestrator/tools/builtin/advisory-lock.mjs +171 -0
  201. package/src/agent/orchestrator/tools/builtin/arg-guard.mjs +455 -0
  202. package/src/agent/orchestrator/tools/builtin/atomic-write.mjs +236 -0
  203. package/src/agent/orchestrator/tools/builtin/bash-tool.mjs +480 -0
  204. package/src/agent/orchestrator/tools/builtin/binary-file.mjs +76 -0
  205. package/src/agent/orchestrator/tools/builtin/builtin-tools.mjs +256 -0
  206. package/src/agent/orchestrator/tools/builtin/cache-layers.mjs +386 -0
  207. package/src/agent/orchestrator/tools/builtin/cwd-utils.mjs +37 -0
  208. package/src/agent/orchestrator/tools/builtin/device-paths.mjs +154 -0
  209. package/src/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +292 -0
  210. package/src/agent/orchestrator/tools/builtin/diff-utils.mjs +109 -0
  211. package/src/agent/orchestrator/tools/builtin/edit-base-guard.mjs +58 -0
  212. package/src/agent/orchestrator/tools/builtin/edit-byte-plan.mjs +240 -0
  213. package/src/agent/orchestrator/tools/builtin/edit-byte-utils.mjs +113 -0
  214. package/src/agent/orchestrator/tools/builtin/edit-commit.mjs +74 -0
  215. package/src/agent/orchestrator/tools/builtin/edit-context-utils.mjs +242 -0
  216. package/src/agent/orchestrator/tools/builtin/edit-diagnostics.mjs +211 -0
  217. package/src/agent/orchestrator/tools/builtin/edit-engine.mjs +1364 -0
  218. package/src/agent/orchestrator/tools/builtin/edit-failure-context.mjs +126 -0
  219. package/src/agent/orchestrator/tools/builtin/edit-hint.mjs +141 -0
  220. package/src/agent/orchestrator/tools/builtin/edit-match-utils.mjs +194 -0
  221. package/src/agent/orchestrator/tools/builtin/edit-partial-write.mjs +60 -0
  222. package/src/agent/orchestrator/tools/builtin/edit-stale-refresh.mjs +168 -0
  223. package/src/agent/orchestrator/tools/builtin/edit-tool.mjs +173 -0
  224. package/src/agent/orchestrator/tools/builtin/edit-utf8-guard.mjs +48 -0
  225. package/src/agent/orchestrator/tools/builtin/fs-reachability.mjs +48 -0
  226. package/src/agent/orchestrator/tools/builtin/fuzzy-match.mjs +99 -0
  227. package/src/agent/orchestrator/tools/builtin/glob-walk.mjs +170 -0
  228. package/src/agent/orchestrator/tools/builtin/grep-formatting.mjs +113 -0
  229. package/src/agent/orchestrator/tools/builtin/hash-utils.mjs +6 -0
  230. package/src/agent/orchestrator/tools/builtin/list-formatting.mjs +7 -0
  231. package/src/agent/orchestrator/tools/builtin/list-tool.mjs +593 -0
  232. package/src/agent/orchestrator/tools/builtin/native-edit-runner.mjs +89 -0
  233. package/src/agent/orchestrator/tools/builtin/notebook-edit-tool.mjs +300 -0
  234. package/src/agent/orchestrator/tools/builtin/open-config-tool.mjs +26 -0
  235. package/src/agent/orchestrator/tools/builtin/path-diagnostics.mjs +152 -0
  236. package/src/agent/orchestrator/tools/builtin/path-locks.mjs +35 -0
  237. package/src/agent/orchestrator/tools/builtin/path-utils.mjs +201 -0
  238. package/src/agent/orchestrator/tools/builtin/read-args.mjs +103 -0
  239. package/src/agent/orchestrator/tools/builtin/read-batch.mjs +172 -0
  240. package/src/agent/orchestrator/tools/builtin/read-constants.mjs +40 -0
  241. package/src/agent/orchestrator/tools/builtin/read-formatting.mjs +118 -0
  242. package/src/agent/orchestrator/tools/builtin/read-image-resize.mjs +189 -0
  243. package/src/agent/orchestrator/tools/builtin/read-image.mjs +88 -0
  244. package/src/agent/orchestrator/tools/builtin/read-lines.mjs +12 -0
  245. package/src/agent/orchestrator/tools/builtin/read-mode-tool.mjs +455 -0
  246. package/src/agent/orchestrator/tools/builtin/read-open.mjs +190 -0
  247. package/src/agent/orchestrator/tools/builtin/read-range-index.mjs +271 -0
  248. package/src/agent/orchestrator/tools/builtin/read-ranges.mjs +26 -0
  249. package/src/agent/orchestrator/tools/builtin/read-single-tool.mjs +728 -0
  250. package/src/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +173 -0
  251. package/src/agent/orchestrator/tools/builtin/read-special-files.mjs +268 -0
  252. package/src/agent/orchestrator/tools/builtin/read-streaming.mjs +602 -0
  253. package/src/agent/orchestrator/tools/builtin/read-tool.mjs +530 -0
  254. package/src/agent/orchestrator/tools/builtin/read-windows.mjs +107 -0
  255. package/src/agent/orchestrator/tools/builtin/rename-tool.mjs +196 -0
  256. package/src/agent/orchestrator/tools/builtin/rg-runner.mjs +422 -0
  257. package/src/agent/orchestrator/tools/builtin/search-builders.mjs +158 -0
  258. package/src/agent/orchestrator/tools/builtin/search-tool.mjs +869 -0
  259. package/src/agent/orchestrator/tools/builtin/shell-analysis.mjs +653 -0
  260. package/src/agent/orchestrator/tools/builtin/shell-jobs.mjs +936 -0
  261. package/src/agent/orchestrator/tools/builtin/shell-output.mjs +36 -0
  262. package/src/agent/orchestrator/tools/builtin/shell-runtime.mjs +214 -0
  263. package/src/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +143 -0
  264. package/src/agent/orchestrator/tools/builtin/snapshot-store.mjs +206 -0
  265. package/src/agent/orchestrator/tools/builtin/snapshot-validation.mjs +98 -0
  266. package/src/agent/orchestrator/tools/builtin/text-stats.mjs +69 -0
  267. package/src/agent/orchestrator/tools/builtin/windows-roots.mjs +23 -0
  268. package/src/agent/orchestrator/tools/builtin/write-tool.mjs +401 -0
  269. package/src/agent/orchestrator/tools/builtin.mjs +500 -0
  270. package/src/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +39 -0
  271. package/src/agent/orchestrator/tools/code-graph-tool-defs.mjs +24 -0
  272. package/src/agent/orchestrator/tools/code-graph.mjs +4095 -0
  273. package/src/agent/orchestrator/tools/cwd-tool.mjs +298 -0
  274. package/src/agent/orchestrator/tools/destructive-warning.mjs +323 -0
  275. package/src/agent/orchestrator/tools/edit-normalize.mjs +603 -0
  276. package/src/agent/orchestrator/tools/env-scrub.mjs +100 -0
  277. package/src/agent/orchestrator/tools/graph-binary-fetcher.mjs +144 -0
  278. package/src/agent/orchestrator/tools/graph-manifest.json +26 -0
  279. package/src/agent/orchestrator/tools/host-input.mjs +204 -0
  280. package/src/agent/orchestrator/tools/mutation-content-cache.mjs +67 -0
  281. package/src/agent/orchestrator/tools/mutation-planner.mjs +75 -0
  282. package/src/agent/orchestrator/tools/next-call-utils.mjs +48 -0
  283. package/src/agent/orchestrator/tools/patch-binary-fetcher.mjs +133 -0
  284. package/src/agent/orchestrator/tools/patch-manifest.json +26 -0
  285. package/src/agent/orchestrator/tools/patch-tool-defs.mjs +20 -0
  286. package/src/agent/orchestrator/tools/patch.mjs +2754 -0
  287. package/src/agent/orchestrator/tools/progress-message.mjs +118 -0
  288. package/src/agent/orchestrator/tools/result-compression.mjs +279 -0
  289. package/src/agent/orchestrator/tools/shell-command.mjs +865 -0
  290. package/src/agent/orchestrator/tools/shell-exec-policy.mjs +89 -0
  291. package/src/agent/orchestrator/tools/shell-policy-danger-target.mjs +27 -0
  292. package/src/agent/orchestrator/tools/shell-policy-imports.mjs +7 -0
  293. package/src/agent/orchestrator/tools/shell-policy.mjs +345 -0
  294. package/src/agent/orchestrator/tools/shell-snapshot.mjs +313 -0
  295. package/src/agent/orchestrator/workflow-store.mjs +93 -0
  296. package/src/agent/tool-defs.mjs +103 -0
  297. package/src/channels/backends/discord.mjs +784 -0
  298. package/src/channels/data/voice-runtime-manifest.json +138 -0
  299. package/src/channels/index.mjs +3229 -0
  300. package/src/channels/lib/cli-worker-host.mjs +12 -0
  301. package/src/channels/lib/config-lock.mjs +13 -0
  302. package/src/channels/lib/config.mjs +292 -0
  303. package/src/channels/lib/drop-trace.mjs +71 -0
  304. package/src/channels/lib/event-pipeline.mjs +81 -0
  305. package/src/channels/lib/event-queue.mjs +345 -0
  306. package/src/channels/lib/executor.mjs +168 -0
  307. package/src/channels/lib/format.mjs +188 -0
  308. package/src/channels/lib/holidays.mjs +138 -0
  309. package/src/channels/lib/hook-pipe-server.mjs +802 -0
  310. package/src/channels/lib/interaction-workflows.mjs +184 -0
  311. package/src/channels/lib/memory-client.mjs +149 -0
  312. package/src/channels/lib/output-forwarder.mjs +765 -0
  313. package/src/channels/lib/runtime-paths.mjs +479 -0
  314. package/src/channels/lib/scheduler.mjs +723 -0
  315. package/src/channels/lib/session-control.mjs +36 -0
  316. package/src/channels/lib/session-discovery.mjs +103 -0
  317. package/src/channels/lib/settings.mjs +11 -0
  318. package/src/channels/lib/state-file.mjs +68 -0
  319. package/src/channels/lib/status-snapshot.mjs +219 -0
  320. package/src/channels/lib/tool-format.mjs +140 -0
  321. package/src/channels/lib/transcript-discovery.mjs +195 -0
  322. package/src/channels/lib/voice-runtime-fetcher.mjs +734 -0
  323. package/src/channels/lib/webhook.mjs +1179 -0
  324. package/src/channels/lib/whisper-server.mjs +477 -0
  325. package/src/channels/tool-defs.mjs +170 -0
  326. package/src/daemon/host.mjs +118 -0
  327. package/src/daemon/mcp-transport.mjs +47 -0
  328. package/src/daemon/session.mjs +100 -0
  329. package/src/daemon/thin-client.mjs +71 -0
  330. package/src/daemon/transport.mjs +163 -0
  331. package/src/memory/data/runtime-manifest.json +40 -0
  332. package/src/memory/index.mjs +3305 -0
  333. package/src/memory/lib/agent-ipc.mjs +93 -0
  334. package/src/memory/lib/bridge-trace-queries.mjs +120 -0
  335. package/src/memory/lib/core-memory-store.mjs +330 -0
  336. package/src/memory/lib/embedding-provider.mjs +269 -0
  337. package/src/memory/lib/embedding-worker.mjs +323 -0
  338. package/src/memory/lib/llm-worker-host.mjs +17 -0
  339. package/src/memory/lib/memory-cycle.mjs +11 -0
  340. package/src/memory/lib/memory-cycle1.mjs +641 -0
  341. package/src/memory/lib/memory-cycle2.mjs +1284 -0
  342. package/src/memory/lib/memory-cycle3.mjs +540 -0
  343. package/src/memory/lib/memory-embed.mjs +299 -0
  344. package/src/memory/lib/memory-extraction.mjs +5 -0
  345. package/src/memory/lib/memory-maintenance-store.mjs +32 -0
  346. package/src/memory/lib/memory-ops-policy.mjs +190 -0
  347. package/src/memory/lib/memory-recall-id-patch.mjs +15 -0
  348. package/src/memory/lib/memory-recall-read-query.mjs +7 -0
  349. package/src/memory/lib/memory-recall-scope-filter.mjs +63 -0
  350. package/src/memory/lib/memory-recall-store.mjs +621 -0
  351. package/src/memory/lib/memory-retrievers.mjs +112 -0
  352. package/src/memory/lib/memory-score.mjs +71 -0
  353. package/src/memory/lib/memory-text-utils.mjs +58 -0
  354. package/src/memory/lib/memory.mjs +412 -0
  355. package/src/memory/lib/model-profile.mjs +85 -0
  356. package/src/memory/lib/pg/adapter.mjs +308 -0
  357. package/src/memory/lib/pg/process.mjs +360 -0
  358. package/src/memory/lib/pg/supervisor.mjs +396 -0
  359. package/src/memory/lib/project-id-resolver.mjs +86 -0
  360. package/src/memory/lib/runtime-fetcher.mjs +442 -0
  361. package/src/memory/lib/trace-store.mjs +728 -0
  362. package/src/memory/tool-defs.mjs +79 -0
  363. package/src/search/index.mjs +1173 -0
  364. package/src/search/lib/backends/anthropic-oauth.mjs +98 -0
  365. package/src/search/lib/backends/exa.mjs +50 -0
  366. package/src/search/lib/backends/firecrawl.mjs +61 -0
  367. package/src/search/lib/backends/gemini-api.mjs +83 -0
  368. package/src/search/lib/backends/grok-oauth.mjs +86 -0
  369. package/src/search/lib/backends/index.mjs +150 -0
  370. package/src/search/lib/backends/openai-api.mjs +144 -0
  371. package/src/search/lib/backends/openai-oauth.mjs +98 -0
  372. package/src/search/lib/backends/openai-web-search.mjs +76 -0
  373. package/src/search/lib/backends/tavily.mjs +55 -0
  374. package/src/search/lib/backends/xai-api.mjs +113 -0
  375. package/src/search/lib/cache.mjs +131 -0
  376. package/src/search/lib/config.mjs +192 -0
  377. package/src/search/lib/formatter.mjs +115 -0
  378. package/src/search/lib/provider-usage.mjs +67 -0
  379. package/src/search/lib/providers.mjs +47 -0
  380. package/src/search/lib/search-intent.mjs +109 -0
  381. package/src/search/lib/setup-handler.mjs +261 -0
  382. package/src/search/lib/state.mjs +201 -0
  383. package/src/search/lib/web-tools.mjs +1207 -0
  384. package/src/search/tool-defs.mjs +83 -0
  385. package/src/setup/defender-exclusion.mjs +183 -0
  386. package/src/shared/abort-controller.mjs +15 -0
  387. package/src/shared/atomic-file.mjs +420 -0
  388. package/src/shared/config.mjs +350 -0
  389. package/src/shared/daemon-recycle.mjs +108 -0
  390. package/src/shared/disable-claude-builtins.mjs +88 -0
  391. package/src/shared/err-text.mjs +12 -0
  392. package/src/shared/llm/cost.mjs +66 -0
  393. package/src/shared/llm/http-agent.mjs +123 -0
  394. package/src/shared/llm/index.mjs +41 -0
  395. package/src/shared/llm/pid-cleanup.mjs +27 -0
  396. package/src/shared/llm/usage-log.mjs +47 -0
  397. package/src/shared/plugin-paths.mjs +58 -0
  398. package/src/shared/schedules-store.mjs +70 -0
  399. package/src/shared/seed.mjs +119 -0
  400. package/src/shared/user-cwd.mjs +213 -0
  401. package/src/shared/user-data-guard.mjs +238 -0
  402. package/src/status/aggregator.mjs +584 -0
  403. package/src/status/server.mjs +413 -0
  404. package/tools.json +1653 -0
@@ -0,0 +1,89 @@
1
+ 'use strict';
2
+
3
+ import { getDestructiveCommandWarning } from './destructive-warning.mjs';
4
+ import { isBlockedCommand, WRAPPER_NAMES } from './shell-policy.mjs';
5
+
6
+ /** @typedef {'allow'|'warn-prompt'|'deny'} ExecPolicyDecision */
7
+
8
+ const EXEC_POLICY_DENY_PATTERNS = [
9
+ /\b(curl|wget|fetch|Invoke-WebRequest|iwr)\b[^\n|&;]*\|[^\n|&;]*\b(sh|bash|zsh|dash|pwsh|powershell)(?:\.exe)?\b/i,
10
+ /\|\s*(sh|bash|zsh|dash|pwsh|powershell)(?:\.exe)?\b/i,
11
+ /\b(?:sh|bash|zsh|dash|pwsh|powershell)(?:\.exe)?\s+<\s*\(/i,
12
+ /\bInvoke-Expression\b/i,
13
+ /\biex\s+/i,
14
+ /\bStart-Process\b[^\n]*\b-Verb\s+RunAs\b/i,
15
+ ];
16
+
17
+ const EXEC_POLICY_DENY_COMMANDS = new Set([
18
+ 'dd', 'diskpart', 'shutdown', 'reboot', 'halt', 'poweroff', 'init', 'telinit',
19
+ 'mkfs', 'mkfs.ext4', 'mkfs.ntfs', 'format', 'fdisk', 'parted',
20
+ ]);
21
+
22
+ const _POLICY_RANK = { allow: 0, 'warn-prompt': 1, deny: 2 };
23
+
24
+ function _firstCommandName(command) {
25
+ const seg = String(command || '').split(/[;&|\n]+/)[0] || '';
26
+ const tokens = seg.trim().split(/\s+/).filter(Boolean);
27
+ let i = 0;
28
+ while (i < tokens.length) {
29
+ const t = tokens[i];
30
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(t)) { i++; continue; }
31
+ if (WRAPPER_NAMES.has(t.toLowerCase())) {
32
+ i++;
33
+ while (i < tokens.length && (/^[-+]/.test(tokens[i]) || /^\d+[smhd]?$/.test(tokens[i]))) i++;
34
+ continue;
35
+ }
36
+ const base = t.replace(/^.*[\\/]/, '').toLowerCase();
37
+ return base.replace(/\.(exe|cmd|bat|com)$/i, '');
38
+ }
39
+ return null;
40
+ }
41
+
42
+ export function classifyExecPolicy(command) {
43
+ const text = String(command || '');
44
+ if (!text.trim()) return { decision: 'allow', reason: '' };
45
+ if (isBlockedCommand(text)) {
46
+ return { decision: 'deny', reason: 'destructive or system-destabilising pattern (hard block)' };
47
+ }
48
+ for (const pat of EXEC_POLICY_DENY_PATTERNS) {
49
+ if (pat.test(text)) {
50
+ return { decision: 'deny', reason: 'high-risk shell invocation (pipe-to-shell, elevated launcher, or remote-exec pattern)' };
51
+ }
52
+ }
53
+ const name = _firstCommandName(text);
54
+ if (name && EXEC_POLICY_DENY_COMMANDS.has(name)) {
55
+ return { decision: 'deny', reason: `command "${name}" is not permitted without sandbox` };
56
+ }
57
+ const warn = getDestructiveCommandWarning(text);
58
+ if (warn) {
59
+ return { decision: 'warn-prompt', reason: warn };
60
+ }
61
+ return { decision: 'allow', reason: '' };
62
+ }
63
+
64
+ export function mergeExecPolicyDecisions(a, b) {
65
+ const left = a && a.decision ? a : { decision: 'allow', reason: '' };
66
+ const right = b && b.decision ? b : { decision: 'allow', reason: '' };
67
+ if (_POLICY_RANK[right.decision] > _POLICY_RANK[left.decision]) return right;
68
+ if (_POLICY_RANK[right.decision] < _POLICY_RANK[left.decision]) return left;
69
+ return right.reason ? right : left;
70
+ }
71
+
72
+ export function evaluateExecPolicyFromTargets(targets) {
73
+ let worst = { decision: 'allow', reason: '' };
74
+ for (const t of targets || []) {
75
+ if (typeof t !== 'string' || !t) continue;
76
+ worst = mergeExecPolicyDecisions(worst, classifyExecPolicy(t));
77
+ if (worst.decision === 'deny') break;
78
+ }
79
+ return worst;
80
+ }
81
+
82
+ /** Pre-spawn block message — deny only. warn-prompt is non-blocking (see destructive-warning prepend). */
83
+ export function formatExecPolicyBlockMessage(policyResult) {
84
+ const r = policyResult || { decision: 'allow' };
85
+ if (r.decision === 'deny') {
86
+ return `Error: command blocked by exec policy${r.reason ? ` — ${r.reason}` : ''}`;
87
+ }
88
+ return null;
89
+ }
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ /** Catastrophic delete targets (shared rm / Remove-Item / del guards). */
4
+ export function isDangerousDeleteTarget(rawTarget) {
5
+ if (rawTarget == null) return false;
6
+ const t = String(rawTarget).trim().replace(/^['"]|['"]$/g, '').trim();
7
+ if (t === '') return false;
8
+ if (t === '*' || t === '.' || t === './' || t === '.\\' || t === '.*') return true;
9
+ const low = t.toLowerCase();
10
+ if (/^\$home(\b|[\\/])/.test(low)) return true;
11
+ if (/^\$env:(userprofile|homepath|home|homedrive|systemroot|windir|programfiles|programdata|systemdrive|allusersprofile|public|appdata|localappdata)\b/.test(low)) return true;
12
+ if (/^%(userprofile|homepath|home|homedrive|systemroot|windir|programfiles|programdata|systemdrive|allusersprofile|public|appdata|localappdata)%/i.test(t)) return true;
13
+ if (/^\$\{(home|userprofile|homepath|homedrive|systemroot|windir|programfiles|programdata|systemdrive)\}/i.test(t)) return true;
14
+ if (/^\$\(home\)/i.test(t)) return true;
15
+ if (/^\\\\[^\\]+\\[^\\]+\\\*?$/.test(t) || /^\\\\[^\\]+\\[^\\]*$/.test(t)) return true;
16
+ if (t.startsWith('$') || t.includes('$(') || /^%[^%]*%/.test(t)) return false;
17
+ if (t === '~' || t.startsWith('~/') || t.startsWith('~\\')) return true;
18
+ if (t === '/' || t === '\\') return true;
19
+ if (t === '/*' || t === '\\*' || t === '/.' || t === '/*.*') return true;
20
+ const unix = t.replace(/\\/g, '/').replace(/\/+$/, '').toLowerCase();
21
+ if (/^\/(etc|usr|bin|sbin|lib|lib64|boot|sys|proc|dev|root|var|home|opt|srv|system|library|applications|users|private|volumes)(\/\*)?$/.test(unix)) return true;
22
+ const win = t.replace(/\//g, '\\').replace(/\\+$/, '').toLowerCase();
23
+ if (/^[a-z]:$/.test(win)) return true;
24
+ if (/^[a-z]:\\\*/.test(win)) return true;
25
+ if (/^[a-z]:\\(windows|program files( \(x86\))?|programdata|users)$/.test(win)) return true;
26
+ return false;
27
+ }
@@ -0,0 +1,7 @@
1
+ export { isDangerousDeleteTarget as _isDangerousDeleteTarget } from './shell-policy-danger-target.mjs';
2
+ export {
3
+ classifyExecPolicy,
4
+ mergeExecPolicyDecisions,
5
+ evaluateExecPolicyFromTargets,
6
+ formatExecPolicyBlockMessage,
7
+ } from './shell-exec-policy.mjs';
@@ -0,0 +1,345 @@
1
+ 'use strict';
2
+
3
+ import { isDangerousDeleteTarget as _isDangerousDeleteTarget } from './shell-policy-danger-target.mjs';
4
+ export { isDangerousDeleteTarget } from './shell-policy-danger-target.mjs';
5
+ // Shell execution security policy — shared constants used by both
6
+ // destructive-warning.mjs (heuristic classifier) and bash-session.mjs
7
+ // (hard block list). Centralised here so the two files stay in sync
8
+ // without requiring manual "drift should be fixed in BOTH files" notes.
9
+ //
10
+ // These are documented security-policy allowlists, not heuristic
11
+ // classifiers: membership is explicit and reviewed on addition.
12
+
13
+ // Shells whose `-c` payloads must be recursively scanned for destructive
14
+ // commands. Expand when a new shell interpreter is supported.
15
+ export const SHELL_NAMES = new Set([
16
+ 'bash', 'sh', 'zsh', 'dash', 'ksh', 'ash',
17
+ ]);
18
+
19
+ // Wrapper programs that transparently exec their first non-option argument.
20
+ // We peel these (and their option args) before reading the real command name.
21
+ export const WRAPPER_NAMES = new Set([
22
+ 'env', 'sudo', 'doas', 'nice', 'stdbuf', 'chronic', 'time', 'timeout',
23
+ 'nohup', 'setpriv', 'ionice', 'taskset',
24
+ ]);
25
+
26
+ // Hard-block patterns shared by the stateless bash tool (builtin.mjs) and
27
+ // the persistent bash_session tool (bash-session.mjs). Adding a pattern
28
+ // here propagates to both without manual sync.
29
+ //
30
+ // These block outright data-destructive or system-destabilising operations
31
+ // that the agent must never execute regardless of context. Informational
32
+ // warnings (non-blocking) live in destructive-warning.mjs instead.
33
+ // A command-runner wrapper (sudo, env, timeout, …) or VAR=val assignment may
34
+ // precede the real command. A destructive verb following such a peeled wrapper
35
+ // chain is still at command position, so `sudo shutdown` / `env timeout 5 dd …`
36
+ // stay hard-blocked, while a bare prose token before the verb (e.g. "graceful
37
+ // shutdown" in a commit message) does NOT satisfy command position and passes.
38
+ // Wrapper names are sourced from WRAPPER_NAMES above so this path and the
39
+ // destructive-warning peeler cannot drift apart. Each chain unit ends in \s+
40
+ // (no zero-width iteration) so the nested quantifier cannot backtrack-blow.
41
+ const _WRAP_CHAIN =
42
+ '(?:' +
43
+ '(?:[A-Za-z_]\\w*=\\S*\\s+)' +
44
+ '|(?:(?:' + [...WRAPPER_NAMES].join('|') + ')\\s+(?:(?:[-+]\\S*|\\d+[smhd]?|\\d+m\\d+s?)\\s+)*)' +
45
+ ')*';
46
+ const _CMD_START = '(?:^|[;&|\\n(){}]\\s*|\\$[\\({]\\s*|[<>]\\(\\s*|`\\s*)' + _WRAP_CHAIN;
47
+ // Wrapper chain for the token-level rm guard. Same shape as _WRAP_CHAIN
48
+ // (backtrack-safe: every unit ends in \s+) but also peels `command`, the
49
+ // bash builtin that execs its first non-option argument. Lets the rm guard
50
+ // see `sudo rm -r -f /`, `env X=1 rm -r -f ~`, `timeout 5 rm -rf /`, etc.
51
+ const _RM_WRAP_CHAIN =
52
+ '(?:' +
53
+ '(?:[A-Za-z_]\\w*=\\S*\\s+)' +
54
+ '|(?:(?:' + [...WRAPPER_NAMES, 'command'].join('|') + ')\\s+(?:(?:[-+]\\S*|\\d+[smhd]?|\\d+m\\d+s?)\\s+)*)' +
55
+ ')*';
56
+ const BLOCKED_PATTERNS = [
57
+ // Recursive deletes (bash `rm -rf`, PowerShell `Remove-Item -Recurse -Force`,
58
+ // cmd `del /s` / `rd /s`) are NOT blocked outright — each is target-checked
59
+ // by a dedicated guard below via _isDangerousDeleteTarget, blocking only
60
+ // filesystem-root / home / top-level-system / whole-cwd targets (CC-level).
61
+ // `git reset --hard` is likewise no longer hard-blocked (CC prompts; the
62
+ // agent workflow already gates destructive git ops).
63
+ // Bare `git push --force` (and `--force=`) still blocks; the safer
64
+ // `--force-with-lease` / `--force-if-includes` variants pass.
65
+ /\bgit\s+push\b[^\n]*?\s--force(?![\w-])/i,
66
+ /\bformat\s+[a-z]:/i,
67
+ new RegExp(_CMD_START + '(?:shutdown|reboot|halt)\\b', 'i'),
68
+ new RegExp(_CMD_START + 'mkfs(?:\\.|\\b)', 'i'),
69
+ new RegExp(_CMD_START + 'dd\\s+[^\\n]*\\b(?:if|of)=/dev/', 'i'),
70
+ new RegExp(_CMD_START + 'diskpart\\b[^\\n]*\\bclean\\b', 'i'),
71
+ /:\(\)\s*\{[^}]*:\|:&[^}]*\};\s*:/, // bash fork-bomb signature
72
+ ];
73
+
74
+ // PowerShell `-EncodedCommand <base64>` (also `-enc`, `-e` short forms)
75
+ // transparently runs a UTF-16LE/base64 script that bypasses the literal-text
76
+ // BLOCKED_PATTERNS scan. Recognise the flag, decode the payload, and re-test
77
+ // the decoded text so a `powershell -EncodedCommand <Remove-Item ...>` smuggle
78
+ // still hits the policy. Bad base64 / decode failure falls through silently
79
+ // — the original literal scan still applies.
80
+ // Option names accept PowerShell's unambiguous prefix abbreviations so that
81
+ // `-nop` (NoProfile), `-nol` (NoLogo), `-noni` (NonInteractive), `-ep`
82
+ // (ExecutionPolicy), `-w hidden` (WindowStyle), etc. preceding the encoded
83
+ // flag no longer make the regex miss and skip decoding. Widening the option
84
+ // whitelist only makes more payloads get decoded + re-scanned; it never lets
85
+ // a previously-blocked command through.
86
+ const _ENCODED_CMD_RE = /(?:^|\s)(?:powershell(?:\.exe)?|pwsh(?:\.exe)?)\s+(?:[-/](?:NoP(?:rofile)?|NoL(?:ogo)?|NonI(?:nteractive)?|Sta|Mta|(?:ExecutionPolicy|Ep|Ex)\s+\S+|(?:WindowStyle|Win|W)\s+\S+|(?:InputFormat|Inp|If)\s+\S+|(?:OutputFormat|Out|Of)\s+\S+|Command|(?:File|Fi)\s+\S+|(?:Version|Ver)\s+\S+)\s+)*[-/](?:EncodedCommand|enc|e)\s+["']?([A-Za-z0-9+/=]+)["']?/gi;
87
+ function _decodePowerShellEncodedCommand(command) {
88
+ const cmd = String(command || '');
89
+ // Scan ALL -EncodedCommand occurrences (quoted or unquoted) so a chained
90
+ // payload like `powershell -enc A...; powershell -enc B...` exposes both
91
+ // decoded scripts to BLOCKED_PATTERNS. PowerShell -EncodedCommand expects
92
+ // UTF-16LE. Bad base64 / decode failure is skipped silently per match.
93
+ const decoded = [];
94
+ for (const m of cmd.matchAll(_ENCODED_CMD_RE)) {
95
+ try {
96
+ const buf = Buffer.from(m[1], 'base64');
97
+ decoded.push(buf.toString('utf16le'));
98
+ } catch { /* skip bad base64 */ }
99
+ }
100
+ return decoded.length > 0 ? decoded.join('\n') : null;
101
+ }
102
+
103
+ // Shared decode for policy scan targets (hard-block + destructive warnings).
104
+ export function decodePowerShellEncodedCommand(command) {
105
+ return _decodePowerShellEncodedCommand(command);
106
+ }
107
+
108
+ // Shared catastrophic-delete target test — see shell-policy-danger-target.mjs
109
+
110
+ // Token-level rm guard. BLOCKED_PATTERNS catches inline split-flag forms
111
+ // (`rm -rf /`, `rm -r -f /`, `rm -fr /`), but the regex misses arbitrary
112
+ // flag interleaving (`rm -r -f -v /`, `rm -v -r -f /`). Tokenise rm args
113
+ // and block any recursive+force combination whose target resolves to
114
+ // root, home, or $HOME — independent of flag order or extra options.
115
+ function _rmRecursiveForceUnsafe(command) {
116
+ const text = String(command || '');
117
+ const RM_RE = new RegExp('(?:^|[;&|\\n(){}]\\s*|\\$[\\({]\\s*|`\\s*)' + _RM_WRAP_CHAIN + '\\brm\\s+([^|;&\\n`)]+)', 'gi');
118
+ for (const m of text.matchAll(RM_RE)) {
119
+ const args = m[1].split(/\s+/).filter(Boolean);
120
+ let recursive = false;
121
+ let force = false;
122
+ const targets = [];
123
+ let endOfOpts = false;
124
+ for (const arg of args) {
125
+ if (endOfOpts) { targets.push(arg); continue; }
126
+ if (arg === '--') { endOfOpts = true; continue; }
127
+ if (arg === '--recursive') { recursive = true; continue; }
128
+ if (arg === '--force') { force = true; continue; }
129
+ if (/^-[a-zA-Z]+$/.test(arg)) {
130
+ if (/[rR]/.test(arg)) recursive = true;
131
+ if (/[fF]/.test(arg)) force = true;
132
+ continue;
133
+ }
134
+ if (arg.startsWith('-')) continue;
135
+ targets.push(arg);
136
+ }
137
+ if (!(recursive && force)) continue;
138
+ for (const t of targets) {
139
+ if (_isDangerousDeleteTarget(t)) return true;
140
+ }
141
+ }
142
+ return false;
143
+ }
144
+
145
+ // PowerShell `Remove-Item -Recurse -Force` target guard. Uses the shared
146
+ // _isDangerousDeleteTarget test (parity with the bash rm guard): blocks only
147
+ // root / home / top-level-system / whole-cwd targets, plus a MISSING target.
148
+ // Generic variables ($x, $env:TEMP) are allowed (CC-level) — only known
149
+ // home/system env vars are treated as dangerous.
150
+ // -Force is matched at its minimum unambiguous PowerShell prefix `-fo` (NOT
151
+ // bare `-f`, which is ambiguous with -Filter); -Recurse matches `-r`/`-rec`.
152
+ function _removeItemRecursiveForceUnsafe(command) {
153
+ const text = String(command || '');
154
+ const RI_RE = /(?:^|[;&|\n(){}]\s*|`\s*)\s*(?:Remove-Item|ri|rm|rmdir|rd|del|erase)\b([^\n;|]*)/gi;
155
+ for (const m of text.matchAll(RI_RE)) {
156
+ const toks = m[1].split(/\s+/).filter(Boolean);
157
+ let recursive = false;
158
+ let force = false;
159
+ const targets = [];
160
+ for (let i = 0; i < toks.length; i += 1) {
161
+ const low = toks[i].toLowerCase();
162
+ if (low.startsWith('-')) {
163
+ if (/^-r(ec(urse)?)?$/.test(low)) { recursive = true; continue; }
164
+ if (/^-r(ec(urse)?)?:\$true$/i.test(low)) { recursive = true; continue; }
165
+ if (/^-fo(rce)?$/.test(low)) { force = true; continue; }
166
+ if (/^-fo(rce)?:\$true$/i.test(low)) { force = true; continue; }
167
+ if (low === '-path' || low === '-literalpath' || low === '-lp') {
168
+ if (toks[i + 1] !== undefined) { targets.push(toks[i + 1]); i += 1; }
169
+ continue;
170
+ }
171
+ continue; // unrelated switch
172
+ }
173
+ targets.push(toks[i]);
174
+ }
175
+ if (!(recursive && force)) continue;
176
+ if (targets.length === 0) return true; // recursive+force with no target
177
+ for (const raw of targets) {
178
+ const parts = raw.replace(/^@\(/, '').replace(/\)$/, '').split(',');
179
+ for (const p0 of parts) {
180
+ if (_isDangerousDeleteTarget(p0)) return true;
181
+ }
182
+ }
183
+ }
184
+ return false;
185
+ }
186
+
187
+ // cmd.exe recursive delete guard: `del /s [..] <path>`, `rd /s [..] <path>`,
188
+ // `rmdir /s <path>`. Only the recursive `/s` form is dangerous (plain `rd`
189
+ // removes empty dirs only; plain `del` is non-recursive), so we block solely
190
+ // when `/s` is present AND the target is catastrophic (via the shared
191
+ // _isDangerousDeleteTarget) or missing. Safe concrete paths pass (CC-level).
192
+ function _cmdRecursiveDeleteUnsafe(command) {
193
+ const text = String(command || '');
194
+ const RE = /(?:^|[;&|\n(){}]\s*|`\s*)\s*(?:del|erase|rd|rmdir)\b([^\n;|&]*)/gi;
195
+ for (const m of text.matchAll(RE)) {
196
+ const toks = m[1].split(/\s+/).filter(Boolean);
197
+ let recursive = false;
198
+ const targets = [];
199
+ for (const tk of toks) {
200
+ if (tk.startsWith('/')) { // cmd switch: /s /q /f /a …
201
+ if (/^\/s/i.test(tk)) recursive = true;
202
+ continue;
203
+ }
204
+ if (tk.startsWith('-')) continue; // stray POSIX-style flag
205
+ targets.push(tk);
206
+ }
207
+ if (!recursive) continue;
208
+ if (targets.length === 0) return true; // `del /s` / `rd /s` with no target
209
+ for (const t of targets) if (_isDangerousDeleteTarget(t)) return true;
210
+ }
211
+ return false;
212
+ }
213
+
214
+ export function isBlockedCommand(command) {
215
+ for (const pat of BLOCKED_PATTERNS) {
216
+ if (pat.test(command)) return true;
217
+ }
218
+ // Token-level rm guard catches split-flag forms the inline regex misses
219
+ // (e.g. `rm -r -f -v /`, `rm -v -R -F ~`).
220
+ if (_rmRecursiveForceUnsafe(command)) return true;
221
+ // PowerShell Remove-Item recursive+force guard — target-checked, parity
222
+ // with the bash rm guard above (and its decoded-payload variant below).
223
+ if (_removeItemRecursiveForceUnsafe(command)) return true;
224
+ // cmd-style recursive delete (`del /s`, `rd /s`, `rmdir /s`) — target-checked.
225
+ if (_cmdRecursiveDeleteUnsafe(command)) return true;
226
+ const decodedForRm = _decodePowerShellEncodedCommand(command);
227
+ if (decodedForRm && _rmRecursiveForceUnsafe(decodedForRm)) return true;
228
+ if (decodedForRm && _removeItemRecursiveForceUnsafe(decodedForRm)) return true;
229
+ if (decodedForRm && _cmdRecursiveDeleteUnsafe(decodedForRm)) return true;
230
+ // Re-scan decoded PowerShell -EncodedCommand payload. A destructive script
231
+ // smuggled as base64 (UTF-16LE) was previously invisible to the literal
232
+ // pattern match. Decode is best-effort; bad base64 / non-text bytes just
233
+ // return null and the function below skips. The decoded form is fed
234
+ // through the same BLOCKED_PATTERNS so any future addition automatically
235
+ // covers the encoded variant too.
236
+ const decoded = _decodePowerShellEncodedCommand(command);
237
+ if (decoded) {
238
+ for (const pat of BLOCKED_PATTERNS) {
239
+ if (pat.test(decoded)) return true;
240
+ }
241
+ }
242
+ return false;
243
+ }
244
+
245
+ const WMIC_PROCESS_DEFAULT_FIELDS = Object.freeze([
246
+ 'ProcessId',
247
+ 'Name',
248
+ 'CreationDate',
249
+ 'ExecutablePath',
250
+ 'CommandLine',
251
+ ]);
252
+
253
+ const WMIC_PROCESS_FIELD_MAP = new Map([
254
+ ['processid', 'ProcessId'],
255
+ ['name', 'Name'],
256
+ ['creationdate', 'CreationDate'],
257
+ ['executablepath', 'ExecutablePath'],
258
+ ['commandline', 'CommandLine'],
259
+ ['parentprocessid', 'ParentProcessId'],
260
+ ['workingsetsize', 'WorkingSetSize'],
261
+ ['threadcount', 'ThreadCount'],
262
+ ['handlecount', 'HandleCount'],
263
+ ]);
264
+
265
+ function _psQuote(value) {
266
+ return `'${String(value).replace(/'/g, "''")}'`;
267
+ }
268
+
269
+ function _psArray(values) {
270
+ return `@(${values.map(_psQuote).join(', ')})`;
271
+ }
272
+
273
+ function _encodePowerShellCommand(script) {
274
+ return Buffer.from(script, 'utf16le').toString('base64');
275
+ }
276
+
277
+ function _parseWmicProcessFields(command) {
278
+ const normalized = String(command || '').replace(/\\"/g, '"');
279
+ const m = normalized.match(/\bget\s+([\s\S]+?)(?:\s+\/format:\w+)?\s*["']?\s*$/i);
280
+ if (!m) return [...WMIC_PROCESS_DEFAULT_FIELDS];
281
+ const fields = [];
282
+ for (const raw of m[1].split(/[,\s]+/)) {
283
+ const key = raw.trim().replace(/[^A-Za-z0-9_]/g, '').toLowerCase();
284
+ const field = WMIC_PROCESS_FIELD_MAP.get(key);
285
+ if (field && !fields.includes(field)) fields.push(field);
286
+ }
287
+ return fields.length ? fields : [...WMIC_PROCESS_DEFAULT_FIELDS];
288
+ }
289
+
290
+ /**
291
+ * Rewrite deprecated `wmic process ... get ...` probes to a bounded
292
+ * PowerShell/CIM equivalent. WMIC routinely stalls for the full shell timeout
293
+ * on Windows hosts; EncodedCommand also protects PowerShell's `$_` token from
294
+ * any outer shell parsing before PowerShell sees it.
295
+ *
296
+ * Returns null for non-matching commands.
297
+ */
298
+ export function maybeRewriteWmicProcessCommand(command) {
299
+ const text = typeof command === 'string' ? command : '';
300
+ // Composite shell structure detection (pipes / && / ; / $( / backtick).
301
+ // The full-command rewrite below replaces the entire `text`, which would
302
+ // silently drop surrounding `cd`, pipes, `&&`/`;` segments. For composite
303
+ // commands containing wmic, return null so the caller falls back to other
304
+ // policy handling instead of dropping context.
305
+ if (/[|&;]|\$\(|`/.test(text) && /\bwmic(?:\.exe)?\s+process\b/i.test(text)) return null;
306
+ if (!/\bwmic(?:\.exe)?\s+process\b/i.test(text)) return null;
307
+ if (!/\bget\b/i.test(text)) {
308
+ return {
309
+ error: 'wmic process commands are disabled because WMIC can stall for minutes; use PowerShell Get-CimInstance/Get-Process instead.',
310
+ };
311
+ }
312
+
313
+ const normalized = text.replace(/\\"/g, '"');
314
+ const names = [...normalized.matchAll(/\bname\s*=\s*['"]([^'"]+)['"]/ig)]
315
+ .map(m => m[1])
316
+ .filter(Boolean);
317
+ const pids = [...normalized.matchAll(/\bprocessid\s*=\s*(\d+)/ig)]
318
+ .map(m => Number(m[1]))
319
+ .filter(Number.isFinite);
320
+ const fields = _parseWmicProcessFields(normalized);
321
+
322
+ const filters = [];
323
+ const setup = [`$fields = ${_psArray(fields)}`];
324
+ if (names.length > 0) {
325
+ setup.push(`$names = ${_psArray([...new Set(names)])}`);
326
+ filters.push('($names -contains $_.Name)');
327
+ }
328
+ if (pids.length > 0) {
329
+ setup.push(`$pids = @(${[...new Set(pids)].join(', ')})`);
330
+ filters.push('($pids -contains [int]$_.ProcessId)');
331
+ }
332
+
333
+ const where = filters.length ? ` | Where-Object { ${filters.join(' -or ')} }` : '';
334
+ const script = [
335
+ ...setup,
336
+ `$ErrorActionPreference = 'Stop'`,
337
+ `Get-CimInstance Win32_Process${where} | Select-Object -Property $fields | Format-List`,
338
+ ].join('; ');
339
+
340
+ return {
341
+ command: `powershell.exe -NoProfile -EncodedCommand ${_encodePowerShellCommand(script)}`,
342
+ timeoutMs: 30_000,
343
+ note: '[auto-rewrite: deprecated wmic process query -> PowerShell Get-CimInstance; timeout capped at 30000ms]',
344
+ };
345
+ }