fix: add React import to StockfishWASM.tsx to resolve JSX type errors#684
Conversation
|
@Cedarich Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 51 minutes and 26 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis pull request introduces three major interconnected features: a Natural Language Agent interface for chess analysis requests with intent parsing and complexity-aware response generation, Stockfish 16.1 WebAssembly integration providing browser-compatible chess engine analysis with TypeScript bridge generation, and a Soroban smart contract deployment CI/CD pipeline featuring automated validation, multi-environment deployments, backup/rollback, and verification. Includes comprehensive documentation, implementation code, unit tests, and a production deployment script. Changes
Sequence DiagramssequenceDiagram
participant User
participant NLAgent as NL Agent
participant IntentParser as Intent Parser
participant EntityExtractor as Entity Extractor
participant Handler as Intent Handler
participant WorkerPool as Engine/Worker Pool
User->>NLAgent: process_request(user_input, fen?, moves?)
NLAgent->>IntentParser: recognize_intent(input)
IntentParser-->>NLAgent: IntentRecognition (intent, confidence)
NLAgent->>IntentParser: detect_complexity(input)
IntentParser-->>NLAgent: ComplexityLevel
alt FEN provided
NLAgent->>Handler: route to handler with FEN
else FEN not provided
NLAgent->>EntityExtractor: extract_fen_from_input(input)
EntityExtractor-->>NLAgent: fen?
NLAgent->>Handler: route to handler (may request FEN)
end
Handler->>WorkerPool: submit(position, depth)
WorkerPool-->>Handler: AnalysisResult
Handler->>NLAgent: format response
NLAgent-->>User: NLAnalysisResponse (text, moves, evaluation)
sequenceDiagram
participant Browser
participant Hook as useStockfishWASM Hook
participant Worker as Web Worker
participant WASM as Stockfish WASM
Browser->>Hook: useStockfishWASM(config)
Hook->>Worker: initialize() + Worker(bridge code)
Worker->>WASM: load stockfish.wasm
WASM-->>Worker: ready
Worker-->>Hook: post('ready')
Hook-->>Browser: isReady=true
Browser->>Hook: analyzePosition(fen, depth)
Hook->>Worker: post('analyze', {fen, depth})
Worker->>WASM: analyzePosition()
WASM-->>Worker: bestmove, evaluation
Worker-->>Hook: post('bestmove', result)
Hook-->>Browser: Promise resolves with AnalysisResult
sequenceDiagram
participant Trigger as GitHub Push/Manual
participant Validate as Validate Job
participant DeployTest as Deploy Testnet
participant DeployFuture as Deploy Futurenet
participant Verify as Verify Job
participant Notify as Notify Job
Trigger->>Validate: cargo test + cargo build wasm32
Validate->>Validate: soroban contract inspect *.wasm
Validate-->>DeployTest: ✓ artifacts ready
Validate-->>DeployFuture: ✓ artifacts ready
DeployTest->>DeployTest: soroban contract deploy (testnet)
DeployTest-->>DeployTest: save contract IDs
DeployTest-->>Verify: upload artifacts
DeployFuture->>DeployFuture: soroban contract deploy (futurenet)
Verify->>Verify: download & verify artifacts
Verify-->>Notify: verification results
Notify->>Notify: record summary (env/commit/status)
Notify-->>Trigger: ✓ complete
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 16
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (8)
.github/workflows/soroban-deploy.yml-274-285 (1)
274-285:⚠️ Potential issue | 🟡 MinorNotification summary hardcodes "Testnet" and ignores futurenet.
echo "- **Environment**: Testnet" >> $GITHUB_STEP_SUMMARYis a fixed string, but the workflow can also dispatch tofuturenet. Whendeploy-futurenetruns (anddeploy-testnetis skipped), this notify job will still report "Environment: Testnet" with askippedstatus. Drive the value from${{ github.event.inputs.environment || 'testnet' }}and addneeds.deploy-futurenetto theneeds:list (and the conditional). Also, shellcheck SC2086 flags the unquoted>> $GITHUB_STEP_SUMMARYredirects throughout this block.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/soroban-deploy.yml around lines 274 - 285, Update the Deployment summary step to derive the environment dynamically and fix unquoted redirects: replace the hardcoded "Testnet" string with the expression that reads the workflow input (github.event.inputs.environment || 'testnet') so the line reports the actual environment, add needs.deploy-futurenet to the job's needs list and reference needs.deploy-futurenet.result in the verification/status lines where appropriate (so deploy-futurenet isn't ignored), and quote the GITHUB_STEP_SUMMARY redirections (use ">> \"$GITHUB_STEP_SUMMARY\"") for every echo to satisfy shellcheck SC2086; locate and change these in the job that writes to GITHUB_STEP_SUMMARY and in any references to deploy-testnet/deploy-futurenet.contracts/deploy_advanced.sh-200-210 (1)
200-210:⚠️ Potential issue | 🟡 Minor
2>&1causes stderr noise to be persisted as the contract ID on success.Combining stdout and stderr into
contract_idmeans any informational linessorobanwrites to stderr (warnings, progress) get saved into.contract-${contract_name}-${network}.id(line 210) and re-used byverify/rollback. Consider capturing stderr separately so the file only contains the deployed contract ID.🛠️ Suggested fix
- contract_id=$(soroban contract deploy \ - --wasm "$wasm_file" \ - --source "$identity" \ - --network "$network" 2>&1) + local stderr_log + stderr_log=$(mktemp) + if contract_id=$(soroban contract deploy \ + --wasm "$wasm_file" \ + --source "$identity" \ + --network "$network" 2>"$stderr_log"); then + contract_id=$(printf '%s' "$contract_id" | tr -d '[:space:]') + rm -f "$stderr_log" + # ... success branch + else + log_message "ERROR" "Deployment failed: $(cat "$stderr_log")" + rm -f "$stderr_log" + return 1 + fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@contracts/deploy_advanced.sh` around lines 200 - 210, The current deployment captures both stdout and stderr into contract_id by using `2>&1` with the `soroban contract deploy` call, causing warnings/progress to be saved as the contract ID; change the invocation so stdout (the actual contract ID) is captured into contract_id while stderr is redirected separately (e.g., to a temp file or a separate variable) and use that stderr output only for logging via log_message, then pass only contract_id to save_contract_id; update the `soroban contract deploy` call, the `contract_id` assignment, and subsequent uses (contract_id, save_contract_id, and any logging) accordingly.contracts/deploy_advanced.sh-287-301 (1)
287-301:⚠️ Potential issue | 🟡 MinorWorkspace build inconsistency between deployment workflow and script.
The GitHub workflow (
.github/workflows/soroban-deploy.ymllines 65-67) builds contracts from thecontracts/directory using the nested workspace at./contracts/Cargo.toml, producing artifacts at./contracts/target/wasm32-unknown-unknown/release/. However,deploy_advanced.shbuilds from the repo root using the root workspace at./Cargo.toml(line 232-233), which produces artifacts at./target/wasm32-unknown-unknown/release/(line 288).The script is internally consistent, but it will fail to locate
.wasmfiles if the workflow has already built them into./contracts/target/, or conversely, the workflow will not find artifacts where the script produces them. Align the build working directory and workspace with the workflow's expectations, or document thatdeploy_advanced.shmust always run its own fresh build.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@contracts/deploy_advanced.sh` around lines 287 - 301, The script currently builds from the repo root but later looks for artifacts under "$CONTRACTS_DIR"/target, causing a workspace mismatch; update the build steps so they run inside the contracts workspace (cd "$CONTRACTS_DIR") before invoking cargo build (both the "build all" and "build specific contract" paths), ensuring artifacts are produced at "$CONTRACTS_DIR/target/wasm32-unknown-unknown/release/" so the existing loop that iterates over "$CONTRACTS_DIR"/target/... and calls deploy_contract "$network" "$name" "$identity" will find the .wasm files; alternatively, if you prefer not to change working dir, modify the artifact lookup to check both "./target/..." and "$CONTRACTS_DIR/target/..." but keep CONTRACTS_DIR, cargo build, and deploy_contract references consistent.agent-engines/gpu_worker/nl_agent.py-311-311 (1)
311-311:⚠️ Potential issue | 🟡 MinorMisleading units: value is in pawns, not centipawns.
result.evaluationis in pawn units (e.g.,0.5), but the string labels it "centipawns". A centipawn evaluation of 0.5 would be a 0.005-pawn advantage, which is not what's being reported. Either drop the parenthetical or convert:f"({int(round(result.evaluation * 100))} centipawns)".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/gpu_worker/nl_agent.py` at line 311, The f-string prints result.evaluation with the wrong unit label ("centipawns")—result.evaluation is in pawns; update the formatting where the evaluation string is built (the f-string using result.evaluation in nl_agent.py) to either remove the "(... centipawns)" parenthetical or convert to centipawns by multiplying result.evaluation by 100 and rounding to an integer (e.g., int(round(result.evaluation * 100))) before appending "centipawns" so the displayed units match the value.frontend/components/chess/StockfishWASM.tsx-267-273 (1)
267-273:⚠️ Potential issue | 🟡 MinorPipeline blocker: unescaped
"characters (line 270).ESLint
react/no-unescaped-entitiesis failing the build.🔧 Suggested fix
- <p>Click "Analyze" to get engine evaluation</p> + <p>Click "Analyze" to get engine evaluation</p>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@frontend/components/chess/StockfishWASM.tsx` around lines 267 - 273, The JSX contains an unescaped double quote in the string inside the conditional return in the StockfishWASM component (the <div className="analysis-empty"> / <p> node), which triggers react/no-unescaped-entities; fix by replacing the raw " characters with an escaped entity (e.g. ") or rewrite the string to avoid raw quotes (e.g. use single quotes or string concatenation) so the <p> text no longer contains unescaped double quotes.agent-engines/gpu_worker/stockfish_wasm_bridge.py-372-398 (1)
372-398:⚠️ Potential issue | 🟡 MinorOpen the generated file as UTF-8 and prefer
pathlib.
open(output_path, 'w')relies on the platform default encoding (cp1252on Windows), which would mangle the emoji characters (✅,🔄,❌,⏳) in the generated TSX. Pinencoding='utf-8'.🔧 Suggested fix
- with open(output_path, 'w') as f: + with open(output_path, 'w', encoding='utf-8') as f: f.write(code)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/gpu_worker/stockfish_wasm_bridge.py` around lines 372 - 398, The generated TSX file is opened without an explicit encoding and uses os.path; update save_bridge_component and the __main__ block to use pathlib.Path for path construction and directory creation and open the file with UTF-8: build output_path with Path(__file__).resolve().parents[2] / "frontend" / "components" / "chess" / "StockfishWASM.tsx", call output_path.parent.mkdir(parents=True, exist_ok=True), then write the code from generate_typescript_bridge() using output_path.open('w', encoding='utf-8') in save_bridge_component to preserve emoji characters and ensure cross-platform behavior.agent-engines/gpu_worker/stockfish_wasm.py-388-407 (1)
388-407:⚠️ Potential issue | 🟡 MinorReturn type annotation doesn't match the actual shape.
get_wasm_download_infois annotateddict[str, str], but the"files"value is itself adict[str, str]. Tighten the annotation (e.g.,dict[str, Any]or aTypedDict) so type checkers see the real structure.🔧 Suggested fix
- def get_wasm_download_info(self) -> dict[str, str]: + def get_wasm_download_info(self) -> dict[str, Any]:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/gpu_worker/stockfish_wasm.py` around lines 388 - 407, The return type annotation of get_wasm_download_info is incorrect: it is declared as dict[str, str] but returns nested dictionaries (e.g., the "files" key maps to a dict[str, str]). Update the annotation for get_wasm_download_info to reflect the actual shape (for example use dict[str, Any] or define a TypedDict describing keys "official_source", "version", "files" (dict[str, str]) and "installation") and apply that type to the function signature so static checkers see the nested structure.agent-engines/gpu_worker/nl_intent_parser.py-139-158 (1)
139-158:⚠️ Potential issue | 🟡 MinorMove extractor docstring claims
O-Osupport but the regex doesn't match castling.
[KQRBN]?[a-h]?[1-8]?x?[a-h][1-8]...requires a destination square[a-h][1-8], soO-OandO-O-Oare silently dropped. If_handle_compare_movesis ever asked to compare castling variants, it returns the "couldn't identify which moves" branch.🔧 Suggested fix
- move_pattern = r'\b([KQRBN]?[a-h]?[1-8]?x?[a-h][1-8](?:=[QRBN])?[+#]?)\b' + move_pattern = ( + r'\b(' + r'O-O(?:-O)?[+#]?' # castling + r'|[KQRBN]?[a-h]?[1-8]?x?[a-h][1-8](?:=[QRBN])?[+#]?' + r')\b' + )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/gpu_worker/nl_intent_parser.py` around lines 139 - 158, The current extract_moves_from_input function's regex only matches moves with a destination square and omits castling notations like O-O and O-O-O; update the move_pattern used in extract_moves_from_input to include an alternation for castling (e.g., match "O-O" and "O-O-O" before the square-based pattern), ensure the alternation captures the full match (so re.findall returns the whole move string) and keep existing filtering logic, and update the docstring to reflect explicit castling support.
🧹 Nitpick comments (9)
agent-engines/tests/test_stockfish_wasm.py (2)
360-376: Test reaches into a private attribute.
self.assertIsNone(engine._engine)couples the test to an internal field name. If the implementation renames or restructures_engine, this assertion silently breaks coverage of cleanup. Prefer asserting via a public state predicate (engine.status == TERMINATEDis already checked) or expose a documentedis_ready()/is_terminated()method.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/tests/test_stockfish_wasm.py` around lines 360 - 376, The test directly inspects the private attribute engine._engine in test_resource_cleanup which couples the test to implementation details; either change the test to assert only public state (e.g., engine.status == WASMEngineStatus.TERMINATED) or add a documented public predicate on StockfishWASMEngine (e.g., is_ready() or is_terminated()) that returns a boolean derived from status and use that in the test instead of referencing _engine; update test_resource_cleanup to call the new public predicate (or remove the _engine assertion) and keep the existing shutdown and status assertion.
5-12: Unused imports.
AsyncMock,MagicMock, andpatchare imported but never referenced in this file — the tests instantiate the realStockfishWASMEnginerather than mocking it. Drop the unused imports unless they will be used in upcoming additions.-from unittest.mock import AsyncMock, MagicMock, patch🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/tests/test_stockfish_wasm.py` around lines 5 - 12, Remove the unused test imports AsyncMock, MagicMock, and patch from the top-level import list in this test file; update the import block that currently brings in StockfishWASMEngine, WASMEngineConfig, WASMEngineStatus, WASMAnalysisResult so it only imports those used symbols, and only reintroduce AsyncMock/MagicMock/patch if you later add tests that actually mock StockfishWASMEngine or related behavior.agent-engines/gpu_worker/nl_models.py (1)
86-108: Minor: serialization key asymmetry between request and response.
NLAnalysisResponse.to_dict()mapsnatural_language_response→"response", whileNLAnalysisRequest.to_dict()preserves field names verbatim ("user_input", etc.). This makes round-tripping (e.g. logging, caching, then re-loading) inconsistent and forces consumers to remember the rename. Consider serializing as"natural_language_response"to keep field names stable across the model surface.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/gpu_worker/nl_models.py` around lines 86 - 108, NLAnalysisResponse.to_dict() currently serializes the natural_language_response field under the key "response", causing asymmetry with NLAnalysisRequest.to_dict(); change the serialization key to "natural_language_response" in NLAnalysisResponse.to_dict() so it matches the model field name and aligns with NLAnalysisRequest.to_dict(); update the dict entry that maps self.natural_language_response to use the "natural_language_response" key (function: NLAnalysisResponse.to_dict, symbol: natural_language_response) and run tests/logging to ensure round-tripping and consumers still behave correctly.agent-engines/tests/test_nl_agent.py (2)
294-305: Brittle string assertions on generated NL responses.
self.assertIn("position", response.natural_language_response.lower())(and similar for"fork","not sure"at lines 340, 353) tightly couples tests to specific wording. If the response template is reworded — e.g. to "Please share the board state first" — the test fails without a behavior change. Consider asserting on response intent/structure or explicit metadata flags (e.g.response.metadata["needs_fen"] is True) rather than substring checks.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/tests/test_nl_agent.py` around lines 294 - 305, The test test_process_without_fen currently asserts on exact substrings in response.natural_language_response which is brittle; update the test to assert on an explicit intent/flag returned by the agent instead (e.g. verify response.metadata["needs_fen"] is True or response.intent == "request_position") and replace similar substring checks in the other tests that look for "fork" and "not sure" with assertions against structured fields (e.g. response.metadata["requires_tactics"] or response.status == "uncertain") so the behavior is validated without coupling to exact wording from self.agent.process_request.
5-5:patchis imported but never used.Only
AsyncMockandMagicMockare used. Minor cleanup.-from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/tests/test_nl_agent.py` at line 5, Remove the unused import "patch" from the import statement that currently reads "from unittest.mock import AsyncMock, MagicMock, patch" in the test file; leave only the used symbols "AsyncMock" and "MagicMock" so the import becomes "from unittest.mock import AsyncMock, MagicMock" to eliminate the unused import warning..github/workflows/soroban-deploy.yml (1)
111-116: Avoid passing secrets through shell interpolation.
echo "${{ secrets.SOROBAN_SECRET_KEY }}" > secret.keyinjects the secret value directly into the shell command line; if the key ever contains characters like$, backticks, or newlines, it can be mangled or interpreted. The recommended pattern is to expose it viaenv:and reference it as$SOROBAN_SECRET_KEYso GitHub treats it as opaque data. Same applies to lines 210-215 for futurenet.🛠️ Suggested fix
- name: Setup deployment identity + env: + SOROBAN_SECRET_KEY: ${{ secrets.SOROBAN_SECRET_KEY }} run: | - echo "${{ secrets.SOROBAN_SECRET_KEY }}" > secret.key - soroban config identity add testnet-deployer \ - --secret-key "$(cat secret.key)" - rm secret.key + soroban config identity add testnet-deployer \ + --secret-key "$SOROBAN_SECRET_KEY"This also avoids writing the key to disk entirely.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/soroban-deploy.yml around lines 111 - 116, The deployment step "Setup deployment identity" is exposing the secret via shell interpolation and temporary file; instead, expose the secret through the job/step env (e.g., SOROBAN_SECRET_KEY) and pass it directly to the soroban command without echoing to disk — update the step to use env: SOROBAN_SECRET_KEY and invoke soroban config identity add testnet-deployer --secret-key "$SOROBAN_SECRET_KEY" (or use soroban's stdin/flag that accepts an environment value) and apply the same change for the futurenet setup to avoid writing secret.key and shell interpolation.contracts/deploy_advanced.sh (1)
6-20: Minor shellcheck hardening.Several
local var=$(cmd)patterns mask the inner command's exit status (SC2155) at lines 37, 64, 85, 102, 189, 290, 321, andlsparses are flagged for unquoted globs (SC2086) at lines 85/89/102. None of these are blocking, but separating declaration from assignment and quoting the globs (and switching tofind -print0 | xargs -0orfind ... -delete) makes the script more robust to filenames with spaces/special characters and to upstream command failures.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@contracts/deploy_advanced.sh` around lines 6 - 20, The script has ShellCheck issues: several occurrences of "local var=$(cmd)" (SC2155) and unquoted glob/ls parsing (SC2086) that can hide failures and break on spaces; for each function where a local variable is assigned from a command (e.g., any uses matching local VAR=$(...) around the lines flagged) split into two statements (declare local VAR first, then assign VAR="$(...)" or capture output with a separate command so the command's exit status is preserved), and replace unquoted glob/ls usages (e.g., patterns that list backups or contract files) with safely quoted globs or use find -print0 | xargs -0 or find ... -delete to handle spaces and special chars; ensure you update the specific symbols/variables where these occur (the local variable names and the places that iterate over files/backups) and run shellcheck to confirm SC2155 and SC2086 are resolved.agent-engines/gpu_worker/nl_agent.py (1)
520-534: Hoistimport reto module scope.Avoid the per-call import inside
_extract_concept;reis a stdlib module and the rest of the package already uses it (nl_intent_parser.py).🔧 Suggested fix
import logging +import re import uuid ... def _extract_concept(self, user_input: str) -> str: """Extract the chess concept from user input.""" patterns = [ r'(?:what is|explain|teach me about|tell me about)\s+(.+?)(?:\?|$)', r'(?:how does)\s+(.+?)(?:\s+work|\?|$)', ] - - import re + for pattern in patterns:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/gpu_worker/nl_agent.py` around lines 520 - 534, The _extract_concept method currently imports the re module inside the function causing per-call imports; move the import to module scope by adding "import re" at top-level of the file and remove the inline "import re" from _extract_concept so the function (and other code like nl_intent_parser.py users) reuse the module-level import; update any linting/comments if necessary to reflect the change and ensure _extract_concept continues to call re.search as before.agent-engines/gpu_worker/stockfish_wasm.py (1)
293-386: Duplicate JS bridge code withstockfish_wasm_bridge.py.This
generate_js_bridge_code()returns an older "simulated response" JS class whilestockfish_wasm_bridge.pyemits a full React/TS bridge for the same protocol. They drift independently (the message names here —analyze,stop— partially overlap, but there is noinit/readyhandshake, noquit, and the analysis result is hard-coded toe4). Pick one source of truth, or clearly mark this as a "fallback / non-React" variant in the docstring so consumers don't wire it up by accident.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@agent-engines/gpu_worker/stockfish_wasm.py` around lines 293 - 386, The generate_js_bridge_code() function emits an out-of-sync JS bridge that duplicates stockfish_wasm_bridge.py and returns a simulated, hard-coded response; fix by consolidating or clearly marking it as a fallback: either (A) remove this implementation and have generate_js_bridge_code() return a small shim that delegates to the canonical bridge in stockfish_wasm_bridge.py, or (B) update the returned code to be an explicit fallback (rename class to StockfishWASMBridgeFallback and update the docstring), add a proper init/ready/quit handshake (support 'init'/'ready' and 'quit' messages), align message names with the canonical protocol (use the same 'analyze'/'stop' semantics), and stop returning hard-coded analysis—have the fallback forward requests to config.onMessage or a worker and only simulate results behind a clearly labeled debug flag.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/soroban-deploy.yml:
- Around line 260-265: The verify-deployment job currently only echoes a
placeholder and must either perform real verification or be disabled; update the
job named verify-deployment to read the artifact file
(deployment-artifacts/contract-ids.txt) and iterate over each contract ID,
invoking soroban contract info --id <id> --network testnet (or the appropriate
network variable) and exit non-zero if any info call fails, emitting useful logs
per contract; alternatively, if you can't implement verification now, mark the
job as TODO/disabled and remove the misleading success echo so the workflow
summary is not falsely green.
- Around line 78-83: The deploy-testnet job's if condition allows any manual
dispatch to run it; update the if on the deploy-testnet job so manual
workflow_dispatch runs only when the dispatched environment input equals
"testnet" (e.g. change the condition to require github.event.inputs.environment
== 'testnet' for workflow_dispatch cases). Edit the deploy-testnet job's if
expression (the current line containing github.event_name ==
'workflow_dispatch') and replace it with a compound check such as (github.ref ==
'refs/heads/main' || (github.event_name == 'workflow_dispatch' &&
github.event.inputs.environment == 'testnet')) so deploy-testnet only runs for
main pushes or manual dispatches targeted at testnet.
- Around line 118-158: The "Deploy contracts" step currently writes unquoted
values to $GITHUB_OUTPUT and there are no job-level outputs declared, so
downstream steps (verify-deployment, notify) can't consume the IDs; fix by
either (A) declaring job outputs that map to the expected dynamic keys and write
to $GITHUB_OUTPUT with quotes (use ">> \"$GITHUB_OUTPUT\"" when appending
CONTRACT_NAME or contract_name values) so GitHub Actions picks them up, or (B)
instead collect all contract IDs into a concrete artifact file (e.g.,
deployment-artifacts/contract-ids.json) inside the "Deploy contracts" step and
upload it via actions/upload-artifact, then have verify-deployment download and
parse that artifact; ensure CONTRACT_NAME, contract_name and $GITHUB_OUTPUT
references are updated to use quoting and the verify-deployment/notify steps
read the artifact or the declared job outputs accordingly.
In `@agent-engines/gpu_worker/nl_agent.py`:
- Around line 302-307: The BEGINNER branch misinterprets UCI engine evals
(result.evaluation) as White-centric; update handling so the evaluation is
reported from the correct perspective: either extend AnalysisResult to include
board context (e.g., active_color or FEN) and normalize result.evaluation to
White's perspective before building the message, or change the phrasing to avoid
White/Black labels (e.g., "good for the side to move" / "good for the
opponent"). Locate the check under ComplexityLevel.BEGINNER and modify how the
string for the evaluation is chosen (the expression using result.evaluation) so
it uses the normalized value or the side-to-move-aware wording while keeping
result.best_move and result.depth in the message.
- Around line 293-410: The helper functions _generate_position_analysis_nl,
_generate_move_suggestion_nl and _generate_move_explanation_nl currently use
direct numeric comparisons and formatting on result.evaluation and
result.nodes_searched (e.g., expressions like result.evaluation > 0.3,
f"{result.evaluation}", and f"{result.nodes_searched:,}") which will raise when
evaluation or nodes_searched is None; create a small centralized guard that uses
the existing _format_evaluation(result.evaluation, complexity) for any displayed
evaluation text and add boolean helpers (e.g.,
_eval_is_positive(result.evaluation), _eval_is_strong(result.evaluation)) that
safely return False when evaluation is None, and a _format_nodes(nodes) that
returns "N/A" if None (or formats with commas otherwise); then replace all
direct comparisons/formatting in _generate_position_analysis_nl,
_generate_move_suggestion_nl, and _generate_move_explanation_nl with these safe
helpers (also use the helpers where building PV and displayed numeric strings)
so None values are handled consistently and no TypeError is thrown.
In `@agent-engines/gpu_worker/nl_intent_parser.py`:
- Around line 122-136: The extract_fen_from_input function is only matching
piece placement and side-to-move, causing incomplete FENs; update the
fen_pattern used in extract_fen_from_input to also capture castling rights (KQkq
or -), en-passant square (e.g. e3 or -), the halfmove clock (one or more digits)
and the fullmove number (one or more digits), separated by spaces in that order,
and allow optional surrounding whitespace before/after; keep returning
match.group(0).strip() from the same function once the regex is extended so
chess.Board() receives a complete FEN.
- Around line 16-47: INTENT_PATTERNS contains seven regex strings with an extra
leading "(" causing unbalanced groups and re.error; for each affected entry in
INTENT_PATTERNS (IntentType.SUGGEST_MOVE, IntentType.EXPLAIN_MOVE,
IntentType.GET_HINT, IntentType.COMPARE_MOVES, IntentType.LEARN_CONCEPT) remove
the stray leading "(" from the listed patterns so the parentheses are balanced
(e.g., patterns under INTENT_PATTERNS[IntentType.SUGGEST_MOVE] and the specific
problematic strings in INTENT_PATTERNS[IntentType.EXPLAIN_MOVE],
INTENT_PATTERNS[IntentType.GET_HINT], INTENT_PATTERNS[IntentType.COMPARE_MOVES],
and INTENT_PATTERNS[IntentType.LEARN_CONCEPT]); then run recognize_intent()
tests to confirm no re.error is raised.
In `@agent-engines/gpu_worker/stockfish_wasm_bridge.py`:
- Around line 11-13: The template string returned by the generator (the
triple-quoted return in gpu_worker.stockfish_wasm_bridge.py that produces
StockfishWASM.tsx) omits the React default import; update that returned content
so the import line reads "import React, { useState, useEffect, useCallback,
useRef } from 'react';" (or otherwise include the default React import alongside
the named hooks) inside the returned template, and ensure the generator path
used by __main__ (which writes frontend/components/chess/StockfishWASM.tsx) now
produces the corrected import so running the script no longer reverts PR `#684`'s
fix.
- Around line 48-258: The generator function generate_typescript_bridge() in
stockfish_wasm_bridge.py must be updated so it emits the current
StockfishWASM.tsx changes: include the React import at the top, use unknown
instead of any (e.g., type for engineRef and message parameter) and properly
type handleEngineMessage's parameter, reorder emitted functions so
handleEngineMessage and cleanup are declared before the useEffect that depends
on them, update the useEffect dependency array to [config, cleanup,
handleEngineMessage] (instead of just [config]), and ensure literal quotes in
JSX are HTML-escaped (use " for "Analyze"); update the generator
templates/strings and symbol names (generate_typescript_bridge,
handleEngineMessage, cleanup, useEffect) accordingly to preserve these fixes on
regeneration.
In `@agent-engines/gpu_worker/stockfish_wasm.py`:
- Around line 193-206: The finally block unconditionally resets self._status to
WASMEngineStatus.READY, masking errors set in the except; change the logic so
the READY state is only set on successful completion or when current status is
not ERROR (e.g., replace the unconditional assignment in the finally with: if
self._status != WASMEngineStatus.ERROR: self._status = WASMEngineStatus.READY),
referring to the _perform_analysis call, the except that sets
WASMEngineStatus.ERROR, and the self._status assignment that currently lives in
the finally.
In `@contracts/deploy_advanced.sh`:
- Around line 94-118: The rollback() function currently only sources the backup
and logs the previous contract_id but does not restore the local ID file or
perform any on-chain action; update rollback() so after sourcing the backup it
writes the previous contract_id back into the persistent id file (the same file
written by save_contract_id, i.e. .contract-${contract_name}-${network}.id)
using the BACKUP_DIR/backup contents (contract_id variable), and add a log
message clarifying that only the local ID file was restored and that on-chain
rollback/upgrades must be performed separately (do not attempt automatic
on-chain switching here). Ensure you reference the rollback() function,
save_contract_id behavior, the .contract-${contract_name}-${network}.id file,
BACKUP_DIR and contract_id when making the change.
- Around line 199-224: The failure branch is unreachable because command
substitution exits under set -e; change the pattern so the command is executed
inside an if-condition that captures stdout/stderr into a variable and lets you
test its exit status: replace the current contract_id=$(soroban contract deploy
... 2>&1) + if [ $? -eq 0 ]; then ... else ... fi with if contract_id=$(soroban
contract deploy --wasm "$wasm_file" --source "$identity" --network "$network"
2>&1); then log success and call save_contract_id/verify_deployment as before
using $contract_id; else log the ERROR with the captured $contract_id output,
echo the failure message, call rollback as needed, and return 1; fi. Apply the
same change in build_contracts(): replace cargo build ... + if [ $? -eq 0 ] with
if build_output=$(cargo build ... 2>&1); then handle success, else log
build_output on failure and return/rollback.
In `@frontend/components/chess/StockfishWASM.tsx`:
- Around line 49-117: The effect currently lists the whole config object in
useEffect deps causing reinitialization; change the dependency array to only the
primitive config fields used during init (e.g., config.jsBridgePath,
config.threads, config.hashSizeMB, config.skillLevel) instead of config, and
keep cleanup and handleEngineMessage out of the array only if they are stable
(they are: cleanup and handleEngineMessage are useCallback([])); update the
useEffect signature that wraps initializeEngine to depend on those primitives
(and workerRef remains as-is), so the initializeEngine/worker setup runs once
per relevant config change and avoids tearing down the Worker on every render.
- Around line 120-155: The handler handleEngineMessage currently types its
parameter as any and uses || which collapses 0 to null; change the parameter to
a well-defined type/interface (e.g., EngineMessage with discriminated union
cases 'bestmove'|'info'|'error' and fields bestMove, evaluation, depth, pv,
nodes, timeMs, message) and replace the evaluation coalescing with nullish
coalescing (data.evaluation ?? null) when building the AnalysisResult in the
'bestmove' branch; keep the existing logic that resolves via
resolveRef.current(result), clears resolveRef/rejectRef, cancels timeoutRef, and
in the 'error' branch call setIsAnalyzing(false), setError(data.message ||
'Engine error') and invoke rejectRef.current(new Error(data.message)) as before.
- Around line 42-46: engineRef is declared as useRef<any> but never used,
causing the no-explicit-any lint failure; remove the engineRef declaration
(const engineRef = useRef<any>(null)) and any references to engineRef.current
(notably the engineRef.current = null line in cleanup()) so the file no longer
contains the unused any-typed ref; if you prefer to keep a ref, replace
useRef<any> with a concrete type matching the engine object and ensure it is
actually read elsewhere (but the simpler fix is to delete engineRef and its
cleanup assignment).
- Around line 61-100: The init race occurs because worker.postMessage({type:
'init', ...}) is sent before the ready listener is registered; move the
ready/handshake listener registration so it runs before sending the 'init'
message. Specifically, register the message handler used for the handshake (the
checkReady handler added via worker.addEventListener('message', checkReady)
and/or set worker.onmessage = (event) => handleEngineMessage(event.data)) before
calling worker.postMessage({ type: 'init', ... }), keep the same
timeout/clearTimeout and worker.removeEventListener('message', checkReady)
logic, and preserve the cancelled check and setIsReady(true) flow so the promise
resolves correctly once the worker sends its 'ready' event.
---
Minor comments:
In @.github/workflows/soroban-deploy.yml:
- Around line 274-285: Update the Deployment summary step to derive the
environment dynamically and fix unquoted redirects: replace the hardcoded
"Testnet" string with the expression that reads the workflow input
(github.event.inputs.environment || 'testnet') so the line reports the actual
environment, add needs.deploy-futurenet to the job's needs list and reference
needs.deploy-futurenet.result in the verification/status lines where appropriate
(so deploy-futurenet isn't ignored), and quote the GITHUB_STEP_SUMMARY
redirections (use ">> \"$GITHUB_STEP_SUMMARY\"") for every echo to satisfy
shellcheck SC2086; locate and change these in the job that writes to
GITHUB_STEP_SUMMARY and in any references to deploy-testnet/deploy-futurenet.
In `@agent-engines/gpu_worker/nl_agent.py`:
- Line 311: The f-string prints result.evaluation with the wrong unit label
("centipawns")—result.evaluation is in pawns; update the formatting where the
evaluation string is built (the f-string using result.evaluation in nl_agent.py)
to either remove the "(... centipawns)" parenthetical or convert to centipawns
by multiplying result.evaluation by 100 and rounding to an integer (e.g.,
int(round(result.evaluation * 100))) before appending "centipawns" so the
displayed units match the value.
In `@agent-engines/gpu_worker/nl_intent_parser.py`:
- Around line 139-158: The current extract_moves_from_input function's regex
only matches moves with a destination square and omits castling notations like
O-O and O-O-O; update the move_pattern used in extract_moves_from_input to
include an alternation for castling (e.g., match "O-O" and "O-O-O" before the
square-based pattern), ensure the alternation captures the full match (so
re.findall returns the whole move string) and keep existing filtering logic, and
update the docstring to reflect explicit castling support.
In `@agent-engines/gpu_worker/stockfish_wasm_bridge.py`:
- Around line 372-398: The generated TSX file is opened without an explicit
encoding and uses os.path; update save_bridge_component and the __main__ block
to use pathlib.Path for path construction and directory creation and open the
file with UTF-8: build output_path with Path(__file__).resolve().parents[2] /
"frontend" / "components" / "chess" / "StockfishWASM.tsx", call
output_path.parent.mkdir(parents=True, exist_ok=True), then write the code from
generate_typescript_bridge() using output_path.open('w', encoding='utf-8') in
save_bridge_component to preserve emoji characters and ensure cross-platform
behavior.
In `@agent-engines/gpu_worker/stockfish_wasm.py`:
- Around line 388-407: The return type annotation of get_wasm_download_info is
incorrect: it is declared as dict[str, str] but returns nested dictionaries
(e.g., the "files" key maps to a dict[str, str]). Update the annotation for
get_wasm_download_info to reflect the actual shape (for example use dict[str,
Any] or define a TypedDict describing keys "official_source", "version", "files"
(dict[str, str]) and "installation") and apply that type to the function
signature so static checkers see the nested structure.
In `@contracts/deploy_advanced.sh`:
- Around line 200-210: The current deployment captures both stdout and stderr
into contract_id by using `2>&1` with the `soroban contract deploy` call,
causing warnings/progress to be saved as the contract ID; change the invocation
so stdout (the actual contract ID) is captured into contract_id while stderr is
redirected separately (e.g., to a temp file or a separate variable) and use that
stderr output only for logging via log_message, then pass only contract_id to
save_contract_id; update the `soroban contract deploy` call, the `contract_id`
assignment, and subsequent uses (contract_id, save_contract_id, and any logging)
accordingly.
- Around line 287-301: The script currently builds from the repo root but later
looks for artifacts under "$CONTRACTS_DIR"/target, causing a workspace mismatch;
update the build steps so they run inside the contracts workspace (cd
"$CONTRACTS_DIR") before invoking cargo build (both the "build all" and "build
specific contract" paths), ensuring artifacts are produced at
"$CONTRACTS_DIR/target/wasm32-unknown-unknown/release/" so the existing loop
that iterates over "$CONTRACTS_DIR"/target/... and calls deploy_contract
"$network" "$name" "$identity" will find the .wasm files; alternatively, if you
prefer not to change working dir, modify the artifact lookup to check both
"./target/..." and "$CONTRACTS_DIR/target/..." but keep CONTRACTS_DIR, cargo
build, and deploy_contract references consistent.
In `@frontend/components/chess/StockfishWASM.tsx`:
- Around line 267-273: The JSX contains an unescaped double quote in the string
inside the conditional return in the StockfishWASM component (the <div
className="analysis-empty"> / <p> node), which triggers
react/no-unescaped-entities; fix by replacing the raw " characters with an
escaped entity (e.g. ") or rewrite the string to avoid raw quotes (e.g. use
single quotes or string concatenation) so the <p> text no longer contains
unescaped double quotes.
---
Nitpick comments:
In @.github/workflows/soroban-deploy.yml:
- Around line 111-116: The deployment step "Setup deployment identity" is
exposing the secret via shell interpolation and temporary file; instead, expose
the secret through the job/step env (e.g., SOROBAN_SECRET_KEY) and pass it
directly to the soroban command without echoing to disk — update the step to use
env: SOROBAN_SECRET_KEY and invoke soroban config identity add testnet-deployer
--secret-key "$SOROBAN_SECRET_KEY" (or use soroban's stdin/flag that accepts an
environment value) and apply the same change for the futurenet setup to avoid
writing secret.key and shell interpolation.
In `@agent-engines/gpu_worker/nl_agent.py`:
- Around line 520-534: The _extract_concept method currently imports the re
module inside the function causing per-call imports; move the import to module
scope by adding "import re" at top-level of the file and remove the inline
"import re" from _extract_concept so the function (and other code like
nl_intent_parser.py users) reuse the module-level import; update any
linting/comments if necessary to reflect the change and ensure _extract_concept
continues to call re.search as before.
In `@agent-engines/gpu_worker/nl_models.py`:
- Around line 86-108: NLAnalysisResponse.to_dict() currently serializes the
natural_language_response field under the key "response", causing asymmetry with
NLAnalysisRequest.to_dict(); change the serialization key to
"natural_language_response" in NLAnalysisResponse.to_dict() so it matches the
model field name and aligns with NLAnalysisRequest.to_dict(); update the dict
entry that maps self.natural_language_response to use the
"natural_language_response" key (function: NLAnalysisResponse.to_dict, symbol:
natural_language_response) and run tests/logging to ensure round-tripping and
consumers still behave correctly.
In `@agent-engines/gpu_worker/stockfish_wasm.py`:
- Around line 293-386: The generate_js_bridge_code() function emits an
out-of-sync JS bridge that duplicates stockfish_wasm_bridge.py and returns a
simulated, hard-coded response; fix by consolidating or clearly marking it as a
fallback: either (A) remove this implementation and have
generate_js_bridge_code() return a small shim that delegates to the canonical
bridge in stockfish_wasm_bridge.py, or (B) update the returned code to be an
explicit fallback (rename class to StockfishWASMBridgeFallback and update the
docstring), add a proper init/ready/quit handshake (support 'init'/'ready' and
'quit' messages), align message names with the canonical protocol (use the same
'analyze'/'stop' semantics), and stop returning hard-coded analysis—have the
fallback forward requests to config.onMessage or a worker and only simulate
results behind a clearly labeled debug flag.
In `@agent-engines/tests/test_nl_agent.py`:
- Around line 294-305: The test test_process_without_fen currently asserts on
exact substrings in response.natural_language_response which is brittle; update
the test to assert on an explicit intent/flag returned by the agent instead
(e.g. verify response.metadata["needs_fen"] is True or response.intent ==
"request_position") and replace similar substring checks in the other tests that
look for "fork" and "not sure" with assertions against structured fields (e.g.
response.metadata["requires_tactics"] or response.status == "uncertain") so the
behavior is validated without coupling to exact wording from
self.agent.process_request.
- Line 5: Remove the unused import "patch" from the import statement that
currently reads "from unittest.mock import AsyncMock, MagicMock, patch" in the
test file; leave only the used symbols "AsyncMock" and "MagicMock" so the import
becomes "from unittest.mock import AsyncMock, MagicMock" to eliminate the unused
import warning.
In `@agent-engines/tests/test_stockfish_wasm.py`:
- Around line 360-376: The test directly inspects the private attribute
engine._engine in test_resource_cleanup which couples the test to implementation
details; either change the test to assert only public state (e.g., engine.status
== WASMEngineStatus.TERMINATED) or add a documented public predicate on
StockfishWASMEngine (e.g., is_ready() or is_terminated()) that returns a boolean
derived from status and use that in the test instead of referencing _engine;
update test_resource_cleanup to call the new public predicate (or remove the
_engine assertion) and keep the existing shutdown and status assertion.
- Around line 5-12: Remove the unused test imports AsyncMock, MagicMock, and
patch from the top-level import list in this test file; update the import block
that currently brings in StockfishWASMEngine, WASMEngineConfig,
WASMEngineStatus, WASMAnalysisResult so it only imports those used symbols, and
only reintroduce AsyncMock/MagicMock/patch if you later add tests that actually
mock StockfishWASMEngine or related behavior.
In `@contracts/deploy_advanced.sh`:
- Around line 6-20: The script has ShellCheck issues: several occurrences of
"local var=$(cmd)" (SC2155) and unquoted glob/ls parsing (SC2086) that can hide
failures and break on spaces; for each function where a local variable is
assigned from a command (e.g., any uses matching local VAR=$(...) around the
lines flagged) split into two statements (declare local VAR first, then assign
VAR="$(...)" or capture output with a separate command so the command's exit
status is preserved), and replace unquoted glob/ls usages (e.g., patterns that
list backups or contract files) with safely quoted globs or use find -print0 |
xargs -0 or find ... -delete to handle spaces and special chars; ensure you
update the specific symbols/variables where these occur (the local variable
names and the places that iterate over files/backups) and run shellcheck to
confirm SC2155 and SC2086 are resolved.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f373d874-39e4-4dbd-9ff3-9f6bbf101ab8
⛔ Files ignored due to path filters (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (13)
.github/workflows/soroban-deploy.ymlIMPLEMENTATION_SUMMARY.mdQUICK_REFERENCE.mdagent-engines/README.mdagent-engines/gpu_worker/nl_agent.pyagent-engines/gpu_worker/nl_intent_parser.pyagent-engines/gpu_worker/nl_models.pyagent-engines/gpu_worker/stockfish_wasm.pyagent-engines/gpu_worker/stockfish_wasm_bridge.pyagent-engines/tests/test_nl_agent.pyagent-engines/tests/test_stockfish_wasm.pycontracts/deploy_advanced.shfrontend/components/chess/StockfishWASM.tsx
Summary
Fixed TypeScript error in
StockfishWASM.tsxwhere JSX elements were implicitly typed as 'any' due to missing React import.Problem
JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists(TS7026)jsx: "preserve"in tsconfig.json, React must be in scope for TypeScript to recognize JSX typesSolution
Reactto the import statement from 'react' moduleChanges
frontend/components/chess/StockfishWASM.tsx: Added React importTesting
closes #637
closes #635
closes #628
closes #647
Summary by CodeRabbit
Release Notes
New Features
Tests