indusagi-coding-agent 0.1.37 → 0.1.39

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 (489) hide show
  1. package/CHANGELOG.md +23 -7
  2. package/README.md +2 -4
  3. package/dist/cli/args.d.ts +6 -128
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +277 -472
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/config-selector.d.ts +9 -62
  8. package/dist/cli/config-selector.d.ts.map +1 -1
  9. package/dist/cli/config-selector.js +31 -146
  10. package/dist/cli/config-selector.js.map +1 -1
  11. package/dist/cli/file-processor.d.ts +1 -69
  12. package/dist/cli/file-processor.d.ts.map +1 -1
  13. package/dist/cli/file-processor.js +36 -267
  14. package/dist/cli/file-processor.js.map +1 -1
  15. package/dist/cli/list-models.d.ts +0 -60
  16. package/dist/cli/list-models.d.ts.map +1 -1
  17. package/dist/cli/list-models.js +53 -246
  18. package/dist/cli/list-models.js.map +1 -1
  19. package/dist/cli/session-picker.d.ts +1 -72
  20. package/dist/cli/session-picker.d.ts.map +1 -1
  21. package/dist/cli/session-picker.js +57 -231
  22. package/dist/cli/session-picker.js.map +1 -1
  23. package/dist/cli.js +25 -31
  24. package/dist/cli.js.map +1 -1
  25. package/dist/config.d.ts +0 -42
  26. package/dist/config.d.ts.map +1 -1
  27. package/dist/config.js +62 -97
  28. package/dist/config.js.map +1 -1
  29. package/dist/core/agent-session.d.ts +23 -0
  30. package/dist/core/agent-session.d.ts.map +1 -1
  31. package/dist/core/agent-session.js +78 -66
  32. package/dist/core/agent-session.js.map +1 -1
  33. package/dist/core/auth-storage.d.ts +4 -95
  34. package/dist/core/auth-storage.d.ts.map +1 -1
  35. package/dist/core/auth-storage.js +233 -288
  36. package/dist/core/auth-storage.js.map +1 -1
  37. package/dist/core/bash-executor.d.ts +0 -323
  38. package/dist/core/bash-executor.d.ts.map +1 -1
  39. package/dist/core/bash-executor.js +126 -359
  40. package/dist/core/bash-executor.js.map +1 -1
  41. package/dist/core/compaction/branch-summarization.d.ts +3 -3
  42. package/dist/core/compaction/branch-summarization.js +16 -16
  43. package/dist/core/compaction/branch-summarization.js.map +1 -1
  44. package/dist/core/compaction/compaction.d.ts +3 -3
  45. package/dist/core/compaction/compaction.js +40 -40
  46. package/dist/core/compaction/compaction.js.map +1 -1
  47. package/dist/core/compaction/index.d.ts +32 -4
  48. package/dist/core/compaction/index.d.ts.map +1 -1
  49. package/dist/core/compaction/index.js +30 -4
  50. package/dist/core/compaction/index.js.map +1 -1
  51. package/dist/core/compaction/utils.d.ts +1 -19
  52. package/dist/core/compaction/utils.d.ts.map +1 -1
  53. package/dist/core/compaction/utils.js +92 -113
  54. package/dist/core/compaction/utils.js.map +1 -1
  55. package/dist/core/discover-packages.d.ts +0 -4
  56. package/dist/core/discover-packages.d.ts.map +1 -1
  57. package/dist/core/discover-packages.js +41 -44
  58. package/dist/core/discover-packages.js.map +1 -1
  59. package/dist/core/event-bus.d.ts +1 -147
  60. package/dist/core/event-bus.d.ts.map +1 -1
  61. package/dist/core/event-bus.js +17 -106
  62. package/dist/core/event-bus.js.map +1 -1
  63. package/dist/core/exec.d.ts +0 -16
  64. package/dist/core/exec.d.ts.map +1 -1
  65. package/dist/core/exec.js +18 -27
  66. package/dist/core/exec.js.map +1 -1
  67. package/dist/core/export-html/ansi-to-html.ts +262 -0
  68. package/dist/core/export-html/index.ts +433 -0
  69. package/dist/core/export-html/template.html +48 -26
  70. package/dist/core/export-html/tool-renderer.d.ts +0 -21
  71. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  72. package/dist/core/export-html/tool-renderer.js +35 -51
  73. package/dist/core/export-html/tool-renderer.js.map +1 -1
  74. package/dist/core/export-html/tool-renderer.ts +80 -0
  75. package/dist/core/export-html/vendor/highlight.min.js +401 -370
  76. package/dist/core/export-html/vendor/marked.min.js +71 -3
  77. package/dist/core/extensions/index.d.ts +7 -4
  78. package/dist/core/extensions/index.d.ts.map +1 -1
  79. package/dist/core/extensions/index.js +17 -3
  80. package/dist/core/extensions/index.js.map +1 -1
  81. package/dist/core/extensions/loader.d.ts +0 -6
  82. package/dist/core/extensions/loader.d.ts.map +1 -1
  83. package/dist/core/extensions/loader.js +60 -56
  84. package/dist/core/extensions/loader.js.map +1 -1
  85. package/dist/core/extensions/runner.d.ts +3 -0
  86. package/dist/core/extensions/runner.d.ts.map +1 -1
  87. package/dist/core/extensions/runner.js +48 -80
  88. package/dist/core/extensions/runner.js.map +1 -1
  89. package/dist/core/extensions/types.d.ts +50 -23
  90. package/dist/core/extensions/types.d.ts.map +1 -1
  91. package/dist/core/footer-data-provider.d.ts +2 -15
  92. package/dist/core/footer-data-provider.d.ts.map +1 -1
  93. package/dist/core/footer-data-provider.js +21 -33
  94. package/dist/core/footer-data-provider.js.map +1 -1
  95. package/dist/core/hooks/loader.js +2 -2
  96. package/dist/core/hooks/loader.js.map +1 -1
  97. package/dist/core/index.d.ts +29 -10
  98. package/dist/core/index.d.ts.map +1 -1
  99. package/dist/core/index.js +29 -10
  100. package/dist/core/index.js.map +1 -1
  101. package/dist/core/keybindings.d.ts +2 -179
  102. package/dist/core/keybindings.d.ts.map +1 -1
  103. package/dist/core/keybindings.js +64 -238
  104. package/dist/core/keybindings.js.map +1 -1
  105. package/dist/core/model-registry.d.ts +26 -181
  106. package/dist/core/model-registry.d.ts.map +1 -1
  107. package/dist/core/model-registry.js +228 -407
  108. package/dist/core/model-registry.js.map +1 -1
  109. package/dist/core/model-resolver.d.ts +0 -139
  110. package/dist/core/model-resolver.d.ts.map +1 -1
  111. package/dist/core/model-resolver.js +36 -217
  112. package/dist/core/model-resolver.js.map +1 -1
  113. package/dist/core/package-manager.d.ts +25 -57
  114. package/dist/core/package-manager.d.ts.map +1 -1
  115. package/dist/core/package-manager.js +326 -964
  116. package/dist/core/package-manager.js.map +1 -1
  117. package/dist/core/prompt-templates.d.ts +2 -34
  118. package/dist/core/prompt-templates.d.ts.map +1 -1
  119. package/dist/core/prompt-templates.js +122 -170
  120. package/dist/core/prompt-templates.js.map +1 -1
  121. package/dist/core/resource-loader.d.ts +19 -12
  122. package/dist/core/resource-loader.d.ts.map +1 -1
  123. package/dist/core/resource-loader.js +353 -467
  124. package/dist/core/resource-loader.js.map +1 -1
  125. package/dist/core/sdk.d.ts +2 -61
  126. package/dist/core/sdk.d.ts.map +1 -1
  127. package/dist/core/sdk.js +184 -252
  128. package/dist/core/sdk.js.map +1 -1
  129. package/dist/core/session-manager.d.ts +447 -1
  130. package/dist/core/session-manager.d.ts.map +1 -1
  131. package/dist/core/session-manager.js +1176 -1
  132. package/dist/core/session-manager.js.map +1 -1
  133. package/dist/core/settings-manager.d.ts +9 -12
  134. package/dist/core/settings-manager.d.ts.map +1 -1
  135. package/dist/core/settings-manager.js +170 -398
  136. package/dist/core/settings-manager.js.map +1 -1
  137. package/dist/core/skills.d.ts +2 -27
  138. package/dist/core/skills.d.ts.map +1 -1
  139. package/dist/core/skills.js +149 -212
  140. package/dist/core/skills.js.map +1 -1
  141. package/dist/core/subagents.d.ts +2 -2
  142. package/dist/core/subagents.d.ts.map +1 -1
  143. package/dist/core/subagents.js +21 -14
  144. package/dist/core/subagents.js.map +1 -1
  145. package/dist/core/system-prompt.d.ts +0 -11
  146. package/dist/core/system-prompt.d.ts.map +1 -1
  147. package/dist/core/system-prompt.js +168 -139
  148. package/dist/core/system-prompt.js.map +1 -1
  149. package/dist/core/timings.d.ts +1 -4
  150. package/dist/core/timings.d.ts.map +1 -1
  151. package/dist/core/timings.js +34 -18
  152. package/dist/core/timings.js.map +1 -1
  153. package/dist/core/todo-store.d.ts +20 -0
  154. package/dist/core/todo-store.d.ts.map +1 -0
  155. package/dist/core/todo-store.js +60 -0
  156. package/dist/core/todo-store.js.map +1 -0
  157. package/dist/core/tools/bash.d.ts +2 -0
  158. package/dist/core/tools/bash.d.ts.map +1 -0
  159. package/dist/core/tools/bash.js +2 -0
  160. package/dist/core/tools/bash.js.map +1 -0
  161. package/dist/core/tools/bg-process.d.ts +1 -6
  162. package/dist/core/tools/bg-process.d.ts.map +1 -1
  163. package/dist/core/tools/bg-process.js +4 -18
  164. package/dist/core/tools/bg-process.js.map +1 -1
  165. package/dist/core/tools/edit-diff.d.ts +9 -0
  166. package/dist/core/tools/edit-diff.d.ts.map +1 -0
  167. package/dist/core/tools/edit-diff.js +2 -0
  168. package/dist/core/tools/edit-diff.js.map +1 -0
  169. package/dist/core/tools/edit.d.ts +2 -0
  170. package/dist/core/tools/edit.d.ts.map +1 -0
  171. package/dist/core/tools/edit.js +2 -0
  172. package/dist/core/tools/edit.js.map +1 -0
  173. package/dist/core/tools/find.d.ts +2 -0
  174. package/dist/core/tools/find.d.ts.map +1 -0
  175. package/dist/core/tools/find.js +2 -0
  176. package/dist/core/tools/find.js.map +1 -0
  177. package/dist/core/tools/grep.d.ts +2 -0
  178. package/dist/core/tools/grep.d.ts.map +1 -0
  179. package/dist/core/tools/grep.js +2 -0
  180. package/dist/core/tools/grep.js.map +1 -0
  181. package/dist/core/tools/index.d.ts +7 -1
  182. package/dist/core/tools/index.d.ts.map +1 -1
  183. package/dist/core/tools/ls.d.ts +2 -0
  184. package/dist/core/tools/ls.d.ts.map +1 -0
  185. package/dist/core/tools/ls.js +2 -0
  186. package/dist/core/tools/ls.js.map +1 -0
  187. package/dist/core/tools/path-utils.d.ts +2 -0
  188. package/dist/core/tools/path-utils.d.ts.map +1 -0
  189. package/dist/core/tools/path-utils.js +2 -0
  190. package/dist/core/tools/path-utils.js.map +1 -0
  191. package/dist/core/tools/read.d.ts +2 -0
  192. package/dist/core/tools/read.d.ts.map +1 -0
  193. package/dist/core/tools/read.js +2 -0
  194. package/dist/core/tools/read.js.map +1 -0
  195. package/dist/core/tools/registry.d.ts +0 -15
  196. package/dist/core/tools/registry.d.ts.map +1 -1
  197. package/dist/core/tools/registry.js +13 -37
  198. package/dist/core/tools/registry.js.map +1 -1
  199. package/dist/core/tools/task.d.ts +17 -23
  200. package/dist/core/tools/task.d.ts.map +1 -1
  201. package/dist/core/tools/task.js +43 -82
  202. package/dist/core/tools/task.js.map +1 -1
  203. package/dist/core/tools/todo.d.ts +17 -20
  204. package/dist/core/tools/todo.d.ts.map +1 -1
  205. package/dist/core/tools/todo.js +79 -58
  206. package/dist/core/tools/todo.js.map +1 -1
  207. package/dist/core/tools/truncate.d.ts +2 -0
  208. package/dist/core/tools/truncate.d.ts.map +1 -0
  209. package/dist/core/tools/truncate.js +2 -0
  210. package/dist/core/tools/truncate.js.map +1 -0
  211. package/dist/core/tools/webfetch.d.ts +2 -0
  212. package/dist/core/tools/webfetch.d.ts.map +1 -0
  213. package/dist/core/tools/webfetch.js +2 -0
  214. package/dist/core/tools/webfetch.js.map +1 -0
  215. package/dist/core/tools/websearch.d.ts +2 -0
  216. package/dist/core/tools/websearch.d.ts.map +1 -0
  217. package/dist/core/tools/websearch.js +2 -0
  218. package/dist/core/tools/websearch.js.map +1 -0
  219. package/dist/core/tools/write.d.ts +2 -0
  220. package/dist/core/tools/write.d.ts.map +1 -0
  221. package/dist/core/tools/write.js +2 -0
  222. package/dist/core/tools/write.js.map +1 -0
  223. package/dist/index.d.ts +35 -29
  224. package/dist/index.d.ts.map +1 -1
  225. package/dist/index.js +33 -41
  226. package/dist/index.js.map +1 -1
  227. package/dist/main.d.ts.map +1 -1
  228. package/dist/main.js +237 -225
  229. package/dist/main.js.map +1 -1
  230. package/dist/migrations.d.ts +0 -25
  231. package/dist/migrations.d.ts.map +1 -1
  232. package/dist/migrations.js +129 -180
  233. package/dist/migrations.js.map +1 -1
  234. package/dist/modes/index.d.ts +13 -6
  235. package/dist/modes/index.d.ts.map +1 -1
  236. package/dist/modes/index.js +11 -5
  237. package/dist/modes/index.js.map +1 -1
  238. package/dist/modes/interactive/components/armin.d.ts +8 -23
  239. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  240. package/dist/modes/interactive/components/armin.js +217 -266
  241. package/dist/modes/interactive/components/armin.js.map +1 -1
  242. package/dist/modes/interactive/components/assistant-message.d.ts +2 -168
  243. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  244. package/dist/modes/interactive/components/assistant-message.js +61 -216
  245. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  246. package/dist/modes/interactive/components/bash-execution.d.ts +6 -313
  247. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  248. package/dist/modes/interactive/components/bash-execution.js +86 -403
  249. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  250. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -3
  251. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  252. package/dist/modes/interactive/components/bordered-loader.js +59 -29
  253. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  254. package/dist/modes/interactive/components/branch-summary-message.d.ts +3 -3
  255. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  256. package/dist/modes/interactive/components/branch-summary-message.js +30 -17
  257. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  258. package/dist/modes/interactive/components/compaction-summary-message.d.ts +3 -3
  259. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  260. package/dist/modes/interactive/components/compaction-summary-message.js +35 -18
  261. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  262. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  263. package/dist/modes/interactive/components/config-selector.js +60 -68
  264. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  265. package/dist/modes/interactive/components/countdown-timer.d.ts +2 -6
  266. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  267. package/dist/modes/interactive/components/countdown-timer.js +32 -18
  268. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  269. package/dist/modes/interactive/components/custom-editor.d.ts +1 -5
  270. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  271. package/dist/modes/interactive/components/custom-editor.js +45 -37
  272. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  273. package/dist/modes/interactive/components/custom-message.d.ts +5 -6
  274. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  275. package/dist/modes/interactive/components/custom-message.js +43 -53
  276. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  277. package/dist/modes/interactive/components/diff.d.ts +0 -3
  278. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  279. package/dist/modes/interactive/components/diff.js +101 -108
  280. package/dist/modes/interactive/components/diff.js.map +1 -1
  281. package/dist/modes/interactive/components/dynamic-border.d.ts +7 -2
  282. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  283. package/dist/modes/interactive/components/dynamic-border.js +24 -4
  284. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  285. package/dist/modes/interactive/components/extension-editor.d.ts +5 -9
  286. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  287. package/dist/modes/interactive/components/extension-editor.js +43 -46
  288. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  289. package/dist/modes/interactive/components/extension-input.d.ts +4 -9
  290. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  291. package/dist/modes/interactive/components/extension-input.js +45 -28
  292. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  293. package/dist/modes/interactive/components/extension-selector.d.ts +7 -12
  294. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  295. package/dist/modes/interactive/components/extension-selector.js +54 -32
  296. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  297. package/dist/modes/interactive/components/footer.d.ts +2 -11
  298. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  299. package/dist/modes/interactive/components/footer.js +135 -183
  300. package/dist/modes/interactive/components/footer.js.map +1 -1
  301. package/dist/modes/interactive/components/index.d.ts +79 -30
  302. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  303. package/dist/modes/interactive/components/index.js +73 -31
  304. package/dist/modes/interactive/components/index.js.map +1 -1
  305. package/dist/modes/interactive/components/keybinding-hints.d.ts +0 -18
  306. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  307. package/dist/modes/interactive/components/keybinding-hints.js +24 -31
  308. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  309. package/dist/modes/interactive/components/login-dialog.d.ts +11 -24
  310. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  311. package/dist/modes/interactive/components/login-dialog.js +89 -86
  312. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  313. package/dist/modes/interactive/components/model-selector.d.ts +15 -19
  314. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  315. package/dist/modes/interactive/components/model-selector.js +104 -157
  316. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  317. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  318. package/dist/modes/interactive/components/oauth-selector.js +5 -5
  319. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  320. package/dist/modes/interactive/components/scoped-models-selector.d.ts +12 -22
  321. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  322. package/dist/modes/interactive/components/scoped-models-selector.js +111 -132
  323. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  324. package/dist/modes/interactive/components/session-selector-search.d.ts +3 -3
  325. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  326. package/dist/modes/interactive/components/session-selector-search.js +92 -103
  327. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  328. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  329. package/dist/modes/interactive/components/session-selector.js +28 -39
  330. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  331. package/dist/modes/interactive/components/settings-selector.d.ts +1 -1
  332. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  333. package/dist/modes/interactive/components/settings-selector.js +111 -203
  334. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  335. package/dist/modes/interactive/components/show-images-selector.d.ts +1 -1
  336. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  337. package/dist/modes/interactive/components/show-images-selector.js +17 -19
  338. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  339. package/dist/modes/interactive/components/skill-invocation-message.d.ts +3 -3
  340. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  341. package/dist/modes/interactive/components/skill-invocation-message.js +29 -19
  342. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  343. package/dist/modes/interactive/components/theme-selector.d.ts +2 -2
  344. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  345. package/dist/modes/interactive/components/theme-selector.js +20 -25
  346. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  347. package/dist/modes/interactive/components/thinking-selector.d.ts +1 -1
  348. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  349. package/dist/modes/interactive/components/thinking-selector.js +19 -20
  350. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  351. package/dist/modes/interactive/components/tool-execution.d.ts +12 -10
  352. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  353. package/dist/modes/interactive/components/tool-execution.js +14 -8
  354. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  355. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  356. package/dist/modes/interactive/components/tree-selector.js +53 -60
  357. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  358. package/dist/modes/interactive/components/user-message-selector.d.ts +3 -9
  359. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  360. package/dist/modes/interactive/components/user-message-selector.js +57 -68
  361. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  362. package/dist/modes/interactive/components/visual-truncate.d.ts +0 -12
  363. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  364. package/dist/modes/interactive/components/visual-truncate.js +14 -22
  365. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  366. package/dist/modes/interactive/interactive-mode.d.ts +6 -0
  367. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  368. package/dist/modes/interactive/interactive-mode.js +118 -113
  369. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  370. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  371. package/dist/modes/interactive/theme/theme.js +189 -39
  372. package/dist/modes/interactive/theme/theme.js.map +1 -1
  373. package/dist/modes/rpc/rpc-client.d.ts +8 -1
  374. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  375. package/dist/modes/rpc/rpc-client.js +88 -59
  376. package/dist/modes/rpc/rpc-client.js.map +1 -1
  377. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  378. package/dist/modes/rpc/rpc-mode.js +24 -46
  379. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  380. package/dist/modes/rpc/rpc-types.d.ts +75 -409
  381. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  382. package/dist/modes/rpc/rpc-types.js +21 -360
  383. package/dist/modes/rpc/rpc-types.js.map +1 -1
  384. package/dist/observability/core/config.d.ts +28 -0
  385. package/dist/observability/core/config.d.ts.map +1 -0
  386. package/dist/observability/core/config.js +150 -0
  387. package/dist/observability/core/config.js.map +1 -0
  388. package/dist/observability/core/event-bus.d.ts +15 -0
  389. package/dist/observability/core/event-bus.d.ts.map +1 -0
  390. package/dist/observability/core/event-bus.js +37 -0
  391. package/dist/observability/core/event-bus.js.map +1 -0
  392. package/dist/observability/core/index.d.ts +12 -0
  393. package/dist/observability/core/index.d.ts.map +1 -0
  394. package/dist/observability/core/index.js +14 -0
  395. package/dist/observability/core/index.js.map +1 -0
  396. package/dist/observability/core/observability.d.ts +63 -0
  397. package/dist/observability/core/observability.d.ts.map +1 -0
  398. package/dist/observability/core/observability.js +127 -0
  399. package/dist/observability/core/observability.js.map +1 -0
  400. package/dist/observability/core/span.d.ts +37 -0
  401. package/dist/observability/core/span.d.ts.map +1 -0
  402. package/dist/observability/core/span.js +90 -0
  403. package/dist/observability/core/span.js.map +1 -0
  404. package/dist/observability/core/tracer.d.ts +22 -0
  405. package/dist/observability/core/tracer.d.ts.map +1 -0
  406. package/dist/observability/core/tracer.js +79 -0
  407. package/dist/observability/core/tracer.js.map +1 -0
  408. package/dist/observability/core/types.d.ts +155 -0
  409. package/dist/observability/core/types.d.ts.map +1 -0
  410. package/dist/observability/core/types.js +38 -0
  411. package/dist/observability/core/types.js.map +1 -0
  412. package/dist/observability/exporters/base-exporter.d.ts +16 -0
  413. package/dist/observability/exporters/base-exporter.d.ts.map +1 -0
  414. package/dist/observability/exporters/base-exporter.js +26 -0
  415. package/dist/observability/exporters/base-exporter.js.map +1 -0
  416. package/dist/observability/exporters/console-exporter.d.ts +22 -0
  417. package/dist/observability/exporters/console-exporter.d.ts.map +1 -0
  418. package/dist/observability/exporters/console-exporter.js +80 -0
  419. package/dist/observability/exporters/console-exporter.js.map +1 -0
  420. package/dist/observability/exporters/file-exporter.d.ts +31 -0
  421. package/dist/observability/exporters/file-exporter.d.ts.map +1 -0
  422. package/dist/observability/exporters/file-exporter.js +120 -0
  423. package/dist/observability/exporters/file-exporter.js.map +1 -0
  424. package/dist/observability/exporters/index.d.ts +12 -0
  425. package/dist/observability/exporters/index.d.ts.map +1 -0
  426. package/dist/observability/exporters/index.js +11 -0
  427. package/dist/observability/exporters/index.js.map +1 -0
  428. package/dist/observability/exporters/langfuse-exporter.d.ts +27 -0
  429. package/dist/observability/exporters/langfuse-exporter.d.ts.map +1 -0
  430. package/dist/observability/exporters/langfuse-exporter.js +146 -0
  431. package/dist/observability/exporters/langfuse-exporter.js.map +1 -0
  432. package/dist/observability/exporters/sentry-exporter.d.ts +22 -0
  433. package/dist/observability/exporters/sentry-exporter.d.ts.map +1 -0
  434. package/dist/observability/exporters/sentry-exporter.js +121 -0
  435. package/dist/observability/exporters/sentry-exporter.js.map +1 -0
  436. package/dist/observability/index.d.ts +3 -0
  437. package/dist/observability/index.d.ts.map +1 -0
  438. package/dist/observability/index.js +3 -0
  439. package/dist/observability/index.js.map +1 -0
  440. package/dist/utils/changelog.d.ts +1 -2
  441. package/dist/utils/changelog.d.ts.map +1 -1
  442. package/dist/utils/changelog.js +53 -61
  443. package/dist/utils/changelog.js.map +1 -1
  444. package/dist/utils/clipboard-image.d.ts.map +1 -1
  445. package/dist/utils/clipboard-image.js +77 -83
  446. package/dist/utils/clipboard-image.js.map +1 -1
  447. package/dist/utils/clipboard.d.ts.map +1 -1
  448. package/dist/utils/clipboard.js +62 -49
  449. package/dist/utils/clipboard.js.map +1 -1
  450. package/dist/utils/image-convert.d.ts +6 -6
  451. package/dist/utils/image-convert.d.ts.map +1 -1
  452. package/dist/utils/image-convert.js +29 -23
  453. package/dist/utils/image-convert.js.map +1 -1
  454. package/dist/utils/image-resize.d.ts +0 -17
  455. package/dist/utils/image-resize.d.ts.map +1 -1
  456. package/dist/utils/image-resize.js +100 -138
  457. package/dist/utils/image-resize.js.map +1 -1
  458. package/dist/utils/mime.d.ts +1 -0
  459. package/dist/utils/mime.d.ts.map +1 -1
  460. package/dist/utils/mime.js +35 -15
  461. package/dist/utils/mime.js.map +1 -1
  462. package/dist/utils/photon.d.ts +4 -15
  463. package/dist/utils/photon.d.ts.map +1 -1
  464. package/dist/utils/photon.js +71 -60
  465. package/dist/utils/photon.js.map +1 -1
  466. package/dist/utils/shell.d.ts +4 -21
  467. package/dist/utils/shell.d.ts.map +1 -1
  468. package/dist/utils/shell.js +101 -124
  469. package/dist/utils/shell.js.map +1 -1
  470. package/dist/utils/sleep.d.ts +1 -1
  471. package/dist/utils/sleep.d.ts.map +1 -1
  472. package/dist/utils/sleep.js +32 -8
  473. package/dist/utils/sleep.js.map +1 -1
  474. package/dist/utils/tools-manager.d.ts +4 -2
  475. package/dist/utils/tools-manager.d.ts.map +1 -1
  476. package/dist/utils/tools-manager.js +96 -122
  477. package/dist/utils/tools-manager.js.map +1 -1
  478. package/docs/PI_MONO_MIT_REMOVAL_GUIDE.md +2132 -0
  479. package/docs/SAME_TO_SAME_PARITY_REPORT.md +312 -0
  480. package/examples/README.md +12 -0
  481. package/package.json +60 -88
  482. package/LICENSE.md +0 -22
  483. package/dist/modes/interactive/theme/dark.json +0 -85
  484. package/dist/modes/interactive/theme/light.json +0 -84
  485. package/dist/modes/interactive/theme/theme-schema.json +0 -335
  486. package/docs/FEATURES.md +0 -306
  487. package/docs/MCP.md +0 -341
  488. package/docs/MEMORY.md +0 -443
  489. package/examples/mcp-servers.example.json +0 -50
@@ -1,253 +1,50 @@
1
1
  import { spawn, spawnSync } from "node:child_process";
2
2
  import { createHash } from "node:crypto";
3
3
  import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
4
- import { homedir, tmpdir } from "node:os";
4
+ import { tmpdir } from "node:os";
5
5
  import { basename, dirname, join, relative, resolve } from "node:path";
6
6
  import { minimatch } from "minimatch";
7
7
  import { CONFIG_DIR_NAME } from "../config.js";
8
- import { looksLikeGitUrl } from "../utils/git.js";
9
8
  const RESOURCE_TYPES = ["extensions", "hooks", "skills", "prompts", "themes"];
10
9
  const FILE_PATTERNS = {
11
- extensions: /\.(ts|js)$/,
12
- hooks: /\.(ts|js)$/,
10
+ extensions: /\.(ts|js|mjs|cjs)$/,
11
+ hooks: /\.(ts|js|mjs|cjs)$/,
13
12
  skills: /\.md$/,
14
13
  prompts: /\.md$/,
15
14
  themes: /\.json$/,
16
15
  };
17
- function isPattern(s) {
18
- return s.startsWith("!") || s.startsWith("+") || s.startsWith("-") || s.includes("*") || s.includes("?");
16
+ function looksLikeGitUrl(source) {
17
+ const normalized = source.replace(/^https?:\/\//, "");
18
+ return ["github.com", "gitlab.com", "bitbucket.org", "codeberg.org"].some((host) => normalized.startsWith(`${host}/`));
19
19
  }
20
- function splitPatterns(entries) {
21
- const plain = [];
22
- const patterns = [];
23
- for (const entry of entries) {
24
- if (isPattern(entry)) {
25
- patterns.push(entry);
26
- }
27
- else {
28
- plain.push(entry);
29
- }
30
- }
31
- return { plain, patterns };
32
- }
33
- function collectFiles(dir, filePattern, skipNodeModules = true) {
34
- const files = [];
35
- if (!existsSync(dir))
36
- return files;
20
+ function readManifest(packageJsonPath) {
37
21
  try {
38
- const entries = readdirSync(dir, { withFileTypes: true });
39
- for (const entry of entries) {
40
- if (entry.name.startsWith("."))
41
- continue;
42
- if (skipNodeModules && entry.name === "node_modules")
43
- continue;
44
- const fullPath = join(dir, entry.name);
45
- let isDir = entry.isDirectory();
46
- let isFile = entry.isFile();
47
- if (entry.isSymbolicLink()) {
48
- try {
49
- const stats = statSync(fullPath);
50
- isDir = stats.isDirectory();
51
- isFile = stats.isFile();
52
- }
53
- catch {
54
- continue;
55
- }
56
- }
57
- if (isDir) {
58
- files.push(...collectFiles(fullPath, filePattern, skipNodeModules));
59
- }
60
- else if (isFile && filePattern.test(entry.name)) {
61
- files.push(fullPath);
62
- }
63
- }
22
+ const parsed = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
23
+ return parsed.indusagi ?? null;
64
24
  }
65
25
  catch {
66
- // Ignore errors
26
+ return null;
67
27
  }
68
- return files;
69
28
  }
70
- function collectSkillEntries(dir, includeRootFiles = true) {
71
- const entries = [];
72
- if (!existsSync(dir))
73
- return entries;
29
+ function safeReaddir(dir) {
74
30
  try {
75
- const dirEntries = readdirSync(dir, { withFileTypes: true });
76
- for (const entry of dirEntries) {
77
- if (entry.name.startsWith("."))
78
- continue;
79
- if (entry.name === "node_modules")
80
- continue;
81
- const fullPath = join(dir, entry.name);
82
- let isDir = entry.isDirectory();
83
- let isFile = entry.isFile();
84
- if (entry.isSymbolicLink()) {
85
- try {
86
- const stats = statSync(fullPath);
87
- isDir = stats.isDirectory();
88
- isFile = stats.isFile();
89
- }
90
- catch {
91
- continue;
92
- }
93
- }
94
- if (isDir) {
95
- entries.push(...collectSkillEntries(fullPath, false));
96
- }
97
- else if (isFile) {
98
- const isRootMd = includeRootFiles && entry.name.endsWith(".md");
99
- const isSkillMd = !includeRootFiles && entry.name === "SKILL.md";
100
- if (isRootMd || isSkillMd) {
101
- entries.push(fullPath);
102
- }
103
- }
104
- }
31
+ return readdirSync(dir);
105
32
  }
106
33
  catch {
107
- // Ignore errors
34
+ return [];
108
35
  }
109
- return entries;
110
- }
111
- function collectAutoSkillEntries(dir, includeRootFiles = true) {
112
- return collectSkillEntries(dir, includeRootFiles);
113
36
  }
114
- function collectAutoPromptEntries(dir) {
115
- const entries = [];
116
- if (!existsSync(dir))
117
- return entries;
118
- try {
119
- const dirEntries = readdirSync(dir, { withFileTypes: true });
120
- for (const entry of dirEntries) {
121
- if (entry.name.startsWith("."))
122
- continue;
123
- if (entry.name === "node_modules")
124
- continue;
125
- const fullPath = join(dir, entry.name);
126
- let isFile = entry.isFile();
127
- if (entry.isSymbolicLink()) {
128
- try {
129
- isFile = statSync(fullPath).isFile();
130
- }
131
- catch {
132
- continue;
133
- }
134
- }
135
- if (isFile && entry.name.endsWith(".md")) {
136
- entries.push(fullPath);
137
- }
138
- }
37
+ function collectFiles(dir, filePattern) {
38
+ if (!existsSync(dir)) {
39
+ return [];
139
40
  }
140
- catch {
141
- // Ignore errors
142
- }
143
- return entries;
144
- }
145
- function collectAutoThemeEntries(dir) {
146
- const entries = [];
147
- if (!existsSync(dir))
148
- return entries;
41
+ const results = [];
149
42
  try {
150
- const dirEntries = readdirSync(dir, { withFileTypes: true });
151
- for (const entry of dirEntries) {
152
- if (entry.name.startsWith("."))
153
- continue;
154
- if (entry.name === "node_modules")
43
+ const entries = readdirSync(dir, { withFileTypes: true });
44
+ for (const entry of entries) {
45
+ if (entry.name.startsWith(".") || entry.name === "node_modules") {
155
46
  continue;
156
- const fullPath = join(dir, entry.name);
157
- let isFile = entry.isFile();
158
- if (entry.isSymbolicLink()) {
159
- try {
160
- isFile = statSync(fullPath).isFile();
161
- }
162
- catch {
163
- continue;
164
- }
165
- }
166
- if (isFile && entry.name.endsWith(".json")) {
167
- entries.push(fullPath);
168
- }
169
- }
170
- }
171
- catch {
172
- // Ignore errors
173
- }
174
- return entries;
175
- }
176
- function readIndusagiManifestFile(packageJsonPath) {
177
- try {
178
- const content = readFileSync(packageJsonPath, "utf-8");
179
- const pkg = JSON.parse(content);
180
- return pkg.indusagi ?? null;
181
- }
182
- catch {
183
- return null;
184
- }
185
- }
186
- function resolveExtensionEntries(dir) {
187
- const packageJsonPath = join(dir, "package.json");
188
- if (existsSync(packageJsonPath)) {
189
- const manifest = readIndusagiManifestFile(packageJsonPath);
190
- if (manifest?.extensions?.length) {
191
- const entries = [];
192
- for (const extPath of manifest.extensions) {
193
- const resolvedExtPath = resolve(dir, extPath);
194
- if (existsSync(resolvedExtPath)) {
195
- entries.push(resolvedExtPath);
196
- }
197
47
  }
198
- if (entries.length > 0) {
199
- return entries;
200
- }
201
- }
202
- }
203
- const indexTs = join(dir, "index.ts");
204
- const indexJs = join(dir, "index.js");
205
- if (existsSync(indexTs)) {
206
- return [indexTs];
207
- }
208
- if (existsSync(indexJs)) {
209
- return [indexJs];
210
- }
211
- return null;
212
- }
213
- function resolveHookEntries(dir) {
214
- const packageJsonPath = join(dir, "package.json");
215
- if (existsSync(packageJsonPath)) {
216
- const manifest = readIndusagiManifestFile(packageJsonPath);
217
- if (manifest?.hooks?.length) {
218
- const entries = [];
219
- for (const hookPath of manifest.hooks) {
220
- const resolvedHookPath = resolve(dir, hookPath);
221
- if (existsSync(resolvedHookPath)) {
222
- entries.push(resolvedHookPath);
223
- }
224
- }
225
- if (entries.length > 0) {
226
- return entries;
227
- }
228
- }
229
- }
230
- const indexTs = join(dir, "index.ts");
231
- const indexJs = join(dir, "index.js");
232
- if (existsSync(indexTs)) {
233
- return [indexTs];
234
- }
235
- if (existsSync(indexJs)) {
236
- return [indexJs];
237
- }
238
- return null;
239
- }
240
- function collectAutoExtensionEntries(dir) {
241
- const entries = [];
242
- if (!existsSync(dir))
243
- return entries;
244
- try {
245
- const dirEntries = readdirSync(dir, { withFileTypes: true });
246
- for (const entry of dirEntries) {
247
- if (entry.name.startsWith("."))
248
- continue;
249
- if (entry.name === "node_modules")
250
- continue;
251
48
  const fullPath = join(dir, entry.name);
252
49
  let isDir = entry.isDirectory();
253
50
  let isFile = entry.isFile();
@@ -261,33 +58,30 @@ function collectAutoExtensionEntries(dir) {
261
58
  continue;
262
59
  }
263
60
  }
264
- if (isFile && (entry.name.endsWith(".ts") || entry.name.endsWith(".js"))) {
265
- entries.push(fullPath);
61
+ if (isDir) {
62
+ results.push(...collectFiles(fullPath, filePattern));
266
63
  }
267
- else if (isDir) {
268
- const resolvedEntries = resolveExtensionEntries(fullPath);
269
- if (resolvedEntries) {
270
- entries.push(...resolvedEntries);
271
- }
64
+ else if (isFile && filePattern.test(entry.name)) {
65
+ results.push(fullPath);
272
66
  }
273
67
  }
274
68
  }
275
69
  catch {
276
- // Ignore errors
70
+ return results;
277
71
  }
278
- return entries;
72
+ return results;
279
73
  }
280
- function collectAutoHookEntries(dir) {
281
- const entries = [];
282
- if (!existsSync(dir))
283
- return entries;
74
+ function collectSkillEntries(dir, includeRootFiles = true) {
75
+ if (!existsSync(dir)) {
76
+ return [];
77
+ }
78
+ const results = [];
284
79
  try {
285
- const dirEntries = readdirSync(dir, { withFileTypes: true });
286
- for (const entry of dirEntries) {
287
- if (entry.name.startsWith("."))
288
- continue;
289
- if (entry.name === "node_modules")
80
+ const entries = readdirSync(dir, { withFileTypes: true });
81
+ for (const entry of entries) {
82
+ if (entry.name.startsWith(".") || entry.name === "node_modules") {
290
83
  continue;
84
+ }
291
85
  const fullPath = join(dir, entry.name);
292
86
  let isDir = entry.isDirectory();
293
87
  let isFile = entry.isFile();
@@ -301,134 +95,40 @@ function collectAutoHookEntries(dir) {
301
95
  continue;
302
96
  }
303
97
  }
304
- if (isFile && (entry.name.endsWith(".ts") || entry.name.endsWith(".js"))) {
305
- entries.push(fullPath);
98
+ if (isDir) {
99
+ results.push(...collectSkillEntries(fullPath, false));
306
100
  }
307
- else if (isDir) {
308
- const resolvedEntries = resolveHookEntries(fullPath);
309
- if (resolvedEntries) {
310
- entries.push(...resolvedEntries);
101
+ else if (isFile) {
102
+ const isRootMd = includeRootFiles && entry.name.endsWith(".md");
103
+ const isSkillMd = !includeRootFiles && entry.name === "SKILL.md";
104
+ if (isRootMd || isSkillMd) {
105
+ results.push(fullPath);
311
106
  }
312
107
  }
313
108
  }
314
109
  }
315
110
  catch {
316
- // Ignore errors
111
+ return results;
317
112
  }
318
- return entries;
113
+ return results;
319
114
  }
320
- function matchesAnyPattern(filePath, patterns, baseDir) {
321
- const rel = relative(baseDir, filePath);
322
- const name = basename(filePath);
323
- const isSkillFile = name === "SKILL.md";
324
- const parentDir = isSkillFile ? dirname(filePath) : undefined;
325
- const parentRel = isSkillFile ? relative(baseDir, parentDir) : undefined;
326
- const parentName = isSkillFile ? basename(parentDir) : undefined;
327
- return patterns.some((pattern) => {
328
- if (minimatch(rel, pattern) || minimatch(name, pattern) || minimatch(filePath, pattern)) {
329
- return true;
330
- }
331
- if (!isSkillFile)
332
- return false;
333
- return minimatch(parentRel, pattern) || minimatch(parentName, pattern) || minimatch(parentDir, pattern);
334
- });
335
- }
336
- function normalizeExactPattern(pattern) {
337
- if (pattern.startsWith("./") || pattern.startsWith(".\\")) {
338
- return pattern.slice(2);
115
+ function matchesFilter(filePath, baseDir, patterns) {
116
+ if (!patterns || patterns.length === 0) {
117
+ return true;
339
118
  }
340
- return pattern;
341
- }
342
- function matchesAnyExactPattern(filePath, patterns, baseDir) {
343
- if (patterns.length === 0)
344
- return false;
345
119
  const rel = relative(baseDir, filePath);
346
120
  const name = basename(filePath);
347
- const isSkillFile = name === "SKILL.md";
348
- const parentDir = isSkillFile ? dirname(filePath) : undefined;
349
- const parentRel = isSkillFile ? relative(baseDir, parentDir) : undefined;
350
121
  return patterns.some((pattern) => {
351
- const normalized = normalizeExactPattern(pattern);
352
- if (normalized === rel || normalized === filePath) {
353
- return true;
354
- }
355
- if (!isSkillFile)
356
- return false;
357
- return normalized === parentRel || normalized === parentDir;
122
+ const normalized = pattern.replace(/^\.\//, "");
123
+ return (minimatch(rel, normalized, { nocase: true }) ||
124
+ minimatch(name, normalized, { nocase: true }) ||
125
+ minimatch(filePath, normalized, { nocase: true }) ||
126
+ rel === normalized ||
127
+ name === normalized);
358
128
  });
359
129
  }
360
- function getOverridePatterns(entries) {
361
- return entries.filter((pattern) => pattern.startsWith("!") || pattern.startsWith("+") || pattern.startsWith("-"));
362
- }
363
- function isEnabledByOverrides(filePath, patterns, baseDir) {
364
- const overrides = getOverridePatterns(patterns);
365
- const excludes = overrides.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
366
- const forceIncludes = overrides.filter((pattern) => pattern.startsWith("+")).map((pattern) => pattern.slice(1));
367
- const forceExcludes = overrides.filter((pattern) => pattern.startsWith("-")).map((pattern) => pattern.slice(1));
368
- let enabled = true;
369
- if (excludes.length > 0 && matchesAnyPattern(filePath, excludes, baseDir)) {
370
- enabled = false;
371
- }
372
- if (forceIncludes.length > 0 && matchesAnyExactPattern(filePath, forceIncludes, baseDir)) {
373
- enabled = true;
374
- }
375
- if (forceExcludes.length > 0 && matchesAnyExactPattern(filePath, forceExcludes, baseDir)) {
376
- enabled = false;
377
- }
378
- return enabled;
379
- }
380
- /**
381
- * Apply patterns to paths and return a Set of enabled paths.
382
- * Pattern types:
383
- * - Plain patterns: include matching paths
384
- * - `!pattern`: exclude matching paths
385
- * - `+path`: force-include exact path (overrides exclusions)
386
- * - `-path`: force-exclude exact path (overrides force-includes)
387
- */
388
- function applyPatterns(allPaths, patterns, baseDir) {
389
- const includes = [];
390
- const excludes = [];
391
- const forceIncludes = [];
392
- const forceExcludes = [];
393
- for (const p of patterns) {
394
- if (p.startsWith("+")) {
395
- forceIncludes.push(p.slice(1));
396
- }
397
- else if (p.startsWith("-")) {
398
- forceExcludes.push(p.slice(1));
399
- }
400
- else if (p.startsWith("!")) {
401
- excludes.push(p.slice(1));
402
- }
403
- else {
404
- includes.push(p);
405
- }
406
- }
407
- // Step 1: Apply includes (or all if no includes)
408
- let result;
409
- if (includes.length === 0) {
410
- result = [...allPaths];
411
- }
412
- else {
413
- result = allPaths.filter((filePath) => matchesAnyPattern(filePath, includes, baseDir));
414
- }
415
- // Step 2: Apply excludes
416
- if (excludes.length > 0) {
417
- result = result.filter((filePath) => !matchesAnyPattern(filePath, excludes, baseDir));
418
- }
419
- // Step 3: Force-include (add back from allPaths, overriding exclusions)
420
- if (forceIncludes.length > 0) {
421
- for (const filePath of allPaths) {
422
- if (!result.includes(filePath) && matchesAnyExactPattern(filePath, forceIncludes, baseDir)) {
423
- result.push(filePath);
424
- }
425
- }
426
- }
427
- // Step 4: Force-exclude (remove even if included or force-included)
428
- if (forceExcludes.length > 0) {
429
- result = result.filter((filePath) => !matchesAnyExactPattern(filePath, forceExcludes, baseDir));
430
- }
431
- return new Set(result);
130
+ function pickPatterns(filter, resourceType) {
131
+ return filter?.[resourceType];
432
132
  }
433
133
  export class DefaultPackageManager {
434
134
  constructor(options) {
@@ -441,40 +141,21 @@ export class DefaultPackageManager {
441
141
  }
442
142
  getInstalledPath(source, scope) {
443
143
  const parsed = this.parseSource(source);
444
- if (parsed.type === "npm") {
445
- const path = this.getNpmInstallPath(parsed, scope);
446
- return existsSync(path) ? path : undefined;
447
- }
448
- if (parsed.type === "git") {
449
- const path = this.getGitInstallPath(parsed, scope);
450
- return existsSync(path) ? path : undefined;
451
- }
452
144
  if (parsed.type === "local") {
453
- const path = this.resolvePath(parsed.path);
454
- return existsSync(path) ? path : undefined;
455
- }
456
- return undefined;
457
- }
458
- emitProgress(event) {
459
- this.progressCallback?.(event);
460
- }
461
- async withProgress(action, source, message, operation) {
462
- this.emitProgress({ type: "start", action, source, message });
463
- try {
464
- await operation();
465
- this.emitProgress({ type: "complete", action, source });
145
+ const resolved = this.resolveLocalPath(parsed.path);
146
+ return existsSync(resolved) ? resolved : undefined;
466
147
  }
467
- catch (error) {
468
- const errorMessage = error instanceof Error ? error.message : String(error);
469
- this.emitProgress({ type: "error", action, source, message: errorMessage });
470
- throw error;
148
+ if (parsed.type === "npm") {
149
+ const installedPath = this.getNpmInstallPath(parsed, scope);
150
+ return existsSync(installedPath) ? installedPath : undefined;
471
151
  }
152
+ const installedPath = this.getGitInstallPath(parsed, scope);
153
+ return existsSync(installedPath) ? installedPath : undefined;
472
154
  }
473
155
  async resolve(onMissing) {
474
156
  const accumulator = this.createAccumulator();
475
157
  const globalSettings = this.settingsManager.getGlobalSettings();
476
158
  const projectSettings = this.settingsManager.getProjectSettings();
477
- // Collect all packages with scope
478
159
  const allPackages = [];
479
160
  for (const pkg of globalSettings.packages ?? []) {
480
161
  allPackages.push({ pkg, scope: "user" });
@@ -482,42 +163,38 @@ export class DefaultPackageManager {
482
163
  for (const pkg of projectSettings.packages ?? []) {
483
164
  allPackages.push({ pkg, scope: "project" });
484
165
  }
485
- // Dedupe: project scope wins over global for same package identity
486
- const packageSources = this.dedupePackages(allPackages);
487
- await this.resolvePackageSources(packageSources, accumulator, onMissing);
488
- const globalBaseDir = this.agentDir;
489
- const projectBaseDir = join(this.cwd, CONFIG_DIR_NAME);
166
+ for (const entry of this.dedupePackages(allPackages)) {
167
+ await this.resolvePackageSource(entry.pkg, entry.scope, accumulator, onMissing);
168
+ }
169
+ const globalBase = this.agentDir;
170
+ const projectBase = join(this.cwd, CONFIG_DIR_NAME);
490
171
  for (const resourceType of RESOURCE_TYPES) {
491
- const target = this.getTargetMap(accumulator, resourceType);
492
- const globalEntries = (globalSettings[resourceType] ?? []);
493
- const projectEntries = (projectSettings[resourceType] ?? []);
494
- this.resolveLocalEntries(globalEntries, resourceType, target, {
495
- source: "local",
496
- scope: "user",
497
- origin: "top-level",
498
- }, globalBaseDir);
499
- this.resolveLocalEntries(projectEntries, resourceType, target, {
500
- source: "local",
501
- scope: "project",
502
- origin: "top-level",
503
- }, projectBaseDir);
172
+ this.resolveTopLevelEntries((globalSettings[resourceType] ?? []), resourceType, accumulator, { source: "local", scope: "user", origin: "top-level", baseDir: globalBase }, globalBase);
173
+ this.resolveTopLevelEntries((projectSettings[resourceType] ?? []), resourceType, accumulator, { source: "local", scope: "project", origin: "top-level", baseDir: projectBase }, projectBase);
504
174
  }
505
- this.addAutoDiscoveredResources(accumulator, globalSettings, projectSettings, globalBaseDir, projectBaseDir);
175
+ this.addConventionalResources(accumulator, this.agentDir, { source: "local", scope: "user", origin: "top-level", baseDir: this.agentDir });
176
+ this.addConventionalResources(accumulator, join(this.cwd, CONFIG_DIR_NAME), {
177
+ source: "local",
178
+ scope: "project",
179
+ origin: "top-level",
180
+ baseDir: join(this.cwd, CONFIG_DIR_NAME),
181
+ });
506
182
  return this.toResolvedPaths(accumulator);
507
183
  }
508
184
  async resolveExtensionSources(sources, options) {
509
185
  const accumulator = this.createAccumulator();
510
186
  const scope = options?.temporary ? "temporary" : options?.local ? "project" : "user";
511
- const packageSources = sources.map((source) => ({ pkg: source, scope }));
512
- await this.resolvePackageSources(packageSources, accumulator);
187
+ for (const source of sources) {
188
+ await this.resolvePackageSource(source, scope, accumulator);
189
+ }
513
190
  return this.toResolvedPaths(accumulator);
514
191
  }
515
192
  async install(source, options) {
516
193
  const parsed = this.parseSource(source);
517
194
  const scope = options?.local ? "project" : "user";
518
- await this.withProgress("install", source, `Installing ${source}...`, async () => {
195
+ await this.withProgress("install", source, async () => {
519
196
  if (parsed.type === "npm") {
520
- await this.installNpm(parsed, scope, false);
197
+ await this.installNpm(parsed, scope);
521
198
  return;
522
199
  }
523
200
  if (parsed.type === "git") {
@@ -530,13 +207,13 @@ export class DefaultPackageManager {
530
207
  async remove(source, options) {
531
208
  const parsed = this.parseSource(source);
532
209
  const scope = options?.local ? "project" : "user";
533
- await this.withProgress("remove", source, `Removing ${source}...`, async () => {
210
+ await this.withProgress("remove", source, async () => {
534
211
  if (parsed.type === "npm") {
535
212
  await this.uninstallNpm(parsed, scope);
536
213
  return;
537
214
  }
538
215
  if (parsed.type === "git") {
539
- await this.removeGit(parsed, scope);
216
+ this.removeGit(parsed, scope);
540
217
  return;
541
218
  }
542
219
  throw new Error(`Unsupported remove source: ${source}`);
@@ -550,239 +227,250 @@ export class DefaultPackageManager {
550
227
  }
551
228
  const globalSettings = this.settingsManager.getGlobalSettings();
552
229
  const projectSettings = this.settingsManager.getProjectSettings();
553
- for (const extension of globalSettings.extensions ?? []) {
554
- await this.updateSourceForScope(extension, "user");
230
+ for (const pkg of globalSettings.packages ?? []) {
231
+ await this.updateSourceForScope(typeof pkg === "string" ? pkg : pkg.source, "user");
555
232
  }
556
- for (const extension of projectSettings.extensions ?? []) {
557
- await this.updateSourceForScope(extension, "project");
233
+ for (const pkg of projectSettings.packages ?? []) {
234
+ await this.updateSourceForScope(typeof pkg === "string" ? pkg : pkg.source, "project");
558
235
  }
559
236
  }
560
- async updateSourceForScope(source, scope) {
237
+ async resolvePackageSource(pkg, scope, accumulator, onMissing) {
238
+ const source = typeof pkg === "string" ? pkg : pkg.source;
239
+ const filter = typeof pkg === "string" ? undefined : pkg;
561
240
  const parsed = this.parseSource(source);
562
- if (parsed.type === "npm") {
563
- if (parsed.pinned)
241
+ const metadata = { source, scope, origin: "package" };
242
+ if (parsed.type === "local") {
243
+ const localPath = this.resolveLocalPath(parsed.path);
244
+ if (!existsSync(localPath)) {
564
245
  return;
565
- await this.withProgress("update", source, `Updating ${source}...`, async () => {
566
- await this.installNpm(parsed, scope, false);
567
- });
246
+ }
247
+ metadata.baseDir = statSync(localPath).isDirectory() ? localPath : dirname(localPath);
248
+ this.collectSourceResources(localPath, accumulator, filter, metadata);
568
249
  return;
569
250
  }
570
- if (parsed.type === "git") {
571
- if (parsed.pinned)
251
+ const installedPath = this.getInstalledPath(source, scope === "temporary" ? "project" : scope);
252
+ if (!installedPath) {
253
+ const action = onMissing ? await onMissing(source) : "install";
254
+ if (action === "skip") {
572
255
  return;
573
- await this.withProgress("update", source, `Updating ${source}...`, async () => {
574
- await this.updateGit(parsed, scope);
575
- });
256
+ }
257
+ if (action === "error") {
258
+ throw new Error(`Missing source: ${source}`);
259
+ }
260
+ await this.installParsedSource(parsed, scope);
261
+ }
262
+ const resolvedPath = this.getInstalledPath(source, scope === "temporary" ? "project" : scope);
263
+ if (!resolvedPath) {
576
264
  return;
577
265
  }
266
+ metadata.baseDir = resolvedPath;
267
+ this.collectSourceResources(resolvedPath, accumulator, filter, metadata);
578
268
  }
579
- async resolvePackageSources(sources, accumulator, onMissing) {
580
- for (const { pkg, scope } of sources) {
581
- const sourceStr = typeof pkg === "string" ? pkg : pkg.source;
582
- const filter = typeof pkg === "object" ? pkg : undefined;
583
- const parsed = this.parseSource(sourceStr);
584
- const metadata = { source: sourceStr, scope, origin: "package" };
585
- if (parsed.type === "local") {
586
- this.resolveLocalExtensionSource(parsed, accumulator, filter, metadata);
587
- continue;
588
- }
589
- const installMissing = async () => {
590
- if (!onMissing) {
591
- await this.installParsedSource(parsed, scope);
592
- return true;
593
- }
594
- const action = await onMissing(sourceStr);
595
- if (action === "skip")
596
- return false;
597
- if (action === "error")
598
- throw new Error(`Missing source: ${sourceStr}`);
599
- await this.installParsedSource(parsed, scope);
600
- return true;
601
- };
602
- if (parsed.type === "npm") {
603
- const installedPath = this.getNpmInstallPath(parsed, scope);
604
- const needsInstall = !existsSync(installedPath) || (await this.npmNeedsUpdate(parsed, installedPath));
605
- if (needsInstall) {
606
- const installed = await installMissing();
607
- if (!installed)
608
- continue;
269
+ collectSourceResources(sourcePath, accumulator, filter, metadata) {
270
+ const stats = statSync(sourcePath);
271
+ if (stats.isFile()) {
272
+ this.addResource(accumulator.extensions, sourcePath, metadata, true);
273
+ return;
274
+ }
275
+ const manifest = readManifest(join(sourcePath, "package.json"));
276
+ const indusagiRoot = existsSync(join(sourcePath, ".indusagi")) ? join(sourcePath, ".indusagi") : sourcePath;
277
+ for (const resourceType of RESOURCE_TYPES) {
278
+ const configuredEntries = manifest?.[resourceType] ?? [];
279
+ const patterns = pickPatterns(filter, resourceType);
280
+ if (configuredEntries.length > 0) {
281
+ for (const entry of configuredEntries) {
282
+ this.addResolvedEntry(resolve(sourcePath, entry), resourceType, accumulator, { ...metadata, baseDir: sourcePath }, patterns);
609
283
  }
610
- metadata.baseDir = installedPath;
611
- this.collectPackageResources(installedPath, accumulator, filter, metadata);
612
284
  continue;
613
285
  }
614
- if (parsed.type === "git") {
615
- const installedPath = this.getGitInstallPath(parsed, scope);
616
- if (!existsSync(installedPath)) {
617
- const installed = await installMissing();
618
- if (!installed)
619
- continue;
620
- }
621
- metadata.baseDir = installedPath;
622
- this.collectPackageResources(installedPath, accumulator, filter, metadata);
623
- }
286
+ const conventionalDir = join(indusagiRoot, resourceType);
287
+ this.addResolvedEntry(conventionalDir, resourceType, accumulator, { ...metadata, baseDir: indusagiRoot }, patterns);
624
288
  }
625
289
  }
626
- resolveLocalExtensionSource(source, accumulator, filter, metadata) {
627
- const resolved = this.resolvePath(source.path);
628
- if (!existsSync(resolved)) {
290
+ addResolvedEntry(entryPath, resourceType, accumulator, metadata, patterns) {
291
+ if (!existsSync(entryPath)) {
629
292
  return;
630
293
  }
631
- try {
632
- const stats = statSync(resolved);
633
- if (stats.isFile()) {
634
- metadata.baseDir = dirname(resolved);
635
- this.addResource(accumulator.extensions, resolved, metadata, true);
636
- return;
294
+ const stats = statSync(entryPath);
295
+ if (stats.isFile()) {
296
+ if (FILE_PATTERNS[resourceType].test(basename(entryPath)) && matchesFilter(entryPath, metadata.baseDir ?? dirname(entryPath), patterns)) {
297
+ this.addResource(this.getTargetMap(accumulator, resourceType), entryPath, metadata, true);
637
298
  }
638
- if (stats.isDirectory()) {
639
- metadata.baseDir = resolved;
640
- const resources = this.collectPackageResources(resolved, accumulator, filter, metadata);
641
- if (!resources) {
642
- this.addResource(accumulator.extensions, resolved, metadata, true);
643
- }
299
+ return;
300
+ }
301
+ const files = this.collectResourceFiles(entryPath, resourceType);
302
+ for (const filePath of files) {
303
+ if (matchesFilter(filePath, metadata.baseDir ?? entryPath, patterns)) {
304
+ this.addResource(this.getTargetMap(accumulator, resourceType), filePath, metadata, true);
644
305
  }
645
306
  }
646
- catch {
307
+ }
308
+ resolveTopLevelEntries(entries, resourceType, accumulator, metadata, baseDir) {
309
+ for (const entry of entries) {
310
+ if (!entry || entry.startsWith("!") || entry.startsWith("+") || entry.startsWith("-")) {
311
+ continue;
312
+ }
313
+ this.addResolvedEntry(resolve(baseDir, entry), resourceType, accumulator, metadata);
314
+ }
315
+ }
316
+ addConventionalResources(accumulator, baseDir, metadata) {
317
+ if (!existsSync(baseDir)) {
647
318
  return;
648
319
  }
320
+ for (const resourceType of RESOURCE_TYPES) {
321
+ this.addResolvedEntry(join(baseDir, resourceType), resourceType, accumulator, metadata);
322
+ }
323
+ }
324
+ collectResourceFiles(baseDir, resourceType) {
325
+ if (resourceType === "skills") {
326
+ return collectSkillEntries(baseDir);
327
+ }
328
+ return collectFiles(baseDir, FILE_PATTERNS[resourceType]);
329
+ }
330
+ addResource(target, resourcePath, metadata, enabled) {
331
+ if (!target.has(resourcePath)) {
332
+ target.set(resourcePath, { metadata: { ...metadata }, enabled });
333
+ return;
334
+ }
335
+ const existing = target.get(resourcePath);
336
+ if (metadata.scope === "project" && existing.metadata.scope === "user") {
337
+ target.set(resourcePath, { metadata: { ...metadata }, enabled });
338
+ }
339
+ }
340
+ getTargetMap(accumulator, resourceType) {
341
+ return accumulator[resourceType];
342
+ }
343
+ createAccumulator() {
344
+ return {
345
+ extensions: new Map(),
346
+ hooks: new Map(),
347
+ skills: new Map(),
348
+ prompts: new Map(),
349
+ themes: new Map(),
350
+ };
351
+ }
352
+ toResolvedPaths(accumulator) {
353
+ const toList = (map) => Array.from(map.entries()).map(([path, value]) => ({ path, enabled: value.enabled, metadata: value.metadata }));
354
+ return {
355
+ extensions: toList(accumulator.extensions),
356
+ hooks: toList(accumulator.hooks),
357
+ skills: toList(accumulator.skills),
358
+ prompts: toList(accumulator.prompts),
359
+ themes: toList(accumulator.themes),
360
+ };
361
+ }
362
+ async updateSourceForScope(source, scope) {
363
+ const parsed = this.parseSource(source);
364
+ if (parsed.type === "npm") {
365
+ if (parsed.pinned) {
366
+ return;
367
+ }
368
+ await this.withProgress("update", source, async () => {
369
+ await this.installNpm(parsed, scope);
370
+ });
371
+ return;
372
+ }
373
+ if (parsed.type === "git") {
374
+ if (parsed.pinned) {
375
+ return;
376
+ }
377
+ await this.withProgress("update", source, async () => {
378
+ await this.updateGit(parsed, scope);
379
+ });
380
+ }
649
381
  }
650
382
  async installParsedSource(parsed, scope) {
651
383
  if (parsed.type === "npm") {
652
- await this.installNpm(parsed, scope, scope === "temporary");
384
+ await this.installNpm(parsed, scope);
653
385
  return;
654
386
  }
655
387
  if (parsed.type === "git") {
656
388
  await this.installGit(parsed, scope);
657
- return;
658
389
  }
659
390
  }
660
391
  parseSource(source) {
661
392
  if (source.startsWith("npm:")) {
662
- const spec = source.slice("npm:".length).trim();
393
+ const spec = source.slice(4).trim();
663
394
  const { name, version } = this.parseNpmSpec(spec);
664
- return {
665
- type: "npm",
666
- spec,
667
- name,
668
- pinned: Boolean(version),
669
- };
395
+ return { type: "npm", spec, name, pinned: Boolean(version) };
670
396
  }
671
397
  if (source.startsWith("git:") || looksLikeGitUrl(source)) {
672
- const repoSpec = source.startsWith("git:") ? source.slice("git:".length).trim() : source;
398
+ const repoSpec = source.startsWith("git:") ? source.slice(4).trim() : source;
673
399
  const [repo, ref] = repoSpec.split("@");
674
400
  const normalized = repo.replace(/^https?:\/\//, "").replace(/\.git$/, "");
675
- const parts = normalized.split("/");
676
- const host = parts.shift() ?? "";
677
- const repoPath = parts.join("/");
678
- return {
679
- type: "git",
680
- repo: normalized,
681
- host,
682
- path: repoPath,
683
- ref,
684
- pinned: Boolean(ref),
685
- };
401
+ return { type: "git", repo: normalized, ref, pinned: Boolean(ref) };
686
402
  }
687
403
  return { type: "local", path: source };
688
404
  }
689
- /**
690
- * Check if an npm package needs to be updated.
691
- * - For unpinned packages: check if registry has a newer version
692
- * - For pinned packages: check if installed version matches the pinned version
693
- */
694
- async npmNeedsUpdate(source, installedPath) {
695
- const installedVersion = this.getInstalledNpmVersion(installedPath);
696
- if (!installedVersion)
697
- return true;
698
- const { version: pinnedVersion } = this.parseNpmSpec(source.spec);
699
- if (pinnedVersion) {
700
- // Pinned: check if installed matches pinned (exact match for now)
701
- return installedVersion !== pinnedVersion;
405
+ parseNpmSpec(spec) {
406
+ const match = spec.match(/^(@?[^@]+(?:\/[^@]+)?)(?:@(.+))?$/);
407
+ if (!match) {
408
+ return { name: spec };
702
409
  }
703
- // Unpinned: check registry for latest version
410
+ return { name: match[1] ?? spec, version: match[2] };
411
+ }
412
+ resolveLocalPath(inputPath) {
413
+ return resolve(this.cwd, inputPath);
414
+ }
415
+ async withProgress(action, source, operation) {
416
+ this.progressCallback?.({ type: "start", action, source });
704
417
  try {
705
- const latestVersion = await this.getLatestNpmVersion(source.name);
706
- return latestVersion !== installedVersion;
418
+ await operation();
419
+ this.progressCallback?.({ type: "complete", action, source });
707
420
  }
708
- catch {
709
- // If we can't check registry, assume it's fine
710
- return false;
421
+ catch (error) {
422
+ this.progressCallback?.({
423
+ type: "error",
424
+ action,
425
+ source,
426
+ message: error instanceof Error ? error.message : String(error),
427
+ });
428
+ throw error;
711
429
  }
712
430
  }
713
- getInstalledNpmVersion(installedPath) {
714
- const packageJsonPath = join(installedPath, "package.json");
715
- if (!existsSync(packageJsonPath))
716
- return undefined;
717
- try {
718
- const content = readFileSync(packageJsonPath, "utf-8");
719
- const pkg = JSON.parse(content);
720
- return pkg.version;
431
+ getNpmInstallRoot(scope) {
432
+ if (scope === "project") {
433
+ return join(this.cwd, CONFIG_DIR_NAME, "packages", "node");
721
434
  }
722
- catch {
723
- return undefined;
435
+ if (scope === "temporary") {
436
+ const hash = createHash("sha1").update(this.cwd).digest("hex").slice(0, 12);
437
+ return join(tmpdir(), `indusagi-screth-packages-${hash}`);
724
438
  }
439
+ return this.agentDir;
725
440
  }
726
- async getLatestNpmVersion(packageName) {
727
- const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
728
- if (!response.ok)
729
- throw new Error(`Failed to fetch npm registry: ${response.status}`);
730
- const data = (await response.json());
731
- return data.version;
441
+ getProjectNpmNodeModules(scope) {
442
+ return join(this.getNpmInstallRoot(scope), "node_modules");
732
443
  }
733
- /**
734
- * Get a unique identity for a package, ignoring version/ref.
735
- * Used to detect when the same package is in both global and project settings.
736
- */
737
- getPackageIdentity(source) {
738
- const parsed = this.parseSource(source);
739
- if (parsed.type === "npm") {
740
- return `npm:${parsed.name}`;
741
- }
742
- if (parsed.type === "git") {
743
- return `git:${parsed.repo}`;
444
+ getNpmInstallPath(source, scope) {
445
+ if (scope === "user") {
446
+ return join(this.getGlobalNpmRoot(), source.name);
744
447
  }
745
- // For local paths, use the absolute resolved path
746
- return `local:${this.resolvePath(parsed.path)}`;
448
+ return join(this.getProjectNpmNodeModules("project"), source.name);
747
449
  }
748
- /**
749
- * Dedupe packages: if same package identity appears in both global and project,
750
- * keep only the project one (project wins).
751
- */
752
- dedupePackages(packages) {
753
- const seen = new Map();
754
- for (const entry of packages) {
755
- const sourceStr = typeof entry.pkg === "string" ? entry.pkg : entry.pkg.source;
756
- const identity = this.getPackageIdentity(sourceStr);
757
- const existing = seen.get(identity);
758
- if (!existing) {
759
- seen.set(identity, entry);
760
- }
761
- else if (entry.scope === "project" && existing.scope === "user") {
762
- // Project wins over user
763
- seen.set(identity, entry);
450
+ getGlobalNpmRoot() {
451
+ if (this.globalNpmRoot) {
452
+ return this.globalNpmRoot;
453
+ }
454
+ let output = "";
455
+ try {
456
+ const result = spawnSync("npm", ["root", "-g"], { encoding: "utf-8" });
457
+ if (result.status === 0 && result.stdout.trim()) {
458
+ output = result.stdout.trim();
764
459
  }
765
- // If existing is project and new is global, keep existing (project)
766
- // If both are same scope, keep first one
767
460
  }
768
- return Array.from(seen.values());
769
- }
770
- parseNpmSpec(spec) {
771
- const match = spec.match(/^(@?[^@]+(?:\/[^@]+)?)(?:@(.+))?$/);
772
- if (!match) {
773
- return { name: spec };
461
+ catch {
462
+ // Ignore and fall back.
774
463
  }
775
- const name = match[1] ?? spec;
776
- const version = match[2];
777
- return { name, version };
464
+ this.globalNpmRoot = output || join(this.agentDir, "node_modules");
465
+ return this.globalNpmRoot;
778
466
  }
779
- async installNpm(source, scope, temporary) {
780
- if (scope === "user" && !temporary) {
467
+ async installNpm(source, scope) {
468
+ if (scope === "user") {
781
469
  await this.runCommand("npm", ["install", "-g", source.spec]);
782
470
  return;
783
471
  }
784
- const installRoot = this.getNpmInstallRoot(scope, temporary);
785
- this.ensureNpmProject(installRoot);
472
+ const installRoot = this.getNpmInstallRoot(scope);
473
+ this.ensureNodeProject(installRoot);
786
474
  await this.runCommand("npm", ["install", source.spec, "--prefix", installRoot]);
787
475
  }
788
476
  async uninstallNpm(source, scope) {
@@ -790,432 +478,106 @@ export class DefaultPackageManager {
790
478
  await this.runCommand("npm", ["uninstall", "-g", source.name]);
791
479
  return;
792
480
  }
793
- const installRoot = this.getNpmInstallRoot(scope, false);
481
+ const installRoot = this.getNpmInstallRoot(scope);
794
482
  if (!existsSync(installRoot)) {
795
483
  return;
796
484
  }
797
485
  await this.runCommand("npm", ["uninstall", source.name, "--prefix", installRoot]);
798
486
  }
487
+ getGitInstallPath(source, scope) {
488
+ const base = scope === "project" ? join(this.cwd, CONFIG_DIR_NAME, "packages", "git") : join(this.agentDir, "packages", "git");
489
+ const hash = createHash("sha1").update(source.repo).digest("hex").slice(0, 12);
490
+ const safeName = source.repo.split("/").pop() || "repo";
491
+ return join(base, `${safeName}-${hash}`);
492
+ }
799
493
  async installGit(source, scope) {
800
- const targetDir = this.getGitInstallPath(source, scope);
494
+ const targetDir = this.getGitInstallPath(source, scope === "temporary" ? "project" : scope);
801
495
  if (existsSync(targetDir)) {
802
496
  return;
803
497
  }
804
- const gitRoot = this.getGitInstallRoot(scope);
805
- if (gitRoot) {
806
- this.ensureGitIgnore(gitRoot);
807
- }
808
498
  mkdirSync(dirname(targetDir), { recursive: true });
809
499
  const cloneUrl = source.repo.startsWith("http") ? source.repo : `https://${source.repo}`;
810
500
  await this.runCommand("git", ["clone", cloneUrl, targetDir]);
811
501
  if (source.ref) {
812
502
  await this.runCommand("git", ["checkout", source.ref], { cwd: targetDir });
813
503
  }
814
- const packageJsonPath = join(targetDir, "package.json");
815
- if (existsSync(packageJsonPath)) {
504
+ if (existsSync(join(targetDir, "package.json"))) {
816
505
  await this.runCommand("npm", ["install"], { cwd: targetDir });
817
506
  }
818
507
  }
819
508
  async updateGit(source, scope) {
820
- const targetDir = this.getGitInstallPath(source, scope);
509
+ const targetDir = this.getGitInstallPath(source, scope === "temporary" ? "project" : scope);
821
510
  if (!existsSync(targetDir)) {
822
511
  await this.installGit(source, scope);
823
512
  return;
824
513
  }
825
514
  await this.runCommand("git", ["pull"], { cwd: targetDir });
826
- const packageJsonPath = join(targetDir, "package.json");
827
- if (existsSync(packageJsonPath)) {
515
+ if (existsSync(join(targetDir, "package.json"))) {
828
516
  await this.runCommand("npm", ["install"], { cwd: targetDir });
829
517
  }
830
518
  }
831
- async removeGit(source, scope) {
832
- const targetDir = this.getGitInstallPath(source, scope);
833
- if (!existsSync(targetDir))
834
- return;
835
- rmSync(targetDir, { recursive: true, force: true });
836
- }
837
- ensureNpmProject(installRoot) {
838
- if (!existsSync(installRoot)) {
839
- mkdirSync(installRoot, { recursive: true });
840
- }
841
- this.ensureGitIgnore(installRoot);
842
- const packageJsonPath = join(installRoot, "package.json");
843
- if (!existsSync(packageJsonPath)) {
844
- const pkgJson = { name: "indusagi-extensions", private: true };
845
- writeFileSync(packageJsonPath, JSON.stringify(pkgJson, null, 2), "utf-8");
846
- }
847
- }
848
- ensureGitIgnore(dir) {
849
- if (!existsSync(dir)) {
850
- mkdirSync(dir, { recursive: true });
851
- }
852
- const ignorePath = join(dir, ".gitignore");
853
- if (!existsSync(ignorePath)) {
854
- writeFileSync(ignorePath, "*\n!.gitignore\n", "utf-8");
855
- }
856
- }
857
- getNpmInstallRoot(scope, temporary) {
858
- if (temporary) {
859
- return this.getTemporaryDir("npm");
860
- }
861
- if (scope === "project") {
862
- return join(this.cwd, CONFIG_DIR_NAME, "npm");
863
- }
864
- return join(this.getGlobalNpmRoot(), "..");
865
- }
866
- getGlobalNpmRoot() {
867
- if (this.globalNpmRoot) {
868
- return this.globalNpmRoot;
869
- }
870
- const result = this.runCommandSync("npm", ["root", "-g"]);
871
- this.globalNpmRoot = result.trim();
872
- return this.globalNpmRoot;
873
- }
874
- getNpmInstallPath(source, scope) {
875
- if (scope === "temporary") {
876
- return join(this.getTemporaryDir("npm"), "node_modules", source.name);
877
- }
878
- if (scope === "project") {
879
- return join(this.cwd, CONFIG_DIR_NAME, "npm", "node_modules", source.name);
880
- }
881
- return join(this.getGlobalNpmRoot(), source.name);
882
- }
883
- getGitInstallPath(source, scope) {
884
- if (scope === "temporary") {
885
- return this.getTemporaryDir(`git-${source.host}`, source.path);
886
- }
887
- if (scope === "project") {
888
- return join(this.cwd, CONFIG_DIR_NAME, "git", source.host, source.path);
889
- }
890
- return join(this.agentDir, "git", source.host, source.path);
891
- }
892
- getGitInstallRoot(scope) {
893
- if (scope === "temporary") {
894
- return undefined;
895
- }
896
- if (scope === "project") {
897
- return join(this.cwd, CONFIG_DIR_NAME, "git");
898
- }
899
- return join(this.agentDir, "git");
900
- }
901
- getTemporaryDir(prefix, suffix) {
902
- const hash = createHash("sha256")
903
- .update(`${prefix}-${suffix ?? ""}`)
904
- .digest("hex")
905
- .slice(0, 8);
906
- return join(tmpdir(), "indusagi-extensions", prefix, hash, suffix ?? "");
907
- }
908
- resolvePath(input) {
909
- const trimmed = input.trim();
910
- if (trimmed === "~")
911
- return homedir();
912
- if (trimmed.startsWith("~/"))
913
- return join(homedir(), trimmed.slice(2));
914
- if (trimmed.startsWith("~"))
915
- return join(homedir(), trimmed.slice(1));
916
- return resolve(this.cwd, trimmed);
917
- }
918
- resolvePathFromBase(input, baseDir) {
919
- const trimmed = input.trim();
920
- if (trimmed === "~")
921
- return homedir();
922
- if (trimmed.startsWith("~/"))
923
- return join(homedir(), trimmed.slice(2));
924
- if (trimmed.startsWith("~"))
925
- return join(homedir(), trimmed.slice(1));
926
- return resolve(baseDir, trimmed);
927
- }
928
- collectPackageResources(packageRoot, accumulator, filter, metadata) {
929
- if (filter) {
930
- for (const resourceType of RESOURCE_TYPES) {
931
- const patterns = filter[resourceType];
932
- const target = this.getTargetMap(accumulator, resourceType);
933
- if (patterns !== undefined) {
934
- this.applyPackageFilter(packageRoot, patterns, resourceType, target, metadata);
935
- }
936
- else {
937
- this.collectDefaultResources(packageRoot, resourceType, target, metadata);
938
- }
939
- }
940
- return true;
941
- }
942
- const manifest = this.readIndusagiManifest(packageRoot);
943
- if (manifest) {
944
- for (const resourceType of RESOURCE_TYPES) {
945
- const entries = manifest[resourceType];
946
- this.addManifestEntries(entries, packageRoot, resourceType, this.getTargetMap(accumulator, resourceType), metadata);
947
- }
948
- return true;
949
- }
950
- let hasAnyDir = false;
951
- for (const resourceType of RESOURCE_TYPES) {
952
- const dir = join(packageRoot, resourceType);
953
- if (existsSync(dir)) {
954
- // Collect all files from the directory (all enabled by default)
955
- const files = resourceType === "skills" ? collectSkillEntries(dir) : collectFiles(dir, FILE_PATTERNS[resourceType]);
956
- for (const f of files) {
957
- this.addResource(this.getTargetMap(accumulator, resourceType), f, metadata, true);
958
- }
959
- hasAnyDir = true;
960
- }
961
- }
962
- return hasAnyDir;
963
- }
964
- collectDefaultResources(packageRoot, resourceType, target, metadata) {
965
- const manifest = this.readIndusagiManifest(packageRoot);
966
- const entries = manifest?.[resourceType];
967
- if (entries) {
968
- this.addManifestEntries(entries, packageRoot, resourceType, target, metadata);
969
- return;
970
- }
971
- const dir = join(packageRoot, resourceType);
972
- if (existsSync(dir)) {
973
- // Collect all files from the directory (all enabled by default)
974
- const files = resourceType === "skills" ? collectSkillEntries(dir) : collectFiles(dir, FILE_PATTERNS[resourceType]);
975
- for (const f of files) {
976
- this.addResource(target, f, metadata, true);
977
- }
978
- }
979
- }
980
- applyPackageFilter(packageRoot, userPatterns, resourceType, target, metadata) {
981
- const { allFiles, enabledByManifest } = this.collectManifestFiles(packageRoot, resourceType);
982
- if (userPatterns.length === 0) {
983
- // No user patterns, just use manifest filtering
984
- for (const f of allFiles) {
985
- this.addResource(target, f, metadata, enabledByManifest.has(f));
986
- }
987
- return;
988
- }
989
- // Apply user patterns on top of manifest-enabled files
990
- const enabledByUser = applyPatterns(allFiles, userPatterns, packageRoot);
991
- for (const f of allFiles) {
992
- const enabled = enabledByUser.has(f);
993
- this.addResource(target, f, metadata, enabled);
994
- }
995
- }
996
- /**
997
- * Collect all files from a package for a resource type, applying manifest patterns.
998
- * Returns { allFiles, enabledByManifest } where enabledByManifest is the set of files
999
- * that pass the manifest's own patterns.
1000
- */
1001
- collectManifestFiles(packageRoot, resourceType) {
1002
- const manifest = this.readIndusagiManifest(packageRoot);
1003
- const entries = manifest?.[resourceType];
1004
- if (entries && entries.length > 0) {
1005
- const allFiles = this.collectFilesFromManifestEntries(entries, packageRoot, resourceType);
1006
- const manifestPatterns = entries.filter(isPattern);
1007
- const enabledByManifest = manifestPatterns.length > 0 ? applyPatterns(allFiles, manifestPatterns, packageRoot) : new Set(allFiles);
1008
- return { allFiles: Array.from(enabledByManifest), enabledByManifest };
1009
- }
1010
- const conventionDir = join(packageRoot, resourceType);
1011
- if (!existsSync(conventionDir)) {
1012
- return { allFiles: [], enabledByManifest: new Set() };
519
+ removeGit(source, scope) {
520
+ const targetDir = this.getGitInstallPath(source, scope === "temporary" ? "project" : scope);
521
+ if (existsSync(targetDir)) {
522
+ rmSync(targetDir, { recursive: true, force: true });
1013
523
  }
1014
- const allFiles = resourceType === "skills"
1015
- ? collectSkillEntries(conventionDir)
1016
- : collectFiles(conventionDir, FILE_PATTERNS[resourceType]);
1017
- return { allFiles, enabledByManifest: new Set(allFiles) };
1018
524
  }
1019
- readIndusagiManifest(packageRoot) {
1020
- const packageJsonPath = join(packageRoot, "package.json");
525
+ ensureNodeProject(dir) {
526
+ mkdirSync(dir, { recursive: true });
527
+ const packageJsonPath = join(dir, "package.json");
1021
528
  if (!existsSync(packageJsonPath)) {
1022
- return null;
1023
- }
1024
- try {
1025
- const content = readFileSync(packageJsonPath, "utf-8");
1026
- const pkg = JSON.parse(content);
1027
- return pkg.indusagi ?? null;
1028
- }
1029
- catch {
1030
- return null;
1031
- }
1032
- }
1033
- addManifestEntries(entries, root, resourceType, target, metadata) {
1034
- if (!entries)
1035
- return;
1036
- const allFiles = this.collectFilesFromManifestEntries(entries, root, resourceType);
1037
- const patterns = entries.filter(isPattern);
1038
- const enabledPaths = applyPatterns(allFiles, patterns, root);
1039
- for (const f of allFiles) {
1040
- if (enabledPaths.has(f)) {
1041
- this.addResource(target, f, metadata, true);
1042
- }
1043
- }
1044
- }
1045
- collectFilesFromManifestEntries(entries, root, resourceType) {
1046
- const plain = entries.filter((entry) => !isPattern(entry));
1047
- const resolved = plain.map((entry) => resolve(root, entry));
1048
- return this.collectFilesFromPaths(resolved, resourceType);
1049
- }
1050
- resolveLocalEntries(entries, resourceType, target, metadata, baseDir) {
1051
- if (entries.length === 0)
1052
- return;
1053
- // Collect all files from plain entries (non-pattern entries)
1054
- const { plain, patterns } = splitPatterns(entries);
1055
- const resolvedPlain = plain.map((p) => this.resolvePathFromBase(p, baseDir));
1056
- const allFiles = this.collectFilesFromPaths(resolvedPlain, resourceType);
1057
- // Determine which files are enabled based on patterns
1058
- const enabledPaths = applyPatterns(allFiles, patterns, baseDir);
1059
- // Add all files with their enabled state
1060
- for (const f of allFiles) {
1061
- this.addResource(target, f, metadata, enabledPaths.has(f));
529
+ writeFileSync(packageJsonPath, JSON.stringify({ name: "indusagi-screth-packages", private: true }, null, 2), "utf-8");
1062
530
  }
1063
531
  }
1064
- addAutoDiscoveredResources(accumulator, globalSettings, projectSettings, globalBaseDir, projectBaseDir) {
1065
- const userMetadata = {
1066
- source: "auto",
1067
- scope: "user",
1068
- origin: "top-level",
1069
- baseDir: globalBaseDir,
1070
- };
1071
- const projectMetadata = {
1072
- source: "auto",
1073
- scope: "project",
1074
- origin: "top-level",
1075
- baseDir: projectBaseDir,
1076
- };
1077
- const userOverrides = {
1078
- extensions: (globalSettings.extensions ?? []),
1079
- hooks: (globalSettings.hooks ?? []),
1080
- skills: (globalSettings.skills ?? []),
1081
- prompts: (globalSettings.prompts ?? []),
1082
- themes: (globalSettings.themes ?? []),
1083
- };
1084
- const projectOverrides = {
1085
- extensions: (projectSettings.extensions ?? []),
1086
- hooks: (projectSettings.hooks ?? []),
1087
- skills: (projectSettings.skills ?? []),
1088
- prompts: (projectSettings.prompts ?? []),
1089
- themes: (projectSettings.themes ?? []),
1090
- };
1091
- const userDirs = {
1092
- extensions: join(globalBaseDir, "extensions"),
1093
- hooks: join(globalBaseDir, "hooks"),
1094
- skills: join(globalBaseDir, "skills"),
1095
- prompts: join(globalBaseDir, "prompts"),
1096
- themes: join(globalBaseDir, "themes"),
1097
- };
1098
- const projectDirs = {
1099
- extensions: join(projectBaseDir, "extensions"),
1100
- hooks: join(projectBaseDir, "hooks"),
1101
- skills: join(projectBaseDir, "skills"),
1102
- prompts: join(projectBaseDir, "prompts"),
1103
- themes: join(projectBaseDir, "themes"),
1104
- };
1105
- const addResources = (resourceType, paths, metadata, overrides, baseDir) => {
1106
- const target = this.getTargetMap(accumulator, resourceType);
1107
- for (const path of paths) {
1108
- const enabled = isEnabledByOverrides(path, overrides, baseDir);
1109
- this.addResource(target, path, metadata, enabled);
1110
- }
1111
- };
1112
- addResources("extensions", collectAutoExtensionEntries(userDirs.extensions), userMetadata, userOverrides.extensions, globalBaseDir);
1113
- addResources("hooks", collectAutoHookEntries(userDirs.hooks), userMetadata, userOverrides.hooks, globalBaseDir);
1114
- addResources("skills", collectAutoSkillEntries(userDirs.skills), userMetadata, userOverrides.skills, globalBaseDir);
1115
- addResources("prompts", collectAutoPromptEntries(userDirs.prompts), userMetadata, userOverrides.prompts, globalBaseDir);
1116
- addResources("themes", collectAutoThemeEntries(userDirs.themes), userMetadata, userOverrides.themes, globalBaseDir);
1117
- addResources("extensions", collectAutoExtensionEntries(projectDirs.extensions), projectMetadata, projectOverrides.extensions, projectBaseDir);
1118
- addResources("hooks", collectAutoHookEntries(projectDirs.hooks), projectMetadata, projectOverrides.hooks, projectBaseDir);
1119
- addResources("skills", collectAutoSkillEntries(projectDirs.skills), projectMetadata, projectOverrides.skills, projectBaseDir);
1120
- addResources("prompts", collectAutoPromptEntries(projectDirs.prompts), projectMetadata, projectOverrides.prompts, projectBaseDir);
1121
- addResources("themes", collectAutoThemeEntries(projectDirs.themes), projectMetadata, projectOverrides.themes, projectBaseDir);
1122
- }
1123
- collectFilesFromPaths(paths, resourceType) {
1124
- const files = [];
1125
- for (const p of paths) {
1126
- if (!existsSync(p))
1127
- continue;
1128
- try {
1129
- const stats = statSync(p);
1130
- if (stats.isFile()) {
1131
- files.push(p);
1132
- }
1133
- else if (stats.isDirectory()) {
1134
- if (resourceType === "skills") {
1135
- files.push(...collectSkillEntries(p));
1136
- }
1137
- else {
1138
- files.push(...collectFiles(p, FILE_PATTERNS[resourceType]));
1139
- }
1140
- }
1141
- }
1142
- catch {
1143
- // Ignore errors
1144
- }
1145
- }
1146
- return files;
1147
- }
1148
- getTargetMap(accumulator, resourceType) {
1149
- switch (resourceType) {
1150
- case "extensions":
1151
- return accumulator.extensions;
1152
- case "hooks":
1153
- return accumulator.hooks;
1154
- case "skills":
1155
- return accumulator.skills;
1156
- case "prompts":
1157
- return accumulator.prompts;
1158
- case "themes":
1159
- return accumulator.themes;
1160
- default:
1161
- throw new Error(`Unknown resource type: ${resourceType}`);
1162
- }
1163
- }
1164
- addResource(map, path, metadata, enabled) {
1165
- if (!path)
1166
- return;
1167
- if (!map.has(path)) {
1168
- map.set(path, { metadata, enabled });
1169
- }
1170
- }
1171
- createAccumulator() {
1172
- return {
1173
- extensions: new Map(),
1174
- hooks: new Map(),
1175
- skills: new Map(),
1176
- prompts: new Map(),
1177
- themes: new Map(),
1178
- };
1179
- }
1180
- toResolvedPaths(accumulator) {
1181
- const toResolved = (entries) => {
1182
- return Array.from(entries.entries()).map(([path, { metadata, enabled }]) => ({
1183
- path,
1184
- enabled,
1185
- metadata,
1186
- }));
1187
- };
1188
- return {
1189
- extensions: toResolved(accumulator.extensions),
1190
- hooks: toResolved(accumulator.hooks),
1191
- skills: toResolved(accumulator.skills),
1192
- prompts: toResolved(accumulator.prompts),
1193
- themes: toResolved(accumulator.themes),
1194
- };
1195
- }
1196
- runCommand(command, args, options) {
1197
- return new Promise((resolvePromise, reject) => {
532
+ async runCommand(command, args, options) {
533
+ await new Promise((resolvePromise, rejectPromise) => {
1198
534
  const child = spawn(command, args, {
1199
- cwd: options?.cwd,
1200
- stdio: "inherit",
535
+ cwd: options?.cwd ?? this.cwd,
536
+ stdio: ["ignore", "pipe", "pipe"],
1201
537
  });
1202
- child.on("error", reject);
1203
- child.on("exit", (code) => {
538
+ let stderr = "";
539
+ child.stderr?.on("data", (data) => {
540
+ stderr += data.toString();
541
+ this.progressCallback?.({
542
+ type: "progress",
543
+ action: command === "git" && args[0] === "clone" ? "clone" : command === "git" ? "pull" : "install",
544
+ source: args.join(" "),
545
+ message: data.toString().trim(),
546
+ });
547
+ });
548
+ child.on("close", (code) => {
1204
549
  if (code === 0) {
1205
550
  resolvePromise();
551
+ return;
1206
552
  }
1207
- else {
1208
- reject(new Error(`${command} ${args.join(" ")} failed with code ${code}`));
1209
- }
553
+ rejectPromise(new Error(stderr.trim() || `${command} ${args.join(" ")} failed with code ${code}`));
554
+ });
555
+ child.on("error", (error) => {
556
+ rejectPromise(error);
1210
557
  });
1211
558
  });
1212
559
  }
1213
- runCommandSync(command, args) {
1214
- const result = spawnSync(command, args, { stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
1215
- if (result.status !== 0) {
1216
- throw new Error(`Failed to run ${command} ${args.join(" ")}: ${result.stderr || result.stdout}`);
560
+ getPackageIdentity(source) {
561
+ const parsed = this.parseSource(source);
562
+ if (parsed.type === "npm") {
563
+ return `npm:${parsed.name}`;
564
+ }
565
+ if (parsed.type === "git") {
566
+ return `git:${parsed.repo}`;
567
+ }
568
+ return `local:${this.resolveLocalPath(parsed.path)}`;
569
+ }
570
+ dedupePackages(packages) {
571
+ const seen = new Map();
572
+ for (const entry of packages) {
573
+ const source = typeof entry.pkg === "string" ? entry.pkg : entry.pkg.source;
574
+ const identity = this.getPackageIdentity(source);
575
+ const existing = seen.get(identity);
576
+ if (!existing || (entry.scope === "project" && existing.scope === "user")) {
577
+ seen.set(identity, entry);
578
+ }
1217
579
  }
1218
- return (result.stdout || result.stderr || "").trim();
580
+ return Array.from(seen.values());
1219
581
  }
1220
582
  }
1221
583
  //# sourceMappingURL=package-manager.js.map