把思考强度收到接口配置里,并支持分组、嗅探和切换同一接口下的模型。
预设不再保存思考强度。设置页会在首屏套用主题。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* API 配置使用记录(浏览器 localStorage)。
|
||||
* 对话菜单与设置页共用:只把「曾经选用过」的模型放进快捷列表。
|
||||
*/
|
||||
|
||||
export const API_PROFILE_USAGE_KEY = "wa-api-profile-usage";
|
||||
|
||||
/** @typedef {{ count: number, lastUsed: number }} ApiProfileUsageEntry */
|
||||
/** @typedef {Record<string, ApiProfileUsageEntry>} ApiProfileUsageMap */
|
||||
|
||||
/** @returns {ApiProfileUsageMap} */
|
||||
export function loadApiProfileUsage() {
|
||||
try {
|
||||
const raw = localStorage.getItem(API_PROFILE_USAGE_KEY);
|
||||
if (!raw) return {};
|
||||
const parsed = JSON.parse(raw);
|
||||
return parsed && typeof parsed === "object" ? parsed : {};
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {ApiProfileUsageMap} usage */
|
||||
export function saveApiProfileUsage(usage) {
|
||||
try {
|
||||
localStorage.setItem(API_PROFILE_USAGE_KEY, JSON.stringify(usage));
|
||||
} catch {
|
||||
/* ignore quota / private mode */
|
||||
}
|
||||
}
|
||||
|
||||
/** 选用成功后记一次;首次出现记 count=1。 */
|
||||
export function recordApiProfileUsage(id) {
|
||||
if (!id) return;
|
||||
const usage = loadApiProfileUsage();
|
||||
const prev = usage[id];
|
||||
usage[id] = {
|
||||
count: (prev?.count || 0) + 1,
|
||||
lastUsed: Date.now(),
|
||||
};
|
||||
saveApiProfileUsage(usage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前生效配置若还没有记录,写入一条(不刷 count)。
|
||||
* @param {string | null | undefined} id
|
||||
*/
|
||||
export function seedApiProfileUsage(id) {
|
||||
if (!id) return;
|
||||
const usage = loadApiProfileUsage();
|
||||
if (usage[id]) return;
|
||||
usage[id] = { count: 1, lastUsed: Date.now() };
|
||||
saveApiProfileUsage(usage);
|
||||
}
|
||||
|
||||
/** 只去掉快捷列表里的曾用记录,不删除配置本身。 */
|
||||
export function forgetApiProfileUsage(id) {
|
||||
if (!id) return false;
|
||||
const usage = loadApiProfileUsage();
|
||||
if (!usage[id]) return false;
|
||||
delete usage[id];
|
||||
saveApiProfileUsage(usage);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @param {Set<string>} validIds */
|
||||
export function pruneApiProfileUsage(validIds) {
|
||||
const usage = loadApiProfileUsage();
|
||||
let changed = false;
|
||||
for (const id of Object.keys(usage)) {
|
||||
if (!validIds.has(id)) {
|
||||
delete usage[id];
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (changed) saveApiProfileUsage(usage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @param {ApiProfileUsageMap} usage
|
||||
*/
|
||||
export function apiProfileUsageRank(id, usage) {
|
||||
const entry = usage[id];
|
||||
return {
|
||||
lastUsed: entry?.lastUsed || 0,
|
||||
count: entry?.count || 0,
|
||||
};
|
||||
}
|
||||
|
||||
/** @param {{ lastUsed: number, count: number }} a @param {{ lastUsed: number, count: number }} b */
|
||||
export function compareApiProfileUsage(a, b) {
|
||||
if (b.lastUsed !== a.lastUsed) return b.lastUsed - a.lastUsed;
|
||||
if (b.count !== a.count) return b.count - a.count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T[]} items
|
||||
* @param {(item: T) => { lastUsed: number, count: number }} rankOf
|
||||
*/
|
||||
export function sortByApiProfileUsage(items, rankOf) {
|
||||
return items
|
||||
.map((item, index) => ({ item, index, rank: rankOf(item) }))
|
||||
.sort((a, b) => compareApiProfileUsage(a.rank, b.rank) || a.index - b.index)
|
||||
.map((entry) => entry.item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 组内成员:只留曾用过的;当前生效始终保留。
|
||||
* @param {Array<{ id: string }>} members
|
||||
* @param {ApiProfileUsageMap} usage
|
||||
* @param {string | null | undefined} activeId
|
||||
*/
|
||||
export function filterUsedApiProfiles(members, usage, activeId) {
|
||||
const used = members.filter(
|
||||
(profile) => profile.id === activeId || Boolean(usage[profile.id]),
|
||||
);
|
||||
return sortByApiProfileUsage(used, (profile) =>
|
||||
apiProfileUsageRank(profile.id, usage),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<{ id: string }>} members
|
||||
* @param {ApiProfileUsageMap} usage
|
||||
*/
|
||||
export function membersUsageRank(members, usage) {
|
||||
return members.reduce(
|
||||
(acc, profile) => {
|
||||
const rank = apiProfileUsageRank(profile.id, usage);
|
||||
return {
|
||||
lastUsed: Math.max(acc.lastUsed, rank.lastUsed),
|
||||
count: acc.count + rank.count,
|
||||
};
|
||||
},
|
||||
{ lastUsed: 0, count: 0 },
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user