coderio 0.4.2__tar.gz → 0.4.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {coderio-0.4.2 → coderio-0.4.3}/CHANGELOG.md +18 -0
- coderio-0.4.3/PKG-INFO +148 -0
- coderio-0.4.3/README.md +103 -0
- coderio-0.4.3/README_en.md +103 -0
- {coderio-0.4.2 → coderio-0.4.3}/pyproject.toml +7 -7
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/deep_loop.py +12 -11
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/repl.py +9 -3
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/config/loader.py +5 -6
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/config/trust.py +55 -6
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/command_policy.py +95 -25
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/win_sandbox.py +0 -4
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_deepagents_compat.py +12 -2
- {coderio-0.4.2 → coderio-0.4.3}/tests/config/test_trust.py +144 -2
- coderio-0.4.3/tests/test_seams.py +894 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_command_policy.py +36 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_sandbox.py +99 -0
- coderio-0.4.2/PKG-INFO +0 -535
- coderio-0.4.2/README.md +0 -487
- coderio-0.4.2/README_en.md +0 -490
- {coderio-0.4.2 → coderio-0.4.3}/.github/dependabot.yml +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/.github/workflows/ci.yml +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/.github/workflows/release.yml +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/.gitignore +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/CONTRIBUTING.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/LICENSE +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/THIRD_PARTY_LICENSES.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/docs/coderio-architecture.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/scripts/verify_deepagent_live.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/scripts/verify_harness_live.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/_deepagents_compat.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/command_review.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/harness.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/harness_middleware.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/hooks.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/permission_middleware.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/prompts.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/skill_tool.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/state.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/agent/stream.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/app.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/commands.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/credentials.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/mcp_cmd.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/multimodal.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/onboarding.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/providers.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/render.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/run_cmd.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/skills_cmd.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/stream.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/tui.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/tui_onboarding.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/tui_screens.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/cli/tui_widgets.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/config/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/config/bootstrap.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/config/models.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/llm/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/llm/factory.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/llm/probe.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/mcp_loader.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/session/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/session/message.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/session/store.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/bundled/executing-plans/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/LICENSE +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/README.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/clarifying-questions/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/clarifying-questions/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/code-review/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/code-review/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/commit-message/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/commit-message/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/debugging/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/debugging/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/error-handling/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/error-handling/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/lion-writing-skills/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/lion-writing-skills/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/naming/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/naming/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/onboarding-unknown-codebase/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/onboarding-unknown-codebase/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/spec-writing/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/spec-writing/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/task-breakdown/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/task-breakdown/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/testing/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/testing/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/verify-and-fix/SKILL.md +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/lion-skills/skills/verify-and-fix/evals/evals.json +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/models.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/parser.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/skills/store.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/base.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/bash.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/edit_file.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/glob_tool.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/grep_tool.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/linux_sandbox.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/list_dir.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/multi_edit.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/note.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/permission.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/read_file.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/sandbox_runner.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/todo.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/web_fetch.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/web_search.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/win_job.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/src/coderio/tools/write_file.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/conftest.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_command_review.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_deep_integration.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_deep_loop.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_deep_loop_unit.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_harness.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_harness_middleware.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_hooks.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_perf_baseline.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_prompts.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_skill_tool.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_state.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/agent/test_stream.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_app.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_command_menu.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_commands.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_credentials.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_input_isolation.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_live_thinking.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_mcp_cmd.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_multimodal.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_onboarding.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_onboarding_logic.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_providers.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_render.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_repl_loop.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_repl_reset.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_run_cmd.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_skills_cmd.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_status_bar.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_stream.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_truncation.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_tui_onboarding.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_tui_picker.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_tui_screens.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_tui_startup.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_tui_widgets.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/cli/test_ux_features.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/config/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/config/test_bootstrap.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/config/test_loader.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/config/test_models.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/conftest.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/e2e/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/llm/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/llm/test_factory.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/llm/test_probe.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/session/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/session/test_message.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/session/test_store.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/skills/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/skills/test_bundled.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/skills/test_parser.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/skills/test_skill_tools.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/skills/test_store.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/test_mcp_loader.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/test_p0_stability.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/test_repl.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/test_version.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/__init__.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_bash.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_concrete_gates.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_edit_prefix.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_file_tools.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_glob_tool.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_grep_tool.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_list_dir.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_multi_edit.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_note.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_permission.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_registry.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_search_tools.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_todo.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_web.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_web_fetch.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/tests/tools/test_win_job.py +0 -0
- {coderio-0.4.2 → coderio-0.4.3}/uv.lock +0 -0
|
@@ -6,6 +6,24 @@ All notable changes to coderio are documented here. The format follows
|
|
|
6
6
|
`pyproject.toml`'s `[project].version` — `coderio.__version__` reads it via
|
|
7
7
|
`importlib.metadata`.
|
|
8
8
|
|
|
9
|
+
## [0.4.3] — 2026-08-21
|
|
10
|
+
|
|
11
|
+
### Security — P1/P2 hardening (audit-verified, adversarial + mutation tested)
|
|
12
|
+
- **command_policy**: replaced fragile `_RM_RECURSIVE_PREFIX` regex (failed on
|
|
13
|
+
`rm -fr /` and `--recursive --force`) with Python-level `_check_recursive_rm()`
|
|
14
|
+
that tokenizes the command and correctly detects recursive flags in any order.
|
|
15
|
+
All flag permutations now blocked: `rm -rf /`, `rm -fr /`, `rm -r -f /`,
|
|
16
|
+
`rm --recursive --force /`, `rm --RECURSIVE /`, `rm -rf ~/`, `rm -rf $HOME/`,
|
|
17
|
+
`rm -rf *`. False positives eliminated: `rm -f /etc/passwd`, `rm --Force /`,
|
|
18
|
+
`echo rm -rf /`.
|
|
19
|
+
- **win_sandbox**: reverted `_dict_to_env_block` env-forwarding plumbing that
|
|
20
|
+
broke `CreateProcessAsUserW` on Win32. `lpEnvironment=None` preserves parent
|
|
21
|
+
env inheritance (safest path). Known limitation documented for future work.
|
|
22
|
+
- **loader**: `_find_project_dir` now accepts `str | Path` (CLI may pass str).
|
|
23
|
+
- **test_seams**: new 22-test seam suite covering command_policy↔middleware,
|
|
24
|
+
loader↔repl↔skills, deep_loop↔sandbox_runner↔win_sandbox boundaries.
|
|
25
|
+
All existing tests (884 passed) + seams (22 passed) green.
|
|
26
|
+
|
|
9
27
|
## [0.4.2] — 2026-08-18
|
|
10
28
|
|
|
11
29
|
### Security — v3 audit short-term batch (#7/#8/#9/#11/#14, all runtime-verified)
|
coderio-0.4.3/PKG-INFO
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: coderio
|
|
3
|
+
Version: 0.4.3
|
|
4
|
+
Summary: A skill-driven coding agent — structural harness, foldable thinking TUI, deepagents engine.
|
|
5
|
+
Author: coderio contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: agent,ai-agent,cli,coding-agent,langchain,langgraph,llm,mcp,model-context-protocol,sandbox,skills,textual,tui
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: ddgs>=4.0
|
|
22
|
+
Requires-Dist: deepagents>=0.6
|
|
23
|
+
Requires-Dist: httpx>=0.27
|
|
24
|
+
Requires-Dist: langchain-anthropic>=0.2
|
|
25
|
+
Requires-Dist: langchain-core>=0.3
|
|
26
|
+
Requires-Dist: langchain-openai>=0.2
|
|
27
|
+
Requires-Dist: langchain>=0.3
|
|
28
|
+
Requires-Dist: langgraph-checkpoint-sqlite>=2.0
|
|
29
|
+
Requires-Dist: langgraph>=0.2
|
|
30
|
+
Requires-Dist: pydantic>=2
|
|
31
|
+
Requires-Dist: rich>=13
|
|
32
|
+
Requires-Dist: textual>=0.40
|
|
33
|
+
Requires-Dist: tomli-w>=1.0
|
|
34
|
+
Requires-Dist: typer>=0.12
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
37
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
39
|
+
Requires-Dist: pytest-cov>=4; extra == 'dev'
|
|
40
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
41
|
+
Requires-Dist: ruff>=0.16; extra == 'dev'
|
|
42
|
+
Provides-Extra: mcp
|
|
43
|
+
Requires-Dist: langchain-mcp-adapters>=0.3.2; extra == 'mcp'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# coderio
|
|
47
|
+
|
|
48
|
+
[中文](README.md) | **English**
|
|
49
|
+
|
|
50
|
+
> The agent claims "done" without running the tests? coderio's harness stops it.
|
|
51
|
+
> A local coding agent with **native Zhipu GLM & StepFun Step coding-plan support** — four-tier permissions, layered sandbox, MCP, lifecycle hooks, and an interactive TUI.
|
|
52
|
+
|
|
53
|
+

|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install coderio
|
|
59
|
+
coderio # onboarding wizard on first launch (pick provider, paste API key, auto context-window probe)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Requires Python 3.11+; Git Bash on Windows. Linux / macOS supported.
|
|
63
|
+
|
|
64
|
+
## Why coderio
|
|
65
|
+
|
|
66
|
+
The shared weakness of coding agents: **the model says "I'm done" and you just have to trust it**. coderio turns that sentence into a structural constraint—
|
|
67
|
+
|
|
68
|
+
### The Four Gates: the agent can't lie to you
|
|
69
|
+
|
|
70
|
+
| Gate | Behavior |
|
|
71
|
+
|---|---|
|
|
72
|
+
| **VerifyGate** | Wrote code, never ran it, wants to finish → intercepted, forced to continue. Parses real exit codes — **a failing test run does NOT count as verified** |
|
|
73
|
+
| **CompletionGate** | Declares done with pending todos → intercepted |
|
|
74
|
+
| **GroundingGate** | Cites files it never read → intercepted |
|
|
75
|
+
| **PlanGate** | Writes code without a todo list → soft nudge |
|
|
76
|
+
|
|
77
|
+
Not a prompt-level soft rule — a system-level control based on tool-call ground truth. Claude Code and Codex don't have this.
|
|
78
|
+
|
|
79
|
+
### Native Chinese coding-plan support
|
|
80
|
+
|
|
81
|
+
Zhipu **GLM Coding Plan** and StepFun **Step Plan** work out of the box (direct Anthropic-protocol connection) — your subscription quota runs a local agent, no proxies, no middle layer. Also supports OpenAI / Anthropic / Ollama / any OpenAI-compatible endpoint, with multi-profile switching.
|
|
82
|
+
|
|
83
|
+
### Layered security, honestly stated
|
|
84
|
+
|
|
85
|
+
- Four permission tiers (plan read-only / confirm per-action / auto_edit / full)
|
|
86
|
+
- Command blacklist + whitelist (accident prevention); Linux bubblewrap OS sandbox (boundary enforcement)
|
|
87
|
+
- First-use repo-config trust confirmation (hostile-repo protection); web_fetch SSRF protection
|
|
88
|
+
- The blacklist/whitelist are **accident prevention, not adversarial defense** — adversarial protection comes from the sandbox + permissions; use a VM for hostile code
|
|
89
|
+
|
|
90
|
+
## Feature highlights
|
|
91
|
+
|
|
92
|
+
- **Interactive TUI**: streaming output, foldable thinking (Ctrl+O), collapsible TODO panel, vertical permission menu, task interruption (Esc), slash-command autocomplete, session management
|
|
93
|
+
- **Headless mode**: `coderio run "task"` one-shot execution (CI / scripts / benchmarks) with graded exit codes
|
|
94
|
+
- **MCP support**: connect external tools via `.mcp.json` (Claude Code-compatible format), managed with `coderio mcp`
|
|
95
|
+
- **Lifecycle hooks**: `[[hooks]]` run your commands at PreToolUse / PostToolUse / UserPromptSubmit (exit 2 = block) — IO contract compatible with Claude Code
|
|
96
|
+
- **Three-layer skills**: bundled + user + project, progressive disclosure saves context
|
|
97
|
+
- **Context governance**: auto-compaction (60% window trigger), large-block offload, sqlite checkpoints across turns
|
|
98
|
+
- **Subagents**: research (read-only, double-enforced) + general-purpose (inherits the main agent's full security stack)
|
|
99
|
+
- **Engineering discipline**: 850+ tests, 80% coverage, mypy hard gate, uv.lock, 3 OS × 2 Python CI matrix
|
|
100
|
+
|
|
101
|
+
<details>
|
|
102
|
+
<summary><b>Config example</b> (click to expand)</summary>
|
|
103
|
+
|
|
104
|
+
```toml
|
|
105
|
+
# ~/.coderio/config.toml
|
|
106
|
+
[model]
|
|
107
|
+
provider_id = "bigmodel_coding_plan" # Zhipu/StepFun coding plan, or openai/anthropic/ollama/custom
|
|
108
|
+
default = "glm-5.2"
|
|
109
|
+
|
|
110
|
+
[tools]
|
|
111
|
+
permission_mode = "confirm" # plan | confirm | auto_edit | full
|
|
112
|
+
sandbox_mode = "off" # off | job (resource limits) | write (Linux file-write isolation)
|
|
113
|
+
|
|
114
|
+
# Lifecycle hooks (Claude Code-compatible contract)
|
|
115
|
+
[[hooks]]
|
|
116
|
+
event = "PreToolUse"
|
|
117
|
+
matcher = "write_file|edit_file"
|
|
118
|
+
command = "python .hooks/protect.py" # JSON on stdin; exit 2 = block
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
MCP, the sandbox 4-tuple, and more: [docs/coderio-architecture.md](docs/coderio-architecture.md).
|
|
122
|
+
|
|
123
|
+
</details>
|
|
124
|
+
|
|
125
|
+
## Common commands
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
coderio # interactive TUI
|
|
129
|
+
coderio run "fix the failing test" --quiet # headless one-shot
|
|
130
|
+
coderio run "task" --dangerously-skip-permissions # full access (explicit opt-in)
|
|
131
|
+
coderio mcp add github --type http --url ... # manage MCP
|
|
132
|
+
coderio skills install # install skill suites
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Type `/` inside the TUI for all commands (/resume sessions, /mode permissions, /profile configs, /think unfold reasoning).
|
|
136
|
+
|
|
137
|
+
## Known limitations
|
|
138
|
+
|
|
139
|
+
- The Windows write-sandbox currently equals job mode (true isolation awaits the ACL work — documented honestly)
|
|
140
|
+
- Blacklist/whitelist are accident-prevention by design (regex can be bypassed by obfuscation); use the sandbox / a VM for adversarial scenarios
|
|
141
|
+
|
|
142
|
+
## Origin
|
|
143
|
+
|
|
144
|
+
A spare-time project, open-sourced as a working reference for developers building their own coding agents. The name is **code + rio** (the author's English name is Lion; "codelion" sounded odd).
|
|
145
|
+
|
|
146
|
+
## Contributing & License
|
|
147
|
+
|
|
148
|
+
Issues and PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). MIT License.
|
coderio-0.4.3/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# coderio
|
|
2
|
+
|
|
3
|
+
**中文** | [English](README_en.md)
|
|
4
|
+
|
|
5
|
+
> 写了代码没跑过测试就说"完成"?coderio 的 harness 会拦住它。
|
|
6
|
+
> 一个**原生支持智谱 GLM / 阶跃 StepFun Coding Plan** 的本地 coding agent——四级权限、多层沙箱、MCP、生命周期 hooks、交互式 TUI。
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## 安装
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install coderio
|
|
14
|
+
coderio # 首次启动进入 onboarding 向导(选 provider、填 API key、自动探测上下文窗口)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
要求:Python 3.11+;Windows 需 Git Bash。支持 Linux / macOS。
|
|
18
|
+
|
|
19
|
+
## 为什么是 coderio
|
|
20
|
+
|
|
21
|
+
市面上 coding agent 的共同软肋:**模型说"我做完了",你就得信**。coderio 把这句话变成了结构约束——
|
|
22
|
+
|
|
23
|
+
### 四道门:agent 骗不了你
|
|
24
|
+
|
|
25
|
+
| 门 | 行为 |
|
|
26
|
+
|---|---|
|
|
27
|
+
| **VerifyGate** | 写了代码没跑验证就想结束 → 拦截、强制续跑。解析真实 exit code,**测试失败不算验证通过** |
|
|
28
|
+
| **CompletionGate** | TODO 没清完就宣布完成 → 拦截 |
|
|
29
|
+
| **GroundingGate** | 引用从未读过的文件下结论 → 拦截 |
|
|
30
|
+
| **PlanGate** | 没 TODO 就动手写码 → 软提醒 |
|
|
31
|
+
|
|
32
|
+
不是提示词软规则,是基于工具调用 ground truth 的系统级控制。Claude Code / Codex 都没有这个。
|
|
33
|
+
|
|
34
|
+
### 原生支持中文 Coding Plan
|
|
35
|
+
|
|
36
|
+
智谱 **GLM Coding Plan** 和阶跃 **StepFun Step Plan** 开箱即用(Anthropic 协议直连)——你的订阅额度跑本地 agent,不需要转发、不需要中间层。同时支持 OpenAI / Anthropic / Ollama / 任意 OpenAI 兼容端点,多 profile 一键切换。
|
|
37
|
+
|
|
38
|
+
### 多层安全,诚实声明
|
|
39
|
+
|
|
40
|
+
- 四级权限(plan 只读 / confirm 逐项确认 / auto_edit / full)
|
|
41
|
+
- 命令黑名单 + 白名单(防手滑);Linux bubblewrap OS 级沙箱(防越界写)
|
|
42
|
+
- 仓库配置首次信任确认(防克隆恶意仓库);web_fetch SSRF 防护
|
|
43
|
+
- 黑白名单是**防手滑不是防对抗**——对抗性防护靠沙箱 + 权限,恶意代码请用 VM
|
|
44
|
+
|
|
45
|
+
## 特性一览
|
|
46
|
+
|
|
47
|
+
- **交互式 TUI**:流式输出、思考折叠(Ctrl+O)、可折叠 TODO 面板、纵向权限菜单、任务中断(Esc)、slash 命令补全、会话管理
|
|
48
|
+
- **headless 模式**:`coderio run "任务"` 单次运行(CI / 脚本 / benchmark),退出码分级
|
|
49
|
+
- **MCP 支持**:`.mcp.json`(Claude Code 兼容格式)接入外部工具,`coderio mcp` 命令行管理
|
|
50
|
+
- **生命周期 hooks**:`[[hooks]]` 在 PreToolUse / PostToolUse / UserPromptSubmit 等事件执行你的命令(exit 2 = 阻断),IO 契约与 Claude Code 兼容
|
|
51
|
+
- **skills 三层加载**:bundled + 用户 + 项目层,渐进披露省上下文
|
|
52
|
+
- **上下文治理**:自动压缩(60% 窗口触发)、大块 offload、sqlite 检查点跨轮持久化
|
|
53
|
+
- **子 agent**:research(只读,双重强制)+ general-purpose(继承主 agent 全部安全层)
|
|
54
|
+
- **工程纪律**:850+ 测试、80% 覆盖率、mypy 硬门、uv.lock 锁定、3 OS × 2 Python CI 矩阵
|
|
55
|
+
|
|
56
|
+
<details>
|
|
57
|
+
<summary><b>配置示例</b>(点击展开)</summary>
|
|
58
|
+
|
|
59
|
+
```toml
|
|
60
|
+
# ~/.coderio/config.toml
|
|
61
|
+
[model]
|
|
62
|
+
provider_id = "bigmodel_coding_plan" # 智谱/阶跃 coding plan,或 openai/anthropic/ollama/自定义
|
|
63
|
+
default = "glm-5.2"
|
|
64
|
+
|
|
65
|
+
[tools]
|
|
66
|
+
permission_mode = "confirm" # plan | confirm | auto_edit | full
|
|
67
|
+
sandbox_mode = "off" # off | job(资源限制)| write(Linux 文件写隔离)
|
|
68
|
+
|
|
69
|
+
# 生命周期 hooks(Claude Code 兼容契约)
|
|
70
|
+
[[hooks]]
|
|
71
|
+
event = "PreToolUse"
|
|
72
|
+
matcher = "write_file|edit_file"
|
|
73
|
+
command = "python .hooks/protect.py" # stdin 收 JSON;exit 2 = 阻断
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
MCP、沙箱四元组、更多配置见 [docs/coderio-architecture.md](docs/coderio-architecture.md)。
|
|
77
|
+
|
|
78
|
+
</details>
|
|
79
|
+
|
|
80
|
+
## 常用命令
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
coderio # 交互式 TUI
|
|
84
|
+
coderio run "修复失败的测试" --quiet # headless 单次
|
|
85
|
+
coderio run "任务" --dangerously-skip-permissions # full 权限(显式选择)
|
|
86
|
+
coderio mcp add github --type http --url ... # 管理 MCP
|
|
87
|
+
coderio skills install # 安装 skill 套件
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
TUI 内输入 `/` 查看全部命令(/resume 恢复会话、/mode 切权限、/profile 切配置、/think 展开思考)。
|
|
91
|
+
|
|
92
|
+
## 已知限制
|
|
93
|
+
|
|
94
|
+
- Windows 写沙箱当前等价于 job 档(真隔离待 ACL,文档如实标注)
|
|
95
|
+
- 黑白名单为防手滑设计(正则可被混淆绕过),对抗性场景用沙箱 / VM
|
|
96
|
+
|
|
97
|
+
## 起源
|
|
98
|
+
|
|
99
|
+
业余项目,开源目的:给想自己搭 coding agent 的开发者一份能跑的参考。名字是 **code + rio**(作者英文名 Lion,本想叫 codelion)。
|
|
100
|
+
|
|
101
|
+
## 贡献与 License
|
|
102
|
+
|
|
103
|
+
欢迎 issue / PR,见 [CONTRIBUTING.md](CONTRIBUTING.md)。MIT License。
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# coderio
|
|
2
|
+
|
|
3
|
+
[中文](README.md) | **English**
|
|
4
|
+
|
|
5
|
+
> The agent claims "done" without running the tests? coderio's harness stops it.
|
|
6
|
+
> A local coding agent with **native Zhipu GLM & StepFun Step coding-plan support** — four-tier permissions, layered sandbox, MCP, lifecycle hooks, and an interactive TUI.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install coderio
|
|
14
|
+
coderio # onboarding wizard on first launch (pick provider, paste API key, auto context-window probe)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Requires Python 3.11+; Git Bash on Windows. Linux / macOS supported.
|
|
18
|
+
|
|
19
|
+
## Why coderio
|
|
20
|
+
|
|
21
|
+
The shared weakness of coding agents: **the model says "I'm done" and you just have to trust it**. coderio turns that sentence into a structural constraint—
|
|
22
|
+
|
|
23
|
+
### The Four Gates: the agent can't lie to you
|
|
24
|
+
|
|
25
|
+
| Gate | Behavior |
|
|
26
|
+
|---|---|
|
|
27
|
+
| **VerifyGate** | Wrote code, never ran it, wants to finish → intercepted, forced to continue. Parses real exit codes — **a failing test run does NOT count as verified** |
|
|
28
|
+
| **CompletionGate** | Declares done with pending todos → intercepted |
|
|
29
|
+
| **GroundingGate** | Cites files it never read → intercepted |
|
|
30
|
+
| **PlanGate** | Writes code without a todo list → soft nudge |
|
|
31
|
+
|
|
32
|
+
Not a prompt-level soft rule — a system-level control based on tool-call ground truth. Claude Code and Codex don't have this.
|
|
33
|
+
|
|
34
|
+
### Native Chinese coding-plan support
|
|
35
|
+
|
|
36
|
+
Zhipu **GLM Coding Plan** and StepFun **Step Plan** work out of the box (direct Anthropic-protocol connection) — your subscription quota runs a local agent, no proxies, no middle layer. Also supports OpenAI / Anthropic / Ollama / any OpenAI-compatible endpoint, with multi-profile switching.
|
|
37
|
+
|
|
38
|
+
### Layered security, honestly stated
|
|
39
|
+
|
|
40
|
+
- Four permission tiers (plan read-only / confirm per-action / auto_edit / full)
|
|
41
|
+
- Command blacklist + whitelist (accident prevention); Linux bubblewrap OS sandbox (boundary enforcement)
|
|
42
|
+
- First-use repo-config trust confirmation (hostile-repo protection); web_fetch SSRF protection
|
|
43
|
+
- The blacklist/whitelist are **accident prevention, not adversarial defense** — adversarial protection comes from the sandbox + permissions; use a VM for hostile code
|
|
44
|
+
|
|
45
|
+
## Feature highlights
|
|
46
|
+
|
|
47
|
+
- **Interactive TUI**: streaming output, foldable thinking (Ctrl+O), collapsible TODO panel, vertical permission menu, task interruption (Esc), slash-command autocomplete, session management
|
|
48
|
+
- **Headless mode**: `coderio run "task"` one-shot execution (CI / scripts / benchmarks) with graded exit codes
|
|
49
|
+
- **MCP support**: connect external tools via `.mcp.json` (Claude Code-compatible format), managed with `coderio mcp`
|
|
50
|
+
- **Lifecycle hooks**: `[[hooks]]` run your commands at PreToolUse / PostToolUse / UserPromptSubmit (exit 2 = block) — IO contract compatible with Claude Code
|
|
51
|
+
- **Three-layer skills**: bundled + user + project, progressive disclosure saves context
|
|
52
|
+
- **Context governance**: auto-compaction (60% window trigger), large-block offload, sqlite checkpoints across turns
|
|
53
|
+
- **Subagents**: research (read-only, double-enforced) + general-purpose (inherits the main agent's full security stack)
|
|
54
|
+
- **Engineering discipline**: 850+ tests, 80% coverage, mypy hard gate, uv.lock, 3 OS × 2 Python CI matrix
|
|
55
|
+
|
|
56
|
+
<details>
|
|
57
|
+
<summary><b>Config example</b> (click to expand)</summary>
|
|
58
|
+
|
|
59
|
+
```toml
|
|
60
|
+
# ~/.coderio/config.toml
|
|
61
|
+
[model]
|
|
62
|
+
provider_id = "bigmodel_coding_plan" # Zhipu/StepFun coding plan, or openai/anthropic/ollama/custom
|
|
63
|
+
default = "glm-5.2"
|
|
64
|
+
|
|
65
|
+
[tools]
|
|
66
|
+
permission_mode = "confirm" # plan | confirm | auto_edit | full
|
|
67
|
+
sandbox_mode = "off" # off | job (resource limits) | write (Linux file-write isolation)
|
|
68
|
+
|
|
69
|
+
# Lifecycle hooks (Claude Code-compatible contract)
|
|
70
|
+
[[hooks]]
|
|
71
|
+
event = "PreToolUse"
|
|
72
|
+
matcher = "write_file|edit_file"
|
|
73
|
+
command = "python .hooks/protect.py" # JSON on stdin; exit 2 = block
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
MCP, the sandbox 4-tuple, and more: [docs/coderio-architecture.md](docs/coderio-architecture.md).
|
|
77
|
+
|
|
78
|
+
</details>
|
|
79
|
+
|
|
80
|
+
## Common commands
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
coderio # interactive TUI
|
|
84
|
+
coderio run "fix the failing test" --quiet # headless one-shot
|
|
85
|
+
coderio run "task" --dangerously-skip-permissions # full access (explicit opt-in)
|
|
86
|
+
coderio mcp add github --type http --url ... # manage MCP
|
|
87
|
+
coderio skills install # install skill suites
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Type `/` inside the TUI for all commands (/resume sessions, /mode permissions, /profile configs, /think unfold reasoning).
|
|
91
|
+
|
|
92
|
+
## Known limitations
|
|
93
|
+
|
|
94
|
+
- The Windows write-sandbox currently equals job mode (true isolation awaits the ACL work — documented honestly)
|
|
95
|
+
- Blacklist/whitelist are accident-prevention by design (regex can be bypassed by obfuscation); use the sandbox / a VM for adversarial scenarios
|
|
96
|
+
|
|
97
|
+
## Origin
|
|
98
|
+
|
|
99
|
+
A spare-time project, open-sourced as a working reference for developers building their own coding agents. The name is **code + rio** (the author's English name is Lion; "codelion" sounded odd).
|
|
100
|
+
|
|
101
|
+
## Contributing & License
|
|
102
|
+
|
|
103
|
+
Issues and PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). MIT License.
|
|
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "coderio"
|
|
8
|
-
version = "0.4.
|
|
8
|
+
version = "0.4.3"
|
|
9
9
|
description = "A skill-driven coding agent — structural harness, foldable thinking TUI, deepagents engine."
|
|
10
10
|
readme = "README_en.md"
|
|
11
11
|
license = "MIT"
|
|
@@ -201,10 +201,9 @@ fail_under = 60
|
|
|
201
201
|
# real type errors (wrong arg counts, None where a value is expected) without
|
|
202
202
|
# blocking on the many untyped third-party deps (langchain, deepagents, textual).
|
|
203
203
|
#
|
|
204
|
-
# CI runs mypy as a HARD GATE
|
|
205
|
-
#
|
|
206
|
-
#
|
|
207
|
-
# TODO, not a permanent pass. Remove entries as the files are fixed.
|
|
204
|
+
# CI runs mypy as a HARD GATE for all modules except the override list below.
|
|
205
|
+
# Modules with `ignore_errors = true` have known type issues — each entry is a
|
|
206
|
+
# tracked TODO. Modules are removed from this list when they pass cleanly.
|
|
208
207
|
python_version = "3.11"
|
|
209
208
|
ignore_missing_imports = true
|
|
210
209
|
warn_redundant_casts = true
|
|
@@ -218,6 +217,9 @@ exclude = ["tests/", "build/", "dist/", "\\.venv/"]
|
|
|
218
217
|
# Per-module overrides: lenient modules (tracked cleanup TODOs).
|
|
219
218
|
# Each entry here is a file with known type issues that would block CI if
|
|
220
219
|
# enforced strictly. Remove entries as the files are cleaned up.
|
|
220
|
+
#
|
|
221
|
+
# Cleaned up 2026-08-21: removed coderio.agent.deep_loop and
|
|
222
|
+
# coderio.mcp_loader (verified mypy clean — 0 errors, only notes).
|
|
221
223
|
[[tool.mypy.overrides]]
|
|
222
224
|
module = [
|
|
223
225
|
"coderio.cli.tui",
|
|
@@ -227,10 +229,8 @@ module = [
|
|
|
227
229
|
"coderio.cli.onboarding",
|
|
228
230
|
"coderio.cli.stream",
|
|
229
231
|
"coderio.cli.repl",
|
|
230
|
-
"coderio.agent.deep_loop",
|
|
231
232
|
"coderio.tools.win_job",
|
|
232
233
|
"coderio.tools.win_sandbox",
|
|
233
|
-
"coderio.mcp_loader",
|
|
234
234
|
"coderio.session.store",
|
|
235
235
|
"coderio.session.message",
|
|
236
236
|
"coderio.llm.probe",
|
|
@@ -298,7 +298,7 @@ def _build_extra_tools(tools, skill_store, active_skills):
|
|
|
298
298
|
return extra
|
|
299
299
|
|
|
300
300
|
|
|
301
|
-
def _build_research_subagent(
|
|
301
|
+
def _build_research_subagent(command_policy=None, hook_runner=None):
|
|
302
302
|
"""Return the research subagent spec (read-only, physically isolated).
|
|
303
303
|
|
|
304
304
|
Tool exclusion uses the compat layer (_deepagents_compat) so that a
|
|
@@ -308,11 +308,12 @@ def _build_research_subagent(gate=None, command_policy=None, hook_runner=None):
|
|
|
308
308
|
work bypassed the user's PreToolUse/PostToolUse hooks entirely. The runner
|
|
309
309
|
is shared with the main agent (stateless across fire() calls).
|
|
310
310
|
|
|
311
|
-
Permission + CommandReview
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
"read-only"
|
|
311
|
+
Permission + CommandReview: execution-time enforcement on top of the
|
|
312
|
+
model-visibility whitelist. The whitelist filters what the model SEES,
|
|
313
|
+
these middlewares gate what actually RUNS. This subagent uses its own
|
|
314
|
+
hardcoded PLAN gate so it can never be upgraded to write access via the
|
|
315
|
+
caller's permission mode (an FULL/auto caller must not turn the "read-only"
|
|
316
|
+
subagent into a writing one).
|
|
316
317
|
"""
|
|
317
318
|
from coderio.agent._deepagents_compat import make_research_subagent_middleware
|
|
318
319
|
|
|
@@ -321,15 +322,15 @@ def _build_research_subagent(gate=None, command_policy=None, hook_runner=None):
|
|
|
321
322
|
from coderio.agent.hooks import HooksMiddleware
|
|
322
323
|
|
|
323
324
|
middleware.insert(0, HooksMiddleware(hook_runner))
|
|
324
|
-
|
|
325
|
-
|
|
325
|
+
from coderio.agent.permission_middleware import PermissionMiddleware
|
|
326
|
+
from coderio.tools.permission import PermissionGate, PermissionMode
|
|
326
327
|
|
|
327
|
-
|
|
328
|
+
middleware.append(PermissionMiddleware(PermissionGate(PermissionMode.PLAN)))
|
|
328
329
|
from coderio.agent.command_review import CommandReviewMiddleware
|
|
329
330
|
from coderio.tools.command_policy import CommandPolicy
|
|
330
331
|
|
|
331
332
|
policy = command_policy or CommandPolicy.default()
|
|
332
|
-
middleware.append(CommandReviewMiddleware(policy
|
|
333
|
+
middleware.append(CommandReviewMiddleware(policy))
|
|
333
334
|
return {
|
|
334
335
|
"name": "research",
|
|
335
336
|
"description": (
|
|
@@ -587,7 +588,7 @@ def run_deep_agent(
|
|
|
587
588
|
"middleware": middleware,
|
|
588
589
|
"backend": backend,
|
|
589
590
|
"subagents": [
|
|
590
|
-
_build_research_subagent(
|
|
591
|
+
_build_research_subagent(command_policy=command_policy, hook_runner=hook_runner),
|
|
591
592
|
_build_general_purpose_subagent(gate, command_policy, stream=stream, hook_runner=hook_runner),
|
|
592
593
|
],
|
|
593
594
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
6
|
from rich.console import Console
|
|
7
7
|
|
|
8
8
|
from coderio.agent.prompts import ActiveSkills
|
|
9
9
|
from coderio.cli.stream import RichStream
|
|
10
|
-
from coderio.config import
|
|
10
|
+
from coderio.config import load_config
|
|
11
|
+
from coderio.config.loader import _find_project_dir
|
|
11
12
|
from coderio.llm import build_chat_model
|
|
12
13
|
from coderio.session.store import Session
|
|
13
14
|
from coderio.skills.store import SkillStore, load_skill_store
|
|
@@ -19,6 +20,9 @@ from coderio.tools.permission import (
|
|
|
19
20
|
RichPromptPermissionGate,
|
|
20
21
|
)
|
|
21
22
|
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from coderio.config import Config
|
|
25
|
+
|
|
22
26
|
BUNDLED_SKILLS = Path(__file__).resolve().parents[1] / "skills"
|
|
23
27
|
|
|
24
28
|
|
|
@@ -100,6 +104,7 @@ def build_runtime(
|
|
|
100
104
|
model_override: str | None = None,
|
|
101
105
|
provider_override: str | None = None,
|
|
102
106
|
):
|
|
107
|
+
search_from = Path(search_from).resolve()
|
|
103
108
|
cfg = load_config(search_from=search_from)
|
|
104
109
|
|
|
105
110
|
if mode_override:
|
|
@@ -118,10 +123,11 @@ def build_runtime(
|
|
|
118
123
|
cfg = _replace(cfg, model=_replace(cfg.model, provider_id=provider_override))
|
|
119
124
|
|
|
120
125
|
if cfg.skills.auto_load:
|
|
126
|
+
_proj = _find_project_dir(search_from)
|
|
121
127
|
store = load_skill_store(
|
|
122
128
|
BUNDLED_SKILLS,
|
|
123
129
|
Path.home() / ".coderio" / "skills",
|
|
124
|
-
|
|
130
|
+
_proj / ".coderio" / "skills",
|
|
125
131
|
)
|
|
126
132
|
else:
|
|
127
133
|
store = SkillStore()
|
|
@@ -37,21 +37,20 @@ def _merge(base: dict, override: dict) -> dict:
|
|
|
37
37
|
return out
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
def _find_project_dir(search_from: Path) -> Path:
|
|
40
|
+
def _find_project_dir(search_from: Path | str) -> Path:
|
|
41
41
|
"""Walk upward from search_from looking for a project's .coderio/config.toml.
|
|
42
42
|
|
|
43
|
-
Never ascends into the user's home directory (the home
|
|
44
|
-
layer, handled separately)
|
|
45
|
-
pick up the real user config as if it were a project config.
|
|
43
|
+
Accepts str or Path. Never ascends into the user's home directory (the home
|
|
44
|
+
~/.coderio is the USER layer, handled separately).
|
|
46
45
|
"""
|
|
47
|
-
cur = search_from.resolve()
|
|
46
|
+
cur = Path(search_from).resolve()
|
|
48
47
|
home = Path(os.path.expanduser("~")).resolve()
|
|
49
48
|
for parent in [cur, *cur.parents]:
|
|
50
49
|
if parent == home:
|
|
51
50
|
break
|
|
52
51
|
if (parent / ".coderio" / "config.toml").is_file():
|
|
53
52
|
return parent
|
|
54
|
-
return
|
|
53
|
+
return cur
|
|
55
54
|
|
|
56
55
|
|
|
57
56
|
def _default_user_dir() -> Path:
|
|
@@ -28,6 +28,7 @@ from __future__ import annotations
|
|
|
28
28
|
import hashlib
|
|
29
29
|
import json
|
|
30
30
|
import logging
|
|
31
|
+
import tomllib
|
|
31
32
|
from pathlib import Path
|
|
32
33
|
|
|
33
34
|
_log = logging.getLogger(__name__)
|
|
@@ -234,12 +235,60 @@ def summarize_repo_configs(search_from: Path | str) -> str:
|
|
|
234
235
|
lines.append(" <unreadable>")
|
|
235
236
|
continue
|
|
236
237
|
if path.name == "config.toml":
|
|
237
|
-
#
|
|
238
|
-
#
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
238
|
+
# Parse TOML structurally so multi-line strings, inline tables, and
|
|
239
|
+
# nested values can't hide hook commands (P2-1 regression test:
|
|
240
|
+
# a multi-line `command = """\n...\n"""` was previously invisible
|
|
241
|
+
# because only raw lines containing a sensitive key were echoed).
|
|
242
|
+
try:
|
|
243
|
+
with open(path, "rb") as _f:
|
|
244
|
+
data = tomllib.load(_f)
|
|
245
|
+
except Exception:
|
|
246
|
+
data = None
|
|
247
|
+
if data is None:
|
|
248
|
+
# Unparseable TOML: the loader will refuse this config later
|
|
249
|
+
# (fail-closed — hooks never run), but the user should SEE
|
|
250
|
+
# that, not a bare byte count. The raw-grep fallback below
|
|
251
|
+
# echoes all sensitive-looking lines INCLUDING command lines
|
|
252
|
+
# (third-party review: the old fallback excluded them on the
|
|
253
|
+
# assumption the structural path had already shown them —
|
|
254
|
+
# but on parse failure that path printed nothing, hiding the
|
|
255
|
+
# hooks entirely).
|
|
256
|
+
lines.append(" <unparseable config.toml — the loader will reject this file>")
|
|
257
|
+
for ln in text.splitlines():
|
|
258
|
+
s = ln.strip()
|
|
259
|
+
if any(k in s for k in _SENSITIVE_KEYS) and "=" in s:
|
|
260
|
+
lines.append(f" {s}")
|
|
261
|
+
else:
|
|
262
|
+
hooks = data.get("hooks", [])
|
|
263
|
+
if isinstance(hooks, list) and hooks:
|
|
264
|
+
lines.append(" [[hooks]]")
|
|
265
|
+
for h in hooks:
|
|
266
|
+
# Shape guard (third-party review): `hooks = [1]` or
|
|
267
|
+
# `hooks = "junk"` previously crashed here (h.get on
|
|
268
|
+
# non-dict) — taking down coderio at the trust prompt
|
|
269
|
+
# before the loader's tolerant _parse_hooks could
|
|
270
|
+
# simply skip the malformed entry.
|
|
271
|
+
if not isinstance(h, dict):
|
|
272
|
+
continue
|
|
273
|
+
cmd = h.get("command")
|
|
274
|
+
if cmd:
|
|
275
|
+
lines.append(f" command = {cmd!r}")
|
|
276
|
+
ev = h.get("event")
|
|
277
|
+
if ev:
|
|
278
|
+
lines.append(f" event = {ev!r}")
|
|
279
|
+
# Echo every line mentioning a sensitive key (non-hook keys).
|
|
280
|
+
# Also skips the top-level `hooks = [...]` inline form — the
|
|
281
|
+
# structural block above already rendered each hook's command.
|
|
282
|
+
for ln in text.splitlines():
|
|
283
|
+
s = ln.strip()
|
|
284
|
+
if any(k in s for k in _SENSITIVE_KEYS) and "=" in s:
|
|
285
|
+
if (
|
|
286
|
+
not s.startswith("[[hooks]]")
|
|
287
|
+
and not s.startswith("command =")
|
|
288
|
+
and not s.startswith("event =")
|
|
289
|
+
and not s.startswith("hooks =")
|
|
290
|
+
):
|
|
291
|
+
lines.append(f" {s}")
|
|
243
292
|
else: # .mcp.json — list servers (they spawn/connect at startup)
|
|
244
293
|
try:
|
|
245
294
|
servers = json.loads(text).get("mcpServers", {})
|