@modelnex/sdk 0.5.39 → 0.5.40

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
@@ -3742,6 +3742,20 @@ function isValueBearingElement(element) {
3742
3742
  element && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)
3743
3743
  );
3744
3744
  }
3745
+ var DEFAULT_TEXT_INPUT_IDLE_COMMIT_MS = 700;
3746
+ var DEFAULT_SELECTION_INPUT_IDLE_COMMIT_MS = 250;
3747
+ function getManualInputCommitPolicy(target) {
3748
+ const tagName = String(target.tagName || "").toLowerCase();
3749
+ const role = String(target.role || "").toLowerCase();
3750
+ const inputType = String(target.type || "").toLowerCase();
3751
+ const isContentEditable = Boolean(target.isContentEditable);
3752
+ const isSelectionLike = tagName === "select" || role === "combobox" || ["checkbox", "radio", "range", "color", "date", "datetime-local", "month", "time", "week"].includes(inputType);
3753
+ return {
3754
+ idleCommitMs: isSelectionLike ? DEFAULT_SELECTION_INPUT_IDLE_COMMIT_MS : DEFAULT_TEXT_INPUT_IDLE_COMMIT_MS,
3755
+ commitOnBlur: !isSelectionLike || tagName === "select" || role === "combobox" || isContentEditable,
3756
+ commitOnChange: true
3757
+ };
3758
+ }
3745
3759
  function resolveWaitTargetElement(element) {
3746
3760
  if (isValueBearingElement(element) || element.isContentEditable) {
3747
3761
  return element;
@@ -3761,9 +3775,40 @@ function readWaitTargetValue(element) {
3761
3775
  if (isValueBearingElement(element)) {
3762
3776
  return element.value.trim();
3763
3777
  }
3778
+ const genericValue = element.value;
3779
+ if (typeof genericValue === "string") {
3780
+ return genericValue.trim();
3781
+ }
3782
+ if (typeof genericValue === "number" && Number.isFinite(genericValue)) {
3783
+ return String(genericValue).trim();
3784
+ }
3764
3785
  if (element.isContentEditable) {
3765
3786
  return (element.textContent || "").trim();
3766
3787
  }
3788
+ const ariaValueText = element.getAttribute("aria-valuetext");
3789
+ if (typeof ariaValueText === "string" && ariaValueText.trim()) {
3790
+ return ariaValueText.trim();
3791
+ }
3792
+ const ariaValueNow = element.getAttribute("aria-valuenow");
3793
+ if (typeof ariaValueNow === "string" && ariaValueNow.trim()) {
3794
+ return ariaValueNow.trim();
3795
+ }
3796
+ if (element.getAttribute("role") === "textbox" || element.getAttribute("role") === "combobox") {
3797
+ const nestedControl = element.querySelector(
3798
+ 'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [contenteditable="true"], [role="textbox"], [role="combobox"]'
3799
+ );
3800
+ if (nestedControl && nestedControl !== element) {
3801
+ const nestedValue = readWaitTargetValue(nestedControl);
3802
+ if (nestedValue) {
3803
+ return nestedValue;
3804
+ }
3805
+ }
3806
+ return (element.textContent || "").trim();
3807
+ }
3808
+ const shadowInput = findInputInShadowRoot(element);
3809
+ if (shadowInput) {
3810
+ return shadowInput.value.trim();
3811
+ }
3767
3812
  return "";
3768
3813
  }
3769
3814
  function buildManualCompletionTranscript(step, eventName) {
@@ -3785,6 +3830,12 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
3785
3830
  const target = resolveWaitTargetElement(rawTarget);
3786
3831
  const completionTranscript = buildManualCompletionTranscript(step, eventName);
3787
3832
  const isInputLikeEvent = isInputLikeWait(eventName, step);
3833
+ const commitPolicy = getManualInputCommitPolicy({
3834
+ tagName: target.tagName,
3835
+ role: target.getAttribute("role"),
3836
+ type: target.type ?? null,
3837
+ isContentEditable: target.isContentEditable
3838
+ });
3788
3839
  if (isInputLikeEvent && readWaitTargetValue(target)) {
3789
3840
  const initialValue = readWaitTargetValue(target);
3790
3841
  return {
@@ -3796,6 +3847,8 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
3796
3847
  let cleanup = () => void 0;
3797
3848
  const promise = new Promise((resolve) => {
3798
3849
  const listeners2 = [];
3850
+ let observer = null;
3851
+ let idleTimer = null;
3799
3852
  let settled = false;
3800
3853
  const finish = () => {
3801
3854
  if (settled) return;
@@ -3808,20 +3861,61 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
3808
3861
  listeners2.push({ node, type, handler });
3809
3862
  };
3810
3863
  if (isInputLikeEvent) {
3811
- const handleInputLikeEvent = () => {
3864
+ const clearIdleCommit = () => {
3865
+ if (idleTimer) {
3866
+ clearTimeout(idleTimer);
3867
+ idleTimer = null;
3868
+ }
3869
+ };
3870
+ const scheduleIdleCommit = () => {
3871
+ const currentValue = readWaitTargetValue(target);
3872
+ if (!currentValue) {
3873
+ clearIdleCommit();
3874
+ return;
3875
+ }
3876
+ clearIdleCommit();
3877
+ idleTimer = setTimeout(() => {
3878
+ idleTimer = null;
3879
+ finish();
3880
+ }, commitPolicy.idleCommitMs);
3881
+ };
3882
+ const handleImmediateCommitEvent = () => {
3812
3883
  const currentValue = readWaitTargetValue(target);
3813
3884
  if (currentValue) {
3885
+ clearIdleCommit();
3814
3886
  finish();
3815
3887
  }
3816
3888
  };
3817
- addListener(target, "input", handleInputLikeEvent);
3818
- addListener(target, "change", handleInputLikeEvent);
3819
- addListener(target, "blur", handleInputLikeEvent);
3889
+ addListener(target, "input", scheduleIdleCommit);
3890
+ if (commitPolicy.commitOnChange) {
3891
+ addListener(target, "change", handleImmediateCommitEvent);
3892
+ }
3893
+ if (commitPolicy.commitOnBlur) {
3894
+ addListener(target, "blur", handleImmediateCommitEvent);
3895
+ }
3896
+ if (typeof MutationObserver !== "undefined") {
3897
+ observer = new MutationObserver(() => {
3898
+ scheduleIdleCommit();
3899
+ });
3900
+ observer.observe(target, {
3901
+ subtree: true,
3902
+ childList: true,
3903
+ characterData: true,
3904
+ attributes: true,
3905
+ attributeFilter: ["value", "aria-valuetext", "aria-valuenow", "aria-activedescendant"]
3906
+ });
3907
+ }
3820
3908
  } else {
3821
3909
  const handleActionEvent = () => finish();
3822
3910
  addListener(target, eventName, handleActionEvent);
3823
3911
  }
3824
3912
  cleanup = () => {
3913
+ if (idleTimer) {
3914
+ clearTimeout(idleTimer);
3915
+ idleTimer = null;
3916
+ }
3917
+ observer?.disconnect();
3918
+ observer = null;
3825
3919
  listeners2.forEach(({ node, type, handler }) => node.removeEventListener(type, handler));
3826
3920
  listeners2.length = 0;
3827
3921
  };
package/dist/index.mjs CHANGED
@@ -3531,6 +3531,20 @@ function isValueBearingElement(element) {
3531
3531
  element && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)
3532
3532
  );
3533
3533
  }
3534
+ var DEFAULT_TEXT_INPUT_IDLE_COMMIT_MS = 700;
3535
+ var DEFAULT_SELECTION_INPUT_IDLE_COMMIT_MS = 250;
3536
+ function getManualInputCommitPolicy(target) {
3537
+ const tagName = String(target.tagName || "").toLowerCase();
3538
+ const role = String(target.role || "").toLowerCase();
3539
+ const inputType = String(target.type || "").toLowerCase();
3540
+ const isContentEditable = Boolean(target.isContentEditable);
3541
+ const isSelectionLike = tagName === "select" || role === "combobox" || ["checkbox", "radio", "range", "color", "date", "datetime-local", "month", "time", "week"].includes(inputType);
3542
+ return {
3543
+ idleCommitMs: isSelectionLike ? DEFAULT_SELECTION_INPUT_IDLE_COMMIT_MS : DEFAULT_TEXT_INPUT_IDLE_COMMIT_MS,
3544
+ commitOnBlur: !isSelectionLike || tagName === "select" || role === "combobox" || isContentEditable,
3545
+ commitOnChange: true
3546
+ };
3547
+ }
3534
3548
  function resolveWaitTargetElement(element) {
3535
3549
  if (isValueBearingElement(element) || element.isContentEditable) {
3536
3550
  return element;
@@ -3550,9 +3564,40 @@ function readWaitTargetValue(element) {
3550
3564
  if (isValueBearingElement(element)) {
3551
3565
  return element.value.trim();
3552
3566
  }
3567
+ const genericValue = element.value;
3568
+ if (typeof genericValue === "string") {
3569
+ return genericValue.trim();
3570
+ }
3571
+ if (typeof genericValue === "number" && Number.isFinite(genericValue)) {
3572
+ return String(genericValue).trim();
3573
+ }
3553
3574
  if (element.isContentEditable) {
3554
3575
  return (element.textContent || "").trim();
3555
3576
  }
3577
+ const ariaValueText = element.getAttribute("aria-valuetext");
3578
+ if (typeof ariaValueText === "string" && ariaValueText.trim()) {
3579
+ return ariaValueText.trim();
3580
+ }
3581
+ const ariaValueNow = element.getAttribute("aria-valuenow");
3582
+ if (typeof ariaValueNow === "string" && ariaValueNow.trim()) {
3583
+ return ariaValueNow.trim();
3584
+ }
3585
+ if (element.getAttribute("role") === "textbox" || element.getAttribute("role") === "combobox") {
3586
+ const nestedControl = element.querySelector(
3587
+ 'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [contenteditable="true"], [role="textbox"], [role="combobox"]'
3588
+ );
3589
+ if (nestedControl && nestedControl !== element) {
3590
+ const nestedValue = readWaitTargetValue(nestedControl);
3591
+ if (nestedValue) {
3592
+ return nestedValue;
3593
+ }
3594
+ }
3595
+ return (element.textContent || "").trim();
3596
+ }
3597
+ const shadowInput = findInputInShadowRoot(element);
3598
+ if (shadowInput) {
3599
+ return shadowInput.value.trim();
3600
+ }
3556
3601
  return "";
3557
3602
  }
3558
3603
  function buildManualCompletionTranscript(step, eventName) {
@@ -3574,6 +3619,12 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
3574
3619
  const target = resolveWaitTargetElement(rawTarget);
3575
3620
  const completionTranscript = buildManualCompletionTranscript(step, eventName);
3576
3621
  const isInputLikeEvent = isInputLikeWait(eventName, step);
3622
+ const commitPolicy = getManualInputCommitPolicy({
3623
+ tagName: target.tagName,
3624
+ role: target.getAttribute("role"),
3625
+ type: target.type ?? null,
3626
+ isContentEditable: target.isContentEditable
3627
+ });
3577
3628
  if (isInputLikeEvent && readWaitTargetValue(target)) {
3578
3629
  const initialValue = readWaitTargetValue(target);
3579
3630
  return {
@@ -3585,6 +3636,8 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
3585
3636
  let cleanup = () => void 0;
3586
3637
  const promise = new Promise((resolve) => {
3587
3638
  const listeners2 = [];
3639
+ let observer = null;
3640
+ let idleTimer = null;
3588
3641
  let settled = false;
3589
3642
  const finish = () => {
3590
3643
  if (settled) return;
@@ -3597,20 +3650,61 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
3597
3650
  listeners2.push({ node, type, handler });
3598
3651
  };
3599
3652
  if (isInputLikeEvent) {
3600
- const handleInputLikeEvent = () => {
3653
+ const clearIdleCommit = () => {
3654
+ if (idleTimer) {
3655
+ clearTimeout(idleTimer);
3656
+ idleTimer = null;
3657
+ }
3658
+ };
3659
+ const scheduleIdleCommit = () => {
3660
+ const currentValue = readWaitTargetValue(target);
3661
+ if (!currentValue) {
3662
+ clearIdleCommit();
3663
+ return;
3664
+ }
3665
+ clearIdleCommit();
3666
+ idleTimer = setTimeout(() => {
3667
+ idleTimer = null;
3668
+ finish();
3669
+ }, commitPolicy.idleCommitMs);
3670
+ };
3671
+ const handleImmediateCommitEvent = () => {
3601
3672
  const currentValue = readWaitTargetValue(target);
3602
3673
  if (currentValue) {
3674
+ clearIdleCommit();
3603
3675
  finish();
3604
3676
  }
3605
3677
  };
3606
- addListener(target, "input", handleInputLikeEvent);
3607
- addListener(target, "change", handleInputLikeEvent);
3608
- addListener(target, "blur", handleInputLikeEvent);
3678
+ addListener(target, "input", scheduleIdleCommit);
3679
+ if (commitPolicy.commitOnChange) {
3680
+ addListener(target, "change", handleImmediateCommitEvent);
3681
+ }
3682
+ if (commitPolicy.commitOnBlur) {
3683
+ addListener(target, "blur", handleImmediateCommitEvent);
3684
+ }
3685
+ if (typeof MutationObserver !== "undefined") {
3686
+ observer = new MutationObserver(() => {
3687
+ scheduleIdleCommit();
3688
+ });
3689
+ observer.observe(target, {
3690
+ subtree: true,
3691
+ childList: true,
3692
+ characterData: true,
3693
+ attributes: true,
3694
+ attributeFilter: ["value", "aria-valuetext", "aria-valuenow", "aria-activedescendant"]
3695
+ });
3696
+ }
3609
3697
  } else {
3610
3698
  const handleActionEvent = () => finish();
3611
3699
  addListener(target, eventName, handleActionEvent);
3612
3700
  }
3613
3701
  cleanup = () => {
3702
+ if (idleTimer) {
3703
+ clearTimeout(idleTimer);
3704
+ idleTimer = null;
3705
+ }
3706
+ observer?.disconnect();
3707
+ observer = null;
3614
3708
  listeners2.forEach(({ node, type, handler }) => node.removeEventListener(type, handler));
3615
3709
  listeners2.length = 0;
3616
3710
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelnex/sdk",
3
- "version": "0.5.39",
3
+ "version": "0.5.40",
4
4
  "description": "React SDK for natural language control of web apps via AI agents",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",