@mydatavalue/polter 0.1.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.
package/dist/index.js ADDED
@@ -0,0 +1,1274 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+
6
+ // src/components/AgentActionProvider.tsx
7
+
8
+ // src/core/schemaGenerator.ts
9
+ function zodToJsonSchema(schema) {
10
+ if (typeof schema.toJSONSchema === "function") {
11
+ try {
12
+ const result = schema.toJSONSchema();
13
+ delete result.$schema;
14
+ return result;
15
+ } catch {
16
+ }
17
+ }
18
+ const def = schema._def;
19
+ const description = schema.description;
20
+ switch (def.typeName) {
21
+ case "ZodString": {
22
+ const result = { type: "string" };
23
+ if (description) result.description = description;
24
+ if (def.checks) {
25
+ for (const check of def.checks) {
26
+ if (check.kind === "min") result.minLength = check.value;
27
+ if (check.kind === "max") result.maxLength = check.value;
28
+ }
29
+ }
30
+ return result;
31
+ }
32
+ case "ZodNumber": {
33
+ const result = { type: "number" };
34
+ if (description) result.description = description;
35
+ if (def.checks) {
36
+ for (const check of def.checks) {
37
+ if (check.kind === "int") result.type = "integer";
38
+ if (check.kind === "min")
39
+ result[check.inclusive ? "minimum" : "exclusiveMinimum"] = check.value;
40
+ if (check.kind === "max")
41
+ result[check.inclusive ? "maximum" : "exclusiveMaximum"] = check.value;
42
+ }
43
+ }
44
+ return result;
45
+ }
46
+ case "ZodBoolean": {
47
+ const result = { type: "boolean" };
48
+ if (description) result.description = description;
49
+ return result;
50
+ }
51
+ case "ZodArray": {
52
+ const result = {
53
+ type: "array",
54
+ items: zodToJsonSchema(def.type)
55
+ };
56
+ if (description) result.description = description;
57
+ if (def.minLength !== null && def.minLength !== void 0)
58
+ result.minItems = def.minLength.value;
59
+ if (def.maxLength !== null && def.maxLength !== void 0)
60
+ result.maxItems = def.maxLength.value;
61
+ return result;
62
+ }
63
+ case "ZodObject": {
64
+ const shape = def.shape();
65
+ const properties = {};
66
+ const required = [];
67
+ for (const [key, value] of Object.entries(shape)) {
68
+ properties[key] = zodToJsonSchema(value);
69
+ if (!value.isOptional()) {
70
+ required.push(key);
71
+ }
72
+ }
73
+ const result = { type: "object", properties };
74
+ if (required.length > 0) result.required = required;
75
+ if (description) result.description = description;
76
+ return result;
77
+ }
78
+ case "ZodEnum": {
79
+ const result = { type: "string", enum: [...def.values] };
80
+ if (description) result.description = description;
81
+ return result;
82
+ }
83
+ case "ZodLiteral": {
84
+ const result = { type: typeof def.value, const: def.value };
85
+ if (description) result.description = description;
86
+ return result;
87
+ }
88
+ case "ZodUnion":
89
+ case "ZodDiscriminatedUnion": {
90
+ const options = def.options;
91
+ const result = { anyOf: options.map((o) => zodToJsonSchema(o)) };
92
+ if (description) result.description = description;
93
+ return result;
94
+ }
95
+ case "ZodOptional": {
96
+ const inner = zodToJsonSchema(def.innerType);
97
+ if (description && !inner.description) inner.description = description;
98
+ return inner;
99
+ }
100
+ case "ZodNullable": {
101
+ const inner = zodToJsonSchema(def.innerType);
102
+ if (description && !inner.description) inner.description = description;
103
+ return inner;
104
+ }
105
+ case "ZodDefault": {
106
+ const inner = zodToJsonSchema(def.innerType);
107
+ if (description && !inner.description) inner.description = description;
108
+ return inner;
109
+ }
110
+ case "ZodRecord": {
111
+ const result = {
112
+ type: "object",
113
+ additionalProperties: zodToJsonSchema(def.valueType)
114
+ };
115
+ if (description) result.description = description;
116
+ return result;
117
+ }
118
+ case "ZodNull": {
119
+ return { type: "null", ...description && { description } };
120
+ }
121
+ case "ZodAny":
122
+ case "ZodUnknown": {
123
+ return description ? { description } : {};
124
+ }
125
+ default: {
126
+ return { type: "object", ...description && { description } };
127
+ }
128
+ }
129
+ }
130
+ function generateToolSchemas(actions) {
131
+ return actions.filter((a) => !a.disabled).map((action) => ({
132
+ name: action.name,
133
+ description: action.description,
134
+ parameters: action.parameters ? zodToJsonSchema(action.parameters) : { type: "object", properties: {} }
135
+ }));
136
+ }
137
+
138
+ // src/executor/visualExecutor.ts
139
+ var stylesInjected = false;
140
+ function injectStyles() {
141
+ if (stylesInjected) return;
142
+ if (typeof document === "undefined") return;
143
+ stylesInjected = true;
144
+ const style = document.createElement("style");
145
+ style.id = "polter-styles";
146
+ style.textContent = `
147
+ @keyframes polter-pulse {
148
+ 0%, 100% { opacity: 1; transform: scale(1); }
149
+ 50% { opacity: 0.7; transform: scale(1.02); }
150
+ }
151
+ @keyframes polter-fade-in {
152
+ from { opacity: 0; transform: translateX(-50%) translateY(4px); }
153
+ to { opacity: 1; transform: translateX(-50%) translateY(0); }
154
+ }
155
+ @keyframes polter-cursor-click {
156
+ 0% { transform: scale(1); }
157
+ 50% { transform: scale(0.85); }
158
+ 100% { transform: scale(1); }
159
+ }
160
+ `;
161
+ document.head.appendChild(style);
162
+ }
163
+ var CURSOR_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
164
+ <path d="M5.5 3.21V20.8c0 .45.54.67.85.35l4.86-4.86a.5.5 0 0 1 .35-.15h6.87c.48 0 .68-.61.3-.92L5.95 2.87a.5.5 0 0 0-.45.34z" fill="#1e293b" stroke="white" stroke-width="1.5" stroke-linejoin="round"/>
165
+ </svg>`;
166
+ function createBlockingOverlay() {
167
+ const overlay = document.createElement("div");
168
+ overlay.className = "polter-blocking-overlay";
169
+ overlay.style.cssText = `
170
+ position:fixed;
171
+ inset:0;
172
+ z-index:99997;
173
+ cursor:not-allowed;
174
+ `;
175
+ document.body.appendChild(overlay);
176
+ return { remove: () => overlay.remove() };
177
+ }
178
+ function createCursor() {
179
+ injectStyles();
180
+ const cursor = document.createElement("div");
181
+ cursor.className = "polter-cursor";
182
+ cursor.innerHTML = CURSOR_SVG;
183
+ cursor.style.cssText = `
184
+ position:fixed;
185
+ left:-40px;
186
+ top:-40px;
187
+ z-index:100000;
188
+ pointer-events:none;
189
+ transition:left 0.4s cubic-bezier(0.4,0,0.2,1),top 0.4s cubic-bezier(0.4,0,0.2,1);
190
+ filter:drop-shadow(0 2px 4px rgba(0,0,0,0.3));
191
+ `;
192
+ document.body.appendChild(cursor);
193
+ return { remove: () => cursor.remove() };
194
+ }
195
+ function moveCursorTo(target, signal) {
196
+ const cursor = document.querySelector(".polter-cursor");
197
+ if (!cursor) return Promise.resolve();
198
+ const rect = target.getBoundingClientRect();
199
+ cursor.style.left = `${rect.left + rect.width / 2}px`;
200
+ cursor.style.top = `${rect.top + rect.height / 2}px`;
201
+ return delay(450, signal);
202
+ }
203
+ function animateCursorClick() {
204
+ const cursor = document.querySelector(".polter-cursor");
205
+ if (!cursor) return;
206
+ cursor.style.animation = "polter-cursor-click 0.2s ease";
207
+ cursor.addEventListener("animationend", () => {
208
+ cursor.style.animation = "";
209
+ }, { once: true });
210
+ }
211
+ function createSpotlight(target, label, config) {
212
+ injectStyles();
213
+ const rect = target.getBoundingClientRect();
214
+ const padding = config.spotlightPadding;
215
+ const overlayRgba = `rgba(0, 0, 0, ${config.overlayOpacity})`;
216
+ const container = document.createElement("div");
217
+ container.className = "polter-spotlight-container";
218
+ container.style.cssText = "position:fixed;inset:0;z-index:99998;pointer-events:none;";
219
+ const spotlight = document.createElement("div");
220
+ spotlight.className = "polter-spotlight";
221
+ spotlight.style.cssText = `
222
+ position:fixed;
223
+ left:${rect.left - padding}px;
224
+ top:${rect.top - padding}px;
225
+ width:${rect.width + padding * 2}px;
226
+ height:${rect.height + padding * 2}px;
227
+ border-radius:8px;
228
+ box-shadow:0 0 0 9999px ${overlayRgba};
229
+ z-index:99998;
230
+ pointer-events:none;
231
+ transition:all 0.3s ease;
232
+ `;
233
+ const ring = document.createElement("div");
234
+ ring.className = "polter-ring";
235
+ ring.style.cssText = `
236
+ position:fixed;
237
+ left:${rect.left - padding - 2}px;
238
+ top:${rect.top - padding - 2}px;
239
+ width:${rect.width + padding * 2 + 4}px;
240
+ height:${rect.height + padding * 2 + 4}px;
241
+ border:2px solid #3b82f6;
242
+ border-radius:10px;
243
+ z-index:99999;
244
+ pointer-events:none;
245
+ animation:polter-pulse 1.5s ease-in-out infinite;
246
+ `;
247
+ container.appendChild(spotlight);
248
+ container.appendChild(ring);
249
+ if (label && config.tooltipEnabled) {
250
+ const tooltip = document.createElement("div");
251
+ tooltip.className = "polter-tooltip";
252
+ tooltip.textContent = label;
253
+ const spaceBelow = window.innerHeight - rect.bottom - padding;
254
+ const isBelow = spaceBelow > 60;
255
+ const tooltipTop = isBelow ? rect.bottom + padding + 12 : rect.top - padding - 44;
256
+ tooltip.style.cssText = `
257
+ position:fixed;
258
+ left:${rect.left + rect.width / 2}px;
259
+ top:${tooltipTop}px;
260
+ transform:translateX(-50%);
261
+ background:#1e293b;
262
+ color:#f8fafc;
263
+ padding:8px 14px;
264
+ border-radius:6px;
265
+ font-size:13px;
266
+ font-weight:500;
267
+ line-height:1.4;
268
+ white-space:nowrap;
269
+ z-index:99999;
270
+ pointer-events:none;
271
+ animation:polter-fade-in 0.2s ease;
272
+ box-shadow:0 4px 12px rgba(0,0,0,0.15);
273
+ `;
274
+ container.appendChild(tooltip);
275
+ }
276
+ document.body.appendChild(container);
277
+ return {
278
+ remove: () => container.remove()
279
+ };
280
+ }
281
+ function delay(ms, signal) {
282
+ return new Promise((resolve, reject) => {
283
+ if (signal?.aborted) {
284
+ reject(new DOMException("Aborted", "AbortError"));
285
+ return;
286
+ }
287
+ const timer = setTimeout(resolve, ms);
288
+ signal?.addEventListener(
289
+ "abort",
290
+ () => {
291
+ clearTimeout(timer);
292
+ reject(new DOMException("Aborted", "AbortError"));
293
+ },
294
+ { once: true }
295
+ );
296
+ });
297
+ }
298
+ function setNativeInputValue(input, value) {
299
+ const nativeSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set ?? Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set;
300
+ if (nativeSetter) {
301
+ nativeSetter.call(input, value);
302
+ } else {
303
+ input.value = value;
304
+ }
305
+ input.dispatchEvent(new Event("input", { bubbles: true }));
306
+ input.dispatchEvent(new Event("change", { bubbles: true }));
307
+ }
308
+ async function simulateTyping(element, value, signal) {
309
+ const input = element;
310
+ input.focus();
311
+ if (input.value) {
312
+ setNativeInputValue(input, "");
313
+ await delay(30, signal);
314
+ }
315
+ const charDelay = Math.max(15, Math.min(40, 800 / value.length));
316
+ for (let i = 0; i < value.length; i++) {
317
+ if (signal?.aborted) return;
318
+ setNativeInputValue(input, value.slice(0, i + 1));
319
+ await delay(charDelay, signal);
320
+ }
321
+ }
322
+ async function resolveStepElement(target, actionName, params, config) {
323
+ if (target.prepareView) {
324
+ await target.prepareView(params);
325
+ await delay(200, config.signal);
326
+ }
327
+ if (target.fromParam && config.resolveTarget) {
328
+ const raw = params[target.fromParam];
329
+ const paramValue = String(Array.isArray(raw) ? raw[0] ?? "" : raw ?? "");
330
+ return config.resolveTarget(actionName, target.fromParam, paramValue, config.signal);
331
+ }
332
+ if (target.fromTarget && config.resolveNamedTarget) {
333
+ return config.resolveNamedTarget(actionName, target.fromTarget, config.signal);
334
+ }
335
+ return target.element;
336
+ }
337
+ async function executeInstant(action, params) {
338
+ try {
339
+ if (action.onExecute) {
340
+ await action.onExecute(params);
341
+ } else {
342
+ const targets = action.getExecutionTargets();
343
+ for (const target of targets) {
344
+ target.element?.click();
345
+ }
346
+ }
347
+ return { success: true, actionName: action.name };
348
+ } catch (err) {
349
+ return { success: false, actionName: action.name, error: String(err) };
350
+ }
351
+ }
352
+ function isElementVisible(el) {
353
+ if (!el.isConnected) return false;
354
+ const rect = el.getBoundingClientRect();
355
+ return rect.width > 0 && rect.height > 0;
356
+ }
357
+ async function executeGuided(action, params, config) {
358
+ const targets = action.getExecutionTargets();
359
+ if (targets.length === 0 || targets.every((t) => t.element && !isElementVisible(t.element))) {
360
+ if (action.onExecute) {
361
+ await action.onExecute(params);
362
+ }
363
+ return { success: true, actionName: action.name };
364
+ }
365
+ let spotlight = null;
366
+ let cursor = null;
367
+ const blocker = createBlockingOverlay();
368
+ if (config.cursorEnabled) {
369
+ cursor = createCursor();
370
+ }
371
+ try {
372
+ for (let i = 0; i < targets.length; i++) {
373
+ const target = targets[i];
374
+ const isLast = i === targets.length - 1;
375
+ const element = await resolveStepElement(target, action.name, params, config);
376
+ if (!element) continue;
377
+ if (!isElementVisible(element)) {
378
+ if (targets.length > 1) {
379
+ blocker.remove();
380
+ cursor?.remove();
381
+ return { success: false, actionName: action.name, error: `Step element not visible: "${target.label}"` };
382
+ }
383
+ continue;
384
+ }
385
+ element.scrollIntoView({ behavior: "smooth", block: "center" });
386
+ await delay(300, config.signal);
387
+ if (cursor) {
388
+ await moveCursorTo(element, config.signal);
389
+ }
390
+ spotlight = createSpotlight(element, target.label, config);
391
+ await delay(config.stepDelay, config.signal);
392
+ if (target.setParam) {
393
+ const inputEl = element.tagName === "INPUT" || element.tagName === "TEXTAREA" ? element : element.querySelector("input, textarea") ?? element;
394
+ const value = String(params[target.setParam] ?? "");
395
+ await simulateTyping(inputEl, value, config.signal);
396
+ } else if (target.setValue && target.onSetValue) {
397
+ const value = params[target.setValue];
398
+ target.onSetValue(value);
399
+ } else if (target.fromParam || target.fromTarget) {
400
+ animateCursorClick();
401
+ element.click();
402
+ } else if (action.onExecute) {
403
+ if (!isLast) {
404
+ animateCursorClick();
405
+ element.click();
406
+ }
407
+ } else {
408
+ animateCursorClick();
409
+ element.click();
410
+ }
411
+ spotlight.remove();
412
+ spotlight = null;
413
+ if (!isLast) {
414
+ await delay(200, config.signal);
415
+ }
416
+ }
417
+ if (action.onExecute) {
418
+ await action.onExecute(params);
419
+ }
420
+ blocker.remove();
421
+ cursor?.remove();
422
+ return { success: true, actionName: action.name };
423
+ } catch (err) {
424
+ spotlight?.remove();
425
+ blocker.remove();
426
+ cursor?.remove();
427
+ if (err instanceof DOMException && err.name === "AbortError") {
428
+ return { success: false, actionName: action.name, error: "Execution cancelled" };
429
+ }
430
+ return { success: false, actionName: action.name, error: String(err) };
431
+ }
432
+ }
433
+ async function executeAction(action, params, config) {
434
+ if (config.mode === "instant") {
435
+ return executeInstant(action, params);
436
+ }
437
+ return executeGuided(action, params, config);
438
+ }
439
+ var AgentActionContext = react.createContext(null);
440
+ function AgentActionProvider({
441
+ mode = "guided",
442
+ stepDelay = 600,
443
+ overlayOpacity = 0.5,
444
+ spotlightPadding = 8,
445
+ tooltipEnabled = true,
446
+ cursorEnabled = true,
447
+ children,
448
+ onExecutionStart,
449
+ onExecutionComplete
450
+ }) {
451
+ const actionsRef = react.useRef(/* @__PURE__ */ new Map());
452
+ const targetsRef = react.useRef(/* @__PURE__ */ new Map());
453
+ const [version, setVersion] = react.useState(0);
454
+ const [isExecuting, setIsExecuting] = react.useState(false);
455
+ const currentExecutionRef = react.useRef(null);
456
+ const registerAction = react.useCallback((action) => {
457
+ const existing = actionsRef.current.get(action.name);
458
+ actionsRef.current.set(action.name, action);
459
+ if (!existing || existing.description !== action.description || existing.disabled !== action.disabled || existing.disabledReason !== action.disabledReason) {
460
+ setVersion((v) => v + 1);
461
+ }
462
+ }, []);
463
+ const unregisterAction = react.useCallback((name) => {
464
+ if (actionsRef.current.delete(name)) {
465
+ setVersion((v) => v + 1);
466
+ }
467
+ }, []);
468
+ const registerTarget = react.useCallback((id, entry) => {
469
+ targetsRef.current.set(id, entry);
470
+ }, []);
471
+ const unregisterTarget = react.useCallback((id) => {
472
+ targetsRef.current.delete(id);
473
+ }, []);
474
+ const resolveTarget = react.useCallback(
475
+ async (actionName, param, value, signal) => {
476
+ const normalizedValue = value.toLowerCase();
477
+ const maxWait = 3e3;
478
+ const pollInterval = 50;
479
+ const start = Date.now();
480
+ while (Date.now() - start < maxWait) {
481
+ if (signal?.aborted) return null;
482
+ for (const entry of targetsRef.current.values()) {
483
+ if ((!entry.action || entry.action === actionName) && entry.param === param && entry.value?.toLowerCase() === normalizedValue && entry.element.isConnected) {
484
+ return entry.element;
485
+ }
486
+ }
487
+ await new Promise((r) => setTimeout(r, pollInterval));
488
+ }
489
+ return null;
490
+ },
491
+ []
492
+ );
493
+ const resolveNamedTarget = react.useCallback(
494
+ async (actionName, name, signal) => {
495
+ const maxWait = 3e3;
496
+ const pollInterval = 50;
497
+ const start = Date.now();
498
+ while (Date.now() - start < maxWait) {
499
+ if (signal?.aborted) return null;
500
+ for (const entry of targetsRef.current.values()) {
501
+ if ((!entry.action || entry.action === actionName) && entry.name === name && entry.element.isConnected) {
502
+ return entry.element;
503
+ }
504
+ }
505
+ await new Promise((r) => setTimeout(r, pollInterval));
506
+ }
507
+ return null;
508
+ },
509
+ []
510
+ );
511
+ const execute = react.useCallback(
512
+ async (actionName, params) => {
513
+ currentExecutionRef.current?.abort();
514
+ const controller = new AbortController();
515
+ currentExecutionRef.current = controller;
516
+ const action = actionsRef.current.get(actionName);
517
+ if (!action) {
518
+ return { success: false, actionName, error: `Action "${actionName}" not found` };
519
+ }
520
+ if (action.disabled) {
521
+ return {
522
+ success: false,
523
+ actionName,
524
+ error: action.disabledReason || "Action is disabled"
525
+ };
526
+ }
527
+ setIsExecuting(true);
528
+ onExecutionStart?.(actionName);
529
+ try {
530
+ const result = await executeAction(action, params ?? {}, {
531
+ mode,
532
+ stepDelay,
533
+ overlayOpacity,
534
+ spotlightPadding,
535
+ tooltipEnabled,
536
+ cursorEnabled,
537
+ signal: controller.signal,
538
+ resolveTarget,
539
+ resolveNamedTarget
540
+ });
541
+ onExecutionComplete?.(result);
542
+ return result;
543
+ } catch (err) {
544
+ const result = {
545
+ success: false,
546
+ actionName,
547
+ error: err instanceof DOMException && err.name === "AbortError" ? "Execution cancelled" : String(err)
548
+ };
549
+ onExecutionComplete?.(result);
550
+ return result;
551
+ } finally {
552
+ setIsExecuting(false);
553
+ if (currentExecutionRef.current === controller) {
554
+ currentExecutionRef.current = null;
555
+ }
556
+ }
557
+ },
558
+ [mode, stepDelay, overlayOpacity, spotlightPadding, tooltipEnabled, cursorEnabled, onExecutionStart, onExecutionComplete, resolveTarget, resolveNamedTarget]
559
+ );
560
+ const availableActions = react.useMemo(
561
+ () => Array.from(actionsRef.current.values()).map((a) => ({
562
+ name: a.name,
563
+ description: a.description,
564
+ disabled: a.disabled,
565
+ disabledReason: a.disabledReason,
566
+ hasParameters: !!a.parameters
567
+ })),
568
+ // eslint-disable-next-line react-hooks/exhaustive-deps
569
+ [version]
570
+ );
571
+ const schemas = react.useMemo(
572
+ () => generateToolSchemas(Array.from(actionsRef.current.values())),
573
+ // eslint-disable-next-line react-hooks/exhaustive-deps
574
+ [version]
575
+ );
576
+ const contextValue = react.useMemo(
577
+ () => ({
578
+ registerAction,
579
+ unregisterAction,
580
+ registerTarget,
581
+ unregisterTarget,
582
+ execute,
583
+ availableActions,
584
+ schemas,
585
+ isExecuting,
586
+ mode
587
+ }),
588
+ [
589
+ registerAction,
590
+ unregisterAction,
591
+ registerTarget,
592
+ unregisterTarget,
593
+ execute,
594
+ availableActions,
595
+ schemas,
596
+ isExecuting,
597
+ mode
598
+ ]
599
+ );
600
+ return /* @__PURE__ */ jsxRuntime.jsx(AgentActionContext.Provider, { value: contextValue, children });
601
+ }
602
+ var AgentStepContext = react.createContext(null);
603
+ function AgentAction({
604
+ name,
605
+ description,
606
+ parameters,
607
+ onExecute,
608
+ disabled = false,
609
+ disabledReason,
610
+ children
611
+ }) {
612
+ const context = react.useContext(AgentActionContext);
613
+ if (!context) {
614
+ throw new Error("AgentAction must be used within an AgentActionProvider");
615
+ }
616
+ const wrapperRef = react.useRef(null);
617
+ const stepsRef = react.useRef(/* @__PURE__ */ new Map());
618
+ const onExecuteRef = react.useRef(onExecute);
619
+ onExecuteRef.current = onExecute;
620
+ const parametersRef = react.useRef(parameters);
621
+ parametersRef.current = parameters;
622
+ const stableOnExecute = react.useCallback((params) => {
623
+ return onExecuteRef.current?.(params);
624
+ }, []);
625
+ const getExecutionTargets = react.useCallback(() => {
626
+ if (stepsRef.current.size > 0) {
627
+ const steps = Array.from(stepsRef.current.values());
628
+ const withElements = steps.filter((s) => s.element);
629
+ const withoutElements = steps.filter((s) => !s.element && (s.fromParam || s.fromTarget));
630
+ withElements.sort((a, b) => {
631
+ if (!a.element || !b.element) return 0;
632
+ const pos = a.element.compareDocumentPosition(b.element);
633
+ return pos & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
634
+ });
635
+ const ordered = [...withElements, ...withoutElements];
636
+ return ordered.map((s) => ({
637
+ label: s.label,
638
+ element: s.element,
639
+ fromParam: s.fromParam,
640
+ fromTarget: s.fromTarget,
641
+ setParam: s.setParam,
642
+ setValue: s.setValue,
643
+ onSetValue: s.onSetValue,
644
+ prepareView: s.prepareView
645
+ }));
646
+ }
647
+ const el = wrapperRef.current?.firstElementChild;
648
+ return el ? [{ label: description, element: el }] : [];
649
+ }, [description]);
650
+ const { registerAction, unregisterAction } = context;
651
+ react.useEffect(() => {
652
+ registerAction({
653
+ name,
654
+ description,
655
+ parameters: parametersRef.current,
656
+ onExecute: onExecuteRef.current ? stableOnExecute : void 0,
657
+ disabled,
658
+ disabledReason,
659
+ getExecutionTargets
660
+ });
661
+ return () => unregisterAction(name);
662
+ }, [name, description, disabled, disabledReason, stableOnExecute, getExecutionTargets, registerAction, unregisterAction]);
663
+ const registerStep = react.useCallback(
664
+ (id, data) => {
665
+ stepsRef.current.set(id, data);
666
+ },
667
+ []
668
+ );
669
+ const unregisterStep = react.useCallback((id) => {
670
+ stepsRef.current.delete(id);
671
+ }, []);
672
+ const stepContextValue = react.useMemo(
673
+ () => ({ registerStep, unregisterStep }),
674
+ [registerStep, unregisterStep]
675
+ );
676
+ if (!children) return null;
677
+ return /* @__PURE__ */ jsxRuntime.jsx(AgentStepContext.Provider, { value: stepContextValue, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: wrapperRef, style: { display: "contents" }, children }) });
678
+ }
679
+ function AgentStep({
680
+ label,
681
+ children,
682
+ fromParam,
683
+ fromTarget,
684
+ setParam,
685
+ setValue,
686
+ onSetValue,
687
+ prepareView
688
+ }) {
689
+ const id = react.useId();
690
+ const wrapperRef = react.useRef(null);
691
+ const stepContext = react.useContext(AgentStepContext);
692
+ if (!stepContext) {
693
+ throw new Error("AgentStep must be used within an AgentAction");
694
+ }
695
+ const onSetValueRef = react.useRef(onSetValue);
696
+ onSetValueRef.current = onSetValue;
697
+ const prepareViewRef = react.useRef(prepareView);
698
+ prepareViewRef.current = prepareView;
699
+ react.useEffect(() => {
700
+ const element = children ? wrapperRef.current?.firstElementChild : null;
701
+ stepContext.registerStep(id, {
702
+ label,
703
+ element,
704
+ fromParam,
705
+ fromTarget,
706
+ setParam,
707
+ setValue,
708
+ onSetValue: onSetValueRef.current,
709
+ prepareView: prepareViewRef.current
710
+ });
711
+ return () => stepContext.unregisterStep(id);
712
+ }, [id, label, fromParam, fromTarget, setParam, setValue, stepContext]);
713
+ if (!children) return null;
714
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: wrapperRef, style: { display: "contents" }, children });
715
+ }
716
+ function AgentTarget({ action, param, value, name, children }) {
717
+ const id = react.useId();
718
+ const wrapperRef = react.useRef(null);
719
+ const context = react.useContext(AgentActionContext);
720
+ if (!context) {
721
+ throw new Error("AgentTarget must be used within an AgentActionProvider");
722
+ }
723
+ const { registerTarget, unregisterTarget } = context;
724
+ react.useEffect(() => {
725
+ const element = wrapperRef.current?.firstElementChild;
726
+ if (element) {
727
+ registerTarget(id, { action, param, value, name, element });
728
+ }
729
+ return () => unregisterTarget(id);
730
+ }, [id, action, param, value, name, registerTarget, unregisterTarget]);
731
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: wrapperRef, style: { display: "contents" }, children });
732
+ }
733
+ function useAgentActions() {
734
+ const context = react.useContext(AgentActionContext);
735
+ if (!context) {
736
+ throw new Error("useAgentActions must be used within an AgentActionProvider");
737
+ }
738
+ return context;
739
+ }
740
+ var logId = 0;
741
+ var PANEL_WIDTH = 440;
742
+ function getSchemaFields(schemas, actionName) {
743
+ const schema = schemas.find((s) => s.name === actionName);
744
+ if (!schema?.parameters) return [];
745
+ const params = schema.parameters;
746
+ const properties = params.properties ?? {};
747
+ const required = params.required ?? [];
748
+ return Object.entries(properties).map(([name, prop]) => ({
749
+ name,
750
+ type: prop.type ?? "string",
751
+ description: prop.description,
752
+ enumValues: prop.enum,
753
+ isRequired: required.includes(name)
754
+ }));
755
+ }
756
+ function AgentDevTools({ defaultOpen = false }) {
757
+ const { availableActions, execute, isExecuting, mode, schemas } = useAgentActions();
758
+ const [open, setOpen] = react.useState(defaultOpen);
759
+ const [log, setLog] = react.useState([]);
760
+ const [expandedAction, setExpandedAction] = react.useState(null);
761
+ const [paramInputs, setParamInputs] = react.useState({});
762
+ const [filter, setFilter] = react.useState("");
763
+ const [tab, setTab] = react.useState("actions");
764
+ const logEndRef = react.useRef(null);
765
+ react.useEffect(() => {
766
+ if (tab === "log") logEndRef.current?.scrollIntoView({ behavior: "smooth" });
767
+ }, [log, tab]);
768
+ const setFieldValue = react.useCallback((actionName, fieldName, value) => {
769
+ setParamInputs((prev) => ({
770
+ ...prev,
771
+ [actionName]: { ...prev[actionName], [fieldName]: value }
772
+ }));
773
+ }, []);
774
+ const handleExecute = react.useCallback(
775
+ async (action) => {
776
+ const entryId = ++logId;
777
+ let params;
778
+ const fields = getSchemaFields(schemas, action.name);
779
+ const rawInputs = paramInputs[action.name];
780
+ if (fields.length > 0 && rawInputs) {
781
+ params = {};
782
+ for (const field of fields) {
783
+ const raw = rawInputs[field.name];
784
+ if (raw === void 0 || raw === "") continue;
785
+ if (field.type === "number" || field.type === "integer") {
786
+ params[field.name] = Number(raw);
787
+ } else if (field.type === "boolean") {
788
+ params[field.name] = raw === "true";
789
+ } else if (field.type === "array") {
790
+ try {
791
+ params[field.name] = JSON.parse(raw);
792
+ } catch {
793
+ setLog((prev) => [
794
+ ...prev,
795
+ {
796
+ id: entryId,
797
+ action: action.name,
798
+ timestamp: Date.now(),
799
+ result: { success: false, actionName: action.name, error: `Invalid JSON for ${field.name}` }
800
+ }
801
+ ]);
802
+ return;
803
+ }
804
+ } else {
805
+ params[field.name] = raw;
806
+ }
807
+ }
808
+ }
809
+ setLog((prev) => [...prev, { id: entryId, action: action.name, params, timestamp: Date.now() }]);
810
+ const result = await execute(action.name, params);
811
+ setLog((prev) => prev.map((e) => e.id === entryId ? { ...e, result } : e));
812
+ },
813
+ [execute, paramInputs, schemas]
814
+ );
815
+ const filtered = filter ? availableActions.filter((a) => a.name.includes(filter) || a.description.includes(filter)) : availableActions;
816
+ if (!open) {
817
+ return /* @__PURE__ */ jsxRuntime.jsxs(
818
+ "button",
819
+ {
820
+ onClick: () => setOpen(true),
821
+ style: {
822
+ position: "fixed",
823
+ bottom: 16,
824
+ right: 16,
825
+ zIndex: 99990,
826
+ height: 36,
827
+ paddingLeft: 12,
828
+ paddingRight: 14,
829
+ borderRadius: 18,
830
+ border: "none",
831
+ cursor: "pointer",
832
+ background: "#3b82f6",
833
+ color: "white",
834
+ fontSize: 13,
835
+ fontWeight: 600,
836
+ fontFamily: "system-ui, sans-serif",
837
+ boxShadow: "0 2px 12px rgba(59,130,246,0.4)",
838
+ display: "flex",
839
+ alignItems: "center",
840
+ gap: 6
841
+ },
842
+ children: [
843
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 16 }, children: "\u2699" }),
844
+ "Agent \xB7 ",
845
+ availableActions.length
846
+ ]
847
+ }
848
+ );
849
+ }
850
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
851
+ /* @__PURE__ */ jsxRuntime.jsx(
852
+ "div",
853
+ {
854
+ onClick: () => setOpen(false),
855
+ style: {
856
+ position: "fixed",
857
+ inset: 0,
858
+ zIndex: 99989,
859
+ background: "rgba(0,0,0,0.15)"
860
+ }
861
+ }
862
+ ),
863
+ /* @__PURE__ */ jsxRuntime.jsxs(
864
+ "div",
865
+ {
866
+ style: {
867
+ position: "fixed",
868
+ top: 0,
869
+ right: 0,
870
+ bottom: 0,
871
+ zIndex: 99990,
872
+ width: PANEL_WIDTH,
873
+ display: "flex",
874
+ flexDirection: "column",
875
+ background: "#0f172a",
876
+ color: "#e2e8f0",
877
+ boxShadow: "-4px 0 24px rgba(0,0,0,0.3)",
878
+ fontFamily: "system-ui, -apple-system, sans-serif",
879
+ fontSize: 13
880
+ },
881
+ children: [
882
+ /* @__PURE__ */ jsxRuntime.jsxs(
883
+ "div",
884
+ {
885
+ style: {
886
+ padding: "16px 20px",
887
+ display: "flex",
888
+ alignItems: "center",
889
+ justifyContent: "space-between",
890
+ borderBottom: "1px solid #1e293b"
891
+ },
892
+ children: [
893
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
894
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 700, fontSize: 15 }, children: "Agent DevTools" }),
895
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: "#64748b", marginTop: 2 }, children: [
896
+ availableActions.length,
897
+ " actions registered \xB7 ",
898
+ mode,
899
+ " mode"
900
+ ] })
901
+ ] }),
902
+ /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setOpen(false), style: closeBtnStyle, children: "\u2715" })
903
+ ]
904
+ }
905
+ ),
906
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", borderBottom: "1px solid #1e293b" }, children: [
907
+ /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setTab("actions"), style: tabStyle(tab === "actions"), children: "Actions" }),
908
+ /* @__PURE__ */ jsxRuntime.jsxs("button", { onClick: () => setTab("log"), style: tabStyle(tab === "log"), children: [
909
+ "Log ",
910
+ log.length > 0 && `(${log.length})`
911
+ ] })
912
+ ] }),
913
+ tab === "actions" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, overflowY: "auto", minHeight: 0 }, children: [
914
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "12px 20px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
915
+ "input",
916
+ {
917
+ value: filter,
918
+ onChange: (e) => setFilter(e.target.value),
919
+ placeholder: "Filter actions...",
920
+ style: filterInputStyle
921
+ }
922
+ ) }),
923
+ filtered.length > 0 && filtered.map((action) => /* @__PURE__ */ jsxRuntime.jsx(
924
+ ActionRow,
925
+ {
926
+ action,
927
+ schemas,
928
+ expanded: expandedAction === action.name,
929
+ onToggle: () => setExpandedAction(expandedAction === action.name ? null : action.name),
930
+ fieldValues: paramInputs[action.name] ?? {},
931
+ onFieldChange: (field, value) => setFieldValue(action.name, field, value),
932
+ onExecute: () => handleExecute(action),
933
+ isExecuting
934
+ },
935
+ action.name
936
+ )),
937
+ filtered.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: 20, color: "#475569", textAlign: "center" }, children: filter ? "No matching actions" : "No actions registered" })
938
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, overflowY: "auto", minHeight: 0 }, children: log.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: 20, color: "#475569", textAlign: "center" }, children: "No executions yet. Run an action to see results here." }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
939
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "8px 20px", display: "flex", justifyContent: "flex-end" }, children: /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setLog([]), style: clearBtnStyle, children: "Clear" }) }),
940
+ log.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "10px 20px", borderBottom: "1px solid #1e293b" }, children: [
941
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
942
+ /* @__PURE__ */ jsxRuntime.jsx(StatusDot, { result: entry.result }),
943
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, fontSize: 13 }, children: entry.action }),
944
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: "auto", fontSize: 11, color: "#475569" }, children: new Date(entry.timestamp).toLocaleTimeString() })
945
+ ] }),
946
+ entry.params && /* @__PURE__ */ jsxRuntime.jsx("pre", { style: logParamsStyle, children: JSON.stringify(entry.params, null, 2) }),
947
+ entry.result && !entry.result.success && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 4, fontSize: 12, color: "#f87171" }, children: entry.result.error })
948
+ ] }, entry.id)),
949
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: logEndRef })
950
+ ] }) })
951
+ ]
952
+ }
953
+ )
954
+ ] });
955
+ }
956
+ function ActionRow({
957
+ action,
958
+ schemas,
959
+ expanded,
960
+ onToggle,
961
+ fieldValues,
962
+ onFieldChange,
963
+ onExecute,
964
+ isExecuting,
965
+ badge
966
+ }) {
967
+ const fields = getSchemaFields(schemas, action.name);
968
+ return /* @__PURE__ */ jsxRuntime.jsxs(
969
+ "div",
970
+ {
971
+ style: {
972
+ padding: "10px 20px",
973
+ borderBottom: "1px solid #1e293b",
974
+ opacity: action.disabled ? 0.5 : 1,
975
+ cursor: "pointer"
976
+ },
977
+ onKeyDown: (e) => {
978
+ if (e.key === "Enter" && expanded && !action.disabled && !isExecuting) {
979
+ e.preventDefault();
980
+ onExecute();
981
+ }
982
+ },
983
+ children: [
984
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { onClick: onToggle, style: { display: "flex", alignItems: "center", gap: 8 }, children: [
985
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#475569", fontSize: 10, flexShrink: 0 }, children: expanded ? "\u25BC" : "\u25B6" }),
986
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
987
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
988
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, color: "#93c5fd" }, children: action.name }),
989
+ badge && /* @__PURE__ */ jsxRuntime.jsx(
990
+ "span",
991
+ {
992
+ style: {
993
+ fontSize: 9,
994
+ padding: "1px 5px",
995
+ borderRadius: 3,
996
+ background: "#1e3a5f",
997
+ color: "#60a5fa",
998
+ fontWeight: 600
999
+ },
1000
+ children: badge
1001
+ }
1002
+ ),
1003
+ action.disabled && /* @__PURE__ */ jsxRuntime.jsx(
1004
+ "span",
1005
+ {
1006
+ style: {
1007
+ fontSize: 9,
1008
+ padding: "1px 5px",
1009
+ borderRadius: 3,
1010
+ background: "#3f1d1d",
1011
+ color: "#f87171",
1012
+ fontWeight: 600
1013
+ },
1014
+ children: "disabled"
1015
+ }
1016
+ )
1017
+ ] }),
1018
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#94a3b8", fontSize: 12, marginTop: 2 }, children: action.disabled && action.disabledReason ? action.disabledReason : action.description })
1019
+ ] }),
1020
+ /* @__PURE__ */ jsxRuntime.jsx(
1021
+ "button",
1022
+ {
1023
+ onClick: (e) => {
1024
+ e.stopPropagation();
1025
+ onExecute();
1026
+ },
1027
+ disabled: action.disabled || isExecuting,
1028
+ style: {
1029
+ padding: "5px 14px",
1030
+ borderRadius: 6,
1031
+ border: "none",
1032
+ fontSize: 12,
1033
+ fontWeight: 600,
1034
+ cursor: action.disabled ? "not-allowed" : "pointer",
1035
+ background: action.disabled ? "#334155" : "#3b82f6",
1036
+ color: "white",
1037
+ flexShrink: 0
1038
+ },
1039
+ children: isExecuting ? "\xB7\xB7\xB7" : "Run"
1040
+ }
1041
+ )
1042
+ ] }),
1043
+ expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 10, marginLeft: 18 }, children: fields.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: fields.map((field) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1044
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { style: { fontSize: 11, color: "#64748b", display: "block", marginBottom: 3 }, children: [
1045
+ field.name,
1046
+ field.isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#f87171", marginLeft: 2 }, children: "*" }),
1047
+ field.description && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#475569", marginLeft: 6 }, children: field.description })
1048
+ ] }),
1049
+ field.enumValues ? /* @__PURE__ */ jsxRuntime.jsxs(
1050
+ "select",
1051
+ {
1052
+ value: fieldValues[field.name] ?? "",
1053
+ onChange: (e) => onFieldChange(field.name, e.target.value),
1054
+ style: fieldSelectStyle,
1055
+ children: [
1056
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select..." }),
1057
+ field.enumValues.map((v) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: v, children: v }, v))
1058
+ ]
1059
+ }
1060
+ ) : field.type === "boolean" ? /* @__PURE__ */ jsxRuntime.jsxs(
1061
+ "select",
1062
+ {
1063
+ value: fieldValues[field.name] ?? "",
1064
+ onChange: (e) => onFieldChange(field.name, e.target.value),
1065
+ style: fieldSelectStyle,
1066
+ children: [
1067
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select..." }),
1068
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "true", children: "true" }),
1069
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "false", children: "false" })
1070
+ ]
1071
+ }
1072
+ ) : field.type === "array" ? /* @__PURE__ */ jsxRuntime.jsx(
1073
+ "textarea",
1074
+ {
1075
+ value: fieldValues[field.name] ?? "",
1076
+ onChange: (e) => onFieldChange(field.name, e.target.value),
1077
+ placeholder: "[1, 2, 3]",
1078
+ rows: 2,
1079
+ style: textareaStyle
1080
+ }
1081
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1082
+ "input",
1083
+ {
1084
+ type: field.type === "number" || field.type === "integer" ? "number" : "text",
1085
+ value: fieldValues[field.name] ?? "",
1086
+ onChange: (e) => onFieldChange(field.name, e.target.value),
1087
+ placeholder: field.description ?? field.name,
1088
+ style: fieldInputStyle
1089
+ }
1090
+ )
1091
+ ] }, field.name)) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: "#475569" }, children: "No parameters" }) })
1092
+ ]
1093
+ }
1094
+ );
1095
+ }
1096
+ function StatusDot({ result }) {
1097
+ const color = !result ? "#fbbf24" : result.success ? "#4ade80" : "#f87171";
1098
+ return /* @__PURE__ */ jsxRuntime.jsx(
1099
+ "span",
1100
+ {
1101
+ style: {
1102
+ width: 8,
1103
+ height: 8,
1104
+ borderRadius: "50%",
1105
+ background: color,
1106
+ display: "inline-block",
1107
+ flexShrink: 0
1108
+ }
1109
+ }
1110
+ );
1111
+ }
1112
+ var closeBtnStyle = {
1113
+ width: 28,
1114
+ height: 28,
1115
+ borderRadius: 6,
1116
+ border: "1px solid #334155",
1117
+ background: "transparent",
1118
+ color: "#94a3b8",
1119
+ cursor: "pointer",
1120
+ fontSize: 14,
1121
+ display: "flex",
1122
+ alignItems: "center",
1123
+ justifyContent: "center"
1124
+ };
1125
+ var tabStyle = (active) => ({
1126
+ flex: 1,
1127
+ padding: "10px 0",
1128
+ border: "none",
1129
+ cursor: "pointer",
1130
+ fontSize: 13,
1131
+ fontWeight: 600,
1132
+ fontFamily: "inherit",
1133
+ background: active ? "#1e293b" : "transparent",
1134
+ color: active ? "#e2e8f0" : "#64748b",
1135
+ borderBottom: active ? "2px solid #3b82f6" : "2px solid transparent"
1136
+ });
1137
+ var filterInputStyle = {
1138
+ width: "100%",
1139
+ background: "#1e293b",
1140
+ border: "1px solid #334155",
1141
+ borderRadius: 6,
1142
+ padding: "8px 12px",
1143
+ color: "#e2e8f0",
1144
+ fontSize: 13,
1145
+ outline: "none",
1146
+ fontFamily: "inherit"
1147
+ };
1148
+ var clearBtnStyle = {
1149
+ padding: "4px 10px",
1150
+ borderRadius: 4,
1151
+ border: "1px solid #334155",
1152
+ background: "transparent",
1153
+ color: "#64748b",
1154
+ cursor: "pointer",
1155
+ fontSize: 11,
1156
+ fontFamily: "inherit"
1157
+ };
1158
+ var fieldInputStyle = {
1159
+ width: "100%",
1160
+ background: "#1e293b",
1161
+ border: "1px solid #334155",
1162
+ borderRadius: 6,
1163
+ padding: "7px 10px",
1164
+ color: "#e2e8f0",
1165
+ fontSize: 12,
1166
+ outline: "none",
1167
+ fontFamily: "inherit"
1168
+ };
1169
+ var fieldSelectStyle = {
1170
+ width: "100%",
1171
+ background: "#1e293b",
1172
+ border: "1px solid #334155",
1173
+ borderRadius: 6,
1174
+ padding: "7px 10px",
1175
+ color: "#e2e8f0",
1176
+ fontSize: 12,
1177
+ outline: "none",
1178
+ fontFamily: "inherit",
1179
+ cursor: "pointer"
1180
+ };
1181
+ var textareaStyle = {
1182
+ width: "100%",
1183
+ background: "#1e293b",
1184
+ border: "1px solid #334155",
1185
+ borderRadius: 6,
1186
+ padding: "8px 10px",
1187
+ color: "#e2e8f0",
1188
+ fontSize: 12,
1189
+ outline: "none",
1190
+ resize: "vertical",
1191
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace"
1192
+ };
1193
+ var logParamsStyle = {
1194
+ marginTop: 4,
1195
+ padding: "6px 8px",
1196
+ background: "#1e293b",
1197
+ borderRadius: 4,
1198
+ fontSize: 11,
1199
+ color: "#94a3b8",
1200
+ overflow: "auto",
1201
+ maxHeight: 80,
1202
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace"
1203
+ };
1204
+ function useAgentAction(config) {
1205
+ const context = react.useContext(AgentActionContext);
1206
+ if (!context) {
1207
+ throw new Error("useAgentAction must be used within an AgentActionProvider");
1208
+ }
1209
+ const configRef = react.useRef(config);
1210
+ configRef.current = config;
1211
+ const { registerAction, unregisterAction } = context;
1212
+ react.useEffect(() => {
1213
+ const items = Array.isArray(configRef.current) ? configRef.current : [configRef.current];
1214
+ for (const item of items) {
1215
+ const onExecute = item.onExecute;
1216
+ const steps = item.steps;
1217
+ registerAction({
1218
+ name: item.name,
1219
+ description: item.description,
1220
+ parameters: item.parameters,
1221
+ onExecute: onExecute ? (params) => onExecute(params) : void 0,
1222
+ disabled: item.disabled ?? false,
1223
+ disabledReason: item.disabledReason,
1224
+ getExecutionTargets: () => {
1225
+ if (!steps?.length) return [];
1226
+ return steps.map((s) => ({
1227
+ label: s.label,
1228
+ element: null,
1229
+ fromParam: s.fromParam,
1230
+ fromTarget: s.fromTarget,
1231
+ setParam: s.setParam,
1232
+ setValue: s.setValue,
1233
+ onSetValue: s.onSetValue,
1234
+ prepareView: s.prepareView
1235
+ }));
1236
+ }
1237
+ });
1238
+ }
1239
+ return () => {
1240
+ const items2 = Array.isArray(configRef.current) ? configRef.current : [configRef.current];
1241
+ for (const item of items2) {
1242
+ unregisterAction(item.name);
1243
+ }
1244
+ };
1245
+ }, [registerAction, unregisterAction]);
1246
+ }
1247
+ function useAgentCommandRouter(fallback, getActionName) {
1248
+ const { execute, availableActions } = useAgentActions();
1249
+ return react.useCallback(
1250
+ async (command) => {
1251
+ const actionName = getActionName(command);
1252
+ const isRegistered = availableActions.some((a) => a.name === actionName && !a.disabled);
1253
+ if (isRegistered) {
1254
+ await execute(actionName, command);
1255
+ return;
1256
+ }
1257
+ await fallback?.(command);
1258
+ },
1259
+ [execute, availableActions, fallback, getActionName]
1260
+ );
1261
+ }
1262
+
1263
+ exports.AgentAction = AgentAction;
1264
+ exports.AgentActionProvider = AgentActionProvider;
1265
+ exports.AgentDevTools = AgentDevTools;
1266
+ exports.AgentStep = AgentStep;
1267
+ exports.AgentTarget = AgentTarget;
1268
+ exports.generateToolSchemas = generateToolSchemas;
1269
+ exports.useAgentAction = useAgentAction;
1270
+ exports.useAgentActions = useAgentActions;
1271
+ exports.useAgentCommandRouter = useAgentCommandRouter;
1272
+ exports.zodToJsonSchema = zodToJsonSchema;
1273
+ //# sourceMappingURL=index.js.map
1274
+ //# sourceMappingURL=index.js.map