@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/dist/index.js CHANGED
@@ -437,6 +437,20 @@ async function executeAction(action, params, config) {
437
437
  return executeGuided(action, params, config);
438
438
  }
439
439
  var AgentActionContext = react.createContext(null);
440
+ function definitionToRegisteredAction(def) {
441
+ return {
442
+ name: def.name,
443
+ description: def.description,
444
+ parameters: def.parameters,
445
+ onExecute: def.onExecute,
446
+ disabled: false,
447
+ disabledReason: void 0,
448
+ getExecutionTargets: () => [],
449
+ route: def.route,
450
+ navigateVia: def.navigateVia,
451
+ mountTimeout: def.mountTimeout
452
+ };
453
+ }
440
454
  function AgentActionProvider({
441
455
  mode = "guided",
442
456
  stepDelay = 600,
@@ -446,24 +460,61 @@ function AgentActionProvider({
446
460
  cursorEnabled = true,
447
461
  children,
448
462
  onExecutionStart,
449
- onExecutionComplete
463
+ onExecutionComplete,
464
+ registry,
465
+ navigate
450
466
  }) {
451
467
  const actionsRef = react.useRef(/* @__PURE__ */ new Map());
452
468
  const targetsRef = react.useRef(/* @__PURE__ */ new Map());
469
+ const registryRef = react.useRef(/* @__PURE__ */ new Map());
470
+ const navigateRef = react.useRef(navigate);
471
+ navigateRef.current = navigate;
453
472
  const [version, setVersion] = react.useState(0);
454
473
  const [isExecuting, setIsExecuting] = react.useState(false);
455
474
  const currentExecutionRef = react.useRef(null);
475
+ react.useEffect(() => {
476
+ const newNames = /* @__PURE__ */ new Set();
477
+ for (const def of registry ?? []) {
478
+ newNames.add(def.name);
479
+ const registryAction = definitionToRegisteredAction(def);
480
+ registryRef.current.set(def.name, registryAction);
481
+ const existing = actionsRef.current.get(def.name);
482
+ if (!existing || existing.getExecutionTargets().length === 0) {
483
+ actionsRef.current.set(def.name, registryAction);
484
+ }
485
+ }
486
+ for (const name of registryRef.current.keys()) {
487
+ if (!newNames.has(name)) {
488
+ registryRef.current.delete(name);
489
+ const current = actionsRef.current.get(name);
490
+ if (current && current.getExecutionTargets().length === 0) {
491
+ actionsRef.current.delete(name);
492
+ }
493
+ }
494
+ }
495
+ setVersion((v) => v + 1);
496
+ }, [registry]);
456
497
  const registerAction = react.useCallback((action) => {
457
498
  const existing = actionsRef.current.get(action.name);
499
+ const registryAction = registryRef.current.get(action.name);
500
+ if (registryAction) {
501
+ if (!action.route) action.route = registryAction.route;
502
+ if (!action.navigateVia) action.navigateVia = registryAction.navigateVia;
503
+ if (action.mountTimeout == null) action.mountTimeout = registryAction.mountTimeout;
504
+ }
458
505
  actionsRef.current.set(action.name, action);
459
506
  if (!existing || existing.description !== action.description || existing.disabled !== action.disabled || existing.disabledReason !== action.disabledReason) {
460
507
  setVersion((v) => v + 1);
461
508
  }
462
509
  }, []);
463
510
  const unregisterAction = react.useCallback((name) => {
464
- if (actionsRef.current.delete(name)) {
465
- setVersion((v) => v + 1);
511
+ const registryAction = registryRef.current.get(name);
512
+ if (registryAction) {
513
+ actionsRef.current.set(name, registryAction);
514
+ } else {
515
+ actionsRef.current.delete(name);
466
516
  }
517
+ setVersion((v) => v + 1);
467
518
  }, []);
468
519
  const registerTarget = react.useCallback((id, entry) => {
469
520
  targetsRef.current.set(id, entry);
@@ -508,12 +559,29 @@ function AgentActionProvider({
508
559
  },
509
560
  []
510
561
  );
562
+ const waitForActionMount = react.useCallback(
563
+ async (name, signal, timeout = 5e3) => {
564
+ const maxWait = timeout;
565
+ const pollInterval = 50;
566
+ const start = Date.now();
567
+ while (Date.now() - start < maxWait) {
568
+ if (signal?.aborted) return null;
569
+ const current = actionsRef.current.get(name);
570
+ if (current && current.getExecutionTargets().length > 0) {
571
+ return current;
572
+ }
573
+ await new Promise((r) => setTimeout(r, pollInterval));
574
+ }
575
+ return actionsRef.current.get(name) ?? null;
576
+ },
577
+ []
578
+ );
511
579
  const execute = react.useCallback(
512
580
  async (actionName, params) => {
513
581
  currentExecutionRef.current?.abort();
514
582
  const controller = new AbortController();
515
583
  currentExecutionRef.current = controller;
516
- const action = actionsRef.current.get(actionName);
584
+ let action = actionsRef.current.get(actionName);
517
585
  if (!action) {
518
586
  return { success: false, actionName, error: `Action "${actionName}" not found` };
519
587
  }
@@ -527,7 +595,7 @@ function AgentActionProvider({
527
595
  setIsExecuting(true);
528
596
  onExecutionStart?.(actionName);
529
597
  try {
530
- const result = await executeAction(action, params ?? {}, {
598
+ const executorConfig = {
531
599
  mode,
532
600
  stepDelay,
533
601
  overlayOpacity,
@@ -537,7 +605,59 @@ function AgentActionProvider({
537
605
  signal: controller.signal,
538
606
  resolveTarget,
539
607
  resolveNamedTarget
540
- });
608
+ };
609
+ if (action.navigateVia && action.navigateVia.length > 0) {
610
+ for (const viaName of action.navigateVia) {
611
+ if (controller.signal.aborted) break;
612
+ const viaRegistered = actionsRef.current.get(viaName);
613
+ const viaTimeout = viaRegistered?.mountTimeout ?? 1e4;
614
+ const viaAction = await waitForActionMount(viaName, controller.signal, viaTimeout);
615
+ if (!viaAction || viaAction.getExecutionTargets().length === 0) {
616
+ return {
617
+ success: false,
618
+ actionName,
619
+ error: `Navigation chain action "${viaName}" not found or has no targets`
620
+ };
621
+ }
622
+ const viaResult = await executeAction(viaAction, {}, executorConfig);
623
+ if (!viaResult.success) {
624
+ return {
625
+ success: false,
626
+ actionName,
627
+ error: `Navigation chain failed at "${viaName}": ${viaResult.error}`
628
+ };
629
+ }
630
+ }
631
+ const mounted = await waitForActionMount(actionName, controller.signal, action.mountTimeout ?? 1e4);
632
+ if (!mounted || mounted.getExecutionTargets().length === 0) {
633
+ return {
634
+ success: false,
635
+ actionName,
636
+ error: `Action "${actionName}" did not mount after navigation chain \u2014 the page may require authentication or failed to load`
637
+ };
638
+ }
639
+ action = mounted;
640
+ } else {
641
+ const targets = action.getExecutionTargets();
642
+ if (targets.length === 0 && action.route && navigateRef.current) {
643
+ const path = action.route(params ?? {});
644
+ await navigateRef.current(path);
645
+ const mounted = await waitForActionMount(actionName, controller.signal, action.mountTimeout);
646
+ if (mounted) {
647
+ action = mounted;
648
+ }
649
+ }
650
+ }
651
+ if (action.disabled) {
652
+ const result2 = {
653
+ success: false,
654
+ actionName,
655
+ error: action.disabledReason || "Action is disabled"
656
+ };
657
+ onExecutionComplete?.(result2);
658
+ return result2;
659
+ }
660
+ const result = await executeAction(action, params ?? {}, executorConfig);
541
661
  onExecutionComplete?.(result);
542
662
  return result;
543
663
  } catch (err) {
@@ -555,7 +675,7 @@ function AgentActionProvider({
555
675
  }
556
676
  }
557
677
  },
558
- [mode, stepDelay, overlayOpacity, spotlightPadding, tooltipEnabled, cursorEnabled, onExecutionStart, onExecutionComplete, resolveTarget, resolveNamedTarget]
678
+ [mode, stepDelay, overlayOpacity, spotlightPadding, tooltipEnabled, cursorEnabled, onExecutionStart, onExecutionComplete, resolveTarget, resolveNamedTarget, waitForActionMount]
559
679
  );
560
680
  const availableActions = react.useMemo(
561
681
  () => Array.from(actionsRef.current.values()).map((a) => ({
@@ -600,19 +720,24 @@ function AgentActionProvider({
600
720
  return /* @__PURE__ */ jsxRuntime.jsx(AgentActionContext.Provider, { value: contextValue, children });
601
721
  }
602
722
  var AgentStepContext = react.createContext(null);
603
- function AgentAction({
604
- name,
605
- description,
606
- parameters,
607
- onExecute,
608
- disabled = false,
609
- disabledReason,
610
- children
611
- }) {
723
+ function AgentAction(props) {
724
+ const {
725
+ action,
726
+ onExecute,
727
+ disabled = false,
728
+ disabledReason,
729
+ children
730
+ } = props;
731
+ const name = props.name ?? action?.name;
732
+ const description = props.description ?? action?.description ?? "";
733
+ const parameters = props.parameters ?? action?.parameters;
612
734
  const context = react.useContext(AgentActionContext);
613
735
  if (!context) {
614
736
  throw new Error("AgentAction must be used within an AgentActionProvider");
615
737
  }
738
+ if (!name) {
739
+ throw new Error('AgentAction requires either a "name" prop or an "action" prop');
740
+ }
616
741
  const wrapperRef = react.useRef(null);
617
742
  const stepsRef = react.useRef(/* @__PURE__ */ new Map());
618
743
  const onExecuteRef = react.useRef(onExecute);
@@ -1251,20 +1376,34 @@ function useAgentCommandRouter(fallback, getActionName) {
1251
1376
  const actionName = getActionName(command);
1252
1377
  const isRegistered = availableActions.some((a) => a.name === actionName && !a.disabled);
1253
1378
  if (isRegistered) {
1254
- await execute(actionName, command);
1255
- return;
1379
+ return await execute(actionName, command);
1256
1380
  }
1257
1381
  await fallback?.(command);
1382
+ return void 0;
1258
1383
  },
1259
1384
  [execute, availableActions, fallback, getActionName]
1260
1385
  );
1261
1386
  }
1262
1387
 
1388
+ // src/core/defineAction.ts
1389
+ function defineAction(config) {
1390
+ return {
1391
+ name: config.name,
1392
+ description: config.description,
1393
+ parameters: config.parameters,
1394
+ route: config.route,
1395
+ onExecute: config.onExecute,
1396
+ navigateVia: config.navigateVia,
1397
+ mountTimeout: config.mountTimeout
1398
+ };
1399
+ }
1400
+
1263
1401
  exports.AgentAction = AgentAction;
1264
1402
  exports.AgentActionProvider = AgentActionProvider;
1265
1403
  exports.AgentDevTools = AgentDevTools;
1266
1404
  exports.AgentStep = AgentStep;
1267
1405
  exports.AgentTarget = AgentTarget;
1406
+ exports.defineAction = defineAction;
1268
1407
  exports.generateToolSchemas = generateToolSchemas;
1269
1408
  exports.useAgentAction = useAgentAction;
1270
1409
  exports.useAgentActions = useAgentActions;