Files
claw/docs/superpowers/plans/2026-04-13-async-eval-then-fix.md
木炎 c60cd308ca feat: service console auto-connect, settings panel, and batch of enhancements
- Auto-connect WebSocket on page load in service console
- Settings modal for editing sgclaw_config.json (API key, base URL, model, skills dir, etc.)
- UpdateConfig/ConfigUpdated protocol messages for remote config save
- save_to_path() for SgClawSettings serialization
- ConfigUpdated handler in sg_claw_client binary
- Protocol serialization tests for new message types
- HTML test assertions for auto-connect and settings UI
- Additional pending changes: deterministic submit, org units, lineloss xlsx export, browser script tool, and docs

🤖 Generated with [Qoder][https://qoder.com]
2026-04-14 14:32:46 +08:00

2.7 KiB

Async Eval .then() Fix Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Fix build_eval_js to handle async script return values using .then() instead of async IIFE.

Architecture: Extract callback-sending logic into a _s helper function inside the generated JS. If the script returns a Promise, call _s via .then(); otherwise call _s synchronously. This keeps the outer IIFE synchronous for C++ injection compatibility.

Tech Stack: Rust, JavaScript


Files

  • Modify: src/browser/callback_backend.rs:433-447 - build_eval_js function

Task 1: Modify build_eval_js to support async via .then()

Files:

  • Modify: src/browser/callback_backend.rs:433-447

  • Step 1: Replace build_eval_js implementation

Replace the entire build_eval_js function body (lines 433-447) with:

fn build_eval_js(source_url: &str, script: &str) -> String {
    let escaped_source_url = escape_js_single_quoted(source_url);
    let callback = EVAL_CALLBACK_NAME;
    let events_url = escape_js_single_quoted(&events_endpoint_url(source_url));

    format!(
        "(function(){{try{{\
         var v=(function(){{return {script}}})();\
         function _s(v){{\
         var t=(typeof v==='string')?v:JSON.stringify(v);\
         try{{callBackJsToCpp('{escaped_source_url}@_@'+window.location.href+'@_@{callback}@_@sgBrowserExcuteJsCodeByDomain@_@'+(t??''))}}catch(_){{}}\
         var j=JSON.stringify({{type:'callback',callback:'{callback}',request_url:'{escaped_source_url}',payload:{{value:(t??'')}}}});\
         try{{var r=new XMLHttpRequest();r.open('POST','{events_url}',true);r.setRequestHeader('Content-Type','application/json');r.send(j)}}catch(_){{}}\
         try{{navigator.sendBeacon('{events_url}',new Blob([j],{{type:'application/json'}}))}}catch(_){{}}\
         }}\
         if(v&&typeof v.then==='function'){{v.then(_s).catch(function(){{}});}}else{{_s(v);}}\
         }}catch(e){{}}}})()"
    )
}
  • Step 2: Run tests

Run: cargo test browser_script_skill_tool --no-fail-fast

Expected: All tests pass.

  • Step 3: Run full test suite

Run: cargo test

Expected: All tests pass (except pre-existing lineloss_period_resolver_prompts_for_missing_period failure which is unrelated).

  • Step 4: Build

Run: cargo build

Expected: Compiles with no errors.

  • Step 5: Commit
git add src/browser/callback_backend.rs
git commit -m "fix: support async browser scripts via .then() in build_eval_js"