mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-11-06 05:17:15 +00:00
refactor(kanban): drop the turn author from the worker spawn env
No turn reads it: the spawned worker client only submits kanban.run, and an owner gateway it starts strips HERMES_TURN_AUTHOR from its environment. The owner sets the author itself (previous commit). This restores the TERMINAL_CWD comment sentence about file_tools rejecting relative values. The chat -q forwarding stays: it gives -q the same author contract as -Q.
This commit is contained in:
1 parent
08f954e505
commit
95953ea5b7
2 files changed
+8
-46
No files matched your search
@@ -2814,10 +2814,10 @@ def _default_spawn(task: Task, workspace: str, *, board: Optional[str] = None) -
|
||||
# Tag the session `kanban` so session-browsing surfaces filter it out by
|
||||
# source instead of rendering one sidebar row per attempt.
|
||||
env["HERMES_SESSION_SOURCE"] = "kanban"
|
||||
# The worker's prompts are this dispatcher's, not the operator's: a bot author keeps memory
|
||||
# providers from filing "work kanban task t_..." and the worker's reply under the human's peer.
|
||||
from agent.turn_author import bot_author_id, turn_author_env
|
||||
env.update(turn_author_env({"id": bot_author_id("kanban"), "name": "Kanban dispatcher", "is_bot": True}))
|
||||
# TERMINAL_CWD takes precedence over process cwd in file_tools and
|
||||
# build_context_files_prompt; without it relative writes land in the gateway
|
||||
# user's home and workers load the gateway's AGENTS.md. file_tools rejects
|
||||
# relative / sentinel values, so only set a real absolute directory.
|
||||
# Pin TERMINAL_CWD to the task's workspace so the worker's file tools and context-file loader anchor on
|
||||
# the workspace, not whatever cwd the dispatching gateway happened to export. The worker subprocess is
|
||||
# already launched with cwd=workspace, but TERMINAL_CWD takes precedence over the process cwd in both
|
||||
|
||||
@@ -1,57 +1,19 @@
|
||||
"""A Kanban worker's turns are authored by the dispatcher, not the operator.
|
||||
"""A dispatcher-authored ``chat -q`` run carries its turn author, as ``chat -Q`` already does.
|
||||
|
||||
The dispatcher spawns ``hermes chat -q "work kanban task <id>"``. Without an author, memory providers
|
||||
filed that prompt and the worker's reply under the human's peer ("the user mentioned kanban task
|
||||
t_..."). The spawn now names a bot author and the non-quiet one-shot path forwards it to every turn,
|
||||
the same contract the quiet path and Bot Mode deliveries already follow.
|
||||
``HERMES_TURN_AUTHOR`` names who wrote a one-shot run's prompts. The non-quiet ``-q`` path ignored it,
|
||||
so the turn reached memory providers as the operator's and tool subprocesses inherited the variable.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
import cli
|
||||
from agent.turn_author import TURN_AUTHOR_ENV, parse_turn_author
|
||||
|
||||
|
||||
def _task(kb):
|
||||
return kb.Task(
|
||||
id="t_author", title="author", body=None, assignee="elias", status="running", priority=0,
|
||||
created_by="test", created_at=1, started_at=None, completed_at=None, workspace_kind="dir",
|
||||
workspace_path=None, claim_lock="lock", claim_expires=None, tenant=None, current_run_id=3,
|
||||
)
|
||||
|
||||
|
||||
def test_worker_spawn_names_the_dispatcher_as_a_bot_author(monkeypatch, tmp_path):
|
||||
root = tmp_path / ".hermes"
|
||||
(root / "profiles" / "elias").mkdir(parents=True)
|
||||
root.joinpath("config.yaml").write_text("{}\n", encoding="utf-8")
|
||||
monkeypatch.setenv("HERMES_HOME", str(root))
|
||||
monkeypatch.setenv(TURN_AUTHOR_ENV, '{"id": "operator", "name": "human", "is_bot": false}')
|
||||
|
||||
from hermes_cli import kanban_db as kb
|
||||
from hermes_cli import kanban_db_dispatch as kbd
|
||||
|
||||
monkeypatch.setattr(kbd, "_resolve_hermes_argv", lambda: ["hermes"])
|
||||
captured = {}
|
||||
|
||||
def fake_popen(cmd, *args, **kwargs):
|
||||
captured["env"] = dict(kwargs.get("env") or {})
|
||||
return SimpleNamespace(pid=4321)
|
||||
|
||||
monkeypatch.setattr(subprocess, "Popen", fake_popen)
|
||||
workspace = tmp_path / "workspace"
|
||||
workspace.mkdir()
|
||||
kbd._default_spawn(_task(kb), str(workspace))
|
||||
|
||||
author = parse_turn_author(captured["env"].get(TURN_AUTHOR_ENV))
|
||||
assert author is not None and author["is_bot"] is True
|
||||
assert author["id"].startswith("bot:")
|
||||
from agent.turn_author import TURN_AUTHOR_ENV
|
||||
|
||||
|
||||
def _one_shot_cli(monkeypatch):
|
||||
|
||||
Reference in new issue
Block a user