@seqyuan/annodex 0.1.11 → 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/chunks/0b9a0da7.9075af772487e743.js +0 -62
  356. package/.next/static/chunks/1413.922d232de90c0c41.js +0 -115
  357. package/.next/static/chunks/1643.467a526a1f24f54d.js +0 -24
  358. package/.next/static/chunks/1852.5543122f11aa7fed.js +0 -1
  359. package/.next/static/chunks/1960.b1e26436d7a5f586.js +0 -1
  360. package/.next/static/chunks/2170a4aa.4213bb2183c9cdf9.js +0 -1
  361. package/.next/static/chunks/2274.6cd173f80a1405a2.js +0 -21
  362. package/.next/static/chunks/2419.347fdfe3c170854d.js +0 -166
  363. package/.next/static/chunks/2619.9aac8983f30c7c8a.js +0 -1
  364. package/.next/static/chunks/2623.d20fabd8e18197c6.js +0 -287
  365. package/.next/static/chunks/2729.f5365061a849d659.js +0 -34
  366. package/.next/static/chunks/2821.934bcf60fbdc28c6.js +0 -1
  367. package/.next/static/chunks/2918becc.abff2ece1de37bc1.js +0 -153
  368. package/.next/static/chunks/2947.114e51cb06d1c01a.js +0 -23
  369. package/.next/static/chunks/3079.4c511fa1144e3adf.js +0 -79
  370. package/.next/static/chunks/3274.208ca44844cd7d95.js +0 -148
  371. package/.next/static/chunks/3308.465a94263d04bfea.js +0 -73
  372. package/.next/static/chunks/3325.e4bfe1ca657f3b5b.js +0 -80
  373. package/.next/static/chunks/3506.2a7eaa08b9f55337.js +0 -90
  374. package/.next/static/chunks/363642f4-043c1475ab9af70e.js +0 -1
  375. package/.next/static/chunks/3794-123fdf632563f469.js +0 -32
  376. package/.next/static/chunks/3837.a755ccfe6f9c1c1c.js +0 -5
  377. package/.next/static/chunks/394.91597771688df6d0.js +0 -1
  378. package/.next/static/chunks/3997.1009c06025691712.js +0 -1
  379. package/.next/static/chunks/4453.91a357dc43c21745.js +0 -1
  380. package/.next/static/chunks/4491.44fdf20580ac72bd.js +0 -24
  381. package/.next/static/chunks/4829.cf1d50e43e6d9db5.js +0 -1
  382. package/.next/static/chunks/498.fe1d9da9ecad6c36.js +0 -1
  383. package/.next/static/chunks/4bd1b696-e356ca5ba0218e27.js +0 -1
  384. package/.next/static/chunks/5019.b5a1a2b8daf17525.js +0 -1
  385. package/.next/static/chunks/5034.8f16c3fa3ce75411.js +0 -1
  386. package/.next/static/chunks/5074.d16651da01ec4e02.js +0 -1
  387. package/.next/static/chunks/51fb665c.0950e1b79671348d.js +0 -45
  388. package/.next/static/chunks/532.5956ed631aff722b.js +0 -9
  389. package/.next/static/chunks/5326.69460442bdcd6cd3.js +0 -1
  390. package/.next/static/chunks/5403.ff110bf5bf600758.js +0 -64
  391. package/.next/static/chunks/547.902a733488cfe3f7.js +0 -77
  392. package/.next/static/chunks/5567.540d7fc108ad6ee5.js +0 -215
  393. package/.next/static/chunks/5590.ef62922166d308b4.js +0 -1
  394. package/.next/static/chunks/5690.9d6eb1edb1399995.js +0 -1
  395. package/.next/static/chunks/5749.25faee4a1e55b854.js +0 -226
  396. package/.next/static/chunks/58bb9007.1ccb6bba34b4c635.js +0 -80
  397. package/.next/static/chunks/6121.f3f43f1896ea0cd9.js +0 -1
  398. package/.next/static/chunks/6600.583c88eef37aa524.js +0 -1
  399. package/.next/static/chunks/6696.a41aec266e657d54.js +0 -141
  400. package/.next/static/chunks/6922.42148793782d2fe7.js +0 -1
  401. package/.next/static/chunks/7006.e191611ffc2b9528.js +0 -43
  402. package/.next/static/chunks/7343.9fbb58204d8ac681.js +0 -1
  403. package/.next/static/chunks/73972abe.25a4cffa03b2bcef.js +0 -119
  404. package/.next/static/chunks/7547.58bda8a2aabba0d4.js +0 -93
  405. package/.next/static/chunks/7648.4ae2f183b4db0353.js +0 -1
  406. package/.next/static/chunks/7874.8db6929b94cdf697.js +0 -1
  407. package/.next/static/chunks/7959.1f20a35df316216a.js +0 -104
  408. package/.next/static/chunks/83.85d62d7fc9850b75.js +0 -29
  409. package/.next/static/chunks/8436.cab94b59cca0a8ff.js +0 -1
  410. package/.next/static/chunks/8451.ff6ff72b57dc52e1.js +0 -1
  411. package/.next/static/chunks/8489.45f22859734f514f.js +0 -36
  412. package/.next/static/chunks/8568.f85d8b36fc9a9037.js +0 -1
  413. package/.next/static/chunks/8771-3e14b6810486df1f.js +0 -1
  414. package/.next/static/chunks/8863.be51033a67436277.js +0 -1
  415. package/.next/static/chunks/90542734.dc1a2723e4f6affb.js +0 -1
  416. package/.next/static/chunks/9500.1488aec06ee78127.js +0 -1
  417. package/.next/static/chunks/9633.155548b5fca6e580.js +0 -1
  418. package/.next/static/chunks/9779.673004a62d70e36a.js +0 -1
  419. package/.next/static/chunks/app/_global-error/page-cc518af6b1ffb191.js +0 -1
  420. package/.next/static/chunks/app/_not-found/page-c72daab99269beff.js +0 -1
  421. package/.next/static/chunks/app/api/agent/[id]/events/route-cc518af6b1ffb191.js +0 -1
  422. package/.next/static/chunks/app/api/agent/[id]/route-cc518af6b1ffb191.js +0 -1
  423. package/.next/static/chunks/app/api/agent/new/route-cc518af6b1ffb191.js +0 -1
  424. package/.next/static/chunks/app/api/auth/all-providers/route-cc518af6b1ffb191.js +0 -1
  425. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-cc518af6b1ffb191.js +0 -1
  426. package/.next/static/chunks/app/api/auth/login/[provider]/route-cc518af6b1ffb191.js +0 -1
  427. package/.next/static/chunks/app/api/auth/login/route-cc518af6b1ffb191.js +0 -1
  428. package/.next/static/chunks/app/api/auth/logout/[provider]/route-cc518af6b1ffb191.js +0 -1
  429. package/.next/static/chunks/app/api/auth/providers/route-cc518af6b1ffb191.js +0 -1
  430. package/.next/static/chunks/app/api/auth/status/route-cc518af6b1ffb191.js +0 -1
  431. package/.next/static/chunks/app/api/default-cwd/route-cc518af6b1ffb191.js +0 -1
  432. package/.next/static/chunks/app/api/files/[...path]/route-cc518af6b1ffb191.js +0 -1
  433. package/.next/static/chunks/app/api/harness/route-cc518af6b1ffb191.js +0 -1
  434. package/.next/static/chunks/app/api/home/route-cc518af6b1ffb191.js +0 -1
  435. package/.next/static/chunks/app/api/internal/runtime/route-cc518af6b1ffb191.js +0 -1
  436. package/.next/static/chunks/app/api/models/route-cc518af6b1ffb191.js +0 -1
  437. package/.next/static/chunks/app/api/models-config/discover/route-cc518af6b1ffb191.js +0 -1
  438. package/.next/static/chunks/app/api/models-config/route-cc518af6b1ffb191.js +0 -1
  439. package/.next/static/chunks/app/api/models-config/test/route-cc518af6b1ffb191.js +0 -1
  440. package/.next/static/chunks/app/api/projects/browse/route-cc518af6b1ffb191.js +0 -1
  441. package/.next/static/chunks/app/api/projects/route-cc518af6b1ffb191.js +0 -1
  442. package/.next/static/chunks/app/api/reports/[id]/route-cc518af6b1ffb191.js +0 -1
  443. package/.next/static/chunks/app/api/search/route-cc518af6b1ffb191.js +0 -1
  444. package/.next/static/chunks/app/api/sessions/[id]/context/route-cc518af6b1ffb191.js +0 -1
  445. package/.next/static/chunks/app/api/sessions/[id]/route-cc518af6b1ffb191.js +0 -1
  446. package/.next/static/chunks/app/api/sessions/new/route-cc518af6b1ffb191.js +0 -1
  447. package/.next/static/chunks/app/api/sessions/route-cc518af6b1ffb191.js +0 -1
  448. package/.next/static/chunks/app/api/settings/route-cc518af6b1ffb191.js +0 -1
  449. package/.next/static/chunks/app/api/skills/install/route-cc518af6b1ffb191.js +0 -1
  450. package/.next/static/chunks/app/api/skills/route-cc518af6b1ffb191.js +0 -1
  451. package/.next/static/chunks/app/api/skills/search/route-cc518af6b1ffb191.js +0 -1
  452. package/.next/static/chunks/app/api/soul/route-cc518af6b1ffb191.js +0 -1
  453. package/.next/static/chunks/app/api/version/route-cc518af6b1ffb191.js +0 -1
  454. package/.next/static/chunks/app/layout-be148b7ae915b22a.js +0 -1
  455. package/.next/static/chunks/app/login/page-ebf0e6de99062783.js +0 -1
  456. package/.next/static/chunks/app/page-a4bfb7d711561cb3.js +0 -260
  457. package/.next/static/chunks/d3ac728e.7964f816a1ca64e5.js +0 -1
  458. package/.next/static/chunks/framework-711ef29bc66f648c.js +0 -1
  459. package/.next/static/chunks/main-app-45a0f19af99d61b6.js +0 -1
  460. package/.next/static/chunks/main-f74964b7ae52493e.js +0 -5
  461. package/.next/static/chunks/next/dist/client/components/builtin/app-error-cc518af6b1ffb191.js +0 -1
  462. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-cc518af6b1ffb191.js +0 -1
  463. package/.next/static/chunks/next/dist/client/components/builtin/global-error-9bfa08b9491621f2.js +0 -1
  464. package/.next/static/chunks/next/dist/client/components/builtin/not-found-cc518af6b1ffb191.js +0 -1
  465. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-cc518af6b1ffb191.js +0 -1
  466. package/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  467. package/.next/static/chunks/webpack-fcf4a889ecbd753c.js +0 -1
  468. package/.next/static/css/45029451a1d7255d.css +0 -3
  469. package/.next/static/lFCcFmLd1ThQXTFUP6olh/_buildManifest.js +0 -1
  470. package/.next/static/lFCcFmLd1ThQXTFUP6olh/_ssgManifest.js +0 -1
  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,213 @@
1
+ import { existsSync, readFileSync } from "fs";
2
+ import type { AssistantMessage } from "./types";
3
+ import { getKnownModelDefaults, listAllModels, readMergedConfig } from "./annodex-config";
4
+
5
+ interface UsageNumbers {
6
+ inputTokens: number;
7
+ outputTokens: number;
8
+ totalTokens: number;
9
+ cachedTokens: number;
10
+ }
11
+
12
+ interface UsageSnapshot {
13
+ turnId: string | null;
14
+ observedAt: string;
15
+ last: UsageNumbers;
16
+ total: UsageNumbers;
17
+ contextWindow: number;
18
+ }
19
+
20
+ export interface CodexSessionUsage {
21
+ messageUsageByTurnId: Map<string, AssistantMessage["usage"]>;
22
+ sessionStats: {
23
+ tokens: { input: number; output: number; cacheRead: number; cacheWrite: number };
24
+ cost: number;
25
+ } | null;
26
+ contextUsage: { percent: number | null; contextWindow: number; tokens: number | null } | null;
27
+ }
28
+
29
+ function isRecord(value: unknown): value is Record<string, unknown> {
30
+ return typeof value === "object" && value !== null && !Array.isArray(value);
31
+ }
32
+
33
+ function numberValue(value: unknown): number {
34
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
35
+ }
36
+
37
+ function parseUsageNumbers(value: unknown): UsageNumbers {
38
+ if (!isRecord(value)) {
39
+ return { inputTokens: 0, outputTokens: 0, totalTokens: 0, cachedTokens: 0 };
40
+ }
41
+ const inputTokens = numberValue(value.input_tokens ?? value.prompt_tokens ?? value.promptTokenCount);
42
+ const outputTokens = numberValue(value.output_tokens ?? value.completion_tokens ?? value.candidatesTokenCount);
43
+ const cachedTokens = numberValue(
44
+ value.cached_input_tokens
45
+ ?? value.cache_read_input_tokens
46
+ ?? value.prompt_cache_hit_tokens
47
+ ?? (isRecord(value.input_tokens_details) ? value.input_tokens_details.cached_tokens : undefined)
48
+ ?? (isRecord(value.prompt_tokens_details) ? value.prompt_tokens_details.cached_tokens : undefined)
49
+ ?? value.cachedContentTokenCount,
50
+ );
51
+ const totalTokens = numberValue(value.total_tokens ?? value.totalTokens) || inputTokens + outputTokens;
52
+ return { inputTokens, outputTokens, totalTokens, cachedTokens };
53
+ }
54
+
55
+ function hasUsage(usage: UsageNumbers): boolean {
56
+ return usage.inputTokens > 0 || usage.outputTokens > 0 || usage.totalTokens > 0 || usage.cachedTokens > 0;
57
+ }
58
+
59
+ function usageKey(snapshot: UsageSnapshot): string {
60
+ return [
61
+ snapshot.turnId ?? "",
62
+ snapshot.last.inputTokens,
63
+ snapshot.last.outputTokens,
64
+ snapshot.last.totalTokens,
65
+ snapshot.last.cachedTokens,
66
+ snapshot.total.inputTokens,
67
+ snapshot.total.outputTokens,
68
+ snapshot.total.totalTokens,
69
+ snapshot.total.cachedTokens,
70
+ snapshot.contextWindow,
71
+ ].join("|");
72
+ }
73
+
74
+ function parseJsonLine(line: string): Record<string, unknown> | null {
75
+ try {
76
+ const parsed = JSON.parse(line) as unknown;
77
+ return isRecord(parsed) ? parsed : null;
78
+ } catch {
79
+ return null;
80
+ }
81
+ }
82
+
83
+ function payloadRecord(line: Record<string, unknown>): Record<string, unknown> | null {
84
+ return isRecord(line.payload) ? line.payload : null;
85
+ }
86
+
87
+ function contextWindowForModel(modelId?: string | null): number {
88
+ if (!modelId) return 0;
89
+ const known = getKnownModelDefaults(modelId);
90
+ if (known?.contextWindow) return known.contextWindow;
91
+ try {
92
+ const match = listAllModels(readMergedConfig()).find((model) => model.modelId === modelId);
93
+ return match?.contextWindow ?? 0;
94
+ } catch {
95
+ return 0;
96
+ }
97
+ }
98
+
99
+ function assistantUsageFromSnapshot(snapshot: UsageSnapshot): AssistantMessage["usage"] {
100
+ const input = snapshot.last.inputTokens;
101
+ const output = snapshot.last.outputTokens;
102
+ const cacheRead = snapshot.last.cachedTokens;
103
+ return {
104
+ input,
105
+ output,
106
+ cacheRead,
107
+ cacheWrite: 0,
108
+ cost: {
109
+ input: 0,
110
+ output: 0,
111
+ cacheRead: 0,
112
+ cacheWrite: 0,
113
+ total: 0,
114
+ },
115
+ };
116
+ }
117
+
118
+ export function readCodexUsageFromFile(filePath: string | null, fallbackModelId?: string | null): CodexSessionUsage {
119
+ if (!filePath || !existsSync(filePath)) {
120
+ return { messageUsageByTurnId: new Map(), sessionStats: null, contextUsage: null };
121
+ }
122
+
123
+ let content = "";
124
+ try {
125
+ content = readFileSync(filePath, "utf-8");
126
+ } catch {
127
+ return { messageUsageByTurnId: new Map(), sessionStats: null, contextUsage: null };
128
+ }
129
+
130
+ const snapshots: UsageSnapshot[] = [];
131
+ let currentTurnId: string | null = null;
132
+ let currentModelId = fallbackModelId ?? null;
133
+ let lastKey = "";
134
+
135
+ for (const line of content.split("\n")) {
136
+ if (!line.trim()) continue;
137
+ const item = parseJsonLine(line);
138
+ if (!item) continue;
139
+ const payload = payloadRecord(item) ?? item;
140
+
141
+ if (item.type === "turn_context") {
142
+ currentTurnId = typeof payload.turn_id === "string" ? payload.turn_id : null;
143
+ if (typeof payload.model === "string" && payload.model.trim()) currentModelId = payload.model;
144
+ continue;
145
+ }
146
+
147
+ if (item.type !== "event_msg" || payload.type !== "token_count" || !isRecord(payload.info)) {
148
+ continue;
149
+ }
150
+
151
+ const last = parseUsageNumbers(payload.info.last_token_usage);
152
+ const total = parseUsageNumbers(payload.info.total_token_usage);
153
+ const contextWindow = numberValue(payload.info.model_context_window) || contextWindowForModel(currentModelId);
154
+ const contextTokens = total.totalTokens || last.totalTokens;
155
+ if (!hasUsage(last) && !hasUsage(total) && contextTokens <= 0) continue;
156
+
157
+ const snapshot: UsageSnapshot = {
158
+ turnId: currentTurnId,
159
+ observedAt: typeof item.timestamp === "string" ? item.timestamp : "",
160
+ last,
161
+ total,
162
+ contextWindow,
163
+ };
164
+ const key = usageKey(snapshot);
165
+ if (key === lastKey) continue;
166
+ lastKey = key;
167
+ snapshots.push(snapshot);
168
+ }
169
+
170
+ const byTurn = new Map<string, UsageSnapshot>();
171
+ for (const snapshot of snapshots) {
172
+ if (snapshot.turnId) byTurn.set(snapshot.turnId, snapshot);
173
+ }
174
+
175
+ const messageUsageByTurnId = new Map<string, AssistantMessage["usage"]>();
176
+ for (const [turnId, snapshot] of byTurn) {
177
+ messageUsageByTurnId.set(turnId, assistantUsageFromSnapshot(snapshot));
178
+ }
179
+
180
+ const latest = snapshots[snapshots.length - 1];
181
+ const total = latest?.total;
182
+ const totalInput = total?.inputTokens ?? 0;
183
+ const totalOutput = total?.outputTokens ?? 0;
184
+ const totalCacheRead = total?.cachedTokens ?? 0;
185
+ const sessionTotal = totalInput + totalOutput + totalCacheRead;
186
+ const sessionStats = sessionTotal > 0
187
+ ? {
188
+ tokens: {
189
+ input: totalInput,
190
+ output: totalOutput,
191
+ cacheRead: totalCacheRead,
192
+ cacheWrite: 0,
193
+ },
194
+ cost: 0,
195
+ }
196
+ : null;
197
+
198
+ const contextWindow = latest?.contextWindow ?? contextWindowForModel(currentModelId);
199
+ const contextTokens = latest ? (latest.last.totalTokens || latest.last.inputTokens || null) : null;
200
+ const contextUsage = contextWindow > 0
201
+ ? {
202
+ percent: contextTokens !== null ? Math.min(100, (contextTokens / contextWindow) * 100) : null,
203
+ contextWindow,
204
+ tokens: contextTokens,
205
+ }
206
+ : null;
207
+
208
+ return { messageUsageByTurnId, sessionStats, contextUsage };
209
+ }
210
+
211
+ export const __codexUsageTest = {
212
+ readCodexUsageFromFile,
213
+ };
@@ -0,0 +1,34 @@
1
+ export function normalizeFilePathSlashes(filePath: string): string {
2
+ if (/^[a-zA-Z]:[\\/]/.test(filePath) || filePath.startsWith("\\\\")) {
3
+ return filePath.replace(/\\/g, "/");
4
+ }
5
+ return filePath;
6
+ }
7
+
8
+ export function encodeFilePathForApi(filePath: string): string {
9
+ return normalizeFilePathSlashes(filePath)
10
+ .split("/")
11
+ .filter(Boolean)
12
+ .map(encodeURIComponent)
13
+ .join("/");
14
+ }
15
+
16
+ export function getFileName(filePath: string): string {
17
+ const normalized = normalizeFilePathSlashes(filePath).replace(/\/+$/, "");
18
+ return normalized.split("/").pop() ?? normalized;
19
+ }
20
+
21
+ export function getRelativeFilePath(filePath: string, cwd?: string): string {
22
+ if (!cwd) return filePath;
23
+
24
+ const normalizedFile = normalizeFilePathSlashes(filePath);
25
+ const normalizedCwd = normalizeFilePathSlashes(cwd).replace(/\/$/, "");
26
+ if (normalizedFile.startsWith(normalizedCwd + "/")) {
27
+ return normalizedFile.slice(normalizedCwd.length + 1);
28
+ }
29
+ return filePath;
30
+ }
31
+
32
+ export function joinFilePath(parent: string, child: string): string {
33
+ return `${normalizeFilePathSlashes(parent).replace(/\/$/, "")}/${child}`;
34
+ }
@@ -0,0 +1,379 @@
1
+ import { inferModelApi, inferProviderApi, type ProviderApi } from "./provider-api";
2
+
3
+ export interface DiscoveredModel {
4
+ id: string;
5
+ name: string;
6
+ ownedBy: string;
7
+ input?: string[];
8
+ contextWindow?: number;
9
+ maxTokens?: number;
10
+ }
11
+
12
+ export interface PiModelImport {
13
+ id: string;
14
+ name: string;
15
+ api?: ProviderApi;
16
+ input?: string[];
17
+ contextWindow: number;
18
+ maxTokens: number;
19
+ reasoning?: boolean;
20
+ }
21
+
22
+ const DEFAULT_CONFIGS = {
23
+ claude: { contextWindow: 200000, maxTokens: 16000 },
24
+ gpt: { contextWindow: 200000, maxTokens: 16000 },
25
+ deepseek: { contextWindow: 128000, maxTokens: 8192 },
26
+ qwen: { contextWindow: 128000, maxTokens: 8192 },
27
+ llama: { contextWindow: 8192, maxTokens: 4096 },
28
+ default: { contextWindow: 200000, maxTokens: 16000 },
29
+ };
30
+
31
+ const CONTEXT_WINDOW_KEYS = [
32
+ "contextWindow",
33
+ "context_window",
34
+ "context_length",
35
+ "contextLength",
36
+ "max_context_length",
37
+ "maxContextLength",
38
+ "max_model_len",
39
+ "model_max_length",
40
+ "input_token_limit",
41
+ "max_input_tokens",
42
+ "maxInputTokens",
43
+ "num_ctx",
44
+ "n_ctx",
45
+ ];
46
+
47
+ const MAX_TOKENS_KEYS = [
48
+ "maxTokens",
49
+ "max_tokens",
50
+ "max_output_tokens",
51
+ "maxOutputTokens",
52
+ "max_completion_tokens",
53
+ "maxCompletionTokens",
54
+ "output_token_limit",
55
+ "completion_token_limit",
56
+ ];
57
+
58
+ function isRecord(value: unknown): value is Record<string, unknown> {
59
+ return typeof value === "object" && value !== null && !Array.isArray(value);
60
+ }
61
+
62
+ function unique(items: string[]): string[] {
63
+ return Array.from(new Set(items));
64
+ }
65
+
66
+ export function normalizeBaseUrl(baseUrl: string): string {
67
+ return baseUrl.trim().replace(/\/+$/, "");
68
+ }
69
+
70
+ export function getModelListEndpoints(baseUrl: string): string[] {
71
+ const normalized = normalizeBaseUrl(baseUrl);
72
+ return unique([
73
+ `${normalized}/v1/models`,
74
+ `${normalized}/models`,
75
+ `${normalized}/api/models`,
76
+ `${normalized}/api/tags`,
77
+ ]);
78
+ }
79
+
80
+ function buildHeaders(apiKey: string): HeadersInit {
81
+ return apiKey.trim() ? { authorization: `Bearer ${apiKey.trim()}` } : {};
82
+ }
83
+
84
+ export async function fetchModelsFromBaseUrl(baseUrl: string, apiKey = ""): Promise<{ endpoint: string; models: DiscoveredModel[] }> {
85
+ const headers = buildHeaders(apiKey);
86
+ const errors: string[] = [];
87
+ const timeoutMs = 8000;
88
+
89
+ for (const endpoint of getModelListEndpoints(baseUrl)) {
90
+ try {
91
+ const response = await fetch(endpoint, {
92
+ method: "GET",
93
+ headers,
94
+ signal: AbortSignal.timeout(timeoutMs),
95
+ });
96
+ if (response.status === 200) {
97
+ const payload = await response.json() as unknown;
98
+ return { endpoint, models: parseModelList(payload) };
99
+ }
100
+ if (response.status !== 404) {
101
+ errors.push(`${endpoint}: HTTP ${response.status}`);
102
+ }
103
+ } catch (error) {
104
+ errors.push(`${endpoint}: ${error instanceof Error ? error.message : String(error)}`);
105
+ }
106
+ }
107
+
108
+ throw new Error(errors.length ? errors.join("; ") : "Could not connect to any model endpoint");
109
+ }
110
+
111
+ export function parseModelList(payload: unknown): DiscoveredModel[] {
112
+ const modelsData = getModelsData(payload);
113
+ const models: DiscoveredModel[] = [];
114
+
115
+ for (const item of modelsData) {
116
+ if (typeof item === "string") {
117
+ models.push({ id: item, name: item, ownedBy: "unknown" });
118
+ continue;
119
+ }
120
+
121
+ if (!isRecord(item)) continue;
122
+
123
+ const id = getStringField(item, ["id", "model_id", "name", "model"]);
124
+ if (!id) continue;
125
+
126
+ const limits = extractModelLimits(item);
127
+ const input = extractInputTypes(item);
128
+ models.push({
129
+ id,
130
+ name: getStringField(item, ["name"]) ?? id,
131
+ ownedBy: getStringField(item, ["owned_by", "ownedBy"]) ?? "unknown",
132
+ ...(input ? { input } : {}),
133
+ ...limits,
134
+ });
135
+ }
136
+
137
+ return models;
138
+ }
139
+
140
+ export async function enrichModelsWithRemoteMetadata(baseUrl: string, apiKey: string, models: DiscoveredModel[]): Promise<DiscoveredModel[]> {
141
+ const enriched = models.map((model) => ({ ...model }));
142
+ const needDetail = enriched.filter((model) => model.contextWindow === undefined || model.maxTokens === undefined);
143
+ if (needDetail.length === 0) return enriched;
144
+
145
+ for (const model of needDetail) {
146
+ const detail = await fetchModelDetail(baseUrl, apiKey, model.id);
147
+ if (!detail) continue;
148
+ const limits = extractModelLimits(detail);
149
+ const input = extractInputTypes(detail);
150
+ model.contextWindow ??= limits.contextWindow;
151
+ model.maxTokens ??= limits.maxTokens;
152
+ model.input ??= input;
153
+ }
154
+
155
+ return enriched;
156
+ }
157
+
158
+ async function fetchModelDetail(baseUrl: string, apiKey: string, modelId: string): Promise<Record<string, unknown> | undefined> {
159
+ const headers = buildHeaders(apiKey);
160
+ const normalized = normalizeBaseUrl(baseUrl);
161
+ const encodedModelId = encodeURIComponent(modelId);
162
+ const getEndpoints = unique([
163
+ `${normalized}/v1/models/${encodedModelId}`,
164
+ `${normalized}/models/${encodedModelId}`,
165
+ `${normalized}/api/models/${encodedModelId}`,
166
+ ]);
167
+
168
+ for (const endpoint of getEndpoints) {
169
+ try {
170
+ const response = await fetch(endpoint, {
171
+ method: "GET",
172
+ headers,
173
+ signal: AbortSignal.timeout(15000),
174
+ });
175
+ if (response.status === 200) {
176
+ const data = await response.json() as unknown;
177
+ if (isRecord(data)) return data;
178
+ }
179
+ } catch {
180
+ // Try the next detail endpoint.
181
+ }
182
+ }
183
+
184
+ try {
185
+ const response = await fetch(`${normalized}/api/show`, {
186
+ method: "POST",
187
+ headers: { ...headers, "content-type": "application/json" },
188
+ body: JSON.stringify({ name: modelId }),
189
+ signal: AbortSignal.timeout(15000),
190
+ });
191
+ if (response.status === 200) {
192
+ const data = await response.json() as unknown;
193
+ if (isRecord(data)) return data;
194
+ }
195
+ } catch {
196
+ // Ollama detail endpoint is optional.
197
+ }
198
+
199
+ return undefined;
200
+ }
201
+
202
+ export function convertToPiModels(models: DiscoveredModel[], includeProviderPrefix = false, provider?: string, baseUrl?: string): PiModelImport[] {
203
+ const providerApi = inferProviderApi(baseUrl, provider);
204
+ return models.map((model) => {
205
+ const fallback = estimateModelParams(model.id);
206
+ const input = inferModelInputTypes(model);
207
+ const api = inferModelApi(model.id, providerApi, baseUrl, provider);
208
+ return {
209
+ id: includeProviderPrefix && provider ? `${provider}/${model.id}` : model.id,
210
+ name: model.name ?? model.id,
211
+ ...(api && api !== providerApi ? { api } : {}),
212
+ ...(input ? { input } : {}),
213
+ contextWindow: model.contextWindow ?? fallback.contextWindow,
214
+ maxTokens: model.maxTokens ?? fallback.maxTokens,
215
+ ...(fallback.reasoning ? { reasoning: true } : {}),
216
+ };
217
+ });
218
+ }
219
+
220
+ function getModelsData(payload: unknown): unknown[] {
221
+ if (Array.isArray(payload)) return payload;
222
+ if (!isRecord(payload)) throw new Error("Could not parse model response format");
223
+ if (Array.isArray(payload.data)) return payload.data;
224
+ if (Array.isArray(payload.models)) return payload.models;
225
+ throw new Error("Could not parse model response format");
226
+ }
227
+
228
+ function extractModelLimits(modelData: unknown): { contextWindow?: number; maxTokens?: number } {
229
+ const contextWindow = findNumericField(modelData, CONTEXT_WINDOW_KEYS);
230
+ const maxTokens = findNumericField(modelData, MAX_TOKENS_KEYS);
231
+ return {
232
+ ...(contextWindow ? { contextWindow } : {}),
233
+ ...(maxTokens ? { maxTokens } : {}),
234
+ };
235
+ }
236
+
237
+ export function inferModelInputTypes(model: Pick<DiscoveredModel, "id" | "name" | "ownedBy" | "input">): string[] | undefined {
238
+ if (model.input?.includes("image")) return ["text", "image"];
239
+ if (looksLikeImageModel(model.id, model.name, model.ownedBy)) return ["text", "image"];
240
+ return undefined;
241
+ }
242
+
243
+ function estimateModelParams(modelId: string): { contextWindow: number; maxTokens: number; reasoning?: boolean } {
244
+ const lower = modelId.toLowerCase();
245
+
246
+ if (lower.includes("claude")) {
247
+ return {
248
+ ...DEFAULT_CONFIGS.claude,
249
+ ...((lower.includes("thinking") || lower.includes("reasoning")) ? { reasoning: true } : {}),
250
+ };
251
+ }
252
+ if (lower.includes("gpt")) return { ...DEFAULT_CONFIGS.gpt };
253
+ if (lower.includes("deepseek")) return { ...DEFAULT_CONFIGS.deepseek };
254
+ if (lower.includes("qwen")) return { ...DEFAULT_CONFIGS.qwen };
255
+ if (lower.includes("llama")) return { ...DEFAULT_CONFIGS.llama };
256
+
257
+ return { ...DEFAULT_CONFIGS.default };
258
+ }
259
+
260
+ function extractInputTypes(modelData: unknown): string[] | undefined {
261
+ if (!isRecord(modelData)) return undefined;
262
+ if (hasImageCapability(modelData)) return ["text", "image"];
263
+ return undefined;
264
+ }
265
+
266
+ function hasImageCapability(value: unknown): boolean {
267
+ if (typeof value === "string") return isImageCapabilityText(value);
268
+ if (typeof value === "boolean" || typeof value === "number" || value === null) return false;
269
+
270
+ if (Array.isArray(value)) {
271
+ return value.some((item) => hasImageCapability(item));
272
+ }
273
+
274
+ if (!isRecord(value)) return false;
275
+
276
+ for (const [key, entry] of Object.entries(value)) {
277
+ const normalizedKey = normalizeKey(key);
278
+ if (typeof entry === "boolean" && entry && IMAGE_CAPABILITY_KEYS.has(normalizedKey)) return true;
279
+ if (IMAGE_CAPABILITY_CONTAINER_KEYS.has(normalizedKey) && hasImageCapability(entry)) return true;
280
+ }
281
+
282
+ return false;
283
+ }
284
+
285
+ function isImageCapabilityText(value: string): boolean {
286
+ const normalized = value.trim().toLowerCase();
287
+ return normalized === "image" || normalized === "images" || normalized === "vision" || normalized === "visual" || normalized === "multimodal";
288
+ }
289
+
290
+ const IMAGE_CAPABILITY_KEYS = new Set(["image", "images", "vision", "visual", "multimodal"]);
291
+ const IMAGE_CAPABILITY_CONTAINER_KEYS = new Set([
292
+ "input",
293
+ "inputs",
294
+ "inputmodalities",
295
+ "modalities",
296
+ "modality",
297
+ "supportedmodalities",
298
+ "capabilities",
299
+ "features",
300
+ "architecture",
301
+ "details",
302
+ "family",
303
+ ]);
304
+
305
+ function looksLikeImageModel(id: string, name?: string, ownedBy?: string): boolean {
306
+ const text = [id, name, ownedBy].filter(Boolean).join(" ").toLowerCase();
307
+ if (!text) return false;
308
+
309
+ const tokenized = text.replace(/[^a-z0-9]+/g, " ");
310
+ if (/\b(?:vision|visual|multimodal|image|images|llava|pixtral|internvl|minicpmv|glm4v)\b/.test(tokenized)) {
311
+ return true;
312
+ }
313
+ if (/(^|[^a-z0-9])(?:vl|v)(?:[^a-z0-9]|$)/.test(text)) return true;
314
+ if (/\bqwen[0-9.]*\s*vl\b|\bqwen\s*vl\b/.test(tokenized)) return true;
315
+ if (/\bgpt\s*4o\b|\bgpt\s*4\s*1\b|\bo3\b|\bo4\b/.test(tokenized)) return true;
316
+ if (/\bgemini\b|\bclaude\s*3\b|\bclaude\s*(?:sonnet|opus|haiku)\s*4\b/.test(tokenized)) return true;
317
+ return false;
318
+ }
319
+
320
+ function findNumericField(data: unknown, keys: string[]): number | undefined {
321
+ if (Array.isArray(data)) {
322
+ for (const item of data) {
323
+ const found = findNumericField(item, keys);
324
+ if (found) return found;
325
+ }
326
+ return undefined;
327
+ }
328
+
329
+ if (!isRecord(data)) return undefined;
330
+
331
+ for (const expectedKey of keys) {
332
+ for (const [actualKey, value] of Object.entries(data)) {
333
+ if (keyMatches(actualKey, expectedKey)) {
334
+ const parsed = parseTokenLimit(value);
335
+ if (parsed) return parsed;
336
+ }
337
+ }
338
+ }
339
+
340
+ for (const value of Object.values(data)) {
341
+ const found = findNumericField(value, keys);
342
+ if (found) return found;
343
+ }
344
+
345
+ return undefined;
346
+ }
347
+
348
+ function parseTokenLimit(value: unknown): number | undefined {
349
+ if (typeof value === "boolean") return undefined;
350
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.trunc(value);
351
+ if (typeof value !== "string") return undefined;
352
+
353
+ const text = value.trim().toLowerCase().replace(/[, _]/g, "");
354
+ const match = /^(\d+(?:\.\d+)?)([km])?$/.exec(text);
355
+ if (!match) return undefined;
356
+
357
+ let number = Number.parseFloat(match[1]);
358
+ if (match[2] === "k") number *= 1000;
359
+ if (match[2] === "m") number *= 1000000;
360
+ return number > 0 ? Math.trunc(number) : undefined;
361
+ }
362
+
363
+ function keyMatches(actualKey: string, expectedKey: string): boolean {
364
+ const actual = normalizeKey(actualKey);
365
+ const expected = normalizeKey(expectedKey);
366
+ return actual === expected || actual.endsWith(`.${expected}`);
367
+ }
368
+
369
+ function normalizeKey(key: string): string {
370
+ return key.toLowerCase().replace(/[^a-z0-9.]/g, "");
371
+ }
372
+
373
+ function getStringField(record: Record<string, unknown>, keys: string[]): string | undefined {
374
+ for (const key of keys) {
375
+ const value = record[key];
376
+ if (typeof value === "string" && value.trim()) return value;
377
+ }
378
+ return undefined;
379
+ }
@@ -0,0 +1,30 @@
1
+ import type { AgentMessage, AssistantMessage, ToolCallContent } from "./types";
2
+
3
+ function isObject(val: unknown): val is Record<string, unknown> {
4
+ return typeof val === "object" && val !== null && !Array.isArray(val);
5
+ }
6
+
7
+ function normalizeToolCallBlock(block: unknown): ToolCallContent | null {
8
+ if (!isObject(block) || block.type !== "toolCall") return null;
9
+ return {
10
+ type: "toolCall",
11
+ toolCallId: typeof block.toolCallId === "string" ? block.toolCallId : (typeof block.id === "string" ? block.id : ""),
12
+ toolName: typeof block.toolName === "string" ? block.toolName : (typeof block.name === "string" ? block.name : ""),
13
+ input: typeof block.input === "object" && block.input !== null && !Array.isArray(block.input)
14
+ ? block.input as Record<string, unknown>
15
+ : (typeof block.arguments === "object" && block.arguments !== null && !Array.isArray(block.arguments)
16
+ ? block.arguments as Record<string, unknown>
17
+ : {}),
18
+ };
19
+ }
20
+
21
+ export function normalizeToolCalls(msg: AgentMessage): AgentMessage {
22
+ if (msg.role !== "assistant") return msg;
23
+ const content = (msg as AssistantMessage).content;
24
+ if (!Array.isArray(content)) return msg;
25
+ const normalized = content.map((block) => {
26
+ const result = normalizeToolCallBlock(block);
27
+ return result ?? block;
28
+ });
29
+ return { ...msg, content: normalized } as AgentMessage;
30
+ }