mirror of
https://github.com/hansjone/netxops.git
synced 2026-10-09 04:00:46 +08:00
Fix reply language ignored when user writes Chinese.
Strengthen Host prompt injection with a per-step reply reminder, read live settings, and stop persona from forcing follow-user language. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
d52c05e774
commit
91f2e9a5c8
7 changed files with 108 additions and 19 deletions
49
lib/index.js
49
lib/index.js
|
|
@ -1343,11 +1343,23 @@ function replyInstruction(setting) {
|
|||
return "";
|
||||
const meta = REPLY_META[normalized];
|
||||
return [
|
||||
"## Reply language requirement",
|
||||
`Regardless of the language the user writes in, you must always write the entire reply in ${meta.native} (${meta.name}) —`,
|
||||
"including explanations, summaries, body text, titles, and error descriptions.",
|
||||
"Keep code, commands, file paths, API names, host names, and proper nouns in their original form; do not translate them.",
|
||||
"This requirement outranks language hints in the user message or persona until the Netx Ops reply-language setting changes."
|
||||
"## Reply language requirement (mandatory)",
|
||||
`The operator set Netx Ops reply language to ${meta.native} (${meta.name}).`,
|
||||
`You MUST write the entire final reply in ${meta.name} only.`,
|
||||
`Do not switch to the user's language even if they write in Chinese, English, or any other language.`,
|
||||
"This includes titles, bullet labels (Result / Evidence / Next may stay as English keywords), explanations, summaries, warnings, and error text.",
|
||||
"Keep code, commands, file paths, API names, host names, UUIDs, and proper nouns unchanged.",
|
||||
'This rule outranks persona wording such as "follow the user language" and outranks language hints in the user message.'
|
||||
].join(" ");
|
||||
}
|
||||
function replyReminder(setting) {
|
||||
const normalized = normalizeReplyLanguage(setting);
|
||||
if (normalized === REPLY_LANGUAGE_DEFAULT)
|
||||
return "";
|
||||
const meta = REPLY_META[normalized];
|
||||
return [
|
||||
`[Reply language] Mandatory: write your entire final answer in ${meta.native} (${meta.name}).`,
|
||||
"Do not answer in the user's language. Code/paths/host names stay original."
|
||||
].join(" ");
|
||||
}
|
||||
|
||||
|
|
@ -4119,11 +4131,26 @@ function apply(ctx, config = Config({})) {
|
|||
});
|
||||
ctx.inject(["systemPrompt", "settings"], (promptCtx) => {
|
||||
const systemPrompt = promptCtx.systemPrompt;
|
||||
const liveConfig = () => {
|
||||
const settings = promptCtx.get("settings");
|
||||
const section = typeof settings?.get === "function" ? (() => {
|
||||
try {
|
||||
return settings.get(NETXOPS_SETTINGS_NAMESPACE);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
})() : undefined;
|
||||
if (section !== null && typeof section === "object" && !Array.isArray(section)) {
|
||||
return { ...source(), ...section };
|
||||
}
|
||||
return source();
|
||||
};
|
||||
const effectiveThinking = () => {
|
||||
const settings = promptCtx.get("settings");
|
||||
const current = source();
|
||||
const current = liveConfig();
|
||||
return resolveThinkingLanguage(normalizeThinkingLanguage(current.thinkingLanguage), readSystemLocalePreference(settings));
|
||||
};
|
||||
const replySetting = () => normalizeReplyLanguage(liveConfig().replyLanguage);
|
||||
promptCtx.effect(() => {
|
||||
const disposers = [];
|
||||
const push = (dispose) => {
|
||||
|
|
@ -4142,9 +4169,15 @@ function apply(ctx, config = Config({})) {
|
|||
}));
|
||||
push(systemPrompt.section({
|
||||
name: "netxops:reply-language",
|
||||
order: 890,
|
||||
text: () => replyInstruction(normalizeReplyLanguage(source().replyLanguage))
|
||||
order: 10150,
|
||||
text: () => replyInstruction(replySetting())
|
||||
}));
|
||||
push(systemPrompt.context({
|
||||
name: "netxops:reply-language-reminder",
|
||||
order: 1100,
|
||||
text: () => replyReminder(replySetting())
|
||||
}));
|
||||
promptCtx.logger.info("netxops: model language prompts registered (thinking=%s reply=%s)", normalizeThinkingLanguage(liveConfig().thinkingLanguage), replySetting());
|
||||
return () => {
|
||||
for (const dispose of disposers.splice(0))
|
||||
dispose();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue