Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ tests/e2e/reports/

# Eval job artifacts
.eval/
.tmp/
tmp/
Cross.toml

# BitFun sandbox data - auto managed
Expand Down
15 changes: 12 additions & 3 deletions docs/architecture/peer-device-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

Peer Device Mode switches the desktop (and mobile control target) data plane
onto another same-account online BitFun device. The React shell stays local;
product invokes and agentic events come from the peer.
product invokes and agentic events come from the peer. The peer may be Desktop
or CLI: both speak the same HostInvoke / DeviceEvent protocol.

## Product goal

Expand Down Expand Up @@ -51,8 +52,12 @@ FS) and must not be mixed with Peer Device Mode.
- editor disk sync poll slows to 15s (from 1s)
- canvas snapshot poll slows to 15s (from 2s)
- workspace search-index poll slows to 30s idle / 5s active
- Peer: decrypt → allow/deny → webview bridge `peer-host-invoke://request` →
same Tauri handlers as local UI → `peer_host_invoke_complete`.
- Peer: decrypt → allow/deny → execute on the peer host:
- Desktop: webview bridge `peer-host-invoke://request` → same Tauri handlers
as local UI → `peer_host_invoke_complete`
- CLI: Core HostInvoke registry (`WorkspaceService`, FS, config, session,
git, `DialogScheduler`) — no webview. Desktop-only surfaces (MiniApp /
cron / ACP list) return empty or no-op so hydrate does not fail.
- Events: peer agentic projection (and other product events such as terminal /
FS / MCP interaction) fan-out as `RemoteCommand::DeviceEvent` to attached
controllers; controller re-emits the same event names locally.
Expand Down Expand Up @@ -80,6 +85,10 @@ Still use normal `openWorkspace` / create-workspace flows (not SSH

- Desktop host invoke / fan-out: `src/apps/desktop/src/api/peer_host_invoke.rs`,
`remote_connect_api.rs`
- CLI host invoke / fan-out: `src/apps/cli/src/peer_host/` (Core registry; no
webview bridge). Device routing in `src/apps/cli/src/account.rs` special-cases
`HostInvoke` / `DeviceEvent`. Same machine Desktop+CLI share one `device_id`;
last `AuthConnect` wins.
- Frontend mode + transport: `src/web-ui/src/infrastructure/peer-device/`,
`adapters/peer-device-adapter.ts`
- Peer directory picker: `pickWorkspaceDirectory.ts`, `PeerDirectoryBrowser.tsx`,
Expand Down
35 changes: 35 additions & 0 deletions docs/superpowers/plans/2026-07-14-cli-login-tui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# CLI Login TUI Implementation Plan

> **For agentic workers:** Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Replace cooked-mode `/login` prompts with a dedicated ratatui Login page.

**Architecture:** New `ui/login_form.rs` owns form state/render/keys. `account::login_with_credentials` performs Auth + persistence + Peer Host. Startup and Chat show the form and handle Submit/Cancel.

**Tech Stack:** ratatui, crossterm, existing CLI account client

---

### Task 1: Account API without stdin

- Modify: `src/apps/cli/src/account.rs`
- [ ] Replace `login_interactive` + echo helpers with `login_with_credentials(relay_url, username, password)`

### Task 2: Login form UI

- Create: `src/apps/cli/src/ui/login_form.rs`
- Modify: `src/apps/cli/src/ui/mod.rs`
- [ ] Full-viewport form with three empty fields + Login button
- [ ] Password masked as `*`
- [ ] Up/Down/Tab focus; Enter advances or submits

### Task 3: Wire startup + chat

- Modify: `src/apps/cli/src/ui/startup.rs`, `src/apps/cli/src/ui/chat/*`, `src/apps/cli/src/modes/chat.rs`
- [ ] `/login` and palette open the form; no raw-mode toggle
- [ ] Submit calls `login_with_credentials`; errors stay on form

### Task 4: Verify

- [ ] `cargo check -p bitfun-cli`
- [ ] Rebuild Ubuntu `~/bitfun-build/target/debug/bitfun-cli`
42 changes: 42 additions & 0 deletions docs/superpowers/plans/2026-07-14-cli-peer-host.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# CLI Peer Host 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:** Make BitFun CLI a full Peer Device Mode host so Desktop A can control CLI B via HostInvoke / DeviceEvent.

**Architecture:** CLI decrypts device RPC, special-cases HostInvoke to a Core command registry (no webview), fans out agentic DeviceEvents to attached controllers. Same device_id as Desktop; last AuthConnect wins.

**Tech Stack:** Rust (`bitfun-cli`), `bitfun-core` services, existing account relay WS.

---

### Task 1: Spec + envelope routing — DONE

- [x] Spec under `docs/superpowers/specs/2026-07-14-cli-peer-host.md`
- [x] `account.rs` routes HostInvoke / DeviceEvent; reply target `"rpc"` for HTTP RPC

### Task 2: Control plane + deny tables — DONE

- [x] `peer_mode_ping` / attach / detach
- [x] LOCAL_ONLY + CLI_UNSUPPORTED deny

### Task 3: Bootstrap Core services — DONE

- [x] WorkspaceService, FileSystemService, DialogScheduler, PersistenceManager
- [x] Wire from `initialize_core_services`

### Task 4: Must HostInvoke registry — DONE

- [x] Workspace / FS / session / dialog / system HIGH_PRIORITY commands

### Task 5: DeviceEvent fan-out — DONE

- [x] EventQueue subscriber + sequential encrypt send

### Task 6: Docs + verify — DONE

- [x] `peer-device-mode.md`, CLI `AGENTS.md`
- [x] `cargo check -p bitfun-cli` (clean)
- [x] `cargo test -p bitfun-cli peer_host`
- [x] Enter peer host via chat `/login` (same Auth Server / Username / Password
+ `~/.bitfun` session/hint as Desktop). No separate `peer-host` CLI subcommand.
37 changes: 37 additions & 0 deletions docs/superpowers/specs/2026-07-14-cli-account-sync-panel-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# CLI Account Sync & Status Panel Design

## Goal

Align CLI `/login` with Desktop Account Login after authentication:

1. After credentials succeed, if cloud settings exist → choose **Use local** / **Use cloud**.
2. Then run the same auto-sync flow (settings + session upload).
3. If already logged in, `/login` opens an **account status** page (not the credential form) with account info and sync progress.

## Views

| Mode | When | UI |
|---|---|---|
| Login | Not logged in | Existing Auth Server / Username / Password / Login |
| SyncChoice | Login succeeded and `has_cloud_settings` | Use local / Use cloud / Cancel (logout) |
| Account | Logged in (or after sync choice / first login) | User id, relay, this device, devices list, sync status/progress, Logout |

## Sync semantics (match Desktop)

- No cloud settings → treat as first login: upload local config (`is_first_login=true`), then export sessions.
- Use local → `is_first_login=true` (upload local settings).
- Use cloud → `is_first_login=false` (download + import settings).
- Cancel on SyncChoice → logout, return to Login.
- Progress phases: uploading/downloading/applying settings → listing/exporting sessions → done/failed.
- Sync runs in background; Account page reads shared progress state (Esc closes panel, sync continues).

## Implementation

- `account.rs`: structured `LoginResult` + `fetch_settings` for `has_cloud_settings`; `run_auto_sync` using `AccountClient`, `ConfigService`, `PersistenceManager`, `sync_state`.
- `ui/account_panel.rs` (replaces single-purpose login form): multi-mode TUI.
- `/login` entry: if logged in → Account; else → Login.

## Non-goals (this change)

- Continuous debounce push like Desktop `init_auto_sync` (follow-up).
- Peer Device Mode controller entry from CLI Account page.
26 changes: 26 additions & 0 deletions docs/superpowers/specs/2026-07-14-cli-login-tui-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# CLI Login TUI Design

## Problem

`/login` temporarily disables raw mode and uses `print!` + echo-off stdin prompts. That fights the ratatui alternate screen and produces misaligned / overlapping characters.

## Decision

Dedicated full-viewport Login page (approach A), ratatui-native, no cooked-mode prompts.

## Behavior

- Entry: `/login` or palette Login from startup or chat.
- Fields start empty (no credential-hint / default relay prefill).
- Focus cycle (Up/Down, Tab/Shift+Tab): Auth Server → Username → Password → Login.
- Password stores plaintext; display is `*` repeated by character count.
- Enter on a text field moves focus down; Enter on Login submits.
- Esc cancels and returns to the previous screen.
- Validation / API errors stay on the form; success hides the form and shows a status/system message.
- Persistence and Peer Host routing reuse existing `account` APIs after credentials are collected.

## Non-goals

- Changing Desktop login UI
- Changing Auth Server protocol
- Prefill / remembered credentials on the form fields
77 changes: 77 additions & 0 deletions docs/superpowers/specs/2026-07-14-cli-peer-host.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# CLI Peer Device Mode Host

## Goal

Desktop A can enter Peer Mode against a same-account CLI process on machine B
using the same HostInvoke / DeviceEvent wire protocol as Desktop B. The CLI is
a **host only** (not a Peer Mode controller).

## Non-goals

- CLI controlling other devices
- Remote-desktop / raw input mirroring
- Splitting same-machine Desktop + CLI into two device list entries
- Full IDE parity (LSP UI, canvas, window chrome) — deny with clear English errors

## Device identity and election

- `device_id = hash(hostname + MAC)` (shared across Desktop and CLI on one machine)
- Relay replaces the live connection for the same `(user_id, device_id)`
- Last successful `AuthConnect` wins as the Peer Host process

## Architecture

1. CLI decrypts `IncomingDeviceMessage` and **special-cases** `HostInvoke` /
`DeviceEvent` (does not send HostInvoke through `RemoteServer::dispatch`).
2. Control plane in Rust: `peer_mode_ping`, `peer_control_attach`,
`peer_control_detach`.
3. Product data plane: CLI HostInvoke registry calls Core services
(`WorkspaceService`, `FileSystemService`, `PersistenceManager`,
`ConversationCoordinator`, `DialogScheduler`, `ConfigService`, `GitService`)
— same Tauri command names and `{ request: ... }` arg shape as Desktop.
4. Agentic (and selected UI) events fan out as `RemoteCommand::DeviceEvent` to
attached controllers.
5. Denied / unsupported commands return
`HostInvokeResult { ok: false, error }` — never fall back to the controller.

## Must-support command surface

Control: `peer_mode_ping`, `peer_control_attach`, `peer_control_detach`

Hydrate / chat / FS:

- Workspace: `initialize_workspace_startup_state`, `get_opened_workspaces`,
`get_recent_workspaces`, `get_current_workspace`, `open_workspace`,
`get_workspace_info`, `cleanup_invalid_workspaces`, `reload_config`
- Config: `get_config`, `get_configs`, `set_config`, `get_agent_profile_config`,
`get_agent_profile_configs`
- Sessions: `list_persisted_sessions*`, `load_session_turns`,
`restore_session_view`, `restore_session_with_turns`, `restore_session`,
`create_session`, `delete_session`, `rename_session`, `archive_session`,
`touch_session_activity`, `get_session_thread_goal`, `update_session_model`,
`ensure_coordinator_session`, `get_available_modes`, `get_session_stats`,
`save_session_turn`
- Snapshot: `rollback_to_turn`, `get_session_files`
- Dialog: `start_dialog_turn`, `cancel_dialog_turn`, `confirm_tool_execution`,
`reject_tool_execution`
- FS / system: `get_directory_children`, `get_directory_children_paginated`,
`list_files`, `check_path_exists`, `create_directory`, `get_system_info`
- Git (local): `git_is_repository`

### Soft empty / no-op (Desktop-only subsystems)

CLI does not run MiniApp runtime, Desktop cron host, or Peer-mounted ACP
client service. These commands succeed with empty / null payloads so Desktop
hydrate does not fail:

- `list_miniapps` → `[]`
- `miniapp_worker_list_running` → `[]`
- `get_acp_clients` → `[]`
- `notify_cron_host_ready` → null Ok
- `list_background_command_activities` → `{ activities: [] }`

## Ownership

- Implementation: `src/apps/cli/src/peer_host/`
- Routing: `src/apps/cli/src/account.rs`
- Product doc: `docs/architecture/peer-device-mode.md`
5 changes: 5 additions & 0 deletions src/apps/cli/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ before Product Profile, TUI Blueprint, branding, packaging, runtime, or plugin a

- This app owns Clap commands, TUI state and rendering, terminal input/lifecycle,
CLI-local settings, structured output projection, and user-facing CLI diagnostics.
- Peer Device Mode **host** support lives in `src/peer_host/`: after `/login`
(same Auth Server / Username / Password flow and `~/.bitfun` session/hint
files as Desktop), device routing stays up so Desktop controllers can
HostInvoke this process. CLI is not a Peer Mode controller. Same-machine
Desktop+CLI share one `device_id`; last AuthConnect wins.
- Shared session, turn, task, tool, permission, context, checkpoint, Subagent,
Harness, MCP, plugin, and capability facts belong to their runtime owners.
- Existing `bitfun-core/product-full` compatibility paths may remain during a
Expand Down
Loading
Loading