fix(ena-planner): align channel options and model-fetch behavior with story-summary
This commit is contained in:
@@ -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">
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user