@synkro-sh/cli 1.7.93 → 1.7.94
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/bootstrap.js +135 -29
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -147,7 +147,7 @@ function getIdentity() {
|
|
|
147
147
|
if (cached2) return cached2;
|
|
148
148
|
let cliVersion = "0.0.0";
|
|
149
149
|
try {
|
|
150
|
-
cliVersion = "1.7.
|
|
150
|
+
cliVersion = "1.7.94";
|
|
151
151
|
} catch {
|
|
152
152
|
}
|
|
153
153
|
const creds = loadCredentialsIdentity();
|
|
@@ -2147,7 +2147,7 @@ var init_codexHookConfig = __esm({
|
|
|
2147
2147
|
|
|
2148
2148
|
// cli/installer/codexHookTrust.ts
|
|
2149
2149
|
import { spawn as spawn2 } from "child_process";
|
|
2150
|
-
function
|
|
2150
|
+
function parseCodexHookTrustRecords(stdout) {
|
|
2151
2151
|
for (const line of stdout.split("\n")) {
|
|
2152
2152
|
let message;
|
|
2153
2153
|
try {
|
|
@@ -2159,20 +2159,41 @@ function parseCodexHookTrustOutput(stdout) {
|
|
|
2159
2159
|
if (!Array.isArray(data)) continue;
|
|
2160
2160
|
const hooks = data.flatMap((entry) => Array.isArray(entry?.hooks) ? entry.hooks : []).filter((hook) => typeof hook.command === "string" && isSynkroHookCommand(hook.command));
|
|
2161
2161
|
if (!hooks.length) return null;
|
|
2162
|
-
return
|
|
2163
|
-
total: hooks.length,
|
|
2164
|
-
trusted: hooks.filter((hook) => hook.trustStatus === "trusted" || hook.trustStatus === "managed").length,
|
|
2165
|
-
needsReview: hooks.filter((hook) => hook.trustStatus === "modified" || hook.trustStatus === "untrusted").length,
|
|
2166
|
-
disabled: hooks.filter((hook) => hook.enabled === false).length
|
|
2167
|
-
};
|
|
2162
|
+
return hooks;
|
|
2168
2163
|
}
|
|
2169
2164
|
return null;
|
|
2170
2165
|
}
|
|
2171
|
-
function
|
|
2166
|
+
function summarizeCodexHookTrust(hooks) {
|
|
2167
|
+
return {
|
|
2168
|
+
total: hooks.length,
|
|
2169
|
+
trusted: hooks.filter((hook) => hook.trustStatus === "trusted" || hook.trustStatus === "managed").length,
|
|
2170
|
+
needsReview: hooks.filter((hook) => hook.trustStatus === "modified" || hook.trustStatus === "untrusted").length,
|
|
2171
|
+
disabled: hooks.filter((hook) => hook.enabled === false).length
|
|
2172
|
+
};
|
|
2173
|
+
}
|
|
2174
|
+
function parseCodexHookTrustOutput(stdout) {
|
|
2175
|
+
const hooks = parseCodexHookTrustRecords(stdout);
|
|
2176
|
+
return hooks ? summarizeCodexHookTrust(hooks) : null;
|
|
2177
|
+
}
|
|
2178
|
+
function buildCodexHookTrustEdits(hooks) {
|
|
2179
|
+
const edits = /* @__PURE__ */ new Map();
|
|
2180
|
+
for (const hook of hooks) {
|
|
2181
|
+
if (typeof hook.command !== "string" || !isSynkroHookCommand(hook.command) || typeof hook.key !== "string" || !hook.key || typeof hook.currentHash !== "string" || !/^sha256:[0-9a-f]{64}$/i.test(hook.currentHash)) continue;
|
|
2182
|
+
const edit = {
|
|
2183
|
+
keyPath: `hooks.state.${JSON.stringify(hook.key)}.trusted_hash`,
|
|
2184
|
+
value: hook.currentHash,
|
|
2185
|
+
mergeStrategy: "upsert"
|
|
2186
|
+
};
|
|
2187
|
+
edits.set(edit.keyPath, edit);
|
|
2188
|
+
}
|
|
2189
|
+
return [...edits.values()];
|
|
2190
|
+
}
|
|
2191
|
+
function queryCodexHookTrust(codexBinary = "codex", cwd = process.cwd(), autoTrust = false) {
|
|
2172
2192
|
return new Promise((resolve6) => {
|
|
2173
2193
|
let settled = false;
|
|
2174
2194
|
let stdout = "";
|
|
2175
2195
|
let pending = "";
|
|
2196
|
+
let hooks = null;
|
|
2176
2197
|
let child;
|
|
2177
2198
|
const finish = (summary) => {
|
|
2178
2199
|
if (settled) return;
|
|
@@ -2217,7 +2238,32 @@ function inspectCodexHookTrust(codexBinary = "codex", cwd = process.cwd()) {
|
|
|
2217
2238
|
params: { cwds: [cwd] }
|
|
2218
2239
|
}) + "\n");
|
|
2219
2240
|
} else if (message?.id === 2) {
|
|
2220
|
-
|
|
2241
|
+
hooks = parseCodexHookTrustRecords(line);
|
|
2242
|
+
if (!hooks || !autoTrust) {
|
|
2243
|
+
finish(hooks ? summarizeCodexHookTrust(hooks) : null);
|
|
2244
|
+
continue;
|
|
2245
|
+
}
|
|
2246
|
+
const edits = buildCodexHookTrustEdits(hooks);
|
|
2247
|
+
if (!edits.length) {
|
|
2248
|
+
finish(summarizeCodexHookTrust(hooks));
|
|
2249
|
+
continue;
|
|
2250
|
+
}
|
|
2251
|
+
child.stdin.write(JSON.stringify({
|
|
2252
|
+
id: 3,
|
|
2253
|
+
method: "config/batchWrite",
|
|
2254
|
+
params: { edits, reloadUserConfig: true }
|
|
2255
|
+
}) + "\n");
|
|
2256
|
+
} else if (message?.id === 3) {
|
|
2257
|
+
if (message?.result?.status !== "ok" || !hooks) {
|
|
2258
|
+
finish(hooks ? summarizeCodexHookTrust(hooks) : null);
|
|
2259
|
+
continue;
|
|
2260
|
+
}
|
|
2261
|
+
finish({
|
|
2262
|
+
total: hooks.length,
|
|
2263
|
+
trusted: hooks.length,
|
|
2264
|
+
needsReview: 0,
|
|
2265
|
+
disabled: hooks.filter((hook) => hook.enabled === false).length
|
|
2266
|
+
});
|
|
2221
2267
|
}
|
|
2222
2268
|
}
|
|
2223
2269
|
});
|
|
@@ -2234,6 +2280,9 @@ function inspectCodexHookTrust(codexBinary = "codex", cwd = process.cwd()) {
|
|
|
2234
2280
|
}
|
|
2235
2281
|
});
|
|
2236
2282
|
}
|
|
2283
|
+
function trustCodexHooks(codexBinary = "codex", cwd = process.cwd()) {
|
|
2284
|
+
return queryCodexHookTrust(codexBinary, cwd, true);
|
|
2285
|
+
}
|
|
2237
2286
|
function codexHookTrustLines(summary) {
|
|
2238
2287
|
if (!summary) {
|
|
2239
2288
|
return [
|
|
@@ -2254,7 +2303,7 @@ function codexHookTrustLines(summary) {
|
|
|
2254
2303
|
];
|
|
2255
2304
|
}
|
|
2256
2305
|
async function reportCodexHookTrust(codexBinary, cwd) {
|
|
2257
|
-
const summary = await
|
|
2306
|
+
const summary = await trustCodexHooks(codexBinary || "codex", cwd);
|
|
2258
2307
|
for (const line of codexHookTrustLines(summary)) console.log(line);
|
|
2259
2308
|
return summary;
|
|
2260
2309
|
}
|
|
@@ -2428,9 +2477,54 @@ function removeCodexManagedBlock(content, path) {
|
|
|
2428
2477
|
if (inside) throw new Error(`Incomplete Synkro MCP marker block in ${path}`);
|
|
2429
2478
|
return { content: out.join("\n").replace(/\n{3,}$/g, "\n\n"), removed };
|
|
2430
2479
|
}
|
|
2431
|
-
function
|
|
2432
|
-
const section = /^\s*\[\s*mcp_servers\s*\.\s*(?:"synkro-guardrails"|'synkro-guardrails'|synkro-guardrails)\s*\]\s*(?:#.*)?$/
|
|
2433
|
-
|
|
2480
|
+
function findCodexMcpSection(content) {
|
|
2481
|
+
const section = /^\s*\[\s*mcp_servers\s*\.\s*(?:"synkro-guardrails"|'synkro-guardrails'|synkro-guardrails)\s*\]\s*(?:#.*)?$/gm;
|
|
2482
|
+
const match = section.exec(content);
|
|
2483
|
+
if (!match) return null;
|
|
2484
|
+
const nextSection = /^\s*\[{1,2}[^\r\n]+?\]{1,2}\s*(?:#.*)?$/gm;
|
|
2485
|
+
nextSection.lastIndex = match.index + match[0].length;
|
|
2486
|
+
const next = nextSection.exec(content);
|
|
2487
|
+
return {
|
|
2488
|
+
start: match.index,
|
|
2489
|
+
end: next?.index ?? content.length,
|
|
2490
|
+
body: content.slice(match.index, next?.index ?? content.length)
|
|
2491
|
+
};
|
|
2492
|
+
}
|
|
2493
|
+
function readTomlString(block, key) {
|
|
2494
|
+
const match = block.match(new RegExp(`^\\s*${key}\\s*=\\s*("(?:[^"\\\\]|\\\\.)*")\\s*$`, "m"));
|
|
2495
|
+
if (!match) return null;
|
|
2496
|
+
try {
|
|
2497
|
+
return JSON.parse(match[1]);
|
|
2498
|
+
} catch {
|
|
2499
|
+
return null;
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
function isRecognizedCodexEntry(block, expectedUrl) {
|
|
2503
|
+
const command = readTomlString(block, "command");
|
|
2504
|
+
const argsLine = block.match(/^\s*args\s*=\s*(\[[^\r\n]*\])\s*$/m);
|
|
2505
|
+
if (command && argsLine) {
|
|
2506
|
+
try {
|
|
2507
|
+
const args2 = JSON.parse(argsLine[1]);
|
|
2508
|
+
if (/(?:^|[\\/])bun(?:\.exe)?$/i.test(command) && Array.isArray(args2) && args2.length === 2 && args2[0] === "run" && args2[1] === MCP_STDIO_PROXY_PATH) return true;
|
|
2509
|
+
} catch {
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
const url = readTomlString(block, "url");
|
|
2513
|
+
return Boolean(expectedUrl && url === expectedUrl);
|
|
2514
|
+
}
|
|
2515
|
+
function stripDetachedCodexMarkers(content) {
|
|
2516
|
+
return content.split("\n").filter((line) => line.trim() !== CODEX_MCP_BEGIN && line.trim() !== CODEX_MCP_END).join("\n");
|
|
2517
|
+
}
|
|
2518
|
+
function removeRecognizedCodexEntry(content, path, expectedUrl) {
|
|
2519
|
+
const range = findCodexMcpSection(content);
|
|
2520
|
+
if (!range) return { content, removed: false };
|
|
2521
|
+
if (!isRecognizedCodexEntry(range.body, expectedUrl)) {
|
|
2522
|
+
throw new Error(
|
|
2523
|
+
`${path} already defines ${CODEX_MCP_SECTION}; remove or rename that unmanaged entry before installing Synkro`
|
|
2524
|
+
);
|
|
2525
|
+
}
|
|
2526
|
+
const next = `${content.slice(0, range.start)}${content.slice(range.end)}`;
|
|
2527
|
+
return { content: next.replace(/\n{3,}$/g, "\n\n"), removed: true };
|
|
2434
2528
|
}
|
|
2435
2529
|
function tomlString(value) {
|
|
2436
2530
|
return JSON.stringify(value);
|
|
@@ -2438,16 +2532,17 @@ function tomlString(value) {
|
|
|
2438
2532
|
function installCodexMcpConfig(opts) {
|
|
2439
2533
|
const path = codexConfigPath(opts.configPath);
|
|
2440
2534
|
const current = readCodexToml(path);
|
|
2441
|
-
const
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2535
|
+
const targetUrl = opts.local ? `stdio://${MCP_STDIO_PROXY_PATH}` : `${opts.gatewayUrl.replace(/\/$/, "")}/api/v1/mcp/guardrails`;
|
|
2536
|
+
const withoutManaged = stripDetachedCodexMarkers(removeCodexManagedBlock(current, path).content);
|
|
2537
|
+
const withoutExisting = removeRecognizedCodexEntry(
|
|
2538
|
+
withoutManaged,
|
|
2539
|
+
path,
|
|
2540
|
+
opts.local ? void 0 : targetUrl
|
|
2541
|
+
).content;
|
|
2447
2542
|
let url;
|
|
2448
2543
|
let body;
|
|
2449
2544
|
if (opts.local) {
|
|
2450
|
-
url =
|
|
2545
|
+
url = targetUrl;
|
|
2451
2546
|
body = [
|
|
2452
2547
|
`[${CODEX_MCP_SECTION}]`,
|
|
2453
2548
|
`command = ${tomlString(opts.bunBin || resolveBunBin2())}`,
|
|
@@ -2456,7 +2551,7 @@ function installCodexMcpConfig(opts) {
|
|
|
2456
2551
|
];
|
|
2457
2552
|
} else {
|
|
2458
2553
|
if (!opts.bearerToken) throw new Error("Codex cloud MCP registration requires a bearer token");
|
|
2459
|
-
url =
|
|
2554
|
+
url = targetUrl;
|
|
2460
2555
|
body = [
|
|
2461
2556
|
`[${CODEX_MCP_SECTION}]`,
|
|
2462
2557
|
`url = ${tomlString(url)}`,
|
|
@@ -2464,7 +2559,7 @@ function installCodexMcpConfig(opts) {
|
|
|
2464
2559
|
"enabled = true"
|
|
2465
2560
|
];
|
|
2466
2561
|
}
|
|
2467
|
-
const prefix =
|
|
2562
|
+
const prefix = withoutExisting.trimEnd();
|
|
2468
2563
|
const managed = [CODEX_MCP_BEGIN, ...body, CODEX_MCP_END].join("\n");
|
|
2469
2564
|
writeCodexTomlAtomic(path, `${prefix}${prefix ? "\n\n" : ""}${managed}
|
|
2470
2565
|
`);
|
|
@@ -2475,8 +2570,19 @@ function uninstallCodexMcpConfig(configPath) {
|
|
|
2475
2570
|
if (!existsSync13(path)) return false;
|
|
2476
2571
|
const current = readCodexToml(path);
|
|
2477
2572
|
const next = removeCodexManagedBlock(current, path);
|
|
2478
|
-
|
|
2479
|
-
|
|
2573
|
+
let content = stripDetachedCodexMarkers(next.content);
|
|
2574
|
+
let removed = next.removed;
|
|
2575
|
+
if (!removed) {
|
|
2576
|
+
try {
|
|
2577
|
+
const recognized = removeRecognizedCodexEntry(content, path);
|
|
2578
|
+
content = recognized.content;
|
|
2579
|
+
removed = recognized.removed;
|
|
2580
|
+
} catch {
|
|
2581
|
+
return false;
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
if (!removed) return false;
|
|
2585
|
+
writeCodexTomlAtomic(path, content.trimEnd() ? `${content.trimEnd()}
|
|
2480
2586
|
` : "");
|
|
2481
2587
|
return true;
|
|
2482
2588
|
}
|
|
@@ -6765,7 +6871,7 @@ var init_dockerInstall = __esm({
|
|
|
6765
6871
|
HOST_PGLITE_PORT = parseInt(process.env.SYNKRO_HOST_PGLITE_PORT || "15433", 10);
|
|
6766
6872
|
CONTAINER_NAME = resolveContainerName();
|
|
6767
6873
|
defaultImageVersion = () => {
|
|
6768
|
-
if (true) return "1.7.
|
|
6874
|
+
if (true) return "1.7.94";
|
|
6769
6875
|
try {
|
|
6770
6876
|
const pkg = JSON.parse(readFileSync17(new URL("../../package.json", import.meta.url), "utf8"));
|
|
6771
6877
|
if (pkg.version) return pkg.version;
|
|
@@ -7734,7 +7840,7 @@ function writeConfigEnv(opts) {
|
|
|
7734
7840
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle2(credsPath)}`,
|
|
7735
7841
|
`SYNKRO_TIER=${shellQuoteSingle2(safeTier)}`,
|
|
7736
7842
|
`SYNKRO_INFERENCE=${shellQuoteSingle2(safeInference)}`,
|
|
7737
|
-
`SYNKRO_VERSION=${shellQuoteSingle2("1.7.
|
|
7843
|
+
`SYNKRO_VERSION=${shellQuoteSingle2("1.7.94")}`
|
|
7738
7844
|
];
|
|
7739
7845
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle2(safeSynkroBin)}`);
|
|
7740
7846
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle2(safeUserId)}`);
|
|
@@ -8476,7 +8582,7 @@ async function installCommand(opts = {}) {
|
|
|
8476
8582
|
await setTelemetryState({ enabled: true, remoteFlushEnabled: telemetryConsent });
|
|
8477
8583
|
emit("install", {
|
|
8478
8584
|
phase: "started",
|
|
8479
|
-
cli_version_to: "1.7.
|
|
8585
|
+
cli_version_to: "1.7.94",
|
|
8480
8586
|
agents_detected: agents.map((a) => a.kind),
|
|
8481
8587
|
with_github: false,
|
|
8482
8588
|
with_local_cc: false,
|
|
@@ -14233,7 +14339,7 @@ var subArgs = args.slice(1);
|
|
|
14233
14339
|
var isDetachedChild = process.env.SYNKRO_TELEMETRY_DETACHED === "1";
|
|
14234
14340
|
var FLUSH_SKIP = /* @__PURE__ */ new Set(["grade", "version", "--version", "-v", "help", "--help", "-h", ""]);
|
|
14235
14341
|
function printVersion() {
|
|
14236
|
-
console.log("1.7.
|
|
14342
|
+
console.log("1.7.94");
|
|
14237
14343
|
}
|
|
14238
14344
|
function printHelp2() {
|
|
14239
14345
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|