Pass through PE refusals to the raw prompt and pin adult PE system prompts.

Enhance no longer fails the studio job when the rewrite refuses or comes back empty; host prompt copies keep the official steps plus the adult appendix after a node re-clone.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-26 14:46:24 -05:00
co-authored by Cursor
parent 99b61e67d7
commit a51118d92a
8 changed files with 512 additions and 16 deletions
+43
View File
@@ -0,0 +1,43 @@
/** Qwen PE refusal / empty-rewrite detection — fail open to promptRaw. */
const REFUSAL_RE =
/i cannot|i can't|i['’]m not able|i am not able|cannot assist|can't assist|won['’]t create|will not create|against my|not appropriate|\bsafety\b|content policy|抱歉|无法|不能协助|不符合/i
const STOP = new Set([
'the', 'and', 'for', 'are', 'was', 'were', 'been', 'being', 'this', 'that', 'with', 'from',
'into', 'your', 'have', 'will', 'would', 'could', 'should', 'about', 'there', 'their', 'them',
'then', 'than', 'when', 'what', 'which', 'while', 'where', 'make', 'made', 'like', 'just',
'only', 'also', 'over', 'under', 'after', 'before', 'between', 'through', 'image', 'photo',
'picture', 'please', 'create', 'generate', 'show', 'want', 'need', 'scene', 'style', 'prompt',
'edit', 'change', 'keep', 'using', 'into', 'onto', 'her', 'him', 'his', 'she', 'they', 'them',
])
/** Concrete tokens from the user brief (latin words ≥3 or CJK runs). */
export function concreteTokens(text) {
const raw = String(text || '').toLowerCase().match(/[a-z][a-z0-9-]{2,}|[\u4e00-\u9fff]{2,}/g) || []
return [...new Set(raw)].filter(w => !STOP.has(w))
}
function isGutted(userPrompt, rewritten) {
const user = String(userPrompt || '').trim()
const out = String(rewritten || '').trim()
if (!user || !out) return !out
if (out.length >= user.length) return false
const nouns = concreteTokens(user)
if (!nouns.length) return false
const lower = out.toLowerCase()
return !nouns.some(n => lower.includes(n))
}
/**
* @returns {{ refused: boolean, reason: string }}
*/
export function qwen21PeRefusal(userPrompt, { positive_prompt, thinking, parse_ok } = {}) {
const positive = String(positive_prompt || '').trim()
const think = String(thinking || '').trim()
if (!parse_ok && !positive) return { refused: true, reason: 'empty rewrite (parse_ok false)' }
if (!positive) return { refused: true, reason: 'empty rewrite' }
if (REFUSAL_RE.test(positive) || REFUSAL_RE.test(think)) return { refused: true, reason: 'model refused' }
if (isGutted(userPrompt, positive)) return { refused: true, reason: 'gutted rewrite' }
return { refused: false, reason: '' }
}