mirror of
https://github.com/TencentCloud/Octop.git
synced 2026-10-17 05:49:32 +08:00
* refactor(agents): group thin modules into domain subpackages Move plugin helpers, memory, settings stores, persona/MBTI, and avatar bootstrap code under plugins/, memory/, settings/, persona/, and experts/ while keeping top-level import shims so existing call sites stay stable. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(agents): drop compatibility shims after subpackage move Call sites already import the new package paths; remove the top-level re-export stubs so the agents tree only shows real modules. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(agents): move thread helpers into threads/ Group artifact shaping, fork, and context breakdown under agents/threads so top-level only keeps lifecycle/config adapters. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(agents): fold profile/runtime/tool catalog into settings/ Move the remaining config-surface helpers under settings/ and drop the skill_package id-list aliases in favor of dump/parse_id_list. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(agents): group workspace_dir and execute_env under workspace/ Keep path resolution and harness execute-env injection together as one workspace package; leave only manager and conversation_mode at top level. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(infra): fix history/SkillHub ownership and drop thin providers/ Move history_projection under history/, share SkillHub host/limits and route expert skill downloads through skills.skillhub_market, and fold Codex OAuth helpers into agents.providers to remove the tiny providers/ package. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: sync AGENTS.md and guides with infra/agents layout Reflect subpackages (settings/workspace/threads/persona, history/, skills/) and drop stale runtime.py / mbti_profiles paths after the agents reorg. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com>
166 lines
5.3 KiB
Python
166 lines
5.3 KiB
Python
"""tests/unit/agents/test_execute_env.py"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from octop.infra.agents.workspace.execute_env import inject_agent_execute_env
|
|
from octop.infra.db.repos.agents import AgentRow
|
|
from octop.infra.utils.env_file import save_env_file
|
|
from octop.infra.utils.paths import PathLayout
|
|
|
|
|
|
def _row(agent_id: str = "a1") -> AgentRow:
|
|
return AgentRow(
|
|
id=1,
|
|
agent_id=agent_id,
|
|
user_id=1,
|
|
name="test",
|
|
description=None,
|
|
persona_mbti=None,
|
|
default_model=None,
|
|
system_prompt=None,
|
|
enabled=1,
|
|
config_json=None,
|
|
last_state=None,
|
|
last_error=None,
|
|
created_at=0,
|
|
updated_at=0,
|
|
)
|
|
|
|
|
|
def test_inject_local_shell_uses_octop_auth_for_new_layout(tmp_path: Path, monkeypatch) -> None:
|
|
monkeypatch.setenv("OCTOP_HOME", str(tmp_path))
|
|
paths = PathLayout(tmp_path)
|
|
paths.ensure_root()
|
|
save_env_file(paths.root / "env", {"GLOBAL_KEY": "global"})
|
|
|
|
ws = paths.ensure_agent_workspace("agent-1")
|
|
(ws / ".env").write_text("AGENT_KEY=agent\n", encoding="utf-8")
|
|
|
|
spec = inject_agent_execute_env(
|
|
{"type": "local_shell", "root_dir": "/", "virtual_mode": True},
|
|
paths=paths,
|
|
row=_row("agent-1"),
|
|
workspace_dir=ws,
|
|
cfg={"system_files_path": ".octop"},
|
|
)
|
|
env = spec["env"]
|
|
assert env["OCTOP_AGENT_ID"] == "agent-1"
|
|
assert (ws / ".octop" / "auth").is_dir()
|
|
assert env["OCTOP_AUTH_DIR"] == str(ws / ".octop" / "auth")
|
|
assert env["OCTOP_HOME"] == str(paths.root)
|
|
assert env["OCTOP_SKILLS_DIR"] == str(ws / ".octop" / "skills")
|
|
assert "GLOBAL_KEY" not in env
|
|
assert "AGENT_KEY" not in env
|
|
assert spec["inherit_env"] is True
|
|
|
|
|
|
def test_inject_legacy_layout_keeps_root_octop_auth(tmp_path: Path, monkeypatch) -> None:
|
|
monkeypatch.setenv("OCTOP_HOME", str(tmp_path))
|
|
paths = PathLayout(tmp_path)
|
|
paths.ensure_root()
|
|
ws = paths.ensure_agent_workspace("agent-legacy")
|
|
|
|
spec = inject_agent_execute_env(
|
|
{"type": "local_shell", "root_dir": "/", "virtual_mode": True},
|
|
paths=paths,
|
|
row=_row("agent-legacy"),
|
|
workspace_dir=ws,
|
|
cfg={},
|
|
)
|
|
assert (ws / ".octop-auth").is_dir()
|
|
assert spec["env"]["OCTOP_AUTH_DIR"] == str(ws / ".octop-auth")
|
|
|
|
|
|
def test_inject_keeps_legacy_auth_when_tokens_already_there(tmp_path: Path, monkeypatch) -> None:
|
|
monkeypatch.setenv("OCTOP_HOME", str(tmp_path))
|
|
paths = PathLayout(tmp_path)
|
|
paths.ensure_root()
|
|
ws = paths.ensure_agent_workspace("agent-mig")
|
|
legacy = ws / ".octop-auth"
|
|
legacy.mkdir()
|
|
(legacy / "token.json").write_text("{}", encoding="utf-8")
|
|
|
|
spec = inject_agent_execute_env(
|
|
{"type": "local_shell", "root_dir": "/", "virtual_mode": True},
|
|
paths=paths,
|
|
row=_row("agent-mig"),
|
|
workspace_dir=ws,
|
|
cfg={"system_files_path": ".octop"},
|
|
)
|
|
assert spec["env"]["OCTOP_AUTH_DIR"] == str(legacy)
|
|
|
|
|
|
def test_inject_composite_default_local_shell(tmp_path: Path, monkeypatch) -> None:
|
|
monkeypatch.setenv("OCTOP_HOME", str(tmp_path))
|
|
paths = PathLayout(tmp_path)
|
|
paths.ensure_root()
|
|
ws = paths.ensure_agent_workspace("agent-c")
|
|
|
|
spec = inject_agent_execute_env(
|
|
{
|
|
"type": "composite",
|
|
"default": {"type": "local_shell", "root_dir": "/", "virtual_mode": True},
|
|
"routes": {},
|
|
},
|
|
paths=paths,
|
|
row=_row("agent-c"),
|
|
workspace_dir=ws,
|
|
cfg={"system_files_path": ".octop"},
|
|
)
|
|
assert spec["default"]["env"]["OCTOP_AGENT_ID"] == "agent-c"
|
|
assert spec["default"]["env"]["OCTOP_AUTH_DIR"] == str(ws / ".octop" / "auth")
|
|
assert spec["default"]["inherit_env"] is True
|
|
|
|
|
|
def test_inject_scoped_root_uses_agent_facing_auth_paths(tmp_path: Path, monkeypatch) -> None:
|
|
monkeypatch.setenv("OCTOP_HOME", str(tmp_path))
|
|
paths = PathLayout(tmp_path)
|
|
paths.ensure_root()
|
|
root = tmp_path / "scoped"
|
|
root.mkdir()
|
|
ws = root / ".octop" / "workspaces" / "agent-s"
|
|
ws.mkdir(parents=True)
|
|
cfg = {
|
|
"system_files_path": ".octop",
|
|
"workspace_dir": "/.octop/workspaces/agent-s",
|
|
"backend": {
|
|
"type": "local_shell",
|
|
"root_dir": str(root),
|
|
"virtual_mode": True,
|
|
},
|
|
}
|
|
|
|
spec = inject_agent_execute_env(
|
|
{"type": "local_shell", "root_dir": str(root), "virtual_mode": True},
|
|
paths=paths,
|
|
row=_row("agent-s"),
|
|
workspace_dir=ws,
|
|
cfg=cfg,
|
|
)
|
|
env = spec["env"]
|
|
assert (ws / ".octop" / "auth").is_dir()
|
|
assert env["OCTOP_AUTH_DIR"] == "/.octop/workspaces/agent-s/.octop/auth"
|
|
assert env["OCTOP_SKILLS_DIR"] == "/.octop/workspaces/agent-s/.octop/skills"
|
|
|
|
|
|
def test_inject_docker_only_sets_platform_defaults(tmp_path: Path, monkeypatch) -> None:
|
|
monkeypatch.setenv("OCTOP_HOME", str(tmp_path))
|
|
paths = PathLayout(tmp_path)
|
|
paths.ensure_root()
|
|
save_env_file(paths.root / "env", {"GLOBAL_KEY": "global"})
|
|
ws = paths.ensure_agent_workspace("agent-2")
|
|
|
|
spec = inject_agent_execute_env(
|
|
{"type": "docker"},
|
|
paths=paths,
|
|
row=_row("agent-2"),
|
|
workspace_dir=ws,
|
|
cfg={"system_files_path": ".octop"},
|
|
)
|
|
env = spec["env"]
|
|
assert env["OCTOP_AGENT_ID"] == "agent-2"
|
|
assert env["OCTOP_AUTH_DIR"] == str(ws / ".octop" / "auth")
|
|
assert "GLOBAL_KEY" not in env
|