@stigmer/react 3.11.1-dev.20260812192248 → 3.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/activity/useRecentActivity.d.ts +3 -2
  2. package/activity/useRecentActivity.d.ts.map +1 -1
  3. package/activity/useRecentActivity.js +3 -2
  4. package/activity/useRecentActivity.js.map +1 -1
  5. package/agent/AgentDetailView.d.ts +2 -12
  6. package/agent/AgentDetailView.d.ts.map +1 -1
  7. package/agent/AgentDetailView.js +10 -42
  8. package/agent/AgentDetailView.js.map +1 -1
  9. package/agent/internal/agentToInput.d.ts.map +1 -1
  10. package/agent/internal/agentToInput.js +0 -8
  11. package/agent/internal/agentToInput.js.map +1 -1
  12. package/dependency-graph/DependencyTreeNode.d.ts.map +1 -1
  13. package/dependency-graph/DependencyTreeNode.js +1 -7
  14. package/dependency-graph/DependencyTreeNode.js.map +1 -1
  15. package/dependency-graph/types.d.ts +8 -20
  16. package/dependency-graph/types.d.ts.map +1 -1
  17. package/dependency-graph/useDependencyGraph.d.ts.map +1 -1
  18. package/dependency-graph/useDependencyGraph.js +2 -20
  19. package/dependency-graph/useDependencyGraph.js.map +1 -1
  20. package/execution/useCreateAgentExecution.d.ts +3 -2
  21. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  22. package/execution/useCreateAgentExecution.js.map +1 -1
  23. package/index.d.ts +0 -2
  24. package/index.d.ts.map +1 -1
  25. package/index.js +0 -6
  26. package/index.js.map +1 -1
  27. package/internal/isUnimplemented.d.ts +17 -0
  28. package/internal/isUnimplemented.d.ts.map +1 -0
  29. package/internal/isUnimplemented.js +26 -0
  30. package/internal/isUnimplemented.js.map +1 -0
  31. package/library/useExportResource.d.ts +3 -4
  32. package/library/useExportResource.d.ts.map +1 -1
  33. package/library/useExportResource.js +1 -1
  34. package/library/useExportResource.js.map +1 -1
  35. package/manifest/EditResourceYamlDialog.d.ts.map +1 -1
  36. package/manifest/EditResourceYamlDialog.js.map +1 -1
  37. package/mcp-server/McpServerConnectDialog.js +7 -3
  38. package/mcp-server/McpServerConnectDialog.js.map +1 -1
  39. package/mcp-server/useMcpServerCredentials.d.ts +38 -10
  40. package/mcp-server/useMcpServerCredentials.d.ts.map +1 -1
  41. package/mcp-server/useMcpServerCredentials.js +50 -7
  42. package/mcp-server/useMcpServerCredentials.js.map +1 -1
  43. package/mcp-server/useOrgOAuthApp.d.ts +22 -0
  44. package/mcp-server/useOrgOAuthApp.d.ts.map +1 -1
  45. package/mcp-server/useOrgOAuthApp.js +39 -7
  46. package/mcp-server/useOrgOAuthApp.js.map +1 -1
  47. package/package.json +4 -4
  48. package/session/useSessionConversation.d.ts +4 -2
  49. package/session/useSessionConversation.d.ts.map +1 -1
  50. package/session/useSessionConversation.js.map +1 -1
  51. package/skill/useSkillVersions.d.ts.map +1 -1
  52. package/skill/useSkillVersions.js +1 -9
  53. package/skill/useSkillVersions.js.map +1 -1
  54. package/src/activity/useRecentActivity.ts +3 -2
  55. package/src/agent/AgentDetailView.tsx +6 -130
  56. package/src/agent/internal/__tests__/agentToInput.test.ts +2 -11
  57. package/src/agent/internal/agentToInput.ts +0 -11
  58. package/src/dependency-graph/DependencyTreeNode.tsx +1 -7
  59. package/src/dependency-graph/__tests__/useDependencyGraph.test.ts +18 -34
  60. package/src/dependency-graph/types.ts +8 -20
  61. package/src/dependency-graph/useDependencyGraph.ts +2 -22
  62. package/src/execution/useCreateAgentExecution.ts +3 -2
  63. package/src/index.ts +0 -82
  64. package/src/internal/isUnimplemented.ts +26 -0
  65. package/src/library/useExportResource.ts +3 -4
  66. package/src/manifest/EditResourceYamlDialog.tsx +1 -2
  67. package/src/manifest/__tests__/ApplyManifestDialog.test.tsx +2 -2
  68. package/src/manifest/__tests__/EditResourceYamlDialog.test.tsx +9 -9
  69. package/src/mcp-server/McpServerConnectDialog.tsx +29 -11
  70. package/src/mcp-server/__tests__/VendorApprovalBlocked.surfaces.test.tsx +103 -5
  71. package/src/mcp-server/__tests__/byoaEditionDegradation.test.tsx +323 -0
  72. package/src/mcp-server/__tests__/useMcpServerCredentials.test.tsx +306 -0
  73. package/src/mcp-server/useMcpServerCredentials.ts +87 -19
  74. package/src/mcp-server/useOrgOAuthApp.ts +54 -8
  75. package/src/session/useSessionConversation.ts +4 -2
  76. package/src/skill/useSkillVersions.ts +1 -11
  77. package/src/workflow/WorkflowCanvasEditor.tsx +37 -7
  78. package/src/workflow/WorkflowExecutionGraph.tsx +26 -1
  79. package/src/workflow/WorkflowExecutionViewer.tsx +27 -13
  80. package/src/workflow/WorkflowNode.tsx +5 -2
  81. package/src/workflow/WorkflowRunDialog.tsx +28 -1
  82. package/src/workflow/__tests__/WorkflowExecutionViewer.reconciliation.test.tsx +48 -1
  83. package/src/workflow/__tests__/WorkflowNode.test.tsx +93 -0
  84. package/src/workflow/__tests__/WorkflowRunDialog.test.tsx +127 -0
  85. package/src/workflow/__tests__/graph-history.test.ts +103 -0
  86. package/src/workflow/__tests__/overview-graph.test.ts +17 -0
  87. package/src/workflow/__tests__/useCanvasKeyboardShortcuts.undo.test.ts +115 -0
  88. package/src/workflow/__tests__/useWorkflowCanvas.undo.test.tsx +133 -0
  89. package/src/workflow/instance/CreateWorkflowInstanceDialog.tsx +16 -7
  90. package/src/workflow/instance/useDeleteWorkflowInstance.ts +9 -4
  91. package/src/workflow/layout/registry-dimensions.ts +2 -5
  92. package/src/workflow/node-shell/NodeShell.tsx +4 -0
  93. package/src/workflow/task-type-visual-registry.ts +5 -3
  94. package/src/workflow/useCanvasKeyboardShortcuts.ts +33 -3
  95. package/src/workflow/useGraphHistory.ts +22 -41
  96. package/src/workflow/useWorkflowCanvas.ts +12 -10
  97. package/src/workflow/useWorkflowSave.ts +2 -15
  98. package/src/workflow/workflow-graph-conversions.ts +25 -3
  99. package/styles.css +1 -1
  100. package/workflow/CanvasTransitionEdge.d.ts +1 -1
  101. package/workflow/WorkflowCanvasEditor.d.ts.map +1 -1
  102. package/workflow/WorkflowCanvasEditor.js +31 -6
  103. package/workflow/WorkflowCanvasEditor.js.map +1 -1
  104. package/workflow/WorkflowExecutionGraph.d.ts.map +1 -1
  105. package/workflow/WorkflowExecutionGraph.js +27 -1
  106. package/workflow/WorkflowExecutionGraph.js.map +1 -1
  107. package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
  108. package/workflow/WorkflowExecutionViewer.js +26 -12
  109. package/workflow/WorkflowExecutionViewer.js.map +1 -1
  110. package/workflow/WorkflowNode.d.ts.map +1 -1
  111. package/workflow/WorkflowNode.js +2 -2
  112. package/workflow/WorkflowNode.js.map +1 -1
  113. package/workflow/WorkflowRunDialog.d.ts +11 -1
  114. package/workflow/WorkflowRunDialog.d.ts.map +1 -1
  115. package/workflow/WorkflowRunDialog.js +16 -2
  116. package/workflow/WorkflowRunDialog.js.map +1 -1
  117. package/workflow/instance/CreateWorkflowInstanceDialog.d.ts.map +1 -1
  118. package/workflow/instance/CreateWorkflowInstanceDialog.js +10 -2
  119. package/workflow/instance/CreateWorkflowInstanceDialog.js.map +1 -1
  120. package/workflow/instance/useDeleteWorkflowInstance.d.ts +9 -4
  121. package/workflow/instance/useDeleteWorkflowInstance.d.ts.map +1 -1
  122. package/workflow/instance/useDeleteWorkflowInstance.js +4 -2
  123. package/workflow/instance/useDeleteWorkflowInstance.js.map +1 -1
  124. package/workflow/layout/registry-dimensions.d.ts.map +1 -1
  125. package/workflow/layout/registry-dimensions.js +2 -5
  126. package/workflow/layout/registry-dimensions.js.map +1 -1
  127. package/workflow/node-shell/NodeShell.js +1 -1
  128. package/workflow/node-shell/NodeShell.js.map +1 -1
  129. package/workflow/task-type-visual-registry.d.ts.map +1 -1
  130. package/workflow/task-type-visual-registry.js +5 -3
  131. package/workflow/task-type-visual-registry.js.map +1 -1
  132. package/workflow/useCanvasKeyboardShortcuts.d.ts +15 -4
  133. package/workflow/useCanvasKeyboardShortcuts.d.ts.map +1 -1
  134. package/workflow/useCanvasKeyboardShortcuts.js +25 -4
  135. package/workflow/useCanvasKeyboardShortcuts.js.map +1 -1
  136. package/workflow/useGraphHistory.d.ts +16 -9
  137. package/workflow/useGraphHistory.d.ts.map +1 -1
  138. package/workflow/useGraphHistory.js +19 -33
  139. package/workflow/useGraphHistory.js.map +1 -1
  140. package/workflow/useWorkflowCanvas.d.ts +1 -3
  141. package/workflow/useWorkflowCanvas.d.ts.map +1 -1
  142. package/workflow/useWorkflowCanvas.js +15 -9
  143. package/workflow/useWorkflowCanvas.js.map +1 -1
  144. package/workflow/useWorkflowSave.d.ts.map +1 -1
  145. package/workflow/useWorkflowSave.js +2 -15
  146. package/workflow/useWorkflowSave.js.map +1 -1
  147. package/workflow/workflow-graph-conversions.d.ts +19 -1
  148. package/workflow/workflow-graph-conversions.d.ts.map +1 -1
  149. package/workflow/workflow-graph-conversions.js +17 -3
  150. package/workflow/workflow-graph-conversions.js.map +1 -1
  151. package/datastore/CollectionRecordsBrowser.d.ts +0 -34
  152. package/datastore/CollectionRecordsBrowser.d.ts.map +0 -1
  153. package/datastore/CollectionRecordsBrowser.js +0 -226
  154. package/datastore/CollectionRecordsBrowser.js.map +0 -1
  155. package/datastore/CollectionSchemaView.d.ts +0 -29
  156. package/datastore/CollectionSchemaView.d.ts.map +0 -1
  157. package/datastore/CollectionSchemaView.js +0 -93
  158. package/datastore/CollectionSchemaView.js.map +0 -1
  159. package/datastore/DatastoreDetailView.d.ts +0 -44
  160. package/datastore/DatastoreDetailView.d.ts.map +0 -1
  161. package/datastore/DatastoreDetailView.js +0 -76
  162. package/datastore/DatastoreDetailView.js.map +0 -1
  163. package/datastore/DatastoreSyncReport.d.ts +0 -19
  164. package/datastore/DatastoreSyncReport.d.ts.map +0 -1
  165. package/datastore/DatastoreSyncReport.js +0 -45
  166. package/datastore/DatastoreSyncReport.js.map +0 -1
  167. package/datastore/DeleteDatastoreDialog.d.ts +0 -35
  168. package/datastore/DeleteDatastoreDialog.d.ts.map +0 -1
  169. package/datastore/DeleteDatastoreDialog.js +0 -90
  170. package/datastore/DeleteDatastoreDialog.js.map +0 -1
  171. package/datastore/FieldValueControl.d.ts +0 -55
  172. package/datastore/FieldValueControl.d.ts.map +0 -1
  173. package/datastore/FieldValueControl.js +0 -138
  174. package/datastore/FieldValueControl.js.map +0 -1
  175. package/datastore/RecordFilterBuilder.d.ts +0 -37
  176. package/datastore/RecordFilterBuilder.d.ts.map +0 -1
  177. package/datastore/RecordFilterBuilder.js +0 -122
  178. package/datastore/RecordFilterBuilder.js.map +0 -1
  179. package/datastore/RecordFormPanel.d.ts +0 -45
  180. package/datastore/RecordFormPanel.d.ts.map +0 -1
  181. package/datastore/RecordFormPanel.js +0 -215
  182. package/datastore/RecordFormPanel.js.map +0 -1
  183. package/datastore/index.d.ts +0 -43
  184. package/datastore/index.d.ts.map +0 -1
  185. package/datastore/index.js +0 -22
  186. package/datastore/index.js.map +0 -1
  187. package/datastore/recordFilter.d.ts +0 -62
  188. package/datastore/recordFilter.d.ts.map +0 -1
  189. package/datastore/recordFilter.js +0 -104
  190. package/datastore/recordFilter.js.map +0 -1
  191. package/datastore/recordValues.d.ts +0 -85
  192. package/datastore/recordValues.d.ts.map +0 -1
  193. package/datastore/recordValues.js +0 -282
  194. package/datastore/recordValues.js.map +0 -1
  195. package/datastore/useDatastore.d.ts +0 -39
  196. package/datastore/useDatastore.d.ts.map +0 -1
  197. package/datastore/useDatastore.js +0 -44
  198. package/datastore/useDatastore.js.map +0 -1
  199. package/datastore/useDatastoreCount.d.ts +0 -50
  200. package/datastore/useDatastoreCount.d.ts.map +0 -1
  201. package/datastore/useDatastoreCount.js +0 -27
  202. package/datastore/useDatastoreCount.js.map +0 -1
  203. package/datastore/useDatastoreDescription.d.ts +0 -54
  204. package/datastore/useDatastoreDescription.d.ts.map +0 -1
  205. package/datastore/useDatastoreDescription.js +0 -50
  206. package/datastore/useDatastoreDescription.js.map +0 -1
  207. package/datastore/useDatastoreList.d.ts +0 -57
  208. package/datastore/useDatastoreList.d.ts.map +0 -1
  209. package/datastore/useDatastoreList.js +0 -29
  210. package/datastore/useDatastoreList.js.map +0 -1
  211. package/datastore/useDatastoreSearch.d.ts +0 -19
  212. package/datastore/useDatastoreSearch.d.ts.map +0 -1
  213. package/datastore/useDatastoreSearch.js +0 -22
  214. package/datastore/useDatastoreSearch.js.map +0 -1
  215. package/datastore/useDeleteDatastore.d.ts +0 -53
  216. package/datastore/useDeleteDatastore.d.ts.map +0 -1
  217. package/datastore/useDeleteDatastore.js +0 -40
  218. package/datastore/useDeleteDatastore.js.map +0 -1
  219. package/datastore/useDeleteRecord.d.ts +0 -34
  220. package/datastore/useDeleteRecord.d.ts.map +0 -1
  221. package/datastore/useDeleteRecord.js +0 -43
  222. package/datastore/useDeleteRecord.js.map +0 -1
  223. package/datastore/useInsertRecord.d.ts +0 -50
  224. package/datastore/useInsertRecord.d.ts.map +0 -1
  225. package/datastore/useInsertRecord.js +0 -55
  226. package/datastore/useInsertRecord.js.map +0 -1
  227. package/datastore/useRecordCollection.d.ts +0 -104
  228. package/datastore/useRecordCollection.d.ts.map +0 -1
  229. package/datastore/useRecordCollection.js +0 -136
  230. package/datastore/useRecordCollection.js.map +0 -1
  231. package/datastore/useRecordList.d.ts +0 -66
  232. package/datastore/useRecordList.d.ts.map +0 -1
  233. package/datastore/useRecordList.js +0 -58
  234. package/datastore/useRecordList.js.map +0 -1
  235. package/datastore/useUpdateRecord.d.ts +0 -52
  236. package/datastore/useUpdateRecord.d.ts.map +0 -1
  237. package/datastore/useUpdateRecord.js +0 -55
  238. package/datastore/useUpdateRecord.js.map +0 -1
  239. package/src/agent/__tests__/AgentDetailView.datastores.test.tsx +0 -166
  240. package/src/datastore/CollectionRecordsBrowser.tsx +0 -571
  241. package/src/datastore/CollectionSchemaView.tsx +0 -247
  242. package/src/datastore/DatastoreDetailView.tsx +0 -201
  243. package/src/datastore/DatastoreSyncReport.tsx +0 -105
  244. package/src/datastore/DeleteDatastoreDialog.tsx +0 -202
  245. package/src/datastore/FieldValueControl.tsx +0 -289
  246. package/src/datastore/RecordFilterBuilder.tsx +0 -422
  247. package/src/datastore/RecordFormPanel.tsx +0 -432
  248. package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +0 -245
  249. package/src/datastore/__tests__/DeleteDatastoreDialog.test.tsx +0 -133
  250. package/src/datastore/__tests__/FieldValueControl.test.tsx +0 -160
  251. package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +0 -155
  252. package/src/datastore/__tests__/RecordFormPanel.test.tsx +0 -227
  253. package/src/datastore/__tests__/recordFilter.test.ts +0 -169
  254. package/src/datastore/__tests__/recordMutations.test.tsx +0 -195
  255. package/src/datastore/__tests__/recordValues.test.ts +0 -359
  256. package/src/datastore/__tests__/schemaAndSyncViews.test.tsx +0 -142
  257. package/src/datastore/__tests__/useDatastoreDescription.test.tsx +0 -143
  258. package/src/datastore/__tests__/useRecordCollection.test.tsx +0 -250
  259. package/src/datastore/__tests__/useRecordList.test.tsx +0 -85
  260. package/src/datastore/index.ts +0 -111
  261. package/src/datastore/recordFilter.ts +0 -154
  262. package/src/datastore/recordValues.ts +0 -327
  263. package/src/datastore/useDatastore.ts +0 -67
  264. package/src/datastore/useDatastoreCount.ts +0 -69
  265. package/src/datastore/useDatastoreDescription.ts +0 -90
  266. package/src/datastore/useDatastoreList.ts +0 -79
  267. package/src/datastore/useDatastoreSearch.ts +0 -39
  268. package/src/datastore/useDeleteDatastore.ts +0 -87
  269. package/src/datastore/useDeleteRecord.ts +0 -77
  270. package/src/datastore/useInsertRecord.ts +0 -92
  271. package/src/datastore/useRecordCollection.ts +0 -256
  272. package/src/datastore/useRecordList.ts +0 -131
  273. package/src/datastore/useUpdateRecord.ts +0 -95
@@ -4,7 +4,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
4
  import { cn } from "@stigmer/theme";
5
5
  import { timestampDate } from "@bufbuild/protobuf/wkt";
6
6
  import type {
7
- DatastoreUsage,
8
7
  McpServerUsage,
9
8
  SubAgent,
10
9
  } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
@@ -17,7 +16,6 @@ import { useUpdateAgent } from "./useUpdateAgent.js";
17
16
  import { agentToInput } from "./internal/agentToInput.js";
18
17
  import { toError } from "../internal/toError.js";
19
18
  import { ErrorMessage } from "../error/ErrorMessage.js";
20
- import { DatastoreIcon } from "../datastore/DatastoreDetailView.js";
21
19
  import { VisibilityBadge } from "../library/VisibilitySelector.js";
22
20
  import { useManageAccess } from "../access/useManageAccess.js";
23
21
  import { AgentShareList } from "../sharing/AgentShareList.js";
@@ -61,13 +59,6 @@ export interface AgentDetailViewProps {
61
59
  * Provides `org` and `slug` of the referenced skill.
62
60
  */
63
61
  readonly onSkillClick?: (ref: { org: string; slug: string }) => void;
64
- /**
65
- * Called when a datastore reference is clicked.
66
- * Provides `org` and `slug` of the referenced datastore so the
67
- * consumer can wire navigation. When the reference has no explicit
68
- * org, the agent's own org is used as fallback.
69
- */
70
- readonly onDatastoreClick?: (ref: { org: string; slug: string }) => void;
71
62
  /**
72
63
  * Called once when the agent resource has been fetched successfully.
73
64
  * Provides the resource display name for use cases like breadcrumbs,
@@ -186,7 +177,7 @@ export interface AgentDetailViewProps {
186
177
  * Fetches the agent via {@link useAgent} internally and renders its
187
178
  * full configuration inside a {@link ResourceDetailShell}: a
188
179
  * standardized header with action bar, followed by structured content
189
- * sections (instructions, MCP server usages, skills, datastores,
180
+ * sections (instructions, MCP server usages, skills,
190
181
  * sub-agents, and environment variables). Sections with no data are
191
182
  * omitted entirely — reducing visual noise per Nielsen heuristic #8.
192
183
  *
@@ -225,7 +216,6 @@ export function AgentDetailView({
225
216
  slug,
226
217
  onMcpServerClick,
227
218
  onSkillClick,
228
- onDatastoreClick,
229
219
  onResourceLoad,
230
220
  primaryAction,
231
221
  actions,
@@ -249,8 +239,8 @@ export function AgentDetailView({
249
239
 
250
240
  // Last failed inline save, attributed to the field that was edited so
251
241
  // only that section shows the message. The backend's message is the
252
- // UX (DD-006): e.g. the datastore exposure guard refuses public +
253
- // datastore_usages with an actionable FAILED_PRECONDITION message.
242
+ // UX (DD-006): server refusals arrive as actionable FAILED_PRECONDITION
243
+ // messages.
254
244
  const [saveError, setSaveError] = useState<{
255
245
  field: string;
256
246
  message: string;
@@ -314,11 +304,9 @@ export function AgentDetailView({
314
304
  onMcpServerClick?.(node.ref);
315
305
  } else if (node.kind === "skill") {
316
306
  onSkillClick?.(node.ref);
317
- } else if (node.kind === "datastore") {
318
- onDatastoreClick?.(node.ref);
319
307
  }
320
308
  },
321
- [onMcpServerClick, onSkillClick, onDatastoreClick],
309
+ [onMcpServerClick, onSkillClick],
322
310
  );
323
311
 
324
312
  const onResourceLoadRef = useRef(onResourceLoad);
@@ -456,7 +444,6 @@ export function AgentDetailView({
456
444
  description={spec?.description}
457
445
  onMcpServerClick={onMcpServerClick}
458
446
  onSkillClick={onSkillClick}
459
- onDatastoreClick={onDatastoreClick}
460
447
  editable={editable}
461
448
  isSaving={isUpdating}
462
449
  saveField={saveField}
@@ -496,7 +483,6 @@ function AgentOverview({
496
483
  description,
497
484
  onMcpServerClick,
498
485
  onSkillClick,
499
- onDatastoreClick,
500
486
  editable,
501
487
  isSaving,
502
488
  saveField,
@@ -508,7 +494,6 @@ function AgentOverview({
508
494
  readonly description?: string;
509
495
  readonly onMcpServerClick?: (ref: { org: string; slug: string }) => void;
510
496
  readonly onSkillClick?: (ref: { org: string; slug: string }) => void;
511
- readonly onDatastoreClick?: (ref: { org: string; slug: string }) => void;
512
497
  readonly editable?: boolean;
513
498
  readonly isSaving?: boolean;
514
499
  readonly saveField?: <K extends keyof import("@stigmer/sdk").AgentInput>(
@@ -519,8 +504,8 @@ function AgentOverview({
519
504
  readonly clearSaveError?: () => void;
520
505
  }) {
521
506
  // The failed save's message, shown only under the section that owns
522
- // the field — a rejection of a datastore edit must not appear under
523
- // the skills editor.
507
+ // the field — a rejection of one section's edit must not appear under
508
+ // another section's editor.
524
509
  const errorFor = (field: keyof import("@stigmer/sdk").AgentInput) =>
525
510
  saveError?.field === field ? saveError.message : undefined;
526
511
  const handleInstructionsSave = useCallback(
@@ -548,15 +533,6 @@ function AgentOverview({
548
533
  [saveField],
549
534
  );
550
535
 
551
- const handleDatastoresSave = useCallback(
552
- async (refs: ResourceRefRow[]) =>
553
- saveField?.(
554
- "datastoreUsages",
555
- refs.map((r) => ({ datastoreRef: { org: r.org, slug: r.slug } })),
556
- ) ?? false,
557
- [saveField],
558
- );
559
-
560
536
  const handleEnvSave = useCallback(
561
537
  async (rows: KeyValueRow[]) => {
562
538
  const env: Record<string, { isSecret?: boolean; description?: string; optional?: boolean }> = {};
@@ -600,19 +576,6 @@ function AgentOverview({
600
576
  [spec?.skillRefs, agentOrg],
601
577
  );
602
578
 
603
- const datastoreRefRows: ResourceRefRow[] = useMemo(
604
- () =>
605
- (spec?.datastoreUsages ?? []).map((usage) => ({
606
- org: usage.datastoreRef?.org || agentOrg,
607
- slug: usage.datastoreRef?.slug ?? "",
608
- label:
609
- usage.datastoreRef?.org && usage.datastoreRef.org !== agentOrg
610
- ? `${usage.datastoreRef.org}/${usage.datastoreRef.slug}`
611
- : usage.datastoreRef?.slug ?? "",
612
- })),
613
- [spec?.datastoreUsages, agentOrg],
614
- );
615
-
616
579
  const envRows: KeyValueRow[] = useMemo(
617
580
  () =>
618
581
  Object.entries(spec?.env ?? {})
@@ -631,13 +594,11 @@ function AgentOverview({
631
594
  const showInstructions = editable || !!spec?.instructions;
632
595
  const showMcpServers = editable || (spec && spec.mcpServerUsages.length > 0);
633
596
  const showSkills = editable || (spec && spec.skillRefs.length > 0);
634
- const showDatastores = editable || (spec && spec.datastoreUsages.length > 0);
635
597
  const showSubAgents = editable || (spec && spec.subAgents.length > 0);
636
598
  const showEnv = editable || (spec?.env && Object.keys(spec.env).length > 0);
637
599
 
638
600
  const [mcpEditing, setMcpEditing] = useState(false);
639
601
  const [skillsEditing, setSkillsEditing] = useState(false);
640
- const [datastoresEditing, setDatastoresEditing] = useState(false);
641
602
  const [envEditing, setEnvEditing] = useState(false);
642
603
 
643
604
  // Entering edit mode discards the previous attempt's error — the
@@ -656,13 +617,6 @@ function AgentOverview({
656
617
  },
657
618
  [clearSaveError],
658
619
  );
659
- const handleDatastoresEditingChange = useCallback(
660
- (editing: boolean) => {
661
- if (editing) clearSaveError?.();
662
- setDatastoresEditing(editing);
663
- },
664
- [clearSaveError],
665
- );
666
620
  const handleEnvEditingChange = useCallback(
667
621
  (editing: boolean) => {
668
622
  if (editing) clearSaveError?.();
@@ -765,31 +719,6 @@ function AgentOverview({
765
719
  </Section>
766
720
  )}
767
721
 
768
- {showDatastores && (
769
- <Section title="Datastores" count={spec?.datastoreUsages.length} onEdit={editable ? () => handleDatastoresEditingChange(!datastoresEditing) : undefined}>
770
- {editable ? (
771
- <InlineEditResourceList
772
- value={datastoreRefRows}
773
- onSave={handleDatastoresSave}
774
- isSaving={isSaving}
775
- error={errorFor("datastoreUsages")}
776
- editing={datastoresEditing}
777
- onEditingChange={handleDatastoresEditingChange}
778
- onItemClick={onDatastoreClick ? (ref) => onDatastoreClick({ org: ref.org, slug: ref.slug }) : undefined}
779
- itemIcon={<DatastoreIcon className="stg:size-4" />}
780
- resourceLabel="datastore"
781
- defaultOrg={agentOrg}
782
- />
783
- ) : (
784
- <DatastoresContent
785
- usages={spec?.datastoreUsages ?? []}
786
- defaultOrg={agentOrg}
787
- onDatastoreClick={onDatastoreClick}
788
- />
789
- )}
790
- </Section>
791
- )}
792
-
793
722
  {showSubAgents && (
794
723
  <SubAgentsSection
795
724
  subAgents={spec?.subAgents ?? []}
@@ -986,59 +915,6 @@ function SkillsContent({
986
915
  );
987
916
  }
988
917
 
989
- function DatastoresContent({
990
- usages,
991
- defaultOrg,
992
- onDatastoreClick,
993
- }: {
994
- readonly usages: readonly DatastoreUsage[];
995
- readonly defaultOrg: string;
996
- readonly onDatastoreClick?: (ref: { org: string; slug: string }) => void;
997
- }) {
998
- return (
999
- <div className="stg:flex stg:flex-col">
1000
- {usages.map((usage, index) => {
1001
- const ref = usage.datastoreRef;
1002
- if (!ref) return null;
1003
-
1004
- const refOrg = ref.org || defaultOrg;
1005
- const label =
1006
- ref.org && ref.org !== defaultOrg
1007
- ? `${ref.org}/${ref.slug}`
1008
- : ref.slug;
1009
-
1010
- const row = (
1011
- <div className="stg:flex stg:items-center stg:gap-3">
1012
- <DatastoreIcon className="stg:size-4 stg:shrink-0 stg:text-muted-foreground" />
1013
- <span className="stg:text-sm stg:font-medium stg:text-foreground">
1014
- {label}
1015
- </span>
1016
- </div>
1017
- );
1018
-
1019
- return onDatastoreClick ? (
1020
- <button
1021
- key={ref.slug || index}
1022
- type="button"
1023
- onClick={() => onDatastoreClick({ org: refOrg, slug: ref.slug })}
1024
- className={cn(
1025
- "stg:w-full stg:rounded-md stg:px-3 stg:py-2 stg:text-left stg:transition-colors",
1026
- "stg:hover:bg-accent-hover",
1027
- "stg:focus-visible:outline-none stg:focus-visible:ring-2 stg:focus-visible:ring-inset stg:focus-visible:ring-ring",
1028
- )}
1029
- >
1030
- {row}
1031
- </button>
1032
- ) : (
1033
- <div key={ref.slug || index} className="stg:px-3 stg:py-2">
1034
- {row}
1035
- </div>
1036
- );
1037
- })}
1038
- </div>
1039
- );
1040
- }
1041
-
1042
918
  interface SubAgentDraft {
1043
919
  name: string;
1044
920
  description: string;
@@ -9,7 +9,7 @@ import { agentToInput } from "../agentToInput";
9
9
 
10
10
  /**
11
11
  * Regression guard for stigmer/stigmer#319 — the console agent editor
12
- * silently deleting `datastore_usages` on save.
12
+ * silently deleting an unmapped spec field on save.
13
13
  *
14
14
  * `agentToInput()` reconstructs a full `AgentInput` from a fetched Agent
15
15
  * so inline edits can re-submit the whole spec (the backend does full
@@ -91,19 +91,10 @@ function fullyPopulatedAgent(): Agent {
91
91
  env: {
92
92
  CLINIC_API_KEY: {
93
93
  isSecret: true,
94
- description: "Records bridge credential",
94
+ description: "Clinic API credential",
95
95
  },
96
96
  REGION: { optional: true },
97
97
  },
98
- datastoreUsages: [
99
- {
100
- datastoreRef: {
101
- org: "acme",
102
- slug: "clinic-records",
103
- kind: ApiResourceKind.datastore,
104
- },
105
- },
106
- ],
107
98
  },
108
99
  });
109
100
  }
@@ -1,7 +1,6 @@
1
1
  import type { Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
2
2
  import type {
3
3
  AgentInput,
4
- DatastoreUsageInput,
5
4
  EnvVarDeclarationInput,
6
5
  McpServerUsageInput,
7
6
  SubAgentInput,
@@ -73,15 +72,6 @@ export function agentToInput(agent: Agent): AgentInput {
73
72
  modelOverride: sa.modelOverride || undefined,
74
73
  }));
75
74
 
76
- const datastoreUsages: DatastoreUsageInput[] | undefined =
77
- spec?.datastoreUsages?.map((usage) => ({
78
- datastoreRef: {
79
- org: usage.datastoreRef?.org ?? "",
80
- slug: usage.datastoreRef?.slug ?? "",
81
- version: usage.datastoreRef?.version || undefined,
82
- },
83
- }));
84
-
85
75
  let env: Record<string, EnvVarDeclarationInput> | undefined;
86
76
  if (spec?.env && Object.keys(spec.env).length > 0) {
87
77
  env = {};
@@ -108,6 +98,5 @@ export function agentToInput(agent: Agent): AgentInput {
108
98
  skillRefs: skillRefs?.length ? skillRefs : undefined,
109
99
  subAgents: subAgents?.length ? subAgents : undefined,
110
100
  env,
111
- datastoreUsages: datastoreUsages?.length ? datastoreUsages : undefined,
112
101
  };
113
102
  }
@@ -2,7 +2,6 @@
2
2
 
3
3
  import { useCallback, useState, type KeyboardEvent } from "react";
4
4
  import { cn } from "@stigmer/theme";
5
- import { DatastoreIcon } from "../datastore/DatastoreDetailView.js";
6
5
  import type { DependencyNode, NodeKind } from "./types.js";
7
6
 
8
7
  interface DependencyTreeNodeProps {
@@ -16,7 +15,6 @@ const KIND_LABELS: Record<NodeKind, string> = {
16
15
  agent: "Agent",
17
16
  "mcp-server": "MCP",
18
17
  skill: "Skill",
19
- datastore: "Datastore",
20
18
  "sub-agent": "Sub-Agent",
21
19
  };
22
20
 
@@ -182,9 +180,7 @@ function kindBadgeClasses(kind: NodeKind): string {
182
180
  case "skill":
183
181
  return "stg:bg-[var(--stgm-status-pending-subtle)] stg:text-[var(--stgm-status-pending)]";
184
182
  // Badges borrow status hues as category colors (skill=pending,
185
- // sub-agent=ready); datastore takes the remaining distinct hue.
186
- case "datastore":
187
- return "stg:bg-[var(--stgm-status-degraded-subtle)] stg:text-[var(--stgm-status-degraded)]";
183
+ // sub-agent=ready).
188
184
  case "sub-agent":
189
185
  return "stg:bg-[var(--stgm-status-ready-subtle)] stg:text-[var(--stgm-status-ready)]";
190
186
  case "agent":
@@ -211,8 +207,6 @@ function NodeIcon({
211
207
  return <McpServerIcon className={className} />;
212
208
  case "skill":
213
209
  return <SkillIcon className={className} />;
214
- case "datastore":
215
- return <DatastoreIcon className={className} />;
216
210
  }
217
211
  }
218
212
 
@@ -15,48 +15,46 @@ function graphFor(spec: Parameters<typeof useDependencyGraph>[0]["spec"]) {
15
15
  return result.current;
16
16
  }
17
17
 
18
- describe("useDependencyGraph — datastore nodes", () => {
19
- it("derives a datastore node with a navigation ref", () => {
18
+ describe("useDependencyGraph", () => {
19
+ it("derives a skill node with a navigation ref", () => {
20
20
  const { tree, isEmpty } = graphFor({
21
21
  ...emptySpec,
22
- datastoreUsages: [
23
- { datastoreRef: { org: "acme", slug: "clinic-records" } },
24
- ],
22
+ skillRefs: [{ org: "acme", slug: "triage-guide" }],
25
23
  });
26
24
 
27
- // A datastore-only agent has dependencies — the tab must appear.
25
+ // A skill-only agent has dependencies — the tab must appear.
28
26
  expect(isEmpty).toBe(false);
29
27
  expect(tree).not.toBeNull();
30
28
  expect(tree!.nodeCount).toBe(2);
31
29
 
32
30
  const node = tree!.root.children[0];
33
31
  expect(node).toMatchObject({
34
- id: "datastore:clinic-records",
35
- kind: "datastore",
36
- label: "clinic-records",
37
- ref: { org: "acme", slug: "clinic-records" },
32
+ id: "skill:triage-guide",
33
+ kind: "skill",
34
+ label: "triage-guide",
35
+ ref: { org: "acme", slug: "triage-guide" },
38
36
  });
39
37
  // Same-org ref gets no qualified label.
40
38
  expect(node.qualifiedLabel).toBeUndefined();
41
39
  });
42
40
 
43
- it("qualifies cross-org datastore labels and falls back to the agent org for empty refs", () => {
41
+ it("qualifies cross-org labels and falls back to the agent org for empty refs", () => {
44
42
  const { tree } = graphFor({
45
43
  ...emptySpec,
46
- datastoreUsages: [
47
- { datastoreRef: { org: "partner", slug: "shared-records" } },
48
- { datastoreRef: { org: "", slug: "local-records" } },
44
+ skillRefs: [
45
+ { org: "partner", slug: "shared-guide" },
46
+ { org: "", slug: "local-guide" },
49
47
  ],
50
48
  });
51
49
 
52
50
  const [crossOrg, relative] = tree!.root.children;
53
- expect(crossOrg.qualifiedLabel).toBe("partner/shared-records");
54
- expect(crossOrg.ref).toEqual({ org: "partner", slug: "shared-records" });
51
+ expect(crossOrg.qualifiedLabel).toBe("partner/shared-guide");
52
+ expect(crossOrg.ref).toEqual({ org: "partner", slug: "shared-guide" });
55
53
  expect(relative.qualifiedLabel).toBeUndefined();
56
- expect(relative.ref).toEqual({ org: "acme", slug: "local-records" });
54
+ expect(relative.ref).toEqual({ org: "acme", slug: "local-guide" });
57
55
  });
58
56
 
59
- it("orders children to mirror the Overview sections: MCP, skills, datastores, sub-agents", () => {
57
+ it("orders children to mirror the Overview sections: MCP, skills, sub-agents", () => {
60
58
  const { tree } = graphFor({
61
59
  mcpServerUsages: [
62
60
  {
@@ -75,32 +73,18 @@ describe("useDependencyGraph — datastore nodes", () => {
75
73
  modelOverride: "",
76
74
  },
77
75
  ],
78
- datastoreUsages: [
79
- { datastoreRef: { org: "acme", slug: "clinic-records" } },
80
- ],
81
76
  });
82
77
 
83
78
  expect(tree!.root.children.map((c) => c.kind)).toEqual([
84
79
  "mcp-server",
85
80
  "skill",
86
- "datastore",
87
81
  "sub-agent",
88
82
  ]);
89
- expect(tree!.nodeCount).toBe(5);
90
- });
91
-
92
- it("accepts specs without the datastoreUsages field (pre-existing public callers)", () => {
93
- const { tree, isEmpty } = graphFor({
94
- ...emptySpec,
95
- skillRefs: [{ org: "acme", slug: "triage-guide" }],
96
- });
97
-
98
- expect(isEmpty).toBe(false);
99
- expect(tree!.root.children.map((c) => c.kind)).toEqual(["skill"]);
83
+ expect(tree!.nodeCount).toBe(4);
100
84
  });
101
85
 
102
86
  it("stays empty when no dependencies exist at all", () => {
103
- const { tree, isEmpty } = graphFor({ ...emptySpec, datastoreUsages: [] });
87
+ const { tree, isEmpty } = graphFor(emptySpec);
104
88
 
105
89
  expect(isEmpty).toBe(true);
106
90
  expect(tree).toBeNull();
@@ -4,10 +4,9 @@
4
4
  * - `"agent"` — the root agent (always the tree root)
5
5
  * - `"mcp-server"` — an MCP server referenced via `mcpServerUsages` or `mcpAccess`
6
6
  * - `"skill"` — a skill referenced via `skillRefs`
7
- * - `"datastore"` — a datastore referenced via `datastoreUsages`
8
7
  * - `"sub-agent"` — an inline sub-agent definition with its own dependencies
9
8
  */
10
- export type NodeKind = "agent" | "mcp-server" | "skill" | "datastore" | "sub-agent";
9
+ export type NodeKind = "agent" | "mcp-server" | "skill" | "sub-agent";
11
10
 
12
11
  /**
13
12
  * A single node in the agent dependency tree.
@@ -16,9 +15,9 @@ export type NodeKind = "agent" | "mcp-server" | "skill" | "datastore" | "sub-age
16
15
  * (MCP servers and skills they access). Edges are implicit in the
17
16
  * parent-child relationship — no separate edge type is needed.
18
17
  *
19
- * Nodes are navigable when `ref` is defined (MCP servers, skills,
20
- * datastores). Sub-agent nodes have no `ref` because they are inline
21
- * definitions within the agent spec, not standalone resources.
18
+ * Nodes are navigable when `ref` is defined (MCP servers and skills).
19
+ * Sub-agent nodes have no `ref` because they are inline definitions
20
+ * within the agent spec, not standalone resources.
22
21
  */
23
22
  export interface DependencyNode {
24
23
  /**
@@ -47,9 +46,9 @@ export interface DependencyNode {
47
46
  /** Child nodes. Empty array for leaf nodes (MCP servers, skills). */
48
47
  readonly children: readonly DependencyNode[];
49
48
  /**
50
- * Navigation reference for clickable nodes. Defined for MCP servers,
51
- * skills, and datastores (standalone resources). Undefined for
52
- * sub-agents (inline definitions) and the root agent.
49
+ * Navigation reference for clickable nodes. Defined for MCP servers
50
+ * and skills (standalone resources). Undefined for sub-agents (inline
51
+ * definitions) and the root agent.
53
52
  */
54
53
  readonly ref?: { readonly org: string; readonly slug: string };
55
54
  }
@@ -71,7 +70,7 @@ export interface DependencyGraphProps {
71
70
  /**
72
71
  * Called when a navigable node is clicked. The `node.ref` field
73
72
  * contains the `org` and `slug` for routing. Only fired for nodes
74
- * where `ref` is defined (MCP servers, skills, datastores).
73
+ * where `ref` is defined (MCP servers and skills).
75
74
  */
76
75
  readonly onNodeClick?: (node: DependencyNode) => void;
77
76
  /**
@@ -120,17 +119,6 @@ export interface UseDependencyGraphOptions {
120
119
  }[];
121
120
  readonly modelOverride: string;
122
121
  }[];
123
- /**
124
- * Datastore attachments (`spec.datastoreUsages`). Optional because
125
- * this hook is a public SDK export: callers passing hand-built spec
126
- * objects written before the field existed must keep compiling.
127
- */
128
- readonly datastoreUsages?: readonly {
129
- readonly datastoreRef?: {
130
- readonly org: string;
131
- readonly slug: string;
132
- };
133
- }[];
134
122
  } | undefined;
135
123
  }
136
124
 
@@ -41,12 +41,10 @@ export function useDependencyGraph({
41
41
  if (!spec) return { tree: null, isEmpty: true };
42
42
 
43
43
  const { mcpServerUsages, skillRefs, subAgents } = spec;
44
- const datastoreUsages = spec.datastoreUsages ?? [];
45
44
 
46
45
  const hasDeps =
47
46
  mcpServerUsages.length > 0 ||
48
47
  skillRefs.length > 0 ||
49
- datastoreUsages.length > 0 ||
50
48
  subAgents.length > 0;
51
49
 
52
50
  if (!hasDeps) return { tree: null, isEmpty: true };
@@ -94,24 +92,6 @@ export function useDependencyGraph({
94
92
  };
95
93
  });
96
94
 
97
- const datastoreNodes: DependencyNode[] = datastoreUsages
98
- .filter((u) => u.datastoreRef)
99
- .map((usage) => {
100
- nodeCount++;
101
- const ref = usage.datastoreRef!;
102
- return {
103
- id: `datastore:${ref.slug}`,
104
- kind: "datastore" as const,
105
- label: ref.slug,
106
- qualifiedLabel:
107
- ref.org && ref.org !== agentOrg
108
- ? `${ref.org}/${ref.slug}`
109
- : undefined,
110
- children: [],
111
- ref: { org: ref.org || agentOrg, slug: ref.slug },
112
- };
113
- });
114
-
115
95
  const subAgentNodes: DependencyNode[] = subAgents.map((sa) => {
116
96
  nodeCount++;
117
97
 
@@ -164,12 +144,12 @@ export function useDependencyGraph({
164
144
  });
165
145
 
166
146
  // Child ordering mirrors the Overview sections: MCP servers,
167
- // skills, datastores, then sub-agents.
147
+ // skills, then sub-agents.
168
148
  const root: DependencyNode = {
169
149
  id: `agent:${agentName}`,
170
150
  kind: "agent",
171
151
  label: agentName,
172
- children: [...mcpNodes, ...skillNodes, ...datastoreNodes, ...subAgentNodes],
152
+ children: [...mcpNodes, ...skillNodes, ...subAgentNodes],
173
153
  };
174
154
 
175
155
  return {
@@ -94,8 +94,9 @@ export interface SharedAgentExecutionFields {
94
94
  *
95
95
  * Values are injected into the agent sandbox for this execution only
96
96
  * and deleted when the execution completes. They take the highest
97
- * merge priority, overriding both Environment values and agent
98
- * defaults.
97
+ * merge priority, overriding Environment values bound via the
98
+ * instance. Keys must be declared in the agent's env declarations
99
+ * (a whitelist, not a value source) or they are dropped.
99
100
  *
100
101
  * Use this for B2B integrations where per-call credentials are
101
102
  * injected at runtime, or for one-off secrets that should not persist.
package/src/index.ts CHANGED
@@ -701,88 +701,6 @@ export type {
701
701
  AgentWizardData,
702
702
  } from "./agent/index.js";
703
703
 
704
- // Datastore — data hooks (kind family + describe projection), record
705
- // hooks (find/insert/update/delete + grid collection), guarded delete,
706
- // the canonical value semantics of declared fields, the typed filter
707
- // model, and the six styled components (detail view, records browser,
708
- // filter builder, record form, schema view, sync report, delete dialog)
709
- export {
710
- useDatastore,
711
- useDatastoreList,
712
- useDatastoreCount,
713
- useDatastoreSearch,
714
- useDatastoreDescription,
715
- DEFAULT_PARTITION,
716
- useRecordList,
717
- useInsertRecord,
718
- useUpdateRecord,
719
- useDeleteRecord,
720
- useRecordCollection,
721
- useDeleteDatastore,
722
- buildUpdateFields,
723
- coerceFieldValue,
724
- formatFieldValue,
725
- formatSystemTimestamp,
726
- isListOperator,
727
- isSortableField,
728
- isValuelessOperator,
729
- operatorsForField,
730
- OPERATOR_LABELS,
731
- RESERVED_FIELD_NAMES,
732
- SYSTEM_FIELD_OPERATORS,
733
- buildRecordFilter,
734
- filterableFields,
735
- formatConditionChip,
736
- isConditionComplete,
737
- FieldValueControl,
738
- FIELD_INPUT_CLASSES,
739
- CollectionSchemaView,
740
- formatSubject,
741
- DatastoreSyncReport,
742
- RecordFilterBuilder,
743
- RecordFormPanel,
744
- CollectionRecordsBrowser,
745
- DeleteDatastoreDialog,
746
- DatastoreDetailView,
747
- DatastoreIcon,
748
- } from "./datastore/index.js";
749
- export type {
750
- UseDatastoreReturn,
751
- UseDatastoreListOptions,
752
- UseDatastoreListReturn,
753
- UseDatastoreCountOptions,
754
- UseDatastoreCountReturn,
755
- UseDatastoreSearchOptions,
756
- UseDatastoreSearchReturn,
757
- UseDatastoreDescriptionReturn,
758
- RecordScope,
759
- UseRecordListParams,
760
- UseRecordListReturn,
761
- InsertRecordArgs,
762
- UseInsertRecordReturn,
763
- UpdateRecordArgs,
764
- UseUpdateRecordReturn,
765
- DeleteRecordArgs,
766
- UseDeleteRecordReturn,
767
- RecordColumnDef,
768
- UseRecordCollectionOptions,
769
- UseRecordCollectionReturn,
770
- DeleteDatastoreArgs,
771
- UseDeleteDatastoreReturn,
772
- CoerceResult,
773
- FilterableField,
774
- RecordConditionDraft,
775
- FieldValueControlProps,
776
- CollectionSchemaViewProps,
777
- DatastoreSyncReportProps,
778
- RecordFilterBuilderProps,
779
- RecordFormPanelProps,
780
- CollectionRecordsBrowserProps,
781
- DeleteDatastoreDialogProps,
782
- DatastoreDetailTab,
783
- DatastoreDetailViewProps,
784
- } from "./datastore/index.js";
785
-
786
704
  // Schedule — the disabled-vs-paused state derivation, the direct-query
787
705
  // list core + workbench adapter (schedules are not search-backed), data
788
706
  // hooks (get by reference, paginated list, count), behavior hooks