Skip to content

feat(v0.2): PromptV2 + chat redesign + theme variants + headless browser#4

Merged
SimpleLittleDev merged 2 commits intomainfrom
devin/1777807887-v0.2-prompt-chat-themes-headless
May 3, 2026
Merged

feat(v0.2): PromptV2 + chat redesign + theme variants + headless browser#4
SimpleLittleDev merged 2 commits intomainfrom
devin/1777807887-v0.2-prompt-chat-themes-headless

Conversation

@SimpleLittleDev
Copy link
Copy Markdown
Owner

Summary

Stacked on top of #3. Continues the v0.2 rollout with Phase 2 (input + chat redesign), Phase 5b (headless browser engine), and Phase 6 (theme variants). All 146 tests pass; lint, typecheck, and build are clean.

Phase 2 — Input editor + chat redesign

  • src/lib/inputHistory.ts — persistent JSONL history at ~/.fastcode/history. Skips empty / exact-duplicate entries, recovers from corrupt lines, trims to a configurable max, falls back to in-memory when the disk is read-only (Termux).
  • src/tui/PromptV2.tsx — multiline editor written directly on useInput (no ink-text-input shim). Features:
    • Shift+Enter / Ctrl+J / Meta+Enter insert a newline; bare Enter submits.
    • ↑ / ↓ recall history when on the first / last line (preserves draft on Down-back-to-edge).
    • Tab autocompletes the slash command on the first token; otherwise inserts a 2-space soft tab.
    • Ctrl+U kills the current line, Ctrl+W deletes the previous word, Ctrl+A / Ctrl+E jump to line start / end, Ctrl+K kills to end of line.
    • Detects bracketed-paste bursts (multi-char input chunks with no modifiers) and inserts the chunk verbatim, including embedded newlines.
    • Cursor block highlights via <Text inverse>; blink toggles unless stable (or noanim mode) is set.
  • src/tui/DiffView.tsx — small unified-diff parser (parseDiff) + themed render. Truncates with a …N more lines footer past maxLines.
  • src/ui/Message.tsxBubbleRole extended with tool, error, warn, success, command, diff. Each variant has a distinct sigil + color routing through the new theme fields. The diff role embeds <DiffView> directly. Bold suppressed when theme.noColor is set.
  • src/app.tsxPromptPromptV2 with historyRef; submitted messages persist before clearing the input. Tool calls now render as tool (call) followed by success / error / diff (result, diff auto-detected). Cancellation uses the warn role.

Phase 5b — Headless browser engine

  • src/browser/headless.tscreateHeadlessEngine() lazily imports playwright-core (kept as an opt-in peer dep, not added to dependencies). Uses chromium.launch({ headless: true }), fetches with domcontentloaded wait, extracts document.body.innerText (serialized as a string so we don't need DOM types in our tsconfig), and clips to maxChars. Throws HeadlessEngineUnavailableError with a friendly install hint when the import fails.
  • src/browser/index.ts — new loadBrowserEngineDetailed({ prefer, strict, policy }) returns { engine, kind }. prefer=auto upgrades to headless when available, prefer=headless non-strict silently falls back to text, prefer=headless strict throws. The legacy loadBrowserEngine() delegates to the detailed variant, so existing callers are unchanged.

Phase 6 — Theme variants

  • src/config/themes.ts — adds cyber (neon magenta/cyan), nocolor (single-color, sets noColor=true so bold is suppressed), hicontrast (a11y, yellowBright + whiteBright on bright backgrounds), and termux (avoids *Bright variants that look bad on AMOLED).
  • pickThemeForCaps({ forceNoColor, os, colorDepth }) automatically picks nocolor for dumb terminals and termux on Android.
  • src/types.tsTheme gains optional warn, tool, command, diffAdd, diffDel, noColor. All five existing themes still validate (the new fields are optional and fall through to existing error / accent / success).

Tests added (25 new, 146 total)

  • test/inputHistory.test.ts (5) — file creation, recall, dedupe, corrupt-line tolerance, trim.
  • test/promptHelpers.test.ts (5) — clamp, posFromOffset, autocompleteCommand.
  • test/diffView.test.ts (3) — kind classification, header vs add/del precedence, blank lines.
  • test/themes.test.ts (6) — variant presence, noColor palette, getTheme fallback, pickThemeForCaps matrix.
  • test/headlessEngine.test.ts (5) — isHeadlessAvailable returns false without playwright-core, prefer=auto and prefer=headless-non-strict fall back to text, prefer=headless-strict throws HeadlessEngineUnavailableError.

npm run check (test + typecheck + lint + build) passes locally.

Review & Testing Checklist for Human

  • PromptV2 paste flow: paste a multi-line JSON / log into the prompt and confirm newlines aren't swallowed and the bubble renders alignment-correct (regression-prone area: bracketed paste vs single-keystroke ambiguity).
  • History recall: send 3 messages, press ↑ three times to walk back, ↓ to walk forward to the empty draft. Confirm ~/.fastcode/history contains JSONL entries.
  • Theme switch: /theme nocolor, /theme termux, /theme cyber, /theme hicontrast and verify each remains readable. Especially check nocolor on a real NO_COLOR=1 terminal.
  • Tool bubbles: trigger any agent tool call (shell, file_read, etc.) and check the new tool → success / error blocks render with distinct sigils. If the tool emits a unified diff in stdout, confirm the diff block colorizes +/- lines.
  • Headless fallback: without installing playwright-core, confirm the app still boots and loadBrowserEngine({ prefer: "headless" }) returns a working text engine. Then npm i playwright-core && npx playwright install chromium and confirm prefer=headless actually launches Chromium.
  • Cross-OS smoke: at minimum boot the TUI on Linux (CI) and on Windows / WSL or Termux locally; check that the prompt cursor block doesn't desync after resize.

Notes

  • Stacked on top of feat(v0.2): living TUI + MCP + sandbox v2 + browser tool #3 — base is main, so this PR's diff includes both phase 1 and phase 2/5b/6 commits. Easier to land as one if feat(v0.2): living TUI + MCP + sandbox v2 + browser tool #3 is approved; we can also rebase to phase-1's branch if you want them split.
  • playwright-core is intentionally not added to dependencies or peerDependencies in package.json. Keeping it user-installed avoids forcing a 50 MB transitive dep on Termux / VPS users who don't want a browser. The error message in HeadlessEngineUnavailableError tells them how to opt in.
  • Old src/ui/Prompt.tsx is untouched (still on disk) for backwards compat in case someone external imported it. Safe to delete in a follow-up.

Link to Devin session: https://app.devin.ai/sessions/0e73b43883c04a17b651ca6aa7dc1a5e
Requested by: @SimpleLittleDev

SimpleLittleDev and others added 2 commits May 3, 2026 11:27
Phase 0 + 1 + 3 + 4 + 5 of the v0.2 blueprint, in one shippable PR.

Core foundations
----------------
- src/core/EventBus.ts: typed pub/sub bus for cross-module events
- src/core/AgentStateMachine.ts: 6-state FSM (idle/thinking/executing/
  waiting/success/error) with explicit transitions

Terminal + TUI
--------------
- src/platform/TerminalCapabilities.ts: single source of truth for OS,
  shell, color depth, unicode, size class, SSH/CI/dumb/Termux/WSL flags
- src/tui/LogoAnimator.tsx: status-reactive living logo with 4-tier
  fidelity (Unicode-rich, Unicode-minimal, ASCII, no-anim)

Model Context Protocol (MCP)
----------------------------
- src/mcp/types.ts | config.ts | client.ts | registry.ts | permission.ts
  | manager.ts | index.ts
- Loads ~/.fastcode/mcp.json + .fastcode/mcp.json + project mcp.json
- Hand-rolled JSON-RPC stdio client (no heavy SDK dep)
- Permission classifier with low/med/high risk + auto/confirm/deny

Sandbox v2
----------
- src/sandbox/PathGuard.ts: resolve + validate every fs path through one
  guard, with deny globs and symlink defense
- src/sandbox/policy.ts: load .fastcode/policy.json, expose shell/network
  guards, default-deny destructive commands
- gitignore-style globToRegex with **/.env etc.

Browser tool
------------
- src/browser/text.ts: text-only engine on top of lib/web.ts
- New agent tool browser_fetch wired through the policy hook
- Headless engine deferred to a follow-up PR (API stable)

Agent integration
-----------------
- runAgentTool now accepts AgentToolServices ({browser, mcp, signal})
- New agent tools: browser_fetch, mcp_call (server.tool addressing)
- AGENT_SYSTEM_PROMPT advertises the new tools

Slash commands
--------------
- /mcp [status|tools|restart <s>|permission <s> <a|c|d>]
- /sandbox [status]
- /mode [normal|compact|focus|debug|noanim]

App wiring
----------
- App holds a single AgentStateMachine + capabilities snapshot
- LogoAnimator renders above the prompt, reacts to FSM state
- MCP manager auto-starts only when .fastcode/mcp.json exists
- AppActions exposes optional mcp / sandbox / setUiMode hooks

Tests (all passing — 122 total, 47 new)
---------------------------------------
- eventBus, stateMachine, terminalCaps, logoAnimator
- sandboxPath, permission, mcpConfig, mcpRegistry
- mcpClient (real stdio echo server fixture), browserText

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…dless browser

Phase 2:
- src/lib/inputHistory.ts: persistent JSONL history at ~/.fastcode/history
- src/tui/PromptV2.tsx: multiline editor (Shift+Enter), Up/Down history recall,
  paste-burst detection, slash-command autocomplete, Ctrl+U/W/A/E/K keybinds,
  cursor block highlight via ink inverse, blink toggle
- src/tui/DiffView.tsx: unified-diff parser + themed +/- rendering
- src/ui/Message.tsx: BubbleRole expanded (tool/error/warn/success/command/diff)
  with distinct sigils, color routing, inline DiffView for diff role

Phase 5b:
- src/browser/headless.ts: lazy playwright-core loader + HeadlessEngineUnavailableError
- src/browser/index.ts: loadBrowserEngineDetailed({ prefer, strict }) with
  graceful fallback to text engine when playwright-core is missing

Phase 6:
- src/config/themes.ts: 4 new themes (cyber, nocolor, hicontrast, termux)
- src/types.ts: Theme adds optional warn/tool/command/diffAdd/diffDel/noColor
- pickThemeForCaps() picks nocolor / termux automatically when warranted

Wiring:
- src/app.tsx: Prompt -> PromptV2 with history ref; tool calls now render
  via tool/success/error/diff blocks; Cancelled goes to warn role

Tests (+25 new, 146 total):
- test/inputHistory.test.ts (5)
- test/diffView.test.ts (3)
- test/themes.test.ts (6)
- test/promptHelpers.test.ts (5)
- test/headlessEngine.test.ts (5)

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@SimpleLittleDev SimpleLittleDev merged commit 29e172b into main May 3, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant