@stigmer/react 3.2.3 → 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 (402) hide show
  1. package/agent/steps/ReviewStep.d.ts.map +1 -1
  2. package/agent/steps/ReviewStep.js +2 -3
  3. package/agent/steps/ReviewStep.js.map +1 -1
  4. package/billing/BaselineEditor.d.ts +9 -0
  5. package/billing/BaselineEditor.d.ts.map +1 -0
  6. package/billing/BaselineEditor.js +253 -0
  7. package/billing/BaselineEditor.js.map +1 -0
  8. package/billing/ModelCatalogPanel.d.ts +28 -0
  9. package/billing/ModelCatalogPanel.d.ts.map +1 -0
  10. package/billing/ModelCatalogPanel.js +102 -0
  11. package/billing/ModelCatalogPanel.js.map +1 -0
  12. package/billing/ModelGovernanceDetail.d.ts +8 -0
  13. package/billing/ModelGovernanceDetail.d.ts.map +1 -0
  14. package/billing/ModelGovernanceDetail.js +64 -0
  15. package/billing/ModelGovernanceDetail.js.map +1 -0
  16. package/billing/OperatorAccessNotice.d.ts +12 -0
  17. package/billing/OperatorAccessNotice.d.ts.map +1 -0
  18. package/billing/OperatorAccessNotice.js +15 -0
  19. package/billing/OperatorAccessNotice.js.map +1 -0
  20. package/billing/PricingGovernanceConsole.d.ts +57 -0
  21. package/billing/PricingGovernanceConsole.d.ts.map +1 -0
  22. package/billing/PricingGovernanceConsole.js +164 -0
  23. package/billing/PricingGovernanceConsole.js.map +1 -0
  24. package/billing/PricingGovernancePanel.d.ts +26 -0
  25. package/billing/PricingGovernancePanel.d.ts.map +1 -0
  26. package/billing/PricingGovernancePanel.js +64 -0
  27. package/billing/PricingGovernancePanel.js.map +1 -0
  28. package/billing/RetireConfirm.d.ts +9 -0
  29. package/billing/RetireConfirm.d.ts.map +1 -0
  30. package/billing/RetireConfirm.js +19 -0
  31. package/billing/RetireConfirm.js.map +1 -0
  32. package/billing/form-primitives.d.ts +18 -0
  33. package/billing/form-primitives.d.ts.map +1 -0
  34. package/billing/form-primitives.js +19 -0
  35. package/billing/form-primitives.js.map +1 -0
  36. package/billing/governance-primitives.d.ts +33 -0
  37. package/billing/governance-primitives.d.ts.map +1 -0
  38. package/billing/governance-primitives.js +43 -0
  39. package/billing/governance-primitives.js.map +1 -0
  40. package/billing/index.d.ts +18 -0
  41. package/billing/index.d.ts.map +1 -1
  42. package/billing/index.js +9 -0
  43. package/billing/index.js.map +1 -1
  44. package/billing/pricing-format.d.ts +12 -0
  45. package/billing/pricing-format.d.ts.map +1 -0
  46. package/billing/pricing-format.js +50 -0
  47. package/billing/pricing-format.js.map +1 -0
  48. package/billing/useDecidePricingOverride.d.ts +46 -0
  49. package/billing/useDecidePricingOverride.d.ts.map +1 -0
  50. package/billing/useDecidePricingOverride.js +44 -0
  51. package/billing/useDecidePricingOverride.js.map +1 -0
  52. package/billing/useModelGovernanceView.d.ts +103 -0
  53. package/billing/useModelGovernanceView.d.ts.map +1 -0
  54. package/billing/useModelGovernanceView.js +144 -0
  55. package/billing/useModelGovernanceView.js.map +1 -0
  56. package/billing/useModelPricingBaselines.d.ts +40 -0
  57. package/billing/useModelPricingBaselines.d.ts.map +1 -0
  58. package/billing/useModelPricingBaselines.js +32 -0
  59. package/billing/useModelPricingBaselines.js.map +1 -0
  60. package/billing/usePricingGovernance.d.ts +39 -0
  61. package/billing/usePricingGovernance.d.ts.map +1 -0
  62. package/billing/usePricingGovernance.js +31 -0
  63. package/billing/usePricingGovernance.js.map +1 -0
  64. package/billing/useRetireModelPricingBaseline.d.ts +31 -0
  65. package/billing/useRetireModelPricingBaseline.d.ts.map +1 -0
  66. package/billing/useRetireModelPricingBaseline.js +36 -0
  67. package/billing/useRetireModelPricingBaseline.js.map +1 -0
  68. package/billing/useUpsertModelPricingBaseline.d.ts +38 -0
  69. package/billing/useUpsertModelPricingBaseline.d.ts.map +1 -0
  70. package/billing/useUpsertModelPricingBaseline.js +37 -0
  71. package/billing/useUpsertModelPricingBaseline.js.map +1 -0
  72. package/channel/AgentChannelsPanel.d.ts.map +1 -1
  73. package/channel/AgentChannelsPanel.js +11 -5
  74. package/channel/AgentChannelsPanel.js.map +1 -1
  75. package/composer/SessionComposer.d.ts +1 -1
  76. package/cursor-accounts/CursorAccountEditor.d.ts +28 -0
  77. package/cursor-accounts/CursorAccountEditor.d.ts.map +1 -0
  78. package/cursor-accounts/CursorAccountEditor.js +51 -0
  79. package/cursor-accounts/CursorAccountEditor.js.map +1 -0
  80. package/cursor-accounts/CursorAccountsAccessNotice.d.ts +11 -0
  81. package/cursor-accounts/CursorAccountsAccessNotice.d.ts.map +1 -0
  82. package/cursor-accounts/CursorAccountsAccessNotice.js +14 -0
  83. package/cursor-accounts/CursorAccountsAccessNotice.js.map +1 -0
  84. package/cursor-accounts/CursorAccountsConsole.d.ts +28 -0
  85. package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -0
  86. package/cursor-accounts/CursorAccountsConsole.js +275 -0
  87. package/cursor-accounts/CursorAccountsConsole.js.map +1 -0
  88. package/cursor-accounts/cursor-account-format.d.ts +10 -0
  89. package/cursor-accounts/cursor-account-format.d.ts.map +1 -0
  90. package/cursor-accounts/cursor-account-format.js +26 -0
  91. package/cursor-accounts/cursor-account-format.js.map +1 -0
  92. package/cursor-accounts/index.d.ts +18 -0
  93. package/cursor-accounts/index.d.ts.map +1 -0
  94. package/cursor-accounts/index.js +13 -0
  95. package/cursor-accounts/index.js.map +1 -0
  96. package/cursor-accounts/useCursorAccountView.d.ts +30 -0
  97. package/cursor-accounts/useCursorAccountView.d.ts.map +1 -0
  98. package/cursor-accounts/useCursorAccountView.js +25 -0
  99. package/cursor-accounts/useCursorAccountView.js.map +1 -0
  100. package/cursor-accounts/useCursorAccounts.d.ts +33 -0
  101. package/cursor-accounts/useCursorAccounts.d.ts.map +1 -0
  102. package/cursor-accounts/useCursorAccounts.js +25 -0
  103. package/cursor-accounts/useCursorAccounts.js.map +1 -0
  104. package/cursor-accounts/useCursorMemberKeyActions.d.ts +49 -0
  105. package/cursor-accounts/useCursorMemberKeyActions.d.ts.map +1 -0
  106. package/cursor-accounts/useCursorMemberKeyActions.js +38 -0
  107. package/cursor-accounts/useCursorMemberKeyActions.js.map +1 -0
  108. package/cursor-accounts/useDeleteCursorAccount.d.ts +30 -0
  109. package/cursor-accounts/useDeleteCursorAccount.d.ts.map +1 -0
  110. package/cursor-accounts/useDeleteCursorAccount.js +32 -0
  111. package/cursor-accounts/useDeleteCursorAccount.js.map +1 -0
  112. package/cursor-accounts/useSyncCursorAccount.d.ts +23 -0
  113. package/cursor-accounts/useSyncCursorAccount.d.ts.map +1 -0
  114. package/cursor-accounts/useSyncCursorAccount.js +31 -0
  115. package/cursor-accounts/useSyncCursorAccount.js.map +1 -0
  116. package/cursor-accounts/useUpsertCursorAccount.d.ts +26 -0
  117. package/cursor-accounts/useUpsertCursorAccount.d.ts.map +1 -0
  118. package/cursor-accounts/useUpsertCursorAccount.js +34 -0
  119. package/cursor-accounts/useUpsertCursorAccount.js.map +1 -0
  120. package/datastore/CollectionRecordsBrowser.d.ts +34 -0
  121. package/datastore/CollectionRecordsBrowser.d.ts.map +1 -0
  122. package/datastore/CollectionRecordsBrowser.js +209 -0
  123. package/datastore/CollectionRecordsBrowser.js.map +1 -0
  124. package/datastore/CollectionSchemaView.d.ts +29 -0
  125. package/datastore/CollectionSchemaView.d.ts.map +1 -0
  126. package/datastore/CollectionSchemaView.js +93 -0
  127. package/datastore/CollectionSchemaView.js.map +1 -0
  128. package/datastore/DatastoreDetailView.d.ts +44 -0
  129. package/datastore/DatastoreDetailView.d.ts.map +1 -0
  130. package/datastore/DatastoreDetailView.js +76 -0
  131. package/datastore/DatastoreDetailView.js.map +1 -0
  132. package/datastore/DatastoreSyncReport.d.ts +19 -0
  133. package/datastore/DatastoreSyncReport.d.ts.map +1 -0
  134. package/datastore/DatastoreSyncReport.js +45 -0
  135. package/datastore/DatastoreSyncReport.js.map +1 -0
  136. package/datastore/DeleteDatastoreDialog.d.ts +35 -0
  137. package/datastore/DeleteDatastoreDialog.d.ts.map +1 -0
  138. package/datastore/DeleteDatastoreDialog.js +90 -0
  139. package/datastore/DeleteDatastoreDialog.js.map +1 -0
  140. package/datastore/FieldValueControl.d.ts +55 -0
  141. package/datastore/FieldValueControl.d.ts.map +1 -0
  142. package/datastore/FieldValueControl.js +138 -0
  143. package/datastore/FieldValueControl.js.map +1 -0
  144. package/datastore/RecordFilterBuilder.d.ts +30 -0
  145. package/datastore/RecordFilterBuilder.d.ts.map +1 -0
  146. package/datastore/RecordFilterBuilder.js +122 -0
  147. package/datastore/RecordFilterBuilder.js.map +1 -0
  148. package/datastore/RecordFormPanel.d.ts +45 -0
  149. package/datastore/RecordFormPanel.d.ts.map +1 -0
  150. package/datastore/RecordFormPanel.js +215 -0
  151. package/datastore/RecordFormPanel.js.map +1 -0
  152. package/datastore/index.d.ts +43 -0
  153. package/datastore/index.d.ts.map +1 -0
  154. package/datastore/index.js +22 -0
  155. package/datastore/index.js.map +1 -0
  156. package/datastore/recordFilter.d.ts +54 -0
  157. package/datastore/recordFilter.d.ts.map +1 -0
  158. package/datastore/recordFilter.js +93 -0
  159. package/datastore/recordFilter.js.map +1 -0
  160. package/datastore/recordValues.d.ts +85 -0
  161. package/datastore/recordValues.d.ts.map +1 -0
  162. package/datastore/recordValues.js +282 -0
  163. package/datastore/recordValues.js.map +1 -0
  164. package/datastore/useDatastore.d.ts +39 -0
  165. package/datastore/useDatastore.d.ts.map +1 -0
  166. package/datastore/useDatastore.js +44 -0
  167. package/datastore/useDatastore.js.map +1 -0
  168. package/datastore/useDatastoreCount.d.ts +48 -0
  169. package/datastore/useDatastoreCount.d.ts.map +1 -0
  170. package/datastore/useDatastoreCount.js +27 -0
  171. package/datastore/useDatastoreCount.js.map +1 -0
  172. package/datastore/useDatastoreDescription.d.ts +54 -0
  173. package/datastore/useDatastoreDescription.d.ts.map +1 -0
  174. package/datastore/useDatastoreDescription.js +50 -0
  175. package/datastore/useDatastoreDescription.js.map +1 -0
  176. package/datastore/useDatastoreList.d.ts +57 -0
  177. package/datastore/useDatastoreList.d.ts.map +1 -0
  178. package/datastore/useDatastoreList.js +29 -0
  179. package/datastore/useDatastoreList.js.map +1 -0
  180. package/datastore/useDatastoreSearch.d.ts +19 -0
  181. package/datastore/useDatastoreSearch.d.ts.map +1 -0
  182. package/datastore/useDatastoreSearch.js +22 -0
  183. package/datastore/useDatastoreSearch.js.map +1 -0
  184. package/datastore/useDeleteDatastore.d.ts +53 -0
  185. package/datastore/useDeleteDatastore.d.ts.map +1 -0
  186. package/datastore/useDeleteDatastore.js +40 -0
  187. package/datastore/useDeleteDatastore.js.map +1 -0
  188. package/datastore/useDeleteRecord.d.ts +34 -0
  189. package/datastore/useDeleteRecord.d.ts.map +1 -0
  190. package/datastore/useDeleteRecord.js +43 -0
  191. package/datastore/useDeleteRecord.js.map +1 -0
  192. package/datastore/useInsertRecord.d.ts +50 -0
  193. package/datastore/useInsertRecord.d.ts.map +1 -0
  194. package/datastore/useInsertRecord.js +55 -0
  195. package/datastore/useInsertRecord.js.map +1 -0
  196. package/datastore/useRecordCollection.d.ts +104 -0
  197. package/datastore/useRecordCollection.d.ts.map +1 -0
  198. package/datastore/useRecordCollection.js +136 -0
  199. package/datastore/useRecordCollection.js.map +1 -0
  200. package/datastore/useRecordList.d.ts +66 -0
  201. package/datastore/useRecordList.d.ts.map +1 -0
  202. package/datastore/useRecordList.js +58 -0
  203. package/datastore/useRecordList.js.map +1 -0
  204. package/datastore/useUpdateRecord.d.ts +52 -0
  205. package/datastore/useUpdateRecord.d.ts.map +1 -0
  206. package/datastore/useUpdateRecord.js +55 -0
  207. package/datastore/useUpdateRecord.js.map +1 -0
  208. package/environment/EnvironmentListPanel.d.ts.map +1 -1
  209. package/environment/EnvironmentListPanel.js +12 -7
  210. package/environment/EnvironmentListPanel.js.map +1 -1
  211. package/iam-policy/index.d.ts +1 -1
  212. package/iam-policy/index.d.ts.map +1 -1
  213. package/iam-policy/index.js.map +1 -1
  214. package/iam-policy/useCheckPermission.d.ts +32 -11
  215. package/iam-policy/useCheckPermission.d.ts.map +1 -1
  216. package/iam-policy/useCheckPermission.js +24 -19
  217. package/iam-policy/useCheckPermission.js.map +1 -1
  218. package/index.d.ts +12 -6
  219. package/index.d.ts.map +1 -1
  220. package/index.js +14 -3
  221. package/index.js.map +1 -1
  222. package/library/index.d.ts +0 -7
  223. package/library/index.d.ts.map +1 -1
  224. package/library/index.js +0 -4
  225. package/library/index.js.map +1 -1
  226. package/library/useApplyResource.d.ts +12 -12
  227. package/library/useApplyResource.d.ts.map +1 -1
  228. package/library/useApplyResource.js +16 -25
  229. package/library/useApplyResource.js.map +1 -1
  230. package/library/useExportResource.d.ts +13 -9
  231. package/library/useExportResource.d.ts.map +1 -1
  232. package/library/useExportResource.js +18 -36
  233. package/library/useExportResource.js.map +1 -1
  234. package/manifest/ApplyManifestDialog.d.ts +48 -0
  235. package/manifest/ApplyManifestDialog.d.ts.map +1 -0
  236. package/manifest/ApplyManifestDialog.js +135 -0
  237. package/manifest/ApplyManifestDialog.js.map +1 -0
  238. package/manifest/EditResourceYamlDialog.d.ts +51 -0
  239. package/manifest/EditResourceYamlDialog.d.ts.map +1 -0
  240. package/manifest/EditResourceYamlDialog.js +104 -0
  241. package/manifest/EditResourceYamlDialog.js.map +1 -0
  242. package/manifest/RedactedSecretsNotice.d.ts +14 -0
  243. package/manifest/RedactedSecretsNotice.d.ts.map +1 -0
  244. package/manifest/RedactedSecretsNotice.js +14 -0
  245. package/manifest/RedactedSecretsNotice.js.map +1 -0
  246. package/manifest/YamlEditor.d.ts +44 -0
  247. package/manifest/YamlEditor.d.ts.map +1 -0
  248. package/manifest/YamlEditor.js +216 -0
  249. package/manifest/YamlEditor.js.map +1 -0
  250. package/manifest/index.d.ts +13 -0
  251. package/manifest/index.d.ts.map +1 -0
  252. package/manifest/index.js +13 -0
  253. package/manifest/index.js.map +1 -0
  254. package/manifest/useApplyManifest.d.ts +82 -0
  255. package/manifest/useApplyManifest.d.ts.map +1 -0
  256. package/manifest/useApplyManifest.js +180 -0
  257. package/manifest/useApplyManifest.js.map +1 -0
  258. package/manifest/useEditResourceYaml.d.ts +106 -0
  259. package/manifest/useEditResourceYaml.d.ts.map +1 -0
  260. package/manifest/useEditResourceYaml.js +168 -0
  261. package/manifest/useEditResourceYaml.js.map +1 -0
  262. package/mcp-server/steps/ReviewStep.d.ts.map +1 -1
  263. package/mcp-server/steps/ReviewStep.js +2 -3
  264. package/mcp-server/steps/ReviewStep.js.map +1 -1
  265. package/package.json +4 -4
  266. package/resource-creation/templates/workflow-templates.js +4 -4
  267. package/session/useEditSessionPrep.js +3 -3
  268. package/session/useEditSessionPrep.js.map +1 -1
  269. package/settings/index.d.ts +2 -1
  270. package/settings/index.d.ts.map +1 -1
  271. package/settings/index.js +2 -1
  272. package/settings/index.js.map +1 -1
  273. package/settings/settings-nav.d.ts +22 -0
  274. package/settings/settings-nav.d.ts.map +1 -1
  275. package/settings/settings-nav.js +32 -1
  276. package/settings/settings-nav.js.map +1 -1
  277. package/settings/useSettingsNavGroups.d.ts +29 -0
  278. package/settings/useSettingsNavGroups.d.ts.map +1 -0
  279. package/settings/useSettingsNavGroups.js +61 -0
  280. package/settings/useSettingsNavGroups.js.map +1 -0
  281. package/src/agent/steps/ReviewStep.tsx +2 -3
  282. package/src/billing/BaselineEditor.tsx +619 -0
  283. package/src/billing/ModelCatalogPanel.tsx +283 -0
  284. package/src/billing/ModelGovernanceDetail.tsx +289 -0
  285. package/src/billing/OperatorAccessNotice.tsx +32 -0
  286. package/src/billing/PricingGovernanceConsole.tsx +465 -0
  287. package/src/billing/PricingGovernancePanel.tsx +166 -0
  288. package/src/billing/RetireConfirm.tsx +82 -0
  289. package/src/billing/__tests__/ModelCatalogPanel.test.tsx +253 -0
  290. package/src/billing/__tests__/PricingGovernanceConsole.test.tsx +410 -0
  291. package/src/billing/__tests__/useModelGovernanceView.test.tsx +308 -0
  292. package/src/billing/form-primitives.tsx +68 -0
  293. package/src/billing/governance-primitives.tsx +133 -0
  294. package/src/billing/index.ts +37 -0
  295. package/src/billing/pricing-format.ts +53 -0
  296. package/src/billing/useDecidePricingOverride.ts +78 -0
  297. package/src/billing/useModelGovernanceView.ts +290 -0
  298. package/src/billing/useModelPricingBaselines.ts +69 -0
  299. package/src/billing/usePricingGovernance.ts +57 -0
  300. package/src/billing/useRetireModelPricingBaseline.ts +65 -0
  301. package/src/billing/useUpsertModelPricingBaseline.ts +72 -0
  302. package/src/channel/AgentChannelsPanel.tsx +27 -1
  303. package/src/composer/SessionComposer.tsx +1 -1
  304. package/src/cursor-accounts/CursorAccountEditor.tsx +181 -0
  305. package/src/cursor-accounts/CursorAccountsAccessNotice.tsx +36 -0
  306. package/src/cursor-accounts/CursorAccountsConsole.tsx +810 -0
  307. package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +384 -0
  308. package/src/cursor-accounts/cursor-account-format.ts +29 -0
  309. package/src/cursor-accounts/index.ts +29 -0
  310. package/src/cursor-accounts/useCursorAccountView.ts +49 -0
  311. package/src/cursor-accounts/useCursorAccounts.ts +49 -0
  312. package/src/cursor-accounts/useCursorMemberKeyActions.ts +106 -0
  313. package/src/cursor-accounts/useDeleteCursorAccount.ts +62 -0
  314. package/src/cursor-accounts/useSyncCursorAccount.ts +54 -0
  315. package/src/cursor-accounts/useUpsertCursorAccount.ts +57 -0
  316. package/src/datastore/CollectionRecordsBrowser.tsx +544 -0
  317. package/src/datastore/CollectionSchemaView.tsx +247 -0
  318. package/src/datastore/DatastoreDetailView.tsx +201 -0
  319. package/src/datastore/DatastoreSyncReport.tsx +105 -0
  320. package/src/datastore/DeleteDatastoreDialog.tsx +202 -0
  321. package/src/datastore/FieldValueControl.tsx +289 -0
  322. package/src/datastore/RecordFilterBuilder.tsx +411 -0
  323. package/src/datastore/RecordFormPanel.tsx +432 -0
  324. package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +207 -0
  325. package/src/datastore/__tests__/DeleteDatastoreDialog.test.tsx +133 -0
  326. package/src/datastore/__tests__/FieldValueControl.test.tsx +160 -0
  327. package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +141 -0
  328. package/src/datastore/__tests__/RecordFormPanel.test.tsx +227 -0
  329. package/src/datastore/__tests__/recordFilter.test.ts +156 -0
  330. package/src/datastore/__tests__/recordMutations.test.tsx +195 -0
  331. package/src/datastore/__tests__/recordValues.test.ts +359 -0
  332. package/src/datastore/__tests__/schemaAndSyncViews.test.tsx +142 -0
  333. package/src/datastore/__tests__/useDatastoreDescription.test.tsx +143 -0
  334. package/src/datastore/__tests__/useRecordCollection.test.tsx +250 -0
  335. package/src/datastore/__tests__/useRecordList.test.tsx +85 -0
  336. package/src/datastore/index.ts +111 -0
  337. package/src/datastore/recordFilter.ts +140 -0
  338. package/src/datastore/recordValues.ts +327 -0
  339. package/src/datastore/useDatastore.ts +67 -0
  340. package/src/datastore/useDatastoreCount.ts +67 -0
  341. package/src/datastore/useDatastoreDescription.ts +90 -0
  342. package/src/datastore/useDatastoreList.ts +79 -0
  343. package/src/datastore/useDatastoreSearch.ts +39 -0
  344. package/src/datastore/useDeleteDatastore.ts +87 -0
  345. package/src/datastore/useDeleteRecord.ts +77 -0
  346. package/src/datastore/useInsertRecord.ts +92 -0
  347. package/src/datastore/useRecordCollection.ts +256 -0
  348. package/src/datastore/useRecordList.ts +131 -0
  349. package/src/datastore/useUpdateRecord.ts +95 -0
  350. package/src/environment/EnvironmentListPanel.tsx +24 -0
  351. package/src/execution/__tests__/useArtifactInspection.test.tsx +12 -2
  352. package/src/iam-policy/__tests__/useCheckPermission.test.tsx +221 -0
  353. package/src/iam-policy/index.ts +1 -0
  354. package/src/iam-policy/useCheckPermission.ts +45 -19
  355. package/src/index.ts +163 -13
  356. package/src/library/index.ts +0 -20
  357. package/src/library/useApplyResource.ts +27 -34
  358. package/src/library/useExportResource.ts +21 -40
  359. package/src/manifest/ApplyManifestDialog.tsx +315 -0
  360. package/src/manifest/EditResourceYamlDialog.tsx +265 -0
  361. package/src/manifest/RedactedSecretsNotice.tsx +30 -0
  362. package/src/manifest/YamlEditor.tsx +272 -0
  363. package/src/manifest/__tests__/EditResourceYamlDialog.test.tsx +118 -0
  364. package/src/manifest/__tests__/useApplyManifest.test.tsx +237 -0
  365. package/src/manifest/__tests__/useEditResourceYaml.test.tsx +252 -0
  366. package/src/manifest/index.ts +33 -0
  367. package/src/manifest/useApplyManifest.ts +270 -0
  368. package/src/manifest/useEditResourceYaml.ts +273 -0
  369. package/src/mcp-server/steps/ReviewStep.tsx +2 -3
  370. package/src/resource-creation/templates/workflow-templates.ts +4 -4
  371. package/src/session/useEditSessionPrep.ts +3 -3
  372. package/src/settings/__tests__/useSettingsNavGroups.test.tsx +138 -0
  373. package/src/settings/index.ts +5 -1
  374. package/src/settings/settings-nav.ts +43 -0
  375. package/src/settings/useSettingsNavGroups.ts +81 -0
  376. package/src/workflow/WorkflowYamlEditor.tsx +6 -270
  377. package/styles.css +1 -1
  378. package/workflow/CanvasTransitionEdge.d.ts +1 -1
  379. package/workflow/WorkflowYamlEditor.d.ts +2 -42
  380. package/workflow/WorkflowYamlEditor.d.ts.map +1 -1
  381. package/workflow/WorkflowYamlEditor.js +5 -214
  382. package/workflow/WorkflowYamlEditor.js.map +1 -1
  383. package/library/ImportResourceDialog.d.ts +0 -43
  384. package/library/ImportResourceDialog.d.ts.map +0 -1
  385. package/library/ImportResourceDialog.js +0 -90
  386. package/library/ImportResourceDialog.js.map +0 -1
  387. package/library/parse-resource-yaml.d.ts +0 -63
  388. package/library/parse-resource-yaml.d.ts.map +0 -1
  389. package/library/parse-resource-yaml.js +0 -407
  390. package/library/parse-resource-yaml.js.map +0 -1
  391. package/library/serialize-resource-yaml.d.ts +0 -103
  392. package/library/serialize-resource-yaml.d.ts.map +0 -1
  393. package/library/serialize-resource-yaml.js +0 -565
  394. package/library/serialize-resource-yaml.js.map +0 -1
  395. package/library/useImportResource.d.ts +0 -84
  396. package/library/useImportResource.d.ts.map +0 -1
  397. package/library/useImportResource.js +0 -188
  398. package/library/useImportResource.js.map +0 -1
  399. package/src/library/ImportResourceDialog.tsx +0 -227
  400. package/src/library/parse-resource-yaml.ts +0 -630
  401. package/src/library/serialize-resource-yaml.ts +0 -756
  402. package/src/library/useImportResource.ts +0 -253
@@ -0,0 +1,250 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { renderHook, waitFor, act } from "@testing-library/react";
3
+ import type { ReactNode } from "react";
4
+ import { create } from "@bufbuild/protobuf";
5
+ import {
6
+ RecordConditionOp,
7
+ RecordEnvelopeSchema,
8
+ RecordFilterSchema,
9
+ RecordListSchema,
10
+ RecordSortDirection,
11
+ type FindRecordsRequest,
12
+ } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/record_io_pb";
13
+ import { StigmerContext } from "../../context";
14
+ import { FetchCacheContext } from "../../internal/FetchCacheProvider";
15
+ import { useRecordCollection, type RecordColumnDef } from "../useRecordCollection";
16
+
17
+ function envelope(id: string, fields: Record<string, unknown> = {}) {
18
+ return create(RecordEnvelopeSchema, { id, fields: fields as never });
19
+ }
20
+
21
+ function recordList(records: ReturnType<typeof envelope>[], total: number) {
22
+ return create(RecordListSchema, { records, total, limit: 25, offset: 0 });
23
+ }
24
+
25
+ function createMockStigmer(findRecords: (req: FindRecordsRequest) => Promise<unknown>) {
26
+ return { datastore: { findRecords } } as never;
27
+ }
28
+
29
+ function wrapper(client: unknown) {
30
+ return function Wrapper({ children }: { children: ReactNode }) {
31
+ return (
32
+ <FetchCacheContext.Provider value={null}>
33
+ <StigmerContext.Provider value={client as never}>
34
+ {children}
35
+ </StigmerContext.Provider>
36
+ </FetchCacheContext.Provider>
37
+ );
38
+ };
39
+ }
40
+
41
+ const COLUMNS: readonly RecordColumnDef[] = [
42
+ { id: "slot_date", header: "Date", cell: (r) => String(r.fields?.["slot_date"] ?? "") },
43
+ { id: "status", header: "Status", cell: (r) => String(r.fields?.["status"] ?? ""), sortable: true },
44
+ ];
45
+
46
+ const SCOPE = { org: "acme", datastore: "clinic", collection: "bookings" } as const;
47
+
48
+ describe("useRecordCollection", () => {
49
+ beforeEach(() => {
50
+ vi.restoreAllMocks();
51
+ });
52
+
53
+ it("fetches records and reports totals", async () => {
54
+ const findRecords = vi
55
+ .fn()
56
+ .mockResolvedValue(recordList([envelope("dsr_1"), envelope("dsr_2")], 51));
57
+ const { result } = renderHook(
58
+ () => useRecordCollection({ ...SCOPE, columns: COLUMNS }),
59
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
60
+ );
61
+
62
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
63
+
64
+ expect(result.current.records).toHaveLength(2);
65
+ expect(result.current.total).toBe(51);
66
+ expect(result.current.totalPages).toBe(3); // 51 records at page size 25
67
+ expect(result.current.currentPage).toBe(1);
68
+ });
69
+
70
+ it("translates page/pageSize into RPC limit/offset", async () => {
71
+ const findRecords = vi.fn().mockResolvedValue(recordList([], 0));
72
+ renderHook(
73
+ () => useRecordCollection({ ...SCOPE, page: 3, pageSize: 10, columns: COLUMNS }),
74
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
75
+ );
76
+
77
+ await waitFor(() => expect(findRecords).toHaveBeenCalled());
78
+ expect(findRecords).toHaveBeenCalledWith(
79
+ expect.objectContaining({ limit: 10, offset: 20 }),
80
+ );
81
+ });
82
+
83
+ it("caps the page size at the RPC max of 100 — one surface, one limit", async () => {
84
+ const findRecords = vi.fn().mockResolvedValue(recordList([], 0));
85
+ renderHook(
86
+ () => useRecordCollection({ ...SCOPE, pageSize: 500, columns: COLUMNS }),
87
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
88
+ );
89
+
90
+ await waitFor(() => expect(findRecords).toHaveBeenCalled());
91
+ expect(findRecords).toHaveBeenCalledWith(expect.objectContaining({ limit: 100 }));
92
+ });
93
+
94
+ it("threads the partition into every fetch (DD-010)", async () => {
95
+ const findRecords = vi.fn().mockResolvedValue(recordList([], 0));
96
+ renderHook(
97
+ () => useRecordCollection({ ...SCOPE, partition: "dr-alt", columns: COLUMNS }),
98
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
99
+ );
100
+
101
+ await waitFor(() => expect(findRecords).toHaveBeenCalled());
102
+ expect(findRecords).toHaveBeenCalledWith(
103
+ expect.objectContaining({ partition: "dr-alt" }),
104
+ );
105
+ });
106
+
107
+ it("passes the typed proto filter through without adding grammar", async () => {
108
+ const filter = create(RecordFilterSchema, {
109
+ conditions: [
110
+ { field: "status", op: RecordConditionOp.eq, value: { kind: { case: "stringValue", value: "confirmed" } } },
111
+ ],
112
+ });
113
+ const findRecords = vi.fn().mockResolvedValue(recordList([], 0));
114
+ renderHook(
115
+ () => useRecordCollection({ ...SCOPE, filter, columns: COLUMNS }),
116
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
117
+ );
118
+
119
+ await waitFor(() => expect(findRecords).toHaveBeenCalled());
120
+ const request = findRecords.mock.calls[0][0] as FindRecordsRequest;
121
+ expect(request.filter?.conditions).toHaveLength(1);
122
+ expect(request.filter?.conditions[0].field).toBe("status");
123
+ });
124
+
125
+ it("builds RecordOrderBy from the controlled sort", async () => {
126
+ const findRecords = vi.fn().mockResolvedValue(recordList([], 0));
127
+ renderHook(
128
+ () =>
129
+ useRecordCollection({
130
+ ...SCOPE,
131
+ sort: { id: "slot_date", direction: "desc" },
132
+ columns: COLUMNS,
133
+ }),
134
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
135
+ );
136
+
137
+ await waitFor(() => expect(findRecords).toHaveBeenCalled());
138
+ const request = findRecords.mock.calls[0][0] as FindRecordsRequest;
139
+ expect(request.orderBy?.field).toBe("slot_date");
140
+ expect(request.orderBy?.direction).toBe(RecordSortDirection.desc);
141
+ });
142
+
143
+ it("reports header sort clicks through onSortChange", async () => {
144
+ const findRecords = vi.fn().mockResolvedValue(recordList([envelope("dsr_1")], 1));
145
+ const onSortChange = vi.fn();
146
+ const { result } = renderHook(
147
+ () => useRecordCollection({ ...SCOPE, sort: null, onSortChange, columns: COLUMNS }),
148
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
149
+ );
150
+
151
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
152
+
153
+ const statusColumn = result.current.table!
154
+ .getHeaderGroups()[0]
155
+ .headers.find((h) => h.id === "status")!;
156
+ act(() => statusColumn.column.toggleSorting(false));
157
+
158
+ expect(onSortChange).toHaveBeenCalledWith({ id: "status", direction: "asc" });
159
+ });
160
+
161
+ it("produces a table keyed by envelope id", async () => {
162
+ const findRecords = vi
163
+ .fn()
164
+ .mockResolvedValue(recordList([envelope("dsr_a"), envelope("dsr_b")], 2));
165
+ const { result } = renderHook(
166
+ () => useRecordCollection({ ...SCOPE, columns: COLUMNS }),
167
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
168
+ );
169
+
170
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
171
+ expect(result.current.table!.getRowModel().rows.map((r) => r.id)).toEqual([
172
+ "dsr_a",
173
+ "dsr_b",
174
+ ]);
175
+ });
176
+
177
+ it("returns a null table when no columns are provided", async () => {
178
+ const findRecords = vi.fn().mockResolvedValue(recordList([], 0));
179
+ const { result } = renderHook(() => useRecordCollection({ ...SCOPE }), {
180
+ wrapper: wrapper(createMockStigmer(findRecords)),
181
+ });
182
+
183
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
184
+ expect(result.current.table).toBeNull();
185
+ });
186
+
187
+ it("skips fetching when the scope is incomplete", () => {
188
+ const findRecords = vi.fn();
189
+ const { result } = renderHook(
190
+ () =>
191
+ useRecordCollection({
192
+ org: "acme",
193
+ datastore: "clinic",
194
+ collection: null,
195
+ columns: COLUMNS,
196
+ }),
197
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
198
+ );
199
+
200
+ expect(result.current.isLoading).toBe(false);
201
+ expect(findRecords).not.toHaveBeenCalled();
202
+ });
203
+
204
+ it("surfaces the record-layer denial verbatim — never a silently empty grid", async () => {
205
+ const denial = new Error("you are not allowed to read records in bookings");
206
+ const findRecords = vi.fn().mockRejectedValue(denial);
207
+ const { result } = renderHook(
208
+ () => useRecordCollection({ ...SCOPE, columns: COLUMNS }),
209
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
210
+ );
211
+
212
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
213
+ expect(result.current.error?.message).toBe(
214
+ "you are not allowed to read records in bookings",
215
+ );
216
+ });
217
+
218
+ it("refetch re-runs the current query", async () => {
219
+ const findRecords = vi.fn().mockResolvedValue(recordList([envelope("dsr_1")], 1));
220
+ const { result } = renderHook(
221
+ () => useRecordCollection({ ...SCOPE, columns: COLUMNS }),
222
+ { wrapper: wrapper(createMockStigmer(findRecords)) },
223
+ );
224
+
225
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
226
+ expect(findRecords).toHaveBeenCalledTimes(1);
227
+
228
+ act(() => result.current.refetch());
229
+ await waitFor(() => expect(findRecords).toHaveBeenCalledTimes(2));
230
+ });
231
+
232
+ it("re-fetches when the filter changes", async () => {
233
+ const findRecords = vi.fn().mockResolvedValue(recordList([], 0));
234
+ const { rerender } = renderHook(
235
+ ({ filter }: { filter?: ReturnType<typeof create<typeof RecordFilterSchema>> }) =>
236
+ useRecordCollection({ ...SCOPE, filter, columns: COLUMNS }),
237
+ { wrapper: wrapper(createMockStigmer(findRecords)), initialProps: {} },
238
+ );
239
+
240
+ await waitFor(() => expect(findRecords).toHaveBeenCalledTimes(1));
241
+
242
+ rerender({
243
+ filter: create(RecordFilterSchema, {
244
+ conditions: [{ field: "status", op: RecordConditionOp.is_null }],
245
+ }),
246
+ });
247
+
248
+ await waitFor(() => expect(findRecords).toHaveBeenCalledTimes(2));
249
+ });
250
+ });
@@ -0,0 +1,85 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { renderHook, waitFor } from "@testing-library/react";
3
+ import type { ReactNode } from "react";
4
+ import { create } from "@bufbuild/protobuf";
5
+ import {
6
+ RecordEnvelopeSchema,
7
+ RecordListSchema,
8
+ } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/record_io_pb";
9
+ import { StigmerContext } from "../../context";
10
+ import { FetchCacheContext } from "../../internal/FetchCacheProvider";
11
+ import { useRecordList } from "../useRecordList";
12
+
13
+ function wrapper(client: unknown) {
14
+ return function Wrapper({ children }: { children: ReactNode }) {
15
+ return (
16
+ <FetchCacheContext.Provider value={null}>
17
+ <StigmerContext.Provider value={client as never}>
18
+ {children}
19
+ </StigmerContext.Provider>
20
+ </FetchCacheContext.Provider>
21
+ );
22
+ };
23
+ }
24
+
25
+ const SCOPE = { org: "acme", datastore: "clinic", collection: "bookings" } as const;
26
+
27
+ describe("useRecordList", () => {
28
+ beforeEach(() => vi.restoreAllMocks());
29
+
30
+ it("fetches a page of records", async () => {
31
+ const list = create(RecordListSchema, {
32
+ records: [create(RecordEnvelopeSchema, { id: "dsr_1" })],
33
+ total: 1,
34
+ });
35
+ const findRecords = vi.fn().mockResolvedValue(list);
36
+ const client = { datastore: { findRecords } } as never;
37
+
38
+ const { result } = renderHook(() => useRecordList({ ...SCOPE }), {
39
+ wrapper: wrapper(client),
40
+ });
41
+
42
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
43
+ expect(result.current.records).toHaveLength(1);
44
+ expect(result.current.total).toBe(1);
45
+ expect(findRecords).toHaveBeenCalledWith(
46
+ expect.objectContaining({
47
+ org: "acme",
48
+ datastore: "clinic",
49
+ collection: "bookings",
50
+ partition: "",
51
+ limit: 0, // unset — the server applies its default of 25
52
+ offset: 0,
53
+ }),
54
+ );
55
+ });
56
+
57
+ it("skips fetching when params is null", () => {
58
+ const findRecords = vi.fn();
59
+ const client = { datastore: { findRecords } } as never;
60
+
61
+ const { result } = renderHook(() => useRecordList(null), {
62
+ wrapper: wrapper(client),
63
+ });
64
+
65
+ expect(result.current.isLoading).toBe(false);
66
+ expect(result.current.records).toEqual([]);
67
+ expect(findRecords).not.toHaveBeenCalled();
68
+ });
69
+
70
+ it("surfaces the record-layer denial verbatim", async () => {
71
+ const denial = new Error("you are not allowed to read records in bookings");
72
+ const client = {
73
+ datastore: { findRecords: vi.fn().mockRejectedValue(denial) },
74
+ } as never;
75
+
76
+ const { result } = renderHook(() => useRecordList({ ...SCOPE }), {
77
+ wrapper: wrapper(client),
78
+ });
79
+
80
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
81
+ expect(result.current.error?.message).toBe(
82
+ "you are not allowed to read records in bookings",
83
+ );
84
+ });
85
+ });
@@ -0,0 +1,111 @@
1
+ export { useDatastore } from "./useDatastore.js";
2
+ export type { UseDatastoreReturn } from "./useDatastore.js";
3
+
4
+ export { useDatastoreList } from "./useDatastoreList.js";
5
+ export type {
6
+ UseDatastoreListOptions,
7
+ UseDatastoreListReturn,
8
+ } from "./useDatastoreList.js";
9
+
10
+ export { useDatastoreCount } from "./useDatastoreCount.js";
11
+ export type {
12
+ UseDatastoreCountOptions,
13
+ UseDatastoreCountReturn,
14
+ } from "./useDatastoreCount.js";
15
+
16
+ export { useDatastoreSearch } from "./useDatastoreSearch.js";
17
+ export type {
18
+ UseDatastoreSearchOptions,
19
+ UseDatastoreSearchReturn,
20
+ } from "./useDatastoreSearch.js";
21
+
22
+ export { useDatastoreDescription, DEFAULT_PARTITION } from "./useDatastoreDescription.js";
23
+ export type { UseDatastoreDescriptionReturn } from "./useDatastoreDescription.js";
24
+
25
+ export { useRecordList } from "./useRecordList.js";
26
+ export type {
27
+ RecordScope,
28
+ UseRecordListParams,
29
+ UseRecordListReturn,
30
+ } from "./useRecordList.js";
31
+
32
+ export { useInsertRecord } from "./useInsertRecord.js";
33
+ export type {
34
+ InsertRecordArgs,
35
+ UseInsertRecordReturn,
36
+ } from "./useInsertRecord.js";
37
+
38
+ export { useUpdateRecord } from "./useUpdateRecord.js";
39
+ export type {
40
+ UpdateRecordArgs,
41
+ UseUpdateRecordReturn,
42
+ } from "./useUpdateRecord.js";
43
+
44
+ export { useDeleteRecord } from "./useDeleteRecord.js";
45
+ export type {
46
+ DeleteRecordArgs,
47
+ UseDeleteRecordReturn,
48
+ } from "./useDeleteRecord.js";
49
+
50
+ export { useRecordCollection } from "./useRecordCollection.js";
51
+ export type {
52
+ RecordColumnDef,
53
+ UseRecordCollectionOptions,
54
+ UseRecordCollectionReturn,
55
+ } from "./useRecordCollection.js";
56
+
57
+ export { useDeleteDatastore } from "./useDeleteDatastore.js";
58
+ export type {
59
+ DeleteDatastoreArgs,
60
+ UseDeleteDatastoreReturn,
61
+ } from "./useDeleteDatastore.js";
62
+
63
+ export {
64
+ buildUpdateFields,
65
+ coerceFieldValue,
66
+ formatFieldValue,
67
+ formatSystemTimestamp,
68
+ isListOperator,
69
+ isSortableField,
70
+ isValuelessOperator,
71
+ operatorsForField,
72
+ OPERATOR_LABELS,
73
+ RESERVED_FIELD_NAMES,
74
+ SYSTEM_FIELD_OPERATORS,
75
+ } from "./recordValues.js";
76
+ export type { CoerceResult } from "./recordValues.js";
77
+
78
+ export {
79
+ buildRecordFilter,
80
+ filterableFields,
81
+ formatConditionChip,
82
+ isConditionComplete,
83
+ } from "./recordFilter.js";
84
+ export type { FilterableField, RecordConditionDraft } from "./recordFilter.js";
85
+
86
+ export { FieldValueControl, FIELD_INPUT_CLASSES } from "./FieldValueControl.js";
87
+ export type { FieldValueControlProps } from "./FieldValueControl.js";
88
+
89
+ export { CollectionSchemaView, formatSubject } from "./CollectionSchemaView.js";
90
+ export type { CollectionSchemaViewProps } from "./CollectionSchemaView.js";
91
+
92
+ export { DatastoreSyncReport } from "./DatastoreSyncReport.js";
93
+ export type { DatastoreSyncReportProps } from "./DatastoreSyncReport.js";
94
+
95
+ export { RecordFilterBuilder } from "./RecordFilterBuilder.js";
96
+ export type { RecordFilterBuilderProps } from "./RecordFilterBuilder.js";
97
+
98
+ export { RecordFormPanel } from "./RecordFormPanel.js";
99
+ export type { RecordFormPanelProps } from "./RecordFormPanel.js";
100
+
101
+ export { CollectionRecordsBrowser } from "./CollectionRecordsBrowser.js";
102
+ export type { CollectionRecordsBrowserProps } from "./CollectionRecordsBrowser.js";
103
+
104
+ export { DeleteDatastoreDialog } from "./DeleteDatastoreDialog.js";
105
+ export type { DeleteDatastoreDialogProps } from "./DeleteDatastoreDialog.js";
106
+
107
+ export { DatastoreDetailView, DatastoreIcon } from "./DatastoreDetailView.js";
108
+ export type {
109
+ DatastoreDetailTab,
110
+ DatastoreDetailViewProps,
111
+ } from "./DatastoreDetailView.js";
@@ -0,0 +1,140 @@
1
+ // The records-specific filter model (DD-008 SD-3) — typed 1:1 against
2
+ // `RecordConditionOp`.
3
+ //
4
+ // Deliberately NOT the workbench `FilterDef`/`FilterValue` model: its
5
+ // `string | string[]` value shape cannot carry typed values or
6
+ // value-less null operators, and its operator set includes `contains`,
7
+ // which `findRecords` cannot serve. Welding a server-grammar contract
8
+ // onto a client-filter model would couple two contracts that evolve
9
+ // independently — so this model mirrors the RPC grammar exactly and can
10
+ // express nothing the RPC cannot serve (DD-008 invariant 2).
11
+
12
+ import { create, fromJson, type JsonValue } from "@bufbuild/protobuf";
13
+ import { ValueSchema } from "@bufbuild/protobuf/wkt";
14
+ import {
15
+ RecordConditionOp,
16
+ RecordConditionSchema,
17
+ RecordFilterSchema,
18
+ type RecordFilter,
19
+ } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/record_io_pb";
20
+ import {
21
+ FieldType,
22
+ type CollectionDeclaration,
23
+ type FieldDeclaration,
24
+ } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/spec_pb";
25
+ import {
26
+ isListOperator,
27
+ isValuelessOperator,
28
+ OPERATOR_LABELS,
29
+ SYSTEM_FIELD_OPERATORS,
30
+ operatorsForField,
31
+ } from "./recordValues.js";
32
+
33
+ /**
34
+ * One draft condition in the filter builder — the client-side twin of
35
+ * the proto `RecordCondition`, with plain JSON values (converted to
36
+ * `google.protobuf.Value` only at request-build time).
37
+ */
38
+ export interface RecordConditionDraft {
39
+ /** Declared field name, or a filterable system field (`id`, `created_at`, `updated_at`). */
40
+ readonly field: string;
41
+ /** Comparison operator — must be admitted by the field's operator set. */
42
+ readonly op: RecordConditionOp;
43
+ /** Scalar comparison value. Absent for `is_null`/`not_null` and list operators. */
44
+ readonly value?: JsonValue;
45
+ /** Comparison values for `is_in`/`not_in`. */
46
+ readonly values?: readonly JsonValue[];
47
+ }
48
+
49
+ /**
50
+ * A field the builder can offer: a declared filterable field or a
51
+ * filterable system field, with the exact operator set the server
52
+ * admits for it.
53
+ */
54
+ export interface FilterableField {
55
+ readonly name: string;
56
+ /** The declaration, or `undefined` for system fields. */
57
+ readonly declaration?: FieldDeclaration;
58
+ /** The field type driving the value control (system fields use fixed types). */
59
+ readonly type: FieldType;
60
+ readonly operators: readonly RecordConditionOp[];
61
+ }
62
+
63
+ /**
64
+ * The fields a collection's filter builder offers: declared filterable
65
+ * fields (json is not filterable) followed by the filterable system
66
+ * fields. `id` conditions take string values; the audit timestamps take
67
+ * RFC 3339 timestamps — both ride the `timestamp`/`string` value
68
+ * controls.
69
+ */
70
+ export function filterableFields(collection: CollectionDeclaration): FilterableField[] {
71
+ const declared: FilterableField[] = [];
72
+ for (const field of collection.fields) {
73
+ const operators = operatorsForField(field);
74
+ if (operators.length === 0) continue; // json — not filterable
75
+ declared.push({ name: field.name, declaration: field, type: field.type, operators });
76
+ }
77
+ return [
78
+ ...declared,
79
+ { name: "id", type: FieldType.string, operators: SYSTEM_FIELD_OPERATORS.get("id")! },
80
+ {
81
+ name: "created_at",
82
+ type: FieldType.timestamp,
83
+ operators: SYSTEM_FIELD_OPERATORS.get("created_at")!,
84
+ },
85
+ {
86
+ name: "updated_at",
87
+ type: FieldType.timestamp,
88
+ operators: SYSTEM_FIELD_OPERATORS.get("updated_at")!,
89
+ },
90
+ ];
91
+ }
92
+
93
+ /**
94
+ * Whether a draft is complete enough to serve: value-less operators
95
+ * need nothing, list operators need at least one value, scalar
96
+ * operators need a value.
97
+ */
98
+ export function isConditionComplete(draft: RecordConditionDraft): boolean {
99
+ if (draft.op === RecordConditionOp.record_condition_op_unspecified) return false;
100
+ if (isValuelessOperator(draft.op)) return true;
101
+ if (isListOperator(draft.op)) return (draft.values?.length ?? 0) > 0;
102
+ return draft.value !== undefined;
103
+ }
104
+
105
+ /**
106
+ * Build the proto `RecordFilter` from complete drafts. Returns
107
+ * `undefined` for an empty set (an absent filter, not an empty one, is
108
+ * the RPC's "no filter").
109
+ */
110
+ export function buildRecordFilter(
111
+ conditions: readonly RecordConditionDraft[],
112
+ ): RecordFilter | undefined {
113
+ const complete = conditions.filter(isConditionComplete);
114
+ if (complete.length === 0) return undefined;
115
+ return create(RecordFilterSchema, {
116
+ conditions: complete.map((draft) =>
117
+ create(RecordConditionSchema, {
118
+ field: draft.field,
119
+ op: draft.op,
120
+ value: draft.value !== undefined ? fromJson(ValueSchema, draft.value) : undefined,
121
+ values: (draft.values ?? []).map((v) => fromJson(ValueSchema, v)),
122
+ }),
123
+ ),
124
+ });
125
+ }
126
+
127
+ /** Chip text for an active condition, e.g. `status = confirmed` or `notes is empty`. */
128
+ export function formatConditionChip(draft: RecordConditionDraft): string {
129
+ const op = OPERATOR_LABELS.get(draft.op) ?? "?";
130
+ if (isValuelessOperator(draft.op)) return `${draft.field} ${op}`;
131
+ if (isListOperator(draft.op)) {
132
+ return `${draft.field} ${op} [${(draft.values ?? []).map(formatChipValue).join(", ")}]`;
133
+ }
134
+ return `${draft.field} ${op} ${formatChipValue(draft.value)}`;
135
+ }
136
+
137
+ function formatChipValue(value: JsonValue | undefined): string {
138
+ if (value === undefined || value === null) return "";
139
+ return typeof value === "string" ? value : JSON.stringify(value);
140
+ }