repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
Mirrored from https://github.com/yingqi-z20/Agent-libOS
stars
latest
clone command
git clone gitlawb://did:key:z6MkqRzA...RfoM/yingqi-z20-Agen...git clone gitlawb://did:key:z6MkqRzA.../yingqi-z20-Agen...d98dd2c9IPC1d ago| #1 | from __future__ import annotations |
| #2 | |
| #3 | import asyncio |
| #4 | import tempfile |
| #5 | import unittest |
| #6 | from pathlib import Path |
| #7 | from types import SimpleNamespace |
| #8 | from unittest.mock import patch |
| #9 | |
| #10 | from agent_libos import Runtime |
| #11 | from agent_libos.capability.manager import CapabilityManager |
| #12 | from agent_libos.models import CapabilityRight |
| #13 | from agent_libos.substrate import LocalResourceProviderSubstrate |
| #14 | from scripts import run_coding_agent |
| #15 | |
| #16 | |
| #17 | class CodingAgentLauncherTests(unittest.TestCase): |
| #18 | def test_default_edit_preset_pregrants_workspace_write_not_delete(self) -> None: |
| #19 | with tempfile.TemporaryDirectory() as tmp: |
| #20 | args = run_coding_agent.build_parser().parse_args( |
| #21 | ["--goal", "edit the workspace", "--workspace", tmp, "--no-run"] |
| #22 | ) |
| #23 | runtime = Runtime.open("local", substrate=LocalResourceProviderSubstrate(Path(tmp))) |
| #24 | try: |
| #25 | pid = runtime.process.spawn(image="coding-agent:v0", goal=args.goal) |
| #26 | |
| #27 | grants = run_coding_agent.configure_coding_agent_permissions(runtime, pid, args) |
| #28 | |
| #29 | self.assertTrue(grants) |
| #30 | self.assertEqual( |
| #31 | runtime.capability.permission_policy( |
| #32 | pid, |
| #33 | runtime.filesystem.workspace_resource(), |
| #34 | CapabilityRight.WRITE, |
| #35 | ), |
| #36 | CapabilityManager.ALWAYS_ALLOW, |
| #37 | ) |
| #38 | self.assertEqual( |
| #39 | runtime.capability.permission_policy( |
| #40 | pid, |
| #41 | runtime.filesystem.workspace_resource(), |
| #42 | CapabilityRight.DELETE, |
| #43 | ), |
| #44 | CapabilityManager.MISSING, |
| #45 | ) |
| #46 | finally: |
| #47 | runtime.close() |
| #48 | |
| #49 | def test_read_only_preset_can_add_specific_write_and_delete_grants(self) -> None: |
| #50 | with tempfile.TemporaryDirectory() as tmp: |
| #51 | args = run_coding_agent.build_parser().parse_args( |
| #52 | [ |
| #53 | "--goal", |
| #54 | "edit selected paths", |
| #55 | "--workspace", |
| #56 | tmp, |
| #57 | "--permission-preset", |
| #58 | "read-only", |
| #59 | "--write-file", |
| #60 | "src/main.py", |
| #61 | "--delete-dir", |
| #62 | "build", |
| #63 | "--no-run", |
| #64 | ] |
| #65 | ) |
| #66 | runtime = Runtime.open("local", substrate=LocalResourceProviderSubstrate(Path(tmp))) |
| #67 | try: |
| #68 | pid = runtime.process.spawn(image="coding-agent:v0", goal=args.goal) |
| #69 | |
| #70 | run_coding_agent.configure_coding_agent_permissions(runtime, pid, args) |
| #71 | |
| #72 | self.assertEqual( |
| #73 | runtime.capability.permission_policy( |
| #74 | pid, |
| #75 | runtime.filesystem.resource_for_path("src/main.py"), |
| #76 | CapabilityRight.WRITE, |
| #77 | ), |
| #78 | CapabilityManager.ALWAYS_ALLOW, |
| #79 | ) |
| #80 | self.assertEqual( |
| #81 | runtime.capability.permission_policy( |
| #82 | pid, |
| #83 | runtime.filesystem.directory_resource_for_path("build"), |
| #84 | CapabilityRight.DELETE, |
| #85 | ), |
| #86 | CapabilityManager.ALWAYS_ALLOW, |
| #87 | ) |
| #88 | self.assertEqual( |
| #89 | runtime.capability.permission_policy( |
| #90 | pid, |
| #91 | runtime.filesystem.workspace_resource(), |
| #92 | CapabilityRight.WRITE, |
| #93 | ), |
| #94 | CapabilityManager.MISSING, |
| #95 | ) |
| #96 | finally: |
| #97 | runtime.close() |
| #98 | |
| #99 | def test_launcher_loads_project_env_before_workspace_mount(self) -> None: |
| #100 | with tempfile.TemporaryDirectory() as tmp: |
| #101 | project_root = Path(tmp) |
| #102 | env_file = project_root / ".env" |
| #103 | env_file.write_text("OPENAI_MODEL=test\n", encoding="utf-8") |
| #104 | args = run_coding_agent.build_parser().parse_args( |
| #105 | ["--goal", "inspect", "--workspace", ".", "--no-run"] |
| #106 | ) |
| #107 | |
| #108 | with ( |
| #109 | patch.object(run_coding_agent, "PROJECT_ROOT", project_root), |
| #110 | patch.object(run_coding_agent, "load_dotenv") as load, |
| #111 | ): |
| #112 | run_coding_agent._load_env(args) |
| #113 | |
| #114 | load.assert_called_once_with(env_file) |
| #115 | |
| #116 | def test_launcher_does_not_change_host_working_directory(self) -> None: |
| #117 | with tempfile.TemporaryDirectory() as tmp: |
| #118 | before = Path.cwd() |
| #119 | args = run_coding_agent.build_parser().parse_args( |
| #120 | ["--goal", "inspect", "--workspace", tmp, "--ephemeral-db", "--no-run"] |
| #121 | ) |
| #122 | |
| #123 | with patch.object(run_coding_agent, "load_dotenv"): |
| #124 | asyncio.run(run_coding_agent.amain(args)) |
| #125 | |
| #126 | self.assertEqual(Path.cwd(), before) |
| #127 | |
| #128 | def test_explicit_missing_env_file_is_rejected(self) -> None: |
| #129 | with tempfile.TemporaryDirectory() as tmp: |
| #130 | missing = Path(tmp) / "missing.env" |
| #131 | args = run_coding_agent.build_parser().parse_args( |
| #132 | ["--goal", "inspect", "--workspace", ".", "--env-file", str(missing), "--no-run"] |
| #133 | ) |
| #134 | |
| #135 | with self.assertRaises(SystemExit): |
| #136 | run_coding_agent._load_env(args) |
| #137 | |
| #138 | def test_audit_counts_are_scoped_to_launched_process(self) -> None: |
| #139 | records = [ |
| #140 | SimpleNamespace(actor="pid_current", action="llm.request"), |
| #141 | SimpleNamespace(actor="pid_other", action="llm.action_repair_requested"), |
| #142 | SimpleNamespace(actor="pid_current", action="llm.action_repair_requested"), |
| #143 | ] |
| #144 | |
| #145 | counts = run_coding_agent._audit_counts_for_process(records, "pid_current") |
| #146 | |
| #147 | self.assertEqual(counts["audit_records"], 2) |
| #148 | self.assertEqual(counts["audit_records_total"], 3) |
| #149 | self.assertEqual(counts["llm_repair_attempts"], 1) |
| #150 | |
| #151 | |
| #152 | if __name__ == "__main__": |
| #153 | unittest.main() |
| #154 |