@stigmer/react 0.3.4 → 0.4.1
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.
- package/billing/AutoRechargeCard.d.ts +38 -0
- package/billing/AutoRechargeCard.d.ts.map +1 -0
- package/billing/AutoRechargeCard.js +90 -0
- package/billing/AutoRechargeCard.js.map +1 -0
- package/billing/BillingSection.d.ts +32 -0
- package/billing/BillingSection.d.ts.map +1 -0
- package/billing/BillingSection.js +81 -0
- package/billing/BillingSection.js.map +1 -0
- package/billing/CreditBalanceCard.d.ts +25 -0
- package/billing/CreditBalanceCard.d.ts.map +1 -0
- package/billing/CreditBalanceCard.js +28 -0
- package/billing/CreditBalanceCard.js.map +1 -0
- package/billing/CreditLedgerTable.d.ts +22 -0
- package/billing/CreditLedgerTable.d.ts.map +1 -0
- package/billing/CreditLedgerTable.js +75 -0
- package/billing/CreditLedgerTable.js.map +1 -0
- package/billing/CreditPackGrid.d.ts +31 -0
- package/billing/CreditPackGrid.d.ts.map +1 -0
- package/billing/CreditPackGrid.js +35 -0
- package/billing/CreditPackGrid.js.map +1 -0
- package/billing/LowBalanceBanner.d.ts +26 -0
- package/billing/LowBalanceBanner.d.ts.map +1 -0
- package/billing/LowBalanceBanner.js +33 -0
- package/billing/LowBalanceBanner.js.map +1 -0
- package/billing/PaymentMethodCard.d.ts +35 -0
- package/billing/PaymentMethodCard.d.ts.map +1 -0
- package/billing/PaymentMethodCard.js +48 -0
- package/billing/PaymentMethodCard.js.map +1 -0
- package/billing/credit-packs.d.ts +25 -0
- package/billing/credit-packs.d.ts.map +1 -0
- package/billing/credit-packs.js +39 -0
- package/billing/credit-packs.js.map +1 -0
- package/billing/format.d.ts +39 -0
- package/billing/format.d.ts.map +1 -0
- package/billing/format.js +90 -0
- package/billing/format.js.map +1 -0
- package/billing/index.d.ts +32 -0
- package/billing/index.d.ts.map +1 -0
- package/billing/index.js +21 -0
- package/billing/index.js.map +1 -0
- package/billing/useBillingAccount.d.ts +40 -0
- package/billing/useBillingAccount.d.ts.map +1 -0
- package/billing/useBillingAccount.js +35 -0
- package/billing/useBillingAccount.js.map +1 -0
- package/billing/useBillingUsageReport.d.ts +42 -0
- package/billing/useBillingUsageReport.d.ts.map +1 -0
- package/billing/useBillingUsageReport.js +43 -0
- package/billing/useBillingUsageReport.js.map +1 -0
- package/billing/useCreateBillingPortalSession.d.ts +35 -0
- package/billing/useCreateBillingPortalSession.d.ts.map +1 -0
- package/billing/useCreateBillingPortalSession.js +50 -0
- package/billing/useCreateBillingPortalSession.js.map +1 -0
- package/billing/useCreateCheckoutSession.d.ts +54 -0
- package/billing/useCreateCheckoutSession.d.ts.map +1 -0
- package/billing/useCreateCheckoutSession.js +58 -0
- package/billing/useCreateCheckoutSession.js.map +1 -0
- package/billing/useCreditLedger.d.ts +48 -0
- package/billing/useCreditLedger.d.ts.map +1 -0
- package/billing/useCreditLedger.js +39 -0
- package/billing/useCreditLedger.js.map +1 -0
- package/billing/useCustomerModelPricing.d.ts +41 -0
- package/billing/useCustomerModelPricing.d.ts.map +1 -0
- package/billing/useCustomerModelPricing.js +37 -0
- package/billing/useCustomerModelPricing.js.map +1 -0
- package/billing/useSetAutoRechargeConfig.d.ts +50 -0
- package/billing/useSetAutoRechargeConfig.d.ts.map +1 -0
- package/billing/useSetAutoRechargeConfig.js +53 -0
- package/billing/useSetAutoRechargeConfig.js.map +1 -0
- package/composer/ComposerToolbar.js +1 -1
- package/composer/ComposerToolbar.js.map +1 -1
- package/composer/SessionComposer.d.ts +1 -1
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +19 -4
- package/composer/SessionComposer.js.map +1 -1
- package/composer/__tests__/SessionComposer-memo.test.d.ts +2 -0
- package/composer/__tests__/SessionComposer-memo.test.d.ts.map +1 -0
- package/composer/__tests__/SessionComposer-memo.test.js +23 -0
- package/composer/__tests__/SessionComposer-memo.test.js.map +1 -0
- package/execution/ApprovalCard.d.ts +5 -1
- package/execution/ApprovalCard.d.ts.map +1 -1
- package/execution/ApprovalCard.js +7 -3
- package/execution/ApprovalCard.js.map +1 -1
- package/execution/ExecutionPhaseBadge.d.ts +1 -1
- package/execution/ExecutionPhaseBadge.d.ts.map +1 -1
- package/execution/ExecutionPhaseBadge.js +3 -2
- package/execution/ExecutionPhaseBadge.js.map +1 -1
- package/execution/MessageEntry.d.ts +7 -3
- package/execution/MessageEntry.d.ts.map +1 -1
- package/execution/MessageEntry.js +19 -8
- package/execution/MessageEntry.js.map +1 -1
- package/execution/MessageThread.d.ts +84 -3
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +113 -65
- package/execution/MessageThread.js.map +1 -1
- package/execution/SetupProgress.d.ts +1 -1
- package/execution/SetupProgress.d.ts.map +1 -1
- package/execution/SetupProgress.js +3 -3
- package/execution/SetupProgress.js.map +1 -1
- package/execution/SubAgentSection.d.ts +5 -1
- package/execution/SubAgentSection.d.ts.map +1 -1
- package/execution/SubAgentSection.js +13 -7
- package/execution/SubAgentSection.js.map +1 -1
- package/execution/ThreadSkeleton.d.ts +22 -0
- package/execution/ThreadSkeleton.d.ts.map +1 -0
- package/execution/ThreadSkeleton.js +26 -0
- package/execution/ThreadSkeleton.js.map +1 -0
- package/execution/ToolCallGroup.d.ts +16 -1
- package/execution/ToolCallGroup.d.ts.map +1 -1
- package/execution/ToolCallGroup.js +31 -3
- package/execution/ToolCallGroup.js.map +1 -1
- package/execution/UsageWidget.d.ts +1 -1
- package/execution/__tests__/message-entry.test.d.ts +2 -0
- package/execution/__tests__/message-entry.test.d.ts.map +1 -0
- package/execution/__tests__/message-entry.test.js +178 -0
- package/execution/__tests__/message-entry.test.js.map +1 -0
- package/execution/__tests__/thread-keys.test.d.ts +2 -0
- package/execution/__tests__/thread-keys.test.d.ts.map +1 -0
- package/execution/__tests__/thread-keys.test.js +289 -0
- package/execution/__tests__/thread-keys.test.js.map +1 -0
- package/execution/__tests__/thread-memoization.test.d.ts +2 -0
- package/execution/__tests__/thread-memoization.test.d.ts.map +1 -0
- package/execution/__tests__/thread-memoization.test.js +262 -0
- package/execution/__tests__/thread-memoization.test.js.map +1 -0
- package/execution/__tests__/thread-skeleton.test.d.ts +2 -0
- package/execution/__tests__/thread-skeleton.test.d.ts.map +1 -0
- package/execution/__tests__/thread-skeleton.test.js +35 -0
- package/execution/__tests__/thread-skeleton.test.js.map +1 -0
- package/execution/__tests__/useExecutionStream.test.js +73 -10
- package/execution/__tests__/useExecutionStream.test.js.map +1 -1
- package/execution/__tests__/useSessionVariables-stability.test.d.ts +2 -0
- package/execution/__tests__/useSessionVariables-stability.test.d.ts.map +1 -0
- package/execution/__tests__/useSessionVariables-stability.test.js +69 -0
- package/execution/__tests__/useSessionVariables-stability.test.js.map +1 -0
- package/execution/__tests__/virtualized-thread.test.d.ts +2 -0
- package/execution/__tests__/virtualized-thread.test.d.ts.map +1 -0
- package/execution/__tests__/virtualized-thread.test.js +274 -0
- package/execution/__tests__/virtualized-thread.test.js.map +1 -0
- package/execution/index.d.ts +2 -0
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +1 -0
- package/execution/index.js.map +1 -1
- package/execution/useExecutionStream.d.ts +35 -10
- package/execution/useExecutionStream.d.ts.map +1 -1
- package/execution/useExecutionStream.js +79 -40
- package/execution/useExecutionStream.js.map +1 -1
- package/execution/useSessionVariables.d.ts.map +1 -1
- package/execution/useSessionVariables.js +4 -3
- package/execution/useSessionVariables.js.map +1 -1
- package/github/useGitHubConnection.d.ts.map +1 -1
- package/github/useGitHubConnection.js +5 -4
- package/github/useGitHubConnection.js.map +1 -1
- package/identity-account/index.d.ts +2 -0
- package/identity-account/index.d.ts.map +1 -0
- package/identity-account/index.js +2 -0
- package/identity-account/index.js.map +1 -0
- package/identity-account/useIdentityAccountGate.d.ts +81 -0
- package/identity-account/useIdentityAccountGate.d.ts.map +1 -0
- package/identity-account/useIdentityAccountGate.js +100 -0
- package/identity-account/useIdentityAccountGate.js.map +1 -0
- package/index.d.ts +10 -4
- package/index.d.ts.map +1 -1
- package/index.js +8 -2
- package/index.js.map +1 -1
- package/internal/FetchCacheProvider.d.ts +44 -0
- package/internal/FetchCacheProvider.d.ts.map +1 -0
- package/internal/FetchCacheProvider.js +61 -0
- package/internal/FetchCacheProvider.js.map +1 -0
- package/internal/JumpToLatestButton.d.ts +14 -0
- package/internal/JumpToLatestButton.d.ts.map +1 -0
- package/internal/JumpToLatestButton.js +19 -0
- package/internal/JumpToLatestButton.js.map +1 -0
- package/internal/ThreadItemWrapper.d.ts +20 -0
- package/internal/ThreadItemWrapper.d.ts.map +1 -0
- package/internal/ThreadItemWrapper.js +44 -0
- package/internal/ThreadItemWrapper.js.map +1 -0
- package/internal/VirtualizedThread.d.ts +25 -0
- package/internal/VirtualizedThread.d.ts.map +1 -0
- package/internal/VirtualizedThread.js +58 -0
- package/internal/VirtualizedThread.js.map +1 -0
- package/internal/__tests__/fetch-cache.test.d.ts +2 -0
- package/internal/__tests__/fetch-cache.test.d.ts.map +1 -0
- package/internal/__tests__/fetch-cache.test.js +182 -0
- package/internal/__tests__/fetch-cache.test.js.map +1 -0
- package/internal/__tests__/stream-controller.test.d.ts +2 -0
- package/internal/__tests__/stream-controller.test.d.ts.map +1 -0
- package/internal/__tests__/stream-controller.test.js +294 -0
- package/internal/__tests__/stream-controller.test.js.map +1 -0
- package/internal/__tests__/thread-animation.test.d.ts +2 -0
- package/internal/__tests__/thread-animation.test.d.ts.map +1 -0
- package/internal/__tests__/thread-animation.test.js +79 -0
- package/internal/__tests__/thread-animation.test.js.map +1 -0
- package/internal/__tests__/useAutoScroll.test.d.ts +2 -0
- package/internal/__tests__/useAutoScroll.test.d.ts.map +1 -0
- package/internal/__tests__/useAutoScroll.test.js +188 -0
- package/internal/__tests__/useAutoScroll.test.js.map +1 -0
- package/internal/__tests__/useFetch-cache.test.d.ts +2 -0
- package/internal/__tests__/useFetch-cache.test.d.ts.map +1 -0
- package/internal/__tests__/useFetch-cache.test.js +137 -0
- package/internal/__tests__/useFetch-cache.test.js.map +1 -0
- package/internal/dev/__tests__/use-key-stability.test.d.ts +2 -0
- package/internal/dev/__tests__/use-key-stability.test.d.ts.map +1 -0
- package/internal/dev/__tests__/use-key-stability.test.js +72 -0
- package/internal/dev/__tests__/use-key-stability.test.js.map +1 -0
- package/internal/dev/__tests__/use-render-tracer.test.d.ts +2 -0
- package/internal/dev/__tests__/use-render-tracer.test.d.ts.map +1 -0
- package/internal/dev/__tests__/use-render-tracer.test.js +55 -0
- package/internal/dev/__tests__/use-render-tracer.test.js.map +1 -0
- package/internal/dev/dom-counter.d.ts +14 -0
- package/internal/dev/dom-counter.d.ts.map +1 -0
- package/internal/dev/dom-counter.js +39 -0
- package/internal/dev/dom-counter.js.map +1 -0
- package/internal/dev/index.d.ts +6 -0
- package/internal/dev/index.d.ts.map +1 -0
- package/internal/dev/index.js +6 -0
- package/internal/dev/index.js.map +1 -0
- package/internal/dev/profiler-wrapper.d.ts +16 -0
- package/internal/dev/profiler-wrapper.d.ts.map +1 -0
- package/internal/dev/profiler-wrapper.js +31 -0
- package/internal/dev/profiler-wrapper.js.map +1 -0
- package/internal/dev/use-key-stability.d.ts +22 -0
- package/internal/dev/use-key-stability.d.ts.map +1 -0
- package/internal/dev/use-key-stability.js +67 -0
- package/internal/dev/use-key-stability.js.map +1 -0
- package/internal/dev/use-render-tracer.d.ts +13 -0
- package/internal/dev/use-render-tracer.d.ts.map +1 -0
- package/internal/dev/use-render-tracer.js +57 -0
- package/internal/dev/use-render-tracer.js.map +1 -0
- package/internal/dev/use-stream-rate.d.ts +23 -0
- package/internal/dev/use-stream-rate.d.ts.map +1 -0
- package/internal/dev/use-stream-rate.js +94 -0
- package/internal/dev/use-stream-rate.js.map +1 -0
- package/internal/fetch-cache.d.ts +72 -0
- package/internal/fetch-cache.d.ts.map +1 -0
- package/internal/fetch-cache.js +118 -0
- package/internal/fetch-cache.js.map +1 -0
- package/internal/store/__tests__/conversation-store.test.d.ts +2 -0
- package/internal/store/__tests__/conversation-store.test.d.ts.map +1 -0
- package/internal/store/__tests__/conversation-store.test.js +200 -0
- package/internal/store/__tests__/conversation-store.test.js.map +1 -0
- package/internal/store/__tests__/structural-share.test.d.ts +2 -0
- package/internal/store/__tests__/structural-share.test.d.ts.map +1 -0
- package/internal/store/__tests__/structural-share.test.js +368 -0
- package/internal/store/__tests__/structural-share.test.js.map +1 -0
- package/internal/store/conversation-store.d.ts +62 -0
- package/internal/store/conversation-store.d.ts.map +1 -0
- package/internal/store/conversation-store.js +95 -0
- package/internal/store/conversation-store.js.map +1 -0
- package/internal/store/index.d.ts +31 -0
- package/internal/store/index.d.ts.map +1 -0
- package/internal/store/index.js +54 -0
- package/internal/store/index.js.map +1 -0
- package/internal/store/structural-share.d.ts +13 -0
- package/internal/store/structural-share.d.ts.map +1 -0
- package/internal/store/structural-share.js +240 -0
- package/internal/store/structural-share.js.map +1 -0
- package/internal/stream-controller.d.ts +85 -0
- package/internal/stream-controller.d.ts.map +1 -0
- package/internal/stream-controller.js +146 -0
- package/internal/stream-controller.js.map +1 -0
- package/internal/useAutoScroll.d.ts +32 -0
- package/internal/useAutoScroll.d.ts.map +1 -0
- package/internal/useAutoScroll.js +97 -0
- package/internal/useAutoScroll.js.map +1 -0
- package/internal/useFetch.d.ts +14 -0
- package/internal/useFetch.d.ts.map +1 -1
- package/internal/useFetch.js +32 -2
- package/internal/useFetch.js.map +1 -1
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +3 -3
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/useMcpServerOAuthConnect.d.ts.map +1 -1
- package/mcp-server/useMcpServerOAuthConnect.js +37 -9
- package/mcp-server/useMcpServerOAuthConnect.js.map +1 -1
- package/package.json +7 -5
- package/session/__tests__/useNewSessionFlow.test.js +16 -0
- package/session/__tests__/useNewSessionFlow.test.js.map +1 -1
- package/session/__tests__/usePersistedModel.test.d.ts +2 -0
- package/session/__tests__/usePersistedModel.test.d.ts.map +1 -0
- package/session/__tests__/usePersistedModel.test.js +82 -0
- package/session/__tests__/usePersistedModel.test.js.map +1 -0
- package/session/__tests__/useSession.test.d.ts +2 -0
- package/session/__tests__/useSession.test.d.ts.map +1 -0
- package/session/__tests__/useSession.test.js +130 -0
- package/session/__tests__/useSession.test.js.map +1 -0
- package/session/useNewSessionFlow.d.ts.map +1 -1
- package/session/useNewSessionFlow.js +12 -6
- package/session/useNewSessionFlow.js.map +1 -1
- package/session/usePersistedModel.d.ts +3 -0
- package/session/usePersistedModel.d.ts.map +1 -1
- package/session/usePersistedModel.js +27 -2
- package/session/usePersistedModel.js.map +1 -1
- package/session/useSession.d.ts.map +1 -1
- package/session/useSession.js +1 -1
- package/session/useSession.js.map +1 -1
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +9 -1
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionExecutions.d.ts.map +1 -1
- package/session/useSessionExecutions.js +1 -1
- package/session/useSessionExecutions.js.map +1 -1
- package/session/useSessionPageFlow.js +1 -1
- package/session/useSessionPageFlow.js.map +1 -1
- package/session/useSessionUsage.d.ts +24 -40
- package/session/useSessionUsage.d.ts.map +1 -1
- package/session/useSessionUsage.js +64 -97
- package/session/useSessionUsage.js.map +1 -1
- package/settings/BillingSection.d.ts +3 -0
- package/settings/BillingSection.d.ts.map +1 -0
- package/settings/BillingSection.js +3 -0
- package/settings/BillingSection.js.map +1 -0
- package/settings/index.d.ts +2 -0
- package/settings/index.d.ts.map +1 -1
- package/settings/index.js +1 -0
- package/settings/index.js.map +1 -1
- package/settings/settings-nav.js +1 -1
- package/settings/settings-nav.js.map +1 -1
- package/src/billing/AutoRechargeCard.tsx +274 -0
- package/src/billing/BillingSection.tsx +255 -0
- package/src/billing/CreditBalanceCard.tsx +81 -0
- package/src/billing/CreditLedgerTable.tsx +281 -0
- package/src/billing/CreditPackGrid.tsx +132 -0
- package/src/billing/LowBalanceBanner.tsx +67 -0
- package/src/billing/PaymentMethodCard.tsx +133 -0
- package/src/billing/credit-packs.ts +54 -0
- package/src/billing/format.ts +97 -0
- package/src/billing/index.ts +51 -0
- package/src/billing/useBillingAccount.ts +64 -0
- package/src/billing/useBillingUsageReport.ts +73 -0
- package/src/billing/useCreateBillingPortalSession.ts +76 -0
- package/src/billing/useCreateCheckoutSession.ts +101 -0
- package/src/billing/useCreditLedger.ts +79 -0
- package/src/billing/useCustomerModelPricing.ts +67 -0
- package/src/billing/useSetAutoRechargeConfig.ts +90 -0
- package/src/composer/ComposerToolbar.tsx +1 -1
- package/src/composer/SessionComposer.tsx +22 -4
- package/src/composer/__tests__/SessionComposer-memo.test.ts +26 -0
- package/src/execution/ApprovalCard.tsx +7 -3
- package/src/execution/ExecutionPhaseBadge.tsx +3 -2
- package/src/execution/MessageEntry.tsx +27 -16
- package/src/execution/MessageThread.tsx +308 -131
- package/src/execution/SetupProgress.tsx +3 -3
- package/src/execution/SubAgentSection.tsx +14 -6
- package/src/execution/ThreadSkeleton.tsx +73 -0
- package/src/execution/ToolCallGroup.tsx +36 -3
- package/src/execution/UsageWidget.tsx +1 -1
- package/src/execution/__tests__/message-entry.test.tsx +236 -0
- package/src/execution/__tests__/thread-keys.test.ts +409 -0
- package/src/execution/__tests__/thread-memoization.test.ts +320 -0
- package/src/execution/__tests__/thread-skeleton.test.tsx +44 -0
- package/src/execution/__tests__/useExecutionStream.test.tsx +109 -12
- package/src/execution/__tests__/useSessionVariables-stability.test.ts +95 -0
- package/src/execution/__tests__/virtualized-thread.test.tsx +401 -0
- package/src/execution/index.ts +3 -0
- package/src/execution/useExecutionStream.ts +123 -48
- package/src/execution/useSessionVariables.ts +17 -12
- package/src/github/useGitHubConnection.ts +18 -13
- package/src/identity-account/index.ts +5 -0
- package/src/identity-account/useIdentityAccountGate.ts +163 -0
- package/src/index.ts +73 -0
- package/src/internal/FetchCacheProvider.tsx +74 -0
- package/src/internal/JumpToLatestButton.tsx +61 -0
- package/src/internal/ThreadItemWrapper.tsx +65 -0
- package/src/internal/VirtualizedThread.tsx +162 -0
- package/src/internal/__tests__/fetch-cache.test.ts +230 -0
- package/src/internal/__tests__/stream-controller.test.ts +395 -0
- package/src/internal/__tests__/thread-animation.test.tsx +121 -0
- package/src/internal/__tests__/useAutoScroll.test.tsx +261 -0
- package/src/internal/__tests__/useFetch-cache.test.ts +214 -0
- package/src/internal/dev/__tests__/use-key-stability.test.ts +124 -0
- package/src/internal/dev/__tests__/use-render-tracer.test.ts +78 -0
- package/src/internal/dev/dom-counter.ts +47 -0
- package/src/internal/dev/index.ts +5 -0
- package/src/internal/dev/profiler-wrapper.tsx +52 -0
- package/src/internal/dev/use-key-stability.ts +86 -0
- package/src/internal/dev/use-render-tracer.ts +70 -0
- package/src/internal/dev/use-stream-rate.ts +138 -0
- package/src/internal/fetch-cache.ts +155 -0
- package/src/internal/store/__tests__/conversation-store.test.ts +257 -0
- package/src/internal/store/__tests__/structural-share.test.ts +454 -0
- package/src/internal/store/conversation-store.ts +128 -0
- package/src/internal/store/index.ts +68 -0
- package/src/internal/store/structural-share.ts +318 -0
- package/src/internal/stream-controller.ts +201 -0
- package/src/internal/useAutoScroll.ts +121 -0
- package/src/internal/useFetch.ts +51 -2
- package/src/mcp-server/McpServerDetailView.tsx +15 -0
- package/src/mcp-server/useMcpServerOAuthConnect.ts +37 -9
- package/src/session/__tests__/useNewSessionFlow.test.tsx +22 -0
- package/src/session/__tests__/usePersistedModel.test.tsx +117 -0
- package/src/session/__tests__/useSession.test.tsx +187 -0
- package/src/session/useNewSessionFlow.ts +12 -6
- package/src/session/usePersistedModel.ts +28 -2
- package/src/session/useSession.ts +1 -0
- package/src/session/useSessionConversation.ts +11 -2
- package/src/session/useSessionExecutions.ts +1 -0
- package/src/session/useSessionPageFlow.ts +1 -1
- package/src/session/useSessionUsage.ts +102 -123
- package/src/settings/BillingSection.tsx +4 -0
- package/src/settings/index.ts +2 -0
- package/src/settings/settings-nav.ts +1 -1
- package/src/styles.css +31 -0
- package/src/usage/AgentBreakdownList.tsx +147 -0
- package/src/usage/CreditRunwayIndicator.tsx +71 -0
- package/src/usage/ExportButton.tsx +115 -0
- package/src/usage/HarnessSplitCard.tsx +103 -0
- package/src/usage/OrgUsagePanel.tsx +109 -45
- package/src/usage/index.ts +15 -0
- package/src/usage/useExportCSV.ts +115 -0
- package/src/usage/useOrgUsageReport.ts +2 -1
- package/src/workspace/__tests__/useWorkspaceEntries-stability.test.ts +76 -0
- package/src/workspace/useWorkspaceEntries.ts +16 -11
- package/styles.css +1 -1
- package/usage/AgentBreakdownList.d.ts +21 -0
- package/usage/AgentBreakdownList.d.ts.map +1 -0
- package/usage/AgentBreakdownList.js +44 -0
- package/usage/AgentBreakdownList.js.map +1 -0
- package/usage/CreditRunwayIndicator.d.ts +21 -0
- package/usage/CreditRunwayIndicator.d.ts.map +1 -0
- package/usage/CreditRunwayIndicator.js +38 -0
- package/usage/CreditRunwayIndicator.js.map +1 -0
- package/usage/ExportButton.d.ts +20 -0
- package/usage/ExportButton.d.ts.map +1 -0
- package/usage/ExportButton.js +36 -0
- package/usage/ExportButton.js.map +1 -0
- package/usage/HarnessSplitCard.d.ts +17 -0
- package/usage/HarnessSplitCard.d.ts.map +1 -0
- package/usage/HarnessSplitCard.js +38 -0
- package/usage/HarnessSplitCard.js.map +1 -0
- package/usage/OrgUsagePanel.d.ts.map +1 -1
- package/usage/OrgUsagePanel.js +30 -22
- package/usage/OrgUsagePanel.js.map +1 -1
- package/usage/index.d.ts +10 -0
- package/usage/index.d.ts.map +1 -1
- package/usage/index.js +5 -0
- package/usage/index.js.map +1 -1
- package/usage/useExportCSV.d.ts +23 -0
- package/usage/useExportCSV.d.ts.map +1 -0
- package/usage/useExportCSV.js +81 -0
- package/usage/useExportCSV.js.map +1 -0
- package/usage/useOrgUsageReport.d.ts +2 -1
- package/usage/useOrgUsageReport.d.ts.map +1 -1
- package/usage/useOrgUsageReport.js +2 -1
- package/usage/useOrgUsageReport.js.map +1 -1
- package/workspace/__tests__/useWorkspaceEntries-stability.test.d.ts +2 -0
- package/workspace/__tests__/useWorkspaceEntries-stability.test.d.ts.map +1 -0
- package/workspace/__tests__/useWorkspaceEntries-stability.test.js +57 -0
- package/workspace/__tests__/useWorkspaceEntries-stability.test.js.map +1 -0
- package/workspace/useWorkspaceEntries.d.ts.map +1 -1
- package/workspace/useWorkspaceEntries.js +5 -4
- package/workspace/useWorkspaceEntries.js.map +1 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@stigmer/theme";
|
|
4
|
+
import { BillingAccountStatus } from "@stigmer/protos/ai/stigmer/billing/v1/enum_pb";
|
|
5
|
+
import {
|
|
6
|
+
CREDIT_PACKS,
|
|
7
|
+
formatPackPrice,
|
|
8
|
+
formatCreditCount,
|
|
9
|
+
type CreditPackInfo,
|
|
10
|
+
} from "./credit-packs";
|
|
11
|
+
|
|
12
|
+
/** Props for {@link CreditPackGrid}. */
|
|
13
|
+
export interface CreditPackGridProps {
|
|
14
|
+
/** Account status — purchases disabled when suspended or closed. */
|
|
15
|
+
readonly accountStatus: BillingAccountStatus;
|
|
16
|
+
/** ID of the pack currently being purchased (shows loading state). */
|
|
17
|
+
readonly purchasingPackId?: string | null;
|
|
18
|
+
/** Called when the user clicks a pack's buy button. */
|
|
19
|
+
readonly onPurchase: (packId: string) => void;
|
|
20
|
+
/** Additional CSS class names. */
|
|
21
|
+
readonly className?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Grid of credit pack cards with purchase buttons.
|
|
26
|
+
*
|
|
27
|
+
* Displays the 3 self-serve credit packs (Starter, Growth, Team)
|
|
28
|
+
* in a responsive grid. Each card shows the pack name, price,
|
|
29
|
+
* credit count, and a buy button. Buttons are disabled when the
|
|
30
|
+
* account is suspended/closed or a purchase is in progress.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* <CreditPackGrid
|
|
35
|
+
* accountStatus={account.status}
|
|
36
|
+
* purchasingPackId={isSubmitting ? activePackId : null}
|
|
37
|
+
* onPurchase={(packId) => createSession({ orgId, packId, ... })}
|
|
38
|
+
* />
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export function CreditPackGrid({
|
|
42
|
+
accountStatus,
|
|
43
|
+
purchasingPackId,
|
|
44
|
+
onPurchase,
|
|
45
|
+
className,
|
|
46
|
+
}: CreditPackGridProps) {
|
|
47
|
+
const isAccountActive =
|
|
48
|
+
accountStatus === BillingAccountStatus.billing_account_active;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div>
|
|
52
|
+
<h3 className="mb-2 text-xs font-semibold text-foreground">
|
|
53
|
+
Purchase Credits
|
|
54
|
+
</h3>
|
|
55
|
+
<div
|
|
56
|
+
className={cn("grid gap-3 sm:grid-cols-3", className)}
|
|
57
|
+
role="group"
|
|
58
|
+
aria-label="Credit packs"
|
|
59
|
+
>
|
|
60
|
+
{CREDIT_PACKS.map((pack) => (
|
|
61
|
+
<PackCard
|
|
62
|
+
key={pack.packId}
|
|
63
|
+
pack={pack}
|
|
64
|
+
isPurchasing={purchasingPackId === pack.packId}
|
|
65
|
+
isDisabled={!isAccountActive || purchasingPackId != null}
|
|
66
|
+
onPurchase={onPurchase}
|
|
67
|
+
/>
|
|
68
|
+
))}
|
|
69
|
+
</div>
|
|
70
|
+
{!isAccountActive && (
|
|
71
|
+
<p className="mt-2 text-xs text-muted-foreground">
|
|
72
|
+
Credit purchases are unavailable while your billing account is{" "}
|
|
73
|
+
{accountStatus === BillingAccountStatus.billing_account_suspended
|
|
74
|
+
? "suspended"
|
|
75
|
+
: "closed"}
|
|
76
|
+
.
|
|
77
|
+
</p>
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// PackCard (internal)
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
function PackCard({
|
|
88
|
+
pack,
|
|
89
|
+
isPurchasing,
|
|
90
|
+
isDisabled,
|
|
91
|
+
onPurchase,
|
|
92
|
+
}: {
|
|
93
|
+
pack: CreditPackInfo;
|
|
94
|
+
isPurchasing: boolean;
|
|
95
|
+
isDisabled: boolean;
|
|
96
|
+
onPurchase: (packId: string) => void;
|
|
97
|
+
}) {
|
|
98
|
+
return (
|
|
99
|
+
<div className="flex flex-col rounded-lg border border-border bg-card px-4 py-4">
|
|
100
|
+
<div className="text-sm font-semibold text-foreground">
|
|
101
|
+
{pack.displayName}
|
|
102
|
+
</div>
|
|
103
|
+
<div className="mt-0.5 text-xs text-muted-foreground">
|
|
104
|
+
{pack.description}
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<div className="mt-3 flex items-baseline gap-1">
|
|
108
|
+
<span className="text-xl font-bold tabular-nums text-foreground">
|
|
109
|
+
{formatPackPrice(pack.priceCents)}
|
|
110
|
+
</span>
|
|
111
|
+
</div>
|
|
112
|
+
<div className="mt-0.5 text-xs tabular-nums text-muted-foreground">
|
|
113
|
+
{formatCreditCount(pack.credits)} credits
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<button
|
|
117
|
+
type="button"
|
|
118
|
+
disabled={isDisabled}
|
|
119
|
+
onClick={() => onPurchase(pack.packId)}
|
|
120
|
+
className={cn(
|
|
121
|
+
"mt-4 w-full rounded-md px-3 py-1.5 text-xs font-medium transition-colors",
|
|
122
|
+
"bg-primary text-primary-foreground",
|
|
123
|
+
"hover:bg-primary/90",
|
|
124
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
125
|
+
)}
|
|
126
|
+
aria-busy={isPurchasing}
|
|
127
|
+
>
|
|
128
|
+
{isPurchasing ? "Redirecting\u2026" : "Buy"}
|
|
129
|
+
</button>
|
|
130
|
+
</div>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@stigmer/theme";
|
|
4
|
+
import { AlertTriangle } from "lucide-react";
|
|
5
|
+
import { formatCreditBalance } from "./format";
|
|
6
|
+
|
|
7
|
+
/** Props for {@link LowBalanceBanner}. */
|
|
8
|
+
export interface LowBalanceBannerProps {
|
|
9
|
+
/** Available balance in micro-USD. */
|
|
10
|
+
readonly availableMicros: bigint;
|
|
11
|
+
/** Threshold in micro-USD below which the warning is shown. */
|
|
12
|
+
readonly thresholdMicros: bigint;
|
|
13
|
+
/** Additional CSS class names. */
|
|
14
|
+
readonly className?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Conditional banner that warns when the available credit balance
|
|
19
|
+
* is below the configured threshold.
|
|
20
|
+
*
|
|
21
|
+
* Renders nothing when the balance is healthy. Not dismissible —
|
|
22
|
+
* it reflects a real account state that the user should address.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* <LowBalanceBanner
|
|
27
|
+
* availableMicros={account.balance.availableMicros}
|
|
28
|
+
* thresholdMicros={account.lowBalanceThresholdMicros}
|
|
29
|
+
* />
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function LowBalanceBanner({
|
|
33
|
+
availableMicros,
|
|
34
|
+
thresholdMicros,
|
|
35
|
+
className,
|
|
36
|
+
}: LowBalanceBannerProps) {
|
|
37
|
+
if (availableMicros >= thresholdMicros) return null;
|
|
38
|
+
|
|
39
|
+
const isZeroOrNegative = availableMicros <= BigInt(0);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div
|
|
43
|
+
role="alert"
|
|
44
|
+
className={cn(
|
|
45
|
+
"flex items-start gap-2.5 rounded-lg border px-3.5 py-3 text-xs",
|
|
46
|
+
isZeroOrNegative
|
|
47
|
+
? "border-destructive/30 bg-destructive/5 text-destructive"
|
|
48
|
+
: "border-warning/30 bg-warning/5 text-warning-foreground",
|
|
49
|
+
className,
|
|
50
|
+
)}
|
|
51
|
+
>
|
|
52
|
+
<AlertTriangle className="mt-0.5 size-3.5 shrink-0" aria-hidden="true" />
|
|
53
|
+
<div>
|
|
54
|
+
<p className="font-medium">
|
|
55
|
+
{isZeroOrNegative
|
|
56
|
+
? "Credit balance exhausted"
|
|
57
|
+
: "Low credit balance"}
|
|
58
|
+
</p>
|
|
59
|
+
<p className="mt-0.5 opacity-80">
|
|
60
|
+
{isZeroOrNegative
|
|
61
|
+
? "Your credit balance is zero. Purchase credits to continue running agent executions."
|
|
62
|
+
: `Your balance (${formatCreditBalance(availableMicros)}) is below the warning threshold. Consider purchasing additional credits.`}
|
|
63
|
+
</p>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@stigmer/theme";
|
|
4
|
+
import type { PaymentMethodSummary } from "@stigmer/protos/ai/stigmer/billing/v1/billing_account_pb";
|
|
5
|
+
import { BillingAccountStatus } from "@stigmer/protos/ai/stigmer/billing/v1/enum_pb";
|
|
6
|
+
|
|
7
|
+
/** Props for {@link PaymentMethodCard}. */
|
|
8
|
+
export interface PaymentMethodCardProps {
|
|
9
|
+
/** The saved payment method, or undefined if none is on file. */
|
|
10
|
+
readonly paymentMethod?: PaymentMethodSummary;
|
|
11
|
+
/** Account status — portal button disabled when suspended or closed. */
|
|
12
|
+
readonly accountStatus: BillingAccountStatus;
|
|
13
|
+
/** `true` while the portal session is being created. */
|
|
14
|
+
readonly isPortalLoading?: boolean;
|
|
15
|
+
/** Called when the user clicks "Manage payment methods". */
|
|
16
|
+
readonly onManage: () => void;
|
|
17
|
+
/** Additional CSS class names. */
|
|
18
|
+
readonly className?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const BRAND_DISPLAY: Record<string, string> = {
|
|
22
|
+
visa: "Visa",
|
|
23
|
+
mastercard: "Mastercard",
|
|
24
|
+
amex: "American Express",
|
|
25
|
+
discover: "Discover",
|
|
26
|
+
diners: "Diners Club",
|
|
27
|
+
jcb: "JCB",
|
|
28
|
+
unionpay: "UnionPay",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function formatBrand(brand: string): string {
|
|
32
|
+
return BRAND_DISPLAY[brand.toLowerCase()] ?? brand;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function formatExpiry(month: number, year: number): string {
|
|
36
|
+
const m = String(month).padStart(2, "0");
|
|
37
|
+
const y = String(year).slice(-2);
|
|
38
|
+
return `${m}/${y}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Displays the saved payment method with a button to open the
|
|
43
|
+
* Stripe Customer Portal for management.
|
|
44
|
+
*
|
|
45
|
+
* Shows card brand, last 4 digits, and expiry when a payment method
|
|
46
|
+
* is on file. Shows an empty state prompt when none exists. The
|
|
47
|
+
* "Manage" button opens the Stripe Customer Portal where users can
|
|
48
|
+
* add, update, or remove payment methods.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* <PaymentMethodCard
|
|
53
|
+
* paymentMethod={account.defaultPaymentMethod}
|
|
54
|
+
* accountStatus={account.status}
|
|
55
|
+
* onManage={() => openPortal(orgId)}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export function PaymentMethodCard({
|
|
60
|
+
paymentMethod,
|
|
61
|
+
accountStatus,
|
|
62
|
+
isPortalLoading,
|
|
63
|
+
onManage,
|
|
64
|
+
className,
|
|
65
|
+
}: PaymentMethodCardProps) {
|
|
66
|
+
const isAccountActive =
|
|
67
|
+
accountStatus === BillingAccountStatus.billing_account_active;
|
|
68
|
+
const hasPm =
|
|
69
|
+
paymentMethod != null && paymentMethod.paymentMethodId !== "";
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div
|
|
73
|
+
className={cn(
|
|
74
|
+
"rounded-lg border border-border bg-card px-4 py-4",
|
|
75
|
+
className,
|
|
76
|
+
)}
|
|
77
|
+
>
|
|
78
|
+
<div className="flex items-center justify-between">
|
|
79
|
+
<h3 className="text-xs font-semibold text-foreground">
|
|
80
|
+
Payment Method
|
|
81
|
+
</h3>
|
|
82
|
+
{hasPm && (
|
|
83
|
+
<button
|
|
84
|
+
type="button"
|
|
85
|
+
disabled={!isAccountActive || isPortalLoading}
|
|
86
|
+
onClick={onManage}
|
|
87
|
+
className={cn(
|
|
88
|
+
"rounded-md px-2.5 py-1 text-xs font-medium transition-colors",
|
|
89
|
+
"text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
90
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
91
|
+
)}
|
|
92
|
+
aria-busy={isPortalLoading}
|
|
93
|
+
>
|
|
94
|
+
{isPortalLoading ? "Opening\u2026" : "Manage"}
|
|
95
|
+
</button>
|
|
96
|
+
)}
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
{hasPm ? (
|
|
100
|
+
<div className="mt-2 flex items-center gap-3">
|
|
101
|
+
<CardBrandIcon brand={paymentMethod.brand} />
|
|
102
|
+
<div>
|
|
103
|
+
<div className="text-sm font-medium text-foreground">
|
|
104
|
+
{formatBrand(paymentMethod.brand)} ····{" "}
|
|
105
|
+
{paymentMethod.last4}
|
|
106
|
+
</div>
|
|
107
|
+
<div className="text-xs text-muted-foreground">
|
|
108
|
+
Expires{" "}
|
|
109
|
+
{formatExpiry(paymentMethod.expMonth, paymentMethod.expYear)}
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
) : (
|
|
114
|
+
<div className="mt-2">
|
|
115
|
+
<p className="text-xs text-muted-foreground">
|
|
116
|
+
No payment method on file. A card will be saved automatically
|
|
117
|
+
when you purchase your first credit pack.
|
|
118
|
+
</p>
|
|
119
|
+
</div>
|
|
120
|
+
)}
|
|
121
|
+
</div>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function CardBrandIcon({ brand }: { brand: string }) {
|
|
126
|
+
return (
|
|
127
|
+
<div className="flex size-9 items-center justify-center rounded-md border border-border bg-background">
|
|
128
|
+
<span className="text-[0.6rem] font-bold uppercase text-muted-foreground">
|
|
129
|
+
{brand.slice(0, 4)}
|
|
130
|
+
</span>
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Metadata for a self-serve credit pack. */
|
|
2
|
+
export interface CreditPackInfo {
|
|
3
|
+
/** Stable identifier matching the backend catalog (e.g., "starter"). */
|
|
4
|
+
readonly packId: string;
|
|
5
|
+
/** Display name shown in the UI. */
|
|
6
|
+
readonly displayName: string;
|
|
7
|
+
/** Brief description of the pack's positioning. */
|
|
8
|
+
readonly description: string;
|
|
9
|
+
/** Price in USD cents (e.g., 1000 = $10.00). */
|
|
10
|
+
readonly priceCents: number;
|
|
11
|
+
/** Number of credits granted (1 credit = $0.01 USD). */
|
|
12
|
+
readonly credits: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Static credit pack catalog matching the backend `CreditPackCatalog`.
|
|
17
|
+
*
|
|
18
|
+
* Packs are static product entries, not database-backed resources.
|
|
19
|
+
* At launch, credits equal the dollar value (no volume bonus).
|
|
20
|
+
*/
|
|
21
|
+
export const CREDIT_PACKS: readonly CreditPackInfo[] = [
|
|
22
|
+
{
|
|
23
|
+
packId: "starter",
|
|
24
|
+
displayName: "Starter",
|
|
25
|
+
description: "For trying things out",
|
|
26
|
+
priceCents: 1_000,
|
|
27
|
+
credits: 1_000,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
packId: "growth",
|
|
31
|
+
displayName: "Growth",
|
|
32
|
+
description: "For growing teams",
|
|
33
|
+
priceCents: 5_000,
|
|
34
|
+
credits: 5_000,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
packId: "team",
|
|
38
|
+
displayName: "Team",
|
|
39
|
+
description: "For production workloads",
|
|
40
|
+
priceCents: 20_000,
|
|
41
|
+
credits: 20_000,
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
/** Format a cent amount as a dollar string (e.g., 1000 -> "$10"). */
|
|
46
|
+
export function formatPackPrice(cents: number): string {
|
|
47
|
+
const dollars = cents / 100;
|
|
48
|
+
return dollars % 1 === 0 ? `$${dollars}` : `$${dollars.toFixed(2)}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Format a credit count with commas (e.g., 5000 -> "5,000"). */
|
|
52
|
+
export function formatCreditCount(credits: number): string {
|
|
53
|
+
return credits.toLocaleString("en-US");
|
|
54
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { LedgerEntryType } from "@stigmer/protos/ai/stigmer/billing/v1/enum_pb";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Convert micro-USD (bigint) to a display string like "$12.50".
|
|
5
|
+
*
|
|
6
|
+
* Micro-USD uses 6 decimal places (1 USD = 1,000,000 micros).
|
|
7
|
+
* The output always shows exactly 2 decimal places.
|
|
8
|
+
*/
|
|
9
|
+
export function formatCreditBalance(micros: bigint | undefined): string {
|
|
10
|
+
if (micros === undefined) return "$0.00";
|
|
11
|
+
const cents = Number(micros) / 10_000;
|
|
12
|
+
const dollars = cents / 100;
|
|
13
|
+
return `$${dollars.toFixed(2)}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Convert micro-USD (bigint) to a signed display string.
|
|
18
|
+
*
|
|
19
|
+
* Positive amounts show "+$5.00", negative show "-$0.23",
|
|
20
|
+
* zero shows "$0.00" (no sign).
|
|
21
|
+
*/
|
|
22
|
+
export function formatLedgerAmount(micros: bigint): string {
|
|
23
|
+
const zero = BigInt(0);
|
|
24
|
+
const absMicros = micros < zero ? -micros : micros;
|
|
25
|
+
const dollars = Number(absMicros) / 1_000_000;
|
|
26
|
+
const formatted = `$${dollars.toFixed(2)}`;
|
|
27
|
+
if (micros > zero) return `+${formatted}`;
|
|
28
|
+
if (micros < zero) return `-${formatted}`;
|
|
29
|
+
return formatted;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const ENTRY_LABELS: Record<number, string> = {
|
|
33
|
+
[LedgerEntryType.purchase_credit]: "Credit Purchase",
|
|
34
|
+
[LedgerEntryType.promotional_credit]: "Promotional Credit",
|
|
35
|
+
[LedgerEntryType.usage_debit]: "Usage",
|
|
36
|
+
[LedgerEntryType.reservation_hold]: "Reservation Hold",
|
|
37
|
+
[LedgerEntryType.reservation_release]: "Reservation Release",
|
|
38
|
+
[LedgerEntryType.adjustment_credit]: "Admin Credit",
|
|
39
|
+
[LedgerEntryType.adjustment_debit]: "Admin Debit",
|
|
40
|
+
[LedgerEntryType.refund_reversal]: "Refund",
|
|
41
|
+
[LedgerEntryType.dispute_hold]: "Dispute Hold",
|
|
42
|
+
[LedgerEntryType.dispute_release]: "Dispute Release",
|
|
43
|
+
[LedgerEntryType.expiry_debit]: "Credit Expiry",
|
|
44
|
+
[LedgerEntryType.auto_recharge_credit]: "Auto-Recharge",
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/** Human-readable label for a ledger entry type. */
|
|
48
|
+
export function ledgerEntryLabel(type: LedgerEntryType): string {
|
|
49
|
+
return ENTRY_LABELS[type] ?? "Unknown";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Whether a ledger entry type represents a credit (positive amount).
|
|
54
|
+
*
|
|
55
|
+
* Used by UI components to choose semantic colors: green for credits,
|
|
56
|
+
* red for debits, gray for holds/releases.
|
|
57
|
+
*/
|
|
58
|
+
export function isCredit(type: LedgerEntryType): boolean {
|
|
59
|
+
return (
|
|
60
|
+
type === LedgerEntryType.purchase_credit ||
|
|
61
|
+
type === LedgerEntryType.promotional_credit ||
|
|
62
|
+
type === LedgerEntryType.adjustment_credit ||
|
|
63
|
+
type === LedgerEntryType.reservation_release ||
|
|
64
|
+
type === LedgerEntryType.dispute_release ||
|
|
65
|
+
type === LedgerEntryType.auto_recharge_credit
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Whether a ledger entry type represents a hold operation.
|
|
71
|
+
*
|
|
72
|
+
* Holds are neither credits nor debits in the user's mental model —
|
|
73
|
+
* they represent temporary balance changes (reservations, disputes).
|
|
74
|
+
*/
|
|
75
|
+
export function isHold(type: LedgerEntryType): boolean {
|
|
76
|
+
return (
|
|
77
|
+
type === LedgerEntryType.reservation_hold ||
|
|
78
|
+
type === LedgerEntryType.dispute_hold
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Format a protobuf Timestamp for ledger display.
|
|
84
|
+
*
|
|
85
|
+
* Returns a locale-appropriate date and time string
|
|
86
|
+
* (e.g., "May 3, 2026, 4:30 PM").
|
|
87
|
+
*/
|
|
88
|
+
export function formatLedgerDate(seconds: bigint): string {
|
|
89
|
+
const date = new Date(Number(seconds) * 1000);
|
|
90
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
91
|
+
month: "short",
|
|
92
|
+
day: "numeric",
|
|
93
|
+
year: "numeric",
|
|
94
|
+
hour: "numeric",
|
|
95
|
+
minute: "2-digit",
|
|
96
|
+
}).format(date);
|
|
97
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Data hooks
|
|
2
|
+
export { useBillingAccount } from "./useBillingAccount";
|
|
3
|
+
export type { UseBillingAccountReturn } from "./useBillingAccount";
|
|
4
|
+
export { useCreditLedger } from "./useCreditLedger";
|
|
5
|
+
export type { UseCreditLedgerReturn, UseCreditLedgerOptions } from "./useCreditLedger";
|
|
6
|
+
export { useBillingUsageReport } from "./useBillingUsageReport";
|
|
7
|
+
export type { UseBillingUsageReportReturn } from "./useBillingUsageReport";
|
|
8
|
+
export { useCustomerModelPricing } from "./useCustomerModelPricing";
|
|
9
|
+
export type { UseCustomerModelPricingReturn } from "./useCustomerModelPricing";
|
|
10
|
+
|
|
11
|
+
// Behavior hooks
|
|
12
|
+
export { useCreateCheckoutSession } from "./useCreateCheckoutSession";
|
|
13
|
+
export type {
|
|
14
|
+
CreateCheckoutSessionInput,
|
|
15
|
+
UseCreateCheckoutSessionReturn,
|
|
16
|
+
} from "./useCreateCheckoutSession";
|
|
17
|
+
export { useCreateBillingPortalSession } from "./useCreateBillingPortalSession";
|
|
18
|
+
export type { UseCreateBillingPortalSessionReturn } from "./useCreateBillingPortalSession";
|
|
19
|
+
export { useSetAutoRechargeConfig } from "./useSetAutoRechargeConfig";
|
|
20
|
+
export type {
|
|
21
|
+
SetAutoRechargeConfigInput,
|
|
22
|
+
UseSetAutoRechargeConfigReturn,
|
|
23
|
+
} from "./useSetAutoRechargeConfig";
|
|
24
|
+
|
|
25
|
+
// Styled components
|
|
26
|
+
export { BillingSection } from "./BillingSection";
|
|
27
|
+
export type { BillingSectionProps } from "./BillingSection";
|
|
28
|
+
export { CreditBalanceCard } from "./CreditBalanceCard";
|
|
29
|
+
export type { CreditBalanceCardProps } from "./CreditBalanceCard";
|
|
30
|
+
export { PaymentMethodCard } from "./PaymentMethodCard";
|
|
31
|
+
export type { PaymentMethodCardProps } from "./PaymentMethodCard";
|
|
32
|
+
export { AutoRechargeCard } from "./AutoRechargeCard";
|
|
33
|
+
export type { AutoRechargeCardProps } from "./AutoRechargeCard";
|
|
34
|
+
export { CreditPackGrid } from "./CreditPackGrid";
|
|
35
|
+
export type { CreditPackGridProps } from "./CreditPackGrid";
|
|
36
|
+
export { CreditLedgerTable } from "./CreditLedgerTable";
|
|
37
|
+
export type { CreditLedgerTableProps } from "./CreditLedgerTable";
|
|
38
|
+
export { LowBalanceBanner } from "./LowBalanceBanner";
|
|
39
|
+
export type { LowBalanceBannerProps } from "./LowBalanceBanner";
|
|
40
|
+
|
|
41
|
+
// Credit pack catalog and formatting utilities
|
|
42
|
+
export { CREDIT_PACKS, formatPackPrice, formatCreditCount } from "./credit-packs";
|
|
43
|
+
export type { CreditPackInfo } from "./credit-packs";
|
|
44
|
+
export {
|
|
45
|
+
formatCreditBalance,
|
|
46
|
+
formatLedgerAmount,
|
|
47
|
+
ledgerEntryLabel,
|
|
48
|
+
isCredit,
|
|
49
|
+
isHold,
|
|
50
|
+
formatLedgerDate,
|
|
51
|
+
} from "./format";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { create } from "@bufbuild/protobuf";
|
|
4
|
+
import {
|
|
5
|
+
GetOrCreateBillingAccountInputSchema,
|
|
6
|
+
} from "@stigmer/protos/ai/stigmer/billing/v1/io_pb";
|
|
7
|
+
import type { BillingAccount } from "@stigmer/protos/ai/stigmer/billing/v1/billing_account_pb";
|
|
8
|
+
import { useStigmer } from "../hooks";
|
|
9
|
+
import { useFetch } from "../internal/useFetch";
|
|
10
|
+
|
|
11
|
+
/** Return value of {@link useBillingAccount}. */
|
|
12
|
+
export interface UseBillingAccountReturn {
|
|
13
|
+
/** The billing account, or `null` before the first successful fetch. */
|
|
14
|
+
readonly account: BillingAccount | null;
|
|
15
|
+
/** `true` while the initial fetch is in flight. */
|
|
16
|
+
readonly isLoading: boolean;
|
|
17
|
+
/** `true` while a background refetch is in flight and stale data is shown. */
|
|
18
|
+
readonly isRefetching: boolean;
|
|
19
|
+
/** Error from the last failed request, or `null` when healthy. */
|
|
20
|
+
readonly error: Error | null;
|
|
21
|
+
/** Discard cached data and re-fetch from the server. */
|
|
22
|
+
readonly refetch: () => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Data hook that fetches the billing account for an organization.
|
|
27
|
+
*
|
|
28
|
+
* Calls `billing.getOrCreateBillingAccount` which is idempotent —
|
|
29
|
+
* creates the account on first call, returns the existing account
|
|
30
|
+
* on subsequent calls. The returned `BillingAccount` includes
|
|
31
|
+
* the embedded `CreditBalance` with available, reserved,
|
|
32
|
+
* promotional, and purchased breakdowns.
|
|
33
|
+
*
|
|
34
|
+
* Pass `null` as `orgId` to skip fetching (stable no-op).
|
|
35
|
+
*
|
|
36
|
+
* @param orgId - Organization ID, or `null` to skip.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```tsx
|
|
40
|
+
* const { account, isLoading, error } = useBillingAccount(orgId);
|
|
41
|
+
*
|
|
42
|
+
* if (isLoading) return <Skeleton />;
|
|
43
|
+
* if (error) return <ErrorMessage error={error} />;
|
|
44
|
+
* if (!account) return null;
|
|
45
|
+
*
|
|
46
|
+
* return <div>Balance: {formatCreditBalance(account.balance?.availableMicros)}</div>;
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function useBillingAccount(
|
|
50
|
+
orgId: string | null,
|
|
51
|
+
): UseBillingAccountReturn {
|
|
52
|
+
const stigmer = useStigmer();
|
|
53
|
+
|
|
54
|
+
const { data: account, isLoading, isRefetching, error, refetch } = useFetch(
|
|
55
|
+
orgId
|
|
56
|
+
? () =>
|
|
57
|
+
stigmer.billing.getOrCreateBillingAccount(orgId)
|
|
58
|
+
: null,
|
|
59
|
+
[orgId, stigmer],
|
|
60
|
+
null as BillingAccount | null,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return { account, isLoading, isRefetching, error, refetch };
|
|
64
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
BillingUsageReportResponse,
|
|
5
|
+
} from "@stigmer/protos/ai/stigmer/billing/v1/io_pb";
|
|
6
|
+
import { useStigmer } from "../hooks";
|
|
7
|
+
import { useFetch } from "../internal/useFetch";
|
|
8
|
+
|
|
9
|
+
/** Return value of {@link useBillingUsageReport}. */
|
|
10
|
+
export interface UseBillingUsageReportReturn {
|
|
11
|
+
/** The usage report, or `null` before the first successful fetch. */
|
|
12
|
+
readonly report: BillingUsageReportResponse | null;
|
|
13
|
+
/** `true` while the initial fetch is in flight. */
|
|
14
|
+
readonly isLoading: boolean;
|
|
15
|
+
/** `true` while a background refetch is in flight and stale data is shown. */
|
|
16
|
+
readonly isRefetching: boolean;
|
|
17
|
+
/** Error from the last failed request, or `null` when healthy. */
|
|
18
|
+
readonly error: Error | null;
|
|
19
|
+
/** Discard cached data and re-fetch from the server. */
|
|
20
|
+
readonly refetch: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Data hook that fetches an aggregated billing usage report for a date range.
|
|
25
|
+
*
|
|
26
|
+
* Returns total provider cost, total billable amount, execution and LLM
|
|
27
|
+
* call counts, and a per-model breakdown with cost tier attribution.
|
|
28
|
+
*
|
|
29
|
+
* Pass `null` as `orgId` to skip fetching (stable no-op).
|
|
30
|
+
*
|
|
31
|
+
* @param orgId - Organization ID, or `null` to skip.
|
|
32
|
+
* @param startTime - Start of the reporting period.
|
|
33
|
+
* @param endTime - End of the reporting period.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* const { report, isLoading } = useBillingUsageReport(
|
|
38
|
+
* orgId,
|
|
39
|
+
* new Date("2026-05-01"),
|
|
40
|
+
* new Date("2026-05-31"),
|
|
41
|
+
* );
|
|
42
|
+
*
|
|
43
|
+
* if (isLoading) return <Skeleton />;
|
|
44
|
+
* if (!report) return null;
|
|
45
|
+
*
|
|
46
|
+
* return <div>Total: {formatCreditBalance(report.totalBillableAmountMicros)}</div>;
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function useBillingUsageReport(
|
|
50
|
+
orgId: string | null,
|
|
51
|
+
startTime: Date,
|
|
52
|
+
endTime: Date,
|
|
53
|
+
): UseBillingUsageReportReturn {
|
|
54
|
+
const stigmer = useStigmer();
|
|
55
|
+
|
|
56
|
+
const startKey = startTime.toISOString();
|
|
57
|
+
const endKey = endTime.toISOString();
|
|
58
|
+
|
|
59
|
+
const { data: report, isLoading, isRefetching, error, refetch } = useFetch(
|
|
60
|
+
orgId
|
|
61
|
+
? () =>
|
|
62
|
+
stigmer.billing.getBillingUsageReport({
|
|
63
|
+
orgId,
|
|
64
|
+
startTime,
|
|
65
|
+
endTime,
|
|
66
|
+
})
|
|
67
|
+
: null,
|
|
68
|
+
[orgId, startKey, endKey, stigmer],
|
|
69
|
+
null as BillingUsageReportResponse | null,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return { report, isLoading, isRefetching, error, refetch };
|
|
73
|
+
}
|