@elevasis/sdk 1.21.0 → 1.22.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 (160) hide show
  1. package/dist/cli.cjs +951 -171
  2. package/dist/index.d.ts +632 -341
  3. package/dist/index.js +3102 -142
  4. package/dist/node/index.d.ts +1 -0
  5. package/dist/node/index.js +19 -1
  6. package/dist/test-utils/index.d.ts +313 -4
  7. package/dist/test-utils/index.js +3246 -281
  8. package/dist/worker/index.js +3041 -80
  9. package/package.json +3 -3
  10. package/reference/claude-config/hooks/post-edit-validate.mjs +98 -98
  11. package/reference/claude-config/hooks/scaffold-registry-reminder.mjs +188 -188
  12. package/reference/claude-config/hooks/tool-failure-recovery.mjs +73 -73
  13. package/reference/claude-config/registries/graph-skills.json +4 -4
  14. package/reference/claude-config/registries/knowledge-flags.json +0 -2
  15. package/reference/claude-config/rules/active-change-index.md +80 -80
  16. package/reference/claude-config/rules/agent-start-here.md +277 -277
  17. package/reference/claude-config/rules/deployment.md +57 -57
  18. package/reference/claude-config/rules/error-handling.md +56 -56
  19. package/reference/claude-config/rules/execution.md +40 -40
  20. package/reference/claude-config/rules/frontend.md +4 -4
  21. package/reference/claude-config/rules/observability.md +31 -31
  22. package/reference/claude-config/rules/operations.md +29 -17
  23. package/reference/claude-config/rules/organization-model.md +110 -84
  24. package/reference/claude-config/rules/organization-os.md +115 -113
  25. package/reference/claude-config/rules/package-taxonomy.md +33 -33
  26. package/reference/claude-config/rules/platform.md +42 -42
  27. package/reference/claude-config/rules/shared-types.md +49 -46
  28. package/reference/claude-config/rules/task-tracking.md +47 -47
  29. package/reference/claude-config/rules/ui.md +200 -200
  30. package/reference/claude-config/rules/vibe.md +235 -235
  31. package/reference/claude-config/scripts/statusline-command.js +18 -18
  32. package/reference/claude-config/settings.json +34 -34
  33. package/reference/claude-config/skills/deploy/{SKILL.md → skill.md} +156 -156
  34. package/reference/claude-config/skills/dsp/SKILL.md +66 -66
  35. package/reference/claude-config/skills/elevasis/SKILL.md +235 -235
  36. package/reference/claude-config/skills/explore/SKILL.md +6 -6
  37. package/reference/claude-config/skills/git-sync/SKILL.md +126 -126
  38. package/reference/claude-config/skills/knowledge/SKILL.md +314 -299
  39. package/reference/claude-config/skills/knowledge/operations/codify-level-a.md +100 -100
  40. package/reference/claude-config/skills/knowledge/operations/codify-level-b.md +159 -159
  41. package/reference/claude-config/skills/knowledge/operations/customers.md +109 -109
  42. package/reference/claude-config/skills/knowledge/operations/features.md +76 -76
  43. package/reference/claude-config/skills/knowledge/operations/goals.md +118 -118
  44. package/reference/claude-config/skills/knowledge/operations/identity.md +93 -93
  45. package/reference/claude-config/skills/knowledge/operations/labels.md +94 -94
  46. package/reference/claude-config/skills/knowledge/operations/offerings.md +109 -109
  47. package/reference/claude-config/skills/knowledge/operations/roles.md +99 -99
  48. package/reference/claude-config/skills/knowledge/operations/techStack.md +30 -30
  49. package/reference/claude-config/skills/project/SKILL.md +1088 -1088
  50. package/reference/claude-config/skills/run-ui/SKILL.md +73 -73
  51. package/reference/claude-config/skills/save/SKILL.md +3 -3
  52. package/reference/claude-config/skills/setup/SKILL.md +275 -275
  53. package/reference/claude-config/skills/status/SKILL.md +59 -59
  54. package/reference/claude-config/skills/submit-request/SKILL.md +180 -180
  55. package/reference/claude-config/skills/sync/SKILL.md +47 -47
  56. package/reference/claude-config/skills/tutorial/SKILL.md +259 -259
  57. package/reference/claude-config/skills/tutorial/progress-template.md +74 -74
  58. package/reference/claude-config/skills/tutorial/technical.md +1303 -1303
  59. package/reference/claude-config/skills/tutorial/vibe-coder.md +890 -890
  60. package/reference/claude-config/sync-notes/2026-04-22-git-sync-and-sync-notes.md +27 -27
  61. package/reference/claude-config/sync-notes/2026-04-22-lead-gen-deliverability-removal.md +30 -30
  62. package/reference/claude-config/sync-notes/2026-04-24-test-utils-and-template-tests.md +73 -73
  63. package/reference/claude-config/sync-notes/2026-04-24-ui-consolidation-and-sdk-cli-train.md +86 -86
  64. package/reference/claude-config/sync-notes/2026-04-25-auth-role-system-and-settings-roles.md +55 -55
  65. package/reference/claude-config/sync-notes/2026-04-27-crm-hitl-action-layer-cutover.md +97 -97
  66. package/reference/claude-config/sync-notes/2026-04-27-lead-gen-substrate-train.md +112 -112
  67. package/reference/claude-config/sync-notes/2026-04-29-crm-state-and-lead-gen-processing-status.md +93 -93
  68. package/reference/claude-config/sync-notes/2026-05-02-crm-ownership-next-action.md +58 -58
  69. package/reference/claude-config/sync-notes/2026-05-02-template-hardcode-workos-config.md +56 -56
  70. package/reference/claude-config/sync-notes/2026-05-04-elevasis-workspace.md +71 -71
  71. package/reference/claude-config/sync-notes/2026-05-04-knowledge-bundle.md +83 -83
  72. package/reference/claude-config/sync-notes/2026-05-04-template-skills-run-ui-and-tutorial.md +59 -59
  73. package/reference/claude-config/sync-notes/2026-05-05-list-builder.md +42 -42
  74. package/reference/claude-config/sync-notes/2026-05-06-crm-spine.md +60 -60
  75. package/reference/claude-config/sync-notes/2026-05-06-sdk-changes-release-train.md +37 -37
  76. package/reference/claude-config/sync-notes/2026-05-07-sdk-changes-release-train.md +34 -34
  77. package/reference/claude-config/sync-notes/2026-05-08-resource-governance-scaffold-guidance.md +38 -38
  78. package/reference/claude-config/sync-notes/2026-05-09-clients-domain.md +32 -32
  79. package/reference/claude-config/sync-notes/2026-05-09-command-system.md +33 -33
  80. package/reference/claude-config/sync-notes/2026-05-09-resource-governance-and-misc.md +69 -69
  81. package/reference/claude-config/sync-notes/2026-05-12-sdk-ready-release-train.md +30 -30
  82. package/reference/claude-config/sync-notes/2026-05-14-organization-model-ontology-refactor.md +42 -0
  83. package/reference/claude-config/sync-notes/README.md +43 -43
  84. package/reference/cli.mdx +808 -808
  85. package/reference/concepts.mdx +146 -146
  86. package/reference/deployment/api.mdx +297 -297
  87. package/reference/deployment/command-center.mdx +209 -209
  88. package/reference/deployment/index.mdx +195 -195
  89. package/reference/deployment/provided-features.mdx +107 -107
  90. package/reference/deployment/ui-execution.mdx +250 -250
  91. package/reference/examples/organization-model.ts +146 -83
  92. package/reference/framework/agent.mdx +156 -156
  93. package/reference/framework/index.mdx +195 -195
  94. package/reference/framework/interaction-guidance.mdx +182 -182
  95. package/reference/framework/memory.mdx +326 -326
  96. package/reference/framework/project-structure.mdx +282 -282
  97. package/reference/framework/tutorial-system.mdx +135 -135
  98. package/reference/getting-started.mdx +142 -142
  99. package/reference/index.mdx +106 -106
  100. package/reference/packages/core/src/README.md +14 -14
  101. package/reference/packages/core/src/business/README.md +2 -2
  102. package/reference/packages/core/src/knowledge/README.md +32 -32
  103. package/reference/packages/core/src/organization-model/README.md +149 -149
  104. package/reference/packages/core/src/test-utils/README.md +37 -37
  105. package/reference/packages/ui/src/api/README.md +18 -18
  106. package/reference/packages/ui/src/app/README.md +24 -24
  107. package/reference/packages/ui/src/auth/README.md +18 -18
  108. package/reference/packages/ui/src/components/README.md +24 -24
  109. package/reference/packages/ui/src/execution/README.md +16 -16
  110. package/reference/packages/ui/src/features/README.md +28 -28
  111. package/reference/packages/ui/src/graph/README.md +16 -16
  112. package/reference/packages/ui/src/hooks/README.md +23 -23
  113. package/reference/packages/ui/src/initialization/README.md +19 -19
  114. package/reference/packages/ui/src/knowledge/README.md +31 -31
  115. package/reference/packages/ui/src/organization/README.md +18 -18
  116. package/reference/packages/ui/src/profile/README.md +19 -19
  117. package/reference/packages/ui/src/provider/README.md +32 -32
  118. package/reference/packages/ui/src/router/README.md +18 -18
  119. package/reference/packages/ui/src/sse/README.md +13 -13
  120. package/reference/packages/ui/src/test-utils/README.md +7 -7
  121. package/reference/packages/ui/src/theme/README.md +23 -23
  122. package/reference/packages/ui/src/theme/presets/README.md +19 -19
  123. package/reference/packages/ui/src/types/README.md +16 -16
  124. package/reference/packages/ui/src/utils/README.md +18 -18
  125. package/reference/packages/ui/src/zustand/README.md +18 -18
  126. package/reference/platform-tools/adapters-integration.mdx +301 -301
  127. package/reference/platform-tools/adapters-platform.mdx +553 -553
  128. package/reference/platform-tools/index.mdx +217 -217
  129. package/reference/platform-tools/type-safety.mdx +82 -82
  130. package/reference/resources/index.mdx +349 -349
  131. package/reference/resources/patterns.mdx +449 -449
  132. package/reference/resources/types.mdx +116 -116
  133. package/reference/roadmap.mdx +165 -165
  134. package/reference/runtime.mdx +173 -173
  135. package/reference/scaffold/core/organization-graph.mdx +110 -90
  136. package/reference/scaffold/core/organization-model.mdx +226 -219
  137. package/reference/scaffold/index.mdx +67 -67
  138. package/reference/scaffold/operations/propagation-pipeline.md +77 -77
  139. package/reference/scaffold/operations/scaffold-maintenance.md +12 -12
  140. package/reference/scaffold/operations/workflow-recipes.md +138 -138
  141. package/reference/scaffold/recipes/add-a-feature.md +308 -88
  142. package/reference/scaffold/recipes/add-a-resource.md +134 -110
  143. package/reference/scaffold/recipes/customize-knowledge-browser.md +5 -5
  144. package/reference/scaffold/recipes/customize-organization-model.md +273 -138
  145. package/reference/scaffold/recipes/extend-a-base-entity.md +8 -8
  146. package/reference/scaffold/recipes/extend-crm.md +3 -3
  147. package/reference/scaffold/recipes/extend-lead-gen.md +400 -400
  148. package/reference/scaffold/recipes/gate-by-feature-or-admin.md +118 -118
  149. package/reference/scaffold/recipes/index.md +46 -46
  150. package/reference/scaffold/recipes/query-the-knowledge-graph.md +197 -170
  151. package/reference/scaffold/reference/contracts.md +2101 -2096
  152. package/reference/scaffold/reference/glossary.md +76 -76
  153. package/reference/scaffold/ui/composition-extensibility.mdx +233 -233
  154. package/reference/scaffold/ui/customization.md +243 -243
  155. package/reference/scaffold/ui/feature-flags-and-gating.md +46 -46
  156. package/reference/scaffold/ui/feature-shell.mdx +72 -72
  157. package/reference/scaffold/ui/recipes.md +221 -214
  158. package/reference/spine/spine-primer.md +96 -96
  159. package/reference/templates/index.mdx +47 -47
  160. package/reference/troubleshooting.mdx +223 -223
@@ -1,250 +1,250 @@
1
- ---
2
- title: UI Execution
3
- description: Trigger workflow and agent executions from a custom React UI -- Run buttons, input forms, and result displays via @elevasis/ui
4
- loadWhen: "Building a custom UI that triggers resource executions (Run buttons, input forms)"
5
- ---
6
-
7
- `@elevasis/ui` ships a set of components and hooks that let your custom React pages trigger workflow and agent executions without wiring up API calls manually. This page is for template users building interactive resource pages in `external/_template` who want to add Run buttons, input forms, and execution result displays.
8
-
9
- The API comes in three tiers: a convenience one-tag component that handles everything, a controlled form primitive for custom modal chrome, and low-level hooks for fully custom rendering. Most template pages need only the first tier.
10
-
11
- ---
12
-
13
- ## Quick Start -- `ResourceExecuteDialog`
14
-
15
- `ResourceExecuteDialog` combines a modal shell, an input form, mutation state, and result display into a single component. Drop it next to a Button and you have a working Run dialog in about fifteen lines.
16
-
17
- ```tsx
18
- import { useState } from 'react'
19
- import { Button } from '@mantine/core'
20
- import { ResourceExecuteDialog } from '@elevasis/ui/features/operations'
21
- import { useNavigate } from '@tanstack/react-router'
22
-
23
- const resource = {
24
- resourceId: 'qualify-lead-workflow',
25
- resourceType: 'workflow' as const,
26
- name: 'Qualify Lead',
27
- formSchema: {
28
- fields: [
29
- { name: 'email', label: 'Lead email', type: 'text', required: true },
30
- { name: 'company', label: 'Company', type: 'text', required: false },
31
- ],
32
- },
33
- }
34
-
35
- export function QualifyLeadPage() {
36
- const [opened, setOpened] = useState(false)
37
- const navigate = useNavigate()
38
-
39
- return (
40
- <>
41
- <Button onClick={() => setOpened(true)}>Run</Button>
42
-
43
- <ResourceExecuteDialog
44
- opened={opened}
45
- onClose={() => setOpened(false)}
46
- resource={resource}
47
- onViewExecution={(executionId) =>
48
- navigate({ to: '/logs/$executionId', params: { executionId } })
49
- }
50
- />
51
- </>
52
- )
53
- }
54
- ```
55
-
56
- What the user sees when they click Run:
57
-
58
- - A modal opens titled "Run workflow" with the resource ID displayed.
59
- - The form renders one field per entry in `formSchema.fields`. Required fields show validation errors on submit.
60
- - On submit, a loading overlay appears while the POST is in flight.
61
- - On success, a teal confirmation card shows the execution ID. A "View execution" button calls `onViewExecution` with that ID.
62
- - On error, a red alert shows the error message with a "Try again" option.
63
-
64
- If `formSchema` is omitted or has no fields, the form skips to a single "Run" button with the message "This workflow takes no input."
65
-
66
- ---
67
-
68
- ## The Three-Tier API
69
-
70
- | Tier | Component / Hook | Use case |
71
- | --------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------- |
72
- | Convenience | `ResourceExecuteDialog` | One-tag Run button + modal + form. Parent only manages `opened` state. |
73
- | Controlled form | `ResourceExecuteForm` | Custom modal chrome; parent owns the mutation and decides where to show results. |
74
- | Low-level | `ExecuteWorkflowModal` + `useExecuteAsync` | Fully custom rendering, non-standard modal behavior, or composing execution into a larger flow. |
75
-
76
- Start with `ResourceExecuteDialog`. Move down the tiers only when you need something the convenience component cannot do.
77
-
78
- ---
79
-
80
- ## Controlled Usage with `ResourceExecuteForm`
81
-
82
- Use `ResourceExecuteForm` when you want to own the modal or display the result somewhere outside the dialog -- for example, rendering the execution ID inline on the page after submission.
83
-
84
- `ResourceExecuteForm` accepts `onSubmit` and `isPending` from the parent. The parent calls `useExecuteAsync()` directly and passes `mutateAsync` as the submit handler.
85
-
86
- ```tsx
87
- import { useState } from 'react'
88
- import { Modal, Button, Text } from '@mantine/core'
89
- import { ResourceExecuteForm } from '@elevasis/ui/features/operations'
90
- import { useExecuteAsync } from '@elevasis/ui/hooks'
91
-
92
- const formSchema = {
93
- fields: [
94
- { name: 'topic', label: 'Topic', type: 'text', required: true },
95
- ],
96
- }
97
-
98
- export function CustomRunPanel() {
99
- const [opened, setOpened] = useState(false)
100
- const mutation = useExecuteAsync()
101
-
102
- const handleSubmit = async (input: Record<string, unknown>) => {
103
- await mutation.mutateAsync({
104
- resourceId: 'research-agent',
105
- resourceType: 'agent',
106
- input,
107
- })
108
- }
109
-
110
- return (
111
- <>
112
- <Button onClick={() => setOpened(true)}>Run agent</Button>
113
-
114
- {mutation.data && (
115
- <Text size="sm">Started: {mutation.data.executionId}</Text>
116
- )}
117
-
118
- <Modal opened={opened} onClose={() => setOpened(false)} title="Run research agent">
119
- <ResourceExecuteForm
120
- formSchema={formSchema}
121
- onSubmit={handleSubmit}
122
- isPending={mutation.isPending}
123
- disabled={mutation.isPending}
124
- submitLabel="Start research"
125
- />
126
- </Modal>
127
- </>
128
- )
129
- }
130
- ```
131
-
132
- `ResourceExecuteForm` props:
133
-
134
- | Prop | Type | Default | Notes |
135
- | ------------- | ------------------------------------ | -------- | ------------------------------------ |
136
- | `formSchema` | `SerializedExecutionFormSchema` | required | Drives field rendering |
137
- | `onSubmit` | `(input) => void | Promise<void>` | required | Called with mapped field values |
138
- | `isPending` | `boolean` | `false` | Shows loading state on submit button |
139
- | `disabled` | `boolean` | `false` | Disables all fields and button |
140
- | `submitLabel` | `string` | `'Run'` | Button label when not pending |
141
-
142
- ---
143
-
144
- ## Low-Level: Hooks and `ExecuteWorkflowModal`
145
-
146
- For complete rendering control, use `useExecuteAsync` and `ExecuteWorkflowModal` independently. `ExecuteWorkflowModal` is a Mantine Modal pre-wired with a loading overlay, a success card (execution ID + "View execution" button), and an error alert. You pass `children` for the input area.
147
-
148
- ```tsx
149
- import { ExecuteWorkflowModal } from '@elevasis/ui/features/operations'
150
- import { useExecuteAsync } from '@elevasis/ui/hooks'
151
-
152
- const { mutateAsync, isPending, error, data, reset } = useExecuteAsync()
153
-
154
- <ExecuteWorkflowModal
155
- opened={opened}
156
- onClose={() => setOpened(false)}
157
- resource={{ resourceId: 'my-workflow', resourceType: 'workflow', name: 'My Workflow' }}
158
- isPending={isPending}
159
- error={error}
160
- result={data ?? null}
161
- onViewExecution={handleViewExecution}
162
- onReset={reset}
163
- >
164
- {/* your custom form or content here */}
165
- </ExecuteWorkflowModal>
166
- ```
167
-
168
- The modal locks close interactions (click-outside, Escape, close button) while `isPending` is true, preventing accidental dismissal mid-execution.
169
-
170
- Source: `packages/ui/src/features/operations/executions/ExecuteWorkflowModal.tsx`, `packages/ui/src/hooks/executions/useExecuteAsync.ts`
171
-
172
- ---
173
-
174
- ## Zod-Validated Execution with `useExecuteWorkflow`
175
-
176
- `useExecuteWorkflow` wraps `useExecuteAsync` with a Zod parse step before the POST. Use it when you are constructing input programmatically (not from a form) and want to catch schema mismatches before they reach the API.
177
-
178
- ```tsx
179
- import { z } from 'zod'
180
- import { useExecuteWorkflow } from '@elevasis/ui/hooks'
181
-
182
- const inputSchema = z.object({
183
- email: z.string().email(),
184
- score: z.number().min(0).max(100),
185
- })
186
-
187
- function useScoredExecution() {
188
- return useExecuteWorkflow({ schema: inputSchema })
189
- }
190
-
191
- // In a component:
192
- const { execute, isPending, data, error } = useScoredExecution()
193
-
194
- await execute({
195
- resourceId: 'score-lead-workflow',
196
- resourceType: 'workflow',
197
- input: { email: 'lead@example.com', score: 72 },
198
- })
199
- ```
200
-
201
- If `input` fails the Zod parse, `execute` throws synchronously with the message `"Invalid workflow input: ..."` before making any network request. The `mutation` object on the return value is the underlying `useExecuteAsync` mutation, giving you full TanStack Query state if needed.
202
-
203
- Prefer `useExecuteWorkflow` over raw `useExecuteAsync` when:
204
-
205
- - Input is assembled from multiple sources (not a single form submit).
206
- - You want TypeScript inference on the input shape via `z.infer`.
207
- - You want a clear validation error message rather than a 400 from the API.
208
-
209
- Source: `packages/ui/src/hooks/executions/useExecuteWorkflow.ts`
210
-
211
- ---
212
-
213
- ## Input Forms
214
-
215
- `ResourceExecuteDialog` and `ResourceExecuteForm` auto-render form fields from `formSchema.fields`. Each field is a `SerializedFormField` with at minimum `name`, `label`, and `type`.
216
-
217
- Supported field types:
218
-
219
- - `text` -- single-line text input
220
- - `textarea` -- multi-line text input
221
- - `number` -- numeric input
222
- - `select` -- dropdown with `options` array
223
- - `checkbox` -- boolean toggle; defaults to `false`
224
- - `radio` -- radio group with `options` array
225
- - `richtext` -- rich text editor
226
-
227
- Required fields (`required: true`) are validated on submit. Custom field-to-input-key remapping is supported via `formSchema.fieldMappings` -- a `Record<string, string>` that renames field values before they are passed to `onSubmit`.
228
-
229
- If `formSchema` is undefined, an empty object, or has `fields: []`, the form skips rendering fields entirely and shows "This workflow takes no input." with a single Run button.
230
-
231
- ---
232
-
233
- ## Error and Result Handling
234
-
235
- Mutation state flows automatically into the modal chrome when using `ResourceExecuteDialog` or `ExecuteWorkflowModal`:
236
-
237
- - **Success** -- a teal alert card displays the execution ID from `result.executionId`. If `onViewExecution` is provided, a "View execution" button calls it with the ID. This is the recommended way to deep-link to the Execution Logs page.
238
- - **Error** -- a red alert displays `error.message`. A "Try again" button calls `onReset`, which clears the mutation state and re-shows the form.
239
- - **Pending** -- a blur overlay covers the form area while the POST is in flight. The modal cannot be dismissed during this state.
240
-
241
- `useExecuteAsync` also invalidates the executions list query on success (keyed by `organizationId` + `resourceId`), so any `useExecutions` query on the page refreshes automatically.
242
-
243
- ---
244
-
245
- ## Related
246
-
247
- - [REST API](api.mdx) -- trigger executions directly over HTTP, without React
248
- - [Command Center](command-center.mdx) -- built-in managed UI; includes Run buttons for all deployed resources
249
- - [Resource Patterns](../resources/patterns.mdx) -- HITL approval patterns and `approval.create()`
250
- - [Platform Adapters](../platform-tools/adapters-platform.mdx) -- `approval.create()` reference
1
+ ---
2
+ title: UI Execution
3
+ description: Trigger workflow and agent executions from a custom React UI -- Run buttons, input forms, and result displays via @elevasis/ui
4
+ loadWhen: "Building a custom UI that triggers resource executions (Run buttons, input forms)"
5
+ ---
6
+
7
+ `@elevasis/ui` ships a set of components and hooks that let your custom React pages trigger workflow and agent executions without wiring up API calls manually. This page is for template users building interactive resource pages in `external/_template` who want to add Run buttons, input forms, and execution result displays.
8
+
9
+ The API comes in three tiers: a convenience one-tag component that handles everything, a controlled form primitive for custom modal chrome, and low-level hooks for fully custom rendering. Most template pages need only the first tier.
10
+
11
+ ---
12
+
13
+ ## Quick Start -- `ResourceExecuteDialog`
14
+
15
+ `ResourceExecuteDialog` combines a modal shell, an input form, mutation state, and result display into a single component. Drop it next to a Button and you have a working Run dialog in about fifteen lines.
16
+
17
+ ```tsx
18
+ import { useState } from 'react'
19
+ import { Button } from '@mantine/core'
20
+ import { ResourceExecuteDialog } from '@elevasis/ui/features/operations'
21
+ import { useNavigate } from '@tanstack/react-router'
22
+
23
+ const resource = {
24
+ resourceId: 'qualify-lead-workflow',
25
+ resourceType: 'workflow' as const,
26
+ name: 'Qualify Lead',
27
+ formSchema: {
28
+ fields: [
29
+ { name: 'email', label: 'Lead email', type: 'text', required: true },
30
+ { name: 'company', label: 'Company', type: 'text', required: false },
31
+ ],
32
+ },
33
+ }
34
+
35
+ export function QualifyLeadPage() {
36
+ const [opened, setOpened] = useState(false)
37
+ const navigate = useNavigate()
38
+
39
+ return (
40
+ <>
41
+ <Button onClick={() => setOpened(true)}>Run</Button>
42
+
43
+ <ResourceExecuteDialog
44
+ opened={opened}
45
+ onClose={() => setOpened(false)}
46
+ resource={resource}
47
+ onViewExecution={(executionId) =>
48
+ navigate({ to: '/logs/$executionId', params: { executionId } })
49
+ }
50
+ />
51
+ </>
52
+ )
53
+ }
54
+ ```
55
+
56
+ What the user sees when they click Run:
57
+
58
+ - A modal opens titled "Run workflow" with the resource ID displayed.
59
+ - The form renders one field per entry in `formSchema.fields`. Required fields show validation errors on submit.
60
+ - On submit, a loading overlay appears while the POST is in flight.
61
+ - On success, a teal confirmation card shows the execution ID. A "View execution" button calls `onViewExecution` with that ID.
62
+ - On error, a red alert shows the error message with a "Try again" option.
63
+
64
+ If `formSchema` is omitted or has no fields, the form skips to a single "Run" button with the message "This workflow takes no input."
65
+
66
+ ---
67
+
68
+ ## The Three-Tier API
69
+
70
+ | Tier | Component / Hook | Use case |
71
+ | --------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------- |
72
+ | Convenience | `ResourceExecuteDialog` | One-tag Run button + modal + form. Parent only manages `opened` state. |
73
+ | Controlled form | `ResourceExecuteForm` | Custom modal chrome; parent owns the mutation and decides where to show results. |
74
+ | Low-level | `ExecuteWorkflowModal` + `useExecuteAsync` | Fully custom rendering, non-standard modal behavior, or composing execution into a larger flow. |
75
+
76
+ Start with `ResourceExecuteDialog`. Move down the tiers only when you need something the convenience component cannot do.
77
+
78
+ ---
79
+
80
+ ## Controlled Usage with `ResourceExecuteForm`
81
+
82
+ Use `ResourceExecuteForm` when you want to own the modal or display the result somewhere outside the dialog -- for example, rendering the execution ID inline on the page after submission.
83
+
84
+ `ResourceExecuteForm` accepts `onSubmit` and `isPending` from the parent. The parent calls `useExecuteAsync()` directly and passes `mutateAsync` as the submit handler.
85
+
86
+ ```tsx
87
+ import { useState } from 'react'
88
+ import { Modal, Button, Text } from '@mantine/core'
89
+ import { ResourceExecuteForm } from '@elevasis/ui/features/operations'
90
+ import { useExecuteAsync } from '@elevasis/ui/hooks'
91
+
92
+ const formSchema = {
93
+ fields: [
94
+ { name: 'topic', label: 'Topic', type: 'text', required: true },
95
+ ],
96
+ }
97
+
98
+ export function CustomRunPanel() {
99
+ const [opened, setOpened] = useState(false)
100
+ const mutation = useExecuteAsync()
101
+
102
+ const handleSubmit = async (input: Record<string, unknown>) => {
103
+ await mutation.mutateAsync({
104
+ resourceId: 'research-agent',
105
+ resourceType: 'agent',
106
+ input,
107
+ })
108
+ }
109
+
110
+ return (
111
+ <>
112
+ <Button onClick={() => setOpened(true)}>Run agent</Button>
113
+
114
+ {mutation.data && (
115
+ <Text size="sm">Started: {mutation.data.executionId}</Text>
116
+ )}
117
+
118
+ <Modal opened={opened} onClose={() => setOpened(false)} title="Run research agent">
119
+ <ResourceExecuteForm
120
+ formSchema={formSchema}
121
+ onSubmit={handleSubmit}
122
+ isPending={mutation.isPending}
123
+ disabled={mutation.isPending}
124
+ submitLabel="Start research"
125
+ />
126
+ </Modal>
127
+ </>
128
+ )
129
+ }
130
+ ```
131
+
132
+ `ResourceExecuteForm` props:
133
+
134
+ | Prop | Type | Default | Notes |
135
+ | ------------- | ------------------------------------ | -------- | ------------------------------------ |
136
+ | `formSchema` | `SerializedExecutionFormSchema` | required | Drives field rendering |
137
+ | `onSubmit` | `(input) => void | Promise<void>` | required | Called with mapped field values |
138
+ | `isPending` | `boolean` | `false` | Shows loading state on submit button |
139
+ | `disabled` | `boolean` | `false` | Disables all fields and button |
140
+ | `submitLabel` | `string` | `'Run'` | Button label when not pending |
141
+
142
+ ---
143
+
144
+ ## Low-Level: Hooks and `ExecuteWorkflowModal`
145
+
146
+ For complete rendering control, use `useExecuteAsync` and `ExecuteWorkflowModal` independently. `ExecuteWorkflowModal` is a Mantine Modal pre-wired with a loading overlay, a success card (execution ID + "View execution" button), and an error alert. You pass `children` for the input area.
147
+
148
+ ```tsx
149
+ import { ExecuteWorkflowModal } from '@elevasis/ui/features/operations'
150
+ import { useExecuteAsync } from '@elevasis/ui/hooks'
151
+
152
+ const { mutateAsync, isPending, error, data, reset } = useExecuteAsync()
153
+
154
+ <ExecuteWorkflowModal
155
+ opened={opened}
156
+ onClose={() => setOpened(false)}
157
+ resource={{ resourceId: 'my-workflow', resourceType: 'workflow', name: 'My Workflow' }}
158
+ isPending={isPending}
159
+ error={error}
160
+ result={data ?? null}
161
+ onViewExecution={handleViewExecution}
162
+ onReset={reset}
163
+ >
164
+ {/* your custom form or content here */}
165
+ </ExecuteWorkflowModal>
166
+ ```
167
+
168
+ The modal locks close interactions (click-outside, Escape, close button) while `isPending` is true, preventing accidental dismissal mid-execution.
169
+
170
+ Source: `packages/ui/src/features/operations/executions/ExecuteWorkflowModal.tsx`, `packages/ui/src/hooks/executions/useExecuteAsync.ts`
171
+
172
+ ---
173
+
174
+ ## Zod-Validated Execution with `useExecuteWorkflow`
175
+
176
+ `useExecuteWorkflow` wraps `useExecuteAsync` with a Zod parse step before the POST. Use it when you are constructing input programmatically (not from a form) and want to catch schema mismatches before they reach the API.
177
+
178
+ ```tsx
179
+ import { z } from 'zod'
180
+ import { useExecuteWorkflow } from '@elevasis/ui/hooks'
181
+
182
+ const inputSchema = z.object({
183
+ email: z.string().email(),
184
+ score: z.number().min(0).max(100),
185
+ })
186
+
187
+ function useScoredExecution() {
188
+ return useExecuteWorkflow({ schema: inputSchema })
189
+ }
190
+
191
+ // In a component:
192
+ const { execute, isPending, data, error } = useScoredExecution()
193
+
194
+ await execute({
195
+ resourceId: 'score-lead-workflow',
196
+ resourceType: 'workflow',
197
+ input: { email: 'lead@example.com', score: 72 },
198
+ })
199
+ ```
200
+
201
+ If `input` fails the Zod parse, `execute` throws synchronously with the message `"Invalid workflow input: ..."` before making any network request. The `mutation` object on the return value is the underlying `useExecuteAsync` mutation, giving you full TanStack Query state if needed.
202
+
203
+ Prefer `useExecuteWorkflow` over raw `useExecuteAsync` when:
204
+
205
+ - Input is assembled from multiple sources (not a single form submit).
206
+ - You want TypeScript inference on the input shape via `z.infer`.
207
+ - You want a clear validation error message rather than a 400 from the API.
208
+
209
+ Source: `packages/ui/src/hooks/executions/useExecuteWorkflow.ts`
210
+
211
+ ---
212
+
213
+ ## Input Forms
214
+
215
+ `ResourceExecuteDialog` and `ResourceExecuteForm` auto-render form fields from `formSchema.fields`. Each field is a `SerializedFormField` with at minimum `name`, `label`, and `type`.
216
+
217
+ Supported field types:
218
+
219
+ - `text` -- single-line text input
220
+ - `textarea` -- multi-line text input
221
+ - `number` -- numeric input
222
+ - `select` -- dropdown with `options` array
223
+ - `checkbox` -- boolean toggle; defaults to `false`
224
+ - `radio` -- radio group with `options` array
225
+ - `richtext` -- rich text editor
226
+
227
+ Required fields (`required: true`) are validated on submit. Custom field-to-input-key remapping is supported via `formSchema.fieldMappings` -- a `Record<string, string>` that renames field values before they are passed to `onSubmit`.
228
+
229
+ If `formSchema` is undefined, an empty object, or has `fields: []`, the form skips rendering fields entirely and shows "This workflow takes no input." with a single Run button.
230
+
231
+ ---
232
+
233
+ ## Error and Result Handling
234
+
235
+ Mutation state flows automatically into the modal chrome when using `ResourceExecuteDialog` or `ExecuteWorkflowModal`:
236
+
237
+ - **Success** -- a teal alert card displays the execution ID from `result.executionId`. If `onViewExecution` is provided, a "View execution" button calls it with the ID. This is the recommended way to deep-link to the Execution Logs page.
238
+ - **Error** -- a red alert displays `error.message`. A "Try again" button calls `onReset`, which clears the mutation state and re-shows the form.
239
+ - **Pending** -- a blur overlay covers the form area while the POST is in flight. The modal cannot be dismissed during this state.
240
+
241
+ `useExecuteAsync` also invalidates the executions list query on success (keyed by `organizationId` + `resourceId`), so any `useExecutions` query on the page refreshes automatically.
242
+
243
+ ---
244
+
245
+ ## Related
246
+
247
+ - [REST API](api.mdx) -- trigger executions directly over HTTP, without React
248
+ - [Command Center](command-center.mdx) -- built-in managed UI; includes Run buttons for all deployed resources
249
+ - [Resource Patterns](../resources/patterns.mdx) -- HITL approval patterns and `approval.create()`
250
+ - [Platform Adapters](../platform-tools/adapters-platform.mdx) -- `approval.create()` reference