mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 15:02:20 +02:00
preserve web tools in compound artifact workflows
This commit is contained in:
@@ -10448,6 +10448,11 @@ def _classify_agent_request(messages: List[Dict], last_user: str) -> Dict[str, o
|
||||
or (_explicit_local_input and not _explicit_web_retrieval)
|
||||
):
|
||||
domains.add("web")
|
||||
if has(
|
||||
r"\b(?:reviews?|ratings?|testimonials?|評判|レビュー)\b",
|
||||
r"\b(?:worth|recommend(?:ed|ation)?|pros?\s+and\s+cons?|buying\s+guide)\b",
|
||||
):
|
||||
domains.add("web")
|
||||
if _looks_like_explicit_browser_interaction(retrieval_query) and not (
|
||||
_personal_domain_turn and not _strong_web_target
|
||||
):
|
||||
|
||||
+51
-2
@@ -699,6 +699,27 @@ 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(?:artifacts?|director(?:y|ies)|files?|outputs?|results?)\b|"
|
||||
r"\.(?:csv|html|json|jsonl|md|tex|txt)\b",
|
||||
raw_text,
|
||||
re.I,
|
||||
)
|
||||
):
|
||||
# Explicit native Web names seal selection to the named tools.
|
||||
# Compound autonomous jobs also require a bounded local
|
||||
# read/write/verify surface; without it, requiring shell_files
|
||||
# makes the whole contract fail closed and drops the Web tools.
|
||||
explicitly_named_web.update(
|
||||
{"read_file", "write_file", "edit_file", "python"}
|
||||
)
|
||||
return frozenset(explicitly_named_web)
|
||||
if (
|
||||
re.search(r"\b(?:look\s*up|search|find)\b", text, re.I)
|
||||
@@ -718,6 +739,21 @@ def selected_tools_for_request(message: str) -> frozenset[str] | None:
|
||||
# begin on an arbitrary browser page can ground an answer in stale or
|
||||
# unrelated content without ever establishing a current source set.
|
||||
return frozenset({"web_search"})
|
||||
if re.search(
|
||||
r"\b(?:reviews?|ratings?|評判|レビュー|testimonials?)\b",
|
||||
text,
|
||||
re.I,
|
||||
) and re.search(
|
||||
r"\b(?:what(?:'s|\s+is)|how\s+are|which|best|good|bad|worth|recommend|"
|
||||
r"compare|pros?|cons?|opinions?|thoughts?|about)\b",
|
||||
text,
|
||||
re.I,
|
||||
):
|
||||
# Product/service review requests are current public-web lookups even
|
||||
# when the user does not say "search". Route them to web_search before
|
||||
# the model sees a schema; otherwise a no-tool contract invites raw
|
||||
# provider-specific markup (notably DeepSeek DSML) that cannot execute.
|
||||
return frozenset({"web_search"})
|
||||
if re.search(
|
||||
r"\buse\s+(?:the\s+)?(?:odysseus\s+)?web_search\b",
|
||||
raw_text,
|
||||
@@ -3371,6 +3407,12 @@ def required_read_operation_for_request(message: str, history: Iterable = ()) ->
|
||||
re.search(r"\b(?:saved\s+)?memor(?:y|ies|es)\b", text, re.I)
|
||||
and re.search(r"\b(?:pull\s+up|peek|list|show|saved)\b", text, re.I)
|
||||
and not re.search(r"\b(?:add|edit|change|delete|forget)\b", text, re.I)
|
||||
and not re.search(
|
||||
r"\b(?:never|without)\s+(?:(?:using|relying\s+on)\s+)?(?:my\s+)?memory\b|"
|
||||
r"\bdo\s+not\s+(?:use|rely\s+on)\s+(?:my\s+)?memory\b",
|
||||
text,
|
||||
re.I,
|
||||
)
|
||||
):
|
||||
return RequiredReadOperation("manage_memory", {"action": "list"}, maximum)
|
||||
if (
|
||||
@@ -4073,8 +4115,15 @@ def requested_capabilities(message: str, history: Iterable = (), *, active_docum
|
||||
# Explicit native-tool requests are stronger than incidental domain
|
||||
# words in the research subject (for example, Git ``pull`` must not
|
||||
# route to scheduled tasks). Keep the whole read-only web family so a
|
||||
# weak search can recover through fetch/browser without schema growth.
|
||||
return frozenset({"search_browser"})
|
||||
# weak search can recover through fetch/browser. A compound artifact
|
||||
# workflow may also have been deliberately selected with a bounded
|
||||
# workspace tool surface; preserve that independent family.
|
||||
selected = selected_tools_for_request(raw_text)
|
||||
selected_families = (
|
||||
frozenset().union(*(_families_for_tool(tool) for tool in selected))
|
||||
if selected else frozenset()
|
||||
)
|
||||
return selected_families or frozenset({"search_browser"})
|
||||
if (
|
||||
re.search(r"\b(?:latest|recent|current|today(?:'s)?)\b", text, re.I)
|
||||
and re.search(r"\b(?:info(?:rmation)?|news|nees|updates?)\b", text, re.I)
|
||||
|
||||
@@ -192,6 +192,16 @@ def test_typo_heavy_product_problem_is_complete_not_ambiguous_fragment() -> None
|
||||
assert not _is_ambiguous_short_low_signal(text)
|
||||
|
||||
|
||||
def test_product_review_request_routes_to_web_search_without_search_verb() -> None:
|
||||
from src.turn_contract import selected_tools_for_request
|
||||
|
||||
assert selected_tools_for_request("What's Dyson pencil vac reviews") == frozenset({"web_search"})
|
||||
assert "web" in _classify_agent_request(
|
||||
[{"role": "user", "content": "What's Dyson pencil vac reviews"}],
|
||||
"What's Dyson pencil vac reviews",
|
||||
)["domains"]
|
||||
|
||||
|
||||
def test_standalone_link_fragment_gets_clarification_path() -> None:
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -2267,6 +2267,19 @@ def test_explicit_native_web_workflow_outranks_incidental_task_words():
|
||||
assert selected_tools_for_request(message) == {"web_search", "web_fetch"}
|
||||
|
||||
|
||||
def test_explicit_native_web_workflow_preserves_workspace_artifact_tools():
|
||||
message = (
|
||||
"Use Odysseus web_search to locate each RFC, then web_fetch every page. "
|
||||
"Create /tmp_workspace/results/inventory.jsonl, read the local inputs, "
|
||||
"and run the Python validator before finishing."
|
||||
)
|
||||
selected = selected_tools_for_request(message)
|
||||
assert selected == {
|
||||
"web_search", "web_fetch", "read_file", "write_file", "edit_file", "python",
|
||||
}
|
||||
assert requested_capabilities(message) == {"search_browser", "shell_files"}
|
||||
|
||||
|
||||
def test_typoed_webhook_inventory_selects_admin_reader():
|
||||
message = "list my webhoks again"
|
||||
assert selected_tools_for_request(message) == {"manage_webhooks"}
|
||||
|
||||
Reference in New Issue
Block a user