- Track tool catalog as a static layer in prompt inspection
- Include tools in cache-warmup request with tool_choice=none
- Ensure tool schema changes are visible to base-static-prefix diagnostics
- Factor test_tool helper for cache-inspect test coverage
- Add env guard with process-global mutex for ALLOW_INSECURE_HTTP tests
- Document LAN vLLM HTTP example in README
- Add config test for reported LAN HTTP endpoint + model resolution
- Guard validate_base_url_security tests against env leak
- Test that edit_file accepts calls with fuzz omitted, fuzz=false, and fuzz=true
- Verify fuzz is excluded from schema required fields but present as optional boolean
- Add agent-mode catalog test confirming edit_file is loaded and fuzz-less calls execute
- Update existing required-fields assertions to check for exactly path/search/replace
- Add docs/PROVIDERS.md placeholder reference in README and CONFIGURATION.md
- Update provider lists to include moonshot, openrouter, novita
- Add MOONSHOT_API_KEY/KIMI_API_KEY env var docs
- Update default_text_model entries for all providers
- Change legacy deepseek-cn alias to deepseek
- Add CODEWHALE_PROVIDER as preferred env var name
The wlcopy_helper_succeeds_when_binary_returns_zero test used
`true` as a stand-in for wl-copy, but `true` exits immediately
without reading stdin. On Linux CI runners the process exits
before the parent can write to the pipe, producing EPIPE and
failing the is_ok() assertion.
Switch to `cat` which reads stdin until EOF (when the pipe is
closed) and then exits 0, faithfully modelling a successful
wl-copy invocation.
The static website/ HTML files were the original codewhale.net surface
before the Next.js app under web/ took over. They have not been deployed
in some time and are now mirrored in the new dedicated site repo
(Hmbown/codewhalesites) only as far as history matters.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the dense 85-line 'What Is It' section with a tight 15-line
version using a three-column table:
- Start with trust — the 'A' preamble
- Clear jurisdiction — Constitution with nine tiers of authority
- Recursive improvement — V4 helps write the harness, loop tightens
All three languages (EN, zh-CN, ja-JP) updated. Contributors preserved.
- Sync root and crate CHANGELOG.md for version drift check
- Add community contributor credits to [0.8.46] section
- Remove stray '...' file that broke Windows git checkout
- config/src/lib.rs: remove undefined has_api_key variable (#2062 conflict)
- ui.rs: clone receipt before move into set_receipt_text
- footer_ui.rs: convert &str to String for if/else type consistency
- rlm.rs: use ref bindings to avoid partial moves of stdout/stderr_preview
- file.rs: prefix unused fuzz variable
- update.rs: remove redundant borrows
- tests.rs: allow print_stderr on catalog metrics test function
All clippy warnings resolved. CI should go green.
Issue 1600 asks for full rename UX: set a custom title, remove it back
to `(unnamed)`. The set side already shipped as `deepseek thread
set-name <id> <name>`, but there was no inverse — users who wanted to
drop a no-longer-relevant title had to either edit the SQLite store by
hand or set a placeholder string.
Add `deepseek thread clear-name <id>`, mirroring the existing
`SetName` arm in `run_thread_command`: look up the thread, set
`name = None`, refresh `updated_at`, upsert. Printed confirmation is
`cleared name for <id>` so it stays distinguishable from the
`renamed` line emitted by `set-name`.
Snapshot help test and the parser-matrix test both gain the new
subcommand. No state-store changes: `upsert_thread` already accepts
`name: None` and `thread list` already prints `(unnamed)` when the
field is empty, so the round-trip is complete with this CLI-only
change.
Co-authored-by: Claude <noreply@anthropic.com>
portable-pty 0.8.1 depends on nix 0.25.1, which lacks loongarch64 in
its ioctl cfg blocks, causing a build failure on LoongArch64 Linux.
portable-pty 0.9.0 depends on nix ^0.28, which fully supports
loongarch64. The public API surface used by CodeWhale is unchanged.
Closes#1945
The `effective_max_output_tokens` heuristic defaults to 64K for any model
not in the known-context-window table. This is fine for DeepSeek's hosted
API (1M context) but causes immediate HTTP 400s on self-hosted providers
with tight `max-model-len`.
Example: vLLM serving Qwen3.6 with `--max-model-len 65536` rejects
requests because 64000 (output) + ~1500 (input) exceeds the limit by 1
token.
This change lets the operator set `DEEPSEEK_MAX_OUTPUT_TOKENS=16384` (or
whatever fits their deployment) to override the heuristic. The env var
takes precedence over the model-table lookup when set to a positive
integer; otherwise the existing behavior is preserved.
No new config struct field — env-only override keeps the public API
unchanged. Useful for embedded users (e.g. pinvou3) who need to control
output budget without forking the engine config schema.
Co-authored-by: hexin <he.xin@h3c.com>
* feat: session token breakdown in footer and /status
Add accumulated session token tracking with input / cache-hit / output
breakdown. Rebased from PR #1666 onto post-rebrand main (v0.8.45).
Changes:
- SessionState: new total_input_tokens, total_cache_hit_tokens,
total_cache_miss_tokens, total_output_tokens fields
- Turn outcome handler: accumulate per-turn token breakdown
- StatusItem::Tokens: new footer chip, enabled by default
- Footer chip: "12K in · 8.1K cch · 2.5K out" format
- /status: expanded with session input/cache/output rows
- /clear and /load: reset accumulated breakdown
* fix: address review feedback — current_session_id, cache guarding, DRY helper
- Restore app.current_session_id assignment accidentally dropped in
apply_loaded_session during rebase (P1: breaks startup-resume and
session-sync paths)
- Guard cache-hit/miss accumulation behind is_some() so providers
that omit cache telemetry don't inflate miss totals
- Extract SessionState::reset_token_breakdown() to avoid duplicating
the four-field reset in core/session/ui call sites
- Hide the "cch" segment from the footer token chip when no cache
data has been recorded
- Show "not reported" in /status session-cache row instead of
"0 hit / 0 miss" when no cache telemetry is available
Adds Metaso AI Search as a new SearchProvider option alongside Bing,
DuckDuckGo, Tavily, and Bocha.
Co-authored-by: Zhao Xiaohong <zhaoxiaohong@metasota.ai>
grep_files runs its directory walk and per-file regex synchronously inside
the async execute(). On a large tree this pins the runtime worker for
minutes, so the turn loop can't observe the cancel token and the stop
button stays unresponsive — the same failure file_search fixed in #2035.
Mirror that fix: move the blocking walk onto spawn_blocking, bounded by a
30s hard timeout with a biased select on the cancel token, via a
run_blocking_grep helper that parallels run_blocking_file_search. Output
and the existing per-file/per-line cancel checks are unchanged.
Co-authored-by: hexin <he.xin@h3c.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(paste): preserve Enter suppression window after non-char keys during paste
* chore(paste): add debug_assert for buffer precondition in deactivate_keep_window
Documents the invariant that buffer must be flushed before calling deactivate_keep_window. The assert fires in debug builds only, catching future misuse without masking upstream bugs.
When the workspace is the user's home directory, the project-scope
config file (~/.deepseek/config.toml) is also the global config file.
Skip the merge to avoid redundant processing and a misleading
"project-scope config key ignored" warning on every launch from ~.
Fixes the home-directory false-positive in the #417 deny-list
check: the deny-list correctly refuses dangerous keys at project
scope, but when cwd == $HOME the project file *is* the global file
so the warning is noise.
The formula downloaded deepseek-macos-arm64 (the deprecation shim) as the
main binary. After the rebranding, deepseek is just a wrapper that spawns
codewhale, but codewhale was never installed — causing "codewhale not
found on PATH" for every Homebrew user.
Now the formula downloads codewhale-* as the primary binary and installs
all four artifacts: codewhale, codewhale-tui, deepseek (legacy shim), and
deepseek-tui (legacy TUI shim).
Closes#2104
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
When running in a Feishu thread-enabled group (话题群), every bot
response — status messages, approval prompts, streaming progress,
turn results — was sent via the Lark SDK's `create` API which spawns
a new standalone topic. The user sees a cluttered group with orphan
topics for each intermediate bot message.
Root cause: `sendText()` only called `client.im.message.create()`
with a bare `chat_id`, never passing any reply context. The Feishu
`reply` API was completely unused.
Fix (two changes, one site each):
1. **lib.mjs — incomingIdentity()**: expose `parentId`, `rootId`,
`threadId` from the raw Feishu message event so callers can
determine thread context. (Not consumed directly yet, but
available for future use.)
2. **index.mjs**:
- `handleIncomingMessage()`: store the latest incoming
`messageId` as `replyToMessageId` in the per-chat thread store.
- `sendText()`: look up `replyToMessageId` from the thread store;
when present, call `client.im.message.reply()` instead of
`create()`. This keeps ALL bot responses nested under the
original user message inside the same topic.
No config changes needed. New chats automatically start using the
reply path; existing chats without a `replyToMessageId` in the store
fall back to the old `create` behaviour.
/ 修复飞书话题群中 bot 消息新建独立话题的问题。所有回复改为使用 reply API
/ 在原话题内嵌套回复,而非通过 create API 创建新话题。