diff --git a/app/pages/admin/global-config/index.vue b/app/pages/admin/global-config/index.vue
index 3a1218e..bd71646 100644
--- a/app/pages/admin/global-config/index.vue
+++ b/app/pages/admin/global-config/index.vue
@@ -17,9 +17,6 @@ const configMeta: ConfigMeta[] = [
{ key: 'siteName', label: '站点名称', description: '网站标题,显示在浏览器标签和页面上', type: 'string', group: '基本设置' },
{ key: 'siteIcon', label: '站点图标', description: 'favicon 图标,支持上传或填写 URL。推荐 32×32 PNG / 16×16 ICO', type: 'string', group: '基本设置' },
{ key: 'allowRegister', label: '允许注册', description: '是否开放新用户注册功能', type: 'boolean', group: '基本设置' },
- { key: 'agentSystemPrompt', label: 'Agent 系统提示词', description: 'Agent 对话的默认系统提示词,引导模型行为', type: 'string', group: 'Agent 设置' },
- { key: 'agentDefaultModelId', label: 'Agent 未登录默认模型 ID', description: '未登录用户(临时会话)使用的默认 LLM 模型 ID(数字,如 2)。留 0 则不设置', type: 'number', group: 'Agent 设置' },
- { key: 'agentTitleModelId', label: 'Agent 标题生成模型 ID', description: '用于自动生成对话标题的 LLM 模型 ID(数字,如 2)。留 0 则不自动生成标题', type: 'number', group: 'Agent 设置' },
]
const form = reactive>(
diff --git a/app/pages/chat/[agentSlug]/index.vue b/app/pages/chat/[agentSlug]/index.vue
index 90ad273..4006c62 100644
--- a/app/pages/chat/[agentSlug]/index.vue
+++ b/app/pages/chat/[agentSlug]/index.vue
@@ -28,7 +28,7 @@ const isCustomPrompt = computed(() =>
!!(sessions.currentSession.value?.systemPrompt?.trim()),
);
const preferredModelId = ref(null);
-const guestDefaultModelId = ref(null);
+const globalDefaultModelId = ref(null);
interface ModelOption {
id: number;
@@ -65,9 +65,9 @@ watch(
currentModelId.value = null;
} else if (mid === null) {
const fallbackSource = auth.loggedIn.value
- ? (preferredModelId.value && modelList.some((m) => m.id === preferredModelId.value) ? preferredModelId.value : null)
- : (guestDefaultModelId.value && modelList.some((m) => m.id === guestDefaultModelId.value) ? guestDefaultModelId.value : null);
- const fallback = fallbackSource ?? modelList[0].id;
+ ? (preferredModelId.value && modelList.some((m) => m.id === preferredModelId.value) ? preferredModelId.value : (globalDefaultModelId.value && modelList.some((m) => m.id === globalDefaultModelId.value) ? globalDefaultModelId.value : null))
+ : (globalDefaultModelId.value && modelList.some((m) => m.id === globalDefaultModelId.value) ? globalDefaultModelId.value : null);
+ const fallback = fallbackSource ?? modelList[0]?.id ?? null;
currentModelId.value = fallback;
}
},
@@ -127,9 +127,7 @@ async function loadModels() {
providerName: m.providerName ?? "—",
supportsTools: m.supportsTools ?? 1,
}));
- if (isGuest) {
- guestDefaultModelId.value = res.data?.defaultModelId ?? null;
- }
+ globalDefaultModelId.value = res.data?.defaultModelId ?? null;
} catch {
models.value = [];
}
diff --git a/packages/drizzle-pkg/db.sqlite b/packages/drizzle-pkg/db.sqlite
index 2c425ae..9f3baeb 100644
Binary files a/packages/drizzle-pkg/db.sqlite and b/packages/drizzle-pkg/db.sqlite differ
diff --git a/server/api/admin/agent-config/index.get.ts b/server/api/admin/agent-config/index.get.ts
index dcd2b6d..a18feb0 100644
--- a/server/api/admin/agent-config/index.get.ts
+++ b/server/api/admin/agent-config/index.get.ts
@@ -2,7 +2,7 @@ import { defineWrappedResponseHandler } from "#server/utils/handler";
import { R } from "#server/utils/response";
import { requireAdmin } from "#server/utils/admin-guard";
import { getConfigGlobal } from "#server/utils/context";
-import { listSystemModels } from "#server/service/llm";
+import { listAllEnabledModels } from "#server/service/llm";
export default defineWrappedResponseHandler(async (event) => {
await requireAdmin(event);
@@ -14,7 +14,7 @@ export default defineWrappedResponseHandler(async (event) => {
getConfigGlobal("agentPublicToolSlugs"),
]);
- const systemModels = await listSystemModels();
+ const systemModels = await listAllEnabledModels();
return R.success({
systemPrompt,
diff --git a/server/api/agents/[agentSlug]/chat/index.post.ts b/server/api/agents/[agentSlug]/chat/index.post.ts
index 28f2cd1..1613d1d 100644
--- a/server/api/agents/[agentSlug]/chat/index.post.ts
+++ b/server/api/agents/[agentSlug]/chat/index.post.ts
@@ -1,5 +1,5 @@
import { defineEventHandler, getRouterParam, readBody, setResponseHeaders } from "h3";
-import { getCurrentUser, getConfigUser } from "#server/utils/context";
+import { getCurrentUser, getConfigUser, getConfigGlobal } from "#server/utils/context";
import { resolveAgentIdentity } from "#server/service/agent/identity";
import { getSessionByIdAndUser } from "#server/service/agent/session";
import { getAgentBySlug } from "#server/service/agent/agent";
@@ -61,6 +61,8 @@ export default defineEventHandler(async (event) => {
preferredModelId = (await getConfigUser(event, "preferredLlmModelId")) ?? null;
}
+ const globalDefaultModelId = (await getConfigGlobal("agentDefaultModelId")) ?? null;
+
const user = identity.userId ? await getCurrentUser(event) : null;
const { response } = await executeChat({
@@ -81,6 +83,7 @@ export default defineEventHandler(async (event) => {
},
ip,
preferredModelId,
+ globalDefaultModelId,
requestId: event.context.requestId,
registerAbort: registerAbortController,
unregisterAbort: unregisterAbortController,
diff --git a/server/api/agents/[agentSlug]/sessions/index.post.ts b/server/api/agents/[agentSlug]/sessions/index.post.ts
index 660eed0..a6c4b87 100644
--- a/server/api/agents/[agentSlug]/sessions/index.post.ts
+++ b/server/api/agents/[agentSlug]/sessions/index.post.ts
@@ -3,7 +3,7 @@ import { R } from "#server/utils/response";
import { resolveAgentIdentity } from "#server/service/agent/identity";
import { createSession } from "#server/service/agent/session";
import { generateTempToken, setTempTokenCookie, getTempTokenTtlMs } from "#server/service/agent/temp-token";
-import { getConfigUser } from "#server/utils/context";
+import { getConfigUser, getConfigGlobal } from "#server/utils/context";
import { getAgentBySlug } from "#server/service/agent/agent";
export default defineWrappedResponseHandler(async (event) => {
@@ -44,6 +44,13 @@ export default defineWrappedResponseHandler(async (event) => {
modelId = agent.defaultModelId;
}
+ if (!modelId) {
+ const globalDefault = await getConfigGlobal("agentDefaultModelId");
+ if (globalDefault && globalDefault > 0) {
+ modelId = globalDefault;
+ }
+ }
+
const body = await readBody(event).catch(() => ({}));
const systemPrompt: string | null =
typeof body?.systemPrompt === "string" && body.systemPrompt.trim().length > 0
diff --git a/server/api/llm/models/index.get.ts b/server/api/llm/models/index.get.ts
index 302f789..46e5020 100644
--- a/server/api/llm/models/index.get.ts
+++ b/server/api/llm/models/index.get.ts
@@ -1,10 +1,29 @@
import { defineWrappedResponseHandler } from "#server/utils/handler";
import { R } from "#server/utils/response";
-import { getCurrentUser } from "#server/utils/context";
-import { listAllEnabledModelsForUser } from "#server/service/llm";
+import { getCurrentUser, getConfigGlobal } from "#server/utils/context";
+import { listAllEnabledModelsForUser, getModelWithProviderByIdAny } from "#server/service/llm";
export default defineWrappedResponseHandler(async (event) => {
const user = await getCurrentUser(event);
- const list = await listAllEnabledModelsForUser(user?.id ?? null);
- return R.success({ list });
+ const [list, globalDefaultModelId] = await Promise.all([
+ listAllEnabledModelsForUser(user?.id ?? null),
+ getConfigGlobal("agentDefaultModelId"),
+ ]);
+
+ if (globalDefaultModelId && !list.some((m) => m.id === globalDefaultModelId)) {
+ const row = await getModelWithProviderByIdAny(globalDefaultModelId);
+ if (row) {
+ list.unshift({
+ id: row.model.id,
+ name: row.model.name,
+ modelId: row.model.modelId,
+ type: row.model.type,
+ providerName: row.provider.name,
+ providerId: row.provider.id,
+ supportsTools: row.model.supportsTools,
+ });
+ }
+ }
+
+ return R.success({ list, defaultModelId: globalDefaultModelId ?? null });
});
diff --git a/server/service/agent/chat-engine.ts b/server/service/agent/chat-engine.ts
index 36878d1..d0a3a39 100644
--- a/server/service/agent/chat-engine.ts
+++ b/server/service/agent/chat-engine.ts
@@ -45,6 +45,7 @@ export interface ChatEngineParams {
};
ip: string;
preferredModelId?: number | null;
+ globalDefaultModelId?: number | null;
requestId?: string;
registerAbort: (sessionId: string, controller: AbortController) => void;
unregisterAbort: (sessionId: string) => void;
@@ -222,13 +223,13 @@ export async function executeChat(params: ChatEngineParams): Promise {
.orderBy(desc(llmModels.createdAt));
}
+export async function listAllEnabledModels(): Promise {
+ return dbGlobal
+ .select({
+ id: llmModels.id,
+ providerId: llmModels.providerId,
+ name: llmModels.name,
+ modelId: llmModels.modelId,
+ type: llmModels.type,
+ enabled: llmModels.enabled,
+ description: llmModels.description,
+ maxTokens: llmModels.maxTokens,
+ supportsTools: llmModels.supportsTools,
+ createdAt: llmModels.createdAt,
+ updatedAt: llmModels.updatedAt,
+ })
+ .from(llmModels)
+ .innerJoin(llmProviders, eq(llmModels.providerId, llmProviders.id))
+ .where(eq(llmModels.enabled, 1))
+ .orderBy(desc(llmModels.createdAt));
+}
+
// ============ 通用 Model 查询(agent 对话核心使用)============
export async function getModelWithProviderById(modelId: number, userId: number | null) {
diff --git a/server/service/llm/model-resolver.ts b/server/service/llm/model-resolver.ts
index 2d5b3ce..44e12e4 100644
--- a/server/service/llm/model-resolver.ts
+++ b/server/service/llm/model-resolver.ts
@@ -40,10 +40,13 @@ export async function resolveModelForUser(
modelId: number,
userId: number | null,
): Promise {
- const modelRow = userId
+ let modelRow = userId
? await getModelWithProviderById(modelId, userId)
: await getSystemModelWithProviderById(modelId);
if (!modelRow) {
+ modelRow = await getModelWithProviderByIdAny(modelId);
+ }
+ if (!modelRow) {
logger.warn("[MODEL-RESOLVER] modelId=%d not found for userId=%s", modelId, userId);
return null;
}