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,201 @@
1
+ /**
2
+ * ElevenLabs TTS Provider Implementation
3
+ */
4
+
5
+ import type { TTSProvider, TTSVoice, TTSRequest, TTSResponse, TTSProviderConfig } from "./provider"
6
+
7
+ const ELEVENLABS_VOICES: TTSVoice[] = [
8
+ { id: "YOq2y2Up4RgXP2HyXjE5", name: "Rachel" },
9
+ { id: "AZnzlk1XvdvUeBnXmlNG", name: "Sam" },
10
+ { id: "CwhRBWXzGAHq8TQ4Fs17", name: "Roger" },
11
+ { id: "EXAVITQu4vr4xnSDxMaL", name: "Sarah" },
12
+ { id: "LyssAJIZ4k3DJGW7QTaO", name: "Elliot" },
13
+ { id: "MFZMEXqYqFN5YSiJqHxo", name: "Charlie" },
14
+ { id: "NFY5qYlrZGkZ9jJp9J4j", name: "Emily" },
15
+ { id: "nP4h3Nz5tJaqBqu4zDu4", name: "Aria" },
16
+ { id: "oWAxZDx7T60O2gCoV7ko", name: "Adam" },
17
+ { id: "pNInz6obpgDQGcFmaJgB", name: "Arnold" },
18
+ { id: "pmqG7SzvK3r3HXQ8N6ZQ", name: "Bella" },
19
+ { id: "rObUfCSj2PE5ZuEbZkrk", name: "Dom" },
20
+ { id: "rpGA7VF8a1eY2Ayt7iM6", name: "Dorothy" },
21
+ { id: "tw1kZhNv6T3jtsJCJSt4", name: "Fin" },
22
+ { id: "wbJZE5tDdP3V3uKPYb1W", name: "Freya" },
23
+ { id: "xQ8P86CzPvXP2Y4QxYOq", name: "Grace" },
24
+ { id: "xR4vQ8J3tN2YwZcKfDm6", name: "James" },
25
+ { id: "yHAj8S3qP5RwN7YvXtZ1", name: "Jenny" },
26
+ { id: "z9Q7X6Y4jV2NtR8PwLm3", name: "Matthew" },
27
+ ]
28
+
29
+ const DEFAULT_MODEL_ID = "eleven_v3"
30
+ const DEFAULT_OUTPUT_FORMAT = "mp3_44100_128"
31
+ const BASE_URL = "https://api.elevenlabs.io/v1"
32
+
33
+ function extensionFromOutputFormat(format: string): string {
34
+ const lower = format.toLowerCase()
35
+ if (lower.startsWith("wav")) return "wav"
36
+ if (lower.startsWith("mp3")) return "mp3"
37
+ return "bin"
38
+ }
39
+
40
+ export class ElevenLabsProvider implements TTSProvider {
41
+ readonly id = "elevenlabs"
42
+ readonly name = "ElevenLabs"
43
+ readonly description = "ElevenLabs Text-to-Speech API"
44
+
45
+ private config: TTSProviderConfig | null = null
46
+ private apiKey: string | null = null
47
+
48
+ async getConfig(): Promise<TTSProviderConfig> {
49
+ if (this.config) return this.config
50
+
51
+ const path = await import("@/global")
52
+ const API_KEY_FILEPATH = path.Global.Path.config + "/secrets/elevenlabs-key"
53
+
54
+ const envKey =
55
+ process.env.NIKCLI_ELEVENLABS_API_KEY ??
56
+ process.env.ELEVENLABS_API_KEY ??
57
+ process.env.XI_API_KEY ??
58
+ process.env.ELEVENLABS_KEY
59
+
60
+ if (envKey && envKey.trim()) {
61
+ this.apiKey = envKey.trim()
62
+ } else {
63
+ const file = Bun.file(API_KEY_FILEPATH)
64
+ if (await file.exists()) {
65
+ this.apiKey = (await file.text()).trim()
66
+ }
67
+ }
68
+
69
+ if (!this.apiKey) {
70
+ throw new Error(
71
+ [
72
+ "ElevenLabs API key not found.",
73
+ "",
74
+ "Set NIKCLI_ELEVENLABS_API_KEY (or ELEVENLABS_API_KEY), or create:",
75
+ API_KEY_FILEPATH,
76
+ "with your API key.",
77
+ ].join("\n"),
78
+ )
79
+ }
80
+
81
+ this.config = {
82
+ apiKey: this.apiKey,
83
+ baseURL: process.env.NIKCLI_ELEVENLABS_BASE_URL ?? BASE_URL,
84
+ timeout: 30000,
85
+ }
86
+
87
+ return this.config
88
+ }
89
+
90
+ async getVoices(): Promise<TTSVoice[]> {
91
+ // Return static list - could fetch from API if needed
92
+ return ELEVENLABS_VOICES
93
+ }
94
+
95
+ async speak(request: TTSRequest, options?: { signal?: AbortSignal }): Promise<TTSResponse> {
96
+ const config = await this.getConfig()
97
+ const modelId = request.modelId ?? DEFAULT_MODEL_ID
98
+ const outputFormat = request.outputFormat ?? DEFAULT_OUTPUT_FORMAT
99
+ const stability = request.stability ?? 0.5
100
+ const similarityBoost = request.similarityBoost ?? 0.75
101
+ const speed = request.speed ?? 1.0
102
+
103
+ const url = `${config.baseURL}/text-to-speech/${request.voiceId}?output_format=${encodeURIComponent(outputFormat)}`
104
+
105
+ const response = await fetch(url, {
106
+ method: "POST",
107
+ headers: {
108
+ "xi-api-key": config.apiKey,
109
+ "Content-Type": "application/json",
110
+ },
111
+ body: JSON.stringify({
112
+ text: request.text,
113
+ model_id: modelId,
114
+ voice_settings: {
115
+ stability,
116
+ similarity_boost: similarityBoost,
117
+ style: 0,
118
+ use_speaker_boost: true,
119
+ speed,
120
+ },
121
+ }),
122
+ signal: options?.signal,
123
+ })
124
+
125
+ if (!response.ok) {
126
+ const errorText = await response.text().catch(() => "")
127
+ let parsedError: any = {}
128
+ try {
129
+ if (errorText) parsedError = JSON.parse(errorText)
130
+ } catch {
131
+ /* ignore */
132
+ }
133
+
134
+ const rawDetail = parsedError.detail
135
+ const errorDetail =
136
+ rawDetail !== null && rawDetail !== undefined && typeof rawDetail === "object"
137
+ ? (rawDetail as any).message ?? JSON.stringify(rawDetail)
138
+ : rawDetail ?? parsedError.message ?? errorText
139
+
140
+ switch (response.status) {
141
+ case 401:
142
+ throw new Error(`ElevenLabs authentication failed (401). Your API key may be invalid or expired.`)
143
+ case 429:
144
+ throw new Error(`ElevenLabs rate limit exceeded (429). Too many requests.`)
145
+ case 400:
146
+ throw new Error(`ElevenLabs bad request (400): ${errorDetail}`)
147
+ default:
148
+ throw new Error(`ElevenLabs error (${response.status}): ${errorDetail}`)
149
+ }
150
+ }
151
+
152
+ const audioBuffer = await response.arrayBuffer()
153
+ const contentType = extensionFromOutputFormat(outputFormat)
154
+
155
+ return {
156
+ audio: audioBuffer,
157
+ contentType,
158
+ metadata: {
159
+ provider: this.id,
160
+ modelId,
161
+ voiceId: request.voiceId,
162
+ },
163
+ }
164
+ }
165
+
166
+ async validate(): Promise<{ valid: boolean; error?: string }> {
167
+ try {
168
+ const config = await this.getConfig()
169
+ if (!config.apiKey) {
170
+ return { valid: false, error: "API key not configured" }
171
+ }
172
+
173
+ // Test with a simple metadata request
174
+ const response = await fetch(`${config.baseURL}/voices`, {
175
+ headers: {
176
+ "xi-api-key": config.apiKey,
177
+ },
178
+ })
179
+
180
+ if (response.status === 401) {
181
+ return { valid: false, error: "Invalid API key" }
182
+ }
183
+
184
+ if (!response.ok) {
185
+ return { valid: false, error: `API returned status ${response.status}` }
186
+ }
187
+
188
+ return { valid: true }
189
+ } catch (error) {
190
+ return { valid: false, error: error instanceof Error ? error.message : "Unknown error" }
191
+ }
192
+ }
193
+ }
194
+
195
+ // Export singleton instance
196
+ export const elevenLabsProvider = new ElevenLabsProvider()
197
+
198
+ // Export voice list for easy access
199
+ export const ELEVENLABS_VOICES_LIST = ELEVENLABS_VOICES
200
+ // Backward-compatible alias (kept intentionally)
201
+ export const ELEVENTLABS_VOICES_LIST = ELEVENLABS_VOICES
@@ -0,0 +1,240 @@
1
+ import type { TTSProvider, TTSProviderConfig, TTSRequest, TTSResponse, TTSVoice } from "./provider"
2
+
3
+ const OPENROUTER_VOICES: TTSVoice[] = [
4
+ { id: "alloy", name: "Alloy" },
5
+ { id: "ash", name: "Ash" },
6
+ { id: "ballad", name: "Ballad" },
7
+ { id: "coral", name: "Coral" },
8
+ { id: "echo", name: "Echo" },
9
+ { id: "fable", name: "Fable" },
10
+ { id: "nova", name: "Nova" },
11
+ { id: "onyx", name: "Onyx" },
12
+ { id: "sage", name: "Sage" },
13
+ { id: "shimmer", name: "Shimmer" },
14
+ ]
15
+
16
+ const DEFAULT_MODEL_ID = "openai/gpt-audio-mini"
17
+ const BASE_URL = "https://openrouter.ai/api/v1"
18
+
19
+ type OpenRouterErrorBody = {
20
+ error?: {
21
+ message?: string
22
+ }
23
+ message?: string
24
+ detail?: string
25
+ }
26
+
27
+ type OpenRouterStreamChunk = {
28
+ choices?: Array<{
29
+ delta?: {
30
+ audio?: {
31
+ data?: string
32
+ }
33
+ }
34
+ }>
35
+ }
36
+
37
+ function buildWavBuffer(pcmData: Uint8Array, sampleRate = 24000, channels = 1, bitsPerSample = 16): ArrayBuffer {
38
+ const dataSize = pcmData.byteLength
39
+ const buffer = new ArrayBuffer(44 + dataSize)
40
+ const view = new DataView(buffer)
41
+
42
+ // RIFF
43
+ view.setUint8(0, 0x52); view.setUint8(1, 0x49); view.setUint8(2, 0x46); view.setUint8(3, 0x46)
44
+ view.setUint32(4, 36 + dataSize, true)
45
+ view.setUint8(8, 0x57); view.setUint8(9, 0x41); view.setUint8(10, 0x56); view.setUint8(11, 0x45)
46
+ // fmt
47
+ view.setUint8(12, 0x66); view.setUint8(13, 0x6d); view.setUint8(14, 0x74); view.setUint8(15, 0x20)
48
+ view.setUint32(16, 16, true)
49
+ view.setUint16(20, 1, true)
50
+ view.setUint16(22, channels, true)
51
+ view.setUint32(24, sampleRate, true)
52
+ view.setUint32(28, (sampleRate * channels * bitsPerSample) / 8, true)
53
+ view.setUint16(32, (channels * bitsPerSample) / 8, true)
54
+ view.setUint16(34, bitsPerSample, true)
55
+ // data
56
+ view.setUint8(36, 0x64); view.setUint8(37, 0x61); view.setUint8(38, 0x74); view.setUint8(39, 0x61)
57
+ view.setUint32(40, dataSize, true)
58
+
59
+ new Uint8Array(buffer, 44).set(pcmData)
60
+ return buffer
61
+ }
62
+
63
+ export class OpenRouterProvider implements TTSProvider {
64
+ readonly id = "openrouter"
65
+ readonly name = "OpenRouter"
66
+ readonly description = "OpenRouter OpenAI-compatible text-to-speech"
67
+
68
+ private config: TTSProviderConfig | null = null
69
+
70
+ async getConfig(): Promise<TTSProviderConfig> {
71
+ if (this.config) return this.config
72
+
73
+ const { Config } = await import("@/config/config")
74
+ const { Auth } = await import("@/auth")
75
+
76
+ const auth = await Auth.get("openrouter")
77
+ const config = await Config.get().catch(() => Config.getGlobal().catch(() => ({}) as any))
78
+
79
+ const providerOptions = config?.provider?.openrouter?.options ?? {}
80
+ const fromProviderOptions = typeof providerOptions.apiKey === "string" ? providerOptions.apiKey : undefined
81
+ const apiKey =
82
+ process.env.NIKCLI_OPENROUTER_API_KEY ??
83
+ process.env.OPENROUTER_API_KEY ??
84
+ (auth?.type === "api" ? auth.key : undefined) ??
85
+ fromProviderOptions
86
+
87
+ if (!apiKey || !apiKey.trim()) {
88
+ throw new Error(
89
+ [
90
+ "OpenRouter API key not found.",
91
+ "",
92
+ "Set NIKCLI_OPENROUTER_API_KEY (or OPENROUTER_API_KEY),",
93
+ "or run `nikcli auth login` and choose openrouter.",
94
+ ].join("\n"),
95
+ )
96
+ }
97
+
98
+ this.config = {
99
+ apiKey: apiKey.trim(),
100
+ baseURL:
101
+ process.env.NIKCLI_OPENROUTER_BASE_URL ??
102
+ (typeof providerOptions.baseURL === "string" ? providerOptions.baseURL : BASE_URL),
103
+ timeout: 30000,
104
+ }
105
+ return this.config
106
+ }
107
+
108
+ async getVoices(): Promise<TTSVoice[]> {
109
+ return OPENROUTER_VOICES
110
+ }
111
+
112
+ async getAudioModels(_options?: { refresh?: boolean }): Promise<TTSVoice[]> {
113
+ return [
114
+ { id: "openai/gpt-audio-mini", name: "GPT Audio Mini" },
115
+ { id: "openai/gpt-audio", name: "GPT Audio" },
116
+ { id: "openai/gpt-4o-audio-preview", name: "GPT-4o Audio Preview" },
117
+ ]
118
+ }
119
+
120
+ async speak(request: TTSRequest, options?: { signal?: AbortSignal }): Promise<TTSResponse> {
121
+ const config = await this.getConfig()
122
+ const modelId = request.modelId ?? DEFAULT_MODEL_ID
123
+ const voiceId = request.voiceId || "alloy"
124
+
125
+ const response = await fetch(`${config.baseURL}/chat/completions`, {
126
+ method: "POST",
127
+ headers: {
128
+ Authorization: `Bearer ${config.apiKey}`,
129
+ "Content-Type": "application/json",
130
+ "HTTP-Referer": "https://nikcli.store/",
131
+ "X-Title": "nikcli",
132
+ },
133
+ body: JSON.stringify({
134
+ model: modelId,
135
+ messages: [{ role: "user", content: request.text }],
136
+ modalities: ["text", "audio"],
137
+ audio: { voice: voiceId, format: "pcm16" },
138
+ stream: true,
139
+ }),
140
+ signal: options?.signal,
141
+ })
142
+
143
+ if (!response.ok) {
144
+ const errorText = await response.text().catch(() => "")
145
+ let errorDetail = errorText
146
+
147
+ try {
148
+ const parsed = JSON.parse(errorText) as OpenRouterErrorBody
149
+ errorDetail = parsed.error?.message ?? parsed.message ?? parsed.detail ?? errorText
150
+ } catch {
151
+ // keep raw text
152
+ }
153
+
154
+ switch (response.status) {
155
+ case 401:
156
+ throw new Error("OpenRouter authentication failed (401). Your API key may be invalid or expired.")
157
+ case 429:
158
+ throw new Error("OpenRouter rate limit exceeded (429). Too many requests.")
159
+ case 400:
160
+ throw new Error(`OpenRouter bad request (400): ${errorDetail}`)
161
+ default:
162
+ throw new Error(`OpenRouter error (${response.status}): ${errorDetail}`)
163
+ }
164
+ }
165
+
166
+ if (!response.body) throw new Error("OpenRouter: empty response body")
167
+
168
+ const reader = response.body.getReader()
169
+ const decoder = new TextDecoder()
170
+ let buffer = ""
171
+ const audioChunks: string[] = []
172
+
173
+ while (true) {
174
+ const { done, value } = await reader.read()
175
+ if (done) break
176
+ buffer += decoder.decode(value, { stream: true })
177
+
178
+ const lines = buffer.split("\n")
179
+ buffer = lines.pop() ?? ""
180
+
181
+ for (const line of lines) {
182
+ const trimmed = line.trim()
183
+ if (!trimmed.startsWith("data:")) continue
184
+ const data = trimmed.slice(5).trim()
185
+ if (data === "[DONE]") continue
186
+
187
+ try {
188
+ const chunk = JSON.parse(data) as OpenRouterStreamChunk
189
+ const audioData = chunk.choices?.[0]?.delta?.audio?.data
190
+ if (audioData) audioChunks.push(audioData)
191
+ } catch {
192
+ // skip malformed SSE chunks
193
+ }
194
+ }
195
+ }
196
+
197
+ const allB64 = audioChunks.join("")
198
+ if (!allB64) throw new Error("OpenRouter: no audio data in stream response")
199
+
200
+ const binary = atob(allB64)
201
+ const pcm = new Uint8Array(binary.length)
202
+ for (let i = 0; i < binary.length; i++) pcm[i] = binary.charCodeAt(i)
203
+
204
+ return {
205
+ audio: buildWavBuffer(pcm),
206
+ contentType: "audio/wav",
207
+ metadata: {
208
+ provider: this.id,
209
+ modelId,
210
+ voiceId,
211
+ },
212
+ }
213
+ }
214
+
215
+ async validate(): Promise<{ valid: boolean; error?: string }> {
216
+ try {
217
+ const config = await this.getConfig()
218
+ const response = await fetch(`${config.baseURL}/models`, {
219
+ headers: {
220
+ Authorization: `Bearer ${config.apiKey}`,
221
+ },
222
+ })
223
+
224
+ if (response.status === 401) {
225
+ return { valid: false, error: "Invalid API key" }
226
+ }
227
+
228
+ if (!response.ok) {
229
+ return { valid: false, error: `API returned status ${response.status}` }
230
+ }
231
+
232
+ return { valid: true }
233
+ } catch (error) {
234
+ return { valid: false, error: error instanceof Error ? error.message : "Unknown error" }
235
+ }
236
+ }
237
+ }
238
+
239
+ export const openRouterProvider = new OpenRouterProvider()
240
+ export const OPENROUTER_VOICES_LIST = OPENROUTER_VOICES
@@ -0,0 +1,83 @@
1
+ /**
2
+ * TTS Provider Abstraction
3
+ *
4
+ * This module defines the interface for Text-to-Speech providers.
5
+ * Multiple providers are supported (e.g., ElevenLabs, OpenRouter),
6
+ * and the architecture allows adding more providers over time.
7
+ */
8
+
9
+ export interface TTSVoice {
10
+ id: string
11
+ name: string
12
+ }
13
+
14
+ export interface TTSProviderConfig {
15
+ apiKey: string
16
+ baseURL?: string
17
+ timeout?: number
18
+ }
19
+
20
+ export interface TTSRequest {
21
+ text: string
22
+ voiceId: string
23
+ modelId?: string
24
+ outputFormat?: string
25
+ stability?: number
26
+ similarityBoost?: number
27
+ speed?: number
28
+ }
29
+
30
+ export interface TTSResponse {
31
+ audio: ArrayBuffer
32
+ contentType: string
33
+ metadata: {
34
+ provider: string
35
+ modelId: string
36
+ voiceId: string
37
+ duration?: number
38
+ }
39
+ }
40
+
41
+ export interface TTSProvider {
42
+ /** Unique identifier for this provider */
43
+ readonly id: string
44
+ /** Human-readable name */
45
+ readonly name: string
46
+ /** Brief description */
47
+ readonly description: string
48
+
49
+ /** List of available voices/models for this provider */
50
+ getVoices(): Promise<TTSVoice[]>
51
+
52
+ /** Convert text to speech */
53
+ speak(request: TTSRequest, options?: { signal?: AbortSignal }): Promise<TTSResponse>
54
+
55
+ /** Validate that the provider is properly configured */
56
+ validate(): Promise<{ valid: boolean; error?: string }>
57
+ }
58
+
59
+ /**
60
+ * Registry for TTS providers
61
+ */
62
+ export class TTSProviderRegistry {
63
+ private providers = new Map<string, TTSProvider>()
64
+
65
+ register(provider: TTSProvider): void {
66
+ this.providers.set(provider.id, provider)
67
+ }
68
+
69
+ get(id: string): TTSProvider | undefined {
70
+ return this.providers.get(id)
71
+ }
72
+
73
+ list(): TTSProvider[] {
74
+ return Array.from(this.providers.values())
75
+ }
76
+
77
+ has(id: string): boolean {
78
+ return this.providers.has(id)
79
+ }
80
+ }
81
+
82
+ // Global registry instance
83
+ export const ttsRegistry = new TTSProviderRegistry()