mirror of
https://github.com/musistudio/claude-code-router.git
synced 2026-07-09 17:18:24 +00:00
Merge branch 'main' into fix/claude-defautl-model-legacty
This commit is contained in:
commit
fcd386c80c
2 changed files with 48 additions and 3 deletions
|
|
@ -1,3 +1,4 @@
|
|||
import { execFileSync } from "node:child_process";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import type {
|
||||
|
|
@ -9,6 +10,7 @@ import type {
|
|||
import {
|
||||
bearerAuthPlugin,
|
||||
findOauthTokenSet,
|
||||
isRecord,
|
||||
missingCandidate,
|
||||
providerInternalNamePlaceholder,
|
||||
providerPayload,
|
||||
|
|
@ -19,6 +21,7 @@ import {
|
|||
} from "@ccr/core/agents/local-providers/shared";
|
||||
|
||||
const claudeDefaultModels = ["claude-sonnet-5"];
|
||||
const claudeCodeKeychainService = "Claude Code-credentials";
|
||||
|
||||
const percentLimitMapping = (id: string, label: string, path: string, window: string) => ({
|
||||
id,
|
||||
|
|
@ -148,6 +151,19 @@ function readClaudeCodeOauth(): OAuthTokenSet | undefined {
|
|||
sourceFile
|
||||
};
|
||||
}
|
||||
|
||||
const keychainRecord = readClaudeCodeKeychainRecord();
|
||||
if (keychainRecord) {
|
||||
const credential = findOauthTokenSet(keychainRecord);
|
||||
if (credential) {
|
||||
return {
|
||||
accessToken: credential.accessToken,
|
||||
refreshToken: credential.refreshToken,
|
||||
sourceFile: `keychain:${claudeCodeKeychainService}`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
|
@ -158,3 +174,24 @@ function claudeCredentialFiles(): string[] {
|
|||
path.join(os.homedir(), ".config", "claude", "credentials.json")
|
||||
]);
|
||||
}
|
||||
|
||||
// Newer macOS builds of the Claude Code CLI store credentials in the
|
||||
// Keychain instead of ~/.claude/.credentials.json. Reading it triggers the
|
||||
// standard macOS keychain access prompt (Allow / Always Allow); the user
|
||||
// declining or the item not existing both surface as a non-zero exit here.
|
||||
function readClaudeCodeKeychainRecord(): Record<string, unknown> | undefined {
|
||||
if (process.platform !== "darwin") {
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
const output = execFileSync(
|
||||
"security",
|
||||
["find-generic-password", "-s", claudeCodeKeychainService, "-w"],
|
||||
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }
|
||||
);
|
||||
const parsed = JSON.parse(output.trim()) as unknown;
|
||||
return isRecord(parsed) ? parsed : undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,12 +60,17 @@ const localAgentProviderApiKey = "ccr-local-agent-login";
|
|||
function materializeProviderPluginTemplates(
|
||||
templates: unknown[],
|
||||
providerName: string,
|
||||
protocol: GatewayProviderConfig["type"]
|
||||
protocol: GatewayProviderConfig["type"],
|
||||
providerId: string
|
||||
): unknown[] {
|
||||
if (templates.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const internalName = protocol ? `${providerName}::${protocol}` : providerName;
|
||||
// The core gateway matches provider plugins against the provider's runtime
|
||||
// identifier (provider.id, or its slug), not the human-readable display name
|
||||
// — the internal name here must mirror providerCapabilityInternalName() in
|
||||
// gateway/service.ts or the plugin's auth-header override silently never applies.
|
||||
const internalName = protocol ? `${providerId}::${protocol}` : providerId;
|
||||
const replacements: Record<string, string> = {
|
||||
[providerInternalNamePlaceholder]: internalName,
|
||||
[providerNamePlaceholder]: providerName,
|
||||
|
|
@ -1431,6 +1436,8 @@ function App() {
|
|||
return false;
|
||||
}
|
||||
|
||||
const existingProvider = providerEditIndex !== undefined ? draftConfig.Providers[providerEditIndex] : undefined;
|
||||
const providerId = existingProvider?.id ?? providerNameSlug(providerName);
|
||||
const provider: GatewayProviderConfig = {
|
||||
api_base_url: normalizeProviderBaseUrl(baseUrl, protocol),
|
||||
api_key: providerDraft.apiKey.trim(),
|
||||
|
|
@ -1438,13 +1445,14 @@ function App() {
|
|||
account: accountConfig,
|
||||
credentials: credentials.length > 0 ? credentials : undefined,
|
||||
icon: providerDraft.icon.trim() || undefined,
|
||||
id: providerId,
|
||||
modelDescriptions,
|
||||
modelDisplayNames,
|
||||
models,
|
||||
name: providerName,
|
||||
type: protocol
|
||||
};
|
||||
const importedProviderPlugins = materializeProviderPluginTemplates(providerDraft.providerPlugins, providerName, protocol);
|
||||
const importedProviderPlugins = materializeProviderPluginTemplates(providerDraft.providerPlugins, providerName, protocol, providerId);
|
||||
const wasImport = providerImportOpen;
|
||||
|
||||
const next = buildConfigUpdate((config) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue