# 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:

```ts
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:
- `fabVisible`
- `windowOpen`
- `settingsOpen`
- `statusBadge`
- `unreadCount`

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**

```bash
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:

```js
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**

```bash
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
- `sgclawSubmitTask` appends a user turn immediately and an assistant turn when complete

Example expectation:

```cc
EXPECT_EQ("user", FindStringValue(*message, "role"));
EXPECT_EQ("打开百度搜索天气", FindStringValue(*message, "content"));
```

**Step 2: Run test to verify it fails**

Run:

```bash
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**

```bash
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:

```bash
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:

```json
{
  "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**

```bash
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:
- `getText` without `selector` is rejected before it hits the browser
- `click` without `selector` is rejected
- `navigate` without `url` is rejected
- DeepSeek multi-round tool-call history does not trigger the `role=tool` 400 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:

```bash
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**

```bash
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**

```bash
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**

1. Open a normal HTTP/HTTPS page.
2. Verify the floating button appears.
3. Click to open popup.
4. Start sgClaw from popup.
5. Submit one browser task and one follow-up task.
6. Click outside popup and verify it collapses to the button.
7. Reopen popup and verify conversation history is still present.
8. 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.
