Files
Genarrative/apps/ai-game-creator-shell/src/services/llmModelCatalog.ts
T
kdletters fb130d1847
Project CI / AI game creator shell Rust lane 1/2 (push) Failing after 57s
Project CI / AI game creator shell Rust lane 2/2 (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled
新增 AGC 模型 Agent 模式与 Claude Agent SDK sidecar
后台模型目录增加 codex/cc 执行模式绑定,旧目录缺省兼容 Codex

AGC 客户端按模型绑定路由 Codex app-server 或 Claude Agent SDK sidecar

随包携带 Node runtime、Claude Agent SDK 与匹配平台 Claude runtime

补充模型配置、客户端选择、运行时适配、MCP 取消和定向测试

同步 AGC 模型配置规范、里程碑计划与共享决策记录
2026-09-30 14:07:25 +08:00

94 lines
2.8 KiB
TypeScript

import { resolveTauriInvoke } from '../app/tauri';
import type { GameCreatorAppConfigView } from '../app/types';
import { type ClientLlmModelCatalog, loadClientLlmModels } from './clientApi';
export type { ClientLlmModel, ClientLlmModelCatalog } from './clientApi';
let cached: ClientLlmModelCatalog | null = null;
let inFlight: Promise<ClientLlmModelCatalog> | null = null;
let source = '';
let generation = 0;
let localRevision = 0;
export const LLM_CONFIG_CHANGED_EVENT = 'agc-llm-config-changed';
export class LlmModelCatalogConfigError extends Error {}
export function notifyLlmConfigChanged() {
generation += 1;
cached = null;
inFlight = null;
source = '';
window.dispatchEvent(new Event(LLM_CONFIG_CHANGED_EVENT));
}
async function loadEffectiveCatalog(epoch: number) {
const invoke = resolveTauriInvoke();
if (!invoke) {
throw new LlmModelCatalogConfigError('本地模型服务不可用');
}
let config: GameCreatorAppConfigView | undefined;
try {
config = await invoke<GameCreatorAppConfigView>(
'read_game_creator_app_config',
);
} catch (error) {
if (epoch === generation) cached = null;
throw new LlmModelCatalogConfigError('读取客户端配置失败');
}
if (epoch !== generation) throw new Error('模型配置已更新');
const llm = config?.config.llm;
const nextSource = llm?.customEnabled
? JSON.stringify(['custom', llm.baseUrl, llm.visibleModels ?? []])
: 'official';
if (source !== nextSource) {
source = nextSource;
cached = null;
}
if (llm?.customEnabled) {
if (cached) return cached;
const ids = llm.visibleModels ?? [];
return {
defaultModelId: ids[0] ?? '',
models: ids.map((id) => ({
id,
displayName: id,
agentMode: 'codex' as const,
})),
revision: --localRevision,
};
}
// 官方模型目录的凭据、请求和响应解析归 Rust;渲染层只接收目录快照。
return loadClientLlmModels();
}
/** 最近一次成功读取的模型目录,用于首屏渲染与刷新失败时兜底。 */
export function cachedLlmModelCatalog() {
return cached;
}
/**
* 读取模型目录;同一时刻只保留一个在途请求,重复触发复用同一结果。
* 读取失败时保留上一次成功目录,不覆盖调用方已生效的选择。
*/
export function refreshLlmModelCatalog() {
if (inFlight) return inFlight;
const epoch = generation;
const request = loadEffectiveCatalog(epoch)
.then((catalog) => {
if (epoch !== generation) throw new Error('模型配置已更新');
cached = catalog;
return catalog;
})
.finally(() => {
if (inFlight === request) inFlight = null;
});
inFlight = request;
return request;
}
export function resetLlmModelCatalogCacheForTest() {
generation += 1;
source = '';
cached = null;
inFlight = null;
}