feat: enhance session sync and add voice input feature
- 增强会话同步:确保所有会话完全同步到新账号 - 强制更新 model_provider 字段 - 添加 session_index.jsonl 重建功能 - 确保数据库 UPSERT 逻辑正确处理所有情况 - 新增语音输入功能(voice_cdp.js, voice_inject.js) - 测试脚本和增强模块 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+72
-10
@@ -304,6 +304,16 @@ function llmGroup() {
|
||||
return config.groups.find(usable) || null;
|
||||
}
|
||||
|
||||
// 供「语音输入」转写用:优先当前激活且勾选 STT 的分组,否则取任一勾选 STT 的分组。
|
||||
// 需配齐 baseUrl+key 且勾了 stt;返回的 group 带 sttModel(如 speech-01 / whisper-1)。
|
||||
function sttGroup() {
|
||||
load();
|
||||
const ok = (g) => g && !g.isDefault && g.baseUrl && g.key && g.stt;
|
||||
const act = config.groups.find((g) => g.id === config.activeId);
|
||||
if (ok(act)) return act;
|
||||
return config.groups.find(ok) || null;
|
||||
}
|
||||
|
||||
// 拉取某个中转 API 的模型列表(试 /v1/models 再 /models)
|
||||
async function fetchModels(baseUrl, key) {
|
||||
if (!baseUrl) throw new Error("请先填 API 地址");
|
||||
@@ -343,6 +353,64 @@ function writeCapture(name, data) {
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function requestTextForIntent(req) {
|
||||
const parts = [];
|
||||
const walk = (v) => {
|
||||
if (v == null) return;
|
||||
if (typeof v === "string") {
|
||||
parts.push(v);
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(v)) {
|
||||
for (const it of v) walk(it);
|
||||
return;
|
||||
}
|
||||
if (typeof v === "object") {
|
||||
for (const key of ["text", "content", "input", "output", "arguments"]) walk(v[key]);
|
||||
}
|
||||
};
|
||||
walk(req && req.input);
|
||||
return parts.join("\n");
|
||||
}
|
||||
|
||||
function hasExplicitGenImageIntent(req) {
|
||||
return /\$gen[\s_-]*image\b/i.test(requestTextForIntent(req));
|
||||
}
|
||||
|
||||
function stripGenImageSkill(instructions) {
|
||||
if (typeof instructions !== "string" || !instructions.includes("gen-image")) return instructions;
|
||||
return instructions
|
||||
.split(/\r?\n/)
|
||||
.filter((line) => !/^\s*-\s+gen-image\s*:/.test(line))
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
function rewriteResponsesBody(body, group) {
|
||||
if (!body.length) return body;
|
||||
let j;
|
||||
try {
|
||||
j = JSON.parse(body.toString("utf-8"));
|
||||
} catch {
|
||||
return body;
|
||||
}
|
||||
if (!j || typeof j !== "object") return body;
|
||||
let changed = false;
|
||||
if (group.model && "model" in j && j.model !== group.model) {
|
||||
j.model = group.model;
|
||||
changed = true;
|
||||
}
|
||||
// 普通聊天分组没有 image-generation 权限时,上游会因 gen-image skill 声明误判为生图请求。
|
||||
// 只有用户显式输入 "$gen image" 才保留该 skill,让真正生图走脚本里的图片接口分组。
|
||||
if (!hasExplicitGenImageIntent(j)) {
|
||||
const nextInstructions = stripGenImageSkill(j.instructions);
|
||||
if (nextInstructions !== j.instructions) {
|
||||
j.instructions = nextInstructions;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed ? Buffer.from(JSON.stringify(j), "utf-8") : body;
|
||||
}
|
||||
|
||||
function handle(req, res) {
|
||||
const g = activeGroup();
|
||||
if (!g) {
|
||||
@@ -360,16 +428,7 @@ function handle(req, res) {
|
||||
req.on("end", () => {
|
||||
let body = Buffer.concat(chunks);
|
||||
const doCapture = /responses/.test(req.url || "");
|
||||
// 分组指定了模型 → 覆盖请求体里的 model
|
||||
if (g.model && body.length) {
|
||||
try {
|
||||
const j = JSON.parse(body.toString("utf-8"));
|
||||
if (j && typeof j === "object" && "model" in j) {
|
||||
j.model = g.model;
|
||||
body = Buffer.from(JSON.stringify(j), "utf-8");
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
if (doCapture) body = rewriteResponsesBody(body, g);
|
||||
// —— chat 模式:Responses ⇄ Chat Completions 协议转换(DeepSeek/GLM/Kimi 等)——
|
||||
if (g.mode === "chat" && /responses/.test(req.url || "")) {
|
||||
let responsesReq = {};
|
||||
@@ -577,6 +636,8 @@ function status() {
|
||||
hasKey: g.isDefault ? true : !!g.key,
|
||||
isDefault: !!g.isDefault,
|
||||
codexImage: !!g.codexImage,
|
||||
stt: !!g.stt,
|
||||
sttModel: g.sttModel || "",
|
||||
})),
|
||||
};
|
||||
}
|
||||
@@ -880,5 +941,6 @@ module.exports = {
|
||||
groupById,
|
||||
usableGroups,
|
||||
llmGroup,
|
||||
sttGroup,
|
||||
fetchModels,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user