@vascend/talos 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (620) hide show
  1. package/README.md +202 -0
  2. package/dist/backend/asset-events.d.ts +31 -0
  3. package/dist/backend/asset-events.js +149 -0
  4. package/dist/backend/assets.d.ts +31 -0
  5. package/dist/backend/assets.js +210 -0
  6. package/dist/backend/auth.d.ts +18 -0
  7. package/dist/backend/auth.js +59 -0
  8. package/dist/backend/config.d.ts +14 -0
  9. package/dist/backend/config.js +41 -0
  10. package/dist/backend/conversations.d.ts +21 -0
  11. package/dist/backend/conversations.js +141 -0
  12. package/dist/backend/crypto.d.ts +9 -0
  13. package/dist/backend/crypto.js +68 -0
  14. package/dist/backend/engine.d.ts +13 -0
  15. package/dist/backend/engine.js +78 -0
  16. package/dist/backend/http.d.ts +25 -0
  17. package/dist/backend/http.js +112 -0
  18. package/dist/backend/index.d.ts +1 -0
  19. package/dist/backend/index.js +24 -0
  20. package/dist/backend/routes.d.ts +14 -0
  21. package/dist/backend/routes.js +169 -0
  22. package/dist/backend/sdk.d.ts +12 -0
  23. package/dist/backend/sdk.js +11 -0
  24. package/dist/backend/server.d.ts +12 -0
  25. package/dist/backend/server.js +91 -0
  26. package/dist/backend/temp-image-store.d.ts +46 -0
  27. package/dist/backend/temp-image-store.js +197 -0
  28. package/dist/backend/types.d.ts +103 -0
  29. package/dist/backend/types.js +29 -0
  30. package/dist/backend/users.d.ts +13 -0
  31. package/dist/backend/users.js +76 -0
  32. package/dist/backend/ws-handler.d.ts +14 -0
  33. package/dist/backend/ws-handler.js +72 -0
  34. package/dist/backend/ws.d.ts +19 -0
  35. package/dist/backend/ws.js +146 -0
  36. package/dist/core/agent.d.ts +56 -0
  37. package/dist/core/agent.js +1783 -0
  38. package/dist/core/background.d.ts +45 -0
  39. package/dist/core/background.js +140 -0
  40. package/dist/core/bootstrap.d.ts +45 -0
  41. package/dist/core/bootstrap.js +294 -0
  42. package/dist/core/cli-args.d.ts +41 -0
  43. package/dist/core/cli-args.js +282 -0
  44. package/dist/core/collapsible-output.d.ts +38 -0
  45. package/dist/core/collapsible-output.js +143 -0
  46. package/dist/core/compaction-checkpoint.d.ts +9 -0
  47. package/dist/core/compaction-checkpoint.js +58 -0
  48. package/dist/core/compaction.d.ts +42 -0
  49. package/dist/core/compaction.js +270 -0
  50. package/dist/core/config.d.ts +49 -0
  51. package/dist/core/config.js +417 -0
  52. package/dist/core/context-ledger.d.ts +99 -0
  53. package/dist/core/context-ledger.js +222 -0
  54. package/dist/core/context-policy.d.ts +17 -0
  55. package/dist/core/context-policy.js +81 -0
  56. package/dist/core/continuation-review.d.ts +23 -0
  57. package/dist/core/continuation-review.js +64 -0
  58. package/dist/core/crash-report.d.ts +3 -0
  59. package/dist/core/crash-report.js +27 -0
  60. package/dist/core/credentials.d.ts +11 -0
  61. package/dist/core/credentials.js +183 -0
  62. package/dist/core/doctor.d.ts +24 -0
  63. package/dist/core/doctor.js +125 -0
  64. package/dist/core/effort.d.ts +5 -0
  65. package/dist/core/effort.js +42 -0
  66. package/dist/core/env-paths.d.ts +3 -0
  67. package/dist/core/env-paths.js +38 -0
  68. package/dist/core/execution-guidance.d.ts +9 -0
  69. package/dist/core/execution-guidance.js +73 -0
  70. package/dist/core/execution-target.d.ts +41 -0
  71. package/dist/core/execution-target.js +69 -0
  72. package/dist/core/file-coordination.d.ts +66 -0
  73. package/dist/core/file-coordination.js +176 -0
  74. package/dist/core/file-lease-store.d.ts +14 -0
  75. package/dist/core/file-lease-store.js +89 -0
  76. package/dist/core/image-limits.d.ts +26 -0
  77. package/dist/core/image-limits.js +205 -0
  78. package/dist/core/interruptible-completion.d.ts +3 -0
  79. package/dist/core/interruptible-completion.js +42 -0
  80. package/dist/core/kingdoms-mode-state.d.ts +24 -0
  81. package/dist/core/kingdoms-mode-state.js +139 -0
  82. package/dist/core/licenza.d.ts +38 -0
  83. package/dist/core/licenza.js +125 -0
  84. package/dist/core/model-limits.d.ts +2 -0
  85. package/dist/core/model-limits.js +36 -0
  86. package/dist/core/output-lifecycle.d.ts +44 -0
  87. package/dist/core/output-lifecycle.js +190 -0
  88. package/dist/core/package-update.d.ts +15 -0
  89. package/dist/core/package-update.js +121 -0
  90. package/dist/core/permission-queue.d.ts +2 -0
  91. package/dist/core/permission-queue.js +20 -0
  92. package/dist/core/prompt-attachment.d.ts +21 -0
  93. package/dist/core/prompt-attachment.js +123 -0
  94. package/dist/core/request-plan.d.ts +16 -0
  95. package/dist/core/request-plan.js +36 -0
  96. package/dist/core/run-timing.d.ts +17 -0
  97. package/dist/core/run-timing.js +123 -0
  98. package/dist/core/self-update.d.ts +17 -0
  99. package/dist/core/self-update.js +54 -0
  100. package/dist/core/session-refs.d.ts +27 -0
  101. package/dist/core/session-refs.js +126 -0
  102. package/dist/core/session-storage.d.ts +4 -0
  103. package/dist/core/session-storage.js +48 -0
  104. package/dist/core/session-title.d.ts +1 -0
  105. package/dist/core/session-title.js +21 -0
  106. package/dist/core/session-usage.d.ts +17 -0
  107. package/dist/core/session-usage.js +74 -0
  108. package/dist/core/session.d.ts +58 -0
  109. package/dist/core/session.js +296 -0
  110. package/dist/core/settings.d.ts +17 -0
  111. package/dist/core/settings.js +107 -0
  112. package/dist/core/storage-retention.d.ts +21 -0
  113. package/dist/core/storage-retention.js +227 -0
  114. package/dist/core/text-sanitize.d.ts +1 -0
  115. package/dist/core/text-sanitize.js +35 -0
  116. package/dist/core/tool-artifacts.d.ts +6 -0
  117. package/dist/core/tool-artifacts.js +51 -0
  118. package/dist/core/tool-compress.d.ts +8 -0
  119. package/dist/core/tool-compress.js +111 -0
  120. package/dist/core/tool-executor.d.ts +16 -0
  121. package/dist/core/tool-executor.js +97 -0
  122. package/dist/core/tool-result-index.d.ts +52 -0
  123. package/dist/core/tool-result-index.js +327 -0
  124. package/dist/core/tool-result-store.d.ts +38 -0
  125. package/dist/core/tool-result-store.js +190 -0
  126. package/dist/core/tool-scheduler.d.ts +16 -0
  127. package/dist/core/tool-scheduler.js +35 -0
  128. package/dist/core/trust.d.ts +21 -0
  129. package/dist/core/trust.js +95 -0
  130. package/dist/core/types.d.ts +402 -0
  131. package/dist/core/types.js +1 -0
  132. package/dist/core/update-check.d.ts +26 -0
  133. package/dist/core/update-check.js +89 -0
  134. package/dist/core/update-process.d.ts +10 -0
  135. package/dist/core/update-process.js +31 -0
  136. package/dist/core/user-inbox.d.ts +23 -0
  137. package/dist/core/user-inbox.js +56 -0
  138. package/dist/core/user-input.d.ts +10 -0
  139. package/dist/core/user-input.js +35 -0
  140. package/dist/core/version.d.ts +1 -0
  141. package/dist/core/version.js +10 -0
  142. package/dist/core/vibe-modes.d.ts +38 -0
  143. package/dist/core/vibe-modes.js +383 -0
  144. package/dist/core/workspace-roots.d.ts +13 -0
  145. package/dist/core/workspace-roots.js +91 -0
  146. package/dist/core/workspace-sessions.d.ts +51 -0
  147. package/dist/core/workspace-sessions.js +243 -0
  148. package/dist/cowork/client.d.ts +29 -0
  149. package/dist/cowork/client.js +49 -0
  150. package/dist/cowork/engine-bridge.d.ts +22 -0
  151. package/dist/cowork/engine-bridge.js +98 -0
  152. package/dist/cowork/index.d.ts +11 -0
  153. package/dist/cowork/index.js +16 -0
  154. package/dist/cowork/ipc.d.ts +97 -0
  155. package/dist/cowork/ipc.js +96 -0
  156. package/dist/cowork/manager.d.ts +66 -0
  157. package/dist/cowork/manager.js +325 -0
  158. package/dist/cowork/store.d.ts +23 -0
  159. package/dist/cowork/store.js +182 -0
  160. package/dist/cowork/sync.d.ts +20 -0
  161. package/dist/cowork/sync.js +164 -0
  162. package/dist/cowork/types.d.ts +78 -0
  163. package/dist/cowork/types.js +21 -0
  164. package/dist/extensions/ext-tools.d.ts +3 -0
  165. package/dist/extensions/ext-tools.js +73 -0
  166. package/dist/extensions/loader.d.ts +91 -0
  167. package/dist/extensions/loader.js +474 -0
  168. package/dist/extensions/settings.d.ts +20 -0
  169. package/dist/extensions/settings.js +86 -0
  170. package/dist/extensions/types.d.ts +219 -0
  171. package/dist/extensions/types.js +1 -0
  172. package/dist/horizon/async-queue.d.ts +9 -0
  173. package/dist/horizon/async-queue.js +46 -0
  174. package/dist/horizon/engine.d.ts +85 -0
  175. package/dist/horizon/engine.js +603 -0
  176. package/dist/horizon/index.d.ts +4 -0
  177. package/dist/horizon/index.js +2 -0
  178. package/dist/horizon/main-team.d.ts +163 -0
  179. package/dist/horizon/main-team.js +774 -0
  180. package/dist/horizon/types.d.ts +233 -0
  181. package/dist/horizon/types.js +1 -0
  182. package/dist/index.d.ts +2 -0
  183. package/dist/index.js +233 -0
  184. package/dist/mcp/protocol.d.ts +81 -0
  185. package/dist/mcp/protocol.js +122 -0
  186. package/dist/package.json +1 -0
  187. package/dist/packages/packages.d.ts +12 -0
  188. package/dist/packages/packages.js +323 -0
  189. package/dist/prompts/templates.d.ts +13 -0
  190. package/dist/prompts/templates.js +139 -0
  191. package/dist/providers/anthropic-oauth.d.ts +13 -0
  192. package/dist/providers/anthropic-oauth.js +124 -0
  193. package/dist/providers/anthropic.d.ts +27 -0
  194. package/dist/providers/anthropic.js +526 -0
  195. package/dist/providers/catalog.d.ts +15 -0
  196. package/dist/providers/catalog.js +166 -0
  197. package/dist/providers/effort.d.ts +12 -0
  198. package/dist/providers/effort.js +102 -0
  199. package/dist/providers/model-catalog.d.ts +43 -0
  200. package/dist/providers/model-catalog.js +70 -0
  201. package/dist/providers/model-effort.d.ts +5 -0
  202. package/dist/providers/model-effort.js +43 -0
  203. package/dist/providers/model-registry.d.ts +39 -0
  204. package/dist/providers/model-registry.js +142 -0
  205. package/dist/providers/models-dev.d.ts +9 -0
  206. package/dist/providers/models-dev.js +97 -0
  207. package/dist/providers/oauth-callback-server.d.ts +28 -0
  208. package/dist/providers/oauth-callback-server.js +184 -0
  209. package/dist/providers/oauth-orchestrator.d.ts +58 -0
  210. package/dist/providers/oauth-orchestrator.js +159 -0
  211. package/dist/providers/oauth-store.d.ts +12 -0
  212. package/dist/providers/oauth-store.js +139 -0
  213. package/dist/providers/open-browser.d.ts +20 -0
  214. package/dist/providers/open-browser.js +92 -0
  215. package/dist/providers/openai-compat.d.ts +14 -0
  216. package/dist/providers/openai-compat.js +523 -0
  217. package/dist/providers/openai-oauth.d.ts +15 -0
  218. package/dist/providers/openai-oauth.js +382 -0
  219. package/dist/providers/openrouter-auth.d.ts +73 -0
  220. package/dist/providers/openrouter-auth.js +321 -0
  221. package/dist/providers/openrouter-manual-fallback.d.ts +25 -0
  222. package/dist/providers/openrouter-manual-fallback.js +161 -0
  223. package/dist/providers/openrouter.d.ts +15 -0
  224. package/dist/providers/openrouter.js +107 -0
  225. package/dist/providers/plan-limits.d.ts +6 -0
  226. package/dist/providers/plan-limits.js +175 -0
  227. package/dist/providers/provider-reset.d.ts +4 -0
  228. package/dist/providers/provider-reset.js +83 -0
  229. package/dist/providers/quota-limits.d.ts +4 -0
  230. package/dist/providers/quota-limits.js +33 -0
  231. package/dist/providers/registry.d.ts +33 -0
  232. package/dist/providers/registry.js +213 -0
  233. package/dist/providers/retry.d.ts +37 -0
  234. package/dist/providers/retry.js +347 -0
  235. package/dist/rpc/server.d.ts +23 -0
  236. package/dist/rpc/server.js +222 -0
  237. package/dist/sdk.d.ts +67 -0
  238. package/dist/sdk.js +64 -0
  239. package/dist/skills/skills.d.ts +17 -0
  240. package/dist/skills/skills.js +155 -0
  241. package/dist/text-sanitize.js +28 -0
  242. package/dist/tools/ask-user.d.ts +2 -0
  243. package/dist/tools/ask-user.js +60 -0
  244. package/dist/tools/builtin.d.ts +48 -0
  245. package/dist/tools/builtin.js +2494 -0
  246. package/dist/tools/capabilities.d.ts +5 -0
  247. package/dist/tools/capabilities.js +55 -0
  248. package/dist/tools/computer-capture.d.ts +2 -0
  249. package/dist/tools/computer-capture.js +91 -0
  250. package/dist/tools/computer-posix.d.ts +5 -0
  251. package/dist/tools/computer-posix.js +136 -0
  252. package/dist/tools/computer-use.d.ts +14 -0
  253. package/dist/tools/computer-use.js +108 -0
  254. package/dist/tools/discovery.d.ts +12 -0
  255. package/dist/tools/discovery.js +205 -0
  256. package/dist/tools/execute.d.ts +2 -0
  257. package/dist/tools/execute.js +73 -0
  258. package/dist/tools/normalize-input.d.ts +17 -0
  259. package/dist/tools/normalize-input.js +174 -0
  260. package/dist/tools/output-artifact.d.ts +3 -0
  261. package/dist/tools/output-artifact.js +80 -0
  262. package/dist/tools/pagination.d.ts +15 -0
  263. package/dist/tools/pagination.js +93 -0
  264. package/dist/tools/plan-status.d.ts +2 -0
  265. package/dist/tools/plan-status.js +109 -0
  266. package/dist/tools/program-input.d.ts +3 -0
  267. package/dist/tools/program-input.js +19 -0
  268. package/dist/tools/program.d.ts +3 -0
  269. package/dist/tools/program.js +567 -0
  270. package/dist/tools/protocol-catalog.d.ts +12 -0
  271. package/dist/tools/protocol-catalog.js +46 -0
  272. package/dist/tools/ramification-tools.d.ts +12 -0
  273. package/dist/tools/ramification-tools.js +528 -0
  274. package/dist/tools/regex-compat.d.ts +9 -0
  275. package/dist/tools/regex-compat.js +96 -0
  276. package/dist/tools/registry.d.ts +51 -0
  277. package/dist/tools/registry.js +185 -0
  278. package/dist/tools/resolve.d.ts +2 -0
  279. package/dist/tools/resolve.js +107 -0
  280. package/dist/tools/shell-env.d.ts +2 -0
  281. package/dist/tools/shell-env.js +7 -0
  282. package/dist/tools/team-input.d.ts +3 -0
  283. package/dist/tools/team-input.js +129 -0
  284. package/dist/tools/team-tools.d.ts +7 -0
  285. package/dist/tools/team-tools.js +348 -0
  286. package/dist/tools/workspace-sessions.d.ts +2 -0
  287. package/dist/tools/workspace-sessions.js +35 -0
  288. package/dist/tui/account-entry.d.ts +1 -0
  289. package/dist/tui/account-entry.js +93 -0
  290. package/dist/tui/attachment-highlight.d.ts +1 -0
  291. package/dist/tui/attachment-highlight.js +24 -0
  292. package/dist/tui/attachment-refs.d.ts +2 -0
  293. package/dist/tui/attachment-refs.js +3 -0
  294. package/dist/tui/bottom-input.d.ts +219 -0
  295. package/dist/tui/bottom-input.js +1958 -0
  296. package/dist/tui/branding.d.ts +107 -0
  297. package/dist/tui/branding.js +750 -0
  298. package/dist/tui/clipboard-image.d.ts +10 -0
  299. package/dist/tui/clipboard-image.js +163 -0
  300. package/dist/tui/clipboard-text.d.ts +9 -0
  301. package/dist/tui/clipboard-text.js +51 -0
  302. package/dist/tui/clipboard-windows.d.ts +8 -0
  303. package/dist/tui/clipboard-windows.js +84 -0
  304. package/dist/tui/collapsible-command.d.ts +15 -0
  305. package/dist/tui/collapsible-command.js +48 -0
  306. package/dist/tui/command-feedback.d.ts +10 -0
  307. package/dist/tui/command-feedback.js +46 -0
  308. package/dist/tui/command-output-registry.d.ts +28 -0
  309. package/dist/tui/command-output-registry.js +103 -0
  310. package/dist/tui/command-transcript.d.ts +12 -0
  311. package/dist/tui/command-transcript.js +90 -0
  312. package/dist/tui/commands.d.ts +20 -0
  313. package/dist/tui/commands.js +131 -0
  314. package/dist/tui/context-bar.d.ts +4 -0
  315. package/dist/tui/context-bar.js +74 -0
  316. package/dist/tui/context-meter.d.ts +25 -0
  317. package/dist/tui/context-meter.js +81 -0
  318. package/dist/tui/cost-binding.d.ts +8 -0
  319. package/dist/tui/cost-binding.js +43 -0
  320. package/dist/tui/cost-tracker.d.ts +49 -0
  321. package/dist/tui/cost-tracker.js +122 -0
  322. package/dist/tui/diff.d.ts +9 -0
  323. package/dist/tui/diff.js +119 -0
  324. package/dist/tui/i18n-catalog.d.ts +5 -0
  325. package/dist/tui/i18n-catalog.js +184 -0
  326. package/dist/tui/i18n.d.ts +6 -0
  327. package/dist/tui/i18n.js +10 -0
  328. package/dist/tui/image-attachments.d.ts +46 -0
  329. package/dist/tui/image-attachments.js +167 -0
  330. package/dist/tui/images.d.ts +12 -0
  331. package/dist/tui/images.js +87 -0
  332. package/dist/tui/intro.d.ts +13 -0
  333. package/dist/tui/intro.js +109 -0
  334. package/dist/tui/language-preference.d.ts +6 -0
  335. package/dist/tui/language-preference.js +24 -0
  336. package/dist/tui/live-output.d.ts +2 -0
  337. package/dist/tui/live-output.js +18 -0
  338. package/dist/tui/locales.d.ts +19 -0
  339. package/dist/tui/locales.js +22 -0
  340. package/dist/tui/login-menu.d.ts +17 -0
  341. package/dist/tui/login-menu.js +58 -0
  342. package/dist/tui/logo.d.ts +8 -0
  343. package/dist/tui/logo.js +305 -0
  344. package/dist/tui/markdown-inline.d.ts +3 -0
  345. package/dist/tui/markdown-inline.js +99 -0
  346. package/dist/tui/markdown-table.d.ts +4 -0
  347. package/dist/tui/markdown-table.js +63 -0
  348. package/dist/tui/markdown.d.ts +11 -0
  349. package/dist/tui/markdown.js +257 -0
  350. package/dist/tui/mcp-transcript.d.ts +7 -0
  351. package/dist/tui/mcp-transcript.js +40 -0
  352. package/dist/tui/model-details.d.ts +2 -0
  353. package/dist/tui/model-details.js +21 -0
  354. package/dist/tui/model-selection.d.ts +7 -0
  355. package/dist/tui/model-selection.js +41 -0
  356. package/dist/tui/native-scrollback.d.ts +27 -0
  357. package/dist/tui/native-scrollback.js +134 -0
  358. package/dist/tui/onboarding.d.ts +72 -0
  359. package/dist/tui/onboarding.js +207 -0
  360. package/dist/tui/paste-collapse.d.ts +39 -0
  361. package/dist/tui/paste-collapse.js +117 -0
  362. package/dist/tui/perm-mode.d.ts +8 -0
  363. package/dist/tui/perm-mode.js +41 -0
  364. package/dist/tui/prompt-queue-store.d.ts +26 -0
  365. package/dist/tui/prompt-queue-store.js +87 -0
  366. package/dist/tui/prompt-queue.d.ts +47 -0
  367. package/dist/tui/prompt-queue.js +187 -0
  368. package/dist/tui/provider-menu.d.ts +33 -0
  369. package/dist/tui/provider-menu.js +175 -0
  370. package/dist/tui/question.d.ts +24 -0
  371. package/dist/tui/question.js +32 -0
  372. package/dist/tui/queue-screen.d.ts +25 -0
  373. package/dist/tui/queue-screen.js +152 -0
  374. package/dist/tui/queue-team.d.ts +3 -0
  375. package/dist/tui/queue-team.js +28 -0
  376. package/dist/tui/queued-questions.d.ts +20 -0
  377. package/dist/tui/queued-questions.js +163 -0
  378. package/dist/tui/quick-help.d.ts +1 -0
  379. package/dist/tui/quick-help.js +53 -0
  380. package/dist/tui/repl.d.ts +78 -0
  381. package/dist/tui/repl.js +4130 -0
  382. package/dist/tui/restore-queued-input.d.ts +3 -0
  383. package/dist/tui/restore-queued-input.js +20 -0
  384. package/dist/tui/review-detail.d.ts +6 -0
  385. package/dist/tui/review-detail.js +56 -0
  386. package/dist/tui/review-files.d.ts +3 -0
  387. package/dist/tui/review-files.js +22 -0
  388. package/dist/tui/review-render.d.ts +22 -0
  389. package/dist/tui/review-render.js +98 -0
  390. package/dist/tui/review-screen.d.ts +38 -0
  391. package/dist/tui/review-screen.js +358 -0
  392. package/dist/tui/review-store.d.ts +60 -0
  393. package/dist/tui/review-store.js +270 -0
  394. package/dist/tui/review-team.d.ts +2 -0
  395. package/dist/tui/review-team.js +27 -0
  396. package/dist/tui/selector-mouse.d.ts +26 -0
  397. package/dist/tui/selector-mouse.js +65 -0
  398. package/dist/tui/selector.d.ts +51 -0
  399. package/dist/tui/selector.js +299 -0
  400. package/dist/tui/session-replay.d.ts +10 -0
  401. package/dist/tui/session-replay.js +78 -0
  402. package/dist/tui/session-usage.d.ts +22 -0
  403. package/dist/tui/session-usage.js +55 -0
  404. package/dist/tui/skill-transcript.d.ts +5 -0
  405. package/dist/tui/skill-transcript.js +31 -0
  406. package/dist/tui/startup.d.ts +5 -0
  407. package/dist/tui/startup.js +61 -0
  408. package/dist/tui/status-line-loader.d.ts +8 -0
  409. package/dist/tui/status-line-loader.js +33 -0
  410. package/dist/tui/status-line.d.ts +38 -0
  411. package/dist/tui/status-line.js +213 -0
  412. package/dist/tui/system-language.d.ts +8 -0
  413. package/dist/tui/system-language.js +41 -0
  414. package/dist/tui/task-labels.d.ts +2 -0
  415. package/dist/tui/task-labels.js +7 -0
  416. package/dist/tui/term-bg.d.ts +4 -0
  417. package/dist/tui/term-bg.js +67 -0
  418. package/dist/tui/terminal-screen.d.ts +12 -0
  419. package/dist/tui/terminal-screen.js +1 -0
  420. package/dist/tui/terminal-text.d.ts +7 -0
  421. package/dist/tui/terminal-text.js +123 -0
  422. package/dist/tui/theme.d.ts +25 -0
  423. package/dist/tui/theme.js +383 -0
  424. package/dist/tui/tool-style.d.ts +7 -0
  425. package/dist/tui/tool-style.js +119 -0
  426. package/dist/tui/update-prompt.d.ts +14 -0
  427. package/dist/tui/update-prompt.js +104 -0
  428. package/dist/tui/usage-footer.d.ts +9 -0
  429. package/dist/tui/usage-footer.js +123 -0
  430. package/dist/tui/vascend-login.d.ts +68 -0
  431. package/dist/tui/vascend-login.js +355 -0
  432. package/dist/tui/web-login.d.ts +28 -0
  433. package/dist/tui/web-login.js +115 -0
  434. package/dist/vascend/activity-status.d.ts +12 -0
  435. package/dist/vascend/activity-status.js +68 -0
  436. package/dist/vascend/architecture-map.d.ts +73 -0
  437. package/dist/vascend/architecture-map.js +424 -0
  438. package/dist/vascend/attention-layout.d.ts +19 -0
  439. package/dist/vascend/attention-layout.js +141 -0
  440. package/dist/vascend/budget-allocator.d.ts +31 -0
  441. package/dist/vascend/budget-allocator.js +79 -0
  442. package/dist/vascend/candidate-collector.d.ts +20 -0
  443. package/dist/vascend/candidate-collector.js +220 -0
  444. package/dist/vascend/code-events.d.ts +24 -0
  445. package/dist/vascend/code-events.js +304 -0
  446. package/dist/vascend/code-graph-memory.d.ts +38 -0
  447. package/dist/vascend/code-graph-memory.js +334 -0
  448. package/dist/vascend/code-graph-runtime.d.ts +19 -0
  449. package/dist/vascend/code-graph-runtime.js +190 -0
  450. package/dist/vascend/code-graph-types.d.ts +58 -0
  451. package/dist/vascend/code-graph-types.js +50 -0
  452. package/dist/vascend/code-parser.d.ts +4 -0
  453. package/dist/vascend/code-parser.js +257 -0
  454. package/dist/vascend/competitor-knowledge.d.ts +53 -0
  455. package/dist/vascend/competitor-knowledge.js +262 -0
  456. package/dist/vascend/completeness.d.ts +16 -0
  457. package/dist/vascend/completeness.js +90 -0
  458. package/dist/vascend/context-autotuner.d.ts +45 -0
  459. package/dist/vascend/context-autotuner.js +231 -0
  460. package/dist/vascend/context-candidate.d.ts +45 -0
  461. package/dist/vascend/context-candidate.js +150 -0
  462. package/dist/vascend/context-capsule.d.ts +51 -0
  463. package/dist/vascend/context-capsule.js +133 -0
  464. package/dist/vascend/context-fabric.d.ts +108 -0
  465. package/dist/vascend/context-fabric.js +480 -0
  466. package/dist/vascend/context-feedback-loop.d.ts +56 -0
  467. package/dist/vascend/context-feedback-loop.js +204 -0
  468. package/dist/vascend/context-learning-identity.d.ts +4 -0
  469. package/dist/vascend/context-learning-identity.js +8 -0
  470. package/dist/vascend/context-links.d.ts +14 -0
  471. package/dist/vascend/context-links.js +83 -0
  472. package/dist/vascend/context-lint.d.ts +22 -0
  473. package/dist/vascend/context-lint.js +91 -0
  474. package/dist/vascend/context-market-selection.d.ts +17 -0
  475. package/dist/vascend/context-market-selection.js +50 -0
  476. package/dist/vascend/context-metrics.d.ts +25 -0
  477. package/dist/vascend/context-metrics.js +57 -0
  478. package/dist/vascend/context-pack-render.d.ts +16 -0
  479. package/dist/vascend/context-pack-render.js +52 -0
  480. package/dist/vascend/context-pareto.d.ts +33 -0
  481. package/dist/vascend/context-pareto.js +165 -0
  482. package/dist/vascend/context-pattern-explorer.d.ts +41 -0
  483. package/dist/vascend/context-pattern-explorer.js +276 -0
  484. package/dist/vascend/context-regret.d.ts +32 -0
  485. package/dist/vascend/context-regret.js +93 -0
  486. package/dist/vascend/context-retriever.d.ts +22 -0
  487. package/dist/vascend/context-retriever.js +243 -0
  488. package/dist/vascend/context-scope-index.d.ts +5 -0
  489. package/dist/vascend/context-scope-index.js +96 -0
  490. package/dist/vascend/context-scorer.d.ts +35 -0
  491. package/dist/vascend/context-scorer.js +162 -0
  492. package/dist/vascend/context-search-index.d.ts +12 -0
  493. package/dist/vascend/context-search-index.js +25 -0
  494. package/dist/vascend/context-snapshot.d.ts +22 -0
  495. package/dist/vascend/context-snapshot.js +135 -0
  496. package/dist/vascend/context-window-compiler.d.ts +42 -0
  497. package/dist/vascend/context-window-compiler.js +237 -0
  498. package/dist/vascend/contract-memory.d.ts +61 -0
  499. package/dist/vascend/contract-memory.js +435 -0
  500. package/dist/vascend/council.d.ts +58 -0
  501. package/dist/vascend/council.js +337 -0
  502. package/dist/vascend/decision-promotion.d.ts +48 -0
  503. package/dist/vascend/decision-promotion.js +410 -0
  504. package/dist/vascend/delta-context.d.ts +12 -0
  505. package/dist/vascend/delta-context.js +36 -0
  506. package/dist/vascend/dev-context-compiler.d.ts +27 -0
  507. package/dist/vascend/dev-context-compiler.js +133 -0
  508. package/dist/vascend/dev-context-layout.d.ts +30 -0
  509. package/dist/vascend/dev-context-layout.js +262 -0
  510. package/dist/vascend/evidence-slots.d.ts +14 -0
  511. package/dist/vascend/evidence-slots.js +55 -0
  512. package/dist/vascend/expansion-levels.d.ts +15 -0
  513. package/dist/vascend/expansion-levels.js +178 -0
  514. package/dist/vascend/file-lock.d.ts +7 -0
  515. package/dist/vascend/file-lock.js +95 -0
  516. package/dist/vascend/granular-kingdom.d.ts +25 -0
  517. package/dist/vascend/granular-kingdom.js +259 -0
  518. package/dist/vascend/granular-launcher.d.ts +48 -0
  519. package/dist/vascend/granular-launcher.js +202 -0
  520. package/dist/vascend/kingdom-bus.d.ts +25 -0
  521. package/dist/vascend/kingdom-bus.js +54 -0
  522. package/dist/vascend/kingdom-channel.d.ts +22 -0
  523. package/dist/vascend/kingdom-channel.js +180 -0
  524. package/dist/vascend/kingdom-kpi.d.ts +48 -0
  525. package/dist/vascend/kingdom-kpi.js +172 -0
  526. package/dist/vascend/kingdom-live.d.ts +28 -0
  527. package/dist/vascend/kingdom-live.js +61 -0
  528. package/dist/vascend/kingdom-run.d.ts +18 -0
  529. package/dist/vascend/kingdom-run.js +506 -0
  530. package/dist/vascend/kingdom-scribe.d.ts +20 -0
  531. package/dist/vascend/kingdom-scribe.js +52 -0
  532. package/dist/vascend/kingdom.d.ts +79 -0
  533. package/dist/vascend/kingdom.js +870 -0
  534. package/dist/vascend/lexical-index.d.ts +10 -0
  535. package/dist/vascend/lexical-index.js +99 -0
  536. package/dist/vascend/lexical-search.d.ts +29 -0
  537. package/dist/vascend/lexical-search.js +262 -0
  538. package/dist/vascend/long-term-context.d.ts +51 -0
  539. package/dist/vascend/long-term-context.js +194 -0
  540. package/dist/vascend/mandate.d.ts +33 -0
  541. package/dist/vascend/mandate.js +107 -0
  542. package/dist/vascend/memory-packet.d.ts +13 -0
  543. package/dist/vascend/memory-packet.js +155 -0
  544. package/dist/vascend/memory-status.d.ts +22 -0
  545. package/dist/vascend/memory-status.js +73 -0
  546. package/dist/vascend/memory-store.d.ts +62 -0
  547. package/dist/vascend/memory-store.js +273 -0
  548. package/dist/vascend/objective-revision.d.ts +69 -0
  549. package/dist/vascend/objective-revision.js +319 -0
  550. package/dist/vascend/patch-plan-store.d.ts +33 -0
  551. package/dist/vascend/patch-plan-store.js +240 -0
  552. package/dist/vascend/patch-plan.d.ts +97 -0
  553. package/dist/vascend/patch-plan.js +345 -0
  554. package/dist/vascend/plan-progress.d.ts +11 -0
  555. package/dist/vascend/plan-progress.js +68 -0
  556. package/dist/vascend/plan-store.d.ts +64 -0
  557. package/dist/vascend/plan-store.js +460 -0
  558. package/dist/vascend/proof-chains.d.ts +19 -0
  559. package/dist/vascend/proof-chains.js +120 -0
  560. package/dist/vascend/ramification-store.d.ts +25 -0
  561. package/dist/vascend/ramification-store.js +94 -0
  562. package/dist/vascend/ramification.d.ts +193 -0
  563. package/dist/vascend/ramification.js +583 -0
  564. package/dist/vascend/recall-planner.d.ts +17 -0
  565. package/dist/vascend/recall-planner.js +109 -0
  566. package/dist/vascend/requirements.d.ts +31 -0
  567. package/dist/vascend/requirements.js +151 -0
  568. package/dist/vascend/reviewer.d.ts +9 -0
  569. package/dist/vascend/reviewer.js +93 -0
  570. package/dist/vascend/room-graph.d.ts +29 -0
  571. package/dist/vascend/room-graph.js +242 -0
  572. package/dist/vascend/room-memory.d.ts +57 -0
  573. package/dist/vascend/room-memory.js +631 -0
  574. package/dist/vascend/runtime.d.ts +84 -0
  575. package/dist/vascend/runtime.js +286 -0
  576. package/dist/vascend/self-improve.d.ts +104 -0
  577. package/dist/vascend/self-improve.js +396 -0
  578. package/dist/vascend/session-search.d.ts +52 -0
  579. package/dist/vascend/session-search.js +349 -0
  580. package/dist/vascend/supersession-graph.d.ts +14 -0
  581. package/dist/vascend/supersession-graph.js +70 -0
  582. package/dist/vascend/team-areas.d.ts +9 -0
  583. package/dist/vascend/team-areas.js +28 -0
  584. package/dist/vascend/team-handoff.d.ts +24 -0
  585. package/dist/vascend/team-handoff.js +37 -0
  586. package/dist/vascend/team-scheduler.d.ts +13 -0
  587. package/dist/vascend/team-scheduler.js +74 -0
  588. package/dist/vascend/team-session.d.ts +42 -0
  589. package/dist/vascend/team-session.js +142 -0
  590. package/dist/vascend/test-failure-memory.d.ts +76 -0
  591. package/dist/vascend/test-failure-memory.js +354 -0
  592. package/dist/vascend/token-market.d.ts +42 -0
  593. package/dist/vascend/token-market.js +144 -0
  594. package/dist/vascend/tuner-baseline-store.d.ts +52 -0
  595. package/dist/vascend/tuner-baseline-store.js +446 -0
  596. package/dist/vascend/user-profile.d.ts +44 -0
  597. package/dist/vascend/user-profile.js +131 -0
  598. package/dist/vascend/vision.d.ts +94 -0
  599. package/dist/vascend/vision.js +375 -0
  600. package/dist/vascend/work-agent.d.ts +12 -0
  601. package/dist/vascend/work-agent.js +83 -0
  602. package/dist/vascend/work-queue.d.ts +62 -0
  603. package/dist/vascend/work-queue.js +255 -0
  604. package/dist/vascend/work-runner.d.ts +64 -0
  605. package/dist/vascend/work-runner.js +137 -0
  606. package/dist/vascend/worktree.d.ts +38 -0
  607. package/dist/vascend/worktree.js +206 -0
  608. package/dist/vendor/computer-use/README.md +7 -0
  609. package/dist/vendor/computer-use/computer-desktop.js +211 -0
  610. package/dist/vendor/computer-use/computer-observe.js +315 -0
  611. package/dist/vendor/computer-use/computer-scripts.js +1230 -0
  612. package/dist/vendor/computer-use/computer-tools.js +2136 -0
  613. package/dist/vendor/computer-use/package.json +1 -0
  614. package/dist/vendor/computer-use/rac/atomic-input.js +91 -0
  615. package/dist/vendor/computer-use/rac/grammatica.js +101 -0
  616. package/dist/vendor/computer-use/rac/parser.js +185 -0
  617. package/dist/vendor/computer-use/rac/protocol.js +136 -0
  618. package/install.ps1 +30 -0
  619. package/install.sh +50 -0
  620. package/package.json +56 -0
@@ -0,0 +1,321 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { loadCredentials } from "../core/credentials.js";
5
+ import { talosConfigDir } from "../core/env-paths.js";
6
+ // Modulo di autenticazione OpenRouter. Supporta due percorsi:
7
+ // 1. API key manuale (l'utente incolla la chiave generata sul sito).
8
+ // 2. OAuth PKCE: l'utente autorizza nel browser, OpenRouter rimanda un
9
+ // `code`, lo scambiamo per una user-controlled API key.
10
+ // Le credenziali sono salvate in ~/.talos/openrouter.json (override via env),
11
+ // separate dal config globale per non mescolarle con i settings dell'utente.
12
+ //
13
+ // Riferimento: https://openrouter.ai/docs/use-cases/oauth-pkce
14
+ const AUTH_BASE = "https://openrouter.ai/auth";
15
+ const KEYS_EXCHANGE_URL = "https://openrouter.ai/api/v1/auth/keys";
16
+ const KEY_INFO_URL = "https://openrouter.ai/api/v1/key";
17
+ // ---------------------------------------------------------------------------
18
+ // Storage sicuro
19
+ // ---------------------------------------------------------------------------
20
+ // Posizione del file credenziali. null se lo storage e' disattivato.
21
+ export function credsPath(env) {
22
+ if (env["TALOS_NO_GLOBAL_CONFIG"] === "1")
23
+ return null;
24
+ const override = String(env["TALOS_OPENROUTER_CREDS_FILE"] ?? "").trim();
25
+ if (override)
26
+ return override;
27
+ return join(talosConfigDir(env), "openrouter.json");
28
+ }
29
+ function readJson(path) {
30
+ try {
31
+ if (!existsSync(path))
32
+ return null;
33
+ const data = JSON.parse(readFileSync(path, "utf8"));
34
+ return typeof data === "object" && data !== null && !Array.isArray(data)
35
+ ? data
36
+ : null;
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ // Legge le credenziali OpenRouter. Priorita': chiave da env (a consumo, gestita
43
+ // fuori da Talos) poi il file su disco. La chiave da env non viene persistita.
44
+ export function readOpenRouterCreds(env) {
45
+ const fromEnv = String(env["TALOS_OPENROUTER_API_KEY"] ?? env["OPENROUTER_API_KEY"] ?? "").trim();
46
+ if (fromEnv)
47
+ return { apiKey: fromEnv, source: "manual", obtainedAt: 0 };
48
+ const path = credsPath(env);
49
+ if (!path)
50
+ return null;
51
+ const json = readJson(path);
52
+ if (!json)
53
+ return null;
54
+ const apiKey = String(json["apiKey"] ?? "").trim();
55
+ if (!apiKey)
56
+ return null;
57
+ const source = json["source"] === "oauth" ? "oauth" : "manual";
58
+ return { apiKey, source, obtainedAt: Number(json["obtainedAt"] ?? 0) };
59
+ }
60
+ // Persiste le credenziali su disco con permessi restrittivi (0600). Best-effort:
61
+ // ritorna false se la scrittura fallisce, true altrimenti.
62
+ export function writeOpenRouterCreds(env, creds) {
63
+ const path = credsPath(env);
64
+ if (!path)
65
+ return false;
66
+ try {
67
+ mkdirSync(dirname(path), { recursive: true });
68
+ const body = JSON.stringify({ apiKey: creds.apiKey, source: creds.source, obtainedAt: creds.obtainedAt || Date.now() }, null, 2);
69
+ // mode 0600: leggibile/scrivibile solo dal proprietario.
70
+ writeFileSync(path, body + "\n", { encoding: "utf8", mode: 0o600 });
71
+ return true;
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ }
77
+ // Cancella le credenziali salvate (logout). True se rimosse o gia' assenti.
78
+ export function clearOpenRouterCreds(env) {
79
+ const path = credsPath(env);
80
+ if (!path)
81
+ return false;
82
+ try {
83
+ if (existsSync(path))
84
+ writeFileSync(path, JSON.stringify({}, null, 2) + "\n", { encoding: "utf8", mode: 0o600 });
85
+ return true;
86
+ }
87
+ catch {
88
+ return false;
89
+ }
90
+ }
91
+ // base64url senza padding (RFC 7636).
92
+ function base64Url(buf) {
93
+ return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
94
+ }
95
+ // Genera un code_verifier random (43-128 char) e il code_challenge S256.
96
+ export function createPkceChallenge(rand = randomBytes) {
97
+ // 32 byte -> 43 char base64url: dentro i limiti RFC 7636.
98
+ const codeVerifier = base64Url(rand(32));
99
+ const codeChallenge = base64Url(createHash("sha256").update(codeVerifier).digest());
100
+ return { codeVerifier, codeChallenge, method: "S256" };
101
+ }
102
+ // Costruisce l'URL a cui mandare l'utente per autorizzare. `callbackUrl` deve
103
+ // combaciare con quello usato allo scambio (per i CLI: spesso un localhost o un
104
+ // URL pubblico del progetto per l'app attribution).
105
+ export function buildAuthUrl(callbackUrl, challenge) {
106
+ const params = new URLSearchParams({
107
+ callback_url: callbackUrl,
108
+ code_challenge: challenge.codeChallenge,
109
+ code_challenge_method: challenge.method,
110
+ });
111
+ return `${AUTH_BASE}?${params.toString()}`;
112
+ }
113
+ // Path del callback su cui il server locale ascolta il redirect di OpenRouter.
114
+ export const CALLBACK_PATH = "/callback";
115
+ // Porta di default del server di callback locale (concordata con i peer).
116
+ export const DEFAULT_CALLBACK_PORT = 8976;
117
+ // Compone l'URL di callback che punta al server locale: per i CLI il redirect
118
+ // di OpenRouter torna su un loopback (http://localhost:porta/callback) invece
119
+ // che su un dominio pubblico (es. vascend.dev). `host` resta configurabile per
120
+ // chi preferisce 127.0.0.1; lo schema e' http perche' e' loopback.
121
+ export function callbackUrlForPort(port = DEFAULT_CALLBACK_PORT, host = "localhost") {
122
+ const p = Number(port);
123
+ if (!Number.isInteger(p) || p < 1 || p > 65535) {
124
+ throw new RangeError(`porta callback non valida: ${port}`);
125
+ }
126
+ // new URL normalizza host/porta; pathname garantisce il /callback esatto.
127
+ const url = new URL(`http://${host}:${p}`);
128
+ url.pathname = CALLBACK_PATH;
129
+ return url.toString().replace(/\/$/, "");
130
+ }
131
+ // Scorciatoia: costruisce l'URL di autorizzazione usando come callback_url il
132
+ // server locale sulla porta data. Unisce callbackUrlForPort + buildAuthUrl, con
133
+ // l'encoding dei parametri gestito da URLSearchParams.
134
+ export function buildAuthUrlForPort(port, challenge, host = "localhost") {
135
+ return buildAuthUrl(callbackUrlForPort(port, host), challenge);
136
+ }
137
+ // Scambia il `code` ricevuto nel callback per una user-controlled API key.
138
+ // Usa il code_verifier generato in createPkceChallenge.
139
+ export async function exchangeCodeForKey(code, codeVerifier, opts = {}) {
140
+ const doFetch = opts.fetchImpl ?? fetch;
141
+ const trimmed = code.trim();
142
+ if (!trimmed)
143
+ return { ok: false, error: "code mancante" };
144
+ try {
145
+ const res = await doFetch(KEYS_EXCHANGE_URL, {
146
+ method: "POST",
147
+ signal: opts.signal,
148
+ headers: { "content-type": "application/json", accept: "application/json" },
149
+ body: JSON.stringify({
150
+ code: trimmed,
151
+ code_verifier: codeVerifier,
152
+ code_challenge_method: "S256",
153
+ }),
154
+ });
155
+ if (!res.ok) {
156
+ const detail = await res.text().catch(() => res.statusText);
157
+ return { ok: false, error: `scambio fallito (${res.status}): ${detail}` };
158
+ }
159
+ const json = (await res.json());
160
+ const key = String(json["key"] ?? "").trim();
161
+ if (!key)
162
+ return { ok: false, error: "risposta priva di key" };
163
+ return { ok: true, apiKey: key };
164
+ }
165
+ catch (err) {
166
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
167
+ }
168
+ }
169
+ export function startOAuthFlow(env, callbackUrl, opts = {}) {
170
+ const challenge = createPkceChallenge(opts.rand);
171
+ const authUrl = buildAuthUrl(callbackUrl, challenge);
172
+ const persist = opts.persist !== false;
173
+ return {
174
+ authUrl,
175
+ challenge,
176
+ async complete(code, callOpts = {}) {
177
+ const result = await exchangeCodeForKey(code, challenge.codeVerifier, callOpts);
178
+ if (result.ok && result.apiKey && persist) {
179
+ writeOpenRouterCreds(env, { apiKey: result.apiKey, source: "oauth", obtainedAt: Date.now() });
180
+ }
181
+ return result;
182
+ },
183
+ };
184
+ }
185
+ // Valida una API key interrogando l'endpoint /key di OpenRouter, che ritorna i
186
+ // metadati della chiave autenticata. 401/403 => chiave non valida.
187
+ export async function validateApiKey(apiKey, opts = {}) {
188
+ const key = apiKey.trim();
189
+ if (!key)
190
+ return { ok: false, error: "API key mancante" };
191
+ const doFetch = opts.fetchImpl ?? fetch;
192
+ const signal = opts.signal ?? AbortSignal.timeout(opts.timeoutMs ?? 8000);
193
+ try {
194
+ const res = await doFetch(KEY_INFO_URL, {
195
+ method: "GET",
196
+ signal,
197
+ headers: { authorization: `Bearer ${key}`, accept: "application/json" },
198
+ });
199
+ if (res.status === 401 || res.status === 403) {
200
+ return { ok: false, error: "API key non valida o non autorizzata" };
201
+ }
202
+ if (!res.ok) {
203
+ const detail = await res.text().catch(() => res.statusText);
204
+ return { ok: false, error: `validazione fallita (${res.status}): ${detail}` };
205
+ }
206
+ const json = (await res.json());
207
+ const data = json["data"] ?? json;
208
+ const limitRaw = data["limit_remaining"];
209
+ return {
210
+ ok: true,
211
+ label: typeof data["label"] === "string" ? data["label"] : undefined,
212
+ limitRemaining: limitRaw === null || limitRaw === undefined ? null : Number(limitRaw),
213
+ usage: data["usage"] !== undefined ? Number(data["usage"]) : undefined,
214
+ };
215
+ }
216
+ catch (err) {
217
+ const msg = err instanceof Error ? err.message : String(err);
218
+ return { ok: false, error: msg };
219
+ }
220
+ }
221
+ // Controllo di forma di una API key OpenRouter (sk-or-...). Non garantisce la
222
+ // validita' (per quella serve validateApiKey), ma intercetta refusi evidenti.
223
+ export function looksLikeApiKey(value) {
224
+ const v = value.trim();
225
+ return /^sk-or-[A-Za-z0-9._-]{8,}$/.test(v);
226
+ }
227
+ // Salva una API key inserita manualmente, dopo averla (opzionalmente) validata.
228
+ // Se `validate` e' true (default) e la chiave non e' valida, NON la persiste.
229
+ export async function saveManualApiKey(env, apiKey, opts = {}) {
230
+ const key = apiKey.trim();
231
+ if (!key)
232
+ return { saved: false, error: "API key mancante" };
233
+ if (opts.validate !== false) {
234
+ const validation = await validateApiKey(key, { signal: opts.signal, fetchImpl: opts.fetchImpl });
235
+ if (!validation.ok)
236
+ return { saved: false, validation, error: validation.error };
237
+ const saved = writeOpenRouterCreds(env, { apiKey: key, source: "manual", obtainedAt: Date.now() });
238
+ return { saved, validation };
239
+ }
240
+ const saved = writeOpenRouterCreds(env, { apiKey: key, source: "manual", obtainedAt: Date.now() });
241
+ return { saved };
242
+ }
243
+ // ---------------------------------------------------------------------------
244
+ // Coesistenza dei metodi di accesso (env API key + OAuth/file + config salvato)
245
+ // ---------------------------------------------------------------------------
246
+ //
247
+ // Per OpenRouter possono coesistere PIU' fonti di credenziale, tutte valide:
248
+ // 1. variabile d'ambiente esportata dall'utente
249
+ // (OPENROUTER_API_KEY o la scoped TALOS_OPENROUTER_API_KEY) - a consumo;
250
+ // 2. credenziale salvata nel config globale (~/.talos/config.json[providers]);
251
+ // 3. file dedicato ~/.talos/openrouter.json scritto da OAuth o inserimento
252
+ // manuale (readOpenRouterCreds).
253
+ // La presenza simultanea NON deve produrre un conflitto ne' lo stato "nessun
254
+ // metodo configurato": basta che UNA fonte abbia una chiave perche' l'accesso
255
+ // sia considerato configurato. La scelta del metodo e' deterministica e segue
256
+ // la precedenza sopra (1 > 2 > 3). Le fonti scartate vengono solo ignorate.
257
+ // Identificatore del provider OpenRouter nel catalogo/config.
258
+ const OPENROUTER_PROVIDER_ID = "openrouter";
259
+ // Nome della env var scoped, allineato a registry.ts/credentials.ts.
260
+ const OPENROUTER_SCOPED_ENV = "TALOS_OPENROUTER_API_KEY";
261
+ // Risolve in modo PURO e DETERMINISTICO quale metodo di accesso OpenRouter usare
262
+ // quando piu' fonti coesistono. Non esegue rete ne' scrive nulla. Garanzie:
263
+ // - se almeno una fonte ha una chiave => configured=true (mai stato vuoto);
264
+ // - la precedenza env > saved > oauth/manual evita ambiguita'/conflitti;
265
+ // - `available` elenca TUTTE le fonti presenti, per trasparenza nella UI.
266
+ export function resolveOpenRouterAccess(env) {
267
+ const available = [];
268
+ // 1. Env esportata dall'utente (nuda o scoped). Massima precedenza: e' una
269
+ // scelta esplicita e a consumo, gestita fuori da Talos.
270
+ const envKey = String(env["OPENROUTER_API_KEY"] ?? env[OPENROUTER_SCOPED_ENV] ?? "").trim();
271
+ if (envKey)
272
+ available.push("env");
273
+ // 2. Credenziale salvata nel config globale (config.json[providers]).
274
+ const savedKey = String(loadCredentials(env)[OPENROUTER_PROVIDER_ID]?.apiKey ?? "").trim();
275
+ if (savedKey)
276
+ available.push("saved");
277
+ // 3. File dedicato (OAuth o inserimento manuale). Leggiamo il file SENZA
278
+ // passare per l'override env di readOpenRouterCreds: qui valutiamo la fonte
279
+ // su disco in modo indipendente, cosi' "available" riflette davvero la
280
+ // coesistenza. Per farlo usiamo readFileCredsOnly che ignora le env.
281
+ const fileCreds = readFileCredsOnly(env);
282
+ if (fileCreds?.apiKey)
283
+ available.push(fileCreds.source === "oauth" ? "oauth" : "manual");
284
+ if (available.length === 0) {
285
+ return {
286
+ configured: false,
287
+ available,
288
+ reason: "nessuna fonte di credenziale OpenRouter (env, config salvato o login OAuth)",
289
+ };
290
+ }
291
+ const method = available[0];
292
+ const apiKey = method === "env" ? envKey : method === "saved" ? savedKey : fileCreds.apiKey;
293
+ const reason = available.length > 1
294
+ ? `piu' fonti presenti (${available.join(", ")}); scelta "${method}" per precedenza`
295
+ : `unica fonte: "${method}"`;
296
+ return { configured: true, apiKey, method, available, reason };
297
+ }
298
+ // Legge SOLO il file dedicato openrouter.json, ignorando le env key. Serve a
299
+ // resolveOpenRouterAccess per distinguere la fonte-file dalla fonte-env quando
300
+ // coesistono (readOpenRouterCreds darebbe priorita' all'env e maschererebbe il
301
+ // file). Mantiene la stessa validazione di forma di readOpenRouterCreds.
302
+ function readFileCredsOnly(env) {
303
+ const path = credsPath(env);
304
+ if (!path)
305
+ return null;
306
+ const json = readJson(path);
307
+ if (!json)
308
+ return null;
309
+ const apiKey = String(json["apiKey"] ?? "").trim();
310
+ if (!apiKey)
311
+ return null;
312
+ const source = json["source"] === "oauth" ? "oauth" : "manual";
313
+ return { apiKey, source, obtainedAt: Number(json["obtainedAt"] ?? 0) };
314
+ }
315
+ // Helper di precedenza riusabile (es. dal registry): ritorna la chiave da usare
316
+ // per OpenRouter considerando tutte le fonti, oppure null se nessuna esiste.
317
+ // Cosi' il registry puo' registrare il provider senza ricomporre la logica.
318
+ export function openRouterApiKey(env) {
319
+ const access = resolveOpenRouterAccess(env);
320
+ return access.configured ? access.apiKey ?? null : null;
321
+ }
@@ -0,0 +1,25 @@
1
+ import type { OAuthFlow } from "./openrouter-auth.js";
2
+ export declare function normalizeAuthCode(raw: string): string;
3
+ export declare function isLikelyAuthCode(value: string): boolean;
4
+ export interface ManualInstructions {
5
+ readonly lines: readonly string[];
6
+ readonly authUrl: string;
7
+ }
8
+ export declare function buildManualInstructions(authUrl: string, reason?: string): ManualInstructions;
9
+ export interface ManualFallbackIo {
10
+ print(line: string): void;
11
+ prompt(label: string): Promise<string | null>;
12
+ }
13
+ export interface ManualFallbackOptions {
14
+ readonly reason?: string;
15
+ readonly maxAttempts?: number;
16
+ readonly signal?: AbortSignal;
17
+ readonly fetchImpl?: typeof fetch;
18
+ }
19
+ export interface ManualFallbackResult {
20
+ readonly ok: boolean;
21
+ readonly apiKey?: string;
22
+ readonly error?: string;
23
+ readonly attempts: number;
24
+ }
25
+ export declare function runManualCodeFallback(io: ManualFallbackIo, flow: OAuthFlow, opts?: ManualFallbackOptions): Promise<ManualFallbackResult>;
@@ -0,0 +1,161 @@
1
+ // Fallback manuale per il login OAuth di OpenRouter.
2
+ //
3
+ // Quando il callback automatico sul server locale non e' percorribile (porta
4
+ // occupata, niente browser, sessione remota/SSH, redirect bloccato da firewall)
5
+ // dobbiamo comunque permettere all'utente di completare il giro PKCE a mano:
6
+ // 1. mostriamo il link di autorizzazione (cliccabile e copiabile);
7
+ // 2. spieghiamo cosa fare con parole semplici;
8
+ // 3. chiediamo di incollare il `code` che OpenRouter mostra/redirige;
9
+ // 4. validiamo l'input (anche se incolla l'intero URL del callback) e
10
+ // scambiamo il code per la API key, con possibilita' di ritentare.
11
+ //
12
+ // Modulo PURO e testabile: tutto l'I/O passa per l'interfaccia ManualFallbackIo
13
+ // (niente accesso diretto a stdin/stdout/console), e lo scambio del code arriva
14
+ // dall'OAuthFlow.complete gia' fornito da openrouter-auth.ts. Nessun side effect
15
+ // nascosto, niente dipendenze a runtime.
16
+ // ---------------------------------------------------------------------------
17
+ // Validazione / normalizzazione del code incollato
18
+ // ---------------------------------------------------------------------------
19
+ // Estrae e normalizza il `code` da cio' che l'utente incolla. Tollerante:
20
+ // - URL completo del callback ("http://localhost:8976/callback?code=ABC&...")
21
+ // - querystring nuda ("?code=ABC&state=x" o "code=ABC")
22
+ // - code nudo ("ABC123"), con eventuali spazi/virgolette/backtick attorno
23
+ // Ritorna il code ripulito, o "" se non se ne ricava uno plausibile.
24
+ export function normalizeAuthCode(raw) {
25
+ if (typeof raw !== "string")
26
+ return "";
27
+ // Rimuove spazi esterni e una eventuale coppia di virgolette/backtick/angolari
28
+ // (capita copiando da chat o markdown: <url>, "code", `code`).
29
+ let s = raw.trim().replace(/^[<"'`\s]+/, "").replace(/[>"'`\s]+$/, "").trim();
30
+ if (!s)
31
+ return "";
32
+ // Caso 1: e' un URL assoluto -> leggi ?code= dalla query.
33
+ const fromUrl = tryExtractFromUrl(s);
34
+ if (fromUrl !== null)
35
+ return fromUrl;
36
+ // Caso 2: contiene una querystring con code= (anche senza schema/host).
37
+ const fromQuery = tryExtractFromQuery(s);
38
+ if (fromQuery !== null)
39
+ return fromQuery;
40
+ // Caso 3: code nudo. Tieni solo il primo token non-spazio e togli un
41
+ // eventuale separatore residuo (& o # con roba dietro).
42
+ s = s.split(/[\s]/)[0] ?? s;
43
+ const amp = s.indexOf("&");
44
+ if (amp >= 0)
45
+ s = s.slice(0, amp);
46
+ const hash = s.indexOf("#");
47
+ if (hash >= 0)
48
+ s = s.slice(0, hash);
49
+ return s.trim();
50
+ }
51
+ function tryExtractFromUrl(s) {
52
+ if (!/^https?:\/\//i.test(s))
53
+ return null;
54
+ try {
55
+ const u = new URL(s);
56
+ const code = u.searchParams.get("code");
57
+ return code ? code.trim() : "";
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ function tryExtractFromQuery(s) {
64
+ if (!/(^|[?&])code=/.test(s))
65
+ return null;
66
+ const q = s.startsWith("?") ? s.slice(1) : s;
67
+ try {
68
+ const params = new URLSearchParams(q);
69
+ const code = params.get("code");
70
+ if (code)
71
+ return code.trim();
72
+ }
73
+ catch {
74
+ // fallthrough al parse manuale
75
+ }
76
+ const m = s.match(/[?&]?code=([^&#\s]+)/);
77
+ return m && m[1] ? decodeURIComponent(m[1]).trim() : "";
78
+ }
79
+ // Controllo di forma di un authorization code OpenRouter. Non garantisce la
80
+ // validita' (per quella serve lo scambio), ma intercetta input vuoti o palesemente
81
+ // sbagliati (URL incollato male, frasi, spazi). I code OpenRouter sono token
82
+ // opachi: accettiamo una sequenza ragionevole di caratteri URL-safe.
83
+ export function isLikelyAuthCode(value) {
84
+ const v = (value ?? "").trim();
85
+ if (v.length < 8 || v.length > 512)
86
+ return false;
87
+ if (/\s/.test(v))
88
+ return false;
89
+ return /^[A-Za-z0-9._~-]+$/.test(v);
90
+ }
91
+ // Costruisce le istruzioni per il percorso manuale. `reason` (opzionale) spiega
92
+ // perche' siamo qui (es. "porta 8976 occupata", "nessun browser disponibile"):
93
+ // se assente usiamo un messaggio neutro.
94
+ export function buildManualInstructions(authUrl, reason) {
95
+ const why = (reason ?? "").trim();
96
+ const lines = [];
97
+ lines.push("Login OpenRouter — modalita' manuale");
98
+ if (why) {
99
+ lines.push(`(callback automatico non disponibile: ${why})`);
100
+ }
101
+ else {
102
+ lines.push("(callback automatico non disponibile: completiamo a mano)");
103
+ }
104
+ lines.push("");
105
+ lines.push("1. Apri questo link nel browser (copialo se non e' cliccabile):");
106
+ lines.push(` ${authUrl}`);
107
+ lines.push("");
108
+ lines.push("2. Autorizza l'accesso su OpenRouter.");
109
+ lines.push("3. Verrai rediretto a un indirizzo localhost che potrebbe non");
110
+ lines.push(" aprirsi (\"impossibile raggiungere il sito\"): e' normale.");
111
+ lines.push("4. Copia il valore del parametro `code` dalla barra degli indirizzi");
112
+ lines.push(" (oppure incolla l'intero URL: estraggo io il code).");
113
+ lines.push("5. Incollalo qui sotto e premi Invio.");
114
+ return { lines, authUrl };
115
+ }
116
+ // Esegue il percorso di fallback manuale: mostra link+istruzioni, chiede il
117
+ // code, lo normalizza/valida, lo scambia via flow.complete e ripete in caso di
118
+ // input invalido o scambio fallito, fino a maxAttempts o annullamento.
119
+ export async function runManualCodeFallback(io, flow, opts = {}) {
120
+ const maxAttempts = Math.max(1, Math.floor(opts.maxAttempts ?? 3));
121
+ const instructions = buildManualInstructions(flow.authUrl, opts.reason);
122
+ for (const line of instructions.lines)
123
+ io.print(line);
124
+ let attempts = 0;
125
+ let lastError = "";
126
+ while (attempts < maxAttempts) {
127
+ const remaining = maxAttempts - attempts;
128
+ const hint = attempts === 0 ? "" : ` (tentativi rimasti: ${remaining})`;
129
+ const raw = await io.prompt(`Incolla il code${hint}`);
130
+ // Annullamento esplicito (Esc/EOF): usciamo subito senza consumare logica.
131
+ if (raw === null) {
132
+ return { ok: false, error: "cancelled", attempts };
133
+ }
134
+ attempts += 1;
135
+ const code = normalizeAuthCode(raw);
136
+ if (!isLikelyAuthCode(code)) {
137
+ lastError = "code non riconosciuto";
138
+ if (attempts < maxAttempts) {
139
+ io.print("Input non valido: incolla il code (o l'intero URL del callback). Riprova.");
140
+ }
141
+ continue;
142
+ }
143
+ let result;
144
+ try {
145
+ result = await flow.complete(code, { signal: opts.signal, fetchImpl: opts.fetchImpl });
146
+ }
147
+ catch (err) {
148
+ result = { ok: false, error: err instanceof Error ? err.message : String(err) };
149
+ }
150
+ if (result.ok && result.apiKey) {
151
+ io.print("Autenticazione completata: API key ottenuta e salvata.");
152
+ return { ok: true, apiKey: result.apiKey, attempts };
153
+ }
154
+ lastError = result.error ?? "scambio fallito";
155
+ if (attempts < maxAttempts) {
156
+ io.print(`Scambio fallito: ${lastError}. Verifica di aver copiato il code giusto e riprova.`);
157
+ }
158
+ }
159
+ io.print("Tentativi esauriti: login manuale non riuscito.");
160
+ return { ok: false, error: lastError || "exhausted", attempts };
161
+ }
@@ -0,0 +1,15 @@
1
+ export interface OpenRouterModel {
2
+ readonly id: string;
3
+ readonly name?: string;
4
+ readonly contextLength?: number;
5
+ readonly promptPrice?: number;
6
+ readonly completionPrice?: number;
7
+ readonly isFree?: boolean;
8
+ }
9
+ export declare function parseOpenRouterModels(payload: unknown): readonly OpenRouterModel[];
10
+ export declare function fetchOpenRouterModels(env?: NodeJS.ProcessEnv, opts?: {
11
+ readonly force?: boolean;
12
+ readonly timeoutMs?: number;
13
+ }): Promise<readonly OpenRouterModel[]>;
14
+ export declare function openRouterDetail(model: OpenRouterModel): string;
15
+ export declare function _resetOpenRouterCache(): void;
@@ -0,0 +1,107 @@
1
+ // Catalogo dinamico dei modelli OpenRouter. OpenRouter espone centinaia di
2
+ // modelli: la lista statica nel catalogo e' solo un seme. Qui scarichiamo
3
+ // l'elenco completo dall'endpoint pubblico `/models` (nessuna chiave richiesta)
4
+ // per alimentare il picker con barra di ricerca.
5
+ const ENDPOINT = "https://openrouter.ai/api/v1/models";
6
+ // Cache di sessione: l'elenco cambia di rado, evitiamo round-trip ripetuti.
7
+ let cache = null;
8
+ let inflight = null;
9
+ function apiKey(env) {
10
+ return String(env["TALOS_OPENROUTER_API_KEY"] ?? env["OPENROUTER_API_KEY"] ?? "").trim();
11
+ }
12
+ function priceK(raw) {
13
+ const n = Number(raw);
14
+ if (!Number.isFinite(n) || n <= 0)
15
+ return undefined;
16
+ // OpenRouter espone il prezzo per singolo token: riportiamo a USD/1M.
17
+ return Math.round(n * 1_000_000 * 100) / 100;
18
+ }
19
+ export function parseOpenRouterModels(payload) {
20
+ const data = payload?.data;
21
+ if (!Array.isArray(data))
22
+ return [];
23
+ const out = [];
24
+ for (const raw of data) {
25
+ const item = raw;
26
+ const id = typeof item["id"] === "string" ? item["id"].trim() : "";
27
+ if (!id)
28
+ continue;
29
+ const pricing = item["pricing"];
30
+ const ctx = Number(item["context_length"]);
31
+ const promptPrice = priceK(pricing?.["prompt"]);
32
+ const completionPrice = priceK(pricing?.["completion"]);
33
+ // Gratuito: OpenRouter marca gli id free col suffisso `:free`, oppure il
34
+ // prezzo prompt+completion e' azzerato (priceK -> undefined su 0).
35
+ const isFree = id.endsWith(":free") || (promptPrice === undefined && completionPrice === undefined);
36
+ out.push({
37
+ id,
38
+ name: typeof item["name"] === "string" ? item["name"] : undefined,
39
+ contextLength: Number.isFinite(ctx) && ctx > 0 ? ctx : undefined,
40
+ promptPrice,
41
+ completionPrice,
42
+ isFree,
43
+ });
44
+ }
45
+ out.sort((a, b) => a.id.localeCompare(b.id));
46
+ return out;
47
+ }
48
+ // Scarica (e memorizza) l'elenco modelli OpenRouter. Fallisce in modo morbido:
49
+ // in caso di errore o timeout restituisce [], cosi' il picker resta usabile coi
50
+ // suggerimenti statici. `force` ignora la cache.
51
+ export async function fetchOpenRouterModels(env = process.env, opts = {}) {
52
+ if (cache && !opts.force)
53
+ return cache;
54
+ if (inflight && !opts.force)
55
+ return inflight;
56
+ const run = (async () => {
57
+ const headers = { accept: "application/json" };
58
+ const key = apiKey(env);
59
+ if (key)
60
+ headers["authorization"] = `Bearer ${key}`;
61
+ headers["http-referer"] = "https://vascend.dev";
62
+ headers["x-title"] = "Vascend Talos";
63
+ try {
64
+ const res = await fetch(ENDPOINT, {
65
+ method: "GET",
66
+ headers,
67
+ signal: AbortSignal.timeout(opts.timeoutMs ?? 8000),
68
+ });
69
+ if (!res.ok)
70
+ return cache ?? [];
71
+ const models = parseOpenRouterModels(await res.json());
72
+ if (models.length)
73
+ cache = models;
74
+ return cache ?? models;
75
+ }
76
+ catch {
77
+ return cache ?? [];
78
+ }
79
+ finally {
80
+ inflight = null;
81
+ }
82
+ })();
83
+ inflight = run;
84
+ return run;
85
+ }
86
+ // Riepilogo compatto per la colonna di dettaglio del picker.
87
+ export function openRouterDetail(model) {
88
+ const parts = [];
89
+ if (model.contextLength) {
90
+ parts.push(model.contextLength >= 1000 ? `${Math.round(model.contextLength / 1000)}k ctx` : `${model.contextLength} ctx`);
91
+ }
92
+ if (model.promptPrice !== undefined || model.completionPrice !== undefined) {
93
+ const usd = "$";
94
+ parts.push(`${usd}${model.promptPrice ?? "?"}/${model.completionPrice ?? "?"} per 1M`);
95
+ }
96
+ else if (model.isFree) {
97
+ // Nessun prezzo = gratuito: mostriamo il tag, cosi' la barra di ricerca del
98
+ // picker filtra i modelli free digitando "free".
99
+ parts.push("free");
100
+ }
101
+ return parts.join(" · ") || (model.name ?? "OpenRouter");
102
+ }
103
+ // Solo per i test: ripulisce la cache di sessione.
104
+ export function _resetOpenRouterCache() {
105
+ cache = null;
106
+ inflight = null;
107
+ }
@@ -0,0 +1,6 @@
1
+ import type { PlanLimits } from "../core/types.js";
2
+ export interface HeaderReader {
3
+ get(name: string): string | null;
4
+ forEach?(callback: (value: string, key: string) => void): void;
5
+ }
6
+ export declare function planLimitsFromHeaders(providerId: string, headers: HeaderReader, now?: number): PlanLimits | null;