22 Commits

Author SHA1 Message Date
Hunter Bown 5fa24733e9 chore(rebrand): update repository links for CodeWhale 2026-05-23 14:07:36 -05:00
Hunter Bown 23daefbe24 feat(npm): publish as codewhale; keep deepseek-tui as deprecation shim
Rename the npm wrapper directory and package from `deepseek-tui` to
`codewhale`. Move under `npm/codewhale/`:
  - `package.json` renamed (name, bin, internal field) — keeps a
    `deepseekBinaryVersion` fallback so old metadata still works.
  - Bin entry points renamed to `bin/codewhale.js` and
    `bin/codewhale-tui.js`; they spawn the corresponding canonical
    binaries via the wrapper.
  - `scripts/artifacts.js` switches to the canonical asset-name matrix
    (`codewhale-*`, `codewhale-tui-*`) and `codewhale-artifacts-sha256.txt`.
  - `scripts/run.js` exports `runCodewhale` and `runCodewhaleTui`; the
    legacy `runDeepseek` exports are gone since nothing else inside the
    package depended on them.
  - `scripts/install.js`, `verify-release-assets.js`, `preflight-glibc.js`
    update brand-mention strings + User-Agent headers. Env vars
    (`DEEPSEEK_TUI_*`, `DEEPSEEK_*`) are explicitly anti-scope and are
    left in place.
  - Tests retargeted at the canonical asset names; all 19 still pass.
  - README rewritten with the new install command and a deprecation
    note about the old package.

Create a one-release deprecation shim at `npm/deepseek-tui/`:
  - `package.json` with no `bin`, just a postinstall script that
    prints a clear message telling the user to install `codewhale`
    instead.
  - `README.md` with the same migration note.
  - Will be removed in v0.9.0 (or whenever Hunter retires the shims).

Release-side scripts in `scripts/release/` follow the rename:
  - `prepare-local-release-assets.js` now requires `npm/codewhale/...`
    and copies the canonical `codewhale*` binaries.
  - `npm-wrapper-smoke.js` smokes the renamed package.
  - `check-versions.sh` reads `npm/codewhale/package.json` for the
    primary check and additionally pins the legacy shim package to
    the same version.
  - `check-published.sh` queries `codewhale@<version>` (with
    `codewhaleBinaryVersion` lookup that falls back to the legacy
    `deepseekBinaryVersion` field).
  - `.github/workflows/auto-tag.yml` watches both `npm/codewhale/` and
    `npm/deepseek-tui/` package.json for auto-tag triggers.

Verified:
  - `npm test` inside `npm/codewhale/` passes 19/19.
  - `npm install --dry-run --ignore-scripts` succeeds for both
    `npm/codewhale/` and `npm/deepseek-tui/`.
  - `scripts/release/check-versions.sh` reports OK.
  - Rust gates re-run: `cargo check`, `cargo fmt --check`,
    `cargo clippy -- -D warnings`, all clean.

No `npm publish` is run from this change — Hunter publishes manually
when the rebrand is ready to ship.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 11:11:53 -05:00
Hunter Bown 47f3c410d6 fix(npm): avoid pnpm optional postinstall hangs 2026-05-14 15:25:40 -05:00
Hunter Bown b816234fbc Merge remote-tracking branch 'origin/pr/1339' into work/v0.8.34 2026-05-12 23:34:22 -05:00
Hunter Bown 9ca759bd11 fix(npm): show timeout hint on first retry (#1538)
Co-Authored-By: jieshu666 <jieshu666@users.noreply.github.com>
2026-05-12 12:10:29 -05:00
Hunter Bown f8a3c6619e fix(npm): map openharmony platform to linux binaries (#1072)
Node's `os.platform()` returns `openharmony` on HarmonyPC and on
OpenHarmony's Linux ABI-compatible userspace. The npm wrapper's
platform-asset matrix only covered `linux` / `darwin` / `win32`,
so `npm i -g deepseek-tui` aborted on those hosts with

    Unsupported platform: openharmony. Supported platforms: …

even though the existing Linux x64 / arm64 binaries run unchanged
on that environment (OpenHarmony is Linux-ABI-compatible at the
ELF level).

Added a `PLATFORM_ALIASES = { openharmony: "linux" }` indirection
that resolves the raw platform name through the alias map before
the `ASSET_MATRIX` lookup. Genuinely unsupported platforms still
report the raw `os.platform()` value in the error so OS-mismatch
bug reports stay diagnostic.

Four pure-JS regression tests pin the behaviour:

- openharmony x64 → linux x64 binaries
- openharmony arm64 → linux arm64 binaries
- known platforms unchanged by the alias map
- freebsd still reports `Unsupported platform: freebsd`

Harvested from PR #1499 by @CrepuscularIRIS

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 01:39:44 -05:00
lixia 904298216c fix: reuse shared npm binary marker path 2026-05-10 11:55:55 +08:00
lixia e61a40f39d fix: adopt verified npm binaries from downloads 2026-05-10 11:26:08 +08:00
Hunter Bown 3f3395e00e fix(npm): make postinstall download failures recoverable 2026-05-07 15:16:17 -05:00
Hunter Bown 77e0810940 fix(npm): explain release mirror on download failures 2026-05-07 13:37:20 -05:00
axobase001 b476703a8d fix(npm): guard unsupported node during install (#1032) 2026-05-07 06:27:38 -05:00
Hunter Bown 593ed2f900 fix(npm): preserve -v passthrough
Summary:
- Stop treating -v as an npm wrapper version fallback.
- Keep wrapper fallback for --version and -V.
- Add a Node regression test for wrapper version flag detection.

Test plan:
- npm test from npm/deepseek-tui
- git diff --check origin/main...HEAD

Supersedes #959.
2026-05-07 03:37:22 -05:00
GK012 9a7cd9f937 fix(npm): add --version fallback in wrapper
fix(npm): add --version fallback in wrapper
2026-05-06 10:19:05 -05:00
zxyasfas 0fded51824 docs: align Rust MSRV references with workspace (#739) 2026-05-05 22:39:50 -05:00
Hunter Bown 9e67e04e4a fix(install,tests): fmt nit + downloadText flowing-mode bug
CI on PR #684 caught two real issues that local checks missed:

**Lint failure (cargo fmt).** A regression test landed with a multi-line
`let ContentBlock::Text { text, .. } = real_user.content...` pattern
that local rustfmt accepted but CI's pinned toolchain collapsed onto a
single line. Reformatted to match.

**npm wrapper smoke failure ("Checksum manifest is missing
deepseek-<platform>").** Subtle Node.js streams interaction in
`install.js` introduced by the network-resilience cluster:

* `httpRequest` attaches a `data` event listener on the response to
  re-arm the stall timer.
* Attaching a `data` listener on a `Readable` puts the stream into
  flowing mode immediately.
* `downloadText` then ran `for await (const chunk of response)` to
  collect the body — the async iterator expects paused-mode and
  silently misses chunks that flow before / between iteration ticks.
* For small bodies (the ~100-byte SHA256 manifest), the entire
  response could flow through the stall listener before the async
  iterator's `read()` calls landed, leaving the joined body empty.
* Result: `parseChecksumManifest("")` returned an empty Map →
  `verifyChecksum` saw no entries → "manifest is missing X" after
  the actual binary download succeeded.

Binary downloads were unaffected because `download()` uses
`response.pipe(sink)` plus a `data` listener for progress — both
consume chunks via `data` events, no async iterator involved.

Fix: collect the response body in `downloadText` via direct `data`/
`end` event subscription. `data` listeners stack — both the stall
re-arm and the body collector fire on every chunk, no flowing-vs-
paused conflict. Stall detection still works.

Verified locally: `node scripts/release/npm-wrapper-smoke.js`
"npm wrapper smoke passed with local assets from <url>".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 22:37:23 -05:00
Hunter Bown 229f02ea2c feat(npm): install.js network resilience for slow / firewalled networks
A community user from China reported `npm install deepseek-tui`
took 18 minutes through a CN npm mirror. The bottleneck is the
GitHub Releases binary fetch (~46 MB across two binaries), not the
npm tarball (which is 6.9 kB). The CN mirror does NOT proxy GitHub
release downloads, so any user behind a slow or lossy connection
is hitting the GitHub fetch directly with no resilience.

Four behaviors added to `npm/deepseek-tui/scripts/install.js`:

1. **Retry with exponential backoff.** Up to 5 attempts on network
   errors (ECONNRESET, ECONNREFUSED, ETIMEDOUT, EAI_AGAIN,
   network/host unreachable, EPIPE, ECONNABORTED) and 5xx upstream
   responses. Backoff `1s, 2s, 4s, 8s, 16s` with ±20% jitter. 4xx
   and checksum-mismatch are flagged non-retryable so we don't
   thrash on permanent failures. Final error includes the underlying
   message and the attempt count.

2. **Per-attempt total timeout + stall detector.** Total timeout
   defaults to 5 minutes per attempt (`DEEPSEEK_TUI_DOWNLOAD_TIMEOUT_MS`,
   alias `DEEPSEEK_DOWNLOAD_TIMEOUT_MS`). A stall detector aborts
   the request when no bytes arrive for 30 s
   (`DEEPSEEK_TUI_DOWNLOAD_STALL_MS`, alias
   `DEEPSEEK_DOWNLOAD_STALL_MS`) so a hung connection doesn't waste
   the whole timeout. Both budgets are surfaced in the error so the
   user can dial them up if they're on a slow pipe.

3. **HTTPS_PROXY / HTTP_PROXY support — pure Node, no new
   dependencies.** Detects `HTTPS_PROXY` / `HTTP_PROXY` (and the
   lowercase variants) and routes through the proxy via CONNECT
   tunneling. `NO_PROXY` exclusion list honored, with `*` and dotted-
   suffix matching. Proxy auth via standard `user:pass@` URL form is
   passed through as `Proxy-Authorization: Basic ...`. Pure-Node
   implementation using `net` + `tls` + `http` + `https` builtins —
   no `https-proxy-agent` dependency added.

4. **Download progress indicator.** Writes to stderr every ~1 MB
   or every 2 s in TTY mode using `\r` to overwrite a single line.
   Non-TTY mode (CI, piped) emits one line per 5 MB so logs stay
   reasonable. Suppressed when `DEEPSEEK_TUI_QUIET_INSTALL=1` or
   when `npm_config_loglevel` is `silent` or `error`. Falls back to
   `N MB downloaded` when the response has no `Content-Length`.

Public API unchanged: existing callers of `getBinaryPath` and `run`
keep working identically when no new env vars are set. The escape
hatch `DEEPSEEK_TUI_DISABLE_INSTALL=1` still exits cleanly.

Verified locally:

* `node -c install.js` and module-load syntax checks.
* `DEEPSEEK_TUI_FORCE_DOWNLOAD=1 DEEPSEEK_TUI_VERSION=0.8.10 node
  install.js` — real GitHub Releases download succeeded with
  visible progress, both binaries landed.
* `HTTPS_PROXY=http://invalid.proxy.local:9999 ... node install.js`
  — proxy path exercised, fails cleanly with the bad host named
  in the error message after retries exhausted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 22:19:34 -05:00
Vishnu 3179b552d4 feat(npm): glibc preflight check on Linux postinstall (#560) (#565)
Linux installs currently succeed even when the host glibc is older than
what the prebuilt binary requires, leaving the user with a cryptic
`GLIBC_2.XX not found` runtime error.

Add a Linux-only preflight in `scripts/preflight-glibc.js` that runs
right after checksum verification:

- Read the highest required `GLIBC_X.Y` symbol from the downloaded
  binary by scanning its bytes (no readelf dependency).
- Detect host glibc via `getconf GNU_LIBC_VERSION`, falling back to
  `ldd --version`.
- If host < required, throw with a clear message pointing at the
  build-from-source path (cargo install / git clone instructions).
- If glibc cannot be detected at all (musl/Alpine), surface the same
  guidance instead of installing an incompatible binary.
- Skipped on macOS/Windows. `DEEPSEEK_TUI_SKIP_GLIBC_CHECK=1` (or the
  legacy `DEEPSEEK_SKIP_GLIBC_CHECK=1`) bypasses the check.

The downloaded file is unlinked on failure, so a failed preflight
leaves nothing behind and npm exits non-zero.

Closes #560
2026-05-04 02:18:26 -05:00
Claude 0e5afe0b01 feat(v0.8.8): linux ARM64 prebuilts + install docs overhaul
Triggered by a Telegram report from a Chinese user trying to deploy
DeepSeek TUI on a HarmonyOS ARM64 thin-and-light: `npm i -g deepseek-tui`
exited with `Unsupported architecture: arm64 on platform linux` because
v0.8.7 only published x64 Linux artifacts. They worked around it with
`cargo install`, but the README never documented that path for ARM users.

This PR closes that gap on three layers:

- **Release workflow** — add `aarch64-unknown-linux-gnu` to the build
  matrix using GitHub's `ubuntu-24.04-arm` runner. v0.8.8 will publish
  `deepseek-linux-arm64` and `deepseek-tui-linux-arm64` alongside the
  existing x64/macOS/Windows assets, plus add the row to the Release
  body's manual-download table.

- **npm wrapper** — uncomment the linux/arm64 row in `ASSET_MATRIX`,
  rewrite the `Unsupported architecture/platform` error to print the
  full `cargo install deepseek-tui-cli deepseek-tui --locked` recipe
  and link to docs/INSTALL.md, and add `DEEPSEEK_TUI_OPTIONAL_INSTALL=1`
  so CI matrices that include unsupported platforms can keep running
  without a binary.

- **Docs** — new docs/INSTALL.md covering every supported platform,
  prebuilt vs. cargo install vs. manual download, cross-compiling x64
  -> ARM64 with `cross` or `gcc-aarch64-linux-gnu`, China mirror setup,
  and a troubleshooting section for the common arm64, MISSING_COMPANION_BINARY,
  and self-update arch-mapping (#503) errors. README and README.zh-CN
  now have an explicit Linux ARM64 quickstart pointing at `cargo install`
  for v0.8.7 today and `npm i -g` for v0.8.8+; the v0.8.7 known-issue
  block is updated to mention both #503 and the missing arm64 prebuilt.

https://claude.ai/code/session_01Fg1FKMtDxVnC4pp6bNBRCS
2026-05-03 04:42:53 +00:00
Hunter Bown ac7c11e751 fix(npm): trust local version marker; only fetch checksum manifest when downloading
The wrapper re-downloaded the SHA-256 manifest from the GitHub release on every
invocation of `deepseek` / `deepseek-tui`, so any GitHub flake, captive portal,
proxy, or offline state broke every command — not just install.

Now ensureBinary returns immediately when the binary exists and its `.version`
marker matches. The manifest fetch is lazy and only runs when a download is
actually needed (first install or DEEPSEEK_TUI_FORCE_DOWNLOAD=1).

Bumps wrapper to 0.8.2; deepseekBinaryVersion stays on 0.8.1 (no new Rust
release required).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 01:15:50 -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 7b91169017 refactor: move source files into workspace crates
- Move src/* into crates/tui/src/ to create a proper workspace structure
- Add .claude/ and .trimtab/ directories for Trimtab closed-loop workflow
- Add DEPENDENCY_GRAPH.md and update documentation
- Update Cargo.toml files to reflect new crate dependencies
- Update CI workflows and npm package scripts
- All tests pass, release build works
2026-03-11 20:00:38 -05:00
Hunter Bown f2881e7e3d feat: add npm package and update install docs
- Add npm/deepseek-tui package that downloads prebuilt binaries from
  GitHub releases (supports macOS, Linux, Windows)
- Published as deepseek-tui@0.3.28 on npmjs.com
- Update README to feature npm as primary install method
- Add npm badge
2026-03-03 09:57:56 -06:00