@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 +11 -3
- package/dist/oauth.d.ts +1 -0
- package/dist/oauth.js +6 -5
- package/dist/proxy.js +22 -2
- package/package.json +1 -1
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
|
-
|
|
87
|
-
|
|
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
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
|
-
|
|
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
|
-
|
|
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':
|
|
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('');
|