mirror of
https://github.com/Wx-2025/ST-Amily2-Chat-Optimisation.git
synced 2026-06-06 09:15:50 +00:00
feat(api): bridge ApiProfileManager to all AI callers, fix config split
- Add core/api/api-resolver.js: getSlotProfile(slot) + providerToApiMode() - core/api.js: getApiSettings() async, reads 'main' slot profile first - NccsApi.js: getNccsApiSettings() async, reads 'nccs' slot profile first - Ngms_api.js: getNgmsApiSettings() async, reads 'ngms' slot profile first - JqyhApi.js: getJqyhApiSettings() async, reads 'jqyh' slot profile first - All callers updated with await; legacy DOM/extension_settings as fallback - .gitignore: add WorkDiary.md and Structure.md (local-only files) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -0,0 +1,2 @@
|
|||||||
|
WorkDiary.md
|
||||||
|
Structure.md
|
||||||
|
|||||||
44
core/api.js
44
core/api.js
@@ -1,5 +1,6 @@
|
|||||||
import { extension_settings, getContext } from "/scripts/extensions.js";
|
import { extension_settings, getContext } from "/scripts/extensions.js";
|
||||||
import { characters } from "/script.js";
|
import { characters } from "/script.js";
|
||||||
|
import { getSlotProfile } from './api/api-resolver.js';
|
||||||
import { world_names } from "/scripts/world-info.js";
|
import { world_names } from "/scripts/world-info.js";
|
||||||
import { extensionName } from "../utils/settings.js";
|
import { extensionName } from "../utils/settings.js";
|
||||||
import { extractContentByTag, replaceContentByTag, extractFullTagBlock } from '../utils/tagProcessor.js';
|
import { extractContentByTag, replaceContentByTag, extractFullTagBlock } from '../utils/tagProcessor.js';
|
||||||
@@ -433,28 +434,43 @@ async function fetchSillyTavernPresetModels() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getApiSettings() {
|
export async function getApiSettings() {
|
||||||
|
// 优先读取 'main' 槽位分配的 Profile
|
||||||
|
const profile = await getSlotProfile('main');
|
||||||
|
if (profile) {
|
||||||
|
return {
|
||||||
|
apiProvider: profile.provider,
|
||||||
|
apiUrl: profile.apiUrl,
|
||||||
|
apiKey: profile.apiKey ?? '',
|
||||||
|
model: profile.model,
|
||||||
|
maxTokens: profile.maxTokens ?? 65500,
|
||||||
|
temperature: profile.temperature ?? 1.0,
|
||||||
|
tavernProfile: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 降级:读旧 DOM 面板配置
|
||||||
const settings = extension_settings[extensionName] || {};
|
const settings = extension_settings[extensionName] || {};
|
||||||
const apiProvider = document.getElementById('amily2_api_provider')?.value || 'openai';
|
const apiProvider = document.getElementById('amily2_api_provider')?.value || 'openai';
|
||||||
|
|
||||||
let model;
|
let model;
|
||||||
if (apiProvider === 'sillytavern_preset') {
|
if (apiProvider === 'sillytavern_preset') {
|
||||||
const context = getContext();
|
const context = getContext();
|
||||||
const profileId = document.getElementById('amily2_preset_selector')?.value;
|
const profileId = document.getElementById('amily2_preset_selector')?.value;
|
||||||
const profile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
|
const stProfile = context.extensionSettings?.connectionManager?.profiles?.find(p => p.id === profileId);
|
||||||
model = profile?.openai_model || 'Preset Model';
|
model = stProfile?.openai_model || 'Preset Model';
|
||||||
} else {
|
} else {
|
||||||
model = document.getElementById('amily2_model')?.value;
|
model = document.getElementById('amily2_model')?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
apiProvider: apiProvider,
|
apiProvider,
|
||||||
apiUrl: document.getElementById('amily2_api_url')?.value.trim() || '',
|
apiUrl: document.getElementById('amily2_api_url')?.value.trim() || '',
|
||||||
apiKey: document.getElementById('amily2_api_key')?.value.trim() || '',
|
apiKey: document.getElementById('amily2_api_key')?.value.trim() || '',
|
||||||
model: model,
|
model,
|
||||||
maxTokens: settings.maxTokens || 4000,
|
maxTokens: settings.maxTokens || 4000,
|
||||||
temperature: settings.temperature || 0.7,
|
temperature: settings.temperature || 0.7,
|
||||||
tavernProfile: document.getElementById('amily2_preset_selector')?.value || ''
|
tavernProfile: document.getElementById('amily2_preset_selector')?.value || '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,8 +484,8 @@ export async function testApiConnection() {
|
|||||||
$button.prop("disabled", true).html('<i class="fas fa-spinner fa-spin"></i> 测试中');
|
$button.prop("disabled", true).html('<i class="fas fa-spinner fa-spin"></i> 测试中');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const apiSettings = getApiSettings();
|
const apiSettings = await getApiSettings();
|
||||||
|
|
||||||
if (apiSettings.apiProvider === 'sillytavern_preset') {
|
if (apiSettings.apiProvider === 'sillytavern_preset') {
|
||||||
if (!apiSettings.tavernProfile) {
|
if (!apiSettings.tavernProfile) {
|
||||||
throw new Error("请先在下方选择一个SillyTavern预设");
|
throw new Error("请先在下方选择一个SillyTavern预设");
|
||||||
@@ -518,7 +534,7 @@ export async function callAI(messages, options = {}) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiSettings = getApiSettings();
|
const apiSettings = await getApiSettings();
|
||||||
|
|
||||||
const finalOptions = {
|
const finalOptions = {
|
||||||
maxTokens: apiSettings.maxTokens,
|
maxTokens: apiSettings.maxTokens,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { extension_settings, getContext } from "/scripts/extensions.js";
|
|||||||
import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
|
import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
|
||||||
import { extensionName } from "../../utils/settings.js";
|
import { extensionName } from "../../utils/settings.js";
|
||||||
import { amilyHelper } from '../../core/tavern-helper/main.js';
|
import { amilyHelper } from '../../core/tavern-helper/main.js';
|
||||||
|
import { getSlotProfile, providerToApiMode } from './api-resolver.js';
|
||||||
|
|
||||||
let ChatCompletionService = undefined;
|
let ChatCompletionService = undefined;
|
||||||
try {
|
try {
|
||||||
@@ -42,15 +43,30 @@ function normalizeApiResponse(responseData) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getJqyhApiSettings() {
|
export async function getJqyhApiSettings() {
|
||||||
|
// 优先读取 'jqyh' 槽位分配的 Profile
|
||||||
|
const profile = await getSlotProfile('jqyh');
|
||||||
|
if (profile) {
|
||||||
|
return {
|
||||||
|
apiMode: providerToApiMode(profile.provider),
|
||||||
|
apiUrl: profile.apiUrl,
|
||||||
|
apiKey: profile.apiKey ?? '',
|
||||||
|
model: profile.model,
|
||||||
|
maxTokens: profile.maxTokens ?? 65500,
|
||||||
|
temperature: profile.temperature ?? 1.0,
|
||||||
|
tavernProfile: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 降级:读旧 extension_settings 字段
|
||||||
return {
|
return {
|
||||||
apiMode: extension_settings[extensionName]?.jqyhApiMode || 'openai_test',
|
apiMode: extension_settings[extensionName]?.jqyhApiMode || 'openai_test',
|
||||||
apiUrl: extension_settings[extensionName]?.jqyhApiUrl?.trim() || '',
|
apiUrl: extension_settings[extensionName]?.jqyhApiUrl?.trim() || '',
|
||||||
apiKey: extension_settings[extensionName]?.jqyhApiKey?.trim() || '',
|
apiKey: extension_settings[extensionName]?.jqyhApiKey?.trim() || '',
|
||||||
model: extension_settings[extensionName]?.jqyhModel || '',
|
model: extension_settings[extensionName]?.jqyhModel || '',
|
||||||
maxTokens: extension_settings[extensionName]?.jqyhMaxTokens || 4000,
|
maxTokens: extension_settings[extensionName]?.jqyhMaxTokens || 4000,
|
||||||
temperature: extension_settings[extensionName]?.jqyhTemperature || 0.7,
|
temperature: extension_settings[extensionName]?.jqyhTemperature || 0.7,
|
||||||
tavernProfile: extension_settings[extensionName]?.jqyhTavernProfile || ''
|
tavernProfile: extension_settings[extensionName]?.jqyhTavernProfile || '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +76,7 @@ export async function callJqyhAI(messages, options = {}) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiSettings = getJqyhApiSettings();
|
const apiSettings = await getJqyhApiSettings();
|
||||||
|
|
||||||
const finalOptions = {
|
const finalOptions = {
|
||||||
maxTokens: apiSettings.maxTokens,
|
maxTokens: apiSettings.maxTokens,
|
||||||
@@ -258,7 +274,7 @@ async function callJqyhSillyTavernPreset(messages, options) {
|
|||||||
export async function fetchJqyhModels() {
|
export async function fetchJqyhModels() {
|
||||||
console.log('[Amily2号-Jqyh外交部] 开始获取模型列表');
|
console.log('[Amily2号-Jqyh外交部] 开始获取模型列表');
|
||||||
|
|
||||||
const apiSettings = getJqyhApiSettings();
|
const apiSettings = await getJqyhApiSettings();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (apiSettings.apiMode === 'sillytavern_preset') {
|
if (apiSettings.apiMode === 'sillytavern_preset') {
|
||||||
@@ -339,7 +355,7 @@ export async function fetchJqyhModels() {
|
|||||||
export async function testJqyhApiConnection() {
|
export async function testJqyhApiConnection() {
|
||||||
console.log('[Amily2号-Jqyh外交部] 开始API连接测试');
|
console.log('[Amily2号-Jqyh外交部] 开始API连接测试');
|
||||||
|
|
||||||
const apiSettings = getJqyhApiSettings();
|
const apiSettings = await getJqyhApiSettings();
|
||||||
|
|
||||||
if (apiSettings.apiMode === 'sillytavern_preset') {
|
if (apiSettings.apiMode === 'sillytavern_preset') {
|
||||||
if (!apiSettings.tavernProfile) {
|
if (!apiSettings.tavernProfile) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { extension_settings, getContext } from "/scripts/extensions.js";
|
|||||||
import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
|
import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
|
||||||
import { extensionName } from "../../utils/settings.js";
|
import { extensionName } from "../../utils/settings.js";
|
||||||
import { amilyHelper } from '../../core/tavern-helper/main.js';
|
import { amilyHelper } from '../../core/tavern-helper/main.js';
|
||||||
|
import { getSlotProfile, providerToApiMode } from './api-resolver.js';
|
||||||
|
|
||||||
let ChatCompletionService = undefined;
|
let ChatCompletionService = undefined;
|
||||||
try {
|
try {
|
||||||
@@ -36,17 +37,34 @@ if (window.Amily2Bus) {
|
|||||||
toastr.error("核心组件 Amily2Bus 丢失,请检查安装。", "Nccs-System");
|
toastr.error("核心组件 Amily2Bus 丢失,请检查安装。", "Nccs-System");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNccsApiSettings() {
|
export async function getNccsApiSettings() {
|
||||||
|
// 优先读取 'nccs' 槽位分配的 Profile
|
||||||
|
const profile = await getSlotProfile('nccs');
|
||||||
|
if (profile) {
|
||||||
|
return {
|
||||||
|
nccsEnabled: true,
|
||||||
|
apiMode: providerToApiMode(profile.provider),
|
||||||
|
apiUrl: profile.apiUrl,
|
||||||
|
apiKey: profile.apiKey ?? '',
|
||||||
|
model: profile.model,
|
||||||
|
maxTokens: profile.maxTokens ?? 65500,
|
||||||
|
temperature: profile.temperature ?? 1.0,
|
||||||
|
tavernProfile: '',
|
||||||
|
useFakeStream: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 降级:读旧 extension_settings 字段
|
||||||
return {
|
return {
|
||||||
nccsEnabled: extension_settings[extensionName]?.nccsEnabled || false,
|
nccsEnabled: extension_settings[extensionName]?.nccsEnabled || false,
|
||||||
apiMode: extension_settings[extensionName]?.nccsApiMode || 'openai_test',
|
apiMode: extension_settings[extensionName]?.nccsApiMode || 'openai_test',
|
||||||
apiUrl: extension_settings[extensionName]?.nccsApiUrl?.trim() || '',
|
apiUrl: extension_settings[extensionName]?.nccsApiUrl?.trim() || '',
|
||||||
apiKey: extension_settings[extensionName]?.nccsApiKey?.trim() || '',
|
apiKey: extension_settings[extensionName]?.nccsApiKey?.trim() || '',
|
||||||
model: extension_settings[extensionName]?.nccsModel || '',
|
model: extension_settings[extensionName]?.nccsModel || '',
|
||||||
maxTokens: extension_settings[extensionName]?.nccsMaxTokens || 4000,
|
maxTokens: extension_settings[extensionName]?.nccsMaxTokens || 4000,
|
||||||
temperature: extension_settings[extensionName]?.nccsTemperature || 0.7,
|
temperature: extension_settings[extensionName]?.nccsTemperature || 0.7,
|
||||||
tavernProfile: extension_settings[extensionName]?.nccsTavernProfile || '',
|
tavernProfile: extension_settings[extensionName]?.nccsTavernProfile || '',
|
||||||
useFakeStream: extension_settings[extensionName]?.nccsFakeStreamEnabled || false
|
useFakeStream: extension_settings[extensionName]?.nccsFakeStreamEnabled || false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +78,7 @@ export async function callNccsAI(messages, options = {}) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const settings = getNccsApiSettings();
|
const settings = await getNccsApiSettings();
|
||||||
const finalOptions = {
|
const finalOptions = {
|
||||||
...settings,
|
...settings,
|
||||||
...options
|
...options
|
||||||
@@ -238,7 +256,7 @@ async function callNccsSillyTavernPreset(messages, options) {
|
|||||||
export async function fetchNccsModels() {
|
export async function fetchNccsModels() {
|
||||||
console.log('[Amily2号-Nccs外交部] 开始获取模型列表');
|
console.log('[Amily2号-Nccs外交部] 开始获取模型列表');
|
||||||
|
|
||||||
const apiSettings = getNccsApiSettings();
|
const apiSettings = await getNccsApiSettings();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (apiSettings.apiMode === 'sillytavern_preset') {
|
if (apiSettings.apiMode === 'sillytavern_preset') {
|
||||||
@@ -320,7 +338,7 @@ export async function fetchNccsModels() {
|
|||||||
export async function testNccsApiConnection() {
|
export async function testNccsApiConnection() {
|
||||||
console.log('[Amily2号-Nccs外交部] 开始API连接测试');
|
console.log('[Amily2号-Nccs外交部] 开始API连接测试');
|
||||||
|
|
||||||
const apiSettings = getNccsApiSettings();
|
const apiSettings = await getNccsApiSettings();
|
||||||
|
|
||||||
if (apiSettings.apiMode === 'sillytavern_preset') {
|
if (apiSettings.apiMode === 'sillytavern_preset') {
|
||||||
if (!apiSettings.tavernProfile) {
|
if (!apiSettings.tavernProfile) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { extension_settings, getContext } from "/scripts/extensions.js";
|
|||||||
import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
|
import { characters, this_chid, getRequestHeaders, saveSettingsDebounced, eventSource, event_types } from "/script.js";
|
||||||
import { extensionName } from "../../utils/settings.js";
|
import { extensionName } from "../../utils/settings.js";
|
||||||
import { amilyHelper } from '../../core/tavern-helper/main.js';
|
import { amilyHelper } from '../../core/tavern-helper/main.js';
|
||||||
|
import { getSlotProfile, providerToApiMode } from './api-resolver.js';
|
||||||
|
|
||||||
let ChatCompletionService = undefined;
|
let ChatCompletionService = undefined;
|
||||||
try {
|
try {
|
||||||
@@ -42,16 +43,32 @@ function normalizeApiResponse(responseData) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNgmsApiSettings() {
|
export async function getNgmsApiSettings() {
|
||||||
|
// 优先读取 'ngms' 槽位分配的 Profile
|
||||||
|
const profile = await getSlotProfile('ngms');
|
||||||
|
if (profile) {
|
||||||
|
return {
|
||||||
|
apiMode: providerToApiMode(profile.provider),
|
||||||
|
apiUrl: profile.apiUrl,
|
||||||
|
apiKey: profile.apiKey ?? '',
|
||||||
|
model: profile.model,
|
||||||
|
maxTokens: profile.maxTokens ?? 65500,
|
||||||
|
temperature: profile.temperature ?? 1.0,
|
||||||
|
tavernProfile: '',
|
||||||
|
useFakeStream: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 降级:读旧 extension_settings 字段
|
||||||
return {
|
return {
|
||||||
apiMode: extension_settings[extensionName]?.ngmsApiMode || 'openai_test',
|
apiMode: extension_settings[extensionName]?.ngmsApiMode || 'openai_test',
|
||||||
apiUrl: extension_settings[extensionName]?.ngmsApiUrl?.trim() || '',
|
apiUrl: extension_settings[extensionName]?.ngmsApiUrl?.trim() || '',
|
||||||
apiKey: extension_settings[extensionName]?.ngmsApiKey?.trim() || '',
|
apiKey: extension_settings[extensionName]?.ngmsApiKey?.trim() || '',
|
||||||
model: extension_settings[extensionName]?.ngmsModel || '',
|
model: extension_settings[extensionName]?.ngmsModel || '',
|
||||||
maxTokens: extension_settings[extensionName]?.ngmsMaxTokens || 4000,
|
maxTokens: extension_settings[extensionName]?.ngmsMaxTokens || 4000,
|
||||||
temperature: extension_settings[extensionName]?.ngmsTemperature || 0.7,
|
temperature: extension_settings[extensionName]?.ngmsTemperature || 0.7,
|
||||||
tavernProfile: extension_settings[extensionName]?.ngmsTavernProfile || '',
|
tavernProfile: extension_settings[extensionName]?.ngmsTavernProfile || '',
|
||||||
useFakeStream: extension_settings[extensionName]?.ngmsFakeStreamEnabled || false
|
useFakeStream: extension_settings[extensionName]?.ngmsFakeStreamEnabled || false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +78,7 @@ export async function callNgmsAI(messages, options = {}) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiSettings = getNgmsApiSettings();
|
const apiSettings = await getNgmsApiSettings();
|
||||||
|
|
||||||
const finalOptions = {
|
const finalOptions = {
|
||||||
maxTokens: apiSettings.maxTokens,
|
maxTokens: apiSettings.maxTokens,
|
||||||
@@ -324,7 +341,7 @@ async function callNgmsSillyTavernPreset(messages, options) {
|
|||||||
export async function fetchNgmsModels() {
|
export async function fetchNgmsModels() {
|
||||||
console.log('[Amily2号-Ngms外交部] 开始获取模型列表');
|
console.log('[Amily2号-Ngms外交部] 开始获取模型列表');
|
||||||
|
|
||||||
const apiSettings = getNgmsApiSettings();
|
const apiSettings = await getNgmsApiSettings();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (apiSettings.apiMode === 'sillytavern_preset') {
|
if (apiSettings.apiMode === 'sillytavern_preset') {
|
||||||
@@ -407,7 +424,7 @@ export async function fetchNgmsModels() {
|
|||||||
export async function testNgmsApiConnection() {
|
export async function testNgmsApiConnection() {
|
||||||
console.log('[Amily2号-Ngms外交部] 开始API连接测试');
|
console.log('[Amily2号-Ngms外交部] 开始API连接测试');
|
||||||
|
|
||||||
const apiSettings = getNgmsApiSettings();
|
const apiSettings = await getNgmsApiSettings();
|
||||||
|
|
||||||
if (apiSettings.apiMode === 'sillytavern_preset') {
|
if (apiSettings.apiMode === 'sillytavern_preset') {
|
||||||
if (!apiSettings.tavernProfile) {
|
if (!apiSettings.tavernProfile) {
|
||||||
|
|||||||
45
core/api/api-resolver.js
Normal file
45
core/api/api-resolver.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* api-resolver.js — API 配置槽位解析器
|
||||||
|
*
|
||||||
|
* 职责:
|
||||||
|
* 优先从 ApiProfileManager 读取功能槽分配的 Profile(含解密 Key),
|
||||||
|
* 无分配时返回 null,由调用方执行旧配置兜底。
|
||||||
|
*
|
||||||
|
* 使用方式:
|
||||||
|
* const profile = await getSlotProfile('main');
|
||||||
|
* if (profile) { // 用 profile.provider / apiUrl / apiKey / model ... }
|
||||||
|
* else { // 回退到旧 DOM / extension_settings 读取 }
|
||||||
|
*
|
||||||
|
* provider → apiMode 映射(供 Nccs / Ngms / Jqyh 内部 switch 使用):
|
||||||
|
* 'openai' → 'openai_test' (经 ST 后端代理发送,规避 CORS)
|
||||||
|
* 'google' → 'openai_test' (Google OpenAI-compat 同样走代理)
|
||||||
|
* 'sillytavern_backend'→ 'openai_test'
|
||||||
|
* 'sillytavern_preset' → 'sillytavern_preset'
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { apiProfileManager } from '../../utils/config/ApiProfileManager.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 Profile.provider 映射到子模块使用的 apiMode 字段。
|
||||||
|
* @param {string} provider
|
||||||
|
* @returns {'openai_test'|'sillytavern_preset'}
|
||||||
|
*/
|
||||||
|
export function providerToApiMode(provider) {
|
||||||
|
return provider === 'sillytavern_preset' ? 'sillytavern_preset' : 'openai_test';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取功能槽对应的完整 Profile(含解密 Key)。
|
||||||
|
* 未分配或读取失败时返回 null。
|
||||||
|
*
|
||||||
|
* @param {string} slot 功能槽名(见 ApiProfileManager.SLOTS)
|
||||||
|
* @returns {Promise<Object|null>}
|
||||||
|
*/
|
||||||
|
export async function getSlotProfile(slot) {
|
||||||
|
try {
|
||||||
|
return await apiProfileManager.getAssignedProfile(slot);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`[ApiResolver] 读取槽位 "${slot}" 失败,降级到旧配置:`, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user