claude-provider-switch 0.1.14 → 0.1.15
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/index.js +97 -17
- package/dist/index.js.map +1 -1
- package/dist/ui/assets/index-BiWhDGyY.css +1 -0
- package/dist/ui/assets/index-Db62qRnR.js +130 -0
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/index-CIDGGnBj.css +0 -1
- package/dist/ui/assets/index-s5w5Pu_a.js +0 -130
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var import_promises5 = __toESM(require("readline/promises"));
|
|
|
34
34
|
// package.json
|
|
35
35
|
var package_default = {
|
|
36
36
|
name: "claude-provider-switch",
|
|
37
|
-
version: "0.1.
|
|
37
|
+
version: "0.1.15",
|
|
38
38
|
description: "CLI + local web UI for switching Claude Code providers",
|
|
39
39
|
license: "MIT",
|
|
40
40
|
homepage: "https://github.com/ladieman217/claude-provider-switch#readme",
|
|
@@ -163,6 +163,7 @@ var writeJsonFile = async (filePath, data) => {
|
|
|
163
163
|
// src/core/config.ts
|
|
164
164
|
var CONFIG_VERSION = 1;
|
|
165
165
|
var PROVIDER_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
166
|
+
var ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
166
167
|
var normalizeProviderName = (name) => name.trim().toLowerCase();
|
|
167
168
|
var normalizeProviderId = (id) => id.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 24).replace(/-+$/g, "");
|
|
168
169
|
var isAnthropicName = (name) => normalizeProviderName(name) === "anthropic";
|
|
@@ -199,6 +200,36 @@ var assertValidProviderId = (id) => {
|
|
|
199
200
|
);
|
|
200
201
|
}
|
|
201
202
|
};
|
|
203
|
+
var normalizeCustomEnv = (customEnv) => {
|
|
204
|
+
if (!customEnv || typeof customEnv !== "object" || Array.isArray(customEnv)) {
|
|
205
|
+
return void 0;
|
|
206
|
+
}
|
|
207
|
+
const entries = Object.entries(customEnv).reduce(
|
|
208
|
+
(acc, [key, value]) => {
|
|
209
|
+
const normalizedKey = key.trim();
|
|
210
|
+
if (!normalizedKey) {
|
|
211
|
+
return acc;
|
|
212
|
+
}
|
|
213
|
+
acc[normalizedKey] = String(value);
|
|
214
|
+
return acc;
|
|
215
|
+
},
|
|
216
|
+
{}
|
|
217
|
+
);
|
|
218
|
+
return Object.keys(entries).length > 0 ? entries : void 0;
|
|
219
|
+
};
|
|
220
|
+
var assertValidCustomEnv = (customEnv) => {
|
|
221
|
+
const normalized = normalizeCustomEnv(customEnv);
|
|
222
|
+
if (!normalized) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
for (const key of Object.keys(normalized)) {
|
|
226
|
+
if (!ENV_KEY_PATTERN.test(key)) {
|
|
227
|
+
throw new Error(
|
|
228
|
+
`Environment variable '${key}' must start with a letter or underscore and contain only letters, numbers, and underscores.`
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
202
233
|
var createDefaultConfig = () => ({
|
|
203
234
|
version: CONFIG_VERSION,
|
|
204
235
|
current: DEFAULT_PRESETS[0]?.id ?? null,
|
|
@@ -229,7 +260,8 @@ var normalizeConfig = (config) => {
|
|
|
229
260
|
const normalizedProviders = providers.filter((provider) => Boolean(provider?.name)).map((provider) => ({
|
|
230
261
|
...provider,
|
|
231
262
|
name: normalizeProviderName(provider.name),
|
|
232
|
-
id: typeof provider.id === "string" ? normalizeProviderId(provider.id) : void 0
|
|
263
|
+
id: typeof provider.id === "string" ? normalizeProviderId(provider.id) : void 0,
|
|
264
|
+
customEnv: normalizeCustomEnv(provider.customEnv)
|
|
233
265
|
}));
|
|
234
266
|
const uniqueProviders = /* @__PURE__ */ new Map();
|
|
235
267
|
for (const provider of normalizedProviders) {
|
|
@@ -294,6 +326,7 @@ var assertValidProviderInput = (provider) => {
|
|
|
294
326
|
throw new Error("Website must be a valid URL.");
|
|
295
327
|
}
|
|
296
328
|
}
|
|
329
|
+
assertValidCustomEnv(provider.customEnv);
|
|
297
330
|
};
|
|
298
331
|
var assertProviderHasAuthToken = (provider) => {
|
|
299
332
|
if (isAnthropicProvider(provider)) {
|
|
@@ -338,6 +371,7 @@ var addProvider = (config, provider) => {
|
|
|
338
371
|
...provider,
|
|
339
372
|
id: nextId,
|
|
340
373
|
name: normalizedName,
|
|
374
|
+
customEnv: normalizeCustomEnv(provider.customEnv),
|
|
341
375
|
modelMappings: provider.modelMappings,
|
|
342
376
|
preset: false
|
|
343
377
|
}
|
|
@@ -361,6 +395,7 @@ var updateProviderById = (config, id, updates) => {
|
|
|
361
395
|
authToken: nextAuthToken,
|
|
362
396
|
model: updates.model !== void 0 ? updates.model : target.model,
|
|
363
397
|
website: updates.website !== void 0 ? updates.website : target.website,
|
|
398
|
+
customEnv: updates.customEnv !== void 0 ? normalizeCustomEnv(updates.customEnv) : target.customEnv,
|
|
364
399
|
description: updates.description !== void 0 ? updates.description : target.description,
|
|
365
400
|
modelMappings: updates.modelMappings !== void 0 ? updates.modelMappings : target.modelMappings,
|
|
366
401
|
preset: target.preset
|
|
@@ -436,6 +471,22 @@ var import_promises3 = __toESM(require("fs/promises"));
|
|
|
436
471
|
var import_path2 = __toESM(require("path"));
|
|
437
472
|
var BACKUP_PREFIX = "settings.backup-";
|
|
438
473
|
var BACKUP_NAME_PATTERN = /^settings\.backup-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z\.json$/;
|
|
474
|
+
var parseCustomEnvValue = (value) => {
|
|
475
|
+
if (typeof value !== "string") {
|
|
476
|
+
return value;
|
|
477
|
+
}
|
|
478
|
+
const normalized = value.trim().toLowerCase();
|
|
479
|
+
if (normalized === "true") {
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
if (normalized === "false") {
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
if (/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(value.trim())) {
|
|
486
|
+
return Number(value);
|
|
487
|
+
}
|
|
488
|
+
return value;
|
|
489
|
+
};
|
|
439
490
|
var readClaudeSettings = async (options = {}) => {
|
|
440
491
|
const { claudeSettingsPath } = resolvePaths(options);
|
|
441
492
|
try {
|
|
@@ -563,6 +614,14 @@ var applyProviderToClaudeSettings = async (provider, options = {}) => {
|
|
|
563
614
|
} else {
|
|
564
615
|
delete env.ANTHROPIC_DEFAULT_HAIKU_MODEL;
|
|
565
616
|
}
|
|
617
|
+
if (provider.customEnv && typeof provider.customEnv === "object") {
|
|
618
|
+
for (const [key, value] of Object.entries(provider.customEnv)) {
|
|
619
|
+
const envKey = key.trim();
|
|
620
|
+
if (envKey) {
|
|
621
|
+
env[envKey] = parseCustomEnvValue(value);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
566
625
|
}
|
|
567
626
|
env.API_TIMEOUT_MS = "3000000";
|
|
568
627
|
if (isAnthropic) {
|
|
@@ -775,6 +834,21 @@ var formatProvider = (provider) => {
|
|
|
775
834
|
}
|
|
776
835
|
return parts.join(" ");
|
|
777
836
|
};
|
|
837
|
+
var parseCustomEnvOptions = (values) => {
|
|
838
|
+
if (!values?.length) {
|
|
839
|
+
return void 0;
|
|
840
|
+
}
|
|
841
|
+
return values.reduce((acc, item) => {
|
|
842
|
+
const separatorIndex = item.indexOf("=");
|
|
843
|
+
if (separatorIndex <= 0) {
|
|
844
|
+
throw new Error(`Invalid env '${item}'. Use KEY=VALUE.`);
|
|
845
|
+
}
|
|
846
|
+
const key = item.slice(0, separatorIndex).trim();
|
|
847
|
+
const value = item.slice(separatorIndex + 1);
|
|
848
|
+
acc[key] = value;
|
|
849
|
+
return acc;
|
|
850
|
+
}, {});
|
|
851
|
+
};
|
|
778
852
|
var findAvailablePort = async (start, attempts = 20) => {
|
|
779
853
|
for (let i = 0; i < attempts; i += 1) {
|
|
780
854
|
const port = start + i;
|
|
@@ -906,7 +980,7 @@ program.command("select").description("Interactively select provider and apply t
|
|
|
906
980
|
rl.close();
|
|
907
981
|
}
|
|
908
982
|
});
|
|
909
|
-
program.command("add").argument("<name>", "Provider name").option("--id <id>", "Stable provider id (lowercase letters/numbers/hyphen)").option("--base-url <url>", "Base URL").option("--token <token>", "Auth token").option("--token-stdin", "Read auth token from stdin").option("--model <model>", "Model name").option("--website <url>", "Website URL").option("--description <text>", "Description").description("Add a custom provider").action(async (name, options) => {
|
|
983
|
+
program.command("add").argument("<name>", "Provider name").option("--id <id>", "Stable provider id (lowercase letters/numbers/hyphen)").option("--base-url <url>", "Base URL").option("--token <token>", "Auth token").option("--token-stdin", "Read auth token from stdin").option("--model <model>", "Model name").option("--website <url>", "Website URL").option("--description <text>", "Description").option("--env <entry...>", "Custom environment variable (repeat or pass multiple KEY=VALUE values)").description("Add a custom provider").action(async (name, options) => {
|
|
910
984
|
if (options.token && options.tokenStdin) {
|
|
911
985
|
console.error("Use either --token or --token-stdin, not both.");
|
|
912
986
|
process.exitCode = 1;
|
|
@@ -931,20 +1005,26 @@ program.command("add").argument("<name>", "Provider name").option("--id <id>", "
|
|
|
931
1005
|
process.exitCode = 1;
|
|
932
1006
|
return;
|
|
933
1007
|
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1008
|
+
try {
|
|
1009
|
+
const config = await ensureConfig();
|
|
1010
|
+
const provider = {
|
|
1011
|
+
id: options.id,
|
|
1012
|
+
name,
|
|
1013
|
+
baseUrl: options.baseUrl,
|
|
1014
|
+
authToken,
|
|
1015
|
+
model: options.model,
|
|
1016
|
+
website: options.website,
|
|
1017
|
+
description: options.description,
|
|
1018
|
+
customEnv: parseCustomEnvOptions(options.env),
|
|
1019
|
+
preset: false
|
|
1020
|
+
};
|
|
1021
|
+
const nextConfig = addProvider(config, provider);
|
|
1022
|
+
await saveConfig(nextConfig);
|
|
1023
|
+
console.log(`Added provider '${name}'.`);
|
|
1024
|
+
} catch (error) {
|
|
1025
|
+
console.error(error.message);
|
|
1026
|
+
process.exitCode = 1;
|
|
1027
|
+
}
|
|
948
1028
|
});
|
|
949
1029
|
program.command("remove").alias("rm").argument("<reference>", "Provider id or name").description("Remove a provider by id or name").action(async (reference) => {
|
|
950
1030
|
const config = await ensureConfig();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../package.json","../src/core/presets.ts","../src/core/config.ts","../src/core/paths.ts","../src/core/fs.ts","../src/core/claudeSettings.ts","../src/server.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport path from \"path\";\nimport net from \"net\";\nimport { exec } from \"child_process\";\nimport { promisify } from \"util\";\nimport readline from \"node:readline/promises\";\nimport packageJson from \"../package.json\";\n\nconst execAsync = promisify(exec);\nimport {\n addProvider,\n assertProviderHasAuthToken,\n applyProviderToClaudeSettings,\n ensureConfig,\n findProviderById,\n removeProvider,\n saveConfig,\n setCurrentProviderById\n} from \"./core\";\nimport type { ProviderConfig } from \"./core\";\nimport { startServer } from \"./server\";\n\nconst defaultUiDist = path.resolve(__dirname, \"ui\");\n\nconst program = new Command();\n\nconst readTokenFromStdin = async (): Promise<string> =>\n await new Promise<string>((resolve, reject) => {\n let token = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => {\n token += chunk;\n });\n process.stdin.on(\"end\", () => resolve(token.trim()));\n process.stdin.on(\"error\", reject);\n });\n\nconst formatProvider = (provider: ProviderConfig) => {\n const parts = [`[${provider.id ?? \"-\"}] ${provider.name}`];\n if (provider.baseUrl) {\n parts.push(`(${provider.baseUrl})`);\n }\n if (provider.model) {\n parts.push(`[model: ${provider.model}]`);\n }\n return parts.join(\" \");\n};\n\nconst findAvailablePort = async (start: number, attempts = 20) => {\n for (let i = 0; i < attempts; i += 1) {\n const port = start + i;\n const available = await new Promise<boolean>((resolve) => {\n const server = net.createServer();\n server.once(\"error\", () => resolve(false));\n server.once(\"listening\", () => {\n server.close(() => resolve(true));\n });\n server.listen(port, \"127.0.0.1\");\n });\n\n if (available) {\n return port;\n }\n }\n\n throw new Error(\"No available port found.\");\n};\n\nconst openBrowser = async (url: string) => {\n const platform = process.platform;\n let command: string;\n\n switch (platform) {\n case \"darwin\":\n command = `open \"${url}\"`;\n break;\n case \"win32\":\n command = `start \"\" \"${url}\"`;\n break;\n default:\n command = `xdg-open \"${url}\"`;\n }\n\n try {\n await execAsync(command);\n } catch {\n // Silently fail - opening browser is not critical\n }\n};\n\nconst applyProviderById = async (id: string): Promise<ProviderConfig> => {\n const config = await ensureConfig();\n const nextConfig = setCurrentProviderById(config, id);\n const provider = findProviderById(nextConfig, id);\n if (!provider) {\n throw new Error(\"Provider not found.\");\n }\n\n assertProviderHasAuthToken(provider);\n await saveConfig(nextConfig);\n await applyProviderToClaudeSettings(provider);\n return provider;\n};\n\nprogram.name(\"claude-provider\").description(\"Claude provider switcher\");\nprogram.version(packageJson.version, \"-v, --version\", \"Show CLI version\");\n\nprogram\n .command(\"version\")\n .description(\"Show CLI version\")\n .action(() => {\n console.log(packageJson.version);\n });\n\nprogram\n .command(\"list\")\n .description(\"List configured providers\")\n .action(async () => {\n const config = await ensureConfig();\n const current = config.current;\n\n for (const provider of config.providers) {\n const marker = provider.id === current ? \"*\" : \" \";\n console.log(`${marker} ${formatProvider(provider)}`);\n }\n });\n\nprogram\n .command(\"current\")\n .description(\"Show current provider\")\n .action(async () => {\n const config = await ensureConfig();\n if (!config.current) {\n console.log(\"No provider selected.\");\n return;\n }\n\n const provider = findProviderById(config, config.current);\n if (!provider) {\n console.log(\"Current provider not found in config.\");\n return;\n }\n\n console.log(formatProvider(provider));\n });\n\nprogram\n .command(\"use\")\n .argument(\"<id>\", \"Provider id\")\n .description(\"Use provider by id and apply to Claude settings\")\n .action(async (id: string) => {\n try {\n const provider = await applyProviderById(id);\n console.log(`Applied provider '${provider.name}'.`);\n } catch (error) {\n console.error((error as Error).message);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command(\"select\")\n .description(\"Interactively select provider and apply to Claude settings\")\n .action(async () => {\n const config = await ensureConfig();\n if (config.providers.length === 0) {\n console.error(\"No providers configured.\");\n process.exitCode = 1;\n return;\n }\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n console.error(\"Interactive select requires a TTY terminal.\");\n process.exitCode = 1;\n return;\n }\n\n const current = config.current;\n config.providers.forEach((provider, index) => {\n const marker = provider.id === current ? \"*\" : \" \";\n console.log(`${index + 1}. ${marker} ${formatProvider(provider)}`);\n });\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n });\n\n try {\n const answer = (await rl.question(\"Select provider by number: \")).trim();\n const selectedIndex = Number.parseInt(answer, 10);\n if (\n !Number.isInteger(selectedIndex) ||\n selectedIndex < 1 ||\n selectedIndex > config.providers.length\n ) {\n console.error(\"Invalid selection.\");\n process.exitCode = 1;\n return;\n }\n\n const provider = config.providers[selectedIndex - 1];\n if (!provider) {\n console.error(\"Provider not found.\");\n process.exitCode = 1;\n return;\n }\n if (!provider.id) {\n console.error(\"Provider id is missing.\");\n process.exitCode = 1;\n return;\n }\n\n const applied = await applyProviderById(provider.id);\n console.log(`Applied provider '${applied.name}'.`);\n } catch (error) {\n console.error((error as Error).message);\n process.exitCode = 1;\n } finally {\n rl.close();\n }\n });\n\nprogram\n .command(\"add\")\n .argument(\"<name>\", \"Provider name\")\n .option(\"--id <id>\", \"Stable provider id (lowercase letters/numbers/hyphen)\")\n .option(\"--base-url <url>\", \"Base URL\")\n .option(\"--token <token>\", \"Auth token\")\n .option(\"--token-stdin\", \"Read auth token from stdin\")\n .option(\"--model <model>\", \"Model name\")\n .option(\"--website <url>\", \"Website URL\")\n .option(\"--description <text>\", \"Description\")\n .description(\"Add a custom provider\")\n .action(async (\n name: string,\n options: {\n id?: string;\n baseUrl?: string;\n token?: string;\n tokenStdin?: boolean;\n model?: string;\n website?: string;\n description?: string;\n }\n ) => {\n if (options.token && options.tokenStdin) {\n console.error(\"Use either --token or --token-stdin, not both.\");\n process.exitCode = 1;\n return;\n }\n\n let authToken = options.token?.trim() ?? \"\";\n if (options.tokenStdin) {\n if (process.stdin.isTTY) {\n console.error(\"No stdin input detected for --token-stdin.\");\n process.exitCode = 1;\n return;\n }\n authToken = await readTokenFromStdin();\n }\n\n if (!options.baseUrl?.trim()) {\n console.error(\"Base URL is required.\");\n process.exitCode = 1;\n return;\n }\n if (!authToken) {\n console.error(\"Auth token is required.\");\n process.exitCode = 1;\n return;\n }\n const config = await ensureConfig();\n const provider: ProviderConfig = {\n id: options.id,\n name,\n baseUrl: options.baseUrl,\n authToken,\n model: options.model,\n website: options.website,\n description: options.description,\n preset: false\n };\n\n const nextConfig = addProvider(config, provider);\n await saveConfig(nextConfig);\n console.log(`Added provider '${name}'.`);\n });\n\nprogram\n .command(\"remove\")\n .alias(\"rm\")\n .argument(\"<reference>\", \"Provider id or name\")\n .description(\"Remove a provider by id or name\")\n .action(async (reference: string) => {\n const config = await ensureConfig();\n const nextConfig = removeProvider(config, reference);\n await saveConfig(nextConfig);\n console.log(`Removed provider '${reference}'.`);\n });\n\nprogram\n .command(\"serve\")\n .description(\"Start local web UI and API server\")\n .option(\"--port <port>\", \"Port\", (value) => Number(value))\n .action(async (options: { port?: number }) => {\n const preferredPort = options.port ?? 8787;\n \n console.log(\"[cps] Starting Claude Provider Switcher...\");\n \n const port = await findAvailablePort(preferredPort, 20);\n if (port !== preferredPort) {\n console.log(`[cps] Port ${preferredPort} is in use, using port ${port}`);\n }\n \n const server = await startServer({ uiDistPath: defaultUiDist }, port);\n\n server.on(\"listening\", () => {\n const localUrl = `http://localhost:${port}`;\n console.log(\"[cps] Server ready!\");\n console.log(`[cps] Local URL: ${localUrl}`);\n console.log(\"[cps] Press Ctrl+C to stop\");\n if (!process.env.CPS_NO_BROWSER) {\n void openBrowser(localUrl);\n }\n });\n\n server.on(\"error\", (err) => {\n console.error(\"[cps] Server error:\", err.message);\n process.exit(1);\n });\n\n process.on(\"SIGINT\", () => {\n console.log(\"\\n[cps] Shutting down...\");\n server.close(() => {\n console.log(\"[cps] Server stopped\");\n process.exit(0);\n });\n });\n });\n\nprogram.parseAsync(process.argv);\n","{\n \"name\": \"claude-provider-switch\",\n \"version\": \"0.1.14\",\n \"description\": \"CLI + local web UI for switching Claude Code providers\",\n \"license\": \"MIT\",\n \"homepage\": \"https://github.com/ladieman217/claude-provider-switch#readme\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/ladieman217/claude-provider-switch.git\",\n \"directory\": \"packages/cli\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/ladieman217/claude-provider-switch/issues\"\n },\n \"keywords\": [\n \"claude\",\n \"anthropic\",\n \"cli\",\n \"provider\",\n \"switcher\"\n ],\n \"main\": \"dist/index.js\",\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n },\n \"bin\": {\n \"cps\": \"dist/index.js\"\n },\n \"scripts\": {\n \"dev\": \"CPS_NO_BROWSER=1 tsx watch src/index.ts serve\",\n \"build\": \"pnpm -C ../ui run build && tsup && node scripts/copy-ui.mjs\",\n \"lint\": \"tsc -p tsconfig.json --noEmit\",\n \"test\": \"vitest run\",\n \"test:http\": \"CPS_ENABLE_HTTP_TESTS=1 vitest run test/server.http.test.ts\",\n \"prepack\": \"pnpm run build\",\n \"prepublishOnly\": \"pnpm run lint && pnpm run test\"\n },\n \"dependencies\": {\n \"commander\": \"^12.1.0\",\n \"express\": \"^4.21.2\"\n },\n \"devDependencies\": {\n \"@types/express\": \"^4.17.21\",\n \"@types/node\": \"^22.10.2\",\n \"@types/supertest\": \"^6.0.2\",\n \"supertest\": \"^7.0.0\",\n \"tsup\": \"^8.3.5\",\n \"tsx\": \"^4.19.2\",\n \"typescript\": \"^5.6.3\",\n \"vitest\": \"^2.1.8\"\n }\n}\n","import { ProviderConfig } from \"./types\";\n\nexport const DEFAULT_PRESETS: ProviderConfig[] = [\n {\n id: \"anthropic\",\n name: \"anthropic\",\n baseUrl: \"https://api.anthropic.com\",\n authToken: \"\",\n model: \"\",\n preset: true,\n description: \"Use your Claude subscription via official API\",\n website: \"https://www.anthropic.com\",\n },\n {\n id: \"volc\",\n name: \"火山方舟Coding Plan\",\n baseUrl: \"https://ark.cn-beijing.volces.com/api/coding\",\n authToken: \"\",\n model: \"ark-code-latest\",\n preset: true,\n description: \"火山方舟 coding plan anthropic compatible endpoint\",\n website: \"https://www.volcengine.com\",\n },\n];\n\n/**\n * Template for creating a new custom provider.\n * This is not a real preset, just a template used when adding custom providers.\n */\nexport const CUSTOM_PROVIDER_TEMPLATE: ProviderConfig = {\n id: \"\",\n name: \"\",\n baseUrl: \"\",\n authToken: \"\",\n model: \"\",\n preset: false,\n description: \"\",\n website: \"\",\n};\n","import fs from \"fs/promises\";\nimport { ConfigFile, PathsOptions, ProviderConfig } from \"./types\";\nimport { DEFAULT_PRESETS } from \"./presets\";\nimport { resolvePaths } from \"./paths\";\nimport { readJsonFile, writeJsonFile } from \"./fs\";\n\nconst CONFIG_VERSION = 1 as const;\nconst PROVIDER_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nexport const normalizeProviderName = (name: string) => name.trim().toLowerCase();\nexport const normalizeProviderId = (id: string) =>\n id\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 24)\n .replace(/-+$/g, \"\");\nconst isAnthropicName = (name: string) => normalizeProviderName(name) === \"anthropic\";\nconst isAnthropicProvider = (provider: ProviderConfig) =>\n isAnthropicName(provider.name);\n\nconst toProviderIdBase = (provider: ProviderConfig) => {\n const explicitId =\n typeof provider.id === \"string\" ? normalizeProviderId(provider.id) : \"\";\n if (explicitId) {\n return explicitId;\n }\n\n const fromName = normalizeProviderId(provider.name);\n return fromName || \"provider\";\n};\n\nconst buildUniqueProviderId = (base: string, usedIds: Set<string>) => {\n if (!usedIds.has(base)) {\n usedIds.add(base);\n return base;\n }\n\n let index = 2;\n let candidate = `${base}-${index}`;\n while (usedIds.has(candidate)) {\n index += 1;\n candidate = `${base}-${index}`;\n }\n\n usedIds.add(candidate);\n return candidate;\n};\n\nconst assertValidProviderId = (id: string) => {\n if (id.length > 24) {\n throw new Error(\"Provider id must be at most 24 characters.\");\n }\n if (!PROVIDER_ID_PATTERN.test(id)) {\n throw new Error(\n \"Provider id must use lowercase letters, numbers, and hyphens only.\"\n );\n }\n};\n\nexport const createDefaultConfig = (): ConfigFile => ({\n version: CONFIG_VERSION,\n current: DEFAULT_PRESETS[0]?.id ?? null,\n providers: DEFAULT_PRESETS.map((provider) => ({ ...provider }))\n});\n\nexport const ensureConfig = async (options: PathsOptions = {}): Promise<ConfigFile> => {\n const { configDir, configPath } = resolvePaths(options);\n await fs.mkdir(configDir, { recursive: true, mode: 0o700 });\n\n try {\n const config = await readJsonFile<ConfigFile>(configPath);\n return normalizeConfig(config);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n\n const config = createDefaultConfig();\n await writeJsonFile(configPath, config);\n return config;\n }\n};\n\nexport const saveConfig = async (\n config: ConfigFile,\n options: PathsOptions = {}\n): Promise<void> => {\n const { configDir, configPath } = resolvePaths(options);\n await fs.mkdir(configDir, { recursive: true, mode: 0o700 });\n await writeJsonFile(configPath, normalizeConfig(config));\n};\n\nexport const normalizeConfig = (config: ConfigFile): ConfigFile => {\n const providers = Array.isArray(config.providers) ? config.providers : [];\n const normalizedProviders = providers\n .filter((provider): provider is ProviderConfig => Boolean(provider?.name))\n .map((provider) => ({\n ...provider,\n name: normalizeProviderName(provider.name),\n id:\n typeof provider.id === \"string\"\n ? normalizeProviderId(provider.id)\n : undefined\n }));\n\n const uniqueProviders = new Map<string, ProviderConfig>();\n for (const provider of normalizedProviders) {\n if (!uniqueProviders.has(provider.name)) {\n uniqueProviders.set(provider.name, provider);\n }\n }\n\n const usedIds = new Set<string>();\n const providersWithIds = Array.from(uniqueProviders.values()).map((provider) => {\n const id = buildUniqueProviderId(toProviderIdBase(provider), usedIds);\n return {\n ...provider,\n id\n };\n });\n\n return {\n version: CONFIG_VERSION,\n current: config.current ? normalizeProviderId(config.current) : null,\n providers: providersWithIds\n };\n};\n\nexport const findProvider = (\n config: ConfigFile,\n name: string\n): ProviderConfig | undefined => {\n const normalized = normalizeProviderName(name);\n return config.providers.find((provider) => provider.name === normalized);\n};\n\nexport const findProviderByReference = (\n config: ConfigFile,\n reference: string\n): ProviderConfig | undefined => {\n const normalizedId = normalizeProviderId(reference);\n if (normalizedId) {\n const byId = config.providers.find((provider) => provider.id === normalizedId);\n if (byId) {\n return byId;\n }\n }\n\n return findProvider(config, reference);\n};\n\nexport const findProviderById = (\n config: ConfigFile,\n id: string\n): ProviderConfig | undefined => {\n const normalizedId = normalizeProviderId(id);\n if (!normalizedId) {\n return undefined;\n }\n return config.providers.find((provider) => provider.id === normalizedId);\n};\n\nexport const assertValidProviderInput = (provider: ProviderConfig) => {\n if (!provider.name.trim()) {\n throw new Error(\"Provider name is required.\");\n }\n if (!provider.baseUrl || !provider.baseUrl.trim()) {\n throw new Error(\"Base URL is required.\");\n }\n if (!provider.authToken || !provider.authToken.trim()) {\n throw new Error(\"Auth token is required.\");\n }\n try {\n new URL(provider.baseUrl);\n } catch {\n throw new Error(\"Base URL must be a valid URL.\");\n }\n if (provider.website) {\n try {\n new URL(provider.website);\n } catch {\n throw new Error(\"Website must be a valid URL.\");\n }\n }\n};\n\nexport const assertProviderHasAuthToken = (provider: ProviderConfig) => {\n if (isAnthropicProvider(provider)) {\n return;\n }\n if (!provider.baseUrl || !provider.baseUrl.trim()) {\n throw new Error(\"Base URL is required to apply provider.\");\n }\n if (!provider.authToken || !provider.authToken.trim()) {\n throw new Error(\"Auth token is required to apply provider.\");\n }\n};\n\nexport const addProvider = (\n config: ConfigFile,\n provider: ProviderConfig\n): ConfigFile => {\n const normalizedName = normalizeProviderName(provider.name);\n if (config.providers.some((item) => item.name === normalizedName)) {\n throw new Error(`Provider '${normalizedName}' already exists.`);\n }\n\n assertValidProviderInput(provider);\n\n const usedIds = new Set(\n config.providers\n .map((item) => (typeof item.id === \"string\" ? normalizeProviderId(item.id) : \"\"))\n .filter(Boolean)\n );\n const rawProvidedId =\n typeof provider.id === \"string\" ? provider.id.trim() : undefined;\n let nextId: string;\n if (rawProvidedId) {\n assertValidProviderId(rawProvidedId);\n const normalizedProvidedId = normalizeProviderId(rawProvidedId);\n if (usedIds.has(normalizedProvidedId)) {\n throw new Error(`Provider id '${normalizedProvidedId}' already exists.`);\n }\n nextId = normalizedProvidedId;\n } else {\n nextId = buildUniqueProviderId(\n toProviderIdBase({ ...provider, name: normalizedName }),\n usedIds\n );\n }\n\n return {\n ...config,\n providers: [\n ...config.providers,\n {\n ...provider,\n id: nextId,\n name: normalizedName,\n modelMappings: provider.modelMappings,\n preset: false\n }\n ]\n };\n};\n\nexport const updateProvider = (\n config: ConfigFile,\n name: string,\n updates: ProviderConfig\n): ConfigFile => {\n const normalizedName = normalizeProviderName(name);\n const target = findProvider(config, normalizedName);\n if (!target) {\n throw new Error(`Provider '${normalizedName}' not found.`);\n }\n if (isAnthropicName(normalizedName) && target.preset) {\n throw new Error(\"Anthropic preset is read-only.\");\n }\n\n const nextAuthToken =\n typeof updates.authToken === \"string\" && updates.authToken.trim()\n ? updates.authToken\n : target.authToken;\n\n const updatedProvider: ProviderConfig = {\n id: target.id,\n name: normalizedName,\n baseUrl: updates.baseUrl !== undefined ? updates.baseUrl : target.baseUrl,\n authToken: nextAuthToken,\n model: updates.model !== undefined ? updates.model : target.model,\n website: updates.website !== undefined ? updates.website : target.website,\n description:\n updates.description !== undefined ? updates.description : target.description,\n modelMappings:\n updates.modelMappings !== undefined ? updates.modelMappings : target.modelMappings,\n preset: target.preset\n };\n\n assertValidProviderInput(updatedProvider);\n\n return {\n ...config,\n providers: config.providers.map((provider) =>\n provider.name === normalizedName ? updatedProvider : provider\n )\n };\n};\n\nexport const updateProviderById = (\n config: ConfigFile,\n id: string,\n updates: ProviderConfig\n): ConfigFile => {\n const normalizedId = normalizeProviderId(id);\n const target = findProviderById(config, normalizedId);\n if (!target) {\n throw new Error(`Provider '${normalizedId}' not found.`);\n }\n if (isAnthropicProvider(target) && target.preset) {\n throw new Error(\"Anthropic preset is read-only.\");\n }\n\n const nextAuthToken =\n typeof updates.authToken === \"string\" && updates.authToken.trim()\n ? updates.authToken\n : target.authToken;\n\n const updatedProvider: ProviderConfig = {\n id: target.id,\n name: target.name,\n baseUrl: updates.baseUrl !== undefined ? updates.baseUrl : target.baseUrl,\n authToken: nextAuthToken,\n model: updates.model !== undefined ? updates.model : target.model,\n website: updates.website !== undefined ? updates.website : target.website,\n description:\n updates.description !== undefined ? updates.description : target.description,\n modelMappings:\n updates.modelMappings !== undefined ? updates.modelMappings : target.modelMappings,\n preset: target.preset\n };\n\n assertValidProviderInput(updatedProvider);\n\n return {\n ...config,\n providers: config.providers.map((provider) =>\n provider.id === normalizedId ? updatedProvider : provider\n )\n };\n};\n\nexport const removeProvider = (config: ConfigFile, name: string): ConfigFile => {\n const target = findProviderByReference(config, name);\n if (!target) {\n throw new Error(`Provider '${name}' not found.`);\n }\n\n if (isAnthropicProvider(target) && target.preset) {\n throw new Error(\"Anthropic preset is read-only.\");\n }\n\n const normalizedName = normalizeProviderName(target.name);\n const removedId = target.id;\n const providers = config.providers.filter((provider) =>\n removedId ? provider.id !== removedId : provider.name !== normalizedName\n );\n\n return {\n ...config,\n current: removedId && config.current === removedId ? null : config.current,\n providers\n };\n};\n\nexport const removeProviderById = (config: ConfigFile, id: string): ConfigFile => {\n const normalizedId = normalizeProviderId(id);\n const target = findProviderById(config, normalizedId);\n if (target && isAnthropicProvider(target) && target.preset) {\n throw new Error(\"Anthropic preset is read-only.\");\n }\n const providers = config.providers.filter(\n (provider) => provider.id !== normalizedId\n );\n\n if (providers.length === config.providers.length) {\n throw new Error(`Provider '${normalizedId}' not found.`);\n }\n\n return {\n ...config,\n current: config.current === normalizedId ? null : config.current,\n providers\n };\n};\n\nexport const setCurrentProvider = (config: ConfigFile, name: string): ConfigFile => {\n const provider = findProviderByReference(config, name);\n if (!provider) {\n throw new Error(`Provider '${name}' not found.`);\n }\n\n return {\n ...config,\n current: provider.id!\n };\n};\n\nexport const setCurrentProviderById = (\n config: ConfigFile,\n id: string\n): ConfigFile => {\n const provider = findProviderById(config, id);\n if (!provider) {\n throw new Error(`Provider id '${id}' not found.`);\n }\n\n return {\n ...config,\n current: provider.id!\n };\n};\n","import path from \"path\";\nimport os from \"os\";\nimport { PathsOptions } from \"./types\";\n\nexport const resolvePaths = (options: PathsOptions = {}) => {\n const fallbackConfigDir = path.join(\n os.homedir(),\n \".config\",\n \"claude-provider-switch\"\n );\n const resolvedConfigPath =\n options.configPath ||\n process.env.CPS_CONFIG_PATH ||\n path.join(fallbackConfigDir, \"config.json\");\n const resolvedConfigDir =\n options.configDir ||\n process.env.CPS_CONFIG_DIR ||\n path.dirname(resolvedConfigPath);\n const resolvedBackupDir =\n options.backupDir ||\n process.env.CPS_BACKUP_DIR ||\n path.join(resolvedConfigDir, \"backups\");\n\n const fallbackClaudeDir = path.join(os.homedir(), \".claude\");\n const resolvedClaudeSettingsPath =\n options.claudeSettingsPath ||\n process.env.CPS_CLAUDE_SETTINGS_PATH ||\n path.join(fallbackClaudeDir, \"settings.json\");\n const resolvedClaudeDir =\n options.claudeDir ||\n process.env.CPS_CLAUDE_DIR ||\n path.dirname(resolvedClaudeSettingsPath);\n\n return {\n configDir: resolvedConfigDir,\n configPath: resolvedConfigPath,\n backupDir: resolvedBackupDir,\n claudeDir: resolvedClaudeDir,\n claudeSettingsPath: resolvedClaudeSettingsPath\n };\n};\n","import fs from \"fs/promises\";\n\nexport const readJsonFile = async <T>(filePath: string): Promise<T> => {\n const raw = await fs.readFile(filePath, \"utf8\");\n return JSON.parse(raw) as T;\n};\n\nexport const ensureOwnerOnlyFile = async (filePath: string) => {\n try {\n await fs.chmod(filePath, 0o600);\n } catch {\n // Ignore chmod errors on unsupported platforms/filesystems.\n }\n};\n\nexport const writeJsonFile = async (filePath: string, data: unknown) => {\n const content = `${JSON.stringify(data, null, 2)}\\n`;\n await fs.writeFile(filePath, content, { encoding: \"utf8\", mode: 0o600 });\n await ensureOwnerOnlyFile(filePath);\n};\n","import fs from \"fs/promises\";\nimport path from \"path\";\nimport { resolvePaths } from \"./paths\";\nimport { PathsOptions, ProviderConfig } from \"./types\";\nimport { ensureOwnerOnlyFile, readJsonFile, writeJsonFile } from \"./fs\";\n\nconst BACKUP_PREFIX = \"settings.backup-\";\nconst BACKUP_NAME_PATTERN =\n /^settings\\.backup-\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}-\\d{3}Z\\.json$/;\n\nexport type ClaudeSettings = {\n env?: Record<string, string>;\n [key: string]: unknown;\n};\n\nexport const readClaudeSettings = async (\n options: PathsOptions = {}\n): Promise<ClaudeSettings> => {\n const { claudeSettingsPath } = resolvePaths(options);\n\n try {\n return await readJsonFile<ClaudeSettings>(claudeSettingsPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n return {};\n }\n};\n\nexport type ClaudeSettingsBackup = {\n name: string;\n mtime: number;\n size: number;\n};\n\nconst listBackups = async (backupDir: string) => {\n try {\n const entries = await fs.readdir(backupDir, { withFileTypes: true });\n return entries\n .filter(\n (entry) => entry.isFile() && entry.name.startsWith(BACKUP_PREFIX)\n )\n .map((entry) => entry.name);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n};\n\nconst pruneBackups = async (backupDir: string, keep = 3) => {\n const backups = await listBackups(backupDir);\n if (backups.length <= keep) {\n return;\n }\n\n const backupPaths = await Promise.all(\n backups.map(async (name) => {\n const fullPath = path.join(backupDir, name);\n const stat = await fs.stat(fullPath);\n return { name, fullPath, mtime: stat.mtimeMs };\n })\n );\n\n backupPaths.sort((a, b) => b.mtime - a.mtime);\n const toRemove = backupPaths.slice(keep);\n\n await Promise.all(toRemove.map((backup) => fs.unlink(backup.fullPath)));\n};\n\nconst backupClaudeSettings = async (\n claudeSettingsPath: string,\n backupDir: string\n) => {\n try {\n await fs.access(claudeSettingsPath);\n } catch {\n return;\n }\n\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const backupName = `${BACKUP_PREFIX}${timestamp}.json`;\n const backupPath = path.join(backupDir, backupName);\n\n await fs.mkdir(backupDir, { recursive: true, mode: 0o700 });\n await fs.copyFile(claudeSettingsPath, backupPath);\n await ensureOwnerOnlyFile(backupPath);\n await pruneBackups(backupDir, 3);\n};\n\nexport const listClaudeSettingsBackups = async (\n options: PathsOptions = {}\n): Promise<ClaudeSettingsBackup[]> => {\n const { backupDir } = resolvePaths(options);\n const names = await listBackups(backupDir);\n\n const backups = await Promise.all(\n names.map(async (name) => {\n const fullPath = path.join(backupDir, name);\n const stat = await fs.stat(fullPath);\n return { name, mtime: stat.mtimeMs, size: stat.size };\n })\n );\n\n return backups.sort((a, b) => b.mtime - a.mtime);\n};\n\nexport const restoreClaudeSettingsBackup = async (\n name: string,\n options: PathsOptions = {}\n): Promise<void> => {\n if (!name || !BACKUP_NAME_PATTERN.test(name)) {\n throw new Error(\"Invalid backup name.\");\n }\n\n const { backupDir, claudeSettingsPath } = resolvePaths(options);\n const resolvedBackupDir = path.resolve(backupDir);\n const backupPath = path.resolve(backupDir, name);\n const relativePath = path.relative(resolvedBackupDir, backupPath);\n if (relativePath.startsWith(\"..\") || path.isAbsolute(relativePath)) {\n throw new Error(\"Invalid backup path.\");\n }\n\n await fs.mkdir(backupDir, { recursive: true, mode: 0o700 });\n await backupClaudeSettings(claudeSettingsPath, backupDir);\n await fs.copyFile(backupPath, claudeSettingsPath);\n await ensureOwnerOnlyFile(claudeSettingsPath);\n};\n\nexport const applyProviderToClaudeSettings = async (\n provider: ProviderConfig,\n options: PathsOptions = {}\n): Promise<ClaudeSettings> => {\n const { claudeDir, backupDir, claudeSettingsPath } = resolvePaths(options);\n\n await fs.mkdir(claudeDir, { recursive: true, mode: 0o700 });\n const settings = await readClaudeSettings(options);\n const env =\n settings.env && typeof settings.env === \"object\"\n ? { ...(settings.env as Record<string, string>) }\n : {};\n\n const isAnthropic =\n provider.name && provider.name.trim().toLowerCase() === \"anthropic\";\n\n if (isAnthropic) {\n delete env.ANTHROPIC_BASE_URL;\n delete env.ANTHROPIC_AUTH_TOKEN;\n delete env.ANTHROPIC_MODEL;\n delete env.ANTHROPIC_SMALL_FAST_MODEL;\n delete env.ANTHROPIC_DEFAULT_OPUS_MODEL;\n delete env.ANTHROPIC_DEFAULT_SONNET_MODEL;\n delete env.ANTHROPIC_DEFAULT_HAIKU_MODEL;\n } else {\n env.ANTHROPIC_BASE_URL = provider.baseUrl ?? \"\";\n env.ANTHROPIC_AUTH_TOKEN = provider.authToken ?? \"\";\n\n // Handle model mappings\n const mappings = provider.modelMappings;\n if (mappings?.defaultModel?.trim()) {\n env.ANTHROPIC_MODEL = mappings.defaultModel.trim();\n } else if (provider.model?.trim()) {\n env.ANTHROPIC_MODEL = provider.model.trim();\n } else {\n delete env.ANTHROPIC_MODEL;\n }\n\n if (mappings?.smallFastModel?.trim()) {\n env.ANTHROPIC_SMALL_FAST_MODEL = mappings.smallFastModel.trim();\n } else {\n delete env.ANTHROPIC_SMALL_FAST_MODEL;\n }\n\n if (mappings?.defaultOpusModel?.trim()) {\n env.ANTHROPIC_DEFAULT_OPUS_MODEL = mappings.defaultOpusModel.trim();\n } else {\n delete env.ANTHROPIC_DEFAULT_OPUS_MODEL;\n }\n\n if (mappings?.defaultSonnetModel?.trim()) {\n env.ANTHROPIC_DEFAULT_SONNET_MODEL = mappings.defaultSonnetModel.trim();\n } else {\n delete env.ANTHROPIC_DEFAULT_SONNET_MODEL;\n }\n\n if (mappings?.defaultHaikuModel?.trim()) {\n env.ANTHROPIC_DEFAULT_HAIKU_MODEL = mappings.defaultHaikuModel.trim();\n } else {\n delete env.ANTHROPIC_DEFAULT_HAIKU_MODEL;\n }\n }\n env.API_TIMEOUT_MS = \"3000000\";\n if (isAnthropic) {\n delete env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC;\n } else {\n env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = \"1\";\n }\n\n const nextSettings = {\n ...settings,\n env\n };\n\n await backupClaudeSettings(claudeSettingsPath, backupDir);\n await writeJsonFile(claudeSettingsPath, nextSettings);\n\n return nextSettings;\n};\n","import express from \"express\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport type { Server } from \"http\";\nimport {\n addProvider,\n assertProviderHasAuthToken,\n applyProviderToClaudeSettings,\n ensureConfig,\n findProviderById,\n findProviderByReference,\n listClaudeSettingsBackups,\n removeProviderById,\n restoreClaudeSettingsBackup,\n saveConfig,\n setCurrentProvider,\n updateProviderById\n} from \"./core\";\nimport type { PathsOptions, ProviderConfig } from \"./core\";\n\n// Logger utility\nconst logger = {\n info: (message: string) => console.log(`[cps] ${message}`),\n error: (message: string) => console.error(`[cps] ${message}`),\n request: (method: string, path: string, statusCode: number, duration: number) => {\n const status = statusCode >= 400 ? \"✗\" : \"✓\";\n console.log(`[cps] ${status} ${method} ${path} ${statusCode} (${duration}ms)`);\n }\n};\n\nexport type ServerOptions = PathsOptions & {\n uiDistPath?: string;\n};\n\nexport const sanitizeProviderForResponse = (\n provider: ProviderConfig\n): ProviderConfig => ({\n ...provider,\n authToken: provider.authToken ? \"***\" : \"\"\n});\n\nexport const sanitizeProvidersForResponse = (\n providers: ProviderConfig[]\n): ProviderConfig[] => providers.map(sanitizeProviderForResponse);\n\nconst loadConfig = async (options: PathsOptions) => ensureConfig(options);\n\nconst resolveUiDist = async (uiDistPath?: string) => {\n if (!uiDistPath) {\n return null;\n }\n\n try {\n const stats = await fs.stat(uiDistPath);\n if (stats.isDirectory()) {\n return uiDistPath;\n }\n } catch {\n return null;\n }\n\n return null;\n};\n\nexport const createApp = async (\n options: ServerOptions = {}\n): Promise<express.Express> => {\n const app = express();\n app.use(express.json());\n\n // Request logging middleware\n app.use((req, res, next) => {\n const start = Date.now();\n res.on(\"finish\", () => {\n const duration = Date.now() - start;\n logger.request(req.method, req.path, res.statusCode, duration);\n });\n next();\n });\n\n app.get(\"/api/providers\", async (_req, res) => {\n try {\n const config = await loadConfig(options);\n res.json({\n providers: sanitizeProvidersForResponse(config.providers),\n current: config.current\n });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n app.post(\"/api/providers\", async (req, res) => {\n try {\n const config = await loadConfig(options);\n const payload = req.body as ProviderConfig;\n const nextConfig = addProvider(config, payload);\n await saveConfig(nextConfig, options);\n res\n .status(201)\n .json({ providers: sanitizeProvidersForResponse(nextConfig.providers) });\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n }\n });\n\n app.put(\"/api/providers/:id\", async (req, res) => {\n try {\n const config = await loadConfig(options);\n const updates = req.body as ProviderConfig;\n const nextConfig = updateProviderById(config, req.params.id, updates);\n await saveConfig(nextConfig, options);\n res.json({ providers: sanitizeProvidersForResponse(nextConfig.providers) });\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n }\n });\n\n app.delete(\"/api/providers/:id\", async (req, res) => {\n try {\n const config = await loadConfig(options);\n const nextConfig = removeProviderById(config, req.params.id);\n await saveConfig(nextConfig, options);\n res.json({\n providers: sanitizeProvidersForResponse(nextConfig.providers),\n current: nextConfig.current\n });\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n }\n });\n\n app.get(\"/api/current\", async (_req, res) => {\n try {\n const config = await loadConfig(options);\n const provider = config.current\n ? findProviderById(config, config.current)\n : undefined;\n res.json({\n current: config.current,\n provider: provider ? sanitizeProviderForResponse(provider) : undefined\n });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n app.get(\"/api/backups\", async (_req, res) => {\n try {\n const backups = await listClaudeSettingsBackups(options);\n res.json({ backups });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n app.post(\"/api/backups/restore\", async (req, res) => {\n try {\n const { name } = req.body as { name?: string };\n if (!name) {\n res.status(400).json({ error: \"Backup name is required.\" });\n return;\n }\n await restoreClaudeSettingsBackup(name, options);\n res.json({ restored: true });\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n }\n });\n\n app.post(\"/api/current\", async (req, res) => {\n try {\n const config = await loadConfig(options);\n const { id, name } = req.body as { id?: string; name?: string };\n const reference = id ?? name;\n if (!reference) {\n res.status(400).json({ error: \"Provider id is required.\" });\n return;\n }\n\n const nextConfig = setCurrentProvider(config, reference);\n const provider = findProviderByReference(nextConfig, reference);\n if (!provider) {\n res.status(404).json({ error: \"Provider not found.\" });\n return;\n }\n\n try {\n assertProviderHasAuthToken(provider);\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n return;\n }\n\n await saveConfig(nextConfig, options);\n await applyProviderToClaudeSettings(provider, options);\n\n res.json({\n current: nextConfig.current,\n provider: sanitizeProviderForResponse(provider)\n });\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n }\n });\n\n const uiDist = await resolveUiDist(options.uiDistPath);\n if (uiDist) {\n app.use(express.static(uiDist));\n app.get(\"*\", async (_req, res) => {\n res.sendFile(path.join(uiDist, \"index.html\"));\n });\n } else {\n app.get(\"/\", (_req, res) => {\n res\n .status(200)\n .send(\n \"UI not built. Run `npm -w packages/ui run build` and restart the server.\"\n );\n });\n }\n\n return app;\n};\n\nexport const startServer = async (\n options: ServerOptions,\n port: number\n): Promise<Server> => {\n const app = await createApp(options);\n return app.listen(port, \"127.0.0.1\");\n};\n"],"mappings":"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","names":["import_path","import_promises","import_promises","path","os","fs","fs","import_promises","import_path","fs","path","import_path","import_promises","path","fs","express","path","net","readline"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../package.json","../src/core/presets.ts","../src/core/config.ts","../src/core/paths.ts","../src/core/fs.ts","../src/core/claudeSettings.ts","../src/server.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport path from \"path\";\nimport net from \"net\";\nimport { exec } from \"child_process\";\nimport { promisify } from \"util\";\nimport readline from \"node:readline/promises\";\nimport packageJson from \"../package.json\";\n\nconst execAsync = promisify(exec);\nimport {\n addProvider,\n assertProviderHasAuthToken,\n applyProviderToClaudeSettings,\n ensureConfig,\n findProviderById,\n removeProvider,\n saveConfig,\n setCurrentProviderById\n} from \"./core\";\nimport type { ProviderConfig } from \"./core\";\nimport { startServer } from \"./server\";\n\nconst defaultUiDist = path.resolve(__dirname, \"ui\");\n\nconst program = new Command();\n\nconst readTokenFromStdin = async (): Promise<string> =>\n await new Promise<string>((resolve, reject) => {\n let token = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => {\n token += chunk;\n });\n process.stdin.on(\"end\", () => resolve(token.trim()));\n process.stdin.on(\"error\", reject);\n });\n\nconst formatProvider = (provider: ProviderConfig) => {\n const parts = [`[${provider.id ?? \"-\"}] ${provider.name}`];\n if (provider.baseUrl) {\n parts.push(`(${provider.baseUrl})`);\n }\n if (provider.model) {\n parts.push(`[model: ${provider.model}]`);\n }\n return parts.join(\" \");\n};\n\nconst parseCustomEnvOptions = (values?: string[]): Record<string, string> | undefined => {\n if (!values?.length) {\n return undefined;\n }\n\n return values.reduce<Record<string, string>>((acc, item) => {\n const separatorIndex = item.indexOf(\"=\");\n if (separatorIndex <= 0) {\n throw new Error(`Invalid env '${item}'. Use KEY=VALUE.`);\n }\n const key = item.slice(0, separatorIndex).trim();\n const value = item.slice(separatorIndex + 1);\n acc[key] = value;\n return acc;\n }, {});\n};\n\nconst findAvailablePort = async (start: number, attempts = 20) => {\n for (let i = 0; i < attempts; i += 1) {\n const port = start + i;\n const available = await new Promise<boolean>((resolve) => {\n const server = net.createServer();\n server.once(\"error\", () => resolve(false));\n server.once(\"listening\", () => {\n server.close(() => resolve(true));\n });\n server.listen(port, \"127.0.0.1\");\n });\n\n if (available) {\n return port;\n }\n }\n\n throw new Error(\"No available port found.\");\n};\n\nconst openBrowser = async (url: string) => {\n const platform = process.platform;\n let command: string;\n\n switch (platform) {\n case \"darwin\":\n command = `open \"${url}\"`;\n break;\n case \"win32\":\n command = `start \"\" \"${url}\"`;\n break;\n default:\n command = `xdg-open \"${url}\"`;\n }\n\n try {\n await execAsync(command);\n } catch {\n // Silently fail - opening browser is not critical\n }\n};\n\nconst applyProviderById = async (id: string): Promise<ProviderConfig> => {\n const config = await ensureConfig();\n const nextConfig = setCurrentProviderById(config, id);\n const provider = findProviderById(nextConfig, id);\n if (!provider) {\n throw new Error(\"Provider not found.\");\n }\n\n assertProviderHasAuthToken(provider);\n await saveConfig(nextConfig);\n await applyProviderToClaudeSettings(provider);\n return provider;\n};\n\nprogram.name(\"claude-provider\").description(\"Claude provider switcher\");\nprogram.version(packageJson.version, \"-v, --version\", \"Show CLI version\");\n\nprogram\n .command(\"version\")\n .description(\"Show CLI version\")\n .action(() => {\n console.log(packageJson.version);\n });\n\nprogram\n .command(\"list\")\n .description(\"List configured providers\")\n .action(async () => {\n const config = await ensureConfig();\n const current = config.current;\n\n for (const provider of config.providers) {\n const marker = provider.id === current ? \"*\" : \" \";\n console.log(`${marker} ${formatProvider(provider)}`);\n }\n });\n\nprogram\n .command(\"current\")\n .description(\"Show current provider\")\n .action(async () => {\n const config = await ensureConfig();\n if (!config.current) {\n console.log(\"No provider selected.\");\n return;\n }\n\n const provider = findProviderById(config, config.current);\n if (!provider) {\n console.log(\"Current provider not found in config.\");\n return;\n }\n\n console.log(formatProvider(provider));\n });\n\nprogram\n .command(\"use\")\n .argument(\"<id>\", \"Provider id\")\n .description(\"Use provider by id and apply to Claude settings\")\n .action(async (id: string) => {\n try {\n const provider = await applyProviderById(id);\n console.log(`Applied provider '${provider.name}'.`);\n } catch (error) {\n console.error((error as Error).message);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command(\"select\")\n .description(\"Interactively select provider and apply to Claude settings\")\n .action(async () => {\n const config = await ensureConfig();\n if (config.providers.length === 0) {\n console.error(\"No providers configured.\");\n process.exitCode = 1;\n return;\n }\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n console.error(\"Interactive select requires a TTY terminal.\");\n process.exitCode = 1;\n return;\n }\n\n const current = config.current;\n config.providers.forEach((provider, index) => {\n const marker = provider.id === current ? \"*\" : \" \";\n console.log(`${index + 1}. ${marker} ${formatProvider(provider)}`);\n });\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n });\n\n try {\n const answer = (await rl.question(\"Select provider by number: \")).trim();\n const selectedIndex = Number.parseInt(answer, 10);\n if (\n !Number.isInteger(selectedIndex) ||\n selectedIndex < 1 ||\n selectedIndex > config.providers.length\n ) {\n console.error(\"Invalid selection.\");\n process.exitCode = 1;\n return;\n }\n\n const provider = config.providers[selectedIndex - 1];\n if (!provider) {\n console.error(\"Provider not found.\");\n process.exitCode = 1;\n return;\n }\n if (!provider.id) {\n console.error(\"Provider id is missing.\");\n process.exitCode = 1;\n return;\n }\n\n const applied = await applyProviderById(provider.id);\n console.log(`Applied provider '${applied.name}'.`);\n } catch (error) {\n console.error((error as Error).message);\n process.exitCode = 1;\n } finally {\n rl.close();\n }\n });\n\nprogram\n .command(\"add\")\n .argument(\"<name>\", \"Provider name\")\n .option(\"--id <id>\", \"Stable provider id (lowercase letters/numbers/hyphen)\")\n .option(\"--base-url <url>\", \"Base URL\")\n .option(\"--token <token>\", \"Auth token\")\n .option(\"--token-stdin\", \"Read auth token from stdin\")\n .option(\"--model <model>\", \"Model name\")\n .option(\"--website <url>\", \"Website URL\")\n .option(\"--description <text>\", \"Description\")\n .option(\"--env <entry...>\", \"Custom environment variable (repeat or pass multiple KEY=VALUE values)\")\n .description(\"Add a custom provider\")\n .action(async (\n name: string,\n options: {\n id?: string;\n baseUrl?: string;\n token?: string;\n tokenStdin?: boolean;\n model?: string;\n website?: string;\n description?: string;\n env?: string[];\n }\n ) => {\n if (options.token && options.tokenStdin) {\n console.error(\"Use either --token or --token-stdin, not both.\");\n process.exitCode = 1;\n return;\n }\n\n let authToken = options.token?.trim() ?? \"\";\n if (options.tokenStdin) {\n if (process.stdin.isTTY) {\n console.error(\"No stdin input detected for --token-stdin.\");\n process.exitCode = 1;\n return;\n }\n authToken = await readTokenFromStdin();\n }\n\n if (!options.baseUrl?.trim()) {\n console.error(\"Base URL is required.\");\n process.exitCode = 1;\n return;\n }\n if (!authToken) {\n console.error(\"Auth token is required.\");\n process.exitCode = 1;\n return;\n }\n try {\n const config = await ensureConfig();\n const provider: ProviderConfig = {\n id: options.id,\n name,\n baseUrl: options.baseUrl,\n authToken,\n model: options.model,\n website: options.website,\n description: options.description,\n customEnv: parseCustomEnvOptions(options.env),\n preset: false\n };\n\n const nextConfig = addProvider(config, provider);\n await saveConfig(nextConfig);\n console.log(`Added provider '${name}'.`);\n } catch (error) {\n console.error((error as Error).message);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command(\"remove\")\n .alias(\"rm\")\n .argument(\"<reference>\", \"Provider id or name\")\n .description(\"Remove a provider by id or name\")\n .action(async (reference: string) => {\n const config = await ensureConfig();\n const nextConfig = removeProvider(config, reference);\n await saveConfig(nextConfig);\n console.log(`Removed provider '${reference}'.`);\n });\n\nprogram\n .command(\"serve\")\n .description(\"Start local web UI and API server\")\n .option(\"--port <port>\", \"Port\", (value) => Number(value))\n .action(async (options: { port?: number }) => {\n const preferredPort = options.port ?? 8787;\n \n console.log(\"[cps] Starting Claude Provider Switcher...\");\n \n const port = await findAvailablePort(preferredPort, 20);\n if (port !== preferredPort) {\n console.log(`[cps] Port ${preferredPort} is in use, using port ${port}`);\n }\n \n const server = await startServer({ uiDistPath: defaultUiDist }, port);\n\n server.on(\"listening\", () => {\n const localUrl = `http://localhost:${port}`;\n console.log(\"[cps] Server ready!\");\n console.log(`[cps] Local URL: ${localUrl}`);\n console.log(\"[cps] Press Ctrl+C to stop\");\n if (!process.env.CPS_NO_BROWSER) {\n void openBrowser(localUrl);\n }\n });\n\n server.on(\"error\", (err) => {\n console.error(\"[cps] Server error:\", err.message);\n process.exit(1);\n });\n\n process.on(\"SIGINT\", () => {\n console.log(\"\\n[cps] Shutting down...\");\n server.close(() => {\n console.log(\"[cps] Server stopped\");\n process.exit(0);\n });\n });\n });\n\nprogram.parseAsync(process.argv);\n","{\n \"name\": \"claude-provider-switch\",\n \"version\": \"0.1.15\",\n \"description\": \"CLI + local web UI for switching Claude Code providers\",\n \"license\": \"MIT\",\n \"homepage\": \"https://github.com/ladieman217/claude-provider-switch#readme\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/ladieman217/claude-provider-switch.git\",\n \"directory\": \"packages/cli\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/ladieman217/claude-provider-switch/issues\"\n },\n \"keywords\": [\n \"claude\",\n \"anthropic\",\n \"cli\",\n \"provider\",\n \"switcher\"\n ],\n \"main\": \"dist/index.js\",\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"engines\": {\n \"node\": \">=18\"\n },\n \"bin\": {\n \"cps\": \"dist/index.js\"\n },\n \"scripts\": {\n \"dev\": \"CPS_NO_BROWSER=1 tsx watch src/index.ts serve\",\n \"build\": \"pnpm -C ../ui run build && tsup && node scripts/copy-ui.mjs\",\n \"lint\": \"tsc -p tsconfig.json --noEmit\",\n \"test\": \"vitest run\",\n \"test:http\": \"CPS_ENABLE_HTTP_TESTS=1 vitest run test/server.http.test.ts\",\n \"prepack\": \"pnpm run build\",\n \"prepublishOnly\": \"pnpm run lint && pnpm run test\"\n },\n \"dependencies\": {\n \"commander\": \"^12.1.0\",\n \"express\": \"^4.21.2\"\n },\n \"devDependencies\": {\n \"@types/express\": \"^4.17.21\",\n \"@types/node\": \"^22.10.2\",\n \"@types/supertest\": \"^6.0.2\",\n \"supertest\": \"^7.0.0\",\n \"tsup\": \"^8.3.5\",\n \"tsx\": \"^4.19.2\",\n \"typescript\": \"^5.6.3\",\n \"vitest\": \"^2.1.8\"\n }\n}\n","import { ProviderConfig } from \"./types\";\n\nexport const DEFAULT_PRESETS: ProviderConfig[] = [\n {\n id: \"anthropic\",\n name: \"anthropic\",\n baseUrl: \"https://api.anthropic.com\",\n authToken: \"\",\n model: \"\",\n preset: true,\n description: \"Use your Claude subscription via official API\",\n website: \"https://www.anthropic.com\",\n },\n {\n id: \"volc\",\n name: \"火山方舟Coding Plan\",\n baseUrl: \"https://ark.cn-beijing.volces.com/api/coding\",\n authToken: \"\",\n model: \"ark-code-latest\",\n preset: true,\n description: \"火山方舟 coding plan anthropic compatible endpoint\",\n website: \"https://www.volcengine.com\",\n },\n];\n\n/**\n * Template for creating a new custom provider.\n * This is not a real preset, just a template used when adding custom providers.\n */\nexport const CUSTOM_PROVIDER_TEMPLATE: ProviderConfig = {\n id: \"\",\n name: \"\",\n baseUrl: \"\",\n authToken: \"\",\n model: \"\",\n preset: false,\n description: \"\",\n website: \"\",\n};\n","import fs from \"fs/promises\";\nimport { ConfigFile, PathsOptions, ProviderConfig } from \"./types\";\nimport { DEFAULT_PRESETS } from \"./presets\";\nimport { resolvePaths } from \"./paths\";\nimport { readJsonFile, writeJsonFile } from \"./fs\";\n\nconst CONFIG_VERSION = 1 as const;\nconst PROVIDER_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nconst ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport const normalizeProviderName = (name: string) => name.trim().toLowerCase();\nexport const normalizeProviderId = (id: string) =>\n id\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 24)\n .replace(/-+$/g, \"\");\nconst isAnthropicName = (name: string) => normalizeProviderName(name) === \"anthropic\";\nconst isAnthropicProvider = (provider: ProviderConfig) =>\n isAnthropicName(provider.name);\n\nconst toProviderIdBase = (provider: ProviderConfig) => {\n const explicitId =\n typeof provider.id === \"string\" ? normalizeProviderId(provider.id) : \"\";\n if (explicitId) {\n return explicitId;\n }\n\n const fromName = normalizeProviderId(provider.name);\n return fromName || \"provider\";\n};\n\nconst buildUniqueProviderId = (base: string, usedIds: Set<string>) => {\n if (!usedIds.has(base)) {\n usedIds.add(base);\n return base;\n }\n\n let index = 2;\n let candidate = `${base}-${index}`;\n while (usedIds.has(candidate)) {\n index += 1;\n candidate = `${base}-${index}`;\n }\n\n usedIds.add(candidate);\n return candidate;\n};\n\nconst assertValidProviderId = (id: string) => {\n if (id.length > 24) {\n throw new Error(\"Provider id must be at most 24 characters.\");\n }\n if (!PROVIDER_ID_PATTERN.test(id)) {\n throw new Error(\n \"Provider id must use lowercase letters, numbers, and hyphens only.\"\n );\n }\n};\n\nconst normalizeCustomEnv = (\n customEnv: ProviderConfig[\"customEnv\"]\n): Record<string, string> | undefined => {\n if (!customEnv || typeof customEnv !== \"object\" || Array.isArray(customEnv)) {\n return undefined;\n }\n\n const entries = Object.entries(customEnv).reduce<Record<string, string>>(\n (acc, [key, value]) => {\n const normalizedKey = key.trim();\n if (!normalizedKey) {\n return acc;\n }\n acc[normalizedKey] = String(value);\n return acc;\n },\n {}\n );\n\n return Object.keys(entries).length > 0 ? entries : undefined;\n};\n\nconst assertValidCustomEnv = (customEnv: ProviderConfig[\"customEnv\"]) => {\n const normalized = normalizeCustomEnv(customEnv);\n if (!normalized) {\n return;\n }\n\n for (const key of Object.keys(normalized)) {\n if (!ENV_KEY_PATTERN.test(key)) {\n throw new Error(\n `Environment variable '${key}' must start with a letter or underscore and contain only letters, numbers, and underscores.`\n );\n }\n }\n};\n\nexport const createDefaultConfig = (): ConfigFile => ({\n version: CONFIG_VERSION,\n current: DEFAULT_PRESETS[0]?.id ?? null,\n providers: DEFAULT_PRESETS.map((provider) => ({ ...provider }))\n});\n\nexport const ensureConfig = async (options: PathsOptions = {}): Promise<ConfigFile> => {\n const { configDir, configPath } = resolvePaths(options);\n await fs.mkdir(configDir, { recursive: true, mode: 0o700 });\n\n try {\n const config = await readJsonFile<ConfigFile>(configPath);\n return normalizeConfig(config);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n\n const config = createDefaultConfig();\n await writeJsonFile(configPath, config);\n return config;\n }\n};\n\nexport const saveConfig = async (\n config: ConfigFile,\n options: PathsOptions = {}\n): Promise<void> => {\n const { configDir, configPath } = resolvePaths(options);\n await fs.mkdir(configDir, { recursive: true, mode: 0o700 });\n await writeJsonFile(configPath, normalizeConfig(config));\n};\n\nexport const normalizeConfig = (config: ConfigFile): ConfigFile => {\n const providers = Array.isArray(config.providers) ? config.providers : [];\n const normalizedProviders = providers\n .filter((provider): provider is ProviderConfig => Boolean(provider?.name))\n .map((provider) => ({\n ...provider,\n name: normalizeProviderName(provider.name),\n id:\n typeof provider.id === \"string\"\n ? normalizeProviderId(provider.id)\n : undefined,\n customEnv: normalizeCustomEnv(provider.customEnv)\n }));\n\n const uniqueProviders = new Map<string, ProviderConfig>();\n for (const provider of normalizedProviders) {\n if (!uniqueProviders.has(provider.name)) {\n uniqueProviders.set(provider.name, provider);\n }\n }\n\n const usedIds = new Set<string>();\n const providersWithIds = Array.from(uniqueProviders.values()).map((provider) => {\n const id = buildUniqueProviderId(toProviderIdBase(provider), usedIds);\n return {\n ...provider,\n id\n };\n });\n\n return {\n version: CONFIG_VERSION,\n current: config.current ? normalizeProviderId(config.current) : null,\n providers: providersWithIds\n };\n};\n\nexport const findProvider = (\n config: ConfigFile,\n name: string\n): ProviderConfig | undefined => {\n const normalized = normalizeProviderName(name);\n return config.providers.find((provider) => provider.name === normalized);\n};\n\nexport const findProviderByReference = (\n config: ConfigFile,\n reference: string\n): ProviderConfig | undefined => {\n const normalizedId = normalizeProviderId(reference);\n if (normalizedId) {\n const byId = config.providers.find((provider) => provider.id === normalizedId);\n if (byId) {\n return byId;\n }\n }\n\n return findProvider(config, reference);\n};\n\nexport const findProviderById = (\n config: ConfigFile,\n id: string\n): ProviderConfig | undefined => {\n const normalizedId = normalizeProviderId(id);\n if (!normalizedId) {\n return undefined;\n }\n return config.providers.find((provider) => provider.id === normalizedId);\n};\n\nexport const assertValidProviderInput = (provider: ProviderConfig) => {\n if (!provider.name.trim()) {\n throw new Error(\"Provider name is required.\");\n }\n if (!provider.baseUrl || !provider.baseUrl.trim()) {\n throw new Error(\"Base URL is required.\");\n }\n if (!provider.authToken || !provider.authToken.trim()) {\n throw new Error(\"Auth token is required.\");\n }\n try {\n new URL(provider.baseUrl);\n } catch {\n throw new Error(\"Base URL must be a valid URL.\");\n }\n if (provider.website) {\n try {\n new URL(provider.website);\n } catch {\n throw new Error(\"Website must be a valid URL.\");\n }\n }\n assertValidCustomEnv(provider.customEnv);\n};\n\nexport const assertProviderHasAuthToken = (provider: ProviderConfig) => {\n if (isAnthropicProvider(provider)) {\n return;\n }\n if (!provider.baseUrl || !provider.baseUrl.trim()) {\n throw new Error(\"Base URL is required to apply provider.\");\n }\n if (!provider.authToken || !provider.authToken.trim()) {\n throw new Error(\"Auth token is required to apply provider.\");\n }\n};\n\nexport const addProvider = (\n config: ConfigFile,\n provider: ProviderConfig\n): ConfigFile => {\n const normalizedName = normalizeProviderName(provider.name);\n if (config.providers.some((item) => item.name === normalizedName)) {\n throw new Error(`Provider '${normalizedName}' already exists.`);\n }\n\n assertValidProviderInput(provider);\n\n const usedIds = new Set(\n config.providers\n .map((item) => (typeof item.id === \"string\" ? normalizeProviderId(item.id) : \"\"))\n .filter(Boolean)\n );\n const rawProvidedId =\n typeof provider.id === \"string\" ? provider.id.trim() : undefined;\n let nextId: string;\n if (rawProvidedId) {\n assertValidProviderId(rawProvidedId);\n const normalizedProvidedId = normalizeProviderId(rawProvidedId);\n if (usedIds.has(normalizedProvidedId)) {\n throw new Error(`Provider id '${normalizedProvidedId}' already exists.`);\n }\n nextId = normalizedProvidedId;\n } else {\n nextId = buildUniqueProviderId(\n toProviderIdBase({ ...provider, name: normalizedName }),\n usedIds\n );\n }\n\n return {\n ...config,\n providers: [\n ...config.providers,\n {\n ...provider,\n id: nextId,\n name: normalizedName,\n customEnv: normalizeCustomEnv(provider.customEnv),\n modelMappings: provider.modelMappings,\n preset: false\n }\n ]\n };\n};\n\nexport const updateProvider = (\n config: ConfigFile,\n name: string,\n updates: ProviderConfig\n): ConfigFile => {\n const normalizedName = normalizeProviderName(name);\n const target = findProvider(config, normalizedName);\n if (!target) {\n throw new Error(`Provider '${normalizedName}' not found.`);\n }\n if (isAnthropicName(normalizedName) && target.preset) {\n throw new Error(\"Anthropic preset is read-only.\");\n }\n\n const nextAuthToken =\n typeof updates.authToken === \"string\" && updates.authToken.trim()\n ? updates.authToken\n : target.authToken;\n\n const updatedProvider: ProviderConfig = {\n id: target.id,\n name: normalizedName,\n baseUrl: updates.baseUrl !== undefined ? updates.baseUrl : target.baseUrl,\n authToken: nextAuthToken,\n model: updates.model !== undefined ? updates.model : target.model,\n website: updates.website !== undefined ? updates.website : target.website,\n customEnv:\n updates.customEnv !== undefined\n ? normalizeCustomEnv(updates.customEnv)\n : target.customEnv,\n description:\n updates.description !== undefined ? updates.description : target.description,\n modelMappings:\n updates.modelMappings !== undefined ? updates.modelMappings : target.modelMappings,\n preset: target.preset\n };\n\n assertValidProviderInput(updatedProvider);\n\n return {\n ...config,\n providers: config.providers.map((provider) =>\n provider.name === normalizedName ? updatedProvider : provider\n )\n };\n};\n\nexport const updateProviderById = (\n config: ConfigFile,\n id: string,\n updates: ProviderConfig\n): ConfigFile => {\n const normalizedId = normalizeProviderId(id);\n const target = findProviderById(config, normalizedId);\n if (!target) {\n throw new Error(`Provider '${normalizedId}' not found.`);\n }\n if (isAnthropicProvider(target) && target.preset) {\n throw new Error(\"Anthropic preset is read-only.\");\n }\n\n const nextAuthToken =\n typeof updates.authToken === \"string\" && updates.authToken.trim()\n ? updates.authToken\n : target.authToken;\n\n const updatedProvider: ProviderConfig = {\n id: target.id,\n name: target.name,\n baseUrl: updates.baseUrl !== undefined ? updates.baseUrl : target.baseUrl,\n authToken: nextAuthToken,\n model: updates.model !== undefined ? updates.model : target.model,\n website: updates.website !== undefined ? updates.website : target.website,\n customEnv:\n updates.customEnv !== undefined\n ? normalizeCustomEnv(updates.customEnv)\n : target.customEnv,\n description:\n updates.description !== undefined ? updates.description : target.description,\n modelMappings:\n updates.modelMappings !== undefined ? updates.modelMappings : target.modelMappings,\n preset: target.preset\n };\n\n assertValidProviderInput(updatedProvider);\n\n return {\n ...config,\n providers: config.providers.map((provider) =>\n provider.id === normalizedId ? updatedProvider : provider\n )\n };\n};\n\nexport const removeProvider = (config: ConfigFile, name: string): ConfigFile => {\n const target = findProviderByReference(config, name);\n if (!target) {\n throw new Error(`Provider '${name}' not found.`);\n }\n\n if (isAnthropicProvider(target) && target.preset) {\n throw new Error(\"Anthropic preset is read-only.\");\n }\n\n const normalizedName = normalizeProviderName(target.name);\n const removedId = target.id;\n const providers = config.providers.filter((provider) =>\n removedId ? provider.id !== removedId : provider.name !== normalizedName\n );\n\n return {\n ...config,\n current: removedId && config.current === removedId ? null : config.current,\n providers\n };\n};\n\nexport const removeProviderById = (config: ConfigFile, id: string): ConfigFile => {\n const normalizedId = normalizeProviderId(id);\n const target = findProviderById(config, normalizedId);\n if (target && isAnthropicProvider(target) && target.preset) {\n throw new Error(\"Anthropic preset is read-only.\");\n }\n const providers = config.providers.filter(\n (provider) => provider.id !== normalizedId\n );\n\n if (providers.length === config.providers.length) {\n throw new Error(`Provider '${normalizedId}' not found.`);\n }\n\n return {\n ...config,\n current: config.current === normalizedId ? null : config.current,\n providers\n };\n};\n\nexport const setCurrentProvider = (config: ConfigFile, name: string): ConfigFile => {\n const provider = findProviderByReference(config, name);\n if (!provider) {\n throw new Error(`Provider '${name}' not found.`);\n }\n\n return {\n ...config,\n current: provider.id!\n };\n};\n\nexport const setCurrentProviderById = (\n config: ConfigFile,\n id: string\n): ConfigFile => {\n const provider = findProviderById(config, id);\n if (!provider) {\n throw new Error(`Provider id '${id}' not found.`);\n }\n\n return {\n ...config,\n current: provider.id!\n };\n};\n","import path from \"path\";\nimport os from \"os\";\nimport { PathsOptions } from \"./types\";\n\nexport const resolvePaths = (options: PathsOptions = {}) => {\n const fallbackConfigDir = path.join(\n os.homedir(),\n \".config\",\n \"claude-provider-switch\"\n );\n const resolvedConfigPath =\n options.configPath ||\n process.env.CPS_CONFIG_PATH ||\n path.join(fallbackConfigDir, \"config.json\");\n const resolvedConfigDir =\n options.configDir ||\n process.env.CPS_CONFIG_DIR ||\n path.dirname(resolvedConfigPath);\n const resolvedBackupDir =\n options.backupDir ||\n process.env.CPS_BACKUP_DIR ||\n path.join(resolvedConfigDir, \"backups\");\n\n const fallbackClaudeDir = path.join(os.homedir(), \".claude\");\n const resolvedClaudeSettingsPath =\n options.claudeSettingsPath ||\n process.env.CPS_CLAUDE_SETTINGS_PATH ||\n path.join(fallbackClaudeDir, \"settings.json\");\n const resolvedClaudeDir =\n options.claudeDir ||\n process.env.CPS_CLAUDE_DIR ||\n path.dirname(resolvedClaudeSettingsPath);\n\n return {\n configDir: resolvedConfigDir,\n configPath: resolvedConfigPath,\n backupDir: resolvedBackupDir,\n claudeDir: resolvedClaudeDir,\n claudeSettingsPath: resolvedClaudeSettingsPath\n };\n};\n","import fs from \"fs/promises\";\n\nexport const readJsonFile = async <T>(filePath: string): Promise<T> => {\n const raw = await fs.readFile(filePath, \"utf8\");\n return JSON.parse(raw) as T;\n};\n\nexport const ensureOwnerOnlyFile = async (filePath: string) => {\n try {\n await fs.chmod(filePath, 0o600);\n } catch {\n // Ignore chmod errors on unsupported platforms/filesystems.\n }\n};\n\nexport const writeJsonFile = async (filePath: string, data: unknown) => {\n const content = `${JSON.stringify(data, null, 2)}\\n`;\n await fs.writeFile(filePath, content, { encoding: \"utf8\", mode: 0o600 });\n await ensureOwnerOnlyFile(filePath);\n};\n","import fs from \"fs/promises\";\nimport path from \"path\";\nimport { resolvePaths } from \"./paths\";\nimport { PathsOptions, ProviderConfig } from \"./types\";\nimport { ensureOwnerOnlyFile, readJsonFile, writeJsonFile } from \"./fs\";\n\nconst BACKUP_PREFIX = \"settings.backup-\";\nconst BACKUP_NAME_PATTERN =\n /^settings\\.backup-\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}-\\d{3}Z\\.json$/;\n\nexport type ClaudeSettings = {\n env?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nconst parseCustomEnvValue = (value: unknown): unknown => {\n if (typeof value !== \"string\") {\n return value;\n }\n\n const normalized = value.trim().toLowerCase();\n if (normalized === \"true\") {\n return true;\n }\n if (normalized === \"false\") {\n return false;\n }\n\n if (/^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$/.test(value.trim())) {\n return Number(value);\n }\n\n return value;\n};\n\nexport const readClaudeSettings = async (\n options: PathsOptions = {}\n): Promise<ClaudeSettings> => {\n const { claudeSettingsPath } = resolvePaths(options);\n\n try {\n return await readJsonFile<ClaudeSettings>(claudeSettingsPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n return {};\n }\n};\n\nexport type ClaudeSettingsBackup = {\n name: string;\n mtime: number;\n size: number;\n};\n\nconst listBackups = async (backupDir: string) => {\n try {\n const entries = await fs.readdir(backupDir, { withFileTypes: true });\n return entries\n .filter(\n (entry) => entry.isFile() && entry.name.startsWith(BACKUP_PREFIX)\n )\n .map((entry) => entry.name);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n};\n\nconst pruneBackups = async (backupDir: string, keep = 3) => {\n const backups = await listBackups(backupDir);\n if (backups.length <= keep) {\n return;\n }\n\n const backupPaths = await Promise.all(\n backups.map(async (name) => {\n const fullPath = path.join(backupDir, name);\n const stat = await fs.stat(fullPath);\n return { name, fullPath, mtime: stat.mtimeMs };\n })\n );\n\n backupPaths.sort((a, b) => b.mtime - a.mtime);\n const toRemove = backupPaths.slice(keep);\n\n await Promise.all(toRemove.map((backup) => fs.unlink(backup.fullPath)));\n};\n\nconst backupClaudeSettings = async (\n claudeSettingsPath: string,\n backupDir: string\n) => {\n try {\n await fs.access(claudeSettingsPath);\n } catch {\n return;\n }\n\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const backupName = `${BACKUP_PREFIX}${timestamp}.json`;\n const backupPath = path.join(backupDir, backupName);\n\n await fs.mkdir(backupDir, { recursive: true, mode: 0o700 });\n await fs.copyFile(claudeSettingsPath, backupPath);\n await ensureOwnerOnlyFile(backupPath);\n await pruneBackups(backupDir, 3);\n};\n\nexport const listClaudeSettingsBackups = async (\n options: PathsOptions = {}\n): Promise<ClaudeSettingsBackup[]> => {\n const { backupDir } = resolvePaths(options);\n const names = await listBackups(backupDir);\n\n const backups = await Promise.all(\n names.map(async (name) => {\n const fullPath = path.join(backupDir, name);\n const stat = await fs.stat(fullPath);\n return { name, mtime: stat.mtimeMs, size: stat.size };\n })\n );\n\n return backups.sort((a, b) => b.mtime - a.mtime);\n};\n\nexport const restoreClaudeSettingsBackup = async (\n name: string,\n options: PathsOptions = {}\n): Promise<void> => {\n if (!name || !BACKUP_NAME_PATTERN.test(name)) {\n throw new Error(\"Invalid backup name.\");\n }\n\n const { backupDir, claudeSettingsPath } = resolvePaths(options);\n const resolvedBackupDir = path.resolve(backupDir);\n const backupPath = path.resolve(backupDir, name);\n const relativePath = path.relative(resolvedBackupDir, backupPath);\n if (relativePath.startsWith(\"..\") || path.isAbsolute(relativePath)) {\n throw new Error(\"Invalid backup path.\");\n }\n\n await fs.mkdir(backupDir, { recursive: true, mode: 0o700 });\n await backupClaudeSettings(claudeSettingsPath, backupDir);\n await fs.copyFile(backupPath, claudeSettingsPath);\n await ensureOwnerOnlyFile(claudeSettingsPath);\n};\n\nexport const applyProviderToClaudeSettings = async (\n provider: ProviderConfig,\n options: PathsOptions = {}\n): Promise<ClaudeSettings> => {\n const { claudeDir, backupDir, claudeSettingsPath } = resolvePaths(options);\n\n await fs.mkdir(claudeDir, { recursive: true, mode: 0o700 });\n const settings = await readClaudeSettings(options);\n const env =\n settings.env && typeof settings.env === \"object\"\n ? { ...(settings.env as Record<string, unknown>) }\n : {};\n\n const isAnthropic =\n provider.name && provider.name.trim().toLowerCase() === \"anthropic\";\n\n if (isAnthropic) {\n delete env.ANTHROPIC_BASE_URL;\n delete env.ANTHROPIC_AUTH_TOKEN;\n delete env.ANTHROPIC_MODEL;\n delete env.ANTHROPIC_SMALL_FAST_MODEL;\n delete env.ANTHROPIC_DEFAULT_OPUS_MODEL;\n delete env.ANTHROPIC_DEFAULT_SONNET_MODEL;\n delete env.ANTHROPIC_DEFAULT_HAIKU_MODEL;\n } else {\n env.ANTHROPIC_BASE_URL = provider.baseUrl ?? \"\";\n env.ANTHROPIC_AUTH_TOKEN = provider.authToken ?? \"\";\n\n // Handle model mappings\n const mappings = provider.modelMappings;\n if (mappings?.defaultModel?.trim()) {\n env.ANTHROPIC_MODEL = mappings.defaultModel.trim();\n } else if (provider.model?.trim()) {\n env.ANTHROPIC_MODEL = provider.model.trim();\n } else {\n delete env.ANTHROPIC_MODEL;\n }\n\n if (mappings?.smallFastModel?.trim()) {\n env.ANTHROPIC_SMALL_FAST_MODEL = mappings.smallFastModel.trim();\n } else {\n delete env.ANTHROPIC_SMALL_FAST_MODEL;\n }\n\n if (mappings?.defaultOpusModel?.trim()) {\n env.ANTHROPIC_DEFAULT_OPUS_MODEL = mappings.defaultOpusModel.trim();\n } else {\n delete env.ANTHROPIC_DEFAULT_OPUS_MODEL;\n }\n\n if (mappings?.defaultSonnetModel?.trim()) {\n env.ANTHROPIC_DEFAULT_SONNET_MODEL = mappings.defaultSonnetModel.trim();\n } else {\n delete env.ANTHROPIC_DEFAULT_SONNET_MODEL;\n }\n\n if (mappings?.defaultHaikuModel?.trim()) {\n env.ANTHROPIC_DEFAULT_HAIKU_MODEL = mappings.defaultHaikuModel.trim();\n } else {\n delete env.ANTHROPIC_DEFAULT_HAIKU_MODEL;\n }\n\n if (provider.customEnv && typeof provider.customEnv === \"object\") {\n for (const [key, value] of Object.entries(provider.customEnv)) {\n const envKey = key.trim();\n if (envKey) {\n env[envKey] = parseCustomEnvValue(value);\n }\n }\n }\n }\n env.API_TIMEOUT_MS = \"3000000\";\n if (isAnthropic) {\n delete env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC;\n } else {\n env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = \"1\";\n }\n\n const nextSettings = {\n ...settings,\n env\n };\n\n await backupClaudeSettings(claudeSettingsPath, backupDir);\n await writeJsonFile(claudeSettingsPath, nextSettings);\n\n return nextSettings;\n};\n","import express from \"express\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport type { Server } from \"http\";\nimport {\n addProvider,\n assertProviderHasAuthToken,\n applyProviderToClaudeSettings,\n ensureConfig,\n findProviderById,\n findProviderByReference,\n listClaudeSettingsBackups,\n removeProviderById,\n restoreClaudeSettingsBackup,\n saveConfig,\n setCurrentProvider,\n updateProviderById\n} from \"./core\";\nimport type { PathsOptions, ProviderConfig } from \"./core\";\n\n// Logger utility\nconst logger = {\n info: (message: string) => console.log(`[cps] ${message}`),\n error: (message: string) => console.error(`[cps] ${message}`),\n request: (method: string, path: string, statusCode: number, duration: number) => {\n const status = statusCode >= 400 ? \"✗\" : \"✓\";\n console.log(`[cps] ${status} ${method} ${path} ${statusCode} (${duration}ms)`);\n }\n};\n\nexport type ServerOptions = PathsOptions & {\n uiDistPath?: string;\n};\n\nexport const sanitizeProviderForResponse = (\n provider: ProviderConfig\n): ProviderConfig => ({\n ...provider,\n authToken: provider.authToken ? \"***\" : \"\"\n});\n\nexport const sanitizeProvidersForResponse = (\n providers: ProviderConfig[]\n): ProviderConfig[] => providers.map(sanitizeProviderForResponse);\n\nconst loadConfig = async (options: PathsOptions) => ensureConfig(options);\n\nconst resolveUiDist = async (uiDistPath?: string) => {\n if (!uiDistPath) {\n return null;\n }\n\n try {\n const stats = await fs.stat(uiDistPath);\n if (stats.isDirectory()) {\n return uiDistPath;\n }\n } catch {\n return null;\n }\n\n return null;\n};\n\nexport const createApp = async (\n options: ServerOptions = {}\n): Promise<express.Express> => {\n const app = express();\n app.use(express.json());\n\n // Request logging middleware\n app.use((req, res, next) => {\n const start = Date.now();\n res.on(\"finish\", () => {\n const duration = Date.now() - start;\n logger.request(req.method, req.path, res.statusCode, duration);\n });\n next();\n });\n\n app.get(\"/api/providers\", async (_req, res) => {\n try {\n const config = await loadConfig(options);\n res.json({\n providers: sanitizeProvidersForResponse(config.providers),\n current: config.current\n });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n app.post(\"/api/providers\", async (req, res) => {\n try {\n const config = await loadConfig(options);\n const payload = req.body as ProviderConfig;\n const nextConfig = addProvider(config, payload);\n await saveConfig(nextConfig, options);\n res\n .status(201)\n .json({ providers: sanitizeProvidersForResponse(nextConfig.providers) });\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n }\n });\n\n app.put(\"/api/providers/:id\", async (req, res) => {\n try {\n const config = await loadConfig(options);\n const updates = req.body as ProviderConfig;\n const nextConfig = updateProviderById(config, req.params.id, updates);\n await saveConfig(nextConfig, options);\n res.json({ providers: sanitizeProvidersForResponse(nextConfig.providers) });\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n }\n });\n\n app.delete(\"/api/providers/:id\", async (req, res) => {\n try {\n const config = await loadConfig(options);\n const nextConfig = removeProviderById(config, req.params.id);\n await saveConfig(nextConfig, options);\n res.json({\n providers: sanitizeProvidersForResponse(nextConfig.providers),\n current: nextConfig.current\n });\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n }\n });\n\n app.get(\"/api/current\", async (_req, res) => {\n try {\n const config = await loadConfig(options);\n const provider = config.current\n ? findProviderById(config, config.current)\n : undefined;\n res.json({\n current: config.current,\n provider: provider ? sanitizeProviderForResponse(provider) : undefined\n });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n app.get(\"/api/backups\", async (_req, res) => {\n try {\n const backups = await listClaudeSettingsBackups(options);\n res.json({ backups });\n } catch (error) {\n res.status(500).json({ error: (error as Error).message });\n }\n });\n\n app.post(\"/api/backups/restore\", async (req, res) => {\n try {\n const { name } = req.body as { name?: string };\n if (!name) {\n res.status(400).json({ error: \"Backup name is required.\" });\n return;\n }\n await restoreClaudeSettingsBackup(name, options);\n res.json({ restored: true });\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n }\n });\n\n app.post(\"/api/current\", async (req, res) => {\n try {\n const config = await loadConfig(options);\n const { id, name } = req.body as { id?: string; name?: string };\n const reference = id ?? name;\n if (!reference) {\n res.status(400).json({ error: \"Provider id is required.\" });\n return;\n }\n\n const nextConfig = setCurrentProvider(config, reference);\n const provider = findProviderByReference(nextConfig, reference);\n if (!provider) {\n res.status(404).json({ error: \"Provider not found.\" });\n return;\n }\n\n try {\n assertProviderHasAuthToken(provider);\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n return;\n }\n\n await saveConfig(nextConfig, options);\n await applyProviderToClaudeSettings(provider, options);\n\n res.json({\n current: nextConfig.current,\n provider: sanitizeProviderForResponse(provider)\n });\n } catch (error) {\n res.status(400).json({ error: (error as Error).message });\n }\n });\n\n const uiDist = await resolveUiDist(options.uiDistPath);\n if (uiDist) {\n app.use(express.static(uiDist));\n app.get(\"*\", async (_req, res) => {\n res.sendFile(path.join(uiDist, \"index.html\"));\n });\n } else {\n app.get(\"/\", (_req, res) => {\n res\n .status(200)\n .send(\n \"UI not built. Run `npm -w packages/ui run build` and restart the server.\"\n );\n });\n }\n\n return app;\n};\n\nexport const startServer = async (\n options: ServerOptions,\n port: number\n): Promise<Server> => {\n const app = await createApp(options);\n return app.listen(port, \"127.0.0.1\");\n};\n"],"mappings":"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","names":["import_path","import_promises","import_promises","path","os","fs","fs","import_promises","import_path","fs","path","import_path","import_promises","path","fs","express","path","net","readline"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=Sora:wght@300;400;600;700&display=swap";*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Sora,ui-sans-serif,system-ui;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:IBM Plex Mono,ui-monospace,SFMono-Regular;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.-left-px{left:-1px}.bottom-4{bottom:1rem}.left-0{left:0}.left-1\/2{left:50%}.left-3{left:.75rem}.right-0{right:0}.top-1\/2{top:50%}.top-4{top:1rem}.top-full{top:100%}.z-10{z-index:10}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.ml-2{margin-left:.5rem}.mr-1{margin-right:.25rem}.mt-1{margin-top:.25rem}.mt-6{margin-top:1.5rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-fit{height:-moz-fit-content;height:fit-content}.h-full{height:100%}.max-h-60{max-height:15rem}.min-h-\[96px\]{min-height:96px}.min-h-screen{min-height:100vh}.w-1{width:.25rem}.w-11{width:2.75rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0px}.min-w-\[8rem\]{min-width:8rem}.max-w-2xl{max-width:42rem}.max-w-6xl{max-width:72rem}.max-w-\[300px\]{max-width:300px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-1{--tw-translate-x: .25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-6{--tw-translate-x: 1.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.animate-slide-up{animation:slideUp .4s ease-out both}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1fr\)_2\.25rem\]{grid-template-columns:minmax(0,1fr) minmax(0,1fr) 2.25rem}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-1{row-gap:.25rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.rounded-r-full{border-top-right-radius:9999px;border-bottom-right-radius:9999px}.border{border-width:1px}.border-t{border-top-width:1px}.border-blue-400\/30{border-color:#60a5fa4d}.border-blue-500\/40{border-color:#3b82f666}.border-coral-400{--tw-border-opacity: 1;border-color:rgb(251 113 133 / var(--tw-border-opacity, 1))}.border-coral-400\/40{border-color:#fb718566}.border-mint-400\/50{border-color:#6ee7b780}.border-mint-500\/20{border-color:#34d39933}.border-mint-500\/30{border-color:#34d3994d}.border-mint-500\/40{border-color:#34d39966}.border-sand-200\/10{border-color:#eee6d71a}.border-sand-200\/20{border-color:#eee6d733}.border-sand-200\/40{border-color:#eee6d766}.border-sand-200\/60{border-color:#eee6d799}.bg-blue-400\/10{background-color:#60a5fa1a}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-blue-500\/\[0\.03\]{background-color:#3b82f608}.bg-coral-500{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity, 1))}.bg-coral-500\/10{background-color:#f43f5e1a}.bg-ink-700{--tw-bg-opacity: 1;background-color:rgb(38 45 62 / var(--tw-bg-opacity, 1))}.bg-ink-700\/50{background-color:#262d3e80}.bg-ink-800\/30{background-color:#1a1f2b4d}.bg-ink-800\/50{background-color:#1a1f2b80}.bg-ink-800\/60{background-color:#1a1f2b99}.bg-ink-800\/95{background-color:#1a1f2bf2}.bg-ink-900{--tw-bg-opacity: 1;background-color:rgb(17 19 24 / var(--tw-bg-opacity, 1))}.bg-ink-900\/60{background-color:#11131899}.bg-ink-900\/70{background-color:#111318b3}.bg-ink-900\/90{background-color:#111318e6}.bg-ink-950\/70{background-color:#0b0c10b3}.bg-mint-500{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity, 1))}.bg-mint-500\/10{background-color:#34d3991a}.bg-mint-500\/20{background-color:#34d39933}.bg-mint-500\/\[0\.03\]{background-color:#34d39908}.bg-sand-200\/20{background-color:#eee6d733}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.p-0{padding:0}.p-1{padding:.25rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-4{padding-bottom:1rem}.pb-6{padding-bottom:1.5rem}.pl-9{padding-left:2.25rem}.pt-2{padding-top:.5rem}.pt-4{padding-top:1rem}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:IBM Plex Mono,ui-monospace,SFMono-Regular}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.tracking-\[0\.25em\]{letter-spacing:.25em}.tracking-tight{letter-spacing:-.025em}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-coral-400{--tw-text-opacity: 1;color:rgb(251 113 133 / var(--tw-text-opacity, 1))}.text-coral-400\/60{color:#fb718599}.text-ink-950{--tw-text-opacity: 1;color:rgb(11 12 16 / var(--tw-text-opacity, 1))}.text-mint-400{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity, 1))}.text-mint-400\/70{color:#6ee7b7b3}.text-sand-100{--tw-text-opacity: 1;color:rgb(246 242 234 / var(--tw-text-opacity, 1))}.text-sand-200{--tw-text-opacity: 1;color:rgb(238 230 215 / var(--tw-text-opacity, 1))}.text-sand-200\/30{color:#eee6d74d}.text-sand-200\/40{color:#eee6d766}.text-sand-200\/50{color:#eee6d780}.text-sand-200\/60{color:#eee6d799}.text-sand-200\/70{color:#eee6d7b3}.text-sand-200\/80{color:#eee6d7cc}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.shadow-\[0_0_20px_rgba\(52\,211\,153\,0\.08\)\]{--tw-shadow: 0 0 20px rgba(52,211,153,.08);--tw-shadow-colored: 0 0 20px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_20px_rgba\(59\,130\,246\,0\.08\)\]{--tw-shadow: 0 0 20px rgba(59,130,246,.08);--tw-shadow-colored: 0 0 20px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-card{--tw-shadow: 0 20px 60px rgba(15, 23, 42, .3);--tw-shadow-colored: 0 20px 60px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-glow-sm{--tw-shadow: 0 0 20px rgba(52, 211, 153, .15);--tw-shadow-colored: 0 0 20px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-mint-500\/20{--tw-ring-color: rgb(52 211 153 / .2)}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-xl{--tw-blur: blur(24px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur{--tw-backdrop-blur: blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}:root{color-scheme:dark}body{--tw-bg-opacity: 1;background-color:rgb(11 12 16 / var(--tw-bg-opacity, 1));font-family:Sora,ui-sans-serif,system-ui;--tw-text-opacity: 1;color:rgb(246 242 234 / var(--tw-text-opacity, 1));min-height:100vh;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#root{min-height:100vh}.app-background{position:fixed;top:0;right:0;bottom:0;left:0;background:radial-gradient(1200px circle at 10% 10%,rgba(52,211,153,.15),transparent 60%),radial-gradient(900px circle at 90% 20%,rgba(248,113,113,.12),transparent 60%),radial-gradient(600px circle at 80% 80%,rgba(52,211,153,.08),transparent 50%),linear-gradient(180deg,#0f172a99,#090a0ef2);z-index:-1}.glass-panel{border-width:1px;border-color:#eee6d71a;background-color:#111318b3;--tw-shadow: 0 20px 60px rgba(15, 23, 42, .3);--tw-shadow-colored: 0 20px 60px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.animate-fade-in{animation:fadeIn .5s ease-out both}.animate-slide-up{animation:slideUp .5s ease-out both}.animate-scale-in{animation:scaleIn .3s ease-out both}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes scaleIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:#eee6d71f;border-radius:3px}::-webkit-scrollbar-thumb:hover{background:#eee6d738}.line-clamp-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}[data-sonner-toast]{--normal-bg: rgba(17, 19, 24, .95) !important;--normal-border: rgba(238, 230, 215, .15) !important;--normal-text: #f6f2ea !important;--success-bg: rgba(52, 211, 153, .1) !important;--success-border: rgba(52, 211, 153, .3) !important;--success-text: #6ee7b7 !important;--error-bg: rgba(244, 63, 94, .1) !important;--error-border: rgba(244, 63, 94, .3) !important;--error-text: #fb7185 !important}[data-sonner-toast] [data-icon]{opacity:.8}.placeholder\:text-sand-200\/60::-moz-placeholder{color:#eee6d799}.placeholder\:text-sand-200\/60::placeholder{color:#eee6d799}.hover\:border-blue-500\/50:hover{border-color:#3b82f680}.hover\:border-coral-400\/60:hover{border-color:#fb718599}.hover\:border-mint-500\/50:hover{border-color:#34d39980}.hover\:border-sand-200\/20:hover{border-color:#eee6d733}.hover\:border-sand-200\/40:hover{border-color:#eee6d766}.hover\:border-sand-200\/80:hover{border-color:#eee6d7cc}.hover\:bg-coral-400:hover{--tw-bg-opacity: 1;background-color:rgb(251 113 133 / var(--tw-bg-opacity, 1))}.hover\:bg-coral-400\/10:hover{background-color:#fb71851a}.hover\:bg-coral-500\/10:hover{background-color:#f43f5e1a}.hover\:bg-coral-500\/20:hover{background-color:#f43f5e33}.hover\:bg-ink-700\/40:hover{background-color:#262d3e66}.hover\:bg-ink-700\/50:hover{background-color:#262d3e80}.hover\:bg-ink-800\/70:hover{background-color:#1a1f2bb3}.hover\:bg-ink-800\/80:hover{background-color:#1a1f2bcc}.hover\:bg-mint-400:hover{--tw-bg-opacity: 1;background-color:rgb(110 231 183 / var(--tw-bg-opacity, 1))}.hover\:bg-mint-500\/10:hover{background-color:#34d3991a}.hover\:bg-sand-200\/10:hover{background-color:#eee6d71a}.hover\:text-coral-400:hover{--tw-text-opacity: 1;color:rgb(251 113 133 / var(--tw-text-opacity, 1))}.hover\:text-mint-400:hover{--tw-text-opacity: 1;color:rgb(110 231 183 / var(--tw-text-opacity, 1))}.hover\:text-sand-100:hover{--tw-text-opacity: 1;color:rgb(246 242 234 / var(--tw-text-opacity, 1))}.hover\:text-sand-200\/80:hover{color:#eee6d7cc}.hover\:shadow-glow-sm:hover{--tw-shadow: 0 0 20px rgba(52, 211, 153, .15);--tw-shadow-colored: 0 0 20px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:bg-sand-200\/10:focus{background-color:#eee6d71a}.focus\:text-sand-100:focus{--tw-text-opacity: 1;color:rgb(246 242 234 / var(--tw-text-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-mint-400\/30:focus{--tw-ring-color: rgb(110 231 183 / .3)}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.focus\:ring-offset-ink-950:focus{--tw-ring-offset-color: #0b0c10}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-coral-400\/50:focus-visible{--tw-ring-color: rgb(251 113 133 / .5)}.focus-visible\:ring-mint-400:focus-visible{--tw-ring-opacity: 1;--tw-ring-color: rgb(110 231 183 / var(--tw-ring-opacity, 1))}.active\:scale-\[0\.98\]:active{--tw-scale-x: .98;--tw-scale-y: .98;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width: 640px){.sm\:block{display:block}.sm\:w-\[200px\]{width:200px}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-12{padding-top:3rem;padding-bottom:3rem}}@media (min-width: 1024px){.lg\:grid-cols-\[1\.5fr_1fr\]{grid-template-columns:1.5fr 1fr}}
|