@stigmer/react 0.3.3 → 0.4.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 (442) hide show
  1. package/billing/AutoRechargeCard.d.ts +38 -0
  2. package/billing/AutoRechargeCard.d.ts.map +1 -0
  3. package/billing/AutoRechargeCard.js +90 -0
  4. package/billing/AutoRechargeCard.js.map +1 -0
  5. package/billing/BillingSection.d.ts +32 -0
  6. package/billing/BillingSection.d.ts.map +1 -0
  7. package/billing/BillingSection.js +81 -0
  8. package/billing/BillingSection.js.map +1 -0
  9. package/billing/CreditBalanceCard.d.ts +25 -0
  10. package/billing/CreditBalanceCard.d.ts.map +1 -0
  11. package/billing/CreditBalanceCard.js +28 -0
  12. package/billing/CreditBalanceCard.js.map +1 -0
  13. package/billing/CreditLedgerTable.d.ts +22 -0
  14. package/billing/CreditLedgerTable.d.ts.map +1 -0
  15. package/billing/CreditLedgerTable.js +75 -0
  16. package/billing/CreditLedgerTable.js.map +1 -0
  17. package/billing/CreditPackGrid.d.ts +31 -0
  18. package/billing/CreditPackGrid.d.ts.map +1 -0
  19. package/billing/CreditPackGrid.js +35 -0
  20. package/billing/CreditPackGrid.js.map +1 -0
  21. package/billing/LowBalanceBanner.d.ts +26 -0
  22. package/billing/LowBalanceBanner.d.ts.map +1 -0
  23. package/billing/LowBalanceBanner.js +33 -0
  24. package/billing/LowBalanceBanner.js.map +1 -0
  25. package/billing/PaymentMethodCard.d.ts +35 -0
  26. package/billing/PaymentMethodCard.d.ts.map +1 -0
  27. package/billing/PaymentMethodCard.js +48 -0
  28. package/billing/PaymentMethodCard.js.map +1 -0
  29. package/billing/credit-packs.d.ts +25 -0
  30. package/billing/credit-packs.d.ts.map +1 -0
  31. package/billing/credit-packs.js +39 -0
  32. package/billing/credit-packs.js.map +1 -0
  33. package/billing/format.d.ts +39 -0
  34. package/billing/format.d.ts.map +1 -0
  35. package/billing/format.js +90 -0
  36. package/billing/format.js.map +1 -0
  37. package/billing/index.d.ts +32 -0
  38. package/billing/index.d.ts.map +1 -0
  39. package/billing/index.js +21 -0
  40. package/billing/index.js.map +1 -0
  41. package/billing/useBillingAccount.d.ts +40 -0
  42. package/billing/useBillingAccount.d.ts.map +1 -0
  43. package/billing/useBillingAccount.js +35 -0
  44. package/billing/useBillingAccount.js.map +1 -0
  45. package/billing/useBillingUsageReport.d.ts +42 -0
  46. package/billing/useBillingUsageReport.d.ts.map +1 -0
  47. package/billing/useBillingUsageReport.js +43 -0
  48. package/billing/useBillingUsageReport.js.map +1 -0
  49. package/billing/useCreateBillingPortalSession.d.ts +35 -0
  50. package/billing/useCreateBillingPortalSession.d.ts.map +1 -0
  51. package/billing/useCreateBillingPortalSession.js +50 -0
  52. package/billing/useCreateBillingPortalSession.js.map +1 -0
  53. package/billing/useCreateCheckoutSession.d.ts +54 -0
  54. package/billing/useCreateCheckoutSession.d.ts.map +1 -0
  55. package/billing/useCreateCheckoutSession.js +58 -0
  56. package/billing/useCreateCheckoutSession.js.map +1 -0
  57. package/billing/useCreditLedger.d.ts +48 -0
  58. package/billing/useCreditLedger.d.ts.map +1 -0
  59. package/billing/useCreditLedger.js +39 -0
  60. package/billing/useCreditLedger.js.map +1 -0
  61. package/billing/useCustomerModelPricing.d.ts +41 -0
  62. package/billing/useCustomerModelPricing.d.ts.map +1 -0
  63. package/billing/useCustomerModelPricing.js +37 -0
  64. package/billing/useCustomerModelPricing.js.map +1 -0
  65. package/billing/useSetAutoRechargeConfig.d.ts +50 -0
  66. package/billing/useSetAutoRechargeConfig.d.ts.map +1 -0
  67. package/billing/useSetAutoRechargeConfig.js +53 -0
  68. package/billing/useSetAutoRechargeConfig.js.map +1 -0
  69. package/composer/ComposerToolbar.js +1 -1
  70. package/composer/ComposerToolbar.js.map +1 -1
  71. package/composer/SessionComposer.d.ts +1 -1
  72. package/composer/SessionComposer.d.ts.map +1 -1
  73. package/composer/SessionComposer.js +19 -4
  74. package/composer/SessionComposer.js.map +1 -1
  75. package/composer/__tests__/SessionComposer-memo.test.d.ts +2 -0
  76. package/composer/__tests__/SessionComposer-memo.test.d.ts.map +1 -0
  77. package/composer/__tests__/SessionComposer-memo.test.js +23 -0
  78. package/composer/__tests__/SessionComposer-memo.test.js.map +1 -0
  79. package/execution/ApprovalCard.d.ts +5 -1
  80. package/execution/ApprovalCard.d.ts.map +1 -1
  81. package/execution/ApprovalCard.js +7 -3
  82. package/execution/ApprovalCard.js.map +1 -1
  83. package/execution/ExecutionPhaseBadge.d.ts +1 -1
  84. package/execution/ExecutionPhaseBadge.d.ts.map +1 -1
  85. package/execution/ExecutionPhaseBadge.js +3 -2
  86. package/execution/ExecutionPhaseBadge.js.map +1 -1
  87. package/execution/MessageEntry.d.ts +7 -3
  88. package/execution/MessageEntry.d.ts.map +1 -1
  89. package/execution/MessageEntry.js +19 -8
  90. package/execution/MessageEntry.js.map +1 -1
  91. package/execution/MessageThread.d.ts +84 -3
  92. package/execution/MessageThread.d.ts.map +1 -1
  93. package/execution/MessageThread.js +113 -65
  94. package/execution/MessageThread.js.map +1 -1
  95. package/execution/SetupProgress.d.ts +1 -1
  96. package/execution/SetupProgress.d.ts.map +1 -1
  97. package/execution/SetupProgress.js +3 -3
  98. package/execution/SetupProgress.js.map +1 -1
  99. package/execution/SubAgentSection.d.ts +5 -1
  100. package/execution/SubAgentSection.d.ts.map +1 -1
  101. package/execution/SubAgentSection.js +13 -7
  102. package/execution/SubAgentSection.js.map +1 -1
  103. package/execution/ThreadSkeleton.d.ts +22 -0
  104. package/execution/ThreadSkeleton.d.ts.map +1 -0
  105. package/execution/ThreadSkeleton.js +26 -0
  106. package/execution/ThreadSkeleton.js.map +1 -0
  107. package/execution/ToolCallGroup.d.ts +16 -1
  108. package/execution/ToolCallGroup.d.ts.map +1 -1
  109. package/execution/ToolCallGroup.js +31 -3
  110. package/execution/ToolCallGroup.js.map +1 -1
  111. package/execution/UsageWidget.d.ts +1 -1
  112. package/execution/__tests__/message-entry.test.d.ts +2 -0
  113. package/execution/__tests__/message-entry.test.d.ts.map +1 -0
  114. package/execution/__tests__/message-entry.test.js +178 -0
  115. package/execution/__tests__/message-entry.test.js.map +1 -0
  116. package/execution/__tests__/thread-keys.test.d.ts +2 -0
  117. package/execution/__tests__/thread-keys.test.d.ts.map +1 -0
  118. package/execution/__tests__/thread-keys.test.js +289 -0
  119. package/execution/__tests__/thread-keys.test.js.map +1 -0
  120. package/execution/__tests__/thread-memoization.test.d.ts +2 -0
  121. package/execution/__tests__/thread-memoization.test.d.ts.map +1 -0
  122. package/execution/__tests__/thread-memoization.test.js +262 -0
  123. package/execution/__tests__/thread-memoization.test.js.map +1 -0
  124. package/execution/__tests__/thread-skeleton.test.d.ts +2 -0
  125. package/execution/__tests__/thread-skeleton.test.d.ts.map +1 -0
  126. package/execution/__tests__/thread-skeleton.test.js +35 -0
  127. package/execution/__tests__/thread-skeleton.test.js.map +1 -0
  128. package/execution/__tests__/useExecutionStream.test.js +73 -10
  129. package/execution/__tests__/useExecutionStream.test.js.map +1 -1
  130. package/execution/__tests__/useSessionVariables-stability.test.d.ts +2 -0
  131. package/execution/__tests__/useSessionVariables-stability.test.d.ts.map +1 -0
  132. package/execution/__tests__/useSessionVariables-stability.test.js +69 -0
  133. package/execution/__tests__/useSessionVariables-stability.test.js.map +1 -0
  134. package/execution/__tests__/virtualized-thread.test.d.ts +2 -0
  135. package/execution/__tests__/virtualized-thread.test.d.ts.map +1 -0
  136. package/execution/__tests__/virtualized-thread.test.js +274 -0
  137. package/execution/__tests__/virtualized-thread.test.js.map +1 -0
  138. package/execution/index.d.ts +2 -0
  139. package/execution/index.d.ts.map +1 -1
  140. package/execution/index.js +1 -0
  141. package/execution/index.js.map +1 -1
  142. package/execution/useExecutionStream.d.ts +35 -10
  143. package/execution/useExecutionStream.d.ts.map +1 -1
  144. package/execution/useExecutionStream.js +79 -40
  145. package/execution/useExecutionStream.js.map +1 -1
  146. package/execution/useSessionVariables.d.ts.map +1 -1
  147. package/execution/useSessionVariables.js +4 -3
  148. package/execution/useSessionVariables.js.map +1 -1
  149. package/github/useGitHubConnection.d.ts.map +1 -1
  150. package/github/useGitHubConnection.js +5 -4
  151. package/github/useGitHubConnection.js.map +1 -1
  152. package/identity-account/index.d.ts +2 -0
  153. package/identity-account/index.d.ts.map +1 -0
  154. package/identity-account/index.js +2 -0
  155. package/identity-account/index.js.map +1 -0
  156. package/identity-account/useIdentityAccountGate.d.ts +81 -0
  157. package/identity-account/useIdentityAccountGate.d.ts.map +1 -0
  158. package/identity-account/useIdentityAccountGate.js +100 -0
  159. package/identity-account/useIdentityAccountGate.js.map +1 -0
  160. package/index.d.ts +10 -4
  161. package/index.d.ts.map +1 -1
  162. package/index.js +8 -2
  163. package/index.js.map +1 -1
  164. package/internal/FetchCacheProvider.d.ts +44 -0
  165. package/internal/FetchCacheProvider.d.ts.map +1 -0
  166. package/internal/FetchCacheProvider.js +61 -0
  167. package/internal/FetchCacheProvider.js.map +1 -0
  168. package/internal/JumpToLatestButton.d.ts +14 -0
  169. package/internal/JumpToLatestButton.d.ts.map +1 -0
  170. package/internal/JumpToLatestButton.js +19 -0
  171. package/internal/JumpToLatestButton.js.map +1 -0
  172. package/internal/ThreadItemWrapper.d.ts +20 -0
  173. package/internal/ThreadItemWrapper.d.ts.map +1 -0
  174. package/internal/ThreadItemWrapper.js +44 -0
  175. package/internal/ThreadItemWrapper.js.map +1 -0
  176. package/internal/VirtualizedThread.d.ts +25 -0
  177. package/internal/VirtualizedThread.d.ts.map +1 -0
  178. package/internal/VirtualizedThread.js +58 -0
  179. package/internal/VirtualizedThread.js.map +1 -0
  180. package/internal/__tests__/fetch-cache.test.d.ts +2 -0
  181. package/internal/__tests__/fetch-cache.test.d.ts.map +1 -0
  182. package/internal/__tests__/fetch-cache.test.js +182 -0
  183. package/internal/__tests__/fetch-cache.test.js.map +1 -0
  184. package/internal/__tests__/stream-controller.test.d.ts +2 -0
  185. package/internal/__tests__/stream-controller.test.d.ts.map +1 -0
  186. package/internal/__tests__/stream-controller.test.js +294 -0
  187. package/internal/__tests__/stream-controller.test.js.map +1 -0
  188. package/internal/__tests__/thread-animation.test.d.ts +2 -0
  189. package/internal/__tests__/thread-animation.test.d.ts.map +1 -0
  190. package/internal/__tests__/thread-animation.test.js +79 -0
  191. package/internal/__tests__/thread-animation.test.js.map +1 -0
  192. package/internal/__tests__/useAutoScroll.test.d.ts +2 -0
  193. package/internal/__tests__/useAutoScroll.test.d.ts.map +1 -0
  194. package/internal/__tests__/useAutoScroll.test.js +188 -0
  195. package/internal/__tests__/useAutoScroll.test.js.map +1 -0
  196. package/internal/__tests__/useFetch-cache.test.d.ts +2 -0
  197. package/internal/__tests__/useFetch-cache.test.d.ts.map +1 -0
  198. package/internal/__tests__/useFetch-cache.test.js +137 -0
  199. package/internal/__tests__/useFetch-cache.test.js.map +1 -0
  200. package/internal/dev/__tests__/use-key-stability.test.d.ts +2 -0
  201. package/internal/dev/__tests__/use-key-stability.test.d.ts.map +1 -0
  202. package/internal/dev/__tests__/use-key-stability.test.js +72 -0
  203. package/internal/dev/__tests__/use-key-stability.test.js.map +1 -0
  204. package/internal/dev/__tests__/use-render-tracer.test.d.ts +2 -0
  205. package/internal/dev/__tests__/use-render-tracer.test.d.ts.map +1 -0
  206. package/internal/dev/__tests__/use-render-tracer.test.js +55 -0
  207. package/internal/dev/__tests__/use-render-tracer.test.js.map +1 -0
  208. package/internal/dev/dom-counter.d.ts +14 -0
  209. package/internal/dev/dom-counter.d.ts.map +1 -0
  210. package/internal/dev/dom-counter.js +39 -0
  211. package/internal/dev/dom-counter.js.map +1 -0
  212. package/internal/dev/index.d.ts +6 -0
  213. package/internal/dev/index.d.ts.map +1 -0
  214. package/internal/dev/index.js +6 -0
  215. package/internal/dev/index.js.map +1 -0
  216. package/internal/dev/profiler-wrapper.d.ts +16 -0
  217. package/internal/dev/profiler-wrapper.d.ts.map +1 -0
  218. package/internal/dev/profiler-wrapper.js +31 -0
  219. package/internal/dev/profiler-wrapper.js.map +1 -0
  220. package/internal/dev/use-key-stability.d.ts +22 -0
  221. package/internal/dev/use-key-stability.d.ts.map +1 -0
  222. package/internal/dev/use-key-stability.js +67 -0
  223. package/internal/dev/use-key-stability.js.map +1 -0
  224. package/internal/dev/use-render-tracer.d.ts +13 -0
  225. package/internal/dev/use-render-tracer.d.ts.map +1 -0
  226. package/internal/dev/use-render-tracer.js +57 -0
  227. package/internal/dev/use-render-tracer.js.map +1 -0
  228. package/internal/dev/use-stream-rate.d.ts +23 -0
  229. package/internal/dev/use-stream-rate.d.ts.map +1 -0
  230. package/internal/dev/use-stream-rate.js +94 -0
  231. package/internal/dev/use-stream-rate.js.map +1 -0
  232. package/internal/fetch-cache.d.ts +72 -0
  233. package/internal/fetch-cache.d.ts.map +1 -0
  234. package/internal/fetch-cache.js +118 -0
  235. package/internal/fetch-cache.js.map +1 -0
  236. package/internal/store/__tests__/conversation-store.test.d.ts +2 -0
  237. package/internal/store/__tests__/conversation-store.test.d.ts.map +1 -0
  238. package/internal/store/__tests__/conversation-store.test.js +200 -0
  239. package/internal/store/__tests__/conversation-store.test.js.map +1 -0
  240. package/internal/store/__tests__/structural-share.test.d.ts +2 -0
  241. package/internal/store/__tests__/structural-share.test.d.ts.map +1 -0
  242. package/internal/store/__tests__/structural-share.test.js +368 -0
  243. package/internal/store/__tests__/structural-share.test.js.map +1 -0
  244. package/internal/store/conversation-store.d.ts +62 -0
  245. package/internal/store/conversation-store.d.ts.map +1 -0
  246. package/internal/store/conversation-store.js +95 -0
  247. package/internal/store/conversation-store.js.map +1 -0
  248. package/internal/store/index.d.ts +31 -0
  249. package/internal/store/index.d.ts.map +1 -0
  250. package/internal/store/index.js +54 -0
  251. package/internal/store/index.js.map +1 -0
  252. package/internal/store/structural-share.d.ts +13 -0
  253. package/internal/store/structural-share.d.ts.map +1 -0
  254. package/internal/store/structural-share.js +240 -0
  255. package/internal/store/structural-share.js.map +1 -0
  256. package/internal/stream-controller.d.ts +85 -0
  257. package/internal/stream-controller.d.ts.map +1 -0
  258. package/internal/stream-controller.js +146 -0
  259. package/internal/stream-controller.js.map +1 -0
  260. package/internal/useAutoScroll.d.ts +32 -0
  261. package/internal/useAutoScroll.d.ts.map +1 -0
  262. package/internal/useAutoScroll.js +97 -0
  263. package/internal/useAutoScroll.js.map +1 -0
  264. package/internal/useFetch.d.ts +14 -0
  265. package/internal/useFetch.d.ts.map +1 -1
  266. package/internal/useFetch.js +32 -2
  267. package/internal/useFetch.js.map +1 -1
  268. package/package.json +7 -5
  269. package/session/__tests__/useNewSessionFlow.test.js +16 -0
  270. package/session/__tests__/useNewSessionFlow.test.js.map +1 -1
  271. package/session/__tests__/usePersistedModel.test.d.ts +2 -0
  272. package/session/__tests__/usePersistedModel.test.d.ts.map +1 -0
  273. package/session/__tests__/usePersistedModel.test.js +82 -0
  274. package/session/__tests__/usePersistedModel.test.js.map +1 -0
  275. package/session/__tests__/useSession.test.d.ts +2 -0
  276. package/session/__tests__/useSession.test.d.ts.map +1 -0
  277. package/session/__tests__/useSession.test.js +130 -0
  278. package/session/__tests__/useSession.test.js.map +1 -0
  279. package/session/useNewSessionFlow.d.ts.map +1 -1
  280. package/session/useNewSessionFlow.js +12 -6
  281. package/session/useNewSessionFlow.js.map +1 -1
  282. package/session/usePersistedModel.d.ts +3 -0
  283. package/session/usePersistedModel.d.ts.map +1 -1
  284. package/session/usePersistedModel.js +27 -2
  285. package/session/usePersistedModel.js.map +1 -1
  286. package/session/useSession.d.ts.map +1 -1
  287. package/session/useSession.js +1 -1
  288. package/session/useSession.js.map +1 -1
  289. package/session/useSessionConversation.d.ts.map +1 -1
  290. package/session/useSessionConversation.js +9 -1
  291. package/session/useSessionConversation.js.map +1 -1
  292. package/session/useSessionExecutions.d.ts.map +1 -1
  293. package/session/useSessionExecutions.js +1 -1
  294. package/session/useSessionExecutions.js.map +1 -1
  295. package/session/useSessionPageFlow.js +1 -1
  296. package/session/useSessionPageFlow.js.map +1 -1
  297. package/session/useSessionUsage.d.ts +24 -40
  298. package/session/useSessionUsage.d.ts.map +1 -1
  299. package/session/useSessionUsage.js +64 -97
  300. package/session/useSessionUsage.js.map +1 -1
  301. package/settings/BillingSection.d.ts +3 -0
  302. package/settings/BillingSection.d.ts.map +1 -0
  303. package/settings/BillingSection.js +3 -0
  304. package/settings/BillingSection.js.map +1 -0
  305. package/settings/index.d.ts +2 -0
  306. package/settings/index.d.ts.map +1 -1
  307. package/settings/index.js +1 -0
  308. package/settings/index.js.map +1 -1
  309. package/settings/settings-nav.js +1 -1
  310. package/settings/settings-nav.js.map +1 -1
  311. package/src/billing/AutoRechargeCard.tsx +274 -0
  312. package/src/billing/BillingSection.tsx +255 -0
  313. package/src/billing/CreditBalanceCard.tsx +81 -0
  314. package/src/billing/CreditLedgerTable.tsx +281 -0
  315. package/src/billing/CreditPackGrid.tsx +132 -0
  316. package/src/billing/LowBalanceBanner.tsx +67 -0
  317. package/src/billing/PaymentMethodCard.tsx +133 -0
  318. package/src/billing/credit-packs.ts +54 -0
  319. package/src/billing/format.ts +97 -0
  320. package/src/billing/index.ts +51 -0
  321. package/src/billing/useBillingAccount.ts +64 -0
  322. package/src/billing/useBillingUsageReport.ts +73 -0
  323. package/src/billing/useCreateBillingPortalSession.ts +76 -0
  324. package/src/billing/useCreateCheckoutSession.ts +101 -0
  325. package/src/billing/useCreditLedger.ts +79 -0
  326. package/src/billing/useCustomerModelPricing.ts +67 -0
  327. package/src/billing/useSetAutoRechargeConfig.ts +90 -0
  328. package/src/composer/ComposerToolbar.tsx +1 -1
  329. package/src/composer/SessionComposer.tsx +22 -4
  330. package/src/composer/__tests__/SessionComposer-memo.test.ts +26 -0
  331. package/src/execution/ApprovalCard.tsx +7 -3
  332. package/src/execution/ExecutionPhaseBadge.tsx +3 -2
  333. package/src/execution/MessageEntry.tsx +27 -16
  334. package/src/execution/MessageThread.tsx +308 -131
  335. package/src/execution/SetupProgress.tsx +3 -3
  336. package/src/execution/SubAgentSection.tsx +14 -6
  337. package/src/execution/ThreadSkeleton.tsx +73 -0
  338. package/src/execution/ToolCallGroup.tsx +36 -3
  339. package/src/execution/UsageWidget.tsx +1 -1
  340. package/src/execution/__tests__/message-entry.test.tsx +236 -0
  341. package/src/execution/__tests__/thread-keys.test.ts +409 -0
  342. package/src/execution/__tests__/thread-memoization.test.ts +320 -0
  343. package/src/execution/__tests__/thread-skeleton.test.tsx +44 -0
  344. package/src/execution/__tests__/useExecutionStream.test.tsx +109 -12
  345. package/src/execution/__tests__/useSessionVariables-stability.test.ts +95 -0
  346. package/src/execution/__tests__/virtualized-thread.test.tsx +401 -0
  347. package/src/execution/index.ts +3 -0
  348. package/src/execution/useExecutionStream.ts +123 -48
  349. package/src/execution/useSessionVariables.ts +17 -12
  350. package/src/github/useGitHubConnection.ts +18 -13
  351. package/src/identity-account/index.ts +5 -0
  352. package/src/identity-account/useIdentityAccountGate.ts +163 -0
  353. package/src/index.ts +73 -0
  354. package/src/internal/FetchCacheProvider.tsx +74 -0
  355. package/src/internal/JumpToLatestButton.tsx +61 -0
  356. package/src/internal/ThreadItemWrapper.tsx +65 -0
  357. package/src/internal/VirtualizedThread.tsx +162 -0
  358. package/src/internal/__tests__/fetch-cache.test.ts +230 -0
  359. package/src/internal/__tests__/stream-controller.test.ts +395 -0
  360. package/src/internal/__tests__/thread-animation.test.tsx +121 -0
  361. package/src/internal/__tests__/useAutoScroll.test.tsx +261 -0
  362. package/src/internal/__tests__/useFetch-cache.test.ts +214 -0
  363. package/src/internal/dev/__tests__/use-key-stability.test.ts +124 -0
  364. package/src/internal/dev/__tests__/use-render-tracer.test.ts +78 -0
  365. package/src/internal/dev/dom-counter.ts +47 -0
  366. package/src/internal/dev/index.ts +5 -0
  367. package/src/internal/dev/profiler-wrapper.tsx +52 -0
  368. package/src/internal/dev/use-key-stability.ts +86 -0
  369. package/src/internal/dev/use-render-tracer.ts +70 -0
  370. package/src/internal/dev/use-stream-rate.ts +138 -0
  371. package/src/internal/fetch-cache.ts +155 -0
  372. package/src/internal/store/__tests__/conversation-store.test.ts +257 -0
  373. package/src/internal/store/__tests__/structural-share.test.ts +454 -0
  374. package/src/internal/store/conversation-store.ts +128 -0
  375. package/src/internal/store/index.ts +68 -0
  376. package/src/internal/store/structural-share.ts +318 -0
  377. package/src/internal/stream-controller.ts +201 -0
  378. package/src/internal/useAutoScroll.ts +121 -0
  379. package/src/internal/useFetch.ts +51 -2
  380. package/src/session/__tests__/useNewSessionFlow.test.tsx +22 -0
  381. package/src/session/__tests__/usePersistedModel.test.tsx +117 -0
  382. package/src/session/__tests__/useSession.test.tsx +187 -0
  383. package/src/session/useNewSessionFlow.ts +12 -6
  384. package/src/session/usePersistedModel.ts +28 -2
  385. package/src/session/useSession.ts +1 -0
  386. package/src/session/useSessionConversation.ts +11 -2
  387. package/src/session/useSessionExecutions.ts +1 -0
  388. package/src/session/useSessionPageFlow.ts +1 -1
  389. package/src/session/useSessionUsage.ts +102 -123
  390. package/src/settings/BillingSection.tsx +4 -0
  391. package/src/settings/index.ts +2 -0
  392. package/src/settings/settings-nav.ts +1 -1
  393. package/src/styles.css +31 -0
  394. package/src/usage/AgentBreakdownList.tsx +147 -0
  395. package/src/usage/CreditRunwayIndicator.tsx +71 -0
  396. package/src/usage/ExportButton.tsx +115 -0
  397. package/src/usage/HarnessSplitCard.tsx +103 -0
  398. package/src/usage/OrgUsagePanel.tsx +109 -45
  399. package/src/usage/index.ts +15 -0
  400. package/src/usage/useExportCSV.ts +115 -0
  401. package/src/usage/useOrgUsageReport.ts +2 -1
  402. package/src/workspace/__tests__/useWorkspaceEntries-stability.test.ts +76 -0
  403. package/src/workspace/useWorkspaceEntries.ts +16 -11
  404. package/styles.css +1 -1
  405. package/usage/AgentBreakdownList.d.ts +21 -0
  406. package/usage/AgentBreakdownList.d.ts.map +1 -0
  407. package/usage/AgentBreakdownList.js +44 -0
  408. package/usage/AgentBreakdownList.js.map +1 -0
  409. package/usage/CreditRunwayIndicator.d.ts +21 -0
  410. package/usage/CreditRunwayIndicator.d.ts.map +1 -0
  411. package/usage/CreditRunwayIndicator.js +38 -0
  412. package/usage/CreditRunwayIndicator.js.map +1 -0
  413. package/usage/ExportButton.d.ts +20 -0
  414. package/usage/ExportButton.d.ts.map +1 -0
  415. package/usage/ExportButton.js +36 -0
  416. package/usage/ExportButton.js.map +1 -0
  417. package/usage/HarnessSplitCard.d.ts +17 -0
  418. package/usage/HarnessSplitCard.d.ts.map +1 -0
  419. package/usage/HarnessSplitCard.js +38 -0
  420. package/usage/HarnessSplitCard.js.map +1 -0
  421. package/usage/OrgUsagePanel.d.ts.map +1 -1
  422. package/usage/OrgUsagePanel.js +30 -22
  423. package/usage/OrgUsagePanel.js.map +1 -1
  424. package/usage/index.d.ts +10 -0
  425. package/usage/index.d.ts.map +1 -1
  426. package/usage/index.js +5 -0
  427. package/usage/index.js.map +1 -1
  428. package/usage/useExportCSV.d.ts +23 -0
  429. package/usage/useExportCSV.d.ts.map +1 -0
  430. package/usage/useExportCSV.js +81 -0
  431. package/usage/useExportCSV.js.map +1 -0
  432. package/usage/useOrgUsageReport.d.ts +2 -1
  433. package/usage/useOrgUsageReport.d.ts.map +1 -1
  434. package/usage/useOrgUsageReport.js +2 -1
  435. package/usage/useOrgUsageReport.js.map +1 -1
  436. package/workspace/__tests__/useWorkspaceEntries-stability.test.d.ts +2 -0
  437. package/workspace/__tests__/useWorkspaceEntries-stability.test.d.ts.map +1 -0
  438. package/workspace/__tests__/useWorkspaceEntries-stability.test.js +57 -0
  439. package/workspace/__tests__/useWorkspaceEntries-stability.test.js.map +1 -0
  440. package/workspace/useWorkspaceEntries.d.ts.map +1 -1
  441. package/workspace/useWorkspaceEntries.js +5 -4
  442. package/workspace/useWorkspaceEntries.js.map +1 -1
@@ -0,0 +1,274 @@
1
+ "use client";
2
+
3
+ import { useState, useCallback, useEffect } from "react";
4
+ import { cn } from "@stigmer/theme";
5
+ import type { AutoRechargeConfig } from "@stigmer/protos/ai/stigmer/billing/v1/billing_account_pb";
6
+ import { BillingAccountStatus } from "@stigmer/protos/ai/stigmer/billing/v1/enum_pb";
7
+ import { getUserMessage } from "@stigmer/sdk";
8
+ import { useSetAutoRechargeConfig } from "./useSetAutoRechargeConfig";
9
+
10
+ /** Props for {@link AutoRechargeCard}. */
11
+ export interface AutoRechargeCardProps {
12
+ /** Organization ID. */
13
+ readonly orgId: string;
14
+ /** Current auto-recharge configuration from the billing account. */
15
+ readonly autoRecharge?: AutoRechargeConfig;
16
+ /** Whether the account has a saved payment method. */
17
+ readonly hasPaymentMethod: boolean;
18
+ /** Account status — config disabled when suspended or closed. */
19
+ readonly accountStatus: BillingAccountStatus;
20
+ /** Called after a successful save so the parent can refresh account data. */
21
+ readonly onSaved?: () => void;
22
+ /** Additional CSS class names. */
23
+ readonly className?: string;
24
+ }
25
+
26
+ const MICROS_PER_DOLLAR = BigInt(1_000_000);
27
+
28
+ function microsToDollars(micros: bigint): string {
29
+ if (micros === BigInt(0)) return "";
30
+ const dollars = Number(micros) / 1_000_000;
31
+ return dollars.toString();
32
+ }
33
+
34
+ function dollarsToMicros(value: string): bigint {
35
+ const num = parseFloat(value);
36
+ if (isNaN(num) || num < 0) return BigInt(0);
37
+ return BigInt(Math.round(num * 1_000_000));
38
+ }
39
+
40
+ /**
41
+ * Auto-recharge configuration card for the billing settings page.
42
+ *
43
+ * Shows a toggle to enable/disable auto-recharge, with input fields
44
+ * for threshold, recharge amount, and monthly cap. Displays a
45
+ * disabled state with an explanatory message when no payment method
46
+ * is on file. Validates inputs client-side before submitting.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * <AutoRechargeCard
51
+ * orgId={orgId}
52
+ * autoRecharge={account.autoRecharge}
53
+ * hasPaymentMethod={!!account.defaultPaymentMethod?.paymentMethodId}
54
+ * accountStatus={account.status}
55
+ * onSaved={refetch}
56
+ * />
57
+ * ```
58
+ */
59
+ export function AutoRechargeCard({
60
+ orgId,
61
+ autoRecharge,
62
+ hasPaymentMethod,
63
+ accountStatus,
64
+ onSaved,
65
+ className,
66
+ }: AutoRechargeCardProps) {
67
+ const { setConfig, isSubmitting, error, clearError } =
68
+ useSetAutoRechargeConfig();
69
+
70
+ const [enabled, setEnabled] = useState(autoRecharge?.enabled ?? false);
71
+ const [threshold, setThreshold] = useState(
72
+ microsToDollars(autoRecharge?.thresholdMicros ?? BigInt(0)),
73
+ );
74
+ const [amount, setAmount] = useState(
75
+ microsToDollars(autoRecharge?.rechargeAmountMicros ?? BigInt(0)),
76
+ );
77
+ const [cap, setCap] = useState(
78
+ microsToDollars(autoRecharge?.monthlyCapMicros ?? BigInt(0)),
79
+ );
80
+ const [saved, setSaved] = useState(false);
81
+
82
+ useEffect(() => {
83
+ if (!autoRecharge) return;
84
+ setEnabled(autoRecharge.enabled);
85
+ setThreshold(microsToDollars(autoRecharge.thresholdMicros));
86
+ setAmount(microsToDollars(autoRecharge.rechargeAmountMicros));
87
+ setCap(microsToDollars(autoRecharge.monthlyCapMicros));
88
+ }, [autoRecharge]);
89
+
90
+ const isAccountActive =
91
+ accountStatus === BillingAccountStatus.billing_account_active;
92
+ const canConfigure = hasPaymentMethod && isAccountActive;
93
+
94
+ const hasChanges =
95
+ enabled !== (autoRecharge?.enabled ?? false) ||
96
+ dollarsToMicros(threshold) !==
97
+ (autoRecharge?.thresholdMicros ?? BigInt(0)) ||
98
+ dollarsToMicros(amount) !==
99
+ (autoRecharge?.rechargeAmountMicros ?? BigInt(0)) ||
100
+ dollarsToMicros(cap) !== (autoRecharge?.monthlyCapMicros ?? BigInt(0));
101
+
102
+ const handleSave = useCallback(async () => {
103
+ clearError();
104
+ setSaved(false);
105
+
106
+ try {
107
+ await setConfig({
108
+ orgId,
109
+ enabled,
110
+ thresholdMicros: dollarsToMicros(threshold),
111
+ rechargeAmountMicros: dollarsToMicros(amount),
112
+ monthlyCapMicros: dollarsToMicros(cap),
113
+ });
114
+ setSaved(true);
115
+ onSaved?.();
116
+ setTimeout(() => setSaved(false), 3000);
117
+ } catch {
118
+ // error state is managed by the hook
119
+ }
120
+ }, [orgId, enabled, threshold, amount, cap, setConfig, clearError, onSaved]);
121
+
122
+ return (
123
+ <div
124
+ className={cn(
125
+ "rounded-lg border border-border bg-card px-4 py-4",
126
+ className,
127
+ )}
128
+ >
129
+ <div className="flex items-center justify-between">
130
+ <div>
131
+ <h3 className="text-xs font-semibold text-foreground">
132
+ Auto-Recharge
133
+ </h3>
134
+ <p className="mt-0.5 text-[0.7rem] text-muted-foreground">
135
+ Automatically add credits when your balance runs low.
136
+ </p>
137
+ </div>
138
+ <button
139
+ type="button"
140
+ role="switch"
141
+ aria-checked={enabled}
142
+ disabled={!canConfigure || isSubmitting}
143
+ onClick={() => setEnabled((prev) => !prev)}
144
+ className={cn(
145
+ "relative inline-flex h-5 w-9 shrink-0 rounded-full transition-colors",
146
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
147
+ "disabled:cursor-not-allowed disabled:opacity-50",
148
+ enabled ? "bg-primary" : "bg-muted",
149
+ )}
150
+ >
151
+ <span
152
+ className={cn(
153
+ "pointer-events-none block size-4 rounded-full bg-background shadow-sm ring-0 transition-transform",
154
+ enabled ? "translate-x-4" : "translate-x-0.5",
155
+ "mt-0.5",
156
+ )}
157
+ />
158
+ </button>
159
+ </div>
160
+
161
+ {!hasPaymentMethod && (
162
+ <p className="mt-3 text-xs text-muted-foreground">
163
+ A saved payment method is required to enable auto-recharge.
164
+ Purchase a credit pack first to save a card.
165
+ </p>
166
+ )}
167
+
168
+ {canConfigure && (
169
+ <div className="mt-4 space-y-3">
170
+ <DollarInput
171
+ id="ar-threshold"
172
+ label="When balance drops below"
173
+ value={threshold}
174
+ onChange={setThreshold}
175
+ disabled={isSubmitting}
176
+ placeholder="e.g. 5"
177
+ />
178
+ <DollarInput
179
+ id="ar-amount"
180
+ label="Recharge amount"
181
+ value={amount}
182
+ onChange={setAmount}
183
+ disabled={isSubmitting}
184
+ placeholder="e.g. 50"
185
+ />
186
+ <DollarInput
187
+ id="ar-cap"
188
+ label="Monthly cap"
189
+ value={cap}
190
+ onChange={setCap}
191
+ disabled={isSubmitting}
192
+ placeholder="e.g. 200"
193
+ />
194
+
195
+ <div className="flex items-center gap-3 pt-1">
196
+ <button
197
+ type="button"
198
+ disabled={!hasChanges || isSubmitting}
199
+ onClick={handleSave}
200
+ className={cn(
201
+ "rounded-md px-3 py-1.5 text-xs font-medium transition-colors",
202
+ "bg-primary text-primary-foreground hover:bg-primary/90",
203
+ "disabled:pointer-events-none disabled:opacity-50",
204
+ )}
205
+ aria-busy={isSubmitting}
206
+ >
207
+ {isSubmitting ? "Saving\u2026" : "Save"}
208
+ </button>
209
+ {saved && (
210
+ <span className="text-xs text-emerald-600 dark:text-emerald-400">
211
+ Saved
212
+ </span>
213
+ )}
214
+ </div>
215
+
216
+ {error && (
217
+ <p className="text-xs text-destructive" role="alert">
218
+ {getUserMessage(error)}
219
+ </p>
220
+ )}
221
+ </div>
222
+ )}
223
+ </div>
224
+ );
225
+ }
226
+
227
+ // ---------------------------------------------------------------------------
228
+ // DollarInput (internal)
229
+ // ---------------------------------------------------------------------------
230
+
231
+ function DollarInput({
232
+ id,
233
+ label,
234
+ value,
235
+ onChange,
236
+ disabled,
237
+ placeholder,
238
+ }: {
239
+ id: string;
240
+ label: string;
241
+ value: string;
242
+ onChange: (v: string) => void;
243
+ disabled?: boolean;
244
+ placeholder?: string;
245
+ }) {
246
+ return (
247
+ <div>
248
+ <label htmlFor={id} className="block text-xs text-muted-foreground">
249
+ {label}
250
+ </label>
251
+ <div className="relative mt-1">
252
+ <span className="pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-xs text-muted-foreground">
253
+ $
254
+ </span>
255
+ <input
256
+ id={id}
257
+ type="number"
258
+ min="0"
259
+ step="any"
260
+ value={value}
261
+ onChange={(e) => onChange(e.target.value)}
262
+ disabled={disabled}
263
+ placeholder={placeholder}
264
+ className={cn(
265
+ "w-full rounded-md border border-input bg-background py-1.5 pl-6 pr-3 text-xs tabular-nums",
266
+ "text-foreground placeholder:text-muted-foreground/60",
267
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
268
+ "disabled:cursor-not-allowed disabled:opacity-50",
269
+ )}
270
+ />
271
+ </div>
272
+ </div>
273
+ );
274
+ }
@@ -0,0 +1,255 @@
1
+ "use client";
2
+
3
+ import { useState, useCallback } from "react";
4
+ import { cn } from "@stigmer/theme";
5
+ import { getUserMessage } from "@stigmer/sdk";
6
+ import { BillingAccountStatus } from "@stigmer/protos/ai/stigmer/billing/v1/enum_pb";
7
+ import { useDeploymentMode } from "../deployment-mode";
8
+ import { CloudFeatureNotice } from "../internal/CloudFeatureNotice";
9
+ import { useOrg } from "../organization/OrgProvider";
10
+ import { useBillingAccount } from "./useBillingAccount";
11
+ import { useCreateCheckoutSession } from "./useCreateCheckoutSession";
12
+ import { useCreateBillingPortalSession } from "./useCreateBillingPortalSession";
13
+ import { CreditBalanceCard } from "./CreditBalanceCard";
14
+ import { PaymentMethodCard } from "./PaymentMethodCard";
15
+ import { AutoRechargeCard } from "./AutoRechargeCard";
16
+ import { CreditPackGrid } from "./CreditPackGrid";
17
+ import { CreditLedgerTable } from "./CreditLedgerTable";
18
+ import { LowBalanceBanner } from "./LowBalanceBanner";
19
+
20
+ /** Props for {@link BillingSection}. */
21
+ export interface BillingSectionProps {
22
+ /**
23
+ * Whether a checkout just completed (e.g., `?checkout=success`).
24
+ *
25
+ * When `true`, an optimistic banner is shown indicating that
26
+ * credits will appear shortly. This prop is typically driven
27
+ * by the host application's URL query parameters.
28
+ */
29
+ readonly checkoutSuccess?: boolean;
30
+ /** Callback to dismiss the checkout success banner. */
31
+ readonly onDismissCheckoutSuccess?: () => void;
32
+ /** Additional CSS class names. */
33
+ readonly className?: string;
34
+ }
35
+
36
+ /**
37
+ * Top-level billing settings section.
38
+ *
39
+ * Composes the billing sub-components into a cohesive settings page:
40
+ * low-balance warning, checkout success banner, credit balance display,
41
+ * credit pack purchase grid, and transaction history. Handles the
42
+ * deployment mode gate (billing unavailable in local mode) and the
43
+ * org-not-selected state.
44
+ *
45
+ * @example
46
+ * ```tsx
47
+ * // In a settings page:
48
+ * <BillingSection checkoutSuccess={searchParams.checkout === "success"} />
49
+ * ```
50
+ */
51
+ export function BillingSection({
52
+ checkoutSuccess,
53
+ onDismissCheckoutSuccess,
54
+ className,
55
+ }: BillingSectionProps) {
56
+ const { activeOrg } = useOrg();
57
+ const mode = useDeploymentMode();
58
+ const orgId = activeOrg?.metadata?.id ?? "";
59
+
60
+ return (
61
+ <section aria-labelledby="billing-heading" className={className}>
62
+ <h2
63
+ id="billing-heading"
64
+ className="text-foreground mb-1 text-sm font-semibold"
65
+ >
66
+ Billing
67
+ </h2>
68
+ <p className="text-muted-foreground mb-4 text-xs">
69
+ Manage credits, purchase credit packs, and view transaction history.
70
+ </p>
71
+
72
+ {mode === "local" ? (
73
+ <CloudFeatureNotice>
74
+ Billing is available on Stigmer Cloud. Connect to a Cloud
75
+ organization to manage credits and purchase credit packs.
76
+ </CloudFeatureNotice>
77
+ ) : !orgId ? (
78
+ <p className="text-muted-foreground py-4 text-center text-xs">
79
+ Select an organization to view billing.
80
+ </p>
81
+ ) : (
82
+ <BillingContent
83
+ orgId={orgId}
84
+ checkoutSuccess={checkoutSuccess}
85
+ onDismissCheckoutSuccess={onDismissCheckoutSuccess}
86
+ />
87
+ )}
88
+ </section>
89
+ );
90
+ }
91
+
92
+ // ---------------------------------------------------------------------------
93
+ // BillingContent (internal)
94
+ // ---------------------------------------------------------------------------
95
+
96
+ function BillingContent({
97
+ orgId,
98
+ checkoutSuccess,
99
+ onDismissCheckoutSuccess,
100
+ }: {
101
+ orgId: string;
102
+ checkoutSuccess?: boolean;
103
+ onDismissCheckoutSuccess?: () => void;
104
+ }) {
105
+ const { account, isLoading, error, refetch } = useBillingAccount(orgId);
106
+ const { createSession, isSubmitting, error: checkoutError, clearError } = useCreateCheckoutSession();
107
+ const { openPortal, isLoading: isPortalLoading } = useCreateBillingPortalSession();
108
+ const [purchasingPackId, setPurchasingPackId] = useState<string | null>(null);
109
+
110
+ const handlePurchase = useCallback(
111
+ (packId: string) => {
112
+ setPurchasingPackId(packId);
113
+ clearError();
114
+
115
+ const baseUrl = typeof window !== "undefined" ? window.location.origin : "";
116
+ const billingPath = `${baseUrl}/settings/billing`;
117
+
118
+ createSession({
119
+ orgId,
120
+ packId,
121
+ successUrl: `${billingPath}?checkout=success`,
122
+ cancelUrl: billingPath,
123
+ }).catch(() => {
124
+ setPurchasingPackId(null);
125
+ });
126
+ },
127
+ [orgId, createSession, clearError],
128
+ );
129
+
130
+ if (isLoading) {
131
+ return (
132
+ <div className="space-y-4" aria-busy="true" aria-label="Loading billing">
133
+ <div className="h-24 animate-pulse rounded-lg bg-muted-subtle" />
134
+ <div className="grid grid-cols-3 gap-3">
135
+ {Array.from({ length: 3 }, (_, i) => (
136
+ <div
137
+ key={i}
138
+ className="h-36 animate-pulse rounded-lg bg-muted-subtle"
139
+ />
140
+ ))}
141
+ </div>
142
+ <div className="h-48 animate-pulse rounded-lg bg-muted-subtle" />
143
+ </div>
144
+ );
145
+ }
146
+
147
+ if (error) {
148
+ return (
149
+ <p className="text-destructive text-xs" role="alert">
150
+ {getUserMessage(error)}
151
+ </p>
152
+ );
153
+ }
154
+
155
+ if (!account) return null;
156
+
157
+ const balance = account.balance;
158
+ if (!balance) return null;
159
+
160
+ const isLowBalance =
161
+ balance.availableMicros < account.lowBalanceThresholdMicros;
162
+
163
+ return (
164
+ <div className="space-y-6">
165
+ {checkoutSuccess && (
166
+ <CheckoutSuccessBanner onDismiss={onDismissCheckoutSuccess} />
167
+ )}
168
+
169
+ <LowBalanceBanner
170
+ availableMicros={balance.availableMicros}
171
+ thresholdMicros={account.lowBalanceThresholdMicros}
172
+ />
173
+
174
+ <CreditBalanceCard balance={balance} isLowBalance={isLowBalance} />
175
+
176
+ <PaymentMethodCard
177
+ paymentMethod={account.defaultPaymentMethod}
178
+ accountStatus={account.status}
179
+ isPortalLoading={isPortalLoading}
180
+ onManage={() => openPortal(orgId)}
181
+ />
182
+
183
+ <AutoRechargeCard
184
+ orgId={orgId}
185
+ autoRecharge={account.autoRecharge}
186
+ hasPaymentMethod={
187
+ account.defaultPaymentMethod != null &&
188
+ account.defaultPaymentMethod.paymentMethodId !== ""
189
+ }
190
+ accountStatus={account.status}
191
+ onSaved={refetch}
192
+ />
193
+
194
+ <CreditPackGrid
195
+ accountStatus={account.status}
196
+ purchasingPackId={isSubmitting ? purchasingPackId : null}
197
+ onPurchase={handlePurchase}
198
+ />
199
+
200
+ {checkoutError && (
201
+ <p className="text-destructive text-xs" role="alert">
202
+ {getUserMessage(checkoutError)}
203
+ </p>
204
+ )}
205
+
206
+ <CreditLedgerTable orgId={orgId} />
207
+ </div>
208
+ );
209
+ }
210
+
211
+ // ---------------------------------------------------------------------------
212
+ // CheckoutSuccessBanner (internal)
213
+ // ---------------------------------------------------------------------------
214
+
215
+ function CheckoutSuccessBanner({
216
+ onDismiss,
217
+ }: {
218
+ onDismiss?: () => void;
219
+ }) {
220
+ return (
221
+ <div
222
+ role="status"
223
+ className="flex items-center justify-between gap-3 rounded-lg border border-emerald-500/30 bg-emerald-500/5 px-3.5 py-3 text-xs text-emerald-700 dark:text-emerald-300"
224
+ >
225
+ <p>
226
+ <span className="font-medium">Payment received</span>
227
+ {" \u2014 "}
228
+ credits will appear in your balance shortly.
229
+ </p>
230
+ {onDismiss && (
231
+ <button
232
+ type="button"
233
+ onClick={onDismiss}
234
+ className="shrink-0 rounded p-0.5 transition-colors hover:bg-emerald-500/10"
235
+ aria-label="Dismiss"
236
+ >
237
+ <svg
238
+ width="14"
239
+ height="14"
240
+ viewBox="0 0 24 24"
241
+ fill="none"
242
+ stroke="currentColor"
243
+ strokeWidth="2"
244
+ strokeLinecap="round"
245
+ strokeLinejoin="round"
246
+ aria-hidden="true"
247
+ >
248
+ <path d="M18 6 6 18" />
249
+ <path d="m6 6 12 12" />
250
+ </svg>
251
+ </button>
252
+ )}
253
+ </div>
254
+ );
255
+ }
@@ -0,0 +1,81 @@
1
+ "use client";
2
+
3
+ import { cn } from "@stigmer/theme";
4
+ import type { CreditBalance } from "@stigmer/protos/ai/stigmer/billing/v1/billing_account_pb";
5
+ import { formatCreditBalance } from "./format";
6
+
7
+ /** Props for {@link CreditBalanceCard}. */
8
+ export interface CreditBalanceCardProps {
9
+ /** The credit balance breakdown from the billing account. */
10
+ readonly balance: CreditBalance;
11
+ /** Whether the balance is below the low-balance threshold. */
12
+ readonly isLowBalance?: boolean;
13
+ /** Additional CSS class names. */
14
+ readonly className?: string;
15
+ }
16
+
17
+ /**
18
+ * Prominent display of the organization's available credit balance.
19
+ *
20
+ * Shows the total available balance as the primary figure, with
21
+ * a secondary breakdown of promotional vs. purchased credits and
22
+ * any reserved amount. Uses semantic colors to indicate balance
23
+ * health: green for healthy, amber for low, red for zero/negative.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * <CreditBalanceCard balance={account.balance} isLowBalance={isLow} />
28
+ * ```
29
+ */
30
+ export function CreditBalanceCard({
31
+ balance,
32
+ isLowBalance,
33
+ className,
34
+ }: CreditBalanceCardProps) {
35
+ const available = balance.availableMicros;
36
+ const zero = BigInt(0);
37
+ const isZeroOrNegative = available <= zero;
38
+
39
+ return (
40
+ <div
41
+ className={cn(
42
+ "rounded-lg border border-border bg-card px-4 py-4",
43
+ className,
44
+ )}
45
+ >
46
+ <div className="text-xs font-medium text-muted-foreground">
47
+ Available Credits
48
+ </div>
49
+ <div
50
+ className={cn(
51
+ "mt-1 text-2xl font-bold tabular-nums",
52
+ isZeroOrNegative
53
+ ? "text-destructive"
54
+ : isLowBalance
55
+ ? "text-warning-foreground"
56
+ : "text-foreground",
57
+ )}
58
+ >
59
+ {formatCreditBalance(available)}
60
+ </div>
61
+
62
+ <div className="mt-3 flex flex-wrap gap-x-4 gap-y-1 text-xs tabular-nums text-muted-foreground">
63
+ {balance.purchasedMicros > zero && (
64
+ <span>
65
+ Purchased: {formatCreditBalance(balance.purchasedMicros)}
66
+ </span>
67
+ )}
68
+ {balance.promotionalMicros > zero && (
69
+ <span>
70
+ Promotional: {formatCreditBalance(balance.promotionalMicros)}
71
+ </span>
72
+ )}
73
+ {balance.reservedMicros > zero && (
74
+ <span>
75
+ Reserved: {formatCreditBalance(balance.reservedMicros)}
76
+ </span>
77
+ )}
78
+ </div>
79
+ </div>
80
+ );
81
+ }