opensteer 0.9.5 → 0.9.7

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 (35) hide show
  1. package/dist/{chunk-7LQL5YUR.js → chunk-3OHKIPBD.js} +571 -738
  2. package/dist/chunk-3OHKIPBD.js.map +1 -0
  3. package/dist/chunk-52UNH5UW.js +458 -0
  4. package/dist/chunk-52UNH5UW.js.map +1 -0
  5. package/dist/{chunk-GSCQQKZZ.js → chunk-PJXN7HED.js} +334 -18
  6. package/dist/chunk-PJXN7HED.js.map +1 -0
  7. package/dist/{chunk-ZRF7WMS3.js → chunk-R33BXCMQ.js} +16 -7
  8. package/dist/chunk-R33BXCMQ.js.map +1 -0
  9. package/dist/{chunk-T5P2QGZ3.js → chunk-U4BUCIZ4.js} +153 -12
  10. package/dist/chunk-U4BUCIZ4.js.map +1 -0
  11. package/dist/cli/bin.cjs +1421 -824
  12. package/dist/cli/bin.cjs.map +1 -1
  13. package/dist/cli/bin.js +286 -129
  14. package/dist/cli/bin.js.map +1 -1
  15. package/dist/index.cjs +1117 -703
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +58 -53
  18. package/dist/index.d.ts +58 -53
  19. package/dist/index.js +4 -4
  20. package/dist/local-view/public/assets/app.js +10 -1
  21. package/dist/local-view/serve-entry.cjs +6815 -1272
  22. package/dist/local-view/serve-entry.cjs.map +1 -1
  23. package/dist/local-view/serve-entry.js +2 -2
  24. package/dist/opensteer-CY2QUJEG.js +6 -0
  25. package/dist/{opensteer-T2JENADR.js.map → opensteer-CY2QUJEG.js.map} +1 -1
  26. package/dist/{session-control-M3JD7ZKA.js → session-control-FIP6ZJLH.js} +4 -4
  27. package/dist/{session-control-M3JD7ZKA.js.map → session-control-FIP6ZJLH.js.map} +1 -1
  28. package/package.json +7 -7
  29. package/dist/chunk-7D45QUZ3.js +0 -332
  30. package/dist/chunk-7D45QUZ3.js.map +0 -1
  31. package/dist/chunk-7LQL5YUR.js.map +0 -1
  32. package/dist/chunk-GSCQQKZZ.js.map +0 -1
  33. package/dist/chunk-T5P2QGZ3.js.map +0 -1
  34. package/dist/chunk-ZRF7WMS3.js.map +0 -1
  35. package/dist/opensteer-T2JENADR.js +0 -6
package/dist/cli/bin.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { runLocalViewService } from '../chunk-ZRF7WMS3.js';
3
- import { createOpensteerSemanticRuntime, dispatchSemanticOperation, loadEnvironment, normalizeOpensteerProviderMode, resolveOpensteerRuntimeConfig, assertProviderSupportsEngine, resolveOpensteerProvider, requireCloudAppBaseUrl, CloudSessionProxy, FlowRecorderCollector, generateReplayScript, OpensteerCloudClient } from '../chunk-7LQL5YUR.js';
4
- import { OpensteerBrowserManager, stopLocalViewService, setLocalViewMode, ensureLocalViewServiceRunning, buildLocalViewSessionUrl, resolveOpensteerEngineName, resolveFilesystemWorkspacePath } from '../chunk-GSCQQKZZ.js';
5
- import { discoverLocalCdpBrowsers, inspectCdpEndpoint, readPersistedLocalBrowserSessionRecord, isProcessRunning, buildLocalViewSessionId, pathExists, readPersistedCloudSessionRecord } from '../chunk-T5P2QGZ3.js';
2
+ import { runLocalViewService } from '../chunk-R33BXCMQ.js';
3
+ import { createOpensteerSemanticRuntime, dispatchSemanticOperation, isBrowserCoreError, loadEnvironment, normalizeOpensteerProviderMode, resolveOpensteerRuntimeConfig, assertProviderSupportsEngine, resolveOpensteerProvider, requireCloudAppBaseUrl, CloudSessionProxy, FlowRecorderCollector, generateReplayScript, OpensteerCloudClient } from '../chunk-3OHKIPBD.js';
4
+ import { isOpensteerProtocolError, OpensteerBrowserManager, stopLocalViewService, setLocalViewMode, ensureLocalViewServiceRunning, buildLocalViewSessionUrl, resolveOpensteerEngineName, resolveFilesystemWorkspacePath } from '../chunk-PJXN7HED.js';
5
+ import { discoverLocalCdpBrowsers, inspectCdpEndpoint, readPersistedLocalBrowserSessionRecord, getPersistedLocalBrowserSessionOwnership, isAttachedLocalBrowserSessionReachable, isProcessRunning, buildLocalViewSessionIdForRecord, pathExists, readPersistedCloudSessionRecord } from '../chunk-U4BUCIZ4.js';
6
6
  import process4 from 'process';
7
7
  import { mkdir, writeFile } from 'fs/promises';
8
8
  import path2 from 'path';
@@ -14,13 +14,115 @@ import { fileURLToPath } from 'url';
14
14
 
15
15
  // package.json
16
16
  var package_default = {
17
- version: "0.9.5"};
17
+ version: "0.9.7"};
18
18
 
19
19
  // src/cli/env-loader.ts
20
20
  async function loadCliEnvironment(cwd) {
21
21
  loadEnvironment(cwd);
22
22
  }
23
23
 
24
+ // src/cli/errors.ts
25
+ var CliError = class extends Error {
26
+ type;
27
+ usage;
28
+ constructor(type, message, usage) {
29
+ super(message);
30
+ this.name = "CliError";
31
+ this.type = type;
32
+ this.usage = usage;
33
+ }
34
+ format() {
35
+ return this.usage === void 0 ? this.message : `${this.message}
36
+ Usage: ${this.usage}`;
37
+ }
38
+ };
39
+ function isCliError(value) {
40
+ return value instanceof CliError;
41
+ }
42
+ function formatCliErrorOutput(error) {
43
+ if (isCliError(error)) {
44
+ return {
45
+ success: false,
46
+ error: error.format(),
47
+ type: error.type
48
+ };
49
+ }
50
+ if (isOpensteerProtocolError(error)) {
51
+ return {
52
+ success: false,
53
+ error: error.message,
54
+ code: error.code,
55
+ retriable: error.retriable
56
+ };
57
+ }
58
+ if (isBrowserCoreError(error)) {
59
+ return {
60
+ success: false,
61
+ error: error.message,
62
+ code: error.code,
63
+ retriable: error.retriable
64
+ };
65
+ }
66
+ if (error instanceof Error && "opensteerError" in error) {
67
+ const oe = error.opensteerError;
68
+ return {
69
+ success: false,
70
+ error: oe.message,
71
+ code: oe.code,
72
+ retriable: oe.retriable
73
+ };
74
+ }
75
+ if (error instanceof SyntaxError) {
76
+ return {
77
+ success: false,
78
+ error: error.message,
79
+ type: "invalid_value"
80
+ };
81
+ }
82
+ return {
83
+ success: false,
84
+ error: error instanceof Error ? error.message : String(error)
85
+ };
86
+ }
87
+ function emitWarning(warning) {
88
+ process.stderr.write(`${JSON.stringify({ warning })}
89
+ `);
90
+ }
91
+ var CLI_USAGE_HINTS = {
92
+ "session.open": "opensteer open <url> [--workspace <id>]",
93
+ "page.goto": "opensteer goto <url>",
94
+ "page.evaluate": "opensteer evaluate <script>",
95
+ "page.add-init-script": "opensteer init-script <script>",
96
+ "dom.click": "opensteer click <element> --persist <key>",
97
+ "dom.hover": "opensteer hover <element> --persist <key>",
98
+ "dom.input": "opensteer input <element> <text> --persist <key>",
99
+ "dom.scroll": "opensteer scroll <direction> <amount> --persist <key>",
100
+ "dom.extract": "opensteer extract <template> --persist <key>",
101
+ "network.detail": "opensteer network detail <recordId>",
102
+ "session.fetch": "opensteer fetch <url>",
103
+ "captcha.solve": "opensteer captcha solve --provider <name> --api-key <key>",
104
+ "scripts.capture": "opensteer scripts capture",
105
+ "scripts.beautify": "opensteer scripts beautify <artifactId>",
106
+ "scripts.deobfuscate": "opensteer scripts deobfuscate <artifactId>",
107
+ "scripts.sandbox": "opensteer scripts sandbox <artifactId>",
108
+ "interaction.capture": "opensteer interaction capture",
109
+ "interaction.get": "opensteer interaction get <traceId>",
110
+ "interaction.replay": "opensteer interaction replay <traceId>",
111
+ "interaction.diff": "opensteer interaction diff <leftTraceId> <rightTraceId>",
112
+ "artifact.read": "opensteer artifact read <artifactId>",
113
+ "computer.click": "opensteer computer click <x> <y>",
114
+ "computer.type": "opensteer computer type <text>",
115
+ "computer.key": "opensteer computer key <key>",
116
+ "computer.scroll": "opensteer computer scroll <x> <y> --dx <n> --dy <n>",
117
+ "computer.move": "opensteer computer move <x> <y>",
118
+ "computer.drag": "opensteer computer drag <x1> <y1> <x2> <y2>",
119
+ "computer.screenshot": "opensteer computer screenshot",
120
+ exec: "opensteer exec <expression>",
121
+ record: "opensteer record --url <url> --workspace <id>",
122
+ "browser.inspect": "opensteer browser inspect <endpoint>",
123
+ "browser.clone": "opensteer browser clone --source-user-data-dir <path>"
124
+ };
125
+
24
126
  // src/cli/help.ts
25
127
  function getHelpText() {
26
128
  return `Opensteer CLI
@@ -279,7 +381,7 @@ function parseCommandLine(argv) {
279
381
  const key = token.slice(2, separator === -1 ? void 0 : separator);
280
382
  const spec = CLI_OPTION_SPECS[key];
281
383
  if (spec === void 0) {
282
- throw new Error(`Unknown option: --${key}.`);
384
+ throw new CliError("unknown_option", `Unknown option: --${key}.`);
283
385
  }
284
386
  if (separator !== -1) {
285
387
  rawOptions.set(key, [...rawOptions.get(key) ?? [], token.slice(separator + 1)]);
@@ -308,7 +410,8 @@ function parseCommandLine(argv) {
308
410
  continue;
309
411
  }
310
412
  if (next === void 0 || next.startsWith("--")) {
311
- throw new Error(
413
+ throw new CliError(
414
+ "missing_arguments",
312
415
  `Option "--${key}" requires a value.${next?.startsWith("--") === true ? ` Use "--${key}=<value>" when the value begins with "--".` : ``}`
313
416
  );
314
417
  }
@@ -354,10 +457,14 @@ function parseCommandLine(argv) {
354
457
  const autoLocalView = readOptionalBoolean(rawOptions, "auto");
355
458
  const noAutoLocalView = readOptionalBoolean(rawOptions, "no-auto");
356
459
  if (autoLocalView === true && noAutoLocalView === true) {
357
- throw new Error('Options "--auto" and "--no-auto" cannot be combined.');
460
+ throw new CliError("invalid_option", 'Options "--auto" and "--no-auto" cannot be combined.');
358
461
  }
359
462
  if (command[0] !== "view" && (autoLocalView !== void 0 || noAutoLocalView !== void 0)) {
360
- throw new Error('Options "--auto" and "--no-auto" are only supported with "view".');
463
+ throw new CliError(
464
+ "invalid_option",
465
+ 'Options "--auto" and "--no-auto" are only supported with "view".',
466
+ "opensteer view --auto"
467
+ );
361
468
  }
362
469
  const global = readOptionalBoolean(rawOptions, "global");
363
470
  const yes = readOptionalBoolean(rawOptions, "yes");
@@ -413,7 +520,7 @@ function parseKeyValueList(values) {
413
520
  values.map((entry) => {
414
521
  const separator = entry.indexOf("=");
415
522
  if (separator <= 0) {
416
- throw new Error(`Expected NAME=VALUE, received "${entry}".`);
523
+ throw new CliError("invalid_value", `Expected NAME=VALUE, received "${entry}".`);
417
524
  }
418
525
  return [entry.slice(0, separator), entry.slice(separator + 1)];
419
526
  })
@@ -444,7 +551,7 @@ function readOptionalBoolean(options, name) {
444
551
  if (value === "false") {
445
552
  return false;
446
553
  }
447
- throw new Error(`Option "--${name}" must be true or false.`);
554
+ throw new CliError("invalid_value", `Option "--${name}" must be true or false.`);
448
555
  }
449
556
  function readOptionalNumber(options, name) {
450
557
  const value = readSingle(options, name);
@@ -453,13 +560,20 @@ function readOptionalNumber(options, name) {
453
560
  }
454
561
  const parsed = Number(value);
455
562
  if (!Number.isFinite(parsed)) {
456
- throw new Error(`Option "--${name}" must be a number.`);
563
+ throw new CliError("invalid_value", `Option "--${name}" must be a number.`);
457
564
  }
458
565
  return parsed;
459
566
  }
460
567
  function readJsonValue(options, name) {
461
568
  const value = readSingle(options, name);
462
- return value === void 0 ? void 0 : JSON.parse(value);
569
+ if (value === void 0) {
570
+ return void 0;
571
+ }
572
+ try {
573
+ return JSON.parse(value);
574
+ } catch {
575
+ throw new CliError("invalid_value", `Option "--${name}" contains invalid JSON.`);
576
+ }
463
577
  }
464
578
  function readJsonObject(options, name) {
465
579
  const parsed = readJsonValue(options, name);
@@ -467,7 +581,7 @@ function readJsonObject(options, name) {
467
581
  return void 0;
468
582
  }
469
583
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
470
- throw new Error(`Option "--${name}" must be a JSON object.`);
584
+ throw new CliError("invalid_value", `Option "--${name}" must be a JSON object.`);
471
585
  }
472
586
  return parsed;
473
587
  }
@@ -477,7 +591,7 @@ function readJsonArray(options, name) {
477
591
  return void 0;
478
592
  }
479
593
  if (!Array.isArray(parsed)) {
480
- throw new Error(`Option "--${name}" must be a JSON array.`);
594
+ throw new CliError("invalid_value", `Option "--${name}" must be a JSON array.`);
481
595
  }
482
596
  return parsed;
483
597
  }
@@ -497,7 +611,7 @@ async function buildOperationInput(operation, parsed, runtime) {
497
611
  case "session.open": {
498
612
  const url = parsed.rest[0];
499
613
  if (url === void 0) {
500
- throw new Error("open requires a URL.");
614
+ throw new CliError("missing_arguments", "open requires a URL.", CLI_USAGE_HINTS[operation]);
501
615
  }
502
616
  return {
503
617
  url,
@@ -530,7 +644,7 @@ async function buildOperationInput(operation, parsed, runtime) {
530
644
  }
531
645
  case "page.goto": {
532
646
  if (parsed.rest[0] === void 0) {
533
- throw new Error("goto requires a URL.");
647
+ throw new CliError("missing_arguments", "goto requires a URL.", CLI_USAGE_HINTS[operation]);
534
648
  }
535
649
  const captureNetwork = readSingle(parsed.rawOptions, "capture-network");
536
650
  return {
@@ -542,14 +656,14 @@ async function buildOperationInput(operation, parsed, runtime) {
542
656
  return parsed.rest[0] === void 0 ? {} : { mode: parsed.rest[0] };
543
657
  case "page.evaluate":
544
658
  if (parsed.rest[0] === void 0) {
545
- throw new Error("evaluate requires a script.");
659
+ throw new CliError("missing_arguments", "evaluate requires a script.", CLI_USAGE_HINTS[operation]);
546
660
  }
547
661
  return {
548
662
  script: joinRest(parsed.rest, 0)
549
663
  };
550
664
  case "page.add-init-script":
551
665
  if (parsed.rest[0] === void 0) {
552
- throw new Error("init-script requires a script.");
666
+ throw new CliError("missing_arguments", "init-script requires a script.", CLI_USAGE_HINTS[operation]);
553
667
  }
554
668
  return {
555
669
  script: joinRest(parsed.rest, 0)
@@ -565,7 +679,7 @@ async function buildOperationInput(operation, parsed, runtime) {
565
679
  return buildElementTargetInput(parsed, "hover");
566
680
  case "dom.input": {
567
681
  if (parsed.rest[1] === void 0) {
568
- throw new Error("input requires an element number and text.");
682
+ throw new CliError("missing_arguments", "input requires an element number and text.", CLI_USAGE_HINTS[operation]);
569
683
  }
570
684
  const pressEnter = readOptionalBoolean(parsed.rawOptions, "press-enter");
571
685
  return {
@@ -596,7 +710,7 @@ async function buildOperationInput(operation, parsed, runtime) {
596
710
  }
597
711
  case "dom.extract": {
598
712
  if (parsed.rest[0] === void 0) {
599
- throw new Error("extract requires a template.");
713
+ throw new CliError("missing_arguments", "extract requires a template.", CLI_USAGE_HINTS[operation]);
600
714
  }
601
715
  const persist = readPersistKey(parsed, "extract");
602
716
  return {
@@ -632,7 +746,7 @@ async function buildOperationInput(operation, parsed, runtime) {
632
746
  }
633
747
  case "network.detail": {
634
748
  if (parsed.rest[0] === void 0) {
635
- throw new Error("network detail requires a record id.");
749
+ throw new CliError("missing_arguments", "network detail requires a record id.", CLI_USAGE_HINTS[operation]);
636
750
  }
637
751
  const probeFlag = readOptionalBoolean(parsed.rawOptions, "probe");
638
752
  return {
@@ -643,7 +757,7 @@ async function buildOperationInput(operation, parsed, runtime) {
643
757
  case "session.fetch": {
644
758
  const url = parsed.rest[0];
645
759
  if (url === void 0) {
646
- throw new Error("fetch requires a URL.");
760
+ throw new CliError("missing_arguments", "fetch requires a URL.", CLI_USAGE_HINTS[operation]);
647
761
  }
648
762
  const bodyJson = readJsonValue(parsed.rawOptions, "body");
649
763
  const bodyText = readSingle(parsed.rawOptions, "body-text");
@@ -651,7 +765,7 @@ async function buildOperationInput(operation, parsed, runtime) {
651
765
  const query = parseKeyValueList(parsed.rawOptions.get("query"));
652
766
  const headers = parseKeyValueList(parsed.rawOptions.get("header"));
653
767
  if (bodyJson !== void 0 && bodyText !== void 0) {
654
- throw new Error('Use either "--body" or "--body-text", not both.');
768
+ throw new CliError("invalid_option", 'Use either "--body" or "--body-text", not both.');
655
769
  }
656
770
  const transport = readSingle(parsed.rawOptions, "transport");
657
771
  const cookies = readOptionalBoolean(parsed.rawOptions, "cookies");
@@ -682,7 +796,7 @@ async function buildOperationInput(operation, parsed, runtime) {
682
796
  const siteKey = readSingle(parsed.rawOptions, "site-key");
683
797
  const pageUrl = readSingle(parsed.rawOptions, "page-url");
684
798
  if (provider === void 0 || apiKey === void 0) {
685
- throw new Error('captcha solve requires "--provider" and "--api-key".');
799
+ throw new CliError("missing_arguments", 'captcha solve requires "--provider" and "--api-key".', CLI_USAGE_HINTS[operation]);
686
800
  }
687
801
  return {
688
802
  provider: readCaptchaProvider(provider),
@@ -712,7 +826,7 @@ async function buildOperationInput(operation, parsed, runtime) {
712
826
  case "scripts.beautify":
713
827
  case "scripts.deobfuscate": {
714
828
  if (parsed.rest[0] === void 0) {
715
- throw new Error(`${parsed.command.join(" ")} requires an artifact id.`);
829
+ throw new CliError("missing_arguments", `${parsed.command.join(" ")} requires an artifact id.`, CLI_USAGE_HINTS[operation]);
716
830
  }
717
831
  const persist = readOptionalBoolean(parsed.rawOptions, "persist");
718
832
  return {
@@ -722,7 +836,7 @@ async function buildOperationInput(operation, parsed, runtime) {
722
836
  }
723
837
  case "scripts.sandbox":
724
838
  if (parsed.rest[0] === void 0) {
725
- throw new Error("scripts sandbox requires an artifact id.");
839
+ throw new CliError("missing_arguments", "scripts sandbox requires an artifact id.", CLI_USAGE_HINTS[operation]);
726
840
  }
727
841
  {
728
842
  const fidelity = readSingle(parsed.rawOptions, "fidelity");
@@ -771,14 +885,14 @@ async function buildOperationInput(operation, parsed, runtime) {
771
885
  case "interaction.get":
772
886
  case "interaction.replay":
773
887
  if (parsed.rest[0] === void 0) {
774
- throw new Error(`${parsed.command.join(" ")} requires a trace id.`);
888
+ throw new CliError("missing_arguments", `${parsed.command.join(" ")} requires a trace id.`, CLI_USAGE_HINTS[operation]);
775
889
  }
776
890
  return {
777
891
  traceId: parsed.rest[0]
778
892
  };
779
893
  case "interaction.diff":
780
894
  if (parsed.rest[0] === void 0 || parsed.rest[1] === void 0) {
781
- throw new Error("interaction diff requires two trace ids.");
895
+ throw new CliError("missing_arguments", "interaction diff requires two trace ids.", CLI_USAGE_HINTS[operation]);
782
896
  }
783
897
  return {
784
898
  leftTraceId: parsed.rest[0],
@@ -786,7 +900,7 @@ async function buildOperationInput(operation, parsed, runtime) {
786
900
  };
787
901
  case "artifact.read":
788
902
  if (parsed.rest[0] === void 0) {
789
- throw new Error("artifact read requires an artifact id.");
903
+ throw new CliError("missing_arguments", "artifact read requires an artifact id.", CLI_USAGE_HINTS[operation]);
790
904
  }
791
905
  return {
792
906
  artifactId: parsed.rest[0]
@@ -794,7 +908,8 @@ async function buildOperationInput(operation, parsed, runtime) {
794
908
  case "session.close":
795
909
  return {};
796
910
  default:
797
- throw new Error(
911
+ throw new CliError(
912
+ "unsupported_operation",
798
913
  `${operation} does not have a direct CLI input shape. Use a supported command or the SDK.`
799
914
  );
800
915
  }
@@ -841,7 +956,7 @@ function buildComputerExecuteInput(parsed) {
841
956
  }
842
957
  case "type":
843
958
  if (parsed.rest[0] === void 0) {
844
- throw new Error("computer type requires text.");
959
+ throw new CliError("missing_arguments", "computer type requires text.");
845
960
  }
846
961
  return {
847
962
  action: {
@@ -852,7 +967,7 @@ function buildComputerExecuteInput(parsed) {
852
967
  };
853
968
  case "key": {
854
969
  if (parsed.rest[0] === void 0) {
855
- throw new Error("computer key requires a key.");
970
+ throw new CliError("missing_arguments", "computer key requires a key.");
856
971
  }
857
972
  const modifiers = readKeyModifiers(readSingle(parsed.rawOptions, "modifiers"));
858
973
  return {
@@ -868,7 +983,7 @@ function buildComputerExecuteInput(parsed) {
868
983
  const dx = readOptionalNumber(parsed.rawOptions, "dx");
869
984
  const dy = readOptionalNumber(parsed.rawOptions, "dy");
870
985
  if (dx === void 0 || dy === void 0) {
871
- throw new Error('computer scroll requires "--dx" and "--dy".');
986
+ throw new CliError("missing_arguments", 'computer scroll requires "--dx" and "--dy".');
872
987
  }
873
988
  return {
874
989
  action: {
@@ -923,49 +1038,50 @@ function buildComputerExecuteInput(parsed) {
923
1038
  }
924
1039
  };
925
1040
  default:
926
- throw new Error(`Unknown computer command: ${parsed.command.join(" ")}`);
1041
+ throw new CliError("unknown_command", `Unknown computer command: ${parsed.command.join(" ")}`);
927
1042
  }
928
1043
  }
929
1044
  async function resolvePageRefByIndex(runtime, index) {
930
1045
  const pages = (await runtime.listPages({})).pages;
931
1046
  const page = pages[index - 1];
932
1047
  if (page === void 0) {
933
- throw new Error(`tab ${String(index)} does not exist.`);
1048
+ throw new CliError("invalid_value", `tab ${String(index)} does not exist.`);
934
1049
  }
935
1050
  return page.pageRef;
936
1051
  }
937
1052
  function readRequiredPositiveInteger(value, message) {
938
1053
  const parsed = readRequiredNumber(value, message);
939
1054
  if (!Number.isInteger(parsed) || parsed < 1) {
940
- throw new Error(message);
1055
+ throw new CliError("missing_arguments", message);
941
1056
  }
942
1057
  return parsed;
943
1058
  }
944
1059
  function readRequiredNumber(value, message) {
945
1060
  if (value === void 0) {
946
- throw new Error(message);
1061
+ throw new CliError("missing_arguments", message);
947
1062
  }
948
1063
  const parsed = Number(value);
949
1064
  if (!Number.isFinite(parsed)) {
950
- throw new Error(message);
1065
+ throw new CliError("missing_arguments", message);
951
1066
  }
952
1067
  return parsed;
953
1068
  }
954
1069
  function readSingleDirection(value) {
955
1070
  if (value === void 0 || !SCROLL_DIRECTIONS.has(value)) {
956
- throw new Error("scroll requires a direction: up, down, left, or right.");
1071
+ throw new CliError("missing_arguments", "scroll requires a direction: up, down, left, or right.");
957
1072
  }
958
1073
  return value;
959
1074
  }
960
1075
  function readClickButton(value) {
961
1076
  if (value === void 0 || !CLICK_BUTTONS.has(value)) {
962
- throw new Error('Expected "--button" to be one of: left, middle, right.');
1077
+ throw new CliError("invalid_value", 'Expected "--button" to be one of: left, middle, right.');
963
1078
  }
964
1079
  return value;
965
1080
  }
966
1081
  function readFetchTransport(value) {
967
1082
  if (value === void 0 || !FETCH_TRANSPORTS.has(value)) {
968
- throw new Error(
1083
+ throw new CliError(
1084
+ "invalid_value",
969
1085
  'Expected "--transport" to be one of: auto, direct, matched-tls, context, page.'
970
1086
  );
971
1087
  }
@@ -973,31 +1089,31 @@ function readFetchTransport(value) {
973
1089
  }
974
1090
  function readCaptchaProvider(value) {
975
1091
  if (value === void 0 || !CAPTCHA_PROVIDERS.has(value)) {
976
- throw new Error('Expected "--provider" to be one of: 2captcha, capsolver.');
1092
+ throw new CliError("invalid_value", 'Expected "--provider" to be one of: 2captcha, capsolver.');
977
1093
  }
978
1094
  return value;
979
1095
  }
980
1096
  function readCaptchaType(value) {
981
1097
  if (value === void 0 || !CAPTCHA_TYPES.has(value)) {
982
- throw new Error('Expected "--type" to be one of: recaptcha-v2, hcaptcha, turnstile.');
1098
+ throw new CliError("invalid_value", 'Expected "--type" to be one of: recaptcha-v2, hcaptcha, turnstile.');
983
1099
  }
984
1100
  return value;
985
1101
  }
986
1102
  function readSandboxFidelity(value) {
987
1103
  if (value === void 0 || !SANDBOX_FIDELITIES.has(value)) {
988
- throw new Error('Expected "--fidelity" to be one of: minimal, standard, full.');
1104
+ throw new CliError("invalid_value", 'Expected "--fidelity" to be one of: minimal, standard, full.');
989
1105
  }
990
1106
  return value;
991
1107
  }
992
1108
  function readSandboxClockMode(value) {
993
1109
  if (value === void 0 || !SANDBOX_CLOCK_MODES.has(value)) {
994
- throw new Error('Expected "--clock" to be one of: real, manual.');
1110
+ throw new CliError("invalid_value", 'Expected "--clock" to be one of: real, manual.');
995
1111
  }
996
1112
  return value;
997
1113
  }
998
1114
  function readScreenshotFormat(value) {
999
1115
  if (value === void 0 || !SCREENSHOT_FORMATS.has(value)) {
1000
- throw new Error('Expected "--format" to be one of: png, jpeg, webp.');
1116
+ throw new CliError("invalid_value", 'Expected "--format" to be one of: png, jpeg, webp.');
1001
1117
  }
1002
1118
  return value;
1003
1119
  }
@@ -1008,7 +1124,7 @@ function readKeyModifiers(value) {
1008
1124
  }
1009
1125
  for (const modifier of modifiers) {
1010
1126
  if (!KEY_MODIFIERS.has(modifier)) {
1011
- throw new Error('Expected "--modifiers" to contain only: Shift, Control, Alt, Meta.');
1127
+ throw new CliError("invalid_value", 'Expected "--modifiers" to contain only: Shift, Control, Alt, Meta.');
1012
1128
  }
1013
1129
  }
1014
1130
  return [...new Set(modifiers)];
@@ -1016,17 +1132,22 @@ function readKeyModifiers(value) {
1016
1132
  function readPersistKey(parsed, verb) {
1017
1133
  const value = readSingle(parsed.rawOptions, "persist");
1018
1134
  if (value === void 0) {
1019
- throw new Error(`${verb} requires "--persist <key>".`);
1135
+ throw new CliError("missing_arguments", `${verb} requires "--persist <key>".`);
1020
1136
  }
1021
1137
  if (value === "true" || value === "false") {
1022
- throw new Error(`${verb} requires "--persist <key>".`);
1138
+ throw new CliError("missing_arguments", `${verb} requires "--persist <key>".`);
1023
1139
  }
1024
1140
  return value;
1025
1141
  }
1026
1142
  function parseRequiredJsonObjectArgument(value, label) {
1027
- const parsed = JSON.parse(value);
1143
+ let parsed;
1144
+ try {
1145
+ parsed = JSON.parse(value);
1146
+ } catch {
1147
+ throw new CliError("invalid_value", `${label} contains invalid JSON.`);
1148
+ }
1028
1149
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
1029
- throw new Error(`${label} must be a JSON object.`);
1150
+ throw new CliError("invalid_value", `${label} must be a JSON object.`);
1030
1151
  }
1031
1152
  return parsed;
1032
1153
  }
@@ -1038,6 +1159,7 @@ function joinRest(rest, startIndex) {
1038
1159
  function renderOperationOutput(operation, result, input) {
1039
1160
  switch (operation) {
1040
1161
  case "session.open":
1162
+ case "page.activate":
1041
1163
  case "page.goto":
1042
1164
  return renderJson(formatNavigationOutput(result));
1043
1165
  case "page.snapshot":
@@ -1046,14 +1168,14 @@ function renderOperationOutput(operation, result, input) {
1046
1168
  case "dom.hover":
1047
1169
  case "dom.input":
1048
1170
  case "dom.scroll":
1049
- return renderJson(formatActionOutput(result, input));
1171
+ return renderJson(formatActionOutput(result));
1050
1172
  case "dom.extract":
1051
1173
  return renderJson(formatExtractOutput(result));
1052
1174
  case "page.list":
1053
- case "page.new":
1054
- case "page.activate":
1055
1175
  case "page.close":
1056
1176
  return formatTabOutput(result);
1177
+ case "page.new":
1178
+ return renderJson(formatCreatedPageOutput(result));
1057
1179
  case "network.query":
1058
1180
  return formatNetworkQueryOutput(result, input);
1059
1181
  case "network.detail":
@@ -1091,6 +1213,12 @@ function formatNavigationOutput(result) {
1091
1213
  ...readStringField(result, "title") === void 0 ? {} : { title: readStringField(result, "title") }
1092
1214
  };
1093
1215
  }
1216
+ function formatCreatedPageOutput(result) {
1217
+ return {
1218
+ ...readStringField(result, "pageRef") === void 0 ? {} : { pageRef: readStringField(result, "pageRef") },
1219
+ ...formatNavigationOutput(result)
1220
+ };
1221
+ }
1094
1222
  function formatSnapshotOutput(result) {
1095
1223
  if (result !== null && typeof result === "object" && typeof result.html === "string") {
1096
1224
  return `${result.html}
@@ -1098,36 +1226,11 @@ function formatSnapshotOutput(result) {
1098
1226
  }
1099
1227
  return renderJson(result);
1100
1228
  }
1101
- function formatActionOutput(result, input) {
1102
- const target = readObjectField(result, "target");
1103
- const output = {
1104
- ...readStringField(target, "tagName") === void 0 ? {} : { tagName: readStringField(target, "tagName") },
1105
- ...readStringField(target, "pathHint") === void 0 ? {} : { pathHint: readStringField(target, "pathHint") }
1229
+ function formatActionOutput(result) {
1230
+ return {
1231
+ ...readStringField(result, "tagName") === void 0 ? {} : { tagName: readStringField(result, "tagName") },
1232
+ ...readStringField(result, "persist") === void 0 ? {} : { persist: readStringField(result, "persist") }
1106
1233
  };
1107
- const point = readObjectField(result, "point");
1108
- if (point !== void 0) {
1109
- output.point = {
1110
- ...readNumberField(point, "x") === void 0 ? {} : { x: readNumberField(point, "x") },
1111
- ...readNumberField(point, "y") === void 0 ? {} : { y: readNumberField(point, "y") }
1112
- };
1113
- }
1114
- const persist = readStringField(target, "persist");
1115
- if (persist !== void 0) {
1116
- output.persist = persist;
1117
- }
1118
- const text = readStringField(input, "text");
1119
- if (text !== void 0) {
1120
- output.text = text;
1121
- }
1122
- const direction = readStringField(input, "direction");
1123
- if (direction !== void 0) {
1124
- output.direction = direction;
1125
- }
1126
- const amount = readNumberField(input, "amount");
1127
- if (amount !== void 0) {
1128
- output.amount = amount;
1129
- }
1130
- return output;
1131
1234
  }
1132
1235
  function formatExtractOutput(result) {
1133
1236
  const data = readUnknownField(result, "data");
@@ -1359,20 +1462,18 @@ function formatStateOutput(result) {
1359
1462
  `;
1360
1463
  }
1361
1464
  function formatComputerOutput(result) {
1362
- const action = readObjectField(result, "action");
1363
1465
  const screenshot = readObjectField(result, "screenshot");
1364
1466
  const payload = readObjectField(screenshot, "payload");
1365
- const timing = readObjectField(result, "timing");
1366
1467
  return {
1367
- ...action === void 0 ? {} : { action },
1468
+ ...readStringField(result, "url") === void 0 ? {} : { url: readStringField(result, "url") },
1469
+ ...readStringField(result, "title") === void 0 ? {} : { title: readStringField(result, "title") },
1368
1470
  ...payload === void 0 ? {} : {
1369
1471
  screenshot: {
1370
1472
  ...readStringField(payload, "uri") === void 0 ? {} : { uri: readStringField(payload, "uri") },
1371
1473
  ...readStringField(screenshot, "format") === void 0 ? {} : { format: readStringField(screenshot, "format") },
1372
1474
  ...readObjectField(screenshot, "size") === void 0 ? {} : { size: readObjectField(screenshot, "size") }
1373
1475
  }
1374
- },
1375
- ...timing === void 0 ? {} : { timingMs: timing }
1476
+ }
1376
1477
  };
1377
1478
  }
1378
1479
  function formatScriptsCaptureOutput(result) {
@@ -2020,7 +2121,7 @@ async function collectOpensteerStatus(input) {
2020
2121
  ...output,
2021
2122
  rootPath,
2022
2123
  lanes: {
2023
- local: describeLocalLane(localRecord, input.provider.mode === "local"),
2124
+ local: await describeLocalLane(localRecord, input.provider.mode === "local"),
2024
2125
  cloud: await describeCloudLane({
2025
2126
  record: cloudRecord,
2026
2127
  current: input.provider.mode === "cloud",
@@ -2072,8 +2173,38 @@ async function readWorkspaceCloudRecord(rootPath) {
2072
2173
  }
2073
2174
  return readPersistedCloudSessionRecord(rootPath);
2074
2175
  }
2075
- function describeLocalLane(record, current) {
2076
- if (record === void 0 || !isProcessRunning(record.pid)) {
2176
+ async function describeLocalLane(record, current) {
2177
+ if (record === void 0) {
2178
+ return {
2179
+ provider: "local",
2180
+ status: "idle",
2181
+ current,
2182
+ summary: "none"
2183
+ };
2184
+ }
2185
+ if (getPersistedLocalBrowserSessionOwnership(record) === "attached") {
2186
+ if (!await isAttachedLocalBrowserSessionReachable(record)) {
2187
+ return {
2188
+ provider: "local",
2189
+ status: "stale",
2190
+ current,
2191
+ summary: "attached browser unavailable",
2192
+ detail: record.engine,
2193
+ engine: record.engine
2194
+ };
2195
+ }
2196
+ const browser2 = record.executablePath ? path2.basename(record.executablePath).replace(/\.[A-Za-z0-9]+$/u, "") : void 0;
2197
+ return {
2198
+ provider: "local",
2199
+ status: "active",
2200
+ current,
2201
+ summary: "attached browser",
2202
+ detail: browser2 ?? record.engine,
2203
+ engine: record.engine,
2204
+ ...browser2 === void 0 ? {} : { browser: browser2 }
2205
+ };
2206
+ }
2207
+ if (!isProcessRunning(record.pid)) {
2077
2208
  return {
2078
2209
  provider: "local",
2079
2210
  status: "idle",
@@ -2182,7 +2313,7 @@ async function handleViewCommand(parsed, options = {}) {
2182
2313
  return;
2183
2314
  }
2184
2315
  if (subcommand !== void 0) {
2185
- throw new Error(`Unknown view command: view ${subcommand}`);
2316
+ throw new CliError("unknown_command", `Unknown view command: view ${subcommand}`);
2186
2317
  }
2187
2318
  if (parsed.options.localViewMode !== void 0) {
2188
2319
  const preference = await setLocalViewMode(parsed.options.localViewMode);
@@ -2219,18 +2350,27 @@ async function resolveWorkspaceSessionId(input) {
2219
2350
  workspace: input.workspace
2220
2351
  });
2221
2352
  const live = await readPersistedLocalBrowserSessionRecord(rootPath);
2222
- if (!live || !isProcessRunning(live.pid)) {
2353
+ if (!live) {
2354
+ return void 0;
2355
+ }
2356
+ if (getPersistedLocalBrowserSessionOwnership(live) === "attached") {
2357
+ if (!await isAttachedLocalBrowserSessionReachable(live)) {
2358
+ return void 0;
2359
+ }
2360
+ } else if (!isProcessRunning(live.pid)) {
2223
2361
  return void 0;
2224
2362
  }
2225
- return buildLocalViewSessionId({
2363
+ return buildLocalViewSessionIdForRecord({
2226
2364
  rootPath,
2227
- pid: live.pid,
2228
- startedAt: live.startedAt
2365
+ live
2229
2366
  });
2230
2367
  }
2231
2368
  function assertNoViewPreferenceFlag(parsed) {
2232
2369
  if (parsed.options.localViewMode !== void 0) {
2233
- throw new Error("View preference flags cannot be combined with this subcommand.");
2370
+ throw new CliError(
2371
+ "invalid_option",
2372
+ "View preference flags cannot be combined with this subcommand."
2373
+ );
2234
2374
  }
2235
2375
  }
2236
2376
  function writeViewOutput(parsed, value) {
@@ -2315,10 +2455,10 @@ async function main() {
2315
2455
  }
2316
2456
  const operation = resolveOperation(parsed.command);
2317
2457
  if (!operation) {
2318
- throw new Error(`Unknown command: ${parsed.command.join(" ")}`);
2458
+ throw new CliError("unknown_command", `Unknown command: ${parsed.command.join(" ")}`);
2319
2459
  }
2320
2460
  if (parsed.options.workspace === void 0) {
2321
- throw new Error('Stateful commands require "--workspace <id>" or OPENSTEER_WORKSPACE.');
2461
+ throw new CliError("missing_workspace", 'Stateful commands require "--workspace <id>" or OPENSTEER_WORKSPACE.');
2322
2462
  }
2323
2463
  const { engineName, provider, runtimeProvider } = resolveCliRuntimeSelection(parsed);
2324
2464
  if (operation === "session.close") {
@@ -2340,28 +2480,43 @@ async function main() {
2340
2480
  let renderOperation = operation;
2341
2481
  try {
2342
2482
  const input = await buildOperationInput(operation, parsed, runtime);
2343
- result = await dispatchSemanticOperation(runtime, operation, input);
2483
+ const rawResult = await dispatchSemanticOperation(runtime, operation, input);
2344
2484
  if (parsed.command[0] === "tab" && operation !== "page.list") {
2345
2485
  renderOperation = "page.list";
2346
2486
  result = await runtime.listPages({});
2487
+ } else {
2488
+ result = rawResult;
2489
+ }
2490
+ let warning;
2491
+ if (result !== null && typeof result === "object" && "warning" in result) {
2492
+ const { warning: w, ...rest } = result;
2493
+ if (typeof w === "string") {
2494
+ warning = w;
2495
+ result = rest;
2496
+ }
2347
2497
  }
2348
2498
  process4.stdout.write(renderOperationOutput(renderOperation, result, input));
2499
+ if (warning !== void 0) {
2500
+ emitWarning(warning);
2501
+ }
2349
2502
  } finally {
2350
2503
  await runtime.disconnect().catch(() => void 0);
2351
2504
  }
2352
2505
  }
2353
2506
  async function handleExecCommand(parsed) {
2354
2507
  if (parsed.options.workspace === void 0) {
2355
- throw new Error('exec requires "--workspace <id>" or OPENSTEER_WORKSPACE.');
2508
+ throw new CliError("missing_workspace", 'exec requires "--workspace <id>" or OPENSTEER_WORKSPACE.');
2356
2509
  }
2357
2510
  const expression = parsed.rest.join(" ");
2358
2511
  if (!expression) {
2359
- throw new Error(
2360
- `exec requires an expression. Example: exec "await this.evaluate('document.title')"`
2512
+ throw new CliError(
2513
+ "missing_arguments",
2514
+ "exec requires an expression.",
2515
+ "opensteer exec <expression>"
2361
2516
  );
2362
2517
  }
2363
2518
  const { engineName, runtimeProvider } = resolveCliRuntimeSelection(parsed);
2364
- const { Opensteer } = await import('../opensteer-T2JENADR.js');
2519
+ const { Opensteer } = await import('../opensteer-CY2QUJEG.js');
2365
2520
  const opensteer = new Opensteer({
2366
2521
  workspace: parsed.options.workspace,
2367
2522
  rootDir: process4.cwd(),
@@ -2393,8 +2548,10 @@ async function handleBrowserCommand(parsed) {
2393
2548
  if (subcommand === "inspect") {
2394
2549
  const endpoint = parsed.options.attachEndpoint ?? parsed.rest[0];
2395
2550
  if (!endpoint) {
2396
- throw new Error(
2397
- 'browser inspect requires "--attach-endpoint <url>" or a positional endpoint.'
2551
+ throw new CliError(
2552
+ "missing_arguments",
2553
+ 'browser inspect requires "--attach-endpoint <url>" or a positional endpoint.',
2554
+ "opensteer browser inspect <endpoint>"
2398
2555
  );
2399
2556
  }
2400
2557
  const result = await inspectCdpEndpoint({
@@ -2407,7 +2564,8 @@ async function handleBrowserCommand(parsed) {
2407
2564
  return;
2408
2565
  }
2409
2566
  if (parsed.options.workspace === void 0) {
2410
- throw new Error(
2567
+ throw new CliError(
2568
+ "missing_workspace",
2411
2569
  'Browser workspace commands require "--workspace <id>" or OPENSTEER_WORKSPACE.'
2412
2570
  );
2413
2571
  }
@@ -2430,7 +2588,11 @@ async function handleBrowserCommand(parsed) {
2430
2588
  case "clone": {
2431
2589
  const sourceUserDataDir = parsed.options.sourceUserDataDir;
2432
2590
  if (!sourceUserDataDir) {
2433
- throw new Error('browser clone requires "--source-user-data-dir <path>".');
2591
+ throw new CliError(
2592
+ "missing_arguments",
2593
+ 'browser clone requires "--source-user-data-dir <path>".',
2594
+ "opensteer browser clone --source-user-data-dir <path>"
2595
+ );
2434
2596
  }
2435
2597
  const result = await manager.clonePersistentBrowser({
2436
2598
  sourceUserDataDir,
@@ -2453,7 +2615,7 @@ async function handleBrowserCommand(parsed) {
2453
2615
  return;
2454
2616
  }
2455
2617
  default:
2456
- throw new Error(`Unknown browser command: ${parsed.command.join(" ")}`);
2618
+ throw new CliError("unknown_command", `Unknown browser command: ${parsed.command.join(" ")}`);
2457
2619
  }
2458
2620
  }
2459
2621
  async function handleCloseCommand(parsed, engineName, providerMode, runtimeProvider) {
@@ -2486,23 +2648,27 @@ async function handleCloseCommand(parsed, engineName, providerMode, runtimeProvi
2486
2648
  }
2487
2649
  async function handleRecordCommandEntry(parsed) {
2488
2650
  if (parsed.options.workspace === void 0) {
2489
- throw new Error('record requires "--workspace <id>" or OPENSTEER_WORKSPACE.');
2651
+ throw new CliError("missing_workspace", 'record requires "--workspace <id>" or OPENSTEER_WORKSPACE.');
2490
2652
  }
2491
2653
  const url = parsed.options.url ?? parsed.rest[0];
2492
2654
  if (url === void 0) {
2493
- throw new Error('record requires "--url <value>" or a positional URL.');
2655
+ throw new CliError(
2656
+ "missing_arguments",
2657
+ 'record requires "--url <value>" or a positional URL.',
2658
+ "opensteer record --url <url> --workspace <id>"
2659
+ );
2494
2660
  }
2495
2661
  const provider = resolveCliProvider(parsed);
2496
2662
  assertCloudCliOptionsMatchProvider(parsed, provider.mode);
2497
2663
  const engineName = resolveCliEngineName(parsed);
2498
2664
  if (engineName !== "playwright") {
2499
- throw new Error("record requires engine=playwright.");
2665
+ throw new CliError("config_conflict", "record requires engine=playwright.");
2500
2666
  }
2501
2667
  const rootDir = process4.cwd();
2502
2668
  const recordBrowser = parsed.options.browser;
2503
2669
  if (provider.mode === "cloud") {
2504
2670
  if (typeof recordBrowser === "object") {
2505
- throw new Error('record does not support browser.mode="attach".');
2671
+ throw new CliError("config_conflict", 'record does not support browser.mode="attach".');
2506
2672
  }
2507
2673
  const runtimeProvider = buildCliRuntimeProvider(parsed, provider.mode);
2508
2674
  const runtimeConfig = resolveOpensteerRuntimeConfig({
@@ -2522,10 +2688,10 @@ async function handleRecordCommandEntry(parsed) {
2522
2688
  return;
2523
2689
  }
2524
2690
  if (parsed.options.launch?.headless === true) {
2525
- throw new Error('record requires a headed browser. Remove "--headless true".');
2691
+ throw new CliError("config_conflict", 'record requires a headed browser. Remove "--headless true".');
2526
2692
  }
2527
2693
  if (typeof recordBrowser === "object") {
2528
- throw new Error('record does not support browser.mode="attach".');
2694
+ throw new CliError("config_conflict", 'record does not support browser.mode="attach".');
2529
2695
  }
2530
2696
  const launch = {
2531
2697
  ...parsed.options.launch ?? {},
@@ -2594,7 +2760,7 @@ function resolveCliBootstrapAction(argv) {
2594
2760
  }
2595
2761
  function buildCliBrowserProfile(parsed) {
2596
2762
  if (parsed.options.cloudProfileReuseIfActive === true && parsed.options.cloudProfileId === void 0) {
2597
- throw new Error('"--cloud-profile-reuse-if-active" requires "--cloud-profile-id <id>".');
2763
+ throw new CliError("invalid_option", '"--cloud-profile-reuse-if-active" requires "--cloud-profile-id <id>".');
2598
2764
  }
2599
2765
  return parsed.options.cloudProfileId === void 0 ? void 0 : {
2600
2766
  profileId: parsed.options.cloudProfileId,
@@ -2655,7 +2821,8 @@ function buildCliRuntimeProvider(parsed, providerMode) {
2655
2821
  }
2656
2822
  function assertCloudCliOptionsMatchProvider(parsed, providerMode) {
2657
2823
  if (providerMode !== "cloud" && (parsed.options.cloudBaseUrl !== void 0 || parsed.options.cloudApiKey !== void 0 || parsed.options.cloudAppBaseUrl !== void 0 || parsed.options.cloudProfileId !== void 0 || parsed.options.cloudProfileReuseIfActive === true)) {
2658
- throw new Error(
2824
+ throw new CliError(
2825
+ "config_conflict",
2659
2826
  'Cloud-specific options require provider=cloud. Set "--provider cloud" or OPENSTEER_PROVIDER=cloud.'
2660
2827
  );
2661
2828
  }
@@ -2689,17 +2856,7 @@ function printVersion() {
2689
2856
  `);
2690
2857
  }
2691
2858
  main().catch((error) => {
2692
- const payload = error instanceof Error ? {
2693
- error: {
2694
- name: error.name,
2695
- message: error.message
2696
- }
2697
- } : {
2698
- error: {
2699
- name: "Error",
2700
- message: String(error)
2701
- }
2702
- };
2859
+ const payload = formatCliErrorOutput(error);
2703
2860
  process4.stderr.write(`${JSON.stringify(payload)}
2704
2861
  `);
2705
2862
  process4.exitCode = 1;