84988e8cdb fix(cli): TUI diagnostics, keyring timeout, Reasonix-home paths / 启动诊断、keyring 超时与 home 路径加固 (#7663)
* fix(cli): harden TUI diagnostics, keyring migration, and home paths

Problem:
- Interactive TUI freezes left zero-byte cli-tui logs and unrecoverable
  terminals on Windows ConPTY and stuck D-Bus startups (#7435, #7507).
- Global hooks/doctor/capdiag could miss the real Reasonix home on Windows
  AppData and REASONIX_HOME isolation (#7411, #7331).
- Legacy keyring migration blocked startup when Secret Service hung.
- #7600's automatic HOME rewrite risked breaking isolation contracts.

Root cause:
- Diagnostics started after heavy work and never flushed milestones/heartbeats.
- Hooks resolved global settings via derived ~/.reasonix rather than the exact
  Reasonix home used by the rest of the product.
- Keyring probes ran unbounded per key with file import ordered after D-Bus.
- Subprocess HOME rewriting conflates service HOME with Reasonix isolation.

Fix:
- Start TUI diagnostics before config/controller work; record milestones and
  flush immediately; 1s heartbeat with 10s stall → goroutine dump + Program.Kill.
- Unify hook/capdiag/doctor on exact ReasonixHomeDir; public paths show
  <reasonix-home>.
- Legacy credential migration: files first, then shared 1s keyring budget with
  empty-success markers; timeout leaves no marker for retry.
- Doctor warns when process HOME ≠ account home without REASONIX_HOME; do not
  auto-rewrite subprocess HOME (#7600 not adopted).

Verification:
- go test ./internal/cli ./internal/config ./internal/hook ./internal/capdiag ./internal/doctor -count=1

Co-authored-by: Zhiyao Wen <[email protected]>
Co-authored-by: zhaotian1 <[email protected]>

* fix(cli): isolate keyring probes and tighten migration markers

Problem:
- In-process keyring timeouts could leave hung D-Bus goroutines and
  collapse found/absent/error/timeout into a single false, risking wrong
  migration-done markers (#7507 audit).
- Keyring markers also skipped legacy credential *file* import.
- doctor HOME warning leaked absolute account paths into shareable reports.
- lint failed on an unused diagnostics mutex; CodeQL flagged SHA-256 of env
  names as secret-like storage.

Root cause:
- Timeout wrappers cannot cancel platform keyring calls in-process.
- skip() treated keyring markers as global migration completion.
- redactHome only knows the process HOME, not the OS account home.

Fix:
- Run legacy keyring batch probes in an isolated helper child with a shared
  1s deadline; parent Kill+Wait on timeout (no parent goroutine leak).
- Four-state outcomes: found / absent / error / timeout; write markers only
  on confirmed absent.
- File import always runs first; markers only filter keyring probes.
- Marker paths use sanitized env names under legacy-keyring-checked/.
- doctor reports HOME mismatch without embedding either path.
- Watchdog WaitGroup drains before closing the diagnostic log file.

Verification:
- go test ./internal/config ./internal/doctor ./internal/cli ./internal/hook ./internal/capdiag -count=1
- go vet ./internal/cli ./internal/config ./internal/doctor

* fix(cli): keyring four-state to metal and secret-free helper

Problem:
- Platform keyring probes still returned (string, bool), so D-Bus/unlock
  failures were treated as absent and could write migration markers.
- The isolated helper printed keyring secrets on stdout, making any
  process that can launch reasonix a credential oracle.
- Watchdog Close waited only 2s, so a stuck Stack/Sync/Kill could write
  a closed diagnostic file.
- Marker names folded distinct keys onto "_" collisions.

Root cause:
- Four-state status stopped at the batch layer; the Secret Service path
  collapsed every error to false.
- Helper was designed as a value RPC instead of an in-child store step.
- Close used a timed wait instead of joining the watchdog fully.

Fix:
- legacyKeyringProbe returns found/absent/error at the platform layer
  (ErrNotFound/empty search → absent; transport/unlock/session errors →
  error).
- Helper stores found secrets via StoreCredentialLines and emits only
  key+status metadata on stdout (no value field).
- Parent never receives secret Values from the helper path; markers only
  on confirmed absent.
- Watchdog WaitGroup is joined fully before closing the log file.
- Marker basenames use base64.RawURLEncoding of the env name.

Verification:
- go test ./internal/config ./internal/cli ./internal/doctor -count=1
- New tests: error does not write marker; helper JSON has no secrets;
  RawURL marker collision-free; four-state in-process outcomes

* fix(cli): drop keyring helper oracle; atomic store-if-absent

Problem:
- The REASONIX_LEGACY_KEYRING_HELPER entrypoint let any process that can
  launch reasonix dump keyring secrets into a caller-controlled
  REASONIX_HOME/.env (disk oracle after stdout was scrubbed).
- Legacy import could overwrite a concurrent settings write or tombstone
  because presence was checked outside the credential lock.

Root cause:
- Migration used an external helper to bound D-Bus hangs, which reopened
  a secret export surface via StoreCredentialLines + controllable home.
- store used unconditional StoreCredentialLines after a TOCTOU check.

Fix:
- Remove the helper entrypoint entirely (main + env dispatch).
- Linux/BSD Secret Service probes use godbus CallWithContext under a
  shared 1s batch deadline so stuck D-Bus calls cancel in-process.
- Found secrets are written only via storeCredentialIfAbsentAndNotCleared
  (same advisory lock re-checks missing/not-cleared before write).
- Channel-forced tests cover user-value and tombstone races without sleep.

Verification:
- go test ./internal/config ./internal/cli ./internal/doctor -count=1
- REASONIX_LEGACY_KEYRING_HELPER=1 reasonix --version is a normal version
  print (no helper path, no oracle home writes)

* fix(cli): private ctx-bound D-Bus keyring and real probe races

Problem:
- dbus.SessionBus left process-global godbus workers that failed goleak
  under Ubuntu/race/coverage.
- GetProperty and session Close used non-context call paths, so a stuck
  bus could still hang CLI past the 1s migration budget.
- Race tests called store-if-absent directly and never forced the
  production probe→store window.

Root cause:
- Shared SessionBus + GetProperty(Background) escaped the batch ctx.
- Channel tests interleaving happened outside lookupLegacyKeyringBatch.

Fix:
- Open a private ConnectSessionBus per probe, race Dial/Auth/Hello
  against the shared ctx, and always Close the connection.
- Resolve Collections and Close sessions only via CallWithContext(ctx).
- Drive store-if-absent races through a blocking probe stub inside
  lookupLegacyKeyringBatch (user write and tombstone cases).
- go mod tidy promotes godbus to a direct dependency.

Verification:
- go test ./internal/config -count=1
- go test -race ./internal/config -count=1
- go test ./internal/control -count=1

* fix(cli): bind keyring bus connect to batch context

Problem:
- ConnectSessionBus had no dbus.WithContext, so a stuck Auth/Hello after
  Dial could keep the connect goroutine and late reaper parked forever
  even though the caller returned at 1s.

Root cause:
- Connection lifecycle was only raced externally; godbus never received
  the migration ctx to Close the transport on deadline.

Fix:
- SessionBusPrivateNoAutoStartup(dbus.WithContext(ctx)) then Auth+Hello,
  so cancel closes the transport and unblocks Auth/Hello I/O.
- Avoid dbus-launch (NoAutoStartup): missing session address fails closed
  instead of hanging in CombinedOutput.
- Outer select still bounds the caller; late *Conn is always closed.
- Document residual: pure Dial hang before newConn remains a godbus limit.

Verification:
- go test ./internal/config -count=1
- go test -race ./internal/config -count=1
- go test ./internal/control -count=1
- GOOS=linux go test ./internal/config -c

* ci: allow Windows smoke runner variance

Problem: The Windows smoke step regularly takes 7-9 minutes and the current run exceeded its 10-minute job budget even though vet and build succeeded.

Root cause: The job-level timeout leaves too little headroom for hosted Windows runner variance.

Fix: Raise only the pull-request Windows smoke job budget to 15 minutes while retaining the per-package 3-minute Go test timeout.

Verification: YAML parse; git diff --check; go test ./internal/cli ./internal/config -count=1.

---------

Co-authored-by: Zhiyao Wen <[email protected]>
Co-authored-by: zhaotian1 <[email protected]>
2026-08-06 14:39:56 +08:00

Reasonix

English  ·  简体中文  ·  Guide  ·  ACP  ·  Extensions  ·  Spec  ·  Website  ·  Discord

npm version CI license downloads GitHub stars AtomGit stars contributors Discussions Discord

esengine/DeepSeek-Reasonix | Trendshift esengine/DeepSeek-Reasonix | Trendshift


A DeepSeek-native AI coding agent for your terminal.

A config- and plugin-driven harness — a single static Go binary, tuned around DeepSeek's prefix cache so token costs stay low across long sessions.


Important

Community · 加入社区 — bilingual Discord for setup help (#help / #求助), workflow showcases, and feature ideas. → https://discord.gg/XF78rEME2D


Features

  • Config-driven. Providers, the agent, enabled tools, and plugins are all declared in reasonix.toml. No hardcoded models.
  • Multi-model & composable. DeepSeek ships as a preset; any OpenAI-compatible endpoint is a config entry, not new code. Optionally run two models together (executor + planner) in separate, cache-stable sessions.
  • Plugin-driven. MCP servers contribute tools, prompts, and resources; Extension Protocol v1 sidecars can also intercept runtime events, contribute Providers and structured UI, and ship versioned plugin packages.
  • Cache-aware context maintenance. Startup injects a small stable environment summary, stale tool output is snipped/pruned before summary compaction, and the built-in tool schema contract is documented for regression review.
  • Zero-friction distribution. CGO_ENABLED=0 single binary; cross-compile to six targets with one command. The only dependency is a TOML parser.

Install

Choose the path that matches how you want to use Reasonix. The CLI/TUI, desktop app, and VS Code extension all use the same local Reasonix engine.

Path A: CLI / TUI

Install the native binary through npm on any supported platform, or use Homebrew on macOS:

npm i -g reasonix                  # any OS; pulls the prebuilt native binary
brew install esengine/reasonix/reasonix   # macOS

Prebuilt archives (darwin|linux|windows × amd64|arm64) and SHA256SUMS are on every GitHub release.

Path B: Desktop app

Use the official download page for the latest desktop build.

Platform Package Architecture
macOS Universal .dmg or .zip Apple Silicon / Intel
Windows Installer .exe or portable .zip x64 / ARM64
Linux .deb or .tar.gz x64

Windows installers are code-signed through SignPath.io with a free certificate provided by the SignPath Foundation.

Path C: VS Code extension

Complete Path A first. The extension does not bundle the CLI; it starts your local reasonix acp backend and adds native chat, editor context, tool-call approvals, model selection, and workspace sessions.

Path D: Build from source

git clone https://github.com/esengine/DeepSeek-Reasonix.git
cd DeepSeek-Reasonix
make build      # -> bin/reasonix(.exe)
make cross      # -> dist/ (darwin|linux|windows × amd64|arm64)

Quick start

CLI / TUI

These commands are for the CLI/TUI installed through Path A:

reasonix setup                      # configure a provider and model
reasonix                            # start an interactive session
reasonix run "implement the TODOs in main.go"

In an interactive session, run /init when you want Reasonix to create project instructions.

Desktop app

Download the installer for your platform from the official download page, install and launch Reasonix, then configure a provider and model in the app. The CLI commands above are not required for the desktop app.

For advanced CLI usage and configuration, see the CLI reference, Guide, and configuration paths.

Documentation

Star History

Star History Chart

Acknowledgments

A small list of folks whose work has shaped Reasonix the most — the current top 20 contributors by commit count. The full contributor graph is on GitHub.

Contributor Contributor Contributor Contributor
SivanCola esengine ttmouse lifu963
reasonix (anonymous) HUQIANTAO GTC2080 light-front-theory
merge-order-check (anonymous) Li-Charles-One eghrhegpe wufengfan (anonymous)
CVEngineer66 dependabot[bot] lanshi17 SuMuxi66
CnsMaple cyq1017 JesonChou XTLine

Also a separate thank-you to Bernardxu123 for designing the project logo, and to AIGC Link for promoting the project on XiaoHongShu.

Contributors to esengine/DeepSeek-Reasonix



MIT — see LICENSE
Built by the community at esengine/DeepSeek-Reasonix


Support this project

If Reasonix has been useful and you'd like to say thanks, you can. It stays a coffee, not a contract — donations don't buy feature priority or change how issues get triaged.

WeChat Pay QR code

2026-11-06 17:13:39 -10:00
Languages
Go 69.3%
TypeScript 20.4%
JavaScript 3.9%
HTML 2.6%
CSS 1.7%
Other 2%