@synkro-sh/cli 1.6.72 → 1.6.73
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 +53 -29
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -145,7 +145,7 @@ function installCCHooks(settingsPath, config) {
|
|
|
145
145
|
{
|
|
146
146
|
type: "command",
|
|
147
147
|
command: config.bashJudgeScriptPath,
|
|
148
|
-
timeout:
|
|
148
|
+
timeout: 50
|
|
149
149
|
}
|
|
150
150
|
],
|
|
151
151
|
[SYNKRO_MARKER]: true
|
|
@@ -156,12 +156,12 @@ function installCCHooks(settingsPath, config) {
|
|
|
156
156
|
{
|
|
157
157
|
type: "command",
|
|
158
158
|
command: config.editPrecheckScriptPath,
|
|
159
|
-
timeout:
|
|
159
|
+
timeout: 50
|
|
160
160
|
},
|
|
161
161
|
{
|
|
162
162
|
type: "command",
|
|
163
163
|
command: config.cwePrecheckScriptPath,
|
|
164
|
-
timeout:
|
|
164
|
+
timeout: 50
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
167
|
type: "command",
|
|
@@ -177,7 +177,7 @@ function installCCHooks(settingsPath, config) {
|
|
|
177
177
|
{
|
|
178
178
|
type: "command",
|
|
179
179
|
command: config.agentJudgeScriptPath,
|
|
180
|
-
timeout:
|
|
180
|
+
timeout: 50
|
|
181
181
|
}
|
|
182
182
|
],
|
|
183
183
|
[SYNKRO_MARKER]: true
|
|
@@ -188,7 +188,7 @@ function installCCHooks(settingsPath, config) {
|
|
|
188
188
|
{
|
|
189
189
|
type: "command",
|
|
190
190
|
command: config.planJudgeScriptPath,
|
|
191
|
-
timeout:
|
|
191
|
+
timeout: 50
|
|
192
192
|
}
|
|
193
193
|
],
|
|
194
194
|
[SYNKRO_MARKER]: true
|
|
@@ -200,7 +200,7 @@ function installCCHooks(settingsPath, config) {
|
|
|
200
200
|
{
|
|
201
201
|
type: "command",
|
|
202
202
|
command: config.mcpGateScriptPath,
|
|
203
|
-
timeout:
|
|
203
|
+
timeout: 50
|
|
204
204
|
}
|
|
205
205
|
],
|
|
206
206
|
[SYNKRO_MARKER]: true
|
|
@@ -1689,7 +1689,12 @@ async function cloudGrade(surface: string, prompt: string, jwt: string, timeoutM
|
|
|
1689
1689
|
// JWT (the Worker derives the org from the token and routes to that org's
|
|
1690
1690
|
// container). Any non-2xx throws so the caller's catch fails open.
|
|
1691
1691
|
const CONTAINERS_URL = process.env.SYNKRO_CONTAINERS_URL || 'https://containers.synkro.sh';
|
|
1692
|
-
|
|
1692
|
+
// Cloud grades cross the network and can hit a cold/queued worker, so they get a
|
|
1693
|
+
// longer leash than on-device channel grades. The hook chain is sized around it:
|
|
1694
|
+
// grade abort (45s) < watchdog (48s) < CC hook budget (50s) \u2014 the grade aborts
|
|
1695
|
+
// FIRST so the caller's catch fails open cleanly before CC ever force-kills us.
|
|
1696
|
+
const CLOUD_GRADE_TIMEOUT_MS = 45000;
|
|
1697
|
+
async function hostedGrade(role: GradeRole, prompt: string, jwt: string, timeoutMs = CLOUD_GRADE_TIMEOUT_MS, agentKind: AgentKind = 'claude_code'): Promise<string> {
|
|
1693
1698
|
const resp = await fetch(CONTAINERS_URL + '/grade/submit', {
|
|
1694
1699
|
method: 'POST',
|
|
1695
1700
|
headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + jwt },
|
|
@@ -1705,18 +1710,20 @@ async function hostedGrade(role: GradeRole, prompt: string, jwt: string, timeout
|
|
|
1705
1710
|
return String(data.result || '');
|
|
1706
1711
|
}
|
|
1707
1712
|
|
|
1708
|
-
//
|
|
1709
|
-
// ccHookConfig.ts) so the AbortSignal fires and the caller's
|
|
1710
|
-
//
|
|
1711
|
-
//
|
|
1712
|
-
// prompt as a hook error instead of a clean pass.
|
|
1713
|
+
// Local-channel default 24s \u2014 MUST stay below the CC hook timeout (50s for
|
|
1714
|
+
// edit/bash/cwe in ccHookConfig.ts) so the AbortSignal fires and the caller's
|
|
1715
|
+
// catch fails open cleanly. A hung on-device worker should fail open fast; only
|
|
1716
|
+
// cloud grades (network + cold workers) get the longer 45s leash below.
|
|
1713
1717
|
export async function localGrade(surface: string, prompt: string, timeoutMs = 24000, agentKind: AgentKind = 'claude_code'): Promise<string> {
|
|
1714
1718
|
const jwt = loadJwt();
|
|
1715
1719
|
if (!jwt) throw new Error('NO_JWT');
|
|
1716
1720
|
// Cloud-container: the grader runs on Cloudflare Containers \u2014 route to the
|
|
1717
1721
|
// hosted ingress instead of the local channel. Same prompt + parseVerdict.
|
|
1722
|
+
// Cloud grades get the full 45s (not the local 24s): the round-trip + a cold
|
|
1723
|
+
// worker routinely needs >24s, which is exactly what was timing out and
|
|
1724
|
+
// failing open on big bash prompts.
|
|
1718
1725
|
if (process.env.SYNKRO_DEPLOY_LOCATION === 'cloud') {
|
|
1719
|
-
return hostedGrade(ROLE_MAP[surface] || 'grade-edit', prompt, jwt,
|
|
1726
|
+
return hostedGrade(ROLE_MAP[surface] || 'grade-edit', prompt, jwt, CLOUD_GRADE_TIMEOUT_MS, agentKind);
|
|
1720
1727
|
}
|
|
1721
1728
|
// BYOK grading mode routes the grade through an LLM API instead of the
|
|
1722
1729
|
// on-device channel worker pool. The grader prompt + parseVerdict are shared.
|
|
@@ -1727,14 +1734,14 @@ export async function localGrade(surface: string, prompt: string, timeoutMs = 24
|
|
|
1727
1734
|
return channelGrade(ROLE_MAP[surface] || 'grade-edit', prompt, jwt, 18929, timeoutMs, agentKind);
|
|
1728
1735
|
}
|
|
1729
1736
|
|
|
1730
|
-
//
|
|
1731
|
-
//
|
|
1732
|
-
//
|
|
1737
|
+
// Local-channel default 24s. Two cwe chunks grade in parallel within the same CC
|
|
1738
|
+
// budget (now 50s), so each must finish under it. Cloud cwe grades take the 45s
|
|
1739
|
+
// hosted leash (parallel chunks \u2192 wall-clock ~45s, still inside the 50s budget).
|
|
1733
1740
|
export async function localGradeCwe(prompt: string, agentKind: AgentKind = 'claude_code', timeoutMs = 24000): Promise<string> {
|
|
1734
1741
|
const jwt = loadJwt();
|
|
1735
1742
|
if (!jwt) throw new Error('NO_JWT');
|
|
1736
1743
|
if (process.env.SYNKRO_DEPLOY_LOCATION === 'cloud') {
|
|
1737
|
-
return hostedGrade('grade-cwe', prompt, jwt,
|
|
1744
|
+
return hostedGrade('grade-cwe', prompt, jwt, CLOUD_GRADE_TIMEOUT_MS, agentKind);
|
|
1738
1745
|
}
|
|
1739
1746
|
return channelGrade('grade-cwe', prompt, jwt, 18930, timeoutMs, agentKind);
|
|
1740
1747
|
}
|
|
@@ -3540,6 +3547,16 @@ export function graderUnavailableMessage(hook: string, target: string, errorMess
|
|
|
3540
3547
|
const agent = agentKind === 'cursor' ? 'Cursor' : 'Claude Code';
|
|
3541
3548
|
return hook + ' ' + target + ' \u2192 local grader not configured for ' + agent + '. Add this agent to your synkro.toml file and run \`synkro install\`.';
|
|
3542
3549
|
}
|
|
3550
|
+
// In cloud-container mode the grade ran against the hosted ingress, NOT a local
|
|
3551
|
+
// worker \u2014 say so, and distinguish a timeout (slow/cold grade) from a true
|
|
3552
|
+
// outage so "local grader unavailable" stops masquerading as a dead grader.
|
|
3553
|
+
if (process.env.SYNKRO_DEPLOY_LOCATION === 'cloud') {
|
|
3554
|
+
const isTimeout = /tim(e|ed)\\s*out|aborted|the operation was aborted/i.test(errorMessage);
|
|
3555
|
+
if (isTimeout) {
|
|
3556
|
+
return hook + ' ' + target + ' \u2192 cloud grade timed out (45s), skipped';
|
|
3557
|
+
}
|
|
3558
|
+
return hook + ' ' + target + ' \u2192 cloud grader unavailable, skipped';
|
|
3559
|
+
}
|
|
3543
3560
|
return hook + ' ' + target + ' \u2192 local grader unavailable, skipped';
|
|
3544
3561
|
}
|
|
3545
3562
|
|
|
@@ -3635,7 +3652,7 @@ const agentKind = (process.env.SYNKRO_HOOK_FORMAT === 'cursor' || process.argv.i
|
|
|
3635
3652
|
|
|
3636
3653
|
async function main() {
|
|
3637
3654
|
setupCursorHookSignals();
|
|
3638
|
-
installHookWatchdog(
|
|
3655
|
+
installHookWatchdog(48000);
|
|
3639
3656
|
try {
|
|
3640
3657
|
const input = await readStdin();
|
|
3641
3658
|
if (!input.trim()) { outputEmpty(); return; }
|
|
@@ -4029,7 +4046,7 @@ function scanPackageCapabilities(pkgName: string, cwd: string): PackageCapabilit
|
|
|
4029
4046
|
|
|
4030
4047
|
async function main() {
|
|
4031
4048
|
setupCursorHookSignals();
|
|
4032
|
-
installHookWatchdog(
|
|
4049
|
+
installHookWatchdog(48000);
|
|
4033
4050
|
try {
|
|
4034
4051
|
const input = await readStdin();
|
|
4035
4052
|
if (!input.trim()) { outputEmpty(); return; }
|
|
@@ -4942,7 +4959,7 @@ function isDuplicate(command: string, sessionId: string): boolean {
|
|
|
4942
4959
|
|
|
4943
4960
|
async function main() {
|
|
4944
4961
|
setupCursorHookSignals();
|
|
4945
|
-
installHookWatchdog(
|
|
4962
|
+
installHookWatchdog(48000);
|
|
4946
4963
|
try {
|
|
4947
4964
|
const input = await readStdin();
|
|
4948
4965
|
if (!input.trim()) { outputEmpty(); return; }
|
|
@@ -5214,7 +5231,7 @@ const agentKind = (process.env.SYNKRO_HOOK_FORMAT === 'cursor' || process.argv.i
|
|
|
5214
5231
|
|
|
5215
5232
|
async function main() {
|
|
5216
5233
|
setupCursorHookSignals();
|
|
5217
|
-
installHookWatchdog(
|
|
5234
|
+
installHookWatchdog(48000);
|
|
5218
5235
|
try {
|
|
5219
5236
|
const input = await readStdin();
|
|
5220
5237
|
if (!input.trim()) { outputEmpty(); return; }
|
|
@@ -5451,7 +5468,7 @@ function appendReviewToPlan(planFile: string, verdict: string): void {
|
|
|
5451
5468
|
|
|
5452
5469
|
async function main() {
|
|
5453
5470
|
setupCursorHookSignals();
|
|
5454
|
-
installHookWatchdog(
|
|
5471
|
+
installHookWatchdog(48000);
|
|
5455
5472
|
try {
|
|
5456
5473
|
const input = await readStdin();
|
|
5457
5474
|
if (!input.trim()) { outputEmpty(); return; }
|
|
@@ -10386,7 +10403,7 @@ function writeConfigEnv(opts) {
|
|
|
10386
10403
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
10387
10404
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
10388
10405
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
10389
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.6.
|
|
10406
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.6.73")}`
|
|
10390
10407
|
];
|
|
10391
10408
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
10392
10409
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -12075,7 +12092,14 @@ function writePluginFiles() {
|
|
|
12075
12092
|
c.pluginSettingsPath,
|
|
12076
12093
|
JSON.stringify({
|
|
12077
12094
|
fastMode: true,
|
|
12078
|
-
enabledMcpjsonServers: ["synkro-local"]
|
|
12095
|
+
enabledMcpjsonServers: ["synkro-local"],
|
|
12096
|
+
// Extended thinking is pure latency tax on a structured verdict grade and
|
|
12097
|
+
// emits reasoning the verdict parser isn't tuned for. effortLevel only
|
|
12098
|
+
// SOFTENS it; CLAUDE_CODE_DISABLE_THINKING=1 is the authoritative off
|
|
12099
|
+
// switch. Mirror the cloud pool (pool-config.sh) so local + cloud graders
|
|
12100
|
+
// behave identically.
|
|
12101
|
+
effortLevel: "low",
|
|
12102
|
+
env: { CLAUDE_CODE_DISABLE_THINKING: "1" }
|
|
12079
12103
|
}, null, 2) + "\n",
|
|
12080
12104
|
"utf-8"
|
|
12081
12105
|
);
|
|
@@ -12316,7 +12340,7 @@ tmux kill-session -t "=$SESSION" 2>/dev/null || true
|
|
|
12316
12340
|
# Start claude inside a detached tmux session so it has a real pty.
|
|
12317
12341
|
# Redirect stderr to the log so we can see why it dies.
|
|
12318
12342
|
tmux new-session -d -s "$SESSION" \\
|
|
12319
|
-
"SYNKRO_CHANNEL_PORT=${CHANNEL_1_PORT} claude --dangerously-load-development-channels server:synkro-local --dangerously-skip-permissions --setting-sources project,local --model claude-sonnet-4-6 2>>$LOG; echo 'claude exited with code '$'?' >> $LOG"
|
|
12343
|
+
"SYNKRO_CHANNEL_PORT=${CHANNEL_1_PORT} CLAUDE_CODE_DISABLE_THINKING=1 claude --dangerously-load-development-channels server:synkro-local --dangerously-skip-permissions --setting-sources project,local --model claude-sonnet-4-6 2>>$LOG; echo 'claude exited with code '$'?' >> $LOG"
|
|
12320
12344
|
|
|
12321
12345
|
# Claude's --dangerously-load-development-channels shows a confirmation
|
|
12322
12346
|
# prompt: option 1 = "I am using this for local development" (accept),
|
|
@@ -12378,7 +12402,7 @@ log "claude version: $(claude --version 2>&1 | head -1)"
|
|
|
12378
12402
|
tmux kill-session -t "=$SESSION" 2>/dev/null || true
|
|
12379
12403
|
|
|
12380
12404
|
tmux new-session -d -s "$SESSION" \\
|
|
12381
|
-
"SYNKRO_CHANNEL_PORT=${CHANNEL_2_PORT} claude --dangerously-load-development-channels server:synkro-local --dangerously-skip-permissions --setting-sources project,local --model claude-sonnet-4-6 2>>$LOG; echo 'claude exited with code '$'?' >> $LOG"
|
|
12405
|
+
"SYNKRO_CHANNEL_PORT=${CHANNEL_2_PORT} CLAUDE_CODE_DISABLE_THINKING=1 claude --dangerously-load-development-channels server:synkro-local --dangerously-skip-permissions --setting-sources project,local --model claude-sonnet-4-6 2>>$LOG; echo 'claude exited with code '$'?' >> $LOG"
|
|
12382
12406
|
|
|
12383
12407
|
sleep 3
|
|
12384
12408
|
if tmux has-session -t "=$SESSION" 2>/dev/null; then
|
|
@@ -12434,7 +12458,7 @@ log "claude version: $(claude --version 2>&1 | head -1)"
|
|
|
12434
12458
|
tmux kill-session -t "=$SESSION" 2>/dev/null || true
|
|
12435
12459
|
|
|
12436
12460
|
tmux new-session -d -s "$SESSION" \\
|
|
12437
|
-
"SYNKRO_CHANNEL_PORT=${CHANNEL_3_PORT} claude --dangerously-load-development-channels server:synkro-local --dangerously-skip-permissions --setting-sources project,local --model claude-sonnet-4-6 2>>$LOG; echo 'claude exited with code '$'?' >> $LOG"
|
|
12461
|
+
"SYNKRO_CHANNEL_PORT=${CHANNEL_3_PORT} CLAUDE_CODE_DISABLE_THINKING=1 claude --dangerously-load-development-channels server:synkro-local --dangerously-skip-permissions --setting-sources project,local --model claude-sonnet-4-6 2>>$LOG; echo 'claude exited with code '$'?' >> $LOG"
|
|
12438
12462
|
|
|
12439
12463
|
sleep 3
|
|
12440
12464
|
if tmux has-session -t "=$SESSION" 2>/dev/null; then
|
|
@@ -12490,7 +12514,7 @@ log "claude version: $(claude --version 2>&1 | head -1)"
|
|
|
12490
12514
|
tmux kill-session -t "=$SESSION" 2>/dev/null || true
|
|
12491
12515
|
|
|
12492
12516
|
tmux new-session -d -s "$SESSION" \\
|
|
12493
|
-
"SYNKRO_CHANNEL_PORT=${CHANNEL_4_PORT} claude --dangerously-load-development-channels server:synkro-local --dangerously-skip-permissions --setting-sources project,local --model claude-sonnet-4-6 2>>$LOG; echo 'claude exited with code '$'?' >> $LOG"
|
|
12517
|
+
"SYNKRO_CHANNEL_PORT=${CHANNEL_4_PORT} CLAUDE_CODE_DISABLE_THINKING=1 claude --dangerously-load-development-channels server:synkro-local --dangerously-skip-permissions --setting-sources project,local --model claude-sonnet-4-6 2>>$LOG; echo 'claude exited with code '$'?' >> $LOG"
|
|
12494
12518
|
|
|
12495
12519
|
sleep 3
|
|
12496
12520
|
if tmux has-session -t "=$SESSION" 2>/dev/null; then
|
|
@@ -14031,7 +14055,7 @@ var args = process.argv.slice(2);
|
|
|
14031
14055
|
var cmd = args[0] || "";
|
|
14032
14056
|
var subArgs = args.slice(1);
|
|
14033
14057
|
function printVersion() {
|
|
14034
|
-
console.log("1.6.
|
|
14058
|
+
console.log("1.6.73");
|
|
14035
14059
|
}
|
|
14036
14060
|
function printHelp2() {
|
|
14037
14061
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|