@btraut/browser-bridge 0.12.1 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.js CHANGED
@@ -41,6 +41,7 @@ var import_express2 = __toESM(require("express"));
41
41
 
42
42
  // packages/shared/src/core-readiness.ts
43
43
  var import_promises = require("node:timers/promises");
44
+ var import_node_net = require("node:net");
44
45
 
45
46
  // packages/shared/src/logging.ts
46
47
  var import_node_fs2 = require("node:fs");
@@ -58,9 +59,49 @@ var ENV_CORE_PORT = "BROWSER_BRIDGE_CORE_PORT";
58
59
  var ENV_VISION_PORT = "BROWSER_VISION_CORE_PORT";
59
60
  var ENV_ISOLATED_MODE = "BROWSER_BRIDGE_ISOLATED_MODE";
60
61
  var ENV_VISION_ISOLATED_MODE = "BROWSER_VISION_ISOLATED_MODE";
62
+ var ENV_BRIDGE_CWD = "BROWSER_BRIDGE_CWD";
63
+ var ENV_PROCESS_PWD = "PWD";
64
+ var ENV_PROCESS_INIT_CWD = "INIT_CWD";
65
+ var ENV_PROCESS_HOME = "HOME";
61
66
  var RUNTIME_METADATA_RELATIVE_PATH = ".context/browser-bridge/dev.json";
62
67
  var DEFAULT_LOG_DIRECTORY_RELATIVE_PATH = ".context/logs/browser-bridge";
63
- var resolveCwd = (cwd) => (0, import_node_path.resolve)(cwd ?? process.cwd());
68
+ var normalizeCandidatePath = (value) => {
69
+ if (typeof value !== "string") {
70
+ return void 0;
71
+ }
72
+ const trimmed = value.trim();
73
+ if (trimmed.length === 0) {
74
+ return void 0;
75
+ }
76
+ return (0, import_node_path.resolve)(trimmed);
77
+ };
78
+ var resolveCwd = (cwd) => {
79
+ const explicit = normalizeCandidatePath(cwd);
80
+ if (explicit) {
81
+ return explicit;
82
+ }
83
+ const envExplicit = normalizeCandidatePath(process.env[ENV_BRIDGE_CWD]);
84
+ if (envExplicit) {
85
+ return envExplicit;
86
+ }
87
+ const processCwd = normalizeCandidatePath(process.cwd());
88
+ if (processCwd && processCwd !== "/") {
89
+ return processCwd;
90
+ }
91
+ const processPwd = normalizeCandidatePath(process.env[ENV_PROCESS_PWD]);
92
+ if (processPwd && processPwd !== "/") {
93
+ return processPwd;
94
+ }
95
+ const initCwd = normalizeCandidatePath(process.env[ENV_PROCESS_INIT_CWD]);
96
+ if (initCwd && initCwd !== "/") {
97
+ return initCwd;
98
+ }
99
+ const home = normalizeCandidatePath(process.env[ENV_PROCESS_HOME]);
100
+ if (home) {
101
+ return home;
102
+ }
103
+ return processCwd ?? (0, import_node_path.resolve)(".");
104
+ };
64
105
  var resolveOptionalPath = (cwd, value) => {
65
106
  if (!value) {
66
107
  return void 0;
@@ -205,8 +246,8 @@ var sanitizeMetadata = (raw) => {
205
246
  updated_at: updatedAt
206
247
  };
207
248
  };
208
- var findGitRoot = (cwd = process.cwd()) => {
209
- let current = (0, import_node_path.resolve)(cwd);
249
+ var findGitRoot = (cwd) => {
250
+ let current = resolveCwd(cwd);
210
251
  while (true) {
211
252
  if ((0, import_node_fs.existsSync)((0, import_node_path.join)(current, ".git"))) {
212
253
  return current;
@@ -597,6 +638,27 @@ var DEFAULT_HEALTH_RETRY_MS = 250;
597
638
  var DEFAULT_HEALTH_ATTEMPTS = 20;
598
639
  var DEFAULT_HEALTH_TIMEOUT_MS = 2e3;
599
640
  var DEFAULT_HEALTH_BUDGET_MS = 15e3;
641
+ var DEFAULT_PORT_REACHABILITY_TIMEOUT_MS = 300;
642
+ var isPortReachableDefault = async (runtime) => {
643
+ return await new Promise((resolve3) => {
644
+ const socket = new import_node_net.Socket();
645
+ let settled = false;
646
+ const finish = (reachable) => {
647
+ if (settled) {
648
+ return;
649
+ }
650
+ settled = true;
651
+ socket.removeAllListeners();
652
+ socket.destroy();
653
+ resolve3(reachable);
654
+ };
655
+ socket.setTimeout(DEFAULT_PORT_REACHABILITY_TIMEOUT_MS);
656
+ socket.once("connect", () => finish(true));
657
+ socket.once("timeout", () => finish(false));
658
+ socket.once("error", () => finish(false));
659
+ socket.connect(runtime.port, runtime.host);
660
+ });
661
+ };
600
662
  var resolveTimeoutMs = (timeoutMs) => {
601
663
  const candidate = timeoutMs ?? (process.env.BROWSER_BRIDGE_CORE_TIMEOUT_MS ? Number.parseInt(process.env.BROWSER_BRIDGE_CORE_TIMEOUT_MS, 10) : process.env.BROWSER_VISION_CORE_TIMEOUT_MS ? Number.parseInt(process.env.BROWSER_VISION_CORE_TIMEOUT_MS, 10) : void 0);
602
664
  if (candidate === void 0 || candidate === null) {
@@ -662,57 +724,71 @@ var createCoreReadinessController = (options = {}) => {
662
724
  baseUrl = `http://${runtime.host}:${runtime.port}`;
663
725
  };
664
726
  const checkHealth = async () => {
665
- try {
666
- const controller = new AbortController();
667
- const timeout = setTimeout(() => controller.abort(), healthTimeoutMs);
727
+ for (const method of ["POST", "GET"]) {
668
728
  try {
669
- let response;
729
+ const controller = new AbortController();
730
+ const timeout = setTimeout(() => controller.abort(), healthTimeoutMs);
670
731
  try {
671
- response = await fetchImpl(`${baseUrl}/health`, {
672
- method: "GET",
673
- signal: controller.signal
674
- });
675
- } catch (error) {
676
- if (controller.signal.aborted || error instanceof Error && error.name === "AbortError") {
677
- logger.warn(`${logPrefix}.health.timeout`, {
732
+ let response;
733
+ try {
734
+ response = await fetchImpl(`${baseUrl}/health`, {
735
+ method,
736
+ signal: controller.signal
737
+ });
738
+ } catch (error) {
739
+ if (controller.signal.aborted || error instanceof Error && error.name === "AbortError") {
740
+ logger.warn(`${logPrefix}.health.timeout`, {
741
+ base_url: baseUrl,
742
+ method,
743
+ timeout_ms: healthTimeoutMs
744
+ });
745
+ continue;
746
+ }
747
+ logger.warn(`${logPrefix}.health.fetch_failed`, {
678
748
  base_url: baseUrl,
679
- timeout_ms: healthTimeoutMs
749
+ method,
750
+ error
680
751
  });
681
- return false;
752
+ throw error;
753
+ }
754
+ if (!response.ok) {
755
+ logger.warn(`${logPrefix}.health.non_ok`, {
756
+ base_url: baseUrl,
757
+ method,
758
+ status: response.status
759
+ });
760
+ continue;
761
+ }
762
+ const data = await response.json().catch(() => null);
763
+ const ok = Boolean(data?.ok);
764
+ if (ok) {
765
+ if (method === "GET") {
766
+ logger.info(`${logPrefix}.health.compat_probe`, {
767
+ base_url: baseUrl,
768
+ method
769
+ });
770
+ }
771
+ return true;
682
772
  }
683
- logger.warn(`${logPrefix}.health.fetch_failed`, {
684
- base_url: baseUrl,
685
- error
686
- });
687
- throw error;
688
- }
689
- if (!response.ok) {
690
- logger.warn(`${logPrefix}.health.non_ok`, {
691
- base_url: baseUrl,
692
- status: response.status
693
- });
694
- return false;
695
- }
696
- const data = await response.json().catch(() => null);
697
- const ok = Boolean(data?.ok);
698
- if (!ok) {
699
773
  logger.warn(`${logPrefix}.health.not_ready`, {
700
- base_url: baseUrl
774
+ base_url: baseUrl,
775
+ method
701
776
  });
777
+ } finally {
778
+ clearTimeout(timeout);
702
779
  }
703
- return ok;
704
- } finally {
705
- clearTimeout(timeout);
780
+ } catch (error) {
781
+ logger.warn(`${logPrefix}.health.error`, {
782
+ base_url: baseUrl,
783
+ method,
784
+ error
785
+ });
706
786
  }
707
- } catch (error) {
708
- logger.warn(`${logPrefix}.health.error`, {
709
- base_url: baseUrl,
710
- error
711
- });
712
- return false;
713
787
  }
788
+ return false;
714
789
  };
715
790
  const ensureCoreRunning = async () => {
791
+ const portReachabilityCheck = options.portReachabilityCheck ?? isPortReachableDefault;
716
792
  refreshRuntime();
717
793
  if (await checkHealth()) {
718
794
  logger.debug(`${logPrefix}.ensure_ready.already_running`, {
@@ -753,6 +829,21 @@ var createCoreReadinessController = (options = {}) => {
753
829
  health_budget_ms: healthBudgetMs,
754
830
  health_timeout_ms: healthTimeoutMs
755
831
  });
832
+ let portOccupied = false;
833
+ try {
834
+ portOccupied = await portReachabilityCheck(runtime);
835
+ } catch (error) {
836
+ logger.warn(`${logPrefix}.ensure_ready.port_probe_failed`, {
837
+ host: runtime.host,
838
+ port: runtime.port,
839
+ error
840
+ });
841
+ }
842
+ if (portOccupied) {
843
+ throw new Error(
844
+ `Core daemon failed to start on ${runtime.host}:${runtime.port}. A process is already listening on this port but did not pass Browser Bridge health checks. Retry with --no-daemon to reuse it, or enable isolated mode (BROWSER_BRIDGE_ISOLATED_MODE=1) for per-worktree ports.`
845
+ );
846
+ }
756
847
  throw new Error(
757
848
  `Core daemon failed to start on ${runtime.host}:${runtime.port}.`
758
849
  );
@@ -783,9 +874,49 @@ var createCoreReadinessController = (options = {}) => {
783
874
  };
784
875
  };
785
876
 
877
+ // packages/shared/src/contract-version.ts
878
+ var HTTP_CONTRACT_VERSION_HEADER = "x-browser-bridge-contract-version";
879
+ var HTTP_CONTRACT_VERSION = "2026-02-17.1";
880
+ var DRIVE_WS_PROTOCOL_VERSION = "2026-02-17.1";
881
+ var resolveContractVersionMismatch = (receivedVersion) => {
882
+ if (!receivedVersion || receivedVersion.trim().length === 0) {
883
+ return void 0;
884
+ }
885
+ if (receivedVersion === HTTP_CONTRACT_VERSION) {
886
+ return void 0;
887
+ }
888
+ return {
889
+ expected: HTTP_CONTRACT_VERSION,
890
+ received: receivedVersion
891
+ };
892
+ };
893
+
786
894
  // packages/shared/src/errors.ts
895
+ var import_zod2 = require("zod");
896
+
897
+ // packages/shared/src/retry-policy.ts
787
898
  var import_zod = require("zod");
788
- var ErrorCodeSchema = import_zod.z.enum([
899
+ var RetryHintSchema = import_zod.z.object({
900
+ retryable: import_zod.z.boolean(),
901
+ reason: import_zod.z.string().optional(),
902
+ retry_after_ms: import_zod.z.number().int().nonnegative().optional(),
903
+ max_attempts: import_zod.z.number().int().positive().optional()
904
+ });
905
+ var DEFAULT_MAX_ATTEMPTS = 1;
906
+ var resolveRetryHint = (input) => ({
907
+ retryable: input.retry?.retryable ?? input.retryable,
908
+ reason: input.retry?.reason,
909
+ retry_after_ms: input.retry?.retry_after_ms,
910
+ max_attempts: input.retry?.max_attempts ?? DEFAULT_MAX_ATTEMPTS
911
+ });
912
+ var shouldRetryByPolicy = (options) => {
913
+ const hint = resolveRetryHint(options);
914
+ const maxAttempts = hint.max_attempts ?? DEFAULT_MAX_ATTEMPTS;
915
+ return hint.retryable && options.attempt < maxAttempts;
916
+ };
917
+
918
+ // packages/shared/src/errors.ts
919
+ var ErrorCodeSchema = import_zod2.z.enum([
789
920
  "UNKNOWN",
790
921
  "INVALID_ARGUMENT",
791
922
  "NOT_FOUND",
@@ -818,32 +949,168 @@ var ErrorCodeSchema = import_zod.z.enum([
818
949
  "EVALUATION_FAILED",
819
950
  "ARTIFACT_IO_ERROR"
820
951
  ]);
821
- var ErrorInfoSchema = import_zod.z.object({
952
+ var PublicErrorCodeSchema = import_zod2.z.enum([
953
+ "UNKNOWN",
954
+ "INVALID_ARGUMENT",
955
+ "NOT_FOUND",
956
+ "ALREADY_EXISTS",
957
+ "FAILED_PRECONDITION",
958
+ "UNAUTHORIZED",
959
+ "FORBIDDEN",
960
+ "CONFLICT",
961
+ "TIMEOUT",
962
+ "CANCELLED",
963
+ "UNAVAILABLE",
964
+ "RATE_LIMITED",
965
+ "NOT_IMPLEMENTED",
966
+ "INTERNAL"
967
+ ]);
968
+ var PublicErrorDetailsSchema = import_zod2.z.object({
969
+ legacy_code: ErrorCodeSchema.optional(),
970
+ reason: import_zod2.z.string().optional(),
971
+ resource: import_zod2.z.string().optional(),
972
+ field: import_zod2.z.string().optional(),
973
+ session_id: import_zod2.z.string().optional(),
974
+ tab_id: import_zod2.z.number().finite().optional(),
975
+ retry_after_ms: import_zod2.z.number().finite().optional(),
976
+ next_step: import_zod2.z.string().optional()
977
+ }).catchall(import_zod2.z.unknown());
978
+ var LEGACY_ERROR_CODE_MAP = {
979
+ PERMISSION_REQUIRED: {
980
+ code: "FORBIDDEN",
981
+ reason: "permission_required"
982
+ },
983
+ PERMISSION_DENIED: {
984
+ code: "FORBIDDEN",
985
+ reason: "permission_denied"
986
+ },
987
+ PERMISSION_PROMPT_TIMEOUT: {
988
+ code: "TIMEOUT",
989
+ reason: "permission_prompt_timeout"
990
+ },
991
+ SESSION_NOT_FOUND: {
992
+ code: "NOT_FOUND",
993
+ reason: "session_not_found",
994
+ resource: "session"
995
+ },
996
+ SESSION_CLOSED: {
997
+ code: "FAILED_PRECONDITION",
998
+ reason: "session_closed",
999
+ resource: "session"
1000
+ },
1001
+ SESSION_BROKEN: {
1002
+ code: "FAILED_PRECONDITION",
1003
+ reason: "session_broken",
1004
+ resource: "session"
1005
+ },
1006
+ DRIVE_UNAVAILABLE: {
1007
+ code: "UNAVAILABLE",
1008
+ reason: "drive_unavailable"
1009
+ },
1010
+ INSPECT_UNAVAILABLE: {
1011
+ code: "UNAVAILABLE",
1012
+ reason: "inspect_unavailable"
1013
+ },
1014
+ EXTENSION_DISCONNECTED: {
1015
+ code: "UNAVAILABLE",
1016
+ reason: "extension_disconnected"
1017
+ },
1018
+ DEBUGGER_IN_USE: {
1019
+ code: "CONFLICT",
1020
+ reason: "debugger_in_use"
1021
+ },
1022
+ ATTACH_DENIED: {
1023
+ code: "FORBIDDEN",
1024
+ reason: "attach_denied"
1025
+ },
1026
+ TAB_NOT_FOUND: {
1027
+ code: "NOT_FOUND",
1028
+ reason: "tab_not_found",
1029
+ resource: "tab"
1030
+ },
1031
+ LOCATOR_NOT_FOUND: {
1032
+ code: "NOT_FOUND",
1033
+ reason: "locator_not_found",
1034
+ resource: "locator"
1035
+ },
1036
+ NOT_SUPPORTED: {
1037
+ code: "NOT_IMPLEMENTED",
1038
+ reason: "not_supported"
1039
+ },
1040
+ NAVIGATION_FAILED: {
1041
+ code: "FAILED_PRECONDITION",
1042
+ reason: "navigation_failed"
1043
+ },
1044
+ EVALUATION_FAILED: {
1045
+ code: "FAILED_PRECONDITION",
1046
+ reason: "evaluation_failed"
1047
+ },
1048
+ ARTIFACT_IO_ERROR: {
1049
+ code: "FAILED_PRECONDITION",
1050
+ reason: "artifact_io_error"
1051
+ }
1052
+ };
1053
+ var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1054
+ var normalizeErrorCode = (code) => LEGACY_ERROR_CODE_MAP[code]?.code ?? (PublicErrorCodeSchema.safeParse(code).success ? code : "INTERNAL");
1055
+ var ErrorInfoSchema = import_zod2.z.object({
822
1056
  code: ErrorCodeSchema,
823
- message: import_zod.z.string(),
824
- retryable: import_zod.z.boolean(),
825
- details: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
1057
+ message: import_zod2.z.string(),
1058
+ retryable: import_zod2.z.boolean(),
1059
+ retry: RetryHintSchema.optional(),
1060
+ details: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional()
826
1061
  });
827
- var ErrorEnvelopeSchema = import_zod.z.object({
828
- ok: import_zod.z.literal(false),
1062
+ var normalizeErrorInfo = (error) => {
1063
+ const parsedCode = ErrorCodeSchema.safeParse(error.code);
1064
+ const normalizedInputCode = parsedCode.success ? parsedCode.data : "INTERNAL";
1065
+ const existingDetails = isRecord(error.details) ? error.details : {};
1066
+ const normalizedInput = {
1067
+ ...error,
1068
+ code: normalizedInputCode,
1069
+ ...parsedCode.success ? {} : {
1070
+ details: {
1071
+ ...existingDetails,
1072
+ legacy_code: error.code,
1073
+ reason: "unknown_code"
1074
+ }
1075
+ }
1076
+ };
1077
+ const mapping = LEGACY_ERROR_CODE_MAP[normalizedInput.code];
1078
+ if (!mapping) {
1079
+ return normalizedInput;
1080
+ }
1081
+ const mappedDetails = isRecord(normalizedInput.details) ? normalizedInput.details : {};
1082
+ const details = {
1083
+ ...mappedDetails,
1084
+ legacy_code: normalizedInput.code,
1085
+ reason: mapping.reason,
1086
+ ...mapping.resource ? { resource: mapping.resource } : {}
1087
+ };
1088
+ return {
1089
+ ...normalizedInput,
1090
+ code: mapping.code,
1091
+ details: PublicErrorDetailsSchema.parse(details)
1092
+ };
1093
+ };
1094
+ var ErrorEnvelopeSchema = import_zod2.z.object({
1095
+ ok: import_zod2.z.literal(false),
829
1096
  error: ErrorInfoSchema
830
1097
  });
831
- var successEnvelopeSchema = (result) => import_zod.z.object({
832
- ok: import_zod.z.literal(true),
1098
+ var successEnvelopeSchema = (result) => import_zod2.z.object({
1099
+ ok: import_zod2.z.literal(true),
833
1100
  result
834
1101
  });
835
1102
 
836
1103
  // packages/shared/src/schemas.ts
837
- var import_zod2 = require("zod");
838
- var LocatorRoleSchema = import_zod2.z.object({
839
- name: import_zod2.z.string(),
840
- value: import_zod2.z.string().optional()
1104
+ var import_zod3 = require("zod");
1105
+ var LocatorRoleSchema = import_zod3.z.object({
1106
+ name: import_zod3.z.string(),
1107
+ value: import_zod3.z.string().optional()
841
1108
  });
842
- var LocatorSchema = import_zod2.z.object({
843
- ref: import_zod2.z.string().min(1).optional(),
844
- testid: import_zod2.z.string().min(1).optional(),
845
- css: import_zod2.z.string().min(1).optional(),
846
- text: import_zod2.z.string().min(1).optional(),
1109
+ var LocatorSchema = import_zod3.z.object({
1110
+ ref: import_zod3.z.string().min(1).optional(),
1111
+ testid: import_zod3.z.string().min(1).optional(),
1112
+ css: import_zod3.z.string().min(1).optional(),
1113
+ text: import_zod3.z.string().min(1).optional(),
847
1114
  role: LocatorRoleSchema.optional()
848
1115
  }).refine(
849
1116
  (value) => Boolean(
@@ -853,12 +1120,12 @@ var LocatorSchema = import_zod2.z.object({
853
1120
  message: "Locator must include at least one selector."
854
1121
  }
855
1122
  );
856
- var OpResultSchema = import_zod2.z.object({
857
- ok: import_zod2.z.literal(true),
858
- message: import_zod2.z.string().optional(),
859
- warnings: import_zod2.z.array(import_zod2.z.string()).optional()
1123
+ var OpResultSchema = import_zod3.z.object({
1124
+ ok: import_zod3.z.literal(true),
1125
+ message: import_zod3.z.string().optional(),
1126
+ warnings: import_zod3.z.array(import_zod3.z.string()).optional()
860
1127
  });
861
- var SessionStateSchema = import_zod2.z.enum([
1128
+ var SessionStateSchema = import_zod3.z.enum([
862
1129
  "INIT",
863
1130
  "DRIVE_READY",
864
1131
  "INSPECT_READY",
@@ -868,269 +1135,270 @@ var SessionStateSchema = import_zod2.z.enum([
868
1135
  "BROKEN",
869
1136
  "CLOSED"
870
1137
  ]);
871
- var SessionInfoSchema = import_zod2.z.object({
872
- session_id: import_zod2.z.string(),
1138
+ var SessionInfoSchema = import_zod3.z.object({
1139
+ session_id: import_zod3.z.string(),
873
1140
  state: SessionStateSchema,
874
- created_at: import_zod2.z.string().datetime().optional()
1141
+ created_at: import_zod3.z.string().datetime().optional()
875
1142
  });
876
- var SessionPlaneStatusSchema = import_zod2.z.object({
877
- connected: import_zod2.z.boolean(),
878
- last_seen_at: import_zod2.z.string().datetime().optional(),
1143
+ var SessionPlaneStatusSchema = import_zod3.z.object({
1144
+ connected: import_zod3.z.boolean(),
1145
+ last_seen_at: import_zod3.z.string().datetime().optional(),
879
1146
  error: ErrorInfoSchema.optional()
880
1147
  });
881
- var SessionStatusSchema = import_zod2.z.object({
882
- session_id: import_zod2.z.string(),
1148
+ var SessionStatusSchema = import_zod3.z.object({
1149
+ session_id: import_zod3.z.string(),
883
1150
  state: SessionStateSchema,
884
1151
  drive: SessionPlaneStatusSchema.optional(),
885
1152
  inspect: SessionPlaneStatusSchema.optional(),
886
- updated_at: import_zod2.z.string().datetime().optional()
1153
+ updated_at: import_zod3.z.string().datetime().optional()
887
1154
  });
888
- var RecoverResultSchema = import_zod2.z.object({
889
- session_id: import_zod2.z.string(),
890
- recovered: import_zod2.z.boolean(),
1155
+ var RecoverResultSchema = import_zod3.z.object({
1156
+ session_id: import_zod3.z.string(),
1157
+ recovered: import_zod3.z.boolean(),
891
1158
  state: SessionStateSchema,
892
- message: import_zod2.z.string().optional()
1159
+ message: import_zod3.z.string().optional()
893
1160
  });
894
- var DiagnosticCheckSchema = import_zod2.z.object({
895
- name: import_zod2.z.string(),
896
- ok: import_zod2.z.boolean(),
897
- message: import_zod2.z.string().optional(),
898
- details: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional()
1161
+ var DiagnosticCheckSchema = import_zod3.z.object({
1162
+ name: import_zod3.z.string(),
1163
+ ok: import_zod3.z.boolean(),
1164
+ message: import_zod3.z.string().optional(),
1165
+ details: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional()
899
1166
  });
900
- var DiagnosticsRuntimeEndpointSchema = import_zod2.z.object({
901
- host: import_zod2.z.string().optional(),
902
- port: import_zod2.z.number().finite().optional(),
903
- base_url: import_zod2.z.string().optional(),
904
- host_source: import_zod2.z.string().optional(),
905
- port_source: import_zod2.z.string().optional(),
906
- metadata_path: import_zod2.z.string().optional(),
907
- isolated_mode: import_zod2.z.boolean().optional()
1167
+ var DiagnosticsRuntimeEndpointSchema = import_zod3.z.object({
1168
+ host: import_zod3.z.string().optional(),
1169
+ port: import_zod3.z.number().finite().optional(),
1170
+ base_url: import_zod3.z.string().optional(),
1171
+ host_source: import_zod3.z.string().optional(),
1172
+ port_source: import_zod3.z.string().optional(),
1173
+ metadata_path: import_zod3.z.string().optional(),
1174
+ isolated_mode: import_zod3.z.boolean().optional()
908
1175
  });
909
- var DiagnosticsRuntimeProcessSchema = import_zod2.z.object({
910
- component: import_zod2.z.enum(["cli", "mcp", "core"]).optional(),
911
- version: import_zod2.z.string().optional(),
912
- pid: import_zod2.z.number().int().positive().optional(),
913
- node_version: import_zod2.z.string().optional(),
914
- binary_path: import_zod2.z.string().optional(),
915
- argv_entry: import_zod2.z.string().optional()
1176
+ var DiagnosticsRuntimeProcessSchema = import_zod3.z.object({
1177
+ component: import_zod3.z.enum(["cli", "mcp", "core"]).optional(),
1178
+ version: import_zod3.z.string().optional(),
1179
+ pid: import_zod3.z.number().int().positive().optional(),
1180
+ node_version: import_zod3.z.string().optional(),
1181
+ binary_path: import_zod3.z.string().optional(),
1182
+ argv_entry: import_zod3.z.string().optional()
916
1183
  });
917
- var DiagnosticsRuntimeCallerSchema = import_zod2.z.object({
1184
+ var DiagnosticsRuntimeCallerSchema = import_zod3.z.object({
918
1185
  endpoint: DiagnosticsRuntimeEndpointSchema.optional(),
919
1186
  process: DiagnosticsRuntimeProcessSchema.optional()
920
1187
  });
921
- var DiagnosticsRuntimeContextSchema = import_zod2.z.object({
1188
+ var DiagnosticsRuntimeContextSchema = import_zod3.z.object({
922
1189
  caller: DiagnosticsRuntimeCallerSchema.optional(),
923
- core: import_zod2.z.object({
1190
+ core: import_zod3.z.object({
924
1191
  endpoint: DiagnosticsRuntimeEndpointSchema.optional(),
925
1192
  process: DiagnosticsRuntimeProcessSchema.optional()
926
1193
  }).optional(),
927
- extension: import_zod2.z.object({
928
- version: import_zod2.z.string().optional(),
1194
+ extension: import_zod3.z.object({
1195
+ version: import_zod3.z.string().optional(),
1196
+ protocol_version: import_zod3.z.string().optional(),
1197
+ capability_negotiated: import_zod3.z.boolean().optional(),
1198
+ capabilities: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.boolean()).optional(),
929
1199
  endpoint: DiagnosticsRuntimeEndpointSchema.optional(),
930
- port_source: import_zod2.z.enum(["default", "storage"]).optional()
1200
+ port_source: import_zod3.z.enum(["default", "storage"]).optional()
931
1201
  }).optional()
932
1202
  });
933
- var DiagnosticReportSchema = import_zod2.z.object({
934
- ok: import_zod2.z.boolean(),
935
- session_id: import_zod2.z.string().optional(),
936
- checks: import_zod2.z.array(DiagnosticCheckSchema).optional(),
937
- sessions: import_zod2.z.object({
938
- count: import_zod2.z.number().finite().optional(),
939
- max_age_ms: import_zod2.z.number().finite().optional(),
940
- max_idle_ms: import_zod2.z.number().finite().optional()
1203
+ var DiagnosticReportSchema = import_zod3.z.object({
1204
+ ok: import_zod3.z.boolean(),
1205
+ session_id: import_zod3.z.string().optional(),
1206
+ checks: import_zod3.z.array(DiagnosticCheckSchema).optional(),
1207
+ sessions: import_zod3.z.object({
1208
+ count: import_zod3.z.number().finite().optional(),
1209
+ max_age_ms: import_zod3.z.number().finite().optional(),
1210
+ max_idle_ms: import_zod3.z.number().finite().optional()
941
1211
  }).optional(),
942
- extension: import_zod2.z.object({
943
- connected: import_zod2.z.boolean().optional(),
944
- version: import_zod2.z.string().optional(),
945
- last_seen_at: import_zod2.z.string().datetime().optional()
1212
+ extension: import_zod3.z.object({
1213
+ connected: import_zod3.z.boolean().optional(),
1214
+ version: import_zod3.z.string().optional(),
1215
+ last_seen_at: import_zod3.z.string().datetime().optional()
946
1216
  }).optional(),
947
- debugger: import_zod2.z.object({
948
- attached: import_zod2.z.boolean().optional(),
949
- idle_timeout_ms: import_zod2.z.number().finite().optional(),
950
- console_buffer_size: import_zod2.z.number().finite().optional(),
951
- network_buffer_size: import_zod2.z.number().finite().optional(),
1217
+ debugger: import_zod3.z.object({
1218
+ attached: import_zod3.z.boolean().optional(),
1219
+ idle_timeout_ms: import_zod3.z.number().finite().optional(),
1220
+ console_buffer_size: import_zod3.z.number().finite().optional(),
1221
+ network_buffer_size: import_zod3.z.number().finite().optional(),
952
1222
  last_error: ErrorInfoSchema.optional()
953
1223
  }).optional(),
954
- artifacts: import_zod2.z.object({
955
- root_dir: import_zod2.z.string().optional()
1224
+ artifacts: import_zod3.z.object({
1225
+ root_dir: import_zod3.z.string().optional()
956
1226
  }).optional(),
957
- recovery: import_zod2.z.object({
958
- last_attempt: import_zod2.z.object({
959
- session_id: import_zod2.z.string(),
960
- recovered: import_zod2.z.boolean(),
1227
+ recovery: import_zod3.z.object({
1228
+ last_attempt: import_zod3.z.object({
1229
+ session_id: import_zod3.z.string(),
1230
+ recovered: import_zod3.z.boolean(),
961
1231
  state: SessionStateSchema,
962
- message: import_zod2.z.string().optional(),
963
- at: import_zod2.z.string()
1232
+ message: import_zod3.z.string().optional(),
1233
+ at: import_zod3.z.string()
964
1234
  }).optional(),
965
- attempts: import_zod2.z.array(
966
- import_zod2.z.object({
967
- session_id: import_zod2.z.string(),
968
- recovered: import_zod2.z.boolean(),
1235
+ attempts: import_zod3.z.array(
1236
+ import_zod3.z.object({
1237
+ session_id: import_zod3.z.string(),
1238
+ recovered: import_zod3.z.boolean(),
969
1239
  state: SessionStateSchema,
970
- message: import_zod2.z.string().optional(),
971
- at: import_zod2.z.string()
1240
+ message: import_zod3.z.string().optional(),
1241
+ at: import_zod3.z.string()
972
1242
  })
973
1243
  ).optional(),
974
- success_count: import_zod2.z.number().finite().optional(),
975
- failure_count: import_zod2.z.number().finite().optional(),
976
- success_rate: import_zod2.z.number().finite().optional(),
977
- recent_failure_count: import_zod2.z.number().finite().optional(),
978
- loop_detected: import_zod2.z.boolean().optional()
1244
+ success_count: import_zod3.z.number().finite().optional(),
1245
+ failure_count: import_zod3.z.number().finite().optional(),
1246
+ success_rate: import_zod3.z.number().finite().optional(),
1247
+ recent_failure_count: import_zod3.z.number().finite().optional(),
1248
+ loop_detected: import_zod3.z.boolean().optional()
979
1249
  }).optional(),
980
- warnings: import_zod2.z.array(import_zod2.z.string()).optional(),
981
- notes: import_zod2.z.array(import_zod2.z.string()).optional(),
1250
+ warnings: import_zod3.z.array(import_zod3.z.string()).optional(),
1251
+ notes: import_zod3.z.array(import_zod3.z.string()).optional(),
982
1252
  runtime: DiagnosticsRuntimeContextSchema.optional()
983
1253
  });
984
- var SessionIdSchema = import_zod2.z.object({
985
- session_id: import_zod2.z.string().min(1)
1254
+ var SessionIdSchema = import_zod3.z.object({
1255
+ session_id: import_zod3.z.string().min(1)
986
1256
  });
987
- var SessionCreateInputSchema = import_zod2.z.object({}).strict().default({});
1257
+ var SessionCreateInputSchema = import_zod3.z.object({}).strict().default({});
988
1258
  var SessionCreateOutputSchema = SessionInfoSchema;
989
1259
  var SessionStatusInputSchema = SessionIdSchema;
990
1260
  var SessionStatusOutputSchema = SessionStatusSchema;
991
1261
  var SessionRecoverInputSchema = SessionIdSchema;
992
1262
  var SessionRecoverOutputSchema = RecoverResultSchema;
993
1263
  var SessionCloseInputSchema = SessionIdSchema;
994
- var SessionCloseOutputSchema = import_zod2.z.object({
995
- ok: import_zod2.z.boolean()
1264
+ var SessionCloseOutputSchema = import_zod3.z.object({
1265
+ ok: import_zod3.z.boolean()
996
1266
  });
997
- var DriveWaitConditionSchema = import_zod2.z.object({
998
- kind: import_zod2.z.enum(["locator_visible", "text_present", "url_matches"]),
999
- value: import_zod2.z.string().min(1)
1267
+ var DriveWaitConditionSchema = import_zod3.z.object({
1268
+ kind: import_zod3.z.enum(["locator_visible", "text_present", "url_matches"]),
1269
+ value: import_zod3.z.string().min(1)
1000
1270
  });
1001
- var DriveNavigateInputSchema = import_zod2.z.object({
1002
- session_id: import_zod2.z.string().min(1),
1003
- url: import_zod2.z.string().min(1),
1004
- tab_id: import_zod2.z.number().finite().optional(),
1005
- wait: import_zod2.z.enum(["none", "domcontentloaded"]).default("domcontentloaded")
1271
+ var DriveNavigateInputSchema = import_zod3.z.object({
1272
+ session_id: import_zod3.z.string().min(1).optional(),
1273
+ url: import_zod3.z.string().min(1),
1274
+ tab_id: import_zod3.z.number().finite().optional(),
1275
+ wait: import_zod3.z.enum(["none", "domcontentloaded"]).default("domcontentloaded")
1276
+ });
1277
+ var DriveNavigateOutputSchema = OpResultSchema.extend({
1278
+ session_id: import_zod3.z.string().min(1)
1006
1279
  });
1007
- var DriveNavigateOutputSchema = OpResultSchema;
1008
- var DriveGoBackInputSchema = import_zod2.z.object({
1009
- session_id: import_zod2.z.string().min(1),
1010
- tab_id: import_zod2.z.number().finite().optional()
1280
+ var DriveGoBackInputSchema = import_zod3.z.object({
1281
+ session_id: import_zod3.z.string().min(1),
1282
+ tab_id: import_zod3.z.number().finite().optional()
1011
1283
  });
1012
1284
  var DriveGoBackOutputSchema = OpResultSchema;
1013
- var DriveGoForwardInputSchema = import_zod2.z.object({
1014
- session_id: import_zod2.z.string().min(1),
1015
- tab_id: import_zod2.z.number().finite().optional()
1285
+ var DriveGoForwardInputSchema = import_zod3.z.object({
1286
+ session_id: import_zod3.z.string().min(1),
1287
+ tab_id: import_zod3.z.number().finite().optional()
1016
1288
  });
1017
1289
  var DriveGoForwardOutputSchema = OpResultSchema;
1018
- var DriveBackInputSchema = DriveGoBackInputSchema;
1019
- var DriveBackOutputSchema = OpResultSchema;
1020
- var DriveForwardInputSchema = DriveGoForwardInputSchema;
1021
- var DriveForwardOutputSchema = OpResultSchema;
1022
- var DriveClickInputSchema = import_zod2.z.object({
1023
- session_id: import_zod2.z.string().min(1),
1290
+ var DriveClickInputSchema = import_zod3.z.object({
1291
+ session_id: import_zod3.z.string().min(1),
1024
1292
  locator: LocatorSchema,
1025
- tab_id: import_zod2.z.number().finite().optional(),
1026
- click_count: import_zod2.z.number().finite().optional()
1293
+ tab_id: import_zod3.z.number().finite().optional(),
1294
+ click_count: import_zod3.z.number().finite().optional()
1027
1295
  });
1028
1296
  var DriveClickOutputSchema = OpResultSchema;
1029
- var DriveHoverInputSchema = import_zod2.z.object({
1030
- session_id: import_zod2.z.string().min(1),
1297
+ var DriveHoverInputSchema = import_zod3.z.object({
1298
+ session_id: import_zod3.z.string().min(1),
1031
1299
  locator: LocatorSchema,
1032
- delay_ms: import_zod2.z.number().min(0).max(1e4).optional(),
1033
- tab_id: import_zod2.z.number().finite().optional()
1300
+ delay_ms: import_zod3.z.number().min(0).max(1e4).optional(),
1301
+ tab_id: import_zod3.z.number().finite().optional()
1034
1302
  });
1035
- var DriveHoverOutputSchema = import_zod2.z.object({
1036
- format: import_zod2.z.literal("html"),
1037
- snapshot: import_zod2.z.string()
1303
+ var DriveHoverOutputSchema = import_zod3.z.object({
1304
+ format: import_zod3.z.literal("html"),
1305
+ snapshot: import_zod3.z.string()
1038
1306
  });
1039
- var DriveSelectInputSchema = import_zod2.z.object({
1040
- session_id: import_zod2.z.string().min(1),
1307
+ var DriveSelectInputSchema = import_zod3.z.object({
1308
+ session_id: import_zod3.z.string().min(1),
1041
1309
  locator: LocatorSchema,
1042
- value: import_zod2.z.string().min(1).optional(),
1043
- text: import_zod2.z.string().min(1).optional(),
1044
- index: import_zod2.z.number().int().min(0).optional(),
1045
- tab_id: import_zod2.z.number().finite().optional()
1310
+ value: import_zod3.z.string().min(1).optional(),
1311
+ text: import_zod3.z.string().min(1).optional(),
1312
+ index: import_zod3.z.number().int().min(0).optional(),
1313
+ tab_id: import_zod3.z.number().finite().optional()
1046
1314
  }).refine((value) => value.value || value.text || value.index !== void 0, {
1047
1315
  message: "Either value, text, or index must be provided.",
1048
1316
  path: ["select"]
1049
1317
  });
1050
1318
  var DriveSelectOutputSchema = OpResultSchema;
1051
- var DriveTypeInputSchema = import_zod2.z.object({
1052
- session_id: import_zod2.z.string().min(1),
1319
+ var DriveTypeInputSchema = import_zod3.z.object({
1320
+ session_id: import_zod3.z.string().min(1),
1053
1321
  locator: LocatorSchema.optional(),
1054
- text: import_zod2.z.string().min(1),
1055
- tab_id: import_zod2.z.number().finite().optional(),
1056
- clear: import_zod2.z.boolean().default(false),
1057
- submit: import_zod2.z.boolean().default(false)
1322
+ text: import_zod3.z.string().min(1),
1323
+ tab_id: import_zod3.z.number().finite().optional(),
1324
+ clear: import_zod3.z.boolean().default(false),
1325
+ submit: import_zod3.z.boolean().default(false)
1058
1326
  });
1059
1327
  var DriveTypeOutputSchema = OpResultSchema;
1060
- var DriveFillFormFieldSchema = import_zod2.z.object({
1061
- selector: import_zod2.z.string().min(1).optional(),
1328
+ var DriveFillFormFieldSchema = import_zod3.z.object({
1329
+ selector: import_zod3.z.string().min(1).optional(),
1062
1330
  locator: LocatorSchema.optional(),
1063
- value: import_zod2.z.union([import_zod2.z.string(), import_zod2.z.boolean()]),
1064
- type: import_zod2.z.enum(["auto", "text", "select", "checkbox", "radio", "contentEditable"]).default("auto"),
1065
- submit: import_zod2.z.boolean().default(false)
1331
+ value: import_zod3.z.union([import_zod3.z.string(), import_zod3.z.boolean()]),
1332
+ type: import_zod3.z.enum(["auto", "text", "select", "checkbox", "radio", "contentEditable"]).default("auto"),
1333
+ submit: import_zod3.z.boolean().default(false)
1066
1334
  }).refine((value) => Boolean(value.selector || value.locator), {
1067
1335
  message: "fill_form field requires selector or locator.",
1068
1336
  path: ["selector"]
1069
1337
  });
1070
- var DriveFillFormInputSchema = import_zod2.z.object({
1071
- session_id: import_zod2.z.string().min(1),
1072
- fields: import_zod2.z.array(DriveFillFormFieldSchema).min(1),
1073
- tab_id: import_zod2.z.number().finite().optional()
1338
+ var DriveFillFormInputSchema = import_zod3.z.object({
1339
+ session_id: import_zod3.z.string().min(1),
1340
+ fields: import_zod3.z.array(DriveFillFormFieldSchema).min(1),
1341
+ tab_id: import_zod3.z.number().finite().optional()
1074
1342
  });
1075
- var DriveFillFormOutputSchema = import_zod2.z.object({
1076
- filled: import_zod2.z.number().finite(),
1077
- attempted: import_zod2.z.number().finite(),
1078
- errors: import_zod2.z.array(import_zod2.z.string()).optional()
1343
+ var DriveFillFormOutputSchema = import_zod3.z.object({
1344
+ filled: import_zod3.z.number().finite(),
1345
+ attempted: import_zod3.z.number().finite(),
1346
+ errors: import_zod3.z.array(import_zod3.z.string()).optional()
1079
1347
  });
1080
- var DriveDragInputSchema = import_zod2.z.object({
1081
- session_id: import_zod2.z.string().min(1),
1348
+ var DriveDragInputSchema = import_zod3.z.object({
1349
+ session_id: import_zod3.z.string().min(1),
1082
1350
  from: LocatorSchema,
1083
1351
  to: LocatorSchema,
1084
- steps: import_zod2.z.number().min(1).max(50).default(12),
1085
- tab_id: import_zod2.z.number().finite().optional()
1352
+ steps: import_zod3.z.number().min(1).max(50).default(12),
1353
+ tab_id: import_zod3.z.number().finite().optional()
1086
1354
  });
1087
1355
  var DriveDragOutputSchema = OpResultSchema;
1088
- var DriveHandleDialogInputSchema = import_zod2.z.object({
1089
- session_id: import_zod2.z.string().min(1),
1090
- action: import_zod2.z.enum(["accept", "dismiss"]),
1091
- promptText: import_zod2.z.string().optional(),
1092
- tab_id: import_zod2.z.number().finite().optional()
1356
+ var DriveHandleDialogInputSchema = import_zod3.z.object({
1357
+ session_id: import_zod3.z.string().min(1),
1358
+ action: import_zod3.z.enum(["accept", "dismiss"]),
1359
+ promptText: import_zod3.z.string().optional(),
1360
+ tab_id: import_zod3.z.number().finite().optional()
1093
1361
  });
1094
1362
  var DriveHandleDialogOutputSchema = OpResultSchema;
1095
1363
  var DialogAcceptInputSchema = SessionIdSchema.extend({
1096
- promptText: import_zod2.z.string().optional(),
1097
- tab_id: import_zod2.z.number().finite().optional()
1364
+ promptText: import_zod3.z.string().optional(),
1365
+ tab_id: import_zod3.z.number().finite().optional()
1098
1366
  });
1099
1367
  var DialogAcceptOutputSchema = OpResultSchema;
1100
1368
  var DialogDismissInputSchema = SessionIdSchema.extend({
1101
- tab_id: import_zod2.z.number().finite().optional()
1369
+ tab_id: import_zod3.z.number().finite().optional()
1102
1370
  });
1103
1371
  var DialogDismissOutputSchema = OpResultSchema;
1104
- var DriveKeyModifiersSchema = import_zod2.z.object({
1105
- ctrl: import_zod2.z.boolean().optional(),
1106
- alt: import_zod2.z.boolean().optional(),
1107
- shift: import_zod2.z.boolean().optional(),
1108
- meta: import_zod2.z.boolean().optional()
1372
+ var DriveKeyModifiersSchema = import_zod3.z.object({
1373
+ ctrl: import_zod3.z.boolean().optional(),
1374
+ alt: import_zod3.z.boolean().optional(),
1375
+ shift: import_zod3.z.boolean().optional(),
1376
+ meta: import_zod3.z.boolean().optional()
1109
1377
  });
1110
- var DriveKeyPressInputSchema = import_zod2.z.object({
1111
- session_id: import_zod2.z.string().min(1),
1112
- key: import_zod2.z.string().min(1),
1378
+ var DriveKeyPressInputSchema = import_zod3.z.object({
1379
+ session_id: import_zod3.z.string().min(1),
1380
+ key: import_zod3.z.string().min(1),
1113
1381
  modifiers: DriveKeyModifiersSchema.optional(),
1114
- tab_id: import_zod2.z.number().finite().optional()
1382
+ tab_id: import_zod3.z.number().finite().optional()
1115
1383
  });
1116
1384
  var DriveKeyPressOutputSchema = OpResultSchema;
1117
- var DriveKeyModifierSchema = import_zod2.z.enum(["ctrl", "alt", "shift", "meta"]);
1118
- var DriveKeyInputSchema = import_zod2.z.object({
1119
- session_id: import_zod2.z.string().min(1),
1120
- key: import_zod2.z.string().min(1),
1121
- modifiers: import_zod2.z.array(DriveKeyModifierSchema).optional(),
1122
- repeat: import_zod2.z.number().int().min(1).max(50).optional(),
1123
- tab_id: import_zod2.z.number().finite().optional()
1385
+ var DriveKeyModifierSchema = import_zod3.z.enum(["ctrl", "alt", "shift", "meta"]);
1386
+ var DriveKeyInputSchema = import_zod3.z.object({
1387
+ session_id: import_zod3.z.string().min(1),
1388
+ key: import_zod3.z.string().min(1),
1389
+ modifiers: import_zod3.z.array(DriveKeyModifierSchema).optional(),
1390
+ repeat: import_zod3.z.number().int().min(1).max(50).optional(),
1391
+ tab_id: import_zod3.z.number().finite().optional()
1124
1392
  });
1125
1393
  var DriveKeyOutputSchema = OpResultSchema;
1126
- var DriveScrollInputSchema = import_zod2.z.object({
1127
- session_id: import_zod2.z.string().min(1),
1128
- delta_x: import_zod2.z.number().finite().optional(),
1129
- delta_y: import_zod2.z.number().finite().optional(),
1130
- top: import_zod2.z.number().finite().optional(),
1131
- left: import_zod2.z.number().finite().optional(),
1132
- behavior: import_zod2.z.enum(["auto", "smooth"]).optional(),
1133
- tab_id: import_zod2.z.number().finite().optional()
1394
+ var DriveScrollInputSchema = import_zod3.z.object({
1395
+ session_id: import_zod3.z.string().min(1),
1396
+ delta_x: import_zod3.z.number().finite().optional(),
1397
+ delta_y: import_zod3.z.number().finite().optional(),
1398
+ top: import_zod3.z.number().finite().optional(),
1399
+ left: import_zod3.z.number().finite().optional(),
1400
+ behavior: import_zod3.z.enum(["auto", "smooth"]).optional(),
1401
+ tab_id: import_zod3.z.number().finite().optional()
1134
1402
  }).refine(
1135
1403
  (value) => value.delta_x !== void 0 || value.delta_y !== void 0 || value.top !== void 0 || value.left !== void 0,
1136
1404
  {
@@ -1139,239 +1407,239 @@ var DriveScrollInputSchema = import_zod2.z.object({
1139
1407
  }
1140
1408
  );
1141
1409
  var DriveScrollOutputSchema = OpResultSchema;
1142
- var DriveWaitForInputSchema = import_zod2.z.object({
1143
- session_id: import_zod2.z.string().min(1),
1410
+ var DriveWaitForInputSchema = import_zod3.z.object({
1411
+ session_id: import_zod3.z.string().min(1),
1144
1412
  condition: DriveWaitConditionSchema,
1145
- timeout_ms: import_zod2.z.number().finite().optional(),
1146
- tab_id: import_zod2.z.number().finite().optional()
1413
+ timeout_ms: import_zod3.z.number().finite().optional(),
1414
+ tab_id: import_zod3.z.number().finite().optional()
1147
1415
  });
1148
1416
  var DriveWaitForOutputSchema = OpResultSchema;
1149
- var DriveTabInfoSchema = import_zod2.z.object({
1150
- tab_id: import_zod2.z.number().finite(),
1151
- window_id: import_zod2.z.number().finite(),
1152
- url: import_zod2.z.string().min(1),
1153
- title: import_zod2.z.string(),
1154
- active: import_zod2.z.boolean().optional(),
1155
- last_active_at: import_zod2.z.string().datetime().optional()
1417
+ var DriveTabInfoSchema = import_zod3.z.object({
1418
+ tab_id: import_zod3.z.number().finite(),
1419
+ window_id: import_zod3.z.number().finite(),
1420
+ url: import_zod3.z.string().min(1),
1421
+ title: import_zod3.z.string(),
1422
+ active: import_zod3.z.boolean().optional(),
1423
+ last_active_at: import_zod3.z.string().datetime().optional()
1156
1424
  });
1157
1425
  var DriveTabListInputSchema = SessionIdSchema;
1158
- var DriveTabListOutputSchema = import_zod2.z.object({
1159
- tabs: import_zod2.z.array(DriveTabInfoSchema)
1426
+ var DriveTabListOutputSchema = import_zod3.z.object({
1427
+ tabs: import_zod3.z.array(DriveTabInfoSchema)
1160
1428
  });
1161
- var DriveTabActivateInputSchema = import_zod2.z.object({
1162
- session_id: import_zod2.z.string().min(1),
1163
- tab_id: import_zod2.z.number().finite()
1429
+ var DriveTabActivateInputSchema = import_zod3.z.object({
1430
+ session_id: import_zod3.z.string().min(1),
1431
+ tab_id: import_zod3.z.number().finite()
1164
1432
  });
1165
1433
  var DriveTabActivateOutputSchema = OpResultSchema;
1166
- var DriveTabCloseInputSchema = import_zod2.z.object({
1167
- session_id: import_zod2.z.string().min(1),
1168
- tab_id: import_zod2.z.number().finite()
1434
+ var DriveTabCloseInputSchema = import_zod3.z.object({
1435
+ session_id: import_zod3.z.string().min(1),
1436
+ tab_id: import_zod3.z.number().finite()
1169
1437
  });
1170
1438
  var DriveTabCloseOutputSchema = OpResultSchema;
1171
- var InspectDomFormatSchema = import_zod2.z.enum(["ax", "html"]);
1172
- var InspectConsistencySchema = import_zod2.z.enum(["best_effort", "quiesce"]);
1173
- var TargetHintSchema = import_zod2.z.object({
1174
- url: import_zod2.z.string().min(1).optional(),
1175
- title: import_zod2.z.string().min(1).optional(),
1176
- last_active_at: import_zod2.z.string().optional(),
1177
- lastActiveAt: import_zod2.z.string().optional()
1439
+ var InspectDomFormatSchema = import_zod3.z.enum(["ax", "html"]);
1440
+ var InspectConsistencySchema = import_zod3.z.enum(["best_effort", "quiesce"]);
1441
+ var TargetHintSchema = import_zod3.z.object({
1442
+ url: import_zod3.z.string().min(1).optional(),
1443
+ title: import_zod3.z.string().min(1).optional(),
1444
+ last_active_at: import_zod3.z.string().optional(),
1445
+ lastActiveAt: import_zod3.z.string().optional()
1178
1446
  });
1179
- var FormFieldInfoSchema = import_zod2.z.object({
1180
- name: import_zod2.z.string(),
1181
- type: import_zod2.z.string(),
1182
- value: import_zod2.z.string(),
1183
- options: import_zod2.z.array(import_zod2.z.string()).optional()
1447
+ var FormFieldInfoSchema = import_zod3.z.object({
1448
+ name: import_zod3.z.string(),
1449
+ type: import_zod3.z.string(),
1450
+ value: import_zod3.z.string(),
1451
+ options: import_zod3.z.array(import_zod3.z.string()).optional()
1184
1452
  });
1185
- var FormInfoSchema = import_zod2.z.object({
1186
- selector: import_zod2.z.string(),
1187
- action: import_zod2.z.string().optional(),
1188
- method: import_zod2.z.string().optional(),
1189
- fields: import_zod2.z.array(FormFieldInfoSchema)
1453
+ var FormInfoSchema = import_zod3.z.object({
1454
+ selector: import_zod3.z.string(),
1455
+ action: import_zod3.z.string().optional(),
1456
+ method: import_zod3.z.string().optional(),
1457
+ fields: import_zod3.z.array(FormFieldInfoSchema)
1190
1458
  });
1191
- var StorageEntrySchema = import_zod2.z.object({
1192
- key: import_zod2.z.string(),
1193
- value: import_zod2.z.string()
1459
+ var StorageEntrySchema = import_zod3.z.object({
1460
+ key: import_zod3.z.string(),
1461
+ value: import_zod3.z.string()
1194
1462
  });
1195
- var PageStateSchema = import_zod2.z.object({
1196
- forms: import_zod2.z.array(FormInfoSchema),
1197
- localStorage: import_zod2.z.array(StorageEntrySchema),
1198
- sessionStorage: import_zod2.z.array(StorageEntrySchema),
1199
- cookies: import_zod2.z.array(StorageEntrySchema),
1200
- warnings: import_zod2.z.array(import_zod2.z.string()).optional()
1463
+ var PageStateSchema = import_zod3.z.object({
1464
+ forms: import_zod3.z.array(FormInfoSchema),
1465
+ localStorage: import_zod3.z.array(StorageEntrySchema),
1466
+ sessionStorage: import_zod3.z.array(StorageEntrySchema),
1467
+ cookies: import_zod3.z.array(StorageEntrySchema),
1468
+ warnings: import_zod3.z.array(import_zod3.z.string()).optional()
1201
1469
  });
1202
- var DomSnapshotSchema = import_zod2.z.object({
1470
+ var DomSnapshotSchema = import_zod3.z.object({
1203
1471
  format: InspectDomFormatSchema,
1204
- snapshot: import_zod2.z.unknown()
1472
+ snapshot: import_zod3.z.unknown()
1205
1473
  }).passthrough();
1206
- var InspectDomSnapshotInputSchema = import_zod2.z.object({
1207
- session_id: import_zod2.z.string().min(1),
1474
+ var InspectDomSnapshotInputSchema = import_zod3.z.object({
1475
+ session_id: import_zod3.z.string().min(1),
1208
1476
  format: InspectDomFormatSchema.default("ax"),
1209
1477
  consistency: InspectConsistencySchema.default("best_effort"),
1210
- interactive: import_zod2.z.boolean().default(false),
1211
- compact: import_zod2.z.boolean().default(false),
1478
+ interactive: import_zod3.z.boolean().default(false),
1479
+ compact: import_zod3.z.boolean().default(false),
1212
1480
  // Used primarily to bound large AX trees for LLM/agent consumption.
1213
1481
  // CLI passes this as a string, so coerce for convenience.
1214
- max_nodes: import_zod2.z.coerce.number().int().positive().max(5e4).optional(),
1215
- selector: import_zod2.z.string().min(1).optional(),
1482
+ max_nodes: import_zod3.z.coerce.number().int().positive().max(5e4).optional(),
1483
+ selector: import_zod3.z.string().min(1).optional(),
1216
1484
  target: TargetHintSchema.optional()
1217
1485
  });
1218
1486
  var InspectDomSnapshotOutputSchema = DomSnapshotSchema;
1219
- var DomDiffResultSchema = import_zod2.z.object({
1220
- added: import_zod2.z.array(import_zod2.z.string()),
1221
- removed: import_zod2.z.array(import_zod2.z.string()),
1222
- changed: import_zod2.z.array(import_zod2.z.string()),
1223
- summary: import_zod2.z.string()
1487
+ var DomDiffResultSchema = import_zod3.z.object({
1488
+ added: import_zod3.z.array(import_zod3.z.string()),
1489
+ removed: import_zod3.z.array(import_zod3.z.string()),
1490
+ changed: import_zod3.z.array(import_zod3.z.string()),
1491
+ summary: import_zod3.z.string()
1224
1492
  });
1225
1493
  var InspectDomDiffInputSchema = SessionIdSchema;
1226
1494
  var InspectDomDiffOutputSchema = DomDiffResultSchema;
1227
1495
  var InspectFindRoleInputSchema = SessionIdSchema.extend({
1228
- kind: import_zod2.z.literal("role"),
1229
- role: import_zod2.z.string().min(1),
1230
- name: import_zod2.z.string().min(1).optional(),
1496
+ kind: import_zod3.z.literal("role"),
1497
+ role: import_zod3.z.string().min(1),
1498
+ name: import_zod3.z.string().min(1).optional(),
1231
1499
  target: TargetHintSchema.optional()
1232
1500
  });
1233
1501
  var InspectFindTextInputSchema = SessionIdSchema.extend({
1234
- kind: import_zod2.z.literal("text"),
1235
- text: import_zod2.z.string().min(1),
1502
+ kind: import_zod3.z.literal("text"),
1503
+ text: import_zod3.z.string().min(1),
1236
1504
  target: TargetHintSchema.optional()
1237
1505
  });
1238
1506
  var InspectFindLabelInputSchema = SessionIdSchema.extend({
1239
- kind: import_zod2.z.literal("label"),
1240
- label: import_zod2.z.string().min(1),
1507
+ kind: import_zod3.z.literal("label"),
1508
+ label: import_zod3.z.string().min(1),
1241
1509
  target: TargetHintSchema.optional()
1242
1510
  });
1243
- var InspectFindInputSchema = import_zod2.z.discriminatedUnion("kind", [
1511
+ var InspectFindInputSchema = import_zod3.z.discriminatedUnion("kind", [
1244
1512
  InspectFindRoleInputSchema,
1245
1513
  InspectFindTextInputSchema,
1246
1514
  InspectFindLabelInputSchema
1247
1515
  ]);
1248
- var InspectFindMatchSchema = import_zod2.z.object({
1249
- ref: import_zod2.z.string(),
1250
- role: import_zod2.z.string().optional(),
1251
- name: import_zod2.z.string().optional()
1516
+ var InspectFindMatchSchema = import_zod3.z.object({
1517
+ ref: import_zod3.z.string(),
1518
+ role: import_zod3.z.string().optional(),
1519
+ name: import_zod3.z.string().optional()
1252
1520
  });
1253
- var InspectFindOutputSchema = import_zod2.z.object({
1254
- matches: import_zod2.z.array(InspectFindMatchSchema),
1255
- warnings: import_zod2.z.array(import_zod2.z.string()).optional()
1521
+ var InspectFindOutputSchema = import_zod3.z.object({
1522
+ matches: import_zod3.z.array(InspectFindMatchSchema),
1523
+ warnings: import_zod3.z.array(import_zod3.z.string()).optional()
1256
1524
  });
1257
1525
  var InspectPageStateInputSchema = SessionIdSchema.extend({
1258
1526
  target: TargetHintSchema.optional()
1259
1527
  });
1260
1528
  var InspectPageStateOutputSchema = PageStateSchema;
1261
- var InspectExtractContentFormatSchema = import_zod2.z.enum([
1529
+ var InspectExtractContentFormatSchema = import_zod3.z.enum([
1262
1530
  "markdown",
1263
1531
  "text",
1264
1532
  "article_json"
1265
1533
  ]);
1266
1534
  var InspectExtractContentInputSchema = SessionIdSchema.extend({
1267
1535
  format: InspectExtractContentFormatSchema.default("markdown"),
1268
- include_metadata: import_zod2.z.boolean().default(true),
1536
+ include_metadata: import_zod3.z.boolean().default(true),
1269
1537
  target: TargetHintSchema.optional()
1270
1538
  });
1271
- var InspectExtractContentOutputSchema = import_zod2.z.object({
1272
- content: import_zod2.z.string(),
1273
- title: import_zod2.z.string().optional(),
1274
- byline: import_zod2.z.string().optional(),
1275
- excerpt: import_zod2.z.string().optional(),
1276
- siteName: import_zod2.z.string().optional(),
1277
- warnings: import_zod2.z.array(import_zod2.z.string()).optional()
1539
+ var InspectExtractContentOutputSchema = import_zod3.z.object({
1540
+ content: import_zod3.z.string(),
1541
+ title: import_zod3.z.string().optional(),
1542
+ byline: import_zod3.z.string().optional(),
1543
+ excerpt: import_zod3.z.string().optional(),
1544
+ siteName: import_zod3.z.string().optional(),
1545
+ warnings: import_zod3.z.array(import_zod3.z.string()).optional()
1278
1546
  });
1279
1547
  var InspectConsoleListInputSchema = SessionIdSchema.extend({
1280
1548
  target: TargetHintSchema.optional()
1281
1549
  });
1282
- var ConsoleSourceLocationSchema = import_zod2.z.object({
1283
- url: import_zod2.z.string().optional(),
1550
+ var ConsoleSourceLocationSchema = import_zod3.z.object({
1551
+ url: import_zod3.z.string().optional(),
1284
1552
  // 1-based line/column for human readability.
1285
- line: import_zod2.z.number().int().positive().optional(),
1286
- column: import_zod2.z.number().int().positive().optional()
1553
+ line: import_zod3.z.number().int().positive().optional(),
1554
+ column: import_zod3.z.number().int().positive().optional()
1287
1555
  }).passthrough();
1288
- var ConsoleStackFrameSchema = import_zod2.z.object({
1289
- functionName: import_zod2.z.string().optional(),
1290
- url: import_zod2.z.string().optional(),
1556
+ var ConsoleStackFrameSchema = import_zod3.z.object({
1557
+ functionName: import_zod3.z.string().optional(),
1558
+ url: import_zod3.z.string().optional(),
1291
1559
  // 1-based line/column for human readability.
1292
- line: import_zod2.z.number().int().positive().optional(),
1293
- column: import_zod2.z.number().int().positive().optional()
1560
+ line: import_zod3.z.number().int().positive().optional(),
1561
+ column: import_zod3.z.number().int().positive().optional()
1294
1562
  }).passthrough();
1295
- var ConsoleRemoteObjectSchema = import_zod2.z.object({
1296
- type: import_zod2.z.string().optional(),
1297
- subtype: import_zod2.z.string().optional(),
1298
- description: import_zod2.z.string().optional(),
1299
- value: import_zod2.z.unknown().optional(),
1300
- unserializableValue: import_zod2.z.string().optional()
1563
+ var ConsoleRemoteObjectSchema = import_zod3.z.object({
1564
+ type: import_zod3.z.string().optional(),
1565
+ subtype: import_zod3.z.string().optional(),
1566
+ description: import_zod3.z.string().optional(),
1567
+ value: import_zod3.z.unknown().optional(),
1568
+ unserializableValue: import_zod3.z.string().optional()
1301
1569
  }).passthrough();
1302
- var ConsoleEntrySchema = import_zod2.z.object({
1303
- level: import_zod2.z.string().optional(),
1304
- text: import_zod2.z.string().optional(),
1305
- timestamp: import_zod2.z.string().datetime().optional(),
1570
+ var ConsoleEntrySchema = import_zod3.z.object({
1571
+ level: import_zod3.z.string().optional(),
1572
+ text: import_zod3.z.string().optional(),
1573
+ timestamp: import_zod3.z.string().datetime().optional(),
1306
1574
  source: ConsoleSourceLocationSchema.optional(),
1307
- stack: import_zod2.z.array(ConsoleStackFrameSchema).optional(),
1575
+ stack: import_zod3.z.array(ConsoleStackFrameSchema).optional(),
1308
1576
  exception: ConsoleRemoteObjectSchema.optional(),
1309
- args: import_zod2.z.array(ConsoleRemoteObjectSchema).optional()
1577
+ args: import_zod3.z.array(ConsoleRemoteObjectSchema).optional()
1310
1578
  }).passthrough();
1311
- var ConsoleListSchema = import_zod2.z.object({
1312
- entries: import_zod2.z.array(ConsoleEntrySchema)
1579
+ var ConsoleListSchema = import_zod3.z.object({
1580
+ entries: import_zod3.z.array(ConsoleEntrySchema)
1313
1581
  }).passthrough();
1314
1582
  var InspectConsoleListOutputSchema = ConsoleListSchema;
1315
- var ArtifactInfoSchema = import_zod2.z.object({
1316
- artifact_id: import_zod2.z.string(),
1317
- path: import_zod2.z.string(),
1318
- mime: import_zod2.z.string()
1583
+ var ArtifactInfoSchema = import_zod3.z.object({
1584
+ artifact_id: import_zod3.z.string(),
1585
+ path: import_zod3.z.string(),
1586
+ mime: import_zod3.z.string()
1319
1587
  });
1320
1588
  var InspectNetworkHarInputSchema = SessionIdSchema.extend({
1321
1589
  target: TargetHintSchema.optional()
1322
1590
  });
1323
1591
  var InspectNetworkHarOutputSchema = ArtifactInfoSchema;
1324
- var InspectEvaluateInputSchema = import_zod2.z.object({
1325
- session_id: import_zod2.z.string().min(1),
1326
- expression: import_zod2.z.string().min(1).optional(),
1592
+ var InspectEvaluateInputSchema = import_zod3.z.object({
1593
+ session_id: import_zod3.z.string().min(1),
1594
+ expression: import_zod3.z.string().min(1).optional(),
1327
1595
  target: TargetHintSchema.optional()
1328
1596
  });
1329
- var EvaluateResultSchema = import_zod2.z.object({
1330
- value: import_zod2.z.unknown().optional(),
1331
- exception: import_zod2.z.unknown().optional()
1597
+ var EvaluateResultSchema = import_zod3.z.object({
1598
+ value: import_zod3.z.unknown().optional(),
1599
+ exception: import_zod3.z.unknown().optional()
1332
1600
  }).passthrough();
1333
1601
  var InspectEvaluateOutputSchema = EvaluateResultSchema;
1334
1602
  var InspectPerformanceMetricsInputSchema = SessionIdSchema.extend({
1335
1603
  target: TargetHintSchema.optional()
1336
1604
  });
1337
- var PerformanceMetricSchema = import_zod2.z.object({
1338
- name: import_zod2.z.string(),
1339
- value: import_zod2.z.number().finite()
1605
+ var PerformanceMetricSchema = import_zod3.z.object({
1606
+ name: import_zod3.z.string(),
1607
+ value: import_zod3.z.number().finite()
1340
1608
  }).passthrough();
1341
- var PerformanceMetricsSchema = import_zod2.z.object({
1342
- metrics: import_zod2.z.array(PerformanceMetricSchema)
1609
+ var PerformanceMetricsSchema = import_zod3.z.object({
1610
+ metrics: import_zod3.z.array(PerformanceMetricSchema)
1343
1611
  }).passthrough();
1344
1612
  var InspectPerformanceMetricsOutputSchema = PerformanceMetricsSchema;
1345
- var ArtifactsScreenshotInputSchema = import_zod2.z.object({
1346
- session_id: import_zod2.z.string().min(1),
1347
- target: import_zod2.z.enum(["viewport", "full"]).default("viewport"),
1348
- fullPage: import_zod2.z.boolean().default(false),
1349
- selector: import_zod2.z.string().min(1).optional(),
1350
- format: import_zod2.z.enum(["png", "jpeg", "webp"]).default("png"),
1351
- quality: import_zod2.z.number().min(0).max(100).optional()
1613
+ var ArtifactsScreenshotInputSchema = import_zod3.z.object({
1614
+ session_id: import_zod3.z.string().min(1),
1615
+ target: import_zod3.z.enum(["viewport", "full"]).default("viewport"),
1616
+ fullPage: import_zod3.z.boolean().default(false),
1617
+ selector: import_zod3.z.string().min(1).optional(),
1618
+ format: import_zod3.z.enum(["png", "jpeg", "webp"]).default("png"),
1619
+ quality: import_zod3.z.number().min(0).max(100).optional()
1352
1620
  });
1353
1621
  var ArtifactsScreenshotOutputSchema = ArtifactInfoSchema;
1354
- var HealthCheckInputSchema = import_zod2.z.object({});
1355
- var HealthCheckOutputSchema = import_zod2.z.object({
1356
- started_at: import_zod2.z.string().min(1),
1357
- uptime_ms: import_zod2.z.number().finite().nonnegative(),
1358
- memory: import_zod2.z.object({
1359
- rss: import_zod2.z.number().finite().nonnegative(),
1360
- heapTotal: import_zod2.z.number().finite().nonnegative(),
1361
- heapUsed: import_zod2.z.number().finite().nonnegative(),
1362
- external: import_zod2.z.number().finite().nonnegative(),
1363
- arrayBuffers: import_zod2.z.number().finite().nonnegative().optional()
1622
+ var HealthCheckInputSchema = import_zod3.z.object({});
1623
+ var HealthCheckOutputSchema = import_zod3.z.object({
1624
+ started_at: import_zod3.z.string().min(1),
1625
+ uptime_ms: import_zod3.z.number().finite().nonnegative(),
1626
+ memory: import_zod3.z.object({
1627
+ rss: import_zod3.z.number().finite().nonnegative(),
1628
+ heapTotal: import_zod3.z.number().finite().nonnegative(),
1629
+ heapUsed: import_zod3.z.number().finite().nonnegative(),
1630
+ external: import_zod3.z.number().finite().nonnegative(),
1631
+ arrayBuffers: import_zod3.z.number().finite().nonnegative().optional()
1364
1632
  }).passthrough(),
1365
- sessions: import_zod2.z.object({
1366
- active: import_zod2.z.number().finite().nonnegative()
1633
+ sessions: import_zod3.z.object({
1634
+ active: import_zod3.z.number().finite().nonnegative()
1367
1635
  }).passthrough(),
1368
- extension: import_zod2.z.object({
1369
- connected: import_zod2.z.boolean(),
1370
- last_seen_at: import_zod2.z.string().min(1).optional()
1636
+ extension: import_zod3.z.object({
1637
+ connected: import_zod3.z.boolean(),
1638
+ last_seen_at: import_zod3.z.string().min(1).optional()
1371
1639
  }).passthrough()
1372
1640
  }).passthrough();
1373
- var DiagnosticsDoctorInputSchema = import_zod2.z.object({
1374
- session_id: import_zod2.z.string().min(1).optional(),
1641
+ var DiagnosticsDoctorInputSchema = import_zod3.z.object({
1642
+ session_id: import_zod3.z.string().min(1).optional(),
1375
1643
  caller: DiagnosticsRuntimeCallerSchema.optional()
1376
1644
  });
1377
1645
  var DiagnosticsDoctorOutputSchema = DiagnosticReportSchema;
@@ -1452,7 +1720,7 @@ var transitionSession = (state, event) => {
1452
1720
  throw new InvalidSessionTransition(state, event);
1453
1721
  };
1454
1722
  var shouldRetryDriveOp = (options) => {
1455
- return options.retryable && options.attempt === 0;
1723
+ return shouldRetryByPolicy(options);
1456
1724
  };
1457
1725
 
1458
1726
  // packages/core/src/session.ts
@@ -1579,39 +1847,30 @@ var SessionRegistry = class {
1579
1847
 
1580
1848
  // packages/core/src/routes/shared.ts
1581
1849
  var sendError = (res, status, error) => {
1582
- res.status(status).json({ ok: false, error });
1850
+ res.status(status).json({ ok: false, error: normalizeErrorInfo(error) });
1583
1851
  };
1584
1852
  var sendResult = (res, result) => {
1585
1853
  res.status(200).json({ ok: true, result });
1586
1854
  };
1587
- var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1855
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1588
1856
  var errorStatus = (code) => {
1589
- switch (code) {
1857
+ switch (normalizeErrorCode(code)) {
1590
1858
  case "INVALID_ARGUMENT":
1591
1859
  return 400;
1592
1860
  case "UNAUTHORIZED":
1593
1861
  return 401;
1594
1862
  case "FORBIDDEN":
1595
- case "PERMISSION_REQUIRED":
1596
- case "PERMISSION_PROMPT_TIMEOUT":
1597
- case "PERMISSION_DENIED":
1598
1863
  return 403;
1599
- case "SESSION_NOT_FOUND":
1600
- case "TAB_NOT_FOUND":
1601
- case "LOCATOR_NOT_FOUND":
1864
+ case "NOT_FOUND":
1602
1865
  return 404;
1603
- case "SESSION_CLOSED":
1604
1866
  case "FAILED_PRECONDITION":
1605
- case "DEBUGGER_IN_USE":
1606
1867
  return 409;
1607
- case "ATTACH_DENIED":
1608
- return 403;
1609
- case "NOT_SUPPORTED":
1610
1868
  case "NOT_IMPLEMENTED":
1611
1869
  return 501;
1612
- case "EXTENSION_DISCONNECTED":
1613
- case "INSPECT_UNAVAILABLE":
1870
+ case "UNAVAILABLE":
1614
1871
  return 503;
1872
+ case "CONFLICT":
1873
+ return 409;
1615
1874
  case "TIMEOUT":
1616
1875
  return 504;
1617
1876
  case "RATE_LIMITED":
@@ -1650,7 +1909,7 @@ var deriveHintFromTabs = (tabs) => {
1650
1909
 
1651
1910
  // packages/core/src/routes/session.ts
1652
1911
  var readSessionId = (body) => {
1653
- if (!isRecord(body)) {
1912
+ if (!isRecord2(body)) {
1654
1913
  return void 0;
1655
1914
  }
1656
1915
  const sessionId = body.session_id;
@@ -1664,7 +1923,7 @@ var createSessionRouter = (registry, options = {}) => {
1664
1923
  router.post("/create", (req, res) => {
1665
1924
  const body = req.body;
1666
1925
  if (body !== void 0) {
1667
- if (!isRecord(body)) {
1926
+ if (!isRecord2(body)) {
1668
1927
  return sendError(res, 400, {
1669
1928
  code: "INVALID_ARGUMENT",
1670
1929
  message: "Request body must be an object.",
@@ -1878,6 +2137,8 @@ var ExtensionBridge = class {
1878
2137
  this.socket = null;
1879
2138
  this.pending = /* @__PURE__ */ new Map();
1880
2139
  this.connected = false;
2140
+ this.capabilityNegotiated = false;
2141
+ this.capabilities = {};
1881
2142
  this.tabs = [];
1882
2143
  this.badMessageLogsRemaining = 3;
1883
2144
  this.heartbeatInterval = null;
@@ -1912,9 +2173,13 @@ var ExtensionBridge = class {
1912
2173
  connected: this.connected,
1913
2174
  lastSeenAt: this.lastSeenAt,
1914
2175
  version: this.version,
2176
+ protocolVersion: this.protocolVersion,
2177
+ protocolMismatch: this.protocolMismatch,
1915
2178
  coreHost: this.coreHost,
1916
2179
  corePort: this.corePort,
1917
2180
  corePortSource: this.corePortSource,
2181
+ capabilityNegotiated: this.capabilityNegotiated,
2182
+ capabilities: this.capabilities,
1918
2183
  tabs: this.tabs
1919
2184
  };
1920
2185
  }
@@ -1933,6 +2198,14 @@ var ExtensionBridge = class {
1933
2198
  };
1934
2199
  }
1935
2200
  async requestInternal(action, params, timeoutMs = 3e4) {
2201
+ if (this.protocolMismatch && action !== "drive.ping") {
2202
+ throw new ExtensionBridgeError(
2203
+ "FAILED_PRECONDITION",
2204
+ "Extension protocol version mismatch.",
2205
+ false,
2206
+ this.protocolMismatch
2207
+ );
2208
+ }
1936
2209
  if (!this.socket || this.socket.readyState !== import_ws.WebSocket.OPEN) {
1937
2210
  throw new ExtensionBridgeError(
1938
2211
  "EXTENSION_DISCONNECTED",
@@ -1940,6 +2213,35 @@ var ExtensionBridge = class {
1940
2213
  true
1941
2214
  );
1942
2215
  }
2216
+ if (action !== "drive.ping") {
2217
+ if (!this.capabilityNegotiated) {
2218
+ throw new ExtensionBridgeError(
2219
+ "FAILED_PRECONDITION",
2220
+ "Capability negotiation has not completed yet.",
2221
+ true,
2222
+ { action, expected: "drive.hello.capabilities" }
2223
+ );
2224
+ }
2225
+ if (this.capabilityNegotiationFailure) {
2226
+ throw new ExtensionBridgeError(
2227
+ "FAILED_PRECONDITION",
2228
+ "Capability negotiation failed: extension hello payload is missing capabilities.",
2229
+ false,
2230
+ {
2231
+ action,
2232
+ ...this.capabilityNegotiationFailure
2233
+ }
2234
+ );
2235
+ }
2236
+ if (this.capabilities[action] !== true) {
2237
+ throw new ExtensionBridgeError(
2238
+ "NOT_IMPLEMENTED",
2239
+ `Extension does not advertise capability for ${action}.`,
2240
+ false,
2241
+ { action }
2242
+ );
2243
+ }
2244
+ }
1943
2245
  const id = (0, import_crypto2.randomUUID)();
1944
2246
  const request = typeof action === "string" && action.startsWith("debugger.") ? {
1945
2247
  id,
@@ -2051,9 +2353,14 @@ var ExtensionBridge = class {
2051
2353
  this.connected = false;
2052
2354
  this.socket = null;
2053
2355
  this.version = void 0;
2356
+ this.protocolVersion = void 0;
2357
+ this.protocolMismatch = void 0;
2054
2358
  this.coreHost = void 0;
2055
2359
  this.corePort = void 0;
2056
2360
  this.corePortSource = void 0;
2361
+ this.capabilityNegotiated = false;
2362
+ this.capabilityNegotiationFailure = void 0;
2363
+ this.capabilities = {};
2057
2364
  this.lastSeenAt = (/* @__PURE__ */ new Date()).toISOString();
2058
2365
  this.applyDriveDisconnected();
2059
2366
  for (const [id, pending] of this.pending.entries()) {
@@ -2110,6 +2417,19 @@ var ExtensionBridge = class {
2110
2417
  if (typeof params?.version === "string") {
2111
2418
  this.version = params.version;
2112
2419
  }
2420
+ if (typeof params?.protocol_version === "string") {
2421
+ this.protocolVersion = params.protocol_version;
2422
+ } else {
2423
+ this.protocolVersion = void 0;
2424
+ }
2425
+ if (this.protocolVersion && this.protocolVersion !== DRIVE_WS_PROTOCOL_VERSION) {
2426
+ this.protocolMismatch = {
2427
+ expected: DRIVE_WS_PROTOCOL_VERSION,
2428
+ received: this.protocolVersion
2429
+ };
2430
+ } else {
2431
+ this.protocolMismatch = void 0;
2432
+ }
2113
2433
  if (typeof params?.core_host === "string") {
2114
2434
  this.coreHost = params.core_host;
2115
2435
  }
@@ -2119,6 +2439,23 @@ var ExtensionBridge = class {
2119
2439
  if (params?.core_port_source === "default" || params?.core_port_source === "storage") {
2120
2440
  this.corePortSource = params.core_port_source;
2121
2441
  }
2442
+ const capabilities = params?.capabilities;
2443
+ if (capabilities && typeof capabilities === "object") {
2444
+ this.capabilities = Object.fromEntries(
2445
+ Object.entries(capabilities).filter(
2446
+ ([name, supported]) => typeof name === "string" && typeof supported === "boolean"
2447
+ )
2448
+ );
2449
+ this.capabilityNegotiated = true;
2450
+ this.capabilityNegotiationFailure = void 0;
2451
+ } else {
2452
+ this.capabilities = {};
2453
+ this.capabilityNegotiated = true;
2454
+ this.capabilityNegotiationFailure = {
2455
+ reason: "missing_capabilities",
2456
+ expected: "drive.hello.capabilities"
2457
+ };
2458
+ }
2122
2459
  }
2123
2460
  }
2124
2461
  if (typeof message.action === "string" && message.action.startsWith("debugger.")) {
@@ -2177,10 +2514,80 @@ var toDriveError = (error) => ({
2177
2514
  code: error.code,
2178
2515
  message: error.message,
2179
2516
  retryable: error.retryable,
2517
+ retry: {
2518
+ retryable: error.retryable,
2519
+ reason: String(error.code).toLowerCase(),
2520
+ max_attempts: 1
2521
+ },
2180
2522
  ...error.details ? { details: error.details } : {}
2181
2523
  });
2182
2524
 
2183
2525
  // packages/core/src/drive.ts
2526
+ var LOOPBACK_NAVIGATION_PREFLIGHT_TIMEOUT_MS = 1200;
2527
+ var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1"]);
2528
+ var isLikelyUnreachableLoopbackError = (message) => {
2529
+ const normalized = message.toLowerCase();
2530
+ return normalized.includes("connection refused") || normalized.includes("econnrefused") || normalized.includes("err_connection_refused") || normalized.includes("enotfound") || normalized.includes("err_name_not_resolved") || normalized.includes("eai_again") || normalized.includes("ehostunreach") || normalized.includes("enetunreach");
2531
+ };
2532
+ var preflightLoopbackNavigation = async (action, params) => {
2533
+ if (action !== "drive.navigate") {
2534
+ return void 0;
2535
+ }
2536
+ const urlValue = params?.url;
2537
+ if (typeof urlValue !== "string" || urlValue.trim().length === 0) {
2538
+ return void 0;
2539
+ }
2540
+ let parsed;
2541
+ try {
2542
+ parsed = new URL(urlValue);
2543
+ } catch {
2544
+ return void 0;
2545
+ }
2546
+ if (!["http:", "https:"].includes(parsed.protocol)) {
2547
+ return void 0;
2548
+ }
2549
+ if (!LOOPBACK_HOSTS.has(parsed.hostname.toLowerCase())) {
2550
+ return void 0;
2551
+ }
2552
+ const controller = new AbortController();
2553
+ const timeout = setTimeout(() => {
2554
+ controller.abort();
2555
+ }, LOOPBACK_NAVIGATION_PREFLIGHT_TIMEOUT_MS);
2556
+ try {
2557
+ await fetch(urlValue, {
2558
+ method: "HEAD",
2559
+ redirect: "manual",
2560
+ signal: controller.signal
2561
+ });
2562
+ return void 0;
2563
+ } catch (error) {
2564
+ if (error instanceof Error && error.name === "AbortError") {
2565
+ return void 0;
2566
+ }
2567
+ const message = error instanceof Error ? error.message : "Navigation preflight failed.";
2568
+ if (!isLikelyUnreachableLoopbackError(message)) {
2569
+ return void 0;
2570
+ }
2571
+ return {
2572
+ code: "NAVIGATION_FAILED",
2573
+ message: `Navigation target is unreachable: ${urlValue}`,
2574
+ retryable: true,
2575
+ retry: {
2576
+ retryable: true,
2577
+ reason: "loopback_target_unreachable",
2578
+ retry_after_ms: 250,
2579
+ max_attempts: 1
2580
+ },
2581
+ details: {
2582
+ url: urlValue,
2583
+ preflight: "loopback_head",
2584
+ reason: message
2585
+ }
2586
+ };
2587
+ } finally {
2588
+ clearTimeout(timeout);
2589
+ }
2590
+ };
2184
2591
  var DriveMutex = class {
2185
2592
  constructor() {
2186
2593
  this.tail = Promise.resolve();
@@ -2242,8 +2649,32 @@ var DriveController = class {
2242
2649
  error: errorInfo
2243
2650
  };
2244
2651
  }
2245
- if (this.bridge.isConnected()) {
2246
- this.ensureDriveReady(sessionId);
2652
+ if (!this.bridge.isConnected()) {
2653
+ const errorInfo = {
2654
+ code: "EXTENSION_DISCONNECTED",
2655
+ message: "Extension is not connected. Open Chrome with the Browser Bridge extension enabled, then retry.",
2656
+ retryable: true,
2657
+ retry: {
2658
+ retryable: true,
2659
+ reason: "extension_disconnected",
2660
+ retry_after_ms: 300,
2661
+ max_attempts: 1
2662
+ },
2663
+ details: {
2664
+ next_step: "Ensure Chrome is running and extension.connected=true."
2665
+ }
2666
+ };
2667
+ this.recordError(errorInfo);
2668
+ return { ok: false, error: errorInfo };
2669
+ }
2670
+ this.ensureDriveReady(sessionId);
2671
+ const preflightError = await preflightLoopbackNavigation(action, params);
2672
+ if (preflightError) {
2673
+ this.recordError(preflightError);
2674
+ return {
2675
+ ok: false,
2676
+ error: preflightError
2677
+ };
2247
2678
  }
2248
2679
  let attempt = 0;
2249
2680
  while (true) {
@@ -2263,9 +2694,18 @@ var DriveController = class {
2263
2694
  const errorInfo = response.error ?? {
2264
2695
  code: "UNKNOWN",
2265
2696
  message: "Drive operation failed.",
2266
- retryable: false
2697
+ retryable: false,
2698
+ retry: {
2699
+ retryable: false,
2700
+ reason: "drive_response_error",
2701
+ max_attempts: 1
2702
+ }
2267
2703
  };
2268
- if (shouldRetryDriveOp({ attempt, retryable: errorInfo.retryable })) {
2704
+ if (shouldRetryDriveOp({
2705
+ attempt,
2706
+ retryable: errorInfo.retryable,
2707
+ retry: errorInfo.retry
2708
+ })) {
2269
2709
  attempt += 1;
2270
2710
  continue;
2271
2711
  }
@@ -2277,7 +2717,11 @@ var DriveController = class {
2277
2717
  this.applyDriveDisconnected(sessionId);
2278
2718
  }
2279
2719
  const errorInfo2 = toDriveError(error);
2280
- if (shouldRetryDriveOp({ attempt, retryable: errorInfo2.retryable })) {
2720
+ if (shouldRetryDriveOp({
2721
+ attempt,
2722
+ retryable: errorInfo2.retryable,
2723
+ retry: errorInfo2.retry
2724
+ })) {
2281
2725
  attempt += 1;
2282
2726
  continue;
2283
2727
  }
@@ -4225,7 +4669,7 @@ var sendArtifactsError = (res, code, message, details, retryable = false) => {
4225
4669
  var registerArtifactsRoutes = (router, options = {}) => {
4226
4670
  const inspect = options.inspectService ?? (options.registry ? createInspectService({ registry: options.registry }) : void 0);
4227
4671
  router.post("/artifacts/screenshot", async (req, res) => {
4228
- if (!isRecord(req.body)) {
4672
+ if (!isRecord2(req.body)) {
4229
4673
  sendArtifactsError(
4230
4674
  res,
4231
4675
  "INVALID_ARGUMENT",
@@ -4310,6 +4754,13 @@ var endpointLabel = (endpoint) => {
4310
4754
  }
4311
4755
  return "unknown";
4312
4756
  };
4757
+ var readCapability = (capabilities, name) => {
4758
+ if (!capabilities) {
4759
+ return void 0;
4760
+ }
4761
+ const candidate = capabilities[name];
4762
+ return typeof candidate === "boolean" ? candidate : void 0;
4763
+ };
4313
4764
  var hasEndpoint = (endpoint) => Boolean(
4314
4765
  endpoint && typeof endpoint.host === "string" && endpoint.host.length > 0 && typeof endpoint.port === "number" && Number.isFinite(endpoint.port)
4315
4766
  );
@@ -4388,6 +4839,23 @@ var buildDiagnosticReport = (sessionId, context = {}) => {
4388
4839
  }
4389
4840
  });
4390
4841
  }
4842
+ if (callerEndpoint?.metadataPath && coreEndpoint?.metadataPath) {
4843
+ const matches = callerEndpoint.metadataPath === coreEndpoint.metadataPath;
4844
+ checks.push({
4845
+ name: "runtime.caller.metadata_path_match",
4846
+ ok: matches,
4847
+ message: matches ? "Caller metadata path matches the active core runtime metadata path." : "Caller metadata path differs from core runtime metadata path (shared core across worktrees).",
4848
+ details: {
4849
+ caller_metadata_path: callerEndpoint.metadataPath,
4850
+ core_metadata_path: coreEndpoint.metadataPath
4851
+ }
4852
+ });
4853
+ if (!matches) {
4854
+ warnings.push(
4855
+ "CLI is talking to a core process started from a different worktree metadata path. If daemon auto-start fails, retry with --no-daemon or enable isolated mode."
4856
+ );
4857
+ }
4858
+ }
4391
4859
  if (extensionConnected && hasEndpoint(coreEndpoint) && hasEndpoint(extensionEndpoint)) {
4392
4860
  const matches = coreEndpoint.host === extensionEndpoint.host && coreEndpoint.port === extensionEndpoint.port;
4393
4861
  checks.push({
@@ -4405,6 +4873,49 @@ var buildDiagnosticReport = (sessionId, context = {}) => {
4405
4873
  }
4406
4874
  });
4407
4875
  }
4876
+ if (extensionConnected) {
4877
+ const capabilityNegotiated = context.runtime?.extension?.capabilityNegotiated ?? false;
4878
+ const capabilities = context.runtime?.extension?.capabilities;
4879
+ const driveNavigateCapability = readCapability(
4880
+ capabilities,
4881
+ "drive.navigate"
4882
+ );
4883
+ const inspectAttachCapability = readCapability(
4884
+ capabilities,
4885
+ "debugger.attach"
4886
+ );
4887
+ const inspectCommandCapability = readCapability(
4888
+ capabilities,
4889
+ "debugger.command"
4890
+ );
4891
+ checks.push({
4892
+ name: "runtime.extension.capability_negotiated",
4893
+ ok: capabilityNegotiated,
4894
+ message: capabilityNegotiated ? "Extension capability negotiation completed." : "Extension capability negotiation is incomplete; action availability may be stale."
4895
+ });
4896
+ checks.push({
4897
+ name: "drive.capability",
4898
+ ok: driveNavigateCapability !== false,
4899
+ message: driveNavigateCapability === false ? "Drive actions are disabled by extension capability negotiation." : "Drive actions are available.",
4900
+ details: driveNavigateCapability === void 0 ? { capability: "drive.navigate", state: "unknown" } : { capability: "drive.navigate", enabled: driveNavigateCapability }
4901
+ });
4902
+ const inspectEnabled = inspectAttachCapability === true && inspectCommandCapability === true;
4903
+ checks.push({
4904
+ name: "inspect.capability",
4905
+ ok: capabilityNegotiated && inspectEnabled,
4906
+ message: capabilityNegotiated && inspectEnabled ? "Inspect debugger capability is enabled." : capabilityNegotiated ? "Inspect debugger capability is disabled in extension options." : "Inspect capability is unknown until extension capability negotiation completes.",
4907
+ details: {
4908
+ required_capabilities: ["debugger.attach", "debugger.command"],
4909
+ debugger_attach: inspectAttachCapability,
4910
+ debugger_command: inspectCommandCapability
4911
+ }
4912
+ });
4913
+ if (capabilityNegotiated && !inspectEnabled) {
4914
+ warnings.push(
4915
+ "Inspect commands require debugger capability. Enable debugger-based inspect in extension options to use inspect.* routes."
4916
+ );
4917
+ }
4918
+ }
4408
4919
  const callerVersion = context.runtime?.caller?.process?.version;
4409
4920
  const extensionVersion = extensionConnected ? context.runtime?.extension?.version : void 0;
4410
4921
  if (callerVersion && extensionVersion) {
@@ -4527,6 +5038,9 @@ var buildDiagnosticReport = (sessionId, context = {}) => {
4527
5038
  } : void 0,
4528
5039
  extension: context.runtime.extension ? {
4529
5040
  version: context.runtime.extension.version,
5041
+ protocol_version: context.runtime.extension.protocolVersion,
5042
+ capability_negotiated: context.runtime.extension.capabilityNegotiated,
5043
+ capabilities: context.runtime.extension.capabilities,
4530
5044
  endpoint: toRuntimeEndpoint(context.runtime.extension.endpoint),
4531
5045
  port_source: context.runtime.extension.portSource
4532
5046
  } : void 0
@@ -4540,9 +5054,9 @@ var PROCESS_STARTED_AT = new Date(
4540
5054
  Date.now() - Math.floor(process.uptime() * 1e3)
4541
5055
  ).toISOString();
4542
5056
  var registerDiagnosticsRoutes = (router, options = {}) => {
4543
- router.post("/health_check", (req, res) => {
5057
+ const handleHealthCheck = (req, res) => {
4544
5058
  const body = req.body ?? {};
4545
- if (!isRecord(body)) {
5059
+ if (!isRecord2(body)) {
4546
5060
  sendError(res, 400, {
4547
5061
  code: "INVALID_ARGUMENT",
4548
5062
  message: "Request body must be an object.",
@@ -4573,10 +5087,12 @@ var registerDiagnosticsRoutes = (router, options = {}) => {
4573
5087
  ...extensionStatus?.lastSeenAt ? { last_seen_at: extensionStatus.lastSeenAt } : {}
4574
5088
  }
4575
5089
  });
4576
- });
5090
+ };
5091
+ router.post("/health/check", handleHealthCheck);
5092
+ router.post("/health_check", handleHealthCheck);
4577
5093
  router.post("/diagnostics/doctor", (req, res) => {
4578
5094
  const body = req.body ?? {};
4579
- if (!isRecord(body)) {
5095
+ if (!isRecord2(body)) {
4580
5096
  sendError(res, 400, {
4581
5097
  code: "INVALID_ARGUMENT",
4582
5098
  message: "Request body must be an object.",
@@ -4675,6 +5191,9 @@ var registerDiagnosticsRoutes = (router, options = {}) => {
4675
5191
  if (status.connected) {
4676
5192
  context.runtime.extension = {
4677
5193
  version: status.version,
5194
+ protocolVersion: status.protocolVersion,
5195
+ capabilityNegotiated: status.capabilityNegotiated,
5196
+ capabilities: status.capabilities,
4678
5197
  endpoint: status.coreHost && typeof status.corePort === "number" ? {
4679
5198
  host: status.coreHost,
4680
5199
  port: status.corePort,
@@ -4762,6 +5281,53 @@ var parseBody = (schema, body) => {
4762
5281
  }
4763
5282
  };
4764
5283
  };
5284
+ var makeNavigateHandler = (schema, drive, registry) => {
5285
+ return (req, res) => {
5286
+ const parsed = parseBody(schema, req.body ?? {});
5287
+ if (parsed.error) {
5288
+ sendError(res, errorStatus("INVALID_ARGUMENT"), {
5289
+ code: "INVALID_ARGUMENT",
5290
+ message: parsed.error.message,
5291
+ retryable: false,
5292
+ ...parsed.error.details ? { details: parsed.error.details } : {}
5293
+ });
5294
+ return;
5295
+ }
5296
+ const body = parsed.data;
5297
+ const parsedSessionId = body.session_id;
5298
+ const sessionId = typeof parsedSessionId === "string" && parsedSessionId.length > 0 ? parsedSessionId : registry.create().id;
5299
+ const params = { ...body };
5300
+ delete params.session_id;
5301
+ void drive.execute(
5302
+ sessionId,
5303
+ "drive.navigate",
5304
+ params
5305
+ ).then((result) => {
5306
+ if (result.ok) {
5307
+ const payload = result.result && typeof result.result === "object" ? {
5308
+ ...result.result,
5309
+ session_id: sessionId
5310
+ } : {
5311
+ ok: true,
5312
+ session_id: sessionId
5313
+ };
5314
+ sendResult(res, payload);
5315
+ return;
5316
+ }
5317
+ sendError(res, errorStatus(result.error.code), result.error);
5318
+ }).catch((error) => {
5319
+ console.error("Drive execute failed:", error);
5320
+ sendError(res, errorStatus("INTERNAL"), {
5321
+ code: "INTERNAL",
5322
+ message: "Unexpected error while executing drive action.",
5323
+ retryable: false,
5324
+ details: {
5325
+ hint: error instanceof Error ? error.message : "Unknown error."
5326
+ }
5327
+ });
5328
+ });
5329
+ };
5330
+ };
4765
5331
  var makeHandler = (action, schema, drive, options = {}) => {
4766
5332
  return (req, res) => {
4767
5333
  const parsed = parseBody(schema, req.body ?? {});
@@ -4776,6 +5342,17 @@ var makeHandler = (action, schema, drive, options = {}) => {
4776
5342
  }
4777
5343
  const body = parsed.data;
4778
5344
  const sessionId = body.session_id;
5345
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
5346
+ sendError(res, errorStatus("INVALID_ARGUMENT"), {
5347
+ code: "INVALID_ARGUMENT",
5348
+ message: "session_id is required",
5349
+ retryable: false,
5350
+ details: {
5351
+ field: "session_id"
5352
+ }
5353
+ });
5354
+ return;
5355
+ }
4779
5356
  const params = { ...body };
4780
5357
  delete params.session_id;
4781
5358
  const timeoutMs = options.timeoutFromParams ? options.timeoutFromParams(params) : void 0;
@@ -4799,7 +5376,7 @@ var makeHandler = (action, schema, drive, options = {}) => {
4799
5376
  });
4800
5377
  };
4801
5378
  };
4802
- var makeDialogHandler = (action, schema, drive) => {
5379
+ var makeDialogHandler = (action, schema, drive, aliasName) => {
4803
5380
  return (req, res) => {
4804
5381
  const parsed = parseBody(schema, req.body ?? {});
4805
5382
  if (parsed.error) {
@@ -4816,8 +5393,20 @@ var makeDialogHandler = (action, schema, drive) => {
4816
5393
  const params = { ...rest, action };
4817
5394
  void drive.execute(sessionId, "drive.handle_dialog", params).then((result) => {
4818
5395
  if (result.ok) {
4819
- const payload = result.result === void 0 ? { ok: true } : result.result;
4820
- sendResult(res, payload);
5396
+ const basePayload = result.result === void 0 ? { ok: true } : result.result;
5397
+ if (!aliasName || typeof basePayload !== "object" || basePayload === null) {
5398
+ sendResult(res, basePayload);
5399
+ return;
5400
+ }
5401
+ const warning = `${aliasName} is deprecated; use drive.handle_dialog.`;
5402
+ const payload = basePayload;
5403
+ const warnings = Array.isArray(payload.warnings) ? payload.warnings.filter(
5404
+ (item) => typeof item === "string"
5405
+ ) : [];
5406
+ sendResult(res, {
5407
+ ...payload,
5408
+ warnings: warnings.includes(warning) ? warnings : [...warnings, warning]
5409
+ });
4821
5410
  return;
4822
5411
  }
4823
5412
  sendError(res, errorStatus(result.error.code), result.error);
@@ -4835,10 +5424,10 @@ var makeDialogHandler = (action, schema, drive) => {
4835
5424
  };
4836
5425
  };
4837
5426
  var registerDriveRoutes = (router, options) => {
4838
- const { drive } = options;
5427
+ const { drive, registry } = options;
4839
5428
  router.post(
4840
5429
  "/drive/navigate",
4841
- makeHandler("drive.navigate", DriveNavigateInputSchema, drive)
5430
+ makeNavigateHandler(DriveNavigateInputSchema, drive, registry)
4842
5431
  );
4843
5432
  router.post(
4844
5433
  "/drive/go_back",
@@ -4848,14 +5437,6 @@ var registerDriveRoutes = (router, options) => {
4848
5437
  "/drive/go_forward",
4849
5438
  makeHandler("drive.go_forward", DriveGoForwardInputSchema, drive)
4850
5439
  );
4851
- router.post(
4852
- "/drive/back",
4853
- makeHandler("drive.back", DriveBackInputSchema, drive)
4854
- );
4855
- router.post(
4856
- "/drive/forward",
4857
- makeHandler("drive.forward", DriveForwardInputSchema, drive)
4858
- );
4859
5440
  router.post(
4860
5441
  "/drive/click",
4861
5442
  makeHandler("drive.click", DriveClickInputSchema, drive)
@@ -4886,11 +5467,16 @@ var registerDriveRoutes = (router, options) => {
4886
5467
  );
4887
5468
  router.post(
4888
5469
  "/dialog/accept",
4889
- makeDialogHandler("accept", DialogAcceptInputSchema, drive)
5470
+ makeDialogHandler("accept", DialogAcceptInputSchema, drive, "dialog.accept")
4890
5471
  );
4891
5472
  router.post(
4892
5473
  "/dialog/dismiss",
4893
- makeDialogHandler("dismiss", DialogDismissInputSchema, drive)
5474
+ makeDialogHandler(
5475
+ "dismiss",
5476
+ DialogDismissInputSchema,
5477
+ drive,
5478
+ "dialog.dismiss"
5479
+ )
4894
5480
  );
4895
5481
  router.post(
4896
5482
  "/drive/key",
@@ -5480,6 +6066,29 @@ var createCoreServer = (options = {}) => {
5480
6066
  });
5481
6067
  const recoveryTracker = new RecoveryTracker();
5482
6068
  app.use(import_express2.default.json({ limit: "1mb" }));
6069
+ app.use((req, res, next) => {
6070
+ res.setHeader(HTTP_CONTRACT_VERSION_HEADER, HTTP_CONTRACT_VERSION);
6071
+ const mismatch = resolveContractVersionMismatch(
6072
+ req.header(HTTP_CONTRACT_VERSION_HEADER) ?? void 0
6073
+ );
6074
+ if (mismatch) {
6075
+ res.status(409).json({
6076
+ ok: false,
6077
+ error: {
6078
+ code: "FAILED_PRECONDITION",
6079
+ message: "HTTP contract version mismatch between client and core server.",
6080
+ retryable: false,
6081
+ details: {
6082
+ header: HTTP_CONTRACT_VERSION_HEADER,
6083
+ expected: mismatch.expected,
6084
+ received: mismatch.received
6085
+ }
6086
+ }
6087
+ });
6088
+ return;
6089
+ }
6090
+ next();
6091
+ });
5483
6092
  if (logger) {
5484
6093
  app.use((req, res, next) => {
5485
6094
  const startedAt = process.hrtime.bigint();
@@ -5495,9 +6104,11 @@ var createCoreServer = (options = {}) => {
5495
6104
  next();
5496
6105
  });
5497
6106
  }
5498
- app.get("/health", (_req, res) => {
6107
+ const sendHealthOk = (_req, res) => {
5499
6108
  res.status(200).json({ ok: true });
5500
- });
6109
+ };
6110
+ app.post("/health", sendHealthOk);
6111
+ app.get("/health", sendHealthOk);
5501
6112
  app.use(
5502
6113
  "/session",
5503
6114
  createSessionRouter(registry, {
@@ -5506,7 +6117,7 @@ var createCoreServer = (options = {}) => {
5506
6117
  recordRecovery: (attempt) => recoveryTracker.record(attempt)
5507
6118
  })
5508
6119
  );
5509
- registerDriveRoutes(app, { drive });
6120
+ registerDriveRoutes(app, { drive, registry });
5510
6121
  registerInspectRoutes(app, {
5511
6122
  registry,
5512
6123
  extensionBridge,
@@ -5734,6 +6345,12 @@ var toReadinessErrorEnvelope = (error, baseUrl) => ({
5734
6345
  code: "UNAVAILABLE",
5735
6346
  message: error instanceof Error ? `Core not ready at ${baseUrl}: ${error.message}` : `Core not ready at ${baseUrl}.`,
5736
6347
  retryable: true,
6348
+ retry: {
6349
+ retryable: true,
6350
+ reason: "core_not_ready",
6351
+ retry_after_ms: 250,
6352
+ max_attempts: 1
6353
+ },
5737
6354
  details: {
5738
6355
  base_url: baseUrl
5739
6356
  }
@@ -5811,7 +6428,8 @@ startCoreServer({ ${startOptions.join(
5811
6428
  const response = await fetchImpl(`${readiness.baseUrl}${requestPath}`, {
5812
6429
  method: "POST",
5813
6430
  headers: {
5814
- "content-type": "application/json"
6431
+ "content-type": "application/json",
6432
+ [HTTP_CONTRACT_VERSION_HEADER]: HTTP_CONTRACT_VERSION
5815
6433
  },
5816
6434
  body: body === void 0 ? void 0 : JSON.stringify(body),
5817
6435
  signal: controller.signal
@@ -5924,6 +6542,22 @@ var toInternalErrorEnvelope = (error) => ({
5924
6542
  }
5925
6543
  });
5926
6544
  var envelope = (schema) => successEnvelopeSchema(schema);
6545
+ var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
6546
+ var addDeprecatedAliasWarning = (envelopeResult, deprecationAlias) => {
6547
+ if (!deprecationAlias || !envelopeResult.ok || typeof envelopeResult.result !== "object" || !envelopeResult.result) {
6548
+ return envelopeResult;
6549
+ }
6550
+ const warning = `${deprecationAlias.alias} is deprecated; use ${deprecationAlias.replacement}.`;
6551
+ const result = envelopeResult.result;
6552
+ const existingWarnings = Array.isArray(result.warnings) ? result.warnings.filter((item) => typeof item === "string") : [];
6553
+ return {
6554
+ ok: true,
6555
+ result: {
6556
+ ...result,
6557
+ warnings: existingWarnings.includes(warning) ? existingWarnings : [...existingWarnings, warning]
6558
+ }
6559
+ };
6560
+ };
5927
6561
  var TOOL_DEFINITIONS = [
5928
6562
  {
5929
6563
  name: "session.create",
@@ -5999,20 +6633,28 @@ var TOOL_DEFINITIONS = [
5999
6633
  name: "drive.back",
6000
6634
  config: {
6001
6635
  title: "Drive Back",
6002
- description: "Go back in browser history.",
6003
- inputSchema: DriveBackInputSchema,
6004
- outputSchema: envelope(DriveBackOutputSchema),
6005
- corePath: "/drive/back"
6636
+ description: "Deprecated alias for drive.go_back.",
6637
+ inputSchema: DriveGoBackInputSchema,
6638
+ outputSchema: envelope(DriveGoBackOutputSchema),
6639
+ corePath: "/drive/go_back",
6640
+ deprecationAlias: {
6641
+ alias: "drive.back",
6642
+ replacement: "drive.go_back"
6643
+ }
6006
6644
  }
6007
6645
  },
6008
6646
  {
6009
6647
  name: "drive.forward",
6010
6648
  config: {
6011
6649
  title: "Drive Forward",
6012
- description: "Go forward in browser history.",
6013
- inputSchema: DriveForwardInputSchema,
6014
- outputSchema: envelope(DriveForwardOutputSchema),
6015
- corePath: "/drive/forward"
6650
+ description: "Deprecated alias for drive.go_forward.",
6651
+ inputSchema: DriveGoForwardInputSchema,
6652
+ outputSchema: envelope(DriveGoForwardOutputSchema),
6653
+ corePath: "/drive/go_forward",
6654
+ deprecationAlias: {
6655
+ alias: "drive.forward",
6656
+ replacement: "drive.go_forward"
6657
+ }
6016
6658
  }
6017
6659
  },
6018
6660
  {
@@ -6089,20 +6731,30 @@ var TOOL_DEFINITIONS = [
6089
6731
  name: "dialog.accept",
6090
6732
  config: {
6091
6733
  title: "Dialog Accept",
6092
- description: "Accept a JavaScript dialog.",
6734
+ description: "Deprecated alias for drive.handle_dialog (action=accept).",
6093
6735
  inputSchema: DialogAcceptInputSchema,
6094
6736
  outputSchema: envelope(DialogAcceptOutputSchema),
6095
- corePath: "/dialog/accept"
6737
+ corePath: "/drive/handle_dialog",
6738
+ deprecationAlias: {
6739
+ alias: "dialog.accept",
6740
+ replacement: "drive.handle_dialog"
6741
+ },
6742
+ transformInput: (args) => isRecord3(args) ? { ...args, action: "accept" } : args
6096
6743
  }
6097
6744
  },
6098
6745
  {
6099
6746
  name: "dialog.dismiss",
6100
6747
  config: {
6101
6748
  title: "Dialog Dismiss",
6102
- description: "Dismiss a JavaScript dialog.",
6749
+ description: "Deprecated alias for drive.handle_dialog (action=dismiss).",
6103
6750
  inputSchema: DialogDismissInputSchema,
6104
6751
  outputSchema: envelope(DialogDismissOutputSchema),
6105
- corePath: "/dialog/dismiss"
6752
+ corePath: "/drive/handle_dialog",
6753
+ deprecationAlias: {
6754
+ alias: "dialog.dismiss",
6755
+ replacement: "drive.handle_dialog"
6756
+ },
6757
+ transformInput: (args) => isRecord3(args) ? { ...args, action: "dismiss" } : args
6106
6758
  }
6107
6759
  },
6108
6760
  {
@@ -6282,7 +6934,7 @@ var TOOL_DEFINITIONS = [
6282
6934
  description: "Check server health including uptime, memory usage, active session count, and extension connection status.",
6283
6935
  inputSchema: HealthCheckInputSchema,
6284
6936
  outputSchema: envelope(HealthCheckOutputSchema),
6285
- corePath: "/health_check"
6937
+ corePath: "/health/check"
6286
6938
  }
6287
6939
  },
6288
6940
  {
@@ -6296,13 +6948,18 @@ var TOOL_DEFINITIONS = [
6296
6948
  }
6297
6949
  }
6298
6950
  ];
6299
- var createToolHandler = (clientProvider, corePath) => {
6951
+ var createToolHandler = (clientProvider, corePath, deprecationAlias, transformInput) => {
6300
6952
  return (async (args, _extra) => {
6301
6953
  void _extra;
6302
6954
  try {
6303
6955
  const client = typeof clientProvider === "function" ? await clientProvider() : clientProvider;
6304
- const envelopeResult = await client.post(corePath, args);
6305
- return toToolResult(envelopeResult);
6956
+ const envelopeResult = await client.post(
6957
+ corePath,
6958
+ transformInput ? transformInput(args) : args
6959
+ );
6960
+ return toToolResult(
6961
+ addDeprecatedAliasWarning(envelopeResult, deprecationAlias)
6962
+ );
6306
6963
  } catch (error) {
6307
6964
  const parsed = ErrorEnvelopeSchema.safeParse(error);
6308
6965
  if (parsed.success) {
@@ -6322,7 +6979,12 @@ var registerBrowserBridgeTools = (server, clientProvider) => {
6322
6979
  inputSchema: tool.config.inputSchema,
6323
6980
  outputSchema: tool.config.outputSchema
6324
6981
  },
6325
- createToolHandler(clientProvider, tool.config.corePath)
6982
+ createToolHandler(
6983
+ clientProvider,
6984
+ tool.config.corePath,
6985
+ tool.config.deprecationAlias,
6986
+ tool.config.transformInput
6987
+ )
6326
6988
  );
6327
6989
  }
6328
6990
  };