fix(ena-planner): align channel options and model-fetch behavior with story-summary

This commit is contained in:
2026-02-25 15:37:05 +08:00
parent 841d5f0e1f
commit e982304182
2 changed files with 50 additions and 54 deletions

View File

@@ -103,9 +103,6 @@
<option value="openai">OpenAI compatible</option>
<option value="gemini">Gemini compatible</option>
<option value="claude">Claude compatible</option>
<option value="deepseek">DeepSeek compatible</option>
<option value="cohere">Cohere compatible</option>
<option value="custom">Custom compatible</option>
</select>
</div>
<div class="form-group hidden" id="ep_model_row">
@@ -123,7 +120,6 @@
<input id="ep_api_key" type="password" class="input" placeholder="仅本地保存,不上传">
</div>
</div>
<div class="form-hint">不需要填写 /v1 前缀,后端会按渠道自动处理。</div>
<div id="ep_model_selector" class="hidden" style="margin-top:12px;">
<label class="form-label">选择模型</label>
<select id="ep_model_select" class="input">

View File

@@ -890,9 +890,6 @@ async function callPlanner(messages, options = {}) {
claude: chat_completion_sources.CLAUDE,
gemini: chat_completion_sources.MAKERSUITE,
google: chat_completion_sources.MAKERSUITE,
cohere: chat_completion_sources.COHERE,
deepseek: chat_completion_sources.DEEPSEEK,
custom: chat_completion_sources.CUSTOM,
}[channel];
if (!source) throw new Error(`Unsupported channel: ${channel}`);
@@ -1029,42 +1026,13 @@ async function callPlanner(messages, options = {}) {
async function fetchModelsForUi() {
const s = ensureSettings();
const channel = String(s.api?.channel || 'st_main').toLowerCase();
const source = channel === 'st_main'
? String(oai_settings?.chat_completion_source || chat_completion_sources.OPENAI)
: ({
openai: chat_completion_sources.OPENAI,
claude: chat_completion_sources.CLAUDE,
gemini: chat_completion_sources.MAKERSUITE,
google: chat_completion_sources.MAKERSUITE,
cohere: chat_completion_sources.COHERE,
deepseek: chat_completion_sources.DEEPSEEK,
custom: chat_completion_sources.CUSTOM,
}[channel]);
if (!source) throw new Error(`Unsupported channel: ${channel}`);
const providerUrl = normalizeProxyBaseUrl(s.api?.url);
const providerKey = String(s.api?.key || '').trim();
if (channel !== 'st_main') {
if (!providerUrl) throw new Error('Please provide API URL');
if (!providerKey) throw new Error('Please provide API KEY');
}
if (channel === 'st_main') {
const source = String(oai_settings?.chat_completion_source || chat_completion_sources.OPENAI);
const payload = {
chat_completion_source: source,
reverse_proxy: channel === 'st_main' ? oai_settings?.reverse_proxy : providerUrl,
proxy_password: channel === 'st_main' ? oai_settings?.proxy_password : providerKey,
reverse_proxy: oai_settings?.reverse_proxy,
proxy_password: oai_settings?.proxy_password,
};
if (source === chat_completion_sources.CUSTOM) {
payload.custom_url = oai_settings?.custom_url;
payload.custom_include_headers = oai_settings?.custom_include_headers;
}
if (source === chat_completion_sources.AZURE_OPENAI) {
payload.azure_base_url = oai_settings?.azure_base_url;
payload.azure_deployment_name = oai_settings?.azure_deployment_name;
payload.azure_api_version = oai_settings?.azure_api_version;
}
const res = await fetch('/api/backends/chat-completions/status', {
method: 'POST',
headers: {
@@ -1083,6 +1051,39 @@ async function fetchModelsForUi() {
return list.map(x => x?.id).filter(Boolean);
}
// Keep consistent with story-summary: direct URL probing for non-ST channels.
let baseUrl = String(s.api?.url || '').trim().replace(/\/+$/, '');
const apiKey = String(s.api?.key || '').trim();
if (!baseUrl) throw new Error('请先填写 API URL');
if (!apiKey) throw new Error('请先填写 API KEY');
const tryFetch = async (url) => {
try {
const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}`, Accept: 'application/json' } });
if (!res.ok) return null;
const data = await res.json();
if (!data) return null;
if (Array.isArray(data?.data)) return data.data.map(x => x?.id).filter(Boolean);
if (Array.isArray(data?.models)) return data.models.map(x => x?.id || x?.name).filter(Boolean);
} catch { }
return null;
};
if (baseUrl.endsWith('/v1')) baseUrl = baseUrl.slice(0, -3);
if (baseUrl.endsWith('/v1beta')) baseUrl = baseUrl.slice(0, -7);
const candidates = channel === 'gemini' || channel === 'google'
? [`${baseUrl}/v1beta/models`, `${baseUrl}/v1/models`, `${baseUrl}/models`]
: [`${baseUrl}/v1/models`, `${baseUrl}/models`];
for (const url of candidates) {
const models = await tryFetch(url);
if (models?.length) return [...new Set(models)];
}
throw new Error('未获取到模型');
}
async function debugWorldbookForUi() {
let out = '正在诊断世界书读取...\n';
const charWb = await getCharacterWorldbooks();
@@ -1528,4 +1529,3 @@ export function cleanupEnaPlanner() {
}
delete window.xiaobaixEnaPlanner;
}