nikcli 0.0.6

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 (602) hide show
  1. package/.turbo/turbo-typecheck.log +1 -0
  2. package/AGENTS.md +27 -0
  3. package/Dockerfile +18 -0
  4. package/README.md +15 -0
  5. package/bin/nikcli +84 -0
  6. package/config.json +13 -0
  7. package/docs/tailscale-mobile/01-tailscale-setup.md +94 -0
  8. package/docs/tailscale-mobile/02-host-setup.md +115 -0
  9. package/docs/tailscale-mobile/03-phone-and-serve.md +134 -0
  10. package/docs/tailscale-mobile/README.md +59 -0
  11. package/examples/README.md +54 -0
  12. package/package.json +147 -0
  13. package/parsers-config.ts +253 -0
  14. package/script/build.ts +179 -0
  15. package/script/postinstall.mjs +125 -0
  16. package/script/publish-registries.ts +187 -0
  17. package/script/publish.ts +100 -0
  18. package/script/schema.ts +47 -0
  19. package/script/seed-e2e.ts +50 -0
  20. package/sequential-prancing-forest.md +373 -0
  21. package/src/acp/README.md +164 -0
  22. package/src/acp/agent.ts +1303 -0
  23. package/src/acp/session.ts +105 -0
  24. package/src/acp/types.ts +22 -0
  25. package/src/agent/agent.ts +528 -0
  26. package/src/agent/generate.txt +32 -0
  27. package/src/agent/prompt/compaction.txt +14 -0
  28. package/src/agent/prompt/explore.txt +18 -0
  29. package/src/agent/prompt/summary.txt +11 -0
  30. package/src/agent/prompt/title.txt +44 -0
  31. package/src/auth/index.ts +73 -0
  32. package/src/bun/index.ts +119 -0
  33. package/src/bun/registry.ts +54 -0
  34. package/src/bus/bus-event.ts +43 -0
  35. package/src/bus/global.ts +10 -0
  36. package/src/bus/index.ts +105 -0
  37. package/src/chatbot/handlers.ts +150 -0
  38. package/src/chatbot/index.ts +132 -0
  39. package/src/cli/bootstrap.ts +17 -0
  40. package/src/cli/cmd/acp.ts +69 -0
  41. package/src/cli/cmd/ads.ts +377 -0
  42. package/src/cli/cmd/agent.ts +259 -0
  43. package/src/cli/cmd/auth.ts +400 -0
  44. package/src/cli/cmd/chatbot.ts +420 -0
  45. package/src/cli/cmd/cmd.ts +7 -0
  46. package/src/cli/cmd/companion.ts +81 -0
  47. package/src/cli/cmd/connectors.ts +593 -0
  48. package/src/cli/cmd/debug/agent.ts +166 -0
  49. package/src/cli/cmd/debug/config.ts +16 -0
  50. package/src/cli/cmd/debug/file.ts +97 -0
  51. package/src/cli/cmd/debug/index.ts +48 -0
  52. package/src/cli/cmd/debug/lsp.ts +52 -0
  53. package/src/cli/cmd/debug/ripgrep.ts +87 -0
  54. package/src/cli/cmd/debug/scrap.ts +16 -0
  55. package/src/cli/cmd/debug/skill.ts +16 -0
  56. package/src/cli/cmd/debug/snapshot.ts +52 -0
  57. package/src/cli/cmd/export.ts +88 -0
  58. package/src/cli/cmd/generate.ts +38 -0
  59. package/src/cli/cmd/github.ts +412 -0
  60. package/src/cli/cmd/image-model.ts +128 -0
  61. package/src/cli/cmd/import.ts +201 -0
  62. package/src/cli/cmd/lovable.ts +128 -0
  63. package/src/cli/cmd/mcp.ts +738 -0
  64. package/src/cli/cmd/mobile.ts +223 -0
  65. package/src/cli/cmd/models.ts +77 -0
  66. package/src/cli/cmd/plug.ts +231 -0
  67. package/src/cli/cmd/pr.ts +104 -0
  68. package/src/cli/cmd/rag-model.ts +167 -0
  69. package/src/cli/cmd/remote.ts +416 -0
  70. package/src/cli/cmd/run.ts +589 -0
  71. package/src/cli/cmd/serve.ts +51 -0
  72. package/src/cli/cmd/session.ts +133 -0
  73. package/src/cli/cmd/speak-model.ts +204 -0
  74. package/src/cli/cmd/stats.ts +402 -0
  75. package/src/cli/cmd/tui/app.tsx +841 -0
  76. package/src/cli/cmd/tui/attach.ts +31 -0
  77. package/src/cli/cmd/tui/component/border.tsx +75 -0
  78. package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
  79. package/src/cli/cmd/tui/component/dialog-command.tsx +172 -0
  80. package/src/cli/cmd/tui/component/dialog-config.tsx +291 -0
  81. package/src/cli/cmd/tui/component/dialog-connectors.tsx +440 -0
  82. package/src/cli/cmd/tui/component/dialog-image-model.tsx +97 -0
  83. package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
  84. package/src/cli/cmd/tui/component/dialog-model.tsx +234 -0
  85. package/src/cli/cmd/tui/component/dialog-provider.tsx +260 -0
  86. package/src/cli/cmd/tui/component/dialog-rag-model.tsx +217 -0
  87. package/src/cli/cmd/tui/component/dialog-remote.tsx +489 -0
  88. package/src/cli/cmd/tui/component/dialog-session-list.tsx +170 -0
  89. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
  90. package/src/cli/cmd/tui/component/dialog-settings/index.tsx +59 -0
  91. package/src/cli/cmd/tui/component/dialog-settings/prompt.tsx +40 -0
  92. package/src/cli/cmd/tui/component/dialog-settings/sidebar.tsx +39 -0
  93. package/src/cli/cmd/tui/component/dialog-settings/spinner.tsx +62 -0
  94. package/src/cli/cmd/tui/component/dialog-settings/ui.tsx +58 -0
  95. package/src/cli/cmd/tui/component/dialog-skills.tsx +117 -0
  96. package/src/cli/cmd/tui/component/dialog-speak-model.tsx +304 -0
  97. package/src/cli/cmd/tui/component/dialog-stash.tsx +87 -0
  98. package/src/cli/cmd/tui/component/dialog-status.tsx +165 -0
  99. package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
  100. package/src/cli/cmd/tui/component/dialog-theme-create.tsx +717 -0
  101. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +52 -0
  102. package/src/cli/cmd/tui/component/dialog-workspace-list.tsx +350 -0
  103. package/src/cli/cmd/tui/component/error-component.tsx +91 -0
  104. package/src/cli/cmd/tui/component/logo.tsx +103 -0
  105. package/src/cli/cmd/tui/component/plugin-route-missing.tsx +14 -0
  106. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +669 -0
  107. package/src/cli/cmd/tui/component/prompt/frecency.tsx +89 -0
  108. package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
  109. package/src/cli/cmd/tui/component/prompt/index.tsx +2165 -0
  110. package/src/cli/cmd/tui/component/prompt/stash.tsx +63 -0
  111. package/src/cli/cmd/tui/component/spinner.tsx +24 -0
  112. package/src/cli/cmd/tui/component/startup-loading.tsx +63 -0
  113. package/src/cli/cmd/tui/component/table/markdown-table.tsx +267 -0
  114. package/src/cli/cmd/tui/component/table-db/db/connections.ts +75 -0
  115. package/src/cli/cmd/tui/component/table-db/db/db-connection.ts +223 -0
  116. package/src/cli/cmd/tui/component/table-db/db/db-preview.ts +202 -0
  117. package/src/cli/cmd/tui/component/table-db/db/factory.ts +77 -0
  118. package/src/cli/cmd/tui/component/table-db/db/index.ts +9 -0
  119. package/src/cli/cmd/tui/component/table-db/db/mysql-connection.ts +330 -0
  120. package/src/cli/cmd/tui/component/table-db/db/postgres-connection.ts +338 -0
  121. package/src/cli/cmd/tui/component/table-db/db/sqlite-connection.ts +302 -0
  122. package/src/cli/cmd/tui/component/table-db/db/types.ts +108 -0
  123. package/src/cli/cmd/tui/component/table-db/table/dbedit-hooks.ts +74 -0
  124. package/src/cli/cmd/tui/component/table-db/table/index.ts +15 -0
  125. package/src/cli/cmd/tui/component/table-db/table/table-events.ts +54 -0
  126. package/src/cli/cmd/tui/component/table-db/table/table-formatters.ts +191 -0
  127. package/src/cli/cmd/tui/component/table-db/table/table-hooks.ts +105 -0
  128. package/src/cli/cmd/tui/component/table-db/table/table-keyboard-handler.ts +255 -0
  129. package/src/cli/cmd/tui/component/table-db/table/table-layout-engine.ts +208 -0
  130. package/src/cli/cmd/tui/component/table-db/table/table-renderable.ts +486 -0
  131. package/src/cli/cmd/tui/component/table-db/table/table-selection-manager.ts +136 -0
  132. package/src/cli/cmd/tui/component/table-db/table/table-state.ts +198 -0
  133. package/src/cli/cmd/tui/component/table-db/table/types.ts +69 -0
  134. package/src/cli/cmd/tui/component/table-db/ui/db-visualizer.tsx +71 -0
  135. package/src/cli/cmd/tui/component/table-db/ui/index.ts +2 -0
  136. package/src/cli/cmd/tui/component/table-db/ui/table-renderer.ts +607 -0
  137. package/src/cli/cmd/tui/component/textarea-keybindings.ts +73 -0
  138. package/src/cli/cmd/tui/component/tips.tsx +195 -0
  139. package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
  140. package/src/cli/cmd/tui/context/args.tsx +14 -0
  141. package/src/cli/cmd/tui/context/directory.ts +13 -0
  142. package/src/cli/cmd/tui/context/exit.tsx +24 -0
  143. package/src/cli/cmd/tui/context/helper.tsx +25 -0
  144. package/src/cli/cmd/tui/context/keybind.tsx +102 -0
  145. package/src/cli/cmd/tui/context/kv.tsx +52 -0
  146. package/src/cli/cmd/tui/context/local.tsx +458 -0
  147. package/src/cli/cmd/tui/context/plugin-keybinds.ts +41 -0
  148. package/src/cli/cmd/tui/context/prompt.tsx +18 -0
  149. package/src/cli/cmd/tui/context/route.tsx +54 -0
  150. package/src/cli/cmd/tui/context/sdk.tsx +128 -0
  151. package/src/cli/cmd/tui/context/server.tsx +8 -0
  152. package/src/cli/cmd/tui/context/sync.tsx +510 -0
  153. package/src/cli/cmd/tui/context/theme/abyss.json +233 -0
  154. package/src/cli/cmd/tui/context/theme/apple.json +235 -0
  155. package/src/cli/cmd/tui/context/theme/arctic.json +232 -0
  156. package/src/cli/cmd/tui/context/theme/aura.json +69 -0
  157. package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
  158. package/src/cli/cmd/tui/context/theme/ayuai.json +229 -0
  159. package/src/cli/cmd/tui/context/theme/blood.json +229 -0
  160. package/src/cli/cmd/tui/context/theme/carbonfox.json +248 -0
  161. package/src/cli/cmd/tui/context/theme/catmoe.json +235 -0
  162. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
  163. package/src/cli/cmd/tui/context/theme/catppuccin-latte.json +233 -0
  164. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
  165. package/src/cli/cmd/tui/context/theme/catppuccin.json +259 -0
  166. package/src/cli/cmd/tui/context/theme/charcoal.json +230 -0
  167. package/src/cli/cmd/tui/context/theme/chromatic.json +235 -0
  168. package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
  169. package/src/cli/cmd/tui/context/theme/cosmic.json +234 -0
  170. package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
  171. package/src/cli/cmd/tui/context/theme/cyber.json +235 -0
  172. package/src/cli/cmd/tui/context/theme/dawnfox.json +229 -0
  173. package/src/cli/cmd/tui/context/theme/dimension.json +235 -0
  174. package/src/cli/cmd/tui/context/theme/dracula-official.json +222 -0
  175. package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
  176. package/src/cli/cmd/tui/context/theme/dream.json +235 -0
  177. package/src/cli/cmd/tui/context/theme/duo.json +235 -0
  178. package/src/cli/cmd/tui/context/theme/dusk.json +235 -0
  179. package/src/cli/cmd/tui/context/theme/ebony.json +232 -0
  180. package/src/cli/cmd/tui/context/theme/equilibrium.json +232 -0
  181. package/src/cli/cmd/tui/context/theme/ethereal.json +235 -0
  182. package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
  183. package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
  184. package/src/cli/cmd/tui/context/theme/fusion.json +235 -0
  185. package/src/cli/cmd/tui/context/theme/ghost.json +235 -0
  186. package/src/cli/cmd/tui/context/theme/github-dark.json +229 -0
  187. package/src/cli/cmd/tui/context/theme/github-dimmed.json +231 -0
  188. package/src/cli/cmd/tui/context/theme/github-light.json +229 -0
  189. package/src/cli/cmd/tui/context/theme/github.json +233 -0
  190. package/src/cli/cmd/tui/context/theme/glass.json +235 -0
  191. package/src/cli/cmd/tui/context/theme/gold.json +235 -0
  192. package/src/cli/cmd/tui/context/theme/gone.json +234 -0
  193. package/src/cli/cmd/tui/context/theme/greyscale.json +229 -0
  194. package/src/cli/cmd/tui/context/theme/gruvbox.json +242 -0
  195. package/src/cli/cmd/tui/context/theme/hacker.json +229 -0
  196. package/src/cli/cmd/tui/context/theme/holo.json +235 -0
  197. package/src/cli/cmd/tui/context/theme/ink.json +235 -0
  198. package/src/cli/cmd/tui/context/theme/jet.json +233 -0
  199. package/src/cli/cmd/tui/context/theme/kanagawa.json +227 -0
  200. package/src/cli/cmd/tui/context/theme/lavender.json +236 -0
  201. package/src/cli/cmd/tui/context/theme/lightph.json +235 -0
  202. package/src/cli/cmd/tui/context/theme/lucent-orng.json +237 -0
  203. package/src/cli/cmd/tui/context/theme/material-ocean.json +230 -0
  204. package/src/cli/cmd/tui/context/theme/material.json +235 -0
  205. package/src/cli/cmd/tui/context/theme/matrix.json +227 -0
  206. package/src/cli/cmd/tui/context/theme/mercury.json +245 -0
  207. package/src/cli/cmd/tui/context/theme/midnight.json +235 -0
  208. package/src/cli/cmd/tui/context/theme/modern.json +235 -0
  209. package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
  210. package/src/cli/cmd/tui/context/theme/muted.json +229 -0
  211. package/src/cli/cmd/tui/context/theme/neon.json +229 -0
  212. package/src/cli/cmd/tui/context/theme/neonfusion.json +235 -0
  213. package/src/cli/cmd/tui/context/theme/neutral.json +235 -0
  214. package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
  215. package/src/cli/cmd/tui/context/theme/nikcli.json +245 -0
  216. package/src/cli/cmd/tui/context/theme/nord.json +223 -0
  217. package/src/cli/cmd/tui/context/theme/nordic.json +235 -0
  218. package/src/cli/cmd/tui/context/theme/nova.json +235 -0
  219. package/src/cli/cmd/tui/context/theme/obsidian.json +234 -0
  220. package/src/cli/cmd/tui/context/theme/one-dark.json +231 -0
  221. package/src/cli/cmd/tui/context/theme/one-pro.json +229 -0
  222. package/src/cli/cmd/tui/context/theme/onyx.json +233 -0
  223. package/src/cli/cmd/tui/context/theme/orng.json +249 -0
  224. package/src/cli/cmd/tui/context/theme/osaka-jade.json +240 -0
  225. package/src/cli/cmd/tui/context/theme/oxocarbon.json +229 -0
  226. package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
  227. package/src/cli/cmd/tui/context/theme/poimandres.json +230 -0
  228. package/src/cli/cmd/tui/context/theme/prism.json +235 -0
  229. package/src/cli/cmd/tui/context/theme/radiant.json +235 -0
  230. package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
  231. package/src/cli/cmd/tui/context/theme/shadow.json +235 -0
  232. package/src/cli/cmd/tui/context/theme/silicon.json +235 -0
  233. package/src/cli/cmd/tui/context/theme/slate.json +233 -0
  234. package/src/cli/cmd/tui/context/theme/soft.json +235 -0
  235. package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
  236. package/src/cli/cmd/tui/context/theme/spectrum.json +235 -0
  237. package/src/cli/cmd/tui/context/theme/starlight.json +233 -0
  238. package/src/cli/cmd/tui/context/theme/sunrise.json +235 -0
  239. package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
  240. package/src/cli/cmd/tui/context/theme/tech.json +235 -0
  241. package/src/cli/cmd/tui/context/theme/tokyonight-storm.json +245 -0
  242. package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
  243. package/src/cli/cmd/tui/context/theme/vapor.json +235 -0
  244. package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
  245. package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
  246. package/src/cli/cmd/tui/context/theme/vivid.json +232 -0
  247. package/src/cli/cmd/tui/context/theme/void.json +235 -0
  248. package/src/cli/cmd/tui/context/theme/vscode.json +235 -0
  249. package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
  250. package/src/cli/cmd/tui/context/theme/zinc.json +236 -0
  251. package/src/cli/cmd/tui/context/theme.tsx +1303 -0
  252. package/src/cli/cmd/tui/event.ts +48 -0
  253. package/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx +152 -0
  254. package/src/cli/cmd/tui/feature-plugins/home/tips.tsx +50 -0
  255. package/src/cli/cmd/tui/feature-plugins/sidebar/context.tsx +63 -0
  256. package/src/cli/cmd/tui/feature-plugins/sidebar/files.tsx +62 -0
  257. package/src/cli/cmd/tui/feature-plugins/sidebar/footer.tsx +93 -0
  258. package/src/cli/cmd/tui/feature-plugins/sidebar/lsp.tsx +66 -0
  259. package/src/cli/cmd/tui/feature-plugins/sidebar/mcp.tsx +96 -0
  260. package/src/cli/cmd/tui/feature-plugins/sidebar/todo.tsx +48 -0
  261. package/src/cli/cmd/tui/feature-plugins/system/plugins.tsx +288 -0
  262. package/src/cli/cmd/tui/plugin/api.tsx +407 -0
  263. package/src/cli/cmd/tui/plugin/index.ts +3 -0
  264. package/src/cli/cmd/tui/plugin/internal.ts +25 -0
  265. package/src/cli/cmd/tui/plugin/runtime.ts +1048 -0
  266. package/src/cli/cmd/tui/plugin/slots.tsx +61 -0
  267. package/src/cli/cmd/tui/routes/home.tsx +153 -0
  268. package/src/cli/cmd/tui/routes/session/dbedit.tsx +474 -0
  269. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +65 -0
  270. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +110 -0
  271. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +105 -0
  272. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
  273. package/src/cli/cmd/tui/routes/session/footer.tsx +75 -0
  274. package/src/cli/cmd/tui/routes/session/header.tsx +177 -0
  275. package/src/cli/cmd/tui/routes/session/index.tsx +2280 -0
  276. package/src/cli/cmd/tui/routes/session/permission.tsx +540 -0
  277. package/src/cli/cmd/tui/routes/session/question.tsx +435 -0
  278. package/src/cli/cmd/tui/routes/session/sidebar.tsx +313 -0
  279. package/src/cli/cmd/tui/thread.ts +174 -0
  280. package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
  281. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
  282. package/src/cli/cmd/tui/ui/dialog-export-options.tsx +204 -0
  283. package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
  284. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +102 -0
  285. package/src/cli/cmd/tui/ui/dialog-select.tsx +389 -0
  286. package/src/cli/cmd/tui/ui/dialog.tsx +180 -0
  287. package/src/cli/cmd/tui/ui/link.tsx +34 -0
  288. package/src/cli/cmd/tui/ui/spinner.ts +368 -0
  289. package/src/cli/cmd/tui/ui/toast.tsx +138 -0
  290. package/src/cli/cmd/tui/util/clipboard.ts +154 -0
  291. package/src/cli/cmd/tui/util/editor.ts +32 -0
  292. package/src/cli/cmd/tui/util/signal.ts +7 -0
  293. package/src/cli/cmd/tui/util/terminal.ts +114 -0
  294. package/src/cli/cmd/tui/util/transcript.ts +98 -0
  295. package/src/cli/cmd/tui/win32.ts +110 -0
  296. package/src/cli/cmd/tui/worker.ts +156 -0
  297. package/src/cli/cmd/uninstall.ts +357 -0
  298. package/src/cli/cmd/upgrade.ts +72 -0
  299. package/src/cli/cmd/web.ts +87 -0
  300. package/src/cli/cmd/workspace-serve.ts +16 -0
  301. package/src/cli/error.ts +57 -0
  302. package/src/cli/network.ts +55 -0
  303. package/src/cli/remote/index.ts +36 -0
  304. package/src/cli/remote/notifications.ts +104 -0
  305. package/src/cli/remote/qr-renderer.ts +86 -0
  306. package/src/cli/remote/remote-service.ts +757 -0
  307. package/src/cli/remote/session-manager.ts +284 -0
  308. package/src/cli/remote/subagent-hooks.ts +151 -0
  309. package/src/cli/remote/types.ts +121 -0
  310. package/src/cli/ui.ts +96 -0
  311. package/src/cli/upgrade.ts +25 -0
  312. package/src/command/index.ts +174 -0
  313. package/src/command/template/initialize.txt +10 -0
  314. package/src/command/template/review.txt +99 -0
  315. package/src/config/config.ts +1760 -0
  316. package/src/config/markdown.ts +88 -0
  317. package/src/config/migrate-tui-config.ts +155 -0
  318. package/src/config/paths.ts +174 -0
  319. package/src/config/tui-schema.ts +36 -0
  320. package/src/config/tui.ts +209 -0
  321. package/src/connectors/api/base.ts +75 -0
  322. package/src/connectors/api/figma.ts +103 -0
  323. package/src/connectors/api/github.ts +247 -0
  324. package/src/connectors/api/lovable.ts +126 -0
  325. package/src/connectors/api/slack.ts +137 -0
  326. package/src/connectors/auth.ts +68 -0
  327. package/src/connectors/cache.ts +119 -0
  328. package/src/connectors/credentials.ts +81 -0
  329. package/src/connectors/index.ts +202 -0
  330. package/src/connectors/registry.ts +358 -0
  331. package/src/docs/context.ts +120 -0
  332. package/src/docs/library.ts +189 -0
  333. package/src/env/index.ts +26 -0
  334. package/src/file/ignore.ts +83 -0
  335. package/src/file/index.ts +411 -0
  336. package/src/file/ripgrep.ts +402 -0
  337. package/src/file/time.ts +65 -0
  338. package/src/file/watcher.ts +127 -0
  339. package/src/flag/flag.ts +128 -0
  340. package/src/format/formatter.ts +356 -0
  341. package/src/format/index.ts +137 -0
  342. package/src/global/index.ts +57 -0
  343. package/src/id/id.ts +83 -0
  344. package/src/ide/index.ts +76 -0
  345. package/src/index.ts +184 -0
  346. package/src/installation/index.ts +246 -0
  347. package/src/lsp/client.ts +250 -0
  348. package/src/lsp/index.ts +483 -0
  349. package/src/lsp/language.ts +119 -0
  350. package/src/lsp/server.ts +2046 -0
  351. package/src/mcp/auth.ts +121 -0
  352. package/src/mcp/index.ts +860 -0
  353. package/src/mcp/oauth-callback.ts +198 -0
  354. package/src/mcp/oauth-provider.ts +148 -0
  355. package/src/mobile/auth.ts +97 -0
  356. package/src/mobile/github-repo.ts +185 -0
  357. package/src/patch/index.ts +631 -0
  358. package/src/permission/arity.ts +150 -0
  359. package/src/permission/dbedit.ts +236 -0
  360. package/src/permission/index.ts +210 -0
  361. package/src/permission/next.ts +287 -0
  362. package/src/plugin/codex.ts +493 -0
  363. package/src/plugin/copilot.ts +261 -0
  364. package/src/plugin/index.ts +714 -0
  365. package/src/plugin/install.ts +379 -0
  366. package/src/plugin/meta.ts +165 -0
  367. package/src/plugin/shared.ts +188 -0
  368. package/src/project/bootstrap.ts +35 -0
  369. package/src/project/instance.ts +84 -0
  370. package/src/project/project.ts +373 -0
  371. package/src/project/state.ts +66 -0
  372. package/src/project/vcs.ts +76 -0
  373. package/src/prompt/stash-store.ts +93 -0
  374. package/src/provider/auth.ts +147 -0
  375. package/src/provider/models-macro.ts +22 -0
  376. package/src/provider/models.ts +216 -0
  377. package/src/provider/provider.ts +1483 -0
  378. package/src/provider/sdk/openai-compatible/src/README.md +5 -0
  379. package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
  380. package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +100 -0
  381. package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
  382. package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
  383. package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
  384. package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
  385. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
  386. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1732 -0
  387. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
  388. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
  389. package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
  390. package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
  391. package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
  392. package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
  393. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
  394. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
  395. package/src/provider/transform.ts +828 -0
  396. package/src/pty/index.ts +241 -0
  397. package/src/question/index.ts +171 -0
  398. package/src/rag/chunk.ts +43 -0
  399. package/src/rag/embed.ts +179 -0
  400. package/src/rag/index.ts +376 -0
  401. package/src/rag/storage.ts +76 -0
  402. package/src/scheduler/index.ts +61 -0
  403. package/src/server/error.ts +36 -0
  404. package/src/server/event.ts +7 -0
  405. package/src/server/mdns.ts +59 -0
  406. package/src/server/routes/chatbot.ts +205 -0
  407. package/src/server/routes/companion.ts +729 -0
  408. package/src/server/routes/config.ts +92 -0
  409. package/src/server/routes/connectors.ts +121 -0
  410. package/src/server/routes/dbedit.ts +76 -0
  411. package/src/server/routes/experimental.ts +210 -0
  412. package/src/server/routes/file.ts +197 -0
  413. package/src/server/routes/global.ts +135 -0
  414. package/src/server/routes/mcp.ts +225 -0
  415. package/src/server/routes/mobile.ts +2044 -0
  416. package/src/server/routes/permission.ts +68 -0
  417. package/src/server/routes/project.ts +82 -0
  418. package/src/server/routes/provider.ts +235 -0
  419. package/src/server/routes/pty.ts +169 -0
  420. package/src/server/routes/question.ts +98 -0
  421. package/src/server/routes/session.ts +968 -0
  422. package/src/server/routes/tui.ts +379 -0
  423. package/src/server/routes/workspace.ts +104 -0
  424. package/src/server/server.ts +761 -0
  425. package/src/server/ssh.ts +207 -0
  426. package/src/session/auth.ts +402 -0
  427. package/src/session/compaction.ts +253 -0
  428. package/src/session/generate.ts +38 -0
  429. package/src/session/index.ts +598 -0
  430. package/src/session/llm.ts +273 -0
  431. package/src/session/message-v2.ts +836 -0
  432. package/src/session/message.ts +189 -0
  433. package/src/session/processor.ts +408 -0
  434. package/src/session/prompt/anthropic-20250930.txt +165 -0
  435. package/src/session/prompt/anthropic.txt +105 -0
  436. package/src/session/prompt/anthropic_spoof.txt +1 -0
  437. package/src/session/prompt/beast.txt +147 -0
  438. package/src/session/prompt/build-switch.txt +5 -0
  439. package/src/session/prompt/codex_header.txt +79 -0
  440. package/src/session/prompt/copilot-gpt-5.txt +143 -0
  441. package/src/session/prompt/gemini.txt +155 -0
  442. package/src/session/prompt/max-steps.txt +16 -0
  443. package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
  444. package/src/session/prompt/plan.txt +25 -0
  445. package/src/session/prompt/qwen.txt +108 -0
  446. package/src/session/prompt.ts +1942 -0
  447. package/src/session/retry.ts +90 -0
  448. package/src/session/revert.ts +120 -0
  449. package/src/session/stats.ts +404 -0
  450. package/src/session/status.ts +84 -0
  451. package/src/session/summary.ts +184 -0
  452. package/src/session/system.ts +195 -0
  453. package/src/session/toast.tsx +105 -0
  454. package/src/session/todo.ts +258 -0
  455. package/src/session/uninstall.ts +357 -0
  456. package/src/share/share-next.ts +421 -0
  457. package/src/share/share.ts +92 -0
  458. package/src/shell/shell.ts +65 -0
  459. package/src/skill/index.ts +1 -0
  460. package/src/skill/skill.ts +232 -0
  461. package/src/snapshot/index.ts +297 -0
  462. package/src/storage/storage.ts +227 -0
  463. package/src/tool/apply_patch.ts +288 -0
  464. package/src/tool/apply_patch.txt +33 -0
  465. package/src/tool/bash.ts +252 -0
  466. package/src/tool/bash.txt +115 -0
  467. package/src/tool/batch.ts +175 -0
  468. package/src/tool/batch.txt +24 -0
  469. package/src/tool/codesearch.ts +132 -0
  470. package/src/tool/codesearch.txt +12 -0
  471. package/src/tool/context_collect.ts +152 -0
  472. package/src/tool/context_collect.txt +9 -0
  473. package/src/tool/context_diagnostics.ts +81 -0
  474. package/src/tool/context_diagnostics.txt +5 -0
  475. package/src/tool/context_related.ts +117 -0
  476. package/src/tool/context_related.txt +5 -0
  477. package/src/tool/context_search.ts +108 -0
  478. package/src/tool/context_search.txt +8 -0
  479. package/src/tool/db-diff.ts +434 -0
  480. package/src/tool/db-table.txt +15 -0
  481. package/src/tool/docs_add.ts +50 -0
  482. package/src/tool/docs_add.txt +5 -0
  483. package/src/tool/docs_context.ts +56 -0
  484. package/src/tool/docs_context.txt +4 -0
  485. package/src/tool/docs_gap_report.ts +79 -0
  486. package/src/tool/docs_gap_report.txt +7 -0
  487. package/src/tool/docs_load.ts +41 -0
  488. package/src/tool/docs_load.txt +4 -0
  489. package/src/tool/docs_request.ts +129 -0
  490. package/src/tool/docs_request.txt +7 -0
  491. package/src/tool/docs_search.ts +51 -0
  492. package/src/tool/docs_search.txt +6 -0
  493. package/src/tool/docs_unload.ts +38 -0
  494. package/src/tool/docs_unload.txt +5 -0
  495. package/src/tool/edit.ts +614 -0
  496. package/src/tool/edit.txt +10 -0
  497. package/src/tool/external-directory.ts +32 -0
  498. package/src/tool/generate_image.ts +174 -0
  499. package/src/tool/generate_image.txt +12 -0
  500. package/src/tool/glob.ts +79 -0
  501. package/src/tool/glob.txt +6 -0
  502. package/src/tool/grep.ts +153 -0
  503. package/src/tool/grep.txt +8 -0
  504. package/src/tool/invalid.ts +17 -0
  505. package/src/tool/ls.ts +116 -0
  506. package/src/tool/ls.txt +1 -0
  507. package/src/tool/lsp.ts +96 -0
  508. package/src/tool/lsp.txt +19 -0
  509. package/src/tool/memory_search.ts +141 -0
  510. package/src/tool/memory_search.txt +8 -0
  511. package/src/tool/multiedit.ts +46 -0
  512. package/src/tool/multiedit.txt +41 -0
  513. package/src/tool/plan-enter.txt +14 -0
  514. package/src/tool/plan-exit.txt +13 -0
  515. package/src/tool/plan.ts +130 -0
  516. package/src/tool/question.ts +33 -0
  517. package/src/tool/question.txt +10 -0
  518. package/src/tool/rag_index.ts +77 -0
  519. package/src/tool/rag_index.txt +10 -0
  520. package/src/tool/rag_reset.ts +26 -0
  521. package/src/tool/rag_reset.txt +4 -0
  522. package/src/tool/rag_search.ts +62 -0
  523. package/src/tool/rag_search.txt +6 -0
  524. package/src/tool/rag_status.ts +45 -0
  525. package/src/tool/rag_status.txt +4 -0
  526. package/src/tool/read.ts +203 -0
  527. package/src/tool/read.txt +12 -0
  528. package/src/tool/registry.ts +214 -0
  529. package/src/tool/skill.ts +169 -0
  530. package/src/tool/skill.txt +3 -0
  531. package/src/tool/smart_docs.ts +74 -0
  532. package/src/tool/smart_docs.txt +7 -0
  533. package/src/tool/speak/elevenlabs.ts +201 -0
  534. package/src/tool/speak/openrouter.ts +240 -0
  535. package/src/tool/speak/provider.ts +83 -0
  536. package/src/tool/speak.ts +440 -0
  537. package/src/tool/task.ts +194 -0
  538. package/src/tool/task.txt +60 -0
  539. package/src/tool/todo.ts +53 -0
  540. package/src/tool/todoread.txt +14 -0
  541. package/src/tool/todowrite.txt +167 -0
  542. package/src/tool/tool.ts +87 -0
  543. package/src/tool/tree.ts +218 -0
  544. package/src/tool/tree.txt +8 -0
  545. package/src/tool/truncation.ts +106 -0
  546. package/src/tool/use-connector.ts +47 -0
  547. package/src/tool/voice.ts +188 -0
  548. package/src/tool/webfetch.ts +205 -0
  549. package/src/tool/webfetch.txt +13 -0
  550. package/src/tool/websearch.ts +150 -0
  551. package/src/tool/websearch.txt +14 -0
  552. package/src/tool/write.ts +80 -0
  553. package/src/tool/write.txt +8 -0
  554. package/src/util/archive.ts +16 -0
  555. package/src/util/color.ts +19 -0
  556. package/src/util/context.ts +25 -0
  557. package/src/util/defer.ts +12 -0
  558. package/src/util/error.ts +77 -0
  559. package/src/util/eventloop.ts +20 -0
  560. package/src/util/filesystem.ts +125 -0
  561. package/src/util/flock.ts +329 -0
  562. package/src/util/fn.ts +11 -0
  563. package/src/util/format.ts +20 -0
  564. package/src/util/hash.ts +7 -0
  565. package/src/util/iife.ts +3 -0
  566. package/src/util/keybind.ts +103 -0
  567. package/src/util/lazy.ts +18 -0
  568. package/src/util/locale.ts +81 -0
  569. package/src/util/lock.ts +98 -0
  570. package/src/util/log.ts +180 -0
  571. package/src/util/network.ts +9 -0
  572. package/src/util/process.ts +15 -0
  573. package/src/util/queue.ts +32 -0
  574. package/src/util/record.ts +3 -0
  575. package/src/util/rpc.ts +66 -0
  576. package/src/util/scrap.ts +10 -0
  577. package/src/util/signal.ts +12 -0
  578. package/src/util/timeout.ts +14 -0
  579. package/src/util/token.ts +7 -0
  580. package/src/util/wildcard.ts +56 -0
  581. package/src/workspace/adaptors/index.ts +271 -0
  582. package/src/workspace/adaptors/types.ts +14 -0
  583. package/src/workspace/adaptors/worktree.ts +31 -0
  584. package/src/workspace/config.ts +19 -0
  585. package/src/workspace/index.ts +223 -0
  586. package/src/workspace/session-proxy-middleware.ts +97 -0
  587. package/src/workspace/sse.ts +66 -0
  588. package/src/workspace/workspace-context.ts +23 -0
  589. package/src/workspace/workspace-server/routes.ts +33 -0
  590. package/src/workspace/workspace-server/server.ts +47 -0
  591. package/src/worktree/index.ts +487 -0
  592. package/sst-env.d.ts +10 -0
  593. package/test/benchmark.test.ts +121 -0
  594. package/test/build-optimizations.test.ts +124 -0
  595. package/test/id-benchmark.test.ts +132 -0
  596. package/test/optimizations.test.ts +302 -0
  597. package/test/preload.ts +1 -0
  598. package/test/solidjs-benchmark.test.ts +262 -0
  599. package/test/solidjs-optimizations.test.ts +259 -0
  600. package/test/tui-benchmark.test.ts +230 -0
  601. package/test/wildcard-benchmark.test.ts +180 -0
  602. package/tsconfig.json +26 -0
@@ -0,0 +1,717 @@
1
+ import { RGBA, TextAttributes } from "@opentui/core"
2
+ import { useKeyboard, useTerminalDimensions } from "@opentui/solid"
3
+ import path from "path"
4
+ import { mkdir } from "fs/promises"
5
+ import { createMemo, For, Show, onMount } from "solid-js"
6
+ import { createStore } from "solid-js/store"
7
+ import { Global } from "@/global"
8
+ import { Filesystem } from "@/util/filesystem"
9
+ import { DEFAULT_THEMES, useTheme } from "../context/theme"
10
+ import { useDialog } from "../ui/dialog"
11
+
12
+ interface ColorDef {
13
+ key: string
14
+ label: string
15
+ description: string
16
+ }
17
+
18
+ const COLOR_DEFS: ColorDef[] = [
19
+ { key: "primary", label: "Primary", description: "Main accent color" },
20
+ { key: "secondary", label: "Secondary", description: "Secondary accent" },
21
+ { key: "accent", label: "Accent", description: "Extra accent" },
22
+ { key: "error", label: "Error", description: "Error color" },
23
+ { key: "warning", label: "Warning", description: "Warning color" },
24
+ { key: "success", label: "Success", description: "Success color" },
25
+ { key: "info", label: "Info", description: "Info color" },
26
+ { key: "text", label: "Text", description: "Main text color" },
27
+ { key: "textMuted", label: "Text Muted", description: "Muted text color" },
28
+ { key: "background", label: "Background", description: "Main background" },
29
+ { key: "backgroundPanel", label: "Panel", description: "Panel background" },
30
+ { key: "backgroundElement", label: "Element", description: "Element background" },
31
+ { key: "border", label: "Border", description: "Border color" },
32
+ { key: "borderActive", label: "Border Active", description: "Active border" },
33
+ { key: "borderSubtle", label: "Border Subtle", description: "Subtle border" },
34
+ ]
35
+
36
+ const PRESET_COLORS = [
37
+ "#6fa3ff",
38
+ "#a78bfa",
39
+ "#f472b6",
40
+ "#ef4444",
41
+ "#f97316",
42
+ "#eab308",
43
+ "#22c55e",
44
+ "#06b6d4",
45
+ "#14b8a6",
46
+ "#6366f1",
47
+ "#d45f5f",
48
+ "#d9a14a",
49
+ "#7fc08f",
50
+ "#58a6b8",
51
+ "#d2b56d",
52
+ "#070707",
53
+ "#121212",
54
+ "#1b1b1b",
55
+ "#242424",
56
+ "#2e2e2e",
57
+ "#3a3a3a",
58
+ "#4a4a4a",
59
+ "#5c5c5c",
60
+ "#8bb4ff",
61
+ "#9a9a9a",
62
+ "#e6e6e6",
63
+ "#f7f7f7",
64
+ "#ededed",
65
+ "#e2e2e2",
66
+ ]
67
+
68
+ function rgbaToHex(rgba: RGBA): string {
69
+ const r = Math.round(rgba.r * 255)
70
+ const g = Math.round(rgba.g * 255)
71
+ const b = Math.round(rgba.b * 255)
72
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`
73
+ }
74
+
75
+ function normalizeThemeName(input: string): { ok: true; value: string } | { ok: false; reason: string } {
76
+ const trimmed = input.trim()
77
+ if (!trimmed) return { ok: false, reason: "Theme name is required." }
78
+
79
+ let slug = trimmed
80
+ .toLowerCase()
81
+ .replace(/[^a-z0-9_-]+/g, "-")
82
+ .replace(/-+/g, "-")
83
+ .replace(/^-+/, "")
84
+ .replace(/-+$/, "")
85
+
86
+ if (!slug) return { ok: false, reason: "Theme name must include letters or numbers." }
87
+ if (slug.length > 64) slug = slug.slice(0, 64).replace(/-+$/, "")
88
+
89
+ const reserved = new Set<string>([...Object.keys(DEFAULT_THEMES), "system"])
90
+ if (reserved.has(slug)) {
91
+ return { ok: false, reason: `"${slug}" is reserved. Choose a different name.` }
92
+ }
93
+
94
+ return { ok: true, value: slug }
95
+ }
96
+
97
+ function generateGrayScale(bg: RGBA, isDark: boolean): Record<number, RGBA> {
98
+ const grays: Record<number, RGBA> = {}
99
+ const bgR = bg.r * 255
100
+ const bgG = bg.g * 255
101
+ const bgB = bg.b * 255
102
+ const luminance = 0.299 * bgR + 0.587 * bgG + 0.114 * bgB
103
+
104
+ for (let i = 1; i <= 12; i++) {
105
+ const factor = i / 12.0
106
+ let newR: number, newG: number, newB: number
107
+
108
+ if (isDark) {
109
+ if (luminance < 10) {
110
+ const grayValue = Math.floor(factor * 0.4 * 255)
111
+ newR = grayValue
112
+ newG = grayValue
113
+ newB = grayValue
114
+ } else {
115
+ const newLum = luminance + (255 - luminance) * factor * 0.4
116
+ const ratio = newLum / luminance
117
+ newR = Math.min(bgR * ratio, 255)
118
+ newG = Math.min(bgG * ratio, 255)
119
+ newB = Math.min(bgB * ratio, 255)
120
+ }
121
+ } else {
122
+ if (luminance > 245) {
123
+ const grayValue = Math.floor(255 - factor * 0.4 * 255)
124
+ newR = grayValue
125
+ newG = grayValue
126
+ newB = grayValue
127
+ } else {
128
+ const newLum = luminance * (1 - factor * 0.4)
129
+ const ratio = newLum / luminance
130
+ newR = Math.max(bgR * ratio, 0)
131
+ newG = Math.max(bgG * ratio, 0)
132
+ newB = Math.max(bgB * ratio, 0)
133
+ }
134
+ }
135
+ grays[i] = RGBA.fromInts(Math.floor(newR), Math.floor(newG), Math.floor(newB))
136
+ }
137
+ return grays
138
+ }
139
+
140
+ function generateMutedTextColor(bg: RGBA, isDark: boolean): RGBA {
141
+ const bgR = bg.r * 255
142
+ const bgG = bg.g * 255
143
+ const bgB = bg.b * 255
144
+ const bgLum = 0.299 * bgR + 0.587 * bgG + 0.114 * bgB
145
+
146
+ let grayValue: number
147
+ if (isDark) {
148
+ grayValue = bgLum < 10 ? 180 : Math.min(Math.floor(160 + bgLum * 0.3), 200)
149
+ } else {
150
+ grayValue = bgLum > 245 ? 75 : Math.max(Math.floor(100 - (255 - bgLum) * 0.2), 60)
151
+ }
152
+ return RGBA.fromInts(grayValue, grayValue, grayValue)
153
+ }
154
+
155
+ export function DialogThemeCreate() {
156
+ const themeCtx = useTheme()
157
+ const { theme } = themeCtx
158
+ const dialog = useDialog()
159
+ const dimensions = useTerminalDimensions()
160
+ let nameInput: any
161
+
162
+ const [store, setStore] = createStore({
163
+ name: "",
164
+ variant: "dark" as "dark" | "light",
165
+ scope: "global" as "global" | "project",
166
+ colors: {
167
+ dark: {} as Record<string, string>,
168
+ light: {} as Record<string, string>,
169
+ },
170
+ selectedColor: "__name__" as string | null,
171
+ selectedIndex: -1,
172
+ pickerIndex: 0,
173
+ saving: false,
174
+ overwriteArmed: false,
175
+ status: "",
176
+ })
177
+
178
+ onMount(() => {
179
+ dialog.setSize("large")
180
+ setTimeout(() => nameInput?.focus?.(), 1)
181
+ })
182
+
183
+ const dialogWidth = createMemo(() => Math.min(80, Math.max(40, dimensions().width - 2)))
184
+ const contentWidth = createMemo(() => Math.max(32, dialogWidth() - 8))
185
+
186
+ const defaultBgHex = (variant: "dark" | "light") => (variant === "dark" ? "#070707" : "#f7f7f7")
187
+ const defaultTextHex = (variant: "dark" | "light") => (variant === "dark" ? "#e6e6e6" : "#070707")
188
+ const defaultAccentHex = "#6fa3ff"
189
+
190
+ const bgHex = (variant: "dark" | "light") => store.colors[variant].background || defaultBgHex(variant)
191
+ const accentHex = (variant: "dark" | "light") => store.colors[variant].primary || defaultAccentHex
192
+
193
+ const grays = createMemo(() => {
194
+ return {
195
+ dark: generateGrayScale(RGBA.fromHex(bgHex("dark")), true),
196
+ light: generateGrayScale(RGBA.fromHex(bgHex("light")), false),
197
+ } as const
198
+ })
199
+
200
+ const textMuted = createMemo(() => {
201
+ return {
202
+ dark: generateMutedTextColor(RGBA.fromHex(bgHex("dark")), true),
203
+ light: generateMutedTextColor(RGBA.fromHex(bgHex("light")), false),
204
+ } as const
205
+ })
206
+
207
+ const selectedColorDef = createMemo(() => COLOR_DEFS.find((c) => c.key === store.selectedColor))
208
+
209
+ const colorsPerRow = createMemo(() => {
210
+ const width = contentWidth()
211
+ if (width >= 72) return 5
212
+ if (width >= 56) return 4
213
+ return 3
214
+ })
215
+
216
+ const colorBoxWidth = createMemo(() => {
217
+ const width = contentWidth()
218
+ const padding = 4
219
+ const gap = 1
220
+ const perRow = colorsPerRow()
221
+ return Math.floor((width - padding - gap * (perRow - 1)) / perRow)
222
+ })
223
+
224
+ const generatedTheme = createMemo(() => {
225
+ const darkPrefix = "darkStep"
226
+ const lightPrefix = "lightStep"
227
+
228
+ return {
229
+ $schema: "https://nikcli.store/theme.json",
230
+ defs: {
231
+ [`${darkPrefix}1`]: bgHex("dark"),
232
+ [`${darkPrefix}2`]: rgbaToHex(grays().dark[2]!),
233
+ [`${darkPrefix}3`]: rgbaToHex(grays().dark[3]!),
234
+ [`${darkPrefix}4`]: rgbaToHex(grays().dark[4]!),
235
+ [`${darkPrefix}5`]: rgbaToHex(grays().dark[5]!),
236
+ [`${darkPrefix}6`]: rgbaToHex(grays().dark[6]!),
237
+ [`${darkPrefix}7`]: rgbaToHex(grays().dark[7]!),
238
+ [`${darkPrefix}8`]: rgbaToHex(grays().dark[8]!),
239
+ [`${darkPrefix}9`]: accentHex("dark"),
240
+ [`${darkPrefix}10`]: rgbaToHex(grays().dark[10]!),
241
+ [`${darkPrefix}11`]: rgbaToHex(textMuted().dark),
242
+ [`${darkPrefix}12`]: rgbaToHex(grays().dark[12]!),
243
+
244
+ [`${lightPrefix}1`]: bgHex("light"),
245
+ [`${lightPrefix}2`]: rgbaToHex(grays().light[2]!),
246
+ [`${lightPrefix}3`]: rgbaToHex(grays().light[3]!),
247
+ [`${lightPrefix}4`]: rgbaToHex(grays().light[4]!),
248
+ [`${lightPrefix}5`]: rgbaToHex(grays().light[5]!),
249
+ [`${lightPrefix}6`]: rgbaToHex(grays().light[6]!),
250
+ [`${lightPrefix}7`]: rgbaToHex(grays().light[7]!),
251
+ [`${lightPrefix}8`]: rgbaToHex(grays().light[8]!),
252
+ [`${lightPrefix}9`]: accentHex("light"),
253
+ [`${lightPrefix}10`]: rgbaToHex(grays().light[10]!),
254
+ [`${lightPrefix}11`]: rgbaToHex(textMuted().light),
255
+ [`${lightPrefix}12`]: rgbaToHex(grays().light[12]!),
256
+ },
257
+ theme: {
258
+ primary: {
259
+ dark: store.colors.dark.primary || `${darkPrefix}9`,
260
+ light: store.colors.light.primary || `${lightPrefix}9`,
261
+ },
262
+ secondary: {
263
+ dark: store.colors.dark.secondary || `${darkPrefix}9`,
264
+ light: store.colors.light.secondary || `${lightPrefix}9`,
265
+ },
266
+ accent: {
267
+ dark: store.colors.dark.accent || `${darkPrefix}9`,
268
+ light: store.colors.light.accent || `${lightPrefix}9`,
269
+ },
270
+ error: { dark: store.colors.dark.error || "#d45f5f", light: store.colors.light.error || "#b42338" },
271
+ warning: { dark: store.colors.dark.warning || "#d9a14a", light: store.colors.light.warning || "#7a4e00" },
272
+ success: { dark: store.colors.dark.success || "#7fc08f", light: store.colors.light.success || "#2f9e44" },
273
+ info: { dark: store.colors.dark.info || "#58a6b8", light: store.colors.light.info || "#0b7285" },
274
+
275
+ text: { dark: store.colors.dark.text || `${darkPrefix}12`, light: store.colors.light.text || `${lightPrefix}12` },
276
+ textMuted: { dark: store.colors.dark.textMuted || `${darkPrefix}11`, light: store.colors.light.textMuted || `${lightPrefix}11` },
277
+ selectedListItemText: { dark: `${darkPrefix}1`, light: `${lightPrefix}1` },
278
+
279
+ background: { dark: store.colors.dark.background || `${darkPrefix}1`, light: store.colors.light.background || `${lightPrefix}1` },
280
+ backgroundPanel: {
281
+ dark: store.colors.dark.backgroundPanel || `${darkPrefix}2`,
282
+ light: store.colors.light.backgroundPanel || `${lightPrefix}2`,
283
+ },
284
+ backgroundElement: {
285
+ dark: store.colors.dark.backgroundElement || `${darkPrefix}3`,
286
+ light: store.colors.light.backgroundElement || `${lightPrefix}3`,
287
+ },
288
+ backgroundMenu: {
289
+ dark: store.colors.dark.backgroundElement || `${darkPrefix}3`,
290
+ light: store.colors.light.backgroundElement || `${lightPrefix}3`,
291
+ },
292
+
293
+ borderSubtle: { dark: store.colors.dark.borderSubtle || `${darkPrefix}6`, light: store.colors.light.borderSubtle || `${lightPrefix}6` },
294
+ border: { dark: store.colors.dark.border || `${darkPrefix}7`, light: store.colors.light.border || `${lightPrefix}7` },
295
+ borderActive: { dark: store.colors.dark.borderActive || `${darkPrefix}8`, light: store.colors.light.borderActive || `${lightPrefix}8` },
296
+
297
+ diffAdded: { dark: "#4fd6be", light: "#1a8d78" },
298
+ diffRemoved: { dark: "#c53b53", light: "#b42338" },
299
+ diffContext: { dark: "#828bb8", light: "#5a6278" },
300
+ diffHunkHeader: { dark: "#828bb8", light: "#5a6278" },
301
+ diffHighlightAdded: { dark: "#b8db87", light: "#2e7d32" },
302
+ diffHighlightRemoved: { dark: "#e26a75", light: "#b42338" },
303
+ diffAddedBg: { dark: "#20303b", light: "#e6f4ea" },
304
+ diffRemovedBg: { dark: "#37222c", light: "#fde7ea" },
305
+ diffContextBg: { dark: `${darkPrefix}2`, light: `${lightPrefix}2` },
306
+ diffLineNumber: { dark: `${darkPrefix}3`, light: `${lightPrefix}3` },
307
+ diffAddedLineNumberBg: { dark: "#1b2b34", light: "#d7f3e3" },
308
+ diffRemovedLineNumberBg: { dark: "#2d1f26", light: "#fbd5dc" },
309
+
310
+ markdownText: { dark: `${darkPrefix}12`, light: `${lightPrefix}12` },
311
+ markdownHeading: {
312
+ dark: store.colors.dark.accent || `${darkPrefix}9`,
313
+ light: store.colors.light.accent || `${lightPrefix}9`,
314
+ },
315
+ markdownLink: { dark: `${darkPrefix}9`, light: `${lightPrefix}9` },
316
+ markdownLinkText: { dark: "#58a6b8", light: "#0b7285" },
317
+ markdownCode: { dark: "#7fc08f", light: "#2f9e44" },
318
+ markdownBlockQuote: { dark: "#d2b56d", light: "#8a6d3b" },
319
+ markdownEmph: { dark: "#d2b56d", light: "#8a6d3b" },
320
+ markdownStrong: { dark: "#d9a14a", light: "#7a4e00" },
321
+ markdownHorizontalRule: { dark: `${darkPrefix}11`, light: `${lightPrefix}11` },
322
+ markdownListItem: { dark: `${darkPrefix}9`, light: `${lightPrefix}9` },
323
+ markdownListEnumeration: { dark: "#58a6b8", light: "#0b7285" },
324
+ markdownImage: { dark: `${darkPrefix}9`, light: `${lightPrefix}9` },
325
+ markdownImageText: { dark: "#58a6b8", light: "#0b7285" },
326
+ markdownCodeBlock: { dark: `${darkPrefix}12`, light: `${lightPrefix}12` },
327
+
328
+ syntaxComment: { dark: `${darkPrefix}11`, light: `${lightPrefix}11` },
329
+ syntaxKeyword: {
330
+ dark: store.colors.dark.accent || `${darkPrefix}9`,
331
+ light: store.colors.light.accent || `${lightPrefix}9`,
332
+ },
333
+ syntaxFunction: { dark: `${darkPrefix}9`, light: `${lightPrefix}9` },
334
+ syntaxVariable: { dark: "#d45f5f", light: "#b42338" },
335
+ syntaxString: { dark: "#7fc08f", light: "#2f9e44" },
336
+ syntaxNumber: { dark: "#d9a14a", light: "#7a4e00" },
337
+ syntaxType: { dark: "#d2b56d", light: "#8a6d3b" },
338
+ syntaxOperator: { dark: "#58a6b8", light: "#0b7285" },
339
+ syntaxPunctuation: { dark: `${darkPrefix}12`, light: `${lightPrefix}12` },
340
+
341
+ thinkingOpacity: 0.6,
342
+ },
343
+ }
344
+ })
345
+
346
+ const resetOverwriteArm = () => {
347
+ if (store.overwriteArmed) setStore("overwriteArmed", false)
348
+ }
349
+
350
+ async function resolveThemesDir() {
351
+ if (store.scope === "global") return path.join(Global.Path.config, "themes")
352
+ const found = await Array.fromAsync(
353
+ Filesystem.up({
354
+ targets: [".nikcli"],
355
+ start: process.cwd(),
356
+ }),
357
+ ).then((x) => x[0])
358
+ const nikcliDir = found ?? path.join(process.cwd(), ".nikcli")
359
+ return path.join(nikcliDir, "themes")
360
+ }
361
+
362
+ const handleSave = async () => {
363
+ const normalized = normalizeThemeName(store.name)
364
+ if (!normalized.ok) {
365
+ setStore("status", normalized.reason)
366
+ return
367
+ }
368
+
369
+ if (store.name.trim() !== normalized.value) {
370
+ setStore("name", normalized.value)
371
+ }
372
+
373
+ setStore("saving", true)
374
+ setStore("status", "")
375
+
376
+ try {
377
+ const themeName = normalized.value
378
+ const themesDir = await resolveThemesDir()
379
+ await mkdir(themesDir, { recursive: true })
380
+ const filePath = path.join(themesDir, `${themeName}.json`)
381
+
382
+ const exists = await Bun.file(filePath).exists()
383
+ if (exists && !store.overwriteArmed) {
384
+ setStore("saving", false)
385
+ setStore("overwriteArmed", true)
386
+ setStore("status", `Theme "${themeName}" already exists. Press Ctrl+S again to overwrite.`)
387
+ return
388
+ }
389
+
390
+ await Bun.write(filePath, JSON.stringify(generatedTheme(), null, 2))
391
+ await themeCtx.reload()
392
+ themeCtx.set(themeName)
393
+ dialog.clear()
394
+ } catch (e) {
395
+ setStore("saving", false)
396
+ setStore("status", e instanceof Error ? e.message : "Failed to save theme.")
397
+ }
398
+ }
399
+
400
+ useKeyboard((evt) => {
401
+ if (evt.ctrl && evt.name === "s" && !store.saving) {
402
+ evt.preventDefault()
403
+ evt.stopPropagation()
404
+ handleSave()
405
+ return
406
+ }
407
+ if (evt.name === "escape") {
408
+ dialog.clear()
409
+ return
410
+ }
411
+
412
+ if (evt.name === "tab") {
413
+ if (store.selectedColor === "__name__") {
414
+ setStore("selectedIndex", 0)
415
+ setStore("selectedColor", COLOR_DEFS[0]!.key)
416
+ } else {
417
+ setStore("selectedIndex", -1)
418
+ setStore("selectedColor", "__name__")
419
+ setTimeout(() => nameInput?.focus?.(), 1)
420
+ }
421
+ return
422
+ }
423
+
424
+ if (evt.name === "v") {
425
+ setStore("variant", store.variant === "dark" ? "light" : "dark")
426
+ resetOverwriteArm()
427
+ return
428
+ }
429
+
430
+ if (evt.name === "g") {
431
+ setStore("scope", store.scope === "global" ? "project" : "global")
432
+ resetOverwriteArm()
433
+ return
434
+ }
435
+
436
+ const perRow = colorsPerRow()
437
+ const totalColors = COLOR_DEFS.length
438
+
439
+ if (evt.name === "down" || evt.name === "j") {
440
+ const next = store.selectedIndex < 0 ? 0 : Math.min(store.selectedIndex + perRow, totalColors - 1)
441
+ setStore("selectedIndex", next)
442
+ setStore("selectedColor", COLOR_DEFS[next]!.key)
443
+ return
444
+ }
445
+ if (evt.name === "up" || evt.name === "k") {
446
+ const next = store.selectedIndex < 0 ? 0 : Math.max(store.selectedIndex - perRow, 0)
447
+ setStore("selectedIndex", next)
448
+ setStore("selectedColor", COLOR_DEFS[next]!.key)
449
+ return
450
+ }
451
+ if (evt.name === "left" || evt.name === "h") {
452
+ const next = store.selectedIndex < 0 ? 0 : Math.max(store.selectedIndex - 1, 0)
453
+ setStore("selectedIndex", next)
454
+ setStore("selectedColor", COLOR_DEFS[next]!.key)
455
+ return
456
+ }
457
+ if (evt.name === "right" || evt.name === "l") {
458
+ const next = store.selectedIndex < 0 ? 0 : Math.min(store.selectedIndex + 1, totalColors - 1)
459
+ setStore("selectedIndex", next)
460
+ setStore("selectedColor", COLOR_DEFS[next]!.key)
461
+ return
462
+ }
463
+
464
+ if (store.selectedColor && store.selectedColor !== "__name__") {
465
+ const pickerTotal = PRESET_COLORS.length
466
+ if (evt.name === "w" || evt.name === "W") {
467
+ setStore("pickerIndex", Math.max(store.pickerIndex - 5, 0))
468
+ return
469
+ }
470
+ if (evt.name === "s" || evt.name === "S") {
471
+ setStore("pickerIndex", Math.min(store.pickerIndex + 5, pickerTotal - 1))
472
+ return
473
+ }
474
+ if (evt.name === "a" || evt.name === "A" || evt.name === "p") {
475
+ setStore("pickerIndex", Math.max(store.pickerIndex - 1, 0))
476
+ return
477
+ }
478
+ if (evt.name === "d" || evt.name === "D" || evt.name === "n") {
479
+ setStore("pickerIndex", Math.min(store.pickerIndex + 1, pickerTotal - 1))
480
+ return
481
+ }
482
+ if (evt.name === "space" || evt.name === " ") {
483
+ const color = PRESET_COLORS[store.pickerIndex]
484
+ if (color && store.selectedColor) {
485
+ setStore("colors", store.variant, store.selectedColor, color)
486
+ resetOverwriteArm()
487
+ }
488
+ return
489
+ }
490
+ }
491
+ })
492
+
493
+ const colorList = createMemo(() => {
494
+ return COLOR_DEFS.map((def, index) => {
495
+ const value =
496
+ store.colors[store.variant][def.key] ||
497
+ (def.key === "primary"
498
+ ? defaultAccentHex
499
+ : def.key === "background"
500
+ ? defaultBgHex(store.variant)
501
+ : def.key === "text"
502
+ ? defaultTextHex(store.variant)
503
+ : defaultAccentHex)
504
+ return { ...def, index, value }
505
+ })
506
+ })
507
+
508
+ return (
509
+ <box paddingLeft={2} paddingRight={2} paddingTop={1} gap={1}>
510
+ <box flexDirection="row" justifyContent="space-between">
511
+ <text attributes={TextAttributes.BOLD} fg={theme.text}>
512
+ Create Theme
513
+ </text>
514
+ <text fg={theme.textMuted}>tab focus · v variant · g scope · ctrl+s save</text>
515
+ </box>
516
+
517
+ <Show when={store.status}>
518
+ <text fg={store.overwriteArmed ? theme.warning : theme.textMuted} wrapMode="word">
519
+ {store.status}
520
+ </text>
521
+ </Show>
522
+
523
+ <box flexDirection="row" gap={1} alignItems="center">
524
+ <text fg={theme.textMuted}>Name:</text>
525
+ <box
526
+ width={25}
527
+ border={["bottom"]}
528
+ borderColor={store.selectedColor === "__name__" ? theme.primary : theme.borderSubtle}
529
+ onMouseUp={() => {
530
+ setStore("selectedColor", "__name__")
531
+ setStore("selectedIndex", -1)
532
+ setTimeout(() => nameInput?.focus?.(), 1)
533
+ }}
534
+ >
535
+ <input
536
+ value={store.name}
537
+ onInput={(v) => {
538
+ setStore("name", v)
539
+ setStore("status", "")
540
+ resetOverwriteArm()
541
+ }}
542
+ placeholder="my-theme"
543
+ cursorColor={theme.primary}
544
+ focusedTextColor={theme.text}
545
+ ref={(r) => {
546
+ nameInput = r
547
+ }}
548
+ />
549
+ </box>
550
+ </box>
551
+
552
+ <box flexDirection="row" gap={1} alignItems="center">
553
+ <text fg={theme.textMuted}>Variant:</text>
554
+ <For each={["dark", "light"] as const}>
555
+ {(variant) => (
556
+ <box
557
+ paddingLeft={1}
558
+ paddingRight={1}
559
+ backgroundColor={store.variant === variant ? theme.primary : theme.backgroundElement}
560
+ onMouseUp={() => {
561
+ setStore("variant", variant)
562
+ resetOverwriteArm()
563
+ }}
564
+ >
565
+ <text fg={store.variant === variant ? theme.selectedListItemText : theme.text}>{variant}</text>
566
+ </box>
567
+ )}
568
+ </For>
569
+ </box>
570
+
571
+ <box flexDirection="row" gap={1} alignItems="center">
572
+ <text fg={theme.textMuted}>Scope:</text>
573
+ <For each={["global", "project"] as const}>
574
+ {(scope) => (
575
+ <box
576
+ paddingLeft={1}
577
+ paddingRight={1}
578
+ backgroundColor={store.scope === scope ? theme.primary : theme.backgroundElement}
579
+ onMouseUp={() => {
580
+ setStore("scope", scope)
581
+ resetOverwriteArm()
582
+ }}
583
+ >
584
+ <text fg={store.scope === scope ? theme.selectedListItemText : theme.text}>{scope}</text>
585
+ </box>
586
+ )}
587
+ </For>
588
+ </box>
589
+
590
+ <box height={1} border={["top"]} borderColor={theme.borderSubtle} />
591
+
592
+ <scrollbox maxHeight={18} scrollbarOptions={{ visible: false }}>
593
+ <box flexDirection="row" flexWrap="wrap" gap={1}>
594
+ <For each={colorList()}>
595
+ {(item) => {
596
+ const isSelected = store.selectedIndex === item.index
597
+ return (
598
+ <box
599
+ width={colorBoxWidth()}
600
+ backgroundColor={theme.backgroundPanel}
601
+ border={["top", "bottom", "left", "right"]}
602
+ borderColor={isSelected ? theme.primary : theme.borderSubtle}
603
+ onMouseUp={() => {
604
+ setStore("selectedIndex", item.index)
605
+ setStore("selectedColor", item.key)
606
+ }}
607
+ >
608
+ <box paddingLeft={1} gap={0}>
609
+ <text fg={isSelected ? theme.primary : theme.text} attributes={isSelected ? TextAttributes.BOLD : undefined}>
610
+ {item.label}
611
+ </text>
612
+ <box flexDirection="row" gap={0} alignItems="center" paddingTop={1}>
613
+ <box width={3} height={1} backgroundColor={RGBA.fromHex(item.value)} />
614
+ <text fg={theme.textMuted} marginLeft={1}>
615
+ {item.value}
616
+ </text>
617
+ </box>
618
+ </box>
619
+ </box>
620
+ )
621
+ }}
622
+ </For>
623
+ </box>
624
+ </scrollbox>
625
+
626
+ <Show when={store.selectedColor && store.selectedColor !== "__name__"}>
627
+ <box
628
+ backgroundColor={theme.backgroundPanel}
629
+ border={["top", "bottom", "left", "right"]}
630
+ borderColor={theme.border}
631
+ paddingLeft={1}
632
+ paddingRight={1}
633
+ paddingTop={1}
634
+ gap={1}
635
+ >
636
+ <box flexDirection="row" justifyContent="space-between">
637
+ <text attributes={TextAttributes.BOLD} fg={theme.text}>
638
+ {selectedColorDef()?.label}: {selectedColorDef()?.description}
639
+ </text>
640
+ </box>
641
+ <scrollbox maxHeight={5} scrollbarOptions={{ visible: false }}>
642
+ <box flexDirection="row" flexWrap="wrap" gap={1}>
643
+ <For each={PRESET_COLORS}>
644
+ {(color, i) => {
645
+ const isSelected = i() === store.pickerIndex
646
+ return (
647
+ <box
648
+ width={4}
649
+ height={1}
650
+ backgroundColor={RGBA.fromHex(color)}
651
+ border={["top", "bottom", "left", "right"]}
652
+ borderColor={isSelected ? theme.primary : theme.borderSubtle}
653
+ onMouseUp={() => {
654
+ setStore("pickerIndex", i())
655
+ if (store.selectedColor) {
656
+ setStore("colors", store.variant, store.selectedColor, color)
657
+ resetOverwriteArm()
658
+ }
659
+ }}
660
+ />
661
+ )
662
+ }}
663
+ </For>
664
+ </box>
665
+ </scrollbox>
666
+ </box>
667
+ </Show>
668
+
669
+ <box height={1} border={["top"]} borderColor={theme.borderSubtle} />
670
+
671
+ <box flexDirection="row" justifyContent="space-between" alignItems="center">
672
+ <box flexDirection="row" gap={1}>
673
+ <box
674
+ width={4}
675
+ height={2}
676
+ backgroundColor={RGBA.fromHex(store.colors[store.variant].primary || defaultAccentHex)}
677
+ border={["top", "bottom", "left", "right"]}
678
+ borderColor={theme.borderSubtle}
679
+ >
680
+ <box paddingLeft={1} paddingTop={1}>
681
+ <text fg={RGBA.fromHex(store.colors[store.variant].background || defaultBgHex(store.variant))}>Aa</text>
682
+ </box>
683
+ </box>
684
+ <box
685
+ width={4}
686
+ height={2}
687
+ backgroundColor={RGBA.fromHex(store.colors[store.variant].background || defaultBgHex(store.variant))}
688
+ border={["top", "bottom", "left", "right"]}
689
+ borderColor={theme.borderSubtle}
690
+ justifyContent="center"
691
+ alignItems="center"
692
+ >
693
+ <text fg={RGBA.fromHex(store.colors[store.variant].text || defaultTextHex(store.variant))}>Text</text>
694
+ </box>
695
+ </box>
696
+
697
+ <box flexDirection="row" gap={1}>
698
+ <box paddingLeft={1} paddingRight={1} backgroundColor={theme.backgroundElement} onMouseUp={() => dialog.clear()}>
699
+ <text fg={theme.textMuted}>Cancel</text>
700
+ </box>
701
+ <box
702
+ paddingLeft={1}
703
+ paddingRight={1}
704
+ backgroundColor={
705
+ store.name && !store.saving ? (store.overwriteArmed ? theme.warning : theme.primary) : theme.backgroundElement
706
+ }
707
+ onMouseUp={() => store.name && !store.saving && handleSave()}
708
+ >
709
+ <text fg={store.name && !store.saving ? theme.selectedListItemText : theme.textMuted}>
710
+ {store.saving ? "Saving..." : store.overwriteArmed ? "Overwrite Theme" : "Save Theme"}
711
+ </text>
712
+ </box>
713
+ </box>
714
+ </box>
715
+ </box>
716
+ )
717
+ }