@jcanizalez7/clauxy 0.1.9 → 0.2.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.
- package/dist/cli.js +313 -144
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2041,84 +2041,18 @@ var init_converter_gemini = __esm(() => {
|
|
|
2041
2041
|
|
|
2042
2042
|
// proxy.ts
|
|
2043
2043
|
var exports_proxy = {};
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
return true;
|
|
2049
|
-
} catch {
|
|
2050
|
-
return false;
|
|
2051
|
-
}
|
|
2052
|
-
}
|
|
2053
|
-
async function findAvailablePort() {
|
|
2054
|
-
if (process.env.PORT) {
|
|
2055
|
-
const port = parseInt(process.env.PORT, 10);
|
|
2056
|
-
if (await isPortAvailable(port)) {
|
|
2057
|
-
return port;
|
|
2058
|
-
}
|
|
2059
|
-
log.error(`Port ${port} is in use. Try a different port with --port <port>`);
|
|
2060
|
-
process.exit(1);
|
|
2061
|
-
}
|
|
2062
|
-
for (const port of PORT_RANGE) {
|
|
2063
|
-
if (await isPortAvailable(port)) {
|
|
2064
|
-
return port;
|
|
2065
|
-
}
|
|
2066
|
-
}
|
|
2067
|
-
log.error(`All ports (${PORT_RANGE.join(", ")}) are in use.`);
|
|
2068
|
-
log.error(`Try: clauxy run --port <port>`);
|
|
2069
|
-
process.exit(1);
|
|
2070
|
-
}
|
|
2071
|
-
async function loadProvider() {
|
|
2072
|
-
const providerId = process.env.CLAUXY_PROVIDER || await Config.getActiveProvider();
|
|
2073
|
-
if (!providerId) {
|
|
2074
|
-
log.error("No provider configured. Run 'clauxy run' to set up.");
|
|
2075
|
-
process.exit(1);
|
|
2076
|
-
}
|
|
2077
|
-
return await getProvider(providerId);
|
|
2078
|
-
}
|
|
2079
|
-
function convertAnthropicToOpenAI(anthropicReq) {
|
|
2080
|
-
if (currentLogLevel === "debug") {
|
|
2081
|
-
for (let i = 0;i < anthropicReq.messages.length; i++) {
|
|
2082
|
-
const msg = anthropicReq.messages[i];
|
|
2083
|
-
if (Array.isArray(msg.content)) {
|
|
2084
|
-
const toolUses = msg.content.filter((b) => b.type === "tool_use").map((b) => b.id);
|
|
2085
|
-
const toolResults = msg.content.filter((b) => b.type === "tool_result").map((b) => b.tool_use_id);
|
|
2086
|
-
if (toolUses.length > 0)
|
|
2087
|
-
log.debug(`msg[${i}] ${msg.role}: tool_use ids: ${toolUses.join(", ")}`);
|
|
2088
|
-
if (toolResults.length > 0)
|
|
2089
|
-
log.debug(`msg[${i}] ${msg.role}: tool_result ids: ${toolResults.join(", ")}`);
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2092
|
-
}
|
|
2093
|
-
const messages = convertMessages(anthropicReq.messages, anthropicReq.system);
|
|
2094
|
-
const tools = convertTools(anthropicReq.tools);
|
|
2095
|
-
const mappedModel = provider.mapModel(anthropicReq.model);
|
|
2096
|
-
log.info(`Model: ${anthropicReq.model} -> ${mappedModel}`);
|
|
2044
|
+
__export(exports_proxy, {
|
|
2045
|
+
startProxy: () => startProxy
|
|
2046
|
+
});
|
|
2047
|
+
function createLogger(level) {
|
|
2097
2048
|
return {
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
max_tokens: anthropicReq.max_tokens,
|
|
2101
|
-
temperature: anthropicReq.temperature,
|
|
2102
|
-
stream: anthropicReq.stream ?? false,
|
|
2103
|
-
...tools && { tools }
|
|
2104
|
-
};
|
|
2105
|
-
}
|
|
2106
|
-
var LOG_LEVELS, currentLogLevel, log, DEFAULT_PORT, PORT_RANGE, provider, convertOpenAIToAnthropic, token, models, PORT, server, c, wireApi, wireApiLabel;
|
|
2107
|
-
var init_proxy = __esm(async () => {
|
|
2108
|
-
init_providers();
|
|
2109
|
-
init_config();
|
|
2110
|
-
init_converter();
|
|
2111
|
-
init_converter_gemini();
|
|
2112
|
-
LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
2113
|
-
currentLogLevel = process.env.CLAUXY_LOG_LEVEL || "info";
|
|
2114
|
-
log = {
|
|
2115
|
-
_shouldLog(level) {
|
|
2116
|
-
return LOG_LEVELS[level] >= LOG_LEVELS[currentLogLevel];
|
|
2049
|
+
_shouldLog(checkLevel) {
|
|
2050
|
+
return LOG_LEVELS[checkLevel] >= LOG_LEVELS[level];
|
|
2117
2051
|
},
|
|
2118
|
-
_format(
|
|
2052
|
+
_format(levelStr, msg) {
|
|
2119
2053
|
const now = new Date;
|
|
2120
2054
|
const ts = now.toISOString().replace("T", " ").substring(0, 19);
|
|
2121
|
-
return `${ts} ${
|
|
2055
|
+
return `${ts} ${levelStr.padEnd(5)} ${msg}`;
|
|
2122
2056
|
},
|
|
2123
2057
|
info(msg) {
|
|
2124
2058
|
if (this._shouldLog("info")) {
|
|
@@ -2146,12 +2080,73 @@ var init_proxy = __esm(async () => {
|
|
|
2146
2080
|
}
|
|
2147
2081
|
}
|
|
2148
2082
|
};
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2083
|
+
}
|
|
2084
|
+
async function isPortAvailable(port) {
|
|
2085
|
+
try {
|
|
2086
|
+
const server = Bun.serve({ port, fetch: () => new Response("") });
|
|
2087
|
+
server.stop();
|
|
2088
|
+
return true;
|
|
2089
|
+
} catch {
|
|
2090
|
+
return false;
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
async function findAvailablePort(requestedPort) {
|
|
2094
|
+
if (requestedPort) {
|
|
2095
|
+
if (await isPortAvailable(requestedPort)) {
|
|
2096
|
+
return requestedPort;
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
for (const port2 of PORT_RANGE) {
|
|
2100
|
+
if (await isPortAvailable(port2)) {
|
|
2101
|
+
return port2;
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
const server = Bun.serve({ port: 0, fetch: () => new Response("") });
|
|
2105
|
+
const port = server.port;
|
|
2106
|
+
server.stop();
|
|
2107
|
+
return port;
|
|
2108
|
+
}
|
|
2109
|
+
async function loadProvider(providerId) {
|
|
2110
|
+
const id = providerId || process.env.CLAUXY_PROVIDER || await Config.getActiveProvider();
|
|
2111
|
+
if (!id) {
|
|
2112
|
+
throw new Error("No provider configured. Run 'clauxy' to set up.");
|
|
2113
|
+
}
|
|
2114
|
+
return await getProvider(id);
|
|
2115
|
+
}
|
|
2116
|
+
async function startProxy(options = {}) {
|
|
2117
|
+
const { port: requestedPort, logLevel = "info", providerId, quiet = false } = options;
|
|
2118
|
+
const log = createLogger(logLevel);
|
|
2119
|
+
const provider = await loadProvider(providerId);
|
|
2120
|
+
function convertAnthropicToOpenAI(anthropicReq) {
|
|
2121
|
+
if (logLevel === "debug") {
|
|
2122
|
+
for (let i = 0;i < anthropicReq.messages.length; i++) {
|
|
2123
|
+
const msg = anthropicReq.messages[i];
|
|
2124
|
+
if (Array.isArray(msg.content)) {
|
|
2125
|
+
const toolUses = msg.content.filter((b) => b.type === "tool_use").map((b) => b.id);
|
|
2126
|
+
const toolResults = msg.content.filter((b) => b.type === "tool_result").map((b) => b.tool_use_id);
|
|
2127
|
+
if (toolUses.length > 0)
|
|
2128
|
+
log.debug(`msg[${i}] ${msg.role}: tool_use ids: ${toolUses.join(", ")}`);
|
|
2129
|
+
if (toolResults.length > 0)
|
|
2130
|
+
log.debug(`msg[${i}] ${msg.role}: tool_result ids: ${toolResults.join(", ")}`);
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
const messages = convertMessages(anthropicReq.messages, anthropicReq.system);
|
|
2135
|
+
const tools = convertTools(anthropicReq.tools);
|
|
2136
|
+
const mappedModel = provider.mapModel(anthropicReq.model);
|
|
2137
|
+
log.info(`Model: ${anthropicReq.model} -> ${mappedModel}`);
|
|
2138
|
+
return {
|
|
2139
|
+
model: mappedModel,
|
|
2140
|
+
messages,
|
|
2141
|
+
max_tokens: anthropicReq.max_tokens,
|
|
2142
|
+
temperature: anthropicReq.temperature,
|
|
2143
|
+
stream: anthropicReq.stream ?? false,
|
|
2144
|
+
...tools && { tools }
|
|
2145
|
+
};
|
|
2146
|
+
}
|
|
2147
|
+
const convertOpenAIToAnthropic = convertResponse;
|
|
2153
2148
|
log.info(`Authenticating with ${provider.info.name}...`);
|
|
2154
|
-
token = await provider.getToken();
|
|
2149
|
+
const token = await provider.getToken();
|
|
2155
2150
|
log.info("\x1B[32m+\x1B[0m Authentication successful");
|
|
2156
2151
|
if (provider.loadCodeAssist) {
|
|
2157
2152
|
log.info("Initializing Cloud Code session...");
|
|
@@ -2162,15 +2157,17 @@ var init_proxy = __esm(async () => {
|
|
|
2162
2157
|
log.warn("\x1B[33m!\x1B[0m Could not get Cloud Code project ID - requests may fail");
|
|
2163
2158
|
}
|
|
2164
2159
|
}
|
|
2165
|
-
models = { big: "default", mid: "default", small: "default" };
|
|
2160
|
+
let models = { big: "default", mid: "default", small: "default" };
|
|
2166
2161
|
if (provider.loadModels) {
|
|
2167
2162
|
models = await provider.loadModels();
|
|
2168
2163
|
}
|
|
2169
|
-
PORT = await findAvailablePort();
|
|
2170
|
-
if (PORT !==
|
|
2164
|
+
const PORT = await findAvailablePort(requestedPort);
|
|
2165
|
+
if (requestedPort && PORT !== requestedPort) {
|
|
2166
|
+
log.warn(`Port ${requestedPort} in use, using port ${PORT} instead`);
|
|
2167
|
+
} else if (!requestedPort && PORT !== DEFAULT_PORT) {
|
|
2171
2168
|
log.warn(`Port 3000 in use, using port ${PORT} instead`);
|
|
2172
2169
|
}
|
|
2173
|
-
server = Bun.serve({
|
|
2170
|
+
const server = Bun.serve({
|
|
2174
2171
|
port: PORT,
|
|
2175
2172
|
async fetch(req) {
|
|
2176
2173
|
const url = new URL(req.url);
|
|
@@ -2365,6 +2362,47 @@ var init_proxy = __esm(async () => {
|
|
|
2365
2362
|
}
|
|
2366
2363
|
}
|
|
2367
2364
|
});
|
|
2365
|
+
if (!quiet) {
|
|
2366
|
+
const wireApi = provider.info.wireApi || "chat";
|
|
2367
|
+
const wireApiLabel = wireApi === "gemini" ? "Gemini API" : wireApi === "responses" ? "Responses API" : "Chat Completions";
|
|
2368
|
+
log.raw(c.dim("=".repeat(60)));
|
|
2369
|
+
log.raw(`${c.green(">")} ${c.bold("Clauxy")} proxy ready on ${c.cyan(`http://localhost:${PORT}`)}`);
|
|
2370
|
+
log.raw(`${c.green(">")} Provider: ${c.cyan(provider.info.name)}`);
|
|
2371
|
+
log.raw(`${c.green(">")} Wire API: ${c.cyan(wireApiLabel)}`);
|
|
2372
|
+
log.raw(c.dim("=".repeat(60)));
|
|
2373
|
+
log.raw(`
|
|
2374
|
+
${c.yellow("Model Mapping")} (Claude -> Provider):`);
|
|
2375
|
+
log.raw(` opus/big -> ${c.cyan(models.big)}`);
|
|
2376
|
+
log.raw(` sonnet/mid -> ${c.cyan(models.mid)}`);
|
|
2377
|
+
log.raw(` haiku/small -> ${c.cyan(models.small)}`);
|
|
2378
|
+
log.raw(`
|
|
2379
|
+
${c.yellow("To change models:")}`);
|
|
2380
|
+
log.raw(c.dim(" CLAUXY_MODEL_BIG=<model> CLAUXY_MODEL_MID=<model> CLAUXY_MODEL_SMALL=<model>"));
|
|
2381
|
+
log.raw(c.dim(" Or run: clauxy model"));
|
|
2382
|
+
log.raw(c.dim("=".repeat(60)));
|
|
2383
|
+
log.raw(`
|
|
2384
|
+
${c.yellow("Run in a NEW terminal:")}
|
|
2385
|
+
`);
|
|
2386
|
+
log.raw(` ${c.green("export")} ANTHROPIC_BASE_URL=${c.cyan(`"http://localhost:${PORT}"`)}`);
|
|
2387
|
+
log.raw(` ${c.green("export")} ANTHROPIC_API_KEY=${c.cyan('"clauxy"')}`);
|
|
2388
|
+
log.raw(` ${c.bold("claude")}
|
|
2389
|
+
`);
|
|
2390
|
+
log.raw(c.dim("=".repeat(60)));
|
|
2391
|
+
}
|
|
2392
|
+
return {
|
|
2393
|
+
server,
|
|
2394
|
+
port: PORT,
|
|
2395
|
+
stop: () => server.stop()
|
|
2396
|
+
};
|
|
2397
|
+
}
|
|
2398
|
+
var LOG_LEVELS, DEFAULT_PORT = 3000, PORT_RANGE, c;
|
|
2399
|
+
var init_proxy = __esm(async () => {
|
|
2400
|
+
init_providers();
|
|
2401
|
+
init_config();
|
|
2402
|
+
init_converter();
|
|
2403
|
+
init_converter_gemini();
|
|
2404
|
+
LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
2405
|
+
PORT_RANGE = [3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009];
|
|
2368
2406
|
c = {
|
|
2369
2407
|
green: (s) => `\x1B[32m${s}\x1B[0m`,
|
|
2370
2408
|
cyan: (s) => `\x1B[36m${s}\x1B[0m`,
|
|
@@ -2372,31 +2410,7 @@ var init_proxy = __esm(async () => {
|
|
|
2372
2410
|
dim: (s) => `\x1B[2m${s}\x1B[0m`,
|
|
2373
2411
|
bold: (s) => `\x1B[1m${s}\x1B[0m`
|
|
2374
2412
|
};
|
|
2375
|
-
|
|
2376
|
-
wireApiLabel = wireApi === "gemini" ? "Gemini API" : wireApi === "responses" ? "Responses API" : "Chat Completions";
|
|
2377
|
-
log.raw(c.dim("=".repeat(60)));
|
|
2378
|
-
log.raw(`${c.green(">")} ${c.bold("Clauxy")} proxy ready on ${c.cyan(`http://localhost:${PORT}`)}`);
|
|
2379
|
-
log.raw(`${c.green(">")} Provider: ${c.cyan(provider.info.name)}`);
|
|
2380
|
-
log.raw(`${c.green(">")} Wire API: ${c.cyan(wireApiLabel)}`);
|
|
2381
|
-
log.raw(c.dim("=".repeat(60)));
|
|
2382
|
-
log.raw(`
|
|
2383
|
-
${c.yellow("Model Mapping")} (Claude -> Provider):`);
|
|
2384
|
-
log.raw(` opus/big -> ${c.cyan(models.big)}`);
|
|
2385
|
-
log.raw(` sonnet/mid -> ${c.cyan(models.mid)}`);
|
|
2386
|
-
log.raw(` haiku/small -> ${c.cyan(models.small)}`);
|
|
2387
|
-
log.raw(`
|
|
2388
|
-
${c.yellow("To change models:")}`);
|
|
2389
|
-
log.raw(c.dim(" CLAUXY_MODEL_BIG=<model> CLAUXY_MODEL_MID=<model> CLAUXY_MODEL_SMALL=<model>"));
|
|
2390
|
-
log.raw(c.dim(" Or run: clauxy model"));
|
|
2391
|
-
log.raw(c.dim("=".repeat(60)));
|
|
2392
|
-
log.raw(`
|
|
2393
|
-
${c.yellow("Run in a NEW terminal:")}
|
|
2394
|
-
`);
|
|
2395
|
-
log.raw(` ${c.green("export")} ANTHROPIC_BASE_URL=${c.cyan(`"http://localhost:${PORT}"`)}`);
|
|
2396
|
-
log.raw(` ${c.green("export")} ANTHROPIC_API_KEY=${c.cyan('"clauxy"')}`);
|
|
2397
|
-
log.raw(` ${c.bold("claude")}
|
|
2398
|
-
`);
|
|
2399
|
-
log.raw(c.dim("=".repeat(60)));
|
|
2413
|
+
if (false) {}
|
|
2400
2414
|
});
|
|
2401
2415
|
|
|
2402
2416
|
// cli/index.ts
|
|
@@ -2441,23 +2455,21 @@ async function selectAndAuthenticate() {
|
|
|
2441
2455
|
return authenticateProvider(providerId);
|
|
2442
2456
|
}
|
|
2443
2457
|
async function authenticateProvider(providerId) {
|
|
2444
|
-
const
|
|
2445
|
-
prompts2.intro(`Clauxy - Connecting to ${
|
|
2446
|
-
const result = await
|
|
2458
|
+
const provider = await getProvider(providerId);
|
|
2459
|
+
prompts2.intro(`Clauxy - Connecting to ${provider.info.name}`);
|
|
2460
|
+
const result = await provider.authenticate();
|
|
2447
2461
|
if (result.type === "failed") {
|
|
2448
2462
|
prompts2.cancel(`Authentication failed: ${result.error}`);
|
|
2449
2463
|
process.exit(1);
|
|
2450
2464
|
}
|
|
2451
2465
|
await Config.setActiveProvider(providerId);
|
|
2452
|
-
prompts2.outro(`Connected to ${
|
|
2466
|
+
prompts2.outro(`Connected to ${provider.info.name}`);
|
|
2453
2467
|
return providerId;
|
|
2454
2468
|
}
|
|
2455
2469
|
async function runCommand(options) {
|
|
2456
|
-
const { port, logLevel, connect, provider
|
|
2457
|
-
process.env.PORT = port.toString();
|
|
2458
|
-
process.env.CLAUXY_LOG_LEVEL = logLevel;
|
|
2470
|
+
const { port, logLevel, connect, provider } = options;
|
|
2459
2471
|
const availableProviders = getProviderList().map((item) => item.id);
|
|
2460
|
-
const providerOverride =
|
|
2472
|
+
const providerOverride = provider?.toLowerCase();
|
|
2461
2473
|
if (providerOverride && !availableProviders.includes(providerOverride)) {
|
|
2462
2474
|
console.error(`Invalid provider: "${providerOverride}". Valid values: ${availableProviders.join(" | ")}.`);
|
|
2463
2475
|
process.exit(1);
|
|
@@ -2482,8 +2494,138 @@ async function runCommand(options) {
|
|
|
2482
2494
|
}
|
|
2483
2495
|
}
|
|
2484
2496
|
await Config.setActiveProvider(activeProvider);
|
|
2485
|
-
|
|
2486
|
-
await
|
|
2497
|
+
const { startProxy: startProxy2 } = await init_proxy().then(() => exports_proxy);
|
|
2498
|
+
await startProxy2({
|
|
2499
|
+
port,
|
|
2500
|
+
logLevel,
|
|
2501
|
+
providerId: activeProvider
|
|
2502
|
+
});
|
|
2503
|
+
await new Promise(() => {});
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2506
|
+
// cli/commands/wrapper.ts
|
|
2507
|
+
init_auth();
|
|
2508
|
+
init_config();
|
|
2509
|
+
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
|
+
async function findClaudeCli() {
|
|
2520
|
+
try {
|
|
2521
|
+
const proc = Bun.spawn(["which", "claude"], {
|
|
2522
|
+
stdout: "pipe",
|
|
2523
|
+
stderr: "pipe"
|
|
2524
|
+
});
|
|
2525
|
+
const exitCode = await proc.exited;
|
|
2526
|
+
if (exitCode === 0) {
|
|
2527
|
+
const output = await new Response(proc.stdout).text();
|
|
2528
|
+
return output.trim();
|
|
2529
|
+
}
|
|
2530
|
+
return null;
|
|
2531
|
+
} catch {
|
|
2532
|
+
return null;
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
async function selectAndAuthenticate2() {
|
|
2536
|
+
prompts3.intro("Clauxy - Connect to AI Provider");
|
|
2537
|
+
const providers = getProviderList();
|
|
2538
|
+
const providerChoice = await prompts3.select({
|
|
2539
|
+
message: "Select your AI provider",
|
|
2540
|
+
options: providers.map((p) => ({
|
|
2541
|
+
label: p.name,
|
|
2542
|
+
value: p.id,
|
|
2543
|
+
hint: p.description
|
|
2544
|
+
}))
|
|
2545
|
+
});
|
|
2546
|
+
const providerId = handleCancel(providerChoice, "Setup cancelled");
|
|
2547
|
+
return authenticateProvider2(providerId);
|
|
2548
|
+
}
|
|
2549
|
+
async function authenticateProvider2(providerId) {
|
|
2550
|
+
const provider = await getProvider(providerId);
|
|
2551
|
+
prompts3.intro(`Clauxy - Connecting to ${provider.info.name}`);
|
|
2552
|
+
const result = await provider.authenticate();
|
|
2553
|
+
if (result.type === "failed") {
|
|
2554
|
+
prompts3.cancel(`Authentication failed: ${result.error}`);
|
|
2555
|
+
process.exit(1);
|
|
2556
|
+
}
|
|
2557
|
+
await Config.setActiveProvider(providerId);
|
|
2558
|
+
prompts3.outro(`Connected to ${provider.info.name}`);
|
|
2559
|
+
return providerId;
|
|
2560
|
+
}
|
|
2561
|
+
async function wrapperCommand(options) {
|
|
2562
|
+
const { logLevel = "warn", connect = false, provider, claudeArgs = [] } = options;
|
|
2563
|
+
const claudePath = await findClaudeCli();
|
|
2564
|
+
if (!claudePath) {
|
|
2565
|
+
console.error(c2.red("Error: Claude CLI not found."));
|
|
2566
|
+
console.error(`
|
|
2567
|
+
Install it with: ${c2.cyan("npm i -g @anthropic-ai/claude-code")}`);
|
|
2568
|
+
console.error(`Or visit: ${c2.cyan("https://docs.anthropic.com/en/docs/claude-code")}`);
|
|
2569
|
+
process.exit(1);
|
|
2570
|
+
}
|
|
2571
|
+
const availableProviders = getProviderList().map((item) => item.id);
|
|
2572
|
+
const providerOverride = provider?.toLowerCase();
|
|
2573
|
+
if (providerOverride && !availableProviders.includes(providerOverride)) {
|
|
2574
|
+
console.error(`Invalid provider: "${providerOverride}". Valid values: ${availableProviders.join(" | ")}.`);
|
|
2575
|
+
process.exit(1);
|
|
2576
|
+
}
|
|
2577
|
+
let activeProvider;
|
|
2578
|
+
if (providerOverride) {
|
|
2579
|
+
const credentials = await Auth.get(providerOverride);
|
|
2580
|
+
if (credentials && !connect) {
|
|
2581
|
+
activeProvider = providerOverride;
|
|
2582
|
+
} else {
|
|
2583
|
+
activeProvider = await authenticateProvider2(providerOverride);
|
|
2584
|
+
}
|
|
2585
|
+
} else {
|
|
2586
|
+
activeProvider = await Config.getActiveProvider();
|
|
2587
|
+
if (!activeProvider || connect) {
|
|
2588
|
+
activeProvider = await selectAndAuthenticate2();
|
|
2589
|
+
} else {
|
|
2590
|
+
const credentials = await Auth.get(activeProvider);
|
|
2591
|
+
if (!credentials) {
|
|
2592
|
+
activeProvider = await selectAndAuthenticate2();
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
await Config.setActiveProvider(activeProvider);
|
|
2597
|
+
const { startProxy: startProxy2 } = await init_proxy().then(() => exports_proxy);
|
|
2598
|
+
const proxyServer = await startProxy2({
|
|
2599
|
+
logLevel,
|
|
2600
|
+
providerId: activeProvider,
|
|
2601
|
+
quiet: true
|
|
2602
|
+
});
|
|
2603
|
+
const providerInfo = await getProvider(activeProvider);
|
|
2604
|
+
console.log(`${c2.green(">")} ${c2.bold("Clauxy")} proxy on ${c2.cyan(`localhost:${proxyServer.port}`)} ${c2.dim(`(${providerInfo.info.name})`)}`);
|
|
2605
|
+
const claude = Bun.spawn(["claude", ...claudeArgs], {
|
|
2606
|
+
env: {
|
|
2607
|
+
...process.env,
|
|
2608
|
+
ANTHROPIC_BASE_URL: `http://localhost:${proxyServer.port}`,
|
|
2609
|
+
ANTHROPIC_API_KEY: "clauxy"
|
|
2610
|
+
},
|
|
2611
|
+
stdin: "inherit",
|
|
2612
|
+
stdout: "inherit",
|
|
2613
|
+
stderr: "inherit"
|
|
2614
|
+
});
|
|
2615
|
+
let isCleaningUp = false;
|
|
2616
|
+
const cleanup = () => {
|
|
2617
|
+
if (isCleaningUp)
|
|
2618
|
+
return;
|
|
2619
|
+
isCleaningUp = true;
|
|
2620
|
+
proxyServer.stop();
|
|
2621
|
+
claude.kill();
|
|
2622
|
+
};
|
|
2623
|
+
process.on("SIGINT", cleanup);
|
|
2624
|
+
process.on("SIGTERM", cleanup);
|
|
2625
|
+
process.on("SIGHUP", cleanup);
|
|
2626
|
+
const exitCode = await claude.exited;
|
|
2627
|
+
proxyServer.stop();
|
|
2628
|
+
process.exit(exitCode);
|
|
2487
2629
|
}
|
|
2488
2630
|
|
|
2489
2631
|
// cli/commands/auth.ts
|
|
@@ -2503,14 +2645,14 @@ Configured Providers:
|
|
|
2503
2645
|
`);
|
|
2504
2646
|
return;
|
|
2505
2647
|
}
|
|
2506
|
-
for (const
|
|
2507
|
-
const auth = allAuth[
|
|
2648
|
+
for (const provider of providers) {
|
|
2649
|
+
const auth = allAuth[provider.id];
|
|
2508
2650
|
if (auth) {
|
|
2509
|
-
const isActive =
|
|
2651
|
+
const isActive = provider.id === activeProvider;
|
|
2510
2652
|
const marker = isActive ? colors.green("*") : " ";
|
|
2511
2653
|
const authType = auth.type === "oauth" ? "OAuth" : "API Key";
|
|
2512
2654
|
const activeLabel = isActive ? ` ${colors.green("[active]")}` : "";
|
|
2513
|
-
console.log(` ${marker} ${
|
|
2655
|
+
console.log(` ${marker} ${provider.name} (${authType})${activeLabel}`);
|
|
2514
2656
|
}
|
|
2515
2657
|
}
|
|
2516
2658
|
console.log("");
|
|
@@ -2520,7 +2662,7 @@ Configured Providers:
|
|
|
2520
2662
|
init_config();
|
|
2521
2663
|
init_providers();
|
|
2522
2664
|
init_models();
|
|
2523
|
-
import * as
|
|
2665
|
+
import * as prompts4 from "@clack/prompts";
|
|
2524
2666
|
|
|
2525
2667
|
// cli/constants.ts
|
|
2526
2668
|
var CUSTOM_MODEL_VALUE = "__custom__";
|
|
@@ -2544,21 +2686,21 @@ async function selectModel(tier, providerId, currentValue) {
|
|
|
2544
2686
|
})),
|
|
2545
2687
|
{ label: "Enter custom model", value: CUSTOM_MODEL_VALUE, hint: "Type model name" }
|
|
2546
2688
|
];
|
|
2547
|
-
const choice = await
|
|
2689
|
+
const choice = await prompts4.select({
|
|
2548
2690
|
message: `Select ${tier} model`,
|
|
2549
2691
|
options,
|
|
2550
2692
|
initialValue: currentValue
|
|
2551
2693
|
});
|
|
2552
|
-
if (
|
|
2694
|
+
if (prompts4.isCancel(choice)) {
|
|
2553
2695
|
return null;
|
|
2554
2696
|
}
|
|
2555
2697
|
if (choice === CUSTOM_MODEL_VALUE) {
|
|
2556
|
-
const custom = await
|
|
2698
|
+
const custom = await prompts4.text({
|
|
2557
2699
|
message: `Enter custom ${tier} model name`,
|
|
2558
2700
|
placeholder: currentValue,
|
|
2559
2701
|
defaultValue: currentValue
|
|
2560
2702
|
});
|
|
2561
|
-
if (
|
|
2703
|
+
if (prompts4.isCancel(custom)) {
|
|
2562
2704
|
return null;
|
|
2563
2705
|
}
|
|
2564
2706
|
return custom;
|
|
@@ -2567,9 +2709,9 @@ async function selectModel(tier, providerId, currentValue) {
|
|
|
2567
2709
|
}
|
|
2568
2710
|
async function configureModels() {
|
|
2569
2711
|
const activeProvider = await Config.getActiveProvider();
|
|
2570
|
-
|
|
2712
|
+
prompts4.intro("Clauxy - Model Configuration");
|
|
2571
2713
|
const providers = getProviderList();
|
|
2572
|
-
const providerChoice = await
|
|
2714
|
+
const providerChoice = await prompts4.select({
|
|
2573
2715
|
message: "Select provider to configure models for",
|
|
2574
2716
|
options: providers.map((p) => ({
|
|
2575
2717
|
label: p.name,
|
|
@@ -2587,7 +2729,7 @@ Current models for ${PROVIDERS[providerId].name}:`);
|
|
|
2587
2729
|
console.log(` Mid: ${currentModels.mid}`);
|
|
2588
2730
|
console.log(` Small: ${currentModels.small}
|
|
2589
2731
|
`);
|
|
2590
|
-
const action = await
|
|
2732
|
+
const action = await prompts4.select({
|
|
2591
2733
|
message: "What would you like to do?",
|
|
2592
2734
|
options: [
|
|
2593
2735
|
{ label: "Configure all models", value: "all" },
|
|
@@ -2605,36 +2747,36 @@ Models reset to defaults:`);
|
|
|
2605
2747
|
console.log(` Big: ${defaults.big}`);
|
|
2606
2748
|
console.log(` Mid: ${defaults.mid}`);
|
|
2607
2749
|
console.log(` Small: ${defaults.small}`);
|
|
2608
|
-
|
|
2750
|
+
prompts4.outro("Done");
|
|
2609
2751
|
return;
|
|
2610
2752
|
}
|
|
2611
|
-
const
|
|
2753
|
+
const models = {
|
|
2612
2754
|
big: currentModels.big,
|
|
2613
2755
|
mid: currentModels.mid,
|
|
2614
2756
|
small: currentModels.small
|
|
2615
2757
|
};
|
|
2616
2758
|
for (const tier of MODEL_TIERS) {
|
|
2617
2759
|
if (action === "all" || action === tier.key) {
|
|
2618
|
-
const result = await selectModel(tier.label, providerId,
|
|
2760
|
+
const result = await selectModel(tier.label, providerId, models[tier.key]);
|
|
2619
2761
|
if (result === null) {
|
|
2620
|
-
|
|
2762
|
+
prompts4.cancel("Cancelled");
|
|
2621
2763
|
process.exit(0);
|
|
2622
2764
|
}
|
|
2623
|
-
|
|
2765
|
+
models[tier.key] = result;
|
|
2624
2766
|
}
|
|
2625
2767
|
}
|
|
2626
|
-
await saveModels(
|
|
2768
|
+
await saveModels(models);
|
|
2627
2769
|
console.log(`
|
|
2628
2770
|
Models configured:`);
|
|
2629
|
-
console.log(` opus/big -> ${
|
|
2630
|
-
console.log(` sonnet/mid -> ${
|
|
2631
|
-
console.log(` haiku/small -> ${
|
|
2632
|
-
|
|
2771
|
+
console.log(` opus/big -> ${models.big}`);
|
|
2772
|
+
console.log(` sonnet/mid -> ${models.mid}`);
|
|
2773
|
+
console.log(` haiku/small -> ${models.small}`);
|
|
2774
|
+
prompts4.outro("Model configuration saved");
|
|
2633
2775
|
}
|
|
2634
2776
|
// package.json
|
|
2635
2777
|
var package_default = {
|
|
2636
2778
|
name: "@jcanizalez7/clauxy",
|
|
2637
|
-
version: "0.
|
|
2779
|
+
version: "0.2.0",
|
|
2638
2780
|
description: "Multi-provider AI proxy for Claude Code (GitHub Copilot, ChatGPT Plus, Google Gemini)",
|
|
2639
2781
|
type: "module",
|
|
2640
2782
|
bin: {
|
|
@@ -2679,7 +2821,7 @@ var package_default = {
|
|
|
2679
2821
|
var run = defineCommand({
|
|
2680
2822
|
meta: {
|
|
2681
2823
|
name: "run",
|
|
2682
|
-
description: "Start the proxy server"
|
|
2824
|
+
description: "Start the proxy server (without launching Claude)"
|
|
2683
2825
|
},
|
|
2684
2826
|
args: {
|
|
2685
2827
|
port: {
|
|
@@ -2715,12 +2857,12 @@ var run = defineCommand({
|
|
|
2715
2857
|
if (!LOG_LEVELS2.includes(logLevel)) {
|
|
2716
2858
|
console.error(`Invalid log level: "${args["log-level"]}". Valid values: ${LOG_LEVELS2.join(" | ")}. Using "${DEFAULT_LOG_LEVEL}".`);
|
|
2717
2859
|
}
|
|
2718
|
-
const
|
|
2860
|
+
const provider = args.provider ? String(args.provider).toLowerCase() : undefined;
|
|
2719
2861
|
await runCommand({
|
|
2720
2862
|
port,
|
|
2721
2863
|
logLevel: LOG_LEVELS2.includes(logLevel) ? logLevel : DEFAULT_LOG_LEVEL,
|
|
2722
2864
|
connect: args.connect,
|
|
2723
|
-
provider
|
|
2865
|
+
provider
|
|
2724
2866
|
});
|
|
2725
2867
|
}
|
|
2726
2868
|
});
|
|
@@ -2758,11 +2900,38 @@ var main = defineCommand({
|
|
|
2758
2900
|
version: package_default.version,
|
|
2759
2901
|
description: "Multi-Provider AI Proxy for Claude Code"
|
|
2760
2902
|
},
|
|
2903
|
+
args: {
|
|
2904
|
+
"log-level": {
|
|
2905
|
+
type: "string",
|
|
2906
|
+
alias: "l",
|
|
2907
|
+
description: "Log level: debug, info, warn, error",
|
|
2908
|
+
default: "warn"
|
|
2909
|
+
},
|
|
2910
|
+
connect: {
|
|
2911
|
+
type: "boolean",
|
|
2912
|
+
alias: "c",
|
|
2913
|
+
description: "Re-authenticate before starting",
|
|
2914
|
+
default: false
|
|
2915
|
+
},
|
|
2916
|
+
provider: {
|
|
2917
|
+
type: "string",
|
|
2918
|
+
alias: "p",
|
|
2919
|
+
description: "Provider to use (copilot, chatgpt, google)"
|
|
2920
|
+
}
|
|
2921
|
+
},
|
|
2761
2922
|
subCommands: {
|
|
2762
2923
|
run,
|
|
2763
2924
|
auth,
|
|
2764
2925
|
model,
|
|
2765
2926
|
models: model
|
|
2927
|
+
},
|
|
2928
|
+
async run({ args, rawArgs }) {
|
|
2929
|
+
await wrapperCommand({
|
|
2930
|
+
logLevel: args["log-level"],
|
|
2931
|
+
connect: args.connect,
|
|
2932
|
+
provider: args.provider,
|
|
2933
|
+
claudeArgs: rawArgs
|
|
2934
|
+
});
|
|
2766
2935
|
}
|
|
2767
2936
|
});
|
|
2768
2937
|
function cli() {
|