@shuyhere/takotako 0.0.1

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 (653) hide show
  1. package/CONTRIBUTING.md +84 -0
  2. package/LICENSE +21 -0
  3. package/README.md +171 -0
  4. package/dist/agents/communication.d.ts +48 -0
  5. package/dist/agents/communication.d.ts.map +1 -0
  6. package/dist/agents/communication.js +123 -0
  7. package/dist/agents/communication.js.map +1 -0
  8. package/dist/agents/config.d.ts +52 -0
  9. package/dist/agents/config.d.ts.map +1 -0
  10. package/dist/agents/config.js +65 -0
  11. package/dist/agents/config.js.map +1 -0
  12. package/dist/agents/model-catalog.d.ts +49 -0
  13. package/dist/agents/model-catalog.d.ts.map +1 -0
  14. package/dist/agents/model-catalog.js +79 -0
  15. package/dist/agents/model-catalog.js.map +1 -0
  16. package/dist/agents/registry.d.ts +71 -0
  17. package/dist/agents/registry.d.ts.map +1 -0
  18. package/dist/agents/registry.js +297 -0
  19. package/dist/agents/registry.js.map +1 -0
  20. package/dist/agents/roles.d.ts +79 -0
  21. package/dist/agents/roles.d.ts.map +1 -0
  22. package/dist/agents/roles.js +174 -0
  23. package/dist/agents/roles.js.map +1 -0
  24. package/dist/agents/subagent.d.ts +124 -0
  25. package/dist/agents/subagent.d.ts.map +1 -0
  26. package/dist/agents/subagent.js +352 -0
  27. package/dist/agents/subagent.js.map +1 -0
  28. package/dist/agents/templates.d.ts +18 -0
  29. package/dist/agents/templates.d.ts.map +1 -0
  30. package/dist/agents/templates.js +341 -0
  31. package/dist/agents/templates.js.map +1 -0
  32. package/dist/agents/thread-binding.d.ts +77 -0
  33. package/dist/agents/thread-binding.d.ts.map +1 -0
  34. package/dist/agents/thread-binding.js +167 -0
  35. package/dist/agents/thread-binding.js.map +1 -0
  36. package/dist/auth/agent-profiles.d.ts +46 -0
  37. package/dist/auth/agent-profiles.d.ts.map +1 -0
  38. package/dist/auth/agent-profiles.js +97 -0
  39. package/dist/auth/agent-profiles.js.map +1 -0
  40. package/dist/auth/allow-from.d.ts +27 -0
  41. package/dist/auth/allow-from.d.ts.map +1 -0
  42. package/dist/auth/allow-from.js +118 -0
  43. package/dist/auth/allow-from.js.map +1 -0
  44. package/dist/auth/oauth.d.ts +66 -0
  45. package/dist/auth/oauth.d.ts.map +1 -0
  46. package/dist/auth/oauth.js +253 -0
  47. package/dist/auth/oauth.js.map +1 -0
  48. package/dist/auth/storage.d.ts +69 -0
  49. package/dist/auth/storage.d.ts.map +1 -0
  50. package/dist/auth/storage.js +157 -0
  51. package/dist/auth/storage.js.map +1 -0
  52. package/dist/cache/file-cache.d.ts +68 -0
  53. package/dist/cache/file-cache.d.ts.map +1 -0
  54. package/dist/cache/file-cache.js +176 -0
  55. package/dist/cache/file-cache.js.map +1 -0
  56. package/dist/cache/manager.d.ts +69 -0
  57. package/dist/cache/manager.d.ts.map +1 -0
  58. package/dist/cache/manager.js +117 -0
  59. package/dist/cache/manager.js.map +1 -0
  60. package/dist/cache/symbol-index.d.ts +75 -0
  61. package/dist/cache/symbol-index.d.ts.map +1 -0
  62. package/dist/cache/symbol-index.js +267 -0
  63. package/dist/cache/symbol-index.js.map +1 -0
  64. package/dist/cache/tool-cache.d.ts +75 -0
  65. package/dist/cache/tool-cache.d.ts.map +1 -0
  66. package/dist/cache/tool-cache.js +173 -0
  67. package/dist/cache/tool-cache.js.map +1 -0
  68. package/dist/channels/channel.d.ts +156 -0
  69. package/dist/channels/channel.d.ts.map +1 -0
  70. package/dist/channels/channel.js +25 -0
  71. package/dist/channels/channel.js.map +1 -0
  72. package/dist/channels/cli.d.ts +35 -0
  73. package/dist/channels/cli.d.ts.map +1 -0
  74. package/dist/channels/cli.js +94 -0
  75. package/dist/channels/cli.js.map +1 -0
  76. package/dist/channels/delivery-queue.d.ts +31 -0
  77. package/dist/channels/delivery-queue.d.ts.map +1 -0
  78. package/dist/channels/delivery-queue.js +127 -0
  79. package/dist/channels/delivery-queue.js.map +1 -0
  80. package/dist/channels/discord.d.ts +124 -0
  81. package/dist/channels/discord.d.ts.map +1 -0
  82. package/dist/channels/discord.js +664 -0
  83. package/dist/channels/discord.js.map +1 -0
  84. package/dist/channels/retry.d.ts +31 -0
  85. package/dist/channels/retry.d.ts.map +1 -0
  86. package/dist/channels/retry.js +94 -0
  87. package/dist/channels/retry.js.map +1 -0
  88. package/dist/channels/telegram.d.ts +69 -0
  89. package/dist/channels/telegram.d.ts.map +1 -0
  90. package/dist/channels/telegram.js +499 -0
  91. package/dist/channels/telegram.js.map +1 -0
  92. package/dist/channels/tui.d.ts +42 -0
  93. package/dist/channels/tui.d.ts.map +1 -0
  94. package/dist/channels/tui.js +126 -0
  95. package/dist/channels/tui.js.map +1 -0
  96. package/dist/cli/acp.d.ts +10 -0
  97. package/dist/cli/acp.d.ts.map +1 -0
  98. package/dist/cli/acp.js +69 -0
  99. package/dist/cli/acp.js.map +1 -0
  100. package/dist/cli/audit.d.ts +11 -0
  101. package/dist/cli/audit.d.ts.map +1 -0
  102. package/dist/cli/audit.js +55 -0
  103. package/dist/cli/audit.js.map +1 -0
  104. package/dist/cli/cache.d.ts +10 -0
  105. package/dist/cli/cache.d.ts.map +1 -0
  106. package/dist/cli/cache.js +77 -0
  107. package/dist/cli/cache.js.map +1 -0
  108. package/dist/cli/config.d.ts +5 -0
  109. package/dist/cli/config.d.ts.map +1 -0
  110. package/dist/cli/config.js +168 -0
  111. package/dist/cli/config.js.map +1 -0
  112. package/dist/cli/cron.d.ts +5 -0
  113. package/dist/cli/cron.d.ts.map +1 -0
  114. package/dist/cli/cron.js +192 -0
  115. package/dist/cli/cron.js.map +1 -0
  116. package/dist/cli/extensions.d.ts +5 -0
  117. package/dist/cli/extensions.d.ts.map +1 -0
  118. package/dist/cli/extensions.js +53 -0
  119. package/dist/cli/extensions.js.map +1 -0
  120. package/dist/cli/logs.d.ts +5 -0
  121. package/dist/cli/logs.d.ts.map +1 -0
  122. package/dist/cli/logs.js +49 -0
  123. package/dist/cli/logs.js.map +1 -0
  124. package/dist/cli/memory.d.ts +5 -0
  125. package/dist/cli/memory.d.ts.map +1 -0
  126. package/dist/cli/memory.js +78 -0
  127. package/dist/cli/memory.js.map +1 -0
  128. package/dist/cli/message.d.ts +5 -0
  129. package/dist/cli/message.d.ts.map +1 -0
  130. package/dist/cli/message.js +69 -0
  131. package/dist/cli/message.js.map +1 -0
  132. package/dist/cli/service.d.ts +14 -0
  133. package/dist/cli/service.d.ts.map +1 -0
  134. package/dist/cli/service.js +181 -0
  135. package/dist/cli/service.js.map +1 -0
  136. package/dist/cli/symphony.d.ts +5 -0
  137. package/dist/cli/symphony.d.ts.map +1 -0
  138. package/dist/cli/symphony.js +114 -0
  139. package/dist/cli/symphony.js.map +1 -0
  140. package/dist/cli/update.d.ts +5 -0
  141. package/dist/cli/update.d.ts.map +1 -0
  142. package/dist/cli/update.js +48 -0
  143. package/dist/cli/update.js.map +1 -0
  144. package/dist/commands/channel-setup.d.ts +31 -0
  145. package/dist/commands/channel-setup.d.ts.map +1 -0
  146. package/dist/commands/channel-setup.js +138 -0
  147. package/dist/commands/channel-setup.js.map +1 -0
  148. package/dist/commands/dispatch.d.ts +48 -0
  149. package/dist/commands/dispatch.d.ts.map +1 -0
  150. package/dist/commands/dispatch.js +68 -0
  151. package/dist/commands/dispatch.js.map +1 -0
  152. package/dist/commands/model-picker.d.ts +16 -0
  153. package/dist/commands/model-picker.d.ts.map +1 -0
  154. package/dist/commands/model-picker.js +120 -0
  155. package/dist/commands/model-picker.js.map +1 -0
  156. package/dist/commands/parser.d.ts +32 -0
  157. package/dist/commands/parser.d.ts.map +1 -0
  158. package/dist/commands/parser.js +39 -0
  159. package/dist/commands/parser.js.map +1 -0
  160. package/dist/commands/registry.d.ts +76 -0
  161. package/dist/commands/registry.d.ts.map +1 -0
  162. package/dist/commands/registry.js +351 -0
  163. package/dist/commands/registry.js.map +1 -0
  164. package/dist/commands/skill-commands.d.ts +35 -0
  165. package/dist/commands/skill-commands.d.ts.map +1 -0
  166. package/dist/commands/skill-commands.js +61 -0
  167. package/dist/commands/skill-commands.js.map +1 -0
  168. package/dist/config/resolve.d.ts +25 -0
  169. package/dist/config/resolve.d.ts.map +1 -0
  170. package/dist/config/resolve.js +289 -0
  171. package/dist/config/resolve.js.map +1 -0
  172. package/dist/config/schema.d.ts +520 -0
  173. package/dist/config/schema.d.ts.map +1 -0
  174. package/dist/config/schema.js +123 -0
  175. package/dist/config/schema.js.map +1 -0
  176. package/dist/core/agent-loop.d.ts +137 -0
  177. package/dist/core/agent-loop.d.ts.map +1 -0
  178. package/dist/core/agent-loop.js +700 -0
  179. package/dist/core/agent-loop.js.map +1 -0
  180. package/dist/core/audit.d.ts +87 -0
  181. package/dist/core/audit.d.ts.map +1 -0
  182. package/dist/core/audit.js +224 -0
  183. package/dist/core/audit.js.map +1 -0
  184. package/dist/core/bootstrap.d.ts +23 -0
  185. package/dist/core/bootstrap.d.ts.map +1 -0
  186. package/dist/core/bootstrap.js +162 -0
  187. package/dist/core/bootstrap.js.map +1 -0
  188. package/dist/core/context.d.ts +44 -0
  189. package/dist/core/context.d.ts.map +1 -0
  190. package/dist/core/context.js +65 -0
  191. package/dist/core/context.js.map +1 -0
  192. package/dist/core/cron.d.ts +111 -0
  193. package/dist/core/cron.d.ts.map +1 -0
  194. package/dist/core/cron.js +284 -0
  195. package/dist/core/cron.js.map +1 -0
  196. package/dist/core/exec-approvals.d.ts +50 -0
  197. package/dist/core/exec-approvals.d.ts.map +1 -0
  198. package/dist/core/exec-approvals.js +187 -0
  199. package/dist/core/exec-approvals.js.map +1 -0
  200. package/dist/core/heartbeat.d.ts +71 -0
  201. package/dist/core/heartbeat.d.ts.map +1 -0
  202. package/dist/core/heartbeat.js +214 -0
  203. package/dist/core/heartbeat.js.map +1 -0
  204. package/dist/core/message-queue.d.ts +60 -0
  205. package/dist/core/message-queue.d.ts.map +1 -0
  206. package/dist/core/message-queue.js +182 -0
  207. package/dist/core/message-queue.js.map +1 -0
  208. package/dist/core/network-policy.d.ts +39 -0
  209. package/dist/core/network-policy.d.ts.map +1 -0
  210. package/dist/core/network-policy.js +121 -0
  211. package/dist/core/network-policy.js.map +1 -0
  212. package/dist/core/progress.d.ts +48 -0
  213. package/dist/core/progress.d.ts.map +1 -0
  214. package/dist/core/progress.js +81 -0
  215. package/dist/core/progress.js.map +1 -0
  216. package/dist/core/prompt.d.ts +105 -0
  217. package/dist/core/prompt.d.ts.map +1 -0
  218. package/dist/core/prompt.js +411 -0
  219. package/dist/core/prompt.js.map +1 -0
  220. package/dist/core/pruning.d.ts +40 -0
  221. package/dist/core/pruning.d.ts.map +1 -0
  222. package/dist/core/pruning.js +165 -0
  223. package/dist/core/pruning.js.map +1 -0
  224. package/dist/core/rate-limiter.d.ts +64 -0
  225. package/dist/core/rate-limiter.d.ts.map +1 -0
  226. package/dist/core/rate-limiter.js +142 -0
  227. package/dist/core/rate-limiter.js.map +1 -0
  228. package/dist/core/reactions.d.ts +31 -0
  229. package/dist/core/reactions.d.ts.map +1 -0
  230. package/dist/core/reactions.js +67 -0
  231. package/dist/core/reactions.js.map +1 -0
  232. package/dist/core/retry-queue.d.ts +56 -0
  233. package/dist/core/retry-queue.d.ts.map +1 -0
  234. package/dist/core/retry-queue.js +106 -0
  235. package/dist/core/retry-queue.js.map +1 -0
  236. package/dist/core/sanitizer.d.ts +38 -0
  237. package/dist/core/sanitizer.d.ts.map +1 -0
  238. package/dist/core/sanitizer.js +181 -0
  239. package/dist/core/sanitizer.js.map +1 -0
  240. package/dist/core/secret-scanner.d.ts +39 -0
  241. package/dist/core/secret-scanner.d.ts.map +1 -0
  242. package/dist/core/secret-scanner.js +96 -0
  243. package/dist/core/secret-scanner.js.map +1 -0
  244. package/dist/core/secrets.d.ts +38 -0
  245. package/dist/core/secrets.d.ts.map +1 -0
  246. package/dist/core/secrets.js +137 -0
  247. package/dist/core/secrets.js.map +1 -0
  248. package/dist/core/security.d.ts +58 -0
  249. package/dist/core/security.d.ts.map +1 -0
  250. package/dist/core/security.js +120 -0
  251. package/dist/core/security.js.map +1 -0
  252. package/dist/core/self-awareness.d.ts +19 -0
  253. package/dist/core/self-awareness.d.ts.map +1 -0
  254. package/dist/core/self-awareness.js +124 -0
  255. package/dist/core/self-awareness.js.map +1 -0
  256. package/dist/core/session-init.d.ts +34 -0
  257. package/dist/core/session-init.d.ts.map +1 -0
  258. package/dist/core/session-init.js +68 -0
  259. package/dist/core/session-init.js.map +1 -0
  260. package/dist/core/streaming.d.ts +82 -0
  261. package/dist/core/streaming.d.ts.map +1 -0
  262. package/dist/core/streaming.js +264 -0
  263. package/dist/core/streaming.js.map +1 -0
  264. package/dist/core/symphony/orchestrator.d.ts +61 -0
  265. package/dist/core/symphony/orchestrator.d.ts.map +1 -0
  266. package/dist/core/symphony/orchestrator.js +476 -0
  267. package/dist/core/symphony/orchestrator.js.map +1 -0
  268. package/dist/core/symphony/status.d.ts +11 -0
  269. package/dist/core/symphony/status.d.ts.map +1 -0
  270. package/dist/core/symphony/status.js +133 -0
  271. package/dist/core/symphony/status.js.map +1 -0
  272. package/dist/core/symphony/types.d.ts +84 -0
  273. package/dist/core/symphony/types.d.ts.map +1 -0
  274. package/dist/core/symphony/types.js +5 -0
  275. package/dist/core/symphony/types.js.map +1 -0
  276. package/dist/core/symphony/workflow.d.ts +18 -0
  277. package/dist/core/symphony/workflow.d.ts.map +1 -0
  278. package/dist/core/symphony/workflow.js +149 -0
  279. package/dist/core/symphony/workflow.js.map +1 -0
  280. package/dist/core/symphony/workspace.d.ts +24 -0
  281. package/dist/core/symphony/workspace.d.ts.map +1 -0
  282. package/dist/core/symphony/workspace.js +94 -0
  283. package/dist/core/symphony/workspace.js.map +1 -0
  284. package/dist/core/thinking.d.ts +27 -0
  285. package/dist/core/thinking.d.ts.map +1 -0
  286. package/dist/core/thinking.js +83 -0
  287. package/dist/core/thinking.js.map +1 -0
  288. package/dist/core/thread-bindings.d.ts +47 -0
  289. package/dist/core/thread-bindings.d.ts.map +1 -0
  290. package/dist/core/thread-bindings.js +94 -0
  291. package/dist/core/thread-bindings.js.map +1 -0
  292. package/dist/core/timezone.d.ts +28 -0
  293. package/dist/core/timezone.d.ts.map +1 -0
  294. package/dist/core/timezone.js +72 -0
  295. package/dist/core/timezone.js.map +1 -0
  296. package/dist/core/tool-loop-detector.d.ts +41 -0
  297. package/dist/core/tool-loop-detector.d.ts.map +1 -0
  298. package/dist/core/tool-loop-detector.js +83 -0
  299. package/dist/core/tool-loop-detector.js.map +1 -0
  300. package/dist/core/tool-validator.d.ts +44 -0
  301. package/dist/core/tool-validator.d.ts.map +1 -0
  302. package/dist/core/tool-validator.js +175 -0
  303. package/dist/core/tool-validator.js.map +1 -0
  304. package/dist/core/typing.d.ts +25 -0
  305. package/dist/core/typing.d.ts.map +1 -0
  306. package/dist/core/typing.js +48 -0
  307. package/dist/core/typing.js.map +1 -0
  308. package/dist/core/usage-tracker.d.ts +66 -0
  309. package/dist/core/usage-tracker.d.ts.map +1 -0
  310. package/dist/core/usage-tracker.js +163 -0
  311. package/dist/core/usage-tracker.js.map +1 -0
  312. package/dist/daemon/commands.d.ts +16 -0
  313. package/dist/daemon/commands.d.ts.map +1 -0
  314. package/dist/daemon/commands.js +445 -0
  315. package/dist/daemon/commands.js.map +1 -0
  316. package/dist/daemon/pid.d.ts +30 -0
  317. package/dist/daemon/pid.d.ts.map +1 -0
  318. package/dist/daemon/pid.js +62 -0
  319. package/dist/daemon/pid.js.map +1 -0
  320. package/dist/doctor/checks/browser.d.ts +9 -0
  321. package/dist/doctor/checks/browser.d.ts.map +1 -0
  322. package/dist/doctor/checks/browser.js +54 -0
  323. package/dist/doctor/checks/browser.js.map +1 -0
  324. package/dist/doctor/checks/channels.d.ts +9 -0
  325. package/dist/doctor/checks/channels.d.ts.map +1 -0
  326. package/dist/doctor/checks/channels.js +90 -0
  327. package/dist/doctor/checks/channels.js.map +1 -0
  328. package/dist/doctor/checks/config.d.ts +10 -0
  329. package/dist/doctor/checks/config.d.ts.map +1 -0
  330. package/dist/doctor/checks/config.js +89 -0
  331. package/dist/doctor/checks/config.js.map +1 -0
  332. package/dist/doctor/checks/memory.d.ts +10 -0
  333. package/dist/doctor/checks/memory.d.ts.map +1 -0
  334. package/dist/doctor/checks/memory.js +82 -0
  335. package/dist/doctor/checks/memory.js.map +1 -0
  336. package/dist/doctor/checks/permissions.d.ts +9 -0
  337. package/dist/doctor/checks/permissions.d.ts.map +1 -0
  338. package/dist/doctor/checks/permissions.js +53 -0
  339. package/dist/doctor/checks/permissions.js.map +1 -0
  340. package/dist/doctor/checks/providers.d.ts +10 -0
  341. package/dist/doctor/checks/providers.d.ts.map +1 -0
  342. package/dist/doctor/checks/providers.js +93 -0
  343. package/dist/doctor/checks/providers.js.map +1 -0
  344. package/dist/doctor/checks/sessions.d.ts +10 -0
  345. package/dist/doctor/checks/sessions.d.ts.map +1 -0
  346. package/dist/doctor/checks/sessions.js +86 -0
  347. package/dist/doctor/checks/sessions.js.map +1 -0
  348. package/dist/doctor/doctor.d.ts +35 -0
  349. package/dist/doctor/doctor.d.ts.map +1 -0
  350. package/dist/doctor/doctor.js +51 -0
  351. package/dist/doctor/doctor.js.map +1 -0
  352. package/dist/doctor/repairs.d.ts +14 -0
  353. package/dist/doctor/repairs.d.ts.map +1 -0
  354. package/dist/doctor/repairs.js +34 -0
  355. package/dist/doctor/repairs.js.map +1 -0
  356. package/dist/gateway/compaction.d.ts +63 -0
  357. package/dist/gateway/compaction.d.ts.map +1 -0
  358. package/dist/gateway/compaction.js +235 -0
  359. package/dist/gateway/compaction.js.map +1 -0
  360. package/dist/gateway/gateway.d.ts +94 -0
  361. package/dist/gateway/gateway.d.ts.map +1 -0
  362. package/dist/gateway/gateway.js +466 -0
  363. package/dist/gateway/gateway.js.map +1 -0
  364. package/dist/gateway/lock.d.ts +24 -0
  365. package/dist/gateway/lock.d.ts.map +1 -0
  366. package/dist/gateway/lock.js +88 -0
  367. package/dist/gateway/lock.js.map +1 -0
  368. package/dist/gateway/protocol.d.ts +117 -0
  369. package/dist/gateway/protocol.d.ts.map +1 -0
  370. package/dist/gateway/protocol.js +5 -0
  371. package/dist/gateway/protocol.js.map +1 -0
  372. package/dist/gateway/session.d.ts +123 -0
  373. package/dist/gateway/session.d.ts.map +1 -0
  374. package/dist/gateway/session.js +573 -0
  375. package/dist/gateway/session.js.map +1 -0
  376. package/dist/hooks/hooks.d.ts +18 -0
  377. package/dist/hooks/hooks.d.ts.map +1 -0
  378. package/dist/hooks/hooks.js +45 -0
  379. package/dist/hooks/hooks.js.map +1 -0
  380. package/dist/hooks/types.d.ts +112 -0
  381. package/dist/hooks/types.d.ts.map +1 -0
  382. package/dist/hooks/types.js +23 -0
  383. package/dist/hooks/types.js.map +1 -0
  384. package/dist/index.d.ts +27 -0
  385. package/dist/index.d.ts.map +1 -0
  386. package/dist/index.js +2900 -0
  387. package/dist/index.js.map +1 -0
  388. package/dist/media/storage.d.ts +25 -0
  389. package/dist/media/storage.d.ts.map +1 -0
  390. package/dist/media/storage.js +97 -0
  391. package/dist/media/storage.js.map +1 -0
  392. package/dist/memory/embeddings.d.ts +46 -0
  393. package/dist/memory/embeddings.d.ts.map +1 -0
  394. package/dist/memory/embeddings.js +118 -0
  395. package/dist/memory/embeddings.js.map +1 -0
  396. package/dist/memory/hybrid.d.ts +35 -0
  397. package/dist/memory/hybrid.d.ts.map +1 -0
  398. package/dist/memory/hybrid.js +156 -0
  399. package/dist/memory/hybrid.js.map +1 -0
  400. package/dist/memory/markdown.d.ts +48 -0
  401. package/dist/memory/markdown.d.ts.map +1 -0
  402. package/dist/memory/markdown.js +228 -0
  403. package/dist/memory/markdown.js.map +1 -0
  404. package/dist/memory/store.d.ts +88 -0
  405. package/dist/memory/store.d.ts.map +1 -0
  406. package/dist/memory/store.js +21 -0
  407. package/dist/memory/store.js.map +1 -0
  408. package/dist/memory/vector.d.ts +24 -0
  409. package/dist/memory/vector.d.ts.map +1 -0
  410. package/dist/memory/vector.js +63 -0
  411. package/dist/memory/vector.js.map +1 -0
  412. package/dist/mods/mod.d.ts +100 -0
  413. package/dist/mods/mod.d.ts.map +1 -0
  414. package/dist/mods/mod.js +242 -0
  415. package/dist/mods/mod.js.map +1 -0
  416. package/dist/onboard/channels.d.ts +12 -0
  417. package/dist/onboard/channels.d.ts.map +1 -0
  418. package/dist/onboard/channels.js +283 -0
  419. package/dist/onboard/channels.js.map +1 -0
  420. package/dist/onboard/models.d.ts +13 -0
  421. package/dist/onboard/models.d.ts.map +1 -0
  422. package/dist/onboard/models.js +491 -0
  423. package/dist/onboard/models.js.map +1 -0
  424. package/dist/onboard/onboard.d.ts +12 -0
  425. package/dist/onboard/onboard.d.ts.map +1 -0
  426. package/dist/onboard/onboard.js +1137 -0
  427. package/dist/onboard/onboard.js.map +1 -0
  428. package/dist/providers/anthropic.d.ts +83 -0
  429. package/dist/providers/anthropic.d.ts.map +1 -0
  430. package/dist/providers/anthropic.js +583 -0
  431. package/dist/providers/anthropic.js.map +1 -0
  432. package/dist/providers/failover.d.ts +46 -0
  433. package/dist/providers/failover.d.ts.map +1 -0
  434. package/dist/providers/failover.js +149 -0
  435. package/dist/providers/failover.js.map +1 -0
  436. package/dist/providers/litellm.d.ts +38 -0
  437. package/dist/providers/litellm.d.ts.map +1 -0
  438. package/dist/providers/litellm.js +349 -0
  439. package/dist/providers/litellm.js.map +1 -0
  440. package/dist/providers/openai.d.ts +28 -0
  441. package/dist/providers/openai.d.ts.map +1 -0
  442. package/dist/providers/openai.js +321 -0
  443. package/dist/providers/openai.js.map +1 -0
  444. package/dist/providers/prompt-cache.d.ts +50 -0
  445. package/dist/providers/prompt-cache.d.ts.map +1 -0
  446. package/dist/providers/prompt-cache.js +96 -0
  447. package/dist/providers/prompt-cache.js.map +1 -0
  448. package/dist/providers/provider.d.ts +173 -0
  449. package/dist/providers/provider.d.ts.map +1 -0
  450. package/dist/providers/provider.js +22 -0
  451. package/dist/providers/provider.js.map +1 -0
  452. package/dist/sandbox/config.d.ts +42 -0
  453. package/dist/sandbox/config.d.ts.map +1 -0
  454. package/dist/sandbox/config.js +20 -0
  455. package/dist/sandbox/config.js.map +1 -0
  456. package/dist/sandbox/container.d.ts +71 -0
  457. package/dist/sandbox/container.d.ts.map +1 -0
  458. package/dist/sandbox/container.js +193 -0
  459. package/dist/sandbox/container.js.map +1 -0
  460. package/dist/sandbox/sandbox.d.ts +82 -0
  461. package/dist/sandbox/sandbox.d.ts.map +1 -0
  462. package/dist/sandbox/sandbox.js +176 -0
  463. package/dist/sandbox/sandbox.js.map +1 -0
  464. package/dist/skills/channel-loader.d.ts +18 -0
  465. package/dist/skills/channel-loader.d.ts.map +1 -0
  466. package/dist/skills/channel-loader.js +35 -0
  467. package/dist/skills/channel-loader.js.map +1 -0
  468. package/dist/skills/extension-loader.d.ts +15 -0
  469. package/dist/skills/extension-loader.d.ts.map +1 -0
  470. package/dist/skills/extension-loader.js +63 -0
  471. package/dist/skills/extension-loader.js.map +1 -0
  472. package/dist/skills/extension-registry.d.ts +32 -0
  473. package/dist/skills/extension-registry.d.ts.map +1 -0
  474. package/dist/skills/extension-registry.js +57 -0
  475. package/dist/skills/extension-registry.js.map +1 -0
  476. package/dist/skills/extensions.d.ts +91 -0
  477. package/dist/skills/extensions.d.ts.map +1 -0
  478. package/dist/skills/extensions.js +14 -0
  479. package/dist/skills/extensions.js.map +1 -0
  480. package/dist/skills/loader.d.ts +64 -0
  481. package/dist/skills/loader.d.ts.map +1 -0
  482. package/dist/skills/loader.js +382 -0
  483. package/dist/skills/loader.js.map +1 -0
  484. package/dist/skills/marketplace.d.ts +56 -0
  485. package/dist/skills/marketplace.d.ts.map +1 -0
  486. package/dist/skills/marketplace.js +183 -0
  487. package/dist/skills/marketplace.js.map +1 -0
  488. package/dist/skills/types.d.ts +94 -0
  489. package/dist/skills/types.d.ts.map +1 -0
  490. package/dist/skills/types.js +9 -0
  491. package/dist/skills/types.js.map +1 -0
  492. package/dist/tools/acp-sessions.d.ts +89 -0
  493. package/dist/tools/acp-sessions.d.ts.map +1 -0
  494. package/dist/tools/acp-sessions.js +391 -0
  495. package/dist/tools/acp-sessions.js.map +1 -0
  496. package/dist/tools/acp.d.ts +18 -0
  497. package/dist/tools/acp.d.ts.map +1 -0
  498. package/dist/tools/acp.js +102 -0
  499. package/dist/tools/acp.js.map +1 -0
  500. package/dist/tools/agent-tools.d.ts +24 -0
  501. package/dist/tools/agent-tools.d.ts.map +1 -0
  502. package/dist/tools/agent-tools.js +611 -0
  503. package/dist/tools/agent-tools.js.map +1 -0
  504. package/dist/tools/browser.d.ts +26 -0
  505. package/dist/tools/browser.d.ts.map +1 -0
  506. package/dist/tools/browser.js +242 -0
  507. package/dist/tools/browser.js.map +1 -0
  508. package/dist/tools/comms.d.ts +8 -0
  509. package/dist/tools/comms.d.ts.map +1 -0
  510. package/dist/tools/comms.js +39 -0
  511. package/dist/tools/comms.js.map +1 -0
  512. package/dist/tools/cron-tools.d.ts +9 -0
  513. package/dist/tools/cron-tools.d.ts.map +1 -0
  514. package/dist/tools/cron-tools.js +117 -0
  515. package/dist/tools/cron-tools.js.map +1 -0
  516. package/dist/tools/exec-safety.d.ts +71 -0
  517. package/dist/tools/exec-safety.d.ts.map +1 -0
  518. package/dist/tools/exec-safety.js +141 -0
  519. package/dist/tools/exec-safety.js.map +1 -0
  520. package/dist/tools/exec.d.ts +24 -0
  521. package/dist/tools/exec.d.ts.map +1 -0
  522. package/dist/tools/exec.js +191 -0
  523. package/dist/tools/exec.js.map +1 -0
  524. package/dist/tools/fs.d.ts +15 -0
  525. package/dist/tools/fs.d.ts.map +1 -0
  526. package/dist/tools/fs.js +249 -0
  527. package/dist/tools/fs.js.map +1 -0
  528. package/dist/tools/git.d.ts +9 -0
  529. package/dist/tools/git.d.ts.map +1 -0
  530. package/dist/tools/git.js +56 -0
  531. package/dist/tools/git.js.map +1 -0
  532. package/dist/tools/image.d.ts +15 -0
  533. package/dist/tools/image.d.ts.map +1 -0
  534. package/dist/tools/image.js +106 -0
  535. package/dist/tools/image.js.map +1 -0
  536. package/dist/tools/introspect.d.ts +22 -0
  537. package/dist/tools/introspect.d.ts.map +1 -0
  538. package/dist/tools/introspect.js +223 -0
  539. package/dist/tools/introspect.js.map +1 -0
  540. package/dist/tools/memory.d.ts +11 -0
  541. package/dist/tools/memory.d.ts.map +1 -0
  542. package/dist/tools/memory.js +101 -0
  543. package/dist/tools/memory.js.map +1 -0
  544. package/dist/tools/message.d.ts +24 -0
  545. package/dist/tools/message.d.ts.map +1 -0
  546. package/dist/tools/message.js +205 -0
  547. package/dist/tools/message.js.map +1 -0
  548. package/dist/tools/model.d.ts +14 -0
  549. package/dist/tools/model.d.ts.map +1 -0
  550. package/dist/tools/model.js +62 -0
  551. package/dist/tools/model.js.map +1 -0
  552. package/dist/tools/policy.d.ts +101 -0
  553. package/dist/tools/policy.d.ts.map +1 -0
  554. package/dist/tools/policy.js +168 -0
  555. package/dist/tools/policy.js.map +1 -0
  556. package/dist/tools/registry.d.ts +52 -0
  557. package/dist/tools/registry.d.ts.map +1 -0
  558. package/dist/tools/registry.js +154 -0
  559. package/dist/tools/registry.js.map +1 -0
  560. package/dist/tools/search.d.ts +10 -0
  561. package/dist/tools/search.d.ts.map +1 -0
  562. package/dist/tools/search.js +78 -0
  563. package/dist/tools/search.js.map +1 -0
  564. package/dist/tools/session.d.ts +13 -0
  565. package/dist/tools/session.d.ts.map +1 -0
  566. package/dist/tools/session.js +142 -0
  567. package/dist/tools/session.js.map +1 -0
  568. package/dist/tools/spawn.d.ts +10 -0
  569. package/dist/tools/spawn.d.ts.map +1 -0
  570. package/dist/tools/spawn.js +72 -0
  571. package/dist/tools/spawn.js.map +1 -0
  572. package/dist/tools/symphony.d.ts +12 -0
  573. package/dist/tools/symphony.d.ts.map +1 -0
  574. package/dist/tools/symphony.js +142 -0
  575. package/dist/tools/symphony.js.map +1 -0
  576. package/dist/tools/system-tools.d.ts +11 -0
  577. package/dist/tools/system-tools.d.ts.map +1 -0
  578. package/dist/tools/system-tools.js +39 -0
  579. package/dist/tools/system-tools.js.map +1 -0
  580. package/dist/tools/tool.d.ts +119 -0
  581. package/dist/tools/tool.d.ts.map +1 -0
  582. package/dist/tools/tool.js +29 -0
  583. package/dist/tools/tool.js.map +1 -0
  584. package/dist/tools/web.d.ts +10 -0
  585. package/dist/tools/web.d.ts.map +1 -0
  586. package/dist/tools/web.js +105 -0
  587. package/dist/tools/web.js.map +1 -0
  588. package/dist/tui/App.d.ts +43 -0
  589. package/dist/tui/App.d.ts.map +1 -0
  590. package/dist/tui/App.js +265 -0
  591. package/dist/tui/App.js.map +1 -0
  592. package/dist/tui/bridge.d.ts +40 -0
  593. package/dist/tui/bridge.d.ts.map +1 -0
  594. package/dist/tui/bridge.js +29 -0
  595. package/dist/tui/bridge.js.map +1 -0
  596. package/dist/tui/components/Header.d.ts +14 -0
  597. package/dist/tui/components/Header.d.ts.map +1 -0
  598. package/dist/tui/components/Header.js +7 -0
  599. package/dist/tui/components/Header.js.map +1 -0
  600. package/dist/tui/components/InputBar.d.ts +10 -0
  601. package/dist/tui/components/InputBar.d.ts.map +1 -0
  602. package/dist/tui/components/InputBar.js +121 -0
  603. package/dist/tui/components/InputBar.js.map +1 -0
  604. package/dist/tui/components/MessageList.d.ts +18 -0
  605. package/dist/tui/components/MessageList.d.ts.map +1 -0
  606. package/dist/tui/components/MessageList.js +34 -0
  607. package/dist/tui/components/MessageList.js.map +1 -0
  608. package/dist/tui/components/Spinner.d.ts +9 -0
  609. package/dist/tui/components/Spinner.d.ts.map +1 -0
  610. package/dist/tui/components/Spinner.js +18 -0
  611. package/dist/tui/components/Spinner.js.map +1 -0
  612. package/dist/tui/components/StatusBar.d.ts +16 -0
  613. package/dist/tui/components/StatusBar.d.ts.map +1 -0
  614. package/dist/tui/components/StatusBar.js +15 -0
  615. package/dist/tui/components/StatusBar.js.map +1 -0
  616. package/dist/tui/components/ToolCallBox.d.ts +12 -0
  617. package/dist/tui/components/ToolCallBox.d.ts.map +1 -0
  618. package/dist/tui/components/ToolCallBox.js +12 -0
  619. package/dist/tui/components/ToolCallBox.js.map +1 -0
  620. package/dist/tui/theme.d.ts +58 -0
  621. package/dist/tui/theme.d.ts.map +1 -0
  622. package/dist/tui/theme.js +80 -0
  623. package/dist/tui/theme.js.map +1 -0
  624. package/dist/utils/logger.d.ts +16 -0
  625. package/dist/utils/logger.d.ts.map +1 -0
  626. package/dist/utils/logger.js +70 -0
  627. package/dist/utils/logger.js.map +1 -0
  628. package/docs/DEVELOPMENT.md +74 -0
  629. package/docs/INSTALL.md +161 -0
  630. package/docs/USAGE.md +94 -0
  631. package/docs/architecture.md +128 -0
  632. package/docs/channels.md +140 -0
  633. package/docs/configuration.md +209 -0
  634. package/docs/io-system.md +430 -0
  635. package/docs/providers.md +99 -0
  636. package/docs/skill-channels.md +113 -0
  637. package/docs/skills.md +246 -0
  638. package/package.json +89 -0
  639. package/skills/acp-router/SKILL.md +41 -0
  640. package/skills/acp-router/tools/acp-router.mjs +239 -0
  641. package/skills/find-skills/SKILL.md +133 -0
  642. package/skills/security-audit/SKILL.md +181 -0
  643. package/skills/security-audit/audit.sh +67 -0
  644. package/skills/skill-creator/SKILL.md +479 -0
  645. package/skills/skill-security-audit/.clawhub/origin.json +7 -0
  646. package/skills/skill-security-audit/SKILL.md +196 -0
  647. package/skills/skill-security-audit/_meta.json +6 -0
  648. package/skills/skill-security-audit/references/prompt-injection-patterns.md +276 -0
  649. package/skills/skill-security-audit/references/vulnerability-patterns.md +348 -0
  650. package/skills/symphony/README.md +53 -0
  651. package/skills/symphony/SKILL.md +75 -0
  652. package/skills/symphony/tools/symphony-orchestrator.ts +8 -0
  653. package/tako.example.json +33 -0
@@ -0,0 +1,1137 @@
1
+ /**
2
+ * Tako 🐙 Interactive Onboarding Wizard
3
+ *
4
+ * Multi-provider setup with fallback chain and conversational identity builder:
5
+ * 1. Provider dashboard — configure multiple providers
6
+ * 2. Fallback model chain — up to 4 models
7
+ * 3. Identity builder — conversational SOUL/IDENTITY/USER generation
8
+ * 4. Channel setup — Discord / Telegram (integrated)
9
+ * 5. Write config + workspace files
10
+ */
11
+ import * as p from '@clack/prompts';
12
+ import { homedir } from 'node:os';
13
+ import { join } from 'node:path';
14
+ import { mkdir, writeFile, readFile } from 'node:fs/promises';
15
+ import { existsSync } from 'node:fs';
16
+ import { DEFAULT_CONFIG } from '../config/schema.js';
17
+ import { writeAuthCredential, getAuthStatus } from '../auth/storage.js';
18
+ import { validateAnthropicSetupToken, runOAuthFlow, OAUTH_PROVIDERS } from '../auth/oauth.js';
19
+ import { LiteLLMProvider } from '../providers/litellm.js';
20
+ const PROVIDERS = [
21
+ {
22
+ id: 'anthropic',
23
+ label: 'Anthropic (Claude)',
24
+ hint: 'API key or setup-token',
25
+ envVar: 'ANTHROPIC_API_KEY',
26
+ authMethods: [
27
+ { value: 'api_key', label: 'API Key', hint: 'paste ANTHROPIC_API_KEY' },
28
+ { value: 'setup_token', label: 'Setup Token', hint: 'from `claude setup-token`' },
29
+ ],
30
+ models: [
31
+ // Fallback models if API fetch fails
32
+ { value: 'anthropic/claude-sonnet-4-6', label: 'claude-sonnet-4-6', hint: 'fast, recommended' },
33
+ { value: 'anthropic/claude-opus-4-6', label: 'claude-opus-4-6', hint: 'powerful, slower' },
34
+ { value: 'anthropic/claude-haiku-4-5', label: 'claude-haiku-4-5', hint: 'fastest, cheapest' },
35
+ ],
36
+ verify: async (apiKey) => {
37
+ const extractError = (body) => {
38
+ if (!body || typeof body !== 'object')
39
+ return 'unknown error';
40
+ const b = body;
41
+ const e = b.error;
42
+ if (typeof e === 'string')
43
+ return e;
44
+ if (e && typeof e === 'object') {
45
+ const m = e.message;
46
+ if (typeof m === 'string')
47
+ return m;
48
+ return JSON.stringify(e);
49
+ }
50
+ if (typeof b.message === 'string')
51
+ return b.message;
52
+ return 'unknown error';
53
+ };
54
+ try {
55
+ const headers = {
56
+ 'anthropic-version': '2023-06-01',
57
+ };
58
+ // Detect OAuth token vs API key
59
+ if (apiKey.includes('sk-ant-oat')) {
60
+ headers['authorization'] = `Bearer ${apiKey}`;
61
+ headers['anthropic-beta'] = 'claude-code-20250219,oauth-2025-04-20';
62
+ }
63
+ else {
64
+ headers['x-api-key'] = apiKey;
65
+ }
66
+ // reference runtime-style: verify key with /v1/models first (not model-dependent)
67
+ const modelsRes = await fetch('https://api.anthropic.com/v1/models', { headers });
68
+ if (modelsRes.ok)
69
+ return { ok: true };
70
+ if (modelsRes.status === 401 || modelsRes.status === 403) {
71
+ return { ok: false, error: 'Invalid API key' };
72
+ }
73
+ // Fallback probe: /v1/messages to differentiate auth vs payload issues
74
+ const msgRes = await fetch('https://api.anthropic.com/v1/messages', {
75
+ method: 'POST',
76
+ headers: { ...headers, 'content-type': 'application/json' },
77
+ body: JSON.stringify({
78
+ model: 'claude-sonnet-4-6',
79
+ max_tokens: 1,
80
+ messages: [{ role: 'user', content: 'hi' }],
81
+ }),
82
+ });
83
+ if (msgRes.ok)
84
+ return { ok: true };
85
+ if (msgRes.status === 401 || msgRes.status === 403) {
86
+ return { ok: false, error: 'Invalid API key' };
87
+ }
88
+ if (msgRes.status === 400) {
89
+ // Auth is valid; request payload/model may be wrong
90
+ return { ok: true };
91
+ }
92
+ const body = await msgRes.json().catch(() => ({}));
93
+ return { ok: false, error: `API returned ${msgRes.status}: ${extractError(body)}` };
94
+ }
95
+ catch (err) {
96
+ return { ok: false, error: `Connection failed: ${err.message}` };
97
+ }
98
+ },
99
+ fetchModels: async (apiKey) => {
100
+ try {
101
+ const headers = { 'anthropic-version': '2023-06-01' };
102
+ if (apiKey.includes('sk-ant-oat')) {
103
+ headers['authorization'] = `Bearer ${apiKey}`;
104
+ headers['anthropic-beta'] = 'claude-code-20250219,oauth-2025-04-20';
105
+ }
106
+ else {
107
+ headers['x-api-key'] = apiKey;
108
+ }
109
+ const res = await fetch('https://api.anthropic.com/v1/models', { headers });
110
+ if (!res.ok)
111
+ return [];
112
+ const data = await res.json();
113
+ return (data.data ?? []).map((m) => m.id).filter((id) => id.includes('claude'));
114
+ }
115
+ catch {
116
+ return [];
117
+ }
118
+ },
119
+ },
120
+ {
121
+ id: 'openai',
122
+ label: 'OpenAI (GPT)',
123
+ hint: 'API key or OAuth',
124
+ envVar: 'OPENAI_API_KEY',
125
+ authMethods: [
126
+ { value: 'api_key', label: 'API Key', hint: 'paste OPENAI_API_KEY' },
127
+ { value: 'oauth', label: 'OAuth (Codex)', hint: 'browser login to ChatGPT' },
128
+ ],
129
+ models: [
130
+ // Fallback models if API fetch fails
131
+ { value: 'openai/gpt-5.2', label: 'gpt-5.2', hint: 'latest' },
132
+ { value: 'openai/gpt-5-mini', label: 'gpt-5-mini', hint: 'fast' },
133
+ { value: 'openai-codex/gpt-5.3-codex', label: 'gpt-5.3-codex', hint: 'Codex OAuth, most powerful' },
134
+ { value: 'openai-codex/gpt-5.2-codex', label: 'gpt-5.2-codex', hint: 'Codex OAuth' },
135
+ ],
136
+ verify: async (apiKey) => {
137
+ try {
138
+ const res = await fetch('https://api.openai.com/v1/models', {
139
+ headers: { Authorization: `Bearer ${apiKey}` },
140
+ });
141
+ if (res.ok)
142
+ return { ok: true };
143
+ if (res.status === 401)
144
+ return { ok: false, error: 'Invalid API key' };
145
+ return { ok: false, error: `API returned ${res.status}` };
146
+ }
147
+ catch (err) {
148
+ return { ok: false, error: `Connection failed: ${err.message}` };
149
+ }
150
+ },
151
+ fetchModels: async (apiKey) => {
152
+ try {
153
+ const res = await fetch('https://api.openai.com/v1/models', {
154
+ headers: { Authorization: `Bearer ${apiKey}` },
155
+ });
156
+ if (!res.ok)
157
+ return [];
158
+ const data = await res.json();
159
+ const NON_CHAT = ['dall-e', 'davinci', 'babbage', 'whisper', 'tts-', 'text-embedding', 'text-moderation', 'canary', 'audio'];
160
+ return (data.data ?? [])
161
+ .map((m) => m.id)
162
+ .filter((id) => !NON_CHAT.some((prefix) => id.startsWith(prefix)))
163
+ .sort((a, b) => {
164
+ // Priority sort: gpt-5 first, then codex, then gpt-4, then rest
165
+ const priority = (m) => {
166
+ if (m.includes('gpt-5'))
167
+ return 0;
168
+ if (m.includes('codex'))
169
+ return 1;
170
+ if (m.includes('gpt-4o'))
171
+ return 2;
172
+ if (m.includes('gpt-4'))
173
+ return 3;
174
+ if (m.includes('o3') || m.includes('o4'))
175
+ return 4;
176
+ return 5;
177
+ };
178
+ return priority(a) - priority(b) || a.localeCompare(b);
179
+ });
180
+ }
181
+ catch {
182
+ return [];
183
+ }
184
+ },
185
+ },
186
+ {
187
+ id: 'litellm',
188
+ label: 'LiteLLM (proxy to 100+ providers)',
189
+ hint: 'OpenAI-compatible proxy',
190
+ envVar: 'LITELLM_API_KEY',
191
+ authMethods: [
192
+ { value: 'proxy', label: 'Proxy connection', hint: 'base URL + optional API key' },
193
+ ],
194
+ models: [],
195
+ verify: async (_apiKey) => ({ ok: true }),
196
+ },
197
+ {
198
+ id: 'custom',
199
+ label: 'Custom (OpenAI-compatible endpoint)',
200
+ hint: 'Any OpenAI-compatible API',
201
+ envVar: 'CUSTOM_API_KEY',
202
+ authMethods: [
203
+ { value: 'api_key', label: 'API Key', hint: 'paste API key' },
204
+ ],
205
+ models: [],
206
+ verify: async (_apiKey) => ({ ok: true }),
207
+ },
208
+ ];
209
+ // ─── Main onboard flow ──────────────────────────────────────────────
210
+ export async function runOnboard() {
211
+ const takoDir = join(homedir(), '.tako');
212
+ const configPath = join(takoDir, 'tako.json');
213
+ p.intro('◉‿◉ Tako Setup');
214
+ // Load existing config if re-running
215
+ let existingConfig = {};
216
+ if (existsSync(configPath)) {
217
+ try {
218
+ existingConfig = JSON.parse(await readFile(configPath, 'utf-8'));
219
+ }
220
+ catch { /* ignore invalid config */ }
221
+ p.log.info('Found existing config at ~/.tako/tako.json — you can update it.');
222
+ }
223
+ // ── Step 1: Multi-provider dashboard ──────────────────────────────
224
+ const configured = [];
225
+ // Pre-populate from existing config
226
+ if (existingConfig.providers?.primary) {
227
+ const existingPrimary = existingConfig.providers.primary.split('/')[0];
228
+ if (PROVIDERS.some((prov) => prov.id === existingPrimary) && !configured.some((c) => c.id === existingPrimary)) {
229
+ configured.push({ id: existingPrimary });
230
+ }
231
+ }
232
+ if (existingConfig.providers?.fallback) {
233
+ for (const fb of existingConfig.providers.fallback) {
234
+ const fbProvider = fb.split('/')[0];
235
+ if (PROVIDERS.some((prov) => prov.id === fbProvider) && !configured.some((c) => c.id === fbProvider)) {
236
+ configured.push({ id: fbProvider });
237
+ }
238
+ }
239
+ }
240
+ // Restore LiteLLM config from existing tako.json
241
+ const existingLitellm = existingConfig.providers?.litellm;
242
+ if (existingLitellm?.baseUrl) {
243
+ const existing = configured.find((c) => c.id === 'litellm');
244
+ if (existing) {
245
+ // Merge litellm-specific fields into the bare entry added from primary/fallback
246
+ existing.litellmEndpointName = existing.litellmEndpointName ?? existingLitellm.name;
247
+ existing.litellmBaseUrl = existing.litellmBaseUrl ?? existingLitellm.baseUrl;
248
+ existing.apiKey = existing.apiKey ?? existingLitellm.apiKey;
249
+ existing.litellmModel = existing.litellmModel ?? existingLitellm.model;
250
+ existing.litellmModels = existing.litellmModels ?? existingLitellm.models;
251
+ }
252
+ else {
253
+ configured.push({
254
+ id: 'litellm',
255
+ litellmEndpointName: existingLitellm.name,
256
+ apiKey: existingLitellm.apiKey,
257
+ litellmBaseUrl: existingLitellm.baseUrl,
258
+ litellmModel: existingLitellm.model,
259
+ litellmModels: existingLitellm.models,
260
+ });
261
+ }
262
+ }
263
+ // Also check auth status for all providers
264
+ for (const prov of PROVIDERS) {
265
+ const status = await getAuthStatus(prov.id);
266
+ if (status.authenticated && !configured.some((c) => c.id === prov.id)) {
267
+ const sourceLabel = status.source === 'env' ? 'env var'
268
+ : status.method === 'oauth' ? 'OAuth'
269
+ : status.method === 'setup_token' ? 'setup token'
270
+ : status.method === 'api_key' ? 'API key'
271
+ : 'auth file';
272
+ configured.push({ id: prov.id, source: sourceLabel });
273
+ }
274
+ }
275
+ // Provider dashboard loop
276
+ let providersDone = false;
277
+ while (!providersDone) {
278
+ // Build dashboard display
279
+ const dashLines = PROVIDERS.map((prov) => {
280
+ const conf = configured.find((c) => c.id === prov.id);
281
+ const icon = conf ? '✅' : '⬜';
282
+ const status = conf
283
+ ? `configured (${conf.source ?? 'API key'})`
284
+ : 'not configured';
285
+ return ` ${prov.label.padEnd(35)} ${icon} ${status}`;
286
+ });
287
+ p.log.message(['', '◉‿◉ Tako Provider Setup', '', ' Provider Status', ' ' + '─'.repeat(50), ...dashLines, ''].join('\n'));
288
+ const action = await p.select({
289
+ message: 'What would you like to do?',
290
+ options: [
291
+ ...PROVIDERS.map((prov) => {
292
+ const isConfigured = configured.some((c) => c.id === prov.id);
293
+ return {
294
+ value: prov.id,
295
+ label: isConfigured ? `Re-configure ${prov.label}` : `Configure ${prov.label}`,
296
+ hint: prov.hint,
297
+ };
298
+ }),
299
+ { value: '__continue__', label: 'Continue →', hint: configured.length > 0 ? `${configured.length} provider(s) ready` : 'at least 1 provider required' },
300
+ ],
301
+ });
302
+ if (p.isCancel(action)) {
303
+ p.cancel('Setup cancelled.');
304
+ process.exit(0);
305
+ }
306
+ if (action === '__continue__') {
307
+ if (configured.length === 0) {
308
+ p.log.warn('You need at least one configured provider to continue.');
309
+ continue;
310
+ }
311
+ providersDone = true;
312
+ }
313
+ else {
314
+ const result = await configureProvider(action);
315
+ if (result) {
316
+ // Replace or add
317
+ const idx = configured.findIndex((c) => c.id === result.id);
318
+ if (idx >= 0)
319
+ configured[idx] = result;
320
+ else
321
+ configured.push(result);
322
+ // Debug: show what was saved
323
+ if (result.id === 'litellm') {
324
+ p.log.info(`[debug] LiteLLM saved to configured: baseUrl=${result.litellmBaseUrl}, models=${result.litellmModels?.join(', ')}`);
325
+ }
326
+ }
327
+ }
328
+ }
329
+ // ── Step 2: Fallback model chain ──────────────────────────────────
330
+ // Collect all available models from configured providers
331
+ const modelSpinner = p.spinner();
332
+ modelSpinner.start('Fetching available models from configured providers...');
333
+ const availableModels = await collectAvailableModels(configured);
334
+ modelSpinner.stop(`Found ${availableModels.length} models from ${configured.length} provider(s).`);
335
+ const modelChain = existingConfig.providers?.primary
336
+ ? [existingConfig.providers.primary, ...(existingConfig.providers.fallback ?? [])]
337
+ : [];
338
+ // Filter out models from providers that are no longer configured
339
+ const configuredIds = new Set(configured.map((c) => c.id));
340
+ const validChain = modelChain.filter((m) => configuredIds.has(m.split('/')[0]));
341
+ // Initialize chain
342
+ const chain = [
343
+ validChain[0] ?? null,
344
+ validChain[1] ?? null,
345
+ validChain[2] ?? null,
346
+ validChain[3] ?? null,
347
+ ];
348
+ let chainDone = false;
349
+ while (!chainDone) {
350
+ const labels = ['Primary', 'Fallback', 'Fallback', 'Fallback'];
351
+ const chainLines = chain.map((model, i) => {
352
+ const num = i + 1;
353
+ const label = labels[i];
354
+ const display = model ?? '(none)';
355
+ const icon = model ? '✅' : '';
356
+ return ` ${num}. ${label.padEnd(10)} ${display.padEnd(35)} ${icon}`;
357
+ });
358
+ p.log.message(['', 'Set up your model fallback chain (up to 4):', '', ...chainLines, ''].join('\n'));
359
+ const slotOptions = chain.map((model, i) => ({
360
+ value: String(i),
361
+ label: model ? `Change slot ${i + 1}: ${model}` : `Set slot ${i + 1} (${labels[i]})`,
362
+ }));
363
+ const chainAction = await p.select({
364
+ message: 'What would you like to do?',
365
+ options: [
366
+ ...slotOptions,
367
+ { value: '__continue__', label: 'Continue →', hint: chain[0] ? 'primary model set' : 'primary model required' },
368
+ ],
369
+ });
370
+ if (p.isCancel(chainAction)) {
371
+ p.cancel('Setup cancelled.');
372
+ process.exit(0);
373
+ }
374
+ if (chainAction === '__continue__') {
375
+ if (!chain[0]) {
376
+ p.log.warn('A primary model is required.');
377
+ continue;
378
+ }
379
+ chainDone = true;
380
+ }
381
+ else {
382
+ const slotIdx = parseInt(chainAction, 10);
383
+ const modelOptions = availableModels.map((m) => ({
384
+ value: m.value,
385
+ label: m.label,
386
+ hint: m.hint,
387
+ }));
388
+ if (slotIdx > 0) {
389
+ modelOptions.push({ value: '__clear__', label: '(none) — remove this fallback', hint: '' });
390
+ }
391
+ const chosen = await p.select({
392
+ message: `Choose model for slot ${slotIdx + 1}:`,
393
+ options: modelOptions,
394
+ });
395
+ if (p.isCancel(chosen))
396
+ continue;
397
+ if (chosen === '__clear__') {
398
+ chain[slotIdx] = null;
399
+ }
400
+ else if (chosen === '__custom__') {
401
+ const customId = await p.text({
402
+ message: 'Enter model ID (e.g. anthropic/claude-sonnet-4-6):',
403
+ validate: (val) => val?.includes('/') ? undefined : 'Format: provider/model-name',
404
+ });
405
+ if (p.isCancel(customId))
406
+ continue;
407
+ chain[slotIdx] = customId;
408
+ }
409
+ else {
410
+ chain[slotIdx] = chosen;
411
+ }
412
+ }
413
+ }
414
+ const primaryModel = chain[0];
415
+ const fallbackModels = chain.slice(1).filter((m) => m !== null);
416
+ // ── Step 3: Conversational identity builder ───────────────────────
417
+ p.log.message('\n◉‿◉ Let\'s get to know each other!\n');
418
+ const ownerName = await p.text({
419
+ message: 'What\'s your name?',
420
+ placeholder: 'Your name',
421
+ validate: (val) => val ? undefined : 'Name is required',
422
+ });
423
+ if (p.isCancel(ownerName)) {
424
+ p.cancel('Setup cancelled.');
425
+ process.exit(0);
426
+ }
427
+ p.log.info(`Nice to meet you, ${ownerName}!`);
428
+ const agentName = await p.text({
429
+ message: 'What should I call myself?',
430
+ placeholder: 'Tako',
431
+ defaultValue: 'Tako',
432
+ validate: (val) => val ? undefined : 'Name is required',
433
+ });
434
+ if (p.isCancel(agentName)) {
435
+ p.cancel('Setup cancelled.');
436
+ process.exit(0);
437
+ }
438
+ const personality = await p.text({
439
+ message: 'Any personality traits you\'d like me to have? (Enter to skip)',
440
+ placeholder: 'e.g. Direct, nerdy, proactive',
441
+ defaultValue: '',
442
+ });
443
+ if (p.isCancel(personality)) {
444
+ p.cancel('Setup cancelled.');
445
+ process.exit(0);
446
+ }
447
+ // ── Step 4: Channel setup ─────────────────────────────────────────
448
+ // Detect existing channel config
449
+ const hasExistingDiscord = !!existingConfig.channels?.discord;
450
+ const hasExistingTelegram = !!existingConfig.channels?.telegram;
451
+ const existingChannels = [
452
+ ...(hasExistingDiscord ? ['Discord'] : []),
453
+ ...(hasExistingTelegram ? ['Telegram'] : []),
454
+ ];
455
+ let discordConfig = hasExistingDiscord ? existingConfig.channels.discord : undefined;
456
+ let telegramConfig = hasExistingTelegram ? existingConfig.channels.telegram : undefined;
457
+ // Build options based on existing config
458
+ const channelOptions = [
459
+ { value: 'keep', label: `Keep current (${existingChannels.length > 0 ? existingChannels.join(' + ') : 'CLI only'})`, hint: 'no changes' },
460
+ { value: 'cli', label: 'CLI only', hint: existingChannels.length > 0 ? 'removes existing channels' : 'start chatting right away' },
461
+ { value: 'discord', label: 'Discord bot', hint: hasExistingDiscord ? 'reconfigure' : 'requires bot token' },
462
+ { value: 'telegram', label: 'Telegram bot', hint: hasExistingTelegram ? 'reconfigure' : 'requires bot token from @BotFather' },
463
+ { value: 'both', label: 'Discord + Telegram', hint: 'set up both' },
464
+ ];
465
+ // Remove 'keep' option if no existing config
466
+ if (!hasExistingDiscord && !hasExistingTelegram) {
467
+ channelOptions.shift();
468
+ }
469
+ const channelChoice = await p.select({
470
+ message: 'Set up messaging channels?',
471
+ options: channelOptions,
472
+ });
473
+ if (p.isCancel(channelChoice)) {
474
+ p.cancel('Setup cancelled.');
475
+ process.exit(0);
476
+ }
477
+ if (channelChoice === 'keep') {
478
+ // Keep existing — do nothing
479
+ }
480
+ else if (channelChoice === 'cli') {
481
+ discordConfig = undefined;
482
+ telegramConfig = undefined;
483
+ }
484
+ else {
485
+ if (channelChoice === 'discord' || channelChoice === 'both') {
486
+ const result = await setupDiscord();
487
+ if (!result) {
488
+ p.cancel('Setup cancelled.');
489
+ process.exit(0);
490
+ }
491
+ discordConfig = result;
492
+ }
493
+ if (channelChoice === 'telegram' || channelChoice === 'both') {
494
+ const result = await setupTelegram();
495
+ if (!result) {
496
+ p.cancel('Setup cancelled.');
497
+ process.exit(0);
498
+ }
499
+ telegramConfig = result;
500
+ }
501
+ }
502
+ // ── Step 5: Deployment mode ─────────────────────────────────────
503
+ const deployMode = await p.select({
504
+ message: 'How will you run Tako?',
505
+ options: [
506
+ { value: 'local', label: 'Locally', hint: 'recommended for development' },
507
+ { value: 'docker', label: 'Docker', hint: 'recommended for production/servers' },
508
+ ],
509
+ });
510
+ if (p.isCancel(deployMode)) {
511
+ p.cancel('Setup cancelled.');
512
+ process.exit(0);
513
+ }
514
+ // ── Step 6: Build config ──────────────────────────────────────────
515
+ // Find litellm config if litellm is configured
516
+ const litellmConfigured = configured.find((c) => c.id === 'litellm');
517
+ // Debug: log litellm config detection
518
+ if (litellmConfigured) {
519
+ p.log.info(`LiteLLM config found: baseUrl=${litellmConfigured.litellmBaseUrl ?? '(none)'}, endpoint=${litellmConfigured.litellmEndpointName ?? '(none)'}, models=${litellmConfigured.litellmModels?.join(', ') ?? '(none)'}`);
520
+ }
521
+ else if (primaryModel.startsWith('litellm/')) {
522
+ p.log.warn('Primary model uses litellm/ prefix but no LiteLLM provider was configured!');
523
+ p.log.warn('The LiteLLM endpoint config will NOT be saved. Please configure LiteLLM first.');
524
+ }
525
+ // Also scan configured array for any litellm entries with models but no baseUrl
526
+ // This catches the case where litellm models were selected from collectAvailableModels
527
+ // but the user didn't explicitly configure litellm as a provider
528
+ const litellmFromModels = primaryModel.startsWith('litellm/') || fallbackModels.some((m) => m.startsWith('litellm/'));
529
+ if (litellmFromModels && !litellmConfigured?.litellmBaseUrl) {
530
+ p.log.warn('⚠ LiteLLM models are in your chain but no LiteLLM endpoint is configured.');
531
+ p.log.warn(' These models will NOT work without a LiteLLM proxy endpoint.');
532
+ p.log.warn(' Go back and configure LiteLLM first, or change your primary model.');
533
+ }
534
+ const config = {
535
+ ...DEFAULT_CONFIG,
536
+ providers: {
537
+ primary: primaryModel,
538
+ ...(fallbackModels.length > 0 ? { fallback: fallbackModels } : {}),
539
+ ...(litellmConfigured?.litellmBaseUrl ? {
540
+ litellm: {
541
+ name: litellmConfigured.litellmEndpointName || 'LiteLLM',
542
+ baseUrl: litellmConfigured.litellmBaseUrl,
543
+ apiKey: litellmConfigured.apiKey || undefined,
544
+ model: litellmConfigured.litellmModel ?? 'default',
545
+ ...(litellmConfigured.litellmModels && litellmConfigured.litellmModels.length > 1
546
+ ? { models: litellmConfigured.litellmModels }
547
+ : {}),
548
+ },
549
+ } : {}),
550
+ },
551
+ channels: {
552
+ ...(discordConfig ? { discord: discordConfig } : {}),
553
+ ...(telegramConfig ? { telegram: telegramConfig } : {}),
554
+ },
555
+ memory: {
556
+ workspace: '~/.tako/workspace',
557
+ },
558
+ };
559
+ // ── Validate: ensure litellm config is present if litellm models are used ──
560
+ if (config.providers.primary.startsWith('litellm/') && !config.providers.litellm) {
561
+ p.log.error('Your primary model uses LiteLLM but no LiteLLM endpoint was configured!');
562
+ p.log.error('This would result in a broken config. Please go back and configure LiteLLM first.');
563
+ p.log.info(`Debug: configured providers = [${configured.map((c) => `${c.id}(baseUrl=${c.litellmBaseUrl ?? 'none'})`).join(', ')}]`);
564
+ p.cancel('Config validation failed.');
565
+ process.exit(1);
566
+ }
567
+ // ── Step 6: Write config + workspace files ────────────────────────
568
+ const writeSpinner = p.spinner();
569
+ writeSpinner.start('Writing configuration...');
570
+ await mkdir(takoDir, { recursive: true });
571
+ await writeFile(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
572
+ // Bootstrap workspace
573
+ const workspaceDir = join(takoDir, 'workspace');
574
+ await mkdir(workspaceDir, { recursive: true });
575
+ await mkdir(join(workspaceDir, 'memory', 'daily'), { recursive: true });
576
+ await mkdir(join(workspaceDir, '.sessions'), { recursive: true });
577
+ // Generate SOUL.md
578
+ const traits = personality ? personality.split(',').map((t) => t.trim()).filter(Boolean) : [];
579
+ const traitSection = traits.length > 0
580
+ ? `\n## Personality\n\n${traits.map((t) => `- **${t}**`).join('\n')}\n`
581
+ : '';
582
+ const soulMd = `# Soul
583
+
584
+ You are ${agentName} 🐙, a general-purpose AI agent. You can do anything — research, coding, writing, analysis, automation. You're the core OS agent with pluggable skill arms for any task.
585
+
586
+ Use your name "${agentName}" when introducing yourself. Avoid using emojis excessively — use them sparingly if at all.
587
+ ${traitSection}
588
+ ## Approach
589
+
590
+ - Think step-by-step before multi-step actions
591
+ - Use the right tool for each task — don't over-engineer
592
+ - Learn from mistakes, store the lesson in memory
593
+ - Keep responses focused and relevant
594
+ - When uncertain, ask rather than guess
595
+ `;
596
+ // Generate IDENTITY.md
597
+ const identityMd = `# Identity
598
+
599
+ - **Name:** ${agentName}
600
+ - **Version:** 0.0.1
601
+ - **Type:** Agent OS (Agent-as-CPU architecture)
602
+ - **Owner:** ${ownerName}
603
+ - **Providers:** ${configured.map((c) => c.id).join(', ')}
604
+ - **Primary Model:** ${primaryModel}
605
+ - **Channels:** ${['CLI', ...(discordConfig ? ['Discord'] : []), ...(telegramConfig ? ['Telegram'] : [])].join(', ')}
606
+ - **Architecture:** Provider → Agent Loop → Tools/Skills → Channel
607
+ `;
608
+ // Generate USER.md
609
+ const userMd = `# User Profile
610
+
611
+ ## Owner
612
+
613
+ - **Name:** ${ownerName}
614
+
615
+ ## Preferences
616
+
617
+ - (populated over time)
618
+ `;
619
+ await writeFile(join(workspaceDir, 'SOUL.md'), soulMd, 'utf-8');
620
+ await writeFile(join(workspaceDir, 'IDENTITY.md'), identityMd, 'utf-8');
621
+ await writeFile(join(workspaceDir, 'USER.md'), userMd, 'utf-8');
622
+ writeSpinner.stop('Config saved to ~/.tako/tako.json');
623
+ // ── Welcome outro ─────────────────────────────────────────────────
624
+ const channels = ['CLI', ...(discordConfig ? ['Discord'] : []), ...(telegramConfig ? ['Telegram'] : [])];
625
+ const fallbackDisplay = fallbackModels.length > 0 ? fallbackModels.join(' → ') : '(none)';
626
+ p.note([
627
+ `Name: ${agentName}`,
628
+ `Owner: ${ownerName}`,
629
+ `Model: ${primaryModel}`,
630
+ `Fallback: ${fallbackDisplay}`,
631
+ `Channels: ${channels.join(', ')}`,
632
+ ].join('\n'), '◉‿◉ All set! Here\'s your Tako:');
633
+ if (deployMode === 'docker') {
634
+ p.outro([
635
+ 'To run with Docker:',
636
+ ' 1. cd to the tako project directory',
637
+ ' 2. ./docker-setup.sh (or: docker compose up -d)',
638
+ '',
639
+ 'Gateway will be at http://127.0.0.1:18790',
640
+ ].join('\n'));
641
+ }
642
+ else {
643
+ p.outro("Run 'tako start' to begin chatting! 🐙");
644
+ }
645
+ }
646
+ // ─── Provider configuration ──────────────────────────────────────────
647
+ async function configureProvider(providerId) {
648
+ const provider = PROVIDERS.find((prov) => prov.id === providerId);
649
+ p.log.info(`Configuring ${provider.label}...`);
650
+ if (provider.id === 'litellm') {
651
+ const result = await setupLiteLLM();
652
+ if (!result)
653
+ return null;
654
+ return { id: 'litellm', apiKey: result.apiKey, litellmEndpointName: result.endpointName, litellmBaseUrl: result.baseUrl, litellmModel: result.model, litellmModels: result.models };
655
+ }
656
+ if (provider.id === 'custom') {
657
+ const baseUrl = await p.text({
658
+ message: 'Enter your API base URL:',
659
+ placeholder: 'https://api.example.com/v1',
660
+ validate: (val) => {
661
+ if (!val)
662
+ return 'URL is required';
663
+ try {
664
+ new URL(val);
665
+ }
666
+ catch {
667
+ return 'Invalid URL';
668
+ }
669
+ return undefined;
670
+ },
671
+ });
672
+ if (p.isCancel(baseUrl))
673
+ return null;
674
+ const keyInput = await p.password({
675
+ message: 'API key (leave empty if none):',
676
+ });
677
+ if (p.isCancel(keyInput))
678
+ return null;
679
+ if (keyInput) {
680
+ const credential = {
681
+ provider: 'custom',
682
+ auth_method: 'api_key',
683
+ api_key: keyInput,
684
+ created_at: Date.now(),
685
+ };
686
+ await writeAuthCredential(credential);
687
+ }
688
+ p.log.success(`Custom provider configured (${baseUrl}).`);
689
+ return { id: 'custom', customBaseUrl: baseUrl };
690
+ }
691
+ // Standard provider (Anthropic, OpenAI)
692
+ let apiKey = '';
693
+ let authMethod = 'api_key';
694
+ if (provider.authMethods.length > 1) {
695
+ const choice = await p.select({
696
+ message: 'How do you want to authenticate?',
697
+ options: provider.authMethods.map((m) => ({
698
+ value: m.value,
699
+ label: m.label,
700
+ hint: m.hint,
701
+ })),
702
+ });
703
+ if (p.isCancel(choice))
704
+ return null;
705
+ authMethod = choice;
706
+ }
707
+ if (authMethod === 'oauth') {
708
+ const oauthProviderKey = provider.id === 'openai' ? 'openai-codex' : provider.id;
709
+ if (OAUTH_PROVIDERS[oauthProviderKey]) {
710
+ const result = await runOAuthFlow(oauthProviderKey, {
711
+ log: (msg) => p.log.info(msg),
712
+ prompt: async (message) => {
713
+ const code = await p.text({ message, validate: (v) => v ? undefined : 'Required' });
714
+ if (p.isCancel(code))
715
+ return null;
716
+ return code;
717
+ },
718
+ });
719
+ if (!result)
720
+ return null;
721
+ p.log.success('OAuth authentication successful! Token stored.');
722
+ }
723
+ else {
724
+ p.log.error(`OAuth not configured for ${provider.id}.`);
725
+ return null;
726
+ }
727
+ }
728
+ else if (authMethod === 'setup_token') {
729
+ p.log.info('Run `claude setup-token` in another terminal to get a setup token.');
730
+ const tokenInput = await p.password({
731
+ message: 'Paste your setup token:',
732
+ validate: (val) => validateAnthropicSetupToken(val ?? ''),
733
+ });
734
+ if (p.isCancel(tokenInput))
735
+ return null;
736
+ const credential = {
737
+ provider: 'anthropic',
738
+ auth_method: 'setup_token',
739
+ setup_token: tokenInput.trim(),
740
+ created_at: Date.now(),
741
+ };
742
+ await writeAuthCredential(credential);
743
+ apiKey = tokenInput.trim(); // Store for dynamic model fetching
744
+ p.log.success('Setup token stored.');
745
+ }
746
+ else {
747
+ // API key flow
748
+ apiKey = process.env[provider.envVar] ?? '';
749
+ if (apiKey) {
750
+ const useExisting = await p.confirm({
751
+ message: `Found ${provider.envVar} in environment. Use it?`,
752
+ initialValue: true,
753
+ });
754
+ if (p.isCancel(useExisting))
755
+ return null;
756
+ if (!useExisting)
757
+ apiKey = '';
758
+ }
759
+ if (!apiKey) {
760
+ const keyInput = await p.password({
761
+ message: `Paste your ${provider.label} API key:`,
762
+ validate: (val) => {
763
+ if (!val || val.trim().length === 0)
764
+ return 'API key is required';
765
+ return undefined;
766
+ },
767
+ });
768
+ if (p.isCancel(keyInput))
769
+ return null;
770
+ apiKey = keyInput;
771
+ }
772
+ // Verify key
773
+ const verifySpinner = p.spinner();
774
+ verifySpinner.start('Verifying API key...');
775
+ const verification = await provider.verify(apiKey);
776
+ if (!verification.ok) {
777
+ verifySpinner.stop(`Key verification failed: ${verification.error}`);
778
+ const continueAnyway = await p.confirm({
779
+ message: 'Continue with this key anyway?',
780
+ initialValue: false,
781
+ });
782
+ if (p.isCancel(continueAnyway) || !continueAnyway)
783
+ return null;
784
+ }
785
+ else {
786
+ verifySpinner.stop(`Key verified! Connected to ${provider.label}.`);
787
+ }
788
+ // Store credential
789
+ const credential = {
790
+ provider: provider.id,
791
+ auth_method: 'api_key',
792
+ api_key: apiKey,
793
+ created_at: Date.now(),
794
+ };
795
+ await writeAuthCredential(credential);
796
+ // Also write to .env for backward compat
797
+ const takoDir = join(homedir(), '.tako');
798
+ const envPath = join(takoDir, '.env');
799
+ let envContent = '';
800
+ if (existsSync(envPath)) {
801
+ envContent = await readFile(envPath, 'utf-8');
802
+ }
803
+ const envLine = `${provider.envVar}=${apiKey}`;
804
+ const regex = new RegExp(`^${provider.envVar}=.*$`, 'm');
805
+ if (regex.test(envContent)) {
806
+ envContent = envContent.replace(regex, envLine);
807
+ }
808
+ else {
809
+ envContent = envContent ? envContent.trimEnd() + '\n' + envLine + '\n' : envLine + '\n';
810
+ }
811
+ await mkdir(takoDir, { recursive: true });
812
+ await writeFile(envPath, envContent, 'utf-8');
813
+ }
814
+ p.log.success(`${provider.label} configured.`);
815
+ return { id: provider.id, apiKey: apiKey || undefined };
816
+ }
817
+ // ─── Model collection ────────────────────────────────────────────────
818
+ async function collectAvailableModels(configured) {
819
+ const models = [];
820
+ for (const cp of configured) {
821
+ const prov = PROVIDERS.find((p) => p.id === cp.id);
822
+ if (!prov)
823
+ continue;
824
+ // Try to fetch models dynamically from the API
825
+ if (prov.fetchModels && cp.apiKey) {
826
+ try {
827
+ const fetched = await prov.fetchModels(cp.apiKey);
828
+ if (fetched.length > 0) {
829
+ models.push(...fetched.map((m) => ({
830
+ value: `${cp.id}/${m}`,
831
+ label: m,
832
+ hint: cp.id,
833
+ })));
834
+ continue; // Skip hardcoded fallback
835
+ }
836
+ }
837
+ catch {
838
+ // Fall through to hardcoded models
839
+ }
840
+ }
841
+ // Fallback to hardcoded model list
842
+ if (prov.models.length > 0) {
843
+ models.push(...prov.models);
844
+ }
845
+ else if (cp.id === 'litellm' && (cp.litellmModels?.length || cp.litellmModel)) {
846
+ const litellmModels = cp.litellmModels ?? (cp.litellmModel ? [cp.litellmModel] : []);
847
+ for (const lm of litellmModels) {
848
+ models.push({ value: `litellm/${lm}`, label: lm, hint: 'LiteLLM proxy' });
849
+ }
850
+ }
851
+ else if (cp.id === 'custom') {
852
+ models.push({ value: 'custom/default', label: 'custom model', hint: 'custom endpoint' });
853
+ }
854
+ }
855
+ // Add Codex OAuth models if authenticated
856
+ const codexAuth = await getAuthStatus('openai-codex');
857
+ if (codexAuth.authenticated && !models.some((m) => m.value.includes('codex'))) {
858
+ models.push({ value: 'openai-codex/gpt-5.3-codex', label: 'gpt-5.3-codex', hint: 'Codex OAuth' }, { value: 'openai-codex/gpt-5.2-codex', label: 'gpt-5.2-codex', hint: 'Codex OAuth' });
859
+ }
860
+ // Add a "custom model" option at the end
861
+ models.push({ value: '__custom__', label: 'Enter model ID manually', hint: 'provider/model-name' });
862
+ return models;
863
+ }
864
+ // ─── LiteLLM setup ──────────────────────────────────────────────────
865
+ async function setupLiteLLM() {
866
+ // Step 1: Choose endpoint preset or enter custom
867
+ const PRESETS = [
868
+ { value: 'local', label: 'Local LiteLLM (localhost:4000)', hint: 'self-hosted proxy' },
869
+ { value: 'ohmygpt', label: 'OhMyGPT', hint: 'https://api.ohmygpt.com' },
870
+ { value: 'openrouter', label: 'OpenRouter', hint: 'https://openrouter.ai/api' },
871
+ { value: 'together', label: 'Together AI', hint: 'https://api.together.xyz' },
872
+ { value: 'custom', label: 'Custom endpoint...', hint: 'enter URL manually' },
873
+ ];
874
+ const PRESET_URLS = {
875
+ local: 'http://localhost:4000',
876
+ ohmygpt: 'https://api.ohmygpt.com',
877
+ openrouter: 'https://openrouter.ai/api',
878
+ together: 'https://api.together.xyz',
879
+ };
880
+ const endpointChoice = await p.select({
881
+ message: 'Choose an endpoint:',
882
+ options: PRESETS,
883
+ });
884
+ if (p.isCancel(endpointChoice))
885
+ return null;
886
+ let baseUrl;
887
+ let endpointName;
888
+ if (endpointChoice === 'custom') {
889
+ const customUrl = await p.text({
890
+ message: 'Endpoint URL:',
891
+ placeholder: 'https://api.example.com/v1',
892
+ validate: (val) => {
893
+ if (!val)
894
+ return 'URL is required';
895
+ try {
896
+ new URL(val);
897
+ }
898
+ catch {
899
+ return 'Invalid URL';
900
+ }
901
+ return undefined;
902
+ },
903
+ });
904
+ if (p.isCancel(customUrl))
905
+ return null;
906
+ baseUrl = customUrl;
907
+ const customName = await p.text({
908
+ message: 'Endpoint name (for display):',
909
+ placeholder: 'my-proxy',
910
+ validate: (val) => val ? undefined : 'Name is required',
911
+ });
912
+ if (p.isCancel(customName))
913
+ return null;
914
+ endpointName = customName;
915
+ }
916
+ else {
917
+ baseUrl = PRESET_URLS[endpointChoice];
918
+ endpointName = PRESETS.find((p) => p.value === endpointChoice).label;
919
+ }
920
+ // Strip trailing /v1 to avoid double path
921
+ baseUrl = baseUrl.replace(/\/+$/, '').replace(/\/v1$/, '');
922
+ // Step 2: API key
923
+ const apiKey = await p.text({
924
+ message: `API key for ${endpointName} (leave empty if none):`,
925
+ placeholder: '',
926
+ defaultValue: '',
927
+ });
928
+ if (p.isCancel(apiKey))
929
+ return null;
930
+ // Test connection
931
+ const testSpinner = p.spinner();
932
+ testSpinner.start('Testing connection...');
933
+ const litellm = new LiteLLMProvider({ baseUrl, apiKey: apiKey || undefined });
934
+ const result = await litellm.testConnection();
935
+ if (result.ok) {
936
+ testSpinner.stop(`Connected! Found ${result.models?.length ?? 0} models on proxy.`);
937
+ if (result.models && result.models.length > 0) {
938
+ p.log.info(`Available models: ${result.models.slice(0, 10).join(', ')}${(result.models.length > 10 ? '...' : '')}`);
939
+ }
940
+ }
941
+ else {
942
+ testSpinner.stop(`Connection test failed: ${result.error}`);
943
+ const continueAnyway = await p.confirm({
944
+ message: 'Continue anyway?',
945
+ initialValue: false,
946
+ });
947
+ if (p.isCancel(continueAnyway) || !continueAnyway)
948
+ return null;
949
+ }
950
+ // Choose or enter model name — filter to chat-capable models, show all
951
+ let model;
952
+ const NON_CHAT_PREFIXES = ['dall-e', 'davinci', 'babbage', 'whisper', 'tts-', 'text-embedding', 'text-moderation'];
953
+ const chatModels = (result.ok && result.models)
954
+ ? result.models.filter((m) => !NON_CHAT_PREFIXES.some((prefix) => m.startsWith(prefix)))
955
+ : [];
956
+ if (chatModels.length > 0) {
957
+ // Sort: gpt-4o and claude models first, then alphabetical
958
+ const priority = (m) => {
959
+ if (m.includes('gpt-4o'))
960
+ return 0;
961
+ if (m.includes('claude'))
962
+ return 1;
963
+ if (m.includes('gpt-4'))
964
+ return 2;
965
+ return 3;
966
+ };
967
+ chatModels.sort((a, b) => priority(a) - priority(b) || a.localeCompare(b));
968
+ const modelChoice = await p.select({
969
+ message: `Choose a model (${chatModels.length} chat models found):`,
970
+ options: [
971
+ ...chatModels.map((m) => ({ value: m, label: m })),
972
+ { value: '__custom__', label: 'Enter model name manually' },
973
+ ],
974
+ });
975
+ if (p.isCancel(modelChoice))
976
+ return null;
977
+ if (modelChoice === '__custom__') {
978
+ const customModel = await p.text({
979
+ message: 'Model name:',
980
+ validate: (val) => val ? undefined : 'Model name is required',
981
+ });
982
+ if (p.isCancel(customModel))
983
+ return null;
984
+ model = customModel;
985
+ }
986
+ else {
987
+ model = modelChoice;
988
+ }
989
+ }
990
+ else {
991
+ const customModel = await p.text({
992
+ message: 'Model name:',
993
+ placeholder: 'gpt-4o',
994
+ validate: (val) => val ? undefined : 'Model name is required',
995
+ });
996
+ if (p.isCancel(customModel))
997
+ return null;
998
+ model = customModel;
999
+ }
1000
+ // Multi-model selection: ask to add more models from the proxy
1001
+ const allModels = [model];
1002
+ if (chatModels.length > 1) {
1003
+ let addMore = true;
1004
+ while (addMore) {
1005
+ const wantMore = await p.confirm({
1006
+ message: 'Add more models from this proxy?',
1007
+ initialValue: false,
1008
+ });
1009
+ if (p.isCancel(wantMore) || !wantMore) {
1010
+ addMore = false;
1011
+ break;
1012
+ }
1013
+ const remaining = chatModels.filter((m) => !allModels.includes(m));
1014
+ if (remaining.length === 0) {
1015
+ p.log.info('No more models available.');
1016
+ break;
1017
+ }
1018
+ const extraModel = await p.select({
1019
+ message: `Add another model (${allModels.length} selected so far):`,
1020
+ options: [
1021
+ ...remaining.map((m) => ({ value: m, label: m })),
1022
+ { value: '__done__', label: 'Done — no more models' },
1023
+ ],
1024
+ });
1025
+ if (p.isCancel(extraModel) || extraModel === '__done__') {
1026
+ addMore = false;
1027
+ }
1028
+ else {
1029
+ allModels.push(extraModel);
1030
+ p.log.info(`Added: ${extraModel} (${allModels.length} total)`);
1031
+ }
1032
+ }
1033
+ }
1034
+ const modelDisplay = allModels.length > 1
1035
+ ? `${allModels.length} models: ${allModels.join(', ')}`
1036
+ : `model: ${model}`;
1037
+ p.log.success(`${endpointName} configured (${baseUrl}, ${modelDisplay}).`);
1038
+ return { endpointName, baseUrl, apiKey: apiKey ?? '', model, models: allModels };
1039
+ }
1040
+ // ─── Channel setup helpers ──────────────────────────────────────────
1041
+ async function setupDiscord() {
1042
+ p.log.info([
1043
+ 'Discord Bot Setup',
1044
+ '',
1045
+ ' 1. Go to https://discord.com/developers/applications',
1046
+ ' 2. Create a New Application → Bot tab → Copy token',
1047
+ '',
1048
+ ' Required Bot Permissions (OAuth2 → URL Generator):',
1049
+ ' ✦ Send Messages ✦ Read Message History',
1050
+ ' ✦ Create Public Threads ✦ Send Messages in Threads',
1051
+ ' ✦ Manage Channels ✦ Embed Links',
1052
+ ' ✦ Attach Files ✦ Add Reactions',
1053
+ ' ✦ Use Slash Commands ✦ Read Messages/View Channels',
1054
+ '',
1055
+ ' Required Privileged Intents (Bot tab → toggle ON):',
1056
+ ' ✦ MESSAGE CONTENT INTENT (required to read messages)',
1057
+ ' ✦ SERVER MEMBERS INTENT (optional, for member info)',
1058
+ '',
1059
+ ' Adding bot to server:',
1060
+ ' Go to OAuth2 → URL Generator → check "bot" + "applications.commands"',
1061
+ ' → select the permissions above → copy the invite URL → open in browser',
1062
+ ].join('\n'));
1063
+ const token = await p.password({
1064
+ message: 'Discord bot token:',
1065
+ validate: (val) => val ? undefined : 'Token is required',
1066
+ });
1067
+ if (p.isCancel(token))
1068
+ return null;
1069
+ // Verify Discord token
1070
+ const spinner = p.spinner();
1071
+ spinner.start('Verifying Discord token...');
1072
+ try {
1073
+ const res = await fetch('https://discord.com/api/v10/users/@me', {
1074
+ headers: { Authorization: `Bot ${token}` },
1075
+ });
1076
+ if (res.ok) {
1077
+ const bot = await res.json();
1078
+ spinner.stop(`Connected! Bot: ${bot.username}#${bot.discriminator}`);
1079
+ }
1080
+ else {
1081
+ spinner.stop('Token verification failed. You can fix this later.');
1082
+ }
1083
+ }
1084
+ catch {
1085
+ spinner.stop('Could not reach Discord API. Token saved anyway.');
1086
+ }
1087
+ const guilds = await p.text({
1088
+ message: 'Restrict to specific guild IDs? (comma-separated, or leave empty for all)',
1089
+ placeholder: 'Leave empty for all guilds',
1090
+ defaultValue: '',
1091
+ });
1092
+ if (p.isCancel(guilds))
1093
+ return null;
1094
+ return {
1095
+ token,
1096
+ ...(guilds && guilds.trim() ? { guilds: guilds.split(',').map((g) => g.trim()) } : {}),
1097
+ };
1098
+ }
1099
+ async function setupTelegram() {
1100
+ p.log.info('Telegram Bot Setup — get a token from @BotFather on Telegram');
1101
+ const token = await p.password({
1102
+ message: 'Telegram bot token:',
1103
+ validate: (val) => val ? undefined : 'Token is required',
1104
+ });
1105
+ if (p.isCancel(token))
1106
+ return null;
1107
+ // Verify Telegram token
1108
+ const spinner = p.spinner();
1109
+ spinner.start('Verifying Telegram token...');
1110
+ try {
1111
+ const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);
1112
+ if (res.ok) {
1113
+ const data = await res.json();
1114
+ spinner.stop(`Connected! Bot: @${data.result.username}`);
1115
+ }
1116
+ else {
1117
+ spinner.stop('Token verification failed. You can fix this later.');
1118
+ }
1119
+ }
1120
+ catch {
1121
+ spinner.stop('Could not reach Telegram API. Token saved anyway.');
1122
+ }
1123
+ const allowedUsers = await p.text({
1124
+ message: 'Restrict to specific user IDs? (comma-separated, or leave empty for all)',
1125
+ placeholder: 'Leave empty to allow all users',
1126
+ defaultValue: '',
1127
+ });
1128
+ if (p.isCancel(allowedUsers))
1129
+ return null;
1130
+ return {
1131
+ token,
1132
+ ...(allowedUsers && allowedUsers.trim()
1133
+ ? { allowedUsers: allowedUsers.split(',').map((u) => u.trim()) }
1134
+ : {}),
1135
+ };
1136
+ }
1137
+ //# sourceMappingURL=onboard.js.map