@karpeleslab/teamclaude 1.0.0 → 1.0.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/package.json +1 -1
- package/src/index.js +15 -1
- package/src/server.js +5 -15
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -266,12 +266,14 @@ async function runCommand() {
|
|
|
266
266
|
const claudeArgs = args.slice(1);
|
|
267
267
|
if (claudeArgs[0] === '--') claudeArgs.shift();
|
|
268
268
|
|
|
269
|
+
// Only set ANTHROPIC_BASE_URL — Claude Code keeps its own OAuth token
|
|
270
|
+
// which the proxy accepts from localhost. Not setting ANTHROPIC_API_KEY
|
|
271
|
+
// lets Claude Code stay in subscription mode (full model access).
|
|
269
272
|
const child = spawn('claude', claudeArgs, {
|
|
270
273
|
stdio: 'inherit',
|
|
271
274
|
env: {
|
|
272
275
|
...process.env,
|
|
273
276
|
ANTHROPIC_BASE_URL: `http://localhost:${config.proxy.port}`,
|
|
274
|
-
ANTHROPIC_API_KEY: config.proxy.apiKey,
|
|
275
277
|
},
|
|
276
278
|
});
|
|
277
279
|
|
|
@@ -332,6 +334,7 @@ async function statusCommand() {
|
|
|
332
334
|
|
|
333
335
|
async function accountsCommand() {
|
|
334
336
|
const config = await loadOrCreateConfig();
|
|
337
|
+
const verbose = args.includes('-v') || args.includes('--verbose');
|
|
335
338
|
|
|
336
339
|
if (config.accounts.length === 0) {
|
|
337
340
|
console.log('No accounts configured.');
|
|
@@ -387,6 +390,17 @@ async function accountsCommand() {
|
|
|
387
390
|
console.log(` [${i + 1}] ${a.name} (${status}${src})`);
|
|
388
391
|
if (p?.email && p.email !== a.name) console.log(` Email: ${p.email}`);
|
|
389
392
|
if (p?.orgName) console.log(` Org: ${p.orgName}`);
|
|
393
|
+
if (verbose && a.expiresAt) {
|
|
394
|
+
const remaining = a.expiresAt - Date.now();
|
|
395
|
+
if (remaining <= 0) {
|
|
396
|
+
console.log(` Token: expired`);
|
|
397
|
+
} else {
|
|
398
|
+
const mins = Math.floor(remaining / 60000);
|
|
399
|
+
const hrs = Math.floor(mins / 60);
|
|
400
|
+
const expiry = hrs > 0 ? `${hrs}h ${mins % 60}m` : `${mins}m`;
|
|
401
|
+
console.log(` Token: expires in ${expiry}`);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
390
404
|
}
|
|
391
405
|
}
|
|
392
406
|
|
package/src/server.js
CHANGED
|
@@ -19,9 +19,11 @@ export function createProxyServer(accountManager, config, hooks = {}) {
|
|
|
19
19
|
|
|
20
20
|
const server = http.createServer(async (req, res) => {
|
|
21
21
|
try {
|
|
22
|
-
// Auth check
|
|
22
|
+
// Auth check — skip for localhost connections
|
|
23
23
|
const clientKey = req.headers['x-api-key'];
|
|
24
|
-
|
|
24
|
+
const remoteAddr = req.socket.remoteAddress;
|
|
25
|
+
const isLocal = remoteAddr === '127.0.0.1' || remoteAddr === '::1' || remoteAddr === '::ffff:127.0.0.1';
|
|
26
|
+
if (proxyApiKey && clientKey !== proxyApiKey && !isLocal) {
|
|
25
27
|
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
26
28
|
res.end(JSON.stringify({
|
|
27
29
|
type: 'error',
|
|
@@ -101,6 +103,7 @@ async function forwardRequest(req, res, body, accountManager, upstream, retryCou
|
|
|
101
103
|
const account = accountManager.getActiveAccount();
|
|
102
104
|
if (!account) {
|
|
103
105
|
ctx.status = 429;
|
|
106
|
+
ctx.account = '(none available)';
|
|
104
107
|
const status = accountManager.getStatus();
|
|
105
108
|
const retryAfter = computeRetryAfter(status.accounts);
|
|
106
109
|
res.writeHead(429, {
|
|
@@ -185,19 +188,6 @@ async function forwardRequest(req, res, body, accountManager, upstream, retryCou
|
|
|
185
188
|
logSections.push(`=== RESPONSE ${upstreamRes.status} ===\n${formatHeaders(upstreamRes.headers)}`);
|
|
186
189
|
}
|
|
187
190
|
|
|
188
|
-
// Handle 429 — retry with next account
|
|
189
|
-
if (upstreamRes.status === 429 && retryCount < maxRetries) {
|
|
190
|
-
const retryAfter = parseInt(upstreamRes.headers.get('retry-after') || '60', 10);
|
|
191
|
-
accountManager.markRateLimited(account.index, retryAfter);
|
|
192
|
-
const drainBuf = await upstreamRes.arrayBuffer();
|
|
193
|
-
if (logDir) {
|
|
194
|
-
logSections.push(`=== RESPONSE BODY (429) ===\n${Buffer.from(drainBuf).toString()}`);
|
|
195
|
-
logSections.push(`=== RETRYING with next account ===`);
|
|
196
|
-
writeRequestLog(logDir, reqId, logSections);
|
|
197
|
-
}
|
|
198
|
-
return forwardRequest(req, res, body, accountManager, upstream, retryCount + 1, hooks, reqId, ctx, logDir);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
191
|
ctx.status = upstreamRes.status;
|
|
202
192
|
|
|
203
193
|
// Build response headers (skip hop-by-hop and encoding headers)
|