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.
3.8 KiB
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:
sourceem_idrun_idtsinputoutputthinkingcachedmodelendpoint
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 tokenscached-> cache-read tokensoutput-> output tokensthinking-> 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 labeledmain. cachedis treated as cache read. LingTai does not expose a separate cache creation counter in the ledger.
When fixing a bug here
- Prefer a minimal redacted
token_ledger.jsonlfixture over fullchat_history.jsonl. - Check whether a daemon entry is already mirrored into the parent ledger before adding new discovery paths.
- Run
npx vitest run tests/providers/lingtai-tui.test.ts.