godot-cli-control 0.2.6__tar.gz → 0.2.7__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.
Files changed (54) hide show
  1. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/PKG-INFO +1 -1
  2. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/README.md +2 -1
  3. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/_version.py +2 -2
  4. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/cli.py +1 -1
  5. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/templates/skill/SKILL.md +29 -6
  6. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/.gitignore +0 -0
  7. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/LICENSE +0 -0
  8. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/CHANGELOG.md +0 -0
  9. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/LICENSE +0 -0
  10. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/bin/run_cli_control.ps1 +0 -0
  11. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/bin/run_cli_control.sh +0 -0
  12. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/bridge/error_codes.gd +0 -0
  13. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/bridge/game_bridge.gd +0 -0
  14. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/bridge/game_bridge.gd.uid +0 -0
  15. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/bridge/input_simulation_api.gd +0 -0
  16. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/bridge/input_simulation_api.gd.uid +0 -0
  17. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/bridge/low_level_api.gd +0 -0
  18. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/bridge/low_level_api.gd.uid +0 -0
  19. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/plugin.cfg +0 -0
  20. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/plugin.gd +0 -0
  21. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/plugin.gd.uid +0 -0
  22. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/tests/gut/test_game_bridge.gd +0 -0
  23. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/tests/gut/test_input_simulation_api.gd +0 -0
  24. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/tests/gut/test_low_level_api.gd +0 -0
  25. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/tests/run_gut.sh +0 -0
  26. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/tests/test_init_walkthrough.py +0 -0
  27. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/addons/godot_cli_control/tests/test_walkthrough.sh +0 -0
  28. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/pyproject.toml +0 -0
  29. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/README.md +0 -0
  30. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/__init__.py +0 -0
  31. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/__main__.py +0 -0
  32. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/_duration.py +0 -0
  33. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/bridge.py +0 -0
  34. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/client.py +0 -0
  35. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/daemon.py +0 -0
  36. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/init_cmd.py +0 -0
  37. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/pytest_plugin.py +0 -0
  38. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/registry.py +0 -0
  39. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/runner.py +0 -0
  40. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/skills_install.py +0 -0
  41. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/templates/__init__.py +0 -0
  42. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/godot_cli_control/templates/skill/__init__.py +0 -0
  43. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/__init__.py +0 -0
  44. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_bridge.py +0 -0
  45. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_cli.py +0 -0
  46. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_cli_helpers.py +0 -0
  47. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_client.py +0 -0
  48. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_daemon.py +0 -0
  49. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_duration.py +0 -0
  50. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_init.py +0 -0
  51. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_pytest_plugin.py +0 -0
  52. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_registry.py +0 -0
  53. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_runner.py +0 -0
  54. {godot_cli_control-0.2.6 → godot_cli_control-0.2.7}/python/tests/test_skills_install.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: godot-cli-control
3
- Version: 0.2.6
3
+ Version: 0.2.7
4
4
  Summary: WebSocket bridge for headless / scripted control of Godot scenes.
5
5
  Author: kesar
6
6
  License: MIT
@@ -93,11 +93,12 @@ All methods callable via `godot-cli-control <method>` or `from godot_cli_control
93
93
  | `action_press(action)` | `await client.action_press("jump")` |
94
94
  | `action_release(action)` | `await client.action_release("jump")` |
95
95
  | `action_tap(action, duration)` | `await client.action_tap("attack", 0.1)` |
96
- | `input_get_pressed` (raw RPC) | `await client.request("input_get_pressed")` |
97
96
  | `hold(action, duration)` | `await client.hold("run", 1.5)` |
98
97
  | `combo(steps)` | `await client.combo([{"action": "jump", "duration": 0.1}])` |
99
98
  | `combo_cancel()` | `await client.combo_cancel()` |
100
99
  | `release_all()` | `await client.release_all()` |
100
+ | `get_pressed()` | `await client.get_pressed()` |
101
+ | `list_input_actions(include_builtin=False)` | `await client.list_input_actions()` |
101
102
 
102
103
  ### Error codes
103
104
 
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.2.6'
22
- __version_tuple__ = version_tuple = (0, 2, 6)
21
+ __version__ = version = '0.2.7'
22
+ __version_tuple__ = version_tuple = (0, 2, 7)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -670,7 +670,7 @@ RPC_SPECS: tuple[RpcSpec, ...] = (
670
670
  handler=cmd_wait_time,
671
671
  description="按 game time 等待 N 秒(在 --write-movie 模式下与录像帧对齐)。",
672
672
  positionals=(
673
- Positional("seconds", None, "等待秒数(>0"),
673
+ Positional("seconds", None, "等待秒数(服务端范围 0 ≤ seconds ≤ 3600;client 在 ≤0 时短路返回成功)"),
674
674
  ),
675
675
  example="wait-time 0.5",
676
676
  text_formatter=_fmt_wait_time_text,
@@ -42,7 +42,8 @@ godot-cli-control daemon stop
42
42
  |---|---|
43
43
  | 0 | Success (or, for `exists` / `visible` / `wait-node`, the boolean was true / found) |
44
44
  | 1 | RPC error (server returned `{"error":...}`); also `exists`/`visible`=false, `wait-node`=timeout, `daemon status`=stopped |
45
- | 2 | Connection / IO / usage error (daemon not running, malformed `combo` input, etc.) |
45
+ | 2 | Connection / IO / usage error (daemon not running, malformed `combo` input, script path not found). Also: **`daemon stop` returns 2** when the daemon stopped cleanly but `ffmpeg` transcode of the recorded `.avi`→`.mp4` failed — the raw `.avi` is kept and `.cli_control/ffmpeg.log` has the details. `run <script>` propagates this: a successful script + failed transcode still exits 2. |
46
+ | 3 | `daemon stop --all` partial failure: at least one daemon in the registry failed to stop. Per-record `rc` is in the JSON `result.stopped[]`. |
46
47
  | 64 | Argparse usage error |
47
48
 
48
49
  Shell-`if` works:
@@ -53,6 +54,22 @@ if godot-cli-control exists /root/Main/Boss; then
53
54
  fi
54
55
  ```
55
56
 
57
+ ## Daemon management
58
+
59
+ ```bash
60
+ godot-cli-control daemon start # boot daemon for cwd project
61
+ godot-cli-control daemon status # exit 0 = running, 1 = stopped
62
+ godot-cli-control daemon stop # stop cwd-project daemon (rc 0; rc 2 = ffmpeg transcode failed)
63
+ godot-cli-control daemon stop --project /path/to/other/godot/project
64
+ godot-cli-control daemon stop --all # stop every registered daemon; exit 3 if any failed
65
+ godot-cli-control daemon ls # list all running daemons (cross-project, walks the registry)
66
+ ```
67
+
68
+ - **`daemon status` payload when running**: `{"state": "running", "pid": N, "port": M}`.
69
+ - **`daemon status` payload when stopped**: `{"state": "stopped"}`. If the previous launch wrote `.cli_control/godot.log` or recorded an exit code, the envelope also includes `"last_log": "<path>"` and/or `"last_exit_code": <int>` — use these to diagnose why the daemon died without manually grepping under `.cli_control/`.
70
+ - **`daemon ls` payload**: `{"daemons": [{"project_root", "pid", "port", "started_at", "godot_bin", "log_path"}, ...]}`. Dead records (PID gone) are auto-pruned on each call, so this is the canonical list of *actually-alive* daemons across all projects on the machine.
71
+ - **`daemon stop --all` payload**: `{"stopped": [{"project_root","pid","port","rc"[, "error"]}, ...], "rc": 0|3}`. Each entry's `rc` is the per-project stop result; the top-level `rc` is the aggregate exit code.
72
+
56
73
  ## JSON envelope examples
57
74
 
58
75
  ```bash
@@ -90,10 +107,10 @@ Three numeric ranges cohabit in `error.code`. Knowing which is which lets you de
90
107
  |---|---|
91
108
  | `1001` | Node not found at the given path. Most common — usually the agent passed a wrong / not-yet-loaded path. Retry after `wait-node`. |
92
109
  | `1002` | Property not found on the node, or shape mismatch (e.g. `text` on a node that doesn't have it). Don't retry; inspect with `tree`. |
93
- | `1003` | Method not found on the node. Schema error — don't retry, inspect with `tree`. |
110
+ | `1003` | Method not found on the node, **or** unknown InputMap action passed to `press`/`release`/`tap`/`hold`/`combo` (`"Unknown action: <name>"`). Schema error — don't retry. For node methods inspect with `tree`; for missing actions run `actions` (or `actions --all`). |
94
111
  | `1004` | Combo already in progress. Call `combo-cancel` (or `release-all`) and re-issue. Safe to retry after that. |
95
112
  | `1005` | Scene tree too large to serialize (default safety limit). Pass `--max-nodes` or query a subtree with `children` / `tree <subpath>`. Don't retry as-is. |
96
- | `1006` | Resource transiently unavailable (e.g. screenshot during scene transition / window resize). Rare under normal use: GameBridge waits for viewport first-frame before accepting connections, and `screenshot` retries internally up to ~500ms. If you still see this, retry after `wait-time 0.05` or similar. |
113
+ | `1006` | Resource transiently unavailable (e.g. screenshot during scene transition / window resize). Rare under normal use: GameBridge waits for viewport first-frame before accepting connections, and `screenshot` retries internally up to ~30 frames (~500ms at 60 fps, ~1s at 30 fps, longer when `--write-movie` lowers the fixed fps). If you still see this, retry after `wait-time 0.05` or similar. |
97
114
 
98
115
  **JSON-RPC standard — negative integers `-32xxx`:**
99
116
 
@@ -143,7 +160,7 @@ Server vs client ranges never overlap, so a single `code` field is unambiguous.
143
160
 
144
161
  **Wait:**
145
162
  - `wait-node <path> [timeout]` — block until node appears (exit 0=found, 1=timeout)
146
- - `wait-time <seconds>` — wait N in-game seconds (matters for `--write-movie`)
163
+ - `wait-time <seconds>` — wait N in-game seconds (matters for `--write-movie`). Server bounds: `0 ≤ seconds ≤ 3600`; passing out-of-range gets `-32602 "seconds must be ..."`. Client short-circuits `seconds <= 0` without an RPC.
147
164
 
148
165
  **Render:**
149
166
  - `screenshot <path>` — write PNG (path is **required** as of 0.2.0)
@@ -190,7 +207,7 @@ godot-cli-control call /root/Game start_game 1 '"easy"' # int 1, string "easy
190
207
 
191
208
  So `position '[100, 200]'` → `Vector2(100, 200)`, `transform '[1,0,0, 0,1,0, 0,0,1, 10,20,30]'` → `Transform3D(IDENTITY, (10,20,30))`. Wrong length or non-numeric elements fail loud with `-32602 "value type mismatch ..."` instead of silently setting `(0, 0)` like pre-0.2.5 versions did.
192
209
 
193
- **Sub-path + Array also fails loud.** `set <node> transform:origin '[10, 20, 30]'` is rejected with `-32602 "sub-path + Array is not supported"`: Godot's `Object.set("transform:origin", Array)` silently drops the Array (origin stays at `(0,0,0)`) — same footgun class as #52, so the server pre-empts it. Sub-paths are scalar-only (`set <node> position:x 1.8`); to write a whole compound Variant use the top-level Array form above.
210
+ **Sub-path + Array also fails loud.** `set <node> transform:origin '[10, 20, 30]'` is rejected with `-32602 "sub-path + Array is not supported"`: Godot's `Object.set("transform:origin", Array)` silently drops the Array (origin stays at `(0,0,0)`) — same class of footgun as the strict Variant checks above, so the server pre-empts it. Sub-paths are scalar-only (`set <node> position:x 1.8`); to write a whole compound Variant use the top-level Array form above.
194
211
 
195
212
  **Footgun**: bare `null` / `true` / `false` / numeric strings parse as JSON literals first, **not** as strings. If you actually mean the string `"null"`, wrap it explicitly:
196
213
 
@@ -294,7 +311,7 @@ Errors raise `RpcError(code, message)` (a `RuntimeError` subclass) that preserve
294
311
  | `await client.is_visible(path)` | `visible <path>` |
295
312
  | `await client.get_children(path)` | `children <path>` |
296
313
  | `await client.screenshot()` | `screenshot <path>` |
297
- | `await client.get_scene_tree(depth)` | `tree [depth]` |
314
+ | `await client.get_scene_tree(depth, max_nodes=None)` | `tree [depth] [--max-nodes N]` |
298
315
  | `await client.wait_for_node(path, timeout)` | `wait-node <path> [timeout]` |
299
316
  | `await client.wait_game_time(seconds)` | `wait-time <seconds>` |
300
317
  | `await client.action_press(action)` | `press <action>` |
@@ -321,6 +338,12 @@ def run(bridge):
321
338
 
322
339
  `bridge` is a synchronous wrapper around `GameClient` — same method names, no `await`. Sibling-imports work (the script's directory is on `sys.path`).
323
340
 
341
+ **Exit code (when `run` started the daemon itself):**
342
+ - `0` — script succeeded and daemon stopped cleanly.
343
+ - `1` — script raised (envelope carries `code: -1005` with the exception summary; full traceback on stderr).
344
+ - `2` — script-path / daemon-start failed, **or** the script succeeded but the auto-`daemon stop` afterwards hit an ffmpeg transcode failure (success envelope still emits, with `daemon_stop_warning` populated; raw `.avi` is preserved).
345
+ - `64` — argparse usage error (e.g. malformed `--idle-timeout`).
346
+
324
347
  ## pytest plugin (preferred for end-to-end test suites)
325
348
 
326
349
  `pip install godot-cli-control[pytest]` registers a `pytest11` entry-point that exposes two fixtures, so a Godot e2e test is a one-liner: