@synkro-sh/cli 1.6.13 → 1.6.15
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 +57 -12
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -1322,9 +1322,15 @@ export async function runInstallScan(command: string, jwt: string): Promise<Inst
|
|
|
1322
1322
|
const summary = scanResp?.summary || '';
|
|
1323
1323
|
const scannedLabel = pkgResults.map((p: any) => p.name + '@' + p.version).join(', ');
|
|
1324
1324
|
if (action === 'block') {
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1325
|
+
// Every critical/high signal (uncapped) + the true CVE total. The grader
|
|
1326
|
+
// only sees what we put in blockContext \u2014 so the real count must be
|
|
1327
|
+
// STATED here; a bare preview lets it under-report (the count is data,
|
|
1328
|
+
// not something the grader should infer from a truncated list).
|
|
1329
|
+
const highSignals = pkgResults
|
|
1330
|
+
.flatMap((p: any) => (p.signals || []).filter((s: any) => s.severity === 'critical' || s.severity === 'high'));
|
|
1331
|
+
const cveCount = pkgResults
|
|
1332
|
+
.flatMap((p: any) => (p.signals || []))
|
|
1333
|
+
.filter((s: any) => s.type === 'cve').length;
|
|
1328
1334
|
const findings: InstallScanResult['findings'] = [];
|
|
1329
1335
|
for (const p of pkgResults) {
|
|
1330
1336
|
for (const s of (p.signals || [])) {
|
|
@@ -1337,10 +1343,20 @@ export async function runInstallScan(command: string, jwt: string): Promise<Inst
|
|
|
1337
1343
|
}
|
|
1338
1344
|
}
|
|
1339
1345
|
}
|
|
1340
|
-
|
|
1346
|
+
// Preview the top 5 detail lines; the headline carries the true total.
|
|
1347
|
+
const blockSignals = highSignals.slice(0, 5);
|
|
1348
|
+
const headline = cveCount > 0
|
|
1349
|
+
? cveCount + ' known CVE' + (cveCount === 1 ? '' : 's') + ' found in ' + (scannedLabel || 'the requested install') + '.\\n'
|
|
1350
|
+
: '';
|
|
1351
|
+
const preview = blockSignals.map((s: any) => s.detail).join('\\n') || summary;
|
|
1352
|
+
const more = highSignals.length > blockSignals.length
|
|
1353
|
+
? '\\n(+' + (highSignals.length - blockSignals.length) + ' more critical/high findings not shown)'
|
|
1354
|
+
: '';
|
|
1341
1355
|
return {
|
|
1342
1356
|
scanned: true, action: 'block',
|
|
1343
|
-
blockContext:
|
|
1357
|
+
blockContext: headline + preview + more
|
|
1358
|
+
+ '\\nReport the CVE count and fix version exactly as stated above \u2014 do not estimate.'
|
|
1359
|
+
+ '\\nDo NOT install packages with security risks. Use a patched version or a different package.',
|
|
1344
1360
|
summary, scannedLabel, findings,
|
|
1345
1361
|
violatedIds: blockSignals.map((s: any) => s.type + ':' + (s.detail || '').slice(0, 40)),
|
|
1346
1362
|
};
|
|
@@ -1556,7 +1572,7 @@ export function parseVerdict(resp: string): Verdict {
|
|
|
1556
1572
|
// Gated cloud telemetry POST \u2014 fires only when storage mode is 'cloud'. The
|
|
1557
1573
|
// local PGLite spool (appendLocalTelemetry) always gets the data regardless,
|
|
1558
1574
|
// so 'local' storage keeps everything on the machine.
|
|
1559
|
-
function shipCloud(jwt: string, path: string, body: Record<string, any>, timeoutMs = 3000): void {
|
|
1575
|
+
export function shipCloud(jwt: string, path: string, body: Record<string, any>, timeoutMs = 3000): void {
|
|
1560
1576
|
if ((process.env.SYNKRO_STORAGE_MODE || 'local') !== 'cloud') return;
|
|
1561
1577
|
fetch(GATEWAY_URL + path, {
|
|
1562
1578
|
method: 'POST',
|
|
@@ -1644,6 +1660,10 @@ const SPOOL_DRAIN_PREFIX = 'telemetry-spool.jsonl.draining.';
|
|
|
1644
1660
|
// appendLocalTelemetry \u2014 durably records one telemetry event. The synchronous
|
|
1645
1661
|
// append IS the durability guarantee; nothing here can drop the event.
|
|
1646
1662
|
export function appendLocalTelemetry(body: Record<string, any>): void {
|
|
1663
|
+
// Cloud storage mode: the dashboard reads Timescale and a cloud-only setup
|
|
1664
|
+
// has no container to drain a local spool \u2014 so skip it. Cloud telemetry goes
|
|
1665
|
+
// via shipCloud; the local spool is only meaningful in local storage mode.
|
|
1666
|
+
if ((process.env.SYNKRO_STORAGE_MODE || 'local') !== 'local') return;
|
|
1647
1667
|
const event = { ...body, _ts: new Date().toISOString() };
|
|
1648
1668
|
try {
|
|
1649
1669
|
appendFileSync(TELEMETRY_SPOOL, JSON.stringify(event) + '\\n');
|
|
@@ -3728,7 +3748,7 @@ main();
|
|
|
3728
3748
|
STOP_SUMMARY_TS = `#!/usr/bin/env bun
|
|
3729
3749
|
import {
|
|
3730
3750
|
loadJwt, detectRepo, loadConfig, tag, readStdin, aggregateUsage, cleanupSessionLog,
|
|
3731
|
-
outputJson, outputEmpty, appendLocalTelemetry, setupCursorHookSignals, hookSessionId, GATEWAY_URL,
|
|
3751
|
+
outputJson, outputEmpty, appendLocalTelemetry, shipCloud, setupCursorHookSignals, hookSessionId, GATEWAY_URL,
|
|
3732
3752
|
} from './_synkro-common.ts';
|
|
3733
3753
|
|
|
3734
3754
|
async function main() {
|
|
@@ -3880,7 +3900,7 @@ main();
|
|
|
3880
3900
|
import {
|
|
3881
3901
|
loadJwt, loadConfig, readStdin, hashCommand, consentGrant, consentHasActive, consentConsume,
|
|
3882
3902
|
appendSessionAction,
|
|
3883
|
-
outputEmpty, appendLocalTelemetry, setupCursorHookSignals, isShellTool, hookSessionId, GATEWAY_URL,
|
|
3903
|
+
outputEmpty, appendLocalTelemetry, shipCloud, setupCursorHookSignals, isShellTool, hookSessionId, GATEWAY_URL,
|
|
3884
3904
|
} from './_synkro-common.ts';
|
|
3885
3905
|
|
|
3886
3906
|
async function main() {
|
|
@@ -3943,7 +3963,7 @@ main();
|
|
|
3943
3963
|
TRANSCRIPT_SYNC_TS = `#!/usr/bin/env bun
|
|
3944
3964
|
import {
|
|
3945
3965
|
loadJwt, detectRepo, readStdin, aggregateUsage, appendLocalTelemetry,
|
|
3946
|
-
outputEmpty, setupCursorHookSignals, hookSessionId, GATEWAY_URL, readSessionLog,
|
|
3966
|
+
outputEmpty, setupCursorHookSignals, hookSessionId, GATEWAY_URL, readSessionLog, shipCloud,
|
|
3947
3967
|
} from './_synkro-common.ts';
|
|
3948
3968
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
3949
3969
|
import { join, dirname } from 'node:path';
|
|
@@ -4436,7 +4456,7 @@ main().catch((e) => {
|
|
|
4436
4456
|
CURSOR_EDIT_CAPTURE_TS = `#!/usr/bin/env bun
|
|
4437
4457
|
import {
|
|
4438
4458
|
loadJwt, ensureFreshJwt, detectRepo, readStdin,
|
|
4439
|
-
appendSessionAction, appendLocalTelemetry, log, GATEWAY_URL,
|
|
4459
|
+
appendSessionAction, appendLocalTelemetry, shipCloud, log, GATEWAY_URL,
|
|
4440
4460
|
} from './_synkro-common.ts';
|
|
4441
4461
|
import { existsSync, readFileSync } from 'node:fs';
|
|
4442
4462
|
import { basename, dirname, join } from 'node:path';
|
|
@@ -6500,7 +6520,7 @@ function writeConfigEnv(opts) {
|
|
|
6500
6520
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
6501
6521
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
6502
6522
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
6503
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.6.
|
|
6523
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.6.15")}`
|
|
6504
6524
|
];
|
|
6505
6525
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
6506
6526
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -9028,6 +9048,29 @@ function updateConfigValue(key, value) {
|
|
|
9028
9048
|
if (!found) updated.splice(updated.length - 1, 0, `${key}='${value}'`);
|
|
9029
9049
|
writeFileSync10(CONFIG_PATH5, updated.join("\n"), "utf-8");
|
|
9030
9050
|
}
|
|
9051
|
+
async function reconcileContainer() {
|
|
9052
|
+
const cfg = readConfigEnv();
|
|
9053
|
+
const cloudOnly = (cfg.SYNKRO_GRADING_MODE || "local") === "byok" && (cfg.SYNKRO_STORAGE_MODE || "local") === "cloud";
|
|
9054
|
+
try {
|
|
9055
|
+
const { dockerInstall: dockerInstall2, dockerSafeStop: dockerSafeStop2, readContainerConfig: readContainerConfig2, assertDockerAvailable: assertDockerAvailable2, waitForContainerReady: waitForContainerReady2 } = await Promise.resolve().then(() => (init_dockerInstall(), dockerInstall_exports));
|
|
9056
|
+
const existing = readContainerConfig2();
|
|
9057
|
+
if (cloudOnly && existing) {
|
|
9058
|
+
console.log("Cloud-only mode \u2014 the local container is no longer needed; stopping it...");
|
|
9059
|
+
await dockerSafeStop2();
|
|
9060
|
+
console.log(" \u2713 container stopped (grading \u2192 BYOK, telemetry \u2192 cloud).");
|
|
9061
|
+
} else if (!cloudOnly && !existing) {
|
|
9062
|
+
assertDockerAvailable2();
|
|
9063
|
+
console.log("This mode needs the Synkro container \u2014 provisioning...");
|
|
9064
|
+
const { detectGitRepo: detectGitRepo3 } = await Promise.resolve().then(() => (init_install(), install_exports));
|
|
9065
|
+
await dockerInstall2({ claudeWorkers: 8, cursorWorkers: 0, connectedRepo: detectGitRepo3() ?? void 0 });
|
|
9066
|
+
const ready = await waitForContainerReady2(6e4);
|
|
9067
|
+
console.log(ready ? " \u2713 container running." : " \u26A0 container did not pass its health check \u2014 see `docker logs synkro-server`.");
|
|
9068
|
+
}
|
|
9069
|
+
} catch (err) {
|
|
9070
|
+
console.warn(` \u26A0 Container reconcile skipped: ${err.message}`);
|
|
9071
|
+
console.warn(" Run `synkro install` to (re)provision the container if needed.");
|
|
9072
|
+
}
|
|
9073
|
+
}
|
|
9031
9074
|
async function configCommand(args2) {
|
|
9032
9075
|
if (args2.length === 0) {
|
|
9033
9076
|
const config2 = readConfigEnv();
|
|
@@ -9057,6 +9100,7 @@ To change:`);
|
|
|
9057
9100
|
console.log(" BYOK grading uses your own provider key \u2014 register one in the");
|
|
9058
9101
|
console.log(" dashboard under Settings \u2192 Provider Keys if you have not already.");
|
|
9059
9102
|
}
|
|
9103
|
+
await reconcileContainer();
|
|
9060
9104
|
return;
|
|
9061
9105
|
}
|
|
9062
9106
|
if (args2[0] === "storage") {
|
|
@@ -9067,6 +9111,7 @@ To change:`);
|
|
|
9067
9111
|
}
|
|
9068
9112
|
updateConfigValue("SYNKRO_STORAGE_MODE", value);
|
|
9069
9113
|
console.log(`\u2713 Storage mode set to '${value}'.`);
|
|
9114
|
+
await reconcileContainer();
|
|
9070
9115
|
return;
|
|
9071
9116
|
}
|
|
9072
9117
|
let inferenceValue;
|
|
@@ -9140,7 +9185,7 @@ var args = process.argv.slice(2);
|
|
|
9140
9185
|
var cmd = args[0] || "";
|
|
9141
9186
|
var subArgs = args.slice(1);
|
|
9142
9187
|
function printVersion() {
|
|
9143
|
-
console.log("1.6.
|
|
9188
|
+
console.log("1.6.15");
|
|
9144
9189
|
}
|
|
9145
9190
|
function printHelp2() {
|
|
9146
9191
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|