skalpel 2.0.0 → 2.0.2

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/cli/index.js CHANGED
@@ -1132,7 +1132,6 @@ import * as readline2 from "readline";
1132
1132
  import * as fs12 from "fs";
1133
1133
  import * as path13 from "path";
1134
1134
  import * as os7 from "os";
1135
- import { execSync as execSync4 } from "child_process";
1136
1135
 
1137
1136
  // src/cli/agents/detect.ts
1138
1137
  import { execSync as execSync3 } from "child_process";
@@ -1195,7 +1194,7 @@ function detectCodex() {
1195
1194
  agent.version = match ? match[1] : versionOutput;
1196
1195
  }
1197
1196
  }
1198
- const configFile = path11.join(codexConfigDir, "config.json");
1197
+ const configFile = path11.join(codexConfigDir, "config.toml");
1199
1198
  if (fs10.existsSync(configFile)) {
1200
1199
  agent.configPath = configFile;
1201
1200
  } else if (hasConfigDir) {
@@ -1238,14 +1237,38 @@ function configureClaudeCode(agent, proxyConfig) {
1238
1237
  config.env.ANTHROPIC_BASE_URL = `http://localhost:${proxyConfig.anthropicPort}`;
1239
1238
  fs11.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
1240
1239
  }
1240
+ function readTomlFile(filePath) {
1241
+ try {
1242
+ return fs11.readFileSync(filePath, "utf-8");
1243
+ } catch {
1244
+ return "";
1245
+ }
1246
+ }
1247
+ function setTomlKey(content, key, value) {
1248
+ const pattern = new RegExp(`^${key.replace(".", "\\.")}\\s*=.*$`, "m");
1249
+ const line = `${key} = "${value}"`;
1250
+ if (pattern.test(content)) {
1251
+ return content.replace(pattern, line);
1252
+ }
1253
+ const sectionMatch = content.match(/^\[/m);
1254
+ if (sectionMatch && sectionMatch.index !== void 0) {
1255
+ return content.slice(0, sectionMatch.index) + line + "\n" + content.slice(sectionMatch.index);
1256
+ }
1257
+ const separator = content.length > 0 && !content.endsWith("\n") ? "\n" : "";
1258
+ return content + separator + line + "\n";
1259
+ }
1260
+ function removeTomlKey(content, key) {
1261
+ const pattern = new RegExp(`^${key.replace(".", "\\.")}\\s*=.*\\n?`, "gm");
1262
+ return content.replace(pattern, "");
1263
+ }
1241
1264
  function configureCodex(agent, proxyConfig) {
1242
1265
  const configDir = process.platform === "win32" ? path12.join(os6.homedir(), "AppData", "Roaming", "codex") : path12.join(os6.homedir(), ".codex");
1243
- const configPath = agent.configPath ?? path12.join(configDir, "config.json");
1266
+ const configPath = agent.configPath ?? path12.join(configDir, "config.toml");
1244
1267
  ensureDir(path12.dirname(configPath));
1245
1268
  createBackup(configPath);
1246
- const config = readJsonFile(configPath);
1247
- config.apiBaseUrl = `http://localhost:${proxyConfig.openaiPort}`;
1248
- fs11.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
1269
+ let content = readTomlFile(configPath);
1270
+ content = setTomlKey(content, "openai_base_url", `http://localhost:${proxyConfig.openaiPort}`);
1271
+ fs11.writeFileSync(configPath, content);
1249
1272
  }
1250
1273
  function configureAgent(agent, proxyConfig) {
1251
1274
  switch (agent.name) {
@@ -1277,7 +1300,7 @@ function unconfigureClaudeCode(agent) {
1277
1300
  }
1278
1301
  function unconfigureCodex(agent) {
1279
1302
  const configDir = process.platform === "win32" ? path12.join(os6.homedir(), "AppData", "Roaming", "codex") : path12.join(os6.homedir(), ".codex");
1280
- const configPath = agent.configPath ?? path12.join(configDir, "config.json");
1303
+ const configPath = agent.configPath ?? path12.join(configDir, "config.toml");
1281
1304
  const backupPath = `${configPath}.skalpel-backup`;
1282
1305
  if (fs11.existsSync(backupPath)) {
1283
1306
  fs11.copyFileSync(backupPath, configPath);
@@ -1285,9 +1308,9 @@ function unconfigureCodex(agent) {
1285
1308
  return;
1286
1309
  }
1287
1310
  if (!fs11.existsSync(configPath)) return;
1288
- const config = readJsonFile(configPath);
1289
- delete config.apiBaseUrl;
1290
- fs11.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
1311
+ let content = readTomlFile(configPath);
1312
+ content = removeTomlKey(content, "openai_base_url");
1313
+ fs11.writeFileSync(configPath, content);
1291
1314
  }
1292
1315
  function unconfigureAgent(agent) {
1293
1316
  switch (agent.name) {
@@ -1304,23 +1327,6 @@ function unconfigureAgent(agent) {
1304
1327
  function print11(msg) {
1305
1328
  console.log(msg);
1306
1329
  }
1307
- function openUrl(url) {
1308
- const osInfo = detectOS();
1309
- try {
1310
- switch (osInfo.platform) {
1311
- case "macos":
1312
- execSync4(`open "${url}"`, { stdio: "pipe" });
1313
- break;
1314
- case "linux":
1315
- execSync4(`xdg-open "${url}"`, { stdio: "pipe" });
1316
- break;
1317
- case "windows":
1318
- execSync4(`start "" "${url}"`, { stdio: "pipe" });
1319
- break;
1320
- }
1321
- } catch {
1322
- }
1323
- }
1324
1330
  async function runWizard(options) {
1325
1331
  const isAuto = options?.auto === true;
1326
1332
  let rl;
@@ -1382,9 +1388,6 @@ async function runWizard(options) {
1382
1388
  }
1383
1389
  }
1384
1390
  if (!apiKey) {
1385
- print11(" Opening Skalpel signup page...");
1386
- openUrl("https://app.skalpel.ai/signup");
1387
- print11("");
1388
1391
  apiKey = await ask(" Paste your Skalpel API key (sk-skalpel-...): ");
1389
1392
  if (!validateApiKey(apiKey)) {
1390
1393
  print11(' Error: Invalid API key. Must start with "sk-skalpel-" and be at least 20 characters.');
@@ -1419,8 +1422,12 @@ async function runWizard(options) {
1419
1422
  print11(" The proxy will be configured and ready when agents are installed.");
1420
1423
  }
1421
1424
  print11("");
1422
- let agentsToConfigure = installedAgents;
1423
- if (installedAgents.length > 0 && !isAuto) {
1425
+ let agentsToConfigure = installedAgents.filter((a) => {
1426
+ if (options?.skipClaude && a.name === "claude-code") return false;
1427
+ if (options?.skipCodex && a.name === "codex") return false;
1428
+ return true;
1429
+ });
1430
+ if (agentsToConfigure.length > 0 && !isAuto) {
1424
1431
  const agentNames = installedAgents.map((a) => a.name).join(", ");
1425
1432
  const confirm = await ask(` Configure ${agentNames}? (Y/n): `);
1426
1433
  if (confirm.toLowerCase() === "n") {
@@ -1656,7 +1663,7 @@ async function runUninstall() {
1656
1663
  var require3 = createRequire2(import.meta.url);
1657
1664
  var pkg2 = require3("../../package.json");
1658
1665
  var program = new Command();
1659
- program.name("skalpel").description("Skalpel AI CLI \u2014 optimize your OpenAI and Anthropic API calls").version(pkg2.version).option("--api-key <key>", "Skalpel API key for non-interactive setup").option("--auto", "Run setup in non-interactive mode").action((options) => runWizard(options));
1666
+ program.name("skalpel").description("Skalpel AI CLI \u2014 optimize your OpenAI and Anthropic API calls").version(pkg2.version).option("--api-key <key>", "Skalpel API key for non-interactive setup").option("--auto", "Run setup in non-interactive mode").option("--skip-claude", "Skip Claude Code configuration").option("--skip-codex", "Skip Codex configuration").action((options) => runWizard(options));
1660
1667
  program.command("init").description("Initialize Skalpel in your project").action(runInit);
1661
1668
  program.command("doctor").description("Check Skalpel configuration health").action(runDoctor);
1662
1669
  program.command("benchmark").description("Run performance benchmarks").action(runBenchmark);