mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-06-15 07:14:08 +00:00
refactor: centralize cron session metadata keys
This commit is contained in:
parent
0e3a57b371
commit
d9d481bc15
@ -130,7 +130,7 @@ Instead, persist a readable automation trigger event, for example:
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Scheduled automation triggered: daily monitor\n\nCheck ...",
|
||||
"_automation_trigger": true,
|
||||
"_automation_turn": true,
|
||||
"automation_id": "abc123",
|
||||
"automation_name": "daily monitor",
|
||||
"automation_run_id": "abc123:1770000000000",
|
||||
|
||||
@ -40,6 +40,7 @@ from nanobot.bus.runtime_events import (
|
||||
from nanobot.command import CommandContext, CommandRouter, register_builtin_commands
|
||||
from nanobot.config.schema import AgentDefaults, ModelPresetConfig
|
||||
from nanobot.cron.automation import (
|
||||
AUTOMATION_HISTORY_META,
|
||||
automation_run_id,
|
||||
automation_trigger,
|
||||
defer_until_session_idle,
|
||||
@ -57,6 +58,7 @@ from nanobot.session.goal_state import (
|
||||
runner_wall_llm_timeout_s,
|
||||
sustained_goal_active,
|
||||
)
|
||||
from nanobot.session.keys import UNIFIED_SESSION_KEY, session_key_for_channel
|
||||
from nanobot.session.manager import Session, SessionManager
|
||||
from nanobot.session.routing import persist_routing_context
|
||||
from nanobot.utils.document import extract_documents, reference_non_image_attachments
|
||||
@ -78,8 +80,6 @@ if TYPE_CHECKING:
|
||||
from nanobot.cron.service import CronService
|
||||
|
||||
|
||||
UNIFIED_SESSION_KEY = "unified:default"
|
||||
|
||||
class TurnState(Enum):
|
||||
RESTORE = auto()
|
||||
COMPACT = auto()
|
||||
@ -522,12 +522,11 @@ class AgentLoop:
|
||||
"""Update context for all tools that need routing info."""
|
||||
from nanobot.agent.tools.context import ContextAware
|
||||
|
||||
if session_key is not None:
|
||||
effective_key = session_key
|
||||
elif self._unified_session:
|
||||
effective_key = UNIFIED_SESSION_KEY
|
||||
else:
|
||||
effective_key = f"{channel}:{chat_id}"
|
||||
effective_key = session_key or session_key_for_channel(
|
||||
channel,
|
||||
chat_id,
|
||||
unified_session=self._unified_session,
|
||||
)
|
||||
request_ctx = RequestContext(
|
||||
channel=channel,
|
||||
chat_id=chat_id,
|
||||
@ -646,7 +645,7 @@ class AgentLoop:
|
||||
if isinstance(persist_content, str) and persist_content.strip():
|
||||
text = persist_content
|
||||
extra.update({
|
||||
"_automation_trigger": True,
|
||||
AUTOMATION_HISTORY_META: True,
|
||||
"automation_id": trigger.get("job_id"),
|
||||
"automation_name": trigger.get("job_name"),
|
||||
"automation_run_id": trigger.get("run_id"),
|
||||
|
||||
@ -142,7 +142,7 @@ class CronTool(Tool, ContextAware):
|
||||
if action == "add":
|
||||
if self._in_cron_context.get():
|
||||
return "Error: cannot schedule new jobs from within a cron job execution"
|
||||
return self._add_job(name, message, every_seconds, cron_expr, tz, at, deliver)
|
||||
return self._add_job(name, message, every_seconds, cron_expr, tz, at)
|
||||
elif action == "list":
|
||||
return self._list_jobs()
|
||||
elif action == "remove":
|
||||
@ -157,7 +157,6 @@ class CronTool(Tool, ContextAware):
|
||||
cron_expr: str | None,
|
||||
tz: str | None,
|
||||
at: str | None,
|
||||
deliver: bool = True,
|
||||
) -> str:
|
||||
if not message:
|
||||
return (
|
||||
|
||||
@ -64,6 +64,10 @@ from nanobot.utils.restart import ( # noqa: E402
|
||||
format_restart_completed_message,
|
||||
should_show_cli_restart_notice,
|
||||
)
|
||||
from nanobot.webui.metadata import ( # noqa: E402
|
||||
WEBUI_MESSAGE_SOURCE_METADATA_KEY,
|
||||
WEBUI_TURN_METADATA_KEY,
|
||||
)
|
||||
|
||||
|
||||
def _sanitize_surrogates(text: str) -> str:
|
||||
@ -89,8 +93,6 @@ class SafeFileHistory(FileHistory):
|
||||
super().store_string(_sanitize_surrogates(string))
|
||||
|
||||
|
||||
_WEBUI_TURN_META_KEY = "webui_turn_id"
|
||||
_WEBUI_MESSAGE_SOURCE_META_KEY = "_webui_message_source"
|
||||
_PROACTIVE_WEBUI_METADATA: ContextVar[dict[str, Any] | None] = ContextVar(
|
||||
"proactive_webui_metadata",
|
||||
default=None,
|
||||
@ -106,13 +108,13 @@ def _proactive_delivery_metadata(
|
||||
) -> dict[str, Any]:
|
||||
"""Return channel metadata for a fresh proactive delivery turn."""
|
||||
out = dict(metadata or {})
|
||||
out.pop(_WEBUI_TURN_META_KEY, None)
|
||||
out.pop(WEBUI_TURN_METADATA_KEY, None)
|
||||
if channel == "websocket":
|
||||
out[_WEBUI_TURN_META_KEY] = f"{turn_seed}:{uuid.uuid4().hex}"
|
||||
out[WEBUI_TURN_METADATA_KEY] = f"{turn_seed}:{uuid.uuid4().hex}"
|
||||
source: dict[str, str] = {"kind": "cron"}
|
||||
if source_label:
|
||||
source["label"] = source_label
|
||||
out[_WEBUI_MESSAGE_SOURCE_META_KEY] = source
|
||||
out[WEBUI_MESSAGE_SOURCE_METADATA_KEY] = source
|
||||
return out
|
||||
|
||||
app = typer.Typer(
|
||||
@ -1034,14 +1036,14 @@ def _run_gateway(
|
||||
schedule_background=lambda coro: agent._schedule_background(coro),
|
||||
).subscribe(runtime_events)
|
||||
|
||||
from nanobot.agent.loop import UNIFIED_SESSION_KEY
|
||||
from nanobot.bus.events import InboundMessage, OutboundMessage
|
||||
from nanobot.session.keys import session_key_for_channel
|
||||
|
||||
def _channel_session_key(channel: str, chat_id: str) -> str:
|
||||
return (
|
||||
UNIFIED_SESSION_KEY
|
||||
if config.agents.defaults.unified_session
|
||||
else f"{channel}:{chat_id}"
|
||||
return session_key_for_channel(
|
||||
channel,
|
||||
chat_id,
|
||||
unified_session=config.agents.defaults.unified_session,
|
||||
)
|
||||
|
||||
def _session_metadata(session_key: str) -> dict[str, Any]:
|
||||
@ -1125,17 +1127,20 @@ def _run_gateway(
|
||||
),
|
||||
}
|
||||
metadata[AUTOMATION_DEFER_UNTIL_IDLE_META] = True
|
||||
run_record_base: dict[str, Any] = {
|
||||
"job_id": job.id,
|
||||
"job_name": job.name,
|
||||
"session_key": session_key,
|
||||
"prompt_ref": prompt_ref,
|
||||
"prompt_vars": {"message": job.payload.message},
|
||||
"rendered_prompt": prompt,
|
||||
}
|
||||
|
||||
cron.write_run_record(
|
||||
run_id,
|
||||
{
|
||||
"job_id": job.id,
|
||||
"job_name": job.name,
|
||||
"session_key": session_key,
|
||||
**run_record_base,
|
||||
"status": "queued",
|
||||
"prompt_ref": prompt_ref,
|
||||
"prompt_vars": {"message": job.payload.message},
|
||||
"rendered_prompt": prompt,
|
||||
},
|
||||
)
|
||||
|
||||
@ -1159,14 +1164,9 @@ def _run_gateway(
|
||||
cron.write_run_record(
|
||||
run_id,
|
||||
{
|
||||
"job_id": job.id,
|
||||
"job_name": job.name,
|
||||
"session_key": session_key,
|
||||
**run_record_base,
|
||||
"status": "error",
|
||||
"error": error_text,
|
||||
"prompt_ref": prompt_ref,
|
||||
"prompt_vars": {"message": job.payload.message},
|
||||
"rendered_prompt": prompt,
|
||||
},
|
||||
)
|
||||
raise
|
||||
@ -1178,13 +1178,8 @@ def _run_gateway(
|
||||
cron.write_run_record(
|
||||
run_id,
|
||||
{
|
||||
"job_id": job.id,
|
||||
"job_name": job.name,
|
||||
"session_key": session_key,
|
||||
**run_record_base,
|
||||
"status": "ok",
|
||||
"prompt_ref": prompt_ref,
|
||||
"prompt_vars": {"message": job.payload.message},
|
||||
"rendered_prompt": prompt,
|
||||
"response": response,
|
||||
},
|
||||
)
|
||||
|
||||
@ -8,6 +8,7 @@ from nanobot.cron.types import CronJob
|
||||
|
||||
AUTOMATION_TRIGGER_META = "_automation_trigger"
|
||||
AUTOMATION_DEFER_UNTIL_IDLE_META = "_defer_until_session_idle"
|
||||
AUTOMATION_HISTORY_META = "_automation_turn"
|
||||
|
||||
|
||||
def automation_trigger(metadata: Mapping[str, Any] | None) -> dict[str, Any] | None:
|
||||
|
||||
12
nanobot/session/keys.py
Normal file
12
nanobot/session/keys.py
Normal file
@ -0,0 +1,12 @@
|
||||
"""Shared session key constants and helpers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
UNIFIED_SESSION_KEY = "unified:default"
|
||||
|
||||
|
||||
def session_key_for_channel(channel: str, chat_id: str, *, unified_session: bool = False) -> str:
|
||||
"""Return the session key for a channel/chat pair."""
|
||||
if unified_session:
|
||||
return UNIFIED_SESSION_KEY
|
||||
return f"{channel}:{chat_id}"
|
||||
@ -14,6 +14,7 @@ from typing import Any
|
||||
from loguru import logger
|
||||
|
||||
from nanobot.config.paths import get_legacy_sessions_dir
|
||||
from nanobot.session.metadata import SESSION_ROUTING_METADATA_KEY
|
||||
from nanobot.utils.helpers import (
|
||||
ensure_dir,
|
||||
estimate_message_tokens,
|
||||
@ -36,7 +37,7 @@ _FORK_VOLATILE_METADATA_KEYS = {
|
||||
"pending_user_turn",
|
||||
"runtime_checkpoint",
|
||||
"thread_goal",
|
||||
"_routing_context",
|
||||
SESSION_ROUTING_METADATA_KEY,
|
||||
"title",
|
||||
"title_user_edited",
|
||||
}
|
||||
|
||||
3
nanobot/session/metadata.py
Normal file
3
nanobot/session/metadata.py
Normal file
@ -0,0 +1,3 @@
|
||||
"""Shared session metadata keys."""
|
||||
|
||||
SESSION_ROUTING_METADATA_KEY = "_routing_context"
|
||||
@ -7,8 +7,7 @@ from typing import Any, Mapping
|
||||
from nanobot.bus.events import InboundMessage
|
||||
from nanobot.cron.automation import is_automation_turn
|
||||
from nanobot.session.manager import Session
|
||||
|
||||
SESSION_ROUTING_METADATA_KEY = "_routing_context"
|
||||
from nanobot.session.metadata import SESSION_ROUTING_METADATA_KEY
|
||||
|
||||
_ROUTING_METADATA_KEYS = {
|
||||
"chat_type",
|
||||
|
||||
4
nanobot/webui/metadata.py
Normal file
4
nanobot/webui/metadata.py
Normal file
@ -0,0 +1,4 @@
|
||||
"""Shared WebUI metadata keys."""
|
||||
|
||||
WEBUI_TURN_METADATA_KEY = "webui_turn_id"
|
||||
WEBUI_MESSAGE_SOURCE_METADATA_KEY = "_webui_message_source"
|
||||
@ -18,6 +18,7 @@ from loguru import logger
|
||||
|
||||
from nanobot.config.paths import get_webui_dir
|
||||
from nanobot.session.manager import SessionManager
|
||||
from nanobot.webui.metadata import WEBUI_MESSAGE_SOURCE_METADATA_KEY, WEBUI_TURN_METADATA_KEY
|
||||
|
||||
WEBUI_TRANSCRIPT_SCHEMA_VERSION = 3
|
||||
WEBUI_FORK_MARKER_EVENT = "fork_marker"
|
||||
@ -29,8 +30,6 @@ _TRANSCRIPT_SEGMENT_RE = re.compile(r"^\d{6}\.jsonl$")
|
||||
_DEFAULT_TRANSCRIPT_PAGE_LIMIT = 160
|
||||
_MAX_TRANSCRIPT_PAGE_LIMIT = 1000
|
||||
_WEBUI_TURN_ID_RE = re.compile(r"^[A-Za-z0-9._:-]{1,128}$")
|
||||
WEBUI_TURN_METADATA_KEY = "webui_turn_id"
|
||||
WEBUI_MESSAGE_SOURCE_METADATA_KEY = "_webui_message_source"
|
||||
_MARKDOWN_LOCAL_IMAGE_RE = re.compile(
|
||||
r"!\[([^\]]*)\]\((<[^>]+>|[^)\s]+)(\s+(?:\"[^\"]*\"|'[^']*'))?\)"
|
||||
)
|
||||
|
||||
@ -20,8 +20,8 @@ from loguru import logger
|
||||
from websockets.http11 import Request as WsRequest
|
||||
from websockets.http11 import Response
|
||||
|
||||
from nanobot.agent.loop import UNIFIED_SESSION_KEY
|
||||
from nanobot.command.builtin import builtin_command_palette
|
||||
from nanobot.session.keys import UNIFIED_SESSION_KEY
|
||||
from nanobot.utils.subagent_channel_display import scrub_subagent_messages_for_channel
|
||||
from nanobot.webui.file_preview import WebUIFilePreviewError, file_preview_payload
|
||||
from nanobot.webui.gateway_tokens import GatewayTokenStore, token_response_payload
|
||||
|
||||
@ -8,6 +8,7 @@ from nanobot.agent.context import ContextBuilder
|
||||
from nanobot.agent.loop import AgentLoop
|
||||
from nanobot.bus.events import InboundMessage
|
||||
from nanobot.bus.queue import MessageBus
|
||||
from nanobot.cron.automation import AUTOMATION_HISTORY_META, AUTOMATION_TRIGGER_META
|
||||
from nanobot.providers.base import LLMResponse
|
||||
from nanobot.session.goal_state import GOAL_STATE_KEY
|
||||
from nanobot.session.manager import Session, SessionManager
|
||||
@ -65,6 +66,41 @@ def test_agent_loop_llm_runtime_reflects_current_provider_and_model(tmp_path: Pa
|
||||
assert runtime.model == "next-model"
|
||||
|
||||
|
||||
def test_persist_automation_turn_uses_distinct_history_marker(tmp_path: Path) -> None:
|
||||
loop = _make_full_loop(tmp_path)
|
||||
session = loop.sessions.get_or_create("websocket:auto")
|
||||
prompt_ref = {"id": "cron.agent_turn.reminder", "version": 1, "sha256": "abc"}
|
||||
|
||||
persisted = loop._persist_user_message_early(
|
||||
InboundMessage(
|
||||
channel="websocket",
|
||||
sender_id="cron",
|
||||
chat_id="auto",
|
||||
content="Automation: internal prompt",
|
||||
metadata={
|
||||
AUTOMATION_TRIGGER_META: {
|
||||
"job_id": "job-1",
|
||||
"job_name": "Daily check",
|
||||
"run_id": "job-1:1",
|
||||
"prompt_ref": prompt_ref,
|
||||
"persist_content": "Scheduled automation triggered: Daily check",
|
||||
}
|
||||
},
|
||||
),
|
||||
session,
|
||||
)
|
||||
|
||||
assert persisted is True
|
||||
message = session.messages[-1]
|
||||
assert message["content"] == "Scheduled automation triggered: Daily check"
|
||||
assert message[AUTOMATION_HISTORY_META] is True
|
||||
assert AUTOMATION_TRIGGER_META not in message
|
||||
assert message["automation_id"] == "job-1"
|
||||
assert message["automation_name"] == "Daily check"
|
||||
assert message["automation_run_id"] == "job-1:1"
|
||||
assert message["automation_prompt_ref"] == prompt_ref
|
||||
|
||||
|
||||
def test_clean_generated_title_strips_reasoning_tags() -> None:
|
||||
assert clean_generated_title("<think>reasoning</think> WebUI polish") == "WebUI polish"
|
||||
assert clean_generated_title("Title: <think> The user said hello") == ""
|
||||
|
||||
@ -592,8 +592,8 @@ async def test_waiting_dispatch_does_not_replace_active_pending_queue(tmp_path):
|
||||
@pytest.mark.asyncio
|
||||
async def test_followup_routed_to_pending_queue(tmp_path):
|
||||
"""Unified-session follow-ups should route into the active pending queue."""
|
||||
from nanobot.agent.loop import UNIFIED_SESSION_KEY
|
||||
from nanobot.bus.events import InboundMessage
|
||||
from nanobot.session.keys import UNIFIED_SESSION_KEY
|
||||
|
||||
loop = _make_loop(tmp_path)
|
||||
loop._unified_session = True
|
||||
|
||||
@ -11,10 +11,10 @@ from urllib.parse import urlencode
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
from nanobot.agent.loop import UNIFIED_SESSION_KEY
|
||||
from nanobot.channels.websocket import WebSocketChannel, WebSocketConfig
|
||||
from nanobot.cron.service import CronService
|
||||
from nanobot.cron.types import CronJob, CronPayload, CronSchedule
|
||||
from nanobot.session.keys import UNIFIED_SESSION_KEY
|
||||
from nanobot.session.manager import Session, SessionManager
|
||||
from nanobot.webui.gateway_services import GatewayServices, build_gateway_services
|
||||
|
||||
|
||||
@ -11,11 +11,13 @@ from typer.testing import CliRunner
|
||||
from nanobot.bus.events import InboundMessage, OutboundMessage
|
||||
from nanobot.cli.commands import _proactive_delivery_metadata, app
|
||||
from nanobot.config.schema import Config
|
||||
from nanobot.cron.automation import AUTOMATION_DEFER_UNTIL_IDLE_META, AUTOMATION_TRIGGER_META
|
||||
from nanobot.cron.types import CronJob, CronPayload
|
||||
from nanobot.providers.factory import ProviderSnapshot, make_provider
|
||||
from nanobot.providers.openai_codex_provider import _strip_model_prefix
|
||||
from nanobot.providers.registry import find_by_name
|
||||
from nanobot.session.routing import SESSION_ROUTING_METADATA_KEY
|
||||
from nanobot.webui.metadata import WEBUI_MESSAGE_SOURCE_METADATA_KEY, WEBUI_TURN_METADATA_KEY
|
||||
|
||||
runner = CliRunner()
|
||||
|
||||
@ -23,7 +25,7 @@ runner = CliRunner()
|
||||
def test_proactive_websocket_delivery_gets_fresh_turn_id() -> None:
|
||||
metadata = {
|
||||
"webui": True,
|
||||
"webui_turn_id": "turn-that-created-the-reminder",
|
||||
WEBUI_TURN_METADATA_KEY: "turn-that-created-the-reminder",
|
||||
"workspace_scope": {"mode": "default"},
|
||||
}
|
||||
|
||||
@ -36,9 +38,9 @@ def test_proactive_websocket_delivery_gets_fresh_turn_id() -> None:
|
||||
|
||||
assert out["webui"] is True
|
||||
assert out["workspace_scope"] == {"mode": "default"}
|
||||
assert out["webui_turn_id"].startswith("cron:drink-water:")
|
||||
assert out["webui_turn_id"] != metadata["webui_turn_id"]
|
||||
assert out["_webui_message_source"] == {"kind": "cron", "label": "drink water"}
|
||||
assert out[WEBUI_TURN_METADATA_KEY].startswith("cron:drink-water:")
|
||||
assert out[WEBUI_TURN_METADATA_KEY] != metadata[WEBUI_TURN_METADATA_KEY]
|
||||
assert out[WEBUI_MESSAGE_SOURCE_METADATA_KEY] == {"kind": "cron", "label": "drink water"}
|
||||
|
||||
|
||||
def _fake_provider():
|
||||
@ -1350,7 +1352,7 @@ def test_gateway_cron_evaluator_receives_scheduled_reminder_context(
|
||||
to="chat-1",
|
||||
channel_meta={
|
||||
"webui": True,
|
||||
"webui_turn_id": old_turn_id,
|
||||
WEBUI_TURN_METADATA_KEY: old_turn_id,
|
||||
"workspace_scope": {"mode": "default"},
|
||||
},
|
||||
),
|
||||
@ -1365,9 +1367,9 @@ def test_gateway_cron_evaluator_receives_scheduled_reminder_context(
|
||||
assert delivered.chat_id == "chat-1"
|
||||
assert delivered.metadata["webui"] is True
|
||||
assert delivered.metadata["workspace_scope"] == {"mode": "default"}
|
||||
assert delivered.metadata["webui_turn_id"].startswith("cron:drink-water:")
|
||||
assert delivered.metadata["webui_turn_id"] != old_turn_id
|
||||
assert delivered.metadata["_webui_message_source"] == {
|
||||
assert delivered.metadata[WEBUI_TURN_METADATA_KEY].startswith("cron:drink-water:")
|
||||
assert delivered.metadata[WEBUI_TURN_METADATA_KEY] != old_turn_id
|
||||
assert delivered.metadata[WEBUI_MESSAGE_SOURCE_METADATA_KEY] == {
|
||||
"kind": "cron",
|
||||
"label": "drink water",
|
||||
}
|
||||
@ -1653,14 +1655,17 @@ def test_gateway_bound_cron_runs_as_session_turn(
|
||||
assert "Automation: Check repository health." in msg.content
|
||||
assert msg.metadata["webui"] is True
|
||||
assert msg.metadata["workspace_scope"]["project_path"] == str(tmp_path)
|
||||
assert msg.metadata["_webui_message_source"] == {"kind": "cron", "label": "Repo check"}
|
||||
trigger = msg.metadata["_automation_trigger"]
|
||||
assert msg.metadata[WEBUI_MESSAGE_SOURCE_METADATA_KEY] == {
|
||||
"kind": "cron",
|
||||
"label": "Repo check",
|
||||
}
|
||||
trigger = msg.metadata[AUTOMATION_TRIGGER_META]
|
||||
assert trigger["job_id"] == "repo-check"
|
||||
assert trigger["job_name"] == "Repo check"
|
||||
assert trigger["persist_content"] == (
|
||||
"Scheduled automation triggered: Repo check\n\nCheck repository health."
|
||||
)
|
||||
assert msg.metadata["_defer_until_session_idle"] is True
|
||||
assert msg.metadata[AUTOMATION_DEFER_UNTIL_IDLE_META] is True
|
||||
statuses = [record["status"] for _run_id, record in seen["run_records"]]
|
||||
assert statuses == ["queued", "ok"]
|
||||
assert seen["run_records"][0][0] == seen["run_records"][1][0]
|
||||
|
||||
@ -347,7 +347,7 @@ def test_add_job_requires_session_key(tmp_path) -> None:
|
||||
tool = _make_tool(tmp_path)
|
||||
tool.set_context(RequestContext(channel="telegram", chat_id="chat-1"))
|
||||
|
||||
result = tool._add_job(None, "Background refresh", 60, None, None, None, deliver=False)
|
||||
result = tool._add_job(None, "Background refresh", 60, None, None, None)
|
||||
|
||||
assert result == "Error: scheduled automations must be created from a chat session"
|
||||
assert tool._cron.list_jobs() == []
|
||||
|
||||
@ -10,6 +10,7 @@ from nanobot.agent.tools.cron import CronTool
|
||||
from nanobot.agent.tools.message import MessageTool
|
||||
from nanobot.agent.tools.spawn import SpawnTool
|
||||
from nanobot.cron.service import CronService
|
||||
from nanobot.session.keys import UNIFIED_SESSION_KEY
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@ -262,7 +263,7 @@ async def test_webui_cron_tool_uses_unified_session_when_enabled(tmp_path) -> No
|
||||
"websocket",
|
||||
"chat-123",
|
||||
metadata={"webui": True},
|
||||
session_key="unified:default",
|
||||
session_key=UNIFIED_SESSION_KEY,
|
||||
)
|
||||
|
||||
result = await tool.execute(action="add", message="standup", every_seconds=300)
|
||||
@ -270,7 +271,7 @@ async def test_webui_cron_tool_uses_unified_session_when_enabled(tmp_path) -> No
|
||||
|
||||
jobs = tool._cron.list_jobs()
|
||||
assert len(jobs) == 1
|
||||
assert jobs[0].payload.session_key == "unified:default"
|
||||
assert jobs[0].payload.session_key == UNIFIED_SESSION_KEY
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user