ompchamber 2.0.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/README.md +7 -6
  2. package/bunfig.toml +11 -0
  3. package/dist/client/index.html +16 -5
  4. package/dist/client/index.js +1393 -0
  5. package/dist/client/static/js/index-prbmx3yj.js +5123 -0
  6. package/dist/client/static/js/index-ranztes9.css +1 -0
  7. package/index.html +54 -0
  8. package/package.json +9 -10
  9. package/public/apple-touch-icon.png +0 -0
  10. package/public/icon-192x192.png +0 -0
  11. package/public/icon.svg +60 -0
  12. package/public/manifest.webmanifest +38 -0
  13. package/src/cli/lib/commands/serve.js +9 -5
  14. package/src/cli/lib/runtime.js +18 -7
  15. package/src/client/components/common/provider-icon/glyphs.ts +118 -0
  16. package/src/client/components/common/provider-icon/index.tsx +85 -0
  17. package/src/client/components/layout/desktop-layout/WorkspacePanels.tsx +4 -0
  18. package/src/client/components/layout/desktop-layout/index.tsx +2 -0
  19. package/src/client/components/mobile/LayoutWrapper.tsx +16 -0
  20. package/src/client/components/mobile/SessionSidebar.tsx +10 -0
  21. package/src/client/components/mobile/mobile-right-sidebar/FullEditor.tsx +0 -1
  22. package/src/client/components/mobile/mobile-session-sidebar/Item.tsx +16 -1
  23. package/src/client/components/mobile/mobile-session-sidebar/List.tsx +3 -0
  24. package/src/client/components/settings/categories/ProviderSettings.tsx +45 -4
  25. package/src/client/components/settings/categories/UsageSettings.tsx +22 -7
  26. package/src/client/components/settings/categories/provider-settings/AddModelModal.tsx +322 -0
  27. package/src/client/components/settings/categories/provider-settings/AddProviderModal.tsx +152 -56
  28. package/src/client/components/settings/categories/provider-settings/AuthSection.tsx +52 -1
  29. package/src/client/components/settings/categories/provider-settings/DeleteProviderModal.tsx +133 -0
  30. package/src/client/components/settings/categories/provider-settings/DialectFields.tsx +136 -0
  31. package/src/client/components/settings/categories/provider-settings/EffortLadder.tsx +89 -0
  32. package/src/client/components/settings/categories/provider-settings/Header.tsx +2 -2
  33. package/src/client/components/settings/categories/provider-settings/LoginModal.tsx +2 -2
  34. package/src/client/components/settings/categories/provider-settings/ModelsList.tsx +22 -2
  35. package/src/client/components/settings/categories/provider-settings/PresetPicker.tsx +82 -0
  36. package/src/client/components/settings/categories/provider-settings/PriceFields.tsx +107 -0
  37. package/src/client/components/settings/categories/provider-settings/ReconnectModal.tsx +43 -22
  38. package/src/client/components/settings/categories/provider-settings/SidebarList.tsx +2 -2
  39. package/src/client/components/settings/categories/usage-settings/LimitsSection.tsx +115 -0
  40. package/src/client/components/settings/categories/usage-settings/ProviderCard.tsx +19 -26
  41. package/src/client/components/settings/categories/usage-settings/ProviderDetail.tsx +29 -22
  42. package/src/client/components/settings/categories/usage-settings/SidebarList.tsx +60 -48
  43. package/src/client/components/settings/categories/usage-settings/format.ts +36 -0
  44. package/src/client/components/settings/categories/usage-settings/providers.ts +52 -28
  45. package/src/client/components/workspace/chat-timeline/AiMessageFooter.tsx +1 -1
  46. package/src/client/components/workspace/chat-timeline/GeneratingIndicator.tsx +1 -1
  47. package/src/client/components/workspace/diff-panel/Toolbar.tsx +71 -38
  48. package/src/client/components/workspace/diff-panel/index.tsx +139 -53
  49. package/src/client/components/workspace/editor/Tabs.tsx +2 -2
  50. package/src/client/components/workspace/editor/Toolbar.tsx +111 -26
  51. package/src/client/components/workspace/editor/index.tsx +27 -9
  52. package/src/client/components/workspace/model-dropdown/Item.tsx +13 -23
  53. package/src/client/components/workspace/model-dropdown/Panel.tsx +1 -1
  54. package/src/client/components/workspace/model-dropdown/Section.tsx +13 -4
  55. package/src/client/components/workspace/model-dropdown/index.tsx +7 -3
  56. package/src/client/components/workspace/usage-panel/ProviderSelect.tsx +10 -5
  57. package/src/client/components/workspace/usage-panel/index.tsx +36 -18
  58. package/src/client/data/samples/dialogue-session.ts +1 -1
  59. package/src/client/data/samples/sample-tools/other.ts +1 -1
  60. package/src/client/data/settings/provider.ts +141 -9
  61. package/src/client/hooks/editor/use-file-editor.ts +24 -27
  62. package/src/client/hooks/models/use-provider-names.ts +1 -1
  63. package/src/client/hooks/settings/providers/actions.ts +337 -0
  64. package/src/client/hooks/settings/providers/api.ts +69 -0
  65. package/src/client/hooks/settings/providers/index.ts +138 -0
  66. package/src/client/hooks/settings/providers/messages.ts +77 -0
  67. package/src/client/hooks/settings/useUsageReport.ts +8 -3
  68. package/src/client/hooks/ui/theme.ts +3 -3
  69. package/src/client/hooks/workspace/file-tabs.ts +62 -11
  70. package/src/client/stubs/elkjs.ts +6 -1
  71. package/src/server/index.ts +20 -2
  72. package/src/server/lib/assets/font-css.server.ts +86 -0
  73. package/src/server/lib/assets/fonts.server.ts +117 -0
  74. package/src/server/lib/bundler/css.ts +116 -0
  75. package/src/server/lib/lifecycle/shell-route.ts +17 -0
  76. package/src/server/lib/models/provider-listing.server.ts +257 -0
  77. package/src/server/lib/models/provider-registry.server.test.ts +122 -0
  78. package/src/server/lib/models/provider-registry.server.ts +76 -25
  79. package/src/server/lib/omp/config/models-config.ts +11 -0
  80. package/src/server/lib/omp/config/models-validation.test.ts +137 -0
  81. package/src/server/lib/omp/config/models-validation.ts +111 -2
  82. package/src/server/lib/omp/config/provider-seeds.test.ts +167 -0
  83. package/src/server/lib/omp/config/provider-seeds.ts +176 -0
  84. package/src/server/lib/omp/config/providers.ts +94 -100
  85. package/src/server/lib/omp/core/auth-credentials.ts +45 -0
  86. package/src/server/lib/omp/session/{usage.ts → usage/aggregate.ts} +1 -118
  87. package/src/server/lib/omp/session/usage/shaping.ts +130 -0
  88. package/src/server/lib/usage/deepseek.ts +4 -5
  89. package/src/server/lib/usage/kenari.ts +7 -6
  90. package/src/server/lib/usage/omp-usage.server.test.ts +126 -0
  91. package/src/server/lib/usage/omp-usage.server.ts +194 -0
  92. package/src/server/lib/usage/provider-key.ts +81 -3
  93. package/src/server/lib/usage/providers.server.test.ts +47 -0
  94. package/src/server/lib/usage/providers.server.ts +208 -0
  95. package/src/server/lib/usage/vendor-balance.server.test.ts +104 -0
  96. package/src/server/lib/usage/vendor-balance.server.ts +284 -0
  97. package/src/server/plugins/shell.server.ts +56 -0
  98. package/src/server/plugins/ssr.ts +24 -36
  99. package/src/server/plugins/static.test.ts +26 -29
  100. package/src/server/plugins/static.ts +40 -19
  101. package/src/server/routes/settings/index.ts +2 -0
  102. package/src/server/routes/settings/provider-model.ts +107 -0
  103. package/src/server/routes/settings/provider-models.ts +65 -202
  104. package/src/server/routes/settings/providers.ts +22 -7
  105. package/src/server/routes/settings/usage.ts +125 -45
  106. package/src/server/routes/telemetry/tokens.ts +2 -1
  107. package/src/shared/lib/fs/diff-parser.test.ts +116 -0
  108. package/src/shared/lib/fs/diff-parser.ts +86 -33
  109. package/src/shared/lib/models/{provider-connection.ts → provider/connection.ts} +37 -0
  110. package/src/shared/lib/models/provider/dialect.ts +179 -0
  111. package/src/shared/lib/models/provider/glyph.test.ts +116 -0
  112. package/src/shared/lib/models/provider/glyph.ts +200 -0
  113. package/src/shared/lib/models/{provider-models.ts → provider/models.ts} +91 -6
  114. package/src/shared/lib/models/provider/presets.test.ts +172 -0
  115. package/src/shared/lib/models/provider/presets.ts +83 -0
  116. package/src/shared/lib/workspace/file-tab-id.ts +29 -0
  117. package/src/shared/types/settings/provider.ts +81 -0
  118. package/src/shared/types/settings/usage.ts +88 -14
  119. package/tsconfig.json +3 -1
  120. package/dist/client/static/css/index.5f630421b7.css +0 -2
  121. package/dist/client/static/font/KaTeX_AMS-Regular.a79f1c3119.woff2 +0 -0
  122. package/dist/client/static/font/KaTeX_Caligraphic-Bold.ec17d13264.woff2 +0 -0
  123. package/dist/client/static/font/KaTeX_Caligraphic-Regular.55fac25845.woff2 +0 -0
  124. package/dist/client/static/font/KaTeX_Fraktur-Bold.d42a5579b0.woff2 +0 -0
  125. package/dist/client/static/font/KaTeX_Fraktur-Regular.d3c882a649.woff2 +0 -0
  126. package/dist/client/static/font/KaTeX_Main-Bold.c3fb5ac22f.woff2 +0 -0
  127. package/dist/client/static/font/KaTeX_Main-BoldItalic.6f2bb1dff2.woff2 +0 -0
  128. package/dist/client/static/font/KaTeX_Main-Italic.8916142bec.woff2 +0 -0
  129. package/dist/client/static/font/KaTeX_Main-Regular.0462f03bdf.woff2 +0 -0
  130. package/dist/client/static/font/KaTeX_Math-BoldItalic.572d331f69.woff2 +0 -0
  131. package/dist/client/static/font/KaTeX_Math-Italic.f28c23acad.woff2 +0 -0
  132. package/dist/client/static/font/KaTeX_SansSerif-Bold.8c5b5494b6.woff2 +0 -0
  133. package/dist/client/static/font/KaTeX_SansSerif-Italic.3b1e59b3ba.woff2 +0 -0
  134. package/dist/client/static/font/KaTeX_SansSerif-Regular.ba21ed5f84.woff2 +0 -0
  135. package/dist/client/static/font/KaTeX_Script-Regular.03e9641d6f.woff2 +0 -0
  136. package/dist/client/static/font/KaTeX_Size1-Regular.eae34984b3.woff2 +0 -0
  137. package/dist/client/static/font/KaTeX_Size2-Regular.5916a24fa3.woff2 +0 -0
  138. package/dist/client/static/font/KaTeX_Size4-Regular.10d95fd3a2.woff2 +0 -0
  139. package/dist/client/static/font/KaTeX_Typewriter-Regular.a8709e3622.woff2 +0 -0
  140. package/dist/client/static/font/fira-code-latin-400-normal.2655b10c55.woff2 +0 -0
  141. package/dist/client/static/font/fira-code-latin-500-normal.92a991f204.woff2 +0 -0
  142. package/dist/client/static/font/fira-code-latin-600-normal.43788eb7f1.woff2 +0 -0
  143. package/dist/client/static/font/fira-code-latin-700-normal.2667215d33.woff2 +0 -0
  144. package/dist/client/static/js/77.0d81c74cf0.js +0 -139
  145. package/dist/client/static/js/77.0d81c74cf0.js.LICENSE.txt +0 -8
  146. package/dist/client/static/js/async/0.8e59f2eb5b.js +0 -1
  147. package/dist/client/static/js/async/0k.5852e6b4fa.js +0 -1
  148. package/dist/client/static/js/async/0w.9ed36d5860.js +0 -1
  149. package/dist/client/static/js/async/1.f387c12b63.js +0 -1
  150. package/dist/client/static/js/async/12.d091f91c99.js +0 -1
  151. package/dist/client/static/js/async/13.8f810a8a6c.js +0 -1
  152. package/dist/client/static/js/async/19.6fe909d55a.js +0 -160
  153. package/dist/client/static/js/async/1b.23f1141a38.js +0 -1
  154. package/dist/client/static/js/async/1k.973e8e21fc.js +0 -2
  155. package/dist/client/static/js/async/1k.973e8e21fc.js.LICENSE.txt +0 -11
  156. package/dist/client/static/js/async/1p.0d5cddda96.js +0 -1
  157. package/dist/client/static/js/async/2.b589f1733b.js +0 -1
  158. package/dist/client/static/js/async/2v.96165101de.js +0 -1
  159. package/dist/client/static/js/async/3.0cacc08423.js +0 -1
  160. package/dist/client/static/js/async/37.b28b2f61cd.js +0 -1
  161. package/dist/client/static/js/async/3d.5085fb913f.js +0 -1
  162. package/dist/client/static/js/async/3j.357c80ff38.js +0 -2
  163. package/dist/client/static/js/async/3j.357c80ff38.js.LICENSE.txt +0 -11
  164. package/dist/client/static/js/async/3p.bcf32a0983.js +0 -1
  165. package/dist/client/static/js/async/3r.3a69e98ee0.js +0 -64
  166. package/dist/client/static/js/async/3u.1228460e2a.js +0 -1
  167. package/dist/client/static/js/async/3y.3530b824ad.js +0 -198
  168. package/dist/client/static/js/async/3y.3530b824ad.js.LICENSE.txt +0 -5
  169. package/dist/client/static/js/async/4.9442eeb472.js +0 -1
  170. package/dist/client/static/js/async/4e.678285ca55.js +0 -1
  171. package/dist/client/static/js/async/4k.33a0c7eeb4.js +0 -1
  172. package/dist/client/static/js/async/4m.928a1dde85.js +0 -31
  173. package/dist/client/static/js/async/4m.928a1dde85.js.LICENSE.txt +0 -11
  174. package/dist/client/static/js/async/4q.aad20dab25.js +0 -1
  175. package/dist/client/static/js/async/5.ebaf8b89cc.js +0 -36
  176. package/dist/client/static/js/async/51.95bcae98af.js +0 -2
  177. package/dist/client/static/js/async/51.95bcae98af.js.LICENSE.txt +0 -6
  178. package/dist/client/static/js/async/5b.d88304bc13.js +0 -1
  179. package/dist/client/static/js/async/5j.d6407c4248.js +0 -287
  180. package/dist/client/static/js/async/5o.88316d4460.js +0 -62
  181. package/dist/client/static/js/async/6.f034c9b528.js +0 -1
  182. package/dist/client/static/js/async/66.5dfa29f957.js +0 -93
  183. package/dist/client/static/js/async/6o.5b1a06a382.js +0 -1
  184. package/dist/client/static/js/async/7.e4a9288dd0.js +0 -1
  185. package/dist/client/static/js/async/73.308dff4da8.js +0 -1
  186. package/dist/client/static/js/async/7e.a1cc9bfd88.js +0 -1
  187. package/dist/client/static/js/async/7g.a7814350c3.js +0 -1
  188. package/dist/client/static/js/async/7l.fadbbc0583.js +0 -1
  189. package/dist/client/static/js/async/8.5067439d8c.js +0 -1
  190. package/dist/client/static/js/async/8j.ea110663fb.js +0 -1
  191. package/dist/client/static/js/async/a.bce4542392.js +0 -1
  192. package/dist/client/static/js/async/aa.65d3852576.js +0 -1
  193. package/dist/client/static/js/async/ar.9303e5f2e8.js +0 -2
  194. package/dist/client/static/js/async/ar.9303e5f2e8.js.LICENSE.txt +0 -11
  195. package/dist/client/static/js/async/az.d656062b0f.js +0 -1
  196. package/dist/client/static/js/async/b.b4f6f06515.js +0 -1
  197. package/dist/client/static/js/async/bi.09688ba75c.js +0 -1
  198. package/dist/client/static/js/async/bq.586bc738d1.js +0 -1
  199. package/dist/client/static/js/async/c.797d933882.js +0 -1
  200. package/dist/client/static/js/async/c0.0af1e640d3.js +0 -24
  201. package/dist/client/static/js/async/ca.8a52cfd447.js +0 -1
  202. package/dist/client/static/js/async/cf.d34fff5d67.js +0 -1
  203. package/dist/client/static/js/async/ct.b74928f7a3.js +0 -1
  204. package/dist/client/static/js/async/cx.3cb0242a3a.js +0 -226
  205. package/dist/client/static/js/async/d.a5fc8fe1b3.js +0 -1
  206. package/dist/client/static/js/async/da.f62c70f6c8.js +0 -1
  207. package/dist/client/static/js/async/dp.1725d6432c.js +0 -1
  208. package/dist/client/static/js/async/e.93214d622b.js +0 -79
  209. package/dist/client/static/js/async/f.ab50467719.js +0 -19
  210. package/dist/client/static/js/async/f.ab50467719.js.LICENSE.txt +0 -12
  211. package/dist/client/static/js/async/f7.46971e9d6d.js +0 -2
  212. package/dist/client/static/js/async/f7.46971e9d6d.js.LICENSE.txt +0 -6
  213. package/dist/client/static/js/async/f8.bbf0dbae70.js +0 -1
  214. package/dist/client/static/js/async/g.cb81980498.js +0 -2
  215. package/dist/client/static/js/async/g.cb81980498.js.LICENSE.txt +0 -11
  216. package/dist/client/static/js/async/h.4e790471e4.js +0 -27
  217. package/dist/client/static/js/async/h1.393f066d09.js +0 -1
  218. package/dist/client/static/js/async/h3.216e9798ab.js +0 -148
  219. package/dist/client/static/js/async/hd.0da931b622.js +0 -1
  220. package/dist/client/static/js/async/hk.ba7fb04d41.js +0 -1
  221. package/dist/client/static/js/async/hn.b645041e00.js +0 -1
  222. package/dist/client/static/js/async/ho.475a5e1ae4.js +0 -1
  223. package/dist/client/static/js/async/hp.e9fe2e395a.js +0 -2
  224. package/dist/client/static/js/async/hp.e9fe2e395a.js.LICENSE.txt +0 -17
  225. package/dist/client/static/js/async/hs.e7c59d8090.js +0 -41
  226. package/dist/client/static/js/async/i.7c148e8440.js +0 -1
  227. package/dist/client/static/js/async/id.573df20f29.js +0 -1
  228. package/dist/client/static/js/async/j.ab925882d8.js +0 -1
  229. package/dist/client/static/js/async/jd.63886a1f09.js +0 -1
  230. package/dist/client/static/js/async/jg.d86ebd4013.js +0 -86
  231. package/dist/client/static/js/async/jl.874d352278.js +0 -1
  232. package/dist/client/static/js/async/jll.11313b455a.js +0 -1
  233. package/dist/client/static/js/async/js.67182759ef.js +0 -1
  234. package/dist/client/static/js/async/jsc.23b70d6f40.js +0 -1
  235. package/dist/client/static/js/async/jse.334588ff5d.js +0 -1
  236. package/dist/client/static/js/async/jz.72eb929106.js +0 -77
  237. package/dist/client/static/js/async/k.3210286401.js +0 -217
  238. package/dist/client/static/js/async/ka.c1990ecaa3.js +0 -115
  239. package/dist/client/static/js/async/katex-vendor.de6a87c308.js +0 -1
  240. package/dist/client/static/js/async/ku.29c8a59d0c.js +0 -1
  241. package/dist/client/static/js/async/ky.8dab1dade0.js +0 -1
  242. package/dist/client/static/js/async/l.12dd34e1be.js +0 -1
  243. package/dist/client/static/js/async/l9.949710adaf.js +0 -83
  244. package/dist/client/static/js/async/l9.949710adaf.js.LICENSE.txt +0 -13
  245. package/dist/client/static/js/async/ls.9d9a01026c.js +0 -104
  246. package/dist/client/static/js/async/m.eb2e6752e2.js +0 -28
  247. package/dist/client/static/js/async/m.eb2e6752e2.js.LICENSE.txt +0 -11
  248. package/dist/client/static/js/async/m3.d2b05f9604.js +0 -2
  249. package/dist/client/static/js/async/m3.d2b05f9604.js.LICENSE.txt +0 -6
  250. package/dist/client/static/js/async/ma.2c261b04dd.js +0 -2
  251. package/dist/client/static/js/async/ma.2c261b04dd.js.LICENSE.txt +0 -6
  252. package/dist/client/static/js/async/me.8ace414f80.js +0 -23
  253. package/dist/client/static/js/async/ms.98960af4eb.js +0 -67
  254. package/dist/client/static/js/async/ms.98960af4eb.js.LICENSE.txt +0 -12
  255. package/dist/client/static/js/async/mt.0352e976d8.js +0 -1
  256. package/dist/client/static/js/async/n.a9f1c51701.js +0 -1
  257. package/dist/client/static/js/async/na.a36cd532d6.js +0 -1
  258. package/dist/client/static/js/async/nk.fc7e58325e.js +0 -1
  259. package/dist/client/static/js/async/o.36353dfb88.js +0 -1
  260. package/dist/client/static/js/async/oc.b73042e8bd.js +0 -8
  261. package/dist/client/static/js/async/og.8eb577893a.js +0 -193
  262. package/dist/client/static/js/async/p.48ecfcd14e.js +0 -1
  263. package/dist/client/static/js/async/px.fc6877924b.js +0 -1
  264. package/dist/client/static/js/async/q.22588845a9.js +0 -21
  265. package/dist/client/static/js/async/q.22588845a9.js.LICENSE.txt +0 -6
  266. package/dist/client/static/js/async/q5.97dc1481b6.js +0 -286
  267. package/dist/client/static/js/async/qs.2a9ddb3c72.js +0 -1
  268. package/dist/client/static/js/async/r.51010ad87c.js +0 -1
  269. package/dist/client/static/js/async/rd.cb6bf495bb.js +0 -2
  270. package/dist/client/static/js/async/rd.cb6bf495bb.js.LICENSE.txt +0 -4
  271. package/dist/client/static/js/async/s.0f395cdda5.js +0 -94
  272. package/dist/client/static/js/async/t.4dca0e2ba8.js +0 -1
  273. package/dist/client/static/js/async/t9.d44f57d518.js +0 -1
  274. package/dist/client/static/js/async/ta.973534bbec.js +0 -1
  275. package/dist/client/static/js/async/tr.e878658140.js +0 -309
  276. package/dist/client/static/js/async/u.0871ac5b22.js +0 -1
  277. package/dist/client/static/js/async/ud.3065bfee31.js +0 -2
  278. package/dist/client/static/js/async/ud.3065bfee31.js.LICENSE.txt +0 -4
  279. package/dist/client/static/js/async/up.ea990da0ff.js +0 -32
  280. package/dist/client/static/js/async/uw.8890abbabc.js +0 -1
  281. package/dist/client/static/js/async/v.7d28d3c241.js +0 -34
  282. package/dist/client/static/js/async/vp.9b13bf8610.js +0 -1
  283. package/dist/client/static/js/async/vt.42416b707d.js +0 -1
  284. package/dist/client/static/js/async/w.08ac210f60.js +0 -1
  285. package/dist/client/static/js/async/wt.ad92393a90.js +0 -1
  286. package/dist/client/static/js/async/x.563f72ca6b.js +0 -1
  287. package/dist/client/static/js/async/x0.475516418f.js +0 -1
  288. package/dist/client/static/js/async/x1.da8687159b.js +0 -90
  289. package/dist/client/static/js/async/xe.da8dcc2015.js +0 -2
  290. package/dist/client/static/js/async/xe.da8dcc2015.js.LICENSE.txt +0 -11
  291. package/dist/client/static/js/async/xl.a3c562a58c.js +0 -1
  292. package/dist/client/static/js/async/xn.6510c0abe2.js +0 -2
  293. package/dist/client/static/js/async/xn.6510c0abe2.js.LICENSE.txt +0 -6
  294. package/dist/client/static/js/async/xn1.83a7784fe1.js +0 -10
  295. package/dist/client/static/js/async/xn1.83a7784fe1.js.LICENSE.txt +0 -11
  296. package/dist/client/static/js/async/xnl.feb0021e50.js +0 -2
  297. package/dist/client/static/js/async/xnl.feb0021e50.js.LICENSE.txt +0 -12
  298. package/dist/client/static/js/async/y.1a9ed7a5d8.js +0 -1
  299. package/dist/client/static/js/async/y6.43c57defe4.js +0 -1
  300. package/dist/client/static/js/async/yb.8c1342401d.js +0 -1
  301. package/dist/client/static/js/async/ybq.4491f2f2dc.js +0 -1
  302. package/dist/client/static/js/async/yg.35bebd6d0c.js +0 -149
  303. package/dist/client/static/js/async/yq.917ddd7ba2.js +0 -1
  304. package/dist/client/static/js/async/ys.00687cf82d.js +0 -38
  305. package/dist/client/static/js/async/yv.d99d829136.js +0 -1
  306. package/dist/client/static/js/async/z.56f61a4374.js +0 -1
  307. package/dist/client/static/js/async/zi.5fdb07b86a.js +0 -24
  308. package/dist/client/static/js/async/zj.654f37e8ff.js +0 -1
  309. package/dist/client/static/js/async/zn.966d6f1cc6.js +0 -1
  310. package/dist/client/static/js/async/zo.26213b40c0.js +0 -1
  311. package/dist/client/static/js/async/zx.e9f4105e00.js +0 -1
  312. package/dist/client/static/js/index.e6a257402a.js +0 -38
  313. package/dist/client/static/js/index.e6a257402a.js.LICENSE.txt +0 -4
  314. package/dist/client/static/js/markdown-vendor.71e43278b3.js +0 -144
  315. package/dist/client/static/js/shiki-vendor.cb8452ddcd.js +0 -1
  316. package/src/client/components/settings/categories/provider-settings/Icons.tsx +0 -35
  317. package/src/client/hooks/settings/providers.ts +0 -326
  318. package/src/server/plugins/dev-assets.ts +0 -49
  319. package/src/shared/lib/code/editor-utils.ts +0 -16
  320. package/src/shared/lib/models/provider-presets.ts +0 -29
  321. /package/dist/client/{apple-touch-icon.png → static/apple-touch-icon-dskx5sr3.png} +0 -0
  322. /package/dist/client/{icon-192x192.png → static/icon-192x192-6gn5cr2f.png} +0 -0
  323. /package/dist/client/{icon.svg → static/icon-d07z9dtz.svg} +0 -0
  324. /package/dist/client/{manifest.webmanifest → static/manifest-bnyy75kt.webmanifest} +0 -0
  325. /package/{dist/client → public}/icon-512x512.png +0 -0
  326. /package/{dist/client → public}/icon-maskable-512x512.png +0 -0
  327. /package/{dist/client → public}/sw.js +0 -0
  328. /package/src/shared/lib/models/{provider-cleanup.ts → provider/cleanup.ts} +0 -0
  329. /package/src/shared/lib/models/{provider-label.ts → provider/label.ts} +0 -0
@@ -1,47 +1,40 @@
1
1
  import type { ReactNode } from 'preact/compat';
2
- import { AlertCircle, KeyRound } from 'lucide-preact';
2
+ import { AlertCircle } from 'lucide-preact';
3
3
 
4
4
  interface ProviderCardProps {
5
5
  providerName: string;
6
- configured: boolean;
6
+ /** Where the credential was found, e.g. "models.yml · agent.db". */
7
+ credentialSources: string[];
8
+ /** Provider-side failure, already human-readable. */
7
9
  error?: string;
8
10
  note?: string;
9
11
  children: ReactNode;
10
12
  }
11
13
 
12
- /** Provider shell: header, configured empty state, error line, and content slot.
13
- * Content is rendered whenever the provider is configured, so partial data
14
- * (e.g. quota fails but balance works) still shows the sections that succeeded. */
15
- export function ProviderCard({ providerName, configured, error, note, children }: ProviderCardProps) {
14
+ /** Provider shell: header, credential provenance, error line, and content slot.
15
+ * Every listed provider has a resolved credential — a keyless provider is never
16
+ * rendered at all — so there is no "not configured" state here. */
17
+ export function ProviderCard({ providerName, credentialSources, error, note, children }: ProviderCardProps) {
16
18
  return (
17
19
  <section className="bg-paper border border-ink/15 rounded-lg shadow-xs">
18
20
  <header className="flex items-center justify-between gap-2 px-3.5 py-2.5 border-b border-ink/10">
19
21
  <span className="text-xs font-semibold text-ink">{providerName}</span>
20
- <span className="text-[10px] font-mono uppercase tracking-wider text-ink/50">
21
- {configured ? 'Connected' : 'Not configured'}
22
+ <span
23
+ className="text-[10px] font-mono uppercase tracking-wider text-ink/50 truncate"
24
+ title={`Credentials from ${credentialSources.join(', ')}`}
25
+ >
26
+ {credentialSources.join(' · ')}
22
27
  </span>
23
28
  </header>
24
29
 
25
30
  <div className="p-3.5 space-y-4">
26
- {!configured ? (
27
- <div className="flex items-start gap-2 text-ink/60 text-xs leading-relaxed">
28
- <KeyRound size={14} className="shrink-0 mt-0.5 text-ink/40" />
29
- <p>
30
- Add the <span className="font-semibold text-ink">{providerName}</span> API key in Settings →
31
- Providers to see its balance, quota, and usage here.
32
- </p>
33
- </div>
34
- ) : (
35
- <>
36
- {error && (
37
- <p className="flex items-start gap-2 text-error text-xs leading-relaxed">
38
- <AlertCircle size={14} className="shrink-0 mt-0.5" />
39
- <span className="break-words">{error}</span>
40
- </p>
41
- )}
42
- {children}
43
- </>
31
+ {error && (
32
+ <p className="flex items-start gap-2 text-error text-xs leading-relaxed">
33
+ <AlertCircle size={14} className="shrink-0 mt-0.5" />
34
+ <span className="break-words">{error}</span>
35
+ </p>
44
36
  )}
37
+ {children}
45
38
 
46
39
  {note && (
47
40
  <p className="text-[10px] text-ink/50 leading-relaxed border-t border-ink/10 pt-2.5">{note}</p>
@@ -1,39 +1,46 @@
1
- import type { UsageReport } from '@/shared/types';
1
+ import type { UsageProviderSummary } from '@/shared/types';
2
2
  import { ProviderCard } from '@/client/components/settings/categories/usage-settings/ProviderCard';
3
3
  import { KenariCard } from '@/client/components/settings/categories/usage-settings/KenariCard';
4
4
  import { DeepSeekCard } from '@/client/components/settings/categories/usage-settings/DeepSeekCard';
5
- import type { UsageProviderId } from '@/client/components/settings/categories/usage-settings/providers';
5
+ import { LimitsSection } from '@/client/components/settings/categories/usage-settings/LimitsSection';
6
6
 
7
7
  const DEEPSEEK_NOTE =
8
8
  'DeepSeek exposes no usage or quota API — only the prepaid balance (and the web console at platform.deepseek.com) is available.';
9
9
 
10
10
  interface ProviderDetailProps {
11
- providerId: UsageProviderId;
12
- report: UsageReport;
11
+ summary: UsageProviderSummary;
13
12
  }
14
13
 
15
- /** Renders one provider's card (Kenari.id or DeepSeek) from a usage report. */
16
- export function ProviderDetail({ providerId, report }: ProviderDetailProps) {
17
- if (providerId === 'kenari') {
18
- return (
19
- <ProviderCard
20
- providerName="Kenari.id"
21
- configured={report.kenari.configured}
22
- error={report.kenari.error}
23
- >
24
- <KenariCard report={report.kenari} />
25
- </ProviderCard>
26
- );
27
- }
14
+ /**
15
+ * Renders one provider's card. kenari and DeepSeek carry richer reports (wallet
16
+ * and Rupiah quota / prepaid balance); every other provider renders the generic
17
+ * quota windows, which for a pay-as-you-go vendor is its credit balance.
18
+ */
19
+ export function ProviderDetail({ summary }: ProviderDetailProps) {
20
+ const hasRichReport = Boolean(summary.kenari || summary.deepseek);
28
21
 
29
22
  return (
30
23
  <ProviderCard
31
- providerName="DeepSeek"
32
- configured={report.deepseek.configured}
33
- error={report.deepseek.error}
34
- note={DEEPSEEK_NOTE}
24
+ providerName={summary.name}
25
+ credentialSources={summary.credentialSources}
26
+ error={summary.error}
27
+ note={summary.deepseek ? DEEPSEEK_NOTE : undefined}
35
28
  >
36
- <DeepSeekCard report={report.deepseek} />
29
+ {summary.kenari && <KenariCard report={summary.kenari} />}
30
+ {summary.deepseek && <DeepSeekCard report={summary.deepseek} />}
31
+
32
+ {/* The rich reports already render their own quota and usage tables, so
33
+ the generic windows would only duplicate them. When the provider
34
+ failed outright and reported no windows, the error line above already
35
+ says so — a second "no quota source" note would contradict it. */}
36
+ {!hasRichReport && (summary.limits.length > 0 || !summary.error) && (
37
+ <LimitsSection
38
+ limits={summary.limits}
39
+ tracked={summary.tracked}
40
+ unavailable={summary.limitsUnavailable}
41
+ notes={summary.notes}
42
+ />
43
+ )}
37
44
  </ProviderCard>
38
45
  );
39
46
  }
@@ -1,6 +1,6 @@
1
- import { Bot, Coins } from 'lucide-preact';
2
1
  import type { UsageReport } from '@/shared/types';
3
- import { buildProviders, statusLabel, type UsageProviderId } from '@/client/components/settings/categories/usage-settings/providers';
2
+ import { buildProviders, statusLabel, type ProviderEntry, type UsageProviderId } from '@/client/components/settings/categories/usage-settings/providers';
3
+ import { ProviderIcon } from '@/client/components/common/provider-icon';
4
4
 
5
5
  interface UsageSidebarListProps {
6
6
  report: UsageReport;
@@ -8,6 +8,14 @@ interface UsageSidebarListProps {
8
8
  onSelectProvider: (providerId: UsageProviderId) => void;
9
9
  }
10
10
 
11
+ function ProviderBadge({ provider, selected }: { provider: ProviderEntry; selected: boolean }) {
12
+ return (
13
+ <span className={selected ? 'text-ink/80' : 'text-ink/60'}>
14
+ <ProviderIcon slug={provider.id} name={provider.name} size={14} />
15
+ </span>
16
+ );
17
+ }
18
+
11
19
  export function UsageSidebarList({
12
20
  report,
13
21
  selectedProviderId,
@@ -18,59 +26,63 @@ export function UsageSidebarList({
18
26
  return (
19
27
  <div className="w-56 sm:w-64 border-r border-ink/10 h-full flex flex-col bg-paper/50 flex-shrink-0 select-none">
20
28
  <div className="px-3.5 py-2.5 border-b border-ink/10 flex items-center justify-between">
21
- <span className="text-xs font-semibold text-ink">Total {providers.length} providers</span>
29
+ <span className="text-xs font-semibold text-ink">
30
+ {providers.length} provider{providers.length === 1 ? '' : 's'} with keys
31
+ </span>
22
32
  </div>
23
33
 
24
34
  <div className="flex-1 scrollbar-overlay-container scrollbar-overlay-static p-1.5 space-y-3 text-xs">
25
- <div>
26
- <div className="px-2.5 pt-1.5 pb-1 text-[10px] font-bold text-ink/50 uppercase tracking-wider">
27
- Providers
28
- </div>
29
- <div className="space-y-0.5">
30
- {providers.map((provider) => {
31
- const isSelected = provider.id === selectedProviderId;
32
- const isConnected = provider.configured && !provider.error;
33
- const Icon = provider.id === 'kenari' ? Coins : Bot;
35
+ {providers.length === 0 ? (
36
+ <p className="px-2.5 py-3 text-[11px] text-ink/50 leading-relaxed">
37
+ No provider credentials detected. Add an API key in Settings → Providers.
38
+ </p>
39
+ ) : (
40
+ <div>
41
+ <div className="px-2.5 pt-1.5 pb-1 text-[10px] font-bold text-ink/50 uppercase tracking-wider">
42
+ Providers
43
+ </div>
44
+ <div className="space-y-0.5">
45
+ {providers.map((provider) => {
46
+ const isSelected = provider.id === selectedProviderId;
34
47
 
35
- return (
36
- <button
37
- key={provider.id}
38
- type="button"
39
- onClick={() => onSelectProvider(provider.id)}
40
- className={`w-full text-left px-2.5 py-2 rounded-lg transition-colors cursor-pointer flex flex-col gap-0.5 group ${
41
- isSelected
42
- ? 'bg-ink/10 text-ink font-medium shadow-2xs'
43
- : 'text-ink/80 hover:bg-ink/5 hover:text-ink'
44
- }`}
45
- >
46
- <div className="flex items-center justify-between gap-1.5">
47
- <div className="flex items-center gap-1.5 min-w-0">
48
- <div className="relative">
49
- <Icon
50
- className={`w-3.5 h-3.5 flex-shrink-0 ${isSelected ? 'text-ink/80' : 'text-ink/60'}`}
51
- />
52
- <span
53
- className={`absolute -top-0.5 -right-0.5 w-1.5 h-1.5 rounded-full ${
54
- isConnected ? 'bg-ink' : 'bg-ink/20'
55
- }`}
56
- />
48
+ return (
49
+ <button
50
+ key={provider.id}
51
+ type="button"
52
+ onClick={() => onSelectProvider(provider.id)}
53
+ className={`w-full text-left px-2.5 py-2 rounded-lg transition-colors cursor-pointer flex flex-col gap-0.5 group ${
54
+ isSelected
55
+ ? 'bg-ink/10 text-ink font-medium shadow-2xs'
56
+ : 'text-ink/80 hover:bg-ink/5 hover:text-ink'
57
+ }`}
58
+ >
59
+ <div className="flex items-center justify-between gap-1.5">
60
+ <div className="flex items-center gap-1.5 min-w-0">
61
+ <div className="relative">
62
+ <ProviderBadge provider={provider} selected={isSelected} />
63
+ <span
64
+ className={`absolute -top-0.5 -right-0.5 w-1.5 h-1.5 rounded-full ${
65
+ provider.error ? 'bg-error/60' : 'bg-ink'
66
+ }`}
67
+ />
68
+ </div>
69
+ <span className="font-semibold text-xs text-ink truncate">{provider.name}</span>
57
70
  </div>
58
- <span className="font-semibold text-xs text-ink truncate">{provider.name}</span>
71
+ <span
72
+ className={`text-[10px] font-mono uppercase px-1.5 py-0.5 rounded bg-ink/10 font-medium ${
73
+ provider.error ? 'text-error' : 'text-ink/70'
74
+ }`}
75
+ >
76
+ {statusLabel(provider)}
77
+ </span>
59
78
  </div>
60
- <span
61
- className={`text-[10px] font-mono uppercase px-1.5 py-0.5 rounded bg-ink/10 font-medium ${
62
- provider.error ? 'text-error' : 'text-ink/70'
63
- }`}
64
- >
65
- {statusLabel(provider)}
66
- </span>
67
- </div>
68
- <p className="text-[11px] text-ink/60 line-clamp-1 leading-snug pl-5">{provider.hint}</p>
69
- </button>
70
- );
71
- })}
79
+ <p className="text-[11px] text-ink/60 line-clamp-1 leading-snug pl-5">{provider.hint}</p>
80
+ </button>
81
+ );
82
+ })}
83
+ </div>
72
84
  </div>
73
- </div>
85
+ )}
74
86
  </div>
75
87
  </div>
76
88
  );
@@ -61,3 +61,39 @@ export function formatAmount(value: string): string {
61
61
  if (value.trim() === '' || !Number.isFinite(parsed)) return value;
62
62
  return formatNumber(parsed);
63
63
  }
64
+
65
+ const usdFormatter = new Intl.NumberFormat('id-ID', {
66
+ minimumFractionDigits: 2,
67
+ maximumFractionDigits: 2,
68
+ });
69
+
70
+ /** USD amounts from provider reports and local cost records. */
71
+ export function formatUsd(value: number): string {
72
+ if (!Number.isFinite(value)) return '$0,00';
73
+ return `$${usdFormatter.format(value)}`;
74
+ }
75
+
76
+ /**
77
+ * Render one quota amount in its own unit. `percent` amounts arrive as 0..100
78
+ * (omp's `used`/`limit` for percent units), everything else as a raw count.
79
+ */
80
+ export function formatUsageAmount(value: number, unit: string): string {
81
+ if (!Number.isFinite(value)) return '—';
82
+ switch (unit) {
83
+ case 'percent':
84
+ return `${new Intl.NumberFormat('id-ID', { maximumFractionDigits: 1 }).format(value)}%`;
85
+ case 'usd':
86
+ return formatUsd(value);
87
+ case 'tokens':
88
+ case 'bytes':
89
+ return formatCompactTokens(value);
90
+ default:
91
+ return formatNumber(value);
92
+ }
93
+ }
94
+
95
+ /** Fraction (0..1) rendered as a whole-percent string. */
96
+ export function formatFractionPercent(fraction: number): string {
97
+ if (!Number.isFinite(fraction)) return '0%';
98
+ return `${new Intl.NumberFormat('id-ID', { maximumFractionDigits: 1 }).format(fraction * 100)}%`;
99
+ }
@@ -1,45 +1,69 @@
1
- import type { UsageReport } from '@/shared/types';
2
- import { formatAmount } from '@/client/components/settings/categories/usage-settings/format';
1
+ import type { UsageLimitWindow, UsageProviderSummary, UsageReport } from '@/shared/types';
2
+ import { formatAmount, formatUsd } from '@/client/components/settings/categories/usage-settings/format';
3
3
 
4
- /** Providers surfaced in the Settings → Usage sidebar and the Usage right panel. */
5
- export type UsageProviderId = 'kenari' | 'deepseek';
4
+ /**
5
+ * Providers surfaced in the Settings → Usage sidebar and the Usage right panel.
6
+ * The id is the provider slug, so the set is open-ended: any provider omp can
7
+ * authenticate shows up here without a code change.
8
+ */
9
+ export type UsageProviderId = string;
6
10
 
7
11
  export interface ProviderEntry {
8
12
  id: UsageProviderId;
9
13
  name: string;
10
- configured: boolean;
14
+ /** Provider-side failure, already human-readable. */
11
15
  error?: string;
16
+ /** Short status line under the name. */
12
17
  hint: string;
18
+ /** Provider-reported quota windows; empty when it exposes no usage endpoint. */
19
+ limits: UsageLimitWindow[];
20
+ /** Whether omp ships a usage adapter for this provider. */
21
+ tracked: boolean;
22
+ /** omp tracks this provider but its endpoint produced nothing. */
23
+ limitsUnavailable?: boolean;
24
+ summary: UsageProviderSummary;
25
+ }
26
+
27
+ /** Compact one-line summary of the most-used quota window. */
28
+ function limitHint(limits: UsageLimitWindow[]): string | undefined {
29
+ const used = limits.filter((limit) => limit.usedFraction !== undefined);
30
+ if (used.length === 0) {
31
+ // A credit balance has no limit to take a fraction of; the remaining
32
+ // amount IS the whole story.
33
+ const credit = limits.find((limit) => limit.unit === 'usd' && limit.remaining !== undefined);
34
+ if (credit) return `${formatUsd(credit.remaining ?? 0)} left`;
35
+ return limits[0]?.label;
36
+ }
37
+ const binding = used.reduce((worst, limit) =>
38
+ (limit.usedFraction ?? 0) > (worst.usedFraction ?? 0) ? limit : worst,
39
+ );
40
+ const percent = Math.round((binding.usedFraction ?? 0) * 100);
41
+ return binding.windowLabel ? `${percent}% · ${binding.windowLabel}` : `${percent}% used`;
13
42
  }
14
43
 
15
44
  /** Derives the provider list (status + hint) from a usage report. */
16
45
  export function buildProviders(report: UsageReport): ProviderEntry[] {
17
- const kenariBalance = report.kenari.quota?.planName;
18
- const deepseekEntry = report.deepseek.balance?.entries[0];
46
+ return report.providers.map((summary) => ({
47
+ id: summary.id,
48
+ name: summary.name,
49
+ error: summary.error,
50
+ hint: providerHint(summary),
51
+ limits: summary.limits,
52
+ tracked: summary.tracked,
53
+ limitsUnavailable: summary.limitsUnavailable,
54
+ summary,
55
+ }));
56
+ }
19
57
 
20
- return [
21
- {
22
- id: 'kenari',
23
- name: 'Kenari.id',
24
- configured: report.kenari.configured,
25
- error: report.kenari.error,
26
- hint: kenariBalance ?? 'Wallet & quota',
27
- },
28
- {
29
- id: 'deepseek',
30
- name: 'DeepSeek',
31
- configured: report.deepseek.configured,
32
- error: report.deepseek.error,
33
- hint: deepseekEntry
34
- ? `${deepseekEntry.currency} ${formatAmount(deepseekEntry.totalBalance)}`
35
- : 'Prepaid balance',
36
- },
37
- ];
58
+ function providerHint(summary: UsageProviderSummary): string {
59
+ const plan = summary.kenari?.quota?.planName;
60
+ if (plan) return plan;
61
+ const balance = summary.deepseek?.balance?.entries[0];
62
+ if (balance) return `${balance.currency} ${formatAmount(balance.totalBalance)}`;
63
+ return limitHint(summary.limits) ?? 'No quota reported';
38
64
  }
39
65
 
40
66
  /** Human-readable connection state for a provider entry. */
41
67
  export function statusLabel(provider: ProviderEntry): string {
42
- if (!provider.configured) return 'Not configured';
43
- if (provider.error) return 'Error';
44
- return 'Connected';
68
+ return provider.error ? 'Error' : 'Connected';
45
69
  }
@@ -3,7 +3,7 @@ import type { ReactNode } from 'preact/compat';
3
3
  import { Bot, Brain, Clock3, Coins, Hourglass, MessageSquarePlus, MoreHorizontal, RotateCcw, X } from 'lucide-preact';
4
4
  import { CopyButton } from '@/client/components/common/CopyButton';
5
5
  import { formatDuration } from '@/shared/lib/chat/duration';
6
- import { providerLabel } from '@/shared/lib/models/provider-label';
6
+ import { providerLabel } from '@/shared/lib/models/provider/label';
7
7
  import { formatCompactTokens } from '@/shared/lib/format/number';
8
8
 
9
9
  interface AiMessageFooterProps {
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useState } from 'preact/hooks';
2
2
  import { Bot } from 'lucide-preact';
3
- import { providerLabel } from '@/shared/lib/models/provider-label';
3
+ import { providerLabel } from '@/shared/lib/models/provider/label';
4
4
 
5
5
  interface GeneratingIndicatorProps {
6
6
  modelName?: string;