viyv-browser-mcp 0.10.2 → 0.10.3
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/index.js +236 -113
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2988,7 +2988,7 @@ var require_compile = __commonJS({
|
|
|
2988
2988
|
const schOrFunc = root.refs[ref];
|
|
2989
2989
|
if (schOrFunc)
|
|
2990
2990
|
return schOrFunc;
|
|
2991
|
-
let _sch =
|
|
2991
|
+
let _sch = resolve4.call(this, root, ref);
|
|
2992
2992
|
if (_sch === void 0) {
|
|
2993
2993
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2994
2994
|
const { schemaId } = this.opts;
|
|
@@ -3015,7 +3015,7 @@ var require_compile = __commonJS({
|
|
|
3015
3015
|
function sameSchemaEnv(s1, s2) {
|
|
3016
3016
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3017
3017
|
}
|
|
3018
|
-
function
|
|
3018
|
+
function resolve4(root, ref) {
|
|
3019
3019
|
let sch;
|
|
3020
3020
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3021
3021
|
ref = sch;
|
|
@@ -3590,7 +3590,7 @@ var require_fast_uri = __commonJS({
|
|
|
3590
3590
|
}
|
|
3591
3591
|
return uri;
|
|
3592
3592
|
}
|
|
3593
|
-
function
|
|
3593
|
+
function resolve4(baseURI, relativeURI, options) {
|
|
3594
3594
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3595
3595
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3596
3596
|
schemelessOptions.skipEscape = true;
|
|
@@ -3817,7 +3817,7 @@ var require_fast_uri = __commonJS({
|
|
|
3817
3817
|
var fastUri = {
|
|
3818
3818
|
SCHEMES,
|
|
3819
3819
|
normalize: normalize2,
|
|
3820
|
-
resolve:
|
|
3820
|
+
resolve: resolve4,
|
|
3821
3821
|
resolveComponent,
|
|
3822
3822
|
equal,
|
|
3823
3823
|
serialize,
|
|
@@ -11452,10 +11452,10 @@ var require_raw_body = __commonJS({
|
|
|
11452
11452
|
if (done) {
|
|
11453
11453
|
return readStream(stream, encoding, length, limit, wrap(done));
|
|
11454
11454
|
}
|
|
11455
|
-
return new Promise(function executor(
|
|
11455
|
+
return new Promise(function executor(resolve4, reject) {
|
|
11456
11456
|
readStream(stream, encoding, length, limit, function onRead(err, buf) {
|
|
11457
11457
|
if (err) return reject(err);
|
|
11458
|
-
|
|
11458
|
+
resolve4(buf);
|
|
11459
11459
|
});
|
|
11460
11460
|
});
|
|
11461
11461
|
}
|
|
@@ -11695,7 +11695,7 @@ var require_content_type = __commonJS({
|
|
|
11695
11695
|
|
|
11696
11696
|
// src/native-host/bridge.ts
|
|
11697
11697
|
import { randomUUID } from "crypto";
|
|
11698
|
-
import { readFileSync as
|
|
11698
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
11699
11699
|
import { createServer as createServer2 } from "net";
|
|
11700
11700
|
import { join as join2 } from "path";
|
|
11701
11701
|
|
|
@@ -11840,59 +11840,156 @@ function shouldBroadcastClosing(reason) {
|
|
|
11840
11840
|
}
|
|
11841
11841
|
}
|
|
11842
11842
|
|
|
11843
|
+
// ../shared/dist/util/semver.js
|
|
11844
|
+
function compareSemver(a, b) {
|
|
11845
|
+
const pa = a.split(".").map((s) => Number.parseInt(s, 10));
|
|
11846
|
+
const pb = b.split(".").map((s) => Number.parseInt(s, 10));
|
|
11847
|
+
for (let i = 0; i < 3; i++) {
|
|
11848
|
+
const ai = Number.isFinite(pa[i]) ? pa[i] : 0;
|
|
11849
|
+
const bi = Number.isFinite(pb[i]) ? pb[i] : 0;
|
|
11850
|
+
const diff = ai - bi;
|
|
11851
|
+
if (diff !== 0)
|
|
11852
|
+
return diff;
|
|
11853
|
+
}
|
|
11854
|
+
return 0;
|
|
11855
|
+
}
|
|
11856
|
+
|
|
11843
11857
|
// src/native-host-updater.ts
|
|
11844
|
-
import {
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
renameSync,
|
|
11851
|
-
unlinkSync
|
|
11852
|
-
} from "fs";
|
|
11858
|
+
import { chmodSync, copyFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
11859
|
+
import { resolve as resolve2 } from "path";
|
|
11860
|
+
import { fileURLToPath } from "url";
|
|
11861
|
+
|
|
11862
|
+
// src/native-host/deployment-state.ts
|
|
11863
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "fs";
|
|
11853
11864
|
import { homedir } from "os";
|
|
11854
11865
|
import { resolve } from "path";
|
|
11855
|
-
|
|
11866
|
+
function getNativeHostDir() {
|
|
11867
|
+
return resolve(homedir(), ".viyv-browser", "native-host");
|
|
11868
|
+
}
|
|
11869
|
+
function getDeploymentBinaryPath() {
|
|
11870
|
+
return resolve(getNativeHostDir(), "index.js");
|
|
11871
|
+
}
|
|
11872
|
+
function getDeploymentVersionPath() {
|
|
11873
|
+
return resolve(getNativeHostDir(), "version");
|
|
11874
|
+
}
|
|
11875
|
+
var SEMVER_CORE = /^\d+\.\d+\.\d+/;
|
|
11876
|
+
function readDeploymentState() {
|
|
11877
|
+
const versionPath = getDeploymentVersionPath();
|
|
11878
|
+
if (!existsSync(versionPath)) {
|
|
11879
|
+
return { version: null };
|
|
11880
|
+
}
|
|
11881
|
+
try {
|
|
11882
|
+
const raw = readFileSync(versionPath, "utf-8").trim();
|
|
11883
|
+
if (!raw || !SEMVER_CORE.test(raw)) {
|
|
11884
|
+
return { version: null };
|
|
11885
|
+
}
|
|
11886
|
+
return { version: raw };
|
|
11887
|
+
} catch {
|
|
11888
|
+
return { version: null };
|
|
11889
|
+
}
|
|
11890
|
+
}
|
|
11891
|
+
function writeDeploymentVersion(version2) {
|
|
11892
|
+
const dir = getNativeHostDir();
|
|
11893
|
+
mkdirSync(dir, { recursive: true });
|
|
11894
|
+
const target = getDeploymentVersionPath();
|
|
11895
|
+
const tmp = resolve(dir, `version.tmp.${process.pid}`);
|
|
11896
|
+
try {
|
|
11897
|
+
writeFileSync(tmp, `${version2}
|
|
11898
|
+
`, "utf-8");
|
|
11899
|
+
renameSync(tmp, target);
|
|
11900
|
+
} catch (err) {
|
|
11901
|
+
try {
|
|
11902
|
+
unlinkSync(tmp);
|
|
11903
|
+
} catch {
|
|
11904
|
+
}
|
|
11905
|
+
throw err;
|
|
11906
|
+
}
|
|
11907
|
+
}
|
|
11908
|
+
|
|
11909
|
+
// src/native-host/sync-policy.ts
|
|
11910
|
+
function decideSyncAction(state, selfVersion) {
|
|
11911
|
+
if (state.version === null) {
|
|
11912
|
+
return {
|
|
11913
|
+
shouldSync: true,
|
|
11914
|
+
reason: "no-deploy-version",
|
|
11915
|
+
deployedVersion: null,
|
|
11916
|
+
selfVersion
|
|
11917
|
+
};
|
|
11918
|
+
}
|
|
11919
|
+
const cmp = compareSemver(selfVersion, state.version);
|
|
11920
|
+
if (cmp > 0) {
|
|
11921
|
+
return {
|
|
11922
|
+
shouldSync: true,
|
|
11923
|
+
reason: "upgrade",
|
|
11924
|
+
deployedVersion: state.version,
|
|
11925
|
+
selfVersion
|
|
11926
|
+
};
|
|
11927
|
+
}
|
|
11928
|
+
if (cmp === 0) {
|
|
11929
|
+
return {
|
|
11930
|
+
shouldSync: true,
|
|
11931
|
+
reason: "same-version-idempotent",
|
|
11932
|
+
deployedVersion: state.version,
|
|
11933
|
+
selfVersion
|
|
11934
|
+
};
|
|
11935
|
+
}
|
|
11936
|
+
return {
|
|
11937
|
+
shouldSync: false,
|
|
11938
|
+
reason: "avoid-downgrade",
|
|
11939
|
+
deployedVersion: state.version,
|
|
11940
|
+
selfVersion
|
|
11941
|
+
};
|
|
11942
|
+
}
|
|
11943
|
+
|
|
11944
|
+
// src/native-host-updater.ts
|
|
11856
11945
|
var PKG_VERSION = (() => {
|
|
11857
|
-
if (true) return "0.10.
|
|
11946
|
+
if (true) return "0.10.3";
|
|
11858
11947
|
try {
|
|
11859
11948
|
const here = fileURLToPath(import.meta.url);
|
|
11860
|
-
const pkgPath =
|
|
11861
|
-
const pkg = JSON.parse(
|
|
11949
|
+
const pkgPath = resolve2(here, "..", "..", "package.json");
|
|
11950
|
+
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
11862
11951
|
return pkg.version ?? "0.0.0-test";
|
|
11863
11952
|
} catch {
|
|
11864
11953
|
return "0.0.0-test";
|
|
11865
11954
|
}
|
|
11866
11955
|
})();
|
|
11867
|
-
var NATIVE_HOST_DIR = resolve(homedir(), ".viyv-browser", "native-host");
|
|
11868
11956
|
function getSourceBinaryPath() {
|
|
11869
11957
|
return fileURLToPath(import.meta.url);
|
|
11870
11958
|
}
|
|
11871
11959
|
function getNativeHostBinaryPath() {
|
|
11872
|
-
return
|
|
11960
|
+
return getDeploymentBinaryPath();
|
|
11873
11961
|
}
|
|
11874
11962
|
function isNativeHostDeployed() {
|
|
11875
|
-
return
|
|
11963
|
+
return existsSync2(getNativeHostBinaryPath());
|
|
11876
11964
|
}
|
|
11877
11965
|
function syncNativeHostBinary() {
|
|
11878
11966
|
const source = getSourceBinaryPath();
|
|
11879
|
-
if (!
|
|
11967
|
+
if (!existsSync2(source)) {
|
|
11880
11968
|
throw new Error(`Source binary not found: ${source}`);
|
|
11881
11969
|
}
|
|
11882
|
-
|
|
11970
|
+
const dir = getNativeHostDir();
|
|
11971
|
+
mkdirSync2(dir, { recursive: true });
|
|
11883
11972
|
const target = getNativeHostBinaryPath();
|
|
11884
|
-
const tmp =
|
|
11973
|
+
const tmp = resolve2(dir, `index.js.tmp.${process.pid}`);
|
|
11885
11974
|
try {
|
|
11886
11975
|
copyFileSync(source, tmp);
|
|
11887
11976
|
chmodSync(tmp, 493);
|
|
11888
|
-
|
|
11977
|
+
renameSync2(tmp, target);
|
|
11889
11978
|
} catch (err) {
|
|
11890
11979
|
try {
|
|
11891
|
-
|
|
11980
|
+
unlinkSync2(tmp);
|
|
11892
11981
|
} catch {
|
|
11893
11982
|
}
|
|
11894
11983
|
throw err;
|
|
11895
11984
|
}
|
|
11985
|
+
writeDeploymentVersion(PKG_VERSION);
|
|
11986
|
+
}
|
|
11987
|
+
function syncNativeHostBinaryIfNeeded() {
|
|
11988
|
+
const decision = decideSyncAction(readDeploymentState(), PKG_VERSION);
|
|
11989
|
+
if (decision.shouldSync) {
|
|
11990
|
+
syncNativeHostBinary();
|
|
11991
|
+
}
|
|
11992
|
+
return decision;
|
|
11896
11993
|
}
|
|
11897
11994
|
function shouldUpdateBridge(bridgeVersion) {
|
|
11898
11995
|
return compareSemver(PKG_VERSION, bridgeVersion) > 0;
|
|
@@ -11900,20 +11997,11 @@ function shouldUpdateBridge(bridgeVersion) {
|
|
|
11900
11997
|
function getPackageVersion() {
|
|
11901
11998
|
return PKG_VERSION;
|
|
11902
11999
|
}
|
|
11903
|
-
function compareSemver(a, b) {
|
|
11904
|
-
const pa = a.split(".").map(Number);
|
|
11905
|
-
const pb = b.split(".").map(Number);
|
|
11906
|
-
for (let i = 0; i < 3; i++) {
|
|
11907
|
-
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
11908
|
-
if (diff !== 0) return diff;
|
|
11909
|
-
}
|
|
11910
|
-
return 0;
|
|
11911
|
-
}
|
|
11912
12000
|
|
|
11913
12001
|
// src/native-host/bridge-control.ts
|
|
11914
12002
|
import { randomBytes } from "crypto";
|
|
11915
12003
|
import { createServer } from "net";
|
|
11916
|
-
import { chmodSync as chmodSync2, mkdirSync as
|
|
12004
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
11917
12005
|
import { dirname } from "path";
|
|
11918
12006
|
var LOG_PREFIX = "[viyv-browser:native-host:control]";
|
|
11919
12007
|
function startBridgeControl(opts) {
|
|
@@ -11923,9 +12011,9 @@ function startBridgeControl(opts) {
|
|
|
11923
12011
|
const { deps, onError } = opts;
|
|
11924
12012
|
let cookie;
|
|
11925
12013
|
try {
|
|
11926
|
-
|
|
12014
|
+
mkdirSync3(dirname(cookiePath), { recursive: true });
|
|
11927
12015
|
cookie = randomBytes(BRIDGE.CONTROL_COOKIE_BYTES);
|
|
11928
|
-
|
|
12016
|
+
writeFileSync2(cookiePath, cookie.toString("hex"), { mode: 384 });
|
|
11929
12017
|
try {
|
|
11930
12018
|
chmodSync2(cookiePath, 384);
|
|
11931
12019
|
} catch {
|
|
@@ -12063,7 +12151,7 @@ function startBridgeControl(opts) {
|
|
|
12063
12151
|
}
|
|
12064
12152
|
|
|
12065
12153
|
// src/native-host/bridge-relay.ts
|
|
12066
|
-
import { readFileSync as
|
|
12154
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
12067
12155
|
import { createConnection } from "net";
|
|
12068
12156
|
import { join } from "path";
|
|
12069
12157
|
|
|
@@ -12165,7 +12253,7 @@ function readProfileIdFromEnv() {
|
|
|
12165
12253
|
const dir = process.env.VIYV_USER_DATA_DIR;
|
|
12166
12254
|
if (!dir) return null;
|
|
12167
12255
|
try {
|
|
12168
|
-
const raw =
|
|
12256
|
+
const raw = readFileSync3(join(dir, "viyv-profile.id"), "utf8").trim();
|
|
12169
12257
|
return raw || null;
|
|
12170
12258
|
} catch {
|
|
12171
12259
|
return null;
|
|
@@ -12841,7 +12929,7 @@ function startBridge(options) {
|
|
|
12841
12929
|
const primaryUserDataDir = process.env.VIYV_USER_DATA_DIR;
|
|
12842
12930
|
if (primaryUserDataDir) {
|
|
12843
12931
|
try {
|
|
12844
|
-
const raw =
|
|
12932
|
+
const raw = readFileSync4(join2(primaryUserDataDir, "viyv-profile.id"), "utf8").trim();
|
|
12845
12933
|
if (raw) {
|
|
12846
12934
|
setProfileId(primaryChromeId, raw);
|
|
12847
12935
|
process.stderr.write(
|
|
@@ -12874,7 +12962,7 @@ function startBridge(options) {
|
|
|
12874
12962
|
|
|
12875
12963
|
// src/server.ts
|
|
12876
12964
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
12877
|
-
import { existsSync as
|
|
12965
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync5, statSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
12878
12966
|
import http from "http";
|
|
12879
12967
|
import { dirname as dirname2 } from "path";
|
|
12880
12968
|
|
|
@@ -24952,7 +25040,7 @@ var Protocol = class {
|
|
|
24952
25040
|
return;
|
|
24953
25041
|
}
|
|
24954
25042
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
24955
|
-
await new Promise((
|
|
25043
|
+
await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
|
|
24956
25044
|
options?.signal?.throwIfAborted();
|
|
24957
25045
|
}
|
|
24958
25046
|
} catch (error2) {
|
|
@@ -24969,7 +25057,7 @@ var Protocol = class {
|
|
|
24969
25057
|
*/
|
|
24970
25058
|
request(request, resultSchema, options) {
|
|
24971
25059
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
24972
|
-
return new Promise((
|
|
25060
|
+
return new Promise((resolve4, reject) => {
|
|
24973
25061
|
const earlyReject = (error2) => {
|
|
24974
25062
|
reject(error2);
|
|
24975
25063
|
};
|
|
@@ -25047,7 +25135,7 @@ var Protocol = class {
|
|
|
25047
25135
|
if (!parseResult.success) {
|
|
25048
25136
|
reject(parseResult.error);
|
|
25049
25137
|
} else {
|
|
25050
|
-
|
|
25138
|
+
resolve4(parseResult.data);
|
|
25051
25139
|
}
|
|
25052
25140
|
} catch (error2) {
|
|
25053
25141
|
reject(error2);
|
|
@@ -25308,12 +25396,12 @@ var Protocol = class {
|
|
|
25308
25396
|
}
|
|
25309
25397
|
} catch {
|
|
25310
25398
|
}
|
|
25311
|
-
return new Promise((
|
|
25399
|
+
return new Promise((resolve4, reject) => {
|
|
25312
25400
|
if (signal.aborted) {
|
|
25313
25401
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
25314
25402
|
return;
|
|
25315
25403
|
}
|
|
25316
|
-
const timeoutId = setTimeout(
|
|
25404
|
+
const timeoutId = setTimeout(resolve4, interval);
|
|
25317
25405
|
signal.addEventListener("abort", () => {
|
|
25318
25406
|
clearTimeout(timeoutId);
|
|
25319
25407
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -26272,7 +26360,7 @@ var McpServer = class {
|
|
|
26272
26360
|
let task = createTaskResult.task;
|
|
26273
26361
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
26274
26362
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
26275
|
-
await new Promise((
|
|
26363
|
+
await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
|
|
26276
26364
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
26277
26365
|
if (!updatedTask) {
|
|
26278
26366
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -27060,12 +27148,12 @@ var StdioServerTransport = class {
|
|
|
27060
27148
|
this.onclose?.();
|
|
27061
27149
|
}
|
|
27062
27150
|
send(message2) {
|
|
27063
|
-
return new Promise((
|
|
27151
|
+
return new Promise((resolve4) => {
|
|
27064
27152
|
const json = serializeMessage(message2);
|
|
27065
27153
|
if (this._stdout.write(json)) {
|
|
27066
|
-
|
|
27154
|
+
resolve4();
|
|
27067
27155
|
} else {
|
|
27068
|
-
this._stdout.once("drain",
|
|
27156
|
+
this._stdout.once("drain", resolve4);
|
|
27069
27157
|
}
|
|
27070
27158
|
});
|
|
27071
27159
|
}
|
|
@@ -27479,7 +27567,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
27479
27567
|
});
|
|
27480
27568
|
if (!chunk) {
|
|
27481
27569
|
if (i === 1) {
|
|
27482
|
-
await new Promise((
|
|
27570
|
+
await new Promise((resolve4) => setTimeout(resolve4));
|
|
27483
27571
|
maxReadCount = 3;
|
|
27484
27572
|
continue;
|
|
27485
27573
|
}
|
|
@@ -27961,9 +28049,9 @@ data:
|
|
|
27961
28049
|
const initRequest = messages.find((m) => isInitializeRequest(m));
|
|
27962
28050
|
const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
|
|
27963
28051
|
if (this._enableJsonResponse) {
|
|
27964
|
-
return new Promise((
|
|
28052
|
+
return new Promise((resolve4) => {
|
|
27965
28053
|
this._streamMapping.set(streamId, {
|
|
27966
|
-
resolveJson:
|
|
28054
|
+
resolveJson: resolve4,
|
|
27967
28055
|
cleanup: () => {
|
|
27968
28056
|
this._streamMapping.delete(streamId);
|
|
27969
28057
|
}
|
|
@@ -28485,11 +28573,11 @@ var BridgeClient = class {
|
|
|
28485
28573
|
* is exhausted or `timeout` if the handshake takes too long.
|
|
28486
28574
|
*/
|
|
28487
28575
|
enqueueToolCall(line) {
|
|
28488
|
-
return new Promise((
|
|
28576
|
+
return new Promise((resolve4, reject) => {
|
|
28489
28577
|
if (this.state === "ready" && this.socket && !this.socket.destroyed) {
|
|
28490
28578
|
try {
|
|
28491
28579
|
this.socket.write(line.endsWith(LINE_TERMINATOR) ? line : line + LINE_TERMINATOR);
|
|
28492
|
-
|
|
28580
|
+
resolve4();
|
|
28493
28581
|
} catch (err) {
|
|
28494
28582
|
reject({ reason: "write-failed", detail: err instanceof Error ? err.message : String(err) });
|
|
28495
28583
|
}
|
|
@@ -28498,7 +28586,7 @@ var BridgeClient = class {
|
|
|
28498
28586
|
const enqueued = this.queue.enqueue({
|
|
28499
28587
|
payload: {
|
|
28500
28588
|
line: line.endsWith(LINE_TERMINATOR) ? line : line + LINE_TERMINATOR,
|
|
28501
|
-
resolve:
|
|
28589
|
+
resolve: resolve4,
|
|
28502
28590
|
reject
|
|
28503
28591
|
},
|
|
28504
28592
|
onFlush: (entry) => {
|
|
@@ -28677,6 +28765,20 @@ function toolCallRejectionToErrorCode(rej) {
|
|
|
28677
28765
|
}
|
|
28678
28766
|
}
|
|
28679
28767
|
|
|
28768
|
+
// src/bridge-protocol/shutdown-request-gate.ts
|
|
28769
|
+
var SHUTDOWN_REQUEST_COOLDOWN_MS = 3e4;
|
|
28770
|
+
function createShutdownGateState() {
|
|
28771
|
+
return { lastSentAt: null, lastVersion: null };
|
|
28772
|
+
}
|
|
28773
|
+
function shouldSendShutdownRequest(state, observedVersion, now, cooldownMs = SHUTDOWN_REQUEST_COOLDOWN_MS) {
|
|
28774
|
+
if (state.lastSentAt === null) return true;
|
|
28775
|
+
if (state.lastVersion !== observedVersion) return true;
|
|
28776
|
+
return now - state.lastSentAt >= cooldownMs;
|
|
28777
|
+
}
|
|
28778
|
+
function markSent(state, version2, now) {
|
|
28779
|
+
return { lastSentAt: now, lastVersion: version2 };
|
|
28780
|
+
}
|
|
28781
|
+
|
|
28680
28782
|
// ../shared/dist/bearer-equals.js
|
|
28681
28783
|
import { timingSafeEqual } from "crypto";
|
|
28682
28784
|
function bearerEquals(header, expectedToken) {
|
|
@@ -34205,6 +34307,7 @@ function computeToolTimeout(tool, input) {
|
|
|
34205
34307
|
var pendingRequests = /* @__PURE__ */ new Map();
|
|
34206
34308
|
var bridgeClient = null;
|
|
34207
34309
|
var bridgeUpdateInfo = null;
|
|
34310
|
+
var shutdownGate = createShutdownGateState();
|
|
34208
34311
|
function getBridgeSocket() {
|
|
34209
34312
|
return bridgeClient?.getSocket() ?? null;
|
|
34210
34313
|
}
|
|
@@ -34325,7 +34428,7 @@ function coerceShape(shape) {
|
|
|
34325
34428
|
return result;
|
|
34326
34429
|
}
|
|
34327
34430
|
function handleFileExport(filePath, result) {
|
|
34328
|
-
|
|
34431
|
+
mkdirSync4(dirname2(filePath), { recursive: true });
|
|
34329
34432
|
let content;
|
|
34330
34433
|
let metadata;
|
|
34331
34434
|
if (typeof result.data === "string") {
|
|
@@ -34345,7 +34448,7 @@ function handleFileExport(filePath, result) {
|
|
|
34345
34448
|
const pages = Array.isArray(result.pages) ? result.pages : [];
|
|
34346
34449
|
metadata = { ok: true, file_path: filePath, page_count: pages.length };
|
|
34347
34450
|
}
|
|
34348
|
-
|
|
34451
|
+
writeFileSync3(filePath, content, "utf-8");
|
|
34349
34452
|
metadata.file_size = Buffer.byteLength(content, "utf-8");
|
|
34350
34453
|
return metadata;
|
|
34351
34454
|
}
|
|
@@ -34733,7 +34836,7 @@ async function handleStreamableHttpRequest(req, res, sessions2) {
|
|
|
34733
34836
|
}
|
|
34734
34837
|
var MAX_BODY_SIZE = 4 * 1024 * 1024;
|
|
34735
34838
|
function parseJsonBody(req) {
|
|
34736
|
-
return new Promise((
|
|
34839
|
+
return new Promise((resolve4, reject) => {
|
|
34737
34840
|
const chunks = [];
|
|
34738
34841
|
let size = 0;
|
|
34739
34842
|
let destroyed = false;
|
|
@@ -34751,7 +34854,7 @@ function parseJsonBody(req) {
|
|
|
34751
34854
|
req.on("end", () => {
|
|
34752
34855
|
if (destroyed) return;
|
|
34753
34856
|
try {
|
|
34754
|
-
|
|
34857
|
+
resolve4(JSON.parse(Buffer.concat(chunks).toString("utf-8")));
|
|
34755
34858
|
} catch (error2) {
|
|
34756
34859
|
reject(new Error(`Invalid JSON: ${error2.message}`));
|
|
34757
34860
|
}
|
|
@@ -34919,15 +35022,24 @@ function handleExtensionMessage(message2) {
|
|
|
34919
35022
|
const bridgeVersion = typeof msg.bridgeVersion === "string" ? msg.bridgeVersion : null;
|
|
34920
35023
|
if (bridgeVersion && shouldUpdateBridge(bridgeVersion)) {
|
|
34921
35024
|
const serverVersion = getPackageVersion();
|
|
34922
|
-
|
|
34923
|
-
|
|
35025
|
+
const nowMs = Date.now();
|
|
35026
|
+
if (shouldSendShutdownRequest(shutdownGate, bridgeVersion, nowMs)) {
|
|
35027
|
+
process.stderr.write(
|
|
35028
|
+
`[viyv-browser:mcp] Bridge version mismatch (bridge=${bridgeVersion}, server=${serverVersion}), requesting restart
|
|
34924
35029
|
`
|
|
34925
|
-
|
|
34926
|
-
|
|
34927
|
-
|
|
34928
|
-
|
|
34929
|
-
|
|
34930
|
-
|
|
35030
|
+
);
|
|
35031
|
+
bridgeUpdateInfo = { from: bridgeVersion, to: serverVersion };
|
|
35032
|
+
const shutdownSock = getBridgeSocket();
|
|
35033
|
+
if (shutdownSock) {
|
|
35034
|
+
shutdownSock.write(
|
|
35035
|
+
`${JSON.stringify({ type: "bridge_shutdown_request", timestamp: nowMs })}
|
|
35036
|
+
`
|
|
35037
|
+
);
|
|
35038
|
+
shutdownGate = markSent(shutdownGate, bridgeVersion, nowMs);
|
|
35039
|
+
}
|
|
35040
|
+
} else {
|
|
35041
|
+
process.stderr.write(
|
|
35042
|
+
`[viyv-browser:mcp] Skipping bridge_shutdown_request \u2014 same version ${bridgeVersion} within cooldown (orphan MCP or external tampering is re-seeding the deploy binary; check for stale viyv-browser-mcp processes)
|
|
34931
35043
|
`
|
|
34932
35044
|
);
|
|
34933
35045
|
}
|
|
@@ -35070,7 +35182,7 @@ async function callExtensionTool(tool, input) {
|
|
|
35070
35182
|
if (paths) {
|
|
35071
35183
|
for (const p of paths) {
|
|
35072
35184
|
try {
|
|
35073
|
-
if (!
|
|
35185
|
+
if (!existsSync3(p) || !statSync(p).isFile()) {
|
|
35074
35186
|
return {
|
|
35075
35187
|
content: [
|
|
35076
35188
|
{
|
|
@@ -35102,7 +35214,7 @@ async function callExtensionTool(tool, input) {
|
|
|
35102
35214
|
let csvData;
|
|
35103
35215
|
if (typeof input.file_path === "string") {
|
|
35104
35216
|
const fp = input.file_path;
|
|
35105
|
-
if (!
|
|
35217
|
+
if (!existsSync3(fp) || !statSync(fp).isFile()) {
|
|
35106
35218
|
return {
|
|
35107
35219
|
content: [
|
|
35108
35220
|
{
|
|
@@ -35114,7 +35226,7 @@ async function callExtensionTool(tool, input) {
|
|
|
35114
35226
|
]
|
|
35115
35227
|
};
|
|
35116
35228
|
}
|
|
35117
|
-
csvData =
|
|
35229
|
+
csvData = readFileSync5(fp, "utf-8");
|
|
35118
35230
|
} else if (typeof input.data === "string") {
|
|
35119
35231
|
csvData = input.data;
|
|
35120
35232
|
}
|
|
@@ -35160,13 +35272,13 @@ async function callExtensionTool(tool, input) {
|
|
|
35160
35272
|
touchSession(agentId);
|
|
35161
35273
|
const client = bridgeClient;
|
|
35162
35274
|
const toolTimeout = computeToolTimeout(tool, input);
|
|
35163
|
-
return new Promise((
|
|
35275
|
+
return new Promise((resolve4) => {
|
|
35164
35276
|
const removeErrorListener = () => {
|
|
35165
35277
|
};
|
|
35166
35278
|
const timer = setTimeout(() => {
|
|
35167
35279
|
pendingRequests.delete(requestId);
|
|
35168
35280
|
removeErrorListener();
|
|
35169
|
-
|
|
35281
|
+
resolve4({
|
|
35170
35282
|
content: [
|
|
35171
35283
|
{
|
|
35172
35284
|
type: "text",
|
|
@@ -35193,12 +35305,12 @@ async function callExtensionTool(tool, input) {
|
|
|
35193
35305
|
if (FILE_EXPORT_TOOLS.has(tool) && typeof filePath === "string" && ("data" in result || "pages" in result)) {
|
|
35194
35306
|
try {
|
|
35195
35307
|
const metadata = handleFileExport(filePath, result);
|
|
35196
|
-
|
|
35308
|
+
resolve4({
|
|
35197
35309
|
content: [{ type: "text", text: JSON.stringify(metadata) }]
|
|
35198
35310
|
});
|
|
35199
35311
|
} catch (e) {
|
|
35200
35312
|
const msg = e instanceof Error ? e.message : String(e);
|
|
35201
|
-
|
|
35313
|
+
resolve4({
|
|
35202
35314
|
content: [
|
|
35203
35315
|
{
|
|
35204
35316
|
type: "text",
|
|
@@ -35217,9 +35329,9 @@ async function callExtensionTool(tool, input) {
|
|
|
35217
35329
|
if (RESULT_EXPORT_TOOLS.has(tool) && typeof filePath === "string") {
|
|
35218
35330
|
try {
|
|
35219
35331
|
const content = JSON.stringify(result, null, 2);
|
|
35220
|
-
|
|
35221
|
-
|
|
35222
|
-
|
|
35332
|
+
mkdirSync4(dirname2(filePath), { recursive: true });
|
|
35333
|
+
writeFileSync3(filePath, content, "utf-8");
|
|
35334
|
+
resolve4({
|
|
35223
35335
|
content: [
|
|
35224
35336
|
{
|
|
35225
35337
|
type: "text",
|
|
@@ -35232,7 +35344,7 @@ async function callExtensionTool(tool, input) {
|
|
|
35232
35344
|
});
|
|
35233
35345
|
} catch (e) {
|
|
35234
35346
|
const msg = e instanceof Error ? e.message : String(e);
|
|
35235
|
-
|
|
35347
|
+
resolve4({
|
|
35236
35348
|
content: [
|
|
35237
35349
|
{
|
|
35238
35350
|
type: "text",
|
|
@@ -35259,21 +35371,21 @@ async function callExtensionTool(tool, input) {
|
|
|
35259
35371
|
}
|
|
35260
35372
|
if (tempImportFile) {
|
|
35261
35373
|
try {
|
|
35262
|
-
|
|
35374
|
+
unlinkSync3(tempImportFile);
|
|
35263
35375
|
} catch {
|
|
35264
35376
|
}
|
|
35265
35377
|
}
|
|
35266
|
-
|
|
35378
|
+
resolve4({ content: buildResponseContent(tool, finalResult) });
|
|
35267
35379
|
},
|
|
35268
35380
|
reject: (error2) => {
|
|
35269
35381
|
removeErrorListener();
|
|
35270
35382
|
if (tempImportFile) {
|
|
35271
35383
|
try {
|
|
35272
|
-
|
|
35384
|
+
unlinkSync3(tempImportFile);
|
|
35273
35385
|
} catch {
|
|
35274
35386
|
}
|
|
35275
35387
|
}
|
|
35276
|
-
|
|
35388
|
+
resolve4({
|
|
35277
35389
|
content: [
|
|
35278
35390
|
{
|
|
35279
35391
|
type: "text",
|
|
@@ -35314,7 +35426,7 @@ async function callExtensionTool(tool, input) {
|
|
|
35314
35426
|
clearTimeout(pending.timer);
|
|
35315
35427
|
pendingRequests.delete(requestId);
|
|
35316
35428
|
const { code, message: message2 } = toolCallRejectionToErrorCode(rej);
|
|
35317
|
-
|
|
35429
|
+
resolve4({
|
|
35318
35430
|
content: [{ type: "text", text: JSON.stringify({ error: { code, message: message2 } }) }]
|
|
35319
35431
|
});
|
|
35320
35432
|
});
|
|
@@ -35338,12 +35450,12 @@ async function handleSwitchBrowser() {
|
|
|
35338
35450
|
setExtensionConnected(false);
|
|
35339
35451
|
}
|
|
35340
35452
|
process.stderr.write("[viyv-browser:mcp] switch_browser: waiting for bridge reconnection...\n");
|
|
35341
|
-
return new Promise((
|
|
35453
|
+
return new Promise((resolve4) => {
|
|
35342
35454
|
const checkInterval = setInterval(() => {
|
|
35343
35455
|
if (bridgeClient?.isReady() && isExtensionConnected()) {
|
|
35344
35456
|
clearInterval(checkInterval);
|
|
35345
35457
|
clearTimeout(timer);
|
|
35346
|
-
|
|
35458
|
+
resolve4({
|
|
35347
35459
|
content: [
|
|
35348
35460
|
{
|
|
35349
35461
|
type: "text",
|
|
@@ -35358,7 +35470,7 @@ async function handleSwitchBrowser() {
|
|
|
35358
35470
|
}, 500);
|
|
35359
35471
|
const timer = setTimeout(() => {
|
|
35360
35472
|
clearInterval(checkInterval);
|
|
35361
|
-
|
|
35473
|
+
resolve4({
|
|
35362
35474
|
content: [
|
|
35363
35475
|
{
|
|
35364
35476
|
type: "text",
|
|
@@ -35377,9 +35489,9 @@ async function handleSwitchBrowser() {
|
|
|
35377
35489
|
|
|
35378
35490
|
// src/setup.ts
|
|
35379
35491
|
import { execSync } from "child_process";
|
|
35380
|
-
import { chmodSync as chmodSync3, existsSync as
|
|
35492
|
+
import { chmodSync as chmodSync3, existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
35381
35493
|
import { homedir as homedir2, platform } from "os";
|
|
35382
|
-
import { dirname as dirname3, resolve as
|
|
35494
|
+
import { dirname as dirname3, resolve as resolve3 } from "path";
|
|
35383
35495
|
function runSetup(options = {}) {
|
|
35384
35496
|
const os = platform();
|
|
35385
35497
|
console.log("Viyv Browser MCP - Native Messaging Host Setup");
|
|
@@ -35411,8 +35523,8 @@ function runSetup(options = {}) {
|
|
|
35411
35523
|
console.log(`Wrapper: ${wrapperPath}`);
|
|
35412
35524
|
for (const manifestPath of manifestPaths) {
|
|
35413
35525
|
console.log(`Manifest path: ${manifestPath}`);
|
|
35414
|
-
|
|
35415
|
-
|
|
35526
|
+
mkdirSync5(dirname3(manifestPath), { recursive: true });
|
|
35527
|
+
writeFileSync4(manifestPath, JSON.stringify(manifest, null, 2));
|
|
35416
35528
|
chmodSync3(manifestPath, 420);
|
|
35417
35529
|
}
|
|
35418
35530
|
console.log("\nNative Messaging Host registered successfully!");
|
|
@@ -35426,17 +35538,17 @@ function runSetup(options = {}) {
|
|
|
35426
35538
|
}
|
|
35427
35539
|
function createNativeHostWrapper(os, binaryPath, dockerMode) {
|
|
35428
35540
|
const manifestDir = dockerMode ? "/etc/chromium/native-messaging-hosts" : dirname3(getManifestPath(os));
|
|
35429
|
-
|
|
35541
|
+
mkdirSync5(manifestDir, { recursive: true });
|
|
35430
35542
|
const nodePath = getNodePath();
|
|
35431
35543
|
if (os === "win32") {
|
|
35432
|
-
const wrapperPath2 =
|
|
35433
|
-
|
|
35544
|
+
const wrapperPath2 = resolve3(manifestDir, `${NATIVE_HOST_NAME}.bat`);
|
|
35545
|
+
writeFileSync4(wrapperPath2, `@echo off\r
|
|
35434
35546
|
"${nodePath}" "${binaryPath}" --native-host\r
|
|
35435
35547
|
`);
|
|
35436
35548
|
return wrapperPath2;
|
|
35437
35549
|
}
|
|
35438
|
-
const wrapperPath =
|
|
35439
|
-
|
|
35550
|
+
const wrapperPath = resolve3(manifestDir, `${NATIVE_HOST_NAME}.sh`);
|
|
35551
|
+
writeFileSync4(wrapperPath, `#!/bin/bash
|
|
35440
35552
|
exec "${nodePath}" "${binaryPath}" --native-host
|
|
35441
35553
|
`);
|
|
35442
35554
|
chmodSync3(wrapperPath, 493);
|
|
@@ -35451,23 +35563,23 @@ function getNodePath() {
|
|
|
35451
35563
|
}
|
|
35452
35564
|
function getDockerManifestPaths() {
|
|
35453
35565
|
return [
|
|
35454
|
-
|
|
35455
|
-
|
|
35566
|
+
resolve3("/etc/chromium/native-messaging-hosts", `${NATIVE_HOST_NAME}.json`),
|
|
35567
|
+
resolve3(homedir2(), ".config/chromium/NativeMessagingHosts", `${NATIVE_HOST_NAME}.json`)
|
|
35456
35568
|
];
|
|
35457
35569
|
}
|
|
35458
35570
|
function getManifestPath(os) {
|
|
35459
35571
|
const home = homedir2();
|
|
35460
35572
|
switch (os) {
|
|
35461
35573
|
case "darwin":
|
|
35462
|
-
return
|
|
35574
|
+
return resolve3(
|
|
35463
35575
|
home,
|
|
35464
35576
|
"Library/Application Support/Google/Chrome/NativeMessagingHosts",
|
|
35465
35577
|
`${NATIVE_HOST_NAME}.json`
|
|
35466
35578
|
);
|
|
35467
35579
|
case "linux":
|
|
35468
|
-
return
|
|
35580
|
+
return resolve3(home, ".config/google-chrome/NativeMessagingHosts", `${NATIVE_HOST_NAME}.json`);
|
|
35469
35581
|
case "win32":
|
|
35470
|
-
return
|
|
35582
|
+
return resolve3(
|
|
35471
35583
|
home,
|
|
35472
35584
|
"AppData/Local/Google/Chrome/User Data/NativeMessagingHosts",
|
|
35473
35585
|
`${NATIVE_HOST_NAME}.json`
|
|
@@ -35487,9 +35599,9 @@ function setupClaudeDesktopConfig() {
|
|
|
35487
35599
|
const configPath = getClaudeDesktopConfigPath();
|
|
35488
35600
|
console.log(`Config path: ${configPath}`);
|
|
35489
35601
|
let config2 = {};
|
|
35490
|
-
if (
|
|
35602
|
+
if (existsSync4(configPath)) {
|
|
35491
35603
|
try {
|
|
35492
|
-
config2 = JSON.parse(
|
|
35604
|
+
config2 = JSON.parse(readFileSync6(configPath, "utf-8"));
|
|
35493
35605
|
} catch {
|
|
35494
35606
|
console.error(
|
|
35495
35607
|
`ERROR: Failed to parse ${configPath}. Fix the JSON manually or delete the file.`
|
|
@@ -35509,8 +35621,8 @@ function setupClaudeDesktopConfig() {
|
|
|
35509
35621
|
env: { PATH: envPath }
|
|
35510
35622
|
};
|
|
35511
35623
|
const configDir = dirname3(configPath);
|
|
35512
|
-
|
|
35513
|
-
|
|
35624
|
+
mkdirSync5(configDir, { recursive: true });
|
|
35625
|
+
writeFileSync4(configPath, JSON.stringify(config2, null, 2));
|
|
35514
35626
|
console.log(`npx path: ${npxPath}`);
|
|
35515
35627
|
console.log("\nClaude Desktop config updated successfully!");
|
|
35516
35628
|
console.log("Please restart Claude Desktop for changes to take effect.");
|
|
@@ -35527,13 +35639,13 @@ function getClaudeDesktopConfigPath() {
|
|
|
35527
35639
|
const home = homedir2();
|
|
35528
35640
|
switch (process.platform) {
|
|
35529
35641
|
case "darwin":
|
|
35530
|
-
return
|
|
35642
|
+
return resolve3(home, "Library/Application Support/Claude/claude_desktop_config.json");
|
|
35531
35643
|
case "linux":
|
|
35532
|
-
return
|
|
35644
|
+
return resolve3(home, ".config/Claude/claude_desktop_config.json");
|
|
35533
35645
|
case "win32":
|
|
35534
|
-
return
|
|
35646
|
+
return resolve3(home, "AppData/Roaming/Claude/claude_desktop_config.json");
|
|
35535
35647
|
default:
|
|
35536
|
-
return
|
|
35648
|
+
return resolve3(home, ".config/Claude/claude_desktop_config.json");
|
|
35537
35649
|
}
|
|
35538
35650
|
}
|
|
35539
35651
|
|
|
@@ -35575,7 +35687,18 @@ if (args.includes("setup")) {
|
|
|
35575
35687
|
const authBearer = authIdx >= 0 ? args[authIdx + 1] : process.env.VIYV_MCP_AUTH_BEARER;
|
|
35576
35688
|
if (isNativeHostDeployed()) {
|
|
35577
35689
|
try {
|
|
35578
|
-
|
|
35690
|
+
const decision = syncNativeHostBinaryIfNeeded();
|
|
35691
|
+
if (decision.shouldSync) {
|
|
35692
|
+
process.stderr.write(
|
|
35693
|
+
`[viyv-browser:mcp] Native host binary synced (self=${decision.selfVersion}, was=${decision.deployedVersion ?? "unknown"}, reason=${decision.reason})
|
|
35694
|
+
`
|
|
35695
|
+
);
|
|
35696
|
+
} else {
|
|
35697
|
+
process.stderr.write(
|
|
35698
|
+
`[viyv-browser:mcp] Native host sync skipped \u2014 deployed v${decision.deployedVersion} is newer than self v${decision.selfVersion} (preventing downgrade by orphan MCP)
|
|
35699
|
+
`
|
|
35700
|
+
);
|
|
35701
|
+
}
|
|
35579
35702
|
} catch (err) {
|
|
35580
35703
|
process.stderr.write(
|
|
35581
35704
|
`[viyv-browser:mcp] WARNING: Failed to update native host binary: ${err.message}
|