@synkro-sh/cli 1.6.60 → 1.6.61
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 +64 -4
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -1593,6 +1593,13 @@ export async function loadConfig(jwt: string, query?: string): Promise<HookConfi
|
|
|
1593
1593
|
export async function route(config: HookConfig, synkroFile?: SynkroFileConfig): Promise<'local' | 'cloud'> {
|
|
1594
1594
|
const gradingMode = synkroFile?.grader?.mode || process.env.SYNKRO_GRADING_MODE || config.gradingMode || 'local';
|
|
1595
1595
|
if (gradingMode === 'byok') return 'cloud';
|
|
1596
|
+
// Cloud-container deploy ([grader] location = cloud): grade via localGrade(),
|
|
1597
|
+
// which routes to the hosted container (containers.synkro.sh) and emits the
|
|
1598
|
+
// same rich systemMessage. Return 'local' so the hook takes that branch \u2014 NOT
|
|
1599
|
+
// the legacy BYOK 'cloud' branch (which a non-BYOK org can't use, so it would
|
|
1600
|
+
// silently produce no verdict / no system message). channelUp() is false in
|
|
1601
|
+
// cloud (no local container), so without this it would wrongly fall to 'cloud'.
|
|
1602
|
+
if (process.env.SYNKRO_DEPLOY_LOCATION === 'cloud') return 'local';
|
|
1596
1603
|
if (config.captureDepth === 'local_only') return 'local';
|
|
1597
1604
|
if (await channelUp()) return 'local';
|
|
1598
1605
|
return 'cloud';
|
|
@@ -1601,6 +1608,10 @@ export async function route(config: HookConfig, synkroFile?: SynkroFileConfig):
|
|
|
1601
1608
|
export async function cweRoute(config: HookConfig, synkroFile?: SynkroFileConfig): Promise<'local' | 'byok' | 'skip'> {
|
|
1602
1609
|
const gradingMode = synkroFile?.grader?.mode || process.env.SYNKRO_GRADING_MODE || config.gradingMode || 'local';
|
|
1603
1610
|
if (gradingMode === 'byok') return 'byok';
|
|
1611
|
+
// Cloud-container: CWE scanning runs on the hosted container via localGradeCwe()
|
|
1612
|
+
// (which honors SYNKRO_DEPLOY_LOCATION). Without this, cweChannelUp() is false in
|
|
1613
|
+
// cloud and we'd fall to 'skip' \u2014 silently disabling CWE scanning in cloud mode.
|
|
1614
|
+
if (process.env.SYNKRO_DEPLOY_LOCATION === 'cloud') return 'local';
|
|
1604
1615
|
if (await cweChannelUp()) return 'local';
|
|
1605
1616
|
return 'skip';
|
|
1606
1617
|
}
|
|
@@ -5671,7 +5682,8 @@ async function main() {
|
|
|
5671
5682
|
const isChannelUp = await channelUp();
|
|
5672
5683
|
const synkroFile = loadSynkroFile(cwd);
|
|
5673
5684
|
const gradingMode = synkroFile.grader.mode || process.env.SYNKRO_GRADING_MODE || 'local';
|
|
5674
|
-
const
|
|
5685
|
+
const deployCloud = process.env.SYNKRO_DEPLOY_LOCATION === 'cloud';
|
|
5686
|
+
const rt = gradingMode === 'byok' ? 'cloud' : (isChannelUp || deployCloud ? 'local' : 'cloud');
|
|
5675
5687
|
|
|
5676
5688
|
let policyName = '';
|
|
5677
5689
|
let silent = false;
|
|
@@ -5705,7 +5717,7 @@ async function main() {
|
|
|
5705
5717
|
|
|
5706
5718
|
const fakeConfig: HookConfig = { captureDepth: 'local_only', tier: 'standard', silent, policyName, rules: [], scanExemptions: [], gradingMode, storageMode: process.env.SYNKRO_STORAGE_MODE || 'local' };
|
|
5707
5719
|
const tagStr = tag(rt, fakeConfig);
|
|
5708
|
-
const routeLine = tagStr + ' inference: ' + (gradingMode === 'byok' ? 'cloud (BYOK)' : isChannelUp ? 'local-cc (channel reachable on 127.0.0.1:18929)' : 'cloud (local-cc channel not reachable)');
|
|
5720
|
+
const routeLine = tagStr + ' inference: ' + (gradingMode === 'byok' ? 'cloud (BYOK)' : deployCloud ? 'cloud container (containers.synkro.sh)' : isChannelUp ? 'local-cc (channel reachable on 127.0.0.1:18929)' : 'cloud (local-cc channel not reachable)');
|
|
5709
5721
|
|
|
5710
5722
|
if (!jwt) {
|
|
5711
5723
|
outputJson({ systemMessage: routeLine });
|
|
@@ -10305,7 +10317,7 @@ function writeConfigEnv(opts) {
|
|
|
10305
10317
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
10306
10318
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
10307
10319
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
10308
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.6.
|
|
10320
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.6.61")}`
|
|
10309
10321
|
];
|
|
10310
10322
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
10311
10323
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -10373,6 +10385,52 @@ async function provisionCloudContainer(opts) {
|
|
|
10373
10385
|
setupToken = "";
|
|
10374
10386
|
}
|
|
10375
10387
|
}
|
|
10388
|
+
async function verifyCloudGrader(jwt2) {
|
|
10389
|
+
const base = (process.env.SYNKRO_CONTAINERS_URL || "https://containers.synkro.sh").replace(/\/$/, "");
|
|
10390
|
+
console.log(" Warming the cloud grader (booting container + checking workers)...");
|
|
10391
|
+
const deadline = Date.now() + 18e4;
|
|
10392
|
+
let healthy = 0;
|
|
10393
|
+
while (Date.now() < deadline) {
|
|
10394
|
+
try {
|
|
10395
|
+
const r = await fetch(`${base}/diag`, { headers: { Authorization: `Bearer ${jwt2}` }, signal: AbortSignal.timeout(6e4) });
|
|
10396
|
+
if (r.ok) {
|
|
10397
|
+
const j = await r.json();
|
|
10398
|
+
healthy = j.claude_code?.healthy ?? 0;
|
|
10399
|
+
if (healthy >= 1) break;
|
|
10400
|
+
}
|
|
10401
|
+
} catch {
|
|
10402
|
+
}
|
|
10403
|
+
await new Promise((res) => setTimeout(res, 5e3));
|
|
10404
|
+
}
|
|
10405
|
+
if (healthy < 1) {
|
|
10406
|
+
console.warn(" \u26A0 cloud grader did not report a healthy worker within ~3m.");
|
|
10407
|
+
console.warn(" Grading is NOT verified \u2014 check the container or re-run `synkro install`.\n");
|
|
10408
|
+
return false;
|
|
10409
|
+
}
|
|
10410
|
+
console.log(` \u2713 ${healthy} Claude worker(s) healthy`);
|
|
10411
|
+
try {
|
|
10412
|
+
const probe = 'Grade this edit. File: t.py. Change: os.system(request.args["cmd"])';
|
|
10413
|
+
const r = await fetch(`${base}/grade/submit`, {
|
|
10414
|
+
method: "POST",
|
|
10415
|
+
headers: { Authorization: `Bearer ${jwt2}`, "Content-Type": "application/json" },
|
|
10416
|
+
body: JSON.stringify({ role: "grade-edit", payload: probe, content: probe, agent_kind: "claude_code" }),
|
|
10417
|
+
signal: AbortSignal.timeout(12e4)
|
|
10418
|
+
});
|
|
10419
|
+
const body = await r.json().catch(() => ({}));
|
|
10420
|
+
if (r.ok && typeof body.result === "string" && body.result.includes("<synkro-verdict>")) {
|
|
10421
|
+
console.log(" \u2713 smoke grade passed \u2014 cloud grading is live\n");
|
|
10422
|
+
return true;
|
|
10423
|
+
}
|
|
10424
|
+
console.warn(` \u26A0 smoke grade did not return a verdict (HTTP ${r.status}).`);
|
|
10425
|
+
console.warn(" The container is provisioned but grading is not healthy \u2014 likely the Claude");
|
|
10426
|
+
console.warn(" setup-token. Re-run `synkro install` to re-authorize the hosted worker.\n");
|
|
10427
|
+
return false;
|
|
10428
|
+
} catch {
|
|
10429
|
+
console.warn(" \u26A0 smoke grade timed out / connection dropped \u2014 grading is not responding.");
|
|
10430
|
+
console.warn(" The container is provisioned but not grading; re-run `synkro install`.\n");
|
|
10431
|
+
return false;
|
|
10432
|
+
}
|
|
10433
|
+
}
|
|
10376
10434
|
function readPersistedDeployLocation() {
|
|
10377
10435
|
try {
|
|
10378
10436
|
if (existsSync11(CONFIG_PATH2)) {
|
|
@@ -10483,6 +10541,7 @@ synkro.toml: deploy location changed ${current} \u2192 ${desired}
|
|
|
10483
10541
|
await provisionCloudContainer({ gatewayUrl, jwt: token, orgId, userId, email, hasClaudeCode, hasCursor });
|
|
10484
10542
|
updateConfigEnvLocation("cloud");
|
|
10485
10543
|
await applyMcpConfig({ gatewayUrl, jwt: token, hasClaudeCode, hasCursor, local: false });
|
|
10544
|
+
await verifyCloudGrader(token);
|
|
10486
10545
|
console.log(" \u2713 grading + rules/MCP now served from Synkro Cloud\n");
|
|
10487
10546
|
} else {
|
|
10488
10547
|
updateConfigEnvLocation("local");
|
|
@@ -10996,6 +11055,7 @@ async function installCommand(opts = {}) {
|
|
|
10996
11055
|
console.log();
|
|
10997
11056
|
} else if (target === "cloud-container") {
|
|
10998
11057
|
await provisionCloudContainer({ gatewayUrl, jwt: token, orgId, userId, email, hasClaudeCode, hasCursor });
|
|
11058
|
+
await verifyCloudGrader(token);
|
|
10999
11059
|
}
|
|
11000
11060
|
if (transcriptConsent) {
|
|
11001
11061
|
const repo = detectGitRepo2();
|
|
@@ -13753,7 +13813,7 @@ var args = process.argv.slice(2);
|
|
|
13753
13813
|
var cmd = args[0] || "";
|
|
13754
13814
|
var subArgs = args.slice(1);
|
|
13755
13815
|
function printVersion() {
|
|
13756
|
-
console.log("1.6.
|
|
13816
|
+
console.log("1.6.61");
|
|
13757
13817
|
}
|
|
13758
13818
|
function printHelp2() {
|
|
13759
13819
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|