browser-opt 1.0.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.
Files changed (107) hide show
  1. package/dist/browser-opt/index.d.ts +9 -0
  2. package/dist/browser-opt/index.d.ts.map +1 -0
  3. package/dist/browser-opt/index.js +7 -0
  4. package/dist/browser-opt/index.js.map +1 -0
  5. package/dist/browser-opt/runner/actions/index.d.ts +13 -0
  6. package/dist/browser-opt/runner/actions/index.d.ts.map +1 -0
  7. package/dist/browser-opt/runner/actions/index.js +44 -0
  8. package/dist/browser-opt/runner/actions/index.js.map +1 -0
  9. package/dist/browser-opt/runner/actions/utils/click-action.d.ts +10 -0
  10. package/dist/browser-opt/runner/actions/utils/click-action.d.ts.map +1 -0
  11. package/dist/browser-opt/runner/actions/utils/click-action.js +17 -0
  12. package/dist/browser-opt/runner/actions/utils/click-action.js.map +1 -0
  13. package/dist/browser-opt/runner/actions/utils/date-action.d.ts +21 -0
  14. package/dist/browser-opt/runner/actions/utils/date-action.d.ts.map +1 -0
  15. package/dist/browser-opt/runner/actions/utils/date-action.js +464 -0
  16. package/dist/browser-opt/runner/actions/utils/date-action.js.map +1 -0
  17. package/dist/browser-opt/runner/actions/utils/dom-action.d.ts +8 -0
  18. package/dist/browser-opt/runner/actions/utils/dom-action.d.ts.map +1 -0
  19. package/dist/browser-opt/runner/actions/utils/dom-action.js +167 -0
  20. package/dist/browser-opt/runner/actions/utils/dom-action.js.map +1 -0
  21. package/dist/browser-opt/runner/actions/utils/fill-action.d.ts +10 -0
  22. package/dist/browser-opt/runner/actions/utils/fill-action.d.ts.map +1 -0
  23. package/dist/browser-opt/runner/actions/utils/fill-action.js +20 -0
  24. package/dist/browser-opt/runner/actions/utils/fill-action.js.map +1 -0
  25. package/dist/browser-opt/runner/actions/utils/handoff-action.d.ts +10 -0
  26. package/dist/browser-opt/runner/actions/utils/handoff-action.d.ts.map +1 -0
  27. package/dist/browser-opt/runner/actions/utils/handoff-action.js +6 -0
  28. package/dist/browser-opt/runner/actions/utils/handoff-action.js.map +1 -0
  29. package/dist/browser-opt/runner/actions/utils/open-action.d.ts +10 -0
  30. package/dist/browser-opt/runner/actions/utils/open-action.d.ts.map +1 -0
  31. package/dist/browser-opt/runner/actions/utils/open-action.js +9 -0
  32. package/dist/browser-opt/runner/actions/utils/open-action.js.map +1 -0
  33. package/dist/browser-opt/runner/actions/utils/select-option-action.d.ts +17 -0
  34. package/dist/browser-opt/runner/actions/utils/select-option-action.d.ts.map +1 -0
  35. package/dist/browser-opt/runner/actions/utils/select-option-action.js +532 -0
  36. package/dist/browser-opt/runner/actions/utils/select-option-action.js.map +1 -0
  37. package/dist/browser-opt/runner/actions/utils/upload-action.d.ts +7 -0
  38. package/dist/browser-opt/runner/actions/utils/upload-action.d.ts.map +1 -0
  39. package/dist/browser-opt/runner/actions/utils/upload-action.js +173 -0
  40. package/dist/browser-opt/runner/actions/utils/upload-action.js.map +1 -0
  41. package/dist/browser-opt/runner/evidence.d.ts +18 -0
  42. package/dist/browser-opt/runner/evidence.d.ts.map +1 -0
  43. package/dist/browser-opt/runner/evidence.js +116 -0
  44. package/dist/browser-opt/runner/evidence.js.map +1 -0
  45. package/dist/browser-opt/runner/handoff.d.ts +28 -0
  46. package/dist/browser-opt/runner/handoff.d.ts.map +1 -0
  47. package/dist/browser-opt/runner/handoff.js +132 -0
  48. package/dist/browser-opt/runner/handoff.js.map +1 -0
  49. package/dist/browser-opt/runner/index.d.ts +11 -0
  50. package/dist/browser-opt/runner/index.d.ts.map +1 -0
  51. package/dist/browser-opt/runner/index.js +244 -0
  52. package/dist/browser-opt/runner/index.js.map +1 -0
  53. package/dist/browser-opt/runner/step-executor.d.ts +5 -0
  54. package/dist/browser-opt/runner/step-executor.d.ts.map +1 -0
  55. package/dist/browser-opt/runner/step-executor.js +302 -0
  56. package/dist/browser-opt/runner/step-executor.js.map +1 -0
  57. package/dist/browser-opt/type.d.ts +120 -0
  58. package/dist/browser-opt/type.d.ts.map +1 -0
  59. package/dist/browser-opt/type.js +2 -0
  60. package/dist/browser-opt/type.js.map +1 -0
  61. package/dist/browser-opt/utils.d.ts +48 -0
  62. package/dist/browser-opt/utils.d.ts.map +1 -0
  63. package/dist/browser-opt/utils.js +885 -0
  64. package/dist/browser-opt/utils.js.map +1 -0
  65. package/dist/browser-opt/workflow/index.d.ts +7 -0
  66. package/dist/browser-opt/workflow/index.d.ts.map +1 -0
  67. package/dist/browser-opt/workflow/index.js +6 -0
  68. package/dist/browser-opt/workflow/index.js.map +1 -0
  69. package/dist/browser-opt/workflow/matcher.d.ts +12 -0
  70. package/dist/browser-opt/workflow/matcher.d.ts.map +1 -0
  71. package/dist/browser-opt/workflow/matcher.js +102 -0
  72. package/dist/browser-opt/workflow/matcher.js.map +1 -0
  73. package/dist/browser-opt/workflow/store.d.ts +15 -0
  74. package/dist/browser-opt/workflow/store.d.ts.map +1 -0
  75. package/dist/browser-opt/workflow/store.js +175 -0
  76. package/dist/browser-opt/workflow/store.js.map +1 -0
  77. package/dist/browser-opt/workflow/type.d.ts +43 -0
  78. package/dist/browser-opt/workflow/type.d.ts.map +1 -0
  79. package/dist/browser-opt/workflow/type.js +6 -0
  80. package/dist/browser-opt/workflow/type.js.map +1 -0
  81. package/dist/cli/browser-opt.d.ts +3 -0
  82. package/dist/cli/browser-opt.d.ts.map +1 -0
  83. package/dist/cli/browser-opt.js +11 -0
  84. package/dist/cli/browser-opt.js.map +1 -0
  85. package/dist/cli/commands/browser-opt.d.ts +2 -0
  86. package/dist/cli/commands/browser-opt.d.ts.map +1 -0
  87. package/dist/cli/commands/browser-opt.js +514 -0
  88. package/dist/cli/commands/browser-opt.js.map +1 -0
  89. package/dist/cli/commands/setup.d.ts +10 -0
  90. package/dist/cli/commands/setup.d.ts.map +1 -0
  91. package/dist/cli/commands/setup.js +35 -0
  92. package/dist/cli/commands/setup.js.map +1 -0
  93. package/dist/cli/utils/args.d.ts +17 -0
  94. package/dist/cli/utils/args.d.ts.map +1 -0
  95. package/dist/cli/utils/args.js +74 -0
  96. package/dist/cli/utils/args.js.map +1 -0
  97. package/dist/cli/utils/constants.d.ts +8 -0
  98. package/dist/cli/utils/constants.d.ts.map +1 -0
  99. package/dist/cli/utils/constants.js +18 -0
  100. package/dist/cli/utils/constants.js.map +1 -0
  101. package/dist/cli/utils/output.d.ts +7 -0
  102. package/dist/cli/utils/output.d.ts.map +1 -0
  103. package/dist/cli/utils/output.js +45 -0
  104. package/dist/cli/utils/output.js.map +1 -0
  105. package/package.json +35 -0
  106. package/skills/browser-opt/SKILL.md +249 -0
  107. package/skills/browser-opt/manifest.json +75 -0
@@ -0,0 +1,8 @@
1
+ /**
2
+ * browser-opt DOM 动作兜底工具,负责在 snapshot 信息缺失时按页面真实 DOM
3
+ * 的字段上下文定位控件,并执行点击、输入等通用动作。
4
+ */
5
+ import type { BrowserAgent } from '@browser-automated/browser-core/agent';
6
+ export declare function clickFieldScopedDomTarget(agent: BrowserAgent, field: string, target: string): string | null;
7
+ export declare function fillFieldScopedDomTarget(agent: BrowserAgent, field: string, value: string): string | null;
8
+ //# sourceMappingURL=dom-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom-action.d.ts","sourceRoot":"","sources":["../../../../../src/browser-opt/runner/actions/utils/dom-action.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAS1E,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiB3G;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgBzG"}
@@ -0,0 +1,167 @@
1
+ export function clickFieldScopedDomTarget(agent, field, target) {
2
+ const script = `(() => {
3
+ const helper = ${fieldScopedDomHelperSource()};
4
+ return JSON.stringify(helper.clickFieldScopedTarget(${JSON.stringify(field)}, ${JSON.stringify(target)}));
5
+ })()`;
6
+ try {
7
+ const parsed = parseEvalJson(agent.evaluate(script));
8
+ if (parsed.found && parsed.clicked) {
9
+ agent.waitMs(300);
10
+ const clickedText = parsed.targetText ? ` (${parsed.targetText.trim()})` : '';
11
+ return `click dom ${field} -> ${target}${clickedText}`;
12
+ }
13
+ return null;
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ export function fillFieldScopedDomTarget(agent, field, value) {
20
+ const script = `(() => {
21
+ const helper = ${fieldScopedDomHelperSource()};
22
+ return JSON.stringify(helper.fillFieldScopedTarget(${JSON.stringify(field)}, ${JSON.stringify(value)}));
23
+ })()`;
24
+ try {
25
+ const parsed = parseEvalJson(agent.evaluate(script));
26
+ if (parsed.found && parsed.filled) {
27
+ agent.waitMs(300);
28
+ return `fill dom ${field} ${JSON.stringify(value)}`;
29
+ }
30
+ return null;
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ function parseEvalJson(raw) {
37
+ const decoded = JSON.parse(raw.trim());
38
+ return typeof decoded === 'string'
39
+ ? JSON.parse(decoded)
40
+ : decoded;
41
+ }
42
+ /** 返回页面上下文内使用的字段近邻定位工具源码,兼容常见表单和伪控件结构。 */
43
+ function fieldScopedDomHelperSource() {
44
+ return `
45
+ (() => {
46
+ const normalize = (value) => String(value || '').replace(/[\\s::,,。;*"'‘’“”]/g, '').toLowerCase();
47
+ const visible = (element) => {
48
+ const style = window.getComputedStyle(element);
49
+ const rect = element.getBoundingClientRect();
50
+ return style.visibility !== 'hidden' && style.display !== 'none' && rect.width > 0 && rect.height > 0;
51
+ };
52
+ const textOf = (element) => [
53
+ element.textContent,
54
+ element.getAttribute('aria-label'),
55
+ element.getAttribute('placeholder'),
56
+ element.getAttribute('title'),
57
+ element.getAttribute('value'),
58
+ ].filter(Boolean).join(' ');
59
+ const textMatches = (element, text) => normalize(textOf(element)).includes(text);
60
+ const disabled = (element) => element.disabled === true || element.getAttribute('aria-disabled') === 'true' || element.matches('[disabled], .disabled, .ant-select-disabled, .is-disabled');
61
+ const clickable = (element) => {
62
+ if (disabled(element)) return false;
63
+ const style = window.getComputedStyle(element);
64
+ const role = element.getAttribute('role') || '';
65
+ return element instanceof HTMLButtonElement
66
+ || element instanceof HTMLAnchorElement
67
+ || element instanceof HTMLInputElement
68
+ || element instanceof HTMLTextAreaElement
69
+ || Boolean(element.onclick)
70
+ || ['button', 'option', 'menuitem', 'menuitemcheckbox', 'checkbox', 'radio', 'switch'].includes(role)
71
+ || element.tabIndex >= 0
72
+ || style.cursor === 'pointer'
73
+ || element.matches('.ant-select, .ant-select-selector, .ant-cascader, .ant-cascader-picker, .el-select, .el-input, .el-input__inner');
74
+ };
75
+ const inputLike = (element) => {
76
+ if (disabled(element)) return false;
77
+ if (element instanceof HTMLTextAreaElement) return true;
78
+ if (element instanceof HTMLInputElement) return !['hidden', 'file', 'checkbox', 'radio', 'button', 'submit', 'reset'].includes(element.type);
79
+ return element.isContentEditable === true;
80
+ };
81
+ const dispatchMouse = (element) => {
82
+ element.scrollIntoView({ block: 'center', inline: 'nearest' });
83
+ const rect = element.getBoundingClientRect();
84
+ const init = {
85
+ bubbles: true,
86
+ cancelable: true,
87
+ view: window,
88
+ clientX: (rect.left + rect.right) / 2,
89
+ clientY: (rect.top + rect.bottom) / 2,
90
+ };
91
+ element.dispatchEvent(new MouseEvent('pointerdown', init));
92
+ element.dispatchEvent(new MouseEvent('mousedown', init));
93
+ element.dispatchEvent(new MouseEvent('mouseup', init));
94
+ element.dispatchEvent(new MouseEvent('click', init));
95
+ };
96
+ const dispatchValue = (element, value) => {
97
+ element.scrollIntoView({ block: 'center', inline: 'nearest' });
98
+ element.focus?.();
99
+ if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
100
+ const proto = element instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
101
+ const setter = Object.getOwnPropertyDescriptor(proto, 'value')?.set;
102
+ setter?.call(element, value);
103
+ } else if (element.isContentEditable) {
104
+ element.textContent = value;
105
+ }
106
+ element.dispatchEvent(new Event('input', { bubbles: true }));
107
+ element.dispatchEvent(new Event('change', { bubbles: true }));
108
+ element.blur?.();
109
+ };
110
+ const candidates = () => [...document.body.querySelectorAll('*')].filter((element) => visible(element));
111
+ const fieldElements = (field) => {
112
+ const fieldText = normalize(field);
113
+ return candidates()
114
+ .filter((element) => textMatches(element, fieldText))
115
+ .map((element) => ({ element, rect: element.getBoundingClientRect(), textLength: normalize(textOf(element)).length }))
116
+ .sort((a, b) => a.textLength - b.textLength || (a.rect.width * a.rect.height) - (b.rect.width * b.rect.height));
117
+ };
118
+ const closestFieldContainer = (element) => element.closest('.ant-form-item, .el-form-item, .form-item, [class*="form-item"], [class*="FormItem"], [class*="field"], [class*="Field"]');
119
+ const nearestByPosition = (fields, targets) => {
120
+ const scored = [];
121
+ for (const field of fields) {
122
+ for (const item of targets) {
123
+ const rect = item.element.getBoundingClientRect();
124
+ if (rect.top < field.rect.top - 8) continue;
125
+ const verticalGap = Math.max(0, rect.top - field.rect.bottom);
126
+ if (verticalGap > 260) continue;
127
+ const horizontalGap = Math.abs(rect.left - field.rect.left);
128
+ scored.push({ element: item.element, score: verticalGap * 10 + horizontalGap });
129
+ }
130
+ }
131
+ scored.sort((a, b) => a.score - b.score);
132
+ return scored[0]?.element || null;
133
+ };
134
+ const scopedTarget = (field, predicate) => {
135
+ const fields = fieldElements(field);
136
+ for (const fieldItem of fields) {
137
+ const container = closestFieldContainer(fieldItem.element);
138
+ const scoped = container ? [...container.querySelectorAll('*')].filter((element) => visible(element) && predicate(element)) : [];
139
+ if (scoped.length > 0) {
140
+ return { element: scoped[0], fields };
141
+ }
142
+ }
143
+ const targets = candidates().filter(predicate).map((element) => ({ element }));
144
+ return { element: nearestByPosition(fields, targets), fields };
145
+ };
146
+ function clickFieldScopedTarget(field, target) {
147
+ const targetText = normalize(target);
148
+ const result = scopedTarget(field, (element) => clickable(element) && textMatches(element, targetText));
149
+ if (result.element) {
150
+ dispatchMouse(result.element);
151
+ return { found: true, clicked: true, targetText: textOf(result.element) };
152
+ }
153
+ return { found: result.fields.length > 0, clicked: false };
154
+ }
155
+ function fillFieldScopedTarget(field, value) {
156
+ const result = scopedTarget(field, inputLike);
157
+ if (result.element) {
158
+ dispatchValue(result.element, value);
159
+ return { found: true, filled: true, targetText: textOf(result.element) };
160
+ }
161
+ return { found: result.fields.length > 0, filled: false };
162
+ }
163
+ return { clickFieldScopedTarget, fillFieldScopedTarget };
164
+ })()
165
+ `;
166
+ }
167
+ //# sourceMappingURL=dom-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom-action.js","sourceRoot":"","sources":["../../../../../src/browser-opt/runner/actions/utils/dom-action.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,yBAAyB,CAAC,KAAmB,EAAE,KAAa,EAAE,MAAc;IAC1F,MAAM,MAAM,GAAG;mBACE,0BAA0B,EAAE;wDACS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;KACnG,CAAC;IAEJ,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACrD,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAClB,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9E,OAAO,aAAa,KAAK,OAAO,MAAM,GAAG,WAAW,EAAE,CAAC;QACzD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,KAAmB,EAAE,KAAa,EAAE,KAAa;IACxF,MAAM,MAAM,GAAG;mBACE,0BAA0B,EAAE;uDACQ,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;KACjG,CAAC;IAEJ,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACrD,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAClB,OAAO,YAAY,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAY,CAAC;IAClD,OAAO,OAAO,OAAO,KAAK,QAAQ;QAChC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAyB;QAC7C,CAAC,CAAC,OAA+B,CAAC;AACtC,CAAC;AAED,0CAA0C;AAC1C,SAAS,0BAA0B;IACjC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyHR,CAAC;AACF,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * browser-opt 输入动作执行器,负责定位输入框并处理登录页阻塞的 handoff。
3
+ */
4
+ import type { BrowserAgent } from '@browser-automated/browser-core/agent';
5
+ import type { DeterministicAction, SnapshotEvidence } from '../../../type.js';
6
+ /** 执行输入动作,登录页阻塞时转为 handoff,避免误报找不到业务字段。 */
7
+ export declare function executeFillAction(agent: BrowserAgent, action: Extract<DeterministicAction, {
8
+ type: 'fill';
9
+ }>, snapshot: SnapshotEvidence): string;
10
+ //# sourceMappingURL=fill-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fill-action.d.ts","sourceRoot":"","sources":["../../../../../src/browser-opt/runner/actions/utils/fill-action.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAK9E,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,OAAO,CAAC,mBAAmB,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACtD,QAAQ,EAAE,gBAAgB,GACzB,MAAM,CAoBR"}
@@ -0,0 +1,20 @@
1
+ import { findTextboxRef } from '../../../utils.js';
2
+ import { buildLoginHandoffActionOutput, isLoginLikeSnapshot } from '../../handoff.js';
3
+ import { fillFieldScopedDomTarget } from './dom-action.js';
4
+ /** 执行输入动作,登录页阻塞时转为 handoff,避免误报找不到业务字段。 */
5
+ export function executeFillAction(agent, action, snapshot) {
6
+ const ref = findTextboxRef(snapshot, action.field);
7
+ if (!ref) {
8
+ if (isLoginLikeSnapshot(snapshot)) {
9
+ return buildLoginHandoffActionOutput(agent, `当前页面仍在登录页,无法继续填写“${action.field}”,请先完成登录后再继续自动化。`);
10
+ }
11
+ const domOutput = fillFieldScopedDomTarget(agent, action.field, action.value);
12
+ if (domOutput) {
13
+ return domOutput;
14
+ }
15
+ throw new Error(`无法找到输入框:${action.field}`);
16
+ }
17
+ const output = agent.fill(ref, action.value);
18
+ return `fill @${ref} ${JSON.stringify(action.value)}\n${output}`.trim();
19
+ }
20
+ //# sourceMappingURL=fill-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fill-action.js","sourceRoot":"","sources":["../../../../../src/browser-opt/runner/actions/utils/fill-action.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,6BAA6B,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,2CAA2C;AAC3C,MAAM,UAAU,iBAAiB,CAC/B,KAAmB,EACnB,MAAsD,EACtD,QAA0B;IAE1B,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,IAAI,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,OAAO,6BAA6B,CAClC,KAAK,EACL,oBAAoB,MAAM,CAAC,KAAK,kBAAkB,CACnD,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,wBAAwB,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9E,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,WAAW,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7C,OAAO,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * browser-opt 人工接管动作执行器,负责把 handoff 消息交给 agent-browser。
3
+ */
4
+ import type { BrowserAgent } from '@browser-automated/browser-core/agent';
5
+ import type { DeterministicAction } from '../../../type.js';
6
+ /** 执行人工接管动作,保持输出格式与其他确定性动作一致。 */
7
+ export declare function executeHandoffAction(agent: BrowserAgent, action: Extract<DeterministicAction, {
8
+ type: 'handoff';
9
+ }>): string;
10
+ //# sourceMappingURL=handoff-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff-action.d.ts","sourceRoot":"","sources":["../../../../../src/browser-opt/runner/actions/utils/handoff-action.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,iCAAiC;AACjC,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,OAAO,CAAC,mBAAmB,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,GACxD,MAAM,CAGR"}
@@ -0,0 +1,6 @@
1
+ /** 执行人工接管动作,保持输出格式与其他确定性动作一致。 */
2
+ export function executeHandoffAction(agent, action) {
3
+ const output = agent.handoff(action.message);
4
+ return `handoff ${JSON.stringify(action.message)}\n${output}`.trim();
5
+ }
6
+ //# sourceMappingURL=handoff-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff-action.js","sourceRoot":"","sources":["../../../../../src/browser-opt/runner/actions/utils/handoff-action.ts"],"names":[],"mappings":"AAMA,iCAAiC;AACjC,MAAM,UAAU,oBAAoB,CAClC,KAAmB,EACnB,MAAyD;IAEzD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO,WAAW,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AACvE,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * browser-opt 打开页面动作执行器,负责处理重复打开跳过和实际 open 命令下发。
3
+ */
4
+ import type { BrowserAgent } from '@browser-automated/browser-core/agent';
5
+ import type { DeterministicAction, DeterministicExecutionOptions } from '../../../type.js';
6
+ /** 执行打开页面动作,避免重复打开 runner 已初始化的目标地址。 */
7
+ export declare function executeOpenAction(agent: BrowserAgent, action: Extract<DeterministicAction, {
8
+ type: 'open';
9
+ }>, options: DeterministicExecutionOptions): string;
10
+ //# sourceMappingURL=open-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-action.d.ts","sourceRoot":"","sources":["../../../../../src/browser-opt/runner/actions/utils/open-action.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAG3F,wCAAwC;AACxC,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,OAAO,CAAC,mBAAmB,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACtD,OAAO,EAAE,6BAA6B,GACrC,MAAM,CAMR"}
@@ -0,0 +1,9 @@
1
+ import { normalizeUrlForCompare } from '../../evidence.js';
2
+ /** 执行打开页面动作,避免重复打开 runner 已初始化的目标地址。 */
3
+ export function executeOpenAction(agent, action, options) {
4
+ if (options.alreadyOpenedUrl && normalizeUrlForCompare(action.url) === normalizeUrlForCompare(options.alreadyOpenedUrl)) {
5
+ return `open skipped: ${action.url} 已由 runner 初始化打开`;
6
+ }
7
+ return agent.open(action.url);
8
+ }
9
+ //# sourceMappingURL=open-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-action.js","sourceRoot":"","sources":["../../../../../src/browser-opt/runner/actions/utils/open-action.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,wCAAwC;AACxC,MAAM,UAAU,iBAAiB,CAC/B,KAAmB,EACnB,MAAsD,EACtD,OAAsC;IAEtC,IAAI,OAAO,CAAC,gBAAgB,IAAI,sBAAsB,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,sBAAsB,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACxH,OAAO,iBAAiB,MAAM,CAAC,GAAG,kBAAkB,CAAC;IACvD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * browser-opt 选项选择动作执行器,负责下拉、单选、复选和 switch 的确定性选择流程。
3
+ */
4
+ import type { BrowserAgent } from '@browser-automated/browser-core/agent';
5
+ import type { DeterministicAction, SnapshotEvidence, DeterministicExecutionOptions } from '../../../type.js';
6
+ /** 执行选项选择动作,包含 switch、原生单选复选框和长表单滚动搜索兜底。 */
7
+ export declare function executeSelectOptionAction(agent: BrowserAgent, action: Extract<DeterministicAction, {
8
+ type: 'select-option';
9
+ }>, snapshot: SnapshotEvidence, options: DeterministicExecutionOptions): string;
10
+ /** 对选择动作做后置状态确认,防止命令发出但页面没有完成目标状态时误报成功。 */
11
+ export declare function verifySelectOptionActionEffect(agent: BrowserAgent, action: Extract<DeterministicAction, {
12
+ type: 'select-option';
13
+ }>, afterSnapshot: SnapshotEvidence): {
14
+ passed: boolean;
15
+ message: string;
16
+ };
17
+ //# sourceMappingURL=select-option-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-option-action.d.ts","sourceRoot":"","sources":["../../../../../src/browser-opt/runner/actions/utils/select-option-action.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAY7G,4CAA4C;AAC5C,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,OAAO,CAAC,mBAAmB,EAAE;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC,EAC/D,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,6BAA6B,GACrC,MAAM,CAiFR;AAED,2CAA2C;AAC3C,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,OAAO,CAAC,mBAAmB,EAAE;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC,EAC/D,aAAa,EAAE,gBAAgB,GAC9B;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA+BtC"}