codeburn/docs/providers/lingtai-tui.md
Rick Culpepper (claude) 4ca2d4824b
Scope the root test script to tests/ so npm test runs from a clean install
vitest's default glob reached the Electron app's specs under app/, which carry their
own vitest config and their own jsdom in app/node_modules. From a root install that
fails with ERR_MODULE_NOT_FOUND: jsdom, so the command CONTRIBUTING documents and the
one RELEASING.md names as the pre-release gate both error out.

Move the scoping CI already applies into package.json: test runs tests/ minus the
parallelism-sensitive cache-refresh-lock suites, test:locks runs those three serially,
test:watch keeps watch mode at the same scope. The first two are byte-identical to the
invocations .github/workflows/tests.yml spells out, so the workflow can be pointed at
the scripts to stop the two drifting apart again; that edit is left out of this PR so it
needs no workflow permissions. test plus test:locks together still cover all 192 files
under tests/.

Scoping the script changes what a trailing path argument means: vitest ORs positional
filters, so 'npm test -- tests/providers/hermes.test.ts' would no longer narrow to that
file, it would run the whole suite. Rewrite those to 'npx vitest run <path>' everywhere
they appear - four provider guides and the MCP design plan, thirteen lines in all.

Also refresh the stale test docs: 42 files/568 tests (now 192 under tests/), the
per-directory counts, the line claiming vitest does not run in CI which stopped being
true when tests.yml landed, and the provider test-gap list, which still named
antigravity and gemini after both gained test files.

Record the cache-refresh-lock naming convention in CONTRIBUTING, since the split makes
it load-bearing: a lock test that misses the prefix runs under the full worker pool and
flakes, and one that matches it but is absent from test:locks never runs at all.
2026-08-09 10:19:58 -05:00

88 lines
3.8 KiB
Markdown

# LingTai TUI
LingTai TUI per-agent token ledger integration.
- **Source:** `src/providers/lingtai-tui.ts`
- **Loading:** eager (`src/providers/index.ts`)
- **Test:** `tests/providers/lingtai-tui.test.ts`
## Where it reads from
| Source | Path |
|---|---|
| Explicit LingTai homes | `$LINGTAI_HOME` or `$LINGTAI_TUI_HOME` if set; path-list values are supported |
| Default LingTai home | `~/.lingtai` |
| Project LingTai homes | `<project>/.lingtai` for projects registered in `~/.lingtai-tui/registry.jsonl` and `~/.lingtai-tui/brief/projects/*/meta.json` |
| Current worktree home | `.lingtai` in the current directory or any parent directory |
| Agent ledgers | `<lingtai-home>/<agent>/logs/token_ledger.jsonl` |
Daemon ledgers nested under `<agent>/daemons/...` are deliberately not discovered during normal scanning. LingTai mirrors daemon usage into the parent agent ledger with `source`, `em_id`, and `run_id` tags, so reading nested ledgers too would double count spend.
## Storage format
Append-only JSONL. Each valid ledger line may include:
- `source`
- `em_id`
- `run_id`
- `ts`
- `input`
- `output`
- `thinking`
- `cached`
- `model`
- `endpoint`
Malformed lines and zero-token entries are skipped. Missing `model` falls back to the agent `.agent.json` `llm.model`, then `unknown`.
## Parser
CodeBurn emits one parsed call per ledger entry. LingTai records provider-normalized total input plus a separate `cached` counter, so the provider maps:
- `input - cached` -> fresh input tokens
- `cached` -> cache-read tokens
- `output` -> output tokens
- `thinking` -> reasoning tokens
Costs are calculated from CodeBurn's normal model pricing table.
## Activity mapping
LingTai's token ledger is an accounting source, not full chat history, so it does not include the original user prompt or per-tool transcript. CodeBurn maps the ledger `source` field conservatively:
| LingTai `source` | CodeBurn activity |
|---|---|
| `main` and unknown sources | Conversation |
| `tc_wake` and other task-coordinator wake sources | Delegation |
| `daemon` | Delegation |
| `summarize_apriori` | Planning |
This keeps the menubar and dashboard **By Activity** view from collapsing all LingTai usage into Conversation while avoiding invented feature/debug/refactor semantics that the ledger cannot prove.
## Project grouping
Discovery reads `<agent>/.agent.json` and groups by `nickname`, `agent_name`, `address`, then the directory name. Project-local homes are prefixed with the project directory name, for example `sample-project-Project Agent`, so same-named agents from different LingTai projects do not collapse together. The parsed call also carries the agent directory as `projectPath`.
## Caching
The shared session cache fingerprints each `token_ledger.jsonl`. `LINGTAI_HOME`, `LINGTAI_TUI_HOME`, and `LINGTAI_TUI_GLOBAL_DIR` are part of the provider environment fingerprint so changing homes invalidates stale cached results.
## Deduplication
Dedup keys include provider name, ledger path, line number, timestamp, model, endpoint, LingTai source tags, and token counts:
`lingtai-tui:<ledger-path>:<line>:<timestamp>:<model>:...`
The ledger is append-only, so line number is stable for normal operation.
## Quirks
- Tool calls are not reconstructed from chat history. The token ledger is the stable accounting source and does not include tool metadata.
- Older ledger entries may not include `source`; those are labeled `main`.
- `cached` is treated as cache read. LingTai does not expose a separate cache creation counter in the ledger.
## When fixing a bug here
1. Prefer a minimal redacted `token_ledger.jsonl` fixture over full `chat_history.jsonl`.
2. Check whether a daemon entry is already mirrored into the parent ledger before adding new discovery paths.
3. Run `npx vitest run tests/providers/lingtai-tui.test.ts`.