mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-09 08:22:19 +02:00
feat(runtime): enforce server request authority
This commit is contained in:
+32
-2
@@ -1316,6 +1316,17 @@ class TaskScheduler:
|
||||
async def _execute_action(self, task, run_id: str | None = None) -> tuple:
|
||||
"""Execute a built-in action (no LLM needed)."""
|
||||
from src.builtin_actions import BUILTIN_ACTIONS
|
||||
from src.agent_runtime.authority import (
|
||||
bind_request_authority, restore_task_authority, task_operation,
|
||||
)
|
||||
authority = restore_task_authority(
|
||||
getattr(task, "request_authority_json", None), task.prompt, task.task_type,
|
||||
task.action, owner=task.owner)
|
||||
from src.settings import get_setting
|
||||
authority = authority.restrict(disabled_tools=get_setting("disabled_tools", []) or ())
|
||||
operation = task_operation(task.task_type, task.action, task.prompt)
|
||||
if operation is None or not authority.permits(operation):
|
||||
return "Scheduled action has no matching server request authority.", False
|
||||
|
||||
action_fn = BUILTIN_ACTIONS.get(task.action)
|
||||
if not action_fn:
|
||||
@@ -1342,7 +1353,8 @@ class TaskScheduler:
|
||||
if getattr(task, "model", None):
|
||||
kwargs["model"] = task.model
|
||||
kwargs["endpoint_url"] = getattr(task, "endpoint_url", None)
|
||||
result, success = await action_fn(**kwargs)
|
||||
with bind_request_authority(authority):
|
||||
result, success = await action_fn(**kwargs)
|
||||
if getattr(task, "model", None):
|
||||
self._last_run_model = task.model
|
||||
return result, success
|
||||
@@ -1945,6 +1957,7 @@ class TaskScheduler:
|
||||
datetime_context_msg: dict | None = None) -> str:
|
||||
"""Run the full agent loop with tool access, collecting the final text."""
|
||||
from src.agent_loop import stream_agent_loop
|
||||
from src.agent_runtime.authority import restore_task_authority
|
||||
|
||||
system_content = system_prompt or "You are a helpful assistant executing a scheduled task. Use available tools to complete the task thoroughly."
|
||||
user_content = override_user_message or task.prompt
|
||||
@@ -2000,6 +2013,10 @@ class TaskScheduler:
|
||||
_task_fallbacks = []
|
||||
# Close the stream in this task on every exit, including the
|
||||
# approval-pause break, so the agent run's context state unwinds here.
|
||||
request_authority = restore_task_authority(
|
||||
getattr(task, "request_authority_json", None), task.prompt,
|
||||
getattr(task, "task_type", "llm"), getattr(task, "action", None),
|
||||
owner=task.owner, session_id=session_id)
|
||||
async with contextlib.aclosing(stream_agent_loop(
|
||||
endpoint_url=endpoint_url,
|
||||
model=model,
|
||||
@@ -2007,11 +2024,13 @@ class TaskScheduler:
|
||||
max_rounds=_task_max_rounds,
|
||||
session_id=session_id,
|
||||
owner=task.owner,
|
||||
workspace=request_authority.workspace or None,
|
||||
headers=headers,
|
||||
disabled_tools=disabled_tools,
|
||||
relevant_tools=relevant_tools,
|
||||
fallbacks=_task_fallbacks,
|
||||
workload="background",
|
||||
request_authority=request_authority,
|
||||
)) as agent_stream:
|
||||
async for event_str in agent_stream:
|
||||
if event_str.startswith("data: ") and not event_str.startswith("data: [DONE]"):
|
||||
@@ -2109,6 +2128,14 @@ class TaskScheduler:
|
||||
|
||||
async def _execute_research_task(self, task, db) -> str:
|
||||
"""Execute a deep research task using DeepResearcher."""
|
||||
from src.agent_runtime.authority import bind_request_authority, restore_task_authority, task_operation
|
||||
from src.settings import get_setting
|
||||
authority = restore_task_authority(
|
||||
getattr(task, "request_authority_json", None), task.prompt, task.task_type,
|
||||
getattr(task, "action", None), owner=task.owner)
|
||||
authority = authority.restrict(disabled_tools=get_setting("disabled_tools", []) or ())
|
||||
if not authority.permits(task_operation(task.task_type, getattr(task, "action", None), task.prompt)):
|
||||
raise PermissionError("Scheduled research has no matching server request authority.")
|
||||
from core.database import Session as DbSession, ChatMessage
|
||||
from src.deep_research import DeepResearcher
|
||||
from src.research_handler import RESEARCH_DATA_DIR, ResearchHandler
|
||||
@@ -2180,7 +2207,8 @@ class TaskScheduler:
|
||||
)
|
||||
|
||||
started_ts = time.time()
|
||||
report = await researcher.research(task.prompt)
|
||||
with bind_request_authority(authority):
|
||||
report = await researcher.research(task.prompt)
|
||||
completed_ts = time.time()
|
||||
try:
|
||||
stats = researcher.get_stats() or {}
|
||||
@@ -2603,6 +2631,7 @@ class TaskScheduler:
|
||||
if (task.output_target or "session") == "session":
|
||||
task.output_target = defs.get("output_target", "none")
|
||||
seeded = []
|
||||
from src.agent_runtime.authority import seal_task_authority
|
||||
for action, defs in HOUSEKEEPING_DEFAULTS.items():
|
||||
if action in existing_actions:
|
||||
continue
|
||||
@@ -2620,6 +2649,7 @@ class TaskScheduler:
|
||||
name=defs["name"],
|
||||
task_type="action",
|
||||
action=action,
|
||||
request_authority_json=seal_task_authority(None, "action", action, owner=owner),
|
||||
trigger_type=trigger_type,
|
||||
trigger_event=defs.get("trigger_event"),
|
||||
trigger_count=defs.get("trigger_count"),
|
||||
|
||||
Reference in New Issue
Block a user