@stigmer/react 3.2.2 → 3.3.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 (513) hide show
  1. package/agent/AgentDetailView.d.ts.map +1 -1
  2. package/agent/AgentDetailView.js +6 -3
  3. package/agent/AgentDetailView.js.map +1 -1
  4. package/agent/steps/ReviewStep.d.ts.map +1 -1
  5. package/agent/steps/ReviewStep.js +2 -3
  6. package/agent/steps/ReviewStep.js.map +1 -1
  7. package/billing/BaselineEditor.d.ts +9 -0
  8. package/billing/BaselineEditor.d.ts.map +1 -0
  9. package/billing/BaselineEditor.js +253 -0
  10. package/billing/BaselineEditor.js.map +1 -0
  11. package/billing/ModelCatalogPanel.d.ts +28 -0
  12. package/billing/ModelCatalogPanel.d.ts.map +1 -0
  13. package/billing/ModelCatalogPanel.js +102 -0
  14. package/billing/ModelCatalogPanel.js.map +1 -0
  15. package/billing/ModelGovernanceDetail.d.ts +8 -0
  16. package/billing/ModelGovernanceDetail.d.ts.map +1 -0
  17. package/billing/ModelGovernanceDetail.js +64 -0
  18. package/billing/ModelGovernanceDetail.js.map +1 -0
  19. package/billing/OperatorAccessNotice.d.ts +12 -0
  20. package/billing/OperatorAccessNotice.d.ts.map +1 -0
  21. package/billing/OperatorAccessNotice.js +15 -0
  22. package/billing/OperatorAccessNotice.js.map +1 -0
  23. package/billing/PricingGovernanceConsole.d.ts +57 -0
  24. package/billing/PricingGovernanceConsole.d.ts.map +1 -0
  25. package/billing/PricingGovernanceConsole.js +164 -0
  26. package/billing/PricingGovernanceConsole.js.map +1 -0
  27. package/billing/PricingGovernancePanel.d.ts +26 -0
  28. package/billing/PricingGovernancePanel.d.ts.map +1 -0
  29. package/billing/PricingGovernancePanel.js +64 -0
  30. package/billing/PricingGovernancePanel.js.map +1 -0
  31. package/billing/RetireConfirm.d.ts +9 -0
  32. package/billing/RetireConfirm.d.ts.map +1 -0
  33. package/billing/RetireConfirm.js +19 -0
  34. package/billing/RetireConfirm.js.map +1 -0
  35. package/billing/form-primitives.d.ts +18 -0
  36. package/billing/form-primitives.d.ts.map +1 -0
  37. package/billing/form-primitives.js +19 -0
  38. package/billing/form-primitives.js.map +1 -0
  39. package/billing/governance-primitives.d.ts +33 -0
  40. package/billing/governance-primitives.d.ts.map +1 -0
  41. package/billing/governance-primitives.js +43 -0
  42. package/billing/governance-primitives.js.map +1 -0
  43. package/billing/index.d.ts +18 -0
  44. package/billing/index.d.ts.map +1 -1
  45. package/billing/index.js +9 -0
  46. package/billing/index.js.map +1 -1
  47. package/billing/pricing-format.d.ts +12 -0
  48. package/billing/pricing-format.d.ts.map +1 -0
  49. package/billing/pricing-format.js +50 -0
  50. package/billing/pricing-format.js.map +1 -0
  51. package/billing/useDecidePricingOverride.d.ts +46 -0
  52. package/billing/useDecidePricingOverride.d.ts.map +1 -0
  53. package/billing/useDecidePricingOverride.js +44 -0
  54. package/billing/useDecidePricingOverride.js.map +1 -0
  55. package/billing/useModelGovernanceView.d.ts +103 -0
  56. package/billing/useModelGovernanceView.d.ts.map +1 -0
  57. package/billing/useModelGovernanceView.js +144 -0
  58. package/billing/useModelGovernanceView.js.map +1 -0
  59. package/billing/useModelPricingBaselines.d.ts +40 -0
  60. package/billing/useModelPricingBaselines.d.ts.map +1 -0
  61. package/billing/useModelPricingBaselines.js +32 -0
  62. package/billing/useModelPricingBaselines.js.map +1 -0
  63. package/billing/usePricingGovernance.d.ts +39 -0
  64. package/billing/usePricingGovernance.d.ts.map +1 -0
  65. package/billing/usePricingGovernance.js +31 -0
  66. package/billing/usePricingGovernance.js.map +1 -0
  67. package/billing/useRetireModelPricingBaseline.d.ts +31 -0
  68. package/billing/useRetireModelPricingBaseline.d.ts.map +1 -0
  69. package/billing/useRetireModelPricingBaseline.js +36 -0
  70. package/billing/useRetireModelPricingBaseline.js.map +1 -0
  71. package/billing/useUpsertModelPricingBaseline.d.ts +38 -0
  72. package/billing/useUpsertModelPricingBaseline.d.ts.map +1 -0
  73. package/billing/useUpsertModelPricingBaseline.js +37 -0
  74. package/billing/useUpsertModelPricingBaseline.js.map +1 -0
  75. package/channel/AgentChannelsPanel.d.ts.map +1 -1
  76. package/channel/AgentChannelsPanel.js +11 -5
  77. package/channel/AgentChannelsPanel.js.map +1 -1
  78. package/composer/SessionComposer.d.ts +1 -1
  79. package/cursor-accounts/CursorAccountEditor.d.ts +28 -0
  80. package/cursor-accounts/CursorAccountEditor.d.ts.map +1 -0
  81. package/cursor-accounts/CursorAccountEditor.js +51 -0
  82. package/cursor-accounts/CursorAccountEditor.js.map +1 -0
  83. package/cursor-accounts/CursorAccountsAccessNotice.d.ts +11 -0
  84. package/cursor-accounts/CursorAccountsAccessNotice.d.ts.map +1 -0
  85. package/cursor-accounts/CursorAccountsAccessNotice.js +14 -0
  86. package/cursor-accounts/CursorAccountsAccessNotice.js.map +1 -0
  87. package/cursor-accounts/CursorAccountsConsole.d.ts +28 -0
  88. package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -0
  89. package/cursor-accounts/CursorAccountsConsole.js +275 -0
  90. package/cursor-accounts/CursorAccountsConsole.js.map +1 -0
  91. package/cursor-accounts/cursor-account-format.d.ts +10 -0
  92. package/cursor-accounts/cursor-account-format.d.ts.map +1 -0
  93. package/cursor-accounts/cursor-account-format.js +26 -0
  94. package/cursor-accounts/cursor-account-format.js.map +1 -0
  95. package/cursor-accounts/index.d.ts +18 -0
  96. package/cursor-accounts/index.d.ts.map +1 -0
  97. package/cursor-accounts/index.js +13 -0
  98. package/cursor-accounts/index.js.map +1 -0
  99. package/cursor-accounts/useCursorAccountView.d.ts +30 -0
  100. package/cursor-accounts/useCursorAccountView.d.ts.map +1 -0
  101. package/cursor-accounts/useCursorAccountView.js +25 -0
  102. package/cursor-accounts/useCursorAccountView.js.map +1 -0
  103. package/cursor-accounts/useCursorAccounts.d.ts +33 -0
  104. package/cursor-accounts/useCursorAccounts.d.ts.map +1 -0
  105. package/cursor-accounts/useCursorAccounts.js +25 -0
  106. package/cursor-accounts/useCursorAccounts.js.map +1 -0
  107. package/cursor-accounts/useCursorMemberKeyActions.d.ts +49 -0
  108. package/cursor-accounts/useCursorMemberKeyActions.d.ts.map +1 -0
  109. package/cursor-accounts/useCursorMemberKeyActions.js +38 -0
  110. package/cursor-accounts/useCursorMemberKeyActions.js.map +1 -0
  111. package/cursor-accounts/useDeleteCursorAccount.d.ts +30 -0
  112. package/cursor-accounts/useDeleteCursorAccount.d.ts.map +1 -0
  113. package/cursor-accounts/useDeleteCursorAccount.js +32 -0
  114. package/cursor-accounts/useDeleteCursorAccount.js.map +1 -0
  115. package/cursor-accounts/useSyncCursorAccount.d.ts +23 -0
  116. package/cursor-accounts/useSyncCursorAccount.d.ts.map +1 -0
  117. package/cursor-accounts/useSyncCursorAccount.js +31 -0
  118. package/cursor-accounts/useSyncCursorAccount.js.map +1 -0
  119. package/cursor-accounts/useUpsertCursorAccount.d.ts +26 -0
  120. package/cursor-accounts/useUpsertCursorAccount.d.ts.map +1 -0
  121. package/cursor-accounts/useUpsertCursorAccount.js +34 -0
  122. package/cursor-accounts/useUpsertCursorAccount.js.map +1 -0
  123. package/datastore/CollectionRecordsBrowser.d.ts +34 -0
  124. package/datastore/CollectionRecordsBrowser.d.ts.map +1 -0
  125. package/datastore/CollectionRecordsBrowser.js +209 -0
  126. package/datastore/CollectionRecordsBrowser.js.map +1 -0
  127. package/datastore/CollectionSchemaView.d.ts +29 -0
  128. package/datastore/CollectionSchemaView.d.ts.map +1 -0
  129. package/datastore/CollectionSchemaView.js +93 -0
  130. package/datastore/CollectionSchemaView.js.map +1 -0
  131. package/datastore/DatastoreDetailView.d.ts +44 -0
  132. package/datastore/DatastoreDetailView.d.ts.map +1 -0
  133. package/datastore/DatastoreDetailView.js +76 -0
  134. package/datastore/DatastoreDetailView.js.map +1 -0
  135. package/datastore/DatastoreSyncReport.d.ts +19 -0
  136. package/datastore/DatastoreSyncReport.d.ts.map +1 -0
  137. package/datastore/DatastoreSyncReport.js +45 -0
  138. package/datastore/DatastoreSyncReport.js.map +1 -0
  139. package/datastore/DeleteDatastoreDialog.d.ts +35 -0
  140. package/datastore/DeleteDatastoreDialog.d.ts.map +1 -0
  141. package/datastore/DeleteDatastoreDialog.js +90 -0
  142. package/datastore/DeleteDatastoreDialog.js.map +1 -0
  143. package/datastore/FieldValueControl.d.ts +55 -0
  144. package/datastore/FieldValueControl.d.ts.map +1 -0
  145. package/datastore/FieldValueControl.js +138 -0
  146. package/datastore/FieldValueControl.js.map +1 -0
  147. package/datastore/RecordFilterBuilder.d.ts +30 -0
  148. package/datastore/RecordFilterBuilder.d.ts.map +1 -0
  149. package/datastore/RecordFilterBuilder.js +122 -0
  150. package/datastore/RecordFilterBuilder.js.map +1 -0
  151. package/datastore/RecordFormPanel.d.ts +45 -0
  152. package/datastore/RecordFormPanel.d.ts.map +1 -0
  153. package/datastore/RecordFormPanel.js +215 -0
  154. package/datastore/RecordFormPanel.js.map +1 -0
  155. package/datastore/index.d.ts +43 -0
  156. package/datastore/index.d.ts.map +1 -0
  157. package/datastore/index.js +22 -0
  158. package/datastore/index.js.map +1 -0
  159. package/datastore/recordFilter.d.ts +54 -0
  160. package/datastore/recordFilter.d.ts.map +1 -0
  161. package/datastore/recordFilter.js +93 -0
  162. package/datastore/recordFilter.js.map +1 -0
  163. package/datastore/recordValues.d.ts +85 -0
  164. package/datastore/recordValues.d.ts.map +1 -0
  165. package/datastore/recordValues.js +282 -0
  166. package/datastore/recordValues.js.map +1 -0
  167. package/datastore/useDatastore.d.ts +39 -0
  168. package/datastore/useDatastore.d.ts.map +1 -0
  169. package/datastore/useDatastore.js +44 -0
  170. package/datastore/useDatastore.js.map +1 -0
  171. package/datastore/useDatastoreCount.d.ts +48 -0
  172. package/datastore/useDatastoreCount.d.ts.map +1 -0
  173. package/datastore/useDatastoreCount.js +27 -0
  174. package/datastore/useDatastoreCount.js.map +1 -0
  175. package/datastore/useDatastoreDescription.d.ts +54 -0
  176. package/datastore/useDatastoreDescription.d.ts.map +1 -0
  177. package/datastore/useDatastoreDescription.js +50 -0
  178. package/datastore/useDatastoreDescription.js.map +1 -0
  179. package/datastore/useDatastoreList.d.ts +57 -0
  180. package/datastore/useDatastoreList.d.ts.map +1 -0
  181. package/datastore/useDatastoreList.js +29 -0
  182. package/datastore/useDatastoreList.js.map +1 -0
  183. package/datastore/useDatastoreSearch.d.ts +19 -0
  184. package/datastore/useDatastoreSearch.d.ts.map +1 -0
  185. package/datastore/useDatastoreSearch.js +22 -0
  186. package/datastore/useDatastoreSearch.js.map +1 -0
  187. package/datastore/useDeleteDatastore.d.ts +53 -0
  188. package/datastore/useDeleteDatastore.d.ts.map +1 -0
  189. package/datastore/useDeleteDatastore.js +40 -0
  190. package/datastore/useDeleteDatastore.js.map +1 -0
  191. package/datastore/useDeleteRecord.d.ts +34 -0
  192. package/datastore/useDeleteRecord.d.ts.map +1 -0
  193. package/datastore/useDeleteRecord.js +43 -0
  194. package/datastore/useDeleteRecord.js.map +1 -0
  195. package/datastore/useInsertRecord.d.ts +50 -0
  196. package/datastore/useInsertRecord.d.ts.map +1 -0
  197. package/datastore/useInsertRecord.js +55 -0
  198. package/datastore/useInsertRecord.js.map +1 -0
  199. package/datastore/useRecordCollection.d.ts +104 -0
  200. package/datastore/useRecordCollection.d.ts.map +1 -0
  201. package/datastore/useRecordCollection.js +136 -0
  202. package/datastore/useRecordCollection.js.map +1 -0
  203. package/datastore/useRecordList.d.ts +66 -0
  204. package/datastore/useRecordList.d.ts.map +1 -0
  205. package/datastore/useRecordList.js +58 -0
  206. package/datastore/useRecordList.js.map +1 -0
  207. package/datastore/useUpdateRecord.d.ts +52 -0
  208. package/datastore/useUpdateRecord.d.ts.map +1 -0
  209. package/datastore/useUpdateRecord.js +55 -0
  210. package/datastore/useUpdateRecord.js.map +1 -0
  211. package/environment/EnvironmentListPanel.d.ts.map +1 -1
  212. package/environment/EnvironmentListPanel.js +12 -7
  213. package/environment/EnvironmentListPanel.js.map +1 -1
  214. package/execution/index.d.ts +1 -2
  215. package/execution/index.d.ts.map +1 -1
  216. package/execution/index.js +0 -1
  217. package/execution/index.js.map +1 -1
  218. package/execution/useLiveAgentExecution.d.ts +17 -1
  219. package/execution/useLiveAgentExecution.d.ts.map +1 -1
  220. package/execution/useLiveAgentExecution.js +19 -4
  221. package/execution/useLiveAgentExecution.js.map +1 -1
  222. package/iam-policy/index.d.ts +1 -1
  223. package/iam-policy/index.d.ts.map +1 -1
  224. package/iam-policy/index.js.map +1 -1
  225. package/iam-policy/useCheckPermission.d.ts +32 -11
  226. package/iam-policy/useCheckPermission.d.ts.map +1 -1
  227. package/iam-policy/useCheckPermission.js +24 -19
  228. package/iam-policy/useCheckPermission.js.map +1 -1
  229. package/index.d.ts +16 -10
  230. package/index.d.ts.map +1 -1
  231. package/index.js +16 -5
  232. package/index.js.map +1 -1
  233. package/internal/useInViewport.d.ts +24 -0
  234. package/internal/useInViewport.d.ts.map +1 -0
  235. package/internal/useInViewport.js +49 -0
  236. package/internal/useInViewport.js.map +1 -0
  237. package/library/VisibilitySelector.d.ts +22 -6
  238. package/library/VisibilitySelector.d.ts.map +1 -1
  239. package/library/VisibilitySelector.js +12 -4
  240. package/library/VisibilitySelector.js.map +1 -1
  241. package/library/index.d.ts +1 -8
  242. package/library/index.d.ts.map +1 -1
  243. package/library/index.js +0 -4
  244. package/library/index.js.map +1 -1
  245. package/library/useApplyResource.d.ts +12 -12
  246. package/library/useApplyResource.d.ts.map +1 -1
  247. package/library/useApplyResource.js +16 -25
  248. package/library/useApplyResource.js.map +1 -1
  249. package/library/useExportResource.d.ts +13 -9
  250. package/library/useExportResource.d.ts.map +1 -1
  251. package/library/useExportResource.js +18 -36
  252. package/library/useExportResource.js.map +1 -1
  253. package/manifest/ApplyManifestDialog.d.ts +48 -0
  254. package/manifest/ApplyManifestDialog.d.ts.map +1 -0
  255. package/manifest/ApplyManifestDialog.js +135 -0
  256. package/manifest/ApplyManifestDialog.js.map +1 -0
  257. package/manifest/EditResourceYamlDialog.d.ts +51 -0
  258. package/manifest/EditResourceYamlDialog.d.ts.map +1 -0
  259. package/manifest/EditResourceYamlDialog.js +104 -0
  260. package/manifest/EditResourceYamlDialog.js.map +1 -0
  261. package/manifest/RedactedSecretsNotice.d.ts +14 -0
  262. package/manifest/RedactedSecretsNotice.d.ts.map +1 -0
  263. package/manifest/RedactedSecretsNotice.js +14 -0
  264. package/manifest/RedactedSecretsNotice.js.map +1 -0
  265. package/manifest/YamlEditor.d.ts +44 -0
  266. package/manifest/YamlEditor.d.ts.map +1 -0
  267. package/manifest/YamlEditor.js +216 -0
  268. package/manifest/YamlEditor.js.map +1 -0
  269. package/manifest/index.d.ts +13 -0
  270. package/manifest/index.d.ts.map +1 -0
  271. package/manifest/index.js +13 -0
  272. package/manifest/index.js.map +1 -0
  273. package/manifest/useApplyManifest.d.ts +82 -0
  274. package/manifest/useApplyManifest.d.ts.map +1 -0
  275. package/manifest/useApplyManifest.js +180 -0
  276. package/manifest/useApplyManifest.js.map +1 -0
  277. package/manifest/useEditResourceYaml.d.ts +106 -0
  278. package/manifest/useEditResourceYaml.d.ts.map +1 -0
  279. package/manifest/useEditResourceYaml.js +168 -0
  280. package/manifest/useEditResourceYaml.js.map +1 -0
  281. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  282. package/mcp-server/McpServerDetailView.js +4 -3
  283. package/mcp-server/McpServerDetailView.js.map +1 -1
  284. package/mcp-server/steps/ReviewStep.d.ts.map +1 -1
  285. package/mcp-server/steps/ReviewStep.js +2 -3
  286. package/mcp-server/steps/ReviewStep.js.map +1 -1
  287. package/package.json +4 -4
  288. package/resource-creation/templates/workflow-templates.js +4 -4
  289. package/session/SessionViewer.js +8 -1
  290. package/session/SessionViewer.js.map +1 -1
  291. package/session/audience.d.ts +6 -1
  292. package/session/audience.d.ts.map +1 -1
  293. package/session/useEditSessionPrep.js +3 -3
  294. package/session/useEditSessionPrep.js.map +1 -1
  295. package/settings/index.d.ts +2 -1
  296. package/settings/index.d.ts.map +1 -1
  297. package/settings/index.js +2 -1
  298. package/settings/index.js.map +1 -1
  299. package/settings/settings-nav.d.ts +22 -0
  300. package/settings/settings-nav.d.ts.map +1 -1
  301. package/settings/settings-nav.js +32 -1
  302. package/settings/settings-nav.js.map +1 -1
  303. package/settings/useSettingsNavGroups.d.ts +29 -0
  304. package/settings/useSettingsNavGroups.d.ts.map +1 -0
  305. package/settings/useSettingsNavGroups.js +61 -0
  306. package/settings/useSettingsNavGroups.js.map +1 -0
  307. package/skill/SkillDetailView.d.ts.map +1 -1
  308. package/skill/SkillDetailView.js +4 -3
  309. package/skill/SkillDetailView.js.map +1 -1
  310. package/src/access/__tests__/useManageAccess.test.tsx +104 -0
  311. package/src/agent/AgentDetailView.tsx +9 -3
  312. package/src/agent/steps/ReviewStep.tsx +2 -3
  313. package/src/billing/BaselineEditor.tsx +619 -0
  314. package/src/billing/ModelCatalogPanel.tsx +283 -0
  315. package/src/billing/ModelGovernanceDetail.tsx +289 -0
  316. package/src/billing/OperatorAccessNotice.tsx +32 -0
  317. package/src/billing/PricingGovernanceConsole.tsx +465 -0
  318. package/src/billing/PricingGovernancePanel.tsx +166 -0
  319. package/src/billing/RetireConfirm.tsx +82 -0
  320. package/src/billing/__tests__/ModelCatalogPanel.test.tsx +253 -0
  321. package/src/billing/__tests__/PricingGovernanceConsole.test.tsx +410 -0
  322. package/src/billing/__tests__/useModelGovernanceView.test.tsx +308 -0
  323. package/src/billing/form-primitives.tsx +68 -0
  324. package/src/billing/governance-primitives.tsx +133 -0
  325. package/src/billing/index.ts +37 -0
  326. package/src/billing/pricing-format.ts +53 -0
  327. package/src/billing/useDecidePricingOverride.ts +78 -0
  328. package/src/billing/useModelGovernanceView.ts +290 -0
  329. package/src/billing/useModelPricingBaselines.ts +69 -0
  330. package/src/billing/usePricingGovernance.ts +57 -0
  331. package/src/billing/useRetireModelPricingBaseline.ts +65 -0
  332. package/src/billing/useUpsertModelPricingBaseline.ts +72 -0
  333. package/src/channel/AgentChannelsPanel.tsx +27 -1
  334. package/src/composer/SessionComposer.tsx +1 -1
  335. package/src/cursor-accounts/CursorAccountEditor.tsx +181 -0
  336. package/src/cursor-accounts/CursorAccountsAccessNotice.tsx +36 -0
  337. package/src/cursor-accounts/CursorAccountsConsole.tsx +810 -0
  338. package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +384 -0
  339. package/src/cursor-accounts/cursor-account-format.ts +29 -0
  340. package/src/cursor-accounts/index.ts +29 -0
  341. package/src/cursor-accounts/useCursorAccountView.ts +49 -0
  342. package/src/cursor-accounts/useCursorAccounts.ts +49 -0
  343. package/src/cursor-accounts/useCursorMemberKeyActions.ts +106 -0
  344. package/src/cursor-accounts/useDeleteCursorAccount.ts +62 -0
  345. package/src/cursor-accounts/useSyncCursorAccount.ts +54 -0
  346. package/src/cursor-accounts/useUpsertCursorAccount.ts +57 -0
  347. package/src/datastore/CollectionRecordsBrowser.tsx +544 -0
  348. package/src/datastore/CollectionSchemaView.tsx +247 -0
  349. package/src/datastore/DatastoreDetailView.tsx +201 -0
  350. package/src/datastore/DatastoreSyncReport.tsx +105 -0
  351. package/src/datastore/DeleteDatastoreDialog.tsx +202 -0
  352. package/src/datastore/FieldValueControl.tsx +289 -0
  353. package/src/datastore/RecordFilterBuilder.tsx +411 -0
  354. package/src/datastore/RecordFormPanel.tsx +432 -0
  355. package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +207 -0
  356. package/src/datastore/__tests__/DeleteDatastoreDialog.test.tsx +133 -0
  357. package/src/datastore/__tests__/FieldValueControl.test.tsx +160 -0
  358. package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +141 -0
  359. package/src/datastore/__tests__/RecordFormPanel.test.tsx +227 -0
  360. package/src/datastore/__tests__/recordFilter.test.ts +156 -0
  361. package/src/datastore/__tests__/recordMutations.test.tsx +195 -0
  362. package/src/datastore/__tests__/recordValues.test.ts +359 -0
  363. package/src/datastore/__tests__/schemaAndSyncViews.test.tsx +142 -0
  364. package/src/datastore/__tests__/useDatastoreDescription.test.tsx +143 -0
  365. package/src/datastore/__tests__/useRecordCollection.test.tsx +250 -0
  366. package/src/datastore/__tests__/useRecordList.test.tsx +85 -0
  367. package/src/datastore/index.ts +111 -0
  368. package/src/datastore/recordFilter.ts +140 -0
  369. package/src/datastore/recordValues.ts +327 -0
  370. package/src/datastore/useDatastore.ts +67 -0
  371. package/src/datastore/useDatastoreCount.ts +67 -0
  372. package/src/datastore/useDatastoreDescription.ts +90 -0
  373. package/src/datastore/useDatastoreList.ts +79 -0
  374. package/src/datastore/useDatastoreSearch.ts +39 -0
  375. package/src/datastore/useDeleteDatastore.ts +87 -0
  376. package/src/datastore/useDeleteRecord.ts +77 -0
  377. package/src/datastore/useInsertRecord.ts +92 -0
  378. package/src/datastore/useRecordCollection.ts +256 -0
  379. package/src/datastore/useRecordList.ts +131 -0
  380. package/src/datastore/useUpdateRecord.ts +95 -0
  381. package/src/environment/EnvironmentListPanel.tsx +24 -0
  382. package/src/execution/__tests__/useArtifactInspection.test.tsx +12 -2
  383. package/src/execution/__tests__/useLiveAgentExecution.test.tsx +125 -0
  384. package/src/execution/index.ts +4 -7
  385. package/src/execution/useLiveAgentExecution.ts +41 -3
  386. package/src/iam-policy/__tests__/useCheckPermission.test.tsx +221 -0
  387. package/src/iam-policy/index.ts +1 -0
  388. package/src/iam-policy/useCheckPermission.ts +45 -19
  389. package/src/index.ts +167 -18
  390. package/src/internal/__tests__/useInViewport.test.tsx +115 -0
  391. package/src/internal/useInViewport.ts +63 -0
  392. package/src/library/VisibilitySelector.tsx +50 -9
  393. package/src/library/__tests__/VisibilitySelector.test.tsx +38 -0
  394. package/src/library/index.ts +4 -21
  395. package/src/library/useApplyResource.ts +27 -34
  396. package/src/library/useExportResource.ts +21 -40
  397. package/src/manifest/ApplyManifestDialog.tsx +315 -0
  398. package/src/manifest/EditResourceYamlDialog.tsx +265 -0
  399. package/src/manifest/RedactedSecretsNotice.tsx +30 -0
  400. package/src/manifest/YamlEditor.tsx +272 -0
  401. package/src/manifest/__tests__/EditResourceYamlDialog.test.tsx +118 -0
  402. package/src/manifest/__tests__/useApplyManifest.test.tsx +237 -0
  403. package/src/manifest/__tests__/useEditResourceYaml.test.tsx +252 -0
  404. package/src/manifest/index.ts +33 -0
  405. package/src/manifest/useApplyManifest.ts +270 -0
  406. package/src/manifest/useEditResourceYaml.ts +273 -0
  407. package/src/mcp-server/McpServerDetailView.tsx +7 -3
  408. package/src/mcp-server/steps/ReviewStep.tsx +2 -3
  409. package/src/resource-creation/templates/workflow-templates.ts +4 -4
  410. package/src/session/SessionViewer.tsx +7 -1
  411. package/src/session/__tests__/audienceWiring.test.tsx +31 -1
  412. package/src/session/audience.ts +6 -1
  413. package/src/session/useEditSessionPrep.ts +3 -3
  414. package/src/settings/__tests__/useSettingsNavGroups.test.tsx +138 -0
  415. package/src/settings/index.ts +5 -1
  416. package/src/settings/settings-nav.ts +43 -0
  417. package/src/settings/useSettingsNavGroups.ts +81 -0
  418. package/src/skill/SkillDetailView.tsx +7 -3
  419. package/src/workflow/WorkflowAgentCallTranscript.tsx +279 -0
  420. package/src/workflow/WorkflowDetailView.tsx +7 -3
  421. package/src/workflow/WorkflowExecutionViewer.tsx +20 -77
  422. package/src/workflow/WorkflowTaskApprovalSummary.tsx +45 -8
  423. package/src/workflow/WorkflowYamlEditor.tsx +6 -270
  424. package/src/workflow/__tests__/WorkflowAgentCallTranscript.liveregion.test.tsx +124 -0
  425. package/src/workflow/__tests__/{WorkflowAgentExecutionDocument.test.tsx → WorkflowAgentCallTranscript.test.tsx} +146 -121
  426. package/src/workflow/__tests__/WorkflowExecutionViewer.approvals.test.tsx +81 -220
  427. package/src/workflow/__tests__/WorkflowExecutionViewer.reconciliation.test.tsx +17 -16
  428. package/src/workflow/__tests__/WorkflowTaskApprovalSummary.test.tsx +52 -2
  429. package/src/workflow/__tests__/WorkflowTaskThread.test.tsx +168 -185
  430. package/src/workflow/__tests__/agent-call-live-experience.test.ts +4 -4
  431. package/src/workflow/__tests__/task-approval.test.ts +119 -0
  432. package/src/workflow/__tests__/task-presentation.test.ts +35 -1
  433. package/src/workflow/__tests__/useWorkflowExecutionPanel.test.ts +0 -57
  434. package/src/workflow/index.ts +6 -3
  435. package/src/workflow/task-detail/index.ts +3 -0
  436. package/src/workflow/task-detail/task-approval.ts +95 -1
  437. package/src/workflow/thread/WorkflowTaskThread.tsx +96 -252
  438. package/src/workflow/thread/task-presentation.ts +8 -2
  439. package/src/workflow/useWorkflowExecutionPanel.ts +0 -47
  440. package/styles.css +1 -1
  441. package/workflow/CanvasTransitionEdge.d.ts +1 -1
  442. package/workflow/WorkflowAgentCallTranscript.d.ts +87 -0
  443. package/workflow/WorkflowAgentCallTranscript.d.ts.map +1 -0
  444. package/workflow/WorkflowAgentCallTranscript.js +98 -0
  445. package/workflow/WorkflowAgentCallTranscript.js.map +1 -0
  446. package/workflow/WorkflowDetailView.d.ts.map +1 -1
  447. package/workflow/WorkflowDetailView.js +4 -3
  448. package/workflow/WorkflowDetailView.js.map +1 -1
  449. package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
  450. package/workflow/WorkflowExecutionViewer.js +23 -52
  451. package/workflow/WorkflowExecutionViewer.js.map +1 -1
  452. package/workflow/WorkflowTaskApprovalSummary.d.ts +1 -1
  453. package/workflow/WorkflowTaskApprovalSummary.d.ts.map +1 -1
  454. package/workflow/WorkflowTaskApprovalSummary.js +18 -1
  455. package/workflow/WorkflowTaskApprovalSummary.js.map +1 -1
  456. package/workflow/WorkflowYamlEditor.d.ts +2 -42
  457. package/workflow/WorkflowYamlEditor.d.ts.map +1 -1
  458. package/workflow/WorkflowYamlEditor.js +5 -214
  459. package/workflow/WorkflowYamlEditor.js.map +1 -1
  460. package/workflow/index.d.ts +2 -2
  461. package/workflow/index.d.ts.map +1 -1
  462. package/workflow/index.js +2 -2
  463. package/workflow/index.js.map +1 -1
  464. package/workflow/task-detail/index.d.ts +1 -1
  465. package/workflow/task-detail/index.d.ts.map +1 -1
  466. package/workflow/task-detail/index.js +1 -1
  467. package/workflow/task-detail/index.js.map +1 -1
  468. package/workflow/task-detail/task-approval.d.ts +44 -1
  469. package/workflow/task-detail/task-approval.d.ts.map +1 -1
  470. package/workflow/task-detail/task-approval.js +47 -0
  471. package/workflow/task-detail/task-approval.js.map +1 -1
  472. package/workflow/thread/WorkflowTaskThread.d.ts +17 -25
  473. package/workflow/thread/WorkflowTaskThread.d.ts.map +1 -1
  474. package/workflow/thread/WorkflowTaskThread.js +60 -105
  475. package/workflow/thread/WorkflowTaskThread.js.map +1 -1
  476. package/workflow/thread/task-presentation.d.ts.map +1 -1
  477. package/workflow/thread/task-presentation.js +7 -2
  478. package/workflow/thread/task-presentation.js.map +1 -1
  479. package/workflow/useWorkflowExecutionPanel.d.ts +0 -12
  480. package/workflow/useWorkflowExecutionPanel.d.ts.map +1 -1
  481. package/workflow/useWorkflowExecutionPanel.js +0 -12
  482. package/workflow/useWorkflowExecutionPanel.js.map +1 -1
  483. package/execution/agent-execution-document.d.ts +0 -31
  484. package/execution/agent-execution-document.d.ts.map +0 -1
  485. package/execution/agent-execution-document.js +0 -48
  486. package/execution/agent-execution-document.js.map +0 -1
  487. package/library/ImportResourceDialog.d.ts +0 -43
  488. package/library/ImportResourceDialog.d.ts.map +0 -1
  489. package/library/ImportResourceDialog.js +0 -90
  490. package/library/ImportResourceDialog.js.map +0 -1
  491. package/library/parse-resource-yaml.d.ts +0 -63
  492. package/library/parse-resource-yaml.d.ts.map +0 -1
  493. package/library/parse-resource-yaml.js +0 -407
  494. package/library/parse-resource-yaml.js.map +0 -1
  495. package/library/serialize-resource-yaml.d.ts +0 -103
  496. package/library/serialize-resource-yaml.d.ts.map +0 -1
  497. package/library/serialize-resource-yaml.js +0 -565
  498. package/library/serialize-resource-yaml.js.map +0 -1
  499. package/library/useImportResource.d.ts +0 -84
  500. package/library/useImportResource.d.ts.map +0 -1
  501. package/library/useImportResource.js +0 -188
  502. package/library/useImportResource.js.map +0 -1
  503. package/src/execution/__tests__/agent-execution-document.test.ts +0 -45
  504. package/src/execution/agent-execution-document.ts +0 -54
  505. package/src/library/ImportResourceDialog.tsx +0 -227
  506. package/src/library/parse-resource-yaml.ts +0 -630
  507. package/src/library/serialize-resource-yaml.ts +0 -756
  508. package/src/library/useImportResource.ts +0 -253
  509. package/src/workflow/WorkflowAgentExecutionDocument.tsx +0 -283
  510. package/workflow/WorkflowAgentExecutionDocument.d.ts +0 -79
  511. package/workflow/WorkflowAgentExecutionDocument.d.ts.map +0 -1
  512. package/workflow/WorkflowAgentExecutionDocument.js +0 -87
  513. package/workflow/WorkflowAgentExecutionDocument.js.map +0 -1
@@ -0,0 +1,95 @@
1
+ "use client";
2
+
3
+ import { useCallback, useState } from "react";
4
+ import { create, type JsonObject } from "@bufbuild/protobuf";
5
+ import {
6
+ UpdateRecordRequestSchema,
7
+ type RecordEnvelope,
8
+ } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/record_io_pb";
9
+ import { useStigmer } from "../hooks.js";
10
+ import { toError } from "../internal/toError.js";
11
+ import type { RecordScope } from "./useRecordList.js";
12
+
13
+ /** Arguments for a single record update. */
14
+ export interface UpdateRecordArgs extends RecordScope {
15
+ /** Record id (`dsr_…`). */
16
+ readonly id: string;
17
+ /**
18
+ * Partial merge (DD-005): only the supplied fields change; an
19
+ * explicit `null` clears a field; absent fields keep their stored
20
+ * values. Constraints evaluate on the merged result. Build this from
21
+ * per-field edits with `buildUpdateFields`.
22
+ */
23
+ readonly fields: JsonObject;
24
+ }
25
+
26
+ /** Return value of {@link useUpdateRecord}. */
27
+ export interface UseUpdateRecordReturn {
28
+ /**
29
+ * Update one record by id. Resolves with the merged envelope. Rejects
30
+ * — and sets `error` — on denial or constraint violation; the error's
31
+ * message is the server's relayable text, byte-for-byte.
32
+ */
33
+ readonly updateRecord: (args: UpdateRecordArgs) => Promise<RecordEnvelope>;
34
+ /** `true` while the update is in flight. */
35
+ readonly isUpdating: boolean;
36
+ /** Error from the last failed update, or `null` when healthy. */
37
+ readonly error: Error | null;
38
+ /** Reset `error` to `null`. */
39
+ readonly clearError: () => void;
40
+ }
41
+
42
+ /**
43
+ * Behavior hook that wraps `datastore.updateRecord()` with loading and
44
+ * error state.
45
+ *
46
+ * The RPC is an honest tri-state partial merge — the hook adds no
47
+ * merge semantics of its own. A record in another partition is
48
+ * NOT_FOUND (DD-010: partition scoping is structural).
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * const { updateRecord } = useUpdateRecord();
53
+ * await updateRecord({
54
+ * org: "acme",
55
+ * datastore: "clinic",
56
+ * collection: "bookings",
57
+ * id: "dsr_01j9...",
58
+ * fields: { patient_phone: "+15550100", notes: null }, // notes cleared
59
+ * });
60
+ * ```
61
+ */
62
+ export function useUpdateRecord(): UseUpdateRecordReturn {
63
+ const stigmer = useStigmer();
64
+ const [isUpdating, setIsUpdating] = useState(false);
65
+ const [error, setError] = useState<Error | null>(null);
66
+
67
+ const clearError = useCallback(() => setError(null), []);
68
+
69
+ const updateRecord = useCallback(
70
+ async (args: UpdateRecordArgs): Promise<RecordEnvelope> => {
71
+ setIsUpdating(true);
72
+ setError(null);
73
+ try {
74
+ return await stigmer.datastore.updateRecord(
75
+ create(UpdateRecordRequestSchema, {
76
+ org: args.org,
77
+ datastore: args.datastore,
78
+ collection: args.collection,
79
+ partition: args.partition ?? "",
80
+ id: args.id,
81
+ fields: args.fields,
82
+ }),
83
+ );
84
+ } catch (err) {
85
+ setError(toError(err));
86
+ throw err;
87
+ } finally {
88
+ setIsUpdating(false);
89
+ }
90
+ },
91
+ [stigmer],
92
+ );
93
+
94
+ return { updateRecord, isUpdating, error, clearError };
95
+ }
@@ -6,6 +6,7 @@ import { getUserMessage } from "@stigmer/sdk";
6
6
  import type { Environment } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
7
7
  import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
8
8
  import { ResourceVisibilityControl } from "../library/ResourceVisibilityControl.js";
9
+ import { EditResourceYamlDialog } from "../manifest/EditResourceYamlDialog.js";
9
10
  import { useEnvironmentList } from "./useEnvironmentList.js";
10
11
  import { EnvironmentVariableEditor } from "./EnvironmentVariableEditor.js";
11
12
  import { isShareRestrictedEnvironment } from "./shareRestriction.js";
@@ -94,6 +95,7 @@ export function EnvironmentListPanel({
94
95
  labels,
95
96
  );
96
97
  const [expandedId, setExpandedId] = useState<string | null>(null);
98
+ const [yamlEnvironment, setYamlEnvironment] = useState<Environment | null>(null);
97
99
 
98
100
  if (onRefetchRef) {
99
101
  onRefetchRef(refetch);
@@ -179,9 +181,18 @@ export function EnvironmentListPanel({
179
181
  onToggle={() => handleToggle(env)}
180
182
  readOnly={readOnly}
181
183
  onVisibilityChanged={refetch}
184
+ onEditYaml={() => setYamlEnvironment(env)}
182
185
  />
183
186
  );
184
187
  })}
188
+ <EditResourceYamlDialog
189
+ open={yamlEnvironment !== null}
190
+ onOpenChange={(open) => {
191
+ if (!open) setYamlEnvironment(null);
192
+ }}
193
+ resource={yamlEnvironment}
194
+ onApplied={refetch}
195
+ />
185
196
  </div>
186
197
  );
187
198
  }
@@ -196,12 +207,14 @@ function EnvironmentCard({
196
207
  onToggle,
197
208
  readOnly,
198
209
  onVisibilityChanged,
210
+ onEditYaml,
199
211
  }: {
200
212
  environment: Environment;
201
213
  isExpanded: boolean;
202
214
  onToggle: () => void;
203
215
  readOnly: boolean;
204
216
  onVisibilityChanged: () => void;
217
+ onEditYaml: () => void;
205
218
  }) {
206
219
  const name =
207
220
  environment.metadata?.name || environment.metadata?.slug || "Unnamed";
@@ -249,6 +262,17 @@ function EnvironmentCard({
249
262
  </div>
250
263
  </button>
251
264
 
265
+ {!readOnly && (
266
+ <button
267
+ type="button"
268
+ onClick={onEditYaml}
269
+ aria-label={`Edit ${name} as YAML`}
270
+ className="shrink-0 rounded px-1.5 py-0.5 text-xs text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
271
+ >
272
+ Edit YAML
273
+ </button>
274
+ )}
275
+
252
276
  {showVisibilityControl && (
253
277
  <ResourceVisibilityControl
254
278
  kind="environment"
@@ -119,12 +119,20 @@ describe("useArtifactInspection — detection + apply", () => {
119
119
 
120
120
  it("applies a detected Agent and fires onApplied with the result", async () => {
121
121
  const getArtifactContent = vi.fn().mockResolvedValue(contentResult(AGENT_YAML));
122
+ // The apply path routes through the kind-agnostic manifest engine:
123
+ // the hook parses the YAML into a ManifestDocument and hands it to
124
+ // stigmer.manifest.apply.
122
125
  const apply = vi.fn().mockResolvedValue({
123
- metadata: { name: "my-agent", org: "acme", slug: "my-agent" },
126
+ yamlKind: "Agent",
127
+ displayName: "Agent",
128
+ name: "my-agent",
129
+ org: "acme",
130
+ slug: "my-agent",
131
+ id: "agt_01",
124
132
  });
125
133
  const stigmer = {
126
134
  agentExecution: { getArtifactContent },
127
- agent: { apply },
135
+ manifest: { apply },
128
136
  } as unknown as Stigmer;
129
137
  const onApplied = vi.fn();
130
138
 
@@ -144,6 +152,8 @@ describe("useArtifactInspection — detection + apply", () => {
144
152
 
145
153
  expect(apply).toHaveBeenCalledTimes(1);
146
154
  expect(apply.mock.calls[0][0].name).toBe("my-agent");
155
+ expect(apply.mock.calls[0][0].handler.yamlKind).toBe("Agent");
156
+ expect(apply.mock.calls[0][0].org).toBe("acme");
147
157
  await waitFor(() => expect(result.current.applyResult?.kind).toBe("Agent"));
148
158
  expect(onApplied).toHaveBeenCalledTimes(1);
149
159
  expect(onApplied.mock.calls[0][0].name).toBe("my-agent");
@@ -200,3 +200,128 @@ describe("useLiveAgentExecution", () => {
200
200
  }
201
201
  });
202
202
  });
203
+
204
+ // ---------------------------------------------------------------------------
205
+ // The { live } visibility gate (T07)
206
+ // ---------------------------------------------------------------------------
207
+
208
+ describe("useLiveAgentExecution { live }", () => {
209
+ it("live: false fetches the snapshot but never subscribes", async () => {
210
+ const running = executionFixture("aex_p1", ExecutionPhase.EXECUTION_IN_PROGRESS);
211
+ mockGet(async () => running);
212
+
213
+ const { result } = renderHook(() =>
214
+ useLiveAgentExecution("aex_p1", { live: false }),
215
+ );
216
+ await waitFor(() => expect(result.current.execution).toBe(running));
217
+
218
+ // Non-terminal + fetched, yet the gate stays closed on every render.
219
+ for (const call of mockUseExecutionStream.mock.calls) {
220
+ expect(call[0]).toBeNull();
221
+ }
222
+ });
223
+
224
+ it("live: true (and omitted) behave identically for a non-terminal execution", async () => {
225
+ const running = executionFixture("aex_p2", ExecutionPhase.EXECUTION_IN_PROGRESS);
226
+ mockGet(async () => running);
227
+
228
+ const { result } = renderHook(() =>
229
+ useLiveAgentExecution("aex_p2", { live: true }),
230
+ );
231
+ await waitFor(() => expect(result.current.execution).not.toBeNull());
232
+
233
+ const lastCall =
234
+ mockUseExecutionStream.mock.calls[mockUseExecutionStream.mock.calls.length - 1];
235
+ expect(lastCall[0]).toBe("aex_p2");
236
+ });
237
+
238
+ it("a terminal execution never streams regardless of live", async () => {
239
+ const terminal = executionFixture("aex_p3", ExecutionPhase.EXECUTION_COMPLETED);
240
+ mockGet(async () => terminal);
241
+
242
+ const { result } = renderHook(() =>
243
+ useLiveAgentExecution("aex_p3", { live: true }),
244
+ );
245
+ await waitFor(() => expect(result.current.execution).toBe(terminal));
246
+
247
+ for (const call of mockUseExecutionStream.mock.calls) {
248
+ expect(call[0]).toBeNull();
249
+ }
250
+ });
251
+
252
+ it("false → true attaches the stream in place", async () => {
253
+ const running = executionFixture("aex_p4", ExecutionPhase.EXECUTION_IN_PROGRESS);
254
+ mockGet(async () => running);
255
+
256
+ const { result, rerender } = renderHook(
257
+ ({ live }: { live: boolean }) =>
258
+ useLiveAgentExecution("aex_p4", { live }),
259
+ { initialProps: { live: false } },
260
+ );
261
+ await waitFor(() => expect(result.current.execution).toBe(running));
262
+
263
+ let lastCall =
264
+ mockUseExecutionStream.mock.calls[mockUseExecutionStream.mock.calls.length - 1];
265
+ expect(lastCall[0]).toBeNull();
266
+
267
+ rerender({ live: true });
268
+
269
+ lastCall =
270
+ mockUseExecutionStream.mock.calls[mockUseExecutionStream.mock.calls.length - 1];
271
+ expect(lastCall[0]).toBe("aex_p4");
272
+ });
273
+
274
+ it("never rewinds: a stream pause keeps the last-streamed snapshot, not the mount fetch", async () => {
275
+ const fetched = executionFixture("aex_p5", ExecutionPhase.EXECUTION_IN_PROGRESS);
276
+ const streamed = executionFixture("aex_p5", ExecutionPhase.EXECUTION_IN_PROGRESS);
277
+ mockGet(async () => fetched);
278
+ mockUseExecutionStream.mockReturnValue({
279
+ ...idleStream(),
280
+ execution: streamed,
281
+ isStreaming: true,
282
+ });
283
+
284
+ const { result, rerender } = renderHook(
285
+ ({ live }: { live: boolean }) =>
286
+ useLiveAgentExecution("aex_p5", { live }),
287
+ { initialProps: { live: true } },
288
+ );
289
+ await waitFor(() => expect(result.current.execution).toBe(streamed));
290
+
291
+ // Pause: the stream hook resets to its idle shape (execution: null) —
292
+ // the exact behavior of an unsubscribed useExecutionStream.
293
+ mockUseExecutionStream.mockReturnValue(idleStream());
294
+ rerender({ live: false });
295
+
296
+ // The freshest streamed snapshot stays visible; the view never rolls
297
+ // back to the mount-time fetch.
298
+ expect(result.current.execution).toBe(streamed);
299
+ });
300
+
301
+ it("does not leak the previous execution's snapshot across an id switch", async () => {
302
+ const first = executionFixture("aex_p6a", ExecutionPhase.EXECUTION_IN_PROGRESS);
303
+ const streamedFirst = executionFixture("aex_p6a", ExecutionPhase.EXECUTION_IN_PROGRESS);
304
+ const second = executionFixture("aex_p6b", ExecutionPhase.EXECUTION_COMPLETED);
305
+ mockGet(async (id) => (id === "aex_p6a" ? first : second));
306
+ mockUseExecutionStream.mockReturnValue({
307
+ ...idleStream(),
308
+ execution: streamedFirst,
309
+ isStreaming: true,
310
+ });
311
+
312
+ const { result, rerender } = renderHook(
313
+ ({ id }: { id: string }) => useLiveAgentExecution(id, { live: true }),
314
+ { initialProps: { id: "aex_p6a" } },
315
+ );
316
+ await waitFor(() => expect(result.current.execution).toBe(streamedFirst));
317
+
318
+ // Switch executions; the stream resets while the new fetch is in flight.
319
+ mockUseExecutionStream.mockReturnValue(idleStream());
320
+ rerender({ id: "aex_p6b" });
321
+
322
+ // The retained snapshot is keyed by id — it must NOT bleed into the
323
+ // new execution's view.
324
+ expect(result.current.execution).not.toBe(streamedFirst);
325
+ await waitFor(() => expect(result.current.execution).toBe(second));
326
+ });
327
+ });
@@ -13,7 +13,10 @@ export { useExecutionStream } from "./useExecutionStream.js";
13
13
  export type { UseExecutionStreamReturn } from "./useExecutionStream.js";
14
14
 
15
15
  export { useLiveAgentExecution } from "./useLiveAgentExecution.js";
16
- export type { UseLiveAgentExecutionReturn } from "./useLiveAgentExecution.js";
16
+ export type {
17
+ UseLiveAgentExecutionOptions,
18
+ UseLiveAgentExecutionReturn,
19
+ } from "./useLiveAgentExecution.js";
17
20
 
18
21
  export { useAgentExecutionActions } from "./useAgentExecutionActions.js";
19
22
  export type {
@@ -291,12 +294,6 @@ export {
291
294
  fileChangeTabPath,
292
295
  } from "./file-change-document.js";
293
296
 
294
- export {
295
- AGENT_EXECUTION_DOCUMENT_ENTRY_ID,
296
- agentExecutionTabPath,
297
- parseAgentExecutionTabPath,
298
- } from "./agent-execution-document.js";
299
-
300
297
  export { ArtifactContentRenderer } from "./ArtifactContentRenderer.js";
301
298
  export type { ArtifactContentRendererProps } from "./ArtifactContentRenderer.js";
302
299
 
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useCallback, useMemo } from "react";
3
+ import { useCallback, useMemo, useRef } from "react";
4
4
  import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
5
5
  import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
6
6
  import { isNotFound } from "@stigmer/sdk";
@@ -9,6 +9,23 @@ import { useFetch } from "../internal/useFetch.js";
9
9
  import { isTerminalPhase } from "./execution-phases.js";
10
10
  import { useExecutionStream } from "./useExecutionStream.js";
11
11
 
12
+ /** Options for {@link useLiveAgentExecution}. */
13
+ export interface UseLiveAgentExecutionOptions {
14
+ /**
15
+ * Whether the live stream may be open. Defaults to `true`.
16
+ *
17
+ * When `false`, the snapshot fetch still runs (so consumers always have
18
+ * something to render) but no subscription is opened — the
19
+ * visibility-gating seam for surfaces that mount many executions at once
20
+ * (e.g. inline agent-call transcripts in the workflow task thread, where
21
+ * only on-screen cards stream). A `false → true` transition attaches the
22
+ * stream in place; a `true → false` transition pauses it while the
23
+ * last-streamed snapshot stays visible (the view never rewinds to the
24
+ * mount-time snapshot).
25
+ */
26
+ readonly live?: boolean;
27
+ }
28
+
12
29
  /** Return value of {@link useLiveAgentExecution}. */
13
30
  export interface UseLiveAgentExecutionReturn {
14
31
  /**
@@ -67,8 +84,10 @@ export interface UseLiveAgentExecutionReturn {
67
84
  */
68
85
  export function useLiveAgentExecution(
69
86
  executionId: string | null,
87
+ options?: UseLiveAgentExecutionOptions,
70
88
  ): UseLiveAgentExecutionReturn {
71
89
  const stigmer = useStigmer();
90
+ const live = options?.live ?? true;
72
91
 
73
92
  const fetchFn = executionId
74
93
  ? async () => {
@@ -94,12 +113,31 @@ export function useLiveAgentExecution(
94
113
  // snapshot never advances, so a run that terminates mid-stream does not
95
114
  // flip this gate and unmount-thrash the subscription — useExecutionStream
96
115
  // ends itself on the terminal snapshot (completion is phase-driven).
116
+ // `live` is the consumer's visibility gate layered on top (an off-screen
117
+ // surface pauses its subscription without losing the fetch).
97
118
  const fetchedPhase =
98
119
  fetched?.status?.phase ?? ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED;
99
- const shouldStream = fetched !== null && !isTerminalPhase(fetchedPhase);
120
+ const shouldStream =
121
+ live && fetched !== null && !isTerminalPhase(fetchedPhase);
100
122
  const stream = useExecutionStream(shouldStream ? executionId : null);
101
123
 
102
- const execution = stream.execution ?? fetched;
124
+ // Retain the freshest snapshot ever shown for THIS execution across a
125
+ // stream pause (`live: true → false`): useExecutionStream resets its
126
+ // store when unsubscribed, so without this a paused surface would rewind
127
+ // to the mount-time fetch — visibly rolling the view backwards. Keyed by
128
+ // id so an execution switch never leaks the previous one's snapshot.
129
+ const lastStreamedRef = useRef<{
130
+ id: string;
131
+ execution: AgentExecution;
132
+ } | null>(null);
133
+ if (executionId && stream.execution) {
134
+ lastStreamedRef.current = { id: executionId, execution: stream.execution };
135
+ } else if (lastStreamedRef.current?.id !== executionId) {
136
+ lastStreamedRef.current = null;
137
+ }
138
+
139
+ const execution =
140
+ stream.execution ?? lastStreamedRef.current?.execution ?? fetched;
103
141
  const phase =
104
142
  execution?.status?.phase ?? ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED;
105
143
 
@@ -0,0 +1,221 @@
1
+ import { describe, it, expect, vi, afterEach } from "vitest";
2
+ import { cleanup, render, screen, waitFor } from "@testing-library/react";
3
+ import type { ReactNode } from "react";
4
+ import { StigmerContext } from "../../context";
5
+ import {
6
+ useCheckPermission,
7
+ type CheckPermissionOptions,
8
+ type PermissionCheckResource,
9
+ } from "../useCheckPermission";
10
+
11
+ function createMockStigmer(checkMyPermission: ReturnType<typeof vi.fn>) {
12
+ return { iamPolicy: { checkMyPermission } } as never;
13
+ }
14
+
15
+ function wrapper(client: unknown) {
16
+ return function Wrapper({ children }: { children: ReactNode }) {
17
+ return (
18
+ <StigmerContext.Provider value={client as never}>
19
+ {children}
20
+ </StigmerContext.Provider>
21
+ );
22
+ };
23
+ }
24
+
25
+ /** Renders the hook and exposes its state via data attributes. */
26
+ function Probe({
27
+ resource,
28
+ relation = "can_edit",
29
+ options,
30
+ }: {
31
+ resource: PermissionCheckResource | null;
32
+ relation?: string;
33
+ options?: CheckPermissionOptions;
34
+ }) {
35
+ const { allowed, isLoading, error } = useCheckPermission(
36
+ resource,
37
+ relation,
38
+ options,
39
+ );
40
+ return (
41
+ <div
42
+ data-testid="probe"
43
+ data-allowed={String(allowed)}
44
+ data-loading={String(isLoading)}
45
+ data-error={String(error !== null)}
46
+ />
47
+ );
48
+ }
49
+
50
+ const AGENT: PermissionCheckResource = { kind: "agent", id: "agt_1" };
51
+
52
+ /** A checkMyPermission stub that stays pending until resolved manually. */
53
+ function pendingCheck() {
54
+ let resolve!: (value: { isAuthorized: boolean }) => void;
55
+ let reject!: (err: unknown) => void;
56
+ const check = vi.fn().mockReturnValue(
57
+ new Promise((res, rej) => {
58
+ resolve = res;
59
+ reject = rej;
60
+ }),
61
+ );
62
+ return { check, resolve: (v: boolean) => resolve({ isAuthorized: v }), reject: (e: unknown) => reject(e) };
63
+ }
64
+
65
+ afterEach(cleanup);
66
+
67
+ describe("useCheckPermission — fail-open (default)", () => {
68
+ it("is allowed while the check is in flight", async () => {
69
+ const { check } = pendingCheck();
70
+ render(<Probe resource={AGENT} />, {
71
+ wrapper: wrapper(createMockStigmer(check)),
72
+ });
73
+
74
+ const probe = screen.getByTestId("probe");
75
+ expect(probe.getAttribute("data-allowed")).toBe("true");
76
+ await waitFor(() =>
77
+ expect(probe.getAttribute("data-loading")).toBe("true"),
78
+ );
79
+ });
80
+
81
+ it("respects an explicit server denial", async () => {
82
+ const check = vi.fn().mockResolvedValue({ isAuthorized: false });
83
+ render(<Probe resource={AGENT} />, {
84
+ wrapper: wrapper(createMockStigmer(check)),
85
+ });
86
+
87
+ await waitFor(() =>
88
+ expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("false"),
89
+ );
90
+ });
91
+
92
+ it("respects an explicit server grant", async () => {
93
+ const check = vi.fn().mockResolvedValue({ isAuthorized: true });
94
+ render(<Probe resource={AGENT} />, {
95
+ wrapper: wrapper(createMockStigmer(check)),
96
+ });
97
+
98
+ const probe = screen.getByTestId("probe");
99
+ await waitFor(() => expect(probe.getAttribute("data-loading")).toBe("false"));
100
+ expect(probe.getAttribute("data-allowed")).toBe("true");
101
+ expect(probe.getAttribute("data-error")).toBe("false");
102
+ });
103
+
104
+ it("fails open on RPC rejection (OSS single-user mode)", async () => {
105
+ const check = vi.fn().mockRejectedValue(new Error("unimplemented"));
106
+ render(<Probe resource={AGENT} />, {
107
+ wrapper: wrapper(createMockStigmer(check)),
108
+ });
109
+
110
+ const probe = screen.getByTestId("probe");
111
+ await waitFor(() => expect(probe.getAttribute("data-error")).toBe("true"));
112
+ expect(probe.getAttribute("data-allowed")).toBe("true");
113
+ expect(probe.getAttribute("data-loading")).toBe("false");
114
+ });
115
+
116
+ it("is allowed when resource is null (check skipped, no RPC)", () => {
117
+ const check = vi.fn();
118
+ render(<Probe resource={null} />, {
119
+ wrapper: wrapper(createMockStigmer(check)),
120
+ });
121
+
122
+ expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("true");
123
+ expect(check).not.toHaveBeenCalled();
124
+ });
125
+ });
126
+
127
+ describe("useCheckPermission — fail-closed", () => {
128
+ const CLOSED: CheckPermissionOptions = { fail: "closed" };
129
+
130
+ it("is denied while the check is in flight (no flash of gated UI)", async () => {
131
+ const { check } = pendingCheck();
132
+ render(<Probe resource={AGENT} options={CLOSED} />, {
133
+ wrapper: wrapper(createMockStigmer(check)),
134
+ });
135
+
136
+ const probe = screen.getByTestId("probe");
137
+ expect(probe.getAttribute("data-allowed")).toBe("false");
138
+ await waitFor(() =>
139
+ expect(probe.getAttribute("data-loading")).toBe("true"),
140
+ );
141
+ expect(probe.getAttribute("data-allowed")).toBe("false");
142
+ });
143
+
144
+ it("is allowed only on an explicit server grant", async () => {
145
+ const check = vi.fn().mockResolvedValue({ isAuthorized: true });
146
+ render(<Probe resource={AGENT} options={CLOSED} />, {
147
+ wrapper: wrapper(createMockStigmer(check)),
148
+ });
149
+
150
+ await waitFor(() =>
151
+ expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("true"),
152
+ );
153
+ });
154
+
155
+ it("fails closed on RPC rejection", async () => {
156
+ const check = vi.fn().mockRejectedValue(new Error("unimplemented"));
157
+ render(<Probe resource={AGENT} options={CLOSED} />, {
158
+ wrapper: wrapper(createMockStigmer(check)),
159
+ });
160
+
161
+ const probe = screen.getByTestId("probe");
162
+ await waitFor(() => expect(probe.getAttribute("data-error")).toBe("true"));
163
+ expect(probe.getAttribute("data-allowed")).toBe("false");
164
+ expect(probe.getAttribute("data-loading")).toBe("false");
165
+ });
166
+
167
+ it("is denied when resource is null (check skipped)", () => {
168
+ const check = vi.fn();
169
+ render(<Probe resource={null} options={CLOSED} />, {
170
+ wrapper: wrapper(createMockStigmer(check)),
171
+ });
172
+
173
+ expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("false");
174
+ expect(check).not.toHaveBeenCalled();
175
+ });
176
+ });
177
+
178
+ describe("useCheckPermission — caching", () => {
179
+ it("serves repeat checks of the same triple from the mount cache", async () => {
180
+ const check = vi.fn().mockResolvedValue({ isAuthorized: true });
181
+ const { rerender } = render(<Probe resource={AGENT} />, {
182
+ wrapper: wrapper(createMockStigmer(check)),
183
+ });
184
+ await waitFor(() =>
185
+ expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("true"),
186
+ );
187
+
188
+ // Switch relation (new triple → one more RPC), then switch back
189
+ // (cached triple → served without an RPC).
190
+ rerender(<Probe resource={AGENT} relation="can_delete" />);
191
+ await waitFor(() => expect(check).toHaveBeenCalledTimes(2));
192
+ rerender(<Probe resource={AGENT} relation="can_edit" />);
193
+ await waitFor(() =>
194
+ expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("true"),
195
+ );
196
+ expect(check).toHaveBeenCalledTimes(2);
197
+ });
198
+
199
+ it("does not cache a failed check as a verdict", async () => {
200
+ // First mount errors; the error must not be pinned as `true` — a
201
+ // remount (fresh cache) with a healthy server gets the real verdict.
202
+ const failing = vi.fn().mockRejectedValue(new Error("blip"));
203
+ const { unmount } = render(
204
+ <Probe resource={AGENT} options={{ fail: "closed" }} />,
205
+ { wrapper: wrapper(createMockStigmer(failing)) },
206
+ );
207
+ await waitFor(() =>
208
+ expect(screen.getByTestId("probe").getAttribute("data-error")).toBe("true"),
209
+ );
210
+ expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("false");
211
+ unmount();
212
+
213
+ const healthy = vi.fn().mockResolvedValue({ isAuthorized: true });
214
+ render(<Probe resource={AGENT} options={{ fail: "closed" }} />, {
215
+ wrapper: wrapper(createMockStigmer(healthy)),
216
+ });
217
+ await waitFor(() =>
218
+ expect(screen.getByTestId("probe").getAttribute("data-allowed")).toBe("true"),
219
+ );
220
+ });
221
+ });
@@ -75,6 +75,7 @@ export {
75
75
 
76
76
  export {
77
77
  useCheckPermission,
78
+ type CheckPermissionOptions,
78
79
  type PermissionCheckResource,
79
80
  type UseCheckPermissionReturn,
80
81
  } from "./useCheckPermission.js";