mirror of https://github.com/garrytan/gstack.git
fix(model-benchmark): recognize macOS Keychain auth in the claude adapter (#1890)
The default macOS Claude Code install stores OAuth under the Keychain generic-password service "Claude Code-credentials" and never writes ~/.claude/.credentials.json, so available()'s file-or-env sniff reported "No Claude auth found" while claude -p worked fine. On darwin the sniff now also probes the Keychain entry — metadata only (no -w, the secret is never read), 5s timeout, any security(1) failure degrades to not-found. Verified live on this machine (subscription install, no creds file, Keychain entry present). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
4d15254229
commit
cd5433add1
|
|
@ -1,6 +1,6 @@
|
||||||
import type { ProviderAdapter, RunOpts, RunResult, AvailabilityCheck } from './types';
|
import type { ProviderAdapter, RunOpts, RunResult, AvailabilityCheck } from './types';
|
||||||
import { estimateCostUsd } from '../pricing';
|
import { estimateCostUsd } from '../pricing';
|
||||||
import { execFileSync } from 'child_process';
|
import { execFileSync, spawnSync } from 'child_process';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
|
|
@ -25,11 +25,30 @@ export class ClaudeAdapter implements ProviderAdapter {
|
||||||
if (!resolved) {
|
if (!resolved) {
|
||||||
return { ok: false, reason: 'claude CLI not found on PATH. Install from https://claude.ai/download or npm i -g @anthropic-ai/claude-code (or set GSTACK_CLAUDE_BIN)' };
|
return { ok: false, reason: 'claude CLI not found on PATH. Install from https://claude.ai/download or npm i -g @anthropic-ai/claude-code (or set GSTACK_CLAUDE_BIN)' };
|
||||||
}
|
}
|
||||||
// Auth sniff: ~/.claude/.credentials.json OR ANTHROPIC_API_KEY
|
// Auth sniff: ~/.claude/.credentials.json OR ANTHROPIC_API_KEY OR (macOS)
|
||||||
|
// the Keychain entry subscription installs use instead of the creds file.
|
||||||
|
// #1890: the default macOS install stores OAuth under the generic-password
|
||||||
|
// service "Claude Code-credentials" and never writes .credentials.json,
|
||||||
|
// so the file-or-env sniff reported "No Claude auth found" while
|
||||||
|
// `claude -p` worked fine. Metadata probe only (no -w — never reads the
|
||||||
|
// secret), and any failure of `security` itself falls through to the
|
||||||
|
// not-found reason rather than throwing.
|
||||||
const credsPath = path.join(os.homedir(), '.claude', '.credentials.json');
|
const credsPath = path.join(os.homedir(), '.claude', '.credentials.json');
|
||||||
const hasCreds = fs.existsSync(credsPath);
|
const hasCreds = fs.existsSync(credsPath);
|
||||||
const hasKey = !!process.env.ANTHROPIC_API_KEY;
|
const hasKey = !!process.env.ANTHROPIC_API_KEY;
|
||||||
if (!hasCreds && !hasKey) {
|
let hasKeychain = false;
|
||||||
|
if (!hasCreds && !hasKey && process.platform === 'darwin') {
|
||||||
|
try {
|
||||||
|
const probe = spawnSync('security', ['find-generic-password', '-s', 'Claude Code-credentials'], {
|
||||||
|
stdio: 'ignore',
|
||||||
|
timeout: 5000,
|
||||||
|
});
|
||||||
|
hasKeychain = probe.status === 0;
|
||||||
|
} catch {
|
||||||
|
hasKeychain = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasCreds && !hasKey && !hasKeychain) {
|
||||||
return { ok: false, reason: 'No Claude auth found. Log in via `claude` interactive session, or export ANTHROPIC_API_KEY.' };
|
return { ok: false, reason: 'No Claude auth found. Log in via `claude` interactive session, or export ANTHROPIC_API_KEY.' };
|
||||||
}
|
}
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue