mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 06:52:20 +02:00
harden web artifact evidence routing
This commit is contained in:
+19
-4
@@ -701,10 +701,13 @@ def selected_tools_for_request(message: str) -> frozenset[str] | None:
|
||||
explicitly_named_web.add("web_fetch")
|
||||
if (
|
||||
re.search(r"(?:file://)?/(?:tmp_)?workspace(?:/|\b)", raw_text, re.I)
|
||||
and re.search(
|
||||
r"\b(?:build|create|edit|persist|produce|save|write)\b",
|
||||
raw_text,
|
||||
re.I,
|
||||
and (
|
||||
re.search(
|
||||
r"\b(?:build|create|edit|persist|produce|save|write)\b",
|
||||
raw_text,
|
||||
re.I,
|
||||
)
|
||||
or re.search(r"\brequired\s+outputs?\b", raw_text, re.I)
|
||||
)
|
||||
and re.search(
|
||||
r"\b(?:artifacts?|director(?:y|ies)|files?|outputs?|results?)\b|"
|
||||
@@ -2557,6 +2560,18 @@ def required_read_operation_for_request(message: str, history: Iterable = ()) ->
|
||||
normalized_text = _normalize_request_lead(message)
|
||||
text, maximum = _read_request_and_limit(message)
|
||||
rows = list(history)
|
||||
if re.search(
|
||||
r"\bwithout\s+(?:using|trusting|relying\s+on)\s+(?:my\s+)?memory\b|"
|
||||
r"\b(?:do\s+not|don['’]?t|dont|never)\b[^.;\n]{0,80}\bfrom\s+memory(?:\s+alone)?\b|"
|
||||
r"\b(?:do\s+not|don['’]?t|dont|never)\s+(?:use|trust|rely\s+on)\s+(?:my\s+)?memory\b",
|
||||
text,
|
||||
re.I,
|
||||
):
|
||||
# These are source-grounding constraints, not requests to read the
|
||||
# user's private Odysseus memory store. Long research/artifact jobs
|
||||
# often also contain words such as "list" or "show", which must not
|
||||
# convert the evidence constraint into a sealed personal-data read.
|
||||
return None
|
||||
# A user can switch families in one conversation and then explicitly come
|
||||
# back using ordinary shorthand (including a one-edit typo):
|
||||
# ``back to emaol show 2 latest``. This is a complete inbox inventory
|
||||
|
||||
@@ -2287,6 +2287,32 @@ def test_negative_memory_evidence_rule_does_not_select_personal_memory():
|
||||
"the fetched page, never memory. Sort every paper list and show the result."
|
||||
)
|
||||
assert required_read_operation_for_request(message) is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"evidence_rule",
|
||||
[
|
||||
"extract every field without trusting memory",
|
||||
"do not answer from memory alone",
|
||||
"do not write the inventory from memory",
|
||||
],
|
||||
)
|
||||
def test_web_evidence_variants_do_not_select_personal_memory(evidence_rule):
|
||||
message = (
|
||||
"Use web_search and web_fetch, then show an author list and write "
|
||||
f"/tmp_workspace/results/report.md; {evidence_rule}."
|
||||
)
|
||||
assert required_read_operation_for_request(message) is None
|
||||
|
||||
|
||||
def test_explicit_web_required_outputs_preserve_workspace_tools():
|
||||
message = (
|
||||
"Run web_search and web_fetch first. Required outputs in "
|
||||
"/tmp_workspace/results: report.jsonl and provenance.md."
|
||||
)
|
||||
assert selected_tools_for_request(message) == frozenset(
|
||||
{"web_search", "web_fetch", "read_file", "write_file", "edit_file", "python"}
|
||||
)
|
||||
assert requested_capabilities(message) == {"search_browser", "shell_files"}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user