god-code 0.4.3__tar.gz → 0.5.1__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.
- god_code-0.4.3/CLAUDE.md → god_code-0.5.1/AGENTS.md +2 -2
- {god_code-0.4.3 → god_code-0.5.1}/CHANGELOG.md +12 -0
- god_code-0.5.1/CLAUDE.md +196 -0
- {god_code-0.4.3 → god_code-0.5.1}/PKG-INFO +1 -1
- {god_code-0.4.3 → god_code-0.5.1}/README.md +31 -5
- god_code-0.5.1/godot_agent/agents/__init__.py +12 -0
- god_code-0.5.1/godot_agent/agents/configs.py +80 -0
- god_code-0.5.1/godot_agent/agents/dispatcher.py +153 -0
- god_code-0.5.1/godot_agent/agents/results.py +15 -0
- god_code-0.5.1/godot_agent/cli.py +1115 -0
- god_code-0.5.1/godot_agent/godot/impact_analysis.py +148 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/scene_writer.py +3 -0
- god_code-0.5.1/godot_agent/llm/adapters/__init__.py +21 -0
- god_code-0.5.1/godot_agent/llm/adapters/anthropic.py +22 -0
- god_code-0.5.1/godot_agent/llm/adapters/base.py +31 -0
- god_code-0.5.1/godot_agent/llm/adapters/openai.py +32 -0
- god_code-0.5.1/godot_agent/llm/client.py +98 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/llm/streaming.py +2 -2
- god_code-0.5.1/godot_agent/llm/types.py +175 -0
- god_code-0.5.1/godot_agent/prompts/assembler.py +189 -0
- god_code-0.5.1/godot_agent/prompts/image_templates.py +102 -0
- god_code-0.5.1/godot_agent/prompts/skill_library.py +130 -0
- god_code-0.5.1/godot_agent/prompts/skill_selector.py +80 -0
- god_code-0.5.1/godot_agent/prompts/system.py +59 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/runtime/config.py +14 -1
- god_code-0.5.1/godot_agent/runtime/design_memory.py +140 -0
- god_code-0.5.1/godot_agent/runtime/engine.py +732 -0
- god_code-0.5.1/godot_agent/runtime/events.py +11 -0
- god_code-0.5.1/godot_agent/runtime/gameplay_reviewer.py +132 -0
- god_code-0.5.1/godot_agent/runtime/modes.py +132 -0
- god_code-0.5.1/godot_agent/runtime/playtest_harness.py +142 -0
- god_code-0.5.1/godot_agent/runtime/providers.py +165 -0
- god_code-0.5.1/godot_agent/runtime/quality_gate.py +316 -0
- god_code-0.5.1/godot_agent/runtime/reviewer.py +228 -0
- god_code-0.5.1/godot_agent/runtime/runtime_bridge.py +74 -0
- god_code-0.5.1/godot_agent/runtime/scenario_specs/hud_feedback.json +7 -0
- god_code-0.5.1/godot_agent/runtime/scenario_specs/player_movement.json +8 -0
- god_code-0.5.1/godot_agent/runtime/scenario_specs/scene_transition.json +7 -0
- god_code-0.5.1/godot_agent/runtime/session.py +132 -0
- god_code-0.5.1/godot_agent/security/__init__.py +1 -0
- god_code-0.5.1/godot_agent/security/classifier.py +87 -0
- god_code-0.5.1/godot_agent/security/hooks.py +140 -0
- god_code-0.5.1/godot_agent/security/policies.py +89 -0
- god_code-0.5.1/godot_agent/security/protected_paths.py +47 -0
- god_code-0.5.1/godot_agent/security/tool_pipeline.py +89 -0
- god_code-0.5.1/godot_agent/testing/__init__.py +1 -0
- god_code-0.5.1/godot_agent/testing/scenario_runner.py +41 -0
- god_code-0.5.1/godot_agent/tools/analysis_tools.py +157 -0
- god_code-0.5.1/godot_agent/tools/base.py +54 -0
- god_code-0.5.1/godot_agent/tools/editor_bridge.py +79 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/tools/file_ops.py +18 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/tools/git.py +10 -1
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/tools/godot_cli.py +12 -1
- god_code-0.5.1/godot_agent/tools/image_gen.py +180 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/tools/list_dir.py +10 -3
- god_code-0.5.1/godot_agent/tools/memory_tool.py +78 -0
- god_code-0.5.1/godot_agent/tools/registry.py +61 -0
- god_code-0.5.1/godot_agent/tools/scene_tools.py +271 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/tools/screenshot.py +11 -1
- god_code-0.5.1/godot_agent/tools/script_tools.py +136 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/tools/search.py +19 -2
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/tools/shell.py +6 -1
- god_code-0.5.1/godot_agent/tools/web_search.py +89 -0
- god_code-0.5.1/godot_agent/tui/display.py +426 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/tui/input_handler.py +73 -12
- {god_code-0.4.3 → god_code-0.5.1}/pyproject.toml +1 -1
- god_code-0.5.1/tests/agents/test_dispatcher.py +97 -0
- god_code-0.5.1/tests/agents/test_playtest_analyst.py +37 -0
- god_code-0.5.1/tests/e2e/test_planner_worker_reviewer_flow.py +136 -0
- god_code-0.5.1/tests/e2e/test_policy_enforcement.py +112 -0
- god_code-0.5.1/tests/e2e/test_scenario_runner.py +16 -0
- god_code-0.5.1/tests/godot/test_impact_analysis.py +39 -0
- god_code-0.5.1/tests/llm/test_adapters.py +37 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/llm/test_client.py +67 -2
- god_code-0.5.1/tests/prompts/test_prompt_assembler.py +80 -0
- god_code-0.5.1/tests/prompts/test_skill_selector.py +30 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/prompts/test_system_prompt.py +5 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/runtime/test_config.py +26 -4
- god_code-0.5.1/tests/runtime/test_design_memory.py +48 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/runtime/test_engine.py +95 -0
- god_code-0.5.1/tests/runtime/test_gameplay_reviewer.py +32 -0
- god_code-0.5.1/tests/runtime/test_mode_restrictions.py +105 -0
- god_code-0.5.1/tests/runtime/test_multi_agent_flow.py +152 -0
- god_code-0.5.1/tests/runtime/test_playtest_harness.py +28 -0
- god_code-0.5.1/tests/runtime/test_quality_gate.py +37 -0
- god_code-0.5.1/tests/runtime/test_reviewer.py +50 -0
- god_code-0.5.1/tests/runtime/test_runtime_bridge.py +30 -0
- god_code-0.5.1/tests/runtime/test_session.py +63 -0
- god_code-0.5.1/tests/security/test_classifier.py +42 -0
- god_code-0.5.1/tests/security/test_hooks.py +122 -0
- god_code-0.5.1/tests/security/test_permissions.py +104 -0
- god_code-0.5.1/tests/security/test_tool_pipeline.py +121 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/test_e2e.py +2 -0
- god_code-0.5.1/tests/test_runtime_switch_commands.py +153 -0
- god_code-0.5.1/tests/tools/test_analysis_tools.py +47 -0
- god_code-0.5.1/tests/tools/test_editor_bridge.py +46 -0
- god_code-0.5.1/tests/tools/test_memory_tool.py +19 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/tools/test_registry.py +5 -0
- god_code-0.5.1/tests/tools/test_scene_tools.py +66 -0
- god_code-0.5.1/tests/tools/test_script_tools.py +47 -0
- god_code-0.5.1/tests/tui/test_input_handler.py +125 -0
- god_code-0.4.3/godot_agent/cli.py +0 -602
- god_code-0.4.3/godot_agent/llm/client.py +0 -189
- god_code-0.4.3/godot_agent/prompts/system.py +0 -114
- god_code-0.4.3/godot_agent/runtime/engine.py +0 -241
- god_code-0.4.3/godot_agent/runtime/session.py +0 -58
- god_code-0.4.3/godot_agent/tools/base.py +0 -30
- god_code-0.4.3/godot_agent/tools/registry.py +0 -29
- god_code-0.4.3/godot_agent/tui/display.py +0 -190
- {god_code-0.4.3 → god_code-0.5.1}/.github/workflows/publish.yml +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/.gitignore +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/CONTRIBUTING.md +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/LICENSE +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/collision_planner.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/consistency_checker.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/dependency_graph.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/gdscript_linter.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/pattern_advisor.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/project.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/resource_validator.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/scene_parser.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/godot/tscn_validator.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/llm/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/llm/vision.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/prompts/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/prompts/build_discipline.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/prompts/godot_playbook.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/prompts/knowledge_selector.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/py.typed +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/runtime/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/runtime/auth.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/runtime/context_manager.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/runtime/error_loop.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/runtime/oauth.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/tools/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/godot_agent/tui/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/test_collision_planner.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/test_consistency.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/test_dependency_graph.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/test_linter.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/test_pattern_advisor.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/test_project.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/test_resource_validator.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/test_scene_parser.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/test_scene_writer.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/godot/test_tscn_validator.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/llm/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/llm/test_vision.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/prompts/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/prompts/test_knowledge_selector.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/runtime/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/runtime/test_context_manager.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/runtime/test_error_loop.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/tools/__init__.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/tools/test_file_ops.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/tools/test_git.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/tools/test_godot_cli.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/tools/test_list_dir.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/tools/test_search.py +0 -0
- {god_code-0.4.3 → god_code-0.5.1}/tests/tools/test_shell.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AGENTS.md — God Code Development Guide
|
|
2
2
|
|
|
3
|
-
> AI coding agent specialized for Godot 4.4 game development. This file guides
|
|
3
|
+
> AI coding agent specialized for Godot 4.4 game development. This file guides Codex when working on the god-code codebase itself.
|
|
4
4
|
|
|
5
5
|
## Project Identity
|
|
6
6
|
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to God Code will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Workspace-style chat TUI with session snapshot, recent activity, and live streaming panels
|
|
9
|
+
- Interaction modes (`apply`, `plan`, `explain`, `review`, `fix`) with mode-aware tool availability
|
|
10
|
+
- Autosaved session metadata with `/sessions`, `/resume`, `/new`, and project-aware restore flow
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Unified `ask` and `chat` rendering pipeline, including tool progress and validation feedback
|
|
14
|
+
- Improved post-tool validation visibility and tool result summaries in interactive sessions
|
|
15
|
+
- Session persistence now preserves assistant tool calls and richer metadata for restore
|
|
16
|
+
|
|
5
17
|
## [0.1.0] - 2026-04-02
|
|
6
18
|
|
|
7
19
|
### Added
|
god_code-0.5.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# CLAUDE.md — God Code Development Guide
|
|
2
|
+
|
|
3
|
+
> AI coding agent specialized for Godot 4.4 game development. This file guides Claude Code when working on the god-code codebase itself.
|
|
4
|
+
|
|
5
|
+
## Project Identity
|
|
6
|
+
|
|
7
|
+
**god-code** — a Python CLI agent that understands GDScript, .tscn scenes, collision layers, and Godot architecture patterns. Multi-provider LLM support with 29 Godot-specific tools, AI sprite generation, and incremental build-and-verify discipline.
|
|
8
|
+
|
|
9
|
+
**PyPI**: `pip install god-code`
|
|
10
|
+
**GitHub**: https://github.com/888wing/god-code
|
|
11
|
+
**License**: GPL-3.0
|
|
12
|
+
|
|
13
|
+
## Tech Stack
|
|
14
|
+
|
|
15
|
+
- **Language**: Python 3.9+ (uses `from __future__ import annotations` for 3.10+ syntax)
|
|
16
|
+
- **CLI**: click
|
|
17
|
+
- **HTTP**: httpx (async)
|
|
18
|
+
- **Models**: pydantic v2 (tool schemas, config, structured outputs)
|
|
19
|
+
- **Image**: Pillow (screenshot + sprite post-processing)
|
|
20
|
+
- **TUI**: rich (panels, markdown, diff, tables, spinner) + prompt_toolkit (history, autocomplete)
|
|
21
|
+
- **Test**: pytest + pytest-asyncio (383 tests)
|
|
22
|
+
- **Build**: hatchling
|
|
23
|
+
- **CI**: GitHub Actions (auto-publish to PyPI on tag)
|
|
24
|
+
|
|
25
|
+
## Current Version: 0.5.1
|
|
26
|
+
|
|
27
|
+
**Stats**: 70 source files, 55 test files, ~11K lines, 383 tests, 29 tools.
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
godot_agent/
|
|
33
|
+
├── cli.py # Click CLI + setup wizard + chat loop
|
|
34
|
+
├── agents/ # Multi-agent system
|
|
35
|
+
│ ├── configs.py # Agent role configurations
|
|
36
|
+
│ ├── dispatcher.py # Planner/worker/reviewer dispatch
|
|
37
|
+
│ └── results.py # Agent result types
|
|
38
|
+
├── runtime/
|
|
39
|
+
│ ├── engine.py # Conversation loop (tools, streaming, quality gates, review)
|
|
40
|
+
│ ├── config.py # AgentConfig (pydantic) + env overrides
|
|
41
|
+
│ ├── session.py # Session persistence with metadata
|
|
42
|
+
│ ├── oauth.py # Codex refresh token flow
|
|
43
|
+
│ ├── error_loop.py # Godot output parsing + fix suggestions
|
|
44
|
+
│ ├── context_manager.py # Smart compression with working memory (1.05M context)
|
|
45
|
+
│ ├── events.py # Engine event system for TUI
|
|
46
|
+
│ ├── modes.py # Interaction modes (apply/plan/explain/review/fix)
|
|
47
|
+
│ ├── providers.py # Provider detection (openai/anthropic/gemini/xai/openrouter)
|
|
48
|
+
│ ├── quality_gate.py # Post-tool validation pipeline
|
|
49
|
+
│ ├── reviewer.py # Automated code review
|
|
50
|
+
│ ├── playtest_harness.py # Automated gameplay testing
|
|
51
|
+
│ ├── gameplay_reviewer.py # Gameplay quality analysis
|
|
52
|
+
│ ├── runtime_bridge.py # Runtime state snapshots
|
|
53
|
+
│ ├── design_memory.py # Persistent design decisions
|
|
54
|
+
│ └── auth.py # Auth context
|
|
55
|
+
├── llm/
|
|
56
|
+
│ ├── client.py # LLMClient with retry, content filter handling
|
|
57
|
+
│ ├── types.py # Message, ToolCall, TokenUsage, ChatResponse, LLMConfig
|
|
58
|
+
│ ├── streaming.py # SSE streaming with tool call assembly
|
|
59
|
+
│ ├── vision.py # Image encoding
|
|
60
|
+
│ └── adapters/ # Provider-specific adapters
|
|
61
|
+
│ ├── base.py # Adapter interface
|
|
62
|
+
│ ├── openai.py # OpenAI/OpenRouter adapter
|
|
63
|
+
│ └── anthropic.py # Anthropic adapter
|
|
64
|
+
├── tools/ # 29 function-calling tools
|
|
65
|
+
│ ├── base.py # BaseTool ABC (strict mode support)
|
|
66
|
+
│ ├── registry.py # ToolRegistry with security pipeline
|
|
67
|
+
│ ├── file_ops.py # read_file, write_file, edit_file (path-contained)
|
|
68
|
+
│ ├── script_tools.py # read_script, edit_script, lint_script
|
|
69
|
+
│ ├── scene_tools.py # read_scene, scene_tree, add/write/remove scene nodes
|
|
70
|
+
│ ├── analysis_tools.py # validate_project, check_consistency, dependency_graph, impact
|
|
71
|
+
│ ├── search.py # grep, glob
|
|
72
|
+
│ ├── list_dir.py # list_dir
|
|
73
|
+
│ ├── git.py # git (shlex-parsed)
|
|
74
|
+
│ ├── shell.py # run_shell (3 safety levels)
|
|
75
|
+
│ ├── godot_cli.py # run_godot (GUT, validate, output parser)
|
|
76
|
+
│ ├── screenshot.py # screenshot_scene (headless)
|
|
77
|
+
│ ├── image_gen.py # generate_sprite (AI pixel art + post-processing)
|
|
78
|
+
│ ├── web_search.py # web_search (Godot docs, web)
|
|
79
|
+
│ ├── memory_tool.py # design memory read/write
|
|
80
|
+
│ └── editor_bridge.py # runtime snapshot, playtest
|
|
81
|
+
├── godot/ # Godot-specific analysis
|
|
82
|
+
│ ├── project.py # project.godot parser
|
|
83
|
+
│ ├── scene_parser.py # .tscn → TscnScene
|
|
84
|
+
│ ├── scene_writer.py # Structured .tscn modification
|
|
85
|
+
│ ├── tscn_validator.py # Format validation + auto-fix
|
|
86
|
+
│ ├── gdscript_linter.py # Style, naming, type annotations
|
|
87
|
+
│ ├── collision_planner.py # Standard 8-layer scheme
|
|
88
|
+
│ ├── consistency_checker.py # Cross-file checks
|
|
89
|
+
│ ├── dependency_graph.py # Project-wide file graph
|
|
90
|
+
│ ├── pattern_advisor.py # Design pattern suggestions
|
|
91
|
+
│ ├── impact_analysis.py # Change impact analysis
|
|
92
|
+
│ └── resource_validator.py # res:// path checks
|
|
93
|
+
├── prompts/
|
|
94
|
+
│ ├── system.py # Compatibility wrapper
|
|
95
|
+
│ ├── assembler.py # Full prompt assembly pipeline
|
|
96
|
+
│ ├── godot_playbook.py # 17 knowledge sections
|
|
97
|
+
│ ├── knowledge_selector.py # Context-aware section scoring
|
|
98
|
+
│ ├── skill_library.py # Skill definitions
|
|
99
|
+
│ ├── skill_selector.py # Dynamic skill activation
|
|
100
|
+
│ ├── build_discipline.py # Build-and-verify rules
|
|
101
|
+
│ └── image_templates.py # Pixel art prompt templates
|
|
102
|
+
├── security/
|
|
103
|
+
│ ├── classifier.py # Tool risk classification
|
|
104
|
+
│ ├── hooks.py # Pre/post execution hooks
|
|
105
|
+
│ ├── policies.py # Execution context + policies
|
|
106
|
+
│ ├── protected_paths.py # Path protection rules
|
|
107
|
+
│ └── tool_pipeline.py # Tool execution pipeline
|
|
108
|
+
├── testing/
|
|
109
|
+
│ └── scenario_runner.py # Automated test scenarios
|
|
110
|
+
└── tui/
|
|
111
|
+
├── display.py # Rich TUI components
|
|
112
|
+
└── input_handler.py # prompt_toolkit input + autocomplete
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Key Patterns
|
|
116
|
+
|
|
117
|
+
### Tool System
|
|
118
|
+
Every tool inherits `BaseTool`. Supports `strict` mode for GPT-5+ structured outputs. Security pipeline validates path containment and safety level before execution.
|
|
119
|
+
|
|
120
|
+
### Provider Adapters
|
|
121
|
+
`llm/adapters/` handles provider-specific request/response formats:
|
|
122
|
+
- OpenAI: `max_completion_tokens` for gpt-5+, `max_tokens` for others
|
|
123
|
+
- Anthropic: `thinking` budget for reasoning models
|
|
124
|
+
- Gemini: `reasoning_effort` parameter
|
|
125
|
+
|
|
126
|
+
### Engine Loop Phases
|
|
127
|
+
```
|
|
128
|
+
PREPARE_CONTEXT → CALL_MODEL → EXECUTE_TOOLS → RUN_QUALITY_GATE → RUN_REVIEWER → NEXT_ROUND → DONE
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Context Management (1.05M window)
|
|
132
|
+
Smart compression at 75% (787K tokens):
|
|
133
|
+
1. Extract working memory (modified files, decisions, errors)
|
|
134
|
+
2. Keep 20 recent messages intact
|
|
135
|
+
3. Replace old turns with memory summary
|
|
136
|
+
4. Tell LLM to re-read files if needed
|
|
137
|
+
|
|
138
|
+
### Interaction Modes
|
|
139
|
+
- `apply`: Full tool access, write code
|
|
140
|
+
- `plan`: Read-only tools, design first
|
|
141
|
+
- `explain`: Read-only, educational
|
|
142
|
+
- `review`: Read-only, quality analysis
|
|
143
|
+
- `fix`: Full tools, error-focused
|
|
144
|
+
|
|
145
|
+
## Development Rules
|
|
146
|
+
|
|
147
|
+
### Adding a New Tool
|
|
148
|
+
1. Create in `godot_agent/tools/your_tool.py` inheriting `BaseTool`
|
|
149
|
+
2. Define `Input`/`Output` as pydantic `BaseModel` (all fields must have defaults for strict mode)
|
|
150
|
+
3. Implement `async execute()`, `is_read_only()`, `is_destructive()`
|
|
151
|
+
4. Register in `cli.py:build_registry()`
|
|
152
|
+
5. Add to `prompts/system.py` active_tools list
|
|
153
|
+
6. Add tests in `tests/tools/`
|
|
154
|
+
|
|
155
|
+
### Adding a Provider
|
|
156
|
+
1. Create adapter in `godot_agent/llm/adapters/`
|
|
157
|
+
2. Register in `runtime/providers.py`
|
|
158
|
+
3. Add detection rules (model prefix, base_url pattern)
|
|
159
|
+
|
|
160
|
+
## Config Reference
|
|
161
|
+
|
|
162
|
+
`~/.config/god-code/config.json`:
|
|
163
|
+
|
|
164
|
+
| Field | Default | Description |
|
|
165
|
+
|-------|---------|-------------|
|
|
166
|
+
| api_key | "" | LLM API key |
|
|
167
|
+
| provider | "openai" | openai, anthropic, gemini, xai, openrouter |
|
|
168
|
+
| model | "gpt-5.4" | Model ID |
|
|
169
|
+
| reasoning_effort | "high" | low, medium, high |
|
|
170
|
+
| mode | "apply" | apply, plan, explain, review, fix |
|
|
171
|
+
| language | "en" | en, zh-TW, ja, ko |
|
|
172
|
+
| verbosity | "normal" | concise, normal, detailed |
|
|
173
|
+
| auto_validate | true | Run Godot after file changes |
|
|
174
|
+
| auto_commit | false | Suggest git commit |
|
|
175
|
+
| token_budget | 0 | Max tokens (0=unlimited) |
|
|
176
|
+
| safety | "normal" | strict, normal, permissive |
|
|
177
|
+
| streaming | true | Stream responses |
|
|
178
|
+
| extra_prompt | "" | Custom instructions |
|
|
179
|
+
|
|
180
|
+
## Testing
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
python -m pytest tests/ -v # Full suite (383 tests)
|
|
184
|
+
python -m pytest tests/tools/ -v # Tool tests only
|
|
185
|
+
python -m pytest tests/e2e/ -v # E2E integration tests
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Release
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Bump version in pyproject.toml + cli.py _VERSION
|
|
192
|
+
git commit -am "release: v0.5.1"
|
|
193
|
+
git tag v0.5.1
|
|
194
|
+
git push && git push --tags
|
|
195
|
+
# → GitHub Actions auto-publishes to PyPI
|
|
196
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: god-code
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: AI coding agent specialized for Godot game development
|
|
5
5
|
Project-URL: Homepage, https://github.com/chuisiufai/god-code
|
|
6
6
|
Project-URL: Repository, https://github.com/chuisiufai/god-code
|
|
@@ -4,12 +4,20 @@ AI coding agent specialized for Godot 4.4 game development. Unlike generic codin
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
7
|
+
- **29 tools**: file ops, scene manipulation, script editing, search, git, shell, Godot headless runner, screenshot, AI sprite generation, web search
|
|
8
|
+
- **AI sprite generation**: pixel art pipeline with chroma key removal, auto-crop, nearest-neighbor resize, style presets
|
|
9
|
+
- **Structured Outputs**: strict JSON schemas for gpt-5+ models — zero tool call parse errors
|
|
10
|
+
- **Web search**: query Godot docs and web when built-in knowledge isn't enough
|
|
11
|
+
- **Workspace-style chat TUI**: session snapshot, activity timeline, live tool feedback, streaming output
|
|
12
|
+
- **Interaction modes**: `apply`, `plan`, `explain`, `review`, `fix` with mode-aware prompts and tool access
|
|
13
|
+
- **Multi-provider**: OpenAI (gpt-5.4), Anthropic (claude-sonnet-4.6), Google (gemini), xAI (grok), OpenRouter, local models
|
|
14
|
+
- **Session recovery**: autosave, `/sessions`, `/resume`, project-aware session metadata
|
|
8
15
|
- **Godot-native understanding**: project.godot parser, .tscn scene parser/writer/validator, collision layer planner
|
|
9
|
-
- **Code quality**: GDScript linter
|
|
10
|
-
- **Smart knowledge injection**: 17 Godot Playbook sections auto-selected by task context
|
|
11
|
-
- **Build discipline**: incremental build-and-verify
|
|
12
|
-
- **
|
|
16
|
+
- **Code quality**: GDScript linter, cross-file consistency checker, design pattern advisor, impact analysis
|
|
17
|
+
- **Smart knowledge injection**: 17 Godot Playbook sections auto-selected by task context + skill system
|
|
18
|
+
- **Build discipline**: incremental build-and-verify with quality gates and automated review
|
|
19
|
+
- **Security**: path containment, shell command blocking (3 safety levels), tool execution pipeline
|
|
20
|
+
- **1.05M context window**: smart compression with working memory extraction at 75% threshold
|
|
13
21
|
|
|
14
22
|
## Install
|
|
15
23
|
|
|
@@ -52,6 +60,9 @@ EOF
|
|
|
52
60
|
# Single prompt
|
|
53
61
|
god-code ask "Add a health bar to the player scene" --project ./my-game
|
|
54
62
|
|
|
63
|
+
# Script-friendly plain output
|
|
64
|
+
god-code ask "Summarize this project" --project ./my-game --plain
|
|
65
|
+
|
|
55
66
|
# Interactive chat
|
|
56
67
|
god-code chat --project ./my-game
|
|
57
68
|
|
|
@@ -108,9 +119,14 @@ god-code logout # Removes stored credentials
|
|
|
108
119
|
"base_url": "https://api.openai.com/v1",
|
|
109
120
|
"model": "gpt-5.4",
|
|
110
121
|
"oauth_token": null,
|
|
122
|
+
"mode": "apply",
|
|
111
123
|
"max_turns": 20,
|
|
112
124
|
"max_tokens": 4096,
|
|
113
125
|
"temperature": 0.0,
|
|
126
|
+
"auto_validate": true,
|
|
127
|
+
"auto_commit": false,
|
|
128
|
+
"streaming": true,
|
|
129
|
+
"autosave_session": true,
|
|
114
130
|
"screenshot_max_iterations": 5,
|
|
115
131
|
"godot_path": "godot",
|
|
116
132
|
"session_dir": ".agent_sessions"
|
|
@@ -119,6 +135,16 @@ god-code logout # Removes stored credentials
|
|
|
119
135
|
|
|
120
136
|
All fields can be overridden with `GODOT_AGENT_` prefixed environment variables.
|
|
121
137
|
|
|
138
|
+
## Chat Commands
|
|
139
|
+
|
|
140
|
+
Interactive chat supports:
|
|
141
|
+
|
|
142
|
+
- `/mode [apply|plan|explain|review|fix]`
|
|
143
|
+
- `/sessions` and `/resume [session-id]`
|
|
144
|
+
- `/new` to start a fresh session
|
|
145
|
+
- `/workspace` to re-render the session snapshot
|
|
146
|
+
- `/set <key> <value>` for live configuration changes
|
|
147
|
+
|
|
122
148
|
## System Prompt & Output Quality
|
|
123
149
|
|
|
124
150
|
God Code's system prompt is dynamically assembled from:
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Multi-agent orchestration primitives for God Code."""
|
|
2
|
+
|
|
3
|
+
from godot_agent.agents.configs import AGENT_CONFIGS, AgentConfig
|
|
4
|
+
from godot_agent.agents.dispatcher import AgentDispatcher
|
|
5
|
+
from godot_agent.agents.results import AgentTaskResult
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"AGENT_CONFIGS",
|
|
9
|
+
"AgentConfig",
|
|
10
|
+
"AgentDispatcher",
|
|
11
|
+
"AgentTaskResult",
|
|
12
|
+
]
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Built-in role configurations for multi-agent orchestration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from godot_agent.runtime.modes import allowed_tools_for_mode
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
|
+
class AgentConfig:
|
|
12
|
+
name: str
|
|
13
|
+
mode: str
|
|
14
|
+
prompt: str
|
|
15
|
+
allowed_tools: set[str]
|
|
16
|
+
auto_validate: bool = False
|
|
17
|
+
max_tool_rounds: int = 8
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
_READ_ONLY_TOOLS = allowed_tools_for_mode("plan")
|
|
21
|
+
_WORKER_TOOLS = allowed_tools_for_mode("apply")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
AGENT_CONFIGS: dict[str, AgentConfig] = {
|
|
25
|
+
"planner": AgentConfig(
|
|
26
|
+
name="planner",
|
|
27
|
+
mode="plan",
|
|
28
|
+
prompt=(
|
|
29
|
+
"You are the Planner agent. Inspect the project and produce a concrete implementation plan, "
|
|
30
|
+
"risks, and validation strategy. Do not edit files."
|
|
31
|
+
),
|
|
32
|
+
allowed_tools=set(_READ_ONLY_TOOLS),
|
|
33
|
+
auto_validate=False,
|
|
34
|
+
max_tool_rounds=6,
|
|
35
|
+
),
|
|
36
|
+
"explorer": AgentConfig(
|
|
37
|
+
name="explorer",
|
|
38
|
+
mode="review",
|
|
39
|
+
prompt=(
|
|
40
|
+
"You are the Explorer agent. Read the project, map the relevant scripts/scenes/resources, "
|
|
41
|
+
"and return concise findings. Do not edit files."
|
|
42
|
+
),
|
|
43
|
+
allowed_tools=set(_READ_ONLY_TOOLS),
|
|
44
|
+
auto_validate=False,
|
|
45
|
+
max_tool_rounds=6,
|
|
46
|
+
),
|
|
47
|
+
"worker": AgentConfig(
|
|
48
|
+
name="worker",
|
|
49
|
+
mode="apply",
|
|
50
|
+
prompt=(
|
|
51
|
+
"You are the Worker agent. Implement the requested change with the smallest viable edit, "
|
|
52
|
+
"then rely on validation and reviewer feedback to converge."
|
|
53
|
+
),
|
|
54
|
+
allowed_tools=set(_WORKER_TOOLS),
|
|
55
|
+
auto_validate=True,
|
|
56
|
+
max_tool_rounds=12,
|
|
57
|
+
),
|
|
58
|
+
"reviewer": AgentConfig(
|
|
59
|
+
name="reviewer",
|
|
60
|
+
mode="review",
|
|
61
|
+
prompt=(
|
|
62
|
+
"You are the Reviewer agent. Validate the changes adversarially and report concrete findings. "
|
|
63
|
+
"Do not edit files."
|
|
64
|
+
),
|
|
65
|
+
allowed_tools=set(_READ_ONLY_TOOLS),
|
|
66
|
+
auto_validate=False,
|
|
67
|
+
max_tool_rounds=4,
|
|
68
|
+
),
|
|
69
|
+
"playtest_analyst": AgentConfig(
|
|
70
|
+
name="playtest_analyst",
|
|
71
|
+
mode="review",
|
|
72
|
+
prompt=(
|
|
73
|
+
"You are the Playtest Analyst agent. Evaluate runtime evidence and scenario-based playtest output, "
|
|
74
|
+
"then explain whether the gameplay intent still holds."
|
|
75
|
+
),
|
|
76
|
+
allowed_tools=set(_READ_ONLY_TOOLS),
|
|
77
|
+
auto_validate=False,
|
|
78
|
+
max_tool_rounds=4,
|
|
79
|
+
),
|
|
80
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Synchronous multi-agent dispatcher."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import replace
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from godot_agent.godot.impact_analysis import format_impact_report, infer_request_impact
|
|
9
|
+
from godot_agent.agents.configs import AGENT_CONFIGS, AgentConfig
|
|
10
|
+
from godot_agent.agents.results import AgentTaskResult
|
|
11
|
+
from godot_agent.llm.client import LLMClient
|
|
12
|
+
from godot_agent.prompts.assembler import PromptAssembler, PromptContext
|
|
13
|
+
from godot_agent.runtime.engine import ConversationEngine
|
|
14
|
+
from godot_agent.runtime.playtest_harness import format_playtest_report, run_playtest_harness
|
|
15
|
+
from godot_agent.runtime.quality_gate import QualityGateReport
|
|
16
|
+
from godot_agent.runtime.runtime_bridge import get_runtime_snapshot
|
|
17
|
+
from godot_agent.runtime.reviewer import format_review_report, review_changes
|
|
18
|
+
from godot_agent.tools.registry import ToolRegistry
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AgentDispatcher:
|
|
22
|
+
"""Creates role-scoped engines and deterministic review passes."""
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
*,
|
|
27
|
+
client: LLMClient,
|
|
28
|
+
registry: ToolRegistry,
|
|
29
|
+
prompt_context: PromptContext | None,
|
|
30
|
+
project_path: str | None,
|
|
31
|
+
godot_path: str = "godot",
|
|
32
|
+
base_allowed_tools: set[str] | None = None,
|
|
33
|
+
) -> None:
|
|
34
|
+
self.client = client
|
|
35
|
+
self.registry = registry
|
|
36
|
+
self.prompt_context = prompt_context
|
|
37
|
+
self.project_path = project_path
|
|
38
|
+
self.godot_path = godot_path
|
|
39
|
+
self.base_allowed_tools = set(base_allowed_tools) if base_allowed_tools is not None else None
|
|
40
|
+
|
|
41
|
+
def _clone_registry(self) -> ToolRegistry:
|
|
42
|
+
cloned = ToolRegistry()
|
|
43
|
+
for tool in self.registry.list_tools():
|
|
44
|
+
cloned.register(tool)
|
|
45
|
+
return cloned
|
|
46
|
+
|
|
47
|
+
def resolve_allowed_tools(self, role: str) -> set[str]:
|
|
48
|
+
config = AGENT_CONFIGS[role]
|
|
49
|
+
if self.base_allowed_tools is None:
|
|
50
|
+
return set(config.allowed_tools)
|
|
51
|
+
return set(config.allowed_tools & self.base_allowed_tools)
|
|
52
|
+
|
|
53
|
+
def _build_prompt_assembler(self, config: AgentConfig) -> PromptAssembler | None:
|
|
54
|
+
if self.prompt_context is None:
|
|
55
|
+
return None
|
|
56
|
+
context = replace(
|
|
57
|
+
self.prompt_context,
|
|
58
|
+
mode=config.mode,
|
|
59
|
+
extra_prompt="\n\n".join(
|
|
60
|
+
section for section in [self.prompt_context.extra_prompt, config.prompt] if section
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
return PromptAssembler(context)
|
|
64
|
+
|
|
65
|
+
def _build_engine(self, config: AgentConfig, *, user_hint: str) -> ConversationEngine:
|
|
66
|
+
registry = self._clone_registry()
|
|
67
|
+
prompt_assembler = self._build_prompt_assembler(config)
|
|
68
|
+
allowed_tools = self.resolve_allowed_tools(config.name)
|
|
69
|
+
if prompt_assembler is not None:
|
|
70
|
+
system_prompt = prompt_assembler.build(
|
|
71
|
+
user_hint=user_hint,
|
|
72
|
+
active_tools=[tool.name for tool in registry.list_tools() if tool.name in allowed_tools],
|
|
73
|
+
)
|
|
74
|
+
else:
|
|
75
|
+
system_prompt = config.prompt
|
|
76
|
+
|
|
77
|
+
engine = ConversationEngine(
|
|
78
|
+
client=self.client,
|
|
79
|
+
registry=registry,
|
|
80
|
+
system_prompt=system_prompt,
|
|
81
|
+
max_tool_rounds=config.max_tool_rounds,
|
|
82
|
+
project_path=self.project_path,
|
|
83
|
+
godot_path=self.godot_path,
|
|
84
|
+
auto_validate=config.auto_validate,
|
|
85
|
+
prompt_assembler=prompt_assembler,
|
|
86
|
+
mode=config.mode,
|
|
87
|
+
)
|
|
88
|
+
engine.base_allowed_tools = set(allowed_tools)
|
|
89
|
+
engine.allowed_tools = set(allowed_tools)
|
|
90
|
+
return engine
|
|
91
|
+
|
|
92
|
+
async def run_planner(self, task: str) -> AgentTaskResult:
|
|
93
|
+
config = AGENT_CONFIGS["planner"]
|
|
94
|
+
engine = self._build_engine(config, user_hint=task)
|
|
95
|
+
planning_prompt = task
|
|
96
|
+
if self.project_path:
|
|
97
|
+
impact_report = infer_request_impact(Path(self.project_path), task)
|
|
98
|
+
planning_prompt = f"{task}\n\nLikely impact before implementation:\n{format_impact_report(impact_report)}"
|
|
99
|
+
content = await engine.submit(planning_prompt)
|
|
100
|
+
return AgentTaskResult(
|
|
101
|
+
role=config.name,
|
|
102
|
+
content=content,
|
|
103
|
+
used_tools=engine.last_turn.tools_called if engine.last_turn else [],
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
async def run_worker(self, task: str, *, plan: str = "") -> AgentTaskResult:
|
|
107
|
+
config = AGENT_CONFIGS["worker"]
|
|
108
|
+
prompt = task if not plan else f"{task}\n\nApproved plan:\n{plan}"
|
|
109
|
+
engine = self._build_engine(config, user_hint=task)
|
|
110
|
+
content = await engine.submit(prompt)
|
|
111
|
+
verdict = "FAIL" if engine.last_review_report and engine.last_review_report.requires_fix else "PASS"
|
|
112
|
+
return AgentTaskResult(
|
|
113
|
+
role=config.name,
|
|
114
|
+
content=content,
|
|
115
|
+
verdict=verdict,
|
|
116
|
+
used_tools=engine.last_turn.tools_called if engine.last_turn else [],
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
async def run_reviewer(
|
|
120
|
+
self,
|
|
121
|
+
*,
|
|
122
|
+
changed_files: set[str],
|
|
123
|
+
quality_report: QualityGateReport | None = None,
|
|
124
|
+
) -> AgentTaskResult:
|
|
125
|
+
if not self.project_path:
|
|
126
|
+
return AgentTaskResult(role="reviewer", verdict="PASS", content="No project path configured.")
|
|
127
|
+
report = await review_changes(
|
|
128
|
+
project_root=Path(self.project_path),
|
|
129
|
+
changed_files=changed_files,
|
|
130
|
+
godot_path=self.godot_path,
|
|
131
|
+
quality_report=quality_report,
|
|
132
|
+
)
|
|
133
|
+
return AgentTaskResult(
|
|
134
|
+
role="reviewer",
|
|
135
|
+
content=format_review_report(report),
|
|
136
|
+
verdict=report.verdict,
|
|
137
|
+
raw=report,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
async def run_playtest_analyst(self, *, changed_files: set[str]) -> AgentTaskResult:
|
|
141
|
+
if not self.project_path:
|
|
142
|
+
return AgentTaskResult(role="playtest_analyst", verdict="PASS", content="No project path configured.")
|
|
143
|
+
report = run_playtest_harness(
|
|
144
|
+
project_root=Path(self.project_path),
|
|
145
|
+
changed_files=changed_files,
|
|
146
|
+
runtime_snapshot=get_runtime_snapshot(),
|
|
147
|
+
)
|
|
148
|
+
return AgentTaskResult(
|
|
149
|
+
role="playtest_analyst",
|
|
150
|
+
content=format_playtest_report(report),
|
|
151
|
+
verdict=report.verdict,
|
|
152
|
+
raw=report,
|
|
153
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Structured results for sub-agent execution."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class AgentTaskResult:
|
|
10
|
+
role: str
|
|
11
|
+
content: str = ""
|
|
12
|
+
verdict: str = "PASS"
|
|
13
|
+
notes: list[str] = field(default_factory=list)
|
|
14
|
+
used_tools: list[str] = field(default_factory=list)
|
|
15
|
+
raw: object | None = None
|