fix: Codex 自动压缩不触发 —— 接管时链接模型目录(绝对路径)进 config.toml (hot 1.5.83)
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"use strict";
|
||||
|
||||
const SKILL_LINK_RE = /\[\$([^\]\n]+)\]\(([^)\n]*)\)/g;
|
||||
const LEADING_SKILL_LINK_RE = /^\s*\[\$([^\]\n]+)\]\(([^)\n]*)\)\s*/;
|
||||
const TRUNCATED_LEADING_SKILL_LINK_RE = /^\s*\[\$([^\]\n]+)\]\([^)\n]*$/;
|
||||
const LEADING_SKILL_TOKEN_RE = /^\s*\$[A-Za-z][\w:.-]*(?:\s+|$)/;
|
||||
|
||||
function normalizeInlineText(text) {
|
||||
return String(text || "")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
function cleanSkillLinks(text) {
|
||||
return String(text || "").replace(SKILL_LINK_RE, (_m, name) => `$${String(name || "").trim()}`);
|
||||
}
|
||||
|
||||
function stripLeadingSkillMentions(text) {
|
||||
let out = cleanSkillLinks(text);
|
||||
let changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
const before = out;
|
||||
out = out.replace(LEADING_SKILL_LINK_RE, "");
|
||||
out = out.replace(TRUNCATED_LEADING_SKILL_LINK_RE, "");
|
||||
out = out.replace(LEADING_SKILL_TOKEN_RE, "");
|
||||
out = out.replace(/^\s*[::,,;;||\-–—]+\s*/, "");
|
||||
changed = out !== before;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function cleanUserVisibleText(text) {
|
||||
return cleanSkillLinks(text);
|
||||
}
|
||||
|
||||
// 某些中转模型会把内部思考误当成普通正文,用 XML 风格标签直接输出。
|
||||
// 只清理明确的内部块,不改动普通文本中的尖括号内容。
|
||||
function stripInternalThoughtBlocks(text) {
|
||||
let out = String(text || "");
|
||||
for (const name of ["thinking", "analysis", "reasoning"]) {
|
||||
const re = new RegExp("<" + name + "\\b[^>]*>[\\s\\S]*?</" + name + "\\s*>", "gi");
|
||||
out = out.replace(re, "");
|
||||
}
|
||||
return out.replace(/<\/?(?:thinking|analysis|reasoning)\b[^>]*>/gi, "");
|
||||
}
|
||||
|
||||
// 流式内容可能把标签拆在多个 chunk 中:未闭合的内部块整体暂不输出。
|
||||
function stripInternalThoughtStreaming(text) {
|
||||
const source = String(text || "");
|
||||
let out = "";
|
||||
let cursor = 0;
|
||||
const openRe = /<(thinking|analysis|reasoning)\b[^>]*>/gi;
|
||||
while (true) {
|
||||
openRe.lastIndex = cursor;
|
||||
const open = openRe.exec(source);
|
||||
if (!open) {
|
||||
out += source.slice(cursor);
|
||||
break;
|
||||
}
|
||||
out += source.slice(cursor, open.index);
|
||||
const closeRe = new RegExp("</" + open[1] + "\\s*>", "i");
|
||||
const tail = source.slice(openRe.lastIndex);
|
||||
const close = closeRe.exec(tail);
|
||||
if (!close) break;
|
||||
cursor = openRe.lastIndex + close.index + close[0].length;
|
||||
}
|
||||
return stripInternalThoughtBlocks(out);
|
||||
}
|
||||
|
||||
function cleanThreadTitle(title, fallback = "", maxLen = 80) {
|
||||
const primary = normalizeInlineText(stripLeadingSkillMentions(title));
|
||||
const secondary = normalizeInlineText(stripLeadingSkillMentions(fallback));
|
||||
const cleaned = primary || secondary || normalizeInlineText(cleanSkillLinks(title)) || normalizeInlineText(cleanSkillLinks(fallback));
|
||||
return cleaned ? cleaned.slice(0, maxLen) : "";
|
||||
}
|
||||
|
||||
function looksLikeSkillMentionTitle(title) {
|
||||
const text = normalizeInlineText(title);
|
||||
return /^\[\$[^\]]+\]\(/.test(text) || /^\$[A-Za-z][\w:.-]*(?:\s|$)/.test(text);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
cleanSkillLinks,
|
||||
cleanThreadTitle,
|
||||
cleanUserVisibleText,
|
||||
stripInternalThoughtBlocks,
|
||||
stripInternalThoughtStreaming,
|
||||
looksLikeSkillMentionTitle,
|
||||
};
|
||||
Reference in New Issue
Block a user