@jcanizalez7/clauxy 0.2.5 → 0.2.7

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 (2) hide show
  1. package/dist/cli.js +178 -109
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1028,7 +1028,7 @@ var init_providers = __esm(() => {
1028
1028
  };
1029
1029
  });
1030
1030
 
1031
- // converter.ts
1031
+ // providers/converters/openai-chat.ts
1032
1032
  function convertTools(anthropicTools) {
1033
1033
  if (!anthropicTools || anthropicTools.length === 0)
1034
1034
  return;
@@ -1323,7 +1323,7 @@ function convertStreamChunk(chunk) {
1323
1323
  }
1324
1324
  }
1325
1325
  var streamState;
1326
- var init_converter = __esm(() => {
1326
+ var init_openai_chat = __esm(() => {
1327
1327
  streamState = {
1328
1328
  messageStarted: false,
1329
1329
  activeBlocks: new Set,
@@ -1331,7 +1331,7 @@ var init_converter = __esm(() => {
1331
1331
  };
1332
1332
  });
1333
1333
 
1334
- // converter-responses.ts
1334
+ // providers/converters/openai-responses.ts
1335
1335
  function parseToolResultContent(content) {
1336
1336
  if (content === null || content === undefined) {
1337
1337
  return "No content provided";
@@ -1656,7 +1656,7 @@ function convertResponsesResponse(response) {
1656
1656
  }
1657
1657
  var streamMessageId = "", streamContentIndex = 0, sentMessageStart = false, sentContentBlockStart = false, currentToolCall = null;
1658
1658
 
1659
- // converter-gemini.ts
1659
+ // providers/converters/gemini.ts
1660
1660
  function sanitizeSchemaForGemini(schema) {
1661
1661
  if (!schema)
1662
1662
  return;
@@ -2026,7 +2026,7 @@ data: ${JSON.stringify({ type: "message_stop" })}
2026
2026
  return results;
2027
2027
  }
2028
2028
  var streamState2;
2029
- var init_converter_gemini = __esm(() => {
2029
+ var init_gemini = __esm(() => {
2030
2030
  streamState2 = {
2031
2031
  messageId: "",
2032
2032
  contentIndex: 0,
@@ -2039,6 +2039,12 @@ var init_converter_gemini = __esm(() => {
2039
2039
  };
2040
2040
  });
2041
2041
 
2042
+ // providers/converters/index.ts
2043
+ var init_converters = __esm(() => {
2044
+ init_openai_chat();
2045
+ init_gemini();
2046
+ });
2047
+
2042
2048
  // proxy.ts
2043
2049
  var exports_proxy = {};
2044
2050
  __export(exports_proxy, {
@@ -2399,8 +2405,7 @@ var LOG_LEVELS, DEFAULT_PORT = 3000, PORT_RANGE, c;
2399
2405
  var init_proxy = __esm(async () => {
2400
2406
  init_providers();
2401
2407
  init_config();
2402
- init_converter();
2403
- init_converter_gemini();
2408
+ init_converters();
2404
2409
  LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
2405
2410
  PORT_RANGE = [3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009];
2406
2411
  c = {
@@ -2416,7 +2421,7 @@ var init_proxy = __esm(async () => {
2416
2421
  // cli/index.ts
2417
2422
  import { defineCommand, runMain } from "citty";
2418
2423
 
2419
- // cli/commands/run.ts
2424
+ // cli/commands/shared-auth.ts
2420
2425
  init_auth();
2421
2426
  init_config();
2422
2427
  init_providers();
@@ -2434,12 +2439,79 @@ function handleCancel(value, message = "Cancelled") {
2434
2439
  var colors = {
2435
2440
  green: (s) => `\x1B[32m${s}\x1B[0m`,
2436
2441
  red: (s) => `\x1B[31m${s}\x1B[0m`,
2442
+ cyan: (s) => `\x1B[36m${s}\x1B[0m`,
2437
2443
  yellow: (s) => `\x1B[33m${s}\x1B[0m`,
2438
2444
  dim: (s) => `\x1B[2m${s}\x1B[0m`,
2445
+ bold: (s) => `\x1B[1m${s}\x1B[0m`,
2439
2446
  reset: "\x1B[0m"
2440
2447
  };
2448
+ function setTerminalTitle(title) {
2449
+ process.stdout.write(`\x1B]0;${title}\x07`);
2450
+ }
2441
2451
 
2442
- // cli/commands/run.ts
2452
+ // cli/errors.ts
2453
+ function printError(error) {
2454
+ console.error(`${colors.red("Error:")} ${error.message}`);
2455
+ if (error.suggestion) {
2456
+ console.error(`${colors.dim("Suggestion:")} ${error.suggestion}`);
2457
+ }
2458
+ if (error.command) {
2459
+ console.error(`${colors.dim("Try:")} ${colors.cyan(error.command)}`);
2460
+ }
2461
+ }
2462
+ var Errors = {
2463
+ claudeNotFound() {
2464
+ return {
2465
+ message: "Claude Code CLI not found",
2466
+ suggestion: "Install it to use Clauxy",
2467
+ command: "npm install -g @anthropic-ai/claude-code"
2468
+ };
2469
+ },
2470
+ invalidProvider(provided, validProviders) {
2471
+ return {
2472
+ message: `Unknown provider "${provided}"`,
2473
+ suggestion: `Valid providers are ${validProviders.join(", ")}`,
2474
+ command: `clauxy -p ${validProviders[0]}`
2475
+ };
2476
+ },
2477
+ authFailed(providerName, details) {
2478
+ return {
2479
+ message: `Authentication failed for ${providerName}${details ? `: ${details}` : ""}`,
2480
+ suggestion: "Check your network connection and try again",
2481
+ command: "clauxy -c"
2482
+ };
2483
+ },
2484
+ invalidPort(provided) {
2485
+ return {
2486
+ message: `Invalid port number "${provided}"`,
2487
+ suggestion: "Port must be a valid number between 1 and 65535",
2488
+ command: "clauxy --port 3000"
2489
+ };
2490
+ },
2491
+ proxyStartFailed(port, details) {
2492
+ return {
2493
+ message: `Failed to start proxy on port ${port}${details ? `: ${details}` : ""}`,
2494
+ suggestion: "The port may be in use. Try a different port",
2495
+ command: `clauxy --port ${port + 1}`
2496
+ };
2497
+ },
2498
+ noCredentials(providerName) {
2499
+ return {
2500
+ message: `No credentials found for ${providerName}`,
2501
+ suggestion: "Run clauxy with the connect flag to authenticate",
2502
+ command: "clauxy -c"
2503
+ };
2504
+ },
2505
+ noProvidersConfigured() {
2506
+ return {
2507
+ message: "No providers configured",
2508
+ suggestion: "Run clauxy to set up a provider",
2509
+ command: "clauxy"
2510
+ };
2511
+ }
2512
+ };
2513
+
2514
+ // cli/commands/shared-auth.ts
2443
2515
  async function selectAndAuthenticate() {
2444
2516
  prompts2.intro("Clauxy - Connect to AI Provider");
2445
2517
  const providers = getProviderList();
@@ -2456,44 +2528,64 @@ async function selectAndAuthenticate() {
2456
2528
  }
2457
2529
  async function authenticateProvider(providerId) {
2458
2530
  const provider = await getProvider(providerId);
2459
- prompts2.intro(`Clauxy - Connecting to ${provider.info.name}`);
2531
+ const spinner2 = prompts2.spinner();
2532
+ spinner2.start(`Connecting to ${provider.info.name}...`);
2460
2533
  const result = await provider.authenticate();
2461
2534
  if (result.type === "failed") {
2462
- prompts2.cancel(`Authentication failed: ${result.error}`);
2535
+ spinner2.stop(`Connection failed`);
2536
+ printError(Errors.authFailed(provider.info.name, result.error));
2463
2537
  process.exit(1);
2464
2538
  }
2539
+ spinner2.stop(`Connected to ${provider.info.name}`);
2465
2540
  await Config.setActiveProvider(providerId);
2466
- prompts2.outro(`Connected to ${provider.info.name}`);
2467
2541
  return providerId;
2468
2542
  }
2469
- async function runCommand(options) {
2470
- const { port, logLevel, connect, provider } = options;
2543
+ async function resolveProvider(options) {
2544
+ const { providerOverride, forceConnect } = options;
2471
2545
  const availableProviders = getProviderList().map((item) => item.id);
2472
- const providerOverride = provider?.toLowerCase();
2473
- if (providerOverride && !availableProviders.includes(providerOverride)) {
2474
- console.error(`Invalid provider: "${providerOverride}". Valid values: ${availableProviders.join(" | ")}.`);
2546
+ const normalizedProvider = providerOverride?.toLowerCase();
2547
+ if (normalizedProvider && !availableProviders.includes(normalizedProvider)) {
2548
+ printError(Errors.invalidProvider(providerOverride, availableProviders));
2475
2549
  process.exit(1);
2476
2550
  }
2477
2551
  let activeProvider;
2478
- if (providerOverride) {
2479
- const credentials = await Auth.get(providerOverride);
2480
- if (credentials && !connect) {
2481
- activeProvider = providerOverride;
2552
+ let didAuthenticate = false;
2553
+ if (normalizedProvider) {
2554
+ const credentials = await Auth.get(normalizedProvider);
2555
+ if (credentials && !forceConnect) {
2556
+ activeProvider = normalizedProvider;
2482
2557
  } else {
2483
- activeProvider = await authenticateProvider(providerOverride);
2558
+ activeProvider = await authenticateProvider(normalizedProvider);
2559
+ didAuthenticate = true;
2484
2560
  }
2485
2561
  } else {
2486
2562
  activeProvider = await Config.getActiveProvider();
2487
- if (!activeProvider || connect) {
2563
+ if (!activeProvider || forceConnect) {
2488
2564
  activeProvider = await selectAndAuthenticate();
2565
+ didAuthenticate = true;
2489
2566
  } else {
2490
2567
  const credentials = await Auth.get(activeProvider);
2491
2568
  if (!credentials) {
2492
2569
  activeProvider = await selectAndAuthenticate();
2570
+ didAuthenticate = true;
2493
2571
  }
2494
2572
  }
2495
2573
  }
2574
+ if (!didAuthenticate) {
2575
+ const provider = await getProvider(activeProvider);
2576
+ console.log(`${colors.dim("Using")} ${provider.info.name}`);
2577
+ }
2496
2578
  await Config.setActiveProvider(activeProvider);
2579
+ return activeProvider;
2580
+ }
2581
+
2582
+ // cli/commands/run.ts
2583
+ async function runCommand(options) {
2584
+ const { port, logLevel, connect, provider } = options;
2585
+ const activeProvider = await resolveProvider({
2586
+ providerOverride: provider,
2587
+ forceConnect: connect
2588
+ });
2497
2589
  const { startProxy: startProxy2 } = await init_proxy().then(() => exports_proxy);
2498
2590
  await startProxy2({
2499
2591
  port,
@@ -2504,21 +2596,7 @@ async function runCommand(options) {
2504
2596
  }
2505
2597
 
2506
2598
  // cli/commands/wrapper.ts
2507
- init_auth();
2508
- init_config();
2509
2599
  init_providers();
2510
- import * as prompts3 from "@clack/prompts";
2511
- var c2 = {
2512
- green: (s) => `\x1B[32m${s}\x1B[0m`,
2513
- cyan: (s) => `\x1B[36m${s}\x1B[0m`,
2514
- yellow: (s) => `\x1B[33m${s}\x1B[0m`,
2515
- dim: (s) => `\x1B[2m${s}\x1B[0m`,
2516
- bold: (s) => `\x1B[1m${s}\x1B[0m`,
2517
- red: (s) => `\x1B[31m${s}\x1B[0m`
2518
- };
2519
- function setTerminalTitle(title) {
2520
- process.stdout.write(`\x1B]0;${title}\x07`);
2521
- }
2522
2600
  async function findClaudeCli() {
2523
2601
  try {
2524
2602
  const proc = Bun.spawn(["which", "claude"], {
@@ -2535,32 +2613,6 @@ async function findClaudeCli() {
2535
2613
  return null;
2536
2614
  }
2537
2615
  }
2538
- async function selectAndAuthenticate2() {
2539
- prompts3.intro("Clauxy - Connect to AI Provider");
2540
- const providers = getProviderList();
2541
- const providerChoice = await prompts3.select({
2542
- message: "Select your AI provider",
2543
- options: providers.map((p) => ({
2544
- label: p.name,
2545
- value: p.id,
2546
- hint: p.description
2547
- }))
2548
- });
2549
- const providerId = handleCancel(providerChoice, "Setup cancelled");
2550
- return authenticateProvider2(providerId);
2551
- }
2552
- async function authenticateProvider2(providerId) {
2553
- const provider = await getProvider(providerId);
2554
- prompts3.intro(`Clauxy - Connecting to ${provider.info.name}`);
2555
- const result = await provider.authenticate();
2556
- if (result.type === "failed") {
2557
- prompts3.cancel(`Authentication failed: ${result.error}`);
2558
- process.exit(1);
2559
- }
2560
- await Config.setActiveProvider(providerId);
2561
- prompts3.outro(`Connected to ${provider.info.name}`);
2562
- return providerId;
2563
- }
2564
2616
  async function isClauxyRunning(port) {
2565
2617
  try {
2566
2618
  const response = await fetch(`http://localhost:${port}/health`, {
@@ -2575,45 +2627,20 @@ async function wrapperCommand(options) {
2575
2627
  const { logLevel = "warn", connect = false, provider, port: requestedPort } = options;
2576
2628
  const claudePath = await findClaudeCli();
2577
2629
  if (!claudePath) {
2578
- console.error(c2.red("Error: Claude CLI not found."));
2579
- console.error(`
2580
- Install it with: ${c2.cyan("npm i -g @anthropic-ai/claude-code")}`);
2581
- console.error(`Or visit: ${c2.cyan("https://docs.anthropic.com/en/docs/claude-code")}`);
2630
+ printError(Errors.claudeNotFound());
2582
2631
  process.exit(1);
2583
2632
  }
2584
- const availableProviders = getProviderList().map((item) => item.id);
2585
- const providerOverride = provider?.toLowerCase();
2586
- if (providerOverride && !availableProviders.includes(providerOverride)) {
2587
- console.error(`Invalid provider: "${providerOverride}". Valid values: ${availableProviders.join(" | ")}.`);
2588
- process.exit(1);
2589
- }
2590
- let activeProvider;
2591
- if (providerOverride) {
2592
- const credentials = await Auth.get(providerOverride);
2593
- if (credentials && !connect) {
2594
- activeProvider = providerOverride;
2595
- } else {
2596
- activeProvider = await authenticateProvider2(providerOverride);
2597
- }
2598
- } else {
2599
- activeProvider = await Config.getActiveProvider();
2600
- if (!activeProvider || connect) {
2601
- activeProvider = await selectAndAuthenticate2();
2602
- } else {
2603
- const credentials = await Auth.get(activeProvider);
2604
- if (!credentials) {
2605
- activeProvider = await selectAndAuthenticate2();
2606
- }
2607
- }
2608
- }
2609
- await Config.setActiveProvider(activeProvider);
2633
+ const activeProvider = await resolveProvider({
2634
+ providerOverride: provider,
2635
+ forceConnect: connect
2636
+ });
2610
2637
  const providerInfo = await getProvider(activeProvider);
2611
2638
  setTerminalTitle(`${providerInfo.info.name} - Clauxy`);
2612
2639
  let proxyPort;
2613
2640
  let proxyServer = null;
2614
2641
  if (requestedPort && await isClauxyRunning(requestedPort)) {
2615
2642
  proxyPort = requestedPort;
2616
- console.log(`${c2.green(">")} ${c2.bold("Clauxy")} reusing proxy on ${c2.cyan(`localhost:${proxyPort}`)}`);
2643
+ console.log(`${colors.green(">")} ${colors.bold("Clauxy")} reusing proxy on ${colors.cyan(`localhost:${proxyPort}`)}`);
2617
2644
  } else {
2618
2645
  const { startProxy: startProxy2 } = await init_proxy().then(() => exports_proxy);
2619
2646
  const server = await startProxy2({
@@ -2624,7 +2651,7 @@ Install it with: ${c2.cyan("npm i -g @anthropic-ai/claude-code")}`);
2624
2651
  });
2625
2652
  proxyServer = server;
2626
2653
  proxyPort = server.port;
2627
- console.log(`${c2.green(">")} ${c2.bold("Clauxy")} proxy on ${c2.cyan(`localhost:${proxyPort}`)} ${c2.dim(`(${providerInfo.info.name})`)}`);
2654
+ console.log(`${colors.green(">")} ${colors.bold("Clauxy")} proxy on ${colors.cyan(`localhost:${proxyPort}`)} ${colors.dim(`(${providerInfo.info.name})`)}`);
2628
2655
  }
2629
2656
  const claude = Bun.spawn(["claude"], {
2630
2657
  env: {
@@ -2665,7 +2692,7 @@ Configured Providers:
2665
2692
  const providers = getProviderList();
2666
2693
  if (Object.keys(allAuth).length === 0) {
2667
2694
  console.log(" No providers configured yet.");
2668
- console.log(` Run 'clauxy run' to set up a provider.
2695
+ console.log(` Run 'clauxy' to set up a provider.
2669
2696
  `);
2670
2697
  return;
2671
2698
  }
@@ -2686,7 +2713,7 @@ Configured Providers:
2686
2713
  init_config();
2687
2714
  init_providers();
2688
2715
  init_models();
2689
- import * as prompts4 from "@clack/prompts";
2716
+ import * as prompts3 from "@clack/prompts";
2690
2717
 
2691
2718
  // cli/constants.ts
2692
2719
  var CUSTOM_MODEL_VALUE = "__custom__";
@@ -2710,21 +2737,21 @@ async function selectModel(tier, providerId, currentValue) {
2710
2737
  })),
2711
2738
  { label: "Enter custom model", value: CUSTOM_MODEL_VALUE, hint: "Type model name" }
2712
2739
  ];
2713
- const choice = await prompts4.select({
2740
+ const choice = await prompts3.select({
2714
2741
  message: `Select ${tier} model`,
2715
2742
  options,
2716
2743
  initialValue: currentValue
2717
2744
  });
2718
- if (prompts4.isCancel(choice)) {
2745
+ if (prompts3.isCancel(choice)) {
2719
2746
  return null;
2720
2747
  }
2721
2748
  if (choice === CUSTOM_MODEL_VALUE) {
2722
- const custom = await prompts4.text({
2749
+ const custom = await prompts3.text({
2723
2750
  message: `Enter custom ${tier} model name`,
2724
2751
  placeholder: currentValue,
2725
2752
  defaultValue: currentValue
2726
2753
  });
2727
- if (prompts4.isCancel(custom)) {
2754
+ if (prompts3.isCancel(custom)) {
2728
2755
  return null;
2729
2756
  }
2730
2757
  return custom;
@@ -2733,9 +2760,9 @@ async function selectModel(tier, providerId, currentValue) {
2733
2760
  }
2734
2761
  async function configureModels() {
2735
2762
  const activeProvider = await Config.getActiveProvider();
2736
- prompts4.intro("Clauxy - Model Configuration");
2763
+ prompts3.intro("Clauxy - Model Configuration");
2737
2764
  const providers = getProviderList();
2738
- const providerChoice = await prompts4.select({
2765
+ const providerChoice = await prompts3.select({
2739
2766
  message: "Select provider to configure models for",
2740
2767
  options: providers.map((p) => ({
2741
2768
  label: p.name,
@@ -2753,7 +2780,7 @@ Current models for ${PROVIDERS[providerId].name}:`);
2753
2780
  console.log(` Mid: ${currentModels.mid}`);
2754
2781
  console.log(` Small: ${currentModels.small}
2755
2782
  `);
2756
- const action = await prompts4.select({
2783
+ const action = await prompts3.select({
2757
2784
  message: "What would you like to do?",
2758
2785
  options: [
2759
2786
  { label: "Configure all models", value: "all" },
@@ -2771,7 +2798,7 @@ Models reset to defaults:`);
2771
2798
  console.log(` Big: ${defaults.big}`);
2772
2799
  console.log(` Mid: ${defaults.mid}`);
2773
2800
  console.log(` Small: ${defaults.small}`);
2774
- prompts4.outro("Done");
2801
+ prompts3.outro("Done");
2775
2802
  return;
2776
2803
  }
2777
2804
  const models = {
@@ -2783,7 +2810,7 @@ Models reset to defaults:`);
2783
2810
  if (action === "all" || action === tier.key) {
2784
2811
  const result = await selectModel(tier.label, providerId, models[tier.key]);
2785
2812
  if (result === null) {
2786
- prompts4.cancel("Cancelled");
2813
+ prompts3.cancel("Cancelled");
2787
2814
  process.exit(0);
2788
2815
  }
2789
2816
  models[tier.key] = result;
@@ -2795,12 +2822,12 @@ Models configured:`);
2795
2822
  console.log(` opus/big -> ${models.big}`);
2796
2823
  console.log(` sonnet/mid -> ${models.mid}`);
2797
2824
  console.log(` haiku/small -> ${models.small}`);
2798
- prompts4.outro("Model configuration saved");
2825
+ prompts3.outro("Model configuration saved");
2799
2826
  }
2800
2827
  // package.json
2801
2828
  var package_default = {
2802
2829
  name: "@jcanizalez7/clauxy",
2803
- version: "0.2.5",
2830
+ version: "0.2.7",
2804
2831
  description: "Multi-provider AI proxy for Claude Code (GitHub Copilot, ChatGPT Plus, Google Gemini)",
2805
2832
  type: "module",
2806
2833
  bin: {
@@ -2967,8 +2994,50 @@ var main = defineCommand({
2967
2994
  });
2968
2995
  }
2969
2996
  });
2997
+ var SUBCOMMANDS = ["run", "auth", "model", "models"];
2970
2998
  function cli() {
2971
- runMain(main);
2999
+ const args = process.argv.slice(2);
3000
+ const firstPositionalArg = args.find((arg) => !arg.startsWith("-"));
3001
+ if (!firstPositionalArg || !SUBCOMMANDS.includes(firstPositionalArg)) {
3002
+ let logLevel = "warn";
3003
+ let connect = false;
3004
+ let provider;
3005
+ let port;
3006
+ for (let i = 0;i < args.length; i++) {
3007
+ const arg = args[i];
3008
+ if (arg === "-h" || arg === "--help") {
3009
+ runMain(main);
3010
+ return;
3011
+ }
3012
+ if (arg === "-v" || arg === "--version") {
3013
+ console.log(package_default.version);
3014
+ return;
3015
+ }
3016
+ if (arg === "-l" || arg === "--log-level") {
3017
+ logLevel = args[++i] || "warn";
3018
+ } else if (arg === "-c" || arg === "--connect") {
3019
+ connect = true;
3020
+ } else if (arg === "-p" || arg === "--provider") {
3021
+ provider = args[++i];
3022
+ } else if (arg === "--port") {
3023
+ const portStr = args[++i];
3024
+ port = portStr ? parseInt(portStr, 10) : undefined;
3025
+ } else if (arg.startsWith("--log-level=")) {
3026
+ logLevel = arg.split("=")[1];
3027
+ } else if (arg.startsWith("--provider=")) {
3028
+ provider = arg.split("=")[1];
3029
+ } else if (arg.startsWith("--port=")) {
3030
+ port = parseInt(arg.split("=")[1], 10);
3031
+ } else if (arg.startsWith("-p=")) {
3032
+ provider = arg.split("=")[1];
3033
+ } else if (arg.startsWith("-l=")) {
3034
+ logLevel = arg.split("=")[1];
3035
+ }
3036
+ }
3037
+ wrapperCommand({ logLevel, connect, provider, port });
3038
+ } else {
3039
+ runMain(main);
3040
+ }
2972
3041
  }
2973
3042
 
2974
3043
  // cli.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jcanizalez7/clauxy",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Multi-provider AI proxy for Claude Code (GitHub Copilot, ChatGPT Plus, Google Gemini)",
5
5
  "type": "module",
6
6
  "bin": {