14 KiB
sgClaw Floating Chat Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Replace the current debug-style sgclaw-chat page as the primary UX with a floating page button + popup chat window, add real multi-turn conversation support, and harden the DeepSeek/browser tool protocol so browser automation is stable.
Architecture: Keep chrome://superrpa-functions/sgclaw-chat and chrome://superrpa-functions/sgclaw-config as debug/config pages, but make the user-facing entry a floating page launcher injected into allowed HTTP/HTTPS pages via existing SuperRPA page-injection capabilities. Reuse the browser-side persistent SgClawSessionService as the session owner, extend it from “logs + final result” to “conversation + runtime state”, and extend the sgClaw pipe path so each submit can carry conversation context instead of behaving like a fresh one-shot task. Fix protocol bugs in parallel: strict action-schema validation, better browser/sgClaw error attribution, and DeepSeek tool-call history compatibility.
Tech Stack: Chromium WebUI + Lit, existing SuperRPA page injection (sg_compat.js / hook injection), browser-side FunctionsUI/SgClawSessionService, Rust sgClaw, ZeroClaw compatibility runtime, DeepSeek OpenAI-compatible chat API.
Task 1: Freeze Current Baseline And Add Pure UI State Tests
Files:
- Create:
/home/zyl/projects/superRpa/src/chrome/browser/resources/superrpa/devtools/functions/sgclaw-chat/sgclaw-floating_state.ts - Create:
/home/zyl/projects/superRpa/src/chrome/browser/resources/superrpa/devtools/functions/sgclaw-chat/sgclaw-floating_state_mainline_unittest.ts - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/resources/superrpa/devtools/BUILD.gn
Step 1: Write the failing test
Write a pure state test that describes the floating UX:
import {
collapseFloatingWindow,
createFloatingViewState,
openFloatingWindow,
toggleSettingsPanel,
} from './sgclaw-floating_state.js';
test('opens from fab and collapses back on blur', () => {
let state = createFloatingViewState();
state = openFloatingWindow(state);
expect(state.windowOpen).toBe(true);
state = collapseFloatingWindow(state);
expect(state.windowOpen).toBe(false);
expect(state.fabVisible).toBe(true);
});
Step 2: Run test to verify it fails
Run: autoninja -C /home/zyl/projects/superRpa/src/out/KylinRelease sgclaw-chat_build_ts
Expected: build/test target fails because the new state module and test do not exist yet.
Step 3: Write minimal implementation
Create a small pure state module with:
fabVisiblewindowOpensettingsOpenstatusBadgeunreadCount
Keep it logic-only; no DOM code here.
Step 4: Run test to verify it passes
Run the same autoninja target or the relevant TS unit target once wired.
Expected: the new state test compiles and passes.
Step 5: Commit
git -C /home/zyl/projects/superRpa/src add \
chrome/browser/resources/superrpa/devtools/functions/sgclaw-chat/sgclaw-floating_state.ts \
chrome/browser/resources/superrpa/devtools/functions/sgclaw-chat/sgclaw-floating_state_mainline_unittest.ts \
chrome/browser/resources/superrpa/devtools/BUILD.gn
git -C /home/zyl/projects/superRpa/src commit -m "test: add sgclaw floating UI state"
Task 2: Build The Floating Page Entry Using Existing SuperRPA Overlay Capabilities
Files:
- Create:
/home/zyl/projects/superRpa/src/chrome/browser/resources/superrpa/sgclaw_overlay.js - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/resources/superrpa/sg_compat.js - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/superrpa/hooks/hook_injector.cc - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/superrpa/hooks/hook_injector.h - Test:
/home/zyl/projects/superRpa/src/chrome/browser/superrpa/sgclaw/sgclaw_chat_smoke.mjs
Step 1: Write the failing smoke expectation
Update the browser smoke so it expects:
- a floating button exists on a normal page
- clicking it opens the sgClaw popup
- clicking outside collapses the popup back to the button
Use an assertion like:
await waitFor(() => page.evaluate(() =>
!!document.querySelector('#superrpa-sgclaw-fab')));
Step 2: Run smoke to verify it fails
Run: node /home/zyl/projects/sgClaw/claw/tools/browser_smoke/run_deepseek_browser_smoke.mjs
Expected: smoke fails because the floating entry does not exist.
Step 3: Write minimal implementation
Implement the launcher inside injected page JS, not a side panel:
- floating circular button in bottom-right
- popup window anchored to the button
- button actions: open chat, stop/start runtime, open settings
- blur/outside-click collapses popup back to button
Prefer reusing the existing SuperRPA overlay/dialog/message primitives in sg_compat.js instead of inventing a second overlay stack.
Step 4: Run smoke to verify it passes
Run the same smoke command.
Expected: smoke reaches the popup, submits a task, and collapses correctly after blur.
Step 5: Commit
git -C /home/zyl/projects/superRpa/src add \
chrome/browser/resources/superrpa/sgclaw_overlay.js \
chrome/browser/resources/superrpa/sg_compat.js \
chrome/browser/superrpa/hooks/hook_injector.cc \
chrome/browser/superrpa/hooks/hook_injector.h \
chrome/browser/superrpa/sgclaw/sgclaw_chat_smoke.mjs
git -C /home/zyl/projects/superRpa/src commit -m "feat: add sgclaw floating launcher"
Task 3: Upgrade Browser Session State From “Result Page” To “Real Conversation”
Files:
- Modify:
/home/zyl/projects/superRpa/src/chrome/browser/ui/webui/superrpa/sgclaw_session_service.h - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/ui/webui/superrpa/sgclaw_session_service.cc - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/ui/webui/superrpa/functions_ui.h - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/ui/webui/superrpa/functions_ui.cc - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/resources/superrpa/devtools/functions/sgclaw-chat/sgclaw-chat.ts - Create:
/home/zyl/projects/superRpa/src/chrome/browser/resources/superrpa/devtools/functions/sgclaw-chat/sgclaw-chat_messages.ts - Test:
/home/zyl/projects/superRpa/src/chrome/browser/ui/webui/superrpa/functions_ui_mainline_unittest.cc
Step 1: Write the failing browser-side tests
Add tests for:
- conversation messages are returned by
sgclawConnect - reopening the chat keeps prior user/assistant turns
sgclawSubmitTaskappends a user turn immediately and an assistant turn when complete
Example expectation:
EXPECT_EQ("user", FindStringValue(*message, "role"));
EXPECT_EQ("打开百度搜索天气", FindStringValue(*message, "content"));
Step 2: Run test to verify it fails
Run:
autoninja -C /home/zyl/projects/superRpa/src/out/KylinRelease \
functions_ui_mainline_unittests
./out/KylinRelease/functions_ui_mainline_unittests
Expected: tests fail because runtime state only has logs/final result.
Step 3: Write minimal implementation
Extend SgClawSessionService to store:
- conversation id
- ordered messages
- pending assistant reply state
- runtime status/logs
Keep the debug page and popup both consuming the same runtime shape.
Step 4: Run test to verify it passes
Run the same test command.
Expected: connect/reopen behavior passes and conversation persists while browser stays open.
Step 5: Commit
git -C /home/zyl/projects/superRpa/src add \
chrome/browser/ui/webui/superrpa/sgclaw_session_service.h \
chrome/browser/ui/webui/superrpa/sgclaw_session_service.cc \
chrome/browser/ui/webui/superrpa/functions_ui.h \
chrome/browser/ui/webui/superrpa/functions_ui.cc \
chrome/browser/resources/superrpa/devtools/functions/sgclaw-chat/sgclaw-chat.ts \
chrome/browser/resources/superrpa/devtools/functions/sgclaw-chat/sgclaw-chat_messages.ts \
chrome/browser/ui/webui/superrpa/functions_ui_mainline_unittest.cc
git -C /home/zyl/projects/superRpa/src commit -m "feat: persist sgclaw conversation state"
Task 4: Extend sgClaw Submit Protocol For Multi-Turn Context
Files:
- Modify:
/home/zyl/projects/superRpa/src/chrome/browser/superrpa/sgclaw/sgclaw_pipe_protocol.h - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/superrpa/sgclaw/sgclaw_pipe_protocol.cc - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/superrpa/sgclaw/sgclaw_process_host.cc - Modify:
/home/zyl/projects/superRpa/src/chrome/browser/ui/webui/superrpa/sgclaw_session_service.cc - Modify:
/home/zyl/projects/sgClaw/claw/src/pipe/protocol.rs - Modify:
/home/zyl/projects/sgClaw/claw/src/agent/mod.rs - Modify:
/home/zyl/projects/sgClaw/claw/src/compat/runtime.rs - Test:
/home/zyl/projects/sgClaw/claw/tests/compat_runtime_test.rs - Test:
/home/zyl/projects/superRpa/src/chrome/browser/superrpa/sgclaw/sgclaw_process_host_mainline_unittest.cc
Step 1: Write the failing protocol tests
Add tests that submit_task can carry:
- current user input
- prior user/assistant turns
- active page URL / title hints if needed
For Rust, add a test that two consecutive submits produce a provider request containing prior turns.
Step 2: Run tests to verify they fail
Run:
python3 /home/zyl/projects/superRpa/src/tools/crates/run_cargo.py test \
--manifest-path /home/zyl/projects/sgClaw/claw/Cargo.toml --test compat_runtime_test
autoninja -C /home/zyl/projects/superRpa/src/out/KylinRelease \
sgclaw_process_host_mainline_unittests
./out/KylinRelease/sgclaw_process_host_mainline_unittests \
--gtest_filter='SgClawProcessHostMainlineTest.*'
Expected: tests fail because submit currently only sends a raw instruction string.
Step 3: Write minimal implementation
Change the pipe payload from one-shot instruction to:
{
"type": "submit_task",
"instruction": "...",
"messages": [
{"role": "user", "content": "..."},
{"role": "assistant", "content": "..."}
]
}
On the Rust side, feed this history into the ZeroClaw turn so the next submit is a continuation, not a new session.
Step 4: Run tests to verify they pass
Run the same Rust + browser unit commands.
Expected: previous-turn context reaches the provider path.
Step 5: Commit
git -C /home/zyl/projects/sgClaw/claw add \
src/pipe/protocol.rs src/agent/mod.rs src/compat/runtime.rs tests/compat_runtime_test.rs
git -C /home/zyl/projects/sgClaw/claw commit -m "feat: carry conversation history through sgclaw pipe"
git -C /home/zyl/projects/superRpa/src add \
chrome/browser/superrpa/sgclaw/sgclaw_pipe_protocol.h \
chrome/browser/superrpa/sgclaw/sgclaw_pipe_protocol.cc \
chrome/browser/superrpa/sgclaw/sgclaw_process_host.cc \
chrome/browser/ui/webui/superrpa/sgclaw_session_service.cc \
chrome/browser/superrpa/sgclaw/sgclaw_process_host_mainline_unittest.cc
git -C /home/zyl/projects/superRpa/src commit -m "feat: send sgclaw conversation context"
Task 5: Harden Tool Schema And DeepSeek Compatibility
Files:
- Modify:
/home/zyl/projects/sgClaw/claw/src/compat/browser_tool_adapter.rs - Modify:
/home/zyl/projects/sgClaw/claw/src/compat/runtime.rs - Modify:
/home/zyl/projects/sgClaw/claw/tests/compat_browser_tool_test.rs - Modify:
/home/zyl/projects/sgClaw/claw/tests/compat_runtime_test.rs - Modify:
/home/zyl/projects/sgClaw/claw/tools/browser_smoke/run_deepseek_browser_smoke.mjs
Step 1: Write the failing tests
Cover:
getTextwithoutselectoris rejected before it hits the browserclickwithoutselectoris rejectednavigatewithouturlis rejected- DeepSeek multi-round tool-call history does not trigger the
role=tool400 anymore - non-task greeting behavior is explicit: either reject or answer in chat-only mode, but not silently pretend to be a browser task
Step 2: Run tests to verify they fail
Run:
python3 /home/zyl/projects/superRpa/src/tools/crates/run_cargo.py test \
--manifest-path /home/zyl/projects/sgClaw/claw/Cargo.toml --lib --tests
node /home/zyl/projects/sgClaw/claw/tools/browser_smoke/run_deepseek_browser_smoke.mjs
Expected: current code allows incomplete tool args and still has DeepSeek history edge cases.
Step 3: Write minimal implementation
Implement:
- action-specific required param validation in
browser_tool_adapter.rs - better tool-result/history formatting if needed for DeepSeek compatibility
- explicit user-facing handling for non-browser-chat input
Step 4: Run tests to verify they pass
Run the same Rust tests and browser smoke.
Expected: no malformed tool actions, no DeepSeek role=tool 400 in smoke.
Step 5: Commit
git -C /home/zyl/projects/sgClaw/claw add \
src/compat/browser_tool_adapter.rs \
src/compat/runtime.rs \
tests/compat_browser_tool_test.rs \
tests/compat_runtime_test.rs \
tools/browser_smoke/run_deepseek_browser_smoke.mjs
git -C /home/zyl/projects/sgClaw/claw commit -m "fix: harden sgclaw tool protocol for DeepSeek"
Task 6: Final Verification And Manual Smoke Checklist
Files:
- Modify if needed:
/home/zyl/projects/superRpa/src/chrome/browser/superrpa/sgclaw/sgclaw_chat_smoke.mjs - Document manual steps in PR/summary, not code
Step 1: Run automated verification
python3 /home/zyl/projects/superRpa/src/tools/crates/run_cargo.py test \
--manifest-path /home/zyl/projects/sgClaw/claw/Cargo.toml --lib --tests
autoninja -C /home/zyl/projects/superRpa/src/out/KylinRelease \
functions_ui_mainline_unittests \
sgclaw_process_host_mainline_unittests
./out/KylinRelease/functions_ui_mainline_unittests
./out/KylinRelease/sgclaw_process_host_mainline_unittests \
--gtest_filter='SgClawProcessHostMainlineTest.*'
node /home/zyl/projects/sgClaw/claw/tools/browser_smoke/run_deepseek_browser_smoke.mjs
Expected: all pass.
Step 2: Manual smoke
- Open a normal HTTP/HTTPS page.
- Verify the floating button appears.
- Click to open popup.
- Start sgClaw from popup.
- Submit one browser task and one follow-up task.
- Click outside popup and verify it collapses to the button.
- Reopen popup and verify conversation history is still present.
- Open settings from the launcher, update model/base URL, return to popup, submit again, and verify hot update.
Step 3: Final commit if verification requires touch-ups
Use focused commit messages only for actual fixes found during verification.