- 支持视频/音频/PDF/文档等多文件类型上传(最大20MB,最多4个) - 视频用 image_url 格式传递(兼容 Gemini OpenAI 兼容层) - 发送前自动生成图片/视频缩略图,聊天记录中显示预览 - 新增消息编辑、重新生成、复制功能 - 支持 reasoning_content 思考过程折叠显示 - 历史对话支持重命名 - 修复 localStorage 存储优化(strip 大文件数据,保留缩略图) - 新增删除历史记录 API 及重启按钮前端组件 Co-Authored-By: Claude Opus 4.7 <[email protected]>
109 lines
4.1 KiB
JavaScript
109 lines
4.1 KiB
JavaScript
import { app } from "../../../scripts/app.js";
|
|
import { api } from "../../../scripts/api.js";
|
|
|
|
app.registerExtension({
|
|
name: "o1key.assetToggle",
|
|
settings: [
|
|
{
|
|
id: "o1key.AssetSave",
|
|
name: "资产保存",
|
|
tooltip: "持久性保存生图记录",
|
|
type: "boolean",
|
|
defaultValue: true,
|
|
},
|
|
],
|
|
async init() {
|
|
const enabled = () => {
|
|
try {
|
|
return app.ui.settings.getSettingValue("o1key.AssetSave", true);
|
|
} catch {
|
|
return true;
|
|
}
|
|
};
|
|
|
|
// --- Patch getHistory: 合并真实 jobs 与持久化历史 ---
|
|
const _origGetHistory = api.getHistory.bind(api);
|
|
api.getHistory = async function (maxItems = 200, opts = {}) {
|
|
const real = await _origGetHistory(maxItems, opts);
|
|
if (!enabled()) return real;
|
|
try {
|
|
const offset = opts?.offset || 0;
|
|
const resp = await fetch(
|
|
`/o1key/output_history?limit=${maxItems}&offset=${offset}`
|
|
);
|
|
if (!resp.ok) return real;
|
|
const data = await resp.json();
|
|
const persisted = data.jobs || [];
|
|
if (!persisted.length) return real;
|
|
if (!real || !Array.isArray(real) || !real.length) {
|
|
// 仅持久化数据时也补充 priority
|
|
const t = data.pagination?.total || persisted.length;
|
|
return persisted.map((j, i) => ({
|
|
...j,
|
|
priority: j.priority ?? t - i,
|
|
}));
|
|
}
|
|
// 合并去重:以 id 为 key,真实 jobs 优先
|
|
const seen = new Set(real.map((j) => j.id));
|
|
const merged = [...real];
|
|
for (const job of persisted) {
|
|
if (!seen.has(job.id)) {
|
|
merged.push(job);
|
|
}
|
|
}
|
|
// 按时间倒序
|
|
merged.sort(
|
|
(a, b) => (b.create_time || 0) - (a.create_time || 0)
|
|
);
|
|
const result = merged.slice(0, maxItems);
|
|
// 补充 priority 字段(队列面板依赖此字段排序)
|
|
const total = data.pagination?.total || result.length;
|
|
for (let idx = 0; idx < result.length; idx++) {
|
|
if (result[idx].priority == null) {
|
|
result[idx] = {
|
|
...result[idx],
|
|
priority: total - idx,
|
|
};
|
|
}
|
|
}
|
|
return result;
|
|
} catch (e) {
|
|
return real;
|
|
}
|
|
};
|
|
|
|
// --- Patch deleteItem: 同时删除 o1key 持久化记录和文件 ---
|
|
const _origDeleteItem = api.deleteItem.bind(api);
|
|
api.deleteItem = async function (type, id) {
|
|
const result = await _origDeleteItem(type, id);
|
|
if (type === "history" && enabled()) {
|
|
try {
|
|
await fetch("/o1key/delete_history", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ delete: [id] }),
|
|
});
|
|
} catch (e) {}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
// --- Patch getJobDetail: 真实 API 失败时回退到本地路由 ---
|
|
const _origGetJobDetail = api.getJobDetail.bind(api);
|
|
api.getJobDetail = async function (jobId) {
|
|
const real = await _origGetJobDetail(jobId);
|
|
if (real) return real;
|
|
if (!enabled()) return undefined;
|
|
try {
|
|
const resp = await fetch(
|
|
`/o1key/job_detail/${encodeURIComponent(jobId)}`
|
|
);
|
|
if (!resp.ok) return undefined;
|
|
return await resp.json();
|
|
} catch (e) {
|
|
return undefined;
|
|
}
|
|
};
|
|
},
|
|
});
|