mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-28 12:12:47 +00:00
fix(claude): preserve catalog on version probe failure
This commit is contained in:
@@ -445,6 +445,29 @@ describe("ClaudeAgentClient.fetchCatalog", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("preserves the catalog when Claude Code version detection fails", async () => {
|
||||
const emptyConfigDir = await fs.mkdtemp(path.join(os.tmpdir(), "paseo-claude-models-empty-"));
|
||||
try {
|
||||
const client = new ClaudeAgentClient({
|
||||
logger,
|
||||
resolveVersion: async () => {
|
||||
throw new Error("unrecognized version output");
|
||||
},
|
||||
configDir: emptyConfigDir,
|
||||
});
|
||||
const { models } = await client.fetchCatalog({
|
||||
scope: "workspace",
|
||||
cwd: "/tmp/claude-models",
|
||||
force: false,
|
||||
});
|
||||
|
||||
expect(models.find((model) => model.isDefault)?.id).toBe("claude-opus-5[1m]");
|
||||
expect(models.map((model) => model.id)).toContain("claude-fable-5[1m]");
|
||||
} finally {
|
||||
await fs.rm(emptyConfigDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("exposes Ultra Code on xhigh-capable Claude models", async () => {
|
||||
const emptyConfigDir = await fs.mkdtemp(path.join(os.tmpdir(), "paseo-claude-models-empty-"));
|
||||
try {
|
||||
|
||||
@@ -364,7 +364,7 @@ interface ClaudeAgentClientOptions {
|
||||
runtimeSettings?: ProviderRuntimeSettings;
|
||||
queryFactory?: ClaudeQueryFactory;
|
||||
resolveBinary?: () => Promise<string>;
|
||||
resolveVersion?: () => Promise<string | null>;
|
||||
resolveVersion?: () => Promise<string>;
|
||||
configDir?: string;
|
||||
}
|
||||
|
||||
@@ -1441,7 +1441,7 @@ export class ClaudeAgentClient implements AgentClient {
|
||||
private readonly runtimeSettings?: ProviderRuntimeSettings;
|
||||
private readonly queryFactory?: ClaudeQueryFactory;
|
||||
private readonly resolveBinary: () => Promise<string>;
|
||||
private readonly resolveVersion: () => Promise<string | null>;
|
||||
private readonly resolveVersion: () => Promise<string>;
|
||||
private readonly configDir?: string;
|
||||
|
||||
constructor(options: ClaudeAgentClientOptions) {
|
||||
@@ -1503,7 +1503,7 @@ export class ClaudeAgentClient implements AgentClient {
|
||||
|
||||
async fetchCatalog(_options: FetchCatalogOptions): Promise<ProviderCatalog> {
|
||||
// Claude exposes a global catalog here; cwd/force are intentionally irrelevant.
|
||||
let claudeCodeVersion: string | null = null;
|
||||
let claudeCodeVersion: string | undefined;
|
||||
try {
|
||||
claudeCodeVersion = await this.resolveVersion();
|
||||
} catch (error) {
|
||||
@@ -1637,14 +1637,14 @@ async function resolveClaudeBinary(runtimeSettings?: ProviderRuntimeSettings): P
|
||||
|
||||
export async function resolveClaudeCodeVersion(
|
||||
runtimeSettings?: ProviderRuntimeSettings,
|
||||
): Promise<string | null> {
|
||||
): Promise<string> {
|
||||
const launch = await resolveProviderLaunch({
|
||||
commandConfig: runtimeSettings?.command,
|
||||
defaultBinary: "claude",
|
||||
});
|
||||
const availability = await checkProviderLaunchAvailable(launch);
|
||||
if (!availability.available) {
|
||||
return null;
|
||||
throw new Error("Claude binary not found while resolving Claude Code version");
|
||||
}
|
||||
const executable = availability.resolvedPath ?? launch.command;
|
||||
const { stdout, stderr } = await execCommand(executable, [...launch.args, "--version"], {
|
||||
@@ -1652,7 +1652,10 @@ export async function resolveClaudeCodeVersion(
|
||||
timeout: 5_000,
|
||||
});
|
||||
const version = parseClaudeCodeVersion(`${stdout}\n${stderr}`);
|
||||
return version?.join(".") ?? null;
|
||||
if (!version) {
|
||||
throw new Error("Unable to parse Claude Code version from --version output");
|
||||
}
|
||||
return version.join(".");
|
||||
}
|
||||
|
||||
async function resolveClaudeAuth(
|
||||
|
||||
@@ -184,7 +184,7 @@ function buildThinkingOptions(
|
||||
return options;
|
||||
}
|
||||
|
||||
export function getClaudeManifestModels(claudeCodeVersion?: string | null): AgentModelDefinition[] {
|
||||
export function getClaudeManifestModels(claudeCodeVersion?: string): AgentModelDefinition[] {
|
||||
const availableModels: readonly ClaudeModelManifestEntry[] = CLAUDE_MODEL_MANIFEST.filter(
|
||||
(model) => isModelAvailableInClaudeCode(model, claudeCodeVersion),
|
||||
);
|
||||
@@ -221,14 +221,11 @@ export function getClaudeManifestModels(claudeCodeVersion?: string | null): Agen
|
||||
|
||||
function isModelAvailableInClaudeCode(
|
||||
model: ClaudeModelManifestEntry,
|
||||
claudeCodeVersion: string | null | undefined,
|
||||
claudeCodeVersion: string | undefined,
|
||||
): boolean {
|
||||
if (!model.minimumClaudeCodeVersion || claudeCodeVersion === undefined) {
|
||||
return true;
|
||||
}
|
||||
if (claudeCodeVersion === null) {
|
||||
return false;
|
||||
}
|
||||
return compareVersions(claudeCodeVersion, model.minimumClaudeCodeVersion) >= 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ const CLAUDE_SETTINGS_MODEL_ENV_KEYS = [
|
||||
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
|
||||
] as const;
|
||||
|
||||
export function getClaudeModels(claudeCodeVersion?: string | null): AgentModelDefinition[] {
|
||||
export function getClaudeModels(claudeCodeVersion?: string): AgentModelDefinition[] {
|
||||
return getClaudeManifestModels(claudeCodeVersion);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ export function findClaudeModel(
|
||||
export async function getClaudeModelsWithSettings(
|
||||
logger: Logger,
|
||||
configDir?: string,
|
||||
claudeCodeVersion?: string | null,
|
||||
claudeCodeVersion?: string,
|
||||
): Promise<AgentModelDefinition[]> {
|
||||
const hardcodedModels = getClaudeModels(claudeCodeVersion);
|
||||
const settingsModels = await readClaudeSettingsModels(logger, configDir);
|
||||
|
||||
Reference in New Issue
Block a user