anthropic-gateway 1.4.0 → 1.5.0

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.
Files changed (3) hide show
  1. package/README.md +2 -0
  2. package/cli.js +33 -37
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -52,6 +52,7 @@ anthropic-gateway setup --base-url https://api.openai.com/v1 --api-key sk-... --
52
52
 
53
53
  After setting up multiple profiles (e.g., one for kilo, one for OpenAI), you can:
54
54
 
55
+ - List all defined profiles: `anthropic-gateway profiles`
55
56
  - Start a specific profile: `anthropic-gateway start openai`
56
57
  - Set the default profile for future `start` commands: `anthropic-gateway select kilo`
57
58
  - Then `anthropic-gateway start` will use the kilo profile without specifying it.
@@ -67,6 +68,7 @@ After setting up multiple profiles (e.g., one for kilo, one for OpenAI), you can
67
68
  | `anthropic-gateway fulllogging on\|off` | Toggle full request/response logging (restart to apply) |
68
69
  | `anthropic-gateway autostart on\|off` | Launch at Windows logon (Startup folder) |
69
70
  | `anthropic-gateway select <profile>` | Set the default profile for future `start` commands |
71
+ | `anthropic-gateway profiles` | List all defined profiles in the config file |
70
72
  | `anthropic-gateway version` | Print the version (also `--version` / `-v`) |
71
73
 
72
74
  ## config.json
package/cli.js CHANGED
@@ -253,39 +253,24 @@ async function cmdSetup(args) {
253
253
  async function cmdStart(args) {
254
254
  ensureHomeDir();
255
255
  const cfgPath = args.config ? path.resolve(args.config) : DEFAULT_CONFIG;
256
- // Determine profile name: from command line argument (second in flags._) or from config's defaultProfile
257
- let profileName = null;
258
- if (args._ && args._.length > 1) {
259
- // args._ is ['start', 'profileName', ...] after parseFlags? Actually parseFlags puts non-flag args in _.
260
- // We'll instead use a different approach: we'll reparse the original argv in the main function.
261
- // For now, we'll rely on the main function to pass profileName via args.profile.
262
- // We'll change the main function later.
263
- }
264
- // We'll change the approach: let's rework the main function to pass profileName as an argument.
265
- // For now, we'll keep it simple and assume no profile argument and later update.
266
- // Let's revert and do a different plan: we'll edit the main function to handle extra args.
267
- // Given the complexity, let's stop and do a fresh edit of the whole cli.js?
268
- // Instead, let's do it step by step: we'll change the main function to capture the profile argument for start and setup.
269
- // We'll do that in the next edit.
270
- // For now, we'll leave cmdStart as is and just update the loadConfig to use defaultProfile.
271
- // We'll then update the main function to pass profileName via args.
272
- // Let's do that now.
273
- // We'll change the main function to set args.profile for start and setup.
274
- // But we are in the middle of editing cli.js, so we can edit the main function too.
275
- // Let's edit the main function after the parseFlags.
276
- // We'll do that in the next edit.
277
- // For now, we'll just update loadConfig to return the default profile when no profileName is given.
278
- // And then we'll update the main function to set args.profile for start and setup.
279
- // Let's continue with the current edit of cmdStart by assuming we will get args.profile from the main function.
280
- // We'll change the function signature to accept args that may have a profile property.
281
- // We'll change the call in the main function later.
282
- // For now, let's just update the function to use args.profile if present, otherwise default.
283
256
  const profileArg = args.profile;
284
257
  const cfg = loadProfile(cfgPath, profileArg); // loadProfile now takes profileName
285
258
  if (cfg.logFile && !path.isAbsolute(cfg.logFile)) cfg.logFile = path.join(HOME_DIR, cfg.logFile);
286
259
  const { makeServer } = require('./lib/server');
287
260
  const server = makeServer(cfg);
288
- const started = await server.start();
261
+ let started;
262
+ try {
263
+ started = await server.start();
264
+ } catch (err) {
265
+ if (err.code === 'EADDRINUSE') {
266
+ fail(`Port ${cfg.port} is already in use. Another process might be running on this port.\n` +
267
+ `To resolve:\n` +
268
+ ` 1. Stop the existing gateway: anthropic-gateway stop\n` +
269
+ ` 2. Or change the port in your config (or use a different profile with a different port).\n` +
270
+ `Underlying error: ${err.message}`);
271
+ }
272
+ throw err; // re-throw if we didn't handle it
273
+ }
289
274
  fs.writeFileSync(PID_FILE, String(process.pid));
290
275
  // Also write the active profile to a file
291
276
  const activeProfilePath = path.join(HOME_DIR, 'active_profile');
@@ -408,7 +393,7 @@ async function cmdSelect(profileName, args) {
408
393
  console.log('defaultProfile set to "' + profileName + '" in ' + cfgPath);
409
394
  }
410
395
 
411
- async function cmdSelect(profileName, args) {
396
+ async function cmdListProfiles(args) {
412
397
  ensureHomeDir();
413
398
  const cfgPath = args && args.config ? path.resolve(args.config) : DEFAULT_CONFIG;
414
399
  if (!fs.existsSync(cfgPath)) fail('no config at ' + cfgPath + ' — run "anthropic-gateway setup" first');
@@ -418,17 +403,26 @@ async function cmdSelect(profileName, args) {
418
403
  } catch (e) {
419
404
  fail('failed to parse config at ' + cfgPath);
420
405
  }
421
- // Ensure we are dealing with the new profiles format
406
+ // Handle legacy config
422
407
  if (!Array.isArray(cfg.profiles)) {
423
- fail('config is in legacy format; please run setup again to migrate to profiles format');
408
+ // Legacy single profile
409
+ if (cfg.providerName) {
410
+ console.log('Profiles (legacy format):');
411
+ console.log(' * ' + cfg.providerName + ' (default)');
412
+ } else {
413
+ console.log('No profiles found in legacy config.');
414
+ }
415
+ return;
424
416
  }
425
- const profileIndex = cfg.profiles.findIndex(p => p.providerName === profileName);
426
- if (profileIndex === -1) {
427
- fail('profile "' + profileName + '" not found in ' + cfgPath + ' (available: ' + cfg.profiles.map(p => p.providerName).join(', ') + ')');
417
+ if (cfg.profiles.length === 0) {
418
+ console.log('No profiles defined.');
419
+ return;
420
+ }
421
+ console.log('Profiles:');
422
+ for (const p of cfg.profiles) {
423
+ const marker = (p.providerName === cfg.defaultProfile) ? ' (default)' : '';
424
+ console.log(' * ' + p.providerName + marker);
428
425
  }
429
- cfg.defaultProfile = profileName;
430
- fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
431
- console.log('defaultProfile set to "' + profileName + '" in ' + cfgPath);
432
426
  }
433
427
 
434
428
  function parseFlags(argv) {
@@ -473,6 +467,7 @@ function parseFlags(argv) {
473
467
  ' anthropic-gateway fulllogging on|off # log full request/response bodies to the log file (restart to apply)',
474
468
  ' anthropic-gateway autostart on|off',
475
469
  ' anthropic-gateway select <profile> # set defaultProfile for future start commands',
470
+ ' anthropic-gateway profiles # list all defined profiles',
476
471
  ' anthropic-gateway version # or: --version, -v',
477
472
  ].join('\n')
478
473
  );
@@ -494,5 +489,6 @@ function parseFlags(argv) {
494
489
  else if (cmd === 'fulllogging') await cmdFullLogging(flags._[1], flags);
495
490
  else if (cmd === 'autostart') await cmdAutostart(flags._[1]);
496
491
  else if (cmd === 'select') await cmdSelect(flags._[1], flags);
492
+ else if (cmd === 'profiles') await cmdListProfiles(flags);
497
493
  else fail('unknown command: ' + cmd);
498
494
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anthropic-gateway",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Anthropic-compatible local gateway for any OpenAI-compatible model provider — make Claude Code (GUI/CLI) work with kilo, OpenAI, DeepSeek, local models, etc.",
5
5
  "license": "MIT",
6
6
  "engines": {