@btraut/browser-bridge 0.11.0 → 0.12.0
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/CHANGELOG.md +29 -0
- package/README.md +41 -0
- package/dist/api.js +878 -128
- package/dist/api.js.map +4 -4
- package/dist/index.js +861 -378
- package/dist/index.js.map +4 -4
- package/extension/assets/ui.css +108 -1
- package/extension/dist/background.js +164 -23
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/popup-ui.js +110 -3
- package/extension/dist/popup-ui.js.map +2 -2
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
- package/skills/browser-bridge/skill.json +1 -1
package/dist/api.js
CHANGED
|
@@ -39,55 +39,8 @@ module.exports = __toCommonJS(api_exports);
|
|
|
39
39
|
var import_http = require("http");
|
|
40
40
|
var import_express2 = __toESM(require("express"));
|
|
41
41
|
|
|
42
|
-
// packages/shared/src/
|
|
43
|
-
var
|
|
44
|
-
var ErrorCodeSchema = import_zod.z.enum([
|
|
45
|
-
"UNKNOWN",
|
|
46
|
-
"INVALID_ARGUMENT",
|
|
47
|
-
"NOT_FOUND",
|
|
48
|
-
"ALREADY_EXISTS",
|
|
49
|
-
"FAILED_PRECONDITION",
|
|
50
|
-
"UNAUTHORIZED",
|
|
51
|
-
"FORBIDDEN",
|
|
52
|
-
"PERMISSION_REQUIRED",
|
|
53
|
-
"PERMISSION_DENIED",
|
|
54
|
-
"PERMISSION_PROMPT_TIMEOUT",
|
|
55
|
-
"CONFLICT",
|
|
56
|
-
"TIMEOUT",
|
|
57
|
-
"CANCELLED",
|
|
58
|
-
"UNAVAILABLE",
|
|
59
|
-
"RATE_LIMITED",
|
|
60
|
-
"NOT_IMPLEMENTED",
|
|
61
|
-
"INTERNAL",
|
|
62
|
-
"SESSION_NOT_FOUND",
|
|
63
|
-
"SESSION_CLOSED",
|
|
64
|
-
"SESSION_BROKEN",
|
|
65
|
-
"DRIVE_UNAVAILABLE",
|
|
66
|
-
"INSPECT_UNAVAILABLE",
|
|
67
|
-
"EXTENSION_DISCONNECTED",
|
|
68
|
-
"DEBUGGER_IN_USE",
|
|
69
|
-
"ATTACH_DENIED",
|
|
70
|
-
"TAB_NOT_FOUND",
|
|
71
|
-
"NOT_SUPPORTED",
|
|
72
|
-
"LOCATOR_NOT_FOUND",
|
|
73
|
-
"NAVIGATION_FAILED",
|
|
74
|
-
"EVALUATION_FAILED",
|
|
75
|
-
"ARTIFACT_IO_ERROR"
|
|
76
|
-
]);
|
|
77
|
-
var ErrorInfoSchema = import_zod.z.object({
|
|
78
|
-
code: ErrorCodeSchema,
|
|
79
|
-
message: import_zod.z.string(),
|
|
80
|
-
retryable: import_zod.z.boolean(),
|
|
81
|
-
details: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
|
|
82
|
-
});
|
|
83
|
-
var ErrorEnvelopeSchema = import_zod.z.object({
|
|
84
|
-
ok: import_zod.z.literal(false),
|
|
85
|
-
error: ErrorInfoSchema
|
|
86
|
-
});
|
|
87
|
-
var successEnvelopeSchema = (result) => import_zod.z.object({
|
|
88
|
-
ok: import_zod.z.literal(true),
|
|
89
|
-
result
|
|
90
|
-
});
|
|
42
|
+
// packages/shared/src/core-readiness.ts
|
|
43
|
+
var import_promises = require("node:timers/promises");
|
|
91
44
|
|
|
92
45
|
// packages/shared/src/logging.ts
|
|
93
46
|
var import_node_fs2 = require("node:fs");
|
|
@@ -638,6 +591,248 @@ var createJsonlLogger = (options) => {
|
|
|
638
591
|
return buildLogger(state, options.bindings ?? {});
|
|
639
592
|
};
|
|
640
593
|
|
|
594
|
+
// packages/shared/src/core-readiness.ts
|
|
595
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
596
|
+
var DEFAULT_HEALTH_RETRY_MS = 250;
|
|
597
|
+
var DEFAULT_HEALTH_ATTEMPTS = 20;
|
|
598
|
+
var DEFAULT_HEALTH_TIMEOUT_MS = 2e3;
|
|
599
|
+
var DEFAULT_HEALTH_BUDGET_MS = 15e3;
|
|
600
|
+
var resolveTimeoutMs = (timeoutMs) => {
|
|
601
|
+
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
|
+
if (candidate === void 0 || candidate === null) {
|
|
603
|
+
return DEFAULT_TIMEOUT_MS;
|
|
604
|
+
}
|
|
605
|
+
const parsed = typeof candidate === "number" ? candidate : Number(candidate);
|
|
606
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
607
|
+
throw new Error(`Invalid timeoutMs: ${String(candidate)}`);
|
|
608
|
+
}
|
|
609
|
+
return Math.floor(parsed);
|
|
610
|
+
};
|
|
611
|
+
var resolvePositiveInteger = (value, fallback) => {
|
|
612
|
+
if (value === void 0) {
|
|
613
|
+
return fallback;
|
|
614
|
+
}
|
|
615
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
616
|
+
throw new Error(`Invalid positive integer value: ${String(value)}`);
|
|
617
|
+
}
|
|
618
|
+
return Math.floor(value);
|
|
619
|
+
};
|
|
620
|
+
var hasExplicitRuntimeInput = (options) => options.host !== void 0 || options.port !== void 0 || process.env.BROWSER_BRIDGE_CORE_HOST !== void 0 || process.env.BROWSER_VISION_CORE_HOST !== void 0 || process.env.BROWSER_BRIDGE_CORE_PORT !== void 0 || process.env.BROWSER_VISION_CORE_PORT !== void 0;
|
|
621
|
+
var createCoreReadinessController = (options = {}) => {
|
|
622
|
+
const logger = options.logger ?? createJsonlLogger({
|
|
623
|
+
stream: "cli",
|
|
624
|
+
cwd: options.cwd
|
|
625
|
+
}).child({ scope: "core-readiness" });
|
|
626
|
+
const logPrefix = options.logPrefix ?? "core";
|
|
627
|
+
const timeoutMs = resolveTimeoutMs(options.timeoutMs);
|
|
628
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
629
|
+
const ensureDaemon = options.ensureDaemon ?? true;
|
|
630
|
+
const healthRetryMs = resolvePositiveInteger(
|
|
631
|
+
options.healthRetryMs,
|
|
632
|
+
DEFAULT_HEALTH_RETRY_MS
|
|
633
|
+
);
|
|
634
|
+
const healthAttempts = resolvePositiveInteger(
|
|
635
|
+
options.healthAttempts,
|
|
636
|
+
DEFAULT_HEALTH_ATTEMPTS
|
|
637
|
+
);
|
|
638
|
+
const healthTimeoutMs = resolvePositiveInteger(
|
|
639
|
+
options.healthTimeoutMs,
|
|
640
|
+
Math.min(timeoutMs, DEFAULT_HEALTH_TIMEOUT_MS)
|
|
641
|
+
);
|
|
642
|
+
const healthBudgetMs = resolvePositiveInteger(
|
|
643
|
+
options.healthBudgetMs,
|
|
644
|
+
DEFAULT_HEALTH_BUDGET_MS
|
|
645
|
+
);
|
|
646
|
+
let runtime = resolveCoreRuntime({
|
|
647
|
+
host: options.host,
|
|
648
|
+
port: options.port,
|
|
649
|
+
cwd: options.cwd,
|
|
650
|
+
strictEnvPort: options.strictEnvPort ?? true
|
|
651
|
+
});
|
|
652
|
+
let baseUrl = `http://${runtime.host}:${runtime.port}`;
|
|
653
|
+
const allowRuntimeRefresh = !hasExplicitRuntimeInput(options);
|
|
654
|
+
const refreshRuntime = () => {
|
|
655
|
+
if (!allowRuntimeRefresh) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
runtime = resolveCoreRuntime({
|
|
659
|
+
cwd: options.cwd,
|
|
660
|
+
strictEnvPort: options.strictEnvPort ?? true
|
|
661
|
+
});
|
|
662
|
+
baseUrl = `http://${runtime.host}:${runtime.port}`;
|
|
663
|
+
};
|
|
664
|
+
const checkHealth = async () => {
|
|
665
|
+
try {
|
|
666
|
+
const controller = new AbortController();
|
|
667
|
+
const timeout = setTimeout(() => controller.abort(), healthTimeoutMs);
|
|
668
|
+
try {
|
|
669
|
+
let response;
|
|
670
|
+
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`, {
|
|
678
|
+
base_url: baseUrl,
|
|
679
|
+
timeout_ms: healthTimeoutMs
|
|
680
|
+
});
|
|
681
|
+
return false;
|
|
682
|
+
}
|
|
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
|
+
logger.warn(`${logPrefix}.health.not_ready`, {
|
|
700
|
+
base_url: baseUrl
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
return ok;
|
|
704
|
+
} finally {
|
|
705
|
+
clearTimeout(timeout);
|
|
706
|
+
}
|
|
707
|
+
} catch (error) {
|
|
708
|
+
logger.warn(`${logPrefix}.health.error`, {
|
|
709
|
+
base_url: baseUrl,
|
|
710
|
+
error
|
|
711
|
+
});
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
const ensureCoreRunning = async () => {
|
|
716
|
+
refreshRuntime();
|
|
717
|
+
if (await checkHealth()) {
|
|
718
|
+
logger.debug(`${logPrefix}.ensure_ready.already_running`, {
|
|
719
|
+
base_url: baseUrl
|
|
720
|
+
});
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
if (!options.spawnDaemon) {
|
|
724
|
+
logger.error(`${logPrefix}.ensure_ready.missing_spawn`, {
|
|
725
|
+
host: runtime.host,
|
|
726
|
+
port: runtime.port
|
|
727
|
+
});
|
|
728
|
+
throw new Error(
|
|
729
|
+
`Core daemon is not running on ${runtime.host}:${runtime.port} and spawnDaemon is not configured.`
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
options.spawnDaemon(runtime);
|
|
733
|
+
const deadlineAt = Date.now() + healthBudgetMs;
|
|
734
|
+
for (let attempt = 0; attempt < healthAttempts; attempt += 1) {
|
|
735
|
+
const remainingBudgetMs = deadlineAt - Date.now();
|
|
736
|
+
if (remainingBudgetMs <= 0) {
|
|
737
|
+
break;
|
|
738
|
+
}
|
|
739
|
+
await (0, import_promises.setTimeout)(Math.min(healthRetryMs, remainingBudgetMs));
|
|
740
|
+
refreshRuntime();
|
|
741
|
+
if (await checkHealth()) {
|
|
742
|
+
logger.info(`${logPrefix}.ensure_ready.ready`, {
|
|
743
|
+
base_url: baseUrl,
|
|
744
|
+
attempts: attempt + 1
|
|
745
|
+
});
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
logger.error(`${logPrefix}.ensure_ready.failed`, {
|
|
750
|
+
host: runtime.host,
|
|
751
|
+
port: runtime.port,
|
|
752
|
+
attempts: healthAttempts,
|
|
753
|
+
health_budget_ms: healthBudgetMs,
|
|
754
|
+
health_timeout_ms: healthTimeoutMs
|
|
755
|
+
});
|
|
756
|
+
throw new Error(
|
|
757
|
+
`Core daemon failed to start on ${runtime.host}:${runtime.port}.`
|
|
758
|
+
);
|
|
759
|
+
};
|
|
760
|
+
let ensurePromise = null;
|
|
761
|
+
const ensureReady = async () => {
|
|
762
|
+
if (!ensureDaemon) {
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
if (!ensurePromise) {
|
|
766
|
+
ensurePromise = ensureCoreRunning().catch((error) => {
|
|
767
|
+
ensurePromise = null;
|
|
768
|
+
throw error;
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
await ensurePromise;
|
|
772
|
+
};
|
|
773
|
+
return {
|
|
774
|
+
get baseUrl() {
|
|
775
|
+
return baseUrl;
|
|
776
|
+
},
|
|
777
|
+
get runtime() {
|
|
778
|
+
return runtime;
|
|
779
|
+
},
|
|
780
|
+
refreshRuntime,
|
|
781
|
+
ensureReady,
|
|
782
|
+
checkHealth
|
|
783
|
+
};
|
|
784
|
+
};
|
|
785
|
+
|
|
786
|
+
// packages/shared/src/errors.ts
|
|
787
|
+
var import_zod = require("zod");
|
|
788
|
+
var ErrorCodeSchema = import_zod.z.enum([
|
|
789
|
+
"UNKNOWN",
|
|
790
|
+
"INVALID_ARGUMENT",
|
|
791
|
+
"NOT_FOUND",
|
|
792
|
+
"ALREADY_EXISTS",
|
|
793
|
+
"FAILED_PRECONDITION",
|
|
794
|
+
"UNAUTHORIZED",
|
|
795
|
+
"FORBIDDEN",
|
|
796
|
+
"PERMISSION_REQUIRED",
|
|
797
|
+
"PERMISSION_DENIED",
|
|
798
|
+
"PERMISSION_PROMPT_TIMEOUT",
|
|
799
|
+
"CONFLICT",
|
|
800
|
+
"TIMEOUT",
|
|
801
|
+
"CANCELLED",
|
|
802
|
+
"UNAVAILABLE",
|
|
803
|
+
"RATE_LIMITED",
|
|
804
|
+
"NOT_IMPLEMENTED",
|
|
805
|
+
"INTERNAL",
|
|
806
|
+
"SESSION_NOT_FOUND",
|
|
807
|
+
"SESSION_CLOSED",
|
|
808
|
+
"SESSION_BROKEN",
|
|
809
|
+
"DRIVE_UNAVAILABLE",
|
|
810
|
+
"INSPECT_UNAVAILABLE",
|
|
811
|
+
"EXTENSION_DISCONNECTED",
|
|
812
|
+
"DEBUGGER_IN_USE",
|
|
813
|
+
"ATTACH_DENIED",
|
|
814
|
+
"TAB_NOT_FOUND",
|
|
815
|
+
"NOT_SUPPORTED",
|
|
816
|
+
"LOCATOR_NOT_FOUND",
|
|
817
|
+
"NAVIGATION_FAILED",
|
|
818
|
+
"EVALUATION_FAILED",
|
|
819
|
+
"ARTIFACT_IO_ERROR"
|
|
820
|
+
]);
|
|
821
|
+
var ErrorInfoSchema = import_zod.z.object({
|
|
822
|
+
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()
|
|
826
|
+
});
|
|
827
|
+
var ErrorEnvelopeSchema = import_zod.z.object({
|
|
828
|
+
ok: import_zod.z.literal(false),
|
|
829
|
+
error: ErrorInfoSchema
|
|
830
|
+
});
|
|
831
|
+
var successEnvelopeSchema = (result) => import_zod.z.object({
|
|
832
|
+
ok: import_zod.z.literal(true),
|
|
833
|
+
result
|
|
834
|
+
});
|
|
835
|
+
|
|
641
836
|
// packages/shared/src/schemas.ts
|
|
642
837
|
var import_zod2 = require("zod");
|
|
643
838
|
var LocatorRoleSchema = import_zod2.z.object({
|
|
@@ -702,6 +897,39 @@ var DiagnosticCheckSchema = import_zod2.z.object({
|
|
|
702
897
|
message: import_zod2.z.string().optional(),
|
|
703
898
|
details: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional()
|
|
704
899
|
});
|
|
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()
|
|
908
|
+
});
|
|
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()
|
|
916
|
+
});
|
|
917
|
+
var DiagnosticsRuntimeCallerSchema = import_zod2.z.object({
|
|
918
|
+
endpoint: DiagnosticsRuntimeEndpointSchema.optional(),
|
|
919
|
+
process: DiagnosticsRuntimeProcessSchema.optional()
|
|
920
|
+
});
|
|
921
|
+
var DiagnosticsRuntimeContextSchema = import_zod2.z.object({
|
|
922
|
+
caller: DiagnosticsRuntimeCallerSchema.optional(),
|
|
923
|
+
core: import_zod2.z.object({
|
|
924
|
+
endpoint: DiagnosticsRuntimeEndpointSchema.optional(),
|
|
925
|
+
process: DiagnosticsRuntimeProcessSchema.optional()
|
|
926
|
+
}).optional(),
|
|
927
|
+
extension: import_zod2.z.object({
|
|
928
|
+
version: import_zod2.z.string().optional(),
|
|
929
|
+
endpoint: DiagnosticsRuntimeEndpointSchema.optional(),
|
|
930
|
+
port_source: import_zod2.z.enum(["default", "storage"]).optional()
|
|
931
|
+
}).optional()
|
|
932
|
+
});
|
|
705
933
|
var DiagnosticReportSchema = import_zod2.z.object({
|
|
706
934
|
ok: import_zod2.z.boolean(),
|
|
707
935
|
session_id: import_zod2.z.string().optional(),
|
|
@@ -750,7 +978,8 @@ var DiagnosticReportSchema = import_zod2.z.object({
|
|
|
750
978
|
loop_detected: import_zod2.z.boolean().optional()
|
|
751
979
|
}).optional(),
|
|
752
980
|
warnings: import_zod2.z.array(import_zod2.z.string()).optional(),
|
|
753
|
-
notes: import_zod2.z.array(import_zod2.z.string()).optional()
|
|
981
|
+
notes: import_zod2.z.array(import_zod2.z.string()).optional(),
|
|
982
|
+
runtime: DiagnosticsRuntimeContextSchema.optional()
|
|
754
983
|
});
|
|
755
984
|
var SessionIdSchema = import_zod2.z.object({
|
|
756
985
|
session_id: import_zod2.z.string().min(1)
|
|
@@ -1142,7 +1371,8 @@ var HealthCheckOutputSchema = import_zod2.z.object({
|
|
|
1142
1371
|
}).passthrough()
|
|
1143
1372
|
}).passthrough();
|
|
1144
1373
|
var DiagnosticsDoctorInputSchema = import_zod2.z.object({
|
|
1145
|
-
session_id: import_zod2.z.string().min(1).optional()
|
|
1374
|
+
session_id: import_zod2.z.string().min(1).optional(),
|
|
1375
|
+
caller: DiagnosticsRuntimeCallerSchema.optional()
|
|
1146
1376
|
});
|
|
1147
1377
|
var DiagnosticsDoctorOutputSchema = DiagnosticReportSchema;
|
|
1148
1378
|
|
|
@@ -1612,14 +1842,14 @@ var InspectError = class extends Error {
|
|
|
1612
1842
|
|
|
1613
1843
|
// packages/core/src/inspect/service.ts
|
|
1614
1844
|
var import_crypto3 = require("crypto");
|
|
1615
|
-
var
|
|
1845
|
+
var import_promises3 = require("node:fs/promises");
|
|
1616
1846
|
var import_node_path4 = __toESM(require("node:path"));
|
|
1617
1847
|
var import_readability = require("@mozilla/readability");
|
|
1618
1848
|
var import_jsdom = require("jsdom");
|
|
1619
1849
|
var import_turndown = __toESM(require("turndown"));
|
|
1620
1850
|
|
|
1621
1851
|
// packages/core/src/artifacts.ts
|
|
1622
|
-
var
|
|
1852
|
+
var import_promises2 = require("node:fs/promises");
|
|
1623
1853
|
var import_node_os = __toESM(require("node:os"));
|
|
1624
1854
|
var import_node_path3 = __toESM(require("node:path"));
|
|
1625
1855
|
var ARTIFACTS_DIR_NAME = "browser-agent";
|
|
@@ -1627,7 +1857,7 @@ var resolveTempRoot = () => process.env.TMPDIR || process.env.TEMP || process.en
|
|
|
1627
1857
|
var getArtifactRootDir = (sessionId) => import_node_path3.default.join(resolveTempRoot(), ARTIFACTS_DIR_NAME, sessionId);
|
|
1628
1858
|
var ensureArtifactRootDir = async (sessionId) => {
|
|
1629
1859
|
const rootDir = getArtifactRootDir(sessionId);
|
|
1630
|
-
await (0,
|
|
1860
|
+
await (0, import_promises2.mkdir)(rootDir, { recursive: true });
|
|
1631
1861
|
return rootDir;
|
|
1632
1862
|
};
|
|
1633
1863
|
|
|
@@ -1681,6 +1911,10 @@ var ExtensionBridge = class {
|
|
|
1681
1911
|
return {
|
|
1682
1912
|
connected: this.connected,
|
|
1683
1913
|
lastSeenAt: this.lastSeenAt,
|
|
1914
|
+
version: this.version,
|
|
1915
|
+
coreHost: this.coreHost,
|
|
1916
|
+
corePort: this.corePort,
|
|
1917
|
+
corePortSource: this.corePortSource,
|
|
1684
1918
|
tabs: this.tabs
|
|
1685
1919
|
};
|
|
1686
1920
|
}
|
|
@@ -1718,7 +1952,7 @@ var ExtensionBridge = class {
|
|
|
1718
1952
|
status: "request",
|
|
1719
1953
|
params
|
|
1720
1954
|
};
|
|
1721
|
-
const response = await new Promise((
|
|
1955
|
+
const response = await new Promise((resolve3, reject) => {
|
|
1722
1956
|
const timeout = setTimeout(() => {
|
|
1723
1957
|
this.pending.delete(id);
|
|
1724
1958
|
reject(
|
|
@@ -1731,7 +1965,7 @@ var ExtensionBridge = class {
|
|
|
1731
1965
|
);
|
|
1732
1966
|
}, timeoutMs);
|
|
1733
1967
|
this.pending.set(id, {
|
|
1734
|
-
resolve:
|
|
1968
|
+
resolve: resolve3,
|
|
1735
1969
|
reject,
|
|
1736
1970
|
timeout
|
|
1737
1971
|
});
|
|
@@ -1816,6 +2050,10 @@ var ExtensionBridge = class {
|
|
|
1816
2050
|
this.stopHeartbeat();
|
|
1817
2051
|
this.connected = false;
|
|
1818
2052
|
this.socket = null;
|
|
2053
|
+
this.version = void 0;
|
|
2054
|
+
this.coreHost = void 0;
|
|
2055
|
+
this.corePort = void 0;
|
|
2056
|
+
this.corePortSource = void 0;
|
|
1819
2057
|
this.lastSeenAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1820
2058
|
this.applyDriveDisconnected();
|
|
1821
2059
|
for (const [id, pending] of this.pending.entries()) {
|
|
@@ -1863,10 +2101,25 @@ var ExtensionBridge = class {
|
|
|
1863
2101
|
}
|
|
1864
2102
|
handleEvent(message) {
|
|
1865
2103
|
if (message.action === "drive.hello" || message.action === "drive.tab_report") {
|
|
1866
|
-
const
|
|
2104
|
+
const params = message.params;
|
|
2105
|
+
const tabs = params?.tabs;
|
|
1867
2106
|
if (Array.isArray(tabs)) {
|
|
1868
2107
|
this.tabs = tabs;
|
|
1869
2108
|
}
|
|
2109
|
+
if (message.action === "drive.hello") {
|
|
2110
|
+
if (typeof params?.version === "string") {
|
|
2111
|
+
this.version = params.version;
|
|
2112
|
+
}
|
|
2113
|
+
if (typeof params?.core_host === "string") {
|
|
2114
|
+
this.coreHost = params.core_host;
|
|
2115
|
+
}
|
|
2116
|
+
if (typeof params?.core_port === "number" && Number.isFinite(params.core_port)) {
|
|
2117
|
+
this.corePort = params.core_port;
|
|
2118
|
+
}
|
|
2119
|
+
if (params?.core_port_source === "default" || params?.core_port_source === "storage") {
|
|
2120
|
+
this.corePortSource = params.core_port_source;
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
1870
2123
|
}
|
|
1871
2124
|
if (typeof message.action === "string" && message.action.startsWith("debugger.")) {
|
|
1872
2125
|
this.emitDebuggerEvent(message);
|
|
@@ -3473,7 +3726,7 @@ var InspectService = class {
|
|
|
3473
3726
|
const rootDir = await ensureArtifactRootDir(input.sessionId);
|
|
3474
3727
|
const artifactId = (0, import_crypto3.randomUUID)();
|
|
3475
3728
|
const filePath = import_node_path4.default.join(rootDir, `har-${artifactId}.json`);
|
|
3476
|
-
await (0,
|
|
3729
|
+
await (0, import_promises3.writeFile)(filePath, JSON.stringify(har, null, 2), "utf-8");
|
|
3477
3730
|
const result = {
|
|
3478
3731
|
artifact_id: artifactId,
|
|
3479
3732
|
path: filePath,
|
|
@@ -3652,7 +3905,7 @@ var InspectService = class {
|
|
|
3652
3905
|
rootDir,
|
|
3653
3906
|
`screenshot-${artifactId}.${extension}`
|
|
3654
3907
|
);
|
|
3655
|
-
await (0,
|
|
3908
|
+
await (0, import_promises3.writeFile)(filePath, Buffer.from(data2, "base64"));
|
|
3656
3909
|
const mime = format === "jpeg" ? "image/jpeg" : `image/${format}`;
|
|
3657
3910
|
const output = {
|
|
3658
3911
|
artifact_id: artifactId,
|
|
@@ -4045,6 +4298,48 @@ var getErrorAgeMs = (timestamp) => {
|
|
|
4045
4298
|
}
|
|
4046
4299
|
return Math.max(0, Date.now() - parsed);
|
|
4047
4300
|
};
|
|
4301
|
+
var endpointLabel = (endpoint) => {
|
|
4302
|
+
if (!endpoint) {
|
|
4303
|
+
return "unknown";
|
|
4304
|
+
}
|
|
4305
|
+
if (endpoint.baseUrl) {
|
|
4306
|
+
return endpoint.baseUrl;
|
|
4307
|
+
}
|
|
4308
|
+
if (endpoint.host && endpoint.port !== void 0) {
|
|
4309
|
+
return `${endpoint.host}:${endpoint.port}`;
|
|
4310
|
+
}
|
|
4311
|
+
return "unknown";
|
|
4312
|
+
};
|
|
4313
|
+
var hasEndpoint = (endpoint) => Boolean(
|
|
4314
|
+
endpoint && typeof endpoint.host === "string" && endpoint.host.length > 0 && typeof endpoint.port === "number" && Number.isFinite(endpoint.port)
|
|
4315
|
+
);
|
|
4316
|
+
var toRuntimeEndpoint = (endpoint) => {
|
|
4317
|
+
if (!endpoint) {
|
|
4318
|
+
return void 0;
|
|
4319
|
+
}
|
|
4320
|
+
return {
|
|
4321
|
+
host: endpoint.host,
|
|
4322
|
+
port: endpoint.port,
|
|
4323
|
+
base_url: endpoint.baseUrl,
|
|
4324
|
+
host_source: endpoint.hostSource,
|
|
4325
|
+
port_source: endpoint.portSource,
|
|
4326
|
+
metadata_path: endpoint.metadataPath,
|
|
4327
|
+
isolated_mode: endpoint.isolatedMode
|
|
4328
|
+
};
|
|
4329
|
+
};
|
|
4330
|
+
var toRuntimeProcess = (process2) => {
|
|
4331
|
+
if (!process2) {
|
|
4332
|
+
return void 0;
|
|
4333
|
+
}
|
|
4334
|
+
return {
|
|
4335
|
+
component: process2.component,
|
|
4336
|
+
version: process2.version,
|
|
4337
|
+
pid: process2.pid,
|
|
4338
|
+
node_version: process2.nodeVersion,
|
|
4339
|
+
binary_path: process2.binaryPath,
|
|
4340
|
+
argv_entry: process2.argvEntry
|
|
4341
|
+
};
|
|
4342
|
+
};
|
|
4048
4343
|
var buildDiagnosticReport = (sessionId, context = {}) => {
|
|
4049
4344
|
const extensionConnected = context.extension?.connected ?? false;
|
|
4050
4345
|
const debuggerAttached = context.debugger?.attached ?? false;
|
|
@@ -4072,6 +4367,57 @@ var buildDiagnosticReport = (sessionId, context = {}) => {
|
|
|
4072
4367
|
}
|
|
4073
4368
|
}
|
|
4074
4369
|
];
|
|
4370
|
+
const coreEndpoint = context.runtime?.core?.endpoint;
|
|
4371
|
+
const callerEndpoint = context.runtime?.caller?.endpoint;
|
|
4372
|
+
const extensionEndpoint = context.runtime?.extension?.endpoint;
|
|
4373
|
+
if (hasEndpoint(coreEndpoint) && hasEndpoint(callerEndpoint)) {
|
|
4374
|
+
const matches = coreEndpoint.host === callerEndpoint.host && coreEndpoint.port === callerEndpoint.port;
|
|
4375
|
+
checks.push({
|
|
4376
|
+
name: "runtime.caller.endpoint_match",
|
|
4377
|
+
ok: matches,
|
|
4378
|
+
message: matches ? `Caller endpoint matches core (${endpointLabel(coreEndpoint)}).` : `Caller endpoint ${endpointLabel(
|
|
4379
|
+
callerEndpoint
|
|
4380
|
+
)} differs from core ${endpointLabel(coreEndpoint)}.`,
|
|
4381
|
+
details: {
|
|
4382
|
+
caller_endpoint: endpointLabel(callerEndpoint),
|
|
4383
|
+
core_endpoint: endpointLabel(coreEndpoint),
|
|
4384
|
+
caller_host_source: callerEndpoint.hostSource,
|
|
4385
|
+
caller_port_source: callerEndpoint.portSource,
|
|
4386
|
+
core_host_source: coreEndpoint.hostSource,
|
|
4387
|
+
core_port_source: coreEndpoint.portSource
|
|
4388
|
+
}
|
|
4389
|
+
});
|
|
4390
|
+
}
|
|
4391
|
+
if (extensionConnected && hasEndpoint(coreEndpoint) && hasEndpoint(extensionEndpoint)) {
|
|
4392
|
+
const matches = coreEndpoint.host === extensionEndpoint.host && coreEndpoint.port === extensionEndpoint.port;
|
|
4393
|
+
checks.push({
|
|
4394
|
+
name: "runtime.extension.endpoint_match",
|
|
4395
|
+
ok: matches,
|
|
4396
|
+
message: matches ? `Extension endpoint matches core (${endpointLabel(coreEndpoint)}).` : `Extension endpoint ${endpointLabel(
|
|
4397
|
+
extensionEndpoint
|
|
4398
|
+
)} differs from core ${endpointLabel(coreEndpoint)}.`,
|
|
4399
|
+
details: {
|
|
4400
|
+
extension_endpoint: endpointLabel(extensionEndpoint),
|
|
4401
|
+
core_endpoint: endpointLabel(coreEndpoint),
|
|
4402
|
+
extension_port_source: context.runtime?.extension?.portSource,
|
|
4403
|
+
core_host_source: coreEndpoint.hostSource,
|
|
4404
|
+
core_port_source: coreEndpoint.portSource
|
|
4405
|
+
}
|
|
4406
|
+
});
|
|
4407
|
+
}
|
|
4408
|
+
const callerVersion = context.runtime?.caller?.process?.version;
|
|
4409
|
+
const extensionVersion = extensionConnected ? context.runtime?.extension?.version : void 0;
|
|
4410
|
+
if (callerVersion && extensionVersion) {
|
|
4411
|
+
checks.push({
|
|
4412
|
+
name: "runtime.extension.version_match_caller",
|
|
4413
|
+
ok: callerVersion === extensionVersion,
|
|
4414
|
+
message: callerVersion === extensionVersion ? `Caller and extension versions match (${callerVersion}).` : `Caller version ${callerVersion} differs from extension version ${extensionVersion}.`,
|
|
4415
|
+
details: {
|
|
4416
|
+
caller_version: callerVersion,
|
|
4417
|
+
extension_version: extensionVersion
|
|
4418
|
+
}
|
|
4419
|
+
});
|
|
4420
|
+
}
|
|
4075
4421
|
if (context.driveLastError) {
|
|
4076
4422
|
const ageMs = getErrorAgeMs(context.driveLastError.at);
|
|
4077
4423
|
const isStale = ageMs !== void 0 && ageMs > STALE_ERROR_THRESHOLD_MS;
|
|
@@ -4144,6 +4490,7 @@ var buildDiagnosticReport = (sessionId, context = {}) => {
|
|
|
4144
4490
|
} : void 0,
|
|
4145
4491
|
extension: {
|
|
4146
4492
|
connected: extensionConnected,
|
|
4493
|
+
version: context.extension?.version,
|
|
4147
4494
|
last_seen_at: context.extension?.lastSeenAt
|
|
4148
4495
|
},
|
|
4149
4496
|
debugger: context.debugger ? {
|
|
@@ -4168,7 +4515,22 @@ var buildDiagnosticReport = (sessionId, context = {}) => {
|
|
|
4168
4515
|
} : {}
|
|
4169
4516
|
} : void 0,
|
|
4170
4517
|
...warnings.length > 0 ? { warnings } : {},
|
|
4171
|
-
notes: ["Diagnostics include runtime status; some checks may be stubbed."]
|
|
4518
|
+
notes: ["Diagnostics include runtime status; some checks may be stubbed."],
|
|
4519
|
+
runtime: context.runtime ? {
|
|
4520
|
+
caller: context.runtime.caller ? {
|
|
4521
|
+
endpoint: toRuntimeEndpoint(context.runtime.caller.endpoint),
|
|
4522
|
+
process: toRuntimeProcess(context.runtime.caller.process)
|
|
4523
|
+
} : void 0,
|
|
4524
|
+
core: context.runtime.core ? {
|
|
4525
|
+
endpoint: toRuntimeEndpoint(context.runtime.core.endpoint),
|
|
4526
|
+
process: toRuntimeProcess(context.runtime.core.process)
|
|
4527
|
+
} : void 0,
|
|
4528
|
+
extension: context.runtime.extension ? {
|
|
4529
|
+
version: context.runtime.extension.version,
|
|
4530
|
+
endpoint: toRuntimeEndpoint(context.runtime.extension.endpoint),
|
|
4531
|
+
port_source: context.runtime.extension.portSource
|
|
4532
|
+
} : void 0
|
|
4533
|
+
} : void 0
|
|
4172
4534
|
};
|
|
4173
4535
|
return report;
|
|
4174
4536
|
};
|
|
@@ -4213,30 +4575,69 @@ var registerDiagnosticsRoutes = (router, options = {}) => {
|
|
|
4213
4575
|
});
|
|
4214
4576
|
});
|
|
4215
4577
|
router.post("/diagnostics/doctor", (req, res) => {
|
|
4216
|
-
|
|
4217
|
-
if (
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
return;
|
|
4225
|
-
}
|
|
4226
|
-
const raw = req.body.session_id;
|
|
4227
|
-
if (raw !== void 0 && (typeof raw !== "string" || raw.length === 0)) {
|
|
4228
|
-
sendError(res, 400, {
|
|
4229
|
-
code: "INVALID_ARGUMENT",
|
|
4230
|
-
message: "session_id must be a non-empty string.",
|
|
4231
|
-
retryable: false,
|
|
4232
|
-
details: { field: "session_id" }
|
|
4233
|
-
});
|
|
4234
|
-
return;
|
|
4235
|
-
}
|
|
4236
|
-
sessionId = raw;
|
|
4578
|
+
const body = req.body ?? {};
|
|
4579
|
+
if (!isRecord(body)) {
|
|
4580
|
+
sendError(res, 400, {
|
|
4581
|
+
code: "INVALID_ARGUMENT",
|
|
4582
|
+
message: "Request body must be an object.",
|
|
4583
|
+
retryable: false
|
|
4584
|
+
});
|
|
4585
|
+
return;
|
|
4237
4586
|
}
|
|
4587
|
+
const parsedDoctorInput = DiagnosticsDoctorInputSchema.safeParse(body);
|
|
4588
|
+
if (!parsedDoctorInput.success) {
|
|
4589
|
+
const issue = parsedDoctorInput.error.issues[0];
|
|
4590
|
+
sendError(res, 400, {
|
|
4591
|
+
code: "INVALID_ARGUMENT",
|
|
4592
|
+
message: issue?.message ?? "Invalid diagnostics doctor request.",
|
|
4593
|
+
retryable: false,
|
|
4594
|
+
details: issue?.path.length ? { field: issue.path.map((part) => String(part)).join(".") } : void 0
|
|
4595
|
+
});
|
|
4596
|
+
return;
|
|
4597
|
+
}
|
|
4598
|
+
const sessionId = parsedDoctorInput.data.session_id;
|
|
4238
4599
|
try {
|
|
4239
4600
|
const context = {};
|
|
4601
|
+
context.runtime = {
|
|
4602
|
+
caller: parsedDoctorInput.data.caller ? {
|
|
4603
|
+
endpoint: parsedDoctorInput.data.caller.endpoint ? {
|
|
4604
|
+
host: parsedDoctorInput.data.caller.endpoint.host,
|
|
4605
|
+
port: parsedDoctorInput.data.caller.endpoint.port,
|
|
4606
|
+
baseUrl: parsedDoctorInput.data.caller.endpoint.base_url,
|
|
4607
|
+
hostSource: parsedDoctorInput.data.caller.endpoint.host_source,
|
|
4608
|
+
portSource: parsedDoctorInput.data.caller.endpoint.port_source,
|
|
4609
|
+
metadataPath: parsedDoctorInput.data.caller.endpoint.metadata_path,
|
|
4610
|
+
isolatedMode: parsedDoctorInput.data.caller.endpoint.isolated_mode
|
|
4611
|
+
} : void 0,
|
|
4612
|
+
process: parsedDoctorInput.data.caller.process ? {
|
|
4613
|
+
component: parsedDoctorInput.data.caller.process.component,
|
|
4614
|
+
version: parsedDoctorInput.data.caller.process.version,
|
|
4615
|
+
pid: parsedDoctorInput.data.caller.process.pid,
|
|
4616
|
+
nodeVersion: parsedDoctorInput.data.caller.process.node_version,
|
|
4617
|
+
binaryPath: parsedDoctorInput.data.caller.process.binary_path,
|
|
4618
|
+
argvEntry: parsedDoctorInput.data.caller.process.argv_entry
|
|
4619
|
+
} : void 0
|
|
4620
|
+
} : void 0,
|
|
4621
|
+
core: {
|
|
4622
|
+
endpoint: options.coreRuntime ? {
|
|
4623
|
+
host: options.coreRuntime.host,
|
|
4624
|
+
port: options.coreRuntime.port,
|
|
4625
|
+
baseUrl: `http://${options.coreRuntime.host}:${options.coreRuntime.port}`,
|
|
4626
|
+
hostSource: options.coreRuntime.hostSource,
|
|
4627
|
+
portSource: options.coreRuntime.portSource,
|
|
4628
|
+
metadataPath: options.coreRuntime.metadataPath,
|
|
4629
|
+
isolatedMode: options.coreRuntime.isolatedMode
|
|
4630
|
+
} : void 0,
|
|
4631
|
+
process: {
|
|
4632
|
+
component: "core",
|
|
4633
|
+
version: options.coreVersion,
|
|
4634
|
+
pid: process.pid,
|
|
4635
|
+
nodeVersion: process.version,
|
|
4636
|
+
binaryPath: process.execPath,
|
|
4637
|
+
argvEntry: process.argv[1]
|
|
4638
|
+
}
|
|
4639
|
+
}
|
|
4640
|
+
};
|
|
4240
4641
|
if (options.registry && sessionId) {
|
|
4241
4642
|
try {
|
|
4242
4643
|
const session = options.registry.require(sessionId);
|
|
@@ -4268,8 +4669,20 @@ var registerDiagnosticsRoutes = (router, options = {}) => {
|
|
|
4268
4669
|
const status = options.extensionBridge.getStatus();
|
|
4269
4670
|
context.extension = {
|
|
4270
4671
|
connected: status.connected,
|
|
4672
|
+
version: status.version,
|
|
4271
4673
|
lastSeenAt: status.lastSeenAt
|
|
4272
4674
|
};
|
|
4675
|
+
if (status.connected) {
|
|
4676
|
+
context.runtime.extension = {
|
|
4677
|
+
version: status.version,
|
|
4678
|
+
endpoint: status.coreHost && typeof status.corePort === "number" ? {
|
|
4679
|
+
host: status.coreHost,
|
|
4680
|
+
port: status.corePort,
|
|
4681
|
+
baseUrl: `http://${status.coreHost}:${status.corePort}`
|
|
4682
|
+
} : void 0,
|
|
4683
|
+
portSource: status.corePortSource
|
|
4684
|
+
};
|
|
4685
|
+
}
|
|
4273
4686
|
}
|
|
4274
4687
|
if (options.debuggerBridge) {
|
|
4275
4688
|
const settings = options.debuggerBridge.getSettings();
|
|
@@ -5110,7 +5523,9 @@ var createCoreServer = (options = {}) => {
|
|
|
5110
5523
|
debuggerBridge,
|
|
5111
5524
|
drive,
|
|
5112
5525
|
inspectService: inspect,
|
|
5113
|
-
recoveryTracker
|
|
5526
|
+
recoveryTracker,
|
|
5527
|
+
coreRuntime: options.runtime,
|
|
5528
|
+
coreVersion: options.version
|
|
5114
5529
|
});
|
|
5115
5530
|
return {
|
|
5116
5531
|
app,
|
|
@@ -5169,7 +5584,7 @@ var resolveSessionCleanupIntervalMs = (ttlMs) => {
|
|
|
5169
5584
|
var isAddressInUseError = (error) => Boolean(
|
|
5170
5585
|
error && typeof error === "object" && "code" in error && error.code === "EADDRINUSE"
|
|
5171
5586
|
);
|
|
5172
|
-
var listenOnPort = (app, extensionBridge, host, port) => new Promise((
|
|
5587
|
+
var listenOnPort = (app, extensionBridge, host, port) => new Promise((resolve3, reject) => {
|
|
5173
5588
|
const server = (0, import_http.createServer)(app);
|
|
5174
5589
|
extensionBridge.attach(server);
|
|
5175
5590
|
const onError = (error) => {
|
|
@@ -5178,7 +5593,7 @@ var listenOnPort = (app, extensionBridge, host, port) => new Promise((resolve2,
|
|
|
5178
5593
|
};
|
|
5179
5594
|
const onListening = () => {
|
|
5180
5595
|
server.off("error", onError);
|
|
5181
|
-
|
|
5596
|
+
resolve3(server);
|
|
5182
5597
|
};
|
|
5183
5598
|
server.once("error", onError);
|
|
5184
5599
|
server.once("listening", onListening);
|
|
@@ -5218,6 +5633,7 @@ var startCoreServer = async (options = {}) => {
|
|
|
5218
5633
|
port: options.port,
|
|
5219
5634
|
strictEnvPort: false
|
|
5220
5635
|
});
|
|
5636
|
+
const coreVersion = process.env.BROWSER_BRIDGE_VERSION ?? process.env.npm_package_version;
|
|
5221
5637
|
logger.info("core.runtime.resolved", {
|
|
5222
5638
|
host: runtime.host,
|
|
5223
5639
|
port: runtime.port,
|
|
@@ -5230,7 +5646,9 @@ var startCoreServer = async (options = {}) => {
|
|
|
5230
5646
|
});
|
|
5231
5647
|
const { app, registry, extensionBridge } = createCoreServer({
|
|
5232
5648
|
registry: options.registry,
|
|
5233
|
-
logger
|
|
5649
|
+
logger,
|
|
5650
|
+
runtime,
|
|
5651
|
+
version: coreVersion
|
|
5234
5652
|
});
|
|
5235
5653
|
const probePorts = resolveProbePortsForRuntime(runtime);
|
|
5236
5654
|
let lastAddressInUseError;
|
|
@@ -5305,36 +5723,92 @@ var startCoreServer = async (options = {}) => {
|
|
|
5305
5723
|
};
|
|
5306
5724
|
|
|
5307
5725
|
// packages/mcp-adapter/src/core-client.ts
|
|
5308
|
-
var
|
|
5726
|
+
var import_node_child_process = require("node:child_process");
|
|
5727
|
+
var import_node_path5 = require("node:path");
|
|
5728
|
+
var DEFAULT_TIMEOUT_MS2 = 3e4;
|
|
5309
5729
|
var normalizePath = (path3) => path3.startsWith("/") ? path3 : `/${path3}`;
|
|
5310
5730
|
var durationMs = (startedAt) => Number((Number(process.hrtime.bigint() - startedAt) / 1e6).toFixed(3));
|
|
5731
|
+
var toReadinessErrorEnvelope = (error, baseUrl) => ({
|
|
5732
|
+
ok: false,
|
|
5733
|
+
error: {
|
|
5734
|
+
code: "UNAVAILABLE",
|
|
5735
|
+
message: error instanceof Error ? `Core not ready at ${baseUrl}: ${error.message}` : `Core not ready at ${baseUrl}.`,
|
|
5736
|
+
retryable: true,
|
|
5737
|
+
details: {
|
|
5738
|
+
base_url: baseUrl
|
|
5739
|
+
}
|
|
5740
|
+
}
|
|
5741
|
+
});
|
|
5311
5742
|
var createCoreClient = (options = {}) => {
|
|
5312
5743
|
const logger = options.logger ?? createJsonlLogger({
|
|
5313
5744
|
stream: "mcp-adapter",
|
|
5314
5745
|
cwd: options.cwd
|
|
5315
5746
|
}).child({ scope: "core-client" });
|
|
5316
|
-
const
|
|
5747
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
5748
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
5749
|
+
const spawnImpl = options.spawnImpl ?? import_node_child_process.spawn;
|
|
5750
|
+
const ensureDaemon = options.ensureDaemon ?? false;
|
|
5751
|
+
const componentVersion = options.componentVersion ?? process.env.BROWSER_BRIDGE_VERSION ?? process.env.npm_package_version;
|
|
5752
|
+
const readiness = createCoreReadinessController({
|
|
5317
5753
|
host: options.host,
|
|
5318
5754
|
port: options.port,
|
|
5319
5755
|
cwd: options.cwd,
|
|
5320
|
-
|
|
5756
|
+
timeoutMs,
|
|
5757
|
+
ensureDaemon,
|
|
5758
|
+
strictEnvPort: true,
|
|
5759
|
+
fetchImpl,
|
|
5760
|
+
logger,
|
|
5761
|
+
logPrefix: "mcp.core",
|
|
5762
|
+
healthRetryMs: options.healthRetryMs,
|
|
5763
|
+
healthAttempts: options.healthAttempts,
|
|
5764
|
+
spawnDaemon: ensureDaemon ? (runtime) => {
|
|
5765
|
+
const coreEntry = (0, import_node_path5.resolve)(__dirname, "api.js");
|
|
5766
|
+
const startOptions = [];
|
|
5767
|
+
if (runtime.hostSource === "option" || runtime.hostSource === "env") {
|
|
5768
|
+
startOptions.push(`host: ${JSON.stringify(runtime.host)}`);
|
|
5769
|
+
}
|
|
5770
|
+
if (runtime.portSource === "option" || runtime.portSource === "env") {
|
|
5771
|
+
startOptions.push(`port: ${runtime.port}`);
|
|
5772
|
+
}
|
|
5773
|
+
const script = `const { startCoreServer } = require(${JSON.stringify(
|
|
5774
|
+
coreEntry
|
|
5775
|
+
)});
|
|
5776
|
+
startCoreServer({ ${startOptions.join(
|
|
5777
|
+
", "
|
|
5778
|
+
)} })
|
|
5779
|
+
.catch((err) => { console.error(err); process.exit(1); });`;
|
|
5780
|
+
logger.info("mcp.core.spawn.start", {
|
|
5781
|
+
host: runtime.host,
|
|
5782
|
+
port: runtime.port,
|
|
5783
|
+
host_source: runtime.hostSource,
|
|
5784
|
+
port_source: runtime.portSource
|
|
5785
|
+
});
|
|
5786
|
+
const child = spawnImpl(process.execPath, ["-e", script], {
|
|
5787
|
+
detached: true,
|
|
5788
|
+
stdio: "ignore",
|
|
5789
|
+
env: { ...process.env }
|
|
5790
|
+
});
|
|
5791
|
+
child.on("error", (error) => {
|
|
5792
|
+
logger.error("mcp.core.spawn.error", {
|
|
5793
|
+
host: runtime.host,
|
|
5794
|
+
port: runtime.port,
|
|
5795
|
+
error
|
|
5796
|
+
});
|
|
5797
|
+
});
|
|
5798
|
+
child.unref();
|
|
5799
|
+
} : void 0
|
|
5321
5800
|
});
|
|
5322
|
-
const host = runtime.host;
|
|
5323
|
-
const port = runtime.port;
|
|
5324
|
-
const baseUrl = `http://${host}:${port}`;
|
|
5325
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
5326
|
-
const fetchImpl = options.fetchImpl ?? fetch;
|
|
5327
5801
|
const requestJson = async (path3, body) => {
|
|
5328
5802
|
const requestPath = normalizePath(path3);
|
|
5329
5803
|
const startedAt = process.hrtime.bigint();
|
|
5330
5804
|
logger.debug("mcp.core.request.start", {
|
|
5331
5805
|
path: requestPath,
|
|
5332
|
-
base_url: baseUrl
|
|
5806
|
+
base_url: readiness.baseUrl
|
|
5333
5807
|
});
|
|
5334
5808
|
const controller = new AbortController();
|
|
5335
5809
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
5336
5810
|
try {
|
|
5337
|
-
const response = await fetchImpl(`${baseUrl}${requestPath}`, {
|
|
5811
|
+
const response = await fetchImpl(`${readiness.baseUrl}${requestPath}`, {
|
|
5338
5812
|
method: "POST",
|
|
5339
5813
|
headers: {
|
|
5340
5814
|
"content-type": "application/json"
|
|
@@ -5346,7 +5820,7 @@ var createCoreClient = (options = {}) => {
|
|
|
5346
5820
|
if (!raw) {
|
|
5347
5821
|
logger.warn("mcp.core.request.empty_response", {
|
|
5348
5822
|
path: requestPath,
|
|
5349
|
-
base_url: baseUrl,
|
|
5823
|
+
base_url: readiness.baseUrl,
|
|
5350
5824
|
status: response.status,
|
|
5351
5825
|
duration_ms: durationMs(startedAt)
|
|
5352
5826
|
});
|
|
@@ -5356,7 +5830,7 @@ var createCoreClient = (options = {}) => {
|
|
|
5356
5830
|
const parsed = JSON.parse(raw);
|
|
5357
5831
|
logger.debug("mcp.core.request.end", {
|
|
5358
5832
|
path: requestPath,
|
|
5359
|
-
base_url: baseUrl,
|
|
5833
|
+
base_url: readiness.baseUrl,
|
|
5360
5834
|
status: response.status,
|
|
5361
5835
|
duration_ms: durationMs(startedAt)
|
|
5362
5836
|
});
|
|
@@ -5365,7 +5839,7 @@ var createCoreClient = (options = {}) => {
|
|
|
5365
5839
|
const message = error instanceof Error ? error.message : "Unknown JSON parse error";
|
|
5366
5840
|
logger.error("mcp.core.request.invalid_json", {
|
|
5367
5841
|
path: requestPath,
|
|
5368
|
-
base_url: baseUrl,
|
|
5842
|
+
base_url: readiness.baseUrl,
|
|
5369
5843
|
status: response.status,
|
|
5370
5844
|
duration_ms: durationMs(startedAt),
|
|
5371
5845
|
error
|
|
@@ -5375,7 +5849,7 @@ var createCoreClient = (options = {}) => {
|
|
|
5375
5849
|
} catch (error) {
|
|
5376
5850
|
logger.error("mcp.core.request.failed", {
|
|
5377
5851
|
path: requestPath,
|
|
5378
|
-
base_url: baseUrl,
|
|
5852
|
+
base_url: readiness.baseUrl,
|
|
5379
5853
|
duration_ms: durationMs(startedAt),
|
|
5380
5854
|
error
|
|
5381
5855
|
});
|
|
@@ -5385,9 +5859,47 @@ var createCoreClient = (options = {}) => {
|
|
|
5385
5859
|
}
|
|
5386
5860
|
};
|
|
5387
5861
|
const post = async (path3, body) => {
|
|
5388
|
-
|
|
5862
|
+
try {
|
|
5863
|
+
await readiness.ensureReady();
|
|
5864
|
+
} catch (error) {
|
|
5865
|
+
logger.warn("mcp.core.ensure_ready.unavailable", {
|
|
5866
|
+
base_url: readiness.baseUrl,
|
|
5867
|
+
error
|
|
5868
|
+
});
|
|
5869
|
+
throw toReadinessErrorEnvelope(error, readiness.baseUrl);
|
|
5870
|
+
}
|
|
5871
|
+
readiness.refreshRuntime();
|
|
5872
|
+
const payload = path3 === "/diagnostics/doctor" && (!body || typeof body === "object" && !Array.isArray(body)) ? {
|
|
5873
|
+
...body && typeof body === "object" ? body : {},
|
|
5874
|
+
caller: {
|
|
5875
|
+
endpoint: {
|
|
5876
|
+
host: readiness.runtime.host,
|
|
5877
|
+
port: readiness.runtime.port,
|
|
5878
|
+
base_url: readiness.baseUrl,
|
|
5879
|
+
host_source: readiness.runtime.hostSource,
|
|
5880
|
+
port_source: readiness.runtime.portSource,
|
|
5881
|
+
metadata_path: readiness.runtime.metadataPath,
|
|
5882
|
+
isolated_mode: readiness.runtime.isolatedMode
|
|
5883
|
+
},
|
|
5884
|
+
process: {
|
|
5885
|
+
component: "mcp",
|
|
5886
|
+
version: componentVersion,
|
|
5887
|
+
pid: process.pid,
|
|
5888
|
+
node_version: process.version,
|
|
5889
|
+
binary_path: process.execPath,
|
|
5890
|
+
argv_entry: process.argv[1]
|
|
5891
|
+
}
|
|
5892
|
+
}
|
|
5893
|
+
} : body;
|
|
5894
|
+
return requestJson(path3, payload);
|
|
5895
|
+
};
|
|
5896
|
+
return {
|
|
5897
|
+
get baseUrl() {
|
|
5898
|
+
return readiness.baseUrl;
|
|
5899
|
+
},
|
|
5900
|
+
ensureReady: readiness.ensureReady,
|
|
5901
|
+
post
|
|
5389
5902
|
};
|
|
5390
|
-
return { baseUrl, post };
|
|
5391
5903
|
};
|
|
5392
5904
|
|
|
5393
5905
|
// packages/mcp-adapter/src/tools.ts
|
|
@@ -5784,10 +6296,11 @@ var TOOL_DEFINITIONS = [
|
|
|
5784
6296
|
}
|
|
5785
6297
|
}
|
|
5786
6298
|
];
|
|
5787
|
-
var createToolHandler = (
|
|
6299
|
+
var createToolHandler = (clientProvider, corePath) => {
|
|
5788
6300
|
return (async (args, _extra) => {
|
|
5789
6301
|
void _extra;
|
|
5790
6302
|
try {
|
|
6303
|
+
const client = typeof clientProvider === "function" ? await clientProvider() : clientProvider;
|
|
5791
6304
|
const envelopeResult = await client.post(corePath, args);
|
|
5792
6305
|
return toToolResult(envelopeResult);
|
|
5793
6306
|
} catch (error) {
|
|
@@ -5799,7 +6312,7 @@ var createToolHandler = (client, corePath) => {
|
|
|
5799
6312
|
}
|
|
5800
6313
|
});
|
|
5801
6314
|
};
|
|
5802
|
-
var registerBrowserBridgeTools = (server,
|
|
6315
|
+
var registerBrowserBridgeTools = (server, clientProvider) => {
|
|
5803
6316
|
for (const tool of TOOL_DEFINITIONS) {
|
|
5804
6317
|
server.registerTool(
|
|
5805
6318
|
tool.name,
|
|
@@ -5809,7 +6322,7 @@ var registerBrowserBridgeTools = (server, client) => {
|
|
|
5809
6322
|
inputSchema: tool.config.inputSchema,
|
|
5810
6323
|
outputSchema: tool.config.outputSchema
|
|
5811
6324
|
},
|
|
5812
|
-
createToolHandler(
|
|
6325
|
+
createToolHandler(clientProvider, tool.config.corePath)
|
|
5813
6326
|
);
|
|
5814
6327
|
}
|
|
5815
6328
|
};
|
|
@@ -5819,53 +6332,290 @@ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
|
5819
6332
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
5820
6333
|
var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
5821
6334
|
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
6335
|
+
|
|
6336
|
+
// packages/mcp-adapter/src/deferred-logger.ts
|
|
6337
|
+
var LOG_LEVEL_PRIORITY2 = {
|
|
6338
|
+
debug: 10,
|
|
6339
|
+
info: 20,
|
|
6340
|
+
warn: 30,
|
|
6341
|
+
error: 40
|
|
6342
|
+
};
|
|
6343
|
+
var isEnabled = (state, level) => LOG_LEVEL_PRIORITY2[level] >= LOG_LEVEL_PRIORITY2[state.level];
|
|
6344
|
+
var enqueue = (state, entry) => {
|
|
6345
|
+
if (state.buffered.length >= state.maxBufferEntries) {
|
|
6346
|
+
state.buffered.shift();
|
|
6347
|
+
state.droppedEntries += 1;
|
|
6348
|
+
}
|
|
6349
|
+
state.buffered.push(entry);
|
|
6350
|
+
};
|
|
6351
|
+
var flushBuffered = (state) => {
|
|
6352
|
+
const destination = state.destination;
|
|
6353
|
+
if (!destination) {
|
|
6354
|
+
return;
|
|
6355
|
+
}
|
|
6356
|
+
if (state.droppedEntries > 0) {
|
|
6357
|
+
destination.warn("mcp.log.buffer.dropped", {
|
|
6358
|
+
dropped_entries: state.droppedEntries
|
|
6359
|
+
});
|
|
6360
|
+
state.droppedEntries = 0;
|
|
6361
|
+
}
|
|
6362
|
+
for (const entry of state.buffered) {
|
|
6363
|
+
destination.log(entry.level, entry.event, {
|
|
6364
|
+
...entry.bindings,
|
|
6365
|
+
...entry.fields
|
|
6366
|
+
});
|
|
6367
|
+
}
|
|
6368
|
+
state.buffered.length = 0;
|
|
6369
|
+
};
|
|
6370
|
+
var buildLogger2 = (state, bindings) => {
|
|
6371
|
+
const log = (level, event, fields = {}) => {
|
|
6372
|
+
if (!isEnabled(state, level)) {
|
|
6373
|
+
return;
|
|
6374
|
+
}
|
|
6375
|
+
if (state.destination) {
|
|
6376
|
+
state.destination.log(level, event, {
|
|
6377
|
+
...bindings,
|
|
6378
|
+
...fields
|
|
6379
|
+
});
|
|
6380
|
+
return;
|
|
6381
|
+
}
|
|
6382
|
+
enqueue(state, {
|
|
6383
|
+
level,
|
|
6384
|
+
event,
|
|
6385
|
+
fields: { ...fields },
|
|
6386
|
+
bindings: { ...bindings }
|
|
6387
|
+
});
|
|
6388
|
+
};
|
|
6389
|
+
return {
|
|
6390
|
+
stream: state.stream,
|
|
6391
|
+
get level() {
|
|
6392
|
+
return state.destination?.level ?? state.level;
|
|
6393
|
+
},
|
|
6394
|
+
get logDir() {
|
|
6395
|
+
return state.destination?.logDir ?? "";
|
|
6396
|
+
},
|
|
6397
|
+
get filePath() {
|
|
6398
|
+
return state.destination?.filePath ?? "";
|
|
6399
|
+
},
|
|
6400
|
+
child: (childBindings) => buildLogger2(state, {
|
|
6401
|
+
...bindings,
|
|
6402
|
+
...childBindings
|
|
6403
|
+
}),
|
|
6404
|
+
log,
|
|
6405
|
+
debug: (event, fields) => log("debug", event, fields),
|
|
6406
|
+
info: (event, fields) => log("info", event, fields),
|
|
6407
|
+
warn: (event, fields) => log("warn", event, fields),
|
|
6408
|
+
error: (event, fields) => log("error", event, fields)
|
|
6409
|
+
};
|
|
6410
|
+
};
|
|
6411
|
+
var createDeferredJsonlLogger = (options) => {
|
|
6412
|
+
const state = {
|
|
6413
|
+
stream: options.stream,
|
|
6414
|
+
level: options.level ?? "debug",
|
|
6415
|
+
destination: null,
|
|
6416
|
+
buffered: [],
|
|
6417
|
+
droppedEntries: 0,
|
|
6418
|
+
maxBufferEntries: Math.max(1, options.maxBufferEntries ?? 2e3)
|
|
6419
|
+
};
|
|
6420
|
+
return {
|
|
6421
|
+
logger: buildLogger2(state, options.bindings ?? {}),
|
|
6422
|
+
activate: () => {
|
|
6423
|
+
if (!state.destination) {
|
|
6424
|
+
state.destination = createJsonlLogger(options);
|
|
6425
|
+
}
|
|
6426
|
+
flushBuffered(state);
|
|
6427
|
+
return state.destination;
|
|
6428
|
+
},
|
|
6429
|
+
isActivated: () => state.destination !== null
|
|
6430
|
+
};
|
|
6431
|
+
};
|
|
6432
|
+
|
|
6433
|
+
// packages/mcp-adapter/src/server.ts
|
|
5822
6434
|
var DEFAULT_SERVER_NAME = "browser-bridge";
|
|
5823
6435
|
var DEFAULT_SERVER_VERSION = "0.0.0";
|
|
5824
|
-
var
|
|
5825
|
-
|
|
5826
|
-
|
|
6436
|
+
var ENV_MCP_EAGER = "BROWSER_BRIDGE_MCP_EAGER";
|
|
6437
|
+
var ENV_LEGACY_MCP_EAGER = "BROWSER_VISION_MCP_EAGER";
|
|
6438
|
+
var parseBoolean2 = (value) => {
|
|
6439
|
+
if (value === void 0) {
|
|
6440
|
+
return void 0;
|
|
6441
|
+
}
|
|
6442
|
+
const normalized = value.trim().toLowerCase();
|
|
6443
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
|
|
6444
|
+
return true;
|
|
6445
|
+
}
|
|
6446
|
+
if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
|
|
6447
|
+
return false;
|
|
6448
|
+
}
|
|
6449
|
+
return void 0;
|
|
6450
|
+
};
|
|
6451
|
+
var resolveEagerMode = (explicit) => {
|
|
6452
|
+
if (typeof explicit === "boolean") {
|
|
6453
|
+
return explicit;
|
|
6454
|
+
}
|
|
6455
|
+
const envValue = parseBoolean2(process.env[ENV_MCP_EAGER]) ?? parseBoolean2(process.env[ENV_LEGACY_MCP_EAGER]);
|
|
6456
|
+
return envValue ?? false;
|
|
6457
|
+
};
|
|
6458
|
+
var toCoreClientOptions = (options, logger) => ({
|
|
6459
|
+
host: options.host,
|
|
6460
|
+
port: options.port,
|
|
6461
|
+
cwd: options.cwd,
|
|
6462
|
+
timeoutMs: options.timeoutMs,
|
|
6463
|
+
ensureDaemon: options.ensureDaemon ?? true,
|
|
6464
|
+
componentVersion: options.version ?? DEFAULT_SERVER_VERSION,
|
|
6465
|
+
healthRetryMs: options.healthRetryMs,
|
|
6466
|
+
healthAttempts: options.healthAttempts,
|
|
6467
|
+
fetchImpl: options.fetchImpl,
|
|
6468
|
+
spawnImpl: options.spawnImpl,
|
|
6469
|
+
logger
|
|
5827
6470
|
});
|
|
5828
|
-
var
|
|
5829
|
-
const
|
|
6471
|
+
var buildInitializationError = (error) => {
|
|
6472
|
+
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "Unknown initialization failure.";
|
|
6473
|
+
return {
|
|
6474
|
+
ok: false,
|
|
6475
|
+
error: {
|
|
6476
|
+
code: "UNAVAILABLE",
|
|
6477
|
+
message: `MCP runtime initialization failed: ${message}`,
|
|
6478
|
+
retryable: true,
|
|
6479
|
+
details: {
|
|
6480
|
+
phase: "mcp_runtime_init"
|
|
6481
|
+
}
|
|
6482
|
+
}
|
|
6483
|
+
};
|
|
6484
|
+
};
|
|
6485
|
+
var resolveDeferredLoggerController = (options) => {
|
|
6486
|
+
if (options.logger) {
|
|
6487
|
+
return {
|
|
6488
|
+
logger: options.logger,
|
|
6489
|
+
activate: () => void 0
|
|
6490
|
+
};
|
|
6491
|
+
}
|
|
6492
|
+
const deferred = createDeferredJsonlLogger({
|
|
6493
|
+
stream: "mcp-adapter",
|
|
6494
|
+
cwd: options.cwd
|
|
6495
|
+
});
|
|
6496
|
+
return {
|
|
6497
|
+
logger: deferred.logger,
|
|
6498
|
+
activate: () => {
|
|
6499
|
+
deferred.activate();
|
|
6500
|
+
}
|
|
6501
|
+
};
|
|
6502
|
+
};
|
|
6503
|
+
var createRuntimeController = (options) => {
|
|
6504
|
+
const deferredLogger = resolveDeferredLoggerController(options);
|
|
6505
|
+
const logger = deferredLogger.logger;
|
|
6506
|
+
const coreLogger = logger.child({ scope: "core-client" });
|
|
6507
|
+
let initializedClient = null;
|
|
6508
|
+
let initializationPromise = null;
|
|
6509
|
+
const createClient = async () => {
|
|
6510
|
+
if (options.coreClient) {
|
|
6511
|
+
return options.coreClient;
|
|
6512
|
+
}
|
|
6513
|
+
if (options.coreClientFactory) {
|
|
6514
|
+
return await options.coreClientFactory(coreLogger);
|
|
6515
|
+
}
|
|
6516
|
+
return createCoreClient(toCoreClientOptions(options, coreLogger));
|
|
6517
|
+
};
|
|
6518
|
+
const proxyClient = {
|
|
6519
|
+
get baseUrl() {
|
|
6520
|
+
return initializedClient?.baseUrl ?? "";
|
|
6521
|
+
},
|
|
6522
|
+
ensureReady: async () => {
|
|
6523
|
+
await ensureInitialized();
|
|
6524
|
+
},
|
|
6525
|
+
post: async (path3, body) => {
|
|
6526
|
+
const client = await ensureInitialized();
|
|
6527
|
+
return client.post(path3, body);
|
|
6528
|
+
}
|
|
6529
|
+
};
|
|
6530
|
+
const ensureInitialized = async () => {
|
|
6531
|
+
if (initializedClient) {
|
|
6532
|
+
return initializedClient;
|
|
6533
|
+
}
|
|
6534
|
+
if (!initializationPromise) {
|
|
6535
|
+
initializationPromise = (async () => {
|
|
6536
|
+
logger.info("mcp.runtime.init.begin");
|
|
6537
|
+
try {
|
|
6538
|
+
const candidate = await createClient();
|
|
6539
|
+
const maybeEnsureReady = candidate.ensureReady;
|
|
6540
|
+
if (typeof maybeEnsureReady === "function") {
|
|
6541
|
+
await maybeEnsureReady.call(candidate);
|
|
6542
|
+
}
|
|
6543
|
+
deferredLogger.activate();
|
|
6544
|
+
initializedClient = candidate;
|
|
6545
|
+
logger.info("mcp.runtime.init.ready", {
|
|
6546
|
+
core_base_url: candidate.baseUrl
|
|
6547
|
+
});
|
|
6548
|
+
return candidate;
|
|
6549
|
+
} catch (error) {
|
|
6550
|
+
logger.error("mcp.runtime.init.failed", {
|
|
6551
|
+
error
|
|
6552
|
+
});
|
|
6553
|
+
throw buildInitializationError(error);
|
|
6554
|
+
}
|
|
6555
|
+
})();
|
|
6556
|
+
initializationPromise = initializationPromise.catch((error) => {
|
|
6557
|
+
initializationPromise = null;
|
|
6558
|
+
throw error;
|
|
6559
|
+
});
|
|
6560
|
+
}
|
|
6561
|
+
return initializationPromise;
|
|
6562
|
+
};
|
|
6563
|
+
return {
|
|
6564
|
+
logger,
|
|
6565
|
+
client: options.coreClient ?? proxyClient,
|
|
6566
|
+
ensureInitialized,
|
|
6567
|
+
isInitialized: () => initializedClient !== null
|
|
6568
|
+
};
|
|
6569
|
+
};
|
|
6570
|
+
var createMcpServerBootstrap = (options = {}) => {
|
|
6571
|
+
const runtime = createRuntimeController(options);
|
|
5830
6572
|
const server = new import_mcp.McpServer({
|
|
5831
6573
|
name: options.name ?? DEFAULT_SERVER_NAME,
|
|
5832
6574
|
version: options.version ?? DEFAULT_SERVER_VERSION
|
|
5833
6575
|
});
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
logger: logger.child({ scope: "core-client" })
|
|
5837
|
-
});
|
|
5838
|
-
registerBrowserBridgeTools(server, client);
|
|
5839
|
-
logger.info("mcp.server.created", {
|
|
6576
|
+
registerBrowserBridgeTools(server, runtime.ensureInitialized);
|
|
6577
|
+
runtime.logger.info("mcp.server.created", {
|
|
5840
6578
|
name: options.name ?? DEFAULT_SERVER_NAME,
|
|
5841
6579
|
version: options.version ?? DEFAULT_SERVER_VERSION,
|
|
5842
|
-
|
|
6580
|
+
lazy_init: true
|
|
5843
6581
|
});
|
|
5844
|
-
return {
|
|
6582
|
+
return {
|
|
6583
|
+
server,
|
|
6584
|
+
client: runtime.client,
|
|
6585
|
+
logger: runtime.logger,
|
|
6586
|
+
ensureInitialized: runtime.ensureInitialized,
|
|
6587
|
+
isInitialized: runtime.isInitialized
|
|
6588
|
+
};
|
|
5845
6589
|
};
|
|
5846
6590
|
var startMcpServer = async (options = {}) => {
|
|
5847
|
-
const
|
|
5848
|
-
|
|
6591
|
+
const eager = resolveEagerMode(options.eager);
|
|
6592
|
+
const handle = createMcpServerBootstrap(options);
|
|
6593
|
+
handle.logger.info("mcp.stdio.start.begin", {
|
|
5849
6594
|
name: options.name ?? DEFAULT_SERVER_NAME,
|
|
5850
|
-
version: options.version ?? DEFAULT_SERVER_VERSION
|
|
5851
|
-
|
|
5852
|
-
const handle = createMcpServer({
|
|
5853
|
-
...options,
|
|
5854
|
-
logger
|
|
6595
|
+
version: options.version ?? DEFAULT_SERVER_VERSION,
|
|
6596
|
+
eager
|
|
5855
6597
|
});
|
|
5856
6598
|
const transport = new import_stdio.StdioServerTransport();
|
|
5857
6599
|
try {
|
|
6600
|
+
if (eager) {
|
|
6601
|
+
await handle.ensureInitialized();
|
|
6602
|
+
}
|
|
5858
6603
|
await handle.server.connect(transport);
|
|
5859
|
-
logger.info("mcp.stdio.start.ready", {
|
|
5860
|
-
core_base_url: handle.client.baseUrl
|
|
6604
|
+
handle.logger.info("mcp.stdio.start.ready", {
|
|
6605
|
+
core_base_url: handle.isInitialized() ? handle.client.baseUrl : null,
|
|
6606
|
+
eager
|
|
5861
6607
|
});
|
|
5862
6608
|
} catch (error) {
|
|
5863
|
-
logger.error("mcp.stdio.start.failed", {
|
|
6609
|
+
handle.logger.error("mcp.stdio.start.failed", {
|
|
5864
6610
|
error
|
|
5865
6611
|
});
|
|
5866
6612
|
throw error;
|
|
5867
6613
|
}
|
|
5868
|
-
return {
|
|
6614
|
+
return {
|
|
6615
|
+
server: handle.server,
|
|
6616
|
+
client: handle.client,
|
|
6617
|
+
transport
|
|
6618
|
+
};
|
|
5869
6619
|
};
|
|
5870
6620
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5871
6621
|
0 && (module.exports = {
|