Commit Graph

1881 Commits

Author SHA1 Message Date
Hunter B 717d728163 feat: survive system sleep mid-turn — detect the suspend gap and retry the request (#2990)
When the host sleeps while a model response is streaming, the connection
dies on wake with 'Stream read error: error decoding response body' and
the turn was lost. The engine now stamps every stream chunk with both
monotonic and wall-clock time; Instant pauses across a suspend while
SystemTime does not, so a >10s divergence on a stream error identifies a
sleep/wake cycle. In that case the partial output is discarded and the
identical request is re-issued (sharing the existing MAX_STREAM_RETRIES=3
budget) instead of failing the turn. Ordinary network flakes keep the
deliberate no-retry-after-content policy from #103.
2026-06-09 23:40:42 -07:00
Hunter B fad04a016f polish: finish the rebrand in agent-facing surfaces
- system prompt environment key deepseek_version -> codewhale_version
- drop legacy .deepseek/instructions.md from the Local Law prompt tier
  (the engine still reads it for back-compat)
- instructions-file truncation marker now states how many bytes were
  omitted so the model knows what it is missing
- CODEWHALE_CHANGELOG const + user-facing /change strings
- codewhale metrics doc headers
2026-06-09 23:36:32 -07:00
Hunter B 6dcdc19077 chore: drop unused deps (tracing-appender, zeroize, rustls in release), orphaned vendor lockfile and one-off verify_task.sh 2026-06-09 23:33:47 -07:00
Hunter B 44c13eb63f fix(release): check-versions validates the generated TUI changelog slice, not byte equality
The packaged changelog is now a recent-releases slice produced by
scripts/sync-changelog.sh (which gains a --check mode); also restore the
SECURITY.md contact line the version gate guards, and finish the stale
binary-name sweep (--bin codewhale examples, qa harness doc).
2026-06-09 23:32:40 -07:00
Hunter B b4edb4e1ef build: generate crates/tui/CHANGELOG.md as a 15-release slice instead of a full manual copy
The /change command embeds this file into every binary via include_str!;
it now carries only recent releases (regenerated by scripts/sync-changelog.sh,
wired into the release checklist). The explicit-version test derives its
fixture versions from the embedded slice instead of hardcoding old ones.
2026-06-09 23:22:00 -07:00
Hunter B bcaf655316 fix: bump npm wrapper version, add v0.8.56 compare link, resync TUI CHANGELOG 2026-06-09 22:35:50 -07:00
Hunter B 6a2ec32c00 fix: bump all internal crate dependency versions to 0.8.56 2026-06-09 22:30:27 -07:00
Hunter B 710b094c8a fix: sync crates/tui/CHANGELOG.md with workspace root for v0.8.56 test gate 2026-06-09 22:26:24 -07:00
Hunter B 44d5aa496d Revert " feat(tui): render hotbar in sidebar"
This reverts commit c90049dd31.
2026-06-09 22:04:14 -07:00
Hunter Bown 3c97ba0799 Merge PR #2945 from reidliu41: render hotbar panel in sidebar
Loads resolved hotbar slot bindings into app state and renders the Hotbar panel at the bottom of the sidebar (render layer only; key dispatch is a follow-up). Part of #2061, ref #2065.
2026-06-09 21:17:13 -07:00
Hunter Bown 40f9a8bf17 Merge PR #2947 from cyq1017: guide >5s shell work to background tasks
Prompt, exec_shell description, and background schema now direct work expected to take >5 seconds (builds, test suites, servers, polling, sleeps) to task_shell_start/background=true. Addresses #2939.
2026-06-09 21:17:00 -07:00
Hunter Bown 45a9bff750 Merge PR #2905 from cyq1017: name the allow_shell blocker in shell tool errors
Missing-shell-tool errors now state that allow_shell = false is the cause, with the existing /config remediation hint. Related #2657.
2026-06-09 21:16:47 -07:00
Hunter Bown f12863f826 Merge PR #2949 from LeoAlex0: decouple allow_shell from static system-prompt prefix
allow_shell now rides the per-turn <runtime_prompt> tag alongside mode/approval; message[0] stays byte-stable across shell toggles and mode switches, preserving the DeepSeek prefix cache. Removes the shell-guidance line-filtering machinery; adds a static Shell Policy reference section.
2026-06-09 21:08:23 -07:00
Hunter Bown f118dff940 Merge PR #2896 from gordonlu: localize status picker surface
Part of the i18n localization batch. Locale strings + MessageId wiring; no logic changes.
2026-06-09 20:09:38 -07:00
Hunter Bown f4ab469bd2 Merge PR #2891 from gordonlu: localize approval dialog surface across 7 locales
Part of the i18n localization batch. Locale strings + MessageId wiring; no logic changes.
2026-06-09 20:09:16 -07:00
Hunter Bown ddae5cfe36 Merge PR #2923 from hongchen1993: allow Volcengine provider in TUI dispatcher
Adds Volcengine to the TUI-supported provider gate and verifies Ark key forwarding.
2026-06-09 20:08:02 -07:00
Hunter Bown dbff899f16 Merge PR #2928 from hongchen1993: prefer dispatcher-provided API key over saved root key
When the CLI dispatcher forwards --api-key with DEEPSEEK_API_KEY_SOURCE=cli, that explicit override now wins over the saved root key for DeepSeek providers.
2026-06-09 20:07:59 -07:00
Hunter Bown 082ba162c3 Merge PR #2946 from h3c-hexin: update Bocha web search response handling
Correct /v1/web-search endpoint, parse webPages.value with legacy pages fallback, surface business error codes; unit tests added.
2026-06-09 20:06:58 -07:00
Hunter Bown 0475c33c1d Merge PR #2951 from LeoAlex0: explain visibility="internal" in Runtime Policy Reference
Clarifies that the runtime_prompt tag is internal instruction, not user input, and that modes should not be announced. Related #2922.
2026-06-09 20:06:46 -07:00
Hunter Bown 607ee1796d Merge PR #2920 from sximelon: write oversized pastes to .codewhale/pastes/
Moves large-paste files from the legacy .deepseek/pastes to .codewhale/pastes, tests updated. Fixes #2914.
2026-06-09 20:06:33 -07:00
Hunter Bown a9a91053fa Merge PR #2930 from idling11: Qwen 3.6 Plus resolution tests
Tests-only: cover qwen3.6-plus and qwen-3.6-plus alias resolution on OpenRouter. Related #2908.
2026-06-09 20:06:20 -07:00
Hunter Bown edadd1e6db Merge PR #2941 from idling11: sync task panel after background shell cancel
Event-driven task panel refresh on exec_shell_cancel/exec_shell_wait/task_cancel plus an immediate refresh after ShellJob actions, so the Tasks sidebar reflects cancellations without waiting for the periodic refresh. Addresses #2937.
2026-06-09 20:05:20 -07:00
Hunter Bown 0e3c4a3dd6 Merge PR #2898 from idling11: avoid PDF read hang via extract_text_by_pages
Fixes the pdf-extract full-document hang on certain xref tables/font encodings by using the per-page extraction path. Closes #2641.
2026-06-09 20:04:15 -07:00
Hunter Bown fb341a9460 Merge PR #2880 from HUQIANTAO: fix 9 bugs across tools, client, and commands
UTF-8 boundary panic in clean_pdf_text, SSE ContentBlockStop index, skills TOCTOU double-call, token-count truncation, strict 6-digit hex decode in from_api_tool_name, response-body read errors surfaced, context_lines clamp, u64→usize try_from in read_file, SiliconflowCn/Volcengine reasoning-content support.
2026-06-09 20:03:45 -07:00
zLeoAlex 88ce926525 fix(prompts): explain visibility="internal" attribute in Runtime Policy Reference
The <runtime_prompt> tag includes a visibility="internal" attribute that
was listed in the tag format but never explained.  Models sometimes
interpreted this as an instruction to announce or restate the current
mode to the user, leading to repetitive YOLO-mode confirmations before
every tool call (#2922).

Add a one-sentence explanation: the attribute marks this tag as a
runtime instruction for the model (not user input), and the model should
apply the referenced rules silently without announcing the mode.

Closes #2922
2026-06-10 01:48:48 +08:00
zLeoAlex 9206eb9d73 refactor(prompts): decouple allow_shell from static system-prompt prefix
Move allow_shell from message[0] (static system prompt) to the per-turn
<runtime_prompt> tag alongside mode and approval.  This preserves the
DeepSeek prefix cache across shell-access toggles and mode switches,
which previously forced YOLO entry/exit to rebuild the entire prompt.

Changes:
- Delete remove_shell_tool_guidance and 3 other dead functions (~60 lines)
- Remove allow_shell field from PromptSessionContext and StaticPromptCtx
- Remove shell_tools_available dead parameter from compose functions
- Add Shell Policy section to Runtime Policy Reference (static text)
- Extend <runtime_prompt> tag with allow_shell="true|false" attribute
- Update tests: omits→always_keeps, 83/83 prompts tests pass
- Drop dead compose_mode_prompt_with_approval_and_model

Net: message[0] bytes are now stable regardless of shell-access state.
Mode/approval/shell flags all use the same per-turn tag pattern.
2026-06-10 01:44:34 +08:00
cyq 9cf2a18c96 fix(tui): guide long shell work to background 2026-06-09 20:09:45 +08:00
hexin 9daad316b0 fix: update Bocha web search response handling 2026-06-09 19:12:53 +08:00
reidliu41 c90049dd31 feat(tui): render hotbar in sidebar
Render configured/default hotbar slots at the bottom of the sidebar.

  Load resolved hotbar bindings into app state, display them as compact sidebar rows, highlight active slots, and preserve unknown
  actions visibly. Keep narrow sidebar rows within the available width so slots do not wrap or disappear.

  Add focused sidebar hotbar render and layout tests.
2026-06-09 18:26:40 +08:00
Hanmiao Li a20fe2a0cd fix(tui): sync task panel state after background shell cancel (#2937)
Background shell task cancellation was unreliable because the Tasks
sidebar panel was not refreshed immediately after cancel actions.

Root cause:
- ShellJobAction::Cancel/CancelAll killed the process in ShellManager
  but did not trigger a task_panel refresh, leaving stale "running"
  entries until the next 2.5 s periodic poll.
- The tool-name refresh list at line 1734 missed exec_shell_cancel,
  exec_shell_wait, and task_cancel.

Fix:
- Add refresh_active_task_panel() call after ShellJobAction dispatch.
- Add exec_shell_cancel, exec_shell_wait, task_cancel to the
  immediate-refresh tool name list.

Tests:
- shell_manager_cancel_transitions_task_to_not_running
- task_panel_entry_roundtrips_status
2026-06-09 15:08:33 +08:00
Hunter B b6604b431a chore(release): add v0.8.55 compare link, sync tui CHANGELOG 2026-06-08 22:40:53 -07:00
Hanmiao Li f356802f9b fix: remove duplicate #[test] and restore lost test attribute 2026-06-09 11:59:16 +08:00
Hanmiao Li 68164524b1 feat(model): complete Qwen 3.6 Plus support with dedicated tests (#2908)
Qwen 3.6 Plus already had full catalog/resolver/picker support. Add
dedicated provider-hinted resolution tests to close the remaining gap.

- Add qwen3_6_plus_resolves_to_canonical_on_openrouter test
- Add qwen3_6_plus_alias_qwen_dash_resolves test
- Both verify /model qwen3.6-plus resolves to qwen/qwen3.6-plus on OpenRouter
2026-06-09 11:49:50 +08:00
hongchen1993 c84292235f feat(config): prefer dispatcher-provided API key over saved DeepSeek key when source is cli
When the CLI dispatcher launches the interactive TUI with an explicit
`--api-key` argument (e.g. for a DeepSeek-compatible subscription
endpoint), the environment variable `DEEPSEEK_API_KEY` carries the
intended key with `DEEPSEEK_API_KEY_SOURCE=cli`. Previously the
saved root `api_key` in config.toml always won over this env override
for the DeepSeek provider, blocking users from running:

    codewhale --provider deepseek \
      --api-key ark-... --base-url https://... --model auto

This change gives the dispatcher-supplied env key priority when the
source marker is `cli`, keeping full backward compatibility for
normal config-file or keyring paths, and also cleaning up a `***`
literal in an unrelated test.
2026-06-09 11:48:59 +08:00
hongchen1993 24b8912e82 fix(cli): allow Volcengine provider in TUI dispatcher 2026-06-09 10:38:48 +08:00
shenbowen 9c68305776 fix(tui): write oversized paste files to .codewhale/pastes/ 2026-06-09 09:58:37 +08:00
Claude a2ae9a1acf fix(codex): satisfy clippy/fmt gate and default to gpt-5.5 for Codex
Tightens the experimental OpenAI Codex (ChatGPT) provider so the v0.8.55
gate is green.

- clippy: collapse 5 nested if/if-let blocks flagged by
  clippy::collapsible_if into let-chains (oauth.rs env-override
  resolution, responses.rs SSE delta handling). cargo clippy --workspace
  --all-targets -- -D warnings is now clean.
- fmt: cargo fmt --all over the Codex/Together changes (the gate's
  --check was failing, incl. a mangled "| ApiProvider::Ollama").
- default model: Config::default_model() now resolves to the Codex
  default (gpt-5.5) for the Codex provider instead of leaking a DeepSeek
  default_text_model the Responses backend rejects. The carve-out sits
  after the explicit provider-scoped model block (so
  [providers.openai_codex] model still wins) and before the
  DeepSeek-validating path, which is unchanged. Adds a behavior test.

https://claude.ai/code/session_013cHWv5sR6XPnVWzfMP8uma
2026-06-09 00:03:42 +00:00
Hunter Bown 0f19c395d5 fix(codex): make the Responses provider work end-to-end + de-slop
Verified live against the ChatGPT Codex backend (real codex login):
`exec --model gpt-5.5` through the openai-codex provider returns a correct
completion. Fixes found while getting there:

- Route the non-streaming path too. create_message only dispatched chat
  completions; for OpenAI Codex it now drives the Responses stream and folds it
  into a MessageResponse (handle_responses_message), so `exec` and other
  non-streaming callers use the same wire path as the interactive stream.
- Present a non-browser User-Agent on the Codex path. The ChatGPT backend sits
  behind Cloudflare, which served a JS challenge (HTTP 403) to our browser-like
  "Mozilla/5.0 (compatible; codewhale/...)" UA. A codex_cli_rs UA passes.
- Always send `instructions` (Responses rejects empty instructions); fall back
  to a minimal system prompt.
- Map reasoning effort onto the Codex-allowed set (none/minimal/low/medium/
  high/xhigh); CodeWhale's "auto" has no equivalent and maps to medium.
- Send `Accept: text/event-stream`.

Antislop pass on the changeset:
- Inline the one-caller codex_access_token wrapper (config calls get_credentials
  directly) and drop the one-caller credentials_present helper; both presence
  checks now use auth_file_path().exists() consistently with the Kimi path.
- Remove dead stream-parser state (ToolCallState fields, unused response_id /
  current_item_type / output_text / thinking_text accumulators).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 16:40:58 -07:00
Hunter Bown b46f607d91 feat(providers): finish OpenAI Codex (ChatGPT OAuth) provider and cut v0.8.55
Completes the in-progress OpenAI Codex provider and bumps the workspace to
0.8.55. Builds on the committed Together AI provider + model catalog work.

OpenAI Codex (ChatGPT) provider — experimental:
- Wire the previously-dead OAuth module into credential resolution. The TUI
  config now resolves the access token via the Codex CLI login in
  ~/.codex/auth.json (env overrides OPENAI_CODEX_ACCESS_TOKEN/CODEX_ACCESS_TOKEN),
  refreshing expired tokens synchronously via the OpenAI token endpoint —
  mirroring the existing Kimi OAuth flow rather than introducing a new pattern.
- Send the ChatGPT backend's required headers from the Responses client
  (chatgpt-account-id, OpenAI-Beta: responses=experimental, originator) and
  stop duplicating the Authorization header already installed on the client.
- Fix the cli crate's non-exhaustive ProviderKind matches (compile blocker).

Consistency / de-slop pass (so the provider fits the whole app, not one path):
- has_api_key_for / active_provider_has_config_api_key now detect the Codex
  OAuth login on disk, the same way they detect Kimi OAuth — a `codex login`
  user is no longer reported as unauthenticated.
- Replace the bogus OPENAI_CODEX_API_KEY hint (which exists nowhere else) with
  the real OPENAI_CODEX_ACCESS_TOKEN/CODEX_ACCESS_TOKEN in the auth-error and
  picker surfaces.
- Drop dead state in the Responses stream parser (unused ToolCallState fields /
  imports); tool-call data is streamed live.
- Update docs/PROVIDERS.md, config.example.toml, and the provider-metadata wire
  test for the Responses wire format.

Release:
- Bump workspace + crates + npm package to 0.8.55; update CHANGELOG.md and
  crates/tui/CHANGELOG.md.

Note: the live Responses round-trip has not been exercised against the
production ChatGPT backend in this environment; the provider ships as preview.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 16:17:30 -07:00
Hunter Bown c13bc24805 feat(models): add Together AI provider and update model catalog for v0.8.55
- Add Together AI as a first-class provider (ProviderKind::Together)
  - Config block [providers.together], env TOGETHER_API_KEY/TOGETHER_BASE_URL/TOGETHER_MODEL
  - Default models: deepseek-ai/DeepSeek-V4-Pro, deepseek-ai/DeepSeek-V4-Flash
  - Base URL: https://api.together.xyz/v1
  - TUI ApiProvider::Together with picker, auth, and capability support
  - CLI auth list/status support

- Add model catalog entries:
  - Qwen 3.7 Max (qwen/qwen3.7-max on OpenRouter)
  - MiniMax 2.7 (minimax/minimax-2.7 on OpenRouter)
  - NVIDIA Nemotron 3 Ultra (nvidia/nemotron-3-ultra on OpenRouter)

- Update docs/PROVIDERS.md, docs/CONFIGURATION.md, config.example.toml
- Update check-provider-registry.py compatible surfaces
- Fix provider picker tests for new provider count

Closes #2906, #2907, #2910, #2912, #2913
2026-06-08 15:12:42 -07:00
cyq b721982bde fix(tui): name allow_shell blocker for shell tools 2026-06-08 23:56:25 +08:00
Hunter B 78ae354fa4 chore(release): merge v0.9.0-stewardship into v0.8.54
Includes Paulo's command parity and Gherkin E2E harnesses,
HUQIANTAO's concurrency/security fixes, LeoAlex0's runtime_prompt
slim, reidliu41's hotbar persistence, HarmonyOS scaffolding,
Whaleflow foundation crate, and all v0.9.0 stabilization work.
2026-06-08 06:54:09 -07:00
Hunter B edd28066e1 chore(release): v0.8.54 — benchmark harness runners, MiMo routing 2026-06-08 06:47:21 -07:00
gordonlu af46bef8d6 feat(i18n): localize status picker surface (7 MessageIds) 2026-06-08 15:31:03 +08:00
Hanmiao Li 1721393b97 fix(pdf): use extract_text_by_pages to avoid hang on full-PDF reads
`pdf_extract::extract_text` uses an internal codepath that can hang on
certain PDF cross-reference tables or font encodings. The per-page
`extract_text_by_pages` path does not trigger this hang and produces
identical output when joined.

When `pages` is not specified, route through `extract_text_by_pages`
and join all pages instead of calling `extract_text`.

Fixes #2641.
2026-06-08 15:27:14 +08:00
gordonlu a241654d79 fix: restore trailing spaces on English ApprovalField labels 2026-06-08 10:05:13 +08:00
gordonlu 7bdc9a8f96 feat(i18n): localize approval dialog surface across 7 locales 2026-06-08 09:34:58 +08:00
Hunter B f88528a5a3 test(subagent): de-flake touch_refreshes_stale_running_agent_heartbeat
The 1ms heartbeat timeout raced the synchronous touch()->cleanup()
gap on loaded CI runners (Windows scheduler can deschedule >1ms),
intermittently reaping the just-touched agent so cleanup() returned 1.
Widen the timeout to 50ms and the staleness sleep to 150ms to keep the
logic exercised without the timing race. Addresses CI flakiness under
the v0.9.0 stabilization gate (#2721).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 10:49:36 -07:00
greyfreedom 17dbed13c7 feat(execpolicy): wire permissions.toml ask-rules into runtime
Harvested from PR #2885 by @greyfreedom. Wires ask-rules into the
app-server and core ExecPolicyEngine (previously inert). Removes the
original PR's NeedsApproval arm that incorrectly allow-listed the
working directory as a network host.

Co-Authored-By: greyfreedom <11493871+greyfreedom@users.noreply.github.com>
2026-06-07 10:49:36 -07:00
Hunter B 4e3184eae9 fix(client): consume probe response body to return connection to pool
Harvested from PR #2884 by @ousamabenyounes. Drops the orphan
desktop tray.rs module (dead code, never wired) from that PR.

Co-Authored-By: Ben Younes <2910651+ousamabenyounes@users.noreply.github.com>
2026-06-07 10:49:36 -07:00