@mydatavalue/polter 0.1.0 → 0.1.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/README.md CHANGED
@@ -6,15 +6,17 @@
6
6
 
7
7
  <p align="center">Declarative React library for agent-driven UI control with visual guided execution.</p>
8
8
 
9
- The agent drives the **real UI** it opens the actual dropdown, clicks the actual button, with the user watching. "Let me show you how" instead of "I did it for you." After seeing it twice, users do it themselves.
9
+ Your UI *is* the agent's interface. It opens the actual dropdown, clicks the actual button, with the user watching. No separate tools to build single source of truth. After seeing it twice, users do it themselves.
10
10
 
11
11
  ## Why
12
12
 
13
- Every SaaS adding an AI agent faces the same problem: the agent does things programmatically but the user never learns where buttons are or how the UI works. They become dependent on the agent.
13
+ Every SaaS adding an AI agent faces two problems:
14
14
 
15
- The alternative agents generating UI at runtimeis worse. Generated UI is unpredictable and breaks muscle memory.
15
+ 1. **Double the work.** You build your UI, then build a whole separate set of agent tools API endpoints, handlers, schemas all duplicating what the UI already does.
16
16
 
17
- **The right pattern**: the agent drives the real UI. It scrolls to the button, spotlights it, pauses so the user sees it, then clicks it. The user watches and learns. Nothing else does this.
17
+ 2. **Users never learn.** The agent does things behind the scenes or generates throwaway UI. Either way, users never see where buttons are or how the interface works. Permanent dependency.
18
+
19
+ **Polter solves both.** Your UI *is* the agent's interface — single source of truth. The agent scrolls to the real button, spotlights it, clicks it. Users watch and learn. After twice, they do it themselves. And you wrote zero agent-specific tools.
18
20
 
19
21
  ## Install
20
22
 
@@ -104,6 +106,76 @@ const handleCommand = useAgentCommandRouter(existingHandler, (cmd) => cmd.action
104
106
  4. `<div style="display: contents">` wrapper provides DOM refs without affecting layout
105
107
  5. Components that mount = actions that exist. Navigate away = actions disappear. No manual sync.
106
108
 
109
+ ## Advanced: `defineAction()` + Registry
110
+
111
+ For multi-page apps, `<AgentAction>` schemas are only available when the component is mounted. If the user says "update the price on property 123" but that page isn't open, the agent can't see the action.
112
+
113
+ `defineAction()` solves this — schemas are available at import time, before any component mounts. Combined with the `registry` prop, the agent gets full knowledge of every action upfront (single LLM roundtrip).
114
+
115
+ ### 1. Define actions (co-located with your feature)
116
+
117
+ ```tsx
118
+ // features/pricing/actions.ts
119
+ import { defineAction } from 'polter';
120
+ import { z } from 'zod';
121
+
122
+ export const updatePrice = defineAction({
123
+ name: 'update_price',
124
+ description: 'Update price markup on a property',
125
+ parameters: z.object({
126
+ property_id: z.string(),
127
+ markup: z.number(),
128
+ }),
129
+ route: (p) => `/properties/${p.property_id}/pricing`,
130
+ });
131
+ ```
132
+
133
+ ### 2. Create a registry (barrel file)
134
+
135
+ ```tsx
136
+ // registry.ts
137
+ import { updatePrice } from './features/pricing/actions';
138
+ import { exportCsv } from './features/reports/actions';
139
+
140
+ export const agentRegistry = [updatePrice, exportCsv];
141
+ ```
142
+
143
+ ### 3. Pass to provider with your router
144
+
145
+ ```tsx
146
+ import { agentRegistry } from './registry';
147
+
148
+ <AgentActionProvider
149
+ registry={agentRegistry}
150
+ navigate={(path) => router.push(path)}
151
+ >
152
+ <App />
153
+ </AgentActionProvider>
154
+ ```
155
+
156
+ ### 4. Components reference the definition
157
+
158
+ ```tsx
159
+ // features/pricing/PricingPage.tsx
160
+ import { updatePrice } from './actions';
161
+
162
+ <AgentAction action={updatePrice} onExecute={(p) => setMarkup(p.markup)}>
163
+ <SaveButton />
164
+ </AgentAction>
165
+ ```
166
+
167
+ ### How it works
168
+
169
+ 1. On mount, the provider registers all registry actions as schema-only entries — the agent sees them immediately
170
+ 2. When the agent calls `execute('update_price', { property_id: '123', markup: 15 })`:
171
+ - Provider calculates the route: `/properties/123/pricing`
172
+ - Calls your `navigate()` function
173
+ - Waits for the `<AgentAction>` component to mount on the new page
174
+ - Runs the visual execution (spotlight, click, etc.)
175
+ 3. When the component unmounts (user navigates away), the action reverts to schema-only — never disappears from the agent's view
176
+
177
+ If an action has no corresponding UI element anywhere in the app, you can provide `onExecute` directly on the definition as an escape hatch — it will execute without navigation or spotlight.
178
+
107
179
  ## API
108
180
 
109
181
  ### Execution modes
@@ -124,6 +196,8 @@ const handleCommand = useAgentCommandRouter(existingHandler, (cmd) => cmd.action
124
196
  | `tooltipEnabled` | `boolean` | `true` |
125
197
  | `onExecutionStart` | `(name: string) => void` | — |
126
198
  | `onExecutionComplete` | `(result: ExecutionResult) => void` | — |
199
+ | `registry` | `ActionDefinition[]` | — |
200
+ | `navigate` | `(path: string) => void \| Promise<void>` | — |
127
201
 
128
202
  ### Disabled actions
129
203
 
@@ -152,174 +226,7 @@ All overlay elements have class names:
152
226
 
153
227
  ## Best practices
154
228
 
155
- ### Use `<AgentAction>` when wrapping a visible element
156
-
157
- The component pattern is for actions that have a single, visible UI element to spotlight:
158
-
159
- ```tsx
160
- // Good — wraps the actual button
161
- <AgentAction name="push_changes" description="Push pending changes">
162
- <PushButton />
163
- </AgentAction>
164
-
165
- // Bad — wraps nothing visible, renders a pointless display:contents div
166
- <AgentAction name="sync_data" description="Sync data"
167
- onExecute={handleSync} />
168
- ```
169
-
170
- ### Wrap conditionally rendered elements with `<AgentAction>` on the outside
171
-
172
- `<AgentAction>` always registers the action regardless of whether its children are rendered. Keep the wrapper always-rendered and put the condition inside — `onExecute` works even when there's nothing visible to spotlight:
173
-
174
- ```tsx
175
- // Bad — conditionally rendering the AgentAction itself, action disappears when button is hidden
176
- {selectedIds.size > 0 && (
177
- <AgentAction name="grant_access" description="Grant access" onExecute={() => handleGrant()}>
178
- <Button onClick={handleGrant}>Grant Access ({selectedIds.size})</Button>
179
- </AgentAction>
180
- )}
181
-
182
- // Good — AgentAction always registered, button conditionally rendered inside
183
- <AgentAction name="grant_access" description="Grant access" onExecute={() => handleGrant()}>
184
- {selectedIds.size > 0 && (
185
- <Button onClick={handleGrant}>Grant Access ({selectedIds.size})</Button>
186
- )}
187
- </AgentAction>
188
- ```
189
-
190
- ### Use `useAgentAction` hook for per-row and programmatic actions
191
-
192
- When N rows each have their own button (sync, edit, navigate), you can't wrap each with `<AgentAction>` — same name would register N times, each overwriting the last. Use the hook + `<AgentTarget>` on each row's element:
193
-
194
- ```tsx
195
- // Hook registers the action once
196
- useAgentAction({
197
- name: 'sync_property',
198
- description: 'Sync a property',
199
- parameters: z.object({ property_id: z.number() }),
200
- onExecute: (p) => handleSync(p.property_id),
201
- steps: [{ label: 'Click Sync', fromParam: 'property_id' }],
202
- });
203
-
204
- // AgentTarget on each row's button (in a column renderer)
205
- <AgentTarget action="sync_property" param="property_id" value={String(propertyId)}>
206
- <SyncButton />
207
- </AgentTarget>
208
- ```
209
-
210
- The hook also accepts an array to batch-register multiple actions in one call:
211
-
212
- ```tsx
213
- useAgentAction([
214
- { name: 'navigate_to_property', ... },
215
- { name: 'sync_property', ... },
216
- { name: 'edit_markup', ... },
217
- ]);
218
- ```
219
-
220
- ### Never nest `AgentTarget` inside Radix `asChild` components
221
-
222
- Radix primitives (`PopoverTrigger`, `DialogTrigger`, `TooltipTrigger`) with `asChild` need their direct child to forward refs. `AgentTarget` inserts a `<div style="display:contents">` wrapper that breaks this:
223
-
224
- ```tsx
225
- // Bad — breaks ref forwarding, trigger won't work
226
- <PopoverTrigger asChild>
227
- <AgentTarget name="my-btn">
228
- <Button>Open</Button>
229
- </AgentTarget>
230
- </PopoverTrigger>
231
-
232
- // Good — wrap outside the Popover entirely
233
- <AgentTarget name="my-btn">
234
- <Popover>
235
- <PopoverTrigger asChild>
236
- <Button>Open</Button>
237
- </PopoverTrigger>
238
- <PopoverContent>...</PopoverContent>
239
- </Popover>
240
- </AgentTarget>
241
- ```
242
-
243
- Since `Popover.Root` renders no DOM element, `AgentTarget`'s `firstElementChild` resolves to the Button directly.
244
-
245
- ### Use shared targets for elements used by multiple actions
246
-
247
- When two actions need the same trigger (e.g. both open the same overflow menu), omit the `action` prop to make a shared target:
248
-
249
- ```tsx
250
- // Shared target — any action can resolve it by name
251
- <AgentTarget name="overflow-menu-btn">
252
- <OverflowMenuPopover>
253
- <AgentTarget name="export-btn">
254
- <ExportButton />
255
- </AgentTarget>
256
- <AgentTarget name="freeze-btn">
257
- <FreezeButton />
258
- </AgentTarget>
259
- </OverflowMenuPopover>
260
- </AgentTarget>
261
-
262
- // Both actions find the same trigger
263
- useAgentAction([
264
- { name: 'export_csv', steps: [
265
- { label: 'Open menu', fromTarget: 'overflow-menu-btn' },
266
- { label: 'Click Export', fromTarget: 'export-btn' },
267
- ]},
268
- { name: 'toggle_freeze', steps: [
269
- { label: 'Open menu', fromTarget: 'overflow-menu-btn' },
270
- { label: 'Click Freeze', fromTarget: 'freeze-btn' },
271
- ]},
272
- ]);
273
- ```
274
-
275
- ### Multi-step is required for dropdowns
276
-
277
- With `onExecute`, the executor skips clicking the last step (to avoid double-firing). If your action has only one step, the click never happens — the dropdown won't open:
278
-
279
- ```tsx
280
- // Bad — single step with onExecute, dropdown never opens
281
- <AgentAction name="filter" onExecute={handleFilter}>
282
- <Select>...</Select>
283
- </AgentAction>
284
-
285
- // Good — two steps: click to open, then select option
286
- <AgentAction name="filter" onExecute={handleFilter}>
287
- <AgentStep label="Open filter">
288
- <Select>
289
- <SelectTrigger>...</SelectTrigger>
290
- <SelectContent>
291
- <AgentTarget action="filter" param="status" value="active">
292
- <SelectItem value="active">Active</SelectItem>
293
- </AgentTarget>
294
- </SelectContent>
295
- </Select>
296
- </AgentStep>
297
- <AgentStep label="Select option" fromParam="status" />
298
- </AgentAction>
299
- ```
300
-
301
- ### Don't deeply nest `<AgentAction>` wrappers
302
-
303
- Each `<AgentAction>` renders a `<div style="display:contents">`. Nesting them creates a chain of `display:contents` divs. `getBoundingClientRect()` on these returns all zeros, causing spotlights to appear at (0,0):
304
-
305
- ```tsx
306
- // Bad — nested wrappers, inner actions resolve to display:contents divs
307
- <AgentAction name="action_a">
308
- <AgentAction name="action_b">
309
- <AgentAction name="action_c">
310
- <ActualContent />
311
- </AgentAction>
312
- </AgentAction>
313
- </AgentAction>
314
-
315
- // Good — flat siblings, each wrapping its own element (or use the hook)
316
- <AgentAction name="action_a">
317
- <ButtonA />
318
- </AgentAction>
319
- <AgentAction name="action_b">
320
- <ButtonB />
321
- </AgentAction>
322
- ```
229
+ See [docs/best-practices.md](docs/best-practices.md) for patterns around conditional rendering, per-row actions, Radix integration, dropdowns, and common pitfalls.
323
230
 
324
231
  ## Zero dependencies
325
232
 
package/dist/index.d.mts CHANGED
@@ -1,6 +1,52 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
3
 
4
+ /**
5
+ * Define an action at import time so its schema is available before the component mounts.
6
+ * Pass defined actions to `<AgentActionProvider registry={[...]}>` for single-roundtrip execution.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * export const updatePrice = defineAction({
11
+ * name: 'update_price',
12
+ * description: 'Update price markup on a property',
13
+ * parameters: z.object({ property_id: z.string(), markup: z.number() }),
14
+ * route: (p) => `/properties/${p.property_id}/pricing`,
15
+ * });
16
+ * ```
17
+ */
18
+ interface ActionDefinition<TParams = Record<string, unknown>> {
19
+ readonly name: string;
20
+ readonly description: string;
21
+ /** Zod schema for action parameters. */
22
+ readonly parameters?: unknown;
23
+ /** Client-side route to navigate to before executing. */
24
+ readonly route?: (params: TParams) => string;
25
+ /** Handler for background execution (no UI component needed). */
26
+ readonly onExecute?: (params: TParams) => void | Promise<void>;
27
+ /**
28
+ * Chain of action names to execute sequentially before this action.
29
+ * Each action in the chain is visually executed (spotlight → click), and the next
30
+ * action is waited on to mount before proceeding. This lets the user see the full
31
+ * navigation path instead of being teleported directly to a route.
32
+ */
33
+ readonly navigateVia?: string[];
34
+ /**
35
+ * How long (ms) to wait for this action's component to mount after navigation.
36
+ * Defaults to 5000ms. Set higher for pages that load slowly
37
+ */
38
+ readonly mountTimeout?: number;
39
+ }
40
+ declare function defineAction<TParams = Record<string, unknown>>(config: {
41
+ name: string;
42
+ description: string;
43
+ parameters?: unknown;
44
+ route?: (params: TParams) => string;
45
+ onExecute?: (params: TParams) => void | Promise<void>;
46
+ navigateVia?: string[];
47
+ mountTimeout?: number;
48
+ }): ActionDefinition<TParams>;
49
+
4
50
  type ExecutionMode = 'guided' | 'instant';
5
51
  interface ExecutionTarget {
6
52
  label: string;
@@ -36,6 +82,12 @@ interface RegisteredAction {
36
82
  disabled: boolean;
37
83
  disabledReason?: string;
38
84
  getExecutionTargets: () => ExecutionTarget[];
85
+ /** Client-side route for navigation before execution (from defineAction). */
86
+ route?: (params: Record<string, unknown>) => string;
87
+ /** Chain of action names to execute sequentially before this action (from defineAction). */
88
+ navigateVia?: string[];
89
+ /** How long (ms) to wait for this action's component to mount after navigation. */
90
+ mountTimeout?: number;
39
91
  }
40
92
  interface ToolSchema {
41
93
  name: string;
@@ -77,6 +129,10 @@ interface AgentActionProviderProps {
77
129
  children: React.ReactNode;
78
130
  onExecutionStart?: (actionName: string) => void;
79
131
  onExecutionComplete?: (result: ExecutionResult) => void;
132
+ /** Pre-defined actions whose schemas are available before their components mount. */
133
+ registry?: ActionDefinition<any>[];
134
+ /** Router integration — called when executing a registry action that needs navigation. */
135
+ navigate?: (path: string) => void | Promise<void>;
80
136
  }
81
137
  interface AgentActionContextValue {
82
138
  registerAction: (action: RegisteredAction) => void;
@@ -90,18 +146,25 @@ interface AgentActionContextValue {
90
146
  mode: ExecutionMode;
91
147
  }
92
148
 
93
- declare function AgentActionProvider({ mode, stepDelay, overlayOpacity, spotlightPadding, tooltipEnabled, cursorEnabled, children, onExecutionStart, onExecutionComplete, }: AgentActionProviderProps): react_jsx_runtime.JSX.Element;
149
+ declare function AgentActionProvider({ mode, stepDelay, overlayOpacity, spotlightPadding, tooltipEnabled, cursorEnabled, children, onExecutionStart, onExecutionComplete, registry, navigate, }: AgentActionProviderProps): react_jsx_runtime.JSX.Element;
94
150
 
95
- interface AgentActionProps {
96
- name: string;
97
- description: string;
98
- parameters?: unknown;
151
+ type AgentActionProps = {
99
152
  onExecute?: (params: Record<string, unknown>) => void | Promise<void>;
100
153
  disabled?: boolean;
101
154
  disabledReason?: string;
102
155
  children?: React$1.ReactNode;
103
- }
104
- declare function AgentAction({ name, description, parameters, onExecute, disabled, disabledReason, children, }: AgentActionProps): react_jsx_runtime.JSX.Element | null;
156
+ } & ({
157
+ action: ActionDefinition<any>;
158
+ name?: string;
159
+ description?: string;
160
+ parameters?: unknown;
161
+ } | {
162
+ action?: never;
163
+ name: string;
164
+ description: string;
165
+ parameters?: unknown;
166
+ });
167
+ declare function AgentAction(props: AgentActionProps): react_jsx_runtime.JSX.Element | null;
105
168
 
106
169
  interface AgentStepProps {
107
170
  label: string;
@@ -200,6 +263,9 @@ declare function useAgentActions(): AgentActionContextValue;
200
263
  * it routes through `execute()` for visual guided execution. Otherwise it falls
201
264
  * through to the original handler.
202
265
  *
266
+ * Returns the `ExecutionResult` for registered actions, or `undefined` for
267
+ * fallback commands.
268
+ *
203
269
  * Works with any command shape — you provide `getActionName` to extract the
204
270
  * action name from your command object.
205
271
  *
@@ -211,10 +277,10 @@ declare function useAgentActions(): AgentActionContextValue;
211
277
  * );
212
278
  * ```
213
279
  */
214
- declare function useAgentCommandRouter<T>(fallback: ((command: T) => void | Promise<void>) | null, getActionName: (command: T) => string): (command: T) => Promise<void>;
280
+ declare function useAgentCommandRouter<T>(fallback: ((command: T) => void | Promise<void>) | null, getActionName: (command: T) => string): (command: T) => Promise<ExecutionResult | undefined>;
215
281
 
216
282
  type JsonSchema = Record<string, unknown>;
217
283
  declare function zodToJsonSchema(schema: unknown): JsonSchema;
218
284
  declare function generateToolSchemas(actions: RegisteredAction[]): ToolSchema[];
219
285
 
220
- export { AgentAction, type AgentActionContextValue, AgentActionProvider, type AgentActionProviderProps, AgentDevTools, AgentStep, AgentTarget, type AgentTargetEntry, type AvailableAction, type ExecutionMode, type ExecutionResult, type ExecutionTarget, type ExecutorConfig, type RegisteredAction, type ToolSchema, generateToolSchemas, useAgentAction, useAgentActions, useAgentCommandRouter, zodToJsonSchema };
286
+ export { type ActionDefinition, AgentAction, type AgentActionContextValue, AgentActionProvider, type AgentActionProviderProps, AgentDevTools, AgentStep, AgentTarget, type AgentTargetEntry, type AvailableAction, type ExecutionMode, type ExecutionResult, type ExecutionTarget, type ExecutorConfig, type RegisteredAction, type ToolSchema, defineAction, generateToolSchemas, useAgentAction, useAgentActions, useAgentCommandRouter, zodToJsonSchema };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,52 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
3
 
4
+ /**
5
+ * Define an action at import time so its schema is available before the component mounts.
6
+ * Pass defined actions to `<AgentActionProvider registry={[...]}>` for single-roundtrip execution.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * export const updatePrice = defineAction({
11
+ * name: 'update_price',
12
+ * description: 'Update price markup on a property',
13
+ * parameters: z.object({ property_id: z.string(), markup: z.number() }),
14
+ * route: (p) => `/properties/${p.property_id}/pricing`,
15
+ * });
16
+ * ```
17
+ */
18
+ interface ActionDefinition<TParams = Record<string, unknown>> {
19
+ readonly name: string;
20
+ readonly description: string;
21
+ /** Zod schema for action parameters. */
22
+ readonly parameters?: unknown;
23
+ /** Client-side route to navigate to before executing. */
24
+ readonly route?: (params: TParams) => string;
25
+ /** Handler for background execution (no UI component needed). */
26
+ readonly onExecute?: (params: TParams) => void | Promise<void>;
27
+ /**
28
+ * Chain of action names to execute sequentially before this action.
29
+ * Each action in the chain is visually executed (spotlight → click), and the next
30
+ * action is waited on to mount before proceeding. This lets the user see the full
31
+ * navigation path instead of being teleported directly to a route.
32
+ */
33
+ readonly navigateVia?: string[];
34
+ /**
35
+ * How long (ms) to wait for this action's component to mount after navigation.
36
+ * Defaults to 5000ms. Set higher for pages that load slowly
37
+ */
38
+ readonly mountTimeout?: number;
39
+ }
40
+ declare function defineAction<TParams = Record<string, unknown>>(config: {
41
+ name: string;
42
+ description: string;
43
+ parameters?: unknown;
44
+ route?: (params: TParams) => string;
45
+ onExecute?: (params: TParams) => void | Promise<void>;
46
+ navigateVia?: string[];
47
+ mountTimeout?: number;
48
+ }): ActionDefinition<TParams>;
49
+
4
50
  type ExecutionMode = 'guided' | 'instant';
5
51
  interface ExecutionTarget {
6
52
  label: string;
@@ -36,6 +82,12 @@ interface RegisteredAction {
36
82
  disabled: boolean;
37
83
  disabledReason?: string;
38
84
  getExecutionTargets: () => ExecutionTarget[];
85
+ /** Client-side route for navigation before execution (from defineAction). */
86
+ route?: (params: Record<string, unknown>) => string;
87
+ /** Chain of action names to execute sequentially before this action (from defineAction). */
88
+ navigateVia?: string[];
89
+ /** How long (ms) to wait for this action's component to mount after navigation. */
90
+ mountTimeout?: number;
39
91
  }
40
92
  interface ToolSchema {
41
93
  name: string;
@@ -77,6 +129,10 @@ interface AgentActionProviderProps {
77
129
  children: React.ReactNode;
78
130
  onExecutionStart?: (actionName: string) => void;
79
131
  onExecutionComplete?: (result: ExecutionResult) => void;
132
+ /** Pre-defined actions whose schemas are available before their components mount. */
133
+ registry?: ActionDefinition<any>[];
134
+ /** Router integration — called when executing a registry action that needs navigation. */
135
+ navigate?: (path: string) => void | Promise<void>;
80
136
  }
81
137
  interface AgentActionContextValue {
82
138
  registerAction: (action: RegisteredAction) => void;
@@ -90,18 +146,25 @@ interface AgentActionContextValue {
90
146
  mode: ExecutionMode;
91
147
  }
92
148
 
93
- declare function AgentActionProvider({ mode, stepDelay, overlayOpacity, spotlightPadding, tooltipEnabled, cursorEnabled, children, onExecutionStart, onExecutionComplete, }: AgentActionProviderProps): react_jsx_runtime.JSX.Element;
149
+ declare function AgentActionProvider({ mode, stepDelay, overlayOpacity, spotlightPadding, tooltipEnabled, cursorEnabled, children, onExecutionStart, onExecutionComplete, registry, navigate, }: AgentActionProviderProps): react_jsx_runtime.JSX.Element;
94
150
 
95
- interface AgentActionProps {
96
- name: string;
97
- description: string;
98
- parameters?: unknown;
151
+ type AgentActionProps = {
99
152
  onExecute?: (params: Record<string, unknown>) => void | Promise<void>;
100
153
  disabled?: boolean;
101
154
  disabledReason?: string;
102
155
  children?: React$1.ReactNode;
103
- }
104
- declare function AgentAction({ name, description, parameters, onExecute, disabled, disabledReason, children, }: AgentActionProps): react_jsx_runtime.JSX.Element | null;
156
+ } & ({
157
+ action: ActionDefinition<any>;
158
+ name?: string;
159
+ description?: string;
160
+ parameters?: unknown;
161
+ } | {
162
+ action?: never;
163
+ name: string;
164
+ description: string;
165
+ parameters?: unknown;
166
+ });
167
+ declare function AgentAction(props: AgentActionProps): react_jsx_runtime.JSX.Element | null;
105
168
 
106
169
  interface AgentStepProps {
107
170
  label: string;
@@ -200,6 +263,9 @@ declare function useAgentActions(): AgentActionContextValue;
200
263
  * it routes through `execute()` for visual guided execution. Otherwise it falls
201
264
  * through to the original handler.
202
265
  *
266
+ * Returns the `ExecutionResult` for registered actions, or `undefined` for
267
+ * fallback commands.
268
+ *
203
269
  * Works with any command shape — you provide `getActionName` to extract the
204
270
  * action name from your command object.
205
271
  *
@@ -211,10 +277,10 @@ declare function useAgentActions(): AgentActionContextValue;
211
277
  * );
212
278
  * ```
213
279
  */
214
- declare function useAgentCommandRouter<T>(fallback: ((command: T) => void | Promise<void>) | null, getActionName: (command: T) => string): (command: T) => Promise<void>;
280
+ declare function useAgentCommandRouter<T>(fallback: ((command: T) => void | Promise<void>) | null, getActionName: (command: T) => string): (command: T) => Promise<ExecutionResult | undefined>;
215
281
 
216
282
  type JsonSchema = Record<string, unknown>;
217
283
  declare function zodToJsonSchema(schema: unknown): JsonSchema;
218
284
  declare function generateToolSchemas(actions: RegisteredAction[]): ToolSchema[];
219
285
 
220
- export { AgentAction, type AgentActionContextValue, AgentActionProvider, type AgentActionProviderProps, AgentDevTools, AgentStep, AgentTarget, type AgentTargetEntry, type AvailableAction, type ExecutionMode, type ExecutionResult, type ExecutionTarget, type ExecutorConfig, type RegisteredAction, type ToolSchema, generateToolSchemas, useAgentAction, useAgentActions, useAgentCommandRouter, zodToJsonSchema };
286
+ export { type ActionDefinition, AgentAction, type AgentActionContextValue, AgentActionProvider, type AgentActionProviderProps, AgentDevTools, AgentStep, AgentTarget, type AgentTargetEntry, type AvailableAction, type ExecutionMode, type ExecutionResult, type ExecutionTarget, type ExecutorConfig, type RegisteredAction, type ToolSchema, defineAction, generateToolSchemas, useAgentAction, useAgentActions, useAgentCommandRouter, zodToJsonSchema };