Skip to content
Draft
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
26 changes: 13 additions & 13 deletions tui/ANATOMY.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ This folder is the self-contained Go module for the `lingtai-tui` terminal UI bi

## Components

- **`tui/main.go:33-1138`** — single-file `package main`. The version stamp (`tui/main.go:31`, set via `-ldflags`), welcome/help text, Rust toolchain startup guidance (`tui/main.go:688-756`), and interactive entry (`tui/main.go:33-96`). After parsing subcommands, it runs global migrations, checks invariants (init.json all-or-nothing, exactly-one-orchestrator), handles upgrade prompts and first-run wizard routing, then launches Bubble Tea.
- **`tui/main.go:35-96`** — subcommand dispatch. Each subcommand returns early; the fallthrough path starts the interactive TUI.
- **`tui/main.go:33-1192`** — single-file `package main`. The version stamp (`tui/main.go:31`, set via `-ldflags`), welcome/help text, Rust toolchain startup guidance (`tui/main.go:668-740`), and interactive entry (`tui/main.go:33-342`). After parsing subcommands, it runs global migrations, checks invariants (init.json all-or-nothing, exactly-one-orchestrator), handles upgrade prompts and first-run wizard routing, then launches Bubble Tea.
- **`tui/main.go:35-89`** — subcommand dispatch. Each subcommand returns early; the fallthrough path starts the interactive TUI.
- **`list_common.go` / `list_unix.go` / `list_windows.go`** — `lingtai-tui list` process discovery and decentralized running-agent inventory rendering. Platform files call shared `processscan` discovery and fail loud with a nonzero exit when the scan command itself fails (`tui/list_unix.go:19-24`, `tui/list_windows.go:19-24`); `internal/inventory` converts process rows into typed, enriched, grouped records (`tui/internal/inventory/inventory.go:105-167`), and `list_common.go` keeps CLI parsing plus table/JSON rendering (`tui/list_common.go:47-181`). `--admin` is a detail mode that adds admin, IM, and state columns; it is not an admin-only filter.
- **`upgrade.go`** — startup TUI binary upgrade flow: after install-method routing (`tui/main.go:113-119`), Homebrew installs keep the existing prompt that detects other running TUI windows, puts affected agents to sleep, stops old TUI processes, and runs `brew upgrade` before asking the user to relaunch; source/user-local installs get a separate explicit `[y/N]` prompt that routes through the source updater backend (`install.sh --update`). Unknown installs are not mutated at startup (version-only).
- **`tui/main.go:688-756`** — `maybePromptRustToolchain` / `markRustPromptSeen`: one-time optional Rust/Cargo startup prompt. Only prompts on an interactive TTY when the managed runtime is on the Python file-search fallback and no `cargo` is on PATH. Writes the `~/.lingtai-tui/runtime/rust-toolchain-prompted` marker on decline/install/skip — including when the probe errors or reports an unsupported runtime — so the Python probe never re-spawns on every launch.
- **`upgrade.go`** — startup TUI binary upgrade flow: after install-method routing (`tui/main.go:103-112`), Homebrew installs keep the existing prompt that detects other running TUI windows, puts affected agents to sleep, stops old TUI processes, and runs `brew upgrade` before asking the user to relaunch; source/user-local installs get a separate explicit `[y/N]` prompt that routes through the source updater backend (`install.sh --update`). Unknown installs are not mutated at startup (version-only).
- **`tui/main.go:668-740`** — `maybePromptRustToolchain` / `markRustPromptSeen`: one-time optional Rust/Cargo startup prompt. Only prompts on an interactive TTY when the managed runtime is on the Python file-search fallback and no `cargo` is on PATH. Writes the `~/.lingtai-tui/runtime/rust-toolchain-prompted` marker on decline/install/skip — including when the probe errors or reports an unsupported runtime — so the Python probe never re-spawns on every launch.
- **`tui/main.go:824-972`** — `cleanMain`/`cleanProject`: suspend agents in `.lingtai/` (10s timeout), then `os.RemoveAll`. Refuses to delete while any agent heartbeat is still fresh after the timeout, when agents cannot be listed, or when an agent appeared during the wait (re-discovered before deleting) — unless `--force` is given (issue #488).
- **`tui/main.go:974-1022`** — `postmanMain`: parse `--port`, collect watch directories, call `postman.Run`.
- **`tui/purge_common.go:9-39` / `tui/purge_unix.go:17-80`** — `purgeMain` (unix): shared processscan-to-purge-target filtering, then SIGTERM → SIGKILL survivors. Build tag `!windows`.
Expand All @@ -67,19 +67,19 @@ This folder is the self-contained Go module for the `lingtai-tui` terminal UI bi
- **`Makefile:1-23`** — build, dev (fast local), cross-compile (darwin/linux × arm64/amd64), clean. Version stamp via `-ldflags "-X main.version=$(VERSION)"` where `VERSION` is `git describe --tags --always`.
- **`tui/i18n/i18n.go:10`** — `//go:embed en.json zh.json wen.json`. The only embed target in the root `tui/` package; all other embeds are in `internal/preset/`.
- **`tui/internal/`** — all substantive packages (tui screens, preset engine, migration system, filesystem readers, process launcher, headless JSON CLI surface, postman, lock shims).
- **`tui/internal/headless/`** — JSON-emitting non-interactive surface. `RunPresets` (lists templates/saved presets as JSON), `RunSpawn` (creates a project + launches an agent), and `ExitError` (structured error codes). Wired from `main.go` via `bootstrapMain` (`tui/main.go:970`), `presetsMain` (`tui/main.go:1058`), and `spawnMain` (`tui/main.go:1082`). For agents and scripts that drive `lingtai-tui` without the Bubble Tea UI.
- **`tui/internal/headless/`** — JSON-emitting non-interactive surface. `RunPresets` (lists templates/saved presets as JSON), `RunSpawn` (creates a project + launches an agent), and `ExitError` (structured error codes). Wired from `main.go` via `bootstrapMain` (`tui/main.go:1024`), `presetsMain` (`tui/main.go:1112`), and `spawnMain` (`tui/main.go:1136`). For agents and scripts that drive `lingtai-tui` without the Bubble Tea UI.

## Connections

- **Called from:** the shell (`lingtai-tui`), Homebrew tap (`lingtai-ai/lingtai/lingtai-tui`), `install.sh`.
- **Calls out:** `tui/internal/tui` (Bubble Tea app), `tui/internal/sqlitelog` (sqlite3-backed `logs/log.sqlite` query helpers for notification events, session boundaries, diagnostics, doctor errors, and clear completion checks), `tui/internal/migrate` (per-project migrations), `tui/internal/globalmigrate` (per-machine migrations), `tui/internal/preset` (bootstrap + utility skill population), `tui/internal/process` (agent launch), `tui/internal/processscan` (shared ps-based agent-process detection), `tui/internal/inventory` (typed running-agent inventory shared by CLI list and `/projects`), `tui/internal/config` (global config, venv, upgrade checks, install-method-routed TUI updater), `tui/internal/postman` (mail relay daemon).
- **Locale resolution** (`tui/main.go:132-134`): immediately after `globalDir` is known, the TUI runs `config.MigrateLegacyLanguage` → `config.LoadTUIConfig` → `i18n.SetLang(tuiCfg.Language)` so every user-visible startup string (codex banner, welcome, agent-count reminder) renders in the configured locale rather than the i18n default. `tuiCfg` is reused for the rest of bootstrap.
- **Bootstrap sequence** (`tui/main.go:218-288`): on every launch, the TUI initializes project-local `.lingtai/` state with `process.InitProject`, registers the project, and explicitly refreshes user-level utility skills via `preset.PopulateBundledLibrary(globalDir)` before returning-user runtime/bootstrap work. Returning users then run `config.NeedsVenv` (for setup banner) → `config.EnsureRuntime` (create/repair venv if needed, then always run the non-blocking `CheckUpgrade`) → `preset.Bootstrap` → `tui.ExportCommandsJSON` → `maybePromptRustToolchain` (one-time optional Rust/Cargo prompt only when file search is on Python fallback and no cargo is on PATH). `CheckUpgrade` auto-upgrades the `lingtai` meta-package from PyPI, which bundles `lingtai-kernel` + all addon MCPs. See `tui/internal/config/ANATOMY.md`.
- **`lingtai-tui doctor` subcommand** (`tui/main.go:980-1020`): runs `config.RunDoctorUpdate` (`tui/main.go:992`) with both `ForceTUI=true` and `ForcePython=true`, then refreshes presets, utility skills, and `commands.json`. The report includes native file-search sidecar / Rust toolchain diagnostics (`config.checkFileSearchNative`). Designed to be usable when the TUI cannot start (broken venv, missing migrations) — it never touches `.lingtai/`. Exit nonzero only on unrecoverable failures.
- **`lingtai-tui self-update` subcommand** (`tui/main.go:1022-1043`): runs `config.RunManualTUIUpdate` (`tui/main.go:1029`) through the detected install-method backend. Homebrew installs run the brew updater; source/user-local installs run the source updater backend (`install.sh --update`); unknown installs produce unsupported guidance without trying brew.
- **Version flow:** `Makefile:4` injects `git describe` into `tui/main.go:31`. On startup, `tui/main.go:125` calls `tui.SetTUIVersion(version)`, which stores it for `/doctor` drift detection.
- **TUI binary upgrade:** `tui/main.go:111-120` checks for a newer release, detects the current install method (`config.DetectCurrentTUIInstall`), then routes on `install.Method` (`tui/main.go:113-119`) and delegates newer-release handling to `upgrade.go` (`handleTUIUpgrade`) for Homebrew and source/user-local installs. Homebrew keeps the existing confirmation flow, can put agents in their projects to sleep, stops other TUI processes, runs the Homebrew backend, and asks the user to relaunch. Source/user-local installs require an explicit `[y/N]` yes before running the source updater backend through `install.sh --update`; unknown installs keep the version-only startup path and do not mutate.
- **i18n loading:** `i18n/i18n.go` embeds the three locale JSONs; `tui/main.go:142` sets the active locale from `tuiCfg.Language` early in startup (see Locale resolution above) so startup banners localize correctly. Each catalog holds only its own language — there are no bilingual entries (a `mail.initial_loading` that mixed `loading...` and `加载中...` was the documented anti-pattern, since split per-locale).
- **Locale resolution** (`tui/main.go:132-137`): immediately after `globalDir` is known, the TUI runs `config.MigrateLegacyLanguage` → `config.LoadTUIConfig` → `i18n.SetLang(tuiCfg.Language)` so every user-visible startup string (codex banner, welcome, agent-count reminder) renders in the configured locale rather than the i18n default. `tuiCfg` is reused for the rest of bootstrap.
- **Bootstrap sequence** (`tui/main.go:213-283`): on every launch, the TUI initializes project-local `.lingtai/` state with `process.InitProject`, registers the project, and explicitly refreshes user-level utility skills via `preset.PopulateBundledLibrary(globalDir)` before returning-user runtime/bootstrap work. Returning users then run `config.NeedsVenv` (for setup banner) → `config.EnsureRuntime` (create/repair venv if needed, then always run the non-blocking `CheckUpgrade`) → `preset.Bootstrap` → `tui.ExportCommandsJSON` → `maybePromptRustToolchain` (one-time optional Rust/Cargo prompt only when file search is on Python fallback and no cargo is on PATH). `CheckUpgrade` auto-upgrades the `lingtai` meta-package from PyPI, which bundles `lingtai-kernel` + all addon MCPs. See `tui/internal/config/ANATOMY.md`.
- **`lingtai-tui doctor` subcommand** (`tui/main.go:1034-1074`): runs `config.RunDoctorUpdate` (`tui/main.go:1046`) with both `ForceTUI=true` and `ForcePython=true`, then refreshes presets, utility skills, and `commands.json`. The report includes native file-search sidecar / Rust toolchain diagnostics (`config.checkFileSearchNative`). Designed to be usable when the TUI cannot start (broken venv, missing migrations) — it never touches `.lingtai/`. Exit nonzero only on unrecoverable failures.
- **`lingtai-tui self-update` subcommand** (`tui/main.go:1076-1097`): runs `config.RunManualTUIUpdate` (`tui/main.go:1083`) through the detected install-method backend. Homebrew installs run the brew updater; source/user-local installs run the source updater backend (`install.sh --update`); unknown installs produce unsupported guidance without trying brew.
- **Version flow:** `Makefile:4` injects `git describe` into `tui/main.go:31`. On startup, `tui/main.go:119` calls `tui.SetTUIVersion(version)`, which stores it for `/doctor` drift detection.
- **TUI binary upgrade:** `tui/main.go:91-115` checks for a newer release, detects the current install method (`config.DetectCurrentTUIInstall`), then routes on `install.Method` (`tui/main.go:103-112`) and delegates newer-release handling to `upgrade.go` (`handleTUIUpgrade`) for Homebrew and source/user-local installs. Homebrew keeps the existing confirmation flow, can put agents in their projects to sleep, stops other TUI processes, runs the Homebrew backend, and asks the user to relaunch. Source/user-local installs require an explicit `[y/N]` yes before running the source updater backend through `install.sh --update`; unknown installs keep the version-only startup path and do not mutate.
- **i18n loading:** `i18n/i18n.go` embeds the three locale JSONs; `tui/main.go:134` sets the active locale from `tuiCfg.Language` early in startup (see Locale resolution above) so startup banners localize correctly. Each catalog holds only its own language — there are no bilingual entries (a `mail.initial_loading` that mixed `loading...` and `加载中...` was the documented anti-pattern, since split per-locale).

## Composition

Expand Down Expand Up @@ -117,5 +117,5 @@ This folder is the self-contained Go module for the `lingtai-tui` terminal UI bi
- **`main.go` is intentionally flat** — every subcommand's `*Main()` function is defined inline in `main.go` or platform-specific `*_unix.go`/`*_windows.go` files. Don't refactor subcommands into `internal/` packages; the flat `main.go` is the contract.
- **Platform shims follow the `//go:build !windows` pattern.** Unix is the primary target; Windows files mirror the same function signatures. Every subcommand (`purge`, `list`, `suspend`) plus `countRunningAgents` and TUI-process upgrade helpers have paired platform files.
- **The platform split** covers: `purge`, `list`, `suspend`, `agent_count`, and `tui_process`. The `postman` subcommand lives in `internal/` and shares no platform-specific `main.go` surface.
- **Version stamping:** `Makefile:4` uses `git describe --tags --always`. Dev builds get `-X main.version=dev`. The upgrade check in `tui/main.go:106-110` skips dev builds (those containing `-` in the version string).
- **Version stamping:** `Makefile:4` uses `git describe --tags --always`. Dev builds get `-X main.version=dev`. The upgrade check in `tui/main.go:98-102` skips dev builds (those containing `-` in the version string).
- **MCP packages are dependencies of `lingtai`.** The `lingtai` PyPI package bundles `lingtai-kernel` + all addon MCPs. `config.CheckUpgrade` on every launch upgrades everything. Users never install MCP packages individually.
4 changes: 2 additions & 2 deletions tui/internal/config/ANATOMY.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ This package manages the TUI's bootstrap sequence — the steps that run before

## Connections

- **Called from:** `tui/main.go:132-288`, the manual `lingtai-tui self-update` path, `tui/internal/tui/firstrun.go:672-675`, and `tui/internal/headless/spawn.go:97-111` — startup, manual self-update, first-run, and headless bootstrap paths. (NOTE: line citations to recompute against current main via the anatomy citation checker.)
- **Called from:** `tui/main.go:93-304`, the manual `lingtai-tui self-update` path (`tui/main.go:1076-1097`), `tui/internal/tui/firstrun.go:672-675`, and `tui/internal/headless/spawn.go:97-111` — startup, manual self-update, first-run, and headless bootstrap paths.
- **Calls out:** PyPI API (`pypi.org/pypi/lingtai/json`), GitHub API (`api.github.com/repos/Lingtai-AI/lingtai/releases/latest`), `uv` / `pip` CLI, and Homebrew for Homebrew-managed TUI binary updates.
- **Bootstrap sequence:**
1. `config.MigrateLegacyLanguage(globalDir)` then `config.LoadTUIConfig` + `i18n.SetLang` — one-shot language migration and locale resolution, run early (`tui/main.go:132-134`) so startup banners localize; project init and utility skill refresh happen explicitly at `tui/main.go:218-230`, and the returning-user runtime sequence follows at `tui/main.go:269-288`
1. `config.MigrateLegacyLanguage(globalDir)` then `config.LoadTUIConfig` + `i18n.SetLang` — one-shot language migration and locale resolution, run early (`tui/main.go:132-137`) so startup banners localize; project init and utility skill refresh happen explicitly at `tui/main.go:213-225`, and the returning-user runtime sequence follows at `tui/main.go:269-283`
2. `config.NeedsVenv(globalDir)` — check if a setup banner should be printed
3. `config.EnsureRuntime(globalDir)` — create/repair venv if needed, then always auto-check/upgrade or convert the `lingtai` Python runtime
4. `preset.Bootstrap(globalDir)` — copy preset resources
Expand Down
Loading