proxitor 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +221 -81
- package/dist/add.cjs +139 -0
- package/dist/add.cjs.map +1 -0
- package/dist/add.mjs +138 -0
- package/dist/add.mjs.map +1 -0
- package/dist/browse.cjs +88 -0
- package/dist/browse.cjs.map +1 -0
- package/dist/browse.mjs +87 -0
- package/dist/browse.mjs.map +1 -0
- package/dist/cli.cjs +148 -25
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +149 -26
- package/dist/cli.mjs.map +1 -1
- package/dist/config.cjs +68 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.mjs +45 -0
- package/dist/config.mjs.map +1 -0
- package/dist/config2.cjs +75 -0
- package/dist/config2.cjs.map +1 -0
- package/dist/config2.mjs +74 -0
- package/dist/config2.mjs.map +1 -0
- package/dist/edit.cjs +82 -0
- package/dist/edit.cjs.map +1 -0
- package/dist/edit.mjs +81 -0
- package/dist/edit.mjs.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +223 -53
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +223 -53
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/list.cjs +33 -0
- package/dist/list.cjs.map +1 -0
- package/dist/list.mjs +31 -0
- package/dist/list.mjs.map +1 -0
- package/dist/providers.cjs +376 -0
- package/dist/providers.cjs.map +1 -0
- package/dist/providers.mjs +279 -0
- package/dist/providers.mjs.map +1 -0
- package/dist/proxy.cjs +128 -8
- package/dist/proxy.cjs.map +1 -1
- package/dist/proxy.mjs +99 -9
- package/dist/proxy.mjs.map +1 -1
- package/dist/remove.cjs +38 -0
- package/dist/remove.cjs.map +1 -0
- package/dist/remove.mjs +37 -0
- package/dist/remove.mjs.map +1 -0
- package/dist/validate.cjs +26 -0
- package/dist/validate.cjs.map +1 -0
- package/dist/validate.mjs +25 -0
- package/dist/validate.mjs.map +1 -0
- package/package.json +10 -3
package/dist/add.mjs
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { c as formatModelHint, f as fetchModels, g as OpenRouterClient, l as formatModelLabel, n as selectProvidersByMode, o as formatContextLength, p as formatPrice, r as selectRoutingMode, t as fetchProvidersForModel, u as formatPricing } from "./providers.mjs";
|
|
2
|
+
import { i as setModelOverride, r as requireConfigPath, t as getModelOverrides } from "./config.mjs";
|
|
3
|
+
import * as clack from "@clack/prompts";
|
|
4
|
+
import { isCancel } from "@clack/prompts";
|
|
5
|
+
//#region src/commands/config/add.ts
|
|
6
|
+
const CUSTOM_PATTERN = "__custom_pattern__";
|
|
7
|
+
/** Run the interactive "Add model override" flow. */
|
|
8
|
+
async function addOverrideCommand(apiKey) {
|
|
9
|
+
clack.intro("Add Model Override");
|
|
10
|
+
const configPath = requireConfigPath();
|
|
11
|
+
const client = new OpenRouterClient(apiKey);
|
|
12
|
+
const models = await loadModelsWithSpinner(client);
|
|
13
|
+
if (!models) return;
|
|
14
|
+
const modelId = await searchModel(models);
|
|
15
|
+
if (!modelId) return;
|
|
16
|
+
if (typeof modelId !== "string") return;
|
|
17
|
+
if (modelId === CUSTOM_PATTERN) {
|
|
18
|
+
const pattern = await enterPattern(models);
|
|
19
|
+
if (!pattern) return;
|
|
20
|
+
if (getModelOverrides(configPath)[pattern]) {
|
|
21
|
+
clack.log.warn(`Override for "${pattern}" already exists. Use Edit instead.`);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
await configureProviderAndSave(configPath, client, pattern, true);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const selected = models.find((m) => m.id === modelId);
|
|
28
|
+
if (selected) displayModelInfo(selected);
|
|
29
|
+
if (getModelOverrides(configPath)[modelId]) {
|
|
30
|
+
clack.log.warn(`Override for "${modelId}" already exists. Use Edit instead.`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
await configureProviderAndSave(configPath, client, modelId, false);
|
|
34
|
+
}
|
|
35
|
+
async function loadModelsWithSpinner(client) {
|
|
36
|
+
const s = clack.spinner();
|
|
37
|
+
s.start("Loading models from OpenRouter...");
|
|
38
|
+
try {
|
|
39
|
+
const models = await fetchModels(client);
|
|
40
|
+
s.stop(`${models.length} models available`);
|
|
41
|
+
return models;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
s.stop("Failed to load models");
|
|
44
|
+
clack.log.error(String(error));
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function searchModel(models) {
|
|
49
|
+
const result = await clack.autocomplete({
|
|
50
|
+
message: "Search for a model",
|
|
51
|
+
placeholder: "Type to search (e.g. \"claude\", \"gpt-4o\", \"qwen\")",
|
|
52
|
+
maxItems: 15,
|
|
53
|
+
options() {
|
|
54
|
+
const query = this.userInput.trim().toLowerCase();
|
|
55
|
+
if (!query) return [{
|
|
56
|
+
value: CUSTOM_PATTERN,
|
|
57
|
+
label: "✏️ Enter custom pattern (e.g. \"claude-*\")"
|
|
58
|
+
}];
|
|
59
|
+
return [...models.filter((m) => {
|
|
60
|
+
return `${m.id} ${m.name}`.toLowerCase().includes(query);
|
|
61
|
+
}).slice(0, 14).map((m) => ({
|
|
62
|
+
value: m.id,
|
|
63
|
+
label: formatModelLabel(m),
|
|
64
|
+
hint: formatModelHint(m)
|
|
65
|
+
})), {
|
|
66
|
+
value: CUSTOM_PATTERN,
|
|
67
|
+
label: "✏️ Enter custom pattern (e.g. \"claude-*\")"
|
|
68
|
+
}];
|
|
69
|
+
},
|
|
70
|
+
filter: (_search, _option) => true
|
|
71
|
+
});
|
|
72
|
+
if (isCancel(result)) return null;
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
async function enterPattern(models) {
|
|
76
|
+
const pattern = await clack.text({
|
|
77
|
+
message: "Enter model pattern",
|
|
78
|
+
placeholder: "e.g. claude-*, gpt-4*, anthropic/*",
|
|
79
|
+
validate: (v) => {
|
|
80
|
+
if (!v?.trim()) return "Pattern cannot be empty";
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
if (isCancel(pattern)) return null;
|
|
84
|
+
const pat = pattern.trim();
|
|
85
|
+
const matches = countPatternMatches(pat, models);
|
|
86
|
+
if (matches > 0) clack.log.info(`Pattern "${pat}" matches ${matches} model(s)`);
|
|
87
|
+
else clack.log.warn(`Pattern "${pat}" does not match any current models — it will still be saved`);
|
|
88
|
+
return pat;
|
|
89
|
+
}
|
|
90
|
+
async function configureProviderAndSave(configPath, client, modelKey, isPattern) {
|
|
91
|
+
const mode = await selectRoutingMode("Configure provider routing");
|
|
92
|
+
if (isCancel(mode)) return;
|
|
93
|
+
if (mode === "skip") {
|
|
94
|
+
setModelOverride(configPath, modelKey, {});
|
|
95
|
+
clack.outro("Done — override saved without provider routing");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const providerOptions = await fetchProvidersForModel(client, modelKey, isPattern);
|
|
99
|
+
if (!providerOptions) return;
|
|
100
|
+
const override = await selectProvidersByMode(mode, providerOptions);
|
|
101
|
+
if (!override) return;
|
|
102
|
+
clack.log.info(`Proposed override:\n ${modelKey}:\n ${formatOverrideYaml(override)}`);
|
|
103
|
+
const save = await clack.confirm({ message: "Save to config?" });
|
|
104
|
+
if (isCancel(save) || !save) {
|
|
105
|
+
clack.outro("Cancelled");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
setModelOverride(configPath, modelKey, override);
|
|
109
|
+
clack.outro("✓ Model override saved");
|
|
110
|
+
}
|
|
111
|
+
function displayModelInfo(model) {
|
|
112
|
+
clack.log.info(`${model.name || model.id}`);
|
|
113
|
+
clack.log.info(` Context: ${formatContextLength(model.context_length)} tokens`);
|
|
114
|
+
clack.log.info(` Pricing: ${formatPricing(model.pricing.prompt, model.pricing.completion)}`);
|
|
115
|
+
if (model.pricing.input_cache_read && model.pricing.input_cache_read !== "0") clack.log.info(` Cache read: ${formatPrice(model.pricing.input_cache_read)}`);
|
|
116
|
+
if (model.pricing.input_cache_write && model.pricing.input_cache_write !== "0") clack.log.info(` Cache write: ${formatPrice(model.pricing.input_cache_write)}`);
|
|
117
|
+
if (model.top_provider?.max_completion_tokens) clack.log.info(` Max output: ${formatContextLength(model.top_provider.max_completion_tokens)} tokens`);
|
|
118
|
+
if (model.architecture?.modality) clack.log.info(` Modality: ${model.architecture.modality}`);
|
|
119
|
+
}
|
|
120
|
+
function countPatternMatches(pattern, models) {
|
|
121
|
+
if (pattern.endsWith("*")) {
|
|
122
|
+
const prefix = pattern.slice(0, -1);
|
|
123
|
+
return models.filter((m) => m.id.startsWith(prefix)).length;
|
|
124
|
+
}
|
|
125
|
+
return models.filter((m) => m.id === pattern).length;
|
|
126
|
+
}
|
|
127
|
+
function formatOverrideYaml(override) {
|
|
128
|
+
const parts = [];
|
|
129
|
+
if (override.provider && typeof override.provider === "object") {
|
|
130
|
+
const p = override.provider;
|
|
131
|
+
for (const [key, value] of Object.entries(p)) parts.push(`provider.${key}: ${JSON.stringify(value)}`);
|
|
132
|
+
}
|
|
133
|
+
return parts.join("\n ") || "(empty)";
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
export { addOverrideCommand };
|
|
137
|
+
|
|
138
|
+
//# sourceMappingURL=add.mjs.map
|
package/dist/add.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.mjs","names":[],"sources":["../src/commands/config/add.ts"],"sourcesContent":["import * as clack from '@clack/prompts'\nimport { isCancel } from '@clack/prompts'\nimport { OpenRouterClient } from '../../openrouter/client.js'\nimport { fetchModels, formatPrice } from '../../openrouter/models.js'\nimport type { OpenRouterModel } from '../../openrouter/types.js'\nimport { getModelOverrides, requireConfigPath, setModelOverride } from './config.js'\nimport {\n formatContextLength,\n formatModelHint,\n formatModelLabel,\n formatPricing,\n} from './format.js'\nimport {\n fetchProvidersForModel,\n selectProvidersByMode,\n selectRoutingMode,\n} from './providers.js'\n\nconst CUSTOM_PATTERN = '__custom_pattern__'\n\n/** Run the interactive \"Add model override\" flow. */\nexport async function addOverrideCommand(apiKey: string): Promise<void> {\n clack.intro('Add Model Override')\n\n const configPath = requireConfigPath()\n const client = new OpenRouterClient(apiKey)\n\n const models = await loadModelsWithSpinner(client)\n if (!models) return\n\n const modelId = await searchModel(models)\n if (!modelId) return\n\n if (typeof modelId !== 'string') return\n\n if (modelId === CUSTOM_PATTERN) {\n const pattern = await enterPattern(models)\n if (!pattern) return\n\n const existing = getModelOverrides(configPath)\n if (existing[pattern]) {\n clack.log.warn(`Override for \"${pattern}\" already exists. Use Edit instead.`)\n return\n }\n\n await configureProviderAndSave(configPath, client, pattern, true)\n return\n }\n\n const selected = models.find(m => m.id === modelId)\n if (selected) displayModelInfo(selected)\n\n const existing = getModelOverrides(configPath)\n if (existing[modelId]) {\n clack.log.warn(`Override for \"${modelId}\" already exists. Use Edit instead.`)\n return\n }\n\n await configureProviderAndSave(configPath, client, modelId, false)\n}\n\nasync function loadModelsWithSpinner(\n client: OpenRouterClient,\n): Promise<OpenRouterModel[] | null> {\n const s = clack.spinner()\n s.start('Loading models from OpenRouter...')\n try {\n const models = await fetchModels(client)\n s.stop(`${models.length} models available`)\n return models\n } catch (error) {\n s.stop('Failed to load models')\n clack.log.error(String(error))\n return null\n }\n}\n\nasync function searchModel(models: OpenRouterModel[]): Promise<string | symbol | null> {\n const result = await clack.autocomplete({\n message: 'Search for a model',\n placeholder: 'Type to search (e.g. \"claude\", \"gpt-4o\", \"qwen\")',\n maxItems: 15,\n options(this: { userInput: string }) {\n const query = this.userInput.trim().toLowerCase()\n\n if (!query) {\n return [\n {\n value: CUSTOM_PATTERN,\n label: '✏️ Enter custom pattern (e.g. \"claude-*\")',\n },\n ]\n }\n\n const filtered = models\n .filter(m => {\n const text = `${m.id} ${m.name}`.toLowerCase()\n return text.includes(query)\n })\n .slice(0, 14)\n .map(m => ({\n value: m.id,\n label: formatModelLabel(m),\n hint: formatModelHint(m),\n }))\n\n return [\n ...filtered,\n { value: CUSTOM_PATTERN, label: '✏️ Enter custom pattern (e.g. \"claude-*\")' },\n ]\n },\n filter: (_search: string, _option: { value: string }) => true,\n })\n\n if (isCancel(result)) return null\n return result as string\n}\n\nasync function enterPattern(models: OpenRouterModel[]): Promise<string | null> {\n const pattern = await clack.text({\n message: 'Enter model pattern',\n placeholder: 'e.g. claude-*, gpt-4*, anthropic/*',\n validate: v => {\n if (!v?.trim()) return 'Pattern cannot be empty'\n return undefined\n },\n })\n\n if (isCancel(pattern)) return null\n\n const pat = (pattern as string).trim()\n const matches = countPatternMatches(pat, models)\n if (matches > 0) {\n clack.log.info(`Pattern \"${pat}\" matches ${matches} model(s)`)\n } else {\n clack.log.warn(\n `Pattern \"${pat}\" does not match any current models — it will still be saved`,\n )\n }\n\n return pat\n}\n\nasync function configureProviderAndSave(\n configPath: string,\n client: OpenRouterClient,\n modelKey: string,\n isPattern: boolean,\n): Promise<void> {\n const mode = await selectRoutingMode('Configure provider routing')\n if (isCancel(mode)) return\n\n if (mode === 'skip') {\n setModelOverride(configPath, modelKey, {})\n clack.outro('Done — override saved without provider routing')\n return\n }\n\n const providerOptions = await fetchProvidersForModel(client, modelKey, isPattern)\n if (!providerOptions) return\n\n const override = await selectProvidersByMode(mode as string, providerOptions)\n if (!override) return\n\n clack.log.info(\n `Proposed override:\\n ${modelKey}:\\n ${formatOverrideYaml(override)}`,\n )\n\n const save = await clack.confirm({ message: 'Save to config?' })\n if (isCancel(save) || !save) {\n clack.outro('Cancelled')\n return\n }\n\n setModelOverride(configPath, modelKey, override)\n clack.outro('✓ Model override saved')\n}\n\nfunction displayModelInfo(model: OpenRouterModel): void {\n clack.log.info(`${model.name || model.id}`)\n clack.log.info(` Context: ${formatContextLength(model.context_length)} tokens`)\n clack.log.info(\n ` Pricing: ${formatPricing(model.pricing.prompt, model.pricing.completion)}`,\n )\n if (model.pricing.input_cache_read && model.pricing.input_cache_read !== '0') {\n clack.log.info(` Cache read: ${formatPrice(model.pricing.input_cache_read)}`)\n }\n if (model.pricing.input_cache_write && model.pricing.input_cache_write !== '0') {\n clack.log.info(` Cache write: ${formatPrice(model.pricing.input_cache_write)}`)\n }\n if (model.top_provider?.max_completion_tokens) {\n clack.log.info(\n ` Max output: ${formatContextLength(model.top_provider.max_completion_tokens)} tokens`,\n )\n }\n if (model.architecture?.modality) {\n clack.log.info(` Modality: ${model.architecture.modality}`)\n }\n}\n\nfunction countPatternMatches(pattern: string, models: OpenRouterModel[]): number {\n if (pattern.endsWith('*')) {\n const prefix = pattern.slice(0, -1)\n return models.filter(m => m.id.startsWith(prefix)).length\n }\n return models.filter(m => m.id === pattern).length\n}\n\nfunction formatOverrideYaml(override: Record<string, unknown>): string {\n const parts: string[] = []\n if (override.provider && typeof override.provider === 'object') {\n const p = override.provider as Record<string, unknown>\n for (const [key, value] of Object.entries(p)) {\n parts.push(`provider.${key}: ${JSON.stringify(value)}`)\n }\n }\n return parts.join('\\n ') || '(empty)'\n}\n"],"mappings":"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"}
|
package/dist/browse.cjs
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const require_proxy = require("./proxy.cjs");
|
|
2
|
+
const require_providers = require("./providers.cjs");
|
|
3
|
+
const require_add = require("./add.cjs");
|
|
4
|
+
let _clack_prompts = require("@clack/prompts");
|
|
5
|
+
_clack_prompts = require_proxy.__toESM(_clack_prompts, 1);
|
|
6
|
+
//#region src/commands/config/browse.ts
|
|
7
|
+
function toOption(m) {
|
|
8
|
+
return {
|
|
9
|
+
value: m.id,
|
|
10
|
+
label: require_providers.formatModelLabel(m),
|
|
11
|
+
hint: require_providers.formatModelHint(m)
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function displayModelDetails(model) {
|
|
15
|
+
_clack_prompts.log.success(`${model.name || model.id}`);
|
|
16
|
+
if (model.description) {
|
|
17
|
+
const desc = model.description.length > 200 ? `${model.description.slice(0, 200)}...` : model.description;
|
|
18
|
+
_clack_prompts.log.info(` ${desc}`);
|
|
19
|
+
}
|
|
20
|
+
_clack_prompts.log.info(` Context: ${require_providers.formatContextLength(model.context_length)} tokens`);
|
|
21
|
+
if (model.top_provider?.max_completion_tokens) _clack_prompts.log.info(` Max output: ${require_providers.formatContextLength(model.top_provider.max_completion_tokens)} tokens`);
|
|
22
|
+
_clack_prompts.log.info(` Pricing: ${require_providers.formatPricing(model.pricing.prompt, model.pricing.completion)}`);
|
|
23
|
+
if (model.pricing.input_cache_read && model.pricing.input_cache_read !== "0") _clack_prompts.log.info(` Cache read: ${require_providers.formatPrice(model.pricing.input_cache_read)}`);
|
|
24
|
+
if (model.pricing.input_cache_write && model.pricing.input_cache_write !== "0") _clack_prompts.log.info(` Cache write: ${require_providers.formatPrice(model.pricing.input_cache_write)}`);
|
|
25
|
+
if (model.architecture?.modality) _clack_prompts.log.info(` Modality: ${model.architecture.modality}`);
|
|
26
|
+
if (model.supported_parameters?.length) _clack_prompts.log.info(` Parameters: ${model.supported_parameters.join(", ")}`);
|
|
27
|
+
}
|
|
28
|
+
async function displayProviders(client, model) {
|
|
29
|
+
const author = require_providers.parseModelAuthor(model.id);
|
|
30
|
+
const slug = require_providers.parseModelSlug(model.id);
|
|
31
|
+
const s = _clack_prompts.spinner();
|
|
32
|
+
s.start("Checking providers...");
|
|
33
|
+
try {
|
|
34
|
+
const endpoints = await require_providers.fetchModelEndpoints(client, author, slug);
|
|
35
|
+
const unique = require_providers.getUniqueProviders(endpoints);
|
|
36
|
+
s.stop(`${unique.length} providers available`);
|
|
37
|
+
for (const p of unique) {
|
|
38
|
+
const ep = endpoints.find((e) => e.tag === p.tag);
|
|
39
|
+
const latency = require_providers.formatLatency(ep?.latency_last_30m?.p50 ?? null);
|
|
40
|
+
const throughput = require_providers.formatThroughput(ep?.throughput_last_30m?.p50 ?? null);
|
|
41
|
+
_clack_prompts.log.info(` ${p.providerName} (${p.tag}) — ${latency} · ${throughput}`);
|
|
42
|
+
}
|
|
43
|
+
} catch {
|
|
44
|
+
s.stop("Could not fetch providers");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Run the interactive "Browse models" flow. */
|
|
48
|
+
async function browseModelsCommand(apiKey) {
|
|
49
|
+
_clack_prompts.intro("Browse Models");
|
|
50
|
+
const client = new require_providers.OpenRouterClient(apiKey);
|
|
51
|
+
const s = _clack_prompts.spinner();
|
|
52
|
+
s.start("Loading models...");
|
|
53
|
+
let models;
|
|
54
|
+
try {
|
|
55
|
+
models = await require_providers.fetchModels(client);
|
|
56
|
+
s.stop(`${models.length} models available`);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
s.stop("Failed to load models");
|
|
59
|
+
_clack_prompts.log.error(String(error));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const modelId = await _clack_prompts.autocomplete({
|
|
63
|
+
message: "Search for a model",
|
|
64
|
+
placeholder: "Type to search...",
|
|
65
|
+
maxItems: 15,
|
|
66
|
+
options() {
|
|
67
|
+
const query = this.userInput.trim().toLowerCase();
|
|
68
|
+
if (!query) return models.slice(0, 15).map(toOption);
|
|
69
|
+
return models.filter((m) => `${m.id} ${m.name}`.toLowerCase().includes(query)).slice(0, 15).map(toOption);
|
|
70
|
+
},
|
|
71
|
+
filter: (_search, _option) => true
|
|
72
|
+
});
|
|
73
|
+
if ((0, _clack_prompts.isCancel)(modelId)) return;
|
|
74
|
+
const model = models.find((m) => m.id === modelId);
|
|
75
|
+
if (!model) return;
|
|
76
|
+
displayModelDetails(model);
|
|
77
|
+
await displayProviders(client, model);
|
|
78
|
+
const configure = await _clack_prompts.confirm({ message: `Configure routing for ${model.id}?` });
|
|
79
|
+
if ((0, _clack_prompts.isCancel)(configure) || !configure) {
|
|
80
|
+
_clack_prompts.outro("Bye!");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
await require_add.addOverrideCommand(apiKey);
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
exports.browseModelsCommand = browseModelsCommand;
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=browse.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browse.cjs","names":["formatModelLabel","formatModelHint","formatContextLength","formatPricing","formatPrice","parseModelAuthor","parseModelSlug","clack","fetchModelEndpoints","getUniqueProviders","formatLatency","formatThroughput","OpenRouterClient","fetchModels","addOverrideCommand"],"sources":["../src/commands/config/browse.ts"],"sourcesContent":["import * as clack from '@clack/prompts'\nimport { isCancel } from '@clack/prompts'\nimport { OpenRouterClient } from '../../openrouter/client.js'\nimport { fetchModelEndpoints, getUniqueProviders } from '../../openrouter/endpoints.js'\nimport {\n fetchModels,\n formatPrice,\n parseModelAuthor,\n parseModelSlug,\n} from '../../openrouter/models.js'\nimport type { OpenRouterModel } from '../../openrouter/types.js'\nimport { addOverrideCommand } from './add.js'\nimport {\n formatContextLength,\n formatLatency,\n formatModelHint,\n formatModelLabel,\n formatPricing,\n formatThroughput,\n} from './format.js'\n\nfunction toOption(m: OpenRouterModel) {\n return { value: m.id, label: formatModelLabel(m), hint: formatModelHint(m) }\n}\n\nfunction displayModelDetails(model: OpenRouterModel): void {\n clack.log.success(`${model.name || model.id}`)\n if (model.description) {\n const desc =\n model.description.length > 200\n ? `${model.description.slice(0, 200)}...`\n : model.description\n clack.log.info(` ${desc}`)\n }\n clack.log.info(` Context: ${formatContextLength(model.context_length)} tokens`)\n if (model.top_provider?.max_completion_tokens) {\n clack.log.info(\n ` Max output: ${formatContextLength(model.top_provider.max_completion_tokens)} tokens`,\n )\n }\n clack.log.info(\n ` Pricing: ${formatPricing(model.pricing.prompt, model.pricing.completion)}`,\n )\n if (model.pricing.input_cache_read && model.pricing.input_cache_read !== '0') {\n clack.log.info(` Cache read: ${formatPrice(model.pricing.input_cache_read)}`)\n }\n if (model.pricing.input_cache_write && model.pricing.input_cache_write !== '0') {\n clack.log.info(` Cache write: ${formatPrice(model.pricing.input_cache_write)}`)\n }\n if (model.architecture?.modality) {\n clack.log.info(` Modality: ${model.architecture.modality}`)\n }\n if (model.supported_parameters?.length) {\n clack.log.info(` Parameters: ${model.supported_parameters.join(', ')}`)\n }\n}\n\nasync function displayProviders(\n client: OpenRouterClient,\n model: OpenRouterModel,\n): Promise<void> {\n const author = parseModelAuthor(model.id)\n const slug = parseModelSlug(model.id)\n const s = clack.spinner()\n s.start('Checking providers...')\n try {\n const endpoints = await fetchModelEndpoints(client, author, slug)\n const unique = getUniqueProviders(endpoints)\n s.stop(`${unique.length} providers available`)\n\n for (const p of unique) {\n const ep = endpoints.find(e => e.tag === p.tag)\n const latency = formatLatency(ep?.latency_last_30m?.p50 ?? null)\n const throughput = formatThroughput(ep?.throughput_last_30m?.p50 ?? null)\n clack.log.info(` ${p.providerName} (${p.tag}) — ${latency} · ${throughput}`)\n }\n } catch {\n s.stop('Could not fetch providers')\n }\n}\n\n/** Run the interactive \"Browse models\" flow. */\nexport async function browseModelsCommand(apiKey: string): Promise<void> {\n clack.intro('Browse Models')\n\n const client = new OpenRouterClient(apiKey)\n\n const s = clack.spinner()\n s.start('Loading models...')\n let models: OpenRouterModel[]\n try {\n models = await fetchModels(client)\n s.stop(`${models.length} models available`)\n } catch (error) {\n s.stop('Failed to load models')\n clack.log.error(String(error))\n return\n }\n\n const modelId = await clack.autocomplete({\n message: 'Search for a model',\n placeholder: 'Type to search...',\n maxItems: 15,\n options(this: { userInput: string }) {\n const query = this.userInput.trim().toLowerCase()\n if (!query) return models.slice(0, 15).map(toOption)\n\n return models\n .filter(m => `${m.id} ${m.name}`.toLowerCase().includes(query))\n .slice(0, 15)\n .map(toOption)\n },\n filter: (_search: string, _option: { value: string }) => true,\n })\n\n if (isCancel(modelId)) return\n\n const model = models.find(m => m.id === modelId)\n if (!model) return\n\n displayModelDetails(model)\n await displayProviders(client, model)\n\n const configure = await clack.confirm({\n message: `Configure routing for ${model.id}?`,\n })\n\n if (isCancel(configure) || !configure) {\n clack.outro('Bye!')\n return\n }\n\n await addOverrideCommand(apiKey)\n}\n"],"mappings":"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"}
|
package/dist/browse.mjs
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { a as getUniqueProviders, c as formatModelHint, d as formatThroughput, f as fetchModels, g as OpenRouterClient, h as parseModelSlug, i as fetchModelEndpoints, l as formatModelLabel, m as parseModelAuthor, o as formatContextLength, p as formatPrice, s as formatLatency, u as formatPricing } from "./providers.mjs";
|
|
2
|
+
import { addOverrideCommand } from "./add.mjs";
|
|
3
|
+
import * as clack from "@clack/prompts";
|
|
4
|
+
import { isCancel } from "@clack/prompts";
|
|
5
|
+
//#region src/commands/config/browse.ts
|
|
6
|
+
function toOption(m) {
|
|
7
|
+
return {
|
|
8
|
+
value: m.id,
|
|
9
|
+
label: formatModelLabel(m),
|
|
10
|
+
hint: formatModelHint(m)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function displayModelDetails(model) {
|
|
14
|
+
clack.log.success(`${model.name || model.id}`);
|
|
15
|
+
if (model.description) {
|
|
16
|
+
const desc = model.description.length > 200 ? `${model.description.slice(0, 200)}...` : model.description;
|
|
17
|
+
clack.log.info(` ${desc}`);
|
|
18
|
+
}
|
|
19
|
+
clack.log.info(` Context: ${formatContextLength(model.context_length)} tokens`);
|
|
20
|
+
if (model.top_provider?.max_completion_tokens) clack.log.info(` Max output: ${formatContextLength(model.top_provider.max_completion_tokens)} tokens`);
|
|
21
|
+
clack.log.info(` Pricing: ${formatPricing(model.pricing.prompt, model.pricing.completion)}`);
|
|
22
|
+
if (model.pricing.input_cache_read && model.pricing.input_cache_read !== "0") clack.log.info(` Cache read: ${formatPrice(model.pricing.input_cache_read)}`);
|
|
23
|
+
if (model.pricing.input_cache_write && model.pricing.input_cache_write !== "0") clack.log.info(` Cache write: ${formatPrice(model.pricing.input_cache_write)}`);
|
|
24
|
+
if (model.architecture?.modality) clack.log.info(` Modality: ${model.architecture.modality}`);
|
|
25
|
+
if (model.supported_parameters?.length) clack.log.info(` Parameters: ${model.supported_parameters.join(", ")}`);
|
|
26
|
+
}
|
|
27
|
+
async function displayProviders(client, model) {
|
|
28
|
+
const author = parseModelAuthor(model.id);
|
|
29
|
+
const slug = parseModelSlug(model.id);
|
|
30
|
+
const s = clack.spinner();
|
|
31
|
+
s.start("Checking providers...");
|
|
32
|
+
try {
|
|
33
|
+
const endpoints = await fetchModelEndpoints(client, author, slug);
|
|
34
|
+
const unique = getUniqueProviders(endpoints);
|
|
35
|
+
s.stop(`${unique.length} providers available`);
|
|
36
|
+
for (const p of unique) {
|
|
37
|
+
const ep = endpoints.find((e) => e.tag === p.tag);
|
|
38
|
+
const latency = formatLatency(ep?.latency_last_30m?.p50 ?? null);
|
|
39
|
+
const throughput = formatThroughput(ep?.throughput_last_30m?.p50 ?? null);
|
|
40
|
+
clack.log.info(` ${p.providerName} (${p.tag}) — ${latency} · ${throughput}`);
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
s.stop("Could not fetch providers");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Run the interactive "Browse models" flow. */
|
|
47
|
+
async function browseModelsCommand(apiKey) {
|
|
48
|
+
clack.intro("Browse Models");
|
|
49
|
+
const client = new OpenRouterClient(apiKey);
|
|
50
|
+
const s = clack.spinner();
|
|
51
|
+
s.start("Loading models...");
|
|
52
|
+
let models;
|
|
53
|
+
try {
|
|
54
|
+
models = await fetchModels(client);
|
|
55
|
+
s.stop(`${models.length} models available`);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
s.stop("Failed to load models");
|
|
58
|
+
clack.log.error(String(error));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const modelId = await clack.autocomplete({
|
|
62
|
+
message: "Search for a model",
|
|
63
|
+
placeholder: "Type to search...",
|
|
64
|
+
maxItems: 15,
|
|
65
|
+
options() {
|
|
66
|
+
const query = this.userInput.trim().toLowerCase();
|
|
67
|
+
if (!query) return models.slice(0, 15).map(toOption);
|
|
68
|
+
return models.filter((m) => `${m.id} ${m.name}`.toLowerCase().includes(query)).slice(0, 15).map(toOption);
|
|
69
|
+
},
|
|
70
|
+
filter: (_search, _option) => true
|
|
71
|
+
});
|
|
72
|
+
if (isCancel(modelId)) return;
|
|
73
|
+
const model = models.find((m) => m.id === modelId);
|
|
74
|
+
if (!model) return;
|
|
75
|
+
displayModelDetails(model);
|
|
76
|
+
await displayProviders(client, model);
|
|
77
|
+
const configure = await clack.confirm({ message: `Configure routing for ${model.id}?` });
|
|
78
|
+
if (isCancel(configure) || !configure) {
|
|
79
|
+
clack.outro("Bye!");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
await addOverrideCommand(apiKey);
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
export { browseModelsCommand };
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=browse.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browse.mjs","names":[],"sources":["../src/commands/config/browse.ts"],"sourcesContent":["import * as clack from '@clack/prompts'\nimport { isCancel } from '@clack/prompts'\nimport { OpenRouterClient } from '../../openrouter/client.js'\nimport { fetchModelEndpoints, getUniqueProviders } from '../../openrouter/endpoints.js'\nimport {\n fetchModels,\n formatPrice,\n parseModelAuthor,\n parseModelSlug,\n} from '../../openrouter/models.js'\nimport type { OpenRouterModel } from '../../openrouter/types.js'\nimport { addOverrideCommand } from './add.js'\nimport {\n formatContextLength,\n formatLatency,\n formatModelHint,\n formatModelLabel,\n formatPricing,\n formatThroughput,\n} from './format.js'\n\nfunction toOption(m: OpenRouterModel) {\n return { value: m.id, label: formatModelLabel(m), hint: formatModelHint(m) }\n}\n\nfunction displayModelDetails(model: OpenRouterModel): void {\n clack.log.success(`${model.name || model.id}`)\n if (model.description) {\n const desc =\n model.description.length > 200\n ? `${model.description.slice(0, 200)}...`\n : model.description\n clack.log.info(` ${desc}`)\n }\n clack.log.info(` Context: ${formatContextLength(model.context_length)} tokens`)\n if (model.top_provider?.max_completion_tokens) {\n clack.log.info(\n ` Max output: ${formatContextLength(model.top_provider.max_completion_tokens)} tokens`,\n )\n }\n clack.log.info(\n ` Pricing: ${formatPricing(model.pricing.prompt, model.pricing.completion)}`,\n )\n if (model.pricing.input_cache_read && model.pricing.input_cache_read !== '0') {\n clack.log.info(` Cache read: ${formatPrice(model.pricing.input_cache_read)}`)\n }\n if (model.pricing.input_cache_write && model.pricing.input_cache_write !== '0') {\n clack.log.info(` Cache write: ${formatPrice(model.pricing.input_cache_write)}`)\n }\n if (model.architecture?.modality) {\n clack.log.info(` Modality: ${model.architecture.modality}`)\n }\n if (model.supported_parameters?.length) {\n clack.log.info(` Parameters: ${model.supported_parameters.join(', ')}`)\n }\n}\n\nasync function displayProviders(\n client: OpenRouterClient,\n model: OpenRouterModel,\n): Promise<void> {\n const author = parseModelAuthor(model.id)\n const slug = parseModelSlug(model.id)\n const s = clack.spinner()\n s.start('Checking providers...')\n try {\n const endpoints = await fetchModelEndpoints(client, author, slug)\n const unique = getUniqueProviders(endpoints)\n s.stop(`${unique.length} providers available`)\n\n for (const p of unique) {\n const ep = endpoints.find(e => e.tag === p.tag)\n const latency = formatLatency(ep?.latency_last_30m?.p50 ?? null)\n const throughput = formatThroughput(ep?.throughput_last_30m?.p50 ?? null)\n clack.log.info(` ${p.providerName} (${p.tag}) — ${latency} · ${throughput}`)\n }\n } catch {\n s.stop('Could not fetch providers')\n }\n}\n\n/** Run the interactive \"Browse models\" flow. */\nexport async function browseModelsCommand(apiKey: string): Promise<void> {\n clack.intro('Browse Models')\n\n const client = new OpenRouterClient(apiKey)\n\n const s = clack.spinner()\n s.start('Loading models...')\n let models: OpenRouterModel[]\n try {\n models = await fetchModels(client)\n s.stop(`${models.length} models available`)\n } catch (error) {\n s.stop('Failed to load models')\n clack.log.error(String(error))\n return\n }\n\n const modelId = await clack.autocomplete({\n message: 'Search for a model',\n placeholder: 'Type to search...',\n maxItems: 15,\n options(this: { userInput: string }) {\n const query = this.userInput.trim().toLowerCase()\n if (!query) return models.slice(0, 15).map(toOption)\n\n return models\n .filter(m => `${m.id} ${m.name}`.toLowerCase().includes(query))\n .slice(0, 15)\n .map(toOption)\n },\n filter: (_search: string, _option: { value: string }) => true,\n })\n\n if (isCancel(modelId)) return\n\n const model = models.find(m => m.id === modelId)\n if (!model) return\n\n displayModelDetails(model)\n await displayProviders(client, model)\n\n const configure = await clack.confirm({\n message: `Configure routing for ${model.id}?`,\n })\n\n if (isCancel(configure) || !configure) {\n clack.outro('Bye!')\n return\n }\n\n await addOverrideCommand(apiKey)\n}\n"],"mappings":"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"}
|
package/dist/cli.cjs
CHANGED
|
@@ -1,36 +1,159 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const require_proxy = require("./proxy.cjs");
|
|
3
|
-
let
|
|
3
|
+
let cmd_ts = require("cmd-ts");
|
|
4
4
|
let dotenv = require("dotenv");
|
|
5
5
|
//#region src/version.ts
|
|
6
|
-
const version = "0.1
|
|
6
|
+
const version = "0.2.1";
|
|
7
7
|
//#endregion
|
|
8
8
|
//#region src/cli.ts
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
const argv = process.argv.slice(2);
|
|
10
|
+
const isInfo = argv.includes("--help") || argv.includes("-h") || argv.includes("--version") || argv.includes("-v");
|
|
11
|
+
if (!isInfo) (0, dotenv.config)();
|
|
12
|
+
async function resolveApiKey(configPath, openrouterKey) {
|
|
13
|
+
if (openrouterKey) return openrouterKey;
|
|
14
|
+
const envKey = process.env.OPENROUTER_API_KEY;
|
|
15
|
+
if (envKey) return envKey;
|
|
15
16
|
try {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
openrouterKey: parsed.options.openrouterKey,
|
|
22
|
-
verbose: parsed.options.verbose
|
|
23
|
-
});
|
|
24
|
-
require_proxy.startProxyServer(config, () => {
|
|
25
|
-
require_proxy.logger.ready(`Proxitor proxy listening on ${config.host}:${config.port}`);
|
|
26
|
-
require_proxy.logger.info(`Routing requests to OpenRouter`);
|
|
27
|
-
});
|
|
28
|
-
} catch (error) {
|
|
29
|
-
require_proxy.logger.error("Failed to start proxy:", error);
|
|
30
|
-
process.exit(1);
|
|
31
|
-
}
|
|
17
|
+
const cfg = await require_proxy.loadConfig({ configPath });
|
|
18
|
+
if (cfg.openrouterKey) return cfg.openrouterKey;
|
|
19
|
+
} catch {}
|
|
20
|
+
require_proxy.logger.error("OpenRouter API key required. Set OPENROUTER_API_KEY, pass --openrouter-key, or add it to config.");
|
|
21
|
+
return null;
|
|
32
22
|
}
|
|
33
|
-
|
|
23
|
+
const configOptionArgs = {
|
|
24
|
+
config: (0, cmd_ts.option)({
|
|
25
|
+
long: "config",
|
|
26
|
+
short: "c",
|
|
27
|
+
type: (0, cmd_ts.optional)(cmd_ts.string),
|
|
28
|
+
description: "Path to config file"
|
|
29
|
+
}),
|
|
30
|
+
openrouterKey: (0, cmd_ts.option)({
|
|
31
|
+
long: "openrouter-key",
|
|
32
|
+
type: (0, cmd_ts.optional)(cmd_ts.string),
|
|
33
|
+
description: "OpenRouter API key"
|
|
34
|
+
})
|
|
35
|
+
};
|
|
36
|
+
const startCommand = (0, cmd_ts.command)({
|
|
37
|
+
name: "start",
|
|
38
|
+
description: "Start proxy server",
|
|
39
|
+
args: {
|
|
40
|
+
port: (0, cmd_ts.option)({
|
|
41
|
+
long: "port",
|
|
42
|
+
short: "p",
|
|
43
|
+
type: cmd_ts.number,
|
|
44
|
+
description: "Proxy server port",
|
|
45
|
+
defaultValue: () => 8080,
|
|
46
|
+
defaultValueIsSerializable: true
|
|
47
|
+
}),
|
|
48
|
+
host: (0, cmd_ts.option)({
|
|
49
|
+
long: "host",
|
|
50
|
+
type: cmd_ts.string,
|
|
51
|
+
description: "Proxy server host",
|
|
52
|
+
defaultValue: () => "0.0.0.0",
|
|
53
|
+
defaultValueIsSerializable: true
|
|
54
|
+
}),
|
|
55
|
+
config: (0, cmd_ts.option)({
|
|
56
|
+
long: "config",
|
|
57
|
+
short: "c",
|
|
58
|
+
type: (0, cmd_ts.optional)(cmd_ts.string),
|
|
59
|
+
description: "Path to config file"
|
|
60
|
+
}),
|
|
61
|
+
noConfig: (0, cmd_ts.flag)({
|
|
62
|
+
long: "no-config",
|
|
63
|
+
description: "Skip config file discovery"
|
|
64
|
+
}),
|
|
65
|
+
openrouterKey: (0, cmd_ts.option)({
|
|
66
|
+
long: "openrouter-key",
|
|
67
|
+
type: (0, cmd_ts.optional)(cmd_ts.string),
|
|
68
|
+
description: "OpenRouter API key"
|
|
69
|
+
}),
|
|
70
|
+
verbose: (0, cmd_ts.flag)({
|
|
71
|
+
long: "verbose",
|
|
72
|
+
description: "Enable verbose logging"
|
|
73
|
+
})
|
|
74
|
+
},
|
|
75
|
+
handler: async (args) => {
|
|
76
|
+
try {
|
|
77
|
+
const cfg = await require_proxy.loadConfig({
|
|
78
|
+
configPath: args.config ?? void 0,
|
|
79
|
+
noConfig: args.noConfig,
|
|
80
|
+
port: args.port,
|
|
81
|
+
host: args.host,
|
|
82
|
+
openrouterKey: args.openrouterKey ?? void 0,
|
|
83
|
+
verbose: args.verbose
|
|
84
|
+
});
|
|
85
|
+
require_proxy.startProxyServer(cfg, () => {
|
|
86
|
+
require_proxy.logger.ready(`Proxitor proxy listening on ${cfg.host}:${cfg.port}`);
|
|
87
|
+
require_proxy.logger.info("Routing requests to OpenRouter");
|
|
88
|
+
});
|
|
89
|
+
} catch (error) {
|
|
90
|
+
require_proxy.logger.error("Failed to start proxy:", error);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
const withApiKey = (fn) => async (args) => {
|
|
96
|
+
const apiKey = await resolveApiKey(args.config ?? void 0, args.openrouterKey ?? void 0);
|
|
97
|
+
if (apiKey) await fn(apiKey);
|
|
98
|
+
};
|
|
99
|
+
const rootCli = (0, cmd_ts.subcommands)({
|
|
100
|
+
name: "proxitor",
|
|
101
|
+
version,
|
|
102
|
+
description: "Lightweight proxy for routing CLI requests to OpenRouter",
|
|
103
|
+
cmds: {
|
|
104
|
+
start: startCommand,
|
|
105
|
+
config: (0, cmd_ts.subcommands)({
|
|
106
|
+
name: "config",
|
|
107
|
+
description: "Manage proxy configuration",
|
|
108
|
+
cmds: {
|
|
109
|
+
add: (0, cmd_ts.command)({
|
|
110
|
+
name: "add",
|
|
111
|
+
description: "Add model override",
|
|
112
|
+
args: configOptionArgs,
|
|
113
|
+
handler: withApiKey(async (k) => (await Promise.resolve().then(() => require("./add.cjs"))).addOverrideCommand(k))
|
|
114
|
+
}),
|
|
115
|
+
edit: (0, cmd_ts.command)({
|
|
116
|
+
name: "edit",
|
|
117
|
+
description: "Edit model override",
|
|
118
|
+
args: configOptionArgs,
|
|
119
|
+
handler: withApiKey(async (k) => (await Promise.resolve().then(() => require("./edit.cjs"))).editOverrideCommand(k))
|
|
120
|
+
}),
|
|
121
|
+
remove: (0, cmd_ts.command)({
|
|
122
|
+
name: "remove",
|
|
123
|
+
description: "Remove model override",
|
|
124
|
+
args: {},
|
|
125
|
+
handler: async () => (await Promise.resolve().then(() => require("./remove.cjs"))).removeOverrideCommand()
|
|
126
|
+
}),
|
|
127
|
+
list: (0, cmd_ts.command)({
|
|
128
|
+
name: "list",
|
|
129
|
+
description: "List current overrides",
|
|
130
|
+
args: {},
|
|
131
|
+
handler: async () => (await Promise.resolve().then(() => require("./list.cjs"))).listOverridesCommand()
|
|
132
|
+
}),
|
|
133
|
+
browse: (0, cmd_ts.command)({
|
|
134
|
+
name: "browse",
|
|
135
|
+
description: "Browse models",
|
|
136
|
+
args: configOptionArgs,
|
|
137
|
+
handler: withApiKey(async (k) => (await Promise.resolve().then(() => require("./browse.cjs"))).browseModelsCommand(k))
|
|
138
|
+
}),
|
|
139
|
+
validate: (0, cmd_ts.command)({
|
|
140
|
+
name: "validate",
|
|
141
|
+
description: "Validate config",
|
|
142
|
+
args: {},
|
|
143
|
+
handler: async () => (await Promise.resolve().then(() => require("./validate.cjs"))).validateConfigCommand()
|
|
144
|
+
}),
|
|
145
|
+
menu: (0, cmd_ts.command)({
|
|
146
|
+
name: "menu",
|
|
147
|
+
description: "Interactive configuration menu",
|
|
148
|
+
args: configOptionArgs,
|
|
149
|
+
handler: withApiKey(async (k) => (await Promise.resolve().then(() => require("./config2.cjs"))).runConfigMenu(k))
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
if (argv.some((a) => !a.startsWith("-")) || isInfo) (0, cmd_ts.run)(rootCli, argv);
|
|
156
|
+
else (0, cmd_ts.run)(startCommand, argv);
|
|
34
157
|
//#endregion
|
|
35
158
|
|
|
36
159
|
//# sourceMappingURL=cli.cjs.map
|
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.cjs","names":["loadConfig"],"sources":["../src/version.ts","../src/cli.ts"],"sourcesContent":["export const version = '0.1
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":["loadConfig","string","number"],"sources":["../src/version.ts","../src/cli.ts"],"sourcesContent":["export const version = '0.2.1'\n","#!/usr/bin/env node\nimport { command, flag, number, option, optional, run, string, subcommands } from 'cmd-ts'\nimport { config as loadDotenv } from 'dotenv'\nimport { loadConfig } from './config.js'\nimport { logger } from './logger.js'\nimport { startProxyServer } from './proxy.js'\nimport { version } from './version.js'\n\nconst argv = process.argv.slice(2)\nconst isInfo =\n argv.includes('--help') ||\n argv.includes('-h') ||\n argv.includes('--version') ||\n argv.includes('-v')\nif (!isInfo) loadDotenv()\n\nasync function resolveApiKey(\n configPath?: string,\n openrouterKey?: string,\n): Promise<string | null> {\n if (openrouterKey) return openrouterKey\n const envKey = process.env.OPENROUTER_API_KEY\n if (envKey) return envKey\n\n try {\n const cfg = await loadConfig({ configPath })\n if (cfg.openrouterKey) return cfg.openrouterKey\n } catch {\n // Config not found or invalid — fall through\n }\n\n logger.error(\n 'OpenRouter API key required. Set OPENROUTER_API_KEY, pass --openrouter-key, or add it to config.',\n )\n return null\n}\n\nconst configOptionArgs = {\n config: option({\n long: 'config',\n short: 'c',\n type: optional(string),\n description: 'Path to config file',\n }),\n openrouterKey: option({\n long: 'openrouter-key',\n type: optional(string),\n description: 'OpenRouter API key',\n }),\n}\n\nconst startCommand = command({\n name: 'start',\n description: 'Start proxy server',\n args: {\n port: option({\n long: 'port',\n short: 'p',\n type: number,\n description: 'Proxy server port',\n defaultValue: () => 8080,\n defaultValueIsSerializable: true,\n }),\n host: option({\n long: 'host',\n type: string,\n description: 'Proxy server host',\n defaultValue: () => '0.0.0.0',\n defaultValueIsSerializable: true,\n }),\n config: option({\n long: 'config',\n short: 'c',\n type: optional(string),\n description: 'Path to config file',\n }),\n noConfig: flag({ long: 'no-config', description: 'Skip config file discovery' }),\n openrouterKey: option({\n long: 'openrouter-key',\n type: optional(string),\n description: 'OpenRouter API key',\n }),\n verbose: flag({ long: 'verbose', description: 'Enable verbose logging' }),\n },\n handler: async args => {\n try {\n const cfg = await loadConfig({\n configPath: args.config ?? undefined,\n noConfig: args.noConfig,\n port: args.port,\n host: args.host,\n openrouterKey: args.openrouterKey ?? undefined,\n verbose: args.verbose,\n })\n startProxyServer(cfg, () => {\n logger.ready(`Proxitor proxy listening on ${cfg.host}:${cfg.port}`)\n logger.info('Routing requests to OpenRouter')\n })\n } catch (error) {\n logger.error('Failed to start proxy:', error)\n process.exit(1)\n }\n },\n})\n\nconst withApiKey =\n (fn: (apiKey: string) => Promise<void>) =>\n async (args: { config?: string; openrouterKey?: string }) => {\n const apiKey = await resolveApiKey(\n args.config ?? undefined,\n args.openrouterKey ?? undefined,\n )\n if (apiKey) await fn(apiKey)\n }\n\nconst configCli = subcommands({\n name: 'config',\n description: 'Manage proxy configuration',\n cmds: {\n add: command({\n name: 'add',\n description: 'Add model override',\n args: configOptionArgs,\n handler: withApiKey(async k =>\n (await import('./commands/config/add.js')).addOverrideCommand(k),\n ),\n }),\n edit: command({\n name: 'edit',\n description: 'Edit model override',\n args: configOptionArgs,\n handler: withApiKey(async k =>\n (await import('./commands/config/edit.js')).editOverrideCommand(k),\n ),\n }),\n remove: command({\n name: 'remove',\n description: 'Remove model override',\n args: {},\n handler: async () =>\n (await import('./commands/config/remove.js')).removeOverrideCommand(),\n }),\n list: command({\n name: 'list',\n description: 'List current overrides',\n args: {},\n handler: async () =>\n (await import('./commands/config/list.js')).listOverridesCommand(),\n }),\n browse: command({\n name: 'browse',\n description: 'Browse models',\n args: configOptionArgs,\n handler: withApiKey(async k =>\n (await import('./commands/config/browse.js')).browseModelsCommand(k),\n ),\n }),\n validate: command({\n name: 'validate',\n description: 'Validate config',\n args: {},\n handler: async () =>\n (await import('./commands/config/validate.js')).validateConfigCommand(),\n }),\n menu: command({\n name: 'menu',\n description: 'Interactive configuration menu',\n args: configOptionArgs,\n handler: withApiKey(async k =>\n (await import('./commands/config.js')).runConfigMenu(k),\n ),\n }),\n },\n})\n\nconst rootCli = subcommands({\n name: 'proxitor',\n version,\n description: 'Lightweight proxy for routing CLI requests to OpenRouter',\n cmds: { start: startCommand, config: configCli },\n})\n\nconst hasSubcommand = argv.some(a => !a.startsWith('-'))\nif (hasSubcommand || isInfo) {\n void run(rootCli, argv)\n} else {\n void run(startCommand, argv)\n}\n"],"mappings":"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"}
|