@desplega.ai/qa-use 2.1.5 → 2.2.2

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 (145) hide show
  1. package/dist/lib/api/browser-types.d.ts +175 -0
  2. package/dist/lib/api/browser-types.d.ts.map +1 -0
  3. package/dist/lib/api/browser-types.js +5 -0
  4. package/dist/lib/api/browser-types.js.map +1 -0
  5. package/dist/lib/api/browser.d.ts +66 -0
  6. package/dist/lib/api/browser.d.ts.map +1 -0
  7. package/dist/lib/api/browser.js +223 -0
  8. package/dist/lib/api/browser.js.map +1 -0
  9. package/dist/package.json +2 -1
  10. package/dist/src/cli/commands/browser/back.d.ts +6 -0
  11. package/dist/src/cli/commands/browser/back.d.ts.map +1 -0
  12. package/dist/src/cli/commands/browser/back.js +42 -0
  13. package/dist/src/cli/commands/browser/back.js.map +1 -0
  14. package/dist/src/cli/commands/browser/check.d.ts +6 -0
  15. package/dist/src/cli/commands/browser/check.d.ts.map +1 -0
  16. package/dist/src/cli/commands/browser/check.js +62 -0
  17. package/dist/src/cli/commands/browser/check.js.map +1 -0
  18. package/dist/src/cli/commands/browser/click.d.ts +6 -0
  19. package/dist/src/cli/commands/browser/click.d.ts.map +1 -0
  20. package/dist/src/cli/commands/browser/click.js +63 -0
  21. package/dist/src/cli/commands/browser/click.js.map +1 -0
  22. package/dist/src/cli/commands/browser/close.d.ts +6 -0
  23. package/dist/src/cli/commands/browser/close.d.ts.map +1 -0
  24. package/dist/src/cli/commands/browser/close.js +44 -0
  25. package/dist/src/cli/commands/browser/close.js.map +1 -0
  26. package/dist/src/cli/commands/browser/create.d.ts +6 -0
  27. package/dist/src/cli/commands/browser/create.d.ts.map +1 -0
  28. package/dist/src/cli/commands/browser/create.js +281 -0
  29. package/dist/src/cli/commands/browser/create.js.map +1 -0
  30. package/dist/src/cli/commands/browser/fill.d.ts +6 -0
  31. package/dist/src/cli/commands/browser/fill.d.ts.map +1 -0
  32. package/dist/src/cli/commands/browser/fill.js +83 -0
  33. package/dist/src/cli/commands/browser/fill.js.map +1 -0
  34. package/dist/src/cli/commands/browser/forward.d.ts +6 -0
  35. package/dist/src/cli/commands/browser/forward.d.ts.map +1 -0
  36. package/dist/src/cli/commands/browser/forward.js +42 -0
  37. package/dist/src/cli/commands/browser/forward.js.map +1 -0
  38. package/dist/src/cli/commands/browser/get-blocks.d.ts +6 -0
  39. package/dist/src/cli/commands/browser/get-blocks.d.ts.map +1 -0
  40. package/dist/src/cli/commands/browser/get-blocks.js +35 -0
  41. package/dist/src/cli/commands/browser/get-blocks.js.map +1 -0
  42. package/dist/src/cli/commands/browser/goto.d.ts +6 -0
  43. package/dist/src/cli/commands/browser/goto.d.ts.map +1 -0
  44. package/dist/src/cli/commands/browser/goto.js +53 -0
  45. package/dist/src/cli/commands/browser/goto.js.map +1 -0
  46. package/dist/src/cli/commands/browser/hover.d.ts +6 -0
  47. package/dist/src/cli/commands/browser/hover.d.ts.map +1 -0
  48. package/dist/src/cli/commands/browser/hover.js +63 -0
  49. package/dist/src/cli/commands/browser/hover.js.map +1 -0
  50. package/dist/src/cli/commands/browser/index.d.ts +9 -0
  51. package/dist/src/cli/commands/browser/index.d.ts.map +1 -0
  52. package/dist/src/cli/commands/browser/index.js +71 -0
  53. package/dist/src/cli/commands/browser/index.js.map +1 -0
  54. package/dist/src/cli/commands/browser/list.d.ts +6 -0
  55. package/dist/src/cli/commands/browser/list.d.ts.map +1 -0
  56. package/dist/src/cli/commands/browser/list.js +85 -0
  57. package/dist/src/cli/commands/browser/list.js.map +1 -0
  58. package/dist/src/cli/commands/browser/press.d.ts +6 -0
  59. package/dist/src/cli/commands/browser/press.d.ts.map +1 -0
  60. package/dist/src/cli/commands/browser/press.js +67 -0
  61. package/dist/src/cli/commands/browser/press.js.map +1 -0
  62. package/dist/src/cli/commands/browser/reload.d.ts +6 -0
  63. package/dist/src/cli/commands/browser/reload.d.ts.map +1 -0
  64. package/dist/src/cli/commands/browser/reload.js +42 -0
  65. package/dist/src/cli/commands/browser/reload.js.map +1 -0
  66. package/dist/src/cli/commands/browser/run.d.ts +6 -0
  67. package/dist/src/cli/commands/browser/run.d.ts.map +1 -0
  68. package/dist/src/cli/commands/browser/run.js +618 -0
  69. package/dist/src/cli/commands/browser/run.js.map +1 -0
  70. package/dist/src/cli/commands/browser/screenshot.d.ts +6 -0
  71. package/dist/src/cli/commands/browser/screenshot.d.ts.map +1 -0
  72. package/dist/src/cli/commands/browser/screenshot.js +72 -0
  73. package/dist/src/cli/commands/browser/screenshot.js.map +1 -0
  74. package/dist/src/cli/commands/browser/scroll-into-view.d.ts +6 -0
  75. package/dist/src/cli/commands/browser/scroll-into-view.d.ts.map +1 -0
  76. package/dist/src/cli/commands/browser/scroll-into-view.js +64 -0
  77. package/dist/src/cli/commands/browser/scroll-into-view.js.map +1 -0
  78. package/dist/src/cli/commands/browser/scroll.d.ts +6 -0
  79. package/dist/src/cli/commands/browser/scroll.d.ts.map +1 -0
  80. package/dist/src/cli/commands/browser/scroll.js +63 -0
  81. package/dist/src/cli/commands/browser/scroll.js.map +1 -0
  82. package/dist/src/cli/commands/browser/select.d.ts +6 -0
  83. package/dist/src/cli/commands/browser/select.d.ts.map +1 -0
  84. package/dist/src/cli/commands/browser/select.js +83 -0
  85. package/dist/src/cli/commands/browser/select.js.map +1 -0
  86. package/dist/src/cli/commands/browser/snapshot.d.ts +6 -0
  87. package/dist/src/cli/commands/browser/snapshot.d.ts.map +1 -0
  88. package/dist/src/cli/commands/browser/snapshot.js +72 -0
  89. package/dist/src/cli/commands/browser/snapshot.js.map +1 -0
  90. package/dist/src/cli/commands/browser/status.d.ts +6 -0
  91. package/dist/src/cli/commands/browser/status.d.ts.map +1 -0
  92. package/dist/src/cli/commands/browser/status.js +91 -0
  93. package/dist/src/cli/commands/browser/status.js.map +1 -0
  94. package/dist/src/cli/commands/browser/stream.d.ts +6 -0
  95. package/dist/src/cli/commands/browser/stream.d.ts.map +1 -0
  96. package/dist/src/cli/commands/browser/stream.js +135 -0
  97. package/dist/src/cli/commands/browser/stream.js.map +1 -0
  98. package/dist/src/cli/commands/browser/tunnel.d.ts +13 -0
  99. package/dist/src/cli/commands/browser/tunnel.d.ts.map +1 -0
  100. package/dist/src/cli/commands/browser/tunnel.js +225 -0
  101. package/dist/src/cli/commands/browser/tunnel.js.map +1 -0
  102. package/dist/src/cli/commands/browser/type.d.ts +6 -0
  103. package/dist/src/cli/commands/browser/type.d.ts.map +1 -0
  104. package/dist/src/cli/commands/browser/type.js +61 -0
  105. package/dist/src/cli/commands/browser/type.js.map +1 -0
  106. package/dist/src/cli/commands/browser/uncheck.d.ts +6 -0
  107. package/dist/src/cli/commands/browser/uncheck.d.ts.map +1 -0
  108. package/dist/src/cli/commands/browser/uncheck.js +62 -0
  109. package/dist/src/cli/commands/browser/uncheck.js.map +1 -0
  110. package/dist/src/cli/commands/browser/url.d.ts +6 -0
  111. package/dist/src/cli/commands/browser/url.d.ts.map +1 -0
  112. package/dist/src/cli/commands/browser/url.js +40 -0
  113. package/dist/src/cli/commands/browser/url.js.map +1 -0
  114. package/dist/src/cli/commands/browser/wait-for-load.d.ts +6 -0
  115. package/dist/src/cli/commands/browser/wait-for-load.d.ts.map +1 -0
  116. package/dist/src/cli/commands/browser/wait-for-load.js +50 -0
  117. package/dist/src/cli/commands/browser/wait-for-load.js.map +1 -0
  118. package/dist/src/cli/commands/browser/wait-for-selector.d.ts +6 -0
  119. package/dist/src/cli/commands/browser/wait-for-selector.d.ts.map +1 -0
  120. package/dist/src/cli/commands/browser/wait-for-selector.js +52 -0
  121. package/dist/src/cli/commands/browser/wait-for-selector.js.map +1 -0
  122. package/dist/src/cli/commands/browser/wait.d.ts +6 -0
  123. package/dist/src/cli/commands/browser/wait.d.ts.map +1 -0
  124. package/dist/src/cli/commands/browser/wait.js +60 -0
  125. package/dist/src/cli/commands/browser/wait.js.map +1 -0
  126. package/dist/src/cli/commands/test/run.d.ts.map +1 -1
  127. package/dist/src/cli/commands/test/run.js +39 -8
  128. package/dist/src/cli/commands/test/run.js.map +1 -1
  129. package/dist/src/cli/index.js +2 -0
  130. package/dist/src/cli/index.js.map +1 -1
  131. package/dist/src/cli/lib/browser-sessions.d.ts +72 -0
  132. package/dist/src/cli/lib/browser-sessions.d.ts.map +1 -0
  133. package/dist/src/cli/lib/browser-sessions.js +184 -0
  134. package/dist/src/cli/lib/browser-sessions.js.map +1 -0
  135. package/dist/src/cli/lib/download.d.ts +2 -2
  136. package/dist/src/cli/lib/download.d.ts.map +1 -1
  137. package/dist/src/cli/lib/download.js +21 -5
  138. package/dist/src/cli/lib/download.js.map +1 -1
  139. package/dist/src/cli/lib/output.d.ts.map +1 -1
  140. package/dist/src/cli/lib/output.js +11 -4
  141. package/dist/src/cli/lib/output.js.map +1 -1
  142. package/lib/api/browser-types.ts +278 -0
  143. package/lib/api/browser.test.ts +378 -0
  144. package/lib/api/browser.ts +279 -0
  145. package/package.json +2 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"click.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/click.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,eAAO,MAAM,YAAY,SAkDrB,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * qa-use browser click - Click element by ref or semantic text
3
+ */
4
+ import { Command } from 'commander';
5
+ import { BrowserApiClient } from '../../../../lib/api/browser.js';
6
+ import { resolveSessionId, touchSession } from '../../lib/browser-sessions.js';
7
+ import { loadConfig } from '../../lib/config.js';
8
+ import { success, error } from '../../lib/output.js';
9
+ /**
10
+ * Normalize ref by stripping leading @ if present
11
+ */
12
+ function normalizeRef(ref) {
13
+ return ref.startsWith('@') ? ref.slice(1) : ref;
14
+ }
15
+ export const clickCommand = new Command('click')
16
+ .description('Click an element by ref or semantic description')
17
+ .argument('[ref]', 'Element ref from snapshot (e.g., "e3" or "@e3")')
18
+ .option('-s, --session-id <id>', 'Session ID (auto-resolved if only one session)')
19
+ .option('-t, --text <description>', 'Semantic element description (AI-based, slower)')
20
+ .action(async (ref, options) => {
21
+ try {
22
+ // Validate that either ref or --text is provided
23
+ if (!ref && !options.text) {
24
+ console.log(error('Either <ref> argument or --text option is required'));
25
+ process.exit(1);
26
+ }
27
+ const config = await loadConfig();
28
+ if (!config.api_key) {
29
+ console.log(error('API key not configured. Run `qa-use setup` first.'));
30
+ process.exit(1);
31
+ }
32
+ const client = new BrowserApiClient(config.api_url);
33
+ client.setApiKey(config.api_key);
34
+ const resolved = await resolveSessionId({
35
+ explicitId: options.sessionId,
36
+ client,
37
+ });
38
+ // Build action with either ref or text
39
+ const action = { type: 'click' };
40
+ if (ref) {
41
+ action.ref = normalizeRef(ref);
42
+ }
43
+ else if (options.text) {
44
+ action.text = options.text;
45
+ }
46
+ const result = await client.executeAction(resolved.id, action);
47
+ if (result.success) {
48
+ const target = ref ? `element ${normalizeRef(ref)}` : `"${options.text}"`;
49
+ console.log(success(`Clicked ${target}`));
50
+ await touchSession(resolved.id);
51
+ }
52
+ else {
53
+ const hint = result.error || 'Click failed';
54
+ console.log(error(`${hint}. Use 'qa-use browser snapshot' to see available elements.`));
55
+ process.exit(1);
56
+ }
57
+ }
58
+ catch (err) {
59
+ console.log(error(err instanceof Error ? err.message : 'Failed to click element'));
60
+ process.exit(1);
61
+ }
62
+ });
63
+ //# sourceMappingURL=click.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"click.js","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/click.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * qa-use browser close - Close a browser session
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const closeCommand: Command;
6
+ //# sourceMappingURL=close.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/close.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,YAAY,SAwCrB,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * qa-use browser close - Close a browser session
3
+ */
4
+ import { Command } from 'commander';
5
+ import { BrowserApiClient } from '../../../../lib/api/browser.js';
6
+ import { resolveSessionId, removeStoredSession } from '../../lib/browser-sessions.js';
7
+ import { loadConfig } from '../../lib/config.js';
8
+ import { success, error, info } from '../../lib/output.js';
9
+ export const closeCommand = new Command('close')
10
+ .description('Close a browser session')
11
+ .option('-s, --session-id <id>', 'Session ID (auto-resolved if only one session)')
12
+ .action(async (options) => {
13
+ try {
14
+ // Load configuration
15
+ const config = await loadConfig();
16
+ if (!config.api_key) {
17
+ console.log(error('API key not configured. Run `qa-use setup` first.'));
18
+ process.exit(1);
19
+ }
20
+ // Create client and set API key
21
+ const client = new BrowserApiClient(config.api_url);
22
+ client.setApiKey(config.api_key);
23
+ // Resolve session ID
24
+ const resolved = await resolveSessionId({
25
+ explicitId: options.sessionId,
26
+ client,
27
+ });
28
+ console.log(info(`Closing session ${resolved.id}...`));
29
+ // Close session on API
30
+ await client.deleteSession(resolved.id);
31
+ // Remove from local storage
32
+ await removeStoredSession(resolved.id);
33
+ console.log(success(`Session ${resolved.id} closed successfully`));
34
+ // Show source if auto-resolved
35
+ if (resolved.source === 'stored') {
36
+ console.log(info('(Session was auto-resolved from local storage)'));
37
+ }
38
+ }
39
+ catch (err) {
40
+ console.log(error(err instanceof Error ? err.message : 'Failed to close session'));
41
+ process.exit(1);
42
+ }
43
+ });
44
+ //# sourceMappingURL=close.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close.js","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/close.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAM3D,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,yBAAyB,CAAC;KACtC,MAAM,CAAC,uBAAuB,EAAE,gDAAgD,CAAC;KACjF,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,EAAE;IACtC,IAAI,CAAC;QACH,qBAAqB;QACrB,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,gCAAgC;QAChC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEjC,qBAAqB;QACrB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC;YACtC,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,MAAM;SACP,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAEvD,uBAAuB;QACvB,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAExC,4BAA4B;QAC5B,MAAM,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAEvC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,QAAQ,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC;QAEnE,+BAA+B;QAC/B,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC;QACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * qa-use browser create - Create a new browser session
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const createCommand: Command;
6
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/create.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC,eAAO,MAAM,aAAa,SA4DtB,CAAC"}
@@ -0,0 +1,281 @@
1
+ /**
2
+ * qa-use browser create - Create a new browser session
3
+ */
4
+ import { Command } from 'commander';
5
+ import { BrowserApiClient } from '../../../../lib/api/browser.js';
6
+ import { BrowserManager } from '../../../../lib/browser/index.js';
7
+ import { TunnelManager } from '../../../../lib/tunnel/index.js';
8
+ import { storeSession, createStoredSession, removeStoredSession, } from '../../lib/browser-sessions.js';
9
+ import { loadConfig } from '../../lib/config.js';
10
+ import { success, error, info, warning } from '../../lib/output.js';
11
+ export const createCommand = new Command('create')
12
+ .description('Create a new browser session')
13
+ .option('--headless', 'Run browser in headless mode (default: true for remote, false for tunnel)')
14
+ .option('--no-headless', 'Run browser with visible UI')
15
+ .option('--viewport <type>', 'Viewport type: desktop, mobile, or tablet (default: desktop)', 'desktop')
16
+ .option('--timeout <seconds>', 'Session timeout in seconds (default: 300)', '300')
17
+ .option('--ws-url <url>', 'WebSocket URL for remote/tunneled browser')
18
+ .option('--tunnel', 'Start local browser with tunnel (keeps process running)')
19
+ .option('-s, --subdomain <name>', 'Custom tunnel subdomain (only with --tunnel)')
20
+ .action(async (options) => {
21
+ // Validate mutually exclusive options
22
+ if (options.tunnel && options.wsUrl) {
23
+ console.log(error('Cannot use both --tunnel and --ws-url'));
24
+ process.exit(1);
25
+ }
26
+ if (options.subdomain && !options.tunnel) {
27
+ console.log(error('--subdomain can only be used with --tunnel'));
28
+ process.exit(1);
29
+ }
30
+ // Load configuration
31
+ const config = await loadConfig();
32
+ if (!config.api_key) {
33
+ console.log(error('API key not configured. Run `qa-use setup` first.'));
34
+ process.exit(1);
35
+ }
36
+ // Validate viewport type
37
+ const validViewports = ['desktop', 'mobile', 'tablet'];
38
+ const viewport = (options.viewport || 'desktop');
39
+ if (!validViewports.includes(viewport)) {
40
+ console.log(error(`Invalid viewport: ${viewport}. Must be one of: ${validViewports.join(', ')}`));
41
+ process.exit(1);
42
+ }
43
+ // Parse timeout
44
+ const timeout = parseInt(String(options.timeout), 10);
45
+ if (isNaN(timeout) || timeout < 60 || timeout > 3600) {
46
+ console.log(error('Timeout must be between 60 and 3600 seconds'));
47
+ process.exit(1);
48
+ }
49
+ // Create client and set API key
50
+ const client = new BrowserApiClient(config.api_url);
51
+ client.setApiKey(config.api_key);
52
+ if (options.tunnel) {
53
+ // Tunnel mode: start local browser + tunnel, then create session
54
+ await runTunnelMode(client, config.api_key, options, viewport, timeout);
55
+ }
56
+ else {
57
+ // Normal mode: create remote session and exit
58
+ await createRemoteSession(client, options, viewport, timeout);
59
+ }
60
+ });
61
+ /**
62
+ * Create a remote browser session (normal mode)
63
+ */
64
+ async function createRemoteSession(client, options, viewport, timeout) {
65
+ try {
66
+ console.log(info('Creating browser session...'));
67
+ // Create session
68
+ const session = await client.createSession({
69
+ headless: options.headless !== false,
70
+ viewport,
71
+ timeout,
72
+ ws_url: options.wsUrl,
73
+ });
74
+ console.log(info(`Session created: ${session.id}`));
75
+ console.log(info(`Status: ${session.status}`));
76
+ // Wait for session to become active if starting
77
+ if (session.status === 'starting') {
78
+ console.log(info('Waiting for session to become active...'));
79
+ const activeSession = await client.waitForStatus(session.id, 'active', 60000);
80
+ console.log(success(`Session ${activeSession.id} is now active`));
81
+ }
82
+ else if (session.status === 'active') {
83
+ console.log(success(`Session ${session.id} is active`));
84
+ }
85
+ // Store session locally
86
+ const storedSession = createStoredSession(session.id);
87
+ await storeSession(storedSession);
88
+ // Print session info
89
+ console.log('');
90
+ console.log(`Session ID: ${session.id}`);
91
+ console.log(`Viewport: ${viewport}`);
92
+ console.log(`Headless: ${options.headless !== false}`);
93
+ console.log(`Timeout: ${timeout}s`);
94
+ if (options.wsUrl) {
95
+ console.log(`WebSocket URL: ${options.wsUrl}`);
96
+ }
97
+ }
98
+ catch (err) {
99
+ console.log(error(err instanceof Error ? err.message : 'Failed to create session'));
100
+ process.exit(1);
101
+ }
102
+ }
103
+ /**
104
+ * Tunnel mode: start local browser + tunnel + API session, then keep running
105
+ */
106
+ async function runTunnelMode(client, apiKey, options, viewport, timeout) {
107
+ // Track resources for cleanup
108
+ let browser = null;
109
+ let tunnel = null;
110
+ let sessionId = null;
111
+ let heartbeatIntervalId = null;
112
+ // Cleanup function
113
+ const cleanup = async (exitCode = 0) => {
114
+ console.log('');
115
+ console.log(info('Shutting down...'));
116
+ // Stop heartbeat
117
+ if (heartbeatIntervalId) {
118
+ clearInterval(heartbeatIntervalId);
119
+ console.log(success('Heartbeat stopped'));
120
+ }
121
+ // Close API session and remove from local storage
122
+ if (sessionId && client) {
123
+ try {
124
+ await client.deleteSession(sessionId);
125
+ await removeStoredSession(sessionId);
126
+ console.log(success('API session closed'));
127
+ }
128
+ catch (err) {
129
+ console.log(warning(`Session cleanup: ${err instanceof Error ? err.message : 'Unknown error'}`));
130
+ }
131
+ }
132
+ // Stop tunnel
133
+ if (tunnel) {
134
+ try {
135
+ await tunnel.stopTunnel();
136
+ console.log(success('Tunnel closed'));
137
+ }
138
+ catch (err) {
139
+ console.log(warning(`Tunnel cleanup: ${err instanceof Error ? err.message : 'Unknown error'}`));
140
+ }
141
+ }
142
+ // Stop browser
143
+ if (browser) {
144
+ try {
145
+ await browser.stopBrowser();
146
+ console.log(success('Browser closed'));
147
+ }
148
+ catch (err) {
149
+ console.log(warning(`Browser cleanup: ${err instanceof Error ? err.message : 'Unknown error'}`));
150
+ }
151
+ }
152
+ console.log('');
153
+ console.log(info('Tunnel mode stopped'));
154
+ process.exit(exitCode);
155
+ };
156
+ // Handle signals for graceful shutdown
157
+ process.on('SIGINT', () => cleanup(0));
158
+ process.on('SIGTERM', () => cleanup(0));
159
+ try {
160
+ // Default to visible browser for tunnel mode (unless --headless explicitly set)
161
+ const headless = options.headless === true;
162
+ console.log('');
163
+ console.log(info('Starting browser with tunnel...'));
164
+ console.log(`Mode: ${headless ? 'Headless' : 'Visible Browser'}`);
165
+ console.log('');
166
+ // Step 1: Start local browser
167
+ console.log(info('Starting browser...'));
168
+ browser = new BrowserManager();
169
+ const browserResult = await browser.startBrowser({ headless });
170
+ const wsEndpoint = browserResult.wsEndpoint;
171
+ console.log(success('Browser started'));
172
+ // Step 2: Start tunnel with deterministic subdomain
173
+ console.log(info('Creating tunnel...'));
174
+ tunnel = new TunnelManager();
175
+ const wsUrl = new URL(wsEndpoint);
176
+ const browserPort = parseInt(wsUrl.port);
177
+ await tunnel.startTunnel(browserPort, {
178
+ subdomain: options.subdomain,
179
+ apiKey: apiKey,
180
+ sessionIndex: 0,
181
+ });
182
+ console.log(success('Tunnel created'));
183
+ // Step 3: Get tunneled WebSocket URL
184
+ const localWsUrl = browser.getWebSocketEndpoint();
185
+ if (!localWsUrl) {
186
+ console.log(error('Failed to get browser WebSocket endpoint'));
187
+ await cleanup(1);
188
+ return;
189
+ }
190
+ const tunneledWsUrl = tunnel.getWebSocketUrl(localWsUrl);
191
+ if (!tunneledWsUrl) {
192
+ console.log(error('Failed to create tunneled WebSocket URL'));
193
+ await cleanup(1);
194
+ return;
195
+ }
196
+ console.log(info(`Tunneled WebSocket: ${tunneledWsUrl}`));
197
+ console.log('');
198
+ // Step 4: Create API session with tunneled ws_url
199
+ console.log(info('Creating API session...'));
200
+ const session = await client.createSession({
201
+ headless,
202
+ viewport,
203
+ timeout,
204
+ ws_url: tunneledWsUrl,
205
+ });
206
+ sessionId = session.id;
207
+ console.log(info(`Session created: ${session.id}`));
208
+ // Wait for session to become active if starting
209
+ if (session.status === 'starting') {
210
+ console.log(info('Waiting for session to become active...'));
211
+ await client.waitForStatus(session.id, 'active', 60000);
212
+ }
213
+ console.log(success('Session is active'));
214
+ // Store session locally
215
+ const storedSession = createStoredSession(session.id);
216
+ await storeSession(storedSession);
217
+ // Print session info
218
+ console.log('');
219
+ console.log('='.repeat(50));
220
+ console.log(success('Browser tunnel ready!'));
221
+ console.log('='.repeat(50));
222
+ console.log('');
223
+ console.log(`Session ID: ${session.id}`);
224
+ console.log(`Viewport: ${viewport}`);
225
+ console.log(`Headless: ${headless}`);
226
+ console.log(`Timeout: ${timeout}s`);
227
+ console.log(`WebSocket URL: ${tunneledWsUrl}`);
228
+ console.log('');
229
+ console.log(info('Use this session with other browser commands:'));
230
+ console.log(` qa-use browser goto https://example.com`);
231
+ console.log(` qa-use browser screenshot`);
232
+ console.log(` qa-use browser snapshot`);
233
+ console.log('');
234
+ console.log(info('Press Ctrl+C to stop'));
235
+ console.log('');
236
+ // Step 5: Set up heartbeat to check session and tunnel health
237
+ let heartbeatCount = 0;
238
+ const heartbeatInterval = 30000; // 30 seconds
239
+ heartbeatIntervalId = setInterval(async () => {
240
+ heartbeatCount++;
241
+ const timestamp = new Date().toLocaleTimeString();
242
+ try {
243
+ // Check if API session still exists
244
+ const sessionStatus = await client.getSession(sessionId);
245
+ if (sessionStatus.status === 'closed') {
246
+ console.log(`[${timestamp}] Session closed externally, shutting down...`);
247
+ await removeStoredSession(sessionId);
248
+ sessionId = null;
249
+ await cleanup(0);
250
+ return;
251
+ }
252
+ // Check tunnel health
253
+ const tunnelHealthy = await tunnel.checkHealth();
254
+ if (tunnelHealthy) {
255
+ console.log(`[${timestamp}] Heartbeat #${heartbeatCount} - healthy`);
256
+ }
257
+ else {
258
+ console.log(`[${timestamp}] ${warning(`Heartbeat #${heartbeatCount} - tunnel unhealthy`)}`);
259
+ }
260
+ }
261
+ catch (err) {
262
+ const errMessage = err instanceof Error ? err.message : 'Unknown error';
263
+ // If session not found, it was closed externally
264
+ if (errMessage.includes('not found') || errMessage.includes('404')) {
265
+ console.log(`[${timestamp}] Session closed externally, shutting down...`);
266
+ await removeStoredSession(sessionId);
267
+ sessionId = null;
268
+ await cleanup(0);
269
+ return;
270
+ }
271
+ console.log(`[${timestamp}] ${warning(`Heartbeat error: ${errMessage}`)}`);
272
+ }
273
+ }, heartbeatInterval);
274
+ // Keep the process running
275
+ }
276
+ catch (err) {
277
+ console.log(error(err instanceof Error ? err.message : 'Failed to start tunnel'));
278
+ await cleanup(1);
279
+ }
280
+ }
281
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/create.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAWpE,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,YAAY,EAAE,2EAA2E,CAAC;KACjG,MAAM,CAAC,eAAe,EAAE,6BAA6B,CAAC;KACtD,MAAM,CACL,mBAAmB,EACnB,8DAA8D,EAC9D,SAAS,CACV;KACA,MAAM,CAAC,qBAAqB,EAAE,2CAA2C,EAAE,KAAK,CAAC;KACjF,MAAM,CAAC,gBAAgB,EAAE,2CAA2C,CAAC;KACrE,MAAM,CAAC,UAAU,EAAE,yDAAyD,CAAC;KAC7E,MAAM,CAAC,wBAAwB,EAAE,8CAA8C,CAAC;KAChF,MAAM,CAAC,KAAK,EAAE,OAAsB,EAAE,EAAE;IACvC,sCAAsC;IACtC,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,qBAAqB;IACrB,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,yBAAyB;IACzB,MAAM,cAAc,GAAmB,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAiB,CAAC;IACjE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,qBAAqB,QAAQ,qBAAqB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CACrF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,gBAAgB;IAChB,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IACtD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,IAAI,EAAE,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,gCAAgC;IAChC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEjC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,iEAAiE;QACjE,MAAM,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1E,CAAC;SAAM,CAAC;QACN,8CAA8C;QAC9C,MAAM,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;AACH,CAAC,CAAC,CAAC;AAEL;;GAEG;AACH,KAAK,UAAU,mBAAmB,CAChC,MAAwB,EACxB,OAAsB,EACtB,QAAsB,EACtB,OAAe;IAEf,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;QAEjD,iBAAiB;QACjB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC;YACzC,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,KAAK;YACpC,QAAQ;YACR,OAAO;YACP,MAAM,EAAE,OAAO,CAAC,KAAK;SACtB,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAE/C,gDAAgD;QAChD,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC,CAAC;YAC7D,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC9E,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,aAAa,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACpE,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,OAAO,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;QAC1D,CAAC;QAED,wBAAwB;QACxB,MAAM,aAAa,GAAG,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACtD,MAAM,YAAY,CAAC,aAAa,CAAC,CAAC;QAElC,qBAAqB;QACrB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,eAAe,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,aAAa,QAAQ,EAAE,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,GAAG,CAAC,CAAC;QACpC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC;QACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa,CAC1B,MAAwB,EACxB,MAAc,EACd,OAAsB,EACtB,QAAsB,EACtB,OAAe;IAEf,8BAA8B;IAC9B,IAAI,OAAO,GAA0B,IAAI,CAAC;IAC1C,IAAI,MAAM,GAAyB,IAAI,CAAC;IACxC,IAAI,SAAS,GAAkB,IAAI,CAAC;IACpC,IAAI,mBAAmB,GAA0B,IAAI,CAAC;IAEtD,mBAAmB;IACnB,MAAM,OAAO,GAAG,KAAK,EAAE,WAAmB,CAAC,EAAE,EAAE;QAC7C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC;QAEtC,iBAAiB;QACjB,IAAI,mBAAmB,EAAE,CAAC;YACxB,aAAa,CAAC,mBAAmB,CAAC,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAC5C,CAAC;QAED,kDAAkD;QAClD,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;gBACtC,MAAM,mBAAmB,CAAC,SAAS,CAAC,CAAC;gBACrC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,GAAG,CACT,OAAO,CAAC,oBAAoB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CACpF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,cAAc;QACd,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC;YACxC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,GAAG,CACT,OAAO,CAAC,mBAAmB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CACnF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,eAAe;QACf,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;gBAC5B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,GAAG,CACT,OAAO,CAAC,oBAAoB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CACpF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC,CAAC;IAEF,uCAAuC;IACvC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAExC,IAAI,CAAC;QACH,gFAAgF;QAChF,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC;QAE3C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,8BAA8B;QAC9B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACzC,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC;QAC/B,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAExC,oDAAoD;QACpD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;QACxC,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QAClC,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEzC,MAAM,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE;YACpC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,MAAM,EAAE,MAAM;YACd,YAAY,EAAE,CAAC;SAChB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAEvC,qCAAqC;QACrC,MAAM,UAAU,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;QAClD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC,CAAC;YAC/D,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC,CAAC;YAC9D,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,aAAa,EAAE,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,kDAAkD;QAClD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC;YACzC,QAAQ;YACR,QAAQ;YACR,OAAO;YACP,MAAM,EAAE,aAAa;SACtB,CAAC,CAAC;QAEH,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAEpD,gDAAgD;QAChD,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC,CAAC;YAC7D,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAE1C,wBAAwB;QACxB,MAAM,aAAa,GAAG,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACtD,MAAM,YAAY,CAAC,aAAa,CAAC,CAAC;QAElC,qBAAqB;QACrB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,GAAG,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,mBAAmB,aAAa,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,8DAA8D;QAC9D,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,MAAM,iBAAiB,GAAG,KAAK,CAAC,CAAC,aAAa;QAE9C,mBAAmB,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YAC3C,cAAc,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,kBAAkB,EAAE,CAAC;YAElD,IAAI,CAAC;gBACH,oCAAoC;gBACpC,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,SAAU,CAAC,CAAC;gBAE1D,IAAI,aAAa,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;oBACtC,OAAO,CAAC,GAAG,CAAC,IAAI,SAAS,+CAA+C,CAAC,CAAC;oBAC1E,MAAM,mBAAmB,CAAC,SAAU,CAAC,CAAC;oBACtC,SAAS,GAAG,IAAI,CAAC;oBACjB,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;oBACjB,OAAO;gBACT,CAAC;gBAED,sBAAsB;gBACtB,MAAM,aAAa,GAAG,MAAM,MAAO,CAAC,WAAW,EAAE,CAAC;gBAElD,IAAI,aAAa,EAAE,CAAC;oBAClB,OAAO,CAAC,GAAG,CAAC,IAAI,SAAS,gBAAgB,cAAc,YAAY,CAAC,CAAC;gBACvE,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CACT,IAAI,SAAS,KAAK,OAAO,CAAC,cAAc,cAAc,qBAAqB,CAAC,EAAE,CAC/E,CAAC;gBACJ,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,UAAU,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;gBAExE,iDAAiD;gBACjD,IAAI,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnE,OAAO,CAAC,GAAG,CAAC,IAAI,SAAS,+CAA+C,CAAC,CAAC;oBAC1E,MAAM,mBAAmB,CAAC,SAAU,CAAC,CAAC;oBACtC,SAAS,GAAG,IAAI,CAAC;oBACjB,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;oBACjB,OAAO;gBACT,CAAC;gBAED,OAAO,CAAC,GAAG,CAAC,IAAI,SAAS,KAAK,OAAO,CAAC,oBAAoB,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC,EAAE,iBAAiB,CAAC,CAAC;QAEtB,2BAA2B;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC;QAClF,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * qa-use browser fill - Fill input field by ref or semantic text
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const fillCommand: Command;
6
+ //# sourceMappingURL=fill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fill.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/fill.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,eAAO,MAAM,WAAW,SA0ErB,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * qa-use browser fill - Fill input field by ref or semantic text
3
+ */
4
+ import { Command } from 'commander';
5
+ import { BrowserApiClient } from '../../../../lib/api/browser.js';
6
+ import { resolveSessionId, touchSession } from '../../lib/browser-sessions.js';
7
+ import { loadConfig } from '../../lib/config.js';
8
+ import { success, error } from '../../lib/output.js';
9
+ /**
10
+ * Normalize ref by stripping leading @ if present
11
+ */
12
+ function normalizeRef(ref) {
13
+ return ref.startsWith('@') ? ref.slice(1) : ref;
14
+ }
15
+ export const fillCommand = new Command('fill')
16
+ .description('Fill an input field by ref or semantic description')
17
+ .argument('[ref]', 'Element ref from snapshot (e.g., "e4" or "@e4")')
18
+ .argument('<value>', 'Value to fill into the field')
19
+ .option('-s, --session-id <id>', 'Session ID (auto-resolved if only one session)')
20
+ .option('-t, --text <description>', 'Semantic element description (AI-based, slower)')
21
+ .action(async (refOrValue, valueOrUndefined, options) => {
22
+ try {
23
+ // Handle argument parsing: if --text is used, first arg is value; otherwise first is ref, second is value
24
+ let ref;
25
+ let value;
26
+ if (options.text) {
27
+ // When using --text, the first argument is the value
28
+ value = refOrValue;
29
+ if (!value) {
30
+ console.log(error('Value argument is required'));
31
+ process.exit(1);
32
+ }
33
+ }
34
+ else {
35
+ // Normal mode: first arg is ref, second is value
36
+ ref = refOrValue;
37
+ value = valueOrUndefined;
38
+ if (!ref || !value) {
39
+ console.log(error('Both <ref> and <value> arguments are required (or use --text with <value>)'));
40
+ process.exit(1);
41
+ }
42
+ }
43
+ const config = await loadConfig();
44
+ if (!config.api_key) {
45
+ console.log(error('API key not configured. Run `qa-use setup` first.'));
46
+ process.exit(1);
47
+ }
48
+ const client = new BrowserApiClient(config.api_url);
49
+ client.setApiKey(config.api_key);
50
+ const resolved = await resolveSessionId({
51
+ explicitId: options.sessionId,
52
+ client,
53
+ });
54
+ // Build action with either ref or text
55
+ const action = {
56
+ type: 'fill',
57
+ value,
58
+ };
59
+ if (ref) {
60
+ action.ref = normalizeRef(ref);
61
+ }
62
+ else if (options.text) {
63
+ action.text = options.text;
64
+ }
65
+ const result = await client.executeAction(resolved.id, action);
66
+ if (result.success) {
67
+ const displayValue = value.length > 50 ? value.slice(0, 47) + '...' : value;
68
+ const target = ref ? normalizeRef(ref) : `"${options.text}"`;
69
+ console.log(success(`Filled ${target} with "${displayValue}"`));
70
+ await touchSession(resolved.id);
71
+ }
72
+ else {
73
+ const hint = result.error || 'Fill failed';
74
+ console.log(error(`${hint}. Use 'qa-use browser snapshot' to see available elements.`));
75
+ process.exit(1);
76
+ }
77
+ }
78
+ catch (err) {
79
+ console.log(error(err instanceof Error ? err.message : 'Failed to fill input'));
80
+ process.exit(1);
81
+ }
82
+ });
83
+ //# sourceMappingURL=fill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fill.js","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/fill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * qa-use browser forward - Navigate forward in browser history
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const forwardCommand: Command;
6
+ //# sourceMappingURL=forward.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forward.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/forward.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,cAAc,SAkCvB,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * qa-use browser forward - Navigate forward in browser history
3
+ */
4
+ import { Command } from 'commander';
5
+ import { BrowserApiClient } from '../../../../lib/api/browser.js';
6
+ import { resolveSessionId, touchSession } from '../../lib/browser-sessions.js';
7
+ import { loadConfig } from '../../lib/config.js';
8
+ import { success, error } from '../../lib/output.js';
9
+ export const forwardCommand = new Command('forward')
10
+ .description('Navigate forward in browser history')
11
+ .option('-s, --session-id <id>', 'Session ID (auto-resolved if only one session)')
12
+ .action(async (options) => {
13
+ try {
14
+ const config = await loadConfig();
15
+ if (!config.api_key) {
16
+ console.log(error('API key not configured. Run `qa-use setup` first.'));
17
+ process.exit(1);
18
+ }
19
+ const client = new BrowserApiClient(config.api_url);
20
+ client.setApiKey(config.api_key);
21
+ const resolved = await resolveSessionId({
22
+ explicitId: options.sessionId,
23
+ client,
24
+ });
25
+ const result = await client.executeAction(resolved.id, {
26
+ type: 'forward',
27
+ });
28
+ if (result.success) {
29
+ console.log(success('Navigated forward'));
30
+ await touchSession(resolved.id);
31
+ }
32
+ else {
33
+ console.log(error(result.error || 'Navigation failed'));
34
+ process.exit(1);
35
+ }
36
+ }
37
+ catch (err) {
38
+ console.log(error(err instanceof Error ? err.message : 'Failed to navigate forward'));
39
+ process.exit(1);
40
+ }
41
+ });
42
+ //# sourceMappingURL=forward.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forward.js","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/forward.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAMrD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,qCAAqC,CAAC;KAClD,MAAM,CAAC,uBAAuB,EAAE,gDAAgD,CAAC;KACjF,MAAM,CAAC,KAAK,EAAE,OAAuB,EAAE,EAAE;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEjC,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC;YACtC,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,MAAM;SACP,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE;YACrD,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC;YAC1C,MAAM,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,mBAAmB,CAAC,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC;QACtF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * qa-use browser get-blocks - Get recorded blocks (test steps) from the session
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const getBlocksCommand: Command;
6
+ //# sourceMappingURL=get-blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-blocks.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/browser/get-blocks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,eAAO,MAAM,gBAAgB,SA4BzB,CAAC"}