@synkro-sh/cli 1.3.57 → 1.3.59

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 CHANGED
@@ -3186,50 +3186,15 @@ jobs:
3186
3186
 
3187
3187
  // cli/installer/githubSetup.ts
3188
3188
  import { existsSync as existsSync5, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
3189
+ import { execSync as execSync2 } from "child_process";
3189
3190
  import { join as join4 } from "path";
3190
- async function encryptSecret(publicKeyBase64, secret) {
3191
- const sodium = await import("libsodium-wrappers").then((m) => m.default ?? m);
3192
- await sodium.ready;
3193
- const keyBytes = sodium.from_base64(publicKeyBase64, sodium.base64_variants.ORIGINAL);
3194
- const messageBytes = sodium.from_string(secret);
3195
- const encryptedBytes = sodium.crypto_box_seal(messageBytes, keyBytes);
3196
- return sodium.to_base64(encryptedBytes, sodium.base64_variants.ORIGINAL);
3197
- }
3198
- async function getRepoPublicKey(opts, owner, repo) {
3199
- const url = `https://api.github.com/repos/${owner}/${repo}/actions/secrets/public-key`;
3200
- const resp = await fetch(url, {
3201
- headers: {
3202
- Authorization: `Bearer ${opts.token}`,
3203
- Accept: "application/vnd.github+json",
3204
- "X-GitHub-Api-Version": "2022-11-28"
3205
- }
3206
- });
3207
- if (!resp.ok) {
3208
- const text = await resp.text().catch(() => "");
3209
- throw new Error(`GitHub API ${resp.status} fetching public key for ${owner}/${repo}: ${text.slice(0, 200)}`);
3210
- }
3211
- return await resp.json();
3212
- }
3213
- async function putRepoSecret(opts, owner, repo, secretName, secretValue, publicKey) {
3214
- const encryptedValue = await encryptSecret(publicKey.key, secretValue);
3215
- const url = `https://api.github.com/repos/${owner}/${repo}/actions/secrets/${encodeURIComponent(secretName)}`;
3216
- const resp = await fetch(url, {
3217
- method: "PUT",
3218
- headers: {
3219
- Authorization: `Bearer ${opts.token}`,
3220
- Accept: "application/vnd.github+json",
3221
- "X-GitHub-Api-Version": "2022-11-28",
3222
- "Content-Type": "application/json"
3223
- },
3224
- body: JSON.stringify({
3225
- encrypted_value: encryptedValue,
3226
- key_id: publicKey.key_id
3227
- })
3191
+ function ghSecretSet(token, owner, repo, name, value) {
3192
+ execSync2(`gh secret set ${name} --repo ${owner}/${repo} --body -`, {
3193
+ input: value,
3194
+ env: { ...process.env, GH_TOKEN: token },
3195
+ stdio: ["pipe", "ignore", "pipe"],
3196
+ timeout: 3e4
3228
3197
  });
3229
- if (!resp.ok) {
3230
- const text = await resp.text().catch(() => "");
3231
- throw new Error(`GitHub API ${resp.status} setting secret ${secretName}: ${text.slice(0, 200)}`);
3232
- }
3233
3198
  }
3234
3199
  async function listAccessibleRepos(opts) {
3235
3200
  const repos = [];
@@ -3257,11 +3222,15 @@ async function listAccessibleRepos(opts) {
3257
3222
  return repos;
3258
3223
  }
3259
3224
  async function pushSecretsToRepo(opts, owner, repo, secrets) {
3260
- const pubkey = await getRepoPublicKey(opts, owner, repo);
3225
+ try {
3226
+ execSync2("gh --version", { stdio: "ignore", timeout: 5e3 });
3227
+ } catch {
3228
+ throw new Error("GitHub CLI (gh) not found. Install it: https://cli.github.com");
3229
+ }
3261
3230
  if (secrets.claudeCodeOauthToken) {
3262
- await putRepoSecret(opts, owner, repo, "CLAUDE_CODE_OAUTH_TOKEN", secrets.claudeCodeOauthToken, pubkey);
3231
+ ghSecretSet(opts.token, owner, repo, "CLAUDE_CODE_OAUTH_TOKEN", secrets.claudeCodeOauthToken);
3263
3232
  }
3264
- await putRepoSecret(opts, owner, repo, "SYNKRO_API_KEY", secrets.synkroApiKey, pubkey);
3233
+ ghSecretSet(opts.token, owner, repo, "SYNKRO_API_KEY", secrets.synkroApiKey);
3265
3234
  }
3266
3235
  function writeWorkflowFile(repoRootPath) {
3267
3236
  const workflowDir = join4(repoRootPath, ".github", "workflows");
@@ -3294,12 +3263,12 @@ var init_githubSetup = __esm({
3294
3263
  });
3295
3264
 
3296
3265
  // cli/commands/repoConnect.ts
3297
- import { execSync as execSync2 } from "child_process";
3266
+ import { execSync as execSync3 } from "child_process";
3298
3267
  import { createServer as createServer2 } from "http";
3299
3268
  import { createInterface } from "readline";
3300
3269
  function detectGitRepo() {
3301
3270
  try {
3302
- const remoteUrl = execSync2("git remote get-url origin", { encoding: "utf-8", timeout: 5e3 }).trim();
3271
+ const remoteUrl = execSync3("git remote get-url origin", { encoding: "utf-8", timeout: 5e3 }).trim();
3303
3272
  const sshMatch = remoteUrl.match(/^git@[^:]+:(.+?)(?:\.git)?$/);
3304
3273
  const httpMatch = remoteUrl.match(/^https?:\/\/[^/]+\/(.+?)(?:\.git)?$/);
3305
3274
  const match = sshMatch || httpMatch;
@@ -3515,7 +3484,7 @@ __export(setupGithub_exports, {
3515
3484
  });
3516
3485
  import { createInterface as createInterface2 } from "readline/promises";
3517
3486
  import { stdin as input, stdout as output } from "process";
3518
- import { execSync as execSync3, spawn as nodeSpawn } from "child_process";
3487
+ import { execSync as execSync4, spawn as nodeSpawn } from "child_process";
3519
3488
  import { existsSync as existsSync6, readFileSync as readFileSync4, unlinkSync as unlinkSync3 } from "fs";
3520
3489
  import { homedir as homedir4, platform as platform2 } from "os";
3521
3490
  import { join as join5 } from "path";
@@ -3594,7 +3563,9 @@ function captureClaudeSetupToken() {
3594
3563
  let raw = "";
3595
3564
  try {
3596
3565
  raw = readFileSync4(tmpFile, "utf-8");
3597
- } catch {
3566
+ } catch (e) {
3567
+ reject(new Error(`Could not read script output file: ${e.message}`));
3568
+ return;
3598
3569
  }
3599
3570
  try {
3600
3571
  unlinkSync3(tmpFile);
@@ -3604,20 +3575,16 @@ function captureClaudeSetupToken() {
3604
3575
  reject(new Error(`claude setup-token exited with code ${code}`));
3605
3576
  return;
3606
3577
  }
3607
- const stripped = raw.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\][^\x07]*\x07/g, "");
3608
- const startIdx = stripped.indexOf("Your OAuth token");
3609
- const endIdx = stripped.indexOf("Store this token");
3610
- if (startIdx === -1 || endIdx === -1) {
3611
- reject(new Error("Could not find token in claude setup-token output"));
3612
- return;
3613
- }
3614
- const section = stripped.slice(startIdx, endIdx).replace(/\s/g, "");
3615
- const match = section.match(/sk-ant-oat01-[A-Za-z0-9_-]+/);
3616
- if (!match) {
3617
- reject(new Error("Could not find token in claude setup-token output"));
3578
+ const yellowRe = /\x1B\[38;2;255;193;7m([^\x1B]*)/g;
3579
+ let yellow = "";
3580
+ let m;
3581
+ while ((m = yellowRe.exec(raw)) !== null) yellow += m[1];
3582
+ const token = yellow.replace(/\s/g, "").match(/sk-ant-oat01-[A-Za-z0-9_-]+/);
3583
+ if (!token) {
3584
+ reject(new Error(`Could not find token in claude setup-token output (file=${raw.length}b, yellow=${yellow.length}b)`));
3618
3585
  return;
3619
3586
  }
3620
- resolve2(match[0]);
3587
+ resolve2(token[0]);
3621
3588
  });
3622
3589
  });
3623
3590
  }
@@ -3727,7 +3694,7 @@ async function setupGithubCommand(opts = {}) {
3727
3694
  }
3728
3695
  } catch {
3729
3696
  try {
3730
- ghToken = execSync3("gh auth token", { encoding: "utf-8", timeout: 5e3 }).trim();
3697
+ ghToken = execSync4("gh auth token", { encoding: "utf-8", timeout: 5e3 }).trim();
3731
3698
  } catch {
3732
3699
  console.error("GitHub not connected. Run `synkro-cli setup-github` interactively to connect.");
3733
3700
  return;
@@ -3761,7 +3728,7 @@ async function setupGithubCommand(opts = {}) {
3761
3728
  }
3762
3729
  console.log(" Validating token...");
3763
3730
  try {
3764
- const validateResult = execSync3(
3731
+ const validateResult = execSync4(
3765
3732
  'claude --print --output-format json "say ok"',
3766
3733
  { env: { ...process.env, CLAUDE_CODE_OAUTH_TOKEN: claudeToken }, encoding: "utf-8", timeout: 3e4, stdio: ["ignore", "pipe", "pipe"] }
3767
3734
  );
@@ -3778,7 +3745,7 @@ async function setupGithubCommand(opts = {}) {
3778
3745
  if (opts.nonInteractive) {
3779
3746
  let currentFullName = null;
3780
3747
  try {
3781
- const remoteUrl = execSync3("git remote get-url origin", { encoding: "utf-8", timeout: 5e3 }).trim();
3748
+ const remoteUrl = execSync4("git remote get-url origin", { encoding: "utf-8", timeout: 5e3 }).trim();
3782
3749
  const m = remoteUrl.match(/(?:github\.com)[:/](.+?)(?:\.git)?$/);
3783
3750
  if (m) currentFullName = m[1];
3784
3751
  } catch {
@@ -3881,7 +3848,7 @@ __export(install_exports, {
3881
3848
  import { existsSync as existsSync7, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, chmodSync, readFileSync as readFileSync5, readdirSync } from "fs";
3882
3849
  import { homedir as homedir5 } from "os";
3883
3850
  import { join as join6 } from "path";
3884
- import { execSync as execSync4 } from "child_process";
3851
+ import { execSync as execSync5 } from "child_process";
3885
3852
  import { createInterface as createInterface3 } from "readline";
3886
3853
  function sanitizeGatewayCandidate(raw) {
3887
3854
  if (!raw) return void 0;
@@ -3987,7 +3954,7 @@ function writeConfigEnv(opts) {
3987
3954
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
3988
3955
  `SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
3989
3956
  `SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
3990
- `SYNKRO_VERSION=${shellQuoteSingle("1.3.57")}`
3957
+ `SYNKRO_VERSION=${shellQuoteSingle("1.3.59")}`
3991
3958
  ];
3992
3959
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
3993
3960
  if (safeOrgId) lines.push(`SYNKRO_ORG_ID=${shellQuoteSingle(safeOrgId)}`);
@@ -4002,11 +3969,11 @@ function writeConfigEnv(opts) {
4002
3969
  function collectLocalMetadata() {
4003
3970
  const meta = { platform: process.platform };
4004
3971
  try {
4005
- meta.display_name = execSync4("git config user.name", { encoding: "utf-8", timeout: 3e3 }).trim();
3972
+ meta.display_name = execSync5("git config user.name", { encoding: "utf-8", timeout: 3e3 }).trim();
4006
3973
  } catch {
4007
3974
  }
4008
3975
  try {
4009
- const remote = execSync4("git remote get-url origin", { encoding: "utf-8", timeout: 3e3 }).trim();
3976
+ const remote = execSync5("git remote get-url origin", { encoding: "utf-8", timeout: 3e3 }).trim();
4010
3977
  const sshMatch = remote.match(/^git@[^:]+:(.+?)(?:\.git)?$/);
4011
3978
  const httpMatch = remote.match(/^https?:\/\/[^/]+\/(.+?)(?:\.git)?$/);
4012
3979
  const m = sshMatch || httpMatch;
@@ -4014,7 +3981,7 @@ function collectLocalMetadata() {
4014
3981
  } catch {
4015
3982
  }
4016
3983
  try {
4017
- meta.cc_version = execSync4("claude --version", { encoding: "utf-8", timeout: 5e3 }).trim().split("\n")[0];
3984
+ meta.cc_version = execSync5("claude --version", { encoding: "utf-8", timeout: 5e3 }).trim().split("\n")[0];
4018
3985
  } catch {
4019
3986
  }
4020
3987
  const claudeDir = join6(homedir5(), ".claude");
@@ -4032,7 +3999,7 @@ function collectLocalMetadata() {
4032
3999
  } catch {
4033
4000
  }
4034
4001
  try {
4035
- const mcpList = execSync4("claude mcp list 2>/dev/null", { encoding: "utf-8", timeout: 1e4 });
4002
+ const mcpList = execSync5("claude mcp list 2>/dev/null", { encoding: "utf-8", timeout: 1e4 });
4036
4003
  const connected = mcpList.split("\n").filter((l) => l.includes("Connected")).map((l) => l.split(":")[0].trim()).filter(Boolean);
4037
4004
  if (connected.length) meta.mcp_servers_connected = connected;
4038
4005
  } catch {
@@ -4335,7 +4302,7 @@ async function installCommand(opts = {}) {
4335
4302
  }
4336
4303
  function detectGitRepo2() {
4337
4304
  try {
4338
- const remoteUrl = execSync4("git remote get-url origin", { encoding: "utf-8", timeout: 5e3 }).trim();
4305
+ const remoteUrl = execSync5("git remote get-url origin", { encoding: "utf-8", timeout: 5e3 }).trim();
4339
4306
  const sshMatch = remoteUrl.match(/^git@[^:]+:(.+?)(?:\.git)?$/);
4340
4307
  const httpMatch = remoteUrl.match(/^https?:\/\/[^/]+\/(.+?)(?:\.git)?$/);
4341
4308
  const match = sshMatch || httpMatch;
@@ -4917,7 +4884,7 @@ var scanPr_exports = {};
4917
4884
  __export(scanPr_exports, {
4918
4885
  scanPrCommand: () => scanPrCommand
4919
4886
  });
4920
- import { execSync as execSync5, spawn } from "child_process";
4887
+ import { execSync as execSync6, spawn } from "child_process";
4921
4888
  import { readFileSync as readFileSync8, existsSync as existsSync10 } from "fs";
4922
4889
  import { join as join9 } from "path";
4923
4890
  function parseMatchSpec(condition) {
@@ -5025,7 +4992,7 @@ function shouldSkipFile(filename) {
5025
4992
  return SKIP_FILE_PATTERNS.some((p) => p.test(filename));
5026
4993
  }
5027
4994
  function ghJson(args2) {
5028
- const out = execSync5(`gh ${args2.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ")}`, {
4995
+ const out = execSync6(`gh ${args2.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ")}`, {
5029
4996
  encoding: "utf-8",
5030
4997
  maxBuffer: 16 * 1024 * 1024
5031
4998
  });
@@ -5323,7 +5290,7 @@ function postPrReview(repo, prNumber, sha, review, skipLineReview = false) {
5323
5290
  ${review.summary}
5324
5291
 
5325
5292
  ` + review.comments.map((c) => `**${c.path}:${c.line}** \u2014 ${c.body}`).join("\n\n");
5326
- execSync5(`gh api -X POST /repos/${repo}/issues/${prNumber}/comments --input -`, {
5293
+ execSync6(`gh api -X POST /repos/${repo}/issues/${prNumber}/comments --input -`, {
5327
5294
  encoding: "utf-8",
5328
5295
  input: JSON.stringify({ body }),
5329
5296
  stdio: ["pipe", "ignore", "pipe"]
@@ -5348,7 +5315,7 @@ ${review.summary}`,
5348
5315
  comments: review.comments
5349
5316
  });
5350
5317
  try {
5351
- execSync5(`gh api -X POST /repos/${repo}/pulls/${prNumber}/reviews --input -`, {
5318
+ execSync6(`gh api -X POST /repos/${repo}/pulls/${prNumber}/reviews --input -`, {
5352
5319
  encoding: "utf-8",
5353
5320
  input: body,
5354
5321
  stdio: ["pipe", "pipe", "pipe"]
@@ -5383,7 +5350,7 @@ function postCheckRun(repo, sha, conclusion, findings) {
5383
5350
  }
5384
5351
  });
5385
5352
  try {
5386
- execSync5(`gh api -X POST /repos/${repo}/check-runs --input -`, {
5353
+ execSync6(`gh api -X POST /repos/${repo}/check-runs --input -`, {
5387
5354
  encoding: "utf-8",
5388
5355
  input: body,
5389
5356
  stdio: ["pipe", "ignore", "pipe"]
@@ -5409,7 +5376,7 @@ function readRepoDeps() {
5409
5376
  }
5410
5377
  function getFullFileContent(filename) {
5411
5378
  try {
5412
- return execSync5(`git show HEAD:${filename}`, { encoding: "utf-8", maxBuffer: 128 * 1024 });
5379
+ return execSync6(`git show HEAD:${filename}`, { encoding: "utf-8", maxBuffer: 128 * 1024 });
5413
5380
  } catch {
5414
5381
  return null;
5415
5382
  }