@phnx-labs/agents-cli 0.1.0

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 (486) hide show
  1. package/CHANGELOG.md +316 -0
  2. package/LICENSE +21 -0
  3. package/README.md +537 -0
  4. package/dist/commands/__tests__/sessions.test.d.ts +2 -0
  5. package/dist/commands/__tests__/sessions.test.d.ts.map +1 -0
  6. package/dist/commands/__tests__/sessions.test.js +636 -0
  7. package/dist/commands/__tests__/sessions.test.js.map +1 -0
  8. package/dist/commands/cloud.d.ts +3 -0
  9. package/dist/commands/cloud.d.ts.map +1 -0
  10. package/dist/commands/cloud.js +322 -0
  11. package/dist/commands/cloud.js.map +1 -0
  12. package/dist/commands/commands.d.ts +3 -0
  13. package/dist/commands/commands.d.ts.map +1 -0
  14. package/dist/commands/commands.js +628 -0
  15. package/dist/commands/commands.js.map +1 -0
  16. package/dist/commands/daemon.d.ts +3 -0
  17. package/dist/commands/daemon.d.ts.map +1 -0
  18. package/dist/commands/daemon.js +110 -0
  19. package/dist/commands/daemon.js.map +1 -0
  20. package/dist/commands/drive.d.ts +3 -0
  21. package/dist/commands/drive.d.ts.map +1 -0
  22. package/dist/commands/drive.js +166 -0
  23. package/dist/commands/drive.js.map +1 -0
  24. package/dist/commands/exec.d.ts +3 -0
  25. package/dist/commands/exec.d.ts.map +1 -0
  26. package/dist/commands/exec.js +241 -0
  27. package/dist/commands/exec.js.map +1 -0
  28. package/dist/commands/fork.d.ts +3 -0
  29. package/dist/commands/fork.d.ts.map +1 -0
  30. package/dist/commands/fork.js +139 -0
  31. package/dist/commands/fork.js.map +1 -0
  32. package/dist/commands/hooks.d.ts +3 -0
  33. package/dist/commands/hooks.d.ts.map +1 -0
  34. package/dist/commands/hooks.js +689 -0
  35. package/dist/commands/hooks.js.map +1 -0
  36. package/dist/commands/init.d.ts +6 -0
  37. package/dist/commands/init.d.ts.map +1 -0
  38. package/dist/commands/init.js +127 -0
  39. package/dist/commands/init.js.map +1 -0
  40. package/dist/commands/mcp.d.ts +3 -0
  41. package/dist/commands/mcp.d.ts.map +1 -0
  42. package/dist/commands/mcp.js +581 -0
  43. package/dist/commands/mcp.js.map +1 -0
  44. package/dist/commands/models.d.ts +3 -0
  45. package/dist/commands/models.d.ts.map +1 -0
  46. package/dist/commands/models.js +158 -0
  47. package/dist/commands/models.js.map +1 -0
  48. package/dist/commands/packages.d.ts +3 -0
  49. package/dist/commands/packages.d.ts.map +1 -0
  50. package/dist/commands/packages.js +541 -0
  51. package/dist/commands/packages.js.map +1 -0
  52. package/dist/commands/permissions.d.ts +3 -0
  53. package/dist/commands/permissions.d.ts.map +1 -0
  54. package/dist/commands/permissions.js +723 -0
  55. package/dist/commands/permissions.js.map +1 -0
  56. package/dist/commands/plugins.d.ts +3 -0
  57. package/dist/commands/plugins.d.ts.map +1 -0
  58. package/dist/commands/plugins.js +382 -0
  59. package/dist/commands/plugins.js.map +1 -0
  60. package/dist/commands/profiles.d.ts +3 -0
  61. package/dist/commands/profiles.d.ts.map +1 -0
  62. package/dist/commands/profiles.js +242 -0
  63. package/dist/commands/profiles.js.map +1 -0
  64. package/dist/commands/pty.d.ts +20 -0
  65. package/dist/commands/pty.d.ts.map +1 -0
  66. package/dist/commands/pty.js +389 -0
  67. package/dist/commands/pty.js.map +1 -0
  68. package/dist/commands/pull.d.ts +3 -0
  69. package/dist/commands/pull.d.ts.map +1 -0
  70. package/dist/commands/pull.js +448 -0
  71. package/dist/commands/pull.js.map +1 -0
  72. package/dist/commands/push.d.ts +3 -0
  73. package/dist/commands/push.d.ts.map +1 -0
  74. package/dist/commands/push.js +180 -0
  75. package/dist/commands/push.js.map +1 -0
  76. package/dist/commands/refresh-memory.d.ts +9 -0
  77. package/dist/commands/refresh-memory.d.ts.map +1 -0
  78. package/dist/commands/refresh-memory.js +45 -0
  79. package/dist/commands/refresh-memory.js.map +1 -0
  80. package/dist/commands/resource-view.d.ts +31 -0
  81. package/dist/commands/resource-view.d.ts.map +1 -0
  82. package/dist/commands/resource-view.js +183 -0
  83. package/dist/commands/resource-view.js.map +1 -0
  84. package/dist/commands/routines.d.ts +3 -0
  85. package/dist/commands/routines.d.ts.map +1 -0
  86. package/dist/commands/routines.js +579 -0
  87. package/dist/commands/routines.js.map +1 -0
  88. package/dist/commands/rules.d.ts +3 -0
  89. package/dist/commands/rules.d.ts.map +1 -0
  90. package/dist/commands/rules.js +488 -0
  91. package/dist/commands/rules.js.map +1 -0
  92. package/dist/commands/secrets.d.ts +3 -0
  93. package/dist/commands/secrets.d.ts.map +1 -0
  94. package/dist/commands/secrets.js +339 -0
  95. package/dist/commands/secrets.js.map +1 -0
  96. package/dist/commands/sessions-picker.d.ts +16 -0
  97. package/dist/commands/sessions-picker.d.ts.map +1 -0
  98. package/dist/commands/sessions-picker.js +256 -0
  99. package/dist/commands/sessions-picker.js.map +1 -0
  100. package/dist/commands/sessions.d.ts +16 -0
  101. package/dist/commands/sessions.d.ts.map +1 -0
  102. package/dist/commands/sessions.js +1077 -0
  103. package/dist/commands/sessions.js.map +1 -0
  104. package/dist/commands/skills.d.ts +3 -0
  105. package/dist/commands/skills.d.ts.map +1 -0
  106. package/dist/commands/skills.js +716 -0
  107. package/dist/commands/skills.js.map +1 -0
  108. package/dist/commands/status.d.ts +3 -0
  109. package/dist/commands/status.d.ts.map +1 -0
  110. package/dist/commands/status.js +19 -0
  111. package/dist/commands/status.js.map +1 -0
  112. package/dist/commands/subagents.d.ts +3 -0
  113. package/dist/commands/subagents.d.ts.map +1 -0
  114. package/dist/commands/subagents.js +350 -0
  115. package/dist/commands/subagents.js.map +1 -0
  116. package/dist/commands/sync.d.ts +3 -0
  117. package/dist/commands/sync.d.ts.map +1 -0
  118. package/dist/commands/sync.js +62 -0
  119. package/dist/commands/sync.js.map +1 -0
  120. package/dist/commands/teams-picker.d.ts +14 -0
  121. package/dist/commands/teams-picker.d.ts.map +1 -0
  122. package/dist/commands/teams-picker.js +278 -0
  123. package/dist/commands/teams-picker.js.map +1 -0
  124. package/dist/commands/teams.d.ts +3 -0
  125. package/dist/commands/teams.d.ts.map +1 -0
  126. package/dist/commands/teams.js +917 -0
  127. package/dist/commands/teams.js.map +1 -0
  128. package/dist/commands/utils.d.ts +39 -0
  129. package/dist/commands/utils.d.ts.map +1 -0
  130. package/dist/commands/utils.js +100 -0
  131. package/dist/commands/utils.js.map +1 -0
  132. package/dist/commands/versions.d.ts +3 -0
  133. package/dist/commands/versions.d.ts.map +1 -0
  134. package/dist/commands/versions.js +700 -0
  135. package/dist/commands/versions.js.map +1 -0
  136. package/dist/commands/view.d.ts +8 -0
  137. package/dist/commands/view.d.ts.map +1 -0
  138. package/dist/commands/view.js +626 -0
  139. package/dist/commands/view.js.map +1 -0
  140. package/dist/index.d.ts +3 -0
  141. package/dist/index.d.ts.map +1 -0
  142. package/dist/index.js +484 -0
  143. package/dist/index.js.map +1 -0
  144. package/dist/lib/__tests__/bugfixes.test.d.ts +2 -0
  145. package/dist/lib/__tests__/bugfixes.test.d.ts.map +1 -0
  146. package/dist/lib/__tests__/bugfixes.test.js +192 -0
  147. package/dist/lib/__tests__/bugfixes.test.js.map +1 -0
  148. package/dist/lib/__tests__/exec.test.d.ts +2 -0
  149. package/dist/lib/__tests__/exec.test.d.ts.map +1 -0
  150. package/dist/lib/__tests__/exec.test.js +446 -0
  151. package/dist/lib/__tests__/exec.test.js.map +1 -0
  152. package/dist/lib/__tests__/git-sync.test.d.ts +2 -0
  153. package/dist/lib/__tests__/git-sync.test.d.ts.map +1 -0
  154. package/dist/lib/__tests__/git-sync.test.js +138 -0
  155. package/dist/lib/__tests__/git-sync.test.js.map +1 -0
  156. package/dist/lib/__tests__/hooks.test.d.ts +2 -0
  157. package/dist/lib/__tests__/hooks.test.d.ts.map +1 -0
  158. package/dist/lib/__tests__/hooks.test.js +203 -0
  159. package/dist/lib/__tests__/hooks.test.js.map +1 -0
  160. package/dist/lib/__tests__/memory-compile.test.d.ts +2 -0
  161. package/dist/lib/__tests__/memory-compile.test.d.ts.map +1 -0
  162. package/dist/lib/__tests__/memory-compile.test.js +95 -0
  163. package/dist/lib/__tests__/memory-compile.test.js.map +1 -0
  164. package/dist/lib/__tests__/models.test.d.ts +2 -0
  165. package/dist/lib/__tests__/models.test.d.ts.map +1 -0
  166. package/dist/lib/__tests__/models.test.js +239 -0
  167. package/dist/lib/__tests__/models.test.js.map +1 -0
  168. package/dist/lib/__tests__/rotate.test.d.ts +2 -0
  169. package/dist/lib/__tests__/rotate.test.d.ts.map +1 -0
  170. package/dist/lib/__tests__/rotate.test.js +80 -0
  171. package/dist/lib/__tests__/rotate.test.js.map +1 -0
  172. package/dist/lib/__tests__/secrets-bundles.test.d.ts +2 -0
  173. package/dist/lib/__tests__/secrets-bundles.test.d.ts.map +1 -0
  174. package/dist/lib/__tests__/secrets-bundles.test.js +104 -0
  175. package/dist/lib/__tests__/secrets-bundles.test.js.map +1 -0
  176. package/dist/lib/__tests__/secrets.test.d.ts +2 -0
  177. package/dist/lib/__tests__/secrets.test.d.ts.map +1 -0
  178. package/dist/lib/__tests__/secrets.test.js +90 -0
  179. package/dist/lib/__tests__/secrets.test.js.map +1 -0
  180. package/dist/lib/__tests__/shims.test.d.ts +2 -0
  181. package/dist/lib/__tests__/shims.test.d.ts.map +1 -0
  182. package/dist/lib/__tests__/shims.test.js +39 -0
  183. package/dist/lib/__tests__/shims.test.js.map +1 -0
  184. package/dist/lib/__tests__/usage.test.d.ts +2 -0
  185. package/dist/lib/__tests__/usage.test.d.ts.map +1 -0
  186. package/dist/lib/__tests__/usage.test.js +220 -0
  187. package/dist/lib/__tests__/usage.test.js.map +1 -0
  188. package/dist/lib/__tests__/versions.test.d.ts +2 -0
  189. package/dist/lib/__tests__/versions.test.d.ts.map +1 -0
  190. package/dist/lib/__tests__/versions.test.js +63 -0
  191. package/dist/lib/__tests__/versions.test.js.map +1 -0
  192. package/dist/lib/agents.d.ts +107 -0
  193. package/dist/lib/agents.d.ts.map +1 -0
  194. package/dist/lib/agents.js +1096 -0
  195. package/dist/lib/agents.js.map +1 -0
  196. package/dist/lib/artifact-actions.d.ts +22 -0
  197. package/dist/lib/artifact-actions.d.ts.map +1 -0
  198. package/dist/lib/artifact-actions.js +55 -0
  199. package/dist/lib/artifact-actions.js.map +1 -0
  200. package/dist/lib/cloud/codex.d.ts +19 -0
  201. package/dist/lib/cloud/codex.d.ts.map +1 -0
  202. package/dist/lib/cloud/codex.js +210 -0
  203. package/dist/lib/cloud/codex.js.map +1 -0
  204. package/dist/lib/cloud/factory.d.ts +26 -0
  205. package/dist/lib/cloud/factory.d.ts.map +1 -0
  206. package/dist/lib/cloud/factory.js +37 -0
  207. package/dist/lib/cloud/factory.js.map +1 -0
  208. package/dist/lib/cloud/registry.d.ts +6 -0
  209. package/dist/lib/cloud/registry.d.ts.map +1 -0
  210. package/dist/lib/cloud/registry.js +56 -0
  211. package/dist/lib/cloud/registry.js.map +1 -0
  212. package/dist/lib/cloud/rush.d.ts +15 -0
  213. package/dist/lib/cloud/rush.d.ts.map +1 -0
  214. package/dist/lib/cloud/rush.js +185 -0
  215. package/dist/lib/cloud/rush.js.map +1 -0
  216. package/dist/lib/cloud/store.d.ts +10 -0
  217. package/dist/lib/cloud/store.d.ts.map +1 -0
  218. package/dist/lib/cloud/store.js +96 -0
  219. package/dist/lib/cloud/store.js.map +1 -0
  220. package/dist/lib/cloud/stream.d.ts +18 -0
  221. package/dist/lib/cloud/stream.d.ts.map +1 -0
  222. package/dist/lib/cloud/stream.js +138 -0
  223. package/dist/lib/cloud/stream.js.map +1 -0
  224. package/dist/lib/cloud/types.d.ts +60 -0
  225. package/dist/lib/cloud/types.d.ts.map +1 -0
  226. package/dist/lib/cloud/types.js +2 -0
  227. package/dist/lib/cloud/types.js.map +1 -0
  228. package/dist/lib/commands.d.ts +121 -0
  229. package/dist/lib/commands.d.ts.map +1 -0
  230. package/dist/lib/commands.js +499 -0
  231. package/dist/lib/commands.js.map +1 -0
  232. package/dist/lib/convert.d.ts +11 -0
  233. package/dist/lib/convert.d.ts.map +1 -0
  234. package/dist/lib/convert.js +45 -0
  235. package/dist/lib/convert.js.map +1 -0
  236. package/dist/lib/daemon.d.ts +22 -0
  237. package/dist/lib/daemon.d.ts.map +1 -0
  238. package/dist/lib/daemon.js +311 -0
  239. package/dist/lib/daemon.js.map +1 -0
  240. package/dist/lib/drive-sync.d.ts +28 -0
  241. package/dist/lib/drive-sync.d.ts.map +1 -0
  242. package/dist/lib/drive-sync.js +193 -0
  243. package/dist/lib/drive-sync.js.map +1 -0
  244. package/dist/lib/exec.d.ts +85 -0
  245. package/dist/lib/exec.d.ts.map +1 -0
  246. package/dist/lib/exec.js +423 -0
  247. package/dist/lib/exec.js.map +1 -0
  248. package/dist/lib/factory.d.ts +57 -0
  249. package/dist/lib/factory.d.ts.map +1 -0
  250. package/dist/lib/factory.js +110 -0
  251. package/dist/lib/factory.js.map +1 -0
  252. package/dist/lib/git.d.ts +146 -0
  253. package/dist/lib/git.d.ts.map +1 -0
  254. package/dist/lib/git.js +635 -0
  255. package/dist/lib/git.js.map +1 -0
  256. package/dist/lib/help.d.ts +3 -0
  257. package/dist/lib/help.d.ts.map +1 -0
  258. package/dist/lib/help.js +63 -0
  259. package/dist/lib/help.js.map +1 -0
  260. package/dist/lib/hooks.d.ts +116 -0
  261. package/dist/lib/hooks.d.ts.map +1 -0
  262. package/dist/lib/hooks.js +837 -0
  263. package/dist/lib/hooks.js.map +1 -0
  264. package/dist/lib/manifest.d.ts +8 -0
  265. package/dist/lib/manifest.d.ts.map +1 -0
  266. package/dist/lib/manifest.js +36 -0
  267. package/dist/lib/manifest.js.map +1 -0
  268. package/dist/lib/markdown.d.ts +5 -0
  269. package/dist/lib/markdown.d.ts.map +1 -0
  270. package/dist/lib/markdown.js +11 -0
  271. package/dist/lib/markdown.js.map +1 -0
  272. package/dist/lib/mcp.d.ts +64 -0
  273. package/dist/lib/mcp.d.ts.map +1 -0
  274. package/dist/lib/mcp.js +327 -0
  275. package/dist/lib/mcp.js.map +1 -0
  276. package/dist/lib/memory-compile.d.ts +56 -0
  277. package/dist/lib/memory-compile.d.ts.map +1 -0
  278. package/dist/lib/memory-compile.js +167 -0
  279. package/dist/lib/memory-compile.js.map +1 -0
  280. package/dist/lib/memory.d.ts +56 -0
  281. package/dist/lib/memory.d.ts.map +1 -0
  282. package/dist/lib/memory.js +267 -0
  283. package/dist/lib/memory.js.map +1 -0
  284. package/dist/lib/models.d.ts +91 -0
  285. package/dist/lib/models.d.ts.map +1 -0
  286. package/dist/lib/models.js +706 -0
  287. package/dist/lib/models.js.map +1 -0
  288. package/dist/lib/permissions.d.ts +204 -0
  289. package/dist/lib/permissions.d.ts.map +1 -0
  290. package/dist/lib/permissions.js +1022 -0
  291. package/dist/lib/permissions.js.map +1 -0
  292. package/dist/lib/picker.d.ts +17 -0
  293. package/dist/lib/picker.d.ts.map +1 -0
  294. package/dist/lib/picker.js +95 -0
  295. package/dist/lib/picker.js.map +1 -0
  296. package/dist/lib/plugins.d.ts +73 -0
  297. package/dist/lib/plugins.d.ts.map +1 -0
  298. package/dist/lib/plugins.js +549 -0
  299. package/dist/lib/plugins.js.map +1 -0
  300. package/dist/lib/profiles-keychain.d.ts +3 -0
  301. package/dist/lib/profiles-keychain.d.ts.map +1 -0
  302. package/dist/lib/profiles-keychain.js +10 -0
  303. package/dist/lib/profiles-keychain.js.map +1 -0
  304. package/dist/lib/profiles-presets.d.ts +15 -0
  305. package/dist/lib/profiles-presets.d.ts.map +1 -0
  306. package/dist/lib/profiles-presets.js +95 -0
  307. package/dist/lib/profiles-presets.js.map +1 -0
  308. package/dist/lib/profiles.d.ts +35 -0
  309. package/dist/lib/profiles.d.ts.map +1 -0
  310. package/dist/lib/profiles.js +123 -0
  311. package/dist/lib/profiles.js.map +1 -0
  312. package/dist/lib/pty-client.d.ts +22 -0
  313. package/dist/lib/pty-client.d.ts.map +1 -0
  314. package/dist/lib/pty-client.js +181 -0
  315. package/dist/lib/pty-client.js.map +1 -0
  316. package/dist/lib/pty-server.d.ts +16 -0
  317. package/dist/lib/pty-server.d.ts.map +1 -0
  318. package/dist/lib/pty-server.js +422 -0
  319. package/dist/lib/pty-server.js.map +1 -0
  320. package/dist/lib/registry.d.ts +28 -0
  321. package/dist/lib/registry.d.ts.map +1 -0
  322. package/dist/lib/registry.js +203 -0
  323. package/dist/lib/registry.js.map +1 -0
  324. package/dist/lib/resources.d.ts +50 -0
  325. package/dist/lib/resources.d.ts.map +1 -0
  326. package/dist/lib/resources.js +103 -0
  327. package/dist/lib/resources.js.map +1 -0
  328. package/dist/lib/rotate.d.ts +52 -0
  329. package/dist/lib/rotate.d.ts.map +1 -0
  330. package/dist/lib/rotate.js +87 -0
  331. package/dist/lib/rotate.js.map +1 -0
  332. package/dist/lib/routines.d.ts +70 -0
  333. package/dist/lib/routines.d.ts.map +1 -0
  334. package/dist/lib/routines.js +325 -0
  335. package/dist/lib/routines.js.map +1 -0
  336. package/dist/lib/runner.d.ts +12 -0
  337. package/dist/lib/runner.d.ts.map +1 -0
  338. package/dist/lib/runner.js +311 -0
  339. package/dist/lib/runner.js.map +1 -0
  340. package/dist/lib/sandbox.d.ts +10 -0
  341. package/dist/lib/sandbox.d.ts.map +1 -0
  342. package/dist/lib/sandbox.js +201 -0
  343. package/dist/lib/sandbox.js.map +1 -0
  344. package/dist/lib/scheduler.d.ts +18 -0
  345. package/dist/lib/scheduler.d.ts.map +1 -0
  346. package/dist/lib/scheduler.js +69 -0
  347. package/dist/lib/scheduler.js.map +1 -0
  348. package/dist/lib/secrets-bundles.d.ts +29 -0
  349. package/dist/lib/secrets-bundles.d.ts.map +1 -0
  350. package/dist/lib/secrets-bundles.js +168 -0
  351. package/dist/lib/secrets-bundles.js.map +1 -0
  352. package/dist/lib/secrets.d.ts +27 -0
  353. package/dist/lib/secrets.d.ts.map +1 -0
  354. package/dist/lib/secrets.js +127 -0
  355. package/dist/lib/secrets.js.map +1 -0
  356. package/dist/lib/session/__tests__/db.test.d.ts +2 -0
  357. package/dist/lib/session/__tests__/db.test.d.ts.map +1 -0
  358. package/dist/lib/session/__tests__/db.test.js +54 -0
  359. package/dist/lib/session/__tests__/db.test.js.map +1 -0
  360. package/dist/lib/session/__tests__/discover.test.d.ts +2 -0
  361. package/dist/lib/session/__tests__/discover.test.d.ts.map +1 -0
  362. package/dist/lib/session/__tests__/discover.test.js +63 -0
  363. package/dist/lib/session/__tests__/discover.test.js.map +1 -0
  364. package/dist/lib/session/__tests__/prompt.test.d.ts +2 -0
  365. package/dist/lib/session/__tests__/prompt.test.d.ts.map +1 -0
  366. package/dist/lib/session/__tests__/prompt.test.js +44 -0
  367. package/dist/lib/session/__tests__/prompt.test.js.map +1 -0
  368. package/dist/lib/session/__tests__/render.test.d.ts +2 -0
  369. package/dist/lib/session/__tests__/render.test.d.ts.map +1 -0
  370. package/dist/lib/session/__tests__/render.test.js +602 -0
  371. package/dist/lib/session/__tests__/render.test.js.map +1 -0
  372. package/dist/lib/session/artifacts.d.ts +5 -0
  373. package/dist/lib/session/artifacts.d.ts.map +1 -0
  374. package/dist/lib/session/artifacts.js +75 -0
  375. package/dist/lib/session/artifacts.js.map +1 -0
  376. package/dist/lib/session/db.d.ts +118 -0
  377. package/dist/lib/session/db.d.ts.map +1 -0
  378. package/dist/lib/session/db.js +576 -0
  379. package/dist/lib/session/db.js.map +1 -0
  380. package/dist/lib/session/discover.d.ts +60 -0
  381. package/dist/lib/session/discover.d.ts.map +1 -0
  382. package/dist/lib/session/discover.js +1272 -0
  383. package/dist/lib/session/discover.js.map +1 -0
  384. package/dist/lib/session/parse.d.ts +23 -0
  385. package/dist/lib/session/parse.d.ts.map +1 -0
  386. package/dist/lib/session/parse.js +650 -0
  387. package/dist/lib/session/parse.js.map +1 -0
  388. package/dist/lib/session/prompt.d.ts +4 -0
  389. package/dist/lib/session/prompt.d.ts.map +1 -0
  390. package/dist/lib/session/prompt.js +64 -0
  391. package/dist/lib/session/prompt.js.map +1 -0
  392. package/dist/lib/session/prompt.test.d.ts +2 -0
  393. package/dist/lib/session/prompt.test.d.ts.map +1 -0
  394. package/dist/lib/session/prompt.test.js +57 -0
  395. package/dist/lib/session/prompt.test.js.map +1 -0
  396. package/dist/lib/session/render.d.ts +90 -0
  397. package/dist/lib/session/render.d.ts.map +1 -0
  398. package/dist/lib/session/render.js +778 -0
  399. package/dist/lib/session/render.js.map +1 -0
  400. package/dist/lib/session/team-filter.d.ts +26 -0
  401. package/dist/lib/session/team-filter.d.ts.map +1 -0
  402. package/dist/lib/session/team-filter.js +66 -0
  403. package/dist/lib/session/team-filter.js.map +1 -0
  404. package/dist/lib/session/team-filter.test.d.ts +2 -0
  405. package/dist/lib/session/team-filter.test.d.ts.map +1 -0
  406. package/dist/lib/session/team-filter.test.js +157 -0
  407. package/dist/lib/session/team-filter.test.js.map +1 -0
  408. package/dist/lib/session/types.d.ts +69 -0
  409. package/dist/lib/session/types.d.ts.map +1 -0
  410. package/dist/lib/session/types.js +2 -0
  411. package/dist/lib/session/types.js.map +1 -0
  412. package/dist/lib/shims.d.ts +228 -0
  413. package/dist/lib/shims.d.ts.map +1 -0
  414. package/dist/lib/shims.js +1170 -0
  415. package/dist/lib/shims.js.map +1 -0
  416. package/dist/lib/skills.d.ts +134 -0
  417. package/dist/lib/skills.d.ts.map +1 -0
  418. package/dist/lib/skills.js +783 -0
  419. package/dist/lib/skills.js.map +1 -0
  420. package/dist/lib/state.d.ts +53 -0
  421. package/dist/lib/state.d.ts.map +1 -0
  422. package/dist/lib/state.js +299 -0
  423. package/dist/lib/state.js.map +1 -0
  424. package/dist/lib/subagents.d.ts +75 -0
  425. package/dist/lib/subagents.d.ts.map +1 -0
  426. package/dist/lib/subagents.js +402 -0
  427. package/dist/lib/subagents.js.map +1 -0
  428. package/dist/lib/teams/agents.d.ts +146 -0
  429. package/dist/lib/teams/agents.d.ts.map +1 -0
  430. package/dist/lib/teams/agents.js +1072 -0
  431. package/dist/lib/teams/agents.js.map +1 -0
  432. package/dist/lib/teams/api.d.ts +77 -0
  433. package/dist/lib/teams/api.d.ts.map +1 -0
  434. package/dist/lib/teams/api.js +229 -0
  435. package/dist/lib/teams/api.js.map +1 -0
  436. package/dist/lib/teams/cloud.d.ts +11 -0
  437. package/dist/lib/teams/cloud.d.ts.map +1 -0
  438. package/dist/lib/teams/cloud.js +169 -0
  439. package/dist/lib/teams/cloud.js.map +1 -0
  440. package/dist/lib/teams/debug.d.ts +2 -0
  441. package/dist/lib/teams/debug.d.ts.map +1 -0
  442. package/dist/lib/teams/debug.js +6 -0
  443. package/dist/lib/teams/debug.js.map +1 -0
  444. package/dist/lib/teams/file_ops.d.ts +6 -0
  445. package/dist/lib/teams/file_ops.d.ts.map +1 -0
  446. package/dist/lib/teams/file_ops.js +59 -0
  447. package/dist/lib/teams/file_ops.js.map +1 -0
  448. package/dist/lib/teams/parsers.d.ts +5 -0
  449. package/dist/lib/teams/parsers.d.ts.map +1 -0
  450. package/dist/lib/teams/parsers.js +826 -0
  451. package/dist/lib/teams/parsers.js.map +1 -0
  452. package/dist/lib/teams/persistence.d.ts +28 -0
  453. package/dist/lib/teams/persistence.d.ts.map +1 -0
  454. package/dist/lib/teams/persistence.js +289 -0
  455. package/dist/lib/teams/persistence.js.map +1 -0
  456. package/dist/lib/teams/ralph.d.ts +8 -0
  457. package/dist/lib/teams/ralph.d.ts.map +1 -0
  458. package/dist/lib/teams/ralph.js +59 -0
  459. package/dist/lib/teams/ralph.js.map +1 -0
  460. package/dist/lib/teams/registry.d.ts +11 -0
  461. package/dist/lib/teams/registry.d.ts.map +1 -0
  462. package/dist/lib/teams/registry.js +56 -0
  463. package/dist/lib/teams/registry.js.map +1 -0
  464. package/dist/lib/teams/summarizer.d.ts +58 -0
  465. package/dist/lib/teams/summarizer.d.ts.map +1 -0
  466. package/dist/lib/teams/summarizer.js +766 -0
  467. package/dist/lib/teams/summarizer.js.map +1 -0
  468. package/dist/lib/template.d.ts +24 -0
  469. package/dist/lib/template.d.ts.map +1 -0
  470. package/dist/lib/template.js +57 -0
  471. package/dist/lib/template.js.map +1 -0
  472. package/dist/lib/types.d.ts +282 -0
  473. package/dist/lib/types.d.ts.map +1 -0
  474. package/dist/lib/types.js +18 -0
  475. package/dist/lib/types.js.map +1 -0
  476. package/dist/lib/usage.d.ts +73 -0
  477. package/dist/lib/usage.d.ts.map +1 -0
  478. package/dist/lib/usage.js +623 -0
  479. package/dist/lib/usage.js.map +1 -0
  480. package/dist/lib/versions.d.ts +248 -0
  481. package/dist/lib/versions.d.ts.map +1 -0
  482. package/dist/lib/versions.js +1737 -0
  483. package/dist/lib/versions.js.map +1 -0
  484. package/package.json +82 -0
  485. package/scripts/postinstall.js +72 -0
  486. package/scripts/rebuild-sqlite.sh +46 -0
@@ -0,0 +1,1170 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { confirm, select } from '@inquirer/prompts';
5
+ import { getShimsDir, getVersionsDir, getBackupsDir, ensureAgentsDir } from './state.js';
6
+ export { getShimsDir };
7
+ import { AGENTS } from './agents.js';
8
+ /**
9
+ * Files and directories to always skip during conflict detection and migration.
10
+ * These are never user config that should be migrated.
11
+ */
12
+ const MIGRATION_IGNORE_LIST = new Set([
13
+ 'node_modules',
14
+ '.git',
15
+ 'bun.lock',
16
+ 'bun.lockb',
17
+ 'package-lock.json',
18
+ 'yarn.lock',
19
+ 'pnpm-lock.yaml',
20
+ '.DS_Store',
21
+ 'Thumbs.db',
22
+ ]);
23
+ /**
24
+ * Check if a file/directory should be ignored during migration.
25
+ */
26
+ function shouldIgnore(name) {
27
+ if (MIGRATION_IGNORE_LIST.has(name))
28
+ return true;
29
+ if (name.endsWith('.backup'))
30
+ return true;
31
+ return false;
32
+ }
33
+ /**
34
+ * Detect conflicting files between source and destination directories.
35
+ * Returns list of filenames that exist in both locations (excluding symlinks in dest).
36
+ */
37
+ export function detectConflicts(src, dest, prefix = '') {
38
+ const conflicts = [];
39
+ if (!fs.existsSync(src) || !fs.existsSync(dest)) {
40
+ return conflicts;
41
+ }
42
+ // Skip if dest is a symlink (managed resources)
43
+ try {
44
+ const destStat = fs.lstatSync(dest);
45
+ if (destStat.isSymbolicLink()) {
46
+ return conflicts;
47
+ }
48
+ }
49
+ catch {
50
+ /* dest not accessible, no conflicts to report */
51
+ return conflicts;
52
+ }
53
+ const entries = fs.readdirSync(src, { withFileTypes: true });
54
+ for (const entry of entries) {
55
+ // Skip files/directories that should never be migrated
56
+ if (shouldIgnore(entry.name)) {
57
+ continue;
58
+ }
59
+ const srcPath = path.join(src, entry.name);
60
+ const destPath = path.join(dest, entry.name);
61
+ const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
62
+ // Skip if dest entry is a symlink (managed resource)
63
+ try {
64
+ const entryDestStat = fs.lstatSync(destPath);
65
+ if (entryDestStat.isSymbolicLink()) {
66
+ continue;
67
+ }
68
+ if (entry.isDirectory()) {
69
+ // Recurse into subdirectories
70
+ conflicts.push(...detectConflicts(srcPath, destPath, relativePath));
71
+ }
72
+ else {
73
+ // File exists in both - it's a conflict
74
+ conflicts.push(relativePath);
75
+ }
76
+ }
77
+ catch {
78
+ // dest entry doesn't exist, not a conflict
79
+ }
80
+ }
81
+ return conflicts;
82
+ }
83
+ /**
84
+ * Prompt user for conflict resolution strategy.
85
+ */
86
+ export async function promptConflictStrategy(conflictInfos) {
87
+ const totalConflicts = conflictInfos.reduce((sum, info) => sum + info.conflicts.length, 0);
88
+ if (totalConflicts === 0) {
89
+ return null; // No conflicts, no prompt needed
90
+ }
91
+ // Show what has conflicts with clear paths
92
+ console.log('\nFile conflicts detected:');
93
+ for (const info of conflictInfos) {
94
+ const agentConfig = AGENTS[info.agent];
95
+ const configDir = agentConfig.configDir; // e.g., ".opencode"
96
+ console.log(` ${info.conflicts.length} file(s) conflict between:`);
97
+ console.log(` ~/${configDir}/ (your config)`);
98
+ console.log(` ${agentConfig.name}@${info.version} (managed version)`);
99
+ }
100
+ console.log();
101
+ // Build choice labels with agent info for clarity
102
+ const firstInfo = conflictInfos[0];
103
+ const firstAgent = AGENTS[firstInfo.agent];
104
+ const versionLabel = conflictInfos.length === 1
105
+ ? `${firstAgent.name}@${firstInfo.version}`
106
+ : 'version';
107
+ const strategy = await select({
108
+ message: 'Which files should be kept?',
109
+ choices: [
110
+ {
111
+ value: 'keep-dest',
112
+ name: `Keep ${versionLabel} files (recommended)`,
113
+ },
114
+ {
115
+ value: 'overwrite',
116
+ name: conflictInfos.length === 1
117
+ ? `Keep ~/${firstAgent.configDir}/ files`
118
+ : 'Keep my config files',
119
+ },
120
+ {
121
+ value: 'ask-per-file',
122
+ name: `Decide per file (${totalConflicts} file${totalConflicts === 1 ? '' : 's'})`,
123
+ },
124
+ ],
125
+ default: 'keep-dest',
126
+ });
127
+ return strategy;
128
+ }
129
+ /**
130
+ * Generate the shim script content for an agent.
131
+ *
132
+ * The shim resolves the version in order:
133
+ * 1. agents.yaml in project root (walk up from $PWD, skip ~/.agents/agents.yaml)
134
+ * 2. ~/.agents/agents.yaml default
135
+ *
136
+ * If version is specified but not installed, auto-installs it.
137
+ *
138
+ * Config isolation is handled via symlinks:
139
+ * ~/.{agent} -> ~/.agents/versions/{agent}/{version}/home/.{agent}/
140
+ */
141
+ /**
142
+ * Current shim schema version. Bump whenever `generateShimScript` changes
143
+ * in a way that requires existing on-disk shims to be regenerated (new
144
+ * flags, fixed argument parsing, new hooks, etc.). `isShimCurrent` reads
145
+ * this marker out of existing shims to decide whether to regenerate.
146
+ *
147
+ * History:
148
+ * v1 — initial shim (implicit, no marker).
149
+ * v2 — `--version=...` form in sync/refresh-memory calls; refresh-memory
150
+ * shim hook for non-@-capable agents.
151
+ * v3 — sync/refresh-memory flag renamed `--version` → `--agent-version`
152
+ * so it no longer collides with commander's top-level `--version`.
153
+ * v4 — project version marker changed from `.agents-version` to a
154
+ * root-level `agents.yaml`; shim now skips ~/.agents/agents.yaml
155
+ * when walking up for a project marker.
156
+ */
157
+ export const SHIM_SCHEMA_VERSION = 4;
158
+ const SHIM_VERSION_MARKER = 'agents-shim-version:';
159
+ export function generateShimScript(agent) {
160
+ const agentConfig = AGENTS[agent];
161
+ const cliCommand = agentConfig.cliCommand;
162
+ const configDirName = `.${agent}`;
163
+ const managedEnv = agent === 'claude'
164
+ ? `
165
+ # Claude stores OAuth credentials in the macOS keychain. Scope them to the
166
+ # selected version's config directory so switching versions also switches the
167
+ # live Claude account.
168
+ export CLAUDE_CONFIG_DIR="$VERSION_DIR/home/${configDirName}"
169
+ `
170
+ : '';
171
+ // Agents that don't natively resolve @-imports in their memory file need
172
+ // agents-cli to recompile when the user edits a rule/preset file. The
173
+ // check is fast (sha256 of ~8 small files) and skips the recompile when
174
+ // sources haven't changed.
175
+ const refreshMemoryCall = !agentConfig.capabilities.memoryImports
176
+ ? `
177
+ # Recompile memory if any rule/preset source has changed since last sync.
178
+ # Fast-path check (~10-20ms) when nothing changed; full recompile only on
179
+ # actual diff. Non-blocking failure — if the refresh errors, we still launch.
180
+ agents refresh-memory --agent "$AGENT" --agent-version "$VERSION" --quiet 2>/dev/null || true
181
+ `
182
+ : '';
183
+ return `#!/bin/bash
184
+ # Auto-generated by agents-cli - do not edit
185
+ # Shim for ${agentConfig.name}
186
+ # ${SHIM_VERSION_MARKER} ${SHIM_SCHEMA_VERSION}
187
+
188
+ AGENTS_DIR="$HOME/.agents"
189
+ AGENT="${agent}"
190
+ CLI_COMMAND="${cliCommand}"
191
+
192
+ # Find project agents.yaml walking up from cwd (skip ~/.agents/agents.yaml)
193
+ find_project_version() {
194
+ local dir="$PWD"
195
+ local user_agents_yaml="$HOME/.agents/agents.yaml"
196
+ while [ "$dir" != "/" ]; do
197
+ local candidate="$dir/agents.yaml"
198
+ if [ -f "$candidate" ] && [ "$candidate" != "$user_agents_yaml" ]; then
199
+ # Parse agents: section — same shape as resolve_default_version()
200
+ local version
201
+ version=$(awk -v agent="$AGENT" '
202
+ /^agents:/ { in_agents=1; next }
203
+ in_agents && /^[^ ]/ { in_agents=0 }
204
+ in_agents && $0 ~ "^ " agent ":" { gsub(/.*:[[:space:]]*["'"'"']?|["'"'"']?[[:space:]]*$/, ""); print; exit }
205
+ ' "$candidate")
206
+ if [ -n "$version" ]; then
207
+ echo "$version"
208
+ return 0
209
+ fi
210
+ fi
211
+ dir=$(dirname "$dir")
212
+ done
213
+ return 1
214
+ }
215
+
216
+ # Resolve version from agents.yaml (user default)
217
+ resolve_default_version() {
218
+ local meta="$AGENTS_DIR/agents.yaml"
219
+ if [ -f "$meta" ]; then
220
+ awk -v agent="$AGENT" '
221
+ /^agents:/ { in_agents=1; next }
222
+ in_agents && /^[^ ]/ { in_agents=0 }
223
+ in_agents && $0 ~ "^ " agent ":" { gsub(/.*:[[:space:]]*["'"'"']?|["'"'"']?[[:space:]]*$/, ""); print; exit }
224
+ ' "$meta"
225
+ fi
226
+ }
227
+
228
+ # Find project-scoped .agents directory (stop at agents.yaml or .git)
229
+ find_project_agents_dir() {
230
+ local dir="$PWD"
231
+ while [ "$dir" != "/" ]; do
232
+ if [ -d "$dir/.agents" ]; then
233
+ echo "$dir/.agents"
234
+ return 0
235
+ fi
236
+ if [ -f "$dir/agents.yaml" ] || [ -d "$dir/.git" ] || [ -f "$dir/.git" ]; then
237
+ break
238
+ fi
239
+ dir=$(dirname "$dir")
240
+ done
241
+ return 1
242
+ }
243
+
244
+ # Try project version first, then global default
245
+ VERSION=$(find_project_version)
246
+ VERSION_SOURCE="project"
247
+ if [ -z "$VERSION" ]; then
248
+ VERSION=$(resolve_default_version)
249
+ VERSION_SOURCE="default"
250
+ fi
251
+
252
+ if [ -z "$VERSION" ]; then
253
+ echo "agents: no version of $AGENT configured" >&2
254
+ echo "Run: agents add $AGENT@<version>" >&2
255
+ exit 1
256
+ fi
257
+
258
+ VERSION_DIR="$AGENTS_DIR/versions/$AGENT/$VERSION"
259
+ BINARY="$VERSION_DIR/node_modules/.bin/$CLI_COMMAND"
260
+
261
+ # Auto-install if not present
262
+ if [ ! -x "$BINARY" ]; then
263
+ if [ "$VERSION_SOURCE" = "project" ]; then
264
+ echo "agents: $AGENT@$VERSION required by agents.yaml but not installed" >&2
265
+
266
+ # Spinner animation
267
+ spin() {
268
+ local pid=$1
269
+ local chars="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
270
+ local i=0
271
+ while kill -0 "$pid" 2>/dev/null; do
272
+ printf "\\r %s Installing $AGENT@$VERSION..." "\${chars:i++%\${#chars}:1}" >&2
273
+ sleep 0.1
274
+ done
275
+ printf "\\r" >&2
276
+ }
277
+
278
+ # Run install in background with spinner
279
+ agents add "$AGENT@$VERSION" --yes >/dev/null 2>&1 &
280
+ install_pid=$!
281
+ spin $install_pid
282
+ wait $install_pid
283
+ install_status=$?
284
+
285
+ if [ $install_status -eq 0 ]; then
286
+ echo " ✔ Installed $AGENT@$VERSION" >&2
287
+ else
288
+ echo " ✗ Failed to install $AGENT@$VERSION" >&2
289
+ exit 1
290
+ fi
291
+ else
292
+ echo "agents: $AGENT@$VERSION not installed" >&2
293
+ echo "Run: agents add $AGENT@$VERSION" >&2
294
+ exit 1
295
+ fi
296
+ fi
297
+
298
+ # Sync project-scoped resources into version home if a project .agents/ is present
299
+ PROJECT_AGENTS_DIR=$(find_project_agents_dir)
300
+ if [ -n "$PROJECT_AGENTS_DIR" ]; then
301
+ agents sync --agent "$AGENT" --agent-version "$VERSION" --project-dir "$PROJECT_AGENTS_DIR" --quiet >/dev/null 2>&1
302
+ fi
303
+ ${refreshMemoryCall}${managedEnv}
304
+
305
+ exec "$BINARY" "$@"
306
+ `;
307
+ }
308
+ /**
309
+ * Create a shim for an agent.
310
+ */
311
+ export function createShim(agent) {
312
+ ensureAgentsDir();
313
+ const shimsDir = getShimsDir();
314
+ const agentConfig = AGENTS[agent];
315
+ const shimPath = path.join(shimsDir, agentConfig.cliCommand);
316
+ const script = generateShimScript(agent);
317
+ fs.writeFileSync(shimPath, script, { mode: 0o755 });
318
+ return shimPath;
319
+ }
320
+ /**
321
+ * Remove the shim for an agent.
322
+ */
323
+ export function removeShim(agent) {
324
+ const shimsDir = getShimsDir();
325
+ const agentConfig = AGENTS[agent];
326
+ const shimPath = path.join(shimsDir, agentConfig.cliCommand);
327
+ if (fs.existsSync(shimPath)) {
328
+ fs.unlinkSync(shimPath);
329
+ return true;
330
+ }
331
+ return false;
332
+ }
333
+ /**
334
+ * Current versioned-alias schema. Bump whenever `generateVersionedAliasScript`
335
+ * changes in a way that requires existing on-disk aliases to be regenerated.
336
+ *
337
+ * History:
338
+ * v1 — implicit (no marker); no CLAUDE_CONFIG_DIR export, so direct
339
+ * `claude@X` invocations leaked into ~/.claude (the default version's
340
+ * symlinked home) and `agents view` never saw the login.
341
+ * v2 — emit CLAUDE_CONFIG_DIR for claude aliases so each version has its
342
+ * own isolated config/OAuth slot; stamp a version marker so stale
343
+ * aliases can be detected and regenerated.
344
+ */
345
+ export const VERSIONED_ALIAS_SCHEMA_VERSION = 2;
346
+ const VERSIONED_ALIAS_VERSION_MARKER = 'agents-versioned-alias-version:';
347
+ /**
348
+ * Generate a versioned alias script that directly execs a specific version.
349
+ * e.g., claude@2.0.65 -> directly runs that version's binary
350
+ */
351
+ export function generateVersionedAliasScript(agent, version) {
352
+ const agentConfig = AGENTS[agent];
353
+ const configDirName = `.${agent}`;
354
+ const managedEnv = agent === 'claude'
355
+ ? `
356
+ # Claude stores OAuth credentials in the macOS keychain. Scope them to this
357
+ # version's config directory so direct aliases also switch the live account.
358
+ export CLAUDE_CONFIG_DIR="$HOME/.agents/versions/${agent}/${version}/home/${configDirName}"
359
+ `
360
+ : '';
361
+ return `#!/bin/bash
362
+ # Auto-generated by agents-cli - do not edit
363
+ # ${VERSIONED_ALIAS_VERSION_MARKER} ${VERSIONED_ALIAS_SCHEMA_VERSION}
364
+ # Direct alias for ${agentConfig.name}@${version}
365
+
366
+ BINARY="$HOME/.agents/versions/${agent}/${version}/node_modules/.bin/${agentConfig.cliCommand}"
367
+
368
+ if [ ! -x "$BINARY" ]; then
369
+ echo "agents: ${agent}@${version} not installed" >&2
370
+ exit 1
371
+ fi
372
+ ${managedEnv}
373
+
374
+ exec "$BINARY" "$@"
375
+ `;
376
+ }
377
+ /**
378
+ * Read the schema version of an on-disk versioned alias. Returns null if the
379
+ * alias doesn't exist or is a pre-v2 alias (no marker — treated as stale).
380
+ */
381
+ export function readVersionedAliasSchemaVersion(agent, version) {
382
+ const aliasPath = getVersionedAliasPath(agent, version);
383
+ if (!fs.existsSync(aliasPath))
384
+ return null;
385
+ try {
386
+ const content = fs.readFileSync(aliasPath, 'utf8');
387
+ const header = content.split('\n', 10).join('\n');
388
+ const match = header.match(new RegExp(VERSIONED_ALIAS_VERSION_MARKER + '\\s*(\\d+)'));
389
+ if (!match)
390
+ return null;
391
+ return Number(match[1]);
392
+ }
393
+ catch {
394
+ return null;
395
+ }
396
+ }
397
+ export function isVersionedAliasCurrent(agent, version) {
398
+ return readVersionedAliasSchemaVersion(agent, version) === VERSIONED_ALIAS_SCHEMA_VERSION;
399
+ }
400
+ /**
401
+ * Regenerate a versioned alias if missing or stale. Mirrors ensureShimCurrent
402
+ * for the main shim — callers can surface a one-line notice when something
403
+ * was upgraded.
404
+ */
405
+ export function ensureVersionedAliasCurrent(agent, version) {
406
+ const aliasPath = getVersionedAliasPath(agent, version);
407
+ if (!fs.existsSync(aliasPath)) {
408
+ createVersionedAlias(agent, version);
409
+ return 'created';
410
+ }
411
+ if (!isVersionedAliasCurrent(agent, version)) {
412
+ createVersionedAlias(agent, version);
413
+ return 'updated';
414
+ }
415
+ return 'current';
416
+ }
417
+ export function getVersionedAliasPath(agent, version) {
418
+ return path.join(getShimsDir(), `${AGENTS[agent].cliCommand}@${version}`);
419
+ }
420
+ /**
421
+ * Create a versioned alias for a specific agent version.
422
+ * e.g., claude@2.0.65
423
+ */
424
+ export function createVersionedAlias(agent, version) {
425
+ ensureAgentsDir();
426
+ const shimsDir = getShimsDir();
427
+ const agentConfig = AGENTS[agent];
428
+ const aliasPath = path.join(shimsDir, `${agentConfig.cliCommand}@${version}`);
429
+ const script = generateVersionedAliasScript(agent, version);
430
+ fs.writeFileSync(aliasPath, script, { mode: 0o755 });
431
+ return aliasPath;
432
+ }
433
+ /**
434
+ * Remove a versioned alias for a specific agent version.
435
+ */
436
+ export function removeVersionedAlias(agent, version) {
437
+ const shimsDir = getShimsDir();
438
+ const agentConfig = AGENTS[agent];
439
+ const aliasPath = path.join(shimsDir, `${agentConfig.cliCommand}@${version}`);
440
+ if (fs.existsSync(aliasPath)) {
441
+ fs.unlinkSync(aliasPath);
442
+ return true;
443
+ }
444
+ return false;
445
+ }
446
+ /**
447
+ * Check if a versioned alias exists.
448
+ */
449
+ export function versionedAliasExists(agent, version) {
450
+ const shimsDir = getShimsDir();
451
+ const agentConfig = AGENTS[agent];
452
+ const aliasPath = path.join(shimsDir, `${agentConfig.cliCommand}@${version}`);
453
+ return fs.existsSync(aliasPath);
454
+ }
455
+ /**
456
+ * Get the path to the agent's config directory in HOME.
457
+ * e.g., ~/.claude for claude, ~/.codex for codex
458
+ */
459
+ function getAgentConfigPath(agent) {
460
+ const agentConfig = AGENTS[agent];
461
+ const home = process.env.AGENTS_REAL_HOME || os.homedir();
462
+ return agentConfig.configDir.replace(os.homedir(), home);
463
+ }
464
+ /**
465
+ * Get the path to the version's config directory.
466
+ * e.g., ~/.agents/versions/claude/2.0.65/home/.claude/
467
+ */
468
+ function getVersionConfigPath(agent, version) {
469
+ const agentConfig = AGENTS[agent];
470
+ const versionsDir = getVersionsDir();
471
+ const configDirName = `.${agent}`; // .claude, .codex, etc.
472
+ return path.join(versionsDir, agent, version, 'home', configDirName);
473
+ }
474
+ /**
475
+ * Detect conflicts that would occur when switching config symlink for an agent/version.
476
+ * This allows collecting conflicts upfront before prompting for a strategy.
477
+ *
478
+ * Returns null if no migration is needed (already symlink or doesn't exist),
479
+ * or ConflictInfo with the list of conflicting files.
480
+ */
481
+ export function detectMigrationConflicts(agent, version) {
482
+ const configPath = getAgentConfigPath(agent);
483
+ const versionConfigPath = getVersionConfigPath(agent, version);
484
+ try {
485
+ const stat = fs.lstatSync(configPath);
486
+ if (stat.isSymbolicLink()) {
487
+ // Already a symlink - no migration needed, no conflicts
488
+ return null;
489
+ }
490
+ else if (stat.isDirectory()) {
491
+ // Real directory exists - would need migration
492
+ // Detect conflicts between user's current config and version home
493
+ const conflicts = detectConflicts(configPath, versionConfigPath);
494
+ return {
495
+ agent,
496
+ version,
497
+ conflicts,
498
+ };
499
+ }
500
+ // Not a directory or symlink - unusual, no conflicts to report
501
+ return null;
502
+ }
503
+ catch (err) {
504
+ if (err.code === 'ENOENT') {
505
+ // Config path doesn't exist - no migration needed
506
+ return null;
507
+ }
508
+ return null;
509
+ }
510
+ }
511
+ /**
512
+ * Switch the agent's config symlink to point to a specific version.
513
+ * e.g., ~/.claude -> ~/.agents/versions/claude/2.0.65/home/.claude/
514
+ *
515
+ * If a real directory exists at the config path, it will be backed up
516
+ * to ~/.agents/backups/{agent}/{timestamp}/ and replaced with a symlink.
517
+ *
518
+ * @param agent - The agent ID
519
+ * @param version - The version to switch to
520
+ *
521
+ * Returns: { success: boolean, backupPath?: string, error?: string }
522
+ */
523
+ export async function switchConfigSymlink(agent, version) {
524
+ const configPath = getAgentConfigPath(agent);
525
+ const versionConfigPath = getVersionConfigPath(agent, version);
526
+ // Ensure version config directory exists
527
+ if (!fs.existsSync(versionConfigPath)) {
528
+ fs.mkdirSync(versionConfigPath, { recursive: true });
529
+ }
530
+ try {
531
+ const stat = fs.lstatSync(configPath);
532
+ if (stat.isSymbolicLink()) {
533
+ // Already a symlink - check if it points to the correct target
534
+ const currentTarget = fs.readlinkSync(configPath);
535
+ const resolvedCurrent = path.resolve(path.dirname(configPath), currentTarget);
536
+ const resolvedTarget = path.resolve(versionConfigPath);
537
+ if (resolvedCurrent === resolvedTarget) {
538
+ // Already pointing to correct target, no-op
539
+ return { success: true };
540
+ }
541
+ // Different target - update it
542
+ fs.unlinkSync(configPath);
543
+ fs.symlinkSync(versionConfigPath, configPath);
544
+ return { success: true };
545
+ }
546
+ else if (stat.isDirectory()) {
547
+ // Real directory exists - backup and replace with symlink
548
+ const timestamp = Date.now();
549
+ // Move to backup location
550
+ const backupsDir = getBackupsDir();
551
+ const agentBackupDir = path.join(backupsDir, agent);
552
+ const finalBackupPath = path.join(agentBackupDir, String(timestamp));
553
+ fs.mkdirSync(agentBackupDir, { recursive: true });
554
+ fs.renameSync(configPath, finalBackupPath);
555
+ // Create symlink
556
+ fs.symlinkSync(versionConfigPath, configPath);
557
+ return { success: true, backupPath: finalBackupPath };
558
+ }
559
+ else {
560
+ return { success: false, error: `${configPath} exists but is not a directory or symlink` };
561
+ }
562
+ }
563
+ catch (err) {
564
+ if (err.code === 'ENOENT') {
565
+ // Config path doesn't exist - create symlink
566
+ fs.symlinkSync(versionConfigPath, configPath);
567
+ return { success: true };
568
+ }
569
+ return { success: false, error: err.message };
570
+ }
571
+ }
572
+ /**
573
+ * Switch home-level files (outside the config dir) to per-version symlinks.
574
+ * e.g., ~/.claude.json -> ~/.agents/versions/claude/2.0.65/home/.claude.json
575
+ *
576
+ * Uses atomic rename to avoid data loss if another session is running.
577
+ * On first migration (real file -> symlink), merges global auth into
578
+ * ALL installed versions so they inherit the current account.
579
+ */
580
+ export function switchHomeFileSymlinks(agent, version) {
581
+ const agentConfig = AGENTS[agent];
582
+ const homeFiles = agentConfig.homeFiles;
583
+ if (!homeFiles || homeFiles.length === 0)
584
+ return { switched: [], errors: [] };
585
+ const home = process.env.AGENTS_REAL_HOME || os.homedir();
586
+ const versionsDir = getVersionsDir();
587
+ const switched = [];
588
+ const errors = [];
589
+ for (const fileName of homeFiles) {
590
+ const globalPath = path.join(home, fileName);
591
+ const versionFilePath = path.join(versionsDir, agent, version, 'home', fileName);
592
+ try {
593
+ // Ensure version home dir exists
594
+ const versionFileDir = path.dirname(versionFilePath);
595
+ if (!fs.existsSync(versionFileDir)) {
596
+ fs.mkdirSync(versionFileDir, { recursive: true });
597
+ }
598
+ let stat = null;
599
+ try {
600
+ stat = fs.lstatSync(globalPath);
601
+ }
602
+ catch {
603
+ // File doesn't exist at global path — just create symlink
604
+ if (!fs.existsSync(versionFilePath)) {
605
+ fs.writeFileSync(versionFilePath, '{}');
606
+ }
607
+ fs.symlinkSync(versionFilePath, globalPath);
608
+ switched.push(fileName);
609
+ continue;
610
+ }
611
+ if (stat.isSymbolicLink()) {
612
+ // Already a symlink — retarget atomically
613
+ const currentTarget = fs.readlinkSync(globalPath);
614
+ const resolvedCurrent = path.resolve(path.dirname(globalPath), currentTarget);
615
+ const resolvedTarget = path.resolve(versionFilePath);
616
+ if (resolvedCurrent === resolvedTarget) {
617
+ switched.push(fileName);
618
+ continue; // Already correct
619
+ }
620
+ // Atomic retarget: create temp symlink, rename over existing
621
+ if (!fs.existsSync(versionFilePath)) {
622
+ fs.writeFileSync(versionFilePath, '{}');
623
+ }
624
+ const tmpPath = `${globalPath}.agents-tmp-${process.pid}`;
625
+ fs.symlinkSync(versionFilePath, tmpPath);
626
+ fs.renameSync(tmpPath, globalPath);
627
+ switched.push(fileName);
628
+ }
629
+ else if (stat.isFile()) {
630
+ // Real file — first-time migration
631
+ // Read the global file content
632
+ const globalContent = JSON.parse(fs.readFileSync(globalPath, 'utf-8'));
633
+ // Merge auth into ALL installed version files for this agent
634
+ const agentVersionsDir = path.join(versionsDir, agent);
635
+ if (fs.existsSync(agentVersionsDir)) {
636
+ for (const ver of fs.readdirSync(agentVersionsDir)) {
637
+ const verFilePath = path.join(agentVersionsDir, ver, 'home', fileName);
638
+ const verFileDir = path.dirname(verFilePath);
639
+ if (!fs.existsSync(verFileDir)) {
640
+ fs.mkdirSync(verFileDir, { recursive: true });
641
+ }
642
+ if (fs.existsSync(verFilePath)) {
643
+ // Merge: version-specific fields + global auth fields
644
+ try {
645
+ const verContent = JSON.parse(fs.readFileSync(verFilePath, 'utf-8'));
646
+ const merged = { ...globalContent, ...verContent };
647
+ // Ensure auth from global always wins
648
+ if (globalContent.oauthAccount) {
649
+ merged.oauthAccount = globalContent.oauthAccount;
650
+ }
651
+ fs.writeFileSync(verFilePath, JSON.stringify(merged, null, 2));
652
+ }
653
+ catch {
654
+ // If version file is invalid JSON, overwrite with global
655
+ fs.writeFileSync(verFilePath, JSON.stringify(globalContent, null, 2));
656
+ }
657
+ }
658
+ else {
659
+ // No version file — copy global wholesale
660
+ fs.writeFileSync(verFilePath, JSON.stringify(globalContent, null, 2));
661
+ }
662
+ }
663
+ }
664
+ // Atomic swap: create temp symlink to target version, rename over real file
665
+ const tmpPath = `${globalPath}.agents-tmp-${process.pid}`;
666
+ fs.symlinkSync(versionFilePath, tmpPath);
667
+ fs.renameSync(tmpPath, globalPath);
668
+ switched.push(fileName);
669
+ }
670
+ }
671
+ catch (err) {
672
+ errors.push(`${fileName}: ${err.message}`);
673
+ }
674
+ }
675
+ return { switched, errors };
676
+ }
677
+ /**
678
+ * Get the current config symlink target version, if any.
679
+ */
680
+ export function getConfigSymlinkVersion(agent) {
681
+ const configPath = getAgentConfigPath(agent);
682
+ try {
683
+ const stat = fs.lstatSync(configPath);
684
+ if (!stat.isSymbolicLink()) {
685
+ return null;
686
+ }
687
+ const target = fs.readlinkSync(configPath);
688
+ // Extract version from path like ~/.agents/versions/claude/2.0.65/home/.claude
689
+ const match = target.match(/versions\/[^/]+\/([^/]+)\/home/);
690
+ return match ? match[1] : null;
691
+ }
692
+ catch {
693
+ /* config path not accessible or not a symlink */
694
+ return null;
695
+ }
696
+ }
697
+ /**
698
+ * Copy directory contents with configurable conflict strategy.
699
+ * Skips when dest is a symlink (managed resources that shouldn't be overwritten).
700
+ *
701
+ * @param src - Source directory
702
+ * @param dest - Destination directory
703
+ * @param strategy - How to handle conflicts: 'keep-dest', 'overwrite', or 'ask-per-file'
704
+ * @param context - Agent/version context for prompts (only used when strategy is 'ask-per-file')
705
+ */
706
+ async function copyDirContents(src, dest, strategy = 'keep-dest', context) {
707
+ // If dest is a symlink, skip - these are managed resources (skills, commands, etc.)
708
+ // that link to central ~/.agents/ and shouldn't be overwritten with local copies
709
+ try {
710
+ const destStat = fs.lstatSync(dest);
711
+ if (destStat.isSymbolicLink()) {
712
+ return; // Skip - don't copy into symlinked directories
713
+ }
714
+ }
715
+ catch {
716
+ // dest doesn't exist, that's fine
717
+ }
718
+ if (!fs.existsSync(dest)) {
719
+ fs.mkdirSync(dest, { recursive: true });
720
+ }
721
+ const entries = fs.readdirSync(src, { withFileTypes: true });
722
+ for (const entry of entries) {
723
+ // Skip files/directories that should never be migrated
724
+ if (shouldIgnore(entry.name)) {
725
+ continue;
726
+ }
727
+ const srcPath = path.join(src, entry.name);
728
+ const destPath = path.join(dest, entry.name);
729
+ // Skip if dest entry is a symlink (managed resource)
730
+ try {
731
+ const entryDestStat = fs.lstatSync(destPath);
732
+ if (entryDestStat.isSymbolicLink()) {
733
+ continue; // Skip - managed resource
734
+ }
735
+ }
736
+ catch {
737
+ // dest entry doesn't exist, that's fine
738
+ }
739
+ if (entry.isDirectory()) {
740
+ await copyDirContents(srcPath, destPath, strategy, context);
741
+ }
742
+ else if (entry.isSymbolicLink()) {
743
+ const linkTarget = fs.readlinkSync(srcPath);
744
+ if (fs.existsSync(destPath)) {
745
+ fs.unlinkSync(destPath);
746
+ }
747
+ fs.symlinkSync(linkTarget, destPath);
748
+ }
749
+ else {
750
+ // File - check for conflict
751
+ if (fs.existsSync(destPath)) {
752
+ // Handle based on strategy
753
+ if (strategy === 'keep-dest') {
754
+ // Keep existing file, skip copying
755
+ continue;
756
+ }
757
+ else if (strategy === 'overwrite') {
758
+ // Back up and overwrite
759
+ fs.copyFileSync(destPath, `${destPath}.backup`);
760
+ }
761
+ else if (strategy === 'ask-per-file') {
762
+ // Back up dest file
763
+ fs.copyFileSync(destPath, `${destPath}.backup`);
764
+ // Ask user with context - use clear path-based terminology
765
+ const agentConfig = context ? AGENTS[context.agent] : null;
766
+ const versionLabel = agentConfig
767
+ ? `${agentConfig.name}@${context.version}`
768
+ : 'version';
769
+ const useMyFile = await confirm({
770
+ message: `${entry.name}: Use your config file instead of ${versionLabel}?`,
771
+ default: false, // Default to keep version (safer)
772
+ });
773
+ if (!useMyFile) {
774
+ continue; // Keep dest (version file), skip copying src
775
+ }
776
+ }
777
+ }
778
+ fs.copyFileSync(srcPath, destPath);
779
+ }
780
+ }
781
+ }
782
+ /**
783
+ * Check if shim exists for an agent.
784
+ */
785
+ export function shimExists(agent) {
786
+ const shimsDir = getShimsDir();
787
+ const agentConfig = AGENTS[agent];
788
+ const shimPath = path.join(shimsDir, agentConfig.cliCommand);
789
+ return fs.existsSync(shimPath);
790
+ }
791
+ /**
792
+ * Read the schema version embedded in an existing on-disk shim. Returns
793
+ * `null` if the shim doesn't exist or has no version marker (pre-v2 shim).
794
+ */
795
+ export function readShimSchemaVersion(agent) {
796
+ if (!shimExists(agent))
797
+ return null;
798
+ try {
799
+ const content = fs.readFileSync(getShimPath(agent), 'utf8');
800
+ // Look at the first ~10 lines only — the marker lives in the header.
801
+ const header = content.split('\n', 10).join('\n');
802
+ const match = header.match(new RegExp(SHIM_VERSION_MARKER + '\\s*(\\d+)'));
803
+ if (!match)
804
+ return null;
805
+ return Number(match[1]);
806
+ }
807
+ catch {
808
+ return null;
809
+ }
810
+ }
811
+ /**
812
+ * True if the on-disk shim's schema version matches `SHIM_SCHEMA_VERSION`.
813
+ * False means either the shim is missing, is pre-v2 (no marker), or is an
814
+ * older version that needs regeneration.
815
+ */
816
+ export function isShimCurrent(agent) {
817
+ const version = readShimSchemaVersion(agent);
818
+ return version === SHIM_SCHEMA_VERSION;
819
+ }
820
+ /**
821
+ * Regenerate the shim if it's missing or outdated. Returns a status describing
822
+ * what happened — callers can surface a one-line notice to the user ("Updated
823
+ * shim for codex") when appropriate.
824
+ */
825
+ export function ensureShimCurrent(agent) {
826
+ if (!shimExists(agent)) {
827
+ createShim(agent);
828
+ return 'created';
829
+ }
830
+ if (!isShimCurrent(agent)) {
831
+ createShim(agent);
832
+ return 'updated';
833
+ }
834
+ return 'current';
835
+ }
836
+ /**
837
+ * Get the path to the shim for an agent.
838
+ */
839
+ export function getShimPath(agent) {
840
+ const shimsDir = getShimsDir();
841
+ const agentConfig = AGENTS[agent];
842
+ return path.join(shimsDir, agentConfig.cliCommand);
843
+ }
844
+ /**
845
+ * Return the first executable path that would be launched for this agent when
846
+ * resolving against PATH, excluding the managed shim itself.
847
+ */
848
+ export function getPathShadowingExecutable(agent) {
849
+ const pathDirs = (process.env.PATH || '').split(path.delimiter).filter(Boolean);
850
+ const shimPath = path.resolve(getShimPath(agent));
851
+ const cliCommand = AGENTS[agent].cliCommand;
852
+ for (const dir of pathDirs) {
853
+ const candidate = path.resolve(dir, cliCommand);
854
+ if (!fs.existsSync(candidate)) {
855
+ continue;
856
+ }
857
+ return candidate === shimPath ? null : candidate;
858
+ }
859
+ return null;
860
+ }
861
+ /**
862
+ * Check if shims directory is in PATH.
863
+ */
864
+ export function isShimsInPath() {
865
+ const shimsDir = getShimsDir();
866
+ const pathDirs = (process.env.PATH || '').split(path.delimiter);
867
+ return pathDirs.some((dir) => path.resolve(dir) === path.resolve(shimsDir));
868
+ }
869
+ /**
870
+ * Get the shell rc file path for the current shell.
871
+ */
872
+ function getShellRcFile() {
873
+ const shell = process.env.SHELL || '/bin/bash';
874
+ const shellName = path.basename(shell);
875
+ let rcFile;
876
+ switch (shellName) {
877
+ case 'zsh':
878
+ rcFile = '.zshrc';
879
+ break;
880
+ case 'fish':
881
+ rcFile = '.config/fish/config.fish';
882
+ break;
883
+ case 'bash':
884
+ default:
885
+ rcFile = '.bashrc';
886
+ break;
887
+ }
888
+ return {
889
+ rcFile,
890
+ rcPath: path.join(os.homedir(), rcFile),
891
+ shell: shellName,
892
+ };
893
+ }
894
+ /**
895
+ * Get shell configuration instructions for adding shims to PATH.
896
+ */
897
+ export function getPathSetupInstructions() {
898
+ const shimsDir = getShimsDir();
899
+ const { rcFile, shell } = getShellRcFile();
900
+ if (shell === 'fish') {
901
+ return `Add to ~/.config/fish/config.fish:
902
+ fish_add_path ${shimsDir}`;
903
+ }
904
+ return `Add to ~/${rcFile} (BEFORE any nvm/node setup):
905
+ export PATH="${shimsDir}:$PATH"
906
+
907
+ IMPORTANT: Shims must come FIRST in PATH to override global installs.
908
+
909
+ Then restart your shell or run:
910
+ source ~/${rcFile}`;
911
+ }
912
+ /**
913
+ * Add shims directory to shell PATH configuration.
914
+ * Returns true if added, false if already present or failed.
915
+ */
916
+ export function addShimsToPath() {
917
+ const shimsDir = getShimsDir();
918
+ const { rcFile, rcPath, shell } = getShellRcFile();
919
+ // Read current rc file content
920
+ let content = '';
921
+ try {
922
+ if (fs.existsSync(rcPath)) {
923
+ content = fs.readFileSync(rcPath, 'utf-8');
924
+ }
925
+ }
926
+ catch (err) {
927
+ return { success: false, error: `Could not read ${rcFile}: ${err.message}` };
928
+ }
929
+ // Check if shims path already in file
930
+ if (content.includes(shimsDir) || content.includes('$HOME/.agents/shims')) {
931
+ return { success: true, alreadyPresent: true, rcFile };
932
+ }
933
+ // Generate the export line
934
+ let exportLine;
935
+ if (shell === 'fish') {
936
+ exportLine = `\n# agents-cli: version-managed agent CLIs\nfish_add_path ${shimsDir}\n`;
937
+ }
938
+ else {
939
+ exportLine = `\n# agents-cli: version-managed agent CLIs\nexport PATH="${shimsDir}:$PATH"\n`;
940
+ }
941
+ // Find insertion point - BEFORE nvm/node setup if possible
942
+ // Look for common patterns that should come AFTER our shims
943
+ const insertBeforePatterns = [
944
+ /^export NVM_DIR=/m,
945
+ /^source.*nvm/m,
946
+ /^\[ -s.*nvm/m,
947
+ /^eval.*fnm/m,
948
+ /^export PATH.*node/m,
949
+ /^export PATH.*npm/m,
950
+ ];
951
+ let insertIndex = -1;
952
+ for (const pattern of insertBeforePatterns) {
953
+ const match = content.match(pattern);
954
+ if (match && match.index !== undefined) {
955
+ // Find start of this line
956
+ let lineStart = match.index;
957
+ while (lineStart > 0 && content[lineStart - 1] !== '\n') {
958
+ lineStart--;
959
+ }
960
+ if (insertIndex === -1 || lineStart < insertIndex) {
961
+ insertIndex = lineStart;
962
+ }
963
+ }
964
+ }
965
+ // Write the updated content
966
+ try {
967
+ // Ensure parent directories exist (especially for fish: ~/.config/fish/)
968
+ const rcDir = path.dirname(rcPath);
969
+ if (!fs.existsSync(rcDir)) {
970
+ fs.mkdirSync(rcDir, { recursive: true });
971
+ }
972
+ let newContent;
973
+ if (insertIndex >= 0) {
974
+ // Insert before nvm/node setup (handles index 0 correctly)
975
+ newContent = content.slice(0, insertIndex) + exportLine + content.slice(insertIndex);
976
+ }
977
+ else {
978
+ // Append to end
979
+ newContent = content + exportLine;
980
+ }
981
+ fs.writeFileSync(rcPath, newContent, 'utf-8');
982
+ return { success: true, rcFile };
983
+ }
984
+ catch (err) {
985
+ return { success: false, error: `Could not write ${rcFile}: ${err.message}` };
986
+ }
987
+ }
988
+ /**
989
+ * Create shims for all installed agents.
990
+ */
991
+ export function ensureAllShims() {
992
+ const versionsDir = getVersionsDir();
993
+ if (!fs.existsSync(versionsDir)) {
994
+ return;
995
+ }
996
+ const entries = fs.readdirSync(versionsDir, { withFileTypes: true });
997
+ for (const entry of entries) {
998
+ if (entry.isDirectory() && AGENTS[entry.name]) {
999
+ const agent = entry.name;
1000
+ const agentVersionsDir = path.join(versionsDir, agent);
1001
+ const versions = fs.readdirSync(agentVersionsDir, { withFileTypes: true })
1002
+ .filter((e) => e.isDirectory());
1003
+ if (versions.length > 0 && !shimExists(agent)) {
1004
+ createShim(agent);
1005
+ }
1006
+ }
1007
+ }
1008
+ }
1009
+ /**
1010
+ * Compare resources between two versions.
1011
+ * Returns resources that exist in currentVersion but not in targetVersion.
1012
+ */
1013
+ export function compareVersionResources(agent, currentVersion, targetVersion) {
1014
+ const agentConfig = AGENTS[agent];
1015
+ const currentPath = getVersionConfigPath(agent, currentVersion);
1016
+ const targetPath = getVersionConfigPath(agent, targetVersion);
1017
+ const diff = {
1018
+ commands: [],
1019
+ skills: [],
1020
+ hooks: [],
1021
+ memory: [],
1022
+ mcp: [],
1023
+ };
1024
+ // Helper to list directory contents (names only)
1025
+ const listDir = (dir) => {
1026
+ if (!fs.existsSync(dir))
1027
+ return [];
1028
+ try {
1029
+ return fs.readdirSync(dir).filter(f => !f.startsWith('.'));
1030
+ }
1031
+ catch {
1032
+ /* directory not readable */
1033
+ return [];
1034
+ }
1035
+ };
1036
+ // Helper to count lines in a file
1037
+ const countLines = (filePath) => {
1038
+ if (!fs.existsSync(filePath))
1039
+ return 0;
1040
+ try {
1041
+ return fs.readFileSync(filePath, 'utf-8').split('\n').length;
1042
+ }
1043
+ catch {
1044
+ /* file not readable */
1045
+ return 0;
1046
+ }
1047
+ };
1048
+ // Compare commands
1049
+ const currentCommands = listDir(path.join(currentPath, agentConfig.commandsSubdir));
1050
+ const targetCommands = new Set(listDir(path.join(targetPath, agentConfig.commandsSubdir)));
1051
+ diff.commands = currentCommands.filter(c => !targetCommands.has(c)).map(c => c.replace(/\.(md|toml)$/, ''));
1052
+ // Compare skills
1053
+ const currentSkills = listDir(path.join(currentPath, 'skills'));
1054
+ const targetSkills = new Set(listDir(path.join(targetPath, 'skills')));
1055
+ diff.skills = currentSkills.filter(s => !targetSkills.has(s));
1056
+ // Compare hooks
1057
+ const currentHooks = listDir(path.join(currentPath, 'hooks'));
1058
+ const targetHooks = new Set(listDir(path.join(targetPath, 'hooks')));
1059
+ diff.hooks = currentHooks.filter(h => !targetHooks.has(h));
1060
+ // Compare memory files (instructionsFile like CLAUDE.md)
1061
+ const memoryFile = agentConfig.instructionsFile;
1062
+ const currentMemoryPath = path.join(currentPath, memoryFile);
1063
+ const targetMemoryPath = path.join(targetPath, memoryFile);
1064
+ const currentLines = countLines(currentMemoryPath);
1065
+ const targetLines = countLines(targetMemoryPath);
1066
+ if (currentLines > 0 && currentLines !== targetLines) {
1067
+ diff.memory.push({ file: memoryFile, currentLines, targetLines });
1068
+ }
1069
+ // Compare MCP servers (from settings.json)
1070
+ const readMcpServers = (configPath) => {
1071
+ const settingsPath = path.join(configPath, 'settings.json');
1072
+ if (!fs.existsSync(settingsPath))
1073
+ return [];
1074
+ try {
1075
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
1076
+ return Object.keys(settings.mcpServers || {});
1077
+ }
1078
+ catch {
1079
+ /* settings.json corrupt or unreadable */
1080
+ return [];
1081
+ }
1082
+ };
1083
+ const currentMcp = readMcpServers(currentPath);
1084
+ const targetMcp = new Set(readMcpServers(targetPath));
1085
+ diff.mcp = currentMcp.filter(m => !targetMcp.has(m));
1086
+ return diff;
1087
+ }
1088
+ /**
1089
+ * Check if a ResourceDiff has any differences.
1090
+ */
1091
+ export function hasResourceDiff(diff) {
1092
+ return (diff.commands.length > 0 ||
1093
+ diff.skills.length > 0 ||
1094
+ diff.hooks.length > 0 ||
1095
+ diff.memory.length > 0 ||
1096
+ diff.mcp.length > 0);
1097
+ }
1098
+ /**
1099
+ * Copy resources from one version to another.
1100
+ * Only copies resources listed in the diff (i.e., ones missing in target).
1101
+ */
1102
+ export function copyResourcesToVersion(agent, fromVersion, toVersion, diff) {
1103
+ const agentConfig = AGENTS[agent];
1104
+ const fromPath = getVersionConfigPath(agent, fromVersion);
1105
+ const toPath = getVersionConfigPath(agent, toVersion);
1106
+ // Helper to copy a file or directory
1107
+ const copyItem = (srcDir, destDir, name) => {
1108
+ const srcPath = path.join(srcDir, name);
1109
+ const destPath = path.join(destDir, name);
1110
+ if (!fs.existsSync(srcPath))
1111
+ return;
1112
+ fs.mkdirSync(destDir, { recursive: true });
1113
+ const stat = fs.statSync(srcPath);
1114
+ if (stat.isDirectory()) {
1115
+ copyDirContents(srcPath, destPath);
1116
+ }
1117
+ else {
1118
+ fs.copyFileSync(srcPath, destPath);
1119
+ }
1120
+ };
1121
+ // Copy missing commands
1122
+ const commandsSubdir = agentConfig.commandsSubdir;
1123
+ const ext = agentConfig.format === 'toml' ? '.toml' : '.md';
1124
+ for (const cmd of diff.commands) {
1125
+ copyItem(path.join(fromPath, commandsSubdir), path.join(toPath, commandsSubdir), `${cmd}${ext}`);
1126
+ }
1127
+ // Copy missing skills
1128
+ for (const skill of diff.skills) {
1129
+ copyItem(path.join(fromPath, 'skills'), path.join(toPath, 'skills'), skill);
1130
+ }
1131
+ // Copy missing hooks
1132
+ for (const hook of diff.hooks) {
1133
+ copyItem(path.join(fromPath, 'hooks'), path.join(toPath, 'hooks'), hook);
1134
+ }
1135
+ // Copy memory file if different
1136
+ for (const mem of diff.memory) {
1137
+ const srcPath = path.join(fromPath, mem.file);
1138
+ const destPath = path.join(toPath, mem.file);
1139
+ if (fs.existsSync(srcPath)) {
1140
+ fs.copyFileSync(srcPath, destPath);
1141
+ }
1142
+ }
1143
+ // Merge MCP servers into target settings.json
1144
+ if (diff.mcp.length > 0) {
1145
+ const fromSettingsPath = path.join(fromPath, 'settings.json');
1146
+ const toSettingsPath = path.join(toPath, 'settings.json');
1147
+ if (fs.existsSync(fromSettingsPath)) {
1148
+ try {
1149
+ const fromSettings = JSON.parse(fs.readFileSync(fromSettingsPath, 'utf-8'));
1150
+ let toSettings = {};
1151
+ if (fs.existsSync(toSettingsPath)) {
1152
+ toSettings = JSON.parse(fs.readFileSync(toSettingsPath, 'utf-8'));
1153
+ }
1154
+ if (!toSettings.mcpServers) {
1155
+ toSettings.mcpServers = {};
1156
+ }
1157
+ for (const serverName of diff.mcp) {
1158
+ if (fromSettings.mcpServers?.[serverName]) {
1159
+ toSettings.mcpServers[serverName] = fromSettings.mcpServers[serverName];
1160
+ }
1161
+ }
1162
+ fs.writeFileSync(toSettingsPath, JSON.stringify(toSettings, null, 2));
1163
+ }
1164
+ catch {
1165
+ /* settings.json parse error, skip MCP merge */
1166
+ }
1167
+ }
1168
+ }
1169
+ }
1170
+ //# sourceMappingURL=shims.js.map