@seqyuan/annodex 0.1.10 → 0.1.12

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 (519) hide show
  1. package/app/api/agent/[id]/events/route.ts +94 -0
  2. package/app/api/agent/[id]/route.ts +83 -0
  3. package/app/api/agent/new/route.ts +53 -0
  4. package/app/api/auth/all-providers/route.ts +21 -0
  5. package/app/api/auth/api-key/[provider]/route.ts +7 -0
  6. package/app/api/auth/login/[provider]/route.ts +7 -0
  7. package/app/api/auth/login/route.ts +22 -0
  8. package/app/api/auth/logout/[provider]/route.ts +7 -0
  9. package/app/api/auth/providers/route.ts +15 -0
  10. package/app/api/auth/status/route.ts +6 -0
  11. package/app/api/default-cwd/route.ts +22 -0
  12. package/app/api/files/[...path]/route.ts +621 -0
  13. package/app/api/harness/route.ts +47 -0
  14. package/app/api/home/route.ts +6 -0
  15. package/app/api/internal/runtime/route.ts +26 -0
  16. package/app/api/models/route.ts +67 -0
  17. package/app/api/models-config/discover/route.ts +42 -0
  18. package/app/api/models-config/route.ts +152 -0
  19. package/app/api/models-config/test/route.ts +154 -0
  20. package/app/api/projects/browse/route.ts +51 -0
  21. package/app/api/projects/route.ts +83 -0
  22. package/app/api/reports/[id]/route.ts +108 -0
  23. package/app/api/search/route.ts +122 -0
  24. package/app/api/sessions/[id]/context/route.ts +23 -0
  25. package/app/api/sessions/[id]/route.ts +124 -0
  26. package/app/api/sessions/new/route.ts +5 -0
  27. package/app/api/sessions/route.ts +16 -0
  28. package/app/api/settings/route.ts +51 -0
  29. package/app/api/skills/install/route.ts +249 -0
  30. package/app/api/skills/route.ts +161 -0
  31. package/app/api/skills/search/route.ts +121 -0
  32. package/app/api/soul/route.ts +47 -0
  33. package/app/api/version/route.ts +55 -0
  34. package/app/globals.css +736 -0
  35. package/app/layout.tsx +40 -0
  36. package/app/login/page.tsx +133 -0
  37. package/app/page.tsx +10 -0
  38. package/components/AppShell.tsx +1058 -0
  39. package/components/ChatInput.tsx +1103 -0
  40. package/components/ChatMinimap.tsx +381 -0
  41. package/components/ChatWindow.tsx +576 -0
  42. package/components/CodeMirrorEditor.tsx +137 -0
  43. package/components/ConversationSearch.tsx +369 -0
  44. package/components/DataTableViewer.tsx +248 -0
  45. package/components/FileExplorer.tsx +758 -0
  46. package/components/FileIcons.tsx +241 -0
  47. package/components/FileViewer.tsx +1273 -0
  48. package/components/GlobalFileEditor.tsx +98 -0
  49. package/components/MarkdownRenderer.tsx +331 -0
  50. package/components/MermaidDiagram.tsx +80 -0
  51. package/components/MessageView.tsx +1141 -0
  52. package/components/ModelsConfig.tsx +1991 -0
  53. package/components/ProjectContext.tsx +252 -0
  54. package/components/ProjectFolderPicker.tsx +202 -0
  55. package/components/ProjectsConfig.tsx +288 -0
  56. package/components/ProviderIcons.tsx +91 -0
  57. package/components/ReportPanel.tsx +237 -0
  58. package/components/ResizeHandle.tsx +105 -0
  59. package/components/SessionSidebar.tsx +1464 -0
  60. package/components/SettingsDialog.tsx +287 -0
  61. package/components/SkillsConfig.tsx +1093 -0
  62. package/components/SubagentPanel.tsx +191 -0
  63. package/components/TabBar.tsx +115 -0
  64. package/components/ToolPanel.tsx +131 -0
  65. package/components/WidgetRenderer.tsx +505 -0
  66. package/components/viewers/DocumentToolbar.tsx +78 -0
  67. package/components/viewers/DocxViewer.tsx +97 -0
  68. package/components/viewers/PdfViewer.tsx +206 -0
  69. package/components/viewers/PptxViewer.tsx +240 -0
  70. package/components/viewers/XlsxViewer.tsx +143 -0
  71. package/hooks/useAgentSession.ts +710 -0
  72. package/hooks/useAudio.ts +50 -0
  73. package/hooks/useDragDrop.ts +52 -0
  74. package/hooks/useResizable.ts +60 -0
  75. package/hooks/useTheme.ts +85 -0
  76. package/lib/agent-client.ts +39 -0
  77. package/lib/annodex-config.ts +556 -0
  78. package/lib/auth-token.ts +74 -0
  79. package/lib/auth.ts +90 -0
  80. package/lib/brand.ts +5 -0
  81. package/lib/code-theme.ts +32 -0
  82. package/lib/codex-compat-proxy.ts +1603 -0
  83. package/lib/codex-home.ts +6 -0
  84. package/lib/codex-server.ts +796 -0
  85. package/lib/codex-session.ts +590 -0
  86. package/lib/codex-usage.ts +213 -0
  87. package/lib/file-paths.ts +34 -0
  88. package/lib/model-discovery.ts +379 -0
  89. package/lib/normalize.ts +30 -0
  90. package/lib/npx.ts +87 -0
  91. package/lib/pi-types.ts +49 -0
  92. package/lib/projects.ts +269 -0
  93. package/lib/provider-api.ts +88 -0
  94. package/lib/report-prompt.ts +61 -0
  95. package/lib/report-store.ts +597 -0
  96. package/lib/report-update-parser.ts +66 -0
  97. package/lib/rpc-manager.ts +668 -0
  98. package/lib/runtime-state.ts +117 -0
  99. package/lib/session-reader.ts +903 -0
  100. package/lib/session-runtime.ts +105 -0
  101. package/lib/subagent-progress.ts +279 -0
  102. package/lib/types.ts +241 -0
  103. package/lib/widget-export.ts +318 -0
  104. package/lib/widget-guidelines.ts +288 -0
  105. package/lib/widget-prompt.ts +76 -0
  106. package/lib/widget-utils.ts +523 -0
  107. package/package.json +23 -18
  108. package/postcss.config.mjs +8 -0
  109. package/proxy.ts +64 -0
  110. package/scripts/postinstall.cjs +25 -0
  111. package/tsconfig.json +41 -0
  112. package/.next/BUILD_ID +0 -1
  113. package/.next/app-path-routes-manifest.json +0 -39
  114. package/.next/build-manifest.json +0 -20
  115. package/.next/diagnostics/build-diagnostics.json +0 -6
  116. package/.next/diagnostics/framework.json +0 -1
  117. package/.next/export-marker.json +0 -6
  118. package/.next/images-manifest.json +0 -68
  119. package/.next/next-minimal-server.js.nft.json +0 -1
  120. package/.next/next-server.js.nft.json +0 -1
  121. package/.next/package.json +0 -1
  122. package/.next/prerender-manifest.json +0 -109
  123. package/.next/react-loadable-manifest.json +0 -2320
  124. package/.next/required-server-files.js +0 -343
  125. package/.next/required-server-files.json +0 -343
  126. package/.next/routes-manifest.json +0 -286
  127. package/.next/server/app/_global-error/page.js +0 -32
  128. package/.next/server/app/_global-error/page.js.nft.json +0 -1
  129. package/.next/server/app/_global-error/page_client-reference-manifest.js +0 -1
  130. package/.next/server/app/_global-error.html +0 -1
  131. package/.next/server/app/_global-error.meta +0 -16
  132. package/.next/server/app/_global-error.rsc +0 -14
  133. package/.next/server/app/_global-error.segments/_full.segment.rsc +0 -14
  134. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +0 -5
  135. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +0 -5
  136. package/.next/server/app/_global-error.segments/_head.segment.rsc +0 -5
  137. package/.next/server/app/_global-error.segments/_index.segment.rsc +0 -5
  138. package/.next/server/app/_global-error.segments/_tree.segment.rsc +0 -1
  139. package/.next/server/app/_not-found/page.js +0 -2
  140. package/.next/server/app/_not-found/page.js.nft.json +0 -1
  141. package/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  142. package/.next/server/app/_not-found.html +0 -1
  143. package/.next/server/app/_not-found.meta +0 -16
  144. package/.next/server/app/_not-found.rsc +0 -18
  145. package/.next/server/app/_not-found.segments/_full.segment.rsc +0 -18
  146. package/.next/server/app/_not-found.segments/_head.segment.rsc +0 -6
  147. package/.next/server/app/_not-found.segments/_index.segment.rsc +0 -5
  148. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +0 -5
  149. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +0 -5
  150. package/.next/server/app/_not-found.segments/_tree.segment.rsc +0 -4
  151. package/.next/server/app/api/agent/[id]/events/route.js +0 -3
  152. package/.next/server/app/api/agent/[id]/events/route.js.nft.json +0 -1
  153. package/.next/server/app/api/agent/[id]/events/route_client-reference-manifest.js +0 -1
  154. package/.next/server/app/api/agent/[id]/route.js +0 -1
  155. package/.next/server/app/api/agent/[id]/route.js.nft.json +0 -1
  156. package/.next/server/app/api/agent/[id]/route_client-reference-manifest.js +0 -1
  157. package/.next/server/app/api/agent/new/route.js +0 -1
  158. package/.next/server/app/api/agent/new/route.js.nft.json +0 -1
  159. package/.next/server/app/api/agent/new/route_client-reference-manifest.js +0 -1
  160. package/.next/server/app/api/auth/all-providers/route.js +0 -1
  161. package/.next/server/app/api/auth/all-providers/route.js.nft.json +0 -1
  162. package/.next/server/app/api/auth/all-providers/route_client-reference-manifest.js +0 -1
  163. package/.next/server/app/api/auth/api-key/[provider]/route.js +0 -1
  164. package/.next/server/app/api/auth/api-key/[provider]/route.js.nft.json +0 -1
  165. package/.next/server/app/api/auth/api-key/[provider]/route_client-reference-manifest.js +0 -1
  166. package/.next/server/app/api/auth/login/[provider]/route.js +0 -1
  167. package/.next/server/app/api/auth/login/[provider]/route.js.nft.json +0 -1
  168. package/.next/server/app/api/auth/login/[provider]/route_client-reference-manifest.js +0 -1
  169. package/.next/server/app/api/auth/login/route.js +0 -1
  170. package/.next/server/app/api/auth/login/route.js.nft.json +0 -1
  171. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +0 -1
  172. package/.next/server/app/api/auth/logout/[provider]/route.js +0 -1
  173. package/.next/server/app/api/auth/logout/[provider]/route.js.nft.json +0 -1
  174. package/.next/server/app/api/auth/logout/[provider]/route_client-reference-manifest.js +0 -1
  175. package/.next/server/app/api/auth/providers/route.js +0 -1
  176. package/.next/server/app/api/auth/providers/route.js.nft.json +0 -1
  177. package/.next/server/app/api/auth/providers/route_client-reference-manifest.js +0 -1
  178. package/.next/server/app/api/auth/status/route.js +0 -1
  179. package/.next/server/app/api/auth/status/route.js.nft.json +0 -1
  180. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +0 -1
  181. package/.next/server/app/api/default-cwd/route.js +0 -1
  182. package/.next/server/app/api/default-cwd/route.js.nft.json +0 -1
  183. package/.next/server/app/api/default-cwd/route_client-reference-manifest.js +0 -1
  184. package/.next/server/app/api/files/[...path]/route.js +0 -4
  185. package/.next/server/app/api/files/[...path]/route.js.nft.json +0 -1
  186. package/.next/server/app/api/files/[...path]/route_client-reference-manifest.js +0 -1
  187. package/.next/server/app/api/harness/route.js +0 -1
  188. package/.next/server/app/api/harness/route.js.nft.json +0 -1
  189. package/.next/server/app/api/harness/route_client-reference-manifest.js +0 -1
  190. package/.next/server/app/api/home/route.js +0 -1
  191. package/.next/server/app/api/home/route.js.nft.json +0 -1
  192. package/.next/server/app/api/home/route_client-reference-manifest.js +0 -1
  193. package/.next/server/app/api/internal/runtime/route.js +0 -1
  194. package/.next/server/app/api/internal/runtime/route.js.nft.json +0 -1
  195. package/.next/server/app/api/internal/runtime/route_client-reference-manifest.js +0 -1
  196. package/.next/server/app/api/models/route.js +0 -1
  197. package/.next/server/app/api/models/route.js.nft.json +0 -1
  198. package/.next/server/app/api/models/route_client-reference-manifest.js +0 -1
  199. package/.next/server/app/api/models-config/discover/route.js +0 -1
  200. package/.next/server/app/api/models-config/discover/route.js.nft.json +0 -1
  201. package/.next/server/app/api/models-config/discover/route_client-reference-manifest.js +0 -1
  202. package/.next/server/app/api/models-config/route.js +0 -1
  203. package/.next/server/app/api/models-config/route.js.nft.json +0 -1
  204. package/.next/server/app/api/models-config/route_client-reference-manifest.js +0 -1
  205. package/.next/server/app/api/models-config/test/route.js +0 -1
  206. package/.next/server/app/api/models-config/test/route.js.nft.json +0 -1
  207. package/.next/server/app/api/models-config/test/route_client-reference-manifest.js +0 -1
  208. package/.next/server/app/api/projects/browse/route.js +0 -1
  209. package/.next/server/app/api/projects/browse/route.js.nft.json +0 -1
  210. package/.next/server/app/api/projects/browse/route_client-reference-manifest.js +0 -1
  211. package/.next/server/app/api/projects/route.js +0 -1
  212. package/.next/server/app/api/projects/route.js.nft.json +0 -1
  213. package/.next/server/app/api/projects/route_client-reference-manifest.js +0 -1
  214. package/.next/server/app/api/reports/[id]/route.js +0 -10
  215. package/.next/server/app/api/reports/[id]/route.js.nft.json +0 -1
  216. package/.next/server/app/api/reports/[id]/route_client-reference-manifest.js +0 -1
  217. package/.next/server/app/api/search/route.js +0 -1
  218. package/.next/server/app/api/search/route.js.nft.json +0 -1
  219. package/.next/server/app/api/search/route_client-reference-manifest.js +0 -1
  220. package/.next/server/app/api/sessions/[id]/context/route.js +0 -1
  221. package/.next/server/app/api/sessions/[id]/context/route.js.nft.json +0 -1
  222. package/.next/server/app/api/sessions/[id]/context/route_client-reference-manifest.js +0 -1
  223. package/.next/server/app/api/sessions/[id]/route.js +0 -1
  224. package/.next/server/app/api/sessions/[id]/route.js.nft.json +0 -1
  225. package/.next/server/app/api/sessions/[id]/route_client-reference-manifest.js +0 -1
  226. package/.next/server/app/api/sessions/new/route.js +0 -1
  227. package/.next/server/app/api/sessions/new/route.js.nft.json +0 -1
  228. package/.next/server/app/api/sessions/new/route_client-reference-manifest.js +0 -1
  229. package/.next/server/app/api/sessions/route.js +0 -1
  230. package/.next/server/app/api/sessions/route.js.nft.json +0 -1
  231. package/.next/server/app/api/sessions/route_client-reference-manifest.js +0 -1
  232. package/.next/server/app/api/settings/route.js +0 -1
  233. package/.next/server/app/api/settings/route.js.nft.json +0 -1
  234. package/.next/server/app/api/settings/route_client-reference-manifest.js +0 -1
  235. package/.next/server/app/api/skills/install/route.js +0 -5
  236. package/.next/server/app/api/skills/install/route.js.nft.json +0 -1
  237. package/.next/server/app/api/skills/install/route_client-reference-manifest.js +0 -1
  238. package/.next/server/app/api/skills/route.js +0 -6
  239. package/.next/server/app/api/skills/route.js.nft.json +0 -1
  240. package/.next/server/app/api/skills/route_client-reference-manifest.js +0 -1
  241. package/.next/server/app/api/skills/search/route.js +0 -1
  242. package/.next/server/app/api/skills/search/route.js.nft.json +0 -1
  243. package/.next/server/app/api/skills/search/route_client-reference-manifest.js +0 -1
  244. package/.next/server/app/api/soul/route.js +0 -1
  245. package/.next/server/app/api/soul/route.js.nft.json +0 -1
  246. package/.next/server/app/api/soul/route_client-reference-manifest.js +0 -1
  247. package/.next/server/app/api/version/route.js +0 -1
  248. package/.next/server/app/api/version/route.js.nft.json +0 -1
  249. package/.next/server/app/api/version/route_client-reference-manifest.js +0 -1
  250. package/.next/server/app/index.html +0 -1
  251. package/.next/server/app/index.meta +0 -14
  252. package/.next/server/app/index.rsc +0 -17
  253. package/.next/server/app/index.segments/__PAGE__.segment.rsc +0 -6
  254. package/.next/server/app/index.segments/_full.segment.rsc +0 -17
  255. package/.next/server/app/index.segments/_head.segment.rsc +0 -6
  256. package/.next/server/app/index.segments/_index.segment.rsc +0 -5
  257. package/.next/server/app/index.segments/_tree.segment.rsc +0 -4
  258. package/.next/server/app/login/page.js +0 -2
  259. package/.next/server/app/login/page.js.nft.json +0 -1
  260. package/.next/server/app/login/page_client-reference-manifest.js +0 -1
  261. package/.next/server/app/login.html +0 -1
  262. package/.next/server/app/login.meta +0 -15
  263. package/.next/server/app/login.rsc +0 -22
  264. package/.next/server/app/login.segments/_full.segment.rsc +0 -22
  265. package/.next/server/app/login.segments/_head.segment.rsc +0 -6
  266. package/.next/server/app/login.segments/_index.segment.rsc +0 -5
  267. package/.next/server/app/login.segments/_tree.segment.rsc +0 -4
  268. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +0 -9
  269. package/.next/server/app/login.segments/login.segment.rsc +0 -5
  270. package/.next/server/app/page.js +0 -261
  271. package/.next/server/app/page.js.nft.json +0 -1
  272. package/.next/server/app/page_client-reference-manifest.js +0 -1
  273. package/.next/server/app-paths-manifest.json +0 -39
  274. package/.next/server/chunks/1048.js +0 -1
  275. package/.next/server/chunks/1367.js +0 -77
  276. package/.next/server/chunks/1381.js +0 -1
  277. package/.next/server/chunks/165.js +0 -1
  278. package/.next/server/chunks/1681.js +0 -215
  279. package/.next/server/chunks/1688.js +0 -45
  280. package/.next/server/chunks/1703.js +0 -79
  281. package/.next/server/chunks/1712.js +0 -43
  282. package/.next/server/chunks/1813.js +0 -1
  283. package/.next/server/chunks/2325.js +0 -80
  284. package/.next/server/chunks/258.js +0 -1
  285. package/.next/server/chunks/2671.js +0 -287
  286. package/.next/server/chunks/2778.js +0 -1
  287. package/.next/server/chunks/2943.js +0 -1
  288. package/.next/server/chunks/3031.js +0 -226
  289. package/.next/server/chunks/3181.js +0 -1
  290. package/.next/server/chunks/3493.js +0 -1
  291. package/.next/server/chunks/3672.js +0 -1
  292. package/.next/server/chunks/3701.js +0 -104
  293. package/.next/server/chunks/4013.js +0 -1
  294. package/.next/server/chunks/402.js +0 -2
  295. package/.next/server/chunks/4035.js +0 -80
  296. package/.next/server/chunks/4248.js +0 -153
  297. package/.next/server/chunks/4367.js +0 -1
  298. package/.next/server/chunks/4406.js +0 -141
  299. package/.next/server/chunks/4741.js +0 -18
  300. package/.next/server/chunks/4768.js +0 -1
  301. package/.next/server/chunks/4858.js +0 -148
  302. package/.next/server/chunks/4980.js +0 -1
  303. package/.next/server/chunks/5155.js +0 -5
  304. package/.next/server/chunks/5293.js +0 -166
  305. package/.next/server/chunks/5399.js +0 -8
  306. package/.next/server/chunks/5409.js +0 -1
  307. package/.next/server/chunks/5797.js +0 -93
  308. package/.next/server/chunks/5851.js +0 -36
  309. package/.next/server/chunks/6206.js +0 -1
  310. package/.next/server/chunks/6296.js +0 -1
  311. package/.next/server/chunks/63.js +0 -45
  312. package/.next/server/chunks/6346.js +0 -1
  313. package/.next/server/chunks/6406.js +0 -23
  314. package/.next/server/chunks/642.js +0 -1
  315. package/.next/server/chunks/6429.js +0 -50
  316. package/.next/server/chunks/6729.js +0 -64
  317. package/.next/server/chunks/6907.js +0 -115
  318. package/.next/server/chunks/6980.js +0 -1
  319. package/.next/server/chunks/7073.js +0 -24
  320. package/.next/server/chunks/7233.js +0 -24
  321. package/.next/server/chunks/7307.js +0 -1
  322. package/.next/server/chunks/7362.js +0 -9
  323. package/.next/server/chunks/7567.js +0 -29
  324. package/.next/server/chunks/7765.js +0 -1
  325. package/.next/server/chunks/7890.js +0 -1
  326. package/.next/server/chunks/8065.js +0 -1
  327. package/.next/server/chunks/8238.js +0 -34
  328. package/.next/server/chunks/8276.js +0 -1
  329. package/.next/server/chunks/8336.js +0 -1
  330. package/.next/server/chunks/8477.js +0 -3
  331. package/.next/server/chunks/8490.js +0 -1
  332. package/.next/server/chunks/8916.js +0 -1
  333. package/.next/server/chunks/9280.js +0 -252
  334. package/.next/server/chunks/9315.js +0 -1
  335. package/.next/server/chunks/9537.js +0 -90
  336. package/.next/server/chunks/966.js +0 -1
  337. package/.next/server/chunks/9818.js +0 -21
  338. package/.next/server/chunks/static/media/pdf.worker.min.c476e1a0.mjs +0 -6
  339. package/.next/server/functions-config-manifest.json +0 -16
  340. package/.next/server/interception-route-rewrite-manifest.js +0 -1
  341. package/.next/server/middleware-build-manifest.js +0 -1
  342. package/.next/server/middleware-manifest.json +0 -6
  343. package/.next/server/middleware-react-loadable-manifest.js +0 -1
  344. package/.next/server/middleware.js +0 -18
  345. package/.next/server/middleware.js.nft.json +0 -1
  346. package/.next/server/next-font-manifest.js +0 -1
  347. package/.next/server/next-font-manifest.json +0 -1
  348. package/.next/server/pages/404.html +0 -1
  349. package/.next/server/pages/500.html +0 -1
  350. package/.next/server/pages-manifest.json +0 -4
  351. package/.next/server/prefetch-hints.json +0 -1
  352. package/.next/server/server-reference-manifest.js +0 -1
  353. package/.next/server/server-reference-manifest.json +0 -1
  354. package/.next/server/webpack-runtime.js +0 -1
  355. package/.next/static/6cuMSvcr0FVO-GiK5RJZh/_buildManifest.js +0 -1
  356. package/.next/static/6cuMSvcr0FVO-GiK5RJZh/_ssgManifest.js +0 -1
  357. package/.next/static/chunks/0b9a0da7.9075af772487e743.js +0 -62
  358. package/.next/static/chunks/1413.922d232de90c0c41.js +0 -115
  359. package/.next/static/chunks/1643.467a526a1f24f54d.js +0 -24
  360. package/.next/static/chunks/1852.5543122f11aa7fed.js +0 -1
  361. package/.next/static/chunks/1960.b1e26436d7a5f586.js +0 -1
  362. package/.next/static/chunks/2170a4aa.4213bb2183c9cdf9.js +0 -1
  363. package/.next/static/chunks/2274.6cd173f80a1405a2.js +0 -21
  364. package/.next/static/chunks/2419.347fdfe3c170854d.js +0 -166
  365. package/.next/static/chunks/2619.9aac8983f30c7c8a.js +0 -1
  366. package/.next/static/chunks/2623.d20fabd8e18197c6.js +0 -287
  367. package/.next/static/chunks/2729.f5365061a849d659.js +0 -34
  368. package/.next/static/chunks/2821.934bcf60fbdc28c6.js +0 -1
  369. package/.next/static/chunks/2918becc.abff2ece1de37bc1.js +0 -153
  370. package/.next/static/chunks/2947.114e51cb06d1c01a.js +0 -23
  371. package/.next/static/chunks/3079.4c511fa1144e3adf.js +0 -79
  372. package/.next/static/chunks/3274.208ca44844cd7d95.js +0 -148
  373. package/.next/static/chunks/3308.465a94263d04bfea.js +0 -73
  374. package/.next/static/chunks/3325.e4bfe1ca657f3b5b.js +0 -80
  375. package/.next/static/chunks/3506.2a7eaa08b9f55337.js +0 -90
  376. package/.next/static/chunks/363642f4-043c1475ab9af70e.js +0 -1
  377. package/.next/static/chunks/3794-123fdf632563f469.js +0 -32
  378. package/.next/static/chunks/3837.a755ccfe6f9c1c1c.js +0 -5
  379. package/.next/static/chunks/394.91597771688df6d0.js +0 -1
  380. package/.next/static/chunks/3997.1009c06025691712.js +0 -1
  381. package/.next/static/chunks/4453.91a357dc43c21745.js +0 -1
  382. package/.next/static/chunks/4491.44fdf20580ac72bd.js +0 -24
  383. package/.next/static/chunks/4829.cf1d50e43e6d9db5.js +0 -1
  384. package/.next/static/chunks/498.fe1d9da9ecad6c36.js +0 -1
  385. package/.next/static/chunks/4bd1b696-e356ca5ba0218e27.js +0 -1
  386. package/.next/static/chunks/5019.b5a1a2b8daf17525.js +0 -1
  387. package/.next/static/chunks/5034.8f16c3fa3ce75411.js +0 -1
  388. package/.next/static/chunks/5074.d16651da01ec4e02.js +0 -1
  389. package/.next/static/chunks/51fb665c.0950e1b79671348d.js +0 -45
  390. package/.next/static/chunks/532.5956ed631aff722b.js +0 -9
  391. package/.next/static/chunks/5326.69460442bdcd6cd3.js +0 -1
  392. package/.next/static/chunks/5403.ff110bf5bf600758.js +0 -64
  393. package/.next/static/chunks/547.902a733488cfe3f7.js +0 -77
  394. package/.next/static/chunks/5567.540d7fc108ad6ee5.js +0 -215
  395. package/.next/static/chunks/5590.ef62922166d308b4.js +0 -1
  396. package/.next/static/chunks/5690.9d6eb1edb1399995.js +0 -1
  397. package/.next/static/chunks/5749.25faee4a1e55b854.js +0 -226
  398. package/.next/static/chunks/58bb9007.1ccb6bba34b4c635.js +0 -80
  399. package/.next/static/chunks/6121.f3f43f1896ea0cd9.js +0 -1
  400. package/.next/static/chunks/6600.583c88eef37aa524.js +0 -1
  401. package/.next/static/chunks/6696.a41aec266e657d54.js +0 -141
  402. package/.next/static/chunks/6922.42148793782d2fe7.js +0 -1
  403. package/.next/static/chunks/7006.e191611ffc2b9528.js +0 -43
  404. package/.next/static/chunks/7343.9fbb58204d8ac681.js +0 -1
  405. package/.next/static/chunks/73972abe.25a4cffa03b2bcef.js +0 -119
  406. package/.next/static/chunks/7547.58bda8a2aabba0d4.js +0 -93
  407. package/.next/static/chunks/7648.4ae2f183b4db0353.js +0 -1
  408. package/.next/static/chunks/7874.8db6929b94cdf697.js +0 -1
  409. package/.next/static/chunks/7959.1f20a35df316216a.js +0 -104
  410. package/.next/static/chunks/83.85d62d7fc9850b75.js +0 -29
  411. package/.next/static/chunks/8436.cab94b59cca0a8ff.js +0 -1
  412. package/.next/static/chunks/8451.ff6ff72b57dc52e1.js +0 -1
  413. package/.next/static/chunks/8489.45f22859734f514f.js +0 -36
  414. package/.next/static/chunks/8568.f85d8b36fc9a9037.js +0 -1
  415. package/.next/static/chunks/8771-3e14b6810486df1f.js +0 -1
  416. package/.next/static/chunks/8863.be51033a67436277.js +0 -1
  417. package/.next/static/chunks/90542734.dc1a2723e4f6affb.js +0 -1
  418. package/.next/static/chunks/9500.1488aec06ee78127.js +0 -1
  419. package/.next/static/chunks/9633.155548b5fca6e580.js +0 -1
  420. package/.next/static/chunks/9779.673004a62d70e36a.js +0 -1
  421. package/.next/static/chunks/app/_global-error/page-cc518af6b1ffb191.js +0 -1
  422. package/.next/static/chunks/app/_not-found/page-c72daab99269beff.js +0 -1
  423. package/.next/static/chunks/app/api/agent/[id]/events/route-cc518af6b1ffb191.js +0 -1
  424. package/.next/static/chunks/app/api/agent/[id]/route-cc518af6b1ffb191.js +0 -1
  425. package/.next/static/chunks/app/api/agent/new/route-cc518af6b1ffb191.js +0 -1
  426. package/.next/static/chunks/app/api/auth/all-providers/route-cc518af6b1ffb191.js +0 -1
  427. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-cc518af6b1ffb191.js +0 -1
  428. package/.next/static/chunks/app/api/auth/login/[provider]/route-cc518af6b1ffb191.js +0 -1
  429. package/.next/static/chunks/app/api/auth/login/route-cc518af6b1ffb191.js +0 -1
  430. package/.next/static/chunks/app/api/auth/logout/[provider]/route-cc518af6b1ffb191.js +0 -1
  431. package/.next/static/chunks/app/api/auth/providers/route-cc518af6b1ffb191.js +0 -1
  432. package/.next/static/chunks/app/api/auth/status/route-cc518af6b1ffb191.js +0 -1
  433. package/.next/static/chunks/app/api/default-cwd/route-cc518af6b1ffb191.js +0 -1
  434. package/.next/static/chunks/app/api/files/[...path]/route-cc518af6b1ffb191.js +0 -1
  435. package/.next/static/chunks/app/api/harness/route-cc518af6b1ffb191.js +0 -1
  436. package/.next/static/chunks/app/api/home/route-cc518af6b1ffb191.js +0 -1
  437. package/.next/static/chunks/app/api/internal/runtime/route-cc518af6b1ffb191.js +0 -1
  438. package/.next/static/chunks/app/api/models/route-cc518af6b1ffb191.js +0 -1
  439. package/.next/static/chunks/app/api/models-config/discover/route-cc518af6b1ffb191.js +0 -1
  440. package/.next/static/chunks/app/api/models-config/route-cc518af6b1ffb191.js +0 -1
  441. package/.next/static/chunks/app/api/models-config/test/route-cc518af6b1ffb191.js +0 -1
  442. package/.next/static/chunks/app/api/projects/browse/route-cc518af6b1ffb191.js +0 -1
  443. package/.next/static/chunks/app/api/projects/route-cc518af6b1ffb191.js +0 -1
  444. package/.next/static/chunks/app/api/reports/[id]/route-cc518af6b1ffb191.js +0 -1
  445. package/.next/static/chunks/app/api/search/route-cc518af6b1ffb191.js +0 -1
  446. package/.next/static/chunks/app/api/sessions/[id]/context/route-cc518af6b1ffb191.js +0 -1
  447. package/.next/static/chunks/app/api/sessions/[id]/route-cc518af6b1ffb191.js +0 -1
  448. package/.next/static/chunks/app/api/sessions/new/route-cc518af6b1ffb191.js +0 -1
  449. package/.next/static/chunks/app/api/sessions/route-cc518af6b1ffb191.js +0 -1
  450. package/.next/static/chunks/app/api/settings/route-cc518af6b1ffb191.js +0 -1
  451. package/.next/static/chunks/app/api/skills/install/route-cc518af6b1ffb191.js +0 -1
  452. package/.next/static/chunks/app/api/skills/route-cc518af6b1ffb191.js +0 -1
  453. package/.next/static/chunks/app/api/skills/search/route-cc518af6b1ffb191.js +0 -1
  454. package/.next/static/chunks/app/api/soul/route-cc518af6b1ffb191.js +0 -1
  455. package/.next/static/chunks/app/api/version/route-cc518af6b1ffb191.js +0 -1
  456. package/.next/static/chunks/app/layout-be148b7ae915b22a.js +0 -1
  457. package/.next/static/chunks/app/login/page-ebf0e6de99062783.js +0 -1
  458. package/.next/static/chunks/app/page-c45d98ea81c548ca.js +0 -260
  459. package/.next/static/chunks/d3ac728e.7964f816a1ca64e5.js +0 -1
  460. package/.next/static/chunks/framework-711ef29bc66f648c.js +0 -1
  461. package/.next/static/chunks/main-app-45a0f19af99d61b6.js +0 -1
  462. package/.next/static/chunks/main-f74964b7ae52493e.js +0 -5
  463. package/.next/static/chunks/next/dist/client/components/builtin/app-error-cc518af6b1ffb191.js +0 -1
  464. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-cc518af6b1ffb191.js +0 -1
  465. package/.next/static/chunks/next/dist/client/components/builtin/global-error-9bfa08b9491621f2.js +0 -1
  466. package/.next/static/chunks/next/dist/client/components/builtin/not-found-cc518af6b1ffb191.js +0 -1
  467. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-cc518af6b1ffb191.js +0 -1
  468. package/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  469. package/.next/static/chunks/webpack-fcf4a889ecbd753c.js +0 -1
  470. package/.next/static/css/45029451a1d7255d.css +0 -3
  471. package/.next/static/media/15605e25b523335c-s.woff2 +0 -0
  472. package/.next/static/media/1a3dce5cfb5f7760-s.woff2 +0 -0
  473. package/.next/static/media/1cdd02902f937a18-s.woff2 +0 -0
  474. package/.next/static/media/4c4b3b30b6bcb2be-s.woff2 +0 -0
  475. package/.next/static/media/641a7b8a5800ee0e-s.woff2 +0 -0
  476. package/.next/static/media/7deddc85b7ffd1dc-s.p.woff2 +0 -0
  477. package/.next/static/media/ec14413c594b3356-s.p.woff2 +0 -0
  478. package/.next/static/media/pdf.worker.min.29aaf158.mjs +0 -6
  479. package/.next/trace +0 -74
  480. package/.next/trace-build +0 -1
  481. package/.next/types/app/api/agent/[id]/events/route.ts +0 -351
  482. package/.next/types/app/api/agent/[id]/route.ts +0 -351
  483. package/.next/types/app/api/agent/new/route.ts +0 -351
  484. package/.next/types/app/api/auth/all-providers/route.ts +0 -351
  485. package/.next/types/app/api/auth/api-key/[provider]/route.ts +0 -351
  486. package/.next/types/app/api/auth/login/[provider]/route.ts +0 -351
  487. package/.next/types/app/api/auth/login/route.ts +0 -351
  488. package/.next/types/app/api/auth/logout/[provider]/route.ts +0 -351
  489. package/.next/types/app/api/auth/providers/route.ts +0 -351
  490. package/.next/types/app/api/auth/status/route.ts +0 -351
  491. package/.next/types/app/api/default-cwd/route.ts +0 -351
  492. package/.next/types/app/api/files/[...path]/route.ts +0 -351
  493. package/.next/types/app/api/harness/route.ts +0 -351
  494. package/.next/types/app/api/home/route.ts +0 -351
  495. package/.next/types/app/api/internal/runtime/route.ts +0 -351
  496. package/.next/types/app/api/models/route.ts +0 -351
  497. package/.next/types/app/api/models-config/discover/route.ts +0 -351
  498. package/.next/types/app/api/models-config/route.ts +0 -351
  499. package/.next/types/app/api/models-config/test/route.ts +0 -351
  500. package/.next/types/app/api/projects/browse/route.ts +0 -351
  501. package/.next/types/app/api/projects/route.ts +0 -351
  502. package/.next/types/app/api/reports/[id]/route.ts +0 -351
  503. package/.next/types/app/api/search/route.ts +0 -351
  504. package/.next/types/app/api/sessions/[id]/context/route.ts +0 -351
  505. package/.next/types/app/api/sessions/[id]/route.ts +0 -351
  506. package/.next/types/app/api/sessions/new/route.ts +0 -351
  507. package/.next/types/app/api/sessions/route.ts +0 -351
  508. package/.next/types/app/api/settings/route.ts +0 -351
  509. package/.next/types/app/api/skills/install/route.ts +0 -351
  510. package/.next/types/app/api/skills/route.ts +0 -351
  511. package/.next/types/app/api/skills/search/route.ts +0 -351
  512. package/.next/types/app/api/soul/route.ts +0 -351
  513. package/.next/types/app/api/version/route.ts +0 -351
  514. package/.next/types/app/layout.ts +0 -87
  515. package/.next/types/app/login/page.ts +0 -87
  516. package/.next/types/app/page.ts +0 -87
  517. package/.next/types/package.json +0 -1
  518. package/.next/types/routes.d.ts +0 -106
  519. package/.next/types/validator.ts +0 -376
@@ -0,0 +1,556 @@
1
+ /**
2
+ * Annodex Config — Hybrid multi-provider configuration
3
+ *
4
+ * Two config sources, merged:
5
+ * 1. ~/.codex/config.toml — codex CLI native (read-only, default model/provider)
6
+ * 2. ~/.config/annodex/providers.json — annodex-managed (API keys, extra providers)
7
+ *
8
+ * Session startup priority:
9
+ * User-selected model in UI → providers.json lookup → config.toml fallback
10
+ */
11
+
12
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
13
+ import { join } from "path";
14
+ import { homedir } from "os";
15
+ import { parse as parseToml } from "smol-toml";
16
+ import { getCodexHome } from "./codex-home";
17
+ import { apiFromCodexWireApi, inferModelApi, isProviderApi, normalizeProviderApi, type ProviderApi, type ReasoningConfig } from "./provider-api";
18
+
19
+ // ============================================================================
20
+ // Types
21
+ // ============================================================================
22
+
23
+ export interface ModelConfig {
24
+ id: string;
25
+ name: string;
26
+ api?: ProviderApi;
27
+ reasoning?: boolean;
28
+ /** Per-model thinking/reasoning parameter mapping for Responses→Chat translation. */
29
+ reasoningConfig?: ReasoningConfig;
30
+ thinkingLevelMap?: Record<string, string | null>;
31
+ contextWindow?: number; // max context window in tokens
32
+ maxTokens?: number; // max output tokens
33
+ input?: string[]; // supported input types e.g. ["text", "image"]
34
+ compat?: Record<string, unknown>;
35
+ }
36
+
37
+ export interface ProviderConfig {
38
+ id: string;
39
+ name: string;
40
+ baseUrl: string;
41
+ apiKey: string;
42
+ api?: ProviderApi;
43
+ /** Per-provider thinking/reasoning parameter mapping for Responses→Chat translation. */
44
+ reasoningConfig?: ReasoningConfig;
45
+ requiresOpenAiAuth?: boolean;
46
+ source?: "annodex" | "codex";
47
+ sourceProviderId?: string;
48
+ models: ModelConfig[];
49
+ }
50
+
51
+ export interface AnnodexProvidersFile {
52
+ providers: ProviderConfig[];
53
+ defaultProvider?: string;
54
+ defaultModel?: string;
55
+ generativeUI?: boolean;
56
+ exists?: boolean;
57
+ }
58
+
59
+ interface CodexTomlProvider {
60
+ name?: string;
61
+ base_url?: string;
62
+ wire_api?: string;
63
+ env_key?: string;
64
+ requires_openai_auth?: boolean;
65
+ }
66
+
67
+ interface CodexTomlConfig {
68
+ model?: string;
69
+ model_provider?: string;
70
+ model_providers?: Record<string, CodexTomlProvider>;
71
+ }
72
+
73
+ interface CodexAuthJson {
74
+ auth_mode?: string;
75
+ OPENAI_API_KEY?: string;
76
+ }
77
+
78
+ export interface ResolvedModelOption {
79
+ provider: string;
80
+ modelId: string;
81
+ name: string;
82
+ api?: ProviderApi;
83
+ reasoning?: boolean;
84
+ thinkingLevelMap?: Record<string, string | null>;
85
+ contextWindow?: number;
86
+ maxTokens?: number;
87
+ input?: string[];
88
+ compat?: Record<string, unknown>;
89
+ }
90
+
91
+ // ============================================================================
92
+ // Paths
93
+ // ============================================================================
94
+
95
+ function getAnnConfigDir(): string {
96
+ return process.env.ANNODEX_CONFIG_DIR
97
+ ?? process.env.ANNOVIBE_CONFIG_DIR
98
+ ?? join(homedir(), ".config", "annodex");
99
+ }
100
+
101
+ function getProvidersPath(): string {
102
+ return join(getAnnConfigDir(), "providers.json");
103
+ }
104
+
105
+ function getCodexConfigPath(): string {
106
+ return join(getCodexHome(), "config.toml");
107
+ }
108
+
109
+ function getCodexAuthPath(): string {
110
+ return join(getCodexHome(), "auth.json");
111
+ }
112
+
113
+ // ============================================================================
114
+ // Defaults
115
+ // ============================================================================
116
+
117
+ /** Known token limits for popular models. Used as fallback when providers.json doesn't specify. */
118
+ const KNOWN_MODEL_DEFAULTS: Record<string, { contextWindow: number; maxTokens: number }> = {
119
+ // OpenAI / Codex
120
+ "gpt-5-codex": { contextWindow: 1_048_576, maxTokens: 128_000 },
121
+ "gpt-5.1-codex-max": { contextWindow: 1_048_576, maxTokens: 128_000 },
122
+ "gpt-5.1-codex-mini": { contextWindow: 1_048_576, maxTokens: 128_000 },
123
+ "gpt-4.1-codex-max": { contextWindow: 1_048_576, maxTokens: 32_768 },
124
+ "gpt-4.1-codex-mini": { contextWindow: 1_048_576, maxTokens: 32_768 },
125
+ // DeepSeek
126
+ "deepseek-chat": { contextWindow: 1_048_576, maxTokens: 8_192 },
127
+ "deepseek-reasoner": { contextWindow: 1_048_576, maxTokens: 8_192 },
128
+ "deepseek-v3": { contextWindow: 1_048_576, maxTokens: 8_192 },
129
+ // Kimi (Moonshot)
130
+ "kimi-k2": { contextWindow: 1_048_576, maxTokens: 8_192 },
131
+ "moonshot-v1-auto": { contextWindow: 1_048_576, maxTokens: 8_192 },
132
+ // GLM (Zhipu)
133
+ "glm-4-plus": { contextWindow: 128_000, maxTokens: 4_096 },
134
+ "glm-4-flash": { contextWindow: 128_000, maxTokens: 4_096 },
135
+ // Qwen
136
+ "qwen-max": { contextWindow: 1_048_576, maxTokens: 8_192 },
137
+ "qwen-plus": { contextWindow: 1_048_576, maxTokens: 8_192 },
138
+ "qwen-turbo": { contextWindow: 1_048_576, maxTokens: 8_192 },
139
+ "qwen3-235b-a22b": { contextWindow: 131_072, maxTokens: 8_192 },
140
+ };
141
+
142
+ export function getKnownModelDefaults(modelId: string | null | undefined): { contextWindow: number; maxTokens: number } | undefined {
143
+ return modelId ? KNOWN_MODEL_DEFAULTS[modelId] : undefined;
144
+ }
145
+
146
+ function defaultProviders(): AnnodexProvidersFile {
147
+ return {
148
+ providers: [],
149
+ exists: false,
150
+ };
151
+ }
152
+
153
+ const CODEX_PROVIDER_PREFIX = "codex:";
154
+
155
+ function codexProviderDisplayId(rawId: string, usedIds: Set<string>): string {
156
+ if (!usedIds.has(rawId)) return rawId;
157
+ let candidate = `${CODEX_PROVIDER_PREFIX}${rawId}`;
158
+ let n = 2;
159
+ while (usedIds.has(candidate)) {
160
+ candidate = `${CODEX_PROVIDER_PREFIX}${rawId}:${n}`;
161
+ n += 1;
162
+ }
163
+ return candidate;
164
+ }
165
+
166
+ // ============================================================================
167
+ // Read codex config.toml
168
+ // ============================================================================
169
+
170
+ function readCodexConfig(): CodexTomlConfig | null {
171
+ const path = getCodexConfigPath();
172
+ if (!existsSync(path)) return null;
173
+ try {
174
+ const raw = readFileSync(path, "utf-8");
175
+ return parseToml(raw) as CodexTomlConfig;
176
+ } catch {
177
+ return null;
178
+ }
179
+ }
180
+
181
+ function readCodexAuth(): CodexAuthJson | null {
182
+ const path = getCodexAuthPath();
183
+ if (!existsSync(path)) return null;
184
+ try {
185
+ return JSON.parse(readFileSync(path, "utf-8")) as CodexAuthJson;
186
+ } catch {
187
+ return null;
188
+ }
189
+ }
190
+
191
+ function codexProviderApiKey(provider: CodexTomlProvider): string {
192
+ if (typeof provider.env_key === "string" && provider.env_key.trim()) return provider.env_key.trim();
193
+ const auth = readCodexAuth();
194
+ if (typeof auth?.OPENAI_API_KEY === "string" && auth.OPENAI_API_KEY.trim()) {
195
+ return auth.OPENAI_API_KEY.trim();
196
+ }
197
+ return "";
198
+ }
199
+
200
+ /** Extract default model + provider from codex config.toml */
201
+ function getCodexDefaults(): { model?: string; providerId?: string; providerName?: string } {
202
+ const cfg = readCodexConfig();
203
+ if (!cfg) return {};
204
+ const model = typeof cfg.model === "string" && cfg.model.trim() ? cfg.model.trim() : undefined;
205
+ const providerId = typeof cfg.model_provider === "string" && cfg.model_provider.trim()
206
+ ? cfg.model_provider.trim()
207
+ : undefined;
208
+ const providerName = providerId ? (cfg.model_providers?.[providerId]?.name ?? providerId) : undefined;
209
+ return {
210
+ model,
211
+ providerId,
212
+ providerName,
213
+ };
214
+ }
215
+
216
+ /** Build provider entries from codex config.toml (without API keys) */
217
+ function getCodexProviders(): ProviderConfig[] {
218
+ const cfg = readCodexConfig();
219
+ if (!cfg?.model_providers) return [];
220
+ const defaultModel = typeof cfg.model === "string" ? cfg.model : "";
221
+ const defaultProvider = typeof cfg.model_provider === "string" ? cfg.model_provider : "";
222
+
223
+ return Object.entries(cfg.model_providers)
224
+ .filter(([, p]) => typeof p.base_url === "string")
225
+ .map(([id, p]) => ({
226
+ id,
227
+ name: p.name ?? id,
228
+ baseUrl: (p.base_url ?? "").replace(/\/+$/, ""),
229
+ apiKey: codexProviderApiKey(p),
230
+ api: apiFromCodexWireApi(p.wire_api, p.base_url, id),
231
+ requiresOpenAiAuth: typeof p.requires_openai_auth === "boolean" ? p.requires_openai_auth : undefined,
232
+ source: "codex" as const,
233
+ sourceProviderId: id,
234
+ models: id === defaultProvider && defaultModel
235
+ ? [{ id: defaultModel, name: defaultModel }]
236
+ : [],
237
+ }));
238
+ }
239
+
240
+ // ============================================================================
241
+ // Read/write annodex providers.json
242
+ // ============================================================================
243
+
244
+ function isRecord(value: unknown): value is Record<string, unknown> {
245
+ return typeof value === "object" && value !== null && !Array.isArray(value);
246
+ }
247
+
248
+ function normalizeStringArray(value: unknown): string[] | undefined {
249
+ if (!Array.isArray(value)) return undefined;
250
+ const strings = value.filter((item): item is string => typeof item === "string" && item.trim().length > 0);
251
+ return strings.length ? strings : undefined;
252
+ }
253
+
254
+ function normalizeThinkingLevelMap(value: unknown): Record<string, string | null> | undefined {
255
+ if (!isRecord(value)) return undefined;
256
+ const normalized: Record<string, string | null> = {};
257
+ for (const [key, entry] of Object.entries(value)) {
258
+ if (!key) continue;
259
+ if (typeof entry === "string") normalized[key] = entry;
260
+ else if (entry === null) normalized[key] = null;
261
+ }
262
+ return Object.keys(normalized).length ? normalized : undefined;
263
+ }
264
+
265
+ function normalizeCompat(value: unknown): Record<string, unknown> | undefined {
266
+ if (!isRecord(value)) return undefined;
267
+ return Object.keys(value).length ? value : undefined;
268
+ }
269
+
270
+ function normalizeReasoningConfig(value: unknown): ReasoningConfig | undefined {
271
+ if (!isRecord(value)) return undefined;
272
+ const config: ReasoningConfig = {};
273
+ if (typeof value.supportsThinking === "boolean") config.supportsThinking = value.supportsThinking;
274
+ if (typeof value.supportsEffort === "boolean") config.supportsEffort = value.supportsEffort;
275
+ if (value.thinkingParam === "thinking" || value.thinkingParam === "enable_thinking") config.thinkingParam = value.thinkingParam;
276
+ if (value.effortParam === "reasoning_effort" || value.effortParam === "reasoning.effort" || value.effortParam === "none" || value.effortParam === null) config.effortParam = value.effortParam;
277
+ if (value.effortValueMode === "deepseek" || value.effortValueMode === "glm" || value.effortValueMode === "openrouter" || value.effortValueMode === "generic") config.effortValueMode = value.effortValueMode;
278
+ if (value.outputFormat === "reasoning_content" || value.outputFormat === "reasoning_details" || value.outputFormat === "reasoning" || value.outputFormat === "think_tags") config.outputFormat = value.outputFormat;
279
+ return Object.keys(config).length ? config : undefined;
280
+ }
281
+
282
+ function normalizeModelConfig(model: unknown): ModelConfig | null {
283
+ if (!isRecord(model) || typeof model.id !== "string") return null;
284
+ const id = model.id.trim();
285
+ if (!id) return null;
286
+ return {
287
+ id,
288
+ name: typeof model.name === "string" && model.name.trim() ? model.name : id,
289
+ api: isProviderApi(model.api) ? model.api : undefined,
290
+ reasoning: typeof model.reasoning === "boolean" ? model.reasoning : undefined,
291
+ reasoningConfig: normalizeReasoningConfig(model.reasoningConfig),
292
+ thinkingLevelMap: normalizeThinkingLevelMap(model.thinkingLevelMap),
293
+ input: normalizeStringArray(model.input),
294
+ contextWindow: typeof model.contextWindow === "number" ? model.contextWindow : undefined,
295
+ maxTokens: typeof model.maxTokens === "number" ? model.maxTokens : undefined,
296
+ compat: normalizeCompat(model.compat),
297
+ };
298
+ }
299
+
300
+ export function readProvidersFile(): AnnodexProvidersFile {
301
+ const path = getProvidersPath();
302
+ if (!existsSync(path)) return defaultProviders();
303
+ try {
304
+ const raw = JSON.parse(readFileSync(path, "utf-8")) as Partial<AnnodexProvidersFile>;
305
+ return {
306
+ providers: Array.isArray(raw.providers)
307
+ ? raw.providers
308
+ .filter((p): p is ProviderConfig =>
309
+ typeof p.id === "string" && typeof p.baseUrl === "string"
310
+ )
311
+ .map((p) => ({
312
+ id: p.id,
313
+ name: typeof p.name === "string" ? p.name : p.id,
314
+ baseUrl: p.baseUrl.replace(/\/+$/, ""),
315
+ apiKey: typeof p.apiKey === "string" ? p.apiKey : "",
316
+ api: normalizeProviderApi(p.api, p.baseUrl, p.id),
317
+ reasoningConfig: normalizeReasoningConfig(p.reasoningConfig),
318
+ requiresOpenAiAuth: typeof p.requiresOpenAiAuth === "boolean" ? p.requiresOpenAiAuth : undefined,
319
+ source: "annodex",
320
+ sourceProviderId: p.id,
321
+ models: Array.isArray(p.models)
322
+ ? p.models
323
+ .map((model) => normalizeModelConfig(model))
324
+ .filter((model): model is ModelConfig => model !== null)
325
+ : [],
326
+ }))
327
+ : defaultProviders().providers,
328
+ defaultProvider: typeof raw.defaultProvider === "string" ? raw.defaultProvider : undefined,
329
+ defaultModel: typeof raw.defaultModel === "string" ? raw.defaultModel : undefined,
330
+ generativeUI: typeof raw.generativeUI === "boolean" ? raw.generativeUI : undefined,
331
+ exists: true,
332
+ };
333
+ } catch {
334
+ return defaultProviders();
335
+ }
336
+ }
337
+
338
+ export function writeProvidersFile(data: AnnodexProvidersFile): AnnodexProvidersFile {
339
+ const dir = getAnnConfigDir();
340
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
341
+ const { exists: _exists, ...persisted } = data;
342
+ void _exists;
343
+ const cleaned: AnnodexProvidersFile = {
344
+ ...persisted,
345
+ providers: persisted.providers.map((provider) => {
346
+ const { source: _source, sourceProviderId: _sourceProviderId, ...savedProvider } = provider;
347
+ void _source;
348
+ void _sourceProviderId;
349
+ return savedProvider;
350
+ }),
351
+ };
352
+ writeFileSync(getProvidersPath(), JSON.stringify(cleaned, null, 2), "utf-8");
353
+ return data;
354
+ }
355
+
356
+ // ============================================================================
357
+ // Merged config (for session spawning)
358
+ // ============================================================================
359
+
360
+ export interface MergedConfig {
361
+ providers: ProviderConfig[];
362
+ defaultModel?: string;
363
+ defaultProvider?: string;
364
+ generativeUI: boolean;
365
+ codexDefaults: { model?: string; providerId?: string; providerName?: string };
366
+ }
367
+
368
+ function providerHasModel(provider: ProviderConfig, modelId: string): boolean {
369
+ return provider.models.length === 0 || provider.models.some((m) => m.id === modelId);
370
+ }
371
+
372
+ function providerSameEndpoint(a: ProviderConfig, b: ProviderConfig): boolean {
373
+ return Boolean(a.baseUrl && b.baseUrl && a.baseUrl.replace(/\/+$/, "") === b.baseUrl.replace(/\/+$/, ""));
374
+ }
375
+
376
+ function applyCodexAuthFallbacks(provider: ProviderConfig, codexProviders: ProviderConfig[]): ProviderConfig {
377
+ const fallback = codexProviders.find((candidate) =>
378
+ candidate.sourceProviderId === provider.id || providerSameEndpoint(candidate, provider)
379
+ );
380
+ if (!fallback) return provider;
381
+ return {
382
+ ...provider,
383
+ apiKey: provider.apiKey || fallback.apiKey,
384
+ requiresOpenAiAuth: provider.requiresOpenAiAuth ?? fallback.requiresOpenAiAuth,
385
+ };
386
+ }
387
+
388
+ function applyModelApiDefaults(provider: ProviderConfig): ProviderConfig {
389
+ const models = provider.models.map((model) => ({
390
+ ...model,
391
+ api: model.api ?? inferModelApi(model.id, provider.api, provider.baseUrl, provider.id),
392
+ }));
393
+ return { ...provider, models };
394
+ }
395
+
396
+ export function readMergedConfig(): MergedConfig {
397
+ const annProviders = readProvidersFile();
398
+ const rawCodexProviders = getCodexProviders();
399
+ const codexDefaults = getCodexDefaults();
400
+
401
+ // Preserve provider identity across sources. UI-managed providers and
402
+ // ~/.codex/config.toml providers may legitimately share an id/model name
403
+ // while pointing at different credentials or protocols.
404
+ const annodexProviders = annProviders.providers.map((provider) => applyCodexAuthFallbacks(provider, rawCodexProviders));
405
+ const usedProviderIds = new Set(annodexProviders.map((p) => p.id));
406
+ const codexProviderIdByRaw = new Map<string, string>();
407
+ const codexProviders = rawCodexProviders.map((provider) => {
408
+ const id = codexProviderDisplayId(provider.id, usedProviderIds);
409
+ usedProviderIds.add(id);
410
+ codexProviderIdByRaw.set(provider.sourceProviderId ?? provider.id, id);
411
+ return {
412
+ ...provider,
413
+ id,
414
+ name: id === provider.id ? provider.name : `${provider.name || provider.id} (Codex)`,
415
+ };
416
+ });
417
+
418
+ const mergedProviders = [...annodexProviders];
419
+ for (const cp of codexProviders) {
420
+ mergedProviders.push(cp);
421
+ }
422
+
423
+ const defaultProvider = codexDefaults.providerId
424
+ ? (codexProviderIdByRaw.get(codexDefaults.providerId) ?? codexDefaults.providerId)
425
+ : undefined;
426
+ const mappedCodexDefaults = {
427
+ ...codexDefaults,
428
+ providerId: defaultProvider,
429
+ };
430
+
431
+ return {
432
+ providers: mergedProviders.map((provider) => applyModelApiDefaults(provider)),
433
+ defaultModel: codexDefaults.model,
434
+ defaultProvider,
435
+ generativeUI: annProviders.generativeUI !== false,
436
+ codexDefaults: mappedCodexDefaults,
437
+ };
438
+ }
439
+
440
+ // ============================================================================
441
+ // Queries
442
+ // ============================================================================
443
+
444
+ export function findProvider(
445
+ config: MergedConfig,
446
+ providerId: string,
447
+ ): ProviderConfig | undefined {
448
+ return config.providers.find((p) => p.id === providerId);
449
+ }
450
+
451
+ export function findCodexProvider(
452
+ config: MergedConfig,
453
+ rawProviderId: string,
454
+ ): ProviderConfig | undefined {
455
+ return config.providers.find((p) => p.source === "codex" && p.sourceProviderId === rawProviderId);
456
+ }
457
+
458
+ export function normalizeRuntimeProviderId(
459
+ config: MergedConfig,
460
+ providerId: string | undefined,
461
+ opts: { preferCodex?: boolean } = {},
462
+ ): string | undefined {
463
+ if (!providerId) return undefined;
464
+ if (opts.preferCodex) return findCodexProvider(config, providerId)?.id ?? providerId;
465
+ return findProvider(config, providerId)?.id ?? findCodexProvider(config, providerId)?.id ?? providerId;
466
+ }
467
+
468
+ export function findModelProvider(
469
+ config: MergedConfig,
470
+ modelId: string,
471
+ ): ProviderConfig | undefined {
472
+ for (const provider of config.providers) {
473
+ if (provider.models.some((m) => m.id === modelId)) return provider;
474
+ }
475
+ return undefined;
476
+ }
477
+
478
+ export function resolveModel(
479
+ config: MergedConfig,
480
+ modelId?: string,
481
+ providerId?: string,
482
+ ): { provider: ProviderConfig; modelId: string } | null {
483
+ const id = modelId || config.defaultModel;
484
+ if (!id) return null;
485
+
486
+ const explicitProvider = providerId ? findProvider(config, providerId) : undefined;
487
+ if (explicitProvider) {
488
+ if (providerHasModel(explicitProvider, id)) {
489
+ return { provider: explicitProvider, modelId: id };
490
+ }
491
+ }
492
+
493
+ if (config.defaultProvider && config.defaultModel === id) {
494
+ const defaultProvider = findProvider(config, config.defaultProvider);
495
+ if (defaultProvider && providerHasModel(defaultProvider, id)) {
496
+ return { provider: defaultProvider, modelId: id };
497
+ }
498
+ }
499
+
500
+ const provider = findModelProvider(config, id);
501
+ if (!provider) return null;
502
+ return { provider, modelId: id };
503
+ }
504
+
505
+ // ============================================================================
506
+ // Model list for UI
507
+ // ============================================================================
508
+
509
+ export function listAllModels(config: MergedConfig): ResolvedModelOption[] {
510
+ const models: ResolvedModelOption[] = [];
511
+ for (const provider of config.providers) {
512
+ for (const model of provider.models) {
513
+ const known = KNOWN_MODEL_DEFAULTS[model.id];
514
+ models.push({
515
+ provider: provider.id,
516
+ modelId: model.id,
517
+ name: model.name || model.id,
518
+ api: model.api,
519
+ reasoning: model.reasoning,
520
+ thinkingLevelMap: model.thinkingLevelMap,
521
+ contextWindow: model.contextWindow ?? known?.contextWindow,
522
+ maxTokens: model.maxTokens ?? known?.maxTokens,
523
+ input: model.input,
524
+ compat: model.compat,
525
+ });
526
+ }
527
+ }
528
+ return models;
529
+ }
530
+
531
+ export function getDefaultModel(
532
+ config: MergedConfig,
533
+ ): { provider: string; modelId: string } | null {
534
+ // 1. Codex config.toml default model
535
+ if (config.codexDefaults.model) {
536
+ const resolved = resolveModel(config, config.codexDefaults.model, config.codexDefaults.providerId);
537
+ if (resolved) return { provider: resolved.provider.id, modelId: resolved.modelId };
538
+ if (config.codexDefaults.providerId) {
539
+ return { provider: config.codexDefaults.providerId, modelId: config.codexDefaults.model };
540
+ }
541
+ }
542
+ // 2. Annodex providers.json defaultProvider / defaultModel
543
+ const annProviders = config.providers.filter((p) => p.source === "annodex");
544
+ for (const provider of annProviders) {
545
+ if (provider.models.length > 0) {
546
+ return { provider: provider.id, modelId: provider.models[0].id };
547
+ }
548
+ }
549
+ // 3. First available model from any provider
550
+ for (const provider of config.providers) {
551
+ if (provider.models.length > 0) {
552
+ return { provider: provider.id, modelId: provider.models[0].id };
553
+ }
554
+ }
555
+ return null;
556
+ }
@@ -0,0 +1,74 @@
1
+ export const COOKIE_NAME = "annodex-auth";
2
+ export const LEGACY_COOKIE_NAME = "annovibe-auth";
3
+ export const PIDEX_COOKIE_NAME = "pidex-auth";
4
+ const COOKIE_MAX_AGE = 30 * 24 * 60 * 60; // 30 days
5
+
6
+ function getSecret(): string {
7
+ return process.env.ANNODEX_AUTH_SECRET
8
+ ?? process.env.ANNOVIBE_AUTH_SECRET
9
+ ?? process.env.PIDEX_AUTH_SECRET
10
+ ?? "annodex-default-secret";
11
+ }
12
+
13
+ function randomHex(bytes: number): string {
14
+ const data = new Uint8Array(bytes);
15
+ globalThis.crypto.getRandomValues(data);
16
+ return Array.from(data, (b) => b.toString(16).padStart(2, "0")).join("");
17
+ }
18
+
19
+ async function hmacHex(secret: string, payload: string): Promise<string> {
20
+ const encoder = new TextEncoder();
21
+ const key = await globalThis.crypto.subtle.importKey(
22
+ "raw",
23
+ encoder.encode(secret),
24
+ { name: "HMAC", hash: "SHA-256" },
25
+ false,
26
+ ["sign"],
27
+ );
28
+ const signature = await globalThis.crypto.subtle.sign("HMAC", key, encoder.encode(payload));
29
+ return Array.from(new Uint8Array(signature), (b) => b.toString(16).padStart(2, "0")).join("");
30
+ }
31
+
32
+ function constantTimeEqual(a: string, b: string): boolean {
33
+ if (a.length !== b.length) return false;
34
+ let ok = 0;
35
+ for (let i = 0; i < a.length; i++) ok |= a.charCodeAt(i) ^ b.charCodeAt(i);
36
+ return ok === 0;
37
+ }
38
+
39
+ export async function createAuthToken(secret?: string): Promise<string> {
40
+ const key = secret ?? getSecret();
41
+ const payload = `${Date.now()}:${randomHex(16)}`;
42
+ const sig = await hmacHex(key, payload);
43
+ return `${payload}:${sig}`;
44
+ }
45
+
46
+ export async function verifyAuthToken(token: string, secret?: string): Promise<boolean> {
47
+ try {
48
+ const key = secret ?? getSecret();
49
+ const parts = token.split(":");
50
+ const sig = parts.pop();
51
+ const payload = parts.join(":");
52
+ if (!sig || !payload) return false;
53
+ const expected = await hmacHex(key, payload);
54
+ return constantTimeEqual(sig, expected);
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ export function getAuthCookieHeader(token: string): string {
61
+ return `${COOKIE_NAME}=${token}; HttpOnly; SameSite=Lax; Path=/; Max-Age=${COOKIE_MAX_AGE}`;
62
+ }
63
+
64
+ export function getClearCookieHeader(): string {
65
+ return `${COOKIE_NAME}=; HttpOnly; SameSite=Lax; Path=/; Max-Age=0`;
66
+ }
67
+
68
+ export function getClearLegacyCookieHeader(): string {
69
+ return `${LEGACY_COOKIE_NAME}=; HttpOnly; SameSite=Lax; Path=/; Max-Age=0`;
70
+ }
71
+
72
+ export function getClearPidexCookieHeader(): string {
73
+ return `${PIDEX_COOKIE_NAME}=; HttpOnly; SameSite=Lax; Path=/; Max-Age=0`;
74
+ }