god-code 0.1.4__tar.gz → 0.1.6__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.1.4 → god_code-0.1.6}/PKG-INFO +1 -1
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/cli.py +104 -13
- {god_code-0.1.4 → god_code-0.1.6}/pyproject.toml +1 -1
- {god_code-0.1.4 → god_code-0.1.6}/.github/workflows/publish.yml +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/.gitignore +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/CHANGELOG.md +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/CLAUDE.md +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/CONTRIBUTING.md +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/LICENSE +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/README.md +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/collision_planner.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/consistency_checker.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/dependency_graph.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/gdscript_linter.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/pattern_advisor.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/project.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/resource_validator.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/scene_parser.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/scene_writer.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/godot/tscn_validator.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/llm/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/llm/client.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/llm/streaming.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/llm/vision.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/prompts/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/prompts/build_discipline.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/prompts/godot_playbook.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/prompts/knowledge_selector.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/prompts/system.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/py.typed +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/runtime/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/runtime/auth.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/runtime/config.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/runtime/context_manager.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/runtime/engine.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/runtime/error_loop.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/runtime/oauth.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/runtime/session.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/tools/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/tools/base.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/tools/file_ops.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/tools/git.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/tools/godot_cli.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/tools/list_dir.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/tools/registry.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/tools/screenshot.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/tools/search.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/godot_agent/tools/shell.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/test_collision_planner.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/test_consistency.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/test_dependency_graph.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/test_linter.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/test_pattern_advisor.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/test_project.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/test_resource_validator.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/test_scene_parser.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/test_scene_writer.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/godot/test_tscn_validator.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/llm/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/llm/test_client.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/llm/test_vision.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/prompts/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/prompts/test_knowledge_selector.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/prompts/test_system_prompt.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/runtime/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/runtime/test_config.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/runtime/test_context_manager.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/runtime/test_engine.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/runtime/test_error_loop.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/test_e2e.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/tools/__init__.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/tools/test_file_ops.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/tools/test_git.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/tools/test_godot_cli.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/tools/test_list_dir.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/tools/test_registry.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/tools/test_search.py +0 -0
- {god_code-0.1.4 → god_code-0.1.6}/tests/tools/test_shell.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: god-code
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
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
|
|
@@ -195,18 +195,36 @@ def _run_setup_wizard() -> None:
|
|
|
195
195
|
click.echo()
|
|
196
196
|
|
|
197
197
|
|
|
198
|
+
_VERSION = "0.1.5"
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _check_update() -> None:
|
|
202
|
+
"""Check PyPI for a newer version. Non-blocking, fails silently."""
|
|
203
|
+
try:
|
|
204
|
+
import httpx as _httpx
|
|
205
|
+
resp = _httpx.get("https://pypi.org/pypi/god-code/json", timeout=3)
|
|
206
|
+
if resp.status_code == 200:
|
|
207
|
+
latest = resp.json()["info"]["version"]
|
|
208
|
+
if latest != _VERSION:
|
|
209
|
+
click.secho(f" Update available: {_VERSION} → {latest}", fg="yellow")
|
|
210
|
+
click.echo(f" Run: pip install --upgrade god-code")
|
|
211
|
+
click.echo()
|
|
212
|
+
except Exception:
|
|
213
|
+
pass
|
|
214
|
+
|
|
215
|
+
|
|
198
216
|
@click.group(invoke_without_command=True)
|
|
199
|
-
@click.version_option(version=
|
|
217
|
+
@click.version_option(version=_VERSION)
|
|
200
218
|
@click.pass_context
|
|
201
219
|
def main(ctx):
|
|
202
220
|
"""God Code -- AI coding assistant for Godot game development."""
|
|
203
221
|
logging.basicConfig(level=logging.WARNING, format="%(message)s")
|
|
222
|
+
_check_update()
|
|
204
223
|
if ctx.invoked_subcommand is None:
|
|
205
224
|
if not _is_configured():
|
|
206
225
|
_run_setup_wizard()
|
|
207
226
|
else:
|
|
208
|
-
|
|
209
|
-
click.echo(ctx.get_help())
|
|
227
|
+
ctx.invoke(chat)
|
|
210
228
|
|
|
211
229
|
|
|
212
230
|
@main.command()
|
|
@@ -285,38 +303,111 @@ def ask(prompt: str, project: str, config: str | None, image: tuple[str, ...]):
|
|
|
285
303
|
@main.command()
|
|
286
304
|
@click.option("--project", "-p", default=".", help="Path to Godot project root")
|
|
287
305
|
@click.option("--config", "-c", default=None, help="Path to config file")
|
|
288
|
-
def chat(project: str, config: str | None):
|
|
306
|
+
def chat(project: str = ".", config: str | None = None):
|
|
289
307
|
"""Start an interactive chat session."""
|
|
290
308
|
cfg = load_config(Path(config) if config else default_config_path())
|
|
291
309
|
if not cfg.api_key and not cfg.oauth_token:
|
|
292
310
|
click.secho("Not configured. Run 'god-code setup' first.", fg="yellow", err=True)
|
|
293
311
|
raise SystemExit(1)
|
|
312
|
+
|
|
294
313
|
project_root = Path(project).resolve()
|
|
295
|
-
engine = build_engine(cfg, project_root)
|
|
296
314
|
session_id = str(uuid.uuid4())[:8]
|
|
297
315
|
|
|
316
|
+
# Detect Godot project
|
|
317
|
+
has_project = (project_root / "project.godot").exists()
|
|
318
|
+
|
|
298
319
|
click.echo()
|
|
299
|
-
click.secho(
|
|
300
|
-
click.echo(f" Session:
|
|
301
|
-
|
|
302
|
-
|
|
320
|
+
click.secho(" God Code", fg="cyan", bold=True)
|
|
321
|
+
click.echo(f" Session: {session_id} | Model: {cfg.model}")
|
|
322
|
+
if has_project:
|
|
323
|
+
from godot_agent.godot.project import parse_project_godot
|
|
324
|
+
proj = parse_project_godot(project_root / "project.godot")
|
|
325
|
+
click.echo(f" Project: {proj.name} ({project_root})")
|
|
326
|
+
else:
|
|
327
|
+
click.echo(f" Working dir: {project_root}")
|
|
328
|
+
click.secho(" No project.godot found. Use /cd to navigate to a Godot project.", fg="yellow")
|
|
303
329
|
click.echo()
|
|
304
|
-
click.echo("
|
|
330
|
+
click.echo(" /cd <path> — change project directory")
|
|
331
|
+
click.echo(" /info — show project info")
|
|
332
|
+
click.echo(" /help — show commands")
|
|
333
|
+
click.echo(" /save — save session")
|
|
334
|
+
click.echo(" /quit — exit")
|
|
305
335
|
click.echo()
|
|
306
336
|
|
|
337
|
+
engine = build_engine(cfg, project_root)
|
|
338
|
+
|
|
339
|
+
def _rebuild_engine(new_root: Path) -> ConversationEngine:
|
|
340
|
+
nonlocal project_root, has_project
|
|
341
|
+
project_root = new_root.resolve()
|
|
342
|
+
has_project = (project_root / "project.godot").exists()
|
|
343
|
+
return build_engine(cfg, project_root)
|
|
344
|
+
|
|
307
345
|
async def _loop() -> None:
|
|
346
|
+
nonlocal engine
|
|
308
347
|
try:
|
|
309
348
|
while True:
|
|
310
349
|
try:
|
|
311
|
-
user_input = click.prompt(
|
|
350
|
+
user_input = click.prompt(
|
|
351
|
+
click.style("you", fg="green"), prompt_suffix="> "
|
|
352
|
+
)
|
|
312
353
|
except (EOFError, KeyboardInterrupt):
|
|
313
354
|
break
|
|
314
|
-
|
|
355
|
+
|
|
356
|
+
cmd = user_input.strip().lower()
|
|
357
|
+
|
|
358
|
+
if cmd in ("/quit", "quit", "/exit", "exit"):
|
|
315
359
|
break
|
|
316
|
-
|
|
360
|
+
|
|
361
|
+
if cmd in ("/save", "save"):
|
|
317
362
|
path = save_session(cfg.session_dir, session_id, engine.messages)
|
|
318
363
|
click.echo(f" Session saved to {path}")
|
|
319
364
|
continue
|
|
365
|
+
|
|
366
|
+
if cmd == "/help":
|
|
367
|
+
click.echo(" /cd <path> — change project directory")
|
|
368
|
+
click.echo(" /info — show project info")
|
|
369
|
+
click.echo(" /save — save session")
|
|
370
|
+
click.echo(" /status — show auth & model info")
|
|
371
|
+
click.echo(" /quit — exit")
|
|
372
|
+
continue
|
|
373
|
+
|
|
374
|
+
if cmd == "/info":
|
|
375
|
+
if has_project:
|
|
376
|
+
from godot_agent.godot.project import parse_project_godot
|
|
377
|
+
proj = parse_project_godot(project_root / "project.godot")
|
|
378
|
+
click.echo(f" Project: {proj.name}")
|
|
379
|
+
click.echo(f" Version: {proj.version}")
|
|
380
|
+
click.echo(f" Main Scene: {proj.main_scene}")
|
|
381
|
+
click.echo(f" Resolution: {proj.viewport_width}x{proj.viewport_height}")
|
|
382
|
+
click.echo(f" Autoloads: {len(proj.autoloads)}")
|
|
383
|
+
else:
|
|
384
|
+
click.secho(f" No project.godot in {project_root}", fg="yellow")
|
|
385
|
+
continue
|
|
386
|
+
|
|
387
|
+
if cmd == "/status":
|
|
388
|
+
click.echo(f" Model: {cfg.model}")
|
|
389
|
+
click.echo(f" Project: {project_root}")
|
|
390
|
+
click.echo(f" Godot: {cfg.godot_path}")
|
|
391
|
+
continue
|
|
392
|
+
|
|
393
|
+
if user_input.strip().startswith("/cd "):
|
|
394
|
+
new_path = Path(user_input.strip()[4:]).expanduser().resolve()
|
|
395
|
+
if not new_path.exists():
|
|
396
|
+
click.secho(f" Path not found: {new_path}", fg="red")
|
|
397
|
+
continue
|
|
398
|
+
await engine.close()
|
|
399
|
+
engine = _rebuild_engine(new_path)
|
|
400
|
+
has_godot = (new_path / "project.godot").exists()
|
|
401
|
+
if has_godot:
|
|
402
|
+
from godot_agent.godot.project import parse_project_godot
|
|
403
|
+
proj = parse_project_godot(new_path / "project.godot")
|
|
404
|
+
click.secho(f" Switched to: {proj.name} ({new_path})", fg="green")
|
|
405
|
+
else:
|
|
406
|
+
click.echo(f" Working dir: {new_path}")
|
|
407
|
+
click.secho(" No project.godot found here.", fg="yellow")
|
|
408
|
+
continue
|
|
409
|
+
|
|
410
|
+
# Regular message → send to LLM
|
|
320
411
|
response = await engine.submit(user_input)
|
|
321
412
|
click.echo()
|
|
322
413
|
click.echo(click.style("agent> ", fg="cyan") + response)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|