@askalf/dario 1.0.7 → 1.0.8

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/cli.js CHANGED
@@ -16,7 +16,7 @@ import { homedir } from 'node:os';
16
16
  import { startOAuthFlow, exchangeCode, getStatus, refreshTokens } from './oauth.js';
17
17
  import { startProxy } from './proxy.js';
18
18
  const args = process.argv.slice(2);
19
- const command = args[0] ?? 'proxy';
19
+ const command = args[0] ?? (process.stdin.isTTY ? 'proxy' : 'proxy');
20
20
  function ask(question) {
21
21
  const rl = createInterface({ input: process.stdin, output: process.stdout });
22
22
  return new Promise(resolve => {
@@ -83,10 +83,18 @@ async function status() {
83
83
  console.log(' ─────────────');
84
84
  console.log('');
85
85
  if (!s.authenticated) {
86
- console.log(` Status: ${s.status === 'expired' ? 'Expired (will auto-refresh)' : 'Not authenticated'}`);
87
- if (s.status === 'none') {
86
+ if (s.status === 'expired' && s.canRefresh) {
87
+ console.log(' Status: Expired (will auto-refresh when proxy starts)');
88
+ console.log(' Run `dario refresh` to refresh now, or `dario proxy` to start.');
89
+ }
90
+ else if (s.status === 'none') {
91
+ console.log(' Status: Not authenticated');
88
92
  console.log(' Run `dario login` to authenticate.');
89
93
  }
94
+ else {
95
+ console.log(` Status: ${s.status}`);
96
+ console.log(' Run `dario login` to re-authenticate.');
97
+ }
90
98
  }
91
99
  else {
92
100
  console.log(` Status: ${s.status}`);
package/dist/oauth.d.ts CHANGED
@@ -45,4 +45,5 @@ export declare function getStatus(): Promise<{
45
45
  status: 'healthy' | 'expiring' | 'expired' | 'none';
46
46
  expiresAt?: number;
47
47
  expiresIn?: string;
48
+ canRefresh?: boolean;
48
49
  }>;
package/dist/oauth.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * Handles authorization, token exchange, storage, and auto-refresh.
6
6
  */
7
7
  import { randomBytes, createHash } from 'node:crypto';
8
- import { readFile, writeFile, mkdir, chmod } from 'node:fs/promises';
8
+ import { readFile, writeFile, mkdir, chmod, rename } from 'node:fs/promises';
9
9
  import { dirname, join } from 'node:path';
10
10
  import { homedir } from 'node:os';
11
11
  // Claude CLI's public OAuth client (PKCE, no secret needed)
@@ -58,7 +58,6 @@ async function saveCredentials(creds) {
58
58
  // Write atomically: write to temp file, then rename
59
59
  const tmpPath = `${path}.tmp.${Date.now()}`;
60
60
  await writeFile(tmpPath, JSON.stringify(creds, null, 2), { mode: 0o600 });
61
- const { rename } = await import('node:fs/promises');
62
61
  await rename(tmpPath, path);
63
62
  // Set permissions (best-effort — no-op on Windows where mode is ignored)
64
63
  try {
@@ -105,10 +104,10 @@ export async function exchangeCode(code, codeVerifier) {
105
104
  redirect_uri: OAUTH_REDIRECT_URI,
106
105
  code_verifier: codeVerifier,
107
106
  }),
107
+ signal: AbortSignal.timeout(30000),
108
108
  });
109
109
  if (!res.ok) {
110
- const err = await res.text().catch(() => 'Unknown error');
111
- throw new Error(`Token exchange failed (${res.status}): ${err}`);
110
+ throw new Error(`Token exchange failed (${res.status}). Check your authorization code and try again.`);
112
111
  }
113
112
  const data = await res.json();
114
113
  const tokens = {
@@ -203,7 +202,9 @@ export async function getStatus() {
203
202
  const { expiresAt } = creds.claudeAiOauth;
204
203
  const now = Date.now();
205
204
  if (expiresAt < now) {
206
- return { authenticated: false, status: 'expired', expiresAt };
205
+ // Expired but has refresh token can be refreshed
206
+ const canRefresh = !!creds.claudeAiOauth.refreshToken;
207
+ return { authenticated: false, status: 'expired', expiresAt, canRefresh };
207
208
  }
208
209
  const ms = expiresAt - now;
209
210
  const hours = Math.floor(ms / 3600000);
package/dist/proxy.js CHANGED
@@ -39,6 +39,16 @@ function getOsName() {
39
39
  }
40
40
  // Persistent session ID per proxy lifetime (like Claude Code does per session)
41
41
  const SESSION_ID = randomUUID();
42
+ // Detect @anthropic-ai/sdk version from installed package
43
+ function detectSdkVersion() {
44
+ try {
45
+ const pkg = require('@anthropic-ai/sdk/package.json');
46
+ return pkg.version ?? '0.81.0';
47
+ }
48
+ catch {
49
+ return '0.81.0';
50
+ }
51
+ }
42
52
  function sanitizeError(err) {
43
53
  const msg = err instanceof Error ? err.message : String(err);
44
54
  // Never leak tokens in error messages
@@ -54,6 +64,7 @@ export async function startProxy(opts = {}) {
54
64
  process.exit(1);
55
65
  }
56
66
  const cliVersion = detectClaudeVersion();
67
+ const sdkVersion = detectSdkVersion();
57
68
  let requestCount = 0;
58
69
  let tokenCostEstimate = 0;
59
70
  const server = createServer(async (req, res) => {
@@ -109,7 +120,6 @@ export async function startProxy(opts = {}) {
109
120
  // Proxy to Anthropic
110
121
  try {
111
122
  const accessToken = await getAccessToken();
112
- requestCount++;
113
123
  // Read request body with size limit
114
124
  const chunks = [];
115
125
  let totalBytes = 0;
@@ -158,7 +168,7 @@ export async function startProxy(opts = {}) {
158
168
  'x-stainless-arch': arch,
159
169
  'x-stainless-lang': 'js',
160
170
  'x-stainless-os': getOsName(),
161
- 'x-stainless-package-version': '0.81.0',
171
+ 'x-stainless-package-version': sdkVersion,
162
172
  'x-stainless-retry-count': '0',
163
173
  'x-stainless-runtime': 'node',
164
174
  'x-stainless-runtime-version': nodeVersion,
@@ -186,6 +196,7 @@ export async function startProxy(opts = {}) {
186
196
  if (v)
187
197
  responseHeaders[h] = v;
188
198
  }
199
+ requestCount++;
189
200
  res.writeHead(upstream.status, responseHeaders);
190
201
  if (isStream && upstream.body) {
191
202
  // Stream SSE chunks through
@@ -229,6 +240,15 @@ export async function startProxy(opts = {}) {
229
240
  res.end(JSON.stringify({ error: 'Proxy error', message: 'Failed to reach upstream API' }));
230
241
  }
231
242
  });
243
+ server.on('error', (err) => {
244
+ if (err.code === 'EADDRINUSE') {
245
+ console.error(`[dario] Port ${port} is already in use. Is another dario proxy running?`);
246
+ }
247
+ else {
248
+ console.error(`[dario] Server error: ${err.message}`);
249
+ }
250
+ process.exit(1);
251
+ });
232
252
  server.listen(port, LOCALHOST, () => {
233
253
  const oauthLine = `OAuth: ${status.status} (expires in ${status.expiresIn})`;
234
254
  console.log('');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Use your Claude subscription as an API. Two commands, no API key. OAuth bridge for Claude Max/Pro.",
5
5
  "type": "module",
6
6
  "bin": {