forked from nexu-io/open-design
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmmd-routes.ts
More file actions
166 lines (140 loc) · 4.42 KB
/
Copy pathmmd-routes.ts
File metadata and controls
166 lines (140 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import { readFile } from 'node:fs/promises';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { DEFAULT_MODEL_OPTION, sanitizeCustomModel } from './models.js';
import type { RuntimeEnv, RuntimeModelOption } from './types.js';
const DEFAULT_MMD_MODEL_ROUTES_FILE = join('.config', 'mms', 'model-routes.json');
const MMD_MODEL_ROUTES_FILE_ENV = 'MMD_MODEL_ROUTES_FILE';
export type MmdRouteLaunchEnv = {
ANTHROPIC_BASE_URL: string;
ANTHROPIC_AUTH_TOKEN?: string;
};
function stringEnv(env: RuntimeEnv, key: string): string | null {
const value = env[key];
if (typeof value !== 'string') return null;
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
}
function resolveHome(env: RuntimeEnv): string | null {
return stringEnv(env, 'HOME') ?? homedir() ?? null;
}
function expandRoutesFileOverride(raw: string, env: RuntimeEnv): string | null {
if (raw === '~') return resolveHome(env);
if (raw.startsWith('~/') || raw.startsWith('~\\')) {
const home = resolveHome(env);
return home ? join(home, raw.slice(2)) : null;
}
return raw;
}
export function resolveMmdRoutesFile(env: RuntimeEnv): string | null {
const override = stringEnv(env, MMD_MODEL_ROUTES_FILE_ENV);
if (override) return expandRoutesFileOverride(override, env);
const home = resolveHome(env);
if (!home) return null;
return join(home, DEFAULT_MMD_MODEL_ROUTES_FILE);
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
export function parseMmdRouteModelIds(raw: unknown): string[] {
if (!isRecord(raw) || !isRecord(raw.routes)) return [];
const seen = new Set<string>();
const ids: string[] = [];
for (const rawId of Object.keys(raw.routes)) {
const id = sanitizeCustomModel(rawId);
if (!id || seen.has(id)) continue;
seen.add(id);
ids.push(id);
}
return ids;
}
export function resolveMmdRouteLaunchEnv(
raw: unknown,
modelId: string | null | undefined,
): MmdRouteLaunchEnv | null {
const id = sanitizeCustomModel(modelId);
if (!id || !isRecord(raw) || !isRecord(raw.routes)) return null;
const route = raw.routes[id];
if (!isRecord(route) || !isRecord(route.primary)) return null;
const baseUrl = typeof route.primary.anthropic_base_url === 'string'
? route.primary.anthropic_base_url.trim()
: '';
if (!baseUrl) return null;
const apiKey = typeof route.primary.api_key === 'string'
? route.primary.api_key.trim()
: '';
return {
ANTHROPIC_BASE_URL: baseUrl,
...(apiKey ? { ANTHROPIC_AUTH_TOKEN: apiKey } : {}),
};
}
function addModel(
out: RuntimeModelOption[],
seen: Set<string>,
option: RuntimeModelOption,
): void {
const id = sanitizeCustomModel(option.id);
if (!id || seen.has(id)) return;
seen.add(id);
const label = typeof option.label === 'string' && option.label.trim().length > 0
? option.label
: id;
out.push({ id, label });
}
export function mergeMmdRouteModels(
routeIds: readonly string[],
fallbackModels: readonly RuntimeModelOption[],
): RuntimeModelOption[] {
const out: RuntimeModelOption[] = [];
const seen = new Set<string>();
addModel(out, seen, DEFAULT_MODEL_OPTION);
for (const routeId of routeIds) {
addModel(out, seen, { id: routeId, label: routeId });
}
for (const model of fallbackModels) {
addModel(out, seen, model);
}
return out;
}
export async function loadMmdRouteModels(
env: RuntimeEnv,
fallbackModels: readonly RuntimeModelOption[],
): Promise<RuntimeModelOption[] | null> {
const routesFile = resolveMmdRoutesFile(env);
if (!routesFile) return null;
let text: string;
try {
text = await readFile(routesFile, 'utf8');
} catch {
return null;
}
let parsed: unknown;
try {
parsed = JSON.parse(text);
} catch {
return null;
}
const routeIds = parseMmdRouteModelIds(parsed);
if (routeIds.length === 0) return null;
return mergeMmdRouteModels(routeIds, fallbackModels);
}
export async function loadMmdRouteLaunchEnv(
env: RuntimeEnv,
modelId: string | null | undefined,
): Promise<MmdRouteLaunchEnv | null> {
const routesFile = resolveMmdRoutesFile(env);
if (!routesFile) return null;
let text: string;
try {
text = await readFile(routesFile, 'utf8');
} catch {
return null;
}
let parsed: unknown;
try {
parsed = JSON.parse(text);
} catch {
return null;
}
return resolveMmdRouteLaunchEnv(parsed, modelId);
}