@yawlabs/mcp 0.65.0 → 0.66.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/dist/index.js +220 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -825,6 +825,7 @@ async function readConfigAt(path5, scope, warnings) {
|
|
|
825
825
|
}
|
|
826
826
|
const servers = Array.isArray(obj.servers) ? obj.servers.filter((v) => typeof v === "string") : void 0;
|
|
827
827
|
const blocked = Array.isArray(obj.blocked) ? obj.blocked.filter((v) => typeof v === "string") : void 0;
|
|
828
|
+
const installNudge = typeof obj.installNudge === "boolean" ? obj.installNudge : void 0;
|
|
828
829
|
if (token5) {
|
|
829
830
|
if (scope === "project") {
|
|
830
831
|
warnings.push(
|
|
@@ -833,7 +834,7 @@ async function readConfigAt(path5, scope, warnings) {
|
|
|
833
834
|
}
|
|
834
835
|
await checkPermissions(path5, warnings);
|
|
835
836
|
}
|
|
836
|
-
return { path: path5, scope, version, token: token5, apiBase, servers, blocked };
|
|
837
|
+
return { path: path5, scope, version, token: token5, apiBase, servers, blocked, installNudge };
|
|
837
838
|
}
|
|
838
839
|
async function checkPermissions(path5, warnings) {
|
|
839
840
|
if (process.platform === "win32") return;
|
|
@@ -855,6 +856,13 @@ function pickServers(files) {
|
|
|
855
856
|
if (project !== void 0) return project;
|
|
856
857
|
return files.find((f) => f.scope === "global")?.servers;
|
|
857
858
|
}
|
|
859
|
+
function pickInstallNudge(files) {
|
|
860
|
+
const local = files.find((f) => f.scope === "local")?.installNudge;
|
|
861
|
+
if (local !== void 0) return local;
|
|
862
|
+
const project = files.find((f) => f.scope === "project")?.installNudge;
|
|
863
|
+
if (project !== void 0) return project;
|
|
864
|
+
return files.find((f) => f.scope === "global")?.installNudge;
|
|
865
|
+
}
|
|
858
866
|
function unionBlocked(files) {
|
|
859
867
|
const set = /* @__PURE__ */ new Set();
|
|
860
868
|
let touched = false;
|
|
@@ -934,6 +942,7 @@ async function loadYawMcpConfig(opts = {}) {
|
|
|
934
942
|
apiBaseSource,
|
|
935
943
|
servers: pickServers(loadedFiles),
|
|
936
944
|
blocked: unionBlocked(loadedFiles),
|
|
945
|
+
installNudge: pickInstallNudge(loadedFiles),
|
|
937
946
|
projectConfigDir,
|
|
938
947
|
loadedFiles,
|
|
939
948
|
warnings
|
|
@@ -963,10 +972,6 @@ function toProfile(config) {
|
|
|
963
972
|
}
|
|
964
973
|
return result;
|
|
965
974
|
}
|
|
966
|
-
async function loadEffectiveProfile(cwd, home) {
|
|
967
|
-
const config = await loadYawMcpConfig({ cwd, home });
|
|
968
|
-
return toProfile(config);
|
|
969
|
-
}
|
|
970
975
|
function isAllowed(rules, namespace) {
|
|
971
976
|
if (!rules) return true;
|
|
972
977
|
if (rules.blocked?.includes(namespace)) return false;
|
|
@@ -2060,6 +2065,18 @@ function cliToNamespaces() {
|
|
|
2060
2065
|
reverseIndexCache = map;
|
|
2061
2066
|
return map;
|
|
2062
2067
|
}
|
|
2068
|
+
var SHADOW_INSTALL_TARGETS = {
|
|
2069
|
+
aws: { package: "@yawlabs/aws-mcp", namespace: "aws", name: "AWS" },
|
|
2070
|
+
caddy: { package: "@yawlabs/caddy-mcp", namespace: "caddy", name: "Caddy" },
|
|
2071
|
+
curl: { package: "@yawlabs/fetch-mcp", namespace: "fetch", name: "Fetch" },
|
|
2072
|
+
wget: { package: "@yawlabs/fetch-mcp", namespace: "fetch", name: "Fetch" },
|
|
2073
|
+
psql: { package: "@yawlabs/postgres-mcp", namespace: "postgres", name: "Postgres" },
|
|
2074
|
+
pg_dump: { package: "@yawlabs/postgres-mcp", namespace: "postgres", name: "Postgres" },
|
|
2075
|
+
tailscale: { package: "@yawlabs/tailscale-mcp", namespace: "tailscale", name: "Tailscale" }
|
|
2076
|
+
};
|
|
2077
|
+
function installTargetForCli(cli) {
|
|
2078
|
+
return SHADOW_INSTALL_TARGETS[cli];
|
|
2079
|
+
}
|
|
2063
2080
|
function formatShadowLine(server) {
|
|
2064
2081
|
const shadows = resolveShadowedClis(server);
|
|
2065
2082
|
if (shadows.length === 0) return null;
|
|
@@ -3987,7 +4004,7 @@ async function runUpgrade(opts = {}) {
|
|
|
3987
4004
|
return { exitCode: 3, lines };
|
|
3988
4005
|
}
|
|
3989
4006
|
function readCurrentVersion() {
|
|
3990
|
-
return true ? "0.
|
|
4007
|
+
return true ? "0.66.0" : "dev";
|
|
3991
4008
|
}
|
|
3992
4009
|
|
|
3993
4010
|
// src/usage-hints.ts
|
|
@@ -4049,7 +4066,7 @@ function selectFlakyNamespaces(entries, limit) {
|
|
|
4049
4066
|
}
|
|
4050
4067
|
|
|
4051
4068
|
// src/doctor-cmd.ts
|
|
4052
|
-
var VERSION = true ? "0.
|
|
4069
|
+
var VERSION = true ? "0.66.0" : "dev";
|
|
4053
4070
|
function isPersistenceDisabled(env) {
|
|
4054
4071
|
const raw = env.YAW_MCP_DISABLE_PERSISTENCE;
|
|
4055
4072
|
return raw !== void 0 && raw !== "" && (raw === "1" || raw.toLowerCase() === "true");
|
|
@@ -6857,7 +6874,7 @@ function defaultSpawn2(cmd, args) {
|
|
|
6857
6874
|
async function maybeAutoUpgrade(deps = {}) {
|
|
6858
6875
|
const optOut = process.env.YAW_MCP_AUTO_UPGRADE;
|
|
6859
6876
|
if (optOut === "0" || optOut?.toLowerCase() === "false") return;
|
|
6860
|
-
const current = deps.currentVersion ?? (true ? "0.
|
|
6877
|
+
const current = deps.currentVersion ?? (true ? "0.66.0" : "dev");
|
|
6861
6878
|
if (current === "dev") return;
|
|
6862
6879
|
const method = (deps.isSeaImpl ? await deps.isSeaImpl() : await detectSea()) ? "binary" : detectInstallMethod(deps.argvPath ?? process.argv[1]);
|
|
6863
6880
|
const latest = await (deps.fetchLatestImpl ?? fetchLatestVersion2)();
|
|
@@ -7590,6 +7607,63 @@ function pushToolCall(history, record, limit = HISTORY_LIMIT) {
|
|
|
7590
7607
|
return history;
|
|
7591
7608
|
}
|
|
7592
7609
|
|
|
7610
|
+
// src/install-nudge.ts
|
|
7611
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
7612
|
+
import { dirname as dirname4, join as join12 } from "path";
|
|
7613
|
+
var INSTALL_NUDGE_MIN_COUNT = 5;
|
|
7614
|
+
var INSTALL_NUDGE_COOLDOWN_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
7615
|
+
var INSTALL_NUDGE_STATE_FILENAME = "install-nudge-state.json";
|
|
7616
|
+
function installNudgeStatePath(home) {
|
|
7617
|
+
return join12(home, CONFIG_DIRNAME, INSTALL_NUDGE_STATE_FILENAME);
|
|
7618
|
+
}
|
|
7619
|
+
function installNudgeEnabled(env, config) {
|
|
7620
|
+
if (env.YAW_MCP_INSTALL_NUDGE === "1") return true;
|
|
7621
|
+
if (config?.installNudge === true) return true;
|
|
7622
|
+
return false;
|
|
7623
|
+
}
|
|
7624
|
+
function readState(home) {
|
|
7625
|
+
const path5 = installNudgeStatePath(home);
|
|
7626
|
+
if (!existsSync7(path5)) return { nudges: [] };
|
|
7627
|
+
try {
|
|
7628
|
+
const parsed = JSON.parse(readFileSync4(path5, "utf8"));
|
|
7629
|
+
if (!parsed || typeof parsed !== "object") return { nudges: [] };
|
|
7630
|
+
const raw = parsed.nudges;
|
|
7631
|
+
if (!Array.isArray(raw)) return { nudges: [] };
|
|
7632
|
+
const nudges = [];
|
|
7633
|
+
for (const entry of raw) {
|
|
7634
|
+
if (entry && typeof entry === "object" && typeof entry.cli === "string" && typeof entry.nudgedAt === "number") {
|
|
7635
|
+
nudges.push({ cli: entry.cli, nudgedAt: entry.nudgedAt });
|
|
7636
|
+
}
|
|
7637
|
+
}
|
|
7638
|
+
return { nudges };
|
|
7639
|
+
} catch {
|
|
7640
|
+
return { nudges: [] };
|
|
7641
|
+
}
|
|
7642
|
+
}
|
|
7643
|
+
function shouldNudge(cli, home, now = Date.now) {
|
|
7644
|
+
const state = readState(home);
|
|
7645
|
+
const rec = state.nudges.find((n) => n.cli === cli);
|
|
7646
|
+
if (!rec) return true;
|
|
7647
|
+
return now() - rec.nudgedAt >= INSTALL_NUDGE_COOLDOWN_MS;
|
|
7648
|
+
}
|
|
7649
|
+
function recordNudge(cli, home, now = Date.now) {
|
|
7650
|
+
try {
|
|
7651
|
+
const at = now();
|
|
7652
|
+
const state = readState(home);
|
|
7653
|
+
const kept = state.nudges.filter((n) => n.cli !== cli && at - n.nudgedAt < INSTALL_NUDGE_COOLDOWN_MS);
|
|
7654
|
+
kept.push({ cli, nudgedAt: at });
|
|
7655
|
+
const path5 = installNudgeStatePath(home);
|
|
7656
|
+
mkdirSync2(dirname4(path5), { recursive: true });
|
|
7657
|
+
writeFileSync2(path5, `${JSON.stringify({ nudges: kept }, null, 2)}
|
|
7658
|
+
`, "utf8");
|
|
7659
|
+
} catch (err) {
|
|
7660
|
+
log("debug", "install-nudge: failed to record nudge state", {
|
|
7661
|
+
cli,
|
|
7662
|
+
error: err instanceof Error ? err.message : String(err)
|
|
7663
|
+
});
|
|
7664
|
+
}
|
|
7665
|
+
}
|
|
7666
|
+
|
|
7593
7667
|
// src/learning.ts
|
|
7594
7668
|
var LEARNING_MIN_OBSERVATIONS = 3;
|
|
7595
7669
|
var LEARNING_MAX_BOOST = 1.1;
|
|
@@ -9353,6 +9427,62 @@ import {
|
|
|
9353
9427
|
ToolListChangedNotificationSchema
|
|
9354
9428
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
9355
9429
|
|
|
9430
|
+
// src/oam-spawn.ts
|
|
9431
|
+
import { execFileSync } from "child_process";
|
|
9432
|
+
import { createRequire } from "module";
|
|
9433
|
+
var requireFrom = createRequire(import.meta.url);
|
|
9434
|
+
function packageName(spec) {
|
|
9435
|
+
const start = spec.startsWith("@") ? 1 : 0;
|
|
9436
|
+
const at = spec.indexOf("@", start);
|
|
9437
|
+
return at === -1 ? spec : spec.slice(0, at);
|
|
9438
|
+
}
|
|
9439
|
+
var oamBinCache;
|
|
9440
|
+
function oamBin() {
|
|
9441
|
+
if (oamBinCache !== void 0) return oamBinCache;
|
|
9442
|
+
const bin = process.env.OAM_BIN || (process.platform === "win32" ? "oam.exe" : "oam");
|
|
9443
|
+
try {
|
|
9444
|
+
execFileSync(bin, ["--version"], { stdio: "ignore" });
|
|
9445
|
+
oamBinCache = bin;
|
|
9446
|
+
} catch {
|
|
9447
|
+
oamBinCache = null;
|
|
9448
|
+
}
|
|
9449
|
+
return oamBinCache;
|
|
9450
|
+
}
|
|
9451
|
+
function rewriteForOam(command, args, deps) {
|
|
9452
|
+
const bin = deps.oamBin;
|
|
9453
|
+
if (!bin) return { command, args };
|
|
9454
|
+
const toOam = (entry, rest) => ({
|
|
9455
|
+
command: bin,
|
|
9456
|
+
args: rest.length > 0 ? ["run", entry, "--", ...rest] : ["run", entry]
|
|
9457
|
+
});
|
|
9458
|
+
if (command === "node") {
|
|
9459
|
+
const [entry, ...rest] = args;
|
|
9460
|
+
if (!entry) return { command, args };
|
|
9461
|
+
return toOam(entry, rest);
|
|
9462
|
+
}
|
|
9463
|
+
if (command === "npx") {
|
|
9464
|
+
const positional = args.filter((a) => a !== "-y" && a !== "--yes");
|
|
9465
|
+
const [spec, ...rest] = positional;
|
|
9466
|
+
if (!spec) return { command, args };
|
|
9467
|
+
const entry = deps.resolveEntry(packageName(spec));
|
|
9468
|
+
if (!entry) return { command, args };
|
|
9469
|
+
return toOam(entry, rest);
|
|
9470
|
+
}
|
|
9471
|
+
return { command, args };
|
|
9472
|
+
}
|
|
9473
|
+
function resolveOamSpawn(command, args) {
|
|
9474
|
+
return rewriteForOam(command, args, {
|
|
9475
|
+
oamBin: oamBin(),
|
|
9476
|
+
resolveEntry: (pkg) => {
|
|
9477
|
+
try {
|
|
9478
|
+
return requireFrom.resolve(pkg);
|
|
9479
|
+
} catch {
|
|
9480
|
+
return null;
|
|
9481
|
+
}
|
|
9482
|
+
}
|
|
9483
|
+
});
|
|
9484
|
+
}
|
|
9485
|
+
|
|
9356
9486
|
// src/uv-bootstrap.ts
|
|
9357
9487
|
import { spawn as spawn5 } from "child_process";
|
|
9358
9488
|
import { createHash as createHash3 } from "crypto";
|
|
@@ -9692,7 +9822,7 @@ function categorizeSpawnError(err) {
|
|
|
9692
9822
|
}
|
|
9693
9823
|
async function connectToUpstream(config, onDisconnect, onListChanged) {
|
|
9694
9824
|
const client = new Client(
|
|
9695
|
-
{ name: "yaw-mcp", version: true ? "0.
|
|
9825
|
+
{ name: "yaw-mcp", version: true ? "0.66.0" : "dev" },
|
|
9696
9826
|
{ capabilities: {} }
|
|
9697
9827
|
);
|
|
9698
9828
|
let transport;
|
|
@@ -9707,7 +9837,10 @@ async function connectToUpstream(config, onDisconnect, onListChanged) {
|
|
|
9707
9837
|
YAW_MCP_VAULT_PASSPHRASE: _excludedVaultPassphrase,
|
|
9708
9838
|
...parentEnv
|
|
9709
9839
|
} = process.env;
|
|
9710
|
-
|
|
9840
|
+
let resolved = await resolveUvSpawn(config.command, config.args ?? []);
|
|
9841
|
+
if (config.runtime === "oam") {
|
|
9842
|
+
resolved = resolveOamSpawn(resolved.command, resolved.args);
|
|
9843
|
+
}
|
|
9711
9844
|
const serverEnv = await resolveServerEnv(config.env ?? {}, config.namespace);
|
|
9712
9845
|
resolvedServerEnv = serverEnv;
|
|
9713
9846
|
const stdioTransport = new StdioClientTransport({
|
|
@@ -10024,7 +10157,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
10024
10157
|
this.apiUrl = apiUrl5;
|
|
10025
10158
|
this.token = token5;
|
|
10026
10159
|
this.server = new Server(
|
|
10027
|
-
{ name: "yaw-mcp", version: true ? "0.
|
|
10160
|
+
{ name: "yaw-mcp", version: true ? "0.66.0" : "dev" },
|
|
10028
10161
|
{
|
|
10029
10162
|
capabilities: {
|
|
10030
10163
|
tools: { listChanged: true },
|
|
@@ -10070,6 +10203,19 @@ var ConnectServer = class _ConnectServer {
|
|
|
10070
10203
|
// same namespace, on deactivate, and on config reconcile.
|
|
10071
10204
|
toolFilters = /* @__PURE__ */ new Map();
|
|
10072
10205
|
profile = null;
|
|
10206
|
+
// Shadow-driven install-nudge gate. Resolved once at start() from the
|
|
10207
|
+
// env override (YAW_MCP_INSTALL_NUDGE=1) OR config (installNudge: true);
|
|
10208
|
+
// off by default. When false, discover NEVER runs the shell-history scan
|
|
10209
|
+
// and its output is byte-identical to today (the load-bearing privacy
|
|
10210
|
+
// property). See install-nudge.ts. Stays false in unit tests that skip
|
|
10211
|
+
// start(), so the nudge block is opt-in there too.
|
|
10212
|
+
installNudge = false;
|
|
10213
|
+
// home / env used by the install-nudge shell-history scan. Default to the
|
|
10214
|
+
// real process values; overridable so tests can point the scan at a
|
|
10215
|
+
// synthetic home + stubbed env without touching the developer's real
|
|
10216
|
+
// shell history or ~/.yaw-mcp/ state file.
|
|
10217
|
+
nudgeHome = homedir16();
|
|
10218
|
+
nudgeEnv = process.env;
|
|
10073
10219
|
// Loaded YAW-MCP.md guides (user-global + project-local). Null until
|
|
10074
10220
|
// start() has run the loader; fail-open if either file is missing,
|
|
10075
10221
|
// unreadable, or empty.
|
|
@@ -10294,7 +10440,8 @@ var ConnectServer = class _ConnectServer {
|
|
|
10294
10440
|
}
|
|
10295
10441
|
this.persistenceReady = true;
|
|
10296
10442
|
}
|
|
10297
|
-
|
|
10443
|
+
const resolvedConfig = await loadYawMcpConfig({ cwd: process.cwd() }).catch(() => null);
|
|
10444
|
+
this.profile = resolvedConfig ? toProfile(resolvedConfig) : null;
|
|
10298
10445
|
if (this.profile) {
|
|
10299
10446
|
log("info", "Loaded profile", {
|
|
10300
10447
|
path: this.profile.path,
|
|
@@ -10303,6 +10450,10 @@ var ConnectServer = class _ConnectServer {
|
|
|
10303
10450
|
block: this.profile.blocked
|
|
10304
10451
|
});
|
|
10305
10452
|
}
|
|
10453
|
+
this.installNudge = installNudgeEnabled(process.env, resolvedConfig);
|
|
10454
|
+
if (this.installNudge) {
|
|
10455
|
+
log("info", "Shadow-driven install nudge enabled");
|
|
10456
|
+
}
|
|
10306
10457
|
this.guides = await loadGuides(process.cwd()).catch(() => ({ user: null, project: null }));
|
|
10307
10458
|
if (this.guides.user || this.guides.project) {
|
|
10308
10459
|
log("info", "Loaded YAW-MCP.md guide", {
|
|
@@ -11097,6 +11248,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
11097
11248
|
lines.push(` ${server.namespace} \u2014 ${server.name} (disabled in dashboard)`);
|
|
11098
11249
|
}
|
|
11099
11250
|
}
|
|
11251
|
+
lines.push(...this.buildInstallCandidatesLines(activeServers));
|
|
11100
11252
|
const activeCount = this.connections.size;
|
|
11101
11253
|
const totalTools = Array.from(this.connections.values()).reduce((sum, c) => {
|
|
11102
11254
|
const f = this.toolFilters.get(c.config.namespace);
|
|
@@ -11115,6 +11267,51 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
11115
11267
|
}
|
|
11116
11268
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
11117
11269
|
}
|
|
11270
|
+
// Build the opt-in "Install candidates" block from the offline shell-
|
|
11271
|
+
// history shadow scan. Returns [] (no lines, byte-identical output) when
|
|
11272
|
+
// the gate is off — the load-bearing privacy property: with the gate
|
|
11273
|
+
// unset the scan never runs and nothing about shell history is read.
|
|
11274
|
+
//
|
|
11275
|
+
// When ON, for each heavily-used CLI the scan found:
|
|
11276
|
+
// - skip unless count >= INSTALL_NUDGE_MIN_COUNT (noise floor),
|
|
11277
|
+
// - skip unless a FIRST-PARTY install target exists (installTargetForCli;
|
|
11278
|
+
// a CLI like kubectl/npm/ssh with no target produces no nudge),
|
|
11279
|
+
// - skip if ANY namespace the CLI maps to is already installed (the user
|
|
11280
|
+
// already has a server that covers it — intersect the hit's namespaces
|
|
11281
|
+
// with the installed set),
|
|
11282
|
+
// - skip if the per-CLI cooldown hasn't elapsed (shouldNudge).
|
|
11283
|
+
// Surviving CLIs are recorded (recordNudge) so they stay suppressed for
|
|
11284
|
+
// the cooldown, and rendered as one line + an mcp_connect_install sketch.
|
|
11285
|
+
//
|
|
11286
|
+
// Privacy: the only data emitted is the aggregate integer count + the
|
|
11287
|
+
// first-party package / namespace / name. No raw history line, command
|
|
11288
|
+
// text, or argument ever reaches this output, and nothing here is sent to
|
|
11289
|
+
// analytics — scanShellHistoryForShadows is local-only and returns just
|
|
11290
|
+
// { cli, count, namespaces }.
|
|
11291
|
+
buildInstallCandidatesLines(activeServers) {
|
|
11292
|
+
if (!this.installNudge) return [];
|
|
11293
|
+
const installedNamespaces = new Set(activeServers.map((s) => s.namespace));
|
|
11294
|
+
const hits = scanShellHistoryForShadows({ home: this.nudgeHome, env: this.nudgeEnv });
|
|
11295
|
+
const candidates = [];
|
|
11296
|
+
for (const hit of hits) {
|
|
11297
|
+
if (hit.count < INSTALL_NUDGE_MIN_COUNT) continue;
|
|
11298
|
+
if (hit.namespaces.some((ns) => installedNamespaces.has(ns))) continue;
|
|
11299
|
+
const target = installTargetForCli(hit.cli);
|
|
11300
|
+
if (!target) continue;
|
|
11301
|
+
if (installedNamespaces.has(target.namespace)) continue;
|
|
11302
|
+
if (!shouldNudge(hit.cli, this.nudgeHome)) continue;
|
|
11303
|
+
candidates.push({ cli: hit.cli, count: hit.count, target });
|
|
11304
|
+
}
|
|
11305
|
+
if (candidates.length === 0) return [];
|
|
11306
|
+
const lines = ["\nInstall candidates (from your recent shell usage; history stays local):"];
|
|
11307
|
+
for (const { cli, count, target } of candidates) {
|
|
11308
|
+
lines.push(` ${cli.padEnd(10)} (ran ${count}x recently) -> install ${target.package}`);
|
|
11309
|
+
const sketch = `mcp_connect_install({ name: ${JSON.stringify(target.name)}, namespace: ${JSON.stringify(target.namespace)}, type: "local", command: "npx", args: ["-y", ${JSON.stringify(target.package)}] })`;
|
|
11310
|
+
lines.push(` ${sketch}`);
|
|
11311
|
+
recordNudge(cli, this.nudgeHome);
|
|
11312
|
+
}
|
|
11313
|
+
return lines;
|
|
11314
|
+
}
|
|
11118
11315
|
// Activate a single server by namespace. Shared by handleActivate,
|
|
11119
11316
|
// handleDispatch, and handleDiscoverWithAutoWarm so error handling,
|
|
11120
11317
|
// retries, caching, and tool-report round-trips live in one place.
|
|
@@ -12581,16 +12778,16 @@ function truncateVersion(v) {
|
|
|
12581
12778
|
import { homedir as homedir17 } from "os";
|
|
12582
12779
|
|
|
12583
12780
|
// src/sync-state.ts
|
|
12584
|
-
import { existsSync as
|
|
12781
|
+
import { existsSync as existsSync8 } from "fs";
|
|
12585
12782
|
import { mkdir as mkdir5, readFile as readFile13 } from "fs/promises";
|
|
12586
|
-
import { dirname as
|
|
12783
|
+
import { dirname as dirname5, join as join13 } from "path";
|
|
12587
12784
|
var SYNC_STATE_FILENAME = "sync-state.json";
|
|
12588
12785
|
function syncStatePath(home) {
|
|
12589
|
-
return
|
|
12786
|
+
return join13(home, CONFIG_DIRNAME, SYNC_STATE_FILENAME);
|
|
12590
12787
|
}
|
|
12591
12788
|
async function readSyncState(home) {
|
|
12592
12789
|
const path5 = syncStatePath(home);
|
|
12593
|
-
if (!
|
|
12790
|
+
if (!existsSync8(path5)) return {};
|
|
12594
12791
|
try {
|
|
12595
12792
|
const raw = await readFile13(path5, "utf8");
|
|
12596
12793
|
const parsed = JSON.parse(raw);
|
|
@@ -12602,7 +12799,7 @@ async function readSyncState(home) {
|
|
|
12602
12799
|
}
|
|
12603
12800
|
async function writeSyncState(home, state) {
|
|
12604
12801
|
const path5 = syncStatePath(home);
|
|
12605
|
-
await mkdir5(
|
|
12802
|
+
await mkdir5(dirname5(path5), { recursive: true });
|
|
12606
12803
|
const existing = await readSyncState(home);
|
|
12607
12804
|
const merged = { ...existing, ...state };
|
|
12608
12805
|
await atomicWriteFile(path5, `${JSON.stringify(merged, null, 2)}
|
|
@@ -12967,10 +13164,10 @@ function suggestFlag(input, limit = 2) {
|
|
|
12967
13164
|
}
|
|
12968
13165
|
|
|
12969
13166
|
// src/sync-cmd.ts
|
|
12970
|
-
import { existsSync as
|
|
13167
|
+
import { existsSync as existsSync9 } from "fs";
|
|
12971
13168
|
import { mkdir as mkdir6, readFile as readFile14 } from "fs/promises";
|
|
12972
13169
|
import { homedir as homedir19 } from "os";
|
|
12973
|
-
import { dirname as
|
|
13170
|
+
import { dirname as dirname6, join as join14 } from "path";
|
|
12974
13171
|
var SYNC_USAGE = `Usage: yaw-mcp sync <push|pull|status> [--json]
|
|
12975
13172
|
|
|
12976
13173
|
Replicate ~/.yaw-mcp/bundles.json across machines via your Yaw
|
|
@@ -13017,11 +13214,11 @@ ${SYNC_USAGE}` };
|
|
|
13017
13214
|
return { ok: true, options: opts };
|
|
13018
13215
|
}
|
|
13019
13216
|
function bundlesPath(home) {
|
|
13020
|
-
return
|
|
13217
|
+
return join14(home, CONFIG_DIRNAME, BUNDLES_FILENAME2);
|
|
13021
13218
|
}
|
|
13022
13219
|
async function readLocalBundles(home) {
|
|
13023
13220
|
const path5 = bundlesPath(home);
|
|
13024
|
-
if (!
|
|
13221
|
+
if (!existsSync9(path5)) return { version: 1, servers: [] };
|
|
13025
13222
|
const raw = await readFile14(path5, "utf8");
|
|
13026
13223
|
let parsed;
|
|
13027
13224
|
try {
|
|
@@ -13037,7 +13234,7 @@ async function readLocalBundles(home) {
|
|
|
13037
13234
|
}
|
|
13038
13235
|
async function writeLocalBundles(home, file) {
|
|
13039
13236
|
const path5 = bundlesPath(home);
|
|
13040
|
-
await mkdir6(
|
|
13237
|
+
await mkdir6(dirname6(path5), { recursive: true });
|
|
13041
13238
|
await atomicWriteFile(path5, `${JSON.stringify(file, null, 2)}
|
|
13042
13239
|
`);
|
|
13043
13240
|
return path5;
|
|
@@ -13648,7 +13845,7 @@ if (subcommand === "compliance") {
|
|
|
13648
13845
|
`);
|
|
13649
13846
|
process.exit(0);
|
|
13650
13847
|
} else if (subcommand === "--version" || subcommand === "-V") {
|
|
13651
|
-
process.stdout.write(`yaw-mcp ${true ? "0.
|
|
13848
|
+
process.stdout.write(`yaw-mcp ${true ? "0.66.0" : "dev"}
|
|
13652
13849
|
`);
|
|
13653
13850
|
process.exit(0);
|
|
13654
13851
|
} else if (subcommand && !subcommand.startsWith("-")) {
|
package/package.json
CHANGED