@phnx-labs/agents-cli 1.12.0 → 1.14.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 (496) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README.md +293 -300
  3. package/dist/commands/alias.d.ts +11 -0
  4. package/dist/commands/alias.js +117 -0
  5. package/dist/commands/beta.d.ts +2 -0
  6. package/dist/commands/beta.js +53 -0
  7. package/dist/commands/cloud.d.ts +10 -0
  8. package/dist/commands/cloud.js +408 -0
  9. package/dist/commands/commands.d.ts +9 -1
  10. package/dist/commands/commands.js +24 -172
  11. package/dist/commands/daemon.d.ts +8 -1
  12. package/dist/commands/daemon.js +13 -5
  13. package/dist/commands/doctor.d.ts +15 -0
  14. package/dist/commands/doctor.js +132 -0
  15. package/dist/commands/drive.d.ts +8 -1
  16. package/dist/commands/drive.js +20 -3
  17. package/dist/commands/exec.d.ts +8 -1
  18. package/dist/commands/exec.js +207 -20
  19. package/dist/commands/factory.d.ts +19 -0
  20. package/dist/commands/factory.js +71 -0
  21. package/dist/commands/fork.d.ts +8 -1
  22. package/dist/commands/fork.js +11 -4
  23. package/dist/commands/hooks.d.ts +9 -1
  24. package/dist/commands/hooks.js +30 -182
  25. package/dist/commands/init.d.ts +15 -1
  26. package/dist/commands/init.js +168 -74
  27. package/dist/commands/mcp.d.ts +9 -1
  28. package/dist/commands/mcp.js +11 -7
  29. package/dist/commands/models.d.ts +8 -1
  30. package/dist/commands/models.js +45 -6
  31. package/dist/commands/packages.d.ts +8 -1
  32. package/dist/commands/packages.js +13 -7
  33. package/dist/commands/permissions.d.ts +9 -1
  34. package/dist/commands/permissions.js +3 -3
  35. package/dist/commands/plugins.d.ts +8 -1
  36. package/dist/commands/plugins.js +13 -2
  37. package/dist/commands/profiles.d.ts +11 -0
  38. package/dist/commands/profiles.js +291 -0
  39. package/dist/commands/prune.d.ts +22 -0
  40. package/dist/commands/prune.js +191 -0
  41. package/dist/commands/pty.d.ts +1 -1
  42. package/dist/commands/pty.js +2 -1
  43. package/dist/commands/pull.d.ts +8 -1
  44. package/dist/commands/pull.js +93 -129
  45. package/dist/commands/refresh-memory.d.ts +7 -1
  46. package/dist/commands/refresh-memory.js +7 -1
  47. package/dist/commands/repo.d.ts +15 -0
  48. package/dist/commands/repo.js +570 -0
  49. package/dist/commands/resource-view.d.ts +10 -3
  50. package/dist/commands/resource-view.js +18 -5
  51. package/dist/commands/routines.d.ts +8 -1
  52. package/dist/commands/routines.js +17 -4
  53. package/dist/commands/rules.d.ts +9 -1
  54. package/dist/commands/rules.js +16 -11
  55. package/dist/commands/secrets.d.ts +10 -0
  56. package/dist/commands/secrets.js +511 -0
  57. package/dist/commands/sessions-picker.d.ts +2 -1
  58. package/dist/commands/sessions-picker.js +88 -11
  59. package/dist/commands/sessions-tail.d.ts +19 -0
  60. package/dist/commands/sessions-tail.js +235 -0
  61. package/dist/commands/sessions.d.ts +2 -1
  62. package/dist/commands/sessions.js +288 -7
  63. package/dist/commands/skills.d.ts +9 -1
  64. package/dist/commands/skills.js +28 -178
  65. package/dist/commands/status.d.ts +7 -1
  66. package/dist/commands/status.js +7 -1
  67. package/dist/commands/subagents.d.ts +8 -1
  68. package/dist/commands/subagents.js +11 -1
  69. package/dist/commands/sync.d.ts +8 -1
  70. package/dist/commands/sync.js +8 -1
  71. package/dist/commands/teams-picker.d.ts +4 -1
  72. package/dist/commands/teams-picker.js +55 -3
  73. package/dist/commands/teams.d.ts +15 -1
  74. package/dist/commands/teams.js +323 -69
  75. package/dist/commands/usage.d.ts +11 -0
  76. package/dist/commands/usage.js +60 -0
  77. package/dist/commands/utils.d.ts +6 -1
  78. package/dist/commands/utils.js +6 -1
  79. package/dist/commands/versions.d.ts +8 -1
  80. package/dist/commands/versions.js +4 -3
  81. package/dist/commands/view.d.ts +47 -2
  82. package/dist/commands/view.js +353 -20
  83. package/dist/index.d.ts +7 -2
  84. package/dist/index.js +205 -38
  85. package/dist/lib/acp/client.d.ts +31 -0
  86. package/dist/lib/acp/client.js +117 -0
  87. package/dist/lib/acp/harnesses.d.ts +26 -0
  88. package/dist/lib/acp/harnesses.js +65 -0
  89. package/dist/lib/acp/run.d.ts +18 -0
  90. package/dist/lib/acp/run.js +39 -0
  91. package/dist/lib/agents.d.ts +74 -2
  92. package/dist/lib/agents.js +207 -23
  93. package/dist/lib/artifact-actions.d.ts +8 -4
  94. package/dist/lib/artifact-actions.js +8 -6
  95. package/dist/lib/auto-pull-worker.d.ts +11 -0
  96. package/dist/lib/auto-pull-worker.js +121 -0
  97. package/dist/lib/auto-pull.d.ts +31 -0
  98. package/dist/lib/auto-pull.js +97 -0
  99. package/dist/lib/beta.d.ts +23 -0
  100. package/dist/lib/beta.js +90 -0
  101. package/dist/lib/capabilities.d.ts +29 -0
  102. package/dist/lib/capabilities.js +74 -0
  103. package/dist/lib/cloud/codex.d.ts +25 -0
  104. package/dist/lib/cloud/codex.js +250 -0
  105. package/dist/lib/cloud/factory.d.ts +31 -0
  106. package/dist/lib/cloud/factory.js +53 -0
  107. package/dist/lib/cloud/registry.d.ts +15 -0
  108. package/dist/lib/cloud/registry.js +67 -0
  109. package/dist/lib/cloud/rush.d.ts +75 -0
  110. package/dist/lib/cloud/rush.js +438 -0
  111. package/dist/lib/cloud/store.d.ts +22 -0
  112. package/dist/lib/cloud/store.js +115 -0
  113. package/dist/lib/cloud/stream.d.ts +23 -0
  114. package/dist/lib/cloud/stream.js +194 -0
  115. package/dist/lib/cloud/types.d.ts +205 -0
  116. package/dist/lib/cloud/types.js +34 -0
  117. package/dist/lib/command-skills.d.ts +20 -0
  118. package/dist/lib/command-skills.js +142 -0
  119. package/dist/lib/commands.d.ts +22 -2
  120. package/dist/lib/commands.js +51 -11
  121. package/dist/lib/convert.d.ts +10 -1
  122. package/dist/lib/convert.js +9 -1
  123. package/dist/lib/daemon.d.ts +21 -1
  124. package/dist/lib/daemon.js +97 -4
  125. package/dist/lib/drive-sync.d.ts +18 -1
  126. package/dist/lib/drive-sync.js +57 -15
  127. package/dist/lib/exec.d.ts +25 -5
  128. package/dist/lib/exec.js +72 -27
  129. package/dist/lib/fs-walk.d.ts +2 -0
  130. package/dist/lib/fs-walk.js +40 -0
  131. package/dist/lib/fuzzy.d.ts +53 -0
  132. package/dist/lib/fuzzy.js +72 -0
  133. package/dist/lib/gemini-settings.d.ts +4 -0
  134. package/dist/lib/gemini-settings.js +33 -0
  135. package/dist/lib/git.d.ts +12 -2
  136. package/dist/lib/git.js +17 -6
  137. package/dist/lib/help.d.ts +20 -1
  138. package/dist/lib/help.js +45 -6
  139. package/dist/lib/hooks/match.d.ts +32 -0
  140. package/dist/lib/hooks/match.js +120 -0
  141. package/dist/lib/hooks.d.ts +17 -4
  142. package/dist/lib/hooks.js +191 -21
  143. package/dist/lib/manifest.d.ts +6 -1
  144. package/dist/lib/manifest.js +15 -4
  145. package/dist/lib/markdown.d.ts +0 -1
  146. package/dist/lib/markdown.js +6 -1
  147. package/dist/lib/mcp.d.ts +0 -1
  148. package/dist/lib/mcp.js +29 -33
  149. package/dist/lib/memory-compile.d.ts +13 -3
  150. package/dist/lib/memory-compile.js +31 -9
  151. package/dist/lib/memory.d.ts +14 -7
  152. package/dist/lib/memory.js +67 -38
  153. package/dist/lib/migrate.d.ts +8 -0
  154. package/dist/lib/migrate.js +85 -0
  155. package/dist/lib/models.d.ts +25 -11
  156. package/dist/lib/models.js +405 -16
  157. package/dist/lib/onepassword.d.ts +63 -0
  158. package/dist/lib/onepassword.js +186 -0
  159. package/dist/lib/paths.d.ts +8 -0
  160. package/dist/lib/paths.js +20 -0
  161. package/dist/lib/permissions.d.ts +24 -2
  162. package/dist/lib/permissions.js +117 -48
  163. package/dist/lib/picker.d.ts +10 -1
  164. package/dist/lib/picker.js +15 -1
  165. package/dist/lib/plugins.d.ts +7 -1
  166. package/dist/lib/plugins.js +10 -1
  167. package/dist/lib/profiles-presets.d.ts +24 -0
  168. package/dist/lib/profiles-presets.js +103 -0
  169. package/dist/lib/profiles.d.ts +69 -0
  170. package/dist/lib/profiles.js +144 -0
  171. package/dist/lib/pty-client.d.ts +1 -1
  172. package/dist/lib/pty-client.js +0 -1
  173. package/dist/lib/pty-server.d.ts +16 -2
  174. package/dist/lib/pty-server.js +92 -3
  175. package/dist/lib/registry.d.ts +23 -3
  176. package/dist/lib/registry.js +153 -8
  177. package/dist/lib/resources.d.ts +28 -1
  178. package/dist/lib/resources.js +79 -1
  179. package/dist/lib/rotate.d.ts +79 -0
  180. package/dist/lib/rotate.js +285 -0
  181. package/dist/lib/routines.d.ts +29 -1
  182. package/dist/lib/routines.js +32 -5
  183. package/dist/lib/runner.d.ts +14 -1
  184. package/dist/lib/runner.js +22 -3
  185. package/dist/lib/sandbox.d.ts +16 -1
  186. package/dist/lib/sandbox.js +39 -16
  187. package/dist/lib/scheduler.d.ts +8 -1
  188. package/dist/lib/scheduler.js +8 -1
  189. package/dist/lib/secrets/AgentsKeychain.app/Contents/CodeResources +0 -0
  190. package/dist/lib/secrets/AgentsKeychain.app/Contents/Info.plist +22 -0
  191. package/dist/lib/secrets/AgentsKeychain.app/Contents/MacOS/AgentsKeychain +0 -0
  192. package/dist/lib/secrets/AgentsKeychain.app/Contents/_CodeSignature/CodeResources +123 -0
  193. package/dist/lib/secrets/AgentsKeychain.app/Contents/embedded.provisionprofile +0 -0
  194. package/dist/lib/secrets/bundles.d.ts +39 -0
  195. package/dist/lib/secrets/bundles.js +189 -0
  196. package/dist/lib/secrets/index.d.ts +55 -0
  197. package/dist/lib/secrets/index.js +211 -0
  198. package/dist/lib/secrets/profiles.d.ts +10 -0
  199. package/dist/lib/secrets/profiles.js +13 -0
  200. package/dist/lib/session/active.d.ts +43 -0
  201. package/dist/lib/session/active.js +392 -0
  202. package/dist/lib/session/artifacts.d.ts +16 -0
  203. package/dist/lib/session/artifacts.js +95 -0
  204. package/dist/lib/session/cloud.d.ts +30 -0
  205. package/dist/lib/session/cloud.js +121 -0
  206. package/dist/lib/session/db.d.ts +23 -2
  207. package/dist/lib/session/db.js +76 -12
  208. package/dist/lib/session/discover.d.ts +19 -4
  209. package/dist/lib/session/discover.js +344 -48
  210. package/dist/lib/session/parse.d.ts +28 -1
  211. package/dist/lib/session/parse.js +267 -9
  212. package/dist/lib/session/prompt.d.ts +9 -1
  213. package/dist/lib/session/prompt.js +17 -3
  214. package/dist/lib/session/render.d.ts +13 -1
  215. package/dist/lib/session/render.js +20 -1
  216. package/dist/lib/session/team-filter.d.ts +9 -1
  217. package/dist/lib/session/team-filter.js +11 -2
  218. package/dist/lib/session/types.d.ts +24 -2
  219. package/dist/lib/session/types.js +10 -2
  220. package/dist/lib/shims.d.ts +93 -5
  221. package/dist/lib/shims.js +380 -67
  222. package/dist/lib/skills.d.ts +27 -2
  223. package/dist/lib/skills.js +127 -65
  224. package/dist/lib/sqlite.d.ts +43 -0
  225. package/dist/lib/sqlite.js +94 -0
  226. package/dist/lib/state.d.ts +114 -22
  227. package/dist/lib/state.js +323 -138
  228. package/dist/lib/subagents.d.ts +9 -1
  229. package/dist/lib/subagents.js +70 -63
  230. package/dist/lib/sync-manifest.d.ts +81 -0
  231. package/dist/lib/sync-manifest.js +450 -0
  232. package/dist/lib/teams/agents.d.ts +103 -5
  233. package/dist/lib/teams/agents.js +414 -91
  234. package/dist/lib/teams/api.d.ts +26 -3
  235. package/dist/lib/teams/api.js +63 -3
  236. package/dist/lib/teams/debug.d.ts +6 -1
  237. package/dist/lib/teams/debug.js +6 -1
  238. package/dist/lib/teams/file_ops.d.ts +7 -1
  239. package/dist/lib/teams/file_ops.js +7 -1
  240. package/dist/lib/teams/index.d.ts +15 -0
  241. package/dist/lib/teams/index.js +14 -0
  242. package/dist/lib/teams/parsers.d.ts +4 -1
  243. package/dist/lib/teams/parsers.js +11 -1
  244. package/dist/lib/teams/persistence.d.ts +15 -1
  245. package/dist/lib/teams/persistence.js +102 -20
  246. package/dist/lib/teams/registry.d.ts +12 -1
  247. package/dist/lib/teams/registry.js +116 -33
  248. package/dist/lib/teams/summarizer.d.ts +15 -1
  249. package/dist/lib/teams/summarizer.js +14 -1
  250. package/dist/lib/teams/supervisor.d.ts +48 -0
  251. package/dist/lib/teams/supervisor.js +73 -0
  252. package/dist/lib/template.d.ts +8 -6
  253. package/dist/lib/template.js +8 -6
  254. package/dist/lib/types.d.ts +147 -8
  255. package/dist/lib/types.js +26 -3
  256. package/dist/lib/usage.d.ts +48 -1
  257. package/dist/lib/usage.js +97 -16
  258. package/dist/lib/version-duplicates.d.ts +21 -0
  259. package/dist/lib/version-duplicates.js +90 -0
  260. package/dist/lib/versions.d.ts +39 -4
  261. package/dist/lib/versions.js +401 -111
  262. package/package.json +33 -18
  263. package/scripts/postinstall.js +126 -30
  264. package/dist/commands/__tests__/sessions.test.d.ts +0 -2
  265. package/dist/commands/__tests__/sessions.test.d.ts.map +0 -1
  266. package/dist/commands/__tests__/sessions.test.js +0 -636
  267. package/dist/commands/__tests__/sessions.test.js.map +0 -1
  268. package/dist/commands/commands.d.ts.map +0 -1
  269. package/dist/commands/commands.js.map +0 -1
  270. package/dist/commands/daemon.d.ts.map +0 -1
  271. package/dist/commands/daemon.js.map +0 -1
  272. package/dist/commands/drive.d.ts.map +0 -1
  273. package/dist/commands/drive.js.map +0 -1
  274. package/dist/commands/exec.d.ts.map +0 -1
  275. package/dist/commands/exec.js.map +0 -1
  276. package/dist/commands/fork.d.ts.map +0 -1
  277. package/dist/commands/fork.js.map +0 -1
  278. package/dist/commands/hooks.d.ts.map +0 -1
  279. package/dist/commands/hooks.js.map +0 -1
  280. package/dist/commands/init.d.ts.map +0 -1
  281. package/dist/commands/init.js.map +0 -1
  282. package/dist/commands/mcp.d.ts.map +0 -1
  283. package/dist/commands/mcp.js.map +0 -1
  284. package/dist/commands/models.d.ts.map +0 -1
  285. package/dist/commands/models.js.map +0 -1
  286. package/dist/commands/packages.d.ts.map +0 -1
  287. package/dist/commands/packages.js.map +0 -1
  288. package/dist/commands/permissions.d.ts.map +0 -1
  289. package/dist/commands/permissions.js.map +0 -1
  290. package/dist/commands/plugins.d.ts.map +0 -1
  291. package/dist/commands/plugins.js.map +0 -1
  292. package/dist/commands/pty.d.ts.map +0 -1
  293. package/dist/commands/pty.js.map +0 -1
  294. package/dist/commands/pull.d.ts.map +0 -1
  295. package/dist/commands/pull.js.map +0 -1
  296. package/dist/commands/push.d.ts +0 -3
  297. package/dist/commands/push.d.ts.map +0 -1
  298. package/dist/commands/push.js +0 -180
  299. package/dist/commands/push.js.map +0 -1
  300. package/dist/commands/refresh-memory.d.ts.map +0 -1
  301. package/dist/commands/refresh-memory.js.map +0 -1
  302. package/dist/commands/resource-view.d.ts.map +0 -1
  303. package/dist/commands/resource-view.js.map +0 -1
  304. package/dist/commands/routines.d.ts.map +0 -1
  305. package/dist/commands/routines.js.map +0 -1
  306. package/dist/commands/rules.d.ts.map +0 -1
  307. package/dist/commands/rules.js.map +0 -1
  308. package/dist/commands/sessions-picker.d.ts.map +0 -1
  309. package/dist/commands/sessions-picker.js.map +0 -1
  310. package/dist/commands/sessions.d.ts.map +0 -1
  311. package/dist/commands/sessions.js.map +0 -1
  312. package/dist/commands/skills.d.ts.map +0 -1
  313. package/dist/commands/skills.js.map +0 -1
  314. package/dist/commands/status.d.ts.map +0 -1
  315. package/dist/commands/status.js.map +0 -1
  316. package/dist/commands/subagents.d.ts.map +0 -1
  317. package/dist/commands/subagents.js.map +0 -1
  318. package/dist/commands/sync.d.ts.map +0 -1
  319. package/dist/commands/sync.js.map +0 -1
  320. package/dist/commands/teams-picker.d.ts.map +0 -1
  321. package/dist/commands/teams-picker.js.map +0 -1
  322. package/dist/commands/teams.d.ts.map +0 -1
  323. package/dist/commands/teams.js.map +0 -1
  324. package/dist/commands/utils.d.ts.map +0 -1
  325. package/dist/commands/utils.js.map +0 -1
  326. package/dist/commands/versions.d.ts.map +0 -1
  327. package/dist/commands/versions.js.map +0 -1
  328. package/dist/commands/view.d.ts.map +0 -1
  329. package/dist/commands/view.js.map +0 -1
  330. package/dist/index.d.ts.map +0 -1
  331. package/dist/index.js.map +0 -1
  332. package/dist/lib/__tests__/bugfixes.test.d.ts +0 -2
  333. package/dist/lib/__tests__/bugfixes.test.d.ts.map +0 -1
  334. package/dist/lib/__tests__/bugfixes.test.js +0 -192
  335. package/dist/lib/__tests__/bugfixes.test.js.map +0 -1
  336. package/dist/lib/__tests__/exec.test.d.ts +0 -2
  337. package/dist/lib/__tests__/exec.test.d.ts.map +0 -1
  338. package/dist/lib/__tests__/exec.test.js +0 -446
  339. package/dist/lib/__tests__/exec.test.js.map +0 -1
  340. package/dist/lib/__tests__/git-sync.test.d.ts +0 -2
  341. package/dist/lib/__tests__/git-sync.test.d.ts.map +0 -1
  342. package/dist/lib/__tests__/git-sync.test.js +0 -138
  343. package/dist/lib/__tests__/git-sync.test.js.map +0 -1
  344. package/dist/lib/__tests__/hooks.test.d.ts +0 -2
  345. package/dist/lib/__tests__/hooks.test.d.ts.map +0 -1
  346. package/dist/lib/__tests__/hooks.test.js +0 -203
  347. package/dist/lib/__tests__/hooks.test.js.map +0 -1
  348. package/dist/lib/__tests__/memory-compile.test.d.ts +0 -2
  349. package/dist/lib/__tests__/memory-compile.test.d.ts.map +0 -1
  350. package/dist/lib/__tests__/memory-compile.test.js +0 -95
  351. package/dist/lib/__tests__/memory-compile.test.js.map +0 -1
  352. package/dist/lib/__tests__/models.test.d.ts +0 -2
  353. package/dist/lib/__tests__/models.test.d.ts.map +0 -1
  354. package/dist/lib/__tests__/models.test.js +0 -184
  355. package/dist/lib/__tests__/models.test.js.map +0 -1
  356. package/dist/lib/__tests__/usage.test.d.ts +0 -2
  357. package/dist/lib/__tests__/usage.test.d.ts.map +0 -1
  358. package/dist/lib/__tests__/usage.test.js +0 -218
  359. package/dist/lib/__tests__/usage.test.js.map +0 -1
  360. package/dist/lib/agents.d.ts.map +0 -1
  361. package/dist/lib/agents.js.map +0 -1
  362. package/dist/lib/artifact-actions.d.ts.map +0 -1
  363. package/dist/lib/artifact-actions.js.map +0 -1
  364. package/dist/lib/commands.d.ts.map +0 -1
  365. package/dist/lib/commands.js.map +0 -1
  366. package/dist/lib/convert.d.ts.map +0 -1
  367. package/dist/lib/convert.js.map +0 -1
  368. package/dist/lib/daemon.d.ts.map +0 -1
  369. package/dist/lib/daemon.js.map +0 -1
  370. package/dist/lib/drive-sync.d.ts.map +0 -1
  371. package/dist/lib/drive-sync.js.map +0 -1
  372. package/dist/lib/exec.d.ts.map +0 -1
  373. package/dist/lib/exec.js.map +0 -1
  374. package/dist/lib/factory.d.ts +0 -57
  375. package/dist/lib/factory.d.ts.map +0 -1
  376. package/dist/lib/factory.js +0 -110
  377. package/dist/lib/factory.js.map +0 -1
  378. package/dist/lib/git.d.ts.map +0 -1
  379. package/dist/lib/git.js.map +0 -1
  380. package/dist/lib/help.d.ts.map +0 -1
  381. package/dist/lib/help.js.map +0 -1
  382. package/dist/lib/hooks.d.ts.map +0 -1
  383. package/dist/lib/hooks.js.map +0 -1
  384. package/dist/lib/manifest.d.ts.map +0 -1
  385. package/dist/lib/manifest.js.map +0 -1
  386. package/dist/lib/markdown.d.ts.map +0 -1
  387. package/dist/lib/markdown.js.map +0 -1
  388. package/dist/lib/mcp.d.ts.map +0 -1
  389. package/dist/lib/mcp.js.map +0 -1
  390. package/dist/lib/memory-compile.d.ts.map +0 -1
  391. package/dist/lib/memory-compile.js.map +0 -1
  392. package/dist/lib/memory.d.ts.map +0 -1
  393. package/dist/lib/memory.js.map +0 -1
  394. package/dist/lib/models.d.ts.map +0 -1
  395. package/dist/lib/models.js.map +0 -1
  396. package/dist/lib/permissions.d.ts.map +0 -1
  397. package/dist/lib/permissions.js.map +0 -1
  398. package/dist/lib/picker.d.ts.map +0 -1
  399. package/dist/lib/picker.js.map +0 -1
  400. package/dist/lib/plugins.d.ts.map +0 -1
  401. package/dist/lib/plugins.js.map +0 -1
  402. package/dist/lib/pty-client.d.ts.map +0 -1
  403. package/dist/lib/pty-client.js.map +0 -1
  404. package/dist/lib/pty-server.d.ts.map +0 -1
  405. package/dist/lib/pty-server.js.map +0 -1
  406. package/dist/lib/registry.d.ts.map +0 -1
  407. package/dist/lib/registry.js.map +0 -1
  408. package/dist/lib/resources.d.ts.map +0 -1
  409. package/dist/lib/resources.js.map +0 -1
  410. package/dist/lib/routines.d.ts.map +0 -1
  411. package/dist/lib/routines.js.map +0 -1
  412. package/dist/lib/runner.d.ts.map +0 -1
  413. package/dist/lib/runner.js.map +0 -1
  414. package/dist/lib/sandbox.d.ts.map +0 -1
  415. package/dist/lib/sandbox.js.map +0 -1
  416. package/dist/lib/scheduler.d.ts.map +0 -1
  417. package/dist/lib/scheduler.js.map +0 -1
  418. package/dist/lib/session/__tests__/db.test.d.ts +0 -2
  419. package/dist/lib/session/__tests__/db.test.d.ts.map +0 -1
  420. package/dist/lib/session/__tests__/db.test.js +0 -54
  421. package/dist/lib/session/__tests__/db.test.js.map +0 -1
  422. package/dist/lib/session/__tests__/discover.test.d.ts +0 -2
  423. package/dist/lib/session/__tests__/discover.test.d.ts.map +0 -1
  424. package/dist/lib/session/__tests__/discover.test.js +0 -63
  425. package/dist/lib/session/__tests__/discover.test.js.map +0 -1
  426. package/dist/lib/session/__tests__/prompt.test.d.ts +0 -2
  427. package/dist/lib/session/__tests__/prompt.test.d.ts.map +0 -1
  428. package/dist/lib/session/__tests__/prompt.test.js +0 -44
  429. package/dist/lib/session/__tests__/prompt.test.js.map +0 -1
  430. package/dist/lib/session/__tests__/render.test.d.ts +0 -2
  431. package/dist/lib/session/__tests__/render.test.d.ts.map +0 -1
  432. package/dist/lib/session/__tests__/render.test.js +0 -602
  433. package/dist/lib/session/__tests__/render.test.js.map +0 -1
  434. package/dist/lib/session/db.d.ts.map +0 -1
  435. package/dist/lib/session/db.js.map +0 -1
  436. package/dist/lib/session/discover.d.ts.map +0 -1
  437. package/dist/lib/session/discover.js.map +0 -1
  438. package/dist/lib/session/parse.d.ts.map +0 -1
  439. package/dist/lib/session/parse.js.map +0 -1
  440. package/dist/lib/session/prompt.d.ts.map +0 -1
  441. package/dist/lib/session/prompt.js.map +0 -1
  442. package/dist/lib/session/prompt.test.d.ts +0 -2
  443. package/dist/lib/session/prompt.test.d.ts.map +0 -1
  444. package/dist/lib/session/prompt.test.js +0 -57
  445. package/dist/lib/session/prompt.test.js.map +0 -1
  446. package/dist/lib/session/render.d.ts.map +0 -1
  447. package/dist/lib/session/render.js.map +0 -1
  448. package/dist/lib/session/team-filter.d.ts.map +0 -1
  449. package/dist/lib/session/team-filter.js.map +0 -1
  450. package/dist/lib/session/team-filter.test.d.ts +0 -2
  451. package/dist/lib/session/team-filter.test.d.ts.map +0 -1
  452. package/dist/lib/session/team-filter.test.js +0 -157
  453. package/dist/lib/session/team-filter.test.js.map +0 -1
  454. package/dist/lib/session/types.d.ts.map +0 -1
  455. package/dist/lib/session/types.js.map +0 -1
  456. package/dist/lib/shims.d.ts.map +0 -1
  457. package/dist/lib/shims.js.map +0 -1
  458. package/dist/lib/skills.d.ts.map +0 -1
  459. package/dist/lib/skills.js.map +0 -1
  460. package/dist/lib/state.d.ts.map +0 -1
  461. package/dist/lib/state.js.map +0 -1
  462. package/dist/lib/subagents.d.ts.map +0 -1
  463. package/dist/lib/subagents.js.map +0 -1
  464. package/dist/lib/teams/agents.d.ts.map +0 -1
  465. package/dist/lib/teams/agents.js.map +0 -1
  466. package/dist/lib/teams/api.d.ts.map +0 -1
  467. package/dist/lib/teams/api.js.map +0 -1
  468. package/dist/lib/teams/cloud.d.ts +0 -11
  469. package/dist/lib/teams/cloud.d.ts.map +0 -1
  470. package/dist/lib/teams/cloud.js +0 -169
  471. package/dist/lib/teams/cloud.js.map +0 -1
  472. package/dist/lib/teams/debug.d.ts.map +0 -1
  473. package/dist/lib/teams/debug.js.map +0 -1
  474. package/dist/lib/teams/file_ops.d.ts.map +0 -1
  475. package/dist/lib/teams/file_ops.js.map +0 -1
  476. package/dist/lib/teams/parsers.d.ts.map +0 -1
  477. package/dist/lib/teams/parsers.js.map +0 -1
  478. package/dist/lib/teams/persistence.d.ts.map +0 -1
  479. package/dist/lib/teams/persistence.js.map +0 -1
  480. package/dist/lib/teams/ralph.d.ts +0 -8
  481. package/dist/lib/teams/ralph.d.ts.map +0 -1
  482. package/dist/lib/teams/ralph.js +0 -59
  483. package/dist/lib/teams/ralph.js.map +0 -1
  484. package/dist/lib/teams/registry.d.ts.map +0 -1
  485. package/dist/lib/teams/registry.js.map +0 -1
  486. package/dist/lib/teams/summarizer.d.ts.map +0 -1
  487. package/dist/lib/teams/summarizer.js.map +0 -1
  488. package/dist/lib/template.d.ts.map +0 -1
  489. package/dist/lib/template.js.map +0 -1
  490. package/dist/lib/types.d.ts.map +0 -1
  491. package/dist/lib/types.js.map +0 -1
  492. package/dist/lib/usage.d.ts.map +0 -1
  493. package/dist/lib/usage.js.map +0 -1
  494. package/dist/lib/versions.d.ts.map +0 -1
  495. package/dist/lib/versions.js.map +0 -1
  496. package/scripts/rebuild-sqlite.sh +0 -46
@@ -0,0 +1,186 @@
1
+ /**
2
+ * 1Password CLI (op) integration for importing secrets from vaults.
3
+ */
4
+ import { spawnSync } from 'child_process';
5
+ import * as fs from 'fs';
6
+ import * as os from 'os';
7
+ import * as path from 'path';
8
+ function runOp(args, input) {
9
+ const result = spawnSync('op', args, {
10
+ stdio: [input !== undefined ? 'pipe' : 'ignore', 'pipe', 'pipe'],
11
+ encoding: 'utf-8',
12
+ maxBuffer: 10 * 1024 * 1024,
13
+ input,
14
+ });
15
+ if (result.error) {
16
+ if (result.error.code === 'ENOENT') {
17
+ return { ok: false, error: '1Password CLI not found. Install: brew install 1password-cli' };
18
+ }
19
+ return { ok: false, error: result.error.message };
20
+ }
21
+ if (result.status !== 0) {
22
+ const stderr = result.stderr?.trim() || '';
23
+ if (stderr.includes('not signed in') || stderr.includes('sign in') || stderr.includes('no active session')) {
24
+ return { ok: false, error: 'Not signed in to 1Password. Run: op signin' };
25
+ }
26
+ return { ok: false, error: stderr || `op exited with code ${result.status}` };
27
+ }
28
+ return { ok: true, stdout: result.stdout };
29
+ }
30
+ export function assertOpAvailable() {
31
+ // `op account list` works with both CLI session tokens and the 1Password
32
+ // desktop biometric integration; `op whoami` fails on the latter.
33
+ const result = runOp(['account', 'list', '--format=json']);
34
+ if (!result.ok) {
35
+ throw new Error(result.error);
36
+ }
37
+ }
38
+ export function listVaults() {
39
+ const result = runOp(['vault', 'list', '--format=json']);
40
+ if (!result.ok)
41
+ throw new Error(result.error);
42
+ return JSON.parse(result.stdout);
43
+ }
44
+ export function listItems(vaultName) {
45
+ const result = runOp(['item', 'list', '--vault', vaultName, '--format=json']);
46
+ if (!result.ok) {
47
+ if (result.error.includes('vault') && result.error.includes('not found')) {
48
+ const vaults = listVaults();
49
+ const available = vaults.map((v) => v.name).join(', ');
50
+ throw new Error(`Vault '${vaultName}' not found. Available: ${available || '(none)'}`);
51
+ }
52
+ throw new Error(result.error);
53
+ }
54
+ const items = JSON.parse(result.stdout);
55
+ return items || [];
56
+ }
57
+ export function getItem(itemId, vaultName) {
58
+ const result = runOp(['item', 'get', itemId, '--vault', vaultName, '--format=json', '--reveal']);
59
+ if (!result.ok)
60
+ throw new Error(result.error);
61
+ return JSON.parse(result.stdout);
62
+ }
63
+ export function toEnvKey(title) {
64
+ return title
65
+ .toUpperCase()
66
+ .replace(/[^A-Z0-9]+/g, '_')
67
+ .replace(/^_+|_+$/g, '')
68
+ .replace(/^(\d)/, '_$1');
69
+ }
70
+ export function slugify(name) {
71
+ return name
72
+ .toLowerCase()
73
+ .replace(/[^a-z0-9]+/g, '-')
74
+ .replace(/^-+|-+$/g, '');
75
+ }
76
+ const IMPORTABLE_FIELD_TYPES = new Set([
77
+ 'CONCEALED', 'concealed',
78
+ 'STRING', 'string', 'text', 'TEXT',
79
+ 'URL', 'url',
80
+ ]);
81
+ const SKIP_FIELD_LABELS = new Set(['username', 'notesPlain', 'notes']);
82
+ function pickBestField(fields) {
83
+ const dominated = fields.filter((f) => IMPORTABLE_FIELD_TYPES.has(f.type) &&
84
+ f.value &&
85
+ !SKIP_FIELD_LABELS.has(f.label?.toLowerCase() || ''));
86
+ if (dominated.length === 0)
87
+ return null;
88
+ // Prefer concealed fields (credentials/passwords)
89
+ const concealed = dominated.find((f) => f.type.toLowerCase() === 'concealed');
90
+ if (concealed)
91
+ return concealed;
92
+ // Then prefer fields labeled credential/password/secret/key/token
93
+ const secretLabels = ['credential', 'password', 'secret', 'key', 'token', 'api_key', 'apikey'];
94
+ const labeled = dominated.find((f) => secretLabels.includes(f.label?.toLowerCase() || ''));
95
+ if (labeled)
96
+ return labeled;
97
+ // Fall back to first importable field
98
+ return dominated[0];
99
+ }
100
+ export function extractSecrets(items, vaultName) {
101
+ const secrets = [];
102
+ const skipped = [];
103
+ for (const summary of items) {
104
+ let item;
105
+ try {
106
+ item = getItem(summary.id, vaultName);
107
+ }
108
+ catch (err) {
109
+ skipped.push({
110
+ itemTitle: summary.title,
111
+ fieldLabel: '*',
112
+ reason: err.message,
113
+ });
114
+ continue;
115
+ }
116
+ const field = pickBestField(item.fields || []);
117
+ if (!field) {
118
+ skipped.push({
119
+ itemTitle: item.title,
120
+ fieldLabel: '*',
121
+ reason: 'no importable fields',
122
+ });
123
+ continue;
124
+ }
125
+ if (field.value.includes('\n')) {
126
+ skipped.push({
127
+ itemTitle: item.title,
128
+ fieldLabel: field.label,
129
+ reason: 'contains newlines (keychain limitation)',
130
+ });
131
+ continue;
132
+ }
133
+ const envKey = toEnvKey(item.title);
134
+ secrets.push({
135
+ envKey,
136
+ itemTitle: item.title,
137
+ fieldLabel: field.label,
138
+ value: field.value,
139
+ });
140
+ }
141
+ return { secrets, skipped };
142
+ }
143
+ export function buildPasswordItemTemplate(title, value) {
144
+ return {
145
+ title,
146
+ category: 'PASSWORD',
147
+ tags: ['agents-cli'],
148
+ fields: [
149
+ { id: 'password', type: 'CONCEALED', purpose: 'PASSWORD', label: 'password', value },
150
+ ],
151
+ };
152
+ }
153
+ export function itemExistsByTitle(title, vaultName) {
154
+ const result = runOp(['item', 'get', title, '--vault', vaultName, '--format=json']);
155
+ if (result.ok)
156
+ return true;
157
+ if (/isn't an item|not found|no item found/i.test(result.error))
158
+ return false;
159
+ throw new Error(result.error);
160
+ }
161
+ export function deleteItemByTitle(title, vaultName) {
162
+ const result = runOp(['item', 'delete', title, '--vault', vaultName]);
163
+ if (!result.ok)
164
+ throw new Error(result.error);
165
+ }
166
+ export function createPasswordItem(title, value, vaultName) {
167
+ // op item create reads stdin templates only from a real pipe; spawnSync's
168
+ // input plumbing is detected as empty and op silently ignores the template.
169
+ // The supported alternative is --template <file>, which works reliably.
170
+ const template = JSON.stringify(buildPasswordItemTemplate(title, value));
171
+ const tmpFile = path.join(os.tmpdir(), `agents-op-tpl-${process.pid}-${Date.now()}.json`);
172
+ fs.writeFileSync(tmpFile, template, { mode: 0o600 });
173
+ try {
174
+ const result = runOp(['item', 'create', '--template', tmpFile, '--vault', vaultName]);
175
+ if (!result.ok)
176
+ throw new Error(result.error);
177
+ }
178
+ finally {
179
+ try {
180
+ fs.unlinkSync(tmpFile);
181
+ }
182
+ catch {
183
+ // best-effort cleanup
184
+ }
185
+ }
186
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Resolve base + name while preventing path-traversal attacks.
3
+ * Rejects path separators, null bytes, '.' and '..', and any resolved path
4
+ * that escapes the base directory. Dot-prefixed names like '.env.example'
5
+ * are allowed — actual traversal is caught by the containment check below.
6
+ * Allows spaces, unicode, and other common filename characters.
7
+ */
8
+ export declare function safeJoin(base: string, name: string): string;
@@ -0,0 +1,20 @@
1
+ import * as path from 'path';
2
+ /**
3
+ * Resolve base + name while preventing path-traversal attacks.
4
+ * Rejects path separators, null bytes, '.' and '..', and any resolved path
5
+ * that escapes the base directory. Dot-prefixed names like '.env.example'
6
+ * are allowed — actual traversal is caught by the containment check below.
7
+ * Allows spaces, unicode, and other common filename characters.
8
+ */
9
+ export function safeJoin(base, name) {
10
+ if (!name ||
11
+ name === '.' || name === '..' ||
12
+ /[\/\\\x00]/.test(name) ||
13
+ name.length > 255) {
14
+ throw new Error(`Invalid name: ${name}`);
15
+ }
16
+ const resolved = path.resolve(base, name);
17
+ if (!resolved.startsWith(path.resolve(base) + path.sep))
18
+ throw new Error(`Path escape: ${name}`);
19
+ return resolved;
20
+ }
@@ -1,9 +1,11 @@
1
1
  import type { AgentId, PermissionSet, InstalledPermission, ClaudePermissions, OpenCodePermissions, CodexPermissions } from './types.js';
2
+ /** Agents that support the permissions subsystem. */
2
3
  export declare const PERMISSIONS_CAPABLE_AGENTS: AgentId[];
4
+ /** Filename used for Codex Starlark deny-rules generated from permission groups. */
3
5
  export declare const CODEX_RULES_FILENAME = "agents-deny.rules";
4
6
  /**
5
7
  * Convert canonical deny rules to Codex Starlark .rules format.
6
- * E.g. "Bash(git reset:*)" prefix_rule(pattern=["git", "reset"], decision="forbidden")
8
+ * E.g. "Bash(git reset:*)" -> prefix_rule(pattern=["git", "reset"], decision="forbidden")
7
9
  */
8
10
  export declare function convertDenyToCodexRules(deny: string[]): string | null;
9
11
  /**
@@ -39,6 +41,27 @@ export declare function discoverPermissionGroups(): PermissionGroupInfo[];
39
41
  * Get total rule count across all permission groups.
40
42
  */
41
43
  export declare function getTotalPermissionRuleCount(): number;
44
+ /**
45
+ * A permission set recipe — names a set and lists which groups it composes.
46
+ * Lives at ~/.agents/permissions/sets/<name>.yaml.
47
+ */
48
+ export interface PermissionSetRecipe {
49
+ name: string;
50
+ description?: string;
51
+ includes: string[];
52
+ }
53
+ /** Env var that selects which set recipe to apply at sync time. */
54
+ export declare const PERMISSION_SET_ENV_VAR = "AGENTS_PERMISSION_SET";
55
+ /**
56
+ * Read a permission set recipe by name from ~/.agents/permissions/sets/.
57
+ * Returns null if the recipe file is missing or malformed.
58
+ */
59
+ export declare function readPermissionSetRecipe(name: string): PermissionSetRecipe | null;
60
+ /**
61
+ * Return the active permission set name from AGENTS_PERMISSION_SET env var,
62
+ * or null if unset. Caller decides the default behavior when null.
63
+ */
64
+ export declare function getActivePermissionSetName(): string | null;
42
65
  /**
43
66
  * Build a PermissionSet from selected groups.
44
67
  * Concatenates allow/deny rules from each group.
@@ -201,4 +224,3 @@ export declare function saveDefaultPermissionSet(set: PermissionSet): {
201
224
  success: boolean;
202
225
  error?: string;
203
226
  };
204
- //# sourceMappingURL=permissions.d.ts.map
@@ -1,17 +1,27 @@
1
+ /**
2
+ * Permission management for AI coding agents.
3
+ *
4
+ * Provides a canonical permission format (PermissionSet with allow/deny rules)
5
+ * and converters to/from each agent's native format (Claude settings.json,
6
+ * OpenCode opencode.jsonc, Codex config.toml + .rules). Handles discovery,
7
+ * installation, removal, and merging of permission groups stored in
8
+ * ~/.agents/permissions/groups/.
9
+ */
1
10
  import * as fs from 'fs';
2
11
  import * as path from 'path';
3
12
  import * as os from 'os';
4
13
  import * as yaml from 'yaml';
5
14
  import * as TOML from 'smol-toml';
6
- import { getPermissionsDir, ensureAgentsDir } from './state.js';
15
+ import { getPermissionsDir, getUserPermissionsDir, ensureAgentsDir } from './state.js';
16
+ import { safeJoin } from './paths.js';
7
17
  const HOME = os.homedir();
8
- // Agents that support permissions
18
+ /** Agents that support the permissions subsystem. */
9
19
  export const PERMISSIONS_CAPABLE_AGENTS = ['claude', 'codex', 'opencode'];
10
- // Codex .rules file name for deny permissions
20
+ /** Filename used for Codex Starlark deny-rules generated from permission groups. */
11
21
  export const CODEX_RULES_FILENAME = 'agents-deny.rules';
12
22
  /**
13
23
  * Convert canonical deny rules to Codex Starlark .rules format.
14
- * E.g. "Bash(git reset:*)" prefix_rule(pattern=["git", "reset"], decision="forbidden")
24
+ * E.g. "Bash(git reset:*)" -> prefix_rule(pattern=["git", "reset"], decision="forbidden")
15
25
  */
16
26
  export function convertDenyToCodexRules(deny) {
17
27
  const rules = [];
@@ -24,7 +34,7 @@ export function convertDenyToCodexRules(deny) {
24
34
  if (!command)
25
35
  continue;
26
36
  const parts = command.split(/\s+/);
27
- const patternStr = parts.map(p => `"${p}"`).join(', ');
37
+ const patternStr = parts.map(p => JSON.stringify(p)).join(', ');
28
38
  rules.push(`prefix_rule(\n pattern = [${patternStr}],\n decision = "forbidden",\n)`);
29
39
  }
30
40
  if (rules.length === 0)
@@ -35,7 +45,7 @@ export function convertDenyToCodexRules(deny) {
35
45
  * Ensure central permissions directory exists.
36
46
  */
37
47
  export function ensurePermissionsDir() {
38
- const dir = getPermissionsDir();
48
+ const dir = getUserPermissionsDir();
39
49
  if (!fs.existsSync(dir)) {
40
50
  fs.mkdirSync(dir, { recursive: true });
41
51
  }
@@ -108,38 +118,37 @@ export function discoverPermissionsFromRepo(repoPath) {
108
118
  * Returns groups with their rule counts.
109
119
  */
110
120
  export function discoverPermissionGroups() {
111
- const groupsDir = path.join(getPermissionsDir(), 'groups');
112
- if (!fs.existsSync(groupsDir)) {
113
- return [];
114
- }
121
+ const seen = new Set();
115
122
  const groups = [];
116
- try {
117
- const entries = fs.readdirSync(groupsDir, { withFileTypes: true });
118
- for (const entry of entries) {
119
- if (!entry.isFile())
120
- continue;
121
- if (!entry.name.endsWith('.yml') && !entry.name.endsWith('.yaml'))
122
- continue;
123
- const filePath = path.join(groupsDir, entry.name);
124
- const name = entry.name.replace(/\.(yaml|yml)$/, '');
125
- // Count rules in this group
126
- let ruleCount = 0;
127
- try {
128
- const content = fs.readFileSync(filePath, 'utf-8');
129
- // Count lines that look like permission entries (start with - " after optional whitespace)
130
- const matches = content.match(/^\s*-\s*"/gm);
131
- ruleCount = matches ? matches.length : 0;
132
- }
133
- catch {
134
- // Skip files we can't read
123
+ // Search user dir first, then system (user wins on name collision)
124
+ for (const baseDir of [getUserPermissionsDir(), getPermissionsDir()]) {
125
+ const groupsDir = path.join(baseDir, 'groups');
126
+ if (!fs.existsSync(groupsDir))
127
+ continue;
128
+ try {
129
+ const entries = fs.readdirSync(groupsDir, { withFileTypes: true });
130
+ for (const entry of entries) {
131
+ if (!entry.isFile())
132
+ continue;
133
+ if (!entry.name.endsWith('.yml') && !entry.name.endsWith('.yaml'))
134
+ continue;
135
+ const name = entry.name.replace(/\.(yaml|yml)$/, '');
136
+ if (seen.has(name))
137
+ continue;
138
+ seen.add(name);
139
+ const filePath = path.join(groupsDir, entry.name);
140
+ let ruleCount = 0;
141
+ try {
142
+ const content = fs.readFileSync(filePath, 'utf-8');
143
+ const matches = content.match(/^\s*-\s*"/gm);
144
+ ruleCount = matches ? matches.length : 0;
145
+ }
146
+ catch { /* Skip files we can't read */ }
147
+ groups.push({ name, ruleCount, path: filePath });
135
148
  }
136
- groups.push({ name, ruleCount, path: filePath });
137
149
  }
150
+ catch { /* Skip inaccessible directory */ }
138
151
  }
139
- catch {
140
- // Skip inaccessible directory
141
- }
142
- // Sort by name (which sorts by numeric prefix)
143
152
  return groups.sort((a, b) => a.name.localeCompare(b.name));
144
153
  }
145
154
  /**
@@ -149,6 +158,45 @@ export function getTotalPermissionRuleCount() {
149
158
  const groups = discoverPermissionGroups();
150
159
  return groups.reduce((sum, g) => sum + g.ruleCount, 0);
151
160
  }
161
+ /** Env var that selects which set recipe to apply at sync time. */
162
+ export const PERMISSION_SET_ENV_VAR = 'AGENTS_PERMISSION_SET';
163
+ /**
164
+ * Read a permission set recipe by name from ~/.agents/permissions/sets/.
165
+ * Returns null if the recipe file is missing or malformed.
166
+ */
167
+ export function readPermissionSetRecipe(name) {
168
+ const setsDir = path.join(getPermissionsDir(), 'sets');
169
+ for (const ext of ['.yaml', '.yml']) {
170
+ const filePath = safeJoin(setsDir, name + ext);
171
+ if (!fs.existsSync(filePath))
172
+ continue;
173
+ try {
174
+ const content = fs.readFileSync(filePath, 'utf-8');
175
+ const parsed = yaml.parse(content);
176
+ if (!parsed || typeof parsed !== 'object')
177
+ return null;
178
+ if (!Array.isArray(parsed.includes))
179
+ return null;
180
+ return {
181
+ name: parsed.name || name,
182
+ description: parsed.description,
183
+ includes: parsed.includes.filter((v) => typeof v === 'string'),
184
+ };
185
+ }
186
+ catch {
187
+ return null;
188
+ }
189
+ }
190
+ return null;
191
+ }
192
+ /**
193
+ * Return the active permission set name from AGENTS_PERMISSION_SET env var,
194
+ * or null if unset. Caller decides the default behavior when null.
195
+ */
196
+ export function getActivePermissionSetName() {
197
+ const v = process.env[PERMISSION_SET_ENV_VAR];
198
+ return v && v.trim() ? v.trim() : null;
199
+ }
152
200
  /**
153
201
  * Build a PermissionSet from selected groups.
154
202
  * Concatenates allow/deny rules from each group.
@@ -157,18 +205,25 @@ export function getTotalPermissionRuleCount() {
157
205
  * permission files often contain unescaped nested quotes that break YAML.
158
206
  */
159
207
  export function buildPermissionsFromGroups(groupNames) {
160
- const groupsDir = path.join(getPermissionsDir(), 'groups');
161
208
  const allAllow = [];
162
209
  const allDeny = [];
163
210
  for (const groupName of groupNames) {
164
- // Try both .yaml and .yml extensions
165
- let filePath = path.join(groupsDir, `${groupName}.yaml`);
166
- if (!fs.existsSync(filePath)) {
167
- filePath = path.join(groupsDir, `${groupName}.yml`);
211
+ // Search user dir first, then system dir
212
+ let filePath = null;
213
+ for (const baseDir of [getUserPermissionsDir(), getPermissionsDir()]) {
214
+ const groupsDir = path.join(baseDir, 'groups');
215
+ for (const ext of ['.yaml', '.yml']) {
216
+ const candidate = safeJoin(groupsDir, `${groupName}${ext}`);
217
+ if (fs.existsSync(candidate)) {
218
+ filePath = candidate;
219
+ break;
220
+ }
221
+ }
222
+ if (filePath)
223
+ break;
168
224
  }
169
- if (!fs.existsSync(filePath)) {
225
+ if (!filePath)
170
226
  continue;
171
- }
172
227
  try {
173
228
  const content = fs.readFileSync(filePath, 'utf-8');
174
229
  // Extract rules using line-by-line regex (more robust than YAML parsing)
@@ -241,7 +296,7 @@ export function listInstalledPermissions() {
241
296
  export function getPermissionSet(name) {
242
297
  const dir = getPermissionsDir();
243
298
  for (const ext of ['.yml', '.yaml']) {
244
- const filePath = path.join(dir, name + ext);
299
+ const filePath = safeJoin(dir, name + ext);
245
300
  if (fs.existsSync(filePath)) {
246
301
  const set = parsePermissionSet(filePath);
247
302
  if (set) {
@@ -260,7 +315,7 @@ export function installPermissionSet(sourcePath, name) {
260
315
  if (!set) {
261
316
  return { success: false, error: 'Invalid permission file' };
262
317
  }
263
- const targetPath = path.join(getPermissionsDir(), name + '.yml');
318
+ const targetPath = safeJoin(getPermissionsDir(), name + '.yml');
264
319
  try {
265
320
  fs.copyFileSync(sourcePath, targetPath);
266
321
  return { success: true };
@@ -275,7 +330,7 @@ export function installPermissionSet(sourcePath, name) {
275
330
  export function removePermissionSet(name) {
276
331
  const dir = getPermissionsDir();
277
332
  for (const ext of ['.yml', '.yaml']) {
278
- const filePath = path.join(dir, name + ext);
333
+ const filePath = safeJoin(dir, name + ext);
279
334
  if (fs.existsSync(filePath)) {
280
335
  try {
281
336
  fs.unlinkSync(filePath);
@@ -316,6 +371,8 @@ function parseCanonicalPattern(permission) {
316
371
  return null;
317
372
  return { tool: match[1].toLowerCase(), pattern: match[2] };
318
373
  }
374
+ /** Blanket-Bash canonical forms that mean "allow any bash command". */
375
+ const BLANKET_BASH_FORMS = new Set(['Bash', 'Bash(*)', 'Bash(**)']);
319
376
  /**
320
377
  * Convert canonical permission set to OpenCode format.
321
378
  * OpenCode uses: { permission: { bash: { "git *": "allow", "rm *": "deny" } } }
@@ -324,6 +381,12 @@ export function convertToOpenCodeFormat(set) {
324
381
  const bashPermissions = {};
325
382
  // Process allow list
326
383
  for (const perm of set.allow) {
384
+ if (BLANKET_BASH_FORMS.has(perm)) {
385
+ // Bare "Bash" has no parens so parseCanonicalPattern returns null;
386
+ // normalize all three blanket forms to "*".
387
+ bashPermissions['*'] = 'allow';
388
+ continue;
389
+ }
327
390
  const parsed = parseCanonicalPattern(perm);
328
391
  if (parsed && parsed.tool === 'bash') {
329
392
  bashPermissions[parsed.pattern] = 'allow';
@@ -350,10 +413,16 @@ export function convertToOpenCodeFormat(set) {
350
413
  */
351
414
  export function convertToCodexFormat(set, cwd) {
352
415
  const result = {};
353
- // Check for broad bash permissions -> suggest full-auto
416
+ // Check for broad bash permissions -> suggest full-auto.
417
+ // Treat the bare blanket form "Bash" the same as "Bash(*)" / "Bash(**)";
418
+ // parseCanonicalPattern requires parens so "Bash" alone wouldn't match
419
+ // otherwise — the difference determines whether a pod runs unattended
420
+ // (approval_policy: 'never') or stalls on interactive approvals.
354
421
  const hasBroadBash = set.allow.some((p) => {
422
+ if (BLANKET_BASH_FORMS.has(p))
423
+ return true;
355
424
  const parsed = parseCanonicalPattern(p);
356
- return parsed && parsed.tool === 'bash' && (parsed.pattern === '*' || parsed.pattern === '**');
425
+ return parsed !== null && parsed.tool === 'bash' && (parsed.pattern === '*' || parsed.pattern === '**');
357
426
  });
358
427
  if (hasBroadBash) {
359
428
  result.approval_policy = 'never';
@@ -946,7 +1015,7 @@ export function exportPermissionsFromPath(filePath) {
946
1015
  */
947
1016
  export function savePermissionSet(set) {
948
1017
  ensurePermissionsDir();
949
- const filePath = path.join(getPermissionsDir(), set.name + '.yml');
1018
+ const filePath = safeJoin(getUserPermissionsDir(), set.name + '.yml');
950
1019
  try {
951
1020
  const content = yaml.stringify({
952
1021
  name: set.name,
@@ -961,6 +1030,7 @@ export function savePermissionSet(set) {
961
1030
  return { success: false, error: err.message };
962
1031
  }
963
1032
  }
1033
+ /** Name used for the default permission set in central storage. */
964
1034
  const DEFAULT_PERMISSION_SET_NAME = 'default';
965
1035
  /**
966
1036
  * Get the default permission set from central storage.
@@ -1019,4 +1089,3 @@ export function saveDefaultPermissionSet(set) {
1019
1089
  set.name = DEFAULT_PERMISSION_SET_NAME;
1020
1090
  return savePermissionSet(set);
1021
1091
  }
1022
- //# sourceMappingURL=permissions.js.map
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Interactive fuzzy-filter picker built on @inquirer/core.
3
+ *
4
+ * Provides a searchable, paginated list UI with optional preview pane
5
+ * for selecting items in the terminal. Used by session picker, command
6
+ * picker, and other interactive selection flows.
7
+ */
8
+ /** Configuration for the interactive picker prompt. */
1
9
  export interface PickerConfig<T> {
2
10
  message: string;
3
11
  items: T[];
@@ -10,8 +18,9 @@ export interface PickerConfig<T> {
10
18
  emptyMessage?: string;
11
19
  enterHint?: string;
12
20
  }
21
+ /** The result returned when the user selects an item. */
13
22
  export interface PickedItem<T> {
14
23
  item: T;
15
24
  }
25
+ /** Show an interactive fuzzy-filter picker and return the selected item, or null on cancel. */
16
26
  export declare function itemPicker<T>(config: PickerConfig<T>): Promise<PickedItem<T> | null>;
17
- //# sourceMappingURL=picker.d.ts.map
@@ -1,5 +1,20 @@
1
+ /**
2
+ * Interactive fuzzy-filter picker built on @inquirer/core.
3
+ *
4
+ * Provides a searchable, paginated list UI with optional preview pane
5
+ * for selecting items in the terminal. Used by session picker, command
6
+ * picker, and other interactive selection flows.
7
+ */
8
+ /**
9
+ * Custom inquirer prompt for searchable, scrollable selection lists.
10
+ *
11
+ * Extends @inquirer/core to support type-ahead filtering, column-aligned
12
+ * display, and keyboard navigation. Used by sessions, teams, and other
13
+ * interactive pickers throughout the CLI.
14
+ */
1
15
  import { createPrompt, useState, useKeypress, useEffect, useMemo, usePagination, usePrefix, makeTheme, isEnterKey, isUpKey, isDownKey, isSpaceKey, Separator, } from '@inquirer/core';
2
16
  import chalk from 'chalk';
17
+ /** Show an interactive fuzzy-filter picker and return the selected item, or null on cancel. */
3
18
  export function itemPicker(config) {
4
19
  const prompt = createPrompt((cfg, done) => {
5
20
  const theme = makeTheme({});
@@ -92,4 +107,3 @@ export function itemPicker(config) {
92
107
  });
93
108
  return prompt(config);
94
109
  }
95
- //# sourceMappingURL=picker.js.map
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Plugin discovery, validation, and syncing.
3
+ *
4
+ * Plugins are bundles in ~/.agents/plugins/ that package skills, hooks, and
5
+ * scripts under a single manifest (plugin.yaml). This module discovers plugins,
6
+ * validates their manifests, and syncs their contents into agent version homes.
7
+ */
1
8
  import type { AgentId, DiscoveredPlugin, PluginManifest } from './types.js';
2
9
  /**
3
10
  * Discover all plugins in ~/.agents/plugins/.
@@ -70,4 +77,3 @@ export declare function removePluginFromVersion(pluginName: string, pluginRoot:
70
77
  * where the plugin no longer exists in ~/.agents/plugins/.
71
78
  */
72
79
  export declare function cleanOrphanedPluginSkills(agent: AgentId, versionHome: string, activePluginNames: Set<string>): string[];
73
- //# sourceMappingURL=plugins.d.ts.map
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Plugin discovery, validation, and syncing.
3
+ *
4
+ * Plugins are bundles in ~/.agents/plugins/ that package skills, hooks, and
5
+ * scripts under a single manifest (plugin.yaml). This module discovers plugins,
6
+ * validates their manifests, and syncs their contents into agent version homes.
7
+ */
1
8
  import * as fs from 'fs';
2
9
  import * as path from 'path';
3
10
  import { getPluginsDir } from './state.js';
@@ -46,6 +53,9 @@ export function loadPluginManifest(pluginRoot) {
46
53
  const parsed = JSON.parse(content);
47
54
  if (!parsed.name || !parsed.version)
48
55
  return null;
56
+ if (/[/\\]/.test(parsed.name) || parsed.name.includes('..') || parsed.name.includes('\0')) {
57
+ return null;
58
+ }
49
59
  return parsed;
50
60
  }
51
61
  catch {
@@ -546,4 +556,3 @@ export function cleanOrphanedPluginSkills(agent, versionHome, activePluginNames)
546
556
  }
547
557
  return removed;
548
558
  }
549
- //# sourceMappingURL=plugins.js.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Built-in profile presets for popular model providers.
3
+ *
4
+ * Each preset bundles a host CLI, API base URL, default model, and provider
5
+ * name so users can `agents profiles add kimi` without manual configuration.
6
+ */
7
+ import type { AgentId } from './types.js';
8
+ /** A pre-configured profile template for a model provider. */
9
+ export interface Preset {
10
+ name: string;
11
+ description: string;
12
+ provider: string;
13
+ host: AgentId;
14
+ env: Record<string, string>;
15
+ authEnvVar: string;
16
+ signupUrl?: string;
17
+ }
18
+ export declare const PRESETS: Preset[];
19
+ /** Look up a preset by name (case-sensitive). */
20
+ export declare function getPreset(name: string): Preset | undefined;
21
+ /** Return a copy of all available presets. */
22
+ export declare function listPresets(): Preset[];
23
+ /** Return the unique set of provider names across all presets. */
24
+ export declare function listProviders(): string[];