@synkro-sh/cli 1.6.30 → 1.6.31
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 +50 -18
- package/dist/bootstrap.js.map +1 -1
- package/package.json +11 -10
package/dist/bootstrap.js
CHANGED
|
@@ -2351,12 +2351,10 @@ export async function pushConversationMessage(
|
|
|
2351
2351
|
type: role,
|
|
2352
2352
|
content: text,
|
|
2353
2353
|
ts: new Date().toISOString(),
|
|
2354
|
+
message_index: seq,
|
|
2354
2355
|
patch_redacted: opts.patchRedacted ?? true,
|
|
2355
2356
|
}],
|
|
2356
2357
|
};
|
|
2357
|
-
if (!opts.patchRedacted) {
|
|
2358
|
-
(body.messages as Record<string, unknown>[])[0].message_index = seq;
|
|
2359
|
-
}
|
|
2360
2358
|
const resp = await fetch('http://127.0.0.1:' + mcpPort + '/api/conversation-sync', {
|
|
2361
2359
|
method: 'POST',
|
|
2362
2360
|
headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + mcpToken },
|
|
@@ -2493,10 +2491,13 @@ export async function syncConversationTranscript(
|
|
|
2493
2491
|
} catch {}
|
|
2494
2492
|
}
|
|
2495
2493
|
|
|
2496
|
-
|
|
2497
|
-
|
|
2494
|
+
if (messages.length === 0) {
|
|
2495
|
+
writeFileSync(offsetFile, String(totalLines), 'utf-8');
|
|
2496
|
+
return { ingested: 0, messages: [] };
|
|
2497
|
+
}
|
|
2498
2498
|
|
|
2499
|
-
const
|
|
2499
|
+
const rawPort = parseInt(process.env.SYNKRO_MCP_PORT || '18931', 10);
|
|
2500
|
+
const mcpPort = (rawPort > 0 && rawPort < 65536) ? rawPort : 18931;
|
|
2500
2501
|
let mcpToken = '';
|
|
2501
2502
|
try { mcpToken = readFileSync(join(HOME, '.synkro', '.mcp-jwt'), 'utf-8').trim(); } catch {}
|
|
2502
2503
|
if (!mcpToken) return { ingested: 0, messages };
|
|
@@ -2509,6 +2510,7 @@ export async function syncConversationTranscript(
|
|
|
2509
2510
|
signal: AbortSignal.timeout(5000),
|
|
2510
2511
|
});
|
|
2511
2512
|
if (resp.ok) {
|
|
2513
|
+
writeFileSync(offsetFile, String(totalLines), 'utf-8');
|
|
2512
2514
|
const data = await resp.json() as { ingested?: number };
|
|
2513
2515
|
return { ingested: data.ingested ?? messages.length, messages };
|
|
2514
2516
|
}
|
|
@@ -3042,7 +3044,17 @@ export function hookSessionId(payload: Record<string, unknown>): string {
|
|
|
3042
3044
|
}
|
|
3043
3045
|
|
|
3044
3046
|
export function isCursorHookFormat(): boolean {
|
|
3045
|
-
return process.env.SYNKRO_HOOK_FORMAT === 'cursor';
|
|
3047
|
+
return process.env.SYNKRO_HOOK_FORMAT === 'cursor' || process.argv.includes('--cursor');
|
|
3048
|
+
}
|
|
3049
|
+
|
|
3050
|
+
// Cursor reads CC hooks from ~/.claude/settings.json and fires them alongside
|
|
3051
|
+
// its own ~/.cursor/hooks.json entries. When that happens, agentKind is
|
|
3052
|
+
// 'claude_code' but the payload model is non-Claude (e.g. gpt-5.5).
|
|
3053
|
+
// Return true so the CC hook can bail out and let Cursor's hooks handle it.
|
|
3054
|
+
export function isCursorInvokingCcHook(agentKind: string, model: string): boolean {
|
|
3055
|
+
if (agentKind === 'cursor') return false;
|
|
3056
|
+
if (!model || model === 'unknown' || model === '') return false;
|
|
3057
|
+
return !model.startsWith('claude-');
|
|
3046
3058
|
}
|
|
3047
3059
|
|
|
3048
3060
|
let cursorHookExited = false;
|
|
@@ -3142,13 +3154,13 @@ import {
|
|
|
3142
3154
|
appendSessionAction, readSessionLog, compressSessionLog, log,
|
|
3143
3155
|
outputJson, outputEmpty, setupCursorHookSignals, isEditTool, hookSessionId, GATEWAY_URL,
|
|
3144
3156
|
logGraderUnavailable, filterRules, ruleFilterText, normalizeMode, countEditLineDelta,
|
|
3145
|
-
captureLineMetrics, cursorModelFromPayload, resolveTranscriptPath,
|
|
3157
|
+
captureLineMetrics, cursorModelFromPayload, resolveTranscriptPath, isCursorInvokingCcHook,
|
|
3146
3158
|
type HookConfig, type Rule,
|
|
3147
3159
|
} from './_synkro-common.ts';
|
|
3148
3160
|
import { existsSync, readFileSync } from 'node:fs';
|
|
3149
3161
|
import { basename, join } from 'node:path';
|
|
3150
3162
|
|
|
3151
|
-
const agentKind = process.env.SYNKRO_HOOK_FORMAT === 'cursor' ? 'cursor' : 'claude_code';
|
|
3163
|
+
const agentKind = (process.env.SYNKRO_HOOK_FORMAT === 'cursor' || process.argv.includes('--cursor')) ? 'cursor' : 'claude_code';
|
|
3152
3164
|
|
|
3153
3165
|
async function main() {
|
|
3154
3166
|
setupCursorHookSignals();
|
|
@@ -3235,6 +3247,8 @@ async function main() {
|
|
|
3235
3247
|
? cursorModelFromPayload(payload)
|
|
3236
3248
|
: (transcript.ccModel || String(payload.model ?? payload.model_id ?? ''));
|
|
3237
3249
|
|
|
3250
|
+
if (isCursorInvokingCcHook(agentKind, captureModel)) { outputEmpty(); return; }
|
|
3251
|
+
|
|
3238
3252
|
// Model detection: prefer transcript (CC), fall back to payload (Cursor)
|
|
3239
3253
|
if (!transcript.ccModel) {
|
|
3240
3254
|
transcript.ccModel = captureModel;
|
|
@@ -3392,12 +3406,12 @@ import {
|
|
|
3392
3406
|
localGradeCwe, parseVerdict, reconstructContent, readStdin, log,
|
|
3393
3407
|
outputJson, outputEmpty, setupCursorHookSignals, isEditTool, isShellTool, isCursorHookFormat,
|
|
3394
3408
|
extractShellCodeWrites, hookSessionId, filePathFromToolInput, emitBlockScanFindings, dispatchFinding, dispatchCapture, GATEWAY_URL,
|
|
3395
|
-
logGraderUnavailable, resolveTranscriptPath,
|
|
3409
|
+
logGraderUnavailable, resolveTranscriptPath, isCursorInvokingCcHook,
|
|
3396
3410
|
} from './_synkro-common.ts';
|
|
3397
3411
|
import { basename, extname, resolve, join, dirname } from 'node:path';
|
|
3398
3412
|
import { readFileSync, readdirSync, existsSync } from 'node:fs';
|
|
3399
3413
|
|
|
3400
|
-
const agentKind = process.env.SYNKRO_HOOK_FORMAT === 'cursor' ? 'cursor' : 'claude_code';
|
|
3414
|
+
const agentKind = (process.env.SYNKRO_HOOK_FORMAT === 'cursor' || process.argv.includes('--cursor')) ? 'cursor' : 'claude_code';
|
|
3401
3415
|
|
|
3402
3416
|
function detectModel(payload: Record<string, unknown>): string {
|
|
3403
3417
|
const raw = String(payload.model ?? payload.model_id ?? '');
|
|
@@ -3543,6 +3557,8 @@ async function main() {
|
|
|
3543
3557
|
const shellCommand = typeof payload.command === 'string' ? payload.command.trim() : '';
|
|
3544
3558
|
const ccModel = detectModel(payload);
|
|
3545
3559
|
|
|
3560
|
+
if (isCursorInvokingCcHook(agentKind, ccModel)) { outputEmpty(); return; }
|
|
3561
|
+
|
|
3546
3562
|
const targets: CweScanTarget[] = [];
|
|
3547
3563
|
|
|
3548
3564
|
if (isCursorHookFormat() && (shellCommand || isShellTool(toolName))) {
|
|
@@ -3946,6 +3962,7 @@ import {
|
|
|
3946
3962
|
loadJwt, ensureFreshJwt, detectRepo, loadConfig, route, tag,
|
|
3947
3963
|
reconstructContent, readStdin, findNearestDeps, filePathFromToolInput, log,
|
|
3948
3964
|
outputJson, outputEmpty, setupCursorHookSignals, isEditTool, hookSessionId, dispatchFinding, dispatchCapture, dispatchScanResult, extractTranscript, emitBlockScanFindings, resolveTranscriptPath, GATEWAY_URL,
|
|
3965
|
+
isCursorHookFormat,
|
|
3949
3966
|
} from './_synkro-common.ts';
|
|
3950
3967
|
import { basename } from 'node:path';
|
|
3951
3968
|
import { readFileSync } from 'node:fs';
|
|
@@ -3976,6 +3993,9 @@ async function main() {
|
|
|
3976
3993
|
return;
|
|
3977
3994
|
}
|
|
3978
3995
|
|
|
3996
|
+
const _m = String(payload.model ?? payload.model_id ?? '');
|
|
3997
|
+
if (!isCursorHookFormat() && _m && !_m.startsWith('claude-')) { outputEmpty(); return; }
|
|
3998
|
+
|
|
3979
3999
|
const toolInput = payload.tool_input || {};
|
|
3980
4000
|
const sessionId = hookSessionId(payload);
|
|
3981
4001
|
const workspaceRoots = Array.isArray(payload.workspace_roots) ? payload.workspace_roots as string[] : [];
|
|
@@ -4238,6 +4258,9 @@ async function main() {
|
|
|
4238
4258
|
if (!input.trim()) { outputEmpty(); return; }
|
|
4239
4259
|
|
|
4240
4260
|
const payload = JSON.parse(input);
|
|
4261
|
+
const _m = String(payload.model ?? payload.model_id ?? '');
|
|
4262
|
+
if (!isCursorHookFormat() && _m && !_m.startsWith('claude-')) { outputEmpty(); return; }
|
|
4263
|
+
|
|
4241
4264
|
const toolInput = payload.tool_input || {};
|
|
4242
4265
|
const command = typeof payload.command === 'string' ? payload.command : (toolInput.command || '');
|
|
4243
4266
|
if (!command) { outputEmpty(); return; }
|
|
@@ -4340,7 +4363,7 @@ import {
|
|
|
4340
4363
|
extractTranscript, readLastPrompt, appendSessionAction, readSessionLog, compressSessionLog, log,
|
|
4341
4364
|
outputJson, outputEmpty, setupCursorHookSignals, isShellTool, hookSessionId, GATEWAY_URL,
|
|
4342
4365
|
logGraderUnavailable, filterRules, ruleFilterText, normalizeMode, appendLocalTelemetry, isSafeInRepoRead,
|
|
4343
|
-
hashCommand, resolveTranscriptPath,
|
|
4366
|
+
hashCommand, resolveTranscriptPath, isCursorHookFormat,
|
|
4344
4367
|
type HookConfig, type Rule,
|
|
4345
4368
|
} from './_synkro-common.ts';
|
|
4346
4369
|
import { createHash } from 'node:crypto';
|
|
@@ -4391,6 +4414,9 @@ async function main() {
|
|
|
4391
4414
|
return;
|
|
4392
4415
|
}
|
|
4393
4416
|
|
|
4417
|
+
const _m = String(payload.model ?? payload.model_id ?? '');
|
|
4418
|
+
if (!isCursorHookFormat() && _m && !_m.startsWith('claude-')) { outputEmpty(); return; }
|
|
4419
|
+
|
|
4394
4420
|
const toolInput = payload.tool_input || {};
|
|
4395
4421
|
const sessionId = hookSessionId(payload);
|
|
4396
4422
|
const toolUseId = payload.tool_use_id || '';
|
|
@@ -4630,11 +4656,11 @@ import {
|
|
|
4630
4656
|
parseVerdict, dispatchCapture, ruleMode, postWithRetry, readStdin,
|
|
4631
4657
|
extractTranscript, readLastPrompt, appendSessionAction, readSessionLog, compressSessionLog, log,
|
|
4632
4658
|
outputJson, outputEmpty, setupCursorHookSignals, isAgentTool, hookSessionId, GATEWAY_URL,
|
|
4633
|
-
logGraderUnavailable, filterRules, normalizeMode, resolveTranscriptPath,
|
|
4659
|
+
logGraderUnavailable, filterRules, normalizeMode, resolveTranscriptPath, isCursorInvokingCcHook,
|
|
4634
4660
|
type HookConfig, type Rule,
|
|
4635
4661
|
} from './_synkro-common.ts';
|
|
4636
4662
|
|
|
4637
|
-
const agentKind = process.env.SYNKRO_HOOK_FORMAT === 'cursor' ? 'cursor' : 'claude_code';
|
|
4663
|
+
const agentKind = (process.env.SYNKRO_HOOK_FORMAT === 'cursor' || process.argv.includes('--cursor')) ? 'cursor' : 'claude_code';
|
|
4638
4664
|
|
|
4639
4665
|
async function main() {
|
|
4640
4666
|
setupCursorHookSignals();
|
|
@@ -4649,6 +4675,9 @@ async function main() {
|
|
|
4649
4675
|
return;
|
|
4650
4676
|
}
|
|
4651
4677
|
|
|
4678
|
+
const _m = String(payload.model ?? payload.model_id ?? '');
|
|
4679
|
+
if (isCursorInvokingCcHook(agentKind, _m)) { outputEmpty(); return; }
|
|
4680
|
+
|
|
4652
4681
|
const toolInput = payload.tool_input || {};
|
|
4653
4682
|
const sessionId = hookSessionId(payload);
|
|
4654
4683
|
const toolUseId = payload.tool_use_id || '';
|
|
@@ -4809,13 +4838,13 @@ import {
|
|
|
4809
4838
|
loadJwt, ensureFreshJwt, detectRepo, loadConfig, route, tag, localGrade,
|
|
4810
4839
|
parseVerdict, dispatchCapture, appendSessionAction, readSessionLog, compressSessionLog, postWithRetry, readStdin, log,
|
|
4811
4840
|
outputJson, outputEmpty, setupCursorHookSignals, isPlanTool, hookSessionId, GATEWAY_URL,
|
|
4812
|
-
filterRules, resolveTranscriptPath,
|
|
4841
|
+
filterRules, resolveTranscriptPath, isCursorInvokingCcHook,
|
|
4813
4842
|
} from './_synkro-common.ts';
|
|
4814
4843
|
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync } from 'node:fs';
|
|
4815
4844
|
import { join } from 'node:path';
|
|
4816
4845
|
import { homedir } from 'node:os';
|
|
4817
4846
|
|
|
4818
|
-
const agentKind = process.env.SYNKRO_HOOK_FORMAT === 'cursor' ? 'cursor' : 'claude_code';
|
|
4847
|
+
const agentKind = (process.env.SYNKRO_HOOK_FORMAT === 'cursor' || process.argv.includes('--cursor')) ? 'cursor' : 'claude_code';
|
|
4819
4848
|
|
|
4820
4849
|
function findLatestPlanInDir(plansDir: string): string | null {
|
|
4821
4850
|
if (!existsSync(plansDir)) return null;
|
|
@@ -4867,6 +4896,9 @@ async function main() {
|
|
|
4867
4896
|
const toolName = payload.tool_name || '';
|
|
4868
4897
|
if (!isPlanTool(toolName)) { outputEmpty(); return; }
|
|
4869
4898
|
|
|
4899
|
+
const _m = String(payload.model ?? payload.model_id ?? '');
|
|
4900
|
+
if (isCursorInvokingCcHook(agentKind, _m)) { outputEmpty(); return; }
|
|
4901
|
+
|
|
4870
4902
|
const planFile = findLatestPlan();
|
|
4871
4903
|
if (!planFile) { outputEmpty(); return; }
|
|
4872
4904
|
const plan = readFileSync(planFile, 'utf-8');
|
|
@@ -7944,7 +7976,7 @@ function writeConfigEnv(opts) {
|
|
|
7944
7976
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
7945
7977
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
7946
7978
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
7947
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.6.
|
|
7979
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.6.31")}`
|
|
7948
7980
|
];
|
|
7949
7981
|
if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
|
|
7950
7982
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
@@ -10715,7 +10747,7 @@ var args = process.argv.slice(2);
|
|
|
10715
10747
|
var cmd = args[0] || "";
|
|
10716
10748
|
var subArgs = args.slice(1);
|
|
10717
10749
|
function printVersion() {
|
|
10718
|
-
console.log("1.6.
|
|
10750
|
+
console.log("1.6.31");
|
|
10719
10751
|
}
|
|
10720
10752
|
function printHelp2() {
|
|
10721
10753
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|