@askalf/dario 2.1.0 → 2.1.1

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 CHANGED
@@ -27,12 +27,12 @@
27
27
  ```bash
28
28
  npx @askalf/dario login # detects Claude Code credentials, starts proxy
29
29
 
30
- # now use it from anywhere
31
- export ANTHROPIC_BASE_URL=http://localhost:3456
32
- export ANTHROPIC_API_KEY=dario
30
+ # now use it from anywhere — Anthropic or OpenAI SDK
31
+ export ANTHROPIC_BASE_URL=http://localhost:3456 # or OPENAI_BASE_URL=http://localhost:3456/v1
32
+ export ANTHROPIC_API_KEY=dario # or OPENAI_API_KEY=dario
33
33
  ```
34
34
 
35
- That's it. Any tool that speaks the Anthropic API now uses your subscription.
35
+ Opus, Sonnet, Haiku — all models, streaming, tool use. Works with OpenClaw, Cursor, Continue, Aider, Hermes, or any tool that speaks the Anthropic or OpenAI API. When rate limited, `--cli` routes through Claude Code for uninterrupted Opus access.
36
36
 
37
37
  ---
38
38
 
@@ -88,6 +88,7 @@ Usage:
88
88
  ANTHROPIC_BASE_URL=http://localhost:3456
89
89
  ANTHROPIC_API_KEY=dario
90
90
 
91
+ Auth: open (no DARIO_API_KEY set)
91
92
  OAuth: healthy (expires in 11h 42m)
92
93
  Model: passthrough (client decides)
93
94
  ```
@@ -294,12 +295,13 @@ ANTHROPIC_BASE_URL=http://localhost:3456 ANTHROPIC_API_KEY=dario your-tool-here
294
295
 
295
296
  ### Proxy Options
296
297
 
297
- | Flag | Description | Default |
298
- |------|-------------|---------|
298
+ | Flag/Env | Description | Default |
299
+ |----------|-------------|---------|
299
300
  | `--cli` | Use Claude CLI as backend (bypasses rate limits) | off |
300
301
  | `--model=MODEL` | Force a model (`opus`, `sonnet`, `haiku`, or full ID) | passthrough |
301
302
  | `--port=PORT` | Port to listen on | `3456` |
302
303
  | `--verbose` / `-v` | Log every request | off |
304
+ | `DARIO_API_KEY` | If set, all endpoints (except `/health`) require matching `x-api-key` header or `Authorization: Bearer` header | unset (open) |
303
305
 
304
306
  ## Supported Features
305
307
 
package/dist/proxy.js CHANGED
@@ -201,7 +201,9 @@ async function handleViaCli(body, model, verbose) {
201
201
  if (!lastUser) {
202
202
  return { status: 400, body: JSON.stringify({ error: 'No user message' }), contentType: 'application/json' };
203
203
  }
204
- const effectiveModel = model ?? parsed.model ?? 'claude-opus-4-6';
204
+ const rawModel = model ?? parsed.model ?? 'claude-opus-4-6';
205
+ // Validate model name — only allow alphanumeric, hyphens, dots, underscores
206
+ const effectiveModel = /^[a-zA-Z0-9._-]+$/.test(rawModel) ? rawModel : 'claude-opus-4-6';
205
207
  const prompt = typeof lastUser.content === 'string'
206
208
  ? lastUser.content
207
209
  : JSON.stringify(lastUser.content);
@@ -237,7 +239,7 @@ async function handleViaCli(body, model, verbose) {
237
239
  if (code !== 0 || !stdout.trim()) {
238
240
  resolve({
239
241
  status: 502,
240
- body: JSON.stringify({ type: 'error', error: { type: 'api_error', message: stderr.substring(0, 200) || 'CLI backend failed' } }),
242
+ body: JSON.stringify({ type: 'error', error: { type: 'api_error', message: sanitizeError(stderr.substring(0, 200)) || 'CLI backend failed' } }),
241
243
  contentType: 'application/json',
242
244
  });
243
245
  return;
@@ -492,6 +494,7 @@ export async function startProxy(opts = {}) {
492
494
  const decoder = new TextDecoder();
493
495
  try {
494
496
  let buffer = '';
497
+ const MAX_LINE_LENGTH = 1_000_000; // 1MB max per SSE line
495
498
  while (true) {
496
499
  const { done, value } = await reader.read();
497
500
  if (done)
@@ -499,6 +502,10 @@ export async function startProxy(opts = {}) {
499
502
  if (isOpenAI) {
500
503
  // Translate Anthropic SSE → OpenAI SSE
501
504
  buffer += decoder.decode(value, { stream: true });
505
+ // Guard against unbounded buffer growth
506
+ if (buffer.length > MAX_LINE_LENGTH) {
507
+ buffer = buffer.slice(-MAX_LINE_LENGTH);
508
+ }
502
509
  const lines = buffer.split('\n');
503
510
  buffer = lines.pop() ?? '';
504
511
  for (const line of lines) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Use your Claude subscription as an API. No API key needed. Local proxy for Claude Max/Pro subscriptions.",
5
5
  "type": "module",
6
6
  "bin": {