@synkro-sh/cli 1.3.18 → 1.3.19
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 +183 -30
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -3224,6 +3224,7 @@ function writeConfigEnv(opts) {
|
|
|
3224
3224
|
const safeOrgId = sanitizeConfigValue(opts.orgId);
|
|
3225
3225
|
const safeEmail = sanitizeConfigValue(opts.email);
|
|
3226
3226
|
const safeTier = sanitizeConfigValue(opts.tier ?? "pro", 32);
|
|
3227
|
+
const safeInference = sanitizeConfigValue(opts.inference ?? "fast", 16);
|
|
3227
3228
|
const lines = [
|
|
3228
3229
|
"# Synkro CLI config (managed by synkro install)",
|
|
3229
3230
|
"# JWT auth \u2014 the hook scripts read SYNKRO_CREDENTIALS_PATH at runtime",
|
|
@@ -3231,7 +3232,8 @@ function writeConfigEnv(opts) {
|
|
|
3231
3232
|
`SYNKRO_GATEWAY_URL=${shellQuoteSingle(safeGateway)}`,
|
|
3232
3233
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
3233
3234
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
3234
|
-
`
|
|
3235
|
+
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
3236
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.3.19")}`
|
|
3235
3237
|
];
|
|
3236
3238
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
3237
3239
|
if (safeOrgId) lines.push(`SYNKRO_ORG_ID=${shellQuoteSingle(safeOrgId)}`);
|
|
@@ -3243,6 +3245,42 @@ function writeConfigEnv(opts) {
|
|
|
3243
3245
|
writeFileSync5(CONFIG_PATH2, lines.join("\n"), "utf-8");
|
|
3244
3246
|
chmodSync(CONFIG_PATH2, 384);
|
|
3245
3247
|
}
|
|
3248
|
+
function collectLocalMetadata() {
|
|
3249
|
+
const meta = { platform: process.platform };
|
|
3250
|
+
try {
|
|
3251
|
+
meta.display_name = execSync4("git config user.name", { encoding: "utf-8", timeout: 3e3 }).trim();
|
|
3252
|
+
} catch {
|
|
3253
|
+
}
|
|
3254
|
+
try {
|
|
3255
|
+
const remote = execSync4("git remote get-url origin", { encoding: "utf-8", timeout: 3e3 }).trim();
|
|
3256
|
+
const m = remote.match(/(?:github\.com)[:/](.+?)(?:\.git)?$/);
|
|
3257
|
+
if (m) meta.active_repo = m[1];
|
|
3258
|
+
} catch {
|
|
3259
|
+
}
|
|
3260
|
+
return meta;
|
|
3261
|
+
}
|
|
3262
|
+
async function fetchUserProfile(gatewayUrl, token) {
|
|
3263
|
+
try {
|
|
3264
|
+
const resp = await fetch(`${gatewayUrl}/api/v1/cli/me`, {
|
|
3265
|
+
headers: { "Authorization": `Bearer ${token}` }
|
|
3266
|
+
});
|
|
3267
|
+
if (!resp.ok) return { tier: "pro", inference: "fast" };
|
|
3268
|
+
const data = await resp.json();
|
|
3269
|
+
const meta = collectLocalMetadata();
|
|
3270
|
+
fetch(`${gatewayUrl}/api/v1/cli/me`, {
|
|
3271
|
+
method: "PATCH",
|
|
3272
|
+
headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" },
|
|
3273
|
+
body: JSON.stringify(meta)
|
|
3274
|
+
}).catch(() => {
|
|
3275
|
+
});
|
|
3276
|
+
return {
|
|
3277
|
+
tier: data.plan_tier ?? "pro",
|
|
3278
|
+
inference: data.fast_inference ? "fast" : "standard"
|
|
3279
|
+
};
|
|
3280
|
+
} catch {
|
|
3281
|
+
return { tier: "pro", inference: "fast" };
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3246
3284
|
function assertGatewayAllowed(gatewayUrl) {
|
|
3247
3285
|
let parsed;
|
|
3248
3286
|
try {
|
|
@@ -3459,8 +3497,10 @@ async function installCommand(opts = {}) {
|
|
|
3459
3497
|
email = info.email;
|
|
3460
3498
|
} catch {
|
|
3461
3499
|
}
|
|
3462
|
-
|
|
3463
|
-
|
|
3500
|
+
const profile = await fetchUserProfile(gatewayUrl, token);
|
|
3501
|
+
writeConfigEnv({ gatewayUrl, userId, orgId, email, tier: profile.tier, inference: profile.inference, transcriptConsent });
|
|
3502
|
+
console.log(`Wrote config to ${CONFIG_PATH2}`);
|
|
3503
|
+
console.log(` inference: ${profile.inference} (server-side grading)
|
|
3464
3504
|
`);
|
|
3465
3505
|
if (transcriptConsent) {
|
|
3466
3506
|
try {
|
|
@@ -3806,7 +3846,7 @@ function readConfigEnv() {
|
|
|
3806
3846
|
}
|
|
3807
3847
|
return out;
|
|
3808
3848
|
}
|
|
3809
|
-
function statusCommand() {
|
|
3849
|
+
async function statusCommand() {
|
|
3810
3850
|
console.log("Synkro CLI status\n");
|
|
3811
3851
|
if (isAuthenticated()) {
|
|
3812
3852
|
const info = getUserInfo();
|
|
@@ -3818,19 +3858,30 @@ function statusCommand() {
|
|
|
3818
3858
|
}
|
|
3819
3859
|
console.log();
|
|
3820
3860
|
const config = readConfigEnv();
|
|
3861
|
+
const gatewayUrl = (config.SYNKRO_GATEWAY_URL || "https://api.synkro.sh").replace(/^['"]|['"]$/g, "");
|
|
3862
|
+
let serverTier = config.SYNKRO_TIER || "(unset)";
|
|
3863
|
+
let serverInference = config.SYNKRO_INFERENCE || "fast";
|
|
3864
|
+
const token = getAccessToken();
|
|
3865
|
+
if (token) {
|
|
3866
|
+
try {
|
|
3867
|
+
const resp = await fetch(`${gatewayUrl}/api/v1/cli/me`, {
|
|
3868
|
+
headers: { "Authorization": `Bearer ${token}` },
|
|
3869
|
+
signal: AbortSignal.timeout(5e3)
|
|
3870
|
+
});
|
|
3871
|
+
if (resp.ok) {
|
|
3872
|
+
const data = await resp.json();
|
|
3873
|
+
serverInference = data.fast_inference ? "fast" : "standard";
|
|
3874
|
+
serverTier = data.plan_tier ?? data.tier ?? serverTier;
|
|
3875
|
+
}
|
|
3876
|
+
} catch {
|
|
3877
|
+
}
|
|
3878
|
+
}
|
|
3821
3879
|
console.log("Config:");
|
|
3822
|
-
console.log(` gateway: ${
|
|
3880
|
+
console.log(` gateway: ${gatewayUrl}`);
|
|
3823
3881
|
console.log(` credentials: ${config.SYNKRO_CREDENTIALS_PATH ?? "(unset)"}`);
|
|
3824
|
-
console.log(` tier: ${
|
|
3825
|
-
const
|
|
3826
|
-
|
|
3827
|
-
const tierCacheFile = join7(SYNKRO_DIR3, `.tier-cache-${userId}`);
|
|
3828
|
-
let inferenceTier = config.SYNKRO_INFERENCE_TIER || null;
|
|
3829
|
-
if (!inferenceTier && existsSync8(tierCacheFile)) {
|
|
3830
|
-
inferenceTier = readFileSync6(tierCacheFile, "utf-8").trim() || null;
|
|
3831
|
-
}
|
|
3832
|
-
const tierLabel = inferenceTier === "fast" ? "'fast' (server-side grading)" : inferenceTier === "free" ? "'free' (local daemon grading)" : "(unknown \u2014 fires on next hook)";
|
|
3833
|
-
console.log(` inference: ${tierLabel}`);
|
|
3882
|
+
console.log(` tier: ${serverTier}`);
|
|
3883
|
+
const inferenceLabel = serverInference === "fast" ? "'fast' (server-side grading)" : "'standard' (local grading)";
|
|
3884
|
+
console.log(` inference: ${inferenceLabel}`);
|
|
3834
3885
|
console.log(` version: ${config.SYNKRO_VERSION ?? "(unset)"}`);
|
|
3835
3886
|
console.log();
|
|
3836
3887
|
const agents = detectAgents();
|
|
@@ -3971,6 +4022,102 @@ var init_unlink = __esm({
|
|
|
3971
4022
|
}
|
|
3972
4023
|
});
|
|
3973
4024
|
|
|
4025
|
+
// cli/commands/config.ts
|
|
4026
|
+
var config_exports = {};
|
|
4027
|
+
__export(config_exports, {
|
|
4028
|
+
configCommand: () => configCommand
|
|
4029
|
+
});
|
|
4030
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync9 } from "fs";
|
|
4031
|
+
import { join as join8 } from "path";
|
|
4032
|
+
import { homedir as homedir7 } from "os";
|
|
4033
|
+
function readConfigEnv2() {
|
|
4034
|
+
if (!existsSync9(CONFIG_PATH4)) return {};
|
|
4035
|
+
const out = {};
|
|
4036
|
+
for (const line of readFileSync7(CONFIG_PATH4, "utf-8").split("\n")) {
|
|
4037
|
+
const t = line.trim();
|
|
4038
|
+
if (!t || t.startsWith("#")) continue;
|
|
4039
|
+
const eq = t.indexOf("=");
|
|
4040
|
+
if (eq > 0) out[t.slice(0, eq).trim()] = t.slice(eq + 1).trim().replace(/^['"]|['"]$/g, "");
|
|
4041
|
+
}
|
|
4042
|
+
return out;
|
|
4043
|
+
}
|
|
4044
|
+
function updateConfigValue(key, value) {
|
|
4045
|
+
if (!existsSync9(CONFIG_PATH4)) {
|
|
4046
|
+
console.error("No config found. Run `synkro install` first.");
|
|
4047
|
+
process.exit(1);
|
|
4048
|
+
}
|
|
4049
|
+
const lines = readFileSync7(CONFIG_PATH4, "utf-8").split("\n");
|
|
4050
|
+
const pattern = new RegExp(`^${key}=`);
|
|
4051
|
+
let found = false;
|
|
4052
|
+
const updated = lines.map((line) => {
|
|
4053
|
+
if (pattern.test(line.trim())) {
|
|
4054
|
+
found = true;
|
|
4055
|
+
return `${key}='${value}'`;
|
|
4056
|
+
}
|
|
4057
|
+
return line;
|
|
4058
|
+
});
|
|
4059
|
+
if (!found) updated.splice(updated.length - 1, 0, `${key}='${value}'`);
|
|
4060
|
+
writeFileSync6(CONFIG_PATH4, updated.join("\n"), "utf-8");
|
|
4061
|
+
}
|
|
4062
|
+
async function configCommand(args2) {
|
|
4063
|
+
if (args2.length === 0) {
|
|
4064
|
+
const config2 = readConfigEnv2();
|
|
4065
|
+
console.log("Synkro config:\n");
|
|
4066
|
+
console.log(` inference: ${config2.SYNKRO_INFERENCE || "fast"}`);
|
|
4067
|
+
console.log(` tier: ${config2.SYNKRO_TIER || "pro"}`);
|
|
4068
|
+
console.log(` gateway: ${config2.SYNKRO_GATEWAY_URL || "https://api.synkro.sh"}`);
|
|
4069
|
+
console.log(` version: ${config2.SYNKRO_VERSION || "?"}`);
|
|
4070
|
+
console.log(`
|
|
4071
|
+
To change: synkro config --inference fast|standard`);
|
|
4072
|
+
return;
|
|
4073
|
+
}
|
|
4074
|
+
let inferenceValue;
|
|
4075
|
+
for (const a of args2) {
|
|
4076
|
+
if (a.startsWith("--inference=")) inferenceValue = a.slice("--inference=".length);
|
|
4077
|
+
else if (a === "--inference" && args2.indexOf(a) + 1 < args2.length) inferenceValue = args2[args2.indexOf(a) + 1];
|
|
4078
|
+
}
|
|
4079
|
+
if (!inferenceValue || !["fast", "standard"].includes(inferenceValue)) {
|
|
4080
|
+
console.error("Usage: synkro config --inference fast|standard");
|
|
4081
|
+
process.exit(1);
|
|
4082
|
+
}
|
|
4083
|
+
if (!isAuthenticated()) {
|
|
4084
|
+
console.error("Not authenticated. Run `synkro login` first.");
|
|
4085
|
+
process.exit(1);
|
|
4086
|
+
}
|
|
4087
|
+
const token = getAccessToken();
|
|
4088
|
+
const config = readConfigEnv2();
|
|
4089
|
+
const gatewayUrl = (config.SYNKRO_GATEWAY_URL || "https://api.synkro.sh").replace(/\/$/, "");
|
|
4090
|
+
try {
|
|
4091
|
+
const resp = await fetch(`${gatewayUrl}/api/v1/cli/me`, {
|
|
4092
|
+
method: "PATCH",
|
|
4093
|
+
headers: {
|
|
4094
|
+
"Authorization": `Bearer ${token}`,
|
|
4095
|
+
"Content-Type": "application/json"
|
|
4096
|
+
},
|
|
4097
|
+
body: JSON.stringify({ fast_inference: inferenceValue === "fast" })
|
|
4098
|
+
});
|
|
4099
|
+
if (!resp.ok) {
|
|
4100
|
+
const errText = await resp.text().catch(() => "");
|
|
4101
|
+
console.error(`Failed to update: ${resp.status} ${errText.slice(0, 200)}`);
|
|
4102
|
+
process.exit(1);
|
|
4103
|
+
}
|
|
4104
|
+
} catch (err) {
|
|
4105
|
+
console.error(`Failed to reach server: ${err.message}`);
|
|
4106
|
+
process.exit(1);
|
|
4107
|
+
}
|
|
4108
|
+
updateConfigValue("SYNKRO_INFERENCE", inferenceValue);
|
|
4109
|
+
console.log(`\u2713 Inference set to '${inferenceValue}'.`);
|
|
4110
|
+
}
|
|
4111
|
+
var SYNKRO_DIR4, CONFIG_PATH4;
|
|
4112
|
+
var init_config = __esm({
|
|
4113
|
+
"cli/commands/config.ts"() {
|
|
4114
|
+
"use strict";
|
|
4115
|
+
init_stub();
|
|
4116
|
+
SYNKRO_DIR4 = join8(homedir7(), ".synkro");
|
|
4117
|
+
CONFIG_PATH4 = join8(SYNKRO_DIR4, "config.env");
|
|
4118
|
+
}
|
|
4119
|
+
});
|
|
4120
|
+
|
|
3974
4121
|
// cli/commands/scanPr.ts
|
|
3975
4122
|
var scanPr_exports = {};
|
|
3976
4123
|
__export(scanPr_exports, {
|
|
@@ -4563,9 +4710,9 @@ var disconnect_exports = {};
|
|
|
4563
4710
|
__export(disconnect_exports, {
|
|
4564
4711
|
disconnectCommand: () => disconnectCommand
|
|
4565
4712
|
});
|
|
4566
|
-
import { existsSync as
|
|
4567
|
-
import { homedir as
|
|
4568
|
-
import { join as
|
|
4713
|
+
import { existsSync as existsSync10, rmSync } from "fs";
|
|
4714
|
+
import { homedir as homedir8 } from "os";
|
|
4715
|
+
import { join as join9 } from "path";
|
|
4569
4716
|
function disconnectCommand(args2 = []) {
|
|
4570
4717
|
const purge = args2.includes("--purge");
|
|
4571
4718
|
console.log("Synkro disconnect starting...\n");
|
|
@@ -4583,25 +4730,25 @@ function disconnectCommand(args2 = []) {
|
|
|
4583
4730
|
console.log(`${mcpRemoved ? "\u2713" : "\xB7"} MCP guardrails server: ${mcpRemoved ? "removed entry from ~/.claude.json" : "no Synkro MCP entry found"}`);
|
|
4584
4731
|
}
|
|
4585
4732
|
if (purge) {
|
|
4586
|
-
if (
|
|
4587
|
-
rmSync(
|
|
4588
|
-
console.log(`\u2713 Removed ${
|
|
4733
|
+
if (existsSync10(SYNKRO_DIR5)) {
|
|
4734
|
+
rmSync(SYNKRO_DIR5, { recursive: true, force: true });
|
|
4735
|
+
console.log(`\u2713 Removed ${SYNKRO_DIR5}`);
|
|
4589
4736
|
} else {
|
|
4590
|
-
console.log(`\xB7 ${
|
|
4737
|
+
console.log(`\xB7 ${SYNKRO_DIR5} already gone, nothing to remove`);
|
|
4591
4738
|
}
|
|
4592
|
-
} else if (
|
|
4593
|
-
console.log(`Config preserved at ${
|
|
4739
|
+
} else if (existsSync10(SYNKRO_DIR5)) {
|
|
4740
|
+
console.log(`Config preserved at ${SYNKRO_DIR5}. Run with --purge to remove.`);
|
|
4594
4741
|
}
|
|
4595
4742
|
console.log("\nSynkro disconnected.");
|
|
4596
4743
|
}
|
|
4597
|
-
var
|
|
4744
|
+
var SYNKRO_DIR5;
|
|
4598
4745
|
var init_disconnect = __esm({
|
|
4599
4746
|
"cli/commands/disconnect.ts"() {
|
|
4600
4747
|
"use strict";
|
|
4601
4748
|
init_agentDetect();
|
|
4602
4749
|
init_ccHookConfig();
|
|
4603
4750
|
init_mcpConfig();
|
|
4604
|
-
|
|
4751
|
+
SYNKRO_DIR5 = join9(homedir8(), ".synkro");
|
|
4605
4752
|
}
|
|
4606
4753
|
});
|
|
4607
4754
|
|
|
@@ -4643,15 +4790,15 @@ var init_reinstall = __esm({
|
|
|
4643
4790
|
});
|
|
4644
4791
|
|
|
4645
4792
|
// cli/bootstrap.js
|
|
4646
|
-
import { readFileSync as
|
|
4793
|
+
import { readFileSync as readFileSync8, existsSync as existsSync11 } from "fs";
|
|
4647
4794
|
import { resolve } from "path";
|
|
4648
4795
|
var envCandidates = [
|
|
4649
4796
|
resolve(process.cwd(), ".env"),
|
|
4650
4797
|
resolve(process.env.HOME ?? "", ".synkro", "config.env")
|
|
4651
4798
|
];
|
|
4652
4799
|
for (const envPath of envCandidates) {
|
|
4653
|
-
if (!
|
|
4654
|
-
const envContent =
|
|
4800
|
+
if (!existsSync11(envPath)) continue;
|
|
4801
|
+
const envContent = readFileSync8(envPath, "utf-8");
|
|
4655
4802
|
for (const line of envContent.split("\n")) {
|
|
4656
4803
|
const trimmed = line.trim();
|
|
4657
4804
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -4679,6 +4826,7 @@ Commands:
|
|
|
4679
4826
|
status Show current setup state
|
|
4680
4827
|
link Link repos to a Synkro project (local git or GitHub OAuth)
|
|
4681
4828
|
unlink Remove repo links from Synkro projects
|
|
4829
|
+
config View or change settings (e.g. --inference fast|standard)
|
|
4682
4830
|
setup-github Configure GitHub PR scanning (push secrets + workflow file)
|
|
4683
4831
|
update Refresh hook configs and judge prompts
|
|
4684
4832
|
disconnect [--purge] Remove Synkro hooks from agents (--purge also removes ~/.synkro)
|
|
@@ -4713,7 +4861,7 @@ async function main() {
|
|
|
4713
4861
|
}
|
|
4714
4862
|
case "status": {
|
|
4715
4863
|
const { statusCommand: statusCommand2 } = await Promise.resolve().then(() => (init_status(), status_exports));
|
|
4716
|
-
statusCommand2();
|
|
4864
|
+
await statusCommand2();
|
|
4717
4865
|
break;
|
|
4718
4866
|
}
|
|
4719
4867
|
case "link": {
|
|
@@ -4726,6 +4874,11 @@ async function main() {
|
|
|
4726
4874
|
await unlinkCommand2();
|
|
4727
4875
|
break;
|
|
4728
4876
|
}
|
|
4877
|
+
case "config": {
|
|
4878
|
+
const { configCommand: configCommand2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
4879
|
+
await configCommand2(subArgs);
|
|
4880
|
+
break;
|
|
4881
|
+
}
|
|
4729
4882
|
case "setup-github": {
|
|
4730
4883
|
const { setupGithubCommand: setupGithubCommand2 } = await Promise.resolve().then(() => (init_setupGithub(), setupGithub_exports));
|
|
4731
4884
|
const ghOpts = {};
|