mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-07-08 11:56:59 +00:00
Guard document style against persona guessing
This commit is contained in:
@@ -1147,6 +1147,12 @@ def _build_system_prompt(
|
|||||||
if active_document:
|
if active_document:
|
||||||
set_active_document(active_document.id)
|
set_active_document(active_document.id)
|
||||||
_doc_raw = active_document.current_content or ""
|
_doc_raw = active_document.current_content or ""
|
||||||
|
_document_writing_style = ""
|
||||||
|
try:
|
||||||
|
from src.settings import load_settings as _load_settings
|
||||||
|
_document_writing_style = (_load_settings().get("document_writing_style", "") or "").strip()
|
||||||
|
except Exception:
|
||||||
|
_document_writing_style = ""
|
||||||
_doc_title_l = (active_document.title or "").strip().lower()
|
_doc_title_l = (active_document.title or "").strip().lower()
|
||||||
_is_email_doc = (
|
_is_email_doc = (
|
||||||
active_document.language == "email"
|
active_document.language == "email"
|
||||||
@@ -1237,6 +1243,21 @@ def _build_system_prompt(
|
|||||||
f'text must match the document EXACTLY and must NOT include the leading line-number '
|
f'text must match the document EXACTLY and must NOT include the leading line-number '
|
||||||
f'or tab (those are reference-only). To rewrite entirely: update_document.'
|
f'or tab (those are reference-only). To rewrite entirely: update_document.'
|
||||||
)
|
)
|
||||||
|
if _document_writing_style:
|
||||||
|
doc_ctx += (
|
||||||
|
"\n\nDOCUMENT WRITING STYLE — use only for normal prose writing/revision in this "
|
||||||
|
"document, not for code/data/JSON and not for email-specific greetings or signatures:\n"
|
||||||
|
f"{_document_writing_style}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
doc_ctx += (
|
||||||
|
"\n\nStyle safety: if the user asks to write/rewrite this document \"in my style\" "
|
||||||
|
"or \"as my style\", do NOT infer that style from memories, identity, public persona, "
|
||||||
|
"creator/channel references, or biographical facts. There is no saved document writing "
|
||||||
|
"style. Ask the user for a style sample or a document writing style description before "
|
||||||
|
"rewriting for style. You may still make ordinary requested edits that do not depend on "
|
||||||
|
"knowing the user's personal style."
|
||||||
|
)
|
||||||
_doc_message = untrusted_context_message("active editor document", doc_ctx)
|
_doc_message = untrusted_context_message("active editor document", doc_ctx)
|
||||||
_doc_message["_protected"] = True
|
_doc_message["_protected"] = True
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,10 @@ DEFAULT_SETTINGS = {
|
|||||||
"task_model": "",
|
"task_model": "",
|
||||||
"default_endpoint_id": "",
|
"default_endpoint_id": "",
|
||||||
"default_model": "",
|
"default_model": "",
|
||||||
|
# Optional prose style used only for normal document writing/editing.
|
||||||
|
# Email replies use email_writing_style instead because greetings,
|
||||||
|
# signatures, and mailbox identity rules are medium-specific.
|
||||||
|
"document_writing_style": "",
|
||||||
# Ordered fallback chain for the default chat model. Each entry is
|
# Ordered fallback chain for the default chat model. Each entry is
|
||||||
# {"endpoint_id": "...", "model": "..."}. If the primary model fails
|
# {"endpoint_id": "...", "model": "..."}. If the primary model fails
|
||||||
# before producing output (endpoint offline / errors), the chat
|
# before producing output (endpoint offline / errors), the chat
|
||||||
|
|||||||
@@ -297,6 +297,36 @@ def test_guide_only_suppresses_active_document_context(monkeypatch):
|
|||||||
assert "Relevant skills" not in prompt_payloads[0]
|
assert "Relevant skills" not in prompt_payloads[0]
|
||||||
|
|
||||||
|
|
||||||
|
def test_document_my_style_does_not_infer_public_persona(monkeypatch):
|
||||||
|
_patch_loop_basics(monkeypatch)
|
||||||
|
monkeypatch.setattr(al, "_build_base_prompt", lambda *a, **k: ("BASE", ""), raising=False)
|
||||||
|
monkeypatch.setattr(al, "_cached_base_prompt", None, raising=False)
|
||||||
|
monkeypatch.setattr(al, "_cached_base_prompt_key", None, raising=False)
|
||||||
|
|
||||||
|
import src.settings as settings
|
||||||
|
monkeypatch.setattr(settings, "load_settings", lambda: {"document_writing_style": ""}, raising=False)
|
||||||
|
|
||||||
|
active_doc = SimpleNamespace(
|
||||||
|
id="doc-style",
|
||||||
|
current_content="A short poem already exists here.",
|
||||||
|
title="Morning Poem",
|
||||||
|
language="markdown",
|
||||||
|
)
|
||||||
|
|
||||||
|
messages, _ = al._build_system_prompt(
|
||||||
|
[{"role": "user", "content": "Write as my style"}],
|
||||||
|
model="local-model",
|
||||||
|
active_document=active_doc,
|
||||||
|
mcp_mgr=None,
|
||||||
|
relevant_tools={"edit_document", "update_document"},
|
||||||
|
suppress_skills=True,
|
||||||
|
)
|
||||||
|
payload = "\n\n".join(str(msg.get("content", "")) for msg in messages)
|
||||||
|
|
||||||
|
assert "There is no saved document writing style" in payload
|
||||||
|
assert "do NOT infer that style from memories, identity, public persona" in payload
|
||||||
|
|
||||||
|
|
||||||
def test_guide_only_skips_teacher_escalation(monkeypatch):
|
def test_guide_only_skips_teacher_escalation(monkeypatch):
|
||||||
_patch_loop_basics(monkeypatch)
|
_patch_loop_basics(monkeypatch)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user