Commit Graph

142 Commits

Author SHA1 Message Date
Hunter Bown 9483248a9f feat(feishu): carry Lighthouse bridge into v0.8.37
Add the Feishu/Lark long-connection bridge, Tencent Lighthouse runbooks, CNB mirror guidance, CNB tag release pipeline, and China-friendly update fallback documentation for the v0.8.37 line.
2026-05-14 03:56:03 -05:00
Hunter Bown 1ecbcfb1f4 docs(install): add download safety verification
Document checksum verification, AV false-positive triage, Linux binary dependency expectations, and blocked-GitHub download fallback guidance.
2026-05-14 03:38:19 -05:00
Hunter Bown a3f88bf6cf fix(search): default web search to bing (#1619)
Summary:
- add Bing as explicit default web_search provider
- keep explicit DuckDuckGo configuration supported
- update docs/help/config examples

Validation: CI green before merge.
2026-05-14 03:31:15 -05:00
Hunter Bown d5c45d962d chore(release): prepare v0.8.36
Squash merge of work/v0.8.36-cache-hygiene into main.

All preflight gates passed: version-drift/check/lint/test (3073 pass, 0 fail) / CodeQL / GitGuardian / npm-smoke. Preparing the v0.8.36 release tag.
2026-05-14 00:31:18 -05:00
Hunter Bown 0ab95aea1c chore(release): start v0.8.35 branch
- Bump workspace, internal crate pins, npm wrapper metadata, generated facts, and docs from 0.8.34 to 0.8.35

- Clarify 60% manual compact guidance vs 80% opt-in automatic guardrail

- Expire completed live-tool rows and collapse stale running shell rows in the Tasks sidebar
2026-05-13 13:36:15 -05:00
Hunter Bown cf45efa07b chore(release): bump workspace to v0.8.34 and clean repo root
- Bump workspace.package.version 0.8.33 -> 0.8.34 across all 14 crates
- Bump npm wrapper version + deepseekBinaryVersion pin
- Update docs/TOOL_SURFACE.md "Current surface" + docs/ARCHITECTURE.md
  current-surface references; historical "removed_in"/"v0.8.33 began
  moving" wording stays as fact
- Update web/lib/facts.generated.ts version pin
- Draft [0.8.34] CHANGELOG section covering the 135 commits since 0.8.33
  (prefix-cache stability, bundled skills, Kitty/Ghostty notifications,
  theme picker, chunked tool dispatch, MCP session-id persistence,
  cost-calc reasoning tokens, and the in-flight internal cleanup)
- Remove stale repo-root development artifacts:
  * TAKEOVER_PROMPT.md (v0.8.6 handoff, 3 minors stale)
  * PROMPT_ANALYSIS.md (v0.8.13-era prompt audit doc)
  * DEPENDENCY_GRAPH.md (claimed monolith layout, predates 14-crate split)
  docs/ARCHITECTURE.md already contains the live crate map.
- Update CONTRIBUTING.md to reference docs/ARCHITECTURE.md for build
  ordering instead of the removed DEPENDENCY_GRAPH.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 01:12:21 -05:00
Hunter Bown 1af37e3fab Add DeepSeek-native bundled workflow skills 2026-05-13 00:53:44 -05:00
Hunter Bown ccfece77e3 Merge remote-tracking branch 'origin/pr/1534' into work/v0.8.34
# Conflicts:
#	crates/tui/src/commands/config.rs
#	crates/tui/src/commands/mod.rs
#	crates/tui/src/palette.rs
#	crates/tui/src/settings.rs
#	crates/tui/src/tui/app.rs
#	crates/tui/src/tui/color_compat.rs
#	crates/tui/src/tui/widgets/footer.rs
2026-05-12 23:58:39 -05:00
Hunter Bown 4766adf8e3 Merge remote-tracking branch 'origin/pr/702' into work/v0.8.34 2026-05-12 23:51:30 -05:00
Hunter Bown ca605d2ef5 Merge remote-tracking branch 'origin/pr/1011' into work/v0.8.34
# Conflicts:
#	docs/INSTALL.md
2026-05-12 23:44:04 -05:00
Hunter Bown a4637fe7d1 fix(settings): reduce motion in VTE flicker terminals
Harvested from PR #1527 by @axobase001.

Co-authored-by: axobase001 <dengzhuoran9@gmail.com>
2026-05-12 23:39:44 -05:00
Hunter Bown 485ba7bbd4 chore(release): finish v0.8.33 polish 2026-05-12 22:03:47 -05:00
Hunter Bown 99c6b22e83 chore(release): v0.8.33 — sub-agent and RLM renovation with persistent sessions
- Persistent RLM sessions (rlm_open/rlm_eval/rlm_close) with bounded REPL helpers
- Fork-aware sub-agent sessions (agent_open/agent_eval/agent_close) with handle_read
- Shared handle_read storage with slice/range/count/JSONPath projections
- Slash-command routing: /rlm, /agent, /relay (/接力) for handoff prompts
- Sidebar renamed to "Work" tab, consistent across Plan/Agent/YOLO modes
- Tool papercuts: file_search excludes, grep_files strings, fetch_url JSON,
  edit_file fuzz, exec_shell merged stdout/stderr, revert_turn no-op reject
- CLI reasoning-effort honoured on non-auto exec routes (#1511 @h3c-hexin)
- Edit-file replacement boundaries clarified (#1516)
- Pandoc output validated before probing (#1523)
- Running turns steerable/repaintable (#1533, #1537)
- Tasks/Activity Detail calmer under load
- npm retry timeout hint (#1538 @reidliu41)
- Issue templates improved (#1525 @reidliu41)
- Shell: kill process group to prevent UI freeze (#828 @CrepuscularIRIS)
- TUI: ignore leaked SGR mouse reports in composer (#1421 @reidliu41)
- Footer: keep chips within available width (#1417 @Wenjunyun123)
- Session picker: scope Ctrl+R to current workspace (#1395 @LinQ)
- Removed stale competitive-analysis doc
- Prompts/docs teach only new tool names
2026-05-12 19:54:08 -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 c8614a24fd fix(tui): enable Kitty keyboard protocol on Windows so Shift+Enter inserts newline
Closes #1359. On Windows 11 + VSCode integrated terminal +
PowerShell, pressing `Shift+Enter` in the composer submitted the
message instead of inserting a newline. `Alt+Enter` / `Ctrl+J`
were broken the same way. Root cause: crossterm's
`PushKeyboardEnhancementFlags` checks `is_ansi_code_supported()`
before emitting the escape, and on Windows that helper queries
the console mode rather than the VT capability and
unconditionally returns false — so the Kitty push `\x1b[>1u` was
never written. xterm.js then stayed in legacy mode where
`Shift+Enter` and `Enter` both encode as `\r`, indistinguishable.

The fix writes the push and pop escapes directly under
`#[cfg(windows)]`, bypassing the crossterm capability gate.
VSCode and Windows Terminal honour the Kitty keyboard protocol;
terminals that don't (older conhost without VT processing)
silently discard the unknown escapes. The same gate also meant
`PopKeyboardEnhancementFlags` was silently dropped on Windows in
the `main.rs` panic hook and in
`tui::external_editor::spawn_editor_for_input` — both call sites
now route through `pop_keyboard_enhancement_flags` so a crash or
`$EDITOR` invocation can't leave the parent shell with a
Kitty-enhanced keyboard state.

Two `#[cfg(windows)]` regression tests pin the direct-write path
so accidentally falling back to `execute!()` against
`crossterm::PushKeyboardEnhancementFlags` would now fail in CI:

- `push_keyboard_flags_writes_kitty_push_sequence_on_windows`
- `pop_keyboard_flags_writes_kitty_pop_sequence_on_windows`

Non-Windows behaviour is unchanged — the existing
`recover_terminal_modes_emits_expected_csi_sequences_with_gating`
test still passes on Linux and macOS.

Also adds a v0.8.29 audit note to `docs/KEYBINDINGS.md` and
documents a pre-existing FocusGained stack-depth bug for a
separate fix.

Harvested from PR #1483 by @CrepuscularIRIS

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 01:04:47 -05:00
Hunter Bown 8f33e4bd48 feat(providers): add AtlasCloud as a first-class provider
AtlasCloud (https://atlascloud.ai) hosts the V4 family on its own
DeepSeek-compatible endpoint at `https://api.atlascloud.ai/v1`, and
several contributors had been running it through the
OpenAI-compatible passthrough with manual `base_url` / model
overrides. Selecting `provider = "atlascloud"` in
`~/.deepseek/config.toml` (or via `DEEPSEEK_PROVIDER=atlascloud`)
now wires up:

- documented `DEFAULT_ATLASCLOUD_BASE_URL` /
  `DEFAULT_ATLASCLOUD_MODEL` defaults so a fresh install needs
  only the api_key
- a `[providers.atlascloud]` config block with the same fields
  every other named provider exposes (api_key / base_url / model
  / http_headers)
- `ATLASCLOUD_API_KEY` env var path, including the secrets test
  cleanup loop so per-test env hygiene continues to work
- the provider-picker / `/provider` slash command entries so the
  provider is reachable from the runtime UI, not just config
- the env-driven `*_BASE_URL` override branch so users who pin a
  proxy can still flip it without editing config.toml

Trust-boundary pins held: AtlasCloud is opt-in (default remains
DeepSeek), no API keys are hardcoded, the api_key resolution flows
through the same `secrets` crate path every other provider uses,
and the provider-config base_url stays settable per environment.

Resolved 3-way merge conflicts in `crates/secrets/src/lib.rs` (env
cleanup loop) and `crates/tui/src/config.rs` (per-provider
base_url match arm + `provider_passes_model_through` predicate)
so the contributor's AtlasCloud branch coexists with the v0.8.x
provider expansion already on `main`. Added the missing match arm
in `validate_provider_base_url` so the non-exhaustive-pattern
check passes after the new variant lands.

Harvested from PR #1436 by @lucaszhu-hue

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 00:40:43 -05:00
Hunter Bown 2e8322bb84 docs(release): cross-link CNB mirror runbook from RELEASE_RUNBOOK 2026-05-11 22:48:08 -05:00
Hunter Bown 90eaf04a84 ci(cnb): rewrite sync workflow with concurrency + scoped push + retry
Closes the persistent "fatal: could not read Username for 'https://cnb.cool'"
failure that bit about half of recent sync-cnb runs.

Root causes from the failure log of run 25705666413 (2026-05-12) and
25697452832 (2026-05-11):

  1. The previous tencentcom/git-sync Docker action discovered every
     local ref via fetch-depth: 0 and tried to push them all —
     including dependabot/* branches that GitHub had locally. Those
     follow-on pushes ran without the configured credential helper
     in scope and failed with the basic-auth prompt error above.

  2. No concurrency guard meant the back-to-back `main` push and
     `v*` tag push that auto-tag.yml fires within ~15s of each other
     raced. Two workflow runs would attempt to push to the same
     CNB remote simultaneously; one would lose.

Rewrite:

  * Hand-rolled `git push` with the CNB token URL-encoded inline so
    the credential is always in scope. No Docker action dependency.
  * `concurrency: group: cnb-sync, cancel-in-progress: false` so
    queued runs serialize cleanly rather than racing or dropping.
  * Only push the ref that triggered the run — `main` on branch
    push (with --force-with-lease for safety), the specific tag on
    tag push. Feature branches and dependabot refs no longer
    mirror.
  * 3-attempt retry with linear backoff (5s, 10s) for transient
    failures (CNB rate-limit, DNS blips, etc.).
  * `workflow_dispatch: {}` trigger so the maintainer can re-run
    against a specific ref manually if the automated run fails.

Adds docs/CNB_MIRROR.md with: the verification steps after a
release, the manual fallback procedure (one-time `git remote add cnb`,
then `git push cnb vX.Y.Z`), the token-rotation procedure, and a
note on why binary release assets aren't on CNB today.

Cross-links from docs/RELEASE_RUNBOOK.md so the verify-after-release
step doesn't get forgotten.
2026-05-11 22:47:54 -05:00
reidliu41 6d099d425c feat: add note management commands
Extend /note beyond append-only usage with list, show, edit, remove,
  clear, path, and explicit add subcommands.

  Keep existing /note <text> behavior compatible, preserve the existing
  --- separated file format, and number notes only at display time so the
  stored notes stay clean.

  Update command help, localization, docs, and tests.
2026-05-10 20:56:39 -05:00
reidliu41 4f8eff0c69 refactor: unify mode switching under /mode
Replace the separate /agent, /plan, and /yolo commands with a single
  /mode command that can either open a picker or switch directly by name
  or number.

  This keeps mode switching in one command surface and avoids duplicating
  similar commands for each mode.
2026-05-10 08:15:19 -05:00
Zhiping 39fd5379fd docs(tui): clarify Windows mouse capture behavior 2026-05-10 08:15:19 -05:00
Hunter Bown bf582cb0f9 chore(release): prepare v0.8.25
- Bump workspace to 0.8.25 (per-crate path-dep pins, Cargo.lock,
  npm/deepseek-tui/package.json all in sync; check-versions.sh green).
- Add v0.8.25 CHANGELOG entry covering markdown table wrap,
  reqwest-based self-update with SHA-256 verification, MCP framing
  centralization, terminal-mode recovery unification, recall_archive
  parent-registry exposure, ContextConfig.per_model removal, plus
  community PRs (#1300 Reid Liu, #1297 Duducoco, #1265 jinpengxuan,
  #1290 Reid Liu, #1246 heloanc, #1282 Wenjunyun123, #1274 Liu-Vince).
- Refresh README.md and README.zh-CN.md "What's New" sections.
- Prune stale docs: V0_7_5_IMPLEMENTATION_PLAN redirect stub,
  v0.8.8-coordinator-prompt, archived v0.8.10 handoff.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 20:50:06 -05:00
Hunter Bown 8e9957da5c chore(release): prepare v0.8.23
- Bump workspace version 0.8.22 → 0.8.23 across Cargo.toml, every per-crate
  path-dependency pin, npm/deepseek-tui/package.json (both `version` and
  `deepseekBinaryVersion`), and Cargo.lock.
- Add a 0.8.23 CHANGELOG entry covering the security hardening stack
  (sanitized child env, plan-mode tool surface, sub-agent approvals,
  symlink walks, runtime API auth, shell safety classification, MCP
  config path traversal), the macOS Keychain prompt fix, the #1244 MCP
  spawn error visibility + env passthrough work, the compact-thinking UX
  change, and a Known issues callout for mid-run MCP stderr.
- Backfill missing CHANGELOG entries for v0.8.21 (community-heavy
  release, contributors credited) and v0.8.22 (fetch_url redirect
  validation). The gap was unintentional, so contributor work is being
  reflected in-repo now.
- Add docs/RELEASE_CHECKLIST.md so future releases gate on the
  CHANGELOG/version/preflight steps explicitly.
2026-05-08 18:17:44 -05:00
Hunter Bown 360438f0c9 docs(docker): prefer writable named data volume
## Summary
- Prefer a writable named Docker volume for the container home data path.
- Document the non-root UID/GID ownership requirement for host bind mounts.
- Update README and Docker docs examples to avoid permission-denied first runs.

## Test plan
- git diff --check
- GitHub CI green: version drift, lint, ubuntu, macOS, Windows, npm wrapper smoke, GitGuardian
2026-05-08 10:22:22 -05:00
Liu-Vince 66a20ded2e docs(config): document additional environment variables
## Summary
- Document DEEPSEEK_STREAM_OPEN_TIMEOUT_SECS.
- Document DEEPSEEK_FORCE_HTTP1.
- Document DEEPSEEK_HOME and DEEPSEEK_AUTOMATIONS_DIR.

## Verification
- GitHub CI passed: lint, version drift, ubuntu/macos/windows tests, npm wrapper smoke, GitGuardian.
2026-05-08 09:01:03 -05:00
Hunter Bown ad31d2bcec docs(competitive-analysis): reflect LSP diagnostics implementation (#1171)
Update competitive analysis to reflect that LSP integration is now
implemented as automatic post-edit diagnostics injection, and adjust
the recommended implementation order accordingly.

Co-authored-by: Stephen Xu <wexu@expediagroup.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-08 02:47:35 -05:00
Hunter Bown 724af9494a fix(tui): keep interactive sessions in alternate screen (#1158) 2026-05-08 02:30:57 -05:00
Aqil Aziz de4ecee41c docs: fix memory skill link (#1096) 2026-05-08 02:21:11 -05:00
Friende 8f39aadf0b docs: fix help keybinding reference (#1095) 2026-05-08 02:20:40 -05:00
Hunter Bown f283e56bd1 fix(prompts): prioritize user language for reasoning (#1137) 2026-05-07 23:53:15 -05:00
Hunter Bown b31b93aaae v0.8.19: endpoint, release workflow, IME + viewport fixes (#1128)
* fix(config): keep DeepSeek beta endpoint for legacy cn alias

* fix(ci): filter download-artifact to deepseek* pattern

Prevents the release aggregation job from picking up non-binary
artifacts (e.g. Docker .dockerbuild cache layers) that cause the
checksum manifest to include spurious entries and the Release to
carry files it shouldn't.

* fix(tui): enable focus events to restore IME after app-switch

On macOS, switching away (Cmd+Tab) and back suspends the IME compositor.
Without focus-event handling, the TUI never signals readiness to the
terminal, so CJK input methods (Pinyin, Zhuyin, etc.) stop working.

- EnableFocusChange on startup so the terminal reports FocusGained/FocusLost
- Re-push KeyboardEnhancementFlags on FocusGained (some terminals reset
  the enhanced keyboard mode on focus-loss)
- DisableFocusChange on shutdown for clean terminal handoff

* chore: cargo fmt

* docs: add DataWhale and DeepSeek to acknowledgments

* docs: fix DeepSeek name etymology in acknowledgments

* fix(tui): recapture viewport on focus restore

* docs: thank DeepSeek and DataWhale bilingually
2026-05-07 23:05:39 -05:00
Hunter Bown ef808d893b docs(install): document rustup mirror fallback
Co-authored-by: nsight <wuyefeima@163.com>
2026-05-07 15:29:05 -05:00
Zhuoran Deng 451d66ab0a docs(sandbox): define windows helper contract 2026-05-07 15:28:10 -05:00
Hunter Bown 8f181c80f8 feat(release): publish supported Docker image 2026-05-07 15:16:23 -05:00
THINKER_ONLY 4aee8a15c6 fix(config): preserve OpenRouter custom endpoint models
When OpenRouter is pointed at a custom base_url, keep explicit model values verbatim instead of remapping DeepSeek aliases to OpenRouter catalog IDs.

Add config coverage for both the dispatcher config crate and the TUI config loader, while preserving existing provider alias behavior such as NVIDIA NIM.

Closes #857
2026-05-07 12:45:37 -05:00
Jefsky Wong 5c112b40bf fix(config): default deepseek-cn to official api.deepseek.com (#1084)
Sets the `deepseek-cn` provider preset's default `base_url` to the official host (`https://api.deepseek.com`) per [api-docs.deepseek.com](https://api-docs.deepseek.com/). Keeps recognizing `api.deepseeki.com` in URL heuristics and chat-client normalization so existing configs continue to work, and updates the `doctor` strict-tool-mode endpoint hint, docs, and examples accordingly.

Closes #1079. Thanks to @Jefsky for the fix.
2026-05-07 12:01:07 -05:00
Hunter Bown 39b2d528cd feat(tools): retrieve spilled tool outputs (#1054) 2026-05-07 06:56:20 -05:00
Hunter Bown 8c36c1c6be feat(subagents): fork parent context on demand (#1048) 2026-05-07 06:33:04 -05:00
Hunter Bown 628fb3c4a8 feat(tui): support custom background color (#1034) 2026-05-07 06:15:58 -05:00
axobase001 9327167e1d fix(engine): align stream idle timeout guard (#1012) 2026-05-07 05:42:24 -05:00
Hunter Bown f97604c3f0 fix(provider): enable OpenAI-compatible TUI runtime (#1017) 2026-05-07 05:32:15 -05:00
nsight 2c8f7e2afa Update docs/INSTALL.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-05-07 17:46:31 +08:00
nsight e439f3710b Update docs/INSTALL.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-05-07 17:46:21 +08:00
郭闯 6bc4239250 docs(install): document rsproxy rustup workaround
- Add rsproxy rustup mirror commands for mainland China Cargo installs
- Document the edition2024 failure caused by old Debian/Ubuntu Cargo packages
- Point users to rustup stable and ~/.cargo/bin/cargo verification
2026-05-07 17:37:37 +08:00
Hunter Bown c270ef81ef fix(tui): harden terminal resume and runtime context
Summary:
- Keep default auto alternate-screen mode inside the TUI so transcript scrolling stays app-owned unless users explicitly opt out.
- Queue terminal resume events when the engine channel is full, avoiding stranded paused terminal state after interactive tool cancellation or bursts.
- Scope crash-checkpoint recovery to the resolved launch workspace instead of the shell cwd.
- Add runtime deepseek_version to the prompt environment block so agents can distinguish installed runtime identity from a stale checkout.

Test plan:
- cargo test -p deepseek-tui --locked on a simulated merge with current main
- cargo fmt --all -- --check
- git diff --check
- Existing PR CI was green for lint, version drift, Linux/macOS/Windows tests, npm wrapper smoke, and GitGuardian.
2026-05-07 03:48:09 -05:00
Hunter Bown 4369410df7 fix(auth): show credential source table
## Summary
- show config, keyring, and env credential sources in deepseek auth status
- point env-only auth failures at auth status and auth set recovery commands
- document auth status and provider key precedence

## Test plan
- cargo test -p deepseek-tui-cli auth_ --locked
- cargo test -p deepseek-tui-cli --locked
- cargo test -p deepseek-tui env_only_auth_error_gets_recovery_hint --locked
- cargo test -p deepseek-config api_key --locked
- cargo test -p deepseek-config config_file_resolves_above_env_and_keyring --locked
- cargo test -p deepseek-config keyring_resolves_when_config_file_empty_even_if_env_is_set --locked
- cargo test -p deepseek-secrets --locked
- cargo fmt --all -- --check
- git diff --check
- cargo clippy -p deepseek-tui-cli -p deepseek-tui -p deepseek-secrets --all-targets --all-features --locked -- -D warnings

Closes #907
2026-05-07 02:55:55 -05:00
Hunter Bown cd75ef886a fix(release): make package-channel docs truthful
Closes #944\n\n## Summary\n- mark Docker/GHCR publishing as experimental while the package is not publicly readable\n- align installer and release docs with the live npm/Scoop state\n- keep package-channel verification explicit for release triage\n\n## Test plan\n- ruby -e 'require "yaml"; YAML.load_file(".github/workflows/release.yml"); puts "release.yml ok"'\n- cargo test -p deepseek-tui-cli update::tests::test_asset_matching_accepts_binary_assets_and_rejects_checksums --locked\n- cargo fmt --all -- --check\n- git diff --check origin/main...HEAD\n- CI: Version drift, Lint, Test (ubuntu-latest), Test (macos-latest), Test (windows-latest), npm wrapper smoke
2026-05-07 02:43:40 -05:00
Hunter Bown c7ed05a07c feat(api): default DeepSeek to beta endpoint
Closes #941.\n\nRefs #938, #939, #940.
2026-05-06 21:24:59 -05:00
Reid 78c415f40c feat(provider): add Ollama provider support (#921)
Source PR: #921 by @reidliu41.
Closes #908.

Local verification:
- cargo test --workspace --all-features ollama
- cargo fmt --all -- --check
- cargo build

Co-authored-by: reidliu41 <reid201711@gmail.com>
2026-05-06 20:16:46 -05:00
Hunter Bown afe99f2b64 feat(runtime): add optional API token guard (#916)
Integrates #856 as a focused runtime API security slice.

Default local behavior remains unchanged. `/v1/*` routes require a token only when `--auth-token` or `DEEPSEEK_RUNTIME_TOKEN` is set, and `/health` remains public for readiness checks.

Co-authored-by: Zhuoran Deng <dengzhuoran9@gmail.com>
2026-05-06 18:37:36 -05:00