@elevasis/sdk 1.21.0 → 1.22.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.
- package/dist/cli.cjs +1239 -173
- package/dist/index.d.ts +1752 -464
- package/dist/index.js +3477 -143
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +19 -1
- package/dist/test-utils/index.d.ts +1188 -127
- package/dist/test-utils/index.js +3359 -152
- package/dist/worker/index.js +3148 -80
- package/package.json +2 -2
- package/reference/claude-config/hooks/post-edit-validate.mjs +98 -98
- package/reference/claude-config/hooks/scaffold-registry-reminder.mjs +188 -188
- package/reference/claude-config/hooks/tool-failure-recovery.mjs +73 -73
- package/reference/claude-config/registries/graph-skills.json +4 -4
- package/reference/claude-config/registries/knowledge-flags.json +0 -2
- package/reference/claude-config/rules/active-change-index.md +80 -80
- package/reference/claude-config/rules/agent-start-here.md +277 -277
- package/reference/claude-config/rules/deployment.md +57 -57
- package/reference/claude-config/rules/error-handling.md +56 -56
- package/reference/claude-config/rules/execution.md +40 -40
- package/reference/claude-config/rules/frontend.md +4 -4
- package/reference/claude-config/rules/observability.md +31 -31
- package/reference/claude-config/rules/operations.md +29 -17
- package/reference/claude-config/rules/organization-model.md +113 -81
- package/reference/claude-config/rules/organization-os.md +115 -113
- package/reference/claude-config/rules/package-taxonomy.md +33 -33
- package/reference/claude-config/rules/platform.md +42 -42
- package/reference/claude-config/rules/shared-types.md +49 -46
- package/reference/claude-config/rules/task-tracking.md +47 -47
- package/reference/claude-config/rules/ui.md +200 -200
- package/reference/claude-config/rules/vibe.md +235 -235
- package/reference/claude-config/scripts/statusline-command.js +18 -18
- package/reference/claude-config/settings.json +34 -34
- package/reference/claude-config/skills/deploy/{SKILL.md → skill.md} +156 -156
- package/reference/claude-config/skills/dsp/SKILL.md +66 -66
- package/reference/claude-config/skills/elevasis/SKILL.md +235 -235
- package/reference/claude-config/skills/explore/SKILL.md +6 -6
- package/reference/claude-config/skills/git-sync/SKILL.md +126 -126
- package/reference/claude-config/skills/knowledge/SKILL.md +314 -299
- package/reference/claude-config/skills/knowledge/operations/codify-level-a.md +100 -100
- package/reference/claude-config/skills/knowledge/operations/codify-level-b.md +159 -159
- package/reference/claude-config/skills/knowledge/operations/customers.md +109 -109
- package/reference/claude-config/skills/knowledge/operations/features.md +76 -76
- package/reference/claude-config/skills/knowledge/operations/goals.md +118 -118
- package/reference/claude-config/skills/knowledge/operations/identity.md +93 -93
- package/reference/claude-config/skills/knowledge/operations/labels.md +94 -94
- package/reference/claude-config/skills/knowledge/operations/offerings.md +109 -109
- package/reference/claude-config/skills/knowledge/operations/roles.md +99 -99
- package/reference/claude-config/skills/knowledge/operations/techStack.md +30 -30
- package/reference/claude-config/skills/project/SKILL.md +1088 -1088
- package/reference/claude-config/skills/run-ui/SKILL.md +73 -73
- package/reference/claude-config/skills/save/SKILL.md +3 -3
- package/reference/claude-config/skills/setup/SKILL.md +275 -275
- package/reference/claude-config/skills/status/SKILL.md +59 -59
- package/reference/claude-config/skills/submit-request/SKILL.md +180 -180
- package/reference/claude-config/skills/sync/SKILL.md +47 -47
- package/reference/claude-config/skills/tutorial/SKILL.md +259 -259
- package/reference/claude-config/skills/tutorial/progress-template.md +74 -74
- package/reference/claude-config/skills/tutorial/technical.md +1303 -1303
- package/reference/claude-config/skills/tutorial/vibe-coder.md +890 -890
- package/reference/claude-config/sync-notes/2026-04-22-git-sync-and-sync-notes.md +27 -27
- package/reference/claude-config/sync-notes/2026-04-22-lead-gen-deliverability-removal.md +30 -30
- package/reference/claude-config/sync-notes/2026-04-24-test-utils-and-template-tests.md +73 -73
- package/reference/claude-config/sync-notes/2026-04-24-ui-consolidation-and-sdk-cli-train.md +86 -86
- package/reference/claude-config/sync-notes/2026-04-25-auth-role-system-and-settings-roles.md +55 -55
- package/reference/claude-config/sync-notes/2026-04-27-crm-hitl-action-layer-cutover.md +97 -97
- package/reference/claude-config/sync-notes/2026-04-27-lead-gen-substrate-train.md +112 -112
- package/reference/claude-config/sync-notes/2026-04-29-crm-state-and-lead-gen-processing-status.md +93 -93
- package/reference/claude-config/sync-notes/2026-05-02-crm-ownership-next-action.md +58 -58
- package/reference/claude-config/sync-notes/2026-05-02-template-hardcode-workos-config.md +56 -56
- package/reference/claude-config/sync-notes/2026-05-04-elevasis-workspace.md +71 -71
- package/reference/claude-config/sync-notes/2026-05-04-knowledge-bundle.md +83 -83
- package/reference/claude-config/sync-notes/2026-05-04-template-skills-run-ui-and-tutorial.md +59 -59
- package/reference/claude-config/sync-notes/2026-05-05-list-builder.md +42 -42
- package/reference/claude-config/sync-notes/2026-05-06-crm-spine.md +60 -60
- package/reference/claude-config/sync-notes/2026-05-06-sdk-changes-release-train.md +37 -37
- package/reference/claude-config/sync-notes/2026-05-07-sdk-changes-release-train.md +34 -34
- package/reference/claude-config/sync-notes/2026-05-08-resource-governance-scaffold-guidance.md +38 -38
- package/reference/claude-config/sync-notes/2026-05-09-clients-domain.md +32 -32
- package/reference/claude-config/sync-notes/2026-05-09-command-system.md +33 -33
- package/reference/claude-config/sync-notes/2026-05-09-resource-governance-and-misc.md +69 -69
- package/reference/claude-config/sync-notes/2026-05-12-sdk-ready-release-train.md +30 -30
- package/reference/claude-config/sync-notes/2026-05-14-organization-model-ontology-refactor.md +45 -0
- package/reference/claude-config/sync-notes/README.md +43 -43
- package/reference/cli.mdx +808 -808
- package/reference/concepts.mdx +146 -146
- package/reference/deployment/api.mdx +297 -297
- package/reference/deployment/command-center.mdx +209 -209
- package/reference/deployment/index.mdx +195 -195
- package/reference/deployment/provided-features.mdx +107 -107
- package/reference/deployment/ui-execution.mdx +250 -250
- package/reference/examples/organization-model.ts +171 -84
- package/reference/framework/agent.mdx +156 -156
- package/reference/framework/index.mdx +195 -195
- package/reference/framework/interaction-guidance.mdx +182 -182
- package/reference/framework/memory.mdx +326 -326
- package/reference/framework/project-structure.mdx +282 -282
- package/reference/framework/tutorial-system.mdx +135 -135
- package/reference/getting-started.mdx +142 -142
- package/reference/index.mdx +106 -106
- package/reference/packages/core/src/README.md +14 -14
- package/reference/packages/core/src/business/README.md +2 -2
- package/reference/packages/core/src/knowledge/README.md +32 -32
- package/reference/packages/core/src/organization-model/README.md +149 -149
- package/reference/packages/core/src/test-utils/README.md +37 -37
- package/reference/packages/ui/src/api/README.md +18 -18
- package/reference/packages/ui/src/app/README.md +24 -24
- package/reference/packages/ui/src/auth/README.md +18 -18
- package/reference/packages/ui/src/components/README.md +24 -24
- package/reference/packages/ui/src/execution/README.md +16 -16
- package/reference/packages/ui/src/features/README.md +28 -28
- package/reference/packages/ui/src/graph/README.md +16 -16
- package/reference/packages/ui/src/hooks/README.md +23 -23
- package/reference/packages/ui/src/initialization/README.md +19 -19
- package/reference/packages/ui/src/knowledge/README.md +31 -31
- package/reference/packages/ui/src/organization/README.md +18 -18
- package/reference/packages/ui/src/profile/README.md +19 -19
- package/reference/packages/ui/src/provider/README.md +32 -32
- package/reference/packages/ui/src/router/README.md +18 -18
- package/reference/packages/ui/src/sse/README.md +13 -13
- package/reference/packages/ui/src/test-utils/README.md +7 -7
- package/reference/packages/ui/src/theme/README.md +23 -23
- package/reference/packages/ui/src/theme/presets/README.md +19 -19
- package/reference/packages/ui/src/types/README.md +16 -16
- package/reference/packages/ui/src/utils/README.md +18 -18
- package/reference/packages/ui/src/zustand/README.md +18 -18
- package/reference/platform-tools/adapters-integration.mdx +301 -301
- package/reference/platform-tools/adapters-platform.mdx +553 -553
- package/reference/platform-tools/index.mdx +217 -217
- package/reference/platform-tools/type-safety.mdx +82 -82
- package/reference/resources/index.mdx +349 -349
- package/reference/resources/patterns.mdx +449 -449
- package/reference/resources/types.mdx +116 -116
- package/reference/roadmap.mdx +165 -165
- package/reference/runtime.mdx +173 -173
- package/reference/scaffold/core/organization-graph.mdx +110 -90
- package/reference/scaffold/core/organization-model.mdx +225 -213
- package/reference/scaffold/index.mdx +67 -67
- package/reference/scaffold/operations/propagation-pipeline.md +77 -77
- package/reference/scaffold/operations/scaffold-maintenance.md +12 -12
- package/reference/scaffold/operations/workflow-recipes.md +138 -138
- package/reference/scaffold/recipes/add-a-feature.md +307 -85
- package/reference/scaffold/recipes/add-a-resource.md +137 -103
- package/reference/scaffold/recipes/customize-knowledge-browser.md +5 -5
- package/reference/scaffold/recipes/customize-organization-model.md +275 -138
- package/reference/scaffold/recipes/extend-a-base-entity.md +8 -8
- package/reference/scaffold/recipes/extend-crm.md +3 -3
- package/reference/scaffold/recipes/extend-lead-gen.md +394 -394
- package/reference/scaffold/recipes/gate-by-feature-or-admin.md +118 -118
- package/reference/scaffold/recipes/index.md +46 -46
- package/reference/scaffold/recipes/query-the-knowledge-graph.md +197 -170
- package/reference/scaffold/reference/contracts.md +2136 -2093
- package/reference/scaffold/reference/glossary.md +76 -76
- package/reference/scaffold/ui/composition-extensibility.mdx +233 -233
- package/reference/scaffold/ui/customization.md +243 -243
- package/reference/scaffold/ui/feature-flags-and-gating.md +46 -46
- package/reference/scaffold/ui/feature-shell.mdx +72 -72
- package/reference/scaffold/ui/recipes.md +221 -214
- package/reference/spine/spine-primer.md +96 -96
- package/reference/templates/index.mdx +47 -47
- 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
|