@stigmer/react 0.3.4 → 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
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useCallback, useEffect, useRef, useState } from "react";
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
4
  import { create } from "@bufbuild/protobuf";
5
5
  import { EnvironmentSecretValueInputSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/io_pb";
6
6
  import { useStigmer } from "../hooks";
@@ -526,16 +526,21 @@ export function useGitHubConnection(
526
526
  }
527
527
  }, []);
528
528
 
529
- return {
530
- isConnected: token !== null,
531
- isLoading,
532
- isConnecting,
533
- popupBlocked,
534
- user,
535
- token,
536
- connect,
537
- handleCallback,
538
- reconcile,
539
- disconnect,
540
- };
529
+ const isConnected = token !== null;
530
+
531
+ return useMemo(
532
+ () => ({
533
+ isConnected,
534
+ isLoading,
535
+ isConnecting,
536
+ popupBlocked,
537
+ user,
538
+ token,
539
+ connect,
540
+ handleCallback,
541
+ reconcile,
542
+ disconnect,
543
+ }),
544
+ [isConnected, isLoading, isConnecting, popupBlocked, user, token, connect, handleCallback, reconcile, disconnect],
545
+ );
541
546
  }
@@ -0,0 +1,5 @@
1
+ export {
2
+ useIdentityAccountGate,
3
+ type IdentityAccountGateState,
4
+ type UseIdentityAccountGateReturn,
5
+ } from "./useIdentityAccountGate";
@@ -0,0 +1,163 @@
1
+ "use client";
2
+
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import type { IdentityAccount } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
5
+ import { isNotFound } from "@stigmer/sdk";
6
+ import { useStigmer } from "../hooks";
7
+ import { toError } from "../internal/toError";
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Types
11
+ // ---------------------------------------------------------------------------
12
+
13
+ /**
14
+ * Discriminated union representing the current state of the identity
15
+ * account gate.
16
+ *
17
+ * Narrow on `status` to access variant-specific data:
18
+ *
19
+ * ```ts
20
+ * if (state.status === "ready") {
21
+ * console.log(state.account.metadata?.id);
22
+ * }
23
+ * ```
24
+ */
25
+ export type IdentityAccountGateState =
26
+ | {
27
+ /** Resolving the caller's identity account via whoAmI. */
28
+ readonly status: "checking";
29
+ }
30
+ | {
31
+ /** whoAmI returned NOT_FOUND; provisionMyAccount is in flight. */
32
+ readonly status: "provisioning";
33
+ }
34
+ | {
35
+ /** Identity account is resolved and available. */
36
+ readonly status: "ready";
37
+ /** The resolved identity account. */
38
+ readonly account: IdentityAccount;
39
+ }
40
+ | {
41
+ /** A non-recoverable error occurred. */
42
+ readonly status: "error";
43
+ /** Human-readable failure message suitable for UI display. */
44
+ readonly message: string;
45
+ };
46
+
47
+ /**
48
+ * Return value of {@link useIdentityAccountGate}.
49
+ *
50
+ * `retry` is always available; the consumer invokes it when
51
+ * `status === "error"`.
52
+ */
53
+ export interface UseIdentityAccountGateReturn {
54
+ /** Current gate state. Discriminated union on `status`. */
55
+ readonly state: IdentityAccountGateState;
56
+ /** Re-attempt the identity resolution from scratch. */
57
+ readonly retry: () => void;
58
+ }
59
+
60
+ // ---------------------------------------------------------------------------
61
+ // Hook
62
+ // ---------------------------------------------------------------------------
63
+
64
+ /**
65
+ * Headless behavior hook that ensures the authenticated caller has an
66
+ * identity account before the application renders.
67
+ *
68
+ * The hook drives the following lifecycle:
69
+ *
70
+ * 1. **`checking`** — calls `whoAmI()` to look up the caller's account.
71
+ * 2. **`provisioning`** — `whoAmI` returned NOT_FOUND (first login after
72
+ * signup); the hook calls `provisionMyAccount()` to create the account
73
+ * and personal organization.
74
+ * 3. **`ready`** — an identity account is available (either pre-existing
75
+ * or freshly provisioned).
76
+ * 4. **`error`** — a non-recoverable failure occurred; `message` carries
77
+ * the reason. Call `retry()` to restart from step 1.
78
+ *
79
+ * The hook is a no-op when `isEnabled` is false — it immediately reports
80
+ * `ready` with a `null`-account shortcut so that disabled-auth deployments
81
+ * skip the gate entirely.
82
+ *
83
+ * @example
84
+ * ```tsx
85
+ * const { state, retry } = useIdentityAccountGate({ isEnabled: true });
86
+ *
87
+ * switch (state.status) {
88
+ * case "checking":
89
+ * case "provisioning":
90
+ * return <Spinner />;
91
+ * case "ready":
92
+ * return <>{children}</>;
93
+ * case "error":
94
+ * return <ErrorScreen message={state.message} onRetry={retry} />;
95
+ * }
96
+ * ```
97
+ */
98
+ export function useIdentityAccountGate(options: {
99
+ /** Set to `true` when OIDC auth is active. When `false`, the gate is bypassed. */
100
+ readonly isEnabled: boolean;
101
+ }): UseIdentityAccountGateReturn {
102
+ const { isEnabled } = options;
103
+ const stigmer = useStigmer();
104
+
105
+ const [state, setState] = useState<IdentityAccountGateState>(
106
+ isEnabled ? { status: "checking" } : BYPASSED_STATE,
107
+ );
108
+
109
+ const attemptRef = useRef(0);
110
+
111
+ const resolve = useCallback(async () => {
112
+ const attempt = ++attemptRef.current;
113
+ setState({ status: "checking" });
114
+
115
+ try {
116
+ const account = await stigmer.identityAccount.whoAmI();
117
+ if (attempt !== attemptRef.current) return;
118
+ setState({ status: "ready", account });
119
+ } catch (whoAmIErr: unknown) {
120
+ if (attempt !== attemptRef.current) return;
121
+
122
+ if (!isNotFound(whoAmIErr)) {
123
+ setState({ status: "error", message: toError(whoAmIErr).message });
124
+ return;
125
+ }
126
+
127
+ setState({ status: "provisioning" });
128
+
129
+ try {
130
+ const account = await stigmer.identityAccount.provisionMyAccount();
131
+ if (attempt !== attemptRef.current) return;
132
+ setState({ status: "ready", account });
133
+ } catch (provisionErr: unknown) {
134
+ if (attempt !== attemptRef.current) return;
135
+ setState({ status: "error", message: toError(provisionErr).message });
136
+ }
137
+ }
138
+ }, [stigmer]);
139
+
140
+ useEffect(() => {
141
+ if (!isEnabled) {
142
+ setState(BYPASSED_STATE);
143
+ return;
144
+ }
145
+ resolve();
146
+ }, [isEnabled, resolve]);
147
+
148
+ const retry = useCallback(() => {
149
+ if (isEnabled) resolve();
150
+ }, [isEnabled, resolve]);
151
+
152
+ return { state, retry };
153
+ }
154
+
155
+ /**
156
+ * Sentinel state used when the gate is disabled. The consumer must treat
157
+ * `status === "ready"` without accessing `account` when auth is disabled
158
+ * (there is no real identity in that mode).
159
+ */
160
+ const BYPASSED_STATE: IdentityAccountGateState = Object.freeze({
161
+ status: "ready",
162
+ account: null as unknown as IdentityAccount,
163
+ });
package/src/index.ts CHANGED
@@ -2,6 +2,10 @@
2
2
  export { StigmerProvider, type StigmerProviderProps } from "./provider";
3
3
  export { StigmerContext } from "./context";
4
4
 
5
+ // Fetch cache
6
+ export { FetchCacheProvider } from "./internal/FetchCacheProvider";
7
+ export type { FetchCacheOptions } from "./internal/fetch-cache";
8
+
5
9
  // Hooks
6
10
  export { useStigmer } from "./hooks";
7
11
 
@@ -139,6 +143,7 @@ export {
139
143
  SubAgentSection,
140
144
  MessageEntry,
141
145
  MessageThread,
146
+ ThreadSkeleton,
142
147
  FollowUpInput,
143
148
  ApprovalCard,
144
149
  ArtifactCard,
@@ -189,6 +194,7 @@ export type {
189
194
  SubAgentSectionProps,
190
195
  MessageEntryProps,
191
196
  MessageThreadProps,
197
+ ThreadSkeletonProps,
192
198
  FollowUpInputProps,
193
199
  ApprovalCardProps,
194
200
  ArtifactCardProps,
@@ -417,6 +423,15 @@ export type {
417
423
  UseSessionEnvPoolReturn,
418
424
  } from "./environment";
419
425
 
426
+ // Identity Account — gate hook for ensuring the caller's identity account exists before app render
427
+ export {
428
+ useIdentityAccountGate,
429
+ } from "./identity-account";
430
+ export type {
431
+ IdentityAccountGateState,
432
+ UseIdentityAccountGateReturn,
433
+ } from "./identity-account";
434
+
420
435
  // IAM Policy — data hooks, behavior hooks, headless hook, and styled components for access management
421
436
  export {
422
437
  useGrantableRoles,
@@ -474,6 +489,53 @@ export type {
474
489
  OrgSwitcherProps,
475
490
  } from "./organization";
476
491
 
492
+ // Billing — data hooks, behavior hooks, styled components, catalog, and formatting utilities
493
+ export {
494
+ useBillingAccount,
495
+ useCreditLedger,
496
+ useBillingUsageReport,
497
+ useCustomerModelPricing,
498
+ useCreateCheckoutSession,
499
+ useCreateBillingPortalSession,
500
+ useSetAutoRechargeConfig,
501
+ BillingSection,
502
+ CreditBalanceCard,
503
+ PaymentMethodCard,
504
+ AutoRechargeCard,
505
+ CreditPackGrid,
506
+ CreditLedgerTable,
507
+ LowBalanceBanner,
508
+ CREDIT_PACKS,
509
+ formatPackPrice,
510
+ formatCreditCount,
511
+ formatCreditBalance,
512
+ formatLedgerAmount,
513
+ ledgerEntryLabel,
514
+ isCredit,
515
+ isHold,
516
+ formatLedgerDate,
517
+ } from "./billing";
518
+ export type {
519
+ UseBillingAccountReturn,
520
+ UseCreditLedgerReturn,
521
+ UseCreditLedgerOptions,
522
+ UseBillingUsageReportReturn,
523
+ UseCustomerModelPricingReturn,
524
+ CreateCheckoutSessionInput,
525
+ UseCreateCheckoutSessionReturn,
526
+ UseCreateBillingPortalSessionReturn,
527
+ SetAutoRechargeConfigInput,
528
+ UseSetAutoRechargeConfigReturn,
529
+ BillingSectionProps,
530
+ CreditBalanceCardProps,
531
+ PaymentMethodCardProps,
532
+ AutoRechargeCardProps,
533
+ CreditPackGridProps,
534
+ CreditLedgerTableProps,
535
+ LowBalanceBannerProps,
536
+ CreditPackInfo,
537
+ } from "./billing";
538
+
477
539
  // Settings — navigation structure + section components shared across app shells
478
540
  export { SETTINGS_NAV_GROUPS } from "./settings";
479
541
  export type { SettingsNavItem, SettingsNavGroup } from "./settings";
@@ -666,6 +728,11 @@ export type {
666
728
  export {
667
729
  useOrgUsageReport,
668
730
  OrgUsagePanel,
731
+ CreditRunwayIndicator,
732
+ AgentBreakdownList,
733
+ HarnessSplitCard,
734
+ useExportCSV,
735
+ ExportButton,
669
736
  DATE_RANGE_PRESETS,
670
737
  dateRangeFromPreset,
671
738
  formatDateRange,
@@ -674,6 +741,12 @@ export {
674
741
  export type {
675
742
  UseOrgUsageReportReturn,
676
743
  OrgUsagePanelProps,
744
+ CreditRunwayIndicatorProps,
745
+ AgentBreakdownListProps,
746
+ HarnessSplitCardProps,
747
+ UseExportCSVReturn,
748
+ ExportFormat,
749
+ ExportButtonProps,
677
750
  DateRange,
678
751
  DateRangePreset,
679
752
  } from "./usage";
@@ -0,0 +1,74 @@
1
+ "use client";
2
+
3
+ import { createContext, useContext, useRef, type ReactNode } from "react";
4
+ import { FetchCache, type FetchCacheOptions } from "./fetch-cache";
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Context
8
+ // ---------------------------------------------------------------------------
9
+
10
+ /**
11
+ * @internal Exported for test-level injection — not part of the public API.
12
+ */
13
+ export const FetchCacheContext = createContext<FetchCache | null>(null);
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Provider
17
+ // ---------------------------------------------------------------------------
18
+
19
+ /**
20
+ * Provides a `FetchCache` instance to descendant `useFetch` hooks.
21
+ *
22
+ * Mount this component **above** any remount boundary (e.g. above a
23
+ * `key`-driven session switch) so that cached data survives when child
24
+ * components unmount and remount. Without this provider, `useFetch`
25
+ * works exactly as before — no cache, no behavior change.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * // In your app shell (above the session key boundary):
30
+ * <FetchCacheProvider>
31
+ * <SessionPageInner key={activeSessionId} id={activeSessionId} />
32
+ * </FetchCacheProvider>
33
+ * ```
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * // With custom limits:
38
+ * <FetchCacheProvider maxEntries={50} ttl={120_000}>
39
+ * <App />
40
+ * </FetchCacheProvider>
41
+ * ```
42
+ */
43
+ export function FetchCacheProvider({
44
+ children,
45
+ maxEntries,
46
+ ttl,
47
+ }: FetchCacheOptions & { children: ReactNode }) {
48
+ const cacheRef = useRef<FetchCache | null>(null);
49
+ if (!cacheRef.current) {
50
+ cacheRef.current = new FetchCache({ maxEntries, ttl });
51
+ }
52
+ return (
53
+ <FetchCacheContext.Provider value={cacheRef.current}>
54
+ {children}
55
+ </FetchCacheContext.Provider>
56
+ );
57
+ }
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // Hook
61
+ // ---------------------------------------------------------------------------
62
+
63
+ /**
64
+ * Access the nearest `FetchCache` from context.
65
+ *
66
+ * Returns `null` when no `FetchCacheProvider` is mounted — callers
67
+ * must handle the null case gracefully (skip caching).
68
+ *
69
+ * @internal Consumed by `useFetch`; not intended for direct use by
70
+ * SDK consumers.
71
+ */
72
+ export function useFetchCache(): FetchCache | null {
73
+ return useContext(FetchCacheContext);
74
+ }
@@ -0,0 +1,61 @@
1
+ "use client";
2
+
3
+ import { cn } from "@stigmer/theme";
4
+
5
+ interface JumpToLatestButtonProps {
6
+ readonly onClick: () => void;
7
+ readonly visible: boolean;
8
+ }
9
+
10
+ /**
11
+ * Floating action button that scrolls the thread to the latest content.
12
+ * Always mounted in the DOM to support enter/exit CSS transitions.
13
+ * Hidden via opacity + pointer-events when `visible` is false.
14
+ *
15
+ * @internal Not part of the public API.
16
+ */
17
+ export function JumpToLatestButton({ onClick, visible }: JumpToLatestButtonProps) {
18
+ return (
19
+ <button
20
+ type="button"
21
+ onClick={onClick}
22
+ aria-label="Jump to latest"
23
+ aria-hidden={!visible}
24
+ tabIndex={visible ? 0 : -1}
25
+ className={cn(
26
+ "absolute bottom-3 left-1/2 z-10 -translate-x-1/2",
27
+ "flex items-center gap-1.5 rounded-full",
28
+ "border border-border bg-card px-3 py-1.5",
29
+ "text-xs font-medium text-muted-foreground shadow-md",
30
+ "transition-[opacity,transform] duration-[var(--stgm-motion-duration)]",
31
+ "hover:bg-muted hover:text-foreground",
32
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
33
+ visible
34
+ ? "pointer-events-auto translate-y-0 opacity-100"
35
+ : "pointer-events-none translate-y-2 opacity-0",
36
+ )}
37
+ >
38
+ <ChevronDownIcon />
39
+ Jump to latest
40
+ </button>
41
+ );
42
+ }
43
+
44
+ function ChevronDownIcon() {
45
+ return (
46
+ <svg
47
+ xmlns="http://www.w3.org/2000/svg"
48
+ width="14"
49
+ height="14"
50
+ viewBox="0 0 24 24"
51
+ fill="none"
52
+ stroke="currentColor"
53
+ strokeWidth="2.5"
54
+ strokeLinecap="round"
55
+ strokeLinejoin="round"
56
+ aria-hidden="true"
57
+ >
58
+ <path d="m6 9 6 6 6-6" />
59
+ </svg>
60
+ );
61
+ }
@@ -0,0 +1,65 @@
1
+ "use client";
2
+
3
+ import { useCallback, useRef, useState, type ReactNode } from "react";
4
+
5
+ interface ThreadItemWrapperProps {
6
+ readonly animate: boolean;
7
+ readonly children: ReactNode;
8
+ }
9
+
10
+ const ANIMATION_CLASS = "stgm-thread-item-enter";
11
+
12
+ /**
13
+ * Thin wrapper that applies the `.stgm-thread-item-enter` CSS animation
14
+ * on mount when `animate` is true. The class is removed after the
15
+ * animation completes (via `onAnimationEnd`) to free the browser from
16
+ * tracking a finished animation.
17
+ *
18
+ * A fallback timeout removes the class if `animationend` never fires
19
+ * (e.g. `prefers-reduced-motion` sets duration to ~0ms, or the test
20
+ * environment doesn't dispatch animation events).
21
+ *
22
+ * @internal Not part of the public API.
23
+ */
24
+ export function ThreadItemWrapper({ animate, children }: ThreadItemWrapperProps) {
25
+ const [entering, setEntering] = useState(animate);
26
+ const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
27
+
28
+ const handleAnimationEnd = useCallback(() => {
29
+ setEntering(false);
30
+ if (timerRef.current !== undefined) {
31
+ clearTimeout(timerRef.current);
32
+ timerRef.current = undefined;
33
+ }
34
+ }, []);
35
+
36
+ const divRef = useCallback(
37
+ (node: HTMLDivElement | null) => {
38
+ if (timerRef.current !== undefined) {
39
+ clearTimeout(timerRef.current);
40
+ timerRef.current = undefined;
41
+ }
42
+ if (node && entering) {
43
+ timerRef.current = setTimeout(() => {
44
+ setEntering(false);
45
+ timerRef.current = undefined;
46
+ }, 300);
47
+ }
48
+ },
49
+ [entering],
50
+ );
51
+
52
+ if (!entering) {
53
+ return children;
54
+ }
55
+
56
+ return (
57
+ <div
58
+ ref={divRef}
59
+ className={ANIMATION_CLASS}
60
+ onAnimationEnd={handleAnimationEnd}
61
+ >
62
+ {children}
63
+ </div>
64
+ );
65
+ }
@@ -0,0 +1,162 @@
1
+ "use client";
2
+
3
+ import {
4
+ forwardRef,
5
+ useCallback,
6
+ useMemo,
7
+ useRef,
8
+ useState,
9
+ type ComponentPropsWithRef,
10
+ } from "react";
11
+ import { Virtuoso, type VirtuosoHandle } from "react-virtuoso";
12
+ import { cn } from "@stigmer/theme";
13
+ import type { ToolCall } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
14
+ import { ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
15
+ import {
16
+ ThreadItemRenderer,
17
+ type ThreadItem,
18
+ } from "../execution/MessageThread";
19
+ import { FilePathContext, type FilePathContextValue } from "../execution/FilePathContext";
20
+ import { SandboxContext, type SandboxContextValue } from "../execution/SandboxContext";
21
+ import { DevProfiler, useDomNodeCount } from "./dev";
22
+ import { JumpToLatestButton } from "./JumpToLatestButton";
23
+ import { ThreadItemWrapper } from "./ThreadItemWrapper";
24
+
25
+ // ---------------------------------------------------------------------------
26
+ // Props
27
+ // ---------------------------------------------------------------------------
28
+
29
+ export interface VirtualizedThreadProps {
30
+ readonly items: readonly ThreadItem[];
31
+ readonly formatToolCallSummary?: (toolCalls: readonly ToolCall[]) => string;
32
+ readonly onApprovalSubmit?: (
33
+ toolCallId: string,
34
+ action: ApprovalAction,
35
+ comment?: string,
36
+ ) => void;
37
+ readonly submittingApprovalIds?: ReadonlySet<string>;
38
+ readonly filePathCtx: FilePathContextValue;
39
+ readonly sandboxCtx: SandboxContextValue;
40
+ }
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // Scrollbar classes shared with the non-virtualized path
44
+ // ---------------------------------------------------------------------------
45
+
46
+ const SCROLLBAR_CLASSES = cn(
47
+ "[scrollbar-width:thin] [scrollbar-color:var(--color-border)_transparent]",
48
+ "[&::-webkit-scrollbar]:w-1.5",
49
+ "[&::-webkit-scrollbar-track]:bg-transparent",
50
+ "[&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-border/40",
51
+ );
52
+
53
+ // ---------------------------------------------------------------------------
54
+ // Custom Virtuoso components
55
+ // ---------------------------------------------------------------------------
56
+
57
+ const ScrollerWithA11y = forwardRef<
58
+ HTMLDivElement,
59
+ ComponentPropsWithRef<"div">
60
+ >(function ScrollerWithA11y(props, ref) {
61
+ return (
62
+ <div
63
+ {...props}
64
+ ref={ref}
65
+ role="log"
66
+ aria-live="polite"
67
+ aria-relevant="additions"
68
+ className={cn(props.className, SCROLLBAR_CLASSES)}
69
+ />
70
+ );
71
+ });
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // VirtualizedThread
75
+ // ---------------------------------------------------------------------------
76
+
77
+ const NEAR_BOTTOM_THRESHOLD_PX = 80;
78
+
79
+ /**
80
+ * Internal component that renders a `MessageThread` item list via
81
+ * `react-virtuoso`. Handles bottom-anchored chat layout,
82
+ * follow-output scroll behavior, and the "Jump to latest" button.
83
+ *
84
+ * Not part of the public API — used only when `MessageThread` receives
85
+ * `virtualized={true}`.
86
+ *
87
+ * @internal
88
+ */
89
+ export function VirtualizedThread({
90
+ items,
91
+ formatToolCallSummary,
92
+ onApprovalSubmit,
93
+ submittingApprovalIds,
94
+ filePathCtx,
95
+ sandboxCtx,
96
+ }: VirtualizedThreadProps) {
97
+ const virtuosoRef = useRef<VirtuosoHandle>(null);
98
+ const scrollerRef = useRef<HTMLDivElement | null>(null);
99
+ const [isAtBottom, setIsAtBottom] = useState(true);
100
+
101
+ useDomNodeCount(scrollerRef, "MessageThread:virtualized");
102
+
103
+ const handleFollowOutput = useCallback(
104
+ (atBottom: boolean) => (atBottom ? "smooth" : false),
105
+ [],
106
+ );
107
+
108
+ const handleScrollerRef = useCallback((ref: HTMLElement | Window | null) => {
109
+ scrollerRef.current = ref instanceof HTMLDivElement ? ref : null;
110
+ }, []);
111
+
112
+ const jumpToLatest = useCallback(() => {
113
+ virtuosoRef.current?.scrollToIndex({
114
+ index: "LAST",
115
+ behavior: "smooth",
116
+ });
117
+ }, []);
118
+
119
+ const renderProps = useMemo(
120
+ () => ({
121
+ formatToolCallSummary,
122
+ onApprovalSubmit,
123
+ submittingApprovalIds,
124
+ }),
125
+ [formatToolCallSummary, onApprovalSubmit, submittingApprovalIds],
126
+ );
127
+
128
+ return (
129
+ <>
130
+ <SandboxContext.Provider value={sandboxCtx}>
131
+ <FilePathContext.Provider value={filePathCtx}>
132
+ <DevProfiler id="MessageThread:virtualized">
133
+ <Virtuoso
134
+ ref={virtuosoRef}
135
+ data={items as ThreadItem[]}
136
+ alignToBottom
137
+ followOutput={handleFollowOutput}
138
+ atBottomStateChange={setIsAtBottom}
139
+ atBottomThreshold={NEAR_BOTTOM_THRESHOLD_PX}
140
+ computeItemKey={(_index, item) => item.key}
141
+ increaseViewportBy={{ top: 200, bottom: 200 }}
142
+ scrollerRef={handleScrollerRef}
143
+ className="h-full"
144
+ components={{ Scroller: ScrollerWithA11y }}
145
+ itemContent={(index, item) => (
146
+ <div className="pb-4 pt-0 first:pt-6">
147
+ <ThreadItemWrapper animate={index >= items.length - 2}>
148
+ <ThreadItemRenderer
149
+ item={item}
150
+ {...renderProps}
151
+ />
152
+ </ThreadItemWrapper>
153
+ </div>
154
+ )}
155
+ />
156
+ </DevProfiler>
157
+ </FilePathContext.Provider>
158
+ </SandboxContext.Provider>
159
+ <JumpToLatestButton onClick={jumpToLatest} visible={!isAtBottom} />
160
+ </>
161
+ );
162
+ }