|
@@ -8,6 +8,8 @@
|
|
|
*/
|
|
*/
|
|
|
import { defineStore } from 'pinia';
|
|
import { defineStore } from 'pinia';
|
|
|
import { useUserStore } from '@/core/store/modules/case';
|
|
import { useUserStore } from '@/core/store/modules/case';
|
|
|
|
|
+import * as modelApi from '@/ai/api/modelApi';
|
|
|
|
|
+import type { AiModel, ModelProvider } from '@/ai/api/types';
|
|
|
import * as codexApi from '../api/codexApi';
|
|
import * as codexApi from '../api/codexApi';
|
|
|
import * as codexArtifactApi from '../api/codexArtifactApi';
|
|
import * as codexArtifactApi from '../api/codexArtifactApi';
|
|
|
import type {
|
|
import type {
|
|
@@ -189,7 +191,10 @@ export const useCodexChatStore = defineStore('codex-chat', {
|
|
|
runtime: null as codexApi.CodexStatus | null,
|
|
runtime: null as codexApi.CodexStatus | null,
|
|
|
/** 运行时探测/启动失败原因 */
|
|
/** 运行时探测/启动失败原因 */
|
|
|
runtimeError: '',
|
|
runtimeError: '',
|
|
|
- models: [] as codexApi.CodexModelOption[],
|
|
|
|
|
|
|
+ /** 对话模型列表(来自后端「模型管理」,过滤 llm;未登录后端时为空) */
|
|
|
|
|
+ models: [] as AiModel[],
|
|
|
|
|
+ /** 模型厂商列表(applySessionModel 查 providerType 用) */
|
|
|
|
|
+ providers: [] as ModelProvider[],
|
|
|
/** 会话列表(localStorage 自持) */
|
|
/** 会话列表(localStorage 自持) */
|
|
|
sessions: [] as CodexSessionMeta[],
|
|
sessions: [] as CodexSessionMeta[],
|
|
|
activeThreadId: '',
|
|
activeThreadId: '',
|
|
@@ -370,12 +375,14 @@ export const useCodexChatStore = defineStore('codex-chat', {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ /** 模型列表来自后端「模型管理」(HTTP+登录态),与 Codex 运行时无关;失败静默降级为空 */
|
|
|
async loadModels() {
|
|
async loadModels() {
|
|
|
- try {
|
|
|
|
|
- this.models = (await codexApi.codexListModels()) || [];
|
|
|
|
|
- } catch {
|
|
|
|
|
- this.models = [];
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const [models, providers] = await Promise.all([
|
|
|
|
|
+ modelApi.listModels().catch(() => [] as AiModel[]),
|
|
|
|
|
+ modelApi.listProviders().catch(() => [] as ModelProvider[]),
|
|
|
|
|
+ ]);
|
|
|
|
|
+ this.models = (models || []).filter((item) => !item.type || item.type === 'llm');
|
|
|
|
|
+ this.providers = providers || [];
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
async loadDefaultCwd() {
|
|
async loadDefaultCwd() {
|
|
@@ -475,6 +482,30 @@ export const useCodexChatStore = defineStore('codex-chat', {
|
|
|
this.persistSessions();
|
|
this.persistSessions();
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 选中即应用:把后端「模型管理」里的一条记录应用到 Codex 运行时
|
|
|
|
|
+ * (provider 是全局单例,会重启子进程),成功后记到当前会话。
|
|
|
|
|
+ * 失败原样抛错——页面负责提示,选择器显示值由会话模型反查驱动、天然回退。
|
|
|
|
|
+ */
|
|
|
|
|
+ async applySessionModel(recordId: string) {
|
|
|
|
|
+ const record = this.models.find((item) => item.id === recordId);
|
|
|
|
|
+ if (!record) throw new Error('模型记录不存在或已被删除,请刷新模型列表');
|
|
|
|
|
+ const providerType = this.providers.find((item) => item.name === record.provider)?.type ?? null;
|
|
|
|
|
+ const result = await codexApi.codexApplyProvider({
|
|
|
|
|
+ modelId: record.modelId || '',
|
|
|
|
|
+ name: record.name || null,
|
|
|
|
|
+ baseUrl: record.baseUrl || null,
|
|
|
|
|
+ apiKey: record.apiKey || null,
|
|
|
|
|
+ headersJson: record.headersJson || null,
|
|
|
|
|
+ config: record.config || null,
|
|
|
|
|
+ providerType,
|
|
|
|
|
+ modelRecordId: record.id,
|
|
|
|
|
+ });
|
|
|
|
|
+ // 应用会重启运行时,状态回写保持 ready 判定新鲜
|
|
|
|
|
+ this.runtime = result.status;
|
|
|
|
|
+ if (this.activeThreadId) this.setSessionModel(this.activeThreadId, record.modelId || null);
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
async startRuntime() {
|
|
async startRuntime() {
|
|
|
try {
|
|
try {
|
|
|
this.runtime = await codexApi.codexStart();
|
|
this.runtime = await codexApi.codexStart();
|