Commit Graph

15 Commits

Author SHA1 Message Date
Hunter Bown fc1970fa55 fix(auth): use config-backed setup without credential prompts 2026-05-03 23:02:11 -05:00
Hunter Bown ad8064b143 chore(v0.8.8): stabilization batch — sub-agent caps, mutex contention, RLM polish, CI cleanup
Bundles the v0.8.8 stabilization fixes that were already implemented in the
working tree, plus the workflow/doc reconciliation called out in #507.

### Sub-agent runtime fixes
- **#509** Default sub-agent cap raised to 10 (configurable via
  `[subagents].max_concurrent` in `config.toml`, hard ceiling 20). The
  running-count calculation now ignores non-running, no-handle, and finished
  handles so completed agents stop counting against the cap.
- **#510** `SharedSubAgentManager` is now `Arc<RwLock<...>>`; the read paths
  that previously held a `Mutex` for inspection now take a read lock,
  eliminating the multi-agent fan-out UI freeze.
- **#511** `compact_tool_result_for_context` summarizes `agent_result` /
  `agent_wait` payloads before they are folded into the parent context.
- **#512** RLM tool cards map to `ToolFamily::Rlm` and render `rlm`, not
  `swarm`. Stale "swarm" wording cleaned in docs/comments/tests.
- **#513** (foreground stopgap only) Foreground RLM work is visible in the
  Agents sidebar projection. Full async RLM lifecycle remains v0.8.9 — the
  issue stays open with a refined scope.

### TUI / UX fixes
- **#487** Offline composer queue is now session-scoped; legacy unscoped
  queues fail closed.
- **#488** Composer Option+Backspace deletes by word; cross-platform key
  routing helpers added.
- **#443/#444** Keyboard enhancement flags pop on normal AND panic exit; the
  raw-mode startup probe is now bounded by a configurable timeout.
- **#449** Production footer reads statusline colors from `app.ui_theme`
  rather than the bespoke palette.
- **#506** `display_path_with_home` no longer mutates `HOME` in tests; the
  flake on shared-env CI is gone.

### Self-update / packaging
- **#503** `update.rs` arch mapping uses release-asset naming (`arm64`/`x64`)
  instead of the raw Rust constants. The platform-asset selector also rejects
  `.sha256` siblings as primary binaries. Tests now live alongside the source
  in `mod tests` (the `#[path]`-based integration test was removed because it
  duplicated test runs and forced a `pub(crate)` helper that no real caller
  used).
- **`Max 5 in flight` wording updated** in `agent_spawn` description,
  `prompts/base.md`, and `docs/TOOL_SURFACE.md` so the model sees the real
  default cap (10) and the configuration knob name.

### CI / release docs (#507)
- Pruned three duplicated/dead workflows: `crates-publish.yml`, `parity.yml`,
  `publish-npm.yml`. Their gates already run in `ci.yml` for every push/PR.
- `release.yml` build job now allows `parity` to be skipped (it only runs on
  tag push), unblocking `workflow_dispatch` reruns. The job still fails
  closed on a real parity failure.
- `RELEASE_RUNBOOK.md` reconciled: crate publishing is documented as the
  manual `scripts/release/publish-crates.sh` flow (no automated workflow);
  references to the deleted workflows removed.
- `CLAUDE.md` notes the `RELEASE_TAG_PAT` requirement for the auto-tag →
  release.yml chain (without it, the tag is created but `release.yml` does
  not fire) and documents the `workflow_dispatch` parity-skip behavior.

### Docs
- `docs/COMPETITIVE_ANALYSIS.md` added — capability matrix vs OpenCode and
  Codex CLI, gap analysis, and recommended implementation order.

### Verification (this branch)
- `cargo fmt --all -- --check` ✓
- `cargo check --workspace --all-targets --locked` ✓
- `cargo clippy --workspace --all-targets --all-features --locked -- -D warnings` ✓
- `cargo test --workspace --all-features --locked` ✓ (1809 + supporting)
- Parity gates ✓ (snapshot, parity_protocol, parity_state)
- `cargo build --release --locked -p deepseek-tui-cli -p deepseek-tui` ✓
- Lockfile drift guard ✓
- `deepseek doctor --json` clean
- `deepseek eval` (offline harness) success=true, 0 tool errors

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 01:57:37 -05:00
Hunter Bown 5bfc1feb62 v0.8.6: survivability, UX polish, and release hardening
Merge the v0.8.6 feature batch and release hardening.\n\nIncludes the full #373-#380/#382-#402 milestone scope, version bump to 0.8.6, secure /share temp-file handling, Windows-safe self-update replacement, and CI portability fixes.\n\nRemote PR checks passed on the final head before merge.
2026-05-02 20:11:33 -05:00
Hunter Bown bb88ab9129 fix(cli): make missing-companion-binary error actually helpful (#258)
@whereiszebra (issue #258) downloaded just \`deepseek-macos-arm64\` from
the GitHub Release, ran it, hit:

  error: deepseek-tui binary not found at /path/to/deepseek-tui.
  Build workspace default members to install it, or set DEEPSEEK_TUI_BIN
  to its absolute path.

…spent 11 minutes figuring out they also needed \`deepseek-tui-macos-arm64\`
sitting next to it, and self-closed with: "Release page does not document
that both deepseek-macos-arm64 and deepseek-tui-macos-arm64 must be
downloaded together."

The dispatcher's error was the wrong message for the population that hits
it most often — direct GitHub Release downloaders. "Build workspace default
members" is meaningless if you didn't clone the repo. \`DEEPSEEK_TUI_BIN\`
is also not what they need.

New message lists the three concrete install paths that actually work for a
fresh user — npm, cargo, or grab BOTH binaries from the same release
page — and keeps the env var override as a final fallback for power
users. No logic change; just better text. Existing
\`locate_sibling_tui_binary_honours_env_override\` test still passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 09:28:28 -05:00
Hunter Bown 5770a5747b fix cargo install packaging for v0.8.1 2026-04-30 23:45:21 -05:00
Hunter Bown 12d79ec774 fix(cli): restore top-level prompt forwarding
Restores top-level prompt forwarding for the deepseek dispatcher.
2026-04-30 21:25:03 -05:00
Hunter Bown 7f2f47edf8 v0.7.7: stabilize sub-agent / swarm / fanout lifecycle, Windows install, and TUI polish (#246)
* wip(v0.7.7): handoff baseline of partial sub-agent stabilization

Captures uncommitted work-in-progress on the v0.7.7 stabilization lane
so subsequent fixes have a stable starting point. Subsequent commits
finish the canonical SubAgentJob/SwarmJob model, fix sidebar/transcript/
footer agreement, copy/paste/cancel contract, checklist rendering, shell
summary preservation, monotonic spend, and version provenance.

Refs #235 #236 #237 #238 #239 #240 #241 #242 #243 #244 #245

* release: bump workspace version to 0.7.7 (#245)

Refs #245

* fix(v0.7.7): canonical swarm card binding, monotonic spend, checklist + shell summary

- Add `swarm_card_index: HashMap<swarm_id, history_index>` so overlapping
  fanouts each project to their own FanoutCard. Eliminates the screenshot
  contradiction where a stale background swarm's progress clobbered a
  newer card (#236, #238).
- Suppress fanout-class tools (`agent_swarm`, `spawn_agents_on_csv`,
  `rlm`, `agent_spawn`) from `active_tool_status_label` so the footer no
  longer reports "tool agent_swarm · 1 active" while sidebar+card show
  the actual worker counts (#236, #238).
- Add `App::displayed_session_cost` + `displayed_cost_high_water` so the
  visible session+sub-agent total is monotonic across reconciliation
  events (cache discounts, provisional → final). New tests: monotonicity
  under negative reconciliation; duplicate dedup keeps display steady (#244).
- Preserve high-signal summary lines from the truncated tail of shell
  output: `test result:`, `failures:`, `error[E…]`, `Finished`,
  `Compiling`, panic markers. Stops the agent re-running cargo gates
  just to see pass/fail under truncation (#242).
- Render `checklist_write` / `todo_*` results as a purpose-built
  checklist card with completed/total + percent header, per-item status
  markers, and a collapsing affordance for long lists. Plumbed through
  the existing `GenericToolCell` so no new variant threading is needed (#241).

Refs #236 #238 #241 #242 #244

* fix(v0.7.7): Esc clears active tool entries optimistically (#243)

When Esc cancels the foreground turn we now finalize the active cell
immediately rather than waiting for the engine's TurnComplete echo to
drain. This stops the footer "tool ... · X active" chip from briefly
contradicting the cancelled state, and frees the composer for the next
message.

Background `block:false` swarms are intentionally NOT killed here — they
remain durable, tracked through `swarm_jobs` and `swarm_card_index` so
their FanoutCard updates as workers land. Subsequent `swarm_status` /
`swarm_result` / `swarm_cancel` tool calls see the canonical store.

New focused test verifies: after Esc, `active_cell` is None, the
background swarm record is preserved, and `is_loading` is cleared so
the composer can submit immediately.

Refs #243

* fix(v0.7.7): Windows .exe lookup + post-turn snapshot detach (#247, #234)

#247 — npm-distributed Windows package failed at runtime because the
Rust dispatcher's `delegate_to_tui` / `delegate_simple_tui` looked for a
sibling named exactly "deepseek-tui", while the actual file shipped by
`scripts/install.js` is `deepseek-tui.exe`. Replace both lookups with
`locate_sibling_tui_binary`, which:

- Honours `DEEPSEEK_TUI_BIN` for explicit overrides
- Tries `deepseek-tui{EXE_SUFFIX}` first (`.exe` on Windows, "" elsewhere)
- Falls back to suffix-less `deepseek-tui` on Windows so users who
  applied the issue's manual workaround still launch successfully
- Emits a platform-correct error path in the bail message

Tests: `sibling_tui_candidate_picks_platform_correct_name`,
`sibling_tui_candidate_windows_falls_back_to_suffixless` (windows-only),
`locate_sibling_tui_binary_honours_env_override`.

#234 — Detach the post-turn workspace snapshot so `git add -A && git
commit` no longer pins the engine loop after `Event::TurnComplete`.
The snapshot still runs on `tokio::task::spawn_blocking`, but the
engine no longer awaits its `JoinHandle`, so the UI accepts input
(text, copy, paste, selection) without waiting for the bookkeeping to
finish. Cycle advance and pre-turn snapshot remain awaited — they are
correctness-sensitive and the cycle path already emits a status chip
("↻ context refreshing…") so the user has visible feedback.

Refs #234 #247

* chore(v0.7.7): bump npm package version 0.7.6 → 0.7.7

Required by `scripts/release/check-versions.sh` ("Version drift" CI
gate); the workspace was bumped to 0.7.7 but `npm/deepseek-tui/package.json`
still reported 0.7.6, blocking PR #246 from going green.

Refs #245
2026-04-30 07:26:26 -05:00
Hunter Bown 30d7650bae feat(cli): #134 add deepseek auth keyring subcommands and surface backend in doctor
Adds first-class keyring management on the dispatcher CLI and wires
the TUI to read its DeepSeek key through the same Secrets façade.

Subcommands:
* `auth set --provider <name>`   writes to the OS keyring; prompts
  on stdin without echo, never prints the key, never touches
  `config.toml`. Supports `--api-key` and `--api-key-stdin`.
* `auth get --provider <name>`   reports `set` / `not set` plus the
  resolving layer (keyring / env / config-file). Never prints the
  value.
* `auth clear --provider <name>` deletes from keyring and from any
  legacy plaintext slot in `config.toml` for parity.
* `auth list`                    table of all known providers and
  whether each layer holds a key. Non-revealing.
* `auth migrate [--dry-run]`     reads `api_key` (root + per-provider
  blocks) from `config.toml`, writes them to the keyring, then
  strips the entries from disk. Idempotent.
* `auth status`                  expanded to also report the active
  keyring backend and per-provider keyring state.

`doctor` now prints `keyring backend: ...` plus per-provider
`keyring=yes/no, env=yes/no` lines and points users at
`deepseek auth set` when no key resolves.

`Config::deepseek_api_key()` in the TUI is rewritten to consult
`Secrets::auto_detect()` first (keyring -> env), then fall back to
the existing TOML slots with a deprecation warning. Error messages
now lead with `deepseek auth set --provider <name>`.

5 new unit tests cover argument parsing for the new subcommands and
end-to-end auth set/clear/migrate behaviour against an
`InMemoryKeyringStore`, verifying that no plaintext key ever lands
in `config.toml`.

Verified manually on macOS:
  $ deepseek auth set --provider deepseek --api-key-stdin
  $ security find-generic-password -s deepseek -a deepseek
  # entry present
  $ deepseek auth migrate
  # api_key lines stripped from ~/.deepseek/config.toml

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:01:43 -05:00
Hunter Bown f118db8201 feat(providers): #52 OpenRouter + Novita as first-class providers
ProviderKind gains Openrouter + Novita variants; ModelRegistry registers
deepseek/deepseek-v4-{pro,flash} against both. /provider opens a picker
modal with inline API-key prompt for un-configured providers. Env
fallbacks: OPENROUTER_API_KEY, NOVITA_API_KEY.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:58:51 -05:00
Hunter Bown 9804c92c21 feat(cli): add 'deepseek metrics' command (closes #70)
Implement `deepseek metrics` as a dispatcher-handled subcommand (no TUI
binary roundtrip) that reads ~/.deepseek/audit.log, session JSON files,
and tasks runtime JSONL event streams, then prints a human-readable
usage rollup aggregated by tool name, compaction events, sub-agent
spawns, and capacity-controller interventions.

Flags: --json (machine-readable) and --since DURATION (e.g. 7d, 24h,
30m, now-2h, 2h30m). Empty/missing audit log exits 0 with an empty
rollup; malformed lines are skipped silently via tracing::trace!.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 14:17:58 -05:00
Hunter Bown d0dc26ce25 Add NVIDIA NIM provider support for DeepSeek 2026-04-24 18:29:19 -05:00
Hunter Bown c4f9078712 release: deepseek tui 0.4.3 2026-04-24 10:48:35 -05:00
Hunter Bown 35595f8edc fix: normalize legacy DeepSeek aliases to V4 flash 2026-04-23 23:08:44 -05:00
Hunter Bown b7bd02d814 feat: DeepSeek V4 support with reasoning-effort control (0.4.0)
Adds first-class DeepSeek V4 Pro and Flash support, updates the default model to deepseek-v4-pro, aligns legacy aliases with the current V4 1M context behavior, and fixes thinking-mode request handling.

Key fixes:
- Send DeepSeek's raw Chat Completions `thinking` parameter at the top level instead of SDK-only `extra_body`.
- Preserve assistant `reasoning_content` for all prior thinking-mode tool-call turns so subsequent requests satisfy DeepSeek V4's replay requirement.
- Fix npm wrapper concurrent first-run downloads by using per-process temporary download paths.
- Add `.mailmap` so historical bot-attributed commits aggregate under Hunter Bown where mailmap is honored.

Verified with the full local Rust gate, live DeepSeek V4 smoke, npm wrapper temp-install smoke, and green PR CI across Linux, macOS, and Windows.
2026-04-23 22:53:20 -05:00
Hunter Bown 37186c3d95 Workspace migration: split into modular crates, parity CI, release updates
- Convert root to Cargo workspace with crates/ layout
- Add deepseek-* crates mirroring Codex architecture
- Add parity CI workflow with snapshot/protocol/state tests
- Update release workflow to build both deepseek and deepseek-tui binaries
- Bump version to 0.3.28
2026-03-02 17:52:46 -06:00