Commit 27f930d
* Pin UV_LINK_MODE=copy in uvx-bridge entries to dodge Windows pywin32 lock (#302)
* Fall back $HOME -> %USERPROFILE% in path-template expand() so OpenCode auto-configure works on Windows (#318)
User on Windows hit "Cannot write to /.config/opencode/opencode.json"
and "ERROR: Could not create directory: '/.config'" when auto-configuring
OpenCode. The leading "/" came from $HOME substituting to the empty
string -- Windows typically only sets USERPROFILE, not HOME. The same
module's _home() helper already does this fallback for ~/ expansion;
bring $HOME into line so the two spellings mean the same thing on
every platform. Running as admin doesn't help because the path itself
is malformed (rooted at the drive root).
OpenCode is the only descriptor that uses $HOME on Windows (because
opencode debug paths reports ~/.config/opencode/opencode.json on every
platform); other clients use $APPDATA / $USERPROFILE and dodged the
trap. Existing test_opencode_client_uses_home_config_on_windows
already exercises the right shape -- passes on Mac/Linux and on
GitHub Actions Windows runners (HOME set by default), which is how
this slipped through. After this change it passes on a stock Windows
box too.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Dedup $HOME fallback to _home() + add mocked-env test for USERPROFILE path (#319)
* Dedup $HOME fallback to _home() and lock USERPROFILE coverage with a mocked-env test
Follow-up to #318. Two review points from Copilot:
1. The new $HOME -> USERPROFILE branch was a fresh fallback path
instead of reusing _home(), so home-directory resolution had two
spellings that could drift again. Fold $HOME's fallback through
_home() so $HOME and ~ are guaranteed to mean the same thing.
2. test_opencode_client_uses_home_config_on_windows did not actually
exercise the new branch on CI: GitHub Actions Windows runners set
HOME by default, so the regression check passed without ever
touching the USERPROFILE fallback. Add a focused test that
explicitly clears HOME and sets USERPROFILE to a known value, runs
both $HOME/foo and ~/foo through expand(), and asserts the fallback
fires for both spellings on every CI platform.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Restore HOME/USERPROFILE via unset-when-empty pattern to avoid leaking defined-empty env vars
Copilot pointed out that OS.set_environment(name, "") creates a
defined-empty env var rather than leaving it unset, so restoring via
the captured saved_* values would silently promote previously-unset
vars to defined-empty for the rest of the test run. Mirror the
unset-when-saved-was-empty pattern already used by the GODOT_AI_MODE
tests in this file so the original unset/set state is preserved
exactly. Also switch the test's HOME-clearing setup from
set_environment("HOME", "") to unset_environment("HOME") for the
same reason.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Detect bare-key TOML sections in _toml_strategy to fix codex duplicate-key error (#320)
* Detect bare-key TOML sections in clients/_toml_strategy so codex reconfigure doesn't append a duplicate
When a user's TOML file has a bare-key section like
[mcp_servers.godot-ai] (valid TOML — bare keys allow [A-Za-z0-9_-]+),
McpTomlStrategy._all_headers only considered the quoted form
[mcp_servers."godot-ai"] that _primary_header always emits. _find_section
returned empty, configure fell through to the append-at-end path, and
the resulting file had two godot-ai sections — codex's TOML parser
rejects this with `duplicate key`. The same bug made check_status
report NOT_CONFIGURED on bare-key files (so the dock looked like the
client was unconfigured) and made remove a silent no-op.
Add _bare_key_header / _is_bare_key helpers and include the bare form
in _all_headers when every segment of toml_section_path matches
[A-Za-z0-9_-]+. _primary_header keeps emitting the quoted form for
new writes (no churn on existing-quoted-form files); the matcher just
tolerates either spelling now.
Add a regression test covering the codex shape: a fixture file with a
bare-key parent section plus a nested .tools subtable that the user
might add to set per-tool approval_mode. The test asserts
check_status detects the entry, configure updates it in place
(no duplicate; subtable customisation survives), and remove cleans
both spellings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Extend remove() to clean subtables in the namespace, not just the parent header
Copilot pointed out that the original fix in this PR is only partial:
remove() matches the parent header [mcp_servers.godot-ai] but stops at
the next bracketed line, which on the codex shape is the user's
[mcp_servers.godot-ai.tools.session_list] subtable. So remove reports
success but leaves the subtable behind. TOML treats that subtable as
implicitly defining mcp_servers.godot-ai, so a later configure
rewriting [mcp_servers."godot-ai"] produces a duplicate-key error
again — the exact shape the original bug took.
Add _subtable_prefixes / _matches_subtable_prefix helpers (mirrors of
the existing _matches_any_header style) and let remove() consume both
the parent header and any subtable header in the namespace before
moving on. Configure is unchanged — it only owns the matched parent
section's body, leaving subtables alone so user customisations like
per-tool approval_mode survive across reconfigure.
Tighten the regression test: assert subtable header AND its body
(approval_mode line) are gone after remove, then round-trip a
configure-after-remove and assert exactly one godot-ai section in
the final file. Pre-fix this round-trip would surface the original
duplicate-key shape.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Disconnect debugger screenshot timer on _clear_pending (#297 blind spot)
`_clear_pending` previously only erased the dict entry on screenshot
success/error, leaving the SceneTreeTimer + bound `_on_timeout` lambda
(which captures `request_id`) alive until the timer naturally fired —
up to `timeout_sec` (8s default) of dead state per request.
Store the bound timeout callable alongside the timer so the cleanup
path can disconnect `timer.timeout` and let the lambda + captured
request_id drop immediately. `_on_timeout` continues to bypass
`_clear_pending` because by the time it runs the timer has already
fired and self-disconnected.
Closes the "debugger timer leak on screenshot success" blind spot
called out in #297.
https://claude.ai/code/session_01EaT7NibPToHgffViz4eEvp
* Apply Copilot review feedback on TOML section-boundary detection
The pre-fix section-end check in remove() and _find_section() required
the next header to satisfy `ends_with("]")`, which doesn't hold for the
TOML `[next_section] # comment` form (valid TOML, hand-written by some
users). The end-of-section loop would walk past such a header and let
remove() clobber unrelated sections that came after.
Factor a shared `_is_any_section_header(line)` helper that finds the
closing `]` and permits whitespace or `#` after it — same shape used by
the existing `_matches_any_header` / `_matches_subtable_prefix` helpers
elsewhere in the file. remove() and _find_section() both consume it.
Adds `test_toml_strategy_remove_tolerates_inline_comment_on_next_header`
locking in the regression: file with `[other_section] # comment` after
the godot-ai section, remove() must delete only the godot-ai section
and preserve [other_section] and its body.
script/ci-check-gdscript: clean.
pytest: 722 passed.
https://claude.ai/code/session_01DwmN9ouQq88KnabiW42y2C
* Retrigger CI
Game capture smoke / Windows failed in 13s on the previous run — the
runtime points at a chickensoft-games/setup-godot@v2 infrastructure
hiccup (every other Windows job on the same SHA passed, and the diff
in this PR doesn't touch the capture path). Empty commit to retest.
https://claude.ai/code/session_01DwmN9ouQq88KnabiW42y2C
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 88e2ebe commit 27f930d
11 files changed
Lines changed: 596 additions & 35 deletions
File tree
- .github/workflows
- plugin/addons/godot_ai
- clients
- debugger
- testing
- script
- test_project/tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
163 | 163 | | |
164 | 164 | | |
165 | 165 | | |
166 | | - | |
| 166 | + | |
167 | 167 | | |
168 | 168 | | |
169 | 169 | | |
| |||
180 | 180 | | |
181 | 181 | | |
182 | 182 | | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
183 | 192 | | |
184 | 193 | | |
185 | 194 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
173 | 173 | | |
174 | 174 | | |
175 | 175 | | |
176 | | - | |
177 | | - | |
178 | | - | |
179 | | - | |
180 | | - | |
181 | | - | |
182 | | - | |
183 | | - | |
184 | | - | |
185 | | - | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
186 | 191 | | |
187 | 192 | | |
188 | 193 | | |
189 | 194 | | |
190 | 195 | | |
191 | 196 | | |
192 | | - | |
| 197 | + | |
193 | 198 | | |
194 | 199 | | |
195 | 200 | | |
196 | 201 | | |
197 | 202 | | |
198 | 203 | | |
199 | | - | |
200 | | - | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
201 | 210 | | |
202 | 211 | | |
203 | 212 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
180 | 180 | | |
181 | 181 | | |
182 | 182 | | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| 82 | + | |
82 | 83 | | |
83 | 84 | | |
84 | 85 | | |
85 | 86 | | |
86 | 87 | | |
87 | 88 | | |
88 | 89 | | |
| 90 | + | |
89 | 91 | | |
90 | 92 | | |
91 | 93 | | |
| |||
113 | 115 | | |
114 | 116 | | |
115 | 117 | | |
116 | | - | |
| 118 | + | |
117 | 119 | | |
118 | | - | |
119 | | - | |
120 | | - | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
121 | 123 | | |
122 | 124 | | |
123 | 125 | | |
124 | 126 | | |
125 | | - | |
126 | | - | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
127 | 133 | | |
128 | 134 | | |
129 | 135 | | |
| |||
132 | 138 | | |
133 | 139 | | |
134 | 140 | | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
135 | 207 | | |
136 | 208 | | |
137 | 209 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
| 42 | + | |
| 43 | + | |
42 | 44 | | |
43 | 45 | | |
44 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
84 | 90 | | |
85 | 91 | | |
86 | 92 | | |
87 | 93 | | |
88 | | - | |
| 94 | + | |
89 | 95 | | |
90 | 96 | | |
91 | | - | |
92 | | - | |
| 97 | + | |
93 | 98 | | |
94 | 99 | | |
95 | 100 | | |
| |||
152 | 157 | | |
153 | 158 | | |
154 | 159 | | |
155 | | - | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
156 | 171 | | |
157 | 172 | | |
158 | 173 | | |
159 | 174 | | |
160 | 175 | | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
161 | 229 | | |
162 | 230 | | |
163 | 231 | | |
| |||
177 | 245 | | |
178 | 246 | | |
179 | 247 | | |
180 | | - | |
181 | | - | |
| 248 | + | |
182 | 249 | | |
183 | 250 | | |
184 | 251 | | |
185 | 252 | | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
35 | | - | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
36 | 39 | | |
37 | 40 | | |
38 | 41 | | |
| |||
216 | 219 | | |
217 | 220 | | |
218 | 221 | | |
219 | | - | |
220 | 222 | | |
221 | | - | |
222 | | - | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
223 | 230 | | |
224 | 231 | | |
225 | 232 | | |
| |||
300 | 307 | | |
301 | 308 | | |
302 | 309 | | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
303 | 315 | | |
0 commit comments