proxitor 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/add.mjs.map +1 -1
- package/dist/browse.mjs.map +1 -1
- package/dist/cli.mjs +29 -16
- package/dist/cli.mjs.map +1 -1
- package/dist/config.mjs.map +1 -1
- package/dist/config2.mjs.map +1 -1
- package/dist/edit.mjs.map +1 -1
- package/dist/list.mjs.map +1 -1
- package/dist/providers.mjs.map +1 -1
- package/dist/remove.mjs.map +1 -1
- package/dist/validate.mjs.map +1 -1
- package/dist/wizard.mjs.map +1 -1
- package/package.json +1 -1
package/dist/add.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.mjs","names":["clack.spinner","clack.autocomplete","isCancel","clack.text","clack.confirm"],"sources":["../src/commands/config/add.ts"],"sourcesContent":["import * as clack from '@clack/prompts'\nimport { isCancel } from '@clack/prompts'\nimport type { OpenRouterDataClient } from '../../openrouter/data-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(client: OpenRouterDataClient): Promise<void> {\n clack.intro('Add Model Override')\n\n const configPath = requireConfigPath()\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: OpenRouterDataClient,\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: OpenRouterDataClient,\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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"}
|
|
1
|
+
{"version":3,"file":"add.mjs","names":["clack.spinner","clack.autocomplete","isCancel","clack.text","clack.confirm"],"sources":["../src/commands/config/add.ts"],"sourcesContent":["import * as clack from '@clack/prompts';\nimport { isCancel } from '@clack/prompts';\nimport type { OpenRouterDataClient } from '../../openrouter/data-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(client: OpenRouterDataClient): Promise<void> {\n clack.intro('Add Model Override');\n\n const configPath = requireConfigPath();\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: OpenRouterDataClient,\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: OpenRouterDataClient,\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.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browse.mjs","names":["clack.spinner","clack.autocomplete","isCancel","clack.confirm"],"sources":["../src/commands/config/browse.ts"],"sourcesContent":["import * as clack from '@clack/prompts'
|
|
1
|
+
{"version":3,"file":"browse.mjs","names":["clack.spinner","clack.autocomplete","isCancel","clack.confirm"],"sources":["../src/commands/config/browse.ts"],"sourcesContent":["import * as clack from '@clack/prompts';\nimport { isCancel } from '@clack/prompts';\nimport type { OpenRouterDataClient } from '../../openrouter/data-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: OpenRouterDataClient,\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(client: OpenRouterDataClient): Promise<void> {\n clack.intro('Browse Models');\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(client);\n}\n"],"mappings":"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"}
|
package/dist/cli.mjs
CHANGED
|
@@ -3800,7 +3800,7 @@ var require_main = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
|
|
|
3800
3800
|
const fs = __require("fs");
|
|
3801
3801
|
const path = __require("path");
|
|
3802
3802
|
const os$1 = __require("os");
|
|
3803
|
-
const crypto = __require("crypto");
|
|
3803
|
+
const crypto$1 = __require("crypto");
|
|
3804
3804
|
const TIPS = [
|
|
3805
3805
|
"◈ encrypted .env [www.dotenvx.com]",
|
|
3806
3806
|
"◈ secrets for agents [www.dotenvx.com]",
|
|
@@ -4005,7 +4005,7 @@ var require_main = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
|
|
|
4005
4005
|
const authTag = ciphertext.subarray(-16);
|
|
4006
4006
|
ciphertext = ciphertext.subarray(12, -16);
|
|
4007
4007
|
try {
|
|
4008
|
-
const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
|
|
4008
|
+
const aesgcm = crypto$1.createDecipheriv("aes-256-gcm", key, nonce);
|
|
4009
4009
|
aesgcm.setAuthTag(authTag);
|
|
4010
4010
|
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
4011
4011
|
} catch (error) {
|
|
@@ -11750,6 +11750,14 @@ function _getDefaultLogLevel() {
|
|
|
11750
11750
|
//#endregion
|
|
11751
11751
|
//#region src/logger.ts
|
|
11752
11752
|
const logger = createConsola().withTag("proxitor");
|
|
11753
|
+
/** Generate a short request ID (first 8 hex chars of a UUID) */
|
|
11754
|
+
function requestId() {
|
|
11755
|
+
return crypto.randomUUID().slice(0, 8);
|
|
11756
|
+
}
|
|
11757
|
+
/** Format a log message with a request ID prefix. */
|
|
11758
|
+
function withReq(id, message) {
|
|
11759
|
+
return `[${id}] ${message}`;
|
|
11760
|
+
}
|
|
11753
11761
|
//#endregion
|
|
11754
11762
|
//#region src/openrouter/client.ts
|
|
11755
11763
|
var OpenRouterClientError = class extends Error {
|
|
@@ -14697,7 +14705,7 @@ function buildUpstreamResponse(upstream, method) {
|
|
|
14697
14705
|
});
|
|
14698
14706
|
}
|
|
14699
14707
|
/** Read and process the request body, returning an error response on failure */
|
|
14700
|
-
async function readRawBody(request) {
|
|
14708
|
+
async function readRawBody(request, reqId) {
|
|
14701
14709
|
try {
|
|
14702
14710
|
return {
|
|
14703
14711
|
ok: true,
|
|
@@ -14705,7 +14713,7 @@ async function readRawBody(request) {
|
|
|
14705
14713
|
};
|
|
14706
14714
|
} catch (err) {
|
|
14707
14715
|
const message = err instanceof Error ? err.message : "Failed to read request body";
|
|
14708
|
-
logger.error(message);
|
|
14716
|
+
logger.error(withReq(reqId, message));
|
|
14709
14717
|
return {
|
|
14710
14718
|
ok: false,
|
|
14711
14719
|
response: Response.json({ error: {
|
|
@@ -14716,7 +14724,7 @@ async function readRawBody(request) {
|
|
|
14716
14724
|
}
|
|
14717
14725
|
}
|
|
14718
14726
|
/** Resolve per-request config: extract model, resolve overrides, build routing and body */
|
|
14719
|
-
function resolveRequest(rawBody, config, method, path) {
|
|
14727
|
+
function resolveRequest(rawBody, config, method, path, reqId) {
|
|
14720
14728
|
const modelName = extractModel(rawBody);
|
|
14721
14729
|
const resolved = resolveModelConfig(config, modelName);
|
|
14722
14730
|
const providerRouting = buildProviderRouting(resolved.provider);
|
|
@@ -14726,7 +14734,7 @@ function resolveRequest(rawBody, config, method, path) {
|
|
|
14726
14734
|
body = readRequestBody(method, rawBody, inject, providerRouting);
|
|
14727
14735
|
} catch (err) {
|
|
14728
14736
|
const message = err instanceof Error ? err.message : "Failed to process request body";
|
|
14729
|
-
logger.error(message);
|
|
14737
|
+
logger.error(withReq(reqId, message));
|
|
14730
14738
|
return {
|
|
14731
14739
|
inject,
|
|
14732
14740
|
body: void 0,
|
|
@@ -14749,22 +14757,22 @@ function resolveRequest(rawBody, config, method, path) {
|
|
|
14749
14757
|
};
|
|
14750
14758
|
}
|
|
14751
14759
|
/** Execute upstream fetch, returning appropriate error responses on failure */
|
|
14752
|
-
async function executeUpstream(upstreamUrl, method, headers, body, signal, path, startedAt) {
|
|
14760
|
+
async function executeUpstream(upstreamUrl, method, headers, body, signal, path, startedAt, reqId) {
|
|
14753
14761
|
let upstream;
|
|
14754
14762
|
try {
|
|
14755
14763
|
upstream = await fetchUpstream(upstreamUrl, method, headers, body, signal);
|
|
14756
14764
|
} catch (err) {
|
|
14757
14765
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
14758
|
-
logger.warn(`Aborted: ${method} ${path}`);
|
|
14766
|
+
logger.warn(withReq(reqId, `Aborted: ${method} ${path}`));
|
|
14759
14767
|
return new Response(null, { status: 499 });
|
|
14760
14768
|
}
|
|
14761
|
-
logger.error("Upstream fetch error:", err);
|
|
14769
|
+
logger.error(withReq(reqId, "Upstream fetch error:"), err);
|
|
14762
14770
|
return Response.json({ error: {
|
|
14763
14771
|
message: "Proxy failed to reach upstream",
|
|
14764
14772
|
type: "proxy_upstream_error"
|
|
14765
14773
|
} }, { status: 502 });
|
|
14766
14774
|
}
|
|
14767
|
-
logger.info(`${method} ${path} ← ${upstream.status} (${Date.now() - startedAt}ms)`);
|
|
14775
|
+
logger.info(withReq(reqId, `${method} ${path} ← ${upstream.status} (${Date.now() - startedAt}ms)`));
|
|
14768
14776
|
return buildUpstreamResponse(upstream, method);
|
|
14769
14777
|
}
|
|
14770
14778
|
function createProxyServer(config, onReady) {
|
|
@@ -14783,16 +14791,18 @@ function createProxyServer(config, onReady) {
|
|
|
14783
14791
|
const path = new URL(c.req.url).pathname;
|
|
14784
14792
|
const upstreamUrl = buildUpstreamUrl(c.req.url, config);
|
|
14785
14793
|
const startedAt = Date.now();
|
|
14786
|
-
const
|
|
14794
|
+
const reqId = requestId();
|
|
14795
|
+
const raw = await readRawBody(c.req.raw, reqId);
|
|
14787
14796
|
if (!raw.ok) return raw.response;
|
|
14788
|
-
const resolved = resolveRequest(raw.body, config, method, path);
|
|
14797
|
+
const resolved = resolveRequest(raw.body, config, method, path, reqId);
|
|
14789
14798
|
if (resolved.error) return resolved.error;
|
|
14790
14799
|
const headers = buildRequestHeaders(c.req.raw.headers, config, resolved.inject, resolved.headers);
|
|
14791
14800
|
const controller = new AbortController();
|
|
14792
14801
|
c.req.raw.signal.addEventListener("abort", () => controller.abort());
|
|
14802
|
+
const upstreamShort = upstreamUrl.replace(/^https?:\/\//, "");
|
|
14793
14803
|
const modelLog = resolved.modelName ? ` model=${resolved.modelName}` : "";
|
|
14794
|
-
logger.info(`${method} ${path} → ${
|
|
14795
|
-
return executeUpstream(upstreamUrl, method, headers, resolved.body, controller.signal, path, startedAt);
|
|
14804
|
+
logger.info(withReq(reqId, `${method} ${path} → ${upstreamShort}${resolved.inject ? " [inject]" : ""}${modelLog}`));
|
|
14805
|
+
return executeUpstream(upstreamUrl, method, headers, resolved.body, controller.signal, path, startedAt, reqId);
|
|
14796
14806
|
});
|
|
14797
14807
|
return serve({
|
|
14798
14808
|
fetch: app.fetch,
|
|
@@ -14826,7 +14836,7 @@ function startProxyServer(config, onReady) {
|
|
|
14826
14836
|
}
|
|
14827
14837
|
//#endregion
|
|
14828
14838
|
//#region src/version.ts
|
|
14829
|
-
const version = "0.
|
|
14839
|
+
const version = "0.6.0";
|
|
14830
14840
|
//#endregion
|
|
14831
14841
|
//#region src/cli.ts
|
|
14832
14842
|
const argv = process.argv.slice(2);
|
|
@@ -14926,7 +14936,10 @@ const withClient = (fn) => async (args) => {
|
|
|
14926
14936
|
apiKey,
|
|
14927
14937
|
authType: cfg.authType,
|
|
14928
14938
|
onFallback: (path) => {
|
|
14929
|
-
|
|
14939
|
+
let endpoint;
|
|
14940
|
+
if (path === "/providers") endpoint = "providers";
|
|
14941
|
+
else if (path === "/models") endpoint = "models";
|
|
14942
|
+
else endpoint = "model providers";
|
|
14930
14943
|
logger.warn(`Custom API did not return ${endpoint}, using OpenRouter data as fallback`);
|
|
14931
14944
|
}
|
|
14932
14945
|
}));
|