@nuanu-ai/agentbrowse 0.2.47 → 0.2.49

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 (198) hide show
  1. package/README.md +81 -10
  2. package/dist/agentpay-gateway.d.ts +9 -0
  3. package/dist/agentpay-gateway.d.ts.map +1 -1
  4. package/dist/agentpay-gateway.js +31 -1
  5. package/dist/agentpay-stagehand-llm.d.ts.map +1 -1
  6. package/dist/agentpay-stagehand-llm.js +9 -1
  7. package/dist/command-api-tracing.d.ts +19 -0
  8. package/dist/command-api-tracing.d.ts.map +1 -0
  9. package/dist/command-api-tracing.js +137 -0
  10. package/dist/commands/act.d.ts.map +1 -1
  11. package/dist/commands/act.js +822 -670
  12. package/dist/commands/act.test-harness.d.ts +6 -0
  13. package/dist/commands/act.test-harness.d.ts.map +1 -1
  14. package/dist/commands/act.test-harness.js +44 -1
  15. package/dist/commands/action-acceptance.d.ts.map +1 -1
  16. package/dist/commands/action-acceptance.js +115 -0
  17. package/dist/commands/captcha-solve.d.ts.map +1 -1
  18. package/dist/commands/captcha-solve.js +83 -16
  19. package/dist/commands/click-action-executor.d.ts +0 -1
  20. package/dist/commands/click-action-executor.d.ts.map +1 -1
  21. package/dist/commands/click-action-executor.js +31 -77
  22. package/dist/commands/close.d.ts +3 -3
  23. package/dist/commands/close.d.ts.map +1 -1
  24. package/dist/commands/close.js +178 -0
  25. package/dist/commands/descriptor-validation.d.ts.map +1 -1
  26. package/dist/commands/descriptor-validation.js +75 -57
  27. package/dist/commands/end-session.d.ts +25 -0
  28. package/dist/commands/end-session.d.ts.map +1 -0
  29. package/dist/commands/end-session.js +161 -0
  30. package/dist/commands/extract-stagehand-executor.js +1 -1
  31. package/dist/commands/extract.d.ts.map +1 -1
  32. package/dist/commands/extract.js +339 -202
  33. package/dist/commands/fill-secret.d.ts +3 -3
  34. package/dist/commands/fill-secret.d.ts.map +1 -1
  35. package/dist/commands/fill-secret.js +419 -234
  36. package/dist/commands/get-secrets-catalog.d.ts.map +1 -1
  37. package/dist/commands/get-secrets-catalog.js +66 -5
  38. package/dist/commands/init.d.ts.map +1 -1
  39. package/dist/commands/init.js +6 -3
  40. package/dist/commands/interaction-kernel.d.ts +46 -0
  41. package/dist/commands/interaction-kernel.d.ts.map +1 -0
  42. package/dist/commands/interaction-kernel.js +215 -0
  43. package/dist/commands/launch.d.ts +1 -3
  44. package/dist/commands/launch.d.ts.map +1 -1
  45. package/dist/commands/launch.js +115 -27
  46. package/dist/commands/navigate.d.ts.map +1 -1
  47. package/dist/commands/navigate.js +188 -45
  48. package/dist/commands/observe-accessibility.d.ts.map +1 -1
  49. package/dist/commands/observe-accessibility.js +46 -39
  50. package/dist/commands/observe-dom-label-contract.d.ts.map +1 -1
  51. package/dist/commands/observe-dom-label-contract.js +5 -0
  52. package/dist/commands/observe-inventory.d.ts +13 -0
  53. package/dist/commands/observe-inventory.d.ts.map +1 -1
  54. package/dist/commands/observe-inventory.js +320 -65
  55. package/dist/commands/observe-persistence.d.ts.map +1 -1
  56. package/dist/commands/observe-persistence.js +3 -0
  57. package/dist/commands/observe-projection.d.ts +1 -0
  58. package/dist/commands/observe-projection.d.ts.map +1 -1
  59. package/dist/commands/observe-projection.js +7 -2
  60. package/dist/commands/observe-protected.d.ts +1 -0
  61. package/dist/commands/observe-protected.d.ts.map +1 -1
  62. package/dist/commands/observe-protected.js +9 -4
  63. package/dist/commands/observe-semantics.d.ts.map +1 -1
  64. package/dist/commands/observe-semantics.js +5 -2
  65. package/dist/commands/observe-stagehand.d.ts +1 -0
  66. package/dist/commands/observe-stagehand.d.ts.map +1 -1
  67. package/dist/commands/observe-stagehand.js +2 -0
  68. package/dist/commands/observe.d.ts +2 -0
  69. package/dist/commands/observe.d.ts.map +1 -1
  70. package/dist/commands/observe.js +387 -203
  71. package/dist/commands/observe.test-harness.d.ts +8 -0
  72. package/dist/commands/observe.test-harness.d.ts.map +1 -1
  73. package/dist/commands/observe.test-harness.js +48 -1
  74. package/dist/commands/poll-secret.d.ts +6 -0
  75. package/dist/commands/poll-secret.d.ts.map +1 -0
  76. package/dist/commands/poll-secret.js +159 -0
  77. package/dist/commands/request-secret.d.ts +6 -0
  78. package/dist/commands/request-secret.d.ts.map +1 -0
  79. package/dist/commands/request-secret.js +284 -0
  80. package/dist/commands/screenshot.d.ts.map +1 -1
  81. package/dist/commands/screenshot.js +172 -7
  82. package/dist/commands/select-action-executor.d.ts.map +1 -1
  83. package/dist/commands/semantic-observe.d.ts +4 -0
  84. package/dist/commands/semantic-observe.d.ts.map +1 -1
  85. package/dist/commands/semantic-observe.js +388 -17
  86. package/dist/commands/start-session.d.ts +31 -0
  87. package/dist/commands/start-session.d.ts.map +1 -0
  88. package/dist/commands/start-session.js +347 -0
  89. package/dist/commands/status.d.ts +2 -1
  90. package/dist/commands/status.d.ts.map +1 -1
  91. package/dist/commands/status.js +166 -144
  92. package/dist/control-semantics.d.ts +1 -0
  93. package/dist/control-semantics.d.ts.map +1 -1
  94. package/dist/control-semantics.js +51 -9
  95. package/dist/generated/build-config.d.ts +2 -0
  96. package/dist/generated/build-config.d.ts.map +1 -0
  97. package/dist/generated/build-config.js +2 -0
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +163 -63
  100. package/dist/otel-exporter.d.ts +58 -0
  101. package/dist/otel-exporter.d.ts.map +1 -0
  102. package/dist/otel-exporter.js +263 -0
  103. package/dist/otel-projector.d.ts +75 -0
  104. package/dist/otel-projector.d.ts.map +1 -0
  105. package/dist/otel-projector.js +409 -0
  106. package/dist/owned-browser.d.ts +1 -1
  107. package/dist/owned-browser.d.ts.map +1 -1
  108. package/dist/owned-browser.js +13 -1
  109. package/dist/owned-process.d.ts +2 -0
  110. package/dist/owned-process.d.ts.map +1 -1
  111. package/dist/owned-process.js +7 -3
  112. package/dist/playwright-runtime.d.ts +1 -1
  113. package/dist/playwright-runtime.d.ts.map +1 -1
  114. package/dist/playwright-runtime.js +8 -8
  115. package/dist/run-observability.d.ts +25 -0
  116. package/dist/run-observability.d.ts.map +1 -0
  117. package/dist/run-observability.js +115 -0
  118. package/dist/run-store.d.ts +274 -0
  119. package/dist/run-store.d.ts.map +1 -0
  120. package/dist/run-store.js +631 -0
  121. package/dist/runtime-metrics.d.ts +27 -0
  122. package/dist/runtime-metrics.d.ts.map +1 -0
  123. package/dist/runtime-metrics.js +66 -0
  124. package/dist/runtime-page-state.d.ts +11 -0
  125. package/dist/runtime-page-state.d.ts.map +1 -0
  126. package/dist/runtime-page-state.js +62 -0
  127. package/dist/runtime-protected-state.d.ts +16 -0
  128. package/dist/runtime-protected-state.d.ts.map +1 -0
  129. package/dist/runtime-protected-state.js +157 -0
  130. package/dist/runtime-state.d.ts +10 -44
  131. package/dist/runtime-state.d.ts.map +1 -1
  132. package/dist/runtime-state.js +57 -222
  133. package/dist/secrets/backend.d.ts +65 -16
  134. package/dist/secrets/backend.d.ts.map +1 -1
  135. package/dist/secrets/backend.js +135 -95
  136. package/dist/secrets/catalog-sync.d.ts.map +1 -1
  137. package/dist/secrets/catalog-sync.js +4 -1
  138. package/dist/secrets/form-matcher.d.ts +5 -5
  139. package/dist/secrets/form-matcher.d.ts.map +1 -1
  140. package/dist/secrets/form-matcher.js +292 -164
  141. package/dist/secrets/intent-output.d.ts +6 -10
  142. package/dist/secrets/intent-output.d.ts.map +1 -1
  143. package/dist/secrets/intent-output.js +4 -58
  144. package/dist/secrets/mock-agentpay-cabinet.d.ts +38 -27
  145. package/dist/secrets/mock-agentpay-cabinet.d.ts.map +1 -1
  146. package/dist/secrets/mock-agentpay-cabinet.js +177 -111
  147. package/dist/secrets/protected-artifact-guard.d.ts +2 -2
  148. package/dist/secrets/protected-artifact-guard.d.ts.map +1 -1
  149. package/dist/secrets/protected-artifact-guard.js +2 -2
  150. package/dist/secrets/protected-bindings.d.ts +1 -1
  151. package/dist/secrets/protected-bindings.d.ts.map +1 -1
  152. package/dist/secrets/protected-bindings.js +6 -0
  153. package/dist/secrets/protected-field-semantics.d.ts +9 -0
  154. package/dist/secrets/protected-field-semantics.d.ts.map +1 -0
  155. package/dist/secrets/protected-field-semantics.js +154 -0
  156. package/dist/secrets/protected-field-values.d.ts.map +1 -1
  157. package/dist/secrets/protected-field-values.js +3 -3
  158. package/dist/secrets/protected-fill.d.ts +1 -1
  159. package/dist/secrets/protected-fill.d.ts.map +1 -1
  160. package/dist/secrets/protected-fill.js +45 -149
  161. package/dist/secrets/protected-value-adapters.d.ts +2 -1
  162. package/dist/secrets/protected-value-adapters.d.ts.map +1 -1
  163. package/dist/secrets/protected-value-adapters.js +80 -1
  164. package/dist/secrets/request-output.d.ts +11 -0
  165. package/dist/secrets/request-output.d.ts.map +1 -0
  166. package/dist/secrets/request-output.js +75 -0
  167. package/dist/secrets/types.d.ts +15 -9
  168. package/dist/secrets/types.d.ts.map +1 -1
  169. package/dist/secrets/types.js +3 -0
  170. package/dist/session-event-exporter.d.ts +36 -0
  171. package/dist/session-event-exporter.d.ts.map +1 -0
  172. package/dist/session-event-exporter.js +428 -0
  173. package/dist/session.d.ts +16 -7
  174. package/dist/session.d.ts.map +1 -1
  175. package/dist/session.js +150 -23
  176. package/dist/sessions-backend.d.ts +354 -0
  177. package/dist/sessions-backend.d.ts.map +1 -0
  178. package/dist/sessions-backend.js +126 -0
  179. package/dist/solver/browser-launcher.d.ts +1 -1
  180. package/dist/solver/browser-launcher.d.ts.map +1 -1
  181. package/dist/solver/browser-launcher.js +39 -13
  182. package/dist/solver/captcha-solver.d.ts.map +1 -1
  183. package/dist/solver/captcha-solver.js +8 -1
  184. package/dist/solver/config.d.ts +0 -1
  185. package/dist/solver/config.d.ts.map +1 -1
  186. package/dist/solver/config.js +0 -22
  187. package/dist/solver/types.d.ts +1 -0
  188. package/dist/solver/types.d.ts.map +1 -1
  189. package/dist/workflow-session-completion.d.ts +33 -0
  190. package/dist/workflow-session-completion.d.ts.map +1 -0
  191. package/dist/workflow-session-completion.js +156 -0
  192. package/package.json +11 -1
  193. package/dist/commands/create-intent.d.ts +0 -6
  194. package/dist/commands/create-intent.d.ts.map +0 -1
  195. package/dist/commands/create-intent.js +0 -75
  196. package/dist/commands/poll-intent.d.ts +0 -6
  197. package/dist/commands/poll-intent.d.ts.map +0 -1
  198. package/dist/commands/poll-intent.js +0 -57
@@ -2,13 +2,19 @@ import { vi } from 'vitest';
2
2
  import type { BrowseSession } from '../session.js';
3
3
  type ViMock = ReturnType<typeof vi.fn>;
4
4
  export declare const captureActionFailureArtifactsMock: ViMock;
5
+ export declare const appendCommandLifecycleEventBestEffortMock: ViMock;
6
+ export declare const captureStepSnapshotBestEffortMock: ViMock;
5
7
  export declare const connectStagehandMock: ViMock;
6
8
  export declare const connectOverCDPMock: ViMock;
9
+ export declare const exportRunStepToOtlpHttpJsonBestEffortMock: ViMock;
10
+ export declare const finishRunStepMock: ViMock;
7
11
  export declare const outputContractFailureMock: ViMock;
8
12
  export declare const outputErrorMock: ViMock;
9
13
  export declare const outputFailureMock: ViMock;
10
14
  export declare const outputJSONMock: ViMock;
15
+ export declare const saveArtifactManifestMock: ViMock;
11
16
  export declare const saveSessionMock: ViMock;
17
+ export declare const startRunStepMock: ViMock;
12
18
  export declare const startActionTraceMock: ViMock;
13
19
  export declare const act: typeof import("./act.js").act;
14
20
  export declare function makeSession(): BrowseSession;
@@ -1 +1 @@
1
- {"version":3,"file":"act.test-harness.d.ts","sourceRoot":"","sources":["../../src/commands/act.test-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,EAAE,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AA6BvC,eAAO,MAAM,iCAAiC,EAAE,MAAgD,CAAC;AACjG,eAAO,MAAM,oBAAoB,EAAE,MAAmC,CAAC;AACvE,eAAO,MAAM,kBAAkB,EAAE,MAAiC,CAAC;AACnE,eAAO,MAAM,yBAAyB,EAAE,MAAwC,CAAC;AACjF,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,iBAAiB,EAAE,MAAgC,CAAC;AACjE,eAAO,MAAM,cAAc,EAAE,MAA6B,CAAC;AAC3D,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,oBAAoB,EAAE,MAAmC,CAAC;AAgCvE,eAAO,MAAQ,GAAG,+BAA6B,CAAC;AAEhD,wBAAgB,WAAW,IAAI,aAAa,CAW3C;AAED,wBAAgB,WAAW,CAAC,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,GAAG,CA2KxE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,GAAG,GAAG,CAM7F;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAqB1C"}
1
+ {"version":3,"file":"act.test-harness.d.ts","sourceRoot":"","sources":["../../src/commands/act.test-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,EAAE,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AAwCvC,eAAO,MAAM,iCAAiC,EAAE,MAAgD,CAAC;AACjG,eAAO,MAAM,yCAAyC,EAAE,MACP,CAAC;AAClD,eAAO,MAAM,iCAAiC,EAAE,MAAgD,CAAC;AACjG,eAAO,MAAM,oBAAoB,EAAE,MAAmC,CAAC;AACvE,eAAO,MAAM,kBAAkB,EAAE,MAAiC,CAAC;AACnE,eAAO,MAAM,yCAAyC,EAAE,MACP,CAAC;AAClD,eAAO,MAAM,iBAAiB,EAAE,MAAgC,CAAC;AACjE,eAAO,MAAM,yBAAyB,EAAE,MAAwC,CAAC;AACjF,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,iBAAiB,EAAE,MAAgC,CAAC;AACjE,eAAO,MAAM,cAAc,EAAE,MAA6B,CAAC;AAC3D,eAAO,MAAM,wBAAwB,EAAE,MAAuC,CAAC;AAC/E,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,gBAAgB,EAAE,MAA+B,CAAC;AAC/D,eAAO,MAAM,oBAAoB,EAAE,MAAmC,CAAC;AA+CvE,eAAO,MAAQ,GAAG,+BAA6B,CAAC;AAEhD,wBAAgB,WAAW,IAAI,aAAa,CAY3C;AAED,wBAAgB,WAAW,CAAC,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,GAAG,CA2KxE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,GAAG,GAAG,CAM7F;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAkC1C"}
@@ -1,6 +1,7 @@
1
1
  import { afterEach, beforeEach, vi } from 'vitest';
2
- import { registerPage } from '../runtime-state.js';
2
+ import { registerPage } from '../runtime-page-state.js';
3
3
  const mocks = vi.hoisted(() => ({
4
+ appendCommandLifecycleEventBestEffortMock: vi.fn(),
4
5
  captureActionFailureArtifactsMock: vi.fn(async () => ({
5
6
  dir: '/tmp/agentbrowse-artifacts/act-test',
6
7
  screenshotPath: '/tmp/agentbrowse-artifacts/act-test/page.png',
@@ -8,8 +9,14 @@ const mocks = vi.hoisted(() => ({
8
9
  tracePath: '/tmp/agentbrowse-artifacts/act-test/trace.zip',
9
10
  actionLogPath: '/tmp/agentbrowse-artifacts/act-test/action-log.json',
10
11
  })),
12
+ captureStepSnapshotBestEffortMock: vi.fn(),
11
13
  connectStagehandMock: vi.fn(),
12
14
  connectOverCDPMock: vi.fn(),
15
+ exportRunStepToOtlpHttpJsonBestEffortMock: vi.fn(async () => ({
16
+ attempted: false,
17
+ reason: 'config_missing',
18
+ })),
19
+ finishRunStepMock: vi.fn(),
13
20
  outputContractFailureMock: vi.fn((payload) => {
14
21
  throw new Error(`outputContractFailure:${JSON.stringify(payload)}`);
15
22
  }),
@@ -20,20 +27,30 @@ const mocks = vi.hoisted(() => ({
20
27
  throw new Error(result.error);
21
28
  }),
22
29
  outputJSONMock: vi.fn(),
30
+ saveArtifactManifestMock: vi.fn(),
23
31
  saveSessionMock: vi.fn(),
32
+ startRunStepMock: vi.fn(() => ({
33
+ stepId: 'step_act_1',
34
+ })),
24
35
  startActionTraceMock: vi.fn(async () => ({
25
36
  finishSuccess: async () => { },
26
37
  finishFailure: async () => '/tmp/agentbrowse-artifacts/act-test/trace.zip',
27
38
  })),
28
39
  }));
29
40
  export const captureActionFailureArtifactsMock = mocks.captureActionFailureArtifactsMock;
41
+ export const appendCommandLifecycleEventBestEffortMock = mocks.appendCommandLifecycleEventBestEffortMock;
42
+ export const captureStepSnapshotBestEffortMock = mocks.captureStepSnapshotBestEffortMock;
30
43
  export const connectStagehandMock = mocks.connectStagehandMock;
31
44
  export const connectOverCDPMock = mocks.connectOverCDPMock;
45
+ export const exportRunStepToOtlpHttpJsonBestEffortMock = mocks.exportRunStepToOtlpHttpJsonBestEffortMock;
46
+ export const finishRunStepMock = mocks.finishRunStepMock;
32
47
  export const outputContractFailureMock = mocks.outputContractFailureMock;
33
48
  export const outputErrorMock = mocks.outputErrorMock;
34
49
  export const outputFailureMock = mocks.outputFailureMock;
35
50
  export const outputJSONMock = mocks.outputJSONMock;
51
+ export const saveArtifactManifestMock = mocks.saveArtifactManifestMock;
36
52
  export const saveSessionMock = mocks.saveSessionMock;
53
+ export const startRunStepMock = mocks.startRunStepMock;
37
54
  export const startActionTraceMock = mocks.startActionTraceMock;
38
55
  vi.mock('playwright-core', () => ({
39
56
  chromium: {
@@ -53,6 +70,18 @@ vi.mock('./action-artifacts.js', () => ({
53
70
  captureActionFailureArtifacts: captureActionFailureArtifactsMock,
54
71
  startActionTrace: startActionTraceMock,
55
72
  }));
73
+ vi.mock('../run-store.js', () => ({
74
+ finishRunStep: finishRunStepMock,
75
+ saveArtifactManifest: saveArtifactManifestMock,
76
+ startRunStep: startRunStepMock,
77
+ }));
78
+ vi.mock('../run-observability.js', () => ({
79
+ appendCommandLifecycleEventBestEffort: appendCommandLifecycleEventBestEffortMock,
80
+ captureStepSnapshotBestEffort: captureStepSnapshotBestEffortMock,
81
+ }));
82
+ vi.mock('../otel-exporter.js', () => ({
83
+ exportRunStepToOtlpHttpJsonBestEffort: exportRunStepToOtlpHttpJsonBestEffortMock,
84
+ }));
56
85
  vi.mock('../session.js', async () => {
57
86
  const actual = await vi.importActual('../session.js');
58
87
  return {
@@ -65,6 +94,7 @@ export function makeSession() {
65
94
  const session = {
66
95
  cdpUrl: 'ws://localhost:9222/devtools/browser/test',
67
96
  pid: 1,
97
+ activeRunId: 'run_123',
68
98
  launchedAt: new Date(0).toISOString(),
69
99
  };
70
100
  registerPage(session, {
@@ -242,9 +272,17 @@ export function makeLocatorCollection(...locators) {
242
272
  export function installActTestHooks() {
243
273
  beforeEach(() => {
244
274
  vi.useRealTimers();
275
+ appendCommandLifecycleEventBestEffortMock.mockReset();
276
+ captureStepSnapshotBestEffortMock.mockReset();
245
277
  connectOverCDPMock.mockReset();
246
278
  connectStagehandMock.mockReset();
247
279
  captureActionFailureArtifactsMock.mockClear();
280
+ exportRunStepToOtlpHttpJsonBestEffortMock.mockReset();
281
+ exportRunStepToOtlpHttpJsonBestEffortMock.mockResolvedValue({
282
+ attempted: false,
283
+ reason: 'config_missing',
284
+ });
285
+ finishRunStepMock.mockReset();
248
286
  outputContractFailureMock.mockReset();
249
287
  outputContractFailureMock.mockImplementation((payload) => {
250
288
  throw new Error(`outputContractFailure:${JSON.stringify(payload)}`);
@@ -252,7 +290,12 @@ export function installActTestHooks() {
252
290
  outputErrorMock.mockClear();
253
291
  outputFailureMock.mockClear();
254
292
  outputJSONMock.mockClear();
293
+ saveArtifactManifestMock.mockReset();
255
294
  saveSessionMock.mockReset();
295
+ startRunStepMock.mockReset();
296
+ startRunStepMock.mockReturnValue({
297
+ stepId: 'step_act_1',
298
+ });
256
299
  startActionTraceMock.mockClear();
257
300
  });
258
301
  afterEach(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"action-acceptance.d.ts","sourceRoot":"","sources":["../../src/commands/action-acceptance.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"action-acceptance.d.ts","sourceRoot":"","sources":["../../src/commands/action-acceptance.ts"],"names":[],"mappings":"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"}
@@ -57,6 +57,105 @@ const ACTION_CANDIDATE_PRIORITY = {
57
57
  };
58
58
  const ACCEPTANCE_POLL_INTERVAL_MS = 100;
59
59
  const ACCEPTANCE_POLL_TIMEOUT_MS = 2_500;
60
+ const ASSOCIATED_CHOICE_STATE_HELPER_SCRIPT = String.raw `
61
+ const ownerWindowOf = (node) => node?.ownerDocument?.defaultView ?? window;
62
+ const isHTMLElementNode = (value) => {
63
+ const view = ownerWindowOf(value);
64
+ return Boolean(view && value instanceof view.HTMLElement);
65
+ };
66
+ const isHTMLInputNode = (value) => {
67
+ const view = ownerWindowOf(value);
68
+ return Boolean(view && value instanceof view.HTMLInputElement);
69
+ };
70
+ const isHTMLLabelNode = (value) => {
71
+ const view = ownerWindowOf(value);
72
+ return Boolean(view && value instanceof view.HTMLLabelElement);
73
+ };
74
+ const isChoiceInput = (candidate) => {
75
+ if (!isHTMLInputNode(candidate)) {
76
+ return false;
77
+ }
78
+ const type = (candidate.type || '').toLowerCase();
79
+ return type === 'radio' || type === 'checkbox';
80
+ };
81
+ const associatedLabelControlOf = (candidate) => {
82
+ if (!isHTMLLabelNode(candidate)) {
83
+ return undefined;
84
+ }
85
+
86
+ const directControl = candidate.control;
87
+ if (isChoiceInput(directControl)) {
88
+ return directControl;
89
+ }
90
+
91
+ const nestedControl = candidate.querySelector?.('input');
92
+ return isChoiceInput(nestedControl) ? nestedControl : undefined;
93
+ };
94
+ const hiddenChoiceSiblingControlOf = (candidate) => {
95
+ if (!isHTMLElementNode(candidate)) {
96
+ return undefined;
97
+ }
98
+
99
+ const parent = candidate.parentElement;
100
+ if (!isHTMLElementNode(parent)) {
101
+ return undefined;
102
+ }
103
+
104
+ const hiddenChoiceSiblings = Array.from(parent.children).filter((sibling) => {
105
+ if (sibling === candidate || !isChoiceInput(sibling)) {
106
+ return false;
107
+ }
108
+
109
+ const style = ownerWindowOf(sibling).getComputedStyle(sibling);
110
+ const rect = sibling.getBoundingClientRect();
111
+ return (
112
+ style.display === 'none' ||
113
+ style.visibility === 'hidden' ||
114
+ style.pointerEvents === 'none' ||
115
+ Number(style.opacity || '1') < 0.05 ||
116
+ rect.width < 4 ||
117
+ rect.height < 4
118
+ );
119
+ });
120
+
121
+ if (hiddenChoiceSiblings.length !== 1) {
122
+ return undefined;
123
+ }
124
+
125
+ const visibleNonChoiceSiblings = Array.from(parent.children).filter((sibling) => {
126
+ if (sibling === hiddenChoiceSiblings[0] || !isHTMLElementNode(sibling)) {
127
+ return false;
128
+ }
129
+
130
+ const style = ownerWindowOf(sibling).getComputedStyle(sibling);
131
+ const rect = sibling.getBoundingClientRect();
132
+ return (
133
+ style.display !== 'none' &&
134
+ style.visibility !== 'hidden' &&
135
+ style.visibility !== 'collapse' &&
136
+ rect.width > 0 &&
137
+ rect.height > 0
138
+ );
139
+ });
140
+
141
+ if (visibleNonChoiceSiblings.length !== 1 || visibleNonChoiceSiblings[0] !== candidate) {
142
+ return undefined;
143
+ }
144
+
145
+ return hiddenChoiceSiblings[0];
146
+ };
147
+ const associatedChoiceControl =
148
+ (isChoiceInput(element) ? element : undefined) ||
149
+ associatedLabelControlOf(element) ||
150
+ hiddenChoiceSiblingControlOf(element);
151
+ if (!associatedChoiceControl) {
152
+ return null;
153
+ }
154
+
155
+ return {
156
+ checked: associatedChoiceControl.indeterminate ? 'mixed' : associatedChoiceControl.checked,
157
+ };
158
+ `;
60
159
  const PAGE_OBSERVATION_SCRIPT = String.raw `(() => {
61
160
  const normalizeText = (value) => (value ?? '').replace(/\s+/g, ' ').trim();
62
161
  const sampleText = (value, limit) => {
@@ -731,6 +830,14 @@ function acceptancePolicyForAction(target, action) {
731
830
  if (action === 'press' && isEditableLikeTarget(target)) {
732
831
  return undefined;
733
832
  }
833
+ if ((action === 'fill' || action === 'type') &&
834
+ target.controlFamily === 'select' &&
835
+ target.allowedActions.includes('fill') &&
836
+ target.allowedActions.includes('select') &&
837
+ (target.kind ?? '').toLowerCase() !== 'select' &&
838
+ (target.semantics?.role ?? '').toLowerCase() === 'combobox') {
839
+ return 'selection';
840
+ }
734
841
  if (action === 'select') {
735
842
  if (target.controlFamily === 'datepicker') {
736
843
  return 'date-selection';
@@ -1147,6 +1254,11 @@ export async function captureLocatorState(locator, keys) {
1147
1254
  };
1148
1255
  })
1149
1256
  .catch(() => ({ selected: null, current: null, pressed: null }));
1257
+ const associatedChoiceState = keys.includes('checked')
1258
+ ? await locator
1259
+ .evaluate((element, source) => Function('element', source)(element), ASSOCIATED_CHOICE_STATE_HELPER_SCRIPT)
1260
+ .catch(() => null)
1261
+ : null;
1150
1262
  for (const key of keys) {
1151
1263
  switch (key) {
1152
1264
  case 'checked': {
@@ -1164,6 +1276,9 @@ export async function captureLocatorState(locator, keys) {
1164
1276
  state.checked = false;
1165
1277
  else if (ariaChecked === 'mixed')
1166
1278
  state.checked = 'mixed';
1279
+ else if (associatedChoiceState && typeof associatedChoiceState === 'object') {
1280
+ state.checked = associatedChoiceState.checked;
1281
+ }
1167
1282
  break;
1168
1283
  }
1169
1284
  case 'selected': {
@@ -1 +1 @@
1
- {"version":3,"file":"captcha-solve.d.ts","sourceRoot":"","sources":["../../src/commands/captcha-solve.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAOnD,wBAAsB,YAAY,CAChC,OAAO,EAAE,aAAa,GAAG,IAAI,EAC7B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
1
+ {"version":3,"file":"captcha-solve.d.ts","sourceRoot":"","sources":["../../src/commands/captcha-solve.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAcnD,wBAAsB,YAAY,CAChC,OAAO,EAAE,aAAa,GAAG,IAAI,EAC7B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAiHf"}
@@ -3,7 +3,11 @@
3
3
  */
4
4
  import { solveCaptchasByCdp } from '../solver/captcha-runtime.js';
5
5
  import { supportsCaptchaSolve } from '../session.js';
6
+ import { withApiTraceContext } from '../command-api-tracing.js';
6
7
  import { info, outputContractFailure, outputJSON } from '../output.js';
8
+ import { exportRunStepToOtlpHttpJsonBestEffort } from '../otel-exporter.js';
9
+ import { appendCommandLifecycleEventBestEffort, captureStepSnapshotBestEffort, } from '../run-observability.js';
10
+ import { finishRunStep, startRunStep } from '../run-store.js';
7
11
  import { applyAgentpayGatewayEnv, resolveAgentpayGatewayConfig } from '../agentpay-gateway.js';
8
12
  const DEFAULT_TIMEOUT_SECONDS = 90;
9
13
  export async function captchaSolve(session, timeoutSeconds) {
@@ -27,23 +31,86 @@ export async function captchaSolve(session, timeoutSeconds) {
27
31
  applyAgentpayGatewayEnv(gateway);
28
32
  const cdpUrl = session.cdpUrl;
29
33
  const sessionProxy = session.transport?.proxyMode === 'proxy' ? session.transport.proxy : undefined;
34
+ const solveStep = session.activeRunId
35
+ ? startRunStep({
36
+ runId: session.activeRunId,
37
+ command: 'solve-captcha',
38
+ input: {
39
+ timeoutSeconds: timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS,
40
+ sharedTransport: Boolean(sessionProxy),
41
+ },
42
+ refs: {
43
+ pageRef: session.runtime?.currentPageRef,
44
+ },
45
+ })
46
+ : null;
47
+ captureStepSnapshotBestEffort({
48
+ session,
49
+ step: solveStep,
50
+ phase: 'before',
51
+ pageRef: session.runtime?.currentPageRef,
52
+ });
53
+ appendCommandLifecycleEventBestEffort({
54
+ step: solveStep,
55
+ phase: 'started',
56
+ attributes: {
57
+ pageRef: session.runtime?.currentPageRef,
58
+ timeoutSeconds: timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS,
59
+ sharedTransport: Boolean(sessionProxy),
60
+ },
61
+ });
30
62
  const timeoutMs = Math.max(1, timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS) * 1000;
31
63
  info(`[captcha] solve-captcha started (timeout ${Math.ceil(timeoutMs / 1000)}s, endpoint ${cdpUrl})`);
32
- const result = await solveCaptchasByCdp(cdpUrl, gateway.apiKey, {
33
- timeoutMs,
34
- solveTimeoutMs: Math.min(timeoutMs, 120000),
35
- apiUrl: gateway.apiUrl,
36
- proxy: sessionProxy,
37
- sharedTransport: Boolean(sessionProxy),
38
- onProgress: (message) => info(message),
39
- });
40
- outputJSON({
41
- success: true,
42
- solved: result.solved,
43
- verified: result.verified,
44
- unresolved: result.unresolved,
45
- unresolvedCaptchas: result.unresolvedCaptchas,
46
- detected: result.detected,
47
- timedOut: result.timedOut,
64
+ return withApiTraceContext({
65
+ runId: session.activeRunId,
66
+ stepId: solveStep?.stepId,
67
+ command: 'solve-captcha',
68
+ }, async () => {
69
+ const result = await solveCaptchasByCdp(cdpUrl, gateway.apiKey, {
70
+ timeoutMs,
71
+ solveTimeoutMs: Math.min(timeoutMs, 120000),
72
+ apiUrl: gateway.apiUrl,
73
+ proxy: sessionProxy,
74
+ sharedTransport: Boolean(sessionProxy),
75
+ onProgress: (message) => info(message),
76
+ });
77
+ captureStepSnapshotBestEffort({
78
+ session,
79
+ step: solveStep,
80
+ phase: 'after',
81
+ pageRef: session.runtime?.currentPageRef,
82
+ });
83
+ appendCommandLifecycleEventBestEffort({
84
+ step: solveStep,
85
+ phase: 'completed',
86
+ attributes: {
87
+ outcomeType: result.timedOut ? 'captcha_solve_timed_out' : 'captcha_solve_completed',
88
+ solved: result.solved,
89
+ verified: result.verified,
90
+ unresolved: result.unresolved,
91
+ detected: result.detected,
92
+ },
93
+ });
94
+ if (session.activeRunId && solveStep?.stepId) {
95
+ finishRunStep({
96
+ runId: session.activeRunId,
97
+ stepId: solveStep.stepId,
98
+ success: !result.timedOut,
99
+ outcomeType: result.timedOut ? 'captcha_solve_timed_out' : 'captcha_solve_completed',
100
+ message: result.timedOut
101
+ ? 'Captcha solving timed out.'
102
+ : 'Captcha solving completed.',
103
+ });
104
+ await exportRunStepToOtlpHttpJsonBestEffort(session.activeRunId, solveStep.stepId);
105
+ }
106
+ outputJSON({
107
+ success: true,
108
+ solved: result.solved,
109
+ verified: result.verified,
110
+ unresolved: result.unresolved,
111
+ unresolvedCaptchas: result.unresolvedCaptchas,
112
+ detected: result.detected,
113
+ timedOut: result.timedOut,
114
+ });
48
115
  });
49
116
  }
@@ -5,7 +5,6 @@ type ClickRetryOptions = {
5
5
  beforeRetry?: () => Promise<void>;
6
6
  guards?: ActionExecutionGuards;
7
7
  clickActivationStrategy?: ClickActivationStrategy;
8
- focusStrategy?: 'iframe-only' | 'active-control';
9
8
  };
10
9
  export declare function applyEditableClickAction(page: Page, locator: Locator, attempts: string[], options?: ClickRetryOptions): Promise<boolean>;
11
10
  export declare function applyTriggerAction(page: Page, locator: Locator, attempts: string[], options?: ClickRetryOptions): Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"click-action-executor.d.ts","sourceRoot":"","sources":["../../src/commands/click-action-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAMrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAEnG,KAAK,iBAAiB,GAAG;IACvB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,aAAa,CAAC,EAAE,aAAa,GAAG,gBAAgB,CAAC;CAClD,CAAC;AA0LF,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAKlB;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAKlB"}
1
+ {"version":3,"file":"click-action-executor.d.ts","sourceRoot":"","sources":["../../src/commands/click-action-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAMrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAEnG,KAAK,iBAAiB,GAAG;IACvB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;CACnD,CAAC;AAiIF,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAElB;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAElB"}
@@ -1,75 +1,32 @@
1
1
  import { LOCATOR_CLICK_TIMEOUT_MS, dismissBlockingOverlay, looksLikeOverlayInterference, } from './action-executor-helpers.js';
2
2
  import { runActionExecutionGuard } from './action-execution-guards.js';
3
- const DEFAULT_FOCUS_ALIGNMENT_RESULT = {
4
- focused: false,
5
- kind: null,
6
- };
7
- function normalizeFocusAlignmentResult(result) {
8
- if (result === true) {
9
- return {
10
- focused: true,
11
- kind: 'iframe',
12
- };
13
- }
14
- if (!result || typeof result !== 'object') {
15
- return DEFAULT_FOCUS_ALIGNMENT_RESULT;
16
- }
17
- const candidate = result;
18
- const focused = candidate.focused === true;
19
- if (!focused) {
20
- return DEFAULT_FOCUS_ALIGNMENT_RESULT;
3
+ async function handoffFocusFromActiveIframe(locator, attempts) {
4
+ const focused = await locator
5
+ .evaluate((element) => {
6
+ if (!(element instanceof HTMLElement)) {
7
+ return false;
8
+ }
9
+ const active = element.ownerDocument.activeElement;
10
+ if (!(active instanceof HTMLIFrameElement)) {
11
+ return false;
12
+ }
13
+ element.focus();
14
+ return element.ownerDocument.activeElement === element;
15
+ })
16
+ .catch(() => false);
17
+ if (focused) {
18
+ attempts.push('locator.focus.handoff-from-iframe');
21
19
  }
22
- return {
23
- focused: true,
24
- kind: candidate.kind === 'iframe' || candidate.kind === 'control' ? candidate.kind : 'control',
25
- };
20
+ return focused;
26
21
  }
27
- async function alignTargetFocusBeforeClick(locator, attempts, focusStrategy) {
28
- const focusProbeResult = await (focusStrategy === 'iframe-only'
29
- ? locator.evaluate((element) => {
30
- if (!(element instanceof HTMLElement)) {
31
- return { focused: false, kind: null };
32
- }
33
- const active = element.ownerDocument.activeElement;
34
- if (!(active instanceof HTMLElement) || active === element) {
35
- return { focused: false, kind: null };
36
- }
37
- if (active === element.ownerDocument.body ||
38
- active === element.ownerDocument.documentElement ||
39
- !(active instanceof HTMLIFrameElement)) {
40
- return { focused: false, kind: null };
41
- }
42
- element.focus();
43
- return {
44
- focused: element.ownerDocument.activeElement === element,
45
- kind: 'iframe',
46
- };
47
- })
48
- : locator.evaluate((element) => {
49
- if (!(element instanceof HTMLElement)) {
50
- return { focused: false, kind: null };
51
- }
52
- const active = element.ownerDocument.activeElement;
53
- if (!(active instanceof HTMLElement) || active === element) {
54
- return { focused: false, kind: null };
55
- }
56
- if (active === element.ownerDocument.body ||
57
- active === element.ownerDocument.documentElement) {
58
- return { focused: false, kind: null };
59
- }
60
- const kind = active instanceof HTMLIFrameElement ? 'iframe' : 'control';
61
- element.focus();
62
- return {
63
- focused: element.ownerDocument.activeElement === element,
64
- kind,
65
- };
66
- })).catch(() => DEFAULT_FOCUS_ALIGNMENT_RESULT);
67
- const focusResult = normalizeFocusAlignmentResult(focusProbeResult);
68
- if (focusResult.focused) {
69
- attempts.push(focusResult.kind === 'iframe'
70
- ? 'locator.focus.handoff-from-iframe'
71
- : 'locator.focus.before-click');
72
- }
22
+ async function waitForPostHandoffQuiescence(page, attempts, options) {
23
+ await runActionExecutionGuard(options?.guards, 'click.focus-handoff.quiescence');
24
+ await page
25
+ .evaluate(() => new Promise((resolve) => {
26
+ window.requestAnimationFrame(() => resolve());
27
+ }))
28
+ .catch(() => undefined);
29
+ attempts.push('locator.focus.handoff-quiescence.raf');
73
30
  }
74
31
  async function ensureLocatorRetryReady(locator, error, options) {
75
32
  await runActionExecutionGuard(options?.guards, 'click.before-retry');
@@ -80,7 +37,10 @@ async function ensureLocatorRetryReady(locator, error, options) {
80
37
  }
81
38
  }
82
39
  async function applyClickSequence(page, locator, attempts, options) {
83
- await alignTargetFocusBeforeClick(locator, attempts, options?.focusStrategy ?? 'iframe-only');
40
+ const handedOffFocus = await handoffFocusFromActiveIframe(locator, attempts);
41
+ if (handedOffFocus) {
42
+ await waitForPostHandoffQuiescence(page, attempts, options);
43
+ }
84
44
  if (options?.clickActivationStrategy === 'dom') {
85
45
  await runActionExecutionGuard(options?.guards, 'click.evaluate.primary');
86
46
  attempts.push('locator.evaluate.click.primary');
@@ -144,14 +104,8 @@ async function applyClickSequence(page, locator, attempts, options) {
144
104
  }
145
105
  }
146
106
  export async function applyEditableClickAction(page, locator, attempts, options) {
147
- return applyClickSequence(page, locator, attempts, {
148
- ...options,
149
- focusStrategy: options?.focusStrategy ?? 'iframe-only',
150
- });
107
+ return applyClickSequence(page, locator, attempts, options);
151
108
  }
152
109
  export async function applyTriggerAction(page, locator, attempts, options) {
153
- return applyClickSequence(page, locator, attempts, {
154
- ...options,
155
- focusStrategy: options?.focusStrategy ?? 'active-control',
156
- });
110
+ return applyClickSequence(page, locator, attempts, options);
157
111
  }
@@ -6,9 +6,9 @@ export type CloseSuccessResult = {
6
6
  };
7
7
  export type CloseFailureResult = {
8
8
  success: false;
9
- error: 'browser_close_failed';
10
- outcomeType: 'blocked';
11
- message: 'Browser close failed.';
9
+ error: 'browser_close_failed' | 'workflow_session_unavailable' | 'workflow_run_unavailable' | 'workflow_step_unavailable' | 'workflow_session_complete_failed';
10
+ outcomeType: 'blocked' | 'failed';
11
+ message: 'Browser close failed.' | 'Browser closed but workflow session completion failed.';
12
12
  reason: string;
13
13
  };
14
14
  export type CloseResult = CloseSuccessResult | CloseFailureResult;
@@ -1 +1 @@
1
- {"version":3,"file":"close.d.ts","sourceRoot":"","sources":["../../src/commands/close.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,IAAI,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,sBAAsB,CAAC;IAC9B,WAAW,EAAE,SAAS,CAAC;IACvB,OAAO,EAAE,uBAAuB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAclE,wBAAsB,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC,CAwBlD"}
1
+ {"version":3,"file":"close.d.ts","sourceRoot":"","sources":["../../src/commands/close.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkBH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,IAAI,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EACD,sBAAsB,GACtB,8BAA8B,GAC9B,0BAA0B,GAC1B,2BAA2B,GAC3B,kCAAkC,CAAC;IACvC,WAAW,EAAE,SAAS,GAAG,QAAQ,CAAC;IAClC,OAAO,EAAE,uBAAuB,GAAG,wDAAwD,CAAC;IAC5F,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AA8ElE,wBAAsB,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC,CA6IlD"}