Skip to content

Commit f6c6ea2

Browse files
authored
List Anthropic models via dedicated handler (#1732)
1 parent 3594d3d commit f6c6ea2

File tree

4 files changed

+71
-43
lines changed

4 files changed

+71
-43
lines changed

apps/desktop/src/components/settings/ai/llm/select.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,12 @@ import { useAuth } from "../../../../auth";
1414
import { useBillingAccess } from "../../../../billing";
1515
import { useConfigValues } from "../../../../config/use-config";
1616
import * as main from "../../../../store/tinybase/main";
17+
import { listAnthropicModels } from "../shared/list-anthropic";
1718
import type { ListModelsResult } from "../shared/list-common";
1819
import { listGoogleModels } from "../shared/list-google";
1920
import { listLMStudioModels } from "../shared/list-lmstudio";
2021
import { listOllamaModels } from "../shared/list-ollama";
21-
import {
22-
listAnthropicModels,
23-
listGenericModels,
24-
listOpenAIModels,
25-
} from "../shared/list-openai";
22+
import { listGenericModels, listOpenAIModels } from "../shared/list-openai";
2623
import { listOpenRouterModels } from "../shared/list-openrouter";
2724
import { ModelCombobox } from "../shared/model-combobox";
2825
import { HealthCheckForConnection } from "./health";
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Effect, pipe, Schema } from "effect";
2+
3+
import {
4+
DEFAULT_RESULT,
5+
fetchJson,
6+
type ListModelsResult,
7+
type ModelIgnoreReason,
8+
partition,
9+
REQUEST_TIMEOUT,
10+
shouldIgnoreCommonKeywords,
11+
} from "./list-common";
12+
13+
const AnthropicModelSchema = Schema.Struct({
14+
data: Schema.Array(
15+
Schema.Struct({
16+
type: Schema.String,
17+
id: Schema.String,
18+
display_name: Schema.String,
19+
created_at: Schema.String,
20+
}),
21+
),
22+
has_more: Schema.Boolean,
23+
first_id: Schema.String,
24+
last_id: Schema.String,
25+
});
26+
27+
export async function listAnthropicModels(
28+
baseUrl: string,
29+
apiKey: string,
30+
): Promise<ListModelsResult> {
31+
if (!baseUrl) {
32+
return DEFAULT_RESULT;
33+
}
34+
35+
return pipe(
36+
fetchJson(`${baseUrl}/models`, {
37+
"x-api-key": apiKey,
38+
"anthropic-version": "2023-06-01",
39+
"anthropic-dangerous-direct-browser-access": "true",
40+
}),
41+
Effect.andThen((json) => Schema.decodeUnknown(AnthropicModelSchema)(json)),
42+
Effect.map(({ data }) =>
43+
partition(
44+
data,
45+
(model) => {
46+
const reasons: ModelIgnoreReason[] = [];
47+
if (shouldIgnoreCommonKeywords(model.id)) {
48+
reasons.push("common_keyword");
49+
}
50+
return reasons.length > 0 ? reasons : null;
51+
},
52+
(model) => model.id,
53+
),
54+
),
55+
Effect.timeout(REQUEST_TIMEOUT),
56+
Effect.catchAll(() => Effect.succeed(DEFAULT_RESULT)),
57+
Effect.runPromise,
58+
);
59+
}

apps/desktop/src/components/settings/ai/shared/list-common.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { fetch as tauriFetch } from "@tauri-apps/plugin-http";
12
import { Effect } from "effect";
23

34
export type ModelIgnoreReason =
@@ -32,14 +33,15 @@ export const commonIgnoreKeywords = [
3233

3334
export const fetchJson = (url: string, headers: Record<string, string>) =>
3435
Effect.tryPromise({
35-
try: () =>
36-
fetch(url, { headers }).then((r) => {
37-
if (!r.ok) {
38-
throw new Error(`HTTP ${r.status}`);
39-
}
40-
return r.json();
41-
}),
42-
catch: () => new Error("Fetch failed"),
36+
try: async () => {
37+
const r = await tauriFetch(url, { method: "GET", headers });
38+
if (!r.ok) {
39+
const errorBody = await r.text();
40+
throw new Error(`HTTP ${r.status}: ${errorBody}`);
41+
}
42+
return r.json();
43+
},
44+
catch: (e) => e,
4345
});
4446

4547
export const shouldIgnoreCommonKeywords = (id: string): boolean => {

apps/desktop/src/components/settings/ai/shared/list-openai.ts

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -48,36 +48,6 @@ export async function listOpenAIModels(
4848
);
4949
}
5050

51-
export async function listAnthropicModels(
52-
baseUrl: string,
53-
apiKey: string,
54-
): Promise<ListModelsResult> {
55-
if (!baseUrl) {
56-
return DEFAULT_RESULT;
57-
}
58-
59-
return pipe(
60-
fetchJson(`${baseUrl}/models`, { Authorization: `Bearer ${apiKey}` }),
61-
Effect.andThen((json) => Schema.decodeUnknown(OpenAIModelSchema)(json)),
62-
Effect.map(({ data }) =>
63-
partition(
64-
data,
65-
(model) => {
66-
const reasons: ModelIgnoreReason[] = [];
67-
if (shouldIgnoreCommonKeywords(model.id)) {
68-
reasons.push("common_keyword");
69-
}
70-
return reasons.length > 0 ? reasons : null;
71-
},
72-
(model) => model.id,
73-
),
74-
),
75-
Effect.timeout(REQUEST_TIMEOUT),
76-
Effect.catchAll(() => Effect.succeed(DEFAULT_RESULT)),
77-
Effect.runPromise,
78-
);
79-
}
80-
8151
export async function listGenericModels(
8252
baseUrl: string,
8353
apiKey: string,

0 commit comments

Comments
 (0)