mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-28 13:32:23 +00:00
+16




![github-actions[bot] <github-actions[bot]@users.noreply.github.com>](/assets/img/avatar_default.png)




Mega Mind
GitHub
YellowSnnowmann
Steven Enamakel
github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Cyrus Gray
Horst1993
Cursor
James Gentes
Sam
Sami Rusani
oxoxDev
Muhammad Ismail
Claude Fable 5
nb213
binyangzhu000-sudo
Steven Enamakel
CodeGhost21
sanil-23
M3gA-Mind
oxoxDev
mysma-9403
mwakidenis
NgoQuocViet2001
viet.ngo
Maciej Myszkiewicz
a40fbb79d2
Co-authored-by: YellowSnnowmann <167776381+YellowSnnowmann@users.noreply.github.com> Co-authored-by: Steven Enamakel <31011319+senamakel@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Cyrus Gray <144336577+graycyrus@users.noreply.github.com> Co-authored-by: Horst1993 <horst.w@gmicloud.ai> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: James Gentes <jgentes@users.noreply.github.com> Co-authored-by: Sam <samrusani@users.noreply.github.com> Co-authored-by: Sami Rusani <14844597+samrusani@users.noreply.github.com> Co-authored-by: oxoxDev <164490987+oxoxDev@users.noreply.github.com> Co-authored-by: Muhammad Ismail <78064250+myi1@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: nb213 <binyangzhu000@gmail.com> Co-authored-by: binyangzhu000-sudo <224954946+binyangzhu000-sudo@users.noreply.github.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> Co-authored-by: CodeGhost21 <164498022+CodeGhost21@users.noreply.github.com> Co-authored-by: sanil-23 <sanil@tinyhumans.ai> Co-authored-by: M3gA-Mind <elvin@mahadao.com> Co-authored-by: oxoxDev <oxoxdev@users.noreply.github.com> Co-authored-by: mysma-9403 <64923976+mysma-9403@users.noreply.github.com> Co-authored-by: mwakidenis <mwakidenice@gmail.com> Co-authored-by: NgoQuocViet2001 <123613986+NgoQuocViet2001@users.noreply.github.com> Co-authored-by: viet.ngo <viet.ngo@sotatek.com> Co-authored-by: Maciej Myszkiewicz <mmyszkiewicz@bwcoders.com>
5.9 KiB
5.9 KiB
Plan: openhuman tui — feature-gated terminal chat UI
Historical v1 plan. The shipped CLI now extends this foundation into a Logs-first four-tab UI (Logs, Chat, Config, Settings). Bare
openhumanauto-launches only with terminal stdin/stdout on a non-container host;--no-tuisuppresses that default and explicitopenhuman tuistill forces the UI. Config uses curated safe getters/updaters, and Settings uses registered auth controllers.
Goal
Running openhuman-core tui (alias chat) opens a ratatui-based terminal UI that is an
interface into the general chat (the same web_chat surface the desktop app uses),
gated behind a Cargo feature tui.
Architecture decisions (grounded in current code)
- Cargo feature:
tui = ["dep:ratatui", "dep:crossterm"], added todefault(repo convention: gates default-ON). It must NOT ship in the desktop app — add'tui': 'Terminal UI subcommand; the desktop app ships its own Tauri UI.'toINTENTIONALLY_NOT_FORWARDEDinscripts/ci/check-feature-forwarding.mjs. - Module: crate-level
src/tui/, gated at its declaration insrc/lib.rs:mod.rsalways compiled; real submodules#[cfg(feature = "tui")];#[cfg(not(feature = "tui"))] mod stub;exposing the samerun_from_cli.stub.rsrun_from_clibails with"tui feature disabled at compile time … rebuild with --features tui"(mirrorsrc/openhuman/mcp_server/stub.rs:42).- No controllers, no agent tools, no
all.rschanges (leaf client, likeflows' philosophy: absence, not degraded registration — but here the only outside touch-point is the CLI arm, which uses the stub for a build-fact error).
- CLI arm: in
src/core/cli.rsmatch (~line 63), add"tui" | "chat" => run_tui_from_cli(&args[1..]). Arm stays un-cfg'd (mcp precedent). Add"tui" | "chat"to the banner-suppressionmatches!at lines 48–50 (a TUI must own the terminal). - In-process core, no HTTP: build a multi-thread tokio runtime with
AGENT_WORKER_STACK_BYTESstack (copyrun_server_commandshape, cli.rs:219–311), thenCoreBuilder::new(HostKind::Cli).domains(DomainSet::full()).services(ServiceSet::none()).build().channel.web_chatneedsDomainGroup::Channels, soharness()is not enough. - Chat flow:
client_id = "tui-<random hex>".- Threads via
runtime.invoke("threads.list"| "threads.create_new", …); CLI flags:--thread <id>,--new(default: create new thread). - Send turn:
runtime.invoke("channel.web_chat", {client_id, thread_id, message, …})(schema:src/openhuman/web_chat/schemas.rs:45; ops entryops.rs:1199/start_chatat 391). - Stream: drain
web_chat::subscribe_web_channel_events()(broadcast bus,src/openhuman/web_chat/event_bus.rs:14), filter by ourclient_id. Rendertext_delta/thinking_delta(delta,delta_kindfields onWebChannelEvent,src/core/socketio.rs:98), showtool_call/tool_resultas status lines, finish onchat_done(usefull_responseas authoritative final text) orchat_error(showmessage). - Cancel in-flight turn:
channel.web_cancelon Esc.
- UI v1 scope (keep it tight):
- Alternate screen + raw mode; transcript viewport with scrollback (PgUp/PgDn/mouse optional), single-line input box, status bar (thread id, model/turn state, key hints), spinner while streaming.
- Keys: Enter=send, Esc=cancel turn, Ctrl+N=new thread, Ctrl+C/Ctrl+D=quit.
- Distinguish user / assistant / thinking (dim) / tool activity / errors. Ocean-ish accent per design tokens is fine but keep it terminal-native.
- Terminal hygiene (critical):
- Panic hook + Drop guard that restores the terminal (leave raw mode, LeaveAlternateScreen) before the panic message prints.
- Logging must not hit stdout/stderr while the TUI owns the terminal —
inspect how
run_from_cli/run_server_commandinit logging (src/core/logging.rs) and route core logs to file only (or suppress console) for the tui arm. Core boot logs corrupting the UI is a bug.
- Separation for testability: pure state module (
transcript.rsorstate.rs) holding a reducerapply_event(&mut TranscriptState, &WebChannelEvent)with no terminal deps — unit-testable. Rendering (render.rs) and event loop (app.rs) stay thin.
Tests / verification (definition of done)
- Unit tests for the reducer: text_delta accumulation, thinking vs text separation, chat_done replaces with full_response, chat_error, ignores other client_ids, tool_call/result lines.
src/core/cli_tests.rs:tui_subcommand_reports_disabled_build_when_gate_off(+chatalias) under#[cfg(not(feature = "tui"))], mirroring the mcp tests (assert error contains "tui feature disabled" and NOT "unknown namespace").- Builds (Apple Silicon: prefix
GGML_NATIVE=OFF):cargo check --manifest-path Cargo.tomlcargo check --no-default-features --features tokenjuice-treesitter(disabled build)cargo test --lib core::cliand the tui module tests, both feature directions:cargo test --lib --no-default-features --features tokenjuice-treesitter core::
node scripts/ci/check-feature-forwarding.mjspasses with the allowlist entry.cargo fmtclean.
Docs
- AGENTS.md: add
tuirow to the feature table + a short gate section (leaf-ish gate, shedsratatui+crossterm, intentionally not forwarded to desktop). src/openhuman/about_app/: add user-facing feature entry for the terminal chat UI.
Non-goals (v1)
- No thread-picker UI beyond
--thread/--newflags, no markdown rendering, no image/artifact display, no approval-request interaction (surface as a status line telling the user to handle it elsewhere), no remote-core (HTTP) mode.
Workflow
Small focused commits on feat/tui-chat in this worktree; don't push.
Debug logging with [tui] prefix on all state transitions.