@nghyane/arcane 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 (738) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/README.md +12 -0
  3. package/examples/README.md +21 -0
  4. package/examples/custom-tools/README.md +109 -0
  5. package/examples/custom-tools/hello/index.ts +20 -0
  6. package/examples/custom-tools/todo/index.ts +206 -0
  7. package/examples/extensions/README.md +143 -0
  8. package/examples/extensions/api-demo.ts +89 -0
  9. package/examples/extensions/chalk-logger.ts +25 -0
  10. package/examples/extensions/hello.ts +32 -0
  11. package/examples/extensions/pirate.ts +43 -0
  12. package/examples/extensions/plan-mode.ts +550 -0
  13. package/examples/extensions/reload-runtime.ts +37 -0
  14. package/examples/extensions/todo.ts +296 -0
  15. package/examples/extensions/tools.ts +144 -0
  16. package/examples/extensions/with-deps/index.ts +35 -0
  17. package/examples/extensions/with-deps/package-lock.json +31 -0
  18. package/examples/extensions/with-deps/package.json +16 -0
  19. package/examples/hooks/README.md +56 -0
  20. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  21. package/examples/hooks/confirm-destructive.ts +58 -0
  22. package/examples/hooks/custom-compaction.ts +116 -0
  23. package/examples/hooks/dirty-repo-guard.ts +51 -0
  24. package/examples/hooks/file-trigger.ts +40 -0
  25. package/examples/hooks/git-checkpoint.ts +52 -0
  26. package/examples/hooks/handoff.ts +150 -0
  27. package/examples/hooks/permission-gate.ts +33 -0
  28. package/examples/hooks/protected-paths.ts +29 -0
  29. package/examples/hooks/qna.ts +119 -0
  30. package/examples/hooks/status-line.ts +39 -0
  31. package/examples/sdk/01-minimal.ts +21 -0
  32. package/examples/sdk/02-custom-model.ts +49 -0
  33. package/examples/sdk/03-custom-prompt.ts +43 -0
  34. package/examples/sdk/04-skills.ts +43 -0
  35. package/examples/sdk/06-extensions.ts +80 -0
  36. package/examples/sdk/06-hooks.ts +61 -0
  37. package/examples/sdk/07-context-files.ts +35 -0
  38. package/examples/sdk/08-prompt-templates.ts +36 -0
  39. package/examples/sdk/08-slash-commands.ts +41 -0
  40. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  41. package/examples/sdk/11-sessions.ts +47 -0
  42. package/examples/sdk/README.md +150 -0
  43. package/package.json +464 -0
  44. package/scripts/format-prompts.ts +184 -0
  45. package/scripts/generate-docs-index.ts +40 -0
  46. package/scripts/generate-template.ts +32 -0
  47. package/src/bun-imports.d.ts +22 -0
  48. package/src/capability/context-file.ts +39 -0
  49. package/src/capability/extension-module.ts +33 -0
  50. package/src/capability/extension.ts +47 -0
  51. package/src/capability/fs.ts +89 -0
  52. package/src/capability/hook.ts +39 -0
  53. package/src/capability/index.ts +432 -0
  54. package/src/capability/instruction.ts +36 -0
  55. package/src/capability/mcp.ts +60 -0
  56. package/src/capability/prompt.ts +34 -0
  57. package/src/capability/rule.ts +223 -0
  58. package/src/capability/settings.ts +34 -0
  59. package/src/capability/skill.ts +48 -0
  60. package/src/capability/slash-command.ts +39 -0
  61. package/src/capability/ssh.ts +41 -0
  62. package/src/capability/system-prompt.ts +34 -0
  63. package/src/capability/tool.ts +37 -0
  64. package/src/capability/types.ts +156 -0
  65. package/src/cli/args.ts +259 -0
  66. package/src/cli/config-cli.ts +357 -0
  67. package/src/cli/file-processor.ts +124 -0
  68. package/src/cli/grep-cli.ts +152 -0
  69. package/src/cli/jupyter-cli.ts +106 -0
  70. package/src/cli/list-models.ts +103 -0
  71. package/src/cli/plugin-cli.ts +661 -0
  72. package/src/cli/session-picker.ts +42 -0
  73. package/src/cli/setup-cli.ts +376 -0
  74. package/src/cli/shell-cli.ts +174 -0
  75. package/src/cli/ssh-cli.ts +179 -0
  76. package/src/cli/stats-cli.ts +197 -0
  77. package/src/cli/update-cli.ts +286 -0
  78. package/src/cli/web-search-cli.ts +143 -0
  79. package/src/cli.ts +65 -0
  80. package/src/commands/commit.ts +36 -0
  81. package/src/commands/config.ts +51 -0
  82. package/src/commands/grep.ts +41 -0
  83. package/src/commands/jupyter.ts +32 -0
  84. package/src/commands/launch.ts +139 -0
  85. package/src/commands/plugin.ts +70 -0
  86. package/src/commands/setup.ts +42 -0
  87. package/src/commands/shell.ts +29 -0
  88. package/src/commands/ssh.ts +60 -0
  89. package/src/commands/stats.ts +29 -0
  90. package/src/commands/update.ts +21 -0
  91. package/src/commands/web-search.ts +42 -0
  92. package/src/commit/agentic/agent.ts +311 -0
  93. package/src/commit/agentic/fallback.ts +96 -0
  94. package/src/commit/agentic/index.ts +359 -0
  95. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  96. package/src/commit/agentic/prompts/session-user.md +25 -0
  97. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  98. package/src/commit/agentic/prompts/system.md +38 -0
  99. package/src/commit/agentic/state.ts +69 -0
  100. package/src/commit/agentic/tools/analyze-file.ts +118 -0
  101. package/src/commit/agentic/tools/git-file-diff.ts +194 -0
  102. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  103. package/src/commit/agentic/tools/git-overview.ts +84 -0
  104. package/src/commit/agentic/tools/index.ts +56 -0
  105. package/src/commit/agentic/tools/propose-changelog.ts +128 -0
  106. package/src/commit/agentic/tools/propose-commit.ts +154 -0
  107. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  108. package/src/commit/agentic/tools/split-commit.ts +280 -0
  109. package/src/commit/agentic/topo-sort.ts +44 -0
  110. package/src/commit/agentic/trivial.ts +51 -0
  111. package/src/commit/agentic/validation.ts +200 -0
  112. package/src/commit/analysis/conventional.ts +165 -0
  113. package/src/commit/analysis/index.ts +4 -0
  114. package/src/commit/analysis/scope.ts +242 -0
  115. package/src/commit/analysis/summary.ts +112 -0
  116. package/src/commit/analysis/validation.ts +66 -0
  117. package/src/commit/changelog/detect.ts +37 -0
  118. package/src/commit/changelog/generate.ts +110 -0
  119. package/src/commit/changelog/index.ts +234 -0
  120. package/src/commit/changelog/parse.ts +44 -0
  121. package/src/commit/cli.ts +93 -0
  122. package/src/commit/git/diff.ts +148 -0
  123. package/src/commit/git/errors.ts +9 -0
  124. package/src/commit/git/index.ts +211 -0
  125. package/src/commit/git/operations.ts +54 -0
  126. package/src/commit/index.ts +5 -0
  127. package/src/commit/map-reduce/index.ts +64 -0
  128. package/src/commit/map-reduce/map-phase.ts +178 -0
  129. package/src/commit/map-reduce/reduce-phase.ts +145 -0
  130. package/src/commit/map-reduce/utils.ts +9 -0
  131. package/src/commit/message.ts +11 -0
  132. package/src/commit/model-selection.ts +69 -0
  133. package/src/commit/pipeline.ts +243 -0
  134. package/src/commit/prompts/analysis-system.md +148 -0
  135. package/src/commit/prompts/analysis-user.md +38 -0
  136. package/src/commit/prompts/changelog-system.md +50 -0
  137. package/src/commit/prompts/changelog-user.md +18 -0
  138. package/src/commit/prompts/file-observer-system.md +24 -0
  139. package/src/commit/prompts/file-observer-user.md +8 -0
  140. package/src/commit/prompts/reduce-system.md +50 -0
  141. package/src/commit/prompts/reduce-user.md +17 -0
  142. package/src/commit/prompts/summary-retry.md +3 -0
  143. package/src/commit/prompts/summary-system.md +38 -0
  144. package/src/commit/prompts/summary-user.md +13 -0
  145. package/src/commit/prompts/types-description.md +2 -0
  146. package/src/commit/types.ts +109 -0
  147. package/src/commit/utils/exclusions.ts +42 -0
  148. package/src/config/file-lock.ts +121 -0
  149. package/src/config/keybindings.ts +280 -0
  150. package/src/config/model-registry.ts +1140 -0
  151. package/src/config/model-resolver.ts +812 -0
  152. package/src/config/prompt-templates.ts +526 -0
  153. package/src/config/resolve-config-value.ts +92 -0
  154. package/src/config/settings-schema.ts +1236 -0
  155. package/src/config/settings.ts +706 -0
  156. package/src/config.ts +414 -0
  157. package/src/cursor.ts +239 -0
  158. package/src/debug/index.ts +431 -0
  159. package/src/debug/log-formatting.ts +60 -0
  160. package/src/debug/log-viewer.ts +903 -0
  161. package/src/debug/profiler.ts +158 -0
  162. package/src/debug/report-bundle.ts +366 -0
  163. package/src/debug/system-info.ts +112 -0
  164. package/src/discovery/agents-md.ts +68 -0
  165. package/src/discovery/agents.ts +199 -0
  166. package/src/discovery/builtin.ts +815 -0
  167. package/src/discovery/claude-plugins.ts +205 -0
  168. package/src/discovery/claude.ts +506 -0
  169. package/src/discovery/cline.ts +83 -0
  170. package/src/discovery/codex.ts +532 -0
  171. package/src/discovery/cursor.ts +218 -0
  172. package/src/discovery/gemini.ts +395 -0
  173. package/src/discovery/github.ts +117 -0
  174. package/src/discovery/helpers.ts +698 -0
  175. package/src/discovery/index.ts +89 -0
  176. package/src/discovery/mcp-json.ts +156 -0
  177. package/src/discovery/opencode.ts +394 -0
  178. package/src/discovery/ssh.ts +160 -0
  179. package/src/discovery/vscode.ts +103 -0
  180. package/src/discovery/windsurf.ts +145 -0
  181. package/src/exa/company.ts +57 -0
  182. package/src/exa/index.ts +62 -0
  183. package/src/exa/linkedin.ts +57 -0
  184. package/src/exa/mcp-client.ts +289 -0
  185. package/src/exa/render.ts +244 -0
  186. package/src/exa/researcher.ts +89 -0
  187. package/src/exa/search.ts +330 -0
  188. package/src/exa/types.ts +166 -0
  189. package/src/exa/websets.ts +247 -0
  190. package/src/exec/bash-executor.ts +184 -0
  191. package/src/exec/exec.ts +53 -0
  192. package/src/export/custom-share.ts +65 -0
  193. package/src/export/html/index.ts +162 -0
  194. package/src/export/html/template.css +889 -0
  195. package/src/export/html/template.generated.ts +2 -0
  196. package/src/export/html/template.html +45 -0
  197. package/src/export/html/template.js +1329 -0
  198. package/src/export/html/template.macro.ts +24 -0
  199. package/src/export/html/vendor/highlight.min.js +1213 -0
  200. package/src/export/html/vendor/marked.min.js +6 -0
  201. package/src/export/ttsr.ts +434 -0
  202. package/src/extensibility/custom-commands/bundled/review/index.ts +433 -0
  203. package/src/extensibility/custom-commands/index.ts +15 -0
  204. package/src/extensibility/custom-commands/loader.ts +231 -0
  205. package/src/extensibility/custom-commands/types.ts +111 -0
  206. package/src/extensibility/custom-tools/index.ts +22 -0
  207. package/src/extensibility/custom-tools/loader.ts +235 -0
  208. package/src/extensibility/custom-tools/types.ts +226 -0
  209. package/src/extensibility/custom-tools/wrapper.ts +45 -0
  210. package/src/extensibility/extensions/index.ts +136 -0
  211. package/src/extensibility/extensions/loader.ts +520 -0
  212. package/src/extensibility/extensions/runner.ts +774 -0
  213. package/src/extensibility/extensions/types.ts +1293 -0
  214. package/src/extensibility/extensions/wrapper.ts +188 -0
  215. package/src/extensibility/hooks/index.ts +16 -0
  216. package/src/extensibility/hooks/loader.ts +273 -0
  217. package/src/extensibility/hooks/runner.ts +441 -0
  218. package/src/extensibility/hooks/tool-wrapper.ts +106 -0
  219. package/src/extensibility/hooks/types.ts +817 -0
  220. package/src/extensibility/plugins/doctor.ts +65 -0
  221. package/src/extensibility/plugins/git-url.ts +281 -0
  222. package/src/extensibility/plugins/index.ts +33 -0
  223. package/src/extensibility/plugins/installer.ts +192 -0
  224. package/src/extensibility/plugins/loader.ts +338 -0
  225. package/src/extensibility/plugins/manager.ts +716 -0
  226. package/src/extensibility/plugins/parser.ts +105 -0
  227. package/src/extensibility/plugins/types.ts +190 -0
  228. package/src/extensibility/skills.ts +385 -0
  229. package/src/extensibility/slash-commands.ts +287 -0
  230. package/src/extensibility/tool-proxy.ts +25 -0
  231. package/src/index.ts +275 -0
  232. package/src/internal-urls/agent-protocol.ts +136 -0
  233. package/src/internal-urls/artifact-protocol.ts +97 -0
  234. package/src/internal-urls/docs-index.generated.ts +54 -0
  235. package/src/internal-urls/docs-protocol.ts +84 -0
  236. package/src/internal-urls/index.ts +31 -0
  237. package/src/internal-urls/json-query.ts +126 -0
  238. package/src/internal-urls/memory-protocol.ts +133 -0
  239. package/src/internal-urls/router.ts +70 -0
  240. package/src/internal-urls/rule-protocol.ts +55 -0
  241. package/src/internal-urls/skill-protocol.ts +111 -0
  242. package/src/internal-urls/types.ts +52 -0
  243. package/src/ipy/executor.ts +556 -0
  244. package/src/ipy/gateway-coordinator.ts +426 -0
  245. package/src/ipy/kernel.ts +892 -0
  246. package/src/ipy/modules.ts +109 -0
  247. package/src/ipy/prelude.py +831 -0
  248. package/src/ipy/prelude.ts +3 -0
  249. package/src/ipy/runtime.ts +222 -0
  250. package/src/lsp/client.ts +867 -0
  251. package/src/lsp/clients/biome-client.ts +202 -0
  252. package/src/lsp/clients/index.ts +50 -0
  253. package/src/lsp/clients/lsp-linter-client.ts +93 -0
  254. package/src/lsp/clients/swiftlint-client.ts +120 -0
  255. package/src/lsp/config.ts +397 -0
  256. package/src/lsp/defaults.json +464 -0
  257. package/src/lsp/edits.ts +109 -0
  258. package/src/lsp/index.ts +1268 -0
  259. package/src/lsp/lspmux.ts +250 -0
  260. package/src/lsp/render.ts +689 -0
  261. package/src/lsp/types.ts +414 -0
  262. package/src/lsp/utils.ts +549 -0
  263. package/src/main.ts +773 -0
  264. package/src/mcp/client.ts +239 -0
  265. package/src/mcp/config-writer.ts +215 -0
  266. package/src/mcp/config.ts +363 -0
  267. package/src/mcp/index.ts +55 -0
  268. package/src/mcp/json-rpc.ts +84 -0
  269. package/src/mcp/loader.ts +124 -0
  270. package/src/mcp/manager.ts +490 -0
  271. package/src/mcp/oauth-discovery.ts +274 -0
  272. package/src/mcp/oauth-flow.ts +229 -0
  273. package/src/mcp/render.ts +123 -0
  274. package/src/mcp/tool-bridge.ts +372 -0
  275. package/src/mcp/tool-cache.ts +121 -0
  276. package/src/mcp/transports/http.ts +332 -0
  277. package/src/mcp/transports/index.ts +6 -0
  278. package/src/mcp/transports/stdio.ts +281 -0
  279. package/src/mcp/types.ts +248 -0
  280. package/src/memories/index.ts +1099 -0
  281. package/src/memories/storage.ts +563 -0
  282. package/src/modes/components/agent-dashboard.ts +1130 -0
  283. package/src/modes/components/assistant-message.ts +144 -0
  284. package/src/modes/components/bash-execution.ts +218 -0
  285. package/src/modes/components/bordered-loader.ts +41 -0
  286. package/src/modes/components/branch-summary-message.ts +45 -0
  287. package/src/modes/components/codemode-group.ts +369 -0
  288. package/src/modes/components/compaction-summary-message.ts +51 -0
  289. package/src/modes/components/countdown-timer.ts +46 -0
  290. package/src/modes/components/custom-editor.ts +181 -0
  291. package/src/modes/components/custom-message.ts +91 -0
  292. package/src/modes/components/diff.ts +186 -0
  293. package/src/modes/components/dynamic-border.ts +25 -0
  294. package/src/modes/components/extensions/extension-dashboard.ts +325 -0
  295. package/src/modes/components/extensions/extension-list.ts +484 -0
  296. package/src/modes/components/extensions/index.ts +9 -0
  297. package/src/modes/components/extensions/inspector-panel.ts +321 -0
  298. package/src/modes/components/extensions/state-manager.ts +586 -0
  299. package/src/modes/components/extensions/types.ts +191 -0
  300. package/src/modes/components/footer.ts +315 -0
  301. package/src/modes/components/history-search.ts +157 -0
  302. package/src/modes/components/hook-editor.ts +101 -0
  303. package/src/modes/components/hook-input.ts +72 -0
  304. package/src/modes/components/hook-message.ts +100 -0
  305. package/src/modes/components/hook-selector.ts +155 -0
  306. package/src/modes/components/index.ts +41 -0
  307. package/src/modes/components/keybinding-hints.ts +65 -0
  308. package/src/modes/components/login-dialog.ts +164 -0
  309. package/src/modes/components/mcp-add-wizard.ts +1295 -0
  310. package/src/modes/components/model-selector.ts +625 -0
  311. package/src/modes/components/oauth-selector.ts +210 -0
  312. package/src/modes/components/plugin-settings.ts +477 -0
  313. package/src/modes/components/python-execution.ts +196 -0
  314. package/src/modes/components/queue-mode-selector.ts +56 -0
  315. package/src/modes/components/read-tool-group.ts +119 -0
  316. package/src/modes/components/session-selector.ts +242 -0
  317. package/src/modes/components/settings-defs.ts +340 -0
  318. package/src/modes/components/settings-selector.ts +529 -0
  319. package/src/modes/components/show-images-selector.ts +45 -0
  320. package/src/modes/components/skill-message.ts +90 -0
  321. package/src/modes/components/status-line/index.ts +4 -0
  322. package/src/modes/components/status-line/presets.ts +94 -0
  323. package/src/modes/components/status-line/segments.ts +352 -0
  324. package/src/modes/components/status-line/separators.ts +55 -0
  325. package/src/modes/components/status-line/types.ts +75 -0
  326. package/src/modes/components/status-line-segment-editor.ts +354 -0
  327. package/src/modes/components/status-line.ts +421 -0
  328. package/src/modes/components/theme-selector.ts +63 -0
  329. package/src/modes/components/thinking-selector.ts +64 -0
  330. package/src/modes/components/todo-display.ts +115 -0
  331. package/src/modes/components/todo-reminder.ts +40 -0
  332. package/src/modes/components/tool-execution.ts +703 -0
  333. package/src/modes/components/tree-selector.ts +904 -0
  334. package/src/modes/components/ttsr-notification.ts +80 -0
  335. package/src/modes/components/user-message-selector.ts +146 -0
  336. package/src/modes/components/user-message.ts +22 -0
  337. package/src/modes/components/visual-truncate.ts +63 -0
  338. package/src/modes/components/welcome.ts +247 -0
  339. package/src/modes/controllers/command-controller.ts +1120 -0
  340. package/src/modes/controllers/event-controller.ts +479 -0
  341. package/src/modes/controllers/extension-ui-controller.ts +778 -0
  342. package/src/modes/controllers/input-controller.ts +671 -0
  343. package/src/modes/controllers/mcp-command-controller.ts +1315 -0
  344. package/src/modes/controllers/selector-controller.ts +712 -0
  345. package/src/modes/controllers/ssh-command-controller.ts +452 -0
  346. package/src/modes/index.ts +15 -0
  347. package/src/modes/interactive-mode.ts +1027 -0
  348. package/src/modes/print-mode.ts +191 -0
  349. package/src/modes/rpc/rpc-client.ts +583 -0
  350. package/src/modes/rpc/rpc-mode.ts +700 -0
  351. package/src/modes/rpc/rpc-types.ts +236 -0
  352. package/src/modes/theme/dark.json +95 -0
  353. package/src/modes/theme/defaults/alabaster.json +93 -0
  354. package/src/modes/theme/defaults/amethyst.json +96 -0
  355. package/src/modes/theme/defaults/anthracite.json +93 -0
  356. package/src/modes/theme/defaults/basalt.json +91 -0
  357. package/src/modes/theme/defaults/birch.json +95 -0
  358. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  359. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  360. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  361. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  362. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  363. package/src/modes/theme/defaults/dark-copper.json +95 -0
  364. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  365. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  366. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  367. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  368. package/src/modes/theme/defaults/dark-ember.json +95 -0
  369. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  370. package/src/modes/theme/defaults/dark-forest.json +96 -0
  371. package/src/modes/theme/defaults/dark-github.json +105 -0
  372. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  373. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  374. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  375. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  376. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  377. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  378. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  379. package/src/modes/theme/defaults/dark-nord.json +97 -0
  380. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  381. package/src/modes/theme/defaults/dark-one.json +100 -0
  382. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  383. package/src/modes/theme/defaults/dark-reef.json +91 -0
  384. package/src/modes/theme/defaults/dark-retro.json +92 -0
  385. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  386. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  387. package/src/modes/theme/defaults/dark-slate.json +95 -0
  388. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  389. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  390. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  391. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  392. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  393. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  394. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  395. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  396. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  397. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  398. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  399. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  400. package/src/modes/theme/defaults/graphite.json +92 -0
  401. package/src/modes/theme/defaults/index.ts +195 -0
  402. package/src/modes/theme/defaults/light-arctic.json +107 -0
  403. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  404. package/src/modes/theme/defaults/light-canyon.json +91 -0
  405. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  406. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  407. package/src/modes/theme/defaults/light-coral.json +95 -0
  408. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  409. package/src/modes/theme/defaults/light-dawn.json +90 -0
  410. package/src/modes/theme/defaults/light-dunes.json +91 -0
  411. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  412. package/src/modes/theme/defaults/light-forest.json +100 -0
  413. package/src/modes/theme/defaults/light-frost.json +95 -0
  414. package/src/modes/theme/defaults/light-github.json +115 -0
  415. package/src/modes/theme/defaults/light-glacier.json +91 -0
  416. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  417. package/src/modes/theme/defaults/light-haze.json +90 -0
  418. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  419. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  420. package/src/modes/theme/defaults/light-lavender.json +95 -0
  421. package/src/modes/theme/defaults/light-meadow.json +91 -0
  422. package/src/modes/theme/defaults/light-mint.json +95 -0
  423. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  424. package/src/modes/theme/defaults/light-ocean.json +99 -0
  425. package/src/modes/theme/defaults/light-one.json +99 -0
  426. package/src/modes/theme/defaults/light-opal.json +91 -0
  427. package/src/modes/theme/defaults/light-orchard.json +91 -0
  428. package/src/modes/theme/defaults/light-paper.json +95 -0
  429. package/src/modes/theme/defaults/light-prism.json +90 -0
  430. package/src/modes/theme/defaults/light-retro.json +98 -0
  431. package/src/modes/theme/defaults/light-sand.json +95 -0
  432. package/src/modes/theme/defaults/light-savanna.json +91 -0
  433. package/src/modes/theme/defaults/light-solarized.json +102 -0
  434. package/src/modes/theme/defaults/light-soleil.json +90 -0
  435. package/src/modes/theme/defaults/light-sunset.json +99 -0
  436. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  437. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  438. package/src/modes/theme/defaults/light-wetland.json +91 -0
  439. package/src/modes/theme/defaults/light-zenith.json +89 -0
  440. package/src/modes/theme/defaults/limestone.json +94 -0
  441. package/src/modes/theme/defaults/mahogany.json +97 -0
  442. package/src/modes/theme/defaults/marble.json +93 -0
  443. package/src/modes/theme/defaults/obsidian.json +91 -0
  444. package/src/modes/theme/defaults/onyx.json +91 -0
  445. package/src/modes/theme/defaults/pearl.json +93 -0
  446. package/src/modes/theme/defaults/porcelain.json +91 -0
  447. package/src/modes/theme/defaults/quartz.json +96 -0
  448. package/src/modes/theme/defaults/sandstone.json +95 -0
  449. package/src/modes/theme/defaults/titanium.json +90 -0
  450. package/src/modes/theme/light.json +93 -0
  451. package/src/modes/theme/mermaid-cache.ts +111 -0
  452. package/src/modes/theme/theme-schema.json +429 -0
  453. package/src/modes/theme/theme.ts +2333 -0
  454. package/src/modes/types.ts +216 -0
  455. package/src/modes/utils/ui-helpers.ts +529 -0
  456. package/src/patch/applicator.ts +1482 -0
  457. package/src/patch/diff.ts +425 -0
  458. package/src/patch/fuzzy.ts +784 -0
  459. package/src/patch/hashline.ts +972 -0
  460. package/src/patch/index.ts +964 -0
  461. package/src/patch/normalize.ts +397 -0
  462. package/src/patch/normative.ts +72 -0
  463. package/src/patch/parser.ts +532 -0
  464. package/src/patch/shared.ts +400 -0
  465. package/src/patch/types.ts +292 -0
  466. package/src/priority.json +35 -0
  467. package/src/prompts/agents/explore.md +48 -0
  468. package/src/prompts/agents/frontmatter.md +9 -0
  469. package/src/prompts/agents/init.md +36 -0
  470. package/src/prompts/agents/librarian.md +53 -0
  471. package/src/prompts/agents/oracle.md +51 -0
  472. package/src/prompts/agents/reviewer.md +70 -0
  473. package/src/prompts/agents/task.md +14 -0
  474. package/src/prompts/compaction/branch-summary-context.md +5 -0
  475. package/src/prompts/compaction/branch-summary-preamble.md +2 -0
  476. package/src/prompts/compaction/branch-summary.md +30 -0
  477. package/src/prompts/compaction/compaction-short-summary.md +9 -0
  478. package/src/prompts/compaction/compaction-summary-context.md +5 -0
  479. package/src/prompts/compaction/compaction-summary.md +38 -0
  480. package/src/prompts/compaction/compaction-turn-prefix.md +17 -0
  481. package/src/prompts/compaction/compaction-update-summary.md +45 -0
  482. package/src/prompts/memories/consolidation.md +30 -0
  483. package/src/prompts/memories/read_path.md +11 -0
  484. package/src/prompts/memories/stage_one_input.md +6 -0
  485. package/src/prompts/memories/stage_one_system.md +21 -0
  486. package/src/prompts/review-request.md +64 -0
  487. package/src/prompts/system/agent-creation-architect.md +65 -0
  488. package/src/prompts/system/agent-creation-user.md +6 -0
  489. package/src/prompts/system/custom-system-prompt.md +68 -0
  490. package/src/prompts/system/file-operations.md +10 -0
  491. package/src/prompts/system/subagent-submit-reminder.md +11 -0
  492. package/src/prompts/system/subagent-system-prompt.md +31 -0
  493. package/src/prompts/system/subagent-user-prompt.md +8 -0
  494. package/src/prompts/system/summarization-system.md +3 -0
  495. package/src/prompts/system/system-prompt.md +300 -0
  496. package/src/prompts/system/title-system.md +2 -0
  497. package/src/prompts/system/ttsr-interrupt.md +7 -0
  498. package/src/prompts/system/web-search.md +28 -0
  499. package/src/prompts/tools/ask.md +44 -0
  500. package/src/prompts/tools/bash.md +24 -0
  501. package/src/prompts/tools/browser.md +33 -0
  502. package/src/prompts/tools/calculator.md +12 -0
  503. package/src/prompts/tools/explore.md +29 -0
  504. package/src/prompts/tools/fetch.md +16 -0
  505. package/src/prompts/tools/find.md +18 -0
  506. package/src/prompts/tools/gemini-image.md +23 -0
  507. package/src/prompts/tools/grep.md +28 -0
  508. package/src/prompts/tools/hashline.md +232 -0
  509. package/src/prompts/tools/librarian.md +24 -0
  510. package/src/prompts/tools/lsp.md +28 -0
  511. package/src/prompts/tools/oracle.md +26 -0
  512. package/src/prompts/tools/patch.md +74 -0
  513. package/src/prompts/tools/python.md +66 -0
  514. package/src/prompts/tools/read.md +36 -0
  515. package/src/prompts/tools/replace.md +38 -0
  516. package/src/prompts/tools/reviewer.md +41 -0
  517. package/src/prompts/tools/ssh.md +51 -0
  518. package/src/prompts/tools/task-summary.md +28 -0
  519. package/src/prompts/tools/task.md +275 -0
  520. package/src/prompts/tools/todo-write.md +65 -0
  521. package/src/prompts/tools/undo-edit.md +7 -0
  522. package/src/prompts/tools/web-search.md +19 -0
  523. package/src/prompts/tools/write.md +18 -0
  524. package/src/sdk.ts +1287 -0
  525. package/src/secrets/index.ts +116 -0
  526. package/src/secrets/obfuscator.ts +269 -0
  527. package/src/secrets/regex.ts +21 -0
  528. package/src/session/agent-session.ts +4669 -0
  529. package/src/session/agent-storage.ts +621 -0
  530. package/src/session/artifacts.ts +132 -0
  531. package/src/session/auth-storage.ts +1433 -0
  532. package/src/session/blob-store.ts +103 -0
  533. package/src/session/compaction/branch-summarization.ts +315 -0
  534. package/src/session/compaction/compaction.ts +864 -0
  535. package/src/session/compaction/index.ts +7 -0
  536. package/src/session/compaction/pruning.ts +91 -0
  537. package/src/session/compaction/utils.ts +171 -0
  538. package/src/session/history-storage.ts +170 -0
  539. package/src/session/messages.ts +317 -0
  540. package/src/session/session-manager.ts +2276 -0
  541. package/src/session/session-storage.ts +342 -0
  542. package/src/session/streaming-output.ts +565 -0
  543. package/src/slash-commands/builtin-registry.ts +439 -0
  544. package/src/ssh/config-writer.ts +183 -0
  545. package/src/ssh/connection-manager.ts +444 -0
  546. package/src/ssh/ssh-executor.ts +127 -0
  547. package/src/ssh/sshfs-mount.ts +135 -0
  548. package/src/stt/downloader.ts +71 -0
  549. package/src/stt/index.ts +3 -0
  550. package/src/stt/recorder.ts +351 -0
  551. package/src/stt/setup.ts +52 -0
  552. package/src/stt/stt-controller.ts +160 -0
  553. package/src/stt/transcribe.py +70 -0
  554. package/src/stt/transcriber.ts +91 -0
  555. package/src/system-prompt.ts +685 -0
  556. package/src/task/agents.ts +155 -0
  557. package/src/task/batch.ts +102 -0
  558. package/src/task/commands.ts +134 -0
  559. package/src/task/discovery.ts +126 -0
  560. package/src/task/executor.ts +908 -0
  561. package/src/task/index.ts +223 -0
  562. package/src/task/output-manager.ts +107 -0
  563. package/src/task/parallel.ts +84 -0
  564. package/src/task/render.ts +326 -0
  565. package/src/task/subprocess-tool-registry.ts +88 -0
  566. package/src/task/template.ts +32 -0
  567. package/src/task/types.ts +144 -0
  568. package/src/tools/ask.ts +523 -0
  569. package/src/tools/bash-interactive.ts +419 -0
  570. package/src/tools/bash-interceptor.ts +105 -0
  571. package/src/tools/bash-normalize.ts +107 -0
  572. package/src/tools/bash-skill-urls.ts +177 -0
  573. package/src/tools/bash.ts +347 -0
  574. package/src/tools/browser.ts +1374 -0
  575. package/src/tools/calculator.ts +537 -0
  576. package/src/tools/context.ts +39 -0
  577. package/src/tools/explore.ts +23 -0
  578. package/src/tools/fetch.ts +1091 -0
  579. package/src/tools/find.ts +540 -0
  580. package/src/tools/fs-cache-invalidation.ts +28 -0
  581. package/src/tools/gemini-image.ts +907 -0
  582. package/src/tools/grep.ts +489 -0
  583. package/src/tools/index.ts +337 -0
  584. package/src/tools/json-tree.ts +231 -0
  585. package/src/tools/jtd-to-json-schema.ts +247 -0
  586. package/src/tools/jtd-to-typescript.ts +198 -0
  587. package/src/tools/librarian.ts +33 -0
  588. package/src/tools/list-limit.ts +40 -0
  589. package/src/tools/notebook.ts +287 -0
  590. package/src/tools/oracle.ts +40 -0
  591. package/src/tools/output-meta.ts +459 -0
  592. package/src/tools/output-utils.ts +63 -0
  593. package/src/tools/path-utils.ts +116 -0
  594. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  595. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  596. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  597. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  598. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  599. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  600. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  601. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  602. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  603. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  604. package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
  605. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  606. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  607. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  608. package/src/tools/python.ts +1118 -0
  609. package/src/tools/read.ts +1193 -0
  610. package/src/tools/render-utils.ts +680 -0
  611. package/src/tools/renderers.ts +60 -0
  612. package/src/tools/reviewer-tool.ts +41 -0
  613. package/src/tools/ssh.ts +326 -0
  614. package/src/tools/subagent-tool.ts +169 -0
  615. package/src/tools/submit-result.ts +152 -0
  616. package/src/tools/todo-write.ts +255 -0
  617. package/src/tools/tool-errors.ts +92 -0
  618. package/src/tools/tool-result.ts +86 -0
  619. package/src/tools/undo-edit.ts +145 -0
  620. package/src/tools/undo-history.ts +22 -0
  621. package/src/tools/write.ts +274 -0
  622. package/src/tui/code-cell.ts +108 -0
  623. package/src/tui/file-list.ts +47 -0
  624. package/src/tui/index.ts +11 -0
  625. package/src/tui/output-block.ts +144 -0
  626. package/src/tui/status-line.ts +39 -0
  627. package/src/tui/tree-list.ts +53 -0
  628. package/src/tui/types.ts +16 -0
  629. package/src/tui/utils.ts +116 -0
  630. package/src/utils/changelog.ts +98 -0
  631. package/src/utils/event-bus.ts +33 -0
  632. package/src/utils/external-editor.ts +59 -0
  633. package/src/utils/file-display-mode.ts +36 -0
  634. package/src/utils/file-mentions.ts +384 -0
  635. package/src/utils/frontmatter.ts +101 -0
  636. package/src/utils/fuzzy.ts +108 -0
  637. package/src/utils/ignore-files.ts +119 -0
  638. package/src/utils/image-convert.ts +27 -0
  639. package/src/utils/image-resize.ts +236 -0
  640. package/src/utils/mime.ts +30 -0
  641. package/src/utils/open.ts +20 -0
  642. package/src/utils/shell-snapshot.ts +199 -0
  643. package/src/utils/timings.ts +26 -0
  644. package/src/utils/title-generator.ts +167 -0
  645. package/src/utils/tools-manager.ts +362 -0
  646. package/src/web/scrapers/artifacthub.ts +215 -0
  647. package/src/web/scrapers/arxiv.ts +88 -0
  648. package/src/web/scrapers/aur.ts +175 -0
  649. package/src/web/scrapers/biorxiv.ts +141 -0
  650. package/src/web/scrapers/bluesky.ts +284 -0
  651. package/src/web/scrapers/brew.ts +177 -0
  652. package/src/web/scrapers/cheatsh.ts +78 -0
  653. package/src/web/scrapers/chocolatey.ts +158 -0
  654. package/src/web/scrapers/choosealicense.ts +110 -0
  655. package/src/web/scrapers/cisa-kev.ts +100 -0
  656. package/src/web/scrapers/clojars.ts +180 -0
  657. package/src/web/scrapers/coingecko.ts +184 -0
  658. package/src/web/scrapers/crates-io.ts +128 -0
  659. package/src/web/scrapers/crossref.ts +149 -0
  660. package/src/web/scrapers/devto.ts +177 -0
  661. package/src/web/scrapers/discogs.ts +307 -0
  662. package/src/web/scrapers/discourse.ts +221 -0
  663. package/src/web/scrapers/dockerhub.ts +160 -0
  664. package/src/web/scrapers/fdroid.ts +158 -0
  665. package/src/web/scrapers/firefox-addons.ts +214 -0
  666. package/src/web/scrapers/flathub.ts +239 -0
  667. package/src/web/scrapers/github-gist.ts +68 -0
  668. package/src/web/scrapers/github.ts +490 -0
  669. package/src/web/scrapers/gitlab.ts +456 -0
  670. package/src/web/scrapers/go-pkg.ts +275 -0
  671. package/src/web/scrapers/hackage.ts +94 -0
  672. package/src/web/scrapers/hackernews.ts +208 -0
  673. package/src/web/scrapers/hex.ts +121 -0
  674. package/src/web/scrapers/huggingface.ts +385 -0
  675. package/src/web/scrapers/iacr.ts +86 -0
  676. package/src/web/scrapers/index.ts +249 -0
  677. package/src/web/scrapers/jetbrains-marketplace.ts +169 -0
  678. package/src/web/scrapers/lemmy.ts +220 -0
  679. package/src/web/scrapers/lobsters.ts +186 -0
  680. package/src/web/scrapers/mastodon.ts +310 -0
  681. package/src/web/scrapers/maven.ts +152 -0
  682. package/src/web/scrapers/mdn.ts +172 -0
  683. package/src/web/scrapers/metacpan.ts +253 -0
  684. package/src/web/scrapers/musicbrainz.ts +272 -0
  685. package/src/web/scrapers/npm.ts +114 -0
  686. package/src/web/scrapers/nuget.ts +205 -0
  687. package/src/web/scrapers/nvd.ts +243 -0
  688. package/src/web/scrapers/ollama.ts +265 -0
  689. package/src/web/scrapers/open-vsx.ts +119 -0
  690. package/src/web/scrapers/opencorporates.ts +275 -0
  691. package/src/web/scrapers/openlibrary.ts +319 -0
  692. package/src/web/scrapers/orcid.ts +298 -0
  693. package/src/web/scrapers/osv.ts +192 -0
  694. package/src/web/scrapers/packagist.ts +174 -0
  695. package/src/web/scrapers/pub-dev.ts +185 -0
  696. package/src/web/scrapers/pubmed.ts +177 -0
  697. package/src/web/scrapers/pypi.ts +129 -0
  698. package/src/web/scrapers/rawg.ts +124 -0
  699. package/src/web/scrapers/readthedocs.ts +125 -0
  700. package/src/web/scrapers/reddit.ts +104 -0
  701. package/src/web/scrapers/repology.ts +262 -0
  702. package/src/web/scrapers/rfc.ts +209 -0
  703. package/src/web/scrapers/rubygems.ts +117 -0
  704. package/src/web/scrapers/searchcode.ts +217 -0
  705. package/src/web/scrapers/sec-edgar.ts +274 -0
  706. package/src/web/scrapers/semantic-scholar.ts +190 -0
  707. package/src/web/scrapers/snapcraft.ts +200 -0
  708. package/src/web/scrapers/sourcegraph.ts +373 -0
  709. package/src/web/scrapers/spdx.ts +121 -0
  710. package/src/web/scrapers/spotify.ts +217 -0
  711. package/src/web/scrapers/stackoverflow.ts +124 -0
  712. package/src/web/scrapers/terraform.ts +304 -0
  713. package/src/web/scrapers/tldr.ts +51 -0
  714. package/src/web/scrapers/twitter.ts +97 -0
  715. package/src/web/scrapers/types.ts +200 -0
  716. package/src/web/scrapers/utils.ts +142 -0
  717. package/src/web/scrapers/vimeo.ts +152 -0
  718. package/src/web/scrapers/vscode-marketplace.ts +195 -0
  719. package/src/web/scrapers/w3c.ts +163 -0
  720. package/src/web/scrapers/wikidata.ts +357 -0
  721. package/src/web/scrapers/wikipedia.ts +95 -0
  722. package/src/web/scrapers/youtube.ts +312 -0
  723. package/src/web/search/auth.ts +178 -0
  724. package/src/web/search/index.ts +598 -0
  725. package/src/web/search/provider.ts +77 -0
  726. package/src/web/search/providers/anthropic.ts +284 -0
  727. package/src/web/search/providers/base.ts +22 -0
  728. package/src/web/search/providers/brave.ts +165 -0
  729. package/src/web/search/providers/codex.ts +377 -0
  730. package/src/web/search/providers/exa.ts +158 -0
  731. package/src/web/search/providers/gemini.ts +437 -0
  732. package/src/web/search/providers/jina.ts +99 -0
  733. package/src/web/search/providers/kimi.ts +196 -0
  734. package/src/web/search/providers/perplexity.ts +546 -0
  735. package/src/web/search/providers/synthetic.ts +136 -0
  736. package/src/web/search/providers/zai.ts +352 -0
  737. package/src/web/search/render.ts +299 -0
  738. package/src/web/search/types.ts +437 -0
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Feature bracket parser for plugin specifiers.
3
+ *
4
+ * Supports syntax like:
5
+ * - "my-plugin" -> base features (null)
6
+ * - "my-plugin[search,web]" -> specific features
7
+ * - "my-plugin[*]" -> all features
8
+ * - "my-plugin[]" -> no optional features
9
+ * - "@scope/plugin@1.2.3[feat]" -> scoped with version and features
10
+ */
11
+
12
+ export interface ParsedPluginSpec {
13
+ /** Package name (may include version specifier like @1.0.0) */
14
+ packageName: string;
15
+ /**
16
+ * Feature selection:
17
+ * - null: use defaults (base features on first install, preserve on reinstall)
18
+ * - "*": all features
19
+ * - string[]: specific features (empty array = no optional features)
20
+ */
21
+ features: string[] | null | "*";
22
+ }
23
+
24
+ /**
25
+ * Parse plugin specifier with feature bracket syntax.
26
+ *
27
+ * @example
28
+ * parsePluginSpec("my-plugin") // { packageName: "my-plugin", features: null }
29
+ * parsePluginSpec("my-plugin[search,web]") // { packageName: "my-plugin", features: ["search", "web"] }
30
+ * parsePluginSpec("my-plugin[*]") // { packageName: "my-plugin", features: "*" }
31
+ * parsePluginSpec("my-plugin[]") // { packageName: "my-plugin", features: [] }
32
+ * parsePluginSpec("@scope/pkg@1.2.3[feat]") // { packageName: "@scope/pkg@1.2.3", features: ["feat"] }
33
+ */
34
+ export function parsePluginSpec(spec: string): ParsedPluginSpec {
35
+ // Find the last bracket pair (to handle version specifiers like @1.0.0)
36
+ const bracketStart = spec.lastIndexOf("[");
37
+ const bracketEnd = spec.lastIndexOf("]");
38
+
39
+ // No brackets or malformed -> base features
40
+ if (bracketStart === -1 || bracketEnd === -1 || bracketEnd < bracketStart) {
41
+ return { packageName: spec, features: null };
42
+ }
43
+
44
+ const packageName = spec.slice(0, bracketStart);
45
+ const featureStr = spec.slice(bracketStart + 1, bracketEnd).trim();
46
+
47
+ // All features
48
+ if (featureStr === "*") {
49
+ return { packageName, features: "*" };
50
+ }
51
+
52
+ // No optional features
53
+ if (featureStr === "") {
54
+ return { packageName, features: [] };
55
+ }
56
+
57
+ // Specific features (comma-separated)
58
+ const features = featureStr
59
+ .split(",")
60
+ .map(f => f.trim())
61
+ .filter(Boolean);
62
+
63
+ return { packageName, features };
64
+ }
65
+
66
+ /**
67
+ * Format a parsed plugin spec back to string form.
68
+ *
69
+ * @example
70
+ * formatPluginSpec({ packageName: "pkg", features: null }) // "pkg"
71
+ * formatPluginSpec({ packageName: "pkg", features: "*" }) // "pkg[*]"
72
+ * formatPluginSpec({ packageName: "pkg", features: [] }) // "pkg[]"
73
+ * formatPluginSpec({ packageName: "pkg", features: ["a", "b"] }) // "pkg[a,b]"
74
+ */
75
+ export function formatPluginSpec(spec: ParsedPluginSpec): string {
76
+ if (spec.features === null) {
77
+ return spec.packageName;
78
+ }
79
+ if (spec.features === "*") {
80
+ return `${spec.packageName}[*]`;
81
+ }
82
+ if (spec.features.length === 0) {
83
+ return `${spec.packageName}[]`;
84
+ }
85
+ return `${spec.packageName}[${spec.features.join(",")}]`;
86
+ }
87
+
88
+ /**
89
+ * Extract the base package name without version specifier.
90
+ * Used for path lookups after npm install.
91
+ *
92
+ * @example
93
+ * extractPackageName("lodash@4.17.21") // "lodash"
94
+ * extractPackageName("@scope/pkg@1.0.0") // "@scope/pkg"
95
+ * extractPackageName("@scope/pkg") // "@scope/pkg"
96
+ */
97
+ export function extractPackageName(specifier: string): string {
98
+ // Handle scoped packages: @scope/name@version -> @scope/name
99
+ if (specifier.startsWith("@")) {
100
+ const match = specifier.match(/^(@[^/]+\/[^@]+)/);
101
+ return match ? match[1] : specifier;
102
+ }
103
+ // Unscoped: name@version -> name
104
+ return specifier.replace(/@[^@]+$/, "");
105
+ }
@@ -0,0 +1,190 @@
1
+ // =============================================================================
2
+ // Plugin Manifest Types (from package.json arc/pi field)
3
+ // =============================================================================
4
+
5
+ /**
6
+ * Feature definition for selective plugin installation.
7
+ * Features allow plugins to expose optional functionality.
8
+ */
9
+ export interface PluginFeature {
10
+ /** Human-readable description */
11
+ description?: string;
12
+ /** Whether this feature is enabled by default */
13
+ default?: boolean;
14
+ /** Additional tool entry points provided by this feature */
15
+ tools?: string[];
16
+ /** Additional hook entry points provided by this feature */
17
+ hooks?: string[];
18
+ /** Additional command files provided by this feature */
19
+ commands?: string[];
20
+ }
21
+
22
+ /**
23
+ * Plugin manifest from package.json arcane or pi field.
24
+ */
25
+ export interface PluginManifest {
26
+ /** Plugin display name (defaults to package name) */
27
+ name?: string;
28
+ /** Plugin version (copied from package.json version) */
29
+ version: string;
30
+ /** Human-readable description */
31
+ description?: string;
32
+
33
+ /** Entry point for base tools (relative path from package root) */
34
+ tools?: string;
35
+ /** Entry point for base hooks (relative path from package root) */
36
+ hooks?: string;
37
+ /** Command files (relative paths from package root) */
38
+ commands?: string[];
39
+
40
+ /** Feature definitions for selective installation */
41
+ features?: Record<string, PluginFeature>;
42
+
43
+ /** Settings schema for plugin configuration */
44
+ settings?: Record<string, PluginSettingSchema>;
45
+ }
46
+
47
+ // =============================================================================
48
+ // Plugin Settings Schema Types
49
+ // =============================================================================
50
+
51
+ export type PluginSettingType = "string" | "number" | "boolean" | "enum";
52
+
53
+ interface PluginSettingBase {
54
+ /** Setting type */
55
+ type: PluginSettingType;
56
+ /** Human-readable description */
57
+ description?: string;
58
+ /** If true, mask value in UI and logs */
59
+ secret?: boolean;
60
+ /** Environment variable to use as fallback value */
61
+ env?: string;
62
+ }
63
+
64
+ export interface StringSetting extends PluginSettingBase {
65
+ type: "string";
66
+ default?: string;
67
+ }
68
+
69
+ export interface NumberSetting extends PluginSettingBase {
70
+ type: "number";
71
+ default?: number;
72
+ min?: number;
73
+ max?: number;
74
+ step?: number;
75
+ }
76
+
77
+ export interface BooleanSetting extends PluginSettingBase {
78
+ type: "boolean";
79
+ default?: boolean;
80
+ }
81
+
82
+ export interface EnumSetting extends PluginSettingBase {
83
+ type: "enum";
84
+ /** Allowed values */
85
+ values: string[];
86
+ default?: string;
87
+ }
88
+
89
+ export type PluginSettingSchema = StringSetting | NumberSetting | BooleanSetting | EnumSetting;
90
+
91
+ // =============================================================================
92
+ // Installed Plugin Types
93
+ // =============================================================================
94
+
95
+ /**
96
+ * Represents an installed plugin with full metadata.
97
+ */
98
+ export interface InstalledPlugin {
99
+ /** npm package name */
100
+ name: string;
101
+ /** Installed version */
102
+ version: string;
103
+ /** Absolute path to package directory */
104
+ path: string;
105
+ /** Parsed arc/pi manifest */
106
+ manifest: PluginManifest;
107
+ /**
108
+ * Enabled features:
109
+ * - null: use defaults (all features with default: true)
110
+ * - string[]: specific features enabled
111
+ */
112
+ enabledFeatures: string[] | null;
113
+ /** Whether the plugin is enabled */
114
+ enabled: boolean;
115
+ }
116
+
117
+ // =============================================================================
118
+ // Runtime Config Types (stored in arcane-plugins.lock.json)
119
+ // =============================================================================
120
+
121
+ /**
122
+ * Per-plugin runtime state stored in lock file.
123
+ */
124
+ export interface PluginRuntimeState {
125
+ /** Installed version */
126
+ version: string;
127
+ /** Enabled features (null = defaults) */
128
+ enabledFeatures: string[] | null;
129
+ /** Whether the plugin is enabled */
130
+ enabled: boolean;
131
+ }
132
+
133
+ /**
134
+ * Runtime configuration persisted to arcane-plugins.lock.json.
135
+ * Tracks plugin states and settings across sessions.
136
+ */
137
+ export interface PluginRuntimeConfig {
138
+ /** Plugin states keyed by package name */
139
+ plugins: Record<string, PluginRuntimeState>;
140
+ /** Plugin settings keyed by package name, then setting key */
141
+ settings: Record<string, Record<string, unknown>>;
142
+ }
143
+
144
+ // =============================================================================
145
+ // Project Override Types
146
+ // =============================================================================
147
+
148
+ /**
149
+ * Project-local plugin overrides (stored in .arcane/plugin-overrides.json).
150
+ * Allows per-project plugin configuration without modifying global state.
151
+ */
152
+ export interface ProjectPluginOverrides {
153
+ /** Plugins to disable in this project */
154
+ disabled?: string[];
155
+ /** Per-plugin feature overrides */
156
+ features?: Record<string, string[]>;
157
+ /** Per-plugin setting overrides */
158
+ settings?: Record<string, Record<string, unknown>>;
159
+ }
160
+
161
+ // =============================================================================
162
+ // Doctor Types
163
+ // =============================================================================
164
+
165
+ export interface DoctorCheck {
166
+ /** Check identifier */
167
+ name: string;
168
+ /** Check result status */
169
+ status: "ok" | "warning" | "error";
170
+ /** Human-readable message */
171
+ message: string;
172
+ /** Whether --fix resolved this issue */
173
+ fixed?: boolean;
174
+ }
175
+
176
+ // =============================================================================
177
+ // Install Options Types
178
+ // =============================================================================
179
+
180
+ export interface InstallOptions {
181
+ /** Overwrite existing without prompting */
182
+ force?: boolean;
183
+ /** Preview changes without applying */
184
+ dryRun?: boolean;
185
+ }
186
+
187
+ export interface DoctorOptions {
188
+ /** Attempt automatic fixes */
189
+ fix?: boolean;
190
+ }
@@ -0,0 +1,385 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
+ import { logger } from "@nghyane/arcane-utils";
5
+ import { getProjectDir } from "@nghyane/arcane-utils/dirs";
6
+ import { skillCapability } from "../capability/skill";
7
+ import type { SourceMeta } from "../capability/types";
8
+ import type { SkillsSettings } from "../config/settings";
9
+ import type { Skill as CapabilitySkill, SkillFrontmatter as ImportedSkillFrontmatter } from "../discovery";
10
+ import { loadCapability } from "../discovery";
11
+ import { parseFrontmatter } from "../utils/frontmatter";
12
+ import { addIgnoreRules, createIgnoreMatcher, type IgnoreMatcher, shouldIgnore } from "../utils/ignore-files";
13
+
14
+ // Re-export SkillFrontmatter for backward compatibility
15
+ export type { ImportedSkillFrontmatter as SkillFrontmatter };
16
+
17
+ export interface Skill {
18
+ name: string;
19
+ description: string;
20
+ filePath: string;
21
+ baseDir: string;
22
+ source: string;
23
+ /** Source metadata for display */
24
+ _source?: SourceMeta;
25
+ }
26
+
27
+ export interface SkillWarning {
28
+ skillPath: string;
29
+ message: string;
30
+ }
31
+
32
+ export interface LoadSkillsResult {
33
+ skills: Skill[];
34
+ warnings: SkillWarning[];
35
+ }
36
+
37
+ export interface LoadSkillsFromDirOptions {
38
+ /** Directory to scan for skills */
39
+ dir: string;
40
+ /** Source identifier for these skills */
41
+ source: string;
42
+ }
43
+
44
+ async function readFileContent(filePath: string): Promise<string | null> {
45
+ try {
46
+ return await fs.readFile(filePath, "utf-8");
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Load skills from a directory recursively.
54
+ * Skills are directories containing a SKILL.md file with frontmatter including a description.
55
+ * Respects .gitignore, .ignore, and .fdignore files.
56
+ */
57
+ export async function loadSkillsFromDir(options: LoadSkillsFromDirOptions): Promise<LoadSkillsResult> {
58
+ const skills: Skill[] = [];
59
+ const warnings: SkillWarning[] = [];
60
+ const seenPaths = new Set<string>();
61
+ const rootDir = options.dir;
62
+
63
+ async function addSkill(skillFile: string, skillDir: string, dirName: string): Promise<void> {
64
+ if (seenPaths.has(skillFile)) return;
65
+ try {
66
+ const content = await fs.readFile(skillFile, "utf-8");
67
+ const { frontmatter } = parseFrontmatter(content, { source: skillFile });
68
+ const name = (frontmatter.name as string) || dirName;
69
+ const description = frontmatter.description as string;
70
+
71
+ if (description) {
72
+ seenPaths.add(skillFile);
73
+ skills.push({
74
+ name,
75
+ description,
76
+ filePath: skillFile,
77
+ baseDir: skillDir,
78
+ source: options.source,
79
+ });
80
+ }
81
+ } catch (error) {
82
+ logger.warn("Failed to load skill", { path: skillFile, error: String(error) });
83
+ }
84
+ }
85
+
86
+ async function scanDir(dir: string, ig: IgnoreMatcher): Promise<void> {
87
+ try {
88
+ // Add ignore rules from this directory
89
+ await addIgnoreRules(ig, dir, rootDir, readFileContent);
90
+
91
+ // First check if this directory itself is a skill
92
+ const selfSkillFile = path.join(dir, "SKILL.md");
93
+ try {
94
+ const s = await fs.stat(selfSkillFile);
95
+ if (s.isFile()) {
96
+ await addSkill(selfSkillFile, dir, path.basename(dir));
97
+ // This directory is a skill, don't recurse
98
+ return;
99
+ }
100
+ } catch {
101
+ // No SKILL.md in this directory
102
+ }
103
+
104
+ // Recurse into subdirectories
105
+ const entries = await fs.readdir(dir, { withFileTypes: true });
106
+
107
+ for (const entry of entries) {
108
+ if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
109
+
110
+ const fullPath = path.join(dir, entry.name);
111
+ const isDir = entry.isDirectory();
112
+
113
+ // Check if this entry should be ignored
114
+ if (shouldIgnore(ig, rootDir, fullPath, isDir)) continue;
115
+
116
+ if (isDir) {
117
+ await scanDir(fullPath, ig);
118
+ }
119
+ }
120
+ } catch (err) {
121
+ warnings.push({ skillPath: dir, message: `Failed to read directory: ${err}` });
122
+ }
123
+ }
124
+
125
+ const ig = createIgnoreMatcher();
126
+ await scanDir(options.dir, ig);
127
+
128
+ return { skills, warnings };
129
+ }
130
+
131
+ /**
132
+ * Scan a directory for SKILL.md files recursively.
133
+ * Used internally by loadSkills for custom directories.
134
+ * Respects .gitignore, .ignore, and .fdignore files.
135
+ */
136
+ async function scanDirectoryForSkills(dir: string): Promise<LoadSkillsResult> {
137
+ const skills: Skill[] = [];
138
+ const warnings: SkillWarning[] = [];
139
+ const seenPaths = new Set<string>();
140
+ const rootDir = dir;
141
+
142
+ async function addSkill(skillFile: string, skillDir: string, dirName: string): Promise<void> {
143
+ if (seenPaths.has(skillFile)) return;
144
+ try {
145
+ const content = await fs.readFile(skillFile, "utf-8");
146
+ const { frontmatter } = parseFrontmatter(content, { source: skillFile });
147
+ const name = (frontmatter.name as string) || dirName;
148
+ const description = frontmatter.description as string;
149
+
150
+ if (description) {
151
+ seenPaths.add(skillFile);
152
+ skills.push({
153
+ name,
154
+ description,
155
+ filePath: skillFile,
156
+ baseDir: skillDir,
157
+ source: "custom",
158
+ });
159
+ }
160
+ } catch (error) {
161
+ logger.warn("Failed to load skill", { path: skillFile, error: String(error) });
162
+ }
163
+ }
164
+
165
+ async function scanDir(currentDir: string, ig: IgnoreMatcher): Promise<void> {
166
+ try {
167
+ // Add ignore rules from this directory
168
+ await addIgnoreRules(ig, currentDir, rootDir, readFileContent);
169
+
170
+ // First check if this directory itself is a skill
171
+ const selfSkillFile = path.join(currentDir, "SKILL.md");
172
+ try {
173
+ const s = await fs.stat(selfSkillFile);
174
+ if (s.isFile()) {
175
+ await addSkill(selfSkillFile, currentDir, path.basename(currentDir));
176
+ // This directory is a skill, don't recurse
177
+ return;
178
+ }
179
+ } catch {
180
+ // No SKILL.md in this directory
181
+ }
182
+
183
+ // Recurse into subdirectories
184
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
185
+
186
+ for (const entry of entries) {
187
+ if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
188
+
189
+ const fullPath = path.join(currentDir, entry.name);
190
+ const isDir = entry.isDirectory();
191
+
192
+ // Check if this entry should be ignored
193
+ if (shouldIgnore(ig, rootDir, fullPath, isDir)) continue;
194
+
195
+ if (isDir) {
196
+ await scanDir(fullPath, ig);
197
+ }
198
+ }
199
+ } catch (err) {
200
+ warnings.push({ skillPath: currentDir, message: `Failed to read directory: ${err}` });
201
+ }
202
+ }
203
+
204
+ const ig = createIgnoreMatcher();
205
+ await scanDir(dir, ig);
206
+
207
+ return { skills, warnings };
208
+ }
209
+
210
+ export interface LoadSkillsOptions extends SkillsSettings {
211
+ /** Working directory for project-local skills. Default: getProjectDir() */
212
+ cwd?: string;
213
+ }
214
+
215
+ /**
216
+ * Load skills from all configured locations.
217
+ * Returns skills and any validation warnings.
218
+ */
219
+ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadSkillsResult> {
220
+ const {
221
+ cwd = getProjectDir(),
222
+ enabled = true,
223
+ enableCodexUser = true,
224
+ enableClaudeUser = true,
225
+ enableClaudeProject = true,
226
+ enablePiUser = true,
227
+ enablePiProject = true,
228
+ customDirectories = [],
229
+ ignoredSkills = [],
230
+ includeSkills = [],
231
+ } = options;
232
+
233
+ // Early return if skills are disabled
234
+ if (!enabled) {
235
+ return { skills: [], warnings: [] };
236
+ }
237
+
238
+ const anyBuiltInSkillSourceEnabled =
239
+ enableCodexUser || enableClaudeUser || enableClaudeProject || enablePiUser || enablePiProject;
240
+ // Helper to check if a source is enabled
241
+ function isSourceEnabled(source: SourceMeta): boolean {
242
+ const { provider, level } = source;
243
+ if (provider === "codex" && level === "user") return enableCodexUser;
244
+ if (provider === "claude" && level === "user") return enableClaudeUser;
245
+ if (provider === "claude" && level === "project") return enableClaudeProject;
246
+ if (provider === "native" && level === "user") return enablePiUser;
247
+ if (provider === "native" && level === "project") return enablePiProject;
248
+ // For other providers (agents, claude-plugins, etc.), treat them as built-in skill sources.
249
+ return anyBuiltInSkillSourceEnabled;
250
+ }
251
+
252
+ // Use capability API to load all skills
253
+ const result = await loadCapability<CapabilitySkill>(skillCapability.id, { cwd });
254
+
255
+ const skillMap = new Map<string, Skill>();
256
+ const realPathSet = new Set<string>();
257
+ const collisionWarnings: SkillWarning[] = [];
258
+
259
+ // Check if skill name matches any of the include patterns
260
+ function matchesIncludePatterns(name: string): boolean {
261
+ if (includeSkills.length === 0) return true;
262
+ return includeSkills.some(pattern => new Bun.Glob(pattern).match(name));
263
+ }
264
+
265
+ // Check if skill name matches any of the ignore patterns
266
+ function matchesIgnorePatterns(name: string): boolean {
267
+ if (ignoredSkills.length === 0) return false;
268
+ return ignoredSkills.some(pattern => new Bun.Glob(pattern).match(name));
269
+ }
270
+
271
+ // Filter skills by source and patterns first
272
+ const filteredSkills = result.items.filter(capSkill => {
273
+ if (!isSourceEnabled(capSkill._source)) return false;
274
+ if (matchesIgnorePatterns(capSkill.name)) return false;
275
+ if (!matchesIncludePatterns(capSkill.name)) return false;
276
+ return true;
277
+ });
278
+
279
+ // Batch resolve all real paths in parallel
280
+ const realPaths = await Promise.all(
281
+ filteredSkills.map(async capSkill => {
282
+ try {
283
+ return await fs.realpath(capSkill.path);
284
+ } catch {
285
+ return capSkill.path;
286
+ }
287
+ }),
288
+ );
289
+
290
+ // Process skills with resolved paths
291
+ for (let i = 0; i < filteredSkills.length; i++) {
292
+ const capSkill = filteredSkills[i];
293
+ const resolvedPath = realPaths[i];
294
+
295
+ // Skip silently if we've already loaded this exact file (via symlink)
296
+ if (realPathSet.has(resolvedPath)) {
297
+ continue;
298
+ }
299
+
300
+ const existing = skillMap.get(capSkill.name);
301
+ if (existing) {
302
+ collisionWarnings.push({
303
+ skillPath: capSkill.path,
304
+ message: `name collision: "${capSkill.name}" already loaded from ${existing.filePath}, skipping this one`,
305
+ });
306
+ } else {
307
+ // Transform capability skill to legacy format
308
+ const skill: Skill = {
309
+ name: capSkill.name,
310
+ description: capSkill.frontmatter?.description || "",
311
+ filePath: capSkill.path,
312
+ baseDir: capSkill.path.replace(/\/SKILL\.md$/, ""),
313
+ source: `${capSkill._source.provider}:${capSkill.level}`,
314
+ _source: capSkill._source,
315
+ };
316
+ skillMap.set(capSkill.name, skill);
317
+ realPathSet.add(resolvedPath);
318
+ }
319
+ }
320
+
321
+ // Process custom directories - scan directly without using full provider system
322
+ const allCustomSkills: Array<{ skill: Skill; path: string }> = [];
323
+ const customScanResults = await Promise.all(
324
+ customDirectories.map(dir => {
325
+ let resolved = dir;
326
+ if (resolved.startsWith("~/")) {
327
+ resolved = path.join(os.homedir(), resolved.slice(2));
328
+ } else if (resolved === "~") {
329
+ resolved = os.homedir();
330
+ }
331
+ return scanDirectoryForSkills(resolved);
332
+ }),
333
+ );
334
+ for (const customSkills of customScanResults) {
335
+ for (const s of customSkills.skills) {
336
+ if (matchesIgnorePatterns(s.name)) continue;
337
+ if (!matchesIncludePatterns(s.name)) continue;
338
+ allCustomSkills.push({
339
+ skill: {
340
+ name: s.name,
341
+ description: s.description,
342
+ filePath: s.filePath,
343
+ baseDir: s.filePath.replace(/\/SKILL\.md$/, ""),
344
+ source: "custom:user",
345
+ _source: { provider: "custom", providerName: "Custom", path: s.filePath, level: "user" },
346
+ },
347
+ path: s.filePath,
348
+ });
349
+ }
350
+ collisionWarnings.push(...customSkills.warnings);
351
+ }
352
+
353
+ // Batch resolve custom skill paths
354
+ const customRealPaths = await Promise.all(
355
+ allCustomSkills.map(async ({ path }) => {
356
+ try {
357
+ return await fs.realpath(path);
358
+ } catch {
359
+ return path;
360
+ }
361
+ }),
362
+ );
363
+
364
+ for (let i = 0; i < allCustomSkills.length; i++) {
365
+ const { skill } = allCustomSkills[i];
366
+ const resolvedPath = customRealPaths[i];
367
+ if (realPathSet.has(resolvedPath)) continue;
368
+
369
+ const existing = skillMap.get(skill.name);
370
+ if (existing) {
371
+ collisionWarnings.push({
372
+ skillPath: skill.filePath,
373
+ message: `name collision: "${skill.name}" already loaded from ${existing.filePath}, skipping this one`,
374
+ });
375
+ } else {
376
+ skillMap.set(skill.name, skill);
377
+ realPathSet.add(resolvedPath);
378
+ }
379
+ }
380
+
381
+ return {
382
+ skills: Array.from(skillMap.values()),
383
+ warnings: [...result.warnings.map(w => ({ skillPath: "", message: w })), ...collisionWarnings],
384
+ };
385
+ }