proxitor 0.1.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/LICENSE +21 -0
- package/README.md +200 -0
- package/dist/cli.cjs +36 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +37 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.cjs +10 -0
- package/dist/index.d.cts +91 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +91 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/proxy.cjs +536 -0
- package/dist/proxy.cjs.map +1 -0
- package/dist/proxy.mjs +454 -0
- package/dist/proxy.mjs.map +1 -0
- package/package.json +85 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# proxitor
|
|
2
|
+
|
|
3
|
+
> Lightweight proxy for routing CLI requests (claude-code, codex) to [OpenRouter](https://openrouter.ai)
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
When using AI CLI tools like Claude Code or Codex, you may want to route requests through OpenRouter for model selection, cost control, or unified API access. Proxitor sits between your CLI tools and OpenRouter, injecting [provider routing](https://openrouter.ai/docs/api/reference/streaming) into requests and streaming responses back unchanged — including SSE streams from LLM models.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# npm
|
|
13
|
+
npm install -g proxitor
|
|
14
|
+
|
|
15
|
+
# bun
|
|
16
|
+
bun install -g proxitor
|
|
17
|
+
|
|
18
|
+
# npx (no install)
|
|
19
|
+
npx proxitor
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Start the proxy
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# With env var
|
|
28
|
+
OPENROUTER_API_KEY=sk-... proxitor
|
|
29
|
+
|
|
30
|
+
# With CLI flag
|
|
31
|
+
proxitor --openrouter-key sk-...
|
|
32
|
+
|
|
33
|
+
# With config file
|
|
34
|
+
proxitor --config ./proxitor.config.yaml
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Configure CLI tools
|
|
38
|
+
|
|
39
|
+
Point your AI CLI tools at the proxy:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Claude Code
|
|
43
|
+
ANTHROPIC_BASE_URL=http://localhost:8080/v1 claude
|
|
44
|
+
|
|
45
|
+
# Codex
|
|
46
|
+
OPENAI_BASE_URL=http://localhost:8080/v1 codex
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Configuration
|
|
50
|
+
|
|
51
|
+
Proxitor looks for config files in this order:
|
|
52
|
+
|
|
53
|
+
1. `proxitor.config.yaml`
|
|
54
|
+
2. `proxitor.config.yml`
|
|
55
|
+
3. `proxitor.config.json`
|
|
56
|
+
4. `.proxitor.yaml`
|
|
57
|
+
5. `.proxitor.yml`
|
|
58
|
+
6. `.proxitor.json`
|
|
59
|
+
|
|
60
|
+
See [`proxitor.config.example.yaml`](./proxitor.config.example.yaml) for a full example.
|
|
61
|
+
|
|
62
|
+
### Priority
|
|
63
|
+
|
|
64
|
+
CLI flags > config file > environment variables > defaults
|
|
65
|
+
|
|
66
|
+
### Provider routing
|
|
67
|
+
|
|
68
|
+
Control which upstream provider handles your requests. Both `only` and `order` accept a single string or an array:
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
# Use a single provider exclusively (no fallbacks)
|
|
72
|
+
provider:
|
|
73
|
+
only: "deepinfra"
|
|
74
|
+
|
|
75
|
+
# Use multiple providers exclusively
|
|
76
|
+
provider:
|
|
77
|
+
only:
|
|
78
|
+
- "openai"
|
|
79
|
+
- "azure"
|
|
80
|
+
|
|
81
|
+
# Prefer a provider, allow fallbacks
|
|
82
|
+
provider:
|
|
83
|
+
order: "anthropic"
|
|
84
|
+
allowFallbacks: true
|
|
85
|
+
|
|
86
|
+
# Try providers in order
|
|
87
|
+
provider:
|
|
88
|
+
order:
|
|
89
|
+
- "anthropic"
|
|
90
|
+
- "deepinfra"
|
|
91
|
+
allowFallbacks: false
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Without `provider` configured, the proxy forwards requests unchanged.
|
|
95
|
+
See the [OpenRouter provider routing docs](https://openrouter.ai/docs/guides/routing/provider-selection) for the full list of supported providers.
|
|
96
|
+
|
|
97
|
+
### Per-model overrides
|
|
98
|
+
|
|
99
|
+
Route different models to different providers using `modelOverrides`. Keys are exact model names or prefix patterns (e.g. `claude-*`). Overrides layer on top of global settings — `provider` replaces the global value, `headers` merge:
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
provider:
|
|
103
|
+
order: "deepinfra"
|
|
104
|
+
|
|
105
|
+
modelOverrides:
|
|
106
|
+
# Exact match — force Anthropic models to Anthropic's own infrastructure
|
|
107
|
+
"claude-sonnet-4-6":
|
|
108
|
+
provider:
|
|
109
|
+
only: "anthropic"
|
|
110
|
+
|
|
111
|
+
# Wildcard — all Claude models prefer Anthropic with fallback
|
|
112
|
+
"claude-*":
|
|
113
|
+
provider:
|
|
114
|
+
order:
|
|
115
|
+
- "anthropic"
|
|
116
|
+
- "deepinfra"
|
|
117
|
+
|
|
118
|
+
# Wildcard — GPT models to OpenAI/Azure, plus a custom header
|
|
119
|
+
"gpt-*":
|
|
120
|
+
provider:
|
|
121
|
+
only:
|
|
122
|
+
- "openai"
|
|
123
|
+
- "azure"
|
|
124
|
+
headers:
|
|
125
|
+
X-Model-Family: "gpt"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
When a model name matches multiple patterns, the most specific match wins (exact name > longer prefix > shorter prefix).
|
|
129
|
+
|
|
130
|
+
### Custom headers
|
|
131
|
+
|
|
132
|
+
Add custom headers to all proxied requests, or per-model via `modelOverrides`:
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
# Global custom headers
|
|
136
|
+
headers:
|
|
137
|
+
X-Custom-Header: "my-value"
|
|
138
|
+
X-Environment: "production"
|
|
139
|
+
|
|
140
|
+
# Per-model headers (merged on top of global)
|
|
141
|
+
modelOverrides:
|
|
142
|
+
"claude-*":
|
|
143
|
+
headers:
|
|
144
|
+
X-Custom-Header: "claude-override" # overrides global value
|
|
145
|
+
X-Extra: "only-for-claude" # added only for this model
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Health check
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
curl http://localhost:8080/health
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## CLI Options
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
proxitor [options]
|
|
158
|
+
|
|
159
|
+
Options:
|
|
160
|
+
-p, --port <port> Proxy server port (default: 8080)
|
|
161
|
+
-h, --host <host> Proxy server host (default: 0.0.0.0)
|
|
162
|
+
-c, --config <path> Path to config file
|
|
163
|
+
--openrouter-key <key> OpenRouter API key
|
|
164
|
+
--verbose Enable verbose logging
|
|
165
|
+
-v, --version Display version
|
|
166
|
+
--help Display help
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Development
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Install dependencies
|
|
173
|
+
pnpm install
|
|
174
|
+
|
|
175
|
+
# Run in dev mode with watch
|
|
176
|
+
pnpm run dev
|
|
177
|
+
|
|
178
|
+
# Run tests
|
|
179
|
+
pnpm run test
|
|
180
|
+
|
|
181
|
+
# Type check
|
|
182
|
+
pnpm run typecheck
|
|
183
|
+
|
|
184
|
+
# Lint + format (Biome)
|
|
185
|
+
pnpm run check:biome
|
|
186
|
+
|
|
187
|
+
# Auto-fix lint + format issues
|
|
188
|
+
pnpm run lint:fix
|
|
189
|
+
pnpm run format
|
|
190
|
+
|
|
191
|
+
# Build
|
|
192
|
+
pnpm run build
|
|
193
|
+
|
|
194
|
+
# Full check (typecheck + biome + test)
|
|
195
|
+
pnpm run check
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## License
|
|
199
|
+
|
|
200
|
+
[MIT](./LICENSE)
|
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const require_proxy = require("./proxy.cjs");
|
|
3
|
+
let cac = require("cac");
|
|
4
|
+
let dotenv = require("dotenv");
|
|
5
|
+
//#region src/version.ts
|
|
6
|
+
const version = "0.1.0";
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/cli.ts
|
|
9
|
+
(0, dotenv.config)();
|
|
10
|
+
const cli = (0, cac.cac)("proxitor");
|
|
11
|
+
cli.version(version).usage("[options]").help();
|
|
12
|
+
cli.option("-p, --port <port>", "Proxy server port", { default: 8080 }).option("-h, --host <host>", "Proxy server host", { default: "0.0.0.0" }).option("-c, --config <path>", "Path to config file").option("--no-config", "Skip config file discovery").option("--openrouter-key <key>", "OpenRouter API key").option("--verbose", "Enable verbose logging");
|
|
13
|
+
const parsed = cli.parse();
|
|
14
|
+
async function main() {
|
|
15
|
+
try {
|
|
16
|
+
const config = await require_proxy.loadConfig({
|
|
17
|
+
configPath: typeof parsed.options.config === "string" ? parsed.options.config : void 0,
|
|
18
|
+
noConfig: parsed.options.config === false,
|
|
19
|
+
port: parsed.options.port,
|
|
20
|
+
host: parsed.options.host,
|
|
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
|
+
}
|
|
32
|
+
}
|
|
33
|
+
main();
|
|
34
|
+
//#endregion
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=cli.cjs.map
|
package/dist/cli.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":["loadConfig"],"sources":["../src/version.ts","../src/cli.ts"],"sourcesContent":["export const version = '0.1.0'\n","#!/usr/bin/env node\nimport { cac } from 'cac'\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\nloadDotenv()\n\nconst cli = cac('proxitor')\n\ncli.version(version).usage('[options]').help()\n\ncli\n .option('-p, --port <port>', 'Proxy server port', { default: 8080 })\n .option('-h, --host <host>', 'Proxy server host', { default: '0.0.0.0' })\n .option('-c, --config <path>', 'Path to config file')\n .option('--no-config', 'Skip config file discovery')\n .option('--openrouter-key <key>', 'OpenRouter API key')\n .option('--verbose', 'Enable verbose logging')\n\nconst parsed = cli.parse()\n\nasync function main() {\n try {\n const config = await loadConfig({\n configPath:\n typeof parsed.options.config === 'string' ? parsed.options.config : undefined,\n noConfig: parsed.options.config === false,\n port: parsed.options.port,\n host: parsed.options.host,\n openrouterKey: parsed.options.openrouterKey,\n verbose: parsed.options.verbose,\n })\n\n startProxyServer(config, () => {\n logger.ready(`Proxitor proxy listening on ${config.host}:${config.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\nvoid main()\n"],"mappings":";;;;;AAAA,MAAa,UAAU;;;mBCQZ;AAEX,MAAM,OAAA,GAAA,IAAA,KAAU,UAAU;AAE1B,IAAI,QAAQ,OAAO,EAAE,MAAM,WAAW,EAAE,KAAK;AAE7C,IACG,OAAO,qBAAqB,qBAAqB,EAAE,SAAS,KAAK,CAAC,EAClE,OAAO,qBAAqB,qBAAqB,EAAE,SAAS,UAAU,CAAC,EACvE,OAAO,uBAAuB,qBAAqB,EACnD,OAAO,eAAe,4BAA4B,EAClD,OAAO,0BAA0B,oBAAoB,EACrD,OAAO,aAAa,wBAAwB;AAE/C,MAAM,SAAS,IAAI,MAAM;AAEzB,eAAe,OAAO;CACpB,IAAI;EACF,MAAM,SAAS,MAAMA,cAAAA,WAAW;GAC9B,YACE,OAAO,OAAO,QAAQ,WAAW,WAAW,OAAO,QAAQ,SAAS,KAAA;GACtE,UAAU,OAAO,QAAQ,WAAW;GACpC,MAAM,OAAO,QAAQ;GACrB,MAAM,OAAO,QAAQ;GACrB,eAAe,OAAO,QAAQ;GAC9B,SAAS,OAAO,QAAQ;EAC1B,CAAC;EAED,cAAA,iBAAiB,cAAc;GAC7B,cAAA,OAAO,MAAM,+BAA+B,OAAO,KAAK,GAAG,OAAO,MAAM;GACxE,cAAA,OAAO,KAAK,gCAAgC;EAC9C,CAAC;CACH,SAAS,OAAO;EACd,cAAA,OAAO,MAAM,0BAA0B,KAAK;EAC5C,QAAQ,KAAK,CAAC;CAChB;AACF;AAEK,KAAK"}
|
package/dist/cli.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { i as logger, n as startProxyServer, o as loadConfig } from "./proxy.mjs";
|
|
3
|
+
import { cac } from "cac";
|
|
4
|
+
import { config } from "dotenv";
|
|
5
|
+
//#region src/version.ts
|
|
6
|
+
const version = "0.1.0";
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/cli.ts
|
|
9
|
+
config();
|
|
10
|
+
const cli = cac("proxitor");
|
|
11
|
+
cli.version(version).usage("[options]").help();
|
|
12
|
+
cli.option("-p, --port <port>", "Proxy server port", { default: 8080 }).option("-h, --host <host>", "Proxy server host", { default: "0.0.0.0" }).option("-c, --config <path>", "Path to config file").option("--no-config", "Skip config file discovery").option("--openrouter-key <key>", "OpenRouter API key").option("--verbose", "Enable verbose logging");
|
|
13
|
+
const parsed = cli.parse();
|
|
14
|
+
async function main() {
|
|
15
|
+
try {
|
|
16
|
+
const config = await loadConfig({
|
|
17
|
+
configPath: typeof parsed.options.config === "string" ? parsed.options.config : void 0,
|
|
18
|
+
noConfig: parsed.options.config === false,
|
|
19
|
+
port: parsed.options.port,
|
|
20
|
+
host: parsed.options.host,
|
|
21
|
+
openrouterKey: parsed.options.openrouterKey,
|
|
22
|
+
verbose: parsed.options.verbose
|
|
23
|
+
});
|
|
24
|
+
startProxyServer(config, () => {
|
|
25
|
+
logger.ready(`Proxitor proxy listening on ${config.host}:${config.port}`);
|
|
26
|
+
logger.info(`Routing requests to OpenRouter`);
|
|
27
|
+
});
|
|
28
|
+
} catch (error) {
|
|
29
|
+
logger.error("Failed to start proxy:", error);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
main();
|
|
34
|
+
//#endregion
|
|
35
|
+
export {};
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=cli.mjs.map
|
package/dist/cli.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":["loadDotenv"],"sources":["../src/version.ts","../src/cli.ts"],"sourcesContent":["export const version = '0.1.0'\n","#!/usr/bin/env node\nimport { cac } from 'cac'\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\nloadDotenv()\n\nconst cli = cac('proxitor')\n\ncli.version(version).usage('[options]').help()\n\ncli\n .option('-p, --port <port>', 'Proxy server port', { default: 8080 })\n .option('-h, --host <host>', 'Proxy server host', { default: '0.0.0.0' })\n .option('-c, --config <path>', 'Path to config file')\n .option('--no-config', 'Skip config file discovery')\n .option('--openrouter-key <key>', 'OpenRouter API key')\n .option('--verbose', 'Enable verbose logging')\n\nconst parsed = cli.parse()\n\nasync function main() {\n try {\n const config = await loadConfig({\n configPath:\n typeof parsed.options.config === 'string' ? parsed.options.config : undefined,\n noConfig: parsed.options.config === false,\n port: parsed.options.port,\n host: parsed.options.host,\n openrouterKey: parsed.options.openrouterKey,\n verbose: parsed.options.verbose,\n })\n\n startProxyServer(config, () => {\n logger.ready(`Proxitor proxy listening on ${config.host}:${config.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\nvoid main()\n"],"mappings":";;;;;AAAA,MAAa,UAAU;;;ACQvBA,OAAW;AAEX,MAAM,MAAM,IAAI,UAAU;AAE1B,IAAI,QAAQ,OAAO,EAAE,MAAM,WAAW,EAAE,KAAK;AAE7C,IACG,OAAO,qBAAqB,qBAAqB,EAAE,SAAS,KAAK,CAAC,EAClE,OAAO,qBAAqB,qBAAqB,EAAE,SAAS,UAAU,CAAC,EACvE,OAAO,uBAAuB,qBAAqB,EACnD,OAAO,eAAe,4BAA4B,EAClD,OAAO,0BAA0B,oBAAoB,EACrD,OAAO,aAAa,wBAAwB;AAE/C,MAAM,SAAS,IAAI,MAAM;AAEzB,eAAe,OAAO;CACpB,IAAI;EACF,MAAM,SAAS,MAAM,WAAW;GAC9B,YACE,OAAO,OAAO,QAAQ,WAAW,WAAW,OAAO,QAAQ,SAAS,KAAA;GACtE,UAAU,OAAO,QAAQ,WAAW;GACpC,MAAM,OAAO,QAAQ;GACrB,MAAM,OAAO,QAAQ;GACrB,eAAe,OAAO,QAAQ;GAC9B,SAAS,OAAO,QAAQ;EAC1B,CAAC;EAED,iBAAiB,cAAc;GAC7B,OAAO,MAAM,+BAA+B,OAAO,KAAK,GAAG,OAAO,MAAM;GACxE,OAAO,KAAK,gCAAgC;EAC9C,CAAC;CACH,SAAS,OAAO;EACd,OAAO,MAAM,0BAA0B,KAAK;EAC5C,QAAQ,KAAK,CAAC;CAChB;AACF;AAEK,KAAK"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_proxy = require("./proxy.cjs");
|
|
3
|
+
exports.buildProviderRouting = require_proxy.buildProviderRouting;
|
|
4
|
+
exports.createProxyServer = require_proxy.createProxyServer;
|
|
5
|
+
exports.extractModel = require_proxy.extractModel;
|
|
6
|
+
exports.loadConfig = require_proxy.loadConfig;
|
|
7
|
+
exports.matchScore = require_proxy.matchScore;
|
|
8
|
+
exports.resolveModelConfig = require_proxy.resolveModelConfig;
|
|
9
|
+
exports.toArray = require_proxy.toArray;
|
|
10
|
+
exports.tryParseBody = require_proxy.tryParseBody;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ServerType } from "@hono/node-server";
|
|
2
|
+
|
|
3
|
+
//#region src/config.d.ts
|
|
4
|
+
/** Percentile cutoffs for performance thresholds */
|
|
5
|
+
type PercentileCutoffs = {
|
|
6
|
+
p50?: number;
|
|
7
|
+
p75?: number;
|
|
8
|
+
p90?: number;
|
|
9
|
+
p99?: number;
|
|
10
|
+
};
|
|
11
|
+
/** Provider sorting options */
|
|
12
|
+
type ProviderSort = 'price' | 'throughput' | 'latency' | {
|
|
13
|
+
by: 'price' | 'throughput' | 'latency';
|
|
14
|
+
partition?: 'model' | 'none';
|
|
15
|
+
};
|
|
16
|
+
/** Maximum pricing for a request */
|
|
17
|
+
type MaxPrice = {
|
|
18
|
+
prompt?: number;
|
|
19
|
+
completion?: number;
|
|
20
|
+
request?: number;
|
|
21
|
+
image?: number;
|
|
22
|
+
};
|
|
23
|
+
type ProviderConfig = {
|
|
24
|
+
/** Allow only these providers (e.g. "deepinfra" or ["anthropic", "openai"]) */only?: string | string[]; /** Try providers in this order (e.g. "anthropic" or ["openai", "together"]) */
|
|
25
|
+
order?: string | string[]; /** Ignore these providers (mirror of only — skip specific providers) */
|
|
26
|
+
ignore?: string | string[]; /** Allow fallback to other providers (default: true) */
|
|
27
|
+
allowFallbacks?: boolean; /** Sort providers by price, throughput, or latency */
|
|
28
|
+
sort?: ProviderSort; /** Filter by quantization levels (e.g. ["fp8", "int4"]) */
|
|
29
|
+
quantizations?: string[]; /** Maximum pricing to accept */
|
|
30
|
+
maxPrice?: MaxPrice; /** Only use providers that support all request parameters (default: false) */
|
|
31
|
+
requireParameters?: boolean; /** Control data collection policy: "allow" or "deny" (default: "allow") */
|
|
32
|
+
dataCollection?: 'allow' | 'deny'; /** Restrict routing to Zero Data Retention endpoints */
|
|
33
|
+
zdr?: boolean; /** Restrict routing to models that allow text distillation */
|
|
34
|
+
enforceDistillableText?: boolean; /** Preferred minimum throughput (tokens/sec) */
|
|
35
|
+
preferredMinThroughput?: number | PercentileCutoffs; /** Preferred maximum latency (seconds) */
|
|
36
|
+
preferredMaxLatency?: number | PercentileCutoffs;
|
|
37
|
+
};
|
|
38
|
+
/** Per-model override: layers on top of global config */
|
|
39
|
+
type ModelOverride = {
|
|
40
|
+
/** Override provider routing for matching models */provider?: ProviderConfig; /** Additional headers to merge for matching models */
|
|
41
|
+
headers?: Record<string, string>;
|
|
42
|
+
};
|
|
43
|
+
/** Result of merging global config with a model-specific override */
|
|
44
|
+
type ResolvedModelConfig = {
|
|
45
|
+
provider?: ProviderConfig;
|
|
46
|
+
headers?: Record<string, string>;
|
|
47
|
+
};
|
|
48
|
+
type ProxyConfig = {
|
|
49
|
+
host: string;
|
|
50
|
+
port: number;
|
|
51
|
+
openrouterKey: string;
|
|
52
|
+
openrouterBaseUrl: string;
|
|
53
|
+
verbose: boolean; /** Request body size limit (default: "50mb") */
|
|
54
|
+
bodyLimit: string; /** Provider routing configuration (global default) */
|
|
55
|
+
provider?: ProviderConfig; /** HTTP-Referer for OpenRouter attribution */
|
|
56
|
+
attributionReferer: string; /** X-Title for OpenRouter attribution */
|
|
57
|
+
attributionTitle: string; /** Custom headers to add to proxied requests (global default) */
|
|
58
|
+
headers?: Record<string, string>; /** Per-model config overrides. Keys are exact model names or prefix patterns (e.g. "claude-*") */
|
|
59
|
+
modelOverrides?: Record<string, ModelOverride>;
|
|
60
|
+
};
|
|
61
|
+
type LoadConfigOptions = {
|
|
62
|
+
configPath?: string;
|
|
63
|
+
noConfig?: boolean;
|
|
64
|
+
host?: string;
|
|
65
|
+
openrouterKey?: string;
|
|
66
|
+
port?: number;
|
|
67
|
+
verbose?: boolean;
|
|
68
|
+
};
|
|
69
|
+
/** Build the provider routing object for OpenRouter request body injection */
|
|
70
|
+
declare function buildProviderRouting(provider?: ProviderConfig): Record<string, unknown> | undefined;
|
|
71
|
+
/** Score a pattern against a model name. Higher = better match. -1 = no match. */
|
|
72
|
+
declare function matchScore(pattern: string, modelName: string): number;
|
|
73
|
+
/** Resolve the effective config for a given model by merging global defaults with the best-matching override */
|
|
74
|
+
declare function resolveModelConfig(config: ProxyConfig, modelName?: string): ResolvedModelConfig;
|
|
75
|
+
declare function loadConfig(options: LoadConfigOptions): Promise<ProxyConfig>;
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/proxy/inject.d.ts
|
|
78
|
+
/** Extract the model name from a raw request body. Returns undefined if not parseable or absent. */
|
|
79
|
+
declare function extractModel(rawBody: ArrayBuffer): string | undefined;
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/proxy.d.ts
|
|
82
|
+
declare function createProxyServer(config: ProxyConfig, onReady?: () => void): ServerType;
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/utils.d.ts
|
|
85
|
+
/** Normalize a single string or array of strings to an array. Returns undefined for empty arrays. */
|
|
86
|
+
declare function toArray(value: string | string[] | undefined): string[] | undefined;
|
|
87
|
+
/** Try to parse an ArrayBuffer as JSON. Returns undefined on failure or empty body. */
|
|
88
|
+
declare function tryParseBody(raw: ArrayBuffer): Record<string, unknown> | undefined;
|
|
89
|
+
//#endregion
|
|
90
|
+
export { type ModelOverride, type ProviderConfig, type ProxyConfig, type ResolvedModelConfig, buildProviderRouting, createProxyServer, extractModel, loadConfig, matchScore, resolveModelConfig, toArray, tryParseBody };
|
|
91
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/config.ts","../src/proxy/inject.ts","../src/proxy.ts","../src/utils.ts"],"mappings":";;;;KAOY,iBAAA;EACV,GAAA;EACA,GAAA;EACA,GAAA;EACA,GAAA;AAAA;;KAIU,YAAA;EAIN,EAAA;EAAwC,SAAS;AAAA;AARlD;AAAA,KAWO,QAAA;EACV,MAAA;EACA,UAAA;EACA,OAAA;EACA,KAAA;AAAA;AAAA,KAGU,cAAA;iFAEV,IAAA,sBARA;EAUA,KAAA,sBARA;EAUA,MAAA,sBATK;EAWL,cAAA,YARU;EAUV,IAAA,GAAO,YAAA;EAEP,aAAA,aAEW;EAAX,QAAA,GAAW,QAAA,EAYoB;EAV/B,iBAAA,YAUgD;EARhD,cAAA,qBAdA;EAgBA,GAAA,YAZA;EAcA,sBAAA,YAZO;EAcP,sBAAA,YAAkC,iBAAA,EAVlC;EAYA,mBAAA,YAA+B,iBAAA;AAAA;;KAIrB,aAAA;EARV,oDAUA,QAAA,GAAW,cAAA,EARuB;EAUlC,OAAA,GAAU,MAAM;AAAA;;KAIN,mBAAA;EACV,QAAA,GAAW,cAAA;EACX,OAAA,GAAU,MAAM;AAAA;AAAA,KAGN,WAAA;EACV,IAAA;EACA,IAAA;EACA,aAAA;EACA,iBAAA;EACA,OAAA,WAdgB;EAgBhB,SAAA,UAZ6B;EAc7B,QAAA,GAAW,cAAA,EAZK;EAchB,kBAAA,UAfW;EAiBX,gBAAA,UAhBU;EAkBV,OAAA,GAAU,MAAA,kBAlBM;EAoBhB,cAAA,GAAiB,MAAA,SAAe,aAAA;AAAA;AAAA,KAc7B,iBAAA;EACH,UAAA;EACA,QAAA;EACA,IAAA;EACA,aAAA;EACA,IAAA;EACA,OAAA;AAAA;;iBAwBc,oBAAA,CACd,QAAA,GAAW,cAAA,GACV,MAAM;;iBA0BO,UAAA,CAAW,OAAA,UAAiB,SAAiB;;iBAW7C,kBAAA,CACd,MAAA,EAAQ,WAAA,EACR,SAAA,YACC,mBAAmB;AAAA,iBAgCA,UAAA,CAAW,OAAA,EAAS,iBAAA,GAAoB,OAAA,CAAQ,WAAA;;;;iBC5MtD,YAAA,CAAa,OAAoB,EAAX,WAAW;;;iBC0JjC,iBAAA,CAAkB,MAAA,EAAQ,WAAA,EAAa,OAAA,gBAAuB,UAAU;;;;iBC5JxE,OAAA,CAAQ,KAAoC;;iBAO5C,YAAA,CAAa,GAAA,EAAK,WAAA,GAAc,MAAM"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ServerType } from "@hono/node-server";
|
|
2
|
+
|
|
3
|
+
//#region src/config.d.ts
|
|
4
|
+
/** Percentile cutoffs for performance thresholds */
|
|
5
|
+
type PercentileCutoffs = {
|
|
6
|
+
p50?: number;
|
|
7
|
+
p75?: number;
|
|
8
|
+
p90?: number;
|
|
9
|
+
p99?: number;
|
|
10
|
+
};
|
|
11
|
+
/** Provider sorting options */
|
|
12
|
+
type ProviderSort = 'price' | 'throughput' | 'latency' | {
|
|
13
|
+
by: 'price' | 'throughput' | 'latency';
|
|
14
|
+
partition?: 'model' | 'none';
|
|
15
|
+
};
|
|
16
|
+
/** Maximum pricing for a request */
|
|
17
|
+
type MaxPrice = {
|
|
18
|
+
prompt?: number;
|
|
19
|
+
completion?: number;
|
|
20
|
+
request?: number;
|
|
21
|
+
image?: number;
|
|
22
|
+
};
|
|
23
|
+
type ProviderConfig = {
|
|
24
|
+
/** Allow only these providers (e.g. "deepinfra" or ["anthropic", "openai"]) */only?: string | string[]; /** Try providers in this order (e.g. "anthropic" or ["openai", "together"]) */
|
|
25
|
+
order?: string | string[]; /** Ignore these providers (mirror of only — skip specific providers) */
|
|
26
|
+
ignore?: string | string[]; /** Allow fallback to other providers (default: true) */
|
|
27
|
+
allowFallbacks?: boolean; /** Sort providers by price, throughput, or latency */
|
|
28
|
+
sort?: ProviderSort; /** Filter by quantization levels (e.g. ["fp8", "int4"]) */
|
|
29
|
+
quantizations?: string[]; /** Maximum pricing to accept */
|
|
30
|
+
maxPrice?: MaxPrice; /** Only use providers that support all request parameters (default: false) */
|
|
31
|
+
requireParameters?: boolean; /** Control data collection policy: "allow" or "deny" (default: "allow") */
|
|
32
|
+
dataCollection?: 'allow' | 'deny'; /** Restrict routing to Zero Data Retention endpoints */
|
|
33
|
+
zdr?: boolean; /** Restrict routing to models that allow text distillation */
|
|
34
|
+
enforceDistillableText?: boolean; /** Preferred minimum throughput (tokens/sec) */
|
|
35
|
+
preferredMinThroughput?: number | PercentileCutoffs; /** Preferred maximum latency (seconds) */
|
|
36
|
+
preferredMaxLatency?: number | PercentileCutoffs;
|
|
37
|
+
};
|
|
38
|
+
/** Per-model override: layers on top of global config */
|
|
39
|
+
type ModelOverride = {
|
|
40
|
+
/** Override provider routing for matching models */provider?: ProviderConfig; /** Additional headers to merge for matching models */
|
|
41
|
+
headers?: Record<string, string>;
|
|
42
|
+
};
|
|
43
|
+
/** Result of merging global config with a model-specific override */
|
|
44
|
+
type ResolvedModelConfig = {
|
|
45
|
+
provider?: ProviderConfig;
|
|
46
|
+
headers?: Record<string, string>;
|
|
47
|
+
};
|
|
48
|
+
type ProxyConfig = {
|
|
49
|
+
host: string;
|
|
50
|
+
port: number;
|
|
51
|
+
openrouterKey: string;
|
|
52
|
+
openrouterBaseUrl: string;
|
|
53
|
+
verbose: boolean; /** Request body size limit (default: "50mb") */
|
|
54
|
+
bodyLimit: string; /** Provider routing configuration (global default) */
|
|
55
|
+
provider?: ProviderConfig; /** HTTP-Referer for OpenRouter attribution */
|
|
56
|
+
attributionReferer: string; /** X-Title for OpenRouter attribution */
|
|
57
|
+
attributionTitle: string; /** Custom headers to add to proxied requests (global default) */
|
|
58
|
+
headers?: Record<string, string>; /** Per-model config overrides. Keys are exact model names or prefix patterns (e.g. "claude-*") */
|
|
59
|
+
modelOverrides?: Record<string, ModelOverride>;
|
|
60
|
+
};
|
|
61
|
+
type LoadConfigOptions = {
|
|
62
|
+
configPath?: string;
|
|
63
|
+
noConfig?: boolean;
|
|
64
|
+
host?: string;
|
|
65
|
+
openrouterKey?: string;
|
|
66
|
+
port?: number;
|
|
67
|
+
verbose?: boolean;
|
|
68
|
+
};
|
|
69
|
+
/** Build the provider routing object for OpenRouter request body injection */
|
|
70
|
+
declare function buildProviderRouting(provider?: ProviderConfig): Record<string, unknown> | undefined;
|
|
71
|
+
/** Score a pattern against a model name. Higher = better match. -1 = no match. */
|
|
72
|
+
declare function matchScore(pattern: string, modelName: string): number;
|
|
73
|
+
/** Resolve the effective config for a given model by merging global defaults with the best-matching override */
|
|
74
|
+
declare function resolveModelConfig(config: ProxyConfig, modelName?: string): ResolvedModelConfig;
|
|
75
|
+
declare function loadConfig(options: LoadConfigOptions): Promise<ProxyConfig>;
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/proxy/inject.d.ts
|
|
78
|
+
/** Extract the model name from a raw request body. Returns undefined if not parseable or absent. */
|
|
79
|
+
declare function extractModel(rawBody: ArrayBuffer): string | undefined;
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/proxy.d.ts
|
|
82
|
+
declare function createProxyServer(config: ProxyConfig, onReady?: () => void): ServerType;
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/utils.d.ts
|
|
85
|
+
/** Normalize a single string or array of strings to an array. Returns undefined for empty arrays. */
|
|
86
|
+
declare function toArray(value: string | string[] | undefined): string[] | undefined;
|
|
87
|
+
/** Try to parse an ArrayBuffer as JSON. Returns undefined on failure or empty body. */
|
|
88
|
+
declare function tryParseBody(raw: ArrayBuffer): Record<string, unknown> | undefined;
|
|
89
|
+
//#endregion
|
|
90
|
+
export { type ModelOverride, type ProviderConfig, type ProxyConfig, type ResolvedModelConfig, buildProviderRouting, createProxyServer, extractModel, loadConfig, matchScore, resolveModelConfig, toArray, tryParseBody };
|
|
91
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/config.ts","../src/proxy/inject.ts","../src/proxy.ts","../src/utils.ts"],"mappings":";;;;KAOY,iBAAA;EACV,GAAA;EACA,GAAA;EACA,GAAA;EACA,GAAA;AAAA;;KAIU,YAAA;EAIN,EAAA;EAAwC,SAAS;AAAA;AARlD;AAAA,KAWO,QAAA;EACV,MAAA;EACA,UAAA;EACA,OAAA;EACA,KAAA;AAAA;AAAA,KAGU,cAAA;iFAEV,IAAA,sBARA;EAUA,KAAA,sBARA;EAUA,MAAA,sBATK;EAWL,cAAA,YARU;EAUV,IAAA,GAAO,YAAA;EAEP,aAAA,aAEW;EAAX,QAAA,GAAW,QAAA,EAYoB;EAV/B,iBAAA,YAUgD;EARhD,cAAA,qBAdA;EAgBA,GAAA,YAZA;EAcA,sBAAA,YAZO;EAcP,sBAAA,YAAkC,iBAAA,EAVlC;EAYA,mBAAA,YAA+B,iBAAA;AAAA;;KAIrB,aAAA;EARV,oDAUA,QAAA,GAAW,cAAA,EARuB;EAUlC,OAAA,GAAU,MAAM;AAAA;;KAIN,mBAAA;EACV,QAAA,GAAW,cAAA;EACX,OAAA,GAAU,MAAM;AAAA;AAAA,KAGN,WAAA;EACV,IAAA;EACA,IAAA;EACA,aAAA;EACA,iBAAA;EACA,OAAA,WAdgB;EAgBhB,SAAA,UAZ6B;EAc7B,QAAA,GAAW,cAAA,EAZK;EAchB,kBAAA,UAfW;EAiBX,gBAAA,UAhBU;EAkBV,OAAA,GAAU,MAAA,kBAlBM;EAoBhB,cAAA,GAAiB,MAAA,SAAe,aAAA;AAAA;AAAA,KAc7B,iBAAA;EACH,UAAA;EACA,QAAA;EACA,IAAA;EACA,aAAA;EACA,IAAA;EACA,OAAA;AAAA;;iBAwBc,oBAAA,CACd,QAAA,GAAW,cAAA,GACV,MAAM;;iBA0BO,UAAA,CAAW,OAAA,UAAiB,SAAiB;;iBAW7C,kBAAA,CACd,MAAA,EAAQ,WAAA,EACR,SAAA,YACC,mBAAmB;AAAA,iBAgCA,UAAA,CAAW,OAAA,EAAS,iBAAA,GAAoB,OAAA,CAAQ,WAAA;;;;iBC5MtD,YAAA,CAAa,OAAoB,EAAX,WAAW;;;iBC0JjC,iBAAA,CAAkB,MAAA,EAAQ,WAAA,EAAa,OAAA,gBAAuB,UAAU;;;;iBC5JxE,OAAA,CAAQ,KAAoC;;iBAO5C,YAAA,CAAa,GAAA,EAAK,WAAA,GAAc,MAAM"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as buildProviderRouting, c as resolveModelConfig, l as toArray, o as loadConfig, r as extractModel, s as matchScore, t as createProxyServer, u as tryParseBody } from "./proxy.mjs";
|
|
2
|
+
export { buildProviderRouting, createProxyServer, extractModel, loadConfig, matchScore, resolveModelConfig, toArray, tryParseBody };
|