- Move preset/model/archive controls from settings card to main menu
- Arrange 4 dropdowns in 2x2 grid with external icons
- Align steer and archive side by side
- Replace #showSettingsCard with #sendMenuCard for preset/model/archive updates
- Add #sendMenuCard after 'new' button action for consistency
- Update help card to reflect current menu layout (12 items)
- Clean up duplicate sessionlist entries in menuHelpText
- Add missing English dictionary entries
Wrap all user-facing chat text in src/channels with a host-side t()
translator (Chinese is the identity default, so untranslated text is
always sent verbatim in Chinese). English is selected via the host
plugin config `language: en` or the DSH_IM_LANGUAGE environment
variable, and the settings UI keeps following the DSH web locale.
- add src/channels/shared/i18n.mjs with setImHostLanguage/t() and a
Chinese-key -> English dictionary split by area (shared + channels)
- complete the English dictionary for every t() key in src/channels,
including the feishu channel (welcome/help, repair flow, interactive
cards, watch flow) and the shared command/approval/stream text
- wrap previously untranslated chat-facing strings in feishu bridge,
feishu runtime, editable-message-stream, harness-client,
connection-test and image-prompt
- dedupe dictionary entries that existed in multiple channel files and
canonicalize conflicting translations into the shared dictionaries
- extend the i18n unit test to decode string-literal escapes so keys
containing \n are checked correctly
- document the language switch in README.md, README.en.md and
CHANGELOG.md, and rebuild lib/index.js
Added English support for bot chat messages across all nine IM
channels and AI Office without changing any Chinese output.
Real agent turns invoke tools constantly; one 'Tool call X' message
per call flooded the chat with near-zero information. Tool frames now
only flush the pending interim explanation text; successful tool
results stay silent, and failures still push the tool name with the
error detail.
Resolve qq-bridge.mjs by keeping the inbound-file support (hasFiles,
files passthrough) and dropping the upstream stream session, which
this branch replaces with the discrete turn-feed notices.
Show what the agent is actually doing during a turn, the way Claude
Code does: interim explanation text, every Tool call, and the error
detail when a tool fails, each as its own pushed message before the
final markdown answer.
- HarnessReplyTracker.consume now returns every frame of a polling
batch in order (same-batch text frames collapse to the latest)
instead of dropping all but the last event, which silently ate
tool-call frames that shared a batch with their result
- tool frames carry callId; status frames carry the correlated
toolName and a flattened error text parsed from the tool/result
error payload (message, or name: code)
- the QQ bridge holds interim step text until the next tool call
(or the end of the turn) pushes it, emits 'Tool call <name>' per
call, emits 'Tool call <name>\nError: <reason>' for failures, and
skips re-sending interim text that already equals the final answer
Other channels keep their existing behaviour: the status frame still
reads '正在整理结果…' and they ignore the new optional fields.