[pull] main from esengine:main#2
Open
pull[bot] wants to merge 1304 commits into
Open
Conversation
Co-authored-by: koge_yvone <wangwei@v-ma.com>
…#1674) The composer's "N queued" label called `t("composer.queueCount", { n })` but the i18n templates use `{count}` — variable mismatch left the placeholder un-interpolated, so the UI rendered the literal string `{count} 个排队` whenever a message was queued while busy. Co-authored-by: reasonix <reasonix@deepseek.com>
…copy button (#1661) Co-authored-by: wufengfan <wufengfan@wufengfandeMacBook-Air.local>
`loopEventToDashboard` was generating dashboard event ids as
`${assistantId}-${role}-${Date.now()}` for both tool_start and tool
events. Different role string and different timestamp → completely
different ids. The SSE bridge passes that id through as the segment
callId, and the dashboard reducer keys segments by it — so tool.result
never matched the segment created by tool.intent, segment.result
stayed undefined, and the card sat in `running` state forever
(its only "done" trigger is `result !== undefined`).
LoopEvent already carries a stable `callId` for this exact purpose
(see `src/loop/types.ts:40-41`: "UI uses this as the card id"). Use
it for both tool_start and tool so they share an id and the reducer
can pair them.
Regression-tested in `tests/loop-to-dashboard.test.ts`.
Co-authored-by: reasonix <reasonix@deepseek.com>
Co-authored-by: wufengfan <wufengfan@wufengfandeMacBook-Air.local>
…eme (#1664) Co-authored-by: wufengfan <wufengfan@wufengfandeMacBook-Air.local>
…history indicator (#1666) - Simplify themes from 7 to 5 (dark, light, midnight, deep-blue, high-contrast) - Add new deep-blue theme with #0153e5 brand color - Rename tokyo-night to midnight (remove geographic name) - Fix input text color to follow theme changes (add FG.body) - Add history mode indicator (↑ history) when viewing past inputs - Optimize bgInput color values for better contrast Closes #1665 Co-authored-by: Bernardxu123 <Bernardxu123@users.noreply.github.com>
#1666 renamed/dropped themes (tokyo-night → midnight, removed default/github-dark/github-light, added deep-blue) but missed three surfaces: - `/theme` slash command's `argsHint` and `argCompleter` still advertised the removed names and were missing `midnight` / `deep-blue` - i18n `themeCaption` dicts in EN.ts and zh-CN.ts still held the removed entries and had no labels for the new themes, so the picker would render the literal i18n key (e.g. `wizard.themeCaption.midnight`) next to the new theme names Drop the stale entries from both locales, add captions for `midnight` and `deep-blue`, and trim the slash command lists to the actual theme set. The "default" caption is gone because the theme itself was removed. Co-authored-by: reasonix <reasonix@deepseek.com>
…to-restore on startup (#1667) Co-authored-by: wufengfan <wufengfan@wufengfandeMacBook-Air.local>
…up) (#1680) #1667 added totalCompletionTokens to SessionMeta and wrote it after every turn via patchSessionMeta, but the carryover plumbing in SessionStats was incomplete: - seedCarryover didn't read meta.totalCompletionTokens - SessionStats had no _carryoverCompletion field - the write call summed only this.turns (no carryover), and trimOldTurns dropped completion tokens into the void Net effect: on every resume, the first turn's patchSessionMeta call overwrote the previously-saved totalCompletionTokens with just the new turn's tally — counter reset to ~0 across restarts. (Cost / cache hit / miss don't have this problem because they each have proper carryover plumbing.) Currently zero user-visible impact since no UI reads the field yet, but the data was already flowing through UsageStats in both dashboard and desktop, so the next surface that exposes it would inherit the bug. Fix mirrors the cacheHit/Miss pattern: new _carryoverCompletion field seeded from meta, a cumulativeCompletionTokens getter, trimOldTurns folds completion tokens into carryover like the other counters, and loop.ts switches the write to use the new getter. Co-authored-by: reasonix <reasonix@deepseek.com>
…1681) `ToolRegistry.setPlanMode(true)` (src/tools.ts:86) already blocks every non-readonly tool at dispatch — but the only path that ever turned it on was the `/plan` slash command. Persisted `editMode = "plan"` (set via config edit or a settings UI that surfaces it) was previously inert: the registry's `_planMode` stayed false across boots, so the model could still call `write_file` etc. Extend `EditMode` to include "plan", and have `buildCodeToolset` mirror the loaded mode into the registry on construction. Desktop host calls the new `applyPlanMode` helper in three places: on `emitSettings`, on every `buildRuntimeFor`, and inside the `settings_save` handler when the user toggles edit mode — so live changes take effect without a rebuild. CLI's `/plan` slash continues to work as the direct toggle. This is the minimal foundation needed before a settings UI in desktop or dashboard can offer "plan" as a 4th edit-mode option. Co-authored-by: reasonix <reasonix@deepseek.com> Co-authored-by: T1anjiu <84212214+T1anjiu@users.noreply.github.com>
…#1685) Two related papercuts in the desktop client: 1. Esc during streaming with a modal (settings / about / jobs popover / workdir popover) open used to fire `abort()` and leave the modal sitting on screen. Now the global Esc handler bails out when any of those flags is set; settings/about modals each install their own `keydown` listener that calls `onClose()`. JobsPop and WorkdirPop already had their own handlers, so this just rounds out the set. 2. Clicking (or Enter-ing) the already-active session in the sidebar used to round-trip a session_load and clear live in-turn state (issue #1653). Skip when `s.name === activeName`. Co-authored-by: reasonix <reasonix@deepseek.com> Co-authored-by: CVEngineer <129239603+CVEngineer66@users.noreply.github.com>
…1675) overflow-wrap is an inherited property; .msg-text already declares it, so the duplicate declarations on .msg-text .markdown and .msg-text p are noise. The combined `.msg-text X, .markdown X` selectors keep their declarations because the standalone .markdown case (cards) has no ancestor setting overflow-wrap. Co-authored-by: reasonix <reasonix@deepseek.com>
#1661 fixed the lang-detection bug for desktop only. Dashboard's pre handler has the same `c.type === "code"` check that fails when react-markdown's component override replaces `code` — the element's type is the override function, not the string "code". For dashboard this didn't just mislabel the language; the fallback returned a vanilla `<pre>` and skipped CodeBlock entirely, so syntax highlighting and the copy button were missing for every fenced code block. Extracted the lang lookup into `extractFencedLang` in both files so it can be unit-tested without rendering CodeView (prism-react-renderer pulls in each package's own React copy under vitest, which breaks full-render tests across desktop/dashboard). Co-authored-by: reasonix <reasonix@deepseek.com>
#1686) Two bugs in the same `Cell` body (#1671): - truncation used `raw.length > inner`, which undercounts wide chars — a CJK row that was visually too wide for the column slipped past the check and overflowed into the gutter - padding used `padEnd(inner)`, which counts string length not cells — short CJK content got padded as if each wide char were 1 cell, so the background-color stripe ran past the column edge Repo already has a cell-aware clipper (`clipToCells`) for the cut and a private `padToCells` in `markdown.tsx` for the pad. Promote `padToCells` to `text-width.ts` so SplitDiff can use both — collapses the original four lines (slice + ternary + padEnd + ascii comment) to a single `padToCells(clipToCells(raw, inner), inner)` and drops the duplicate definition from `markdown.tsx`. Supersedes #1683, which fixed the detection half but left the slice + padEnd in place — for CJK content the truncated string ended up wider than `inner` and short rows still over-padded. Co-authored-by: reasonix <reasonix@deepseek.com> Co-authored-by: Bernardxu123 <Bernardxu123@users.noreply.github.com>
…el width (#1688) Co-authored-by: wufengfan <wufengfan@wufengfandeMacBook-Air.local>
…moved, persisted usage stats, plan dispatch gate Headline themes: - Desktop: bundle the CLI-hosted React dashboard, retire Tauri+Preact duplicate (#1418) - Config: drop preset abstraction; flash/pro are direct model selections (#1657, #1630) - Stats: persist cumulative usage to session meta + auto-restore on startup (#1667, #1680, #1643, #1628) - Plans: editMode="plan" enforced at the ToolRegistry dispatch gate (#1681); step advance fix (#1629) - Context: fold once at turn start, drop pre-flight + byte-ceiling (#1642, #1646); collapsible compacted card (#1649) - Subagents: per-skill flash/pro override + Settings UI (#1632) - Desktop polish: sidebar drag-resize (#1688), responsive collapse (#1585), copy/edit overlay + msg-history nav (#1645), Esc closes modal not turn (#1685), QQ tab isolation (#1672), DiffCard for edits (#1662), theme-aware highlighting (#1655), system events toggle (#1654/#1650), macOS TCC inheritance (#1614), dashboard.enabled (#1612) - Dashboard polish: persistent session URL (#1586, #1589, #1599), theme-aware highlighting (#1664), IME confirm-enter guard (#1689), code-fence lang fix (#1677), vendor chunk split (#1587), markdown table h-scroll (#1562) - TUI: Alt+S input stash/recall; static history isolated from input rerenders (#1635); legacy mouse drop (#1637, #1648); multi-edit gated in review (#1647) - Diff: SplitDiff column border holds under CJK (#1686) - MCP: workspace roots passed to servers (#1625); codeCommand honors mcpServers (#1603) - Config plumbing: (baseUrl, apiKey) resolved as a tuple (#1658); stale model id self-heal (#1663) See CHANGELOG for the full list.
…tests find dist/ Dashboard smoke tests added in #1418 read `dashboard/dist/app.js` and `app.css` at filesystem level. They pass under `npm run verify` (which builds first) but fail under `npm publish`, whose `prepublishOnly` ran in `lint → typecheck → test → build` order — tests fire before the artifacts they need exist. Reorder to `lint → typecheck → build → test` so the publish-time gate matches the verify-time gate. Caught when the v0.50.0 publish-npm.yml run failed before reaching `npm publish`.
#1584 wired `npm --prefix dashboard ci && npm --prefix desktop ci` into root `postinstall` to fix CI's missing workspace deps. But the published tarball ships only build artifacts under `dashboard/` (index.html, app.css, dist/) and no `desktop/` at all, so end-user `npx reasonix@0.50.0 code` failed during the dashboard `npm ci` and the bin never ran — the only visible output was npm's cleanup warnings on the half-extracted tree. Move the workspace install into `scripts/postinstall.mjs`, which exits 0 when `dashboard/package.json` is absent (i.e. when running from the tarball, not the repo). Ship the script via `files:`. Deprecate 0.50.0 on npm so existing installers see the warning.
Node 18+ refuses to execFile `npm.cmd` directly on Windows (CVE-2024-27980 mitigation), throwing `spawnSync npm.cmd EINVAL`. Failed every Windows CI matrix entry on main after 0.50.1. `execSync` routes through cmd.exe / sh, matching what the original inline `&&`-chained postinstall did before #1584's regression. End-user installs of reasonix@0.50.1 are unaffected: postinstall short-circuits via the `dashboard/package.json` existence check before reaching the broken execFile call. Only repo checkouts at tag v0.50.1 hit the bug, which is dev-side only.
…ant turn (#1691) Co-authored-by: wufengfan <wufengfan@wufengfandeMacBook-Air.local>
…ix hash evidence | 缓存诊断 v1 (#2188) * feat(cache): add prompt cache diagnostics * fix(cache): hash sent tool snapshot in diagnostics * perf(cache): memoize prefix diagnostic hashes
…t fixes (#2221) * fix(theme): meet WCAG AA contrast for fg.faint and fg.meta across all themes fg.faint failed WCAG on all 4 dark themes (ratios 1.63-2.56:1, need 4.5:1). fg.meta failed on midnight (2.35-2.91:1) and was borderline on others. Dark theme bgElev (#151d2f) was too close to bgInput for surface distinction. Changes per theme: - dark: meta #778294→#9aa5b5, faint #4d5666→#8791a3, bgElev #151d2f→#1c2844 - light: meta #6b7280→#5c6371, faint #9ca3af→#666d7b - midnight: meta #565f89→#9da5bb, faint #414868→#8a92a8 - deep-blue: meta #808080→#909090, faint #606060→#8c8c8c - high-contrast: already passes, no changes * fix(ui): replace dim with explicit colors in ReasoningCard and ToolCard - ReasoningCard: replace `dim` prop with explicit `FG.sub` color - ToolCard: replace conditional `dim` with explicit `FG.faint`/`errColor` Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(ui): replace all remaining ANSI dim with explicit FG.faint colors Replace every remaining `dim` prop across 22 UI components with explicit `color={FG.faint}` (or conditional color logic where dim was used as a boolean toggle). The ANSI `dim` attribute (SGR 2) halves brightness of the foreground color, causing near-invisible text on dark terminals where the default foreground is already low-contrast. Components fixed: - mcp-browse, AtMentionSuggestions, DiffApp, EditConfirm - McpBrowser, McpHub, McpMarketplace - PlanReviseConfirm, PlanStepList - RecordView, ReplayApp, Select, Setup - SlashArgPicker, SlashSuggestions, SplitDiff - StatsPanel, Wizard, char-bar, ctx-breakdown - markdown-view (SpanText ambientDim), primitives (Bar, ContextCell) For conditional dim (e.g. `dim={isDone}`), replaced with conditional color logic (`color={isDone ? FG.faint : originalColor}`). The Bar component's `dim` prop was removed entirely — callers now pass the appropriate color directly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: HUQIANTAO <HUQIANTAO@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…on memory (#2219) * fix(server): convert sync fs I/O to async across server API layer and session memory Replace blocking readFileSync/writeFileSync/readdirSync/statSync/existsSync with non-blocking readFile/writeFile/readdir/stat from node:fs/promises in all server API handlers and session.ts. This prevents the event loop from blocking on disk I/O during concurrent HTTP requests. - assets.ts: async cached reads (resolveAssetDir stays sync for module load) - skills.ts, memory.ts, hooks.ts, browse.ts, project-tree.ts, files.ts, checkpoint-diffs.ts, health.ts, sessions.ts: async handlers - session.ts: added async variants (listSessionsAsync, deleteSessionAsync, loadSessionMessagesAsync, readTailMessagesAsync, etc.) - atomic-write.ts: added async atomicWrite alongside sync atomicWriteSync - index.ts: await renderIndexHtml/serveAsset in dispatch Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * style: fix biome formatting and lint errors - files.ts: add explicit Stats type annotation (noImplicitAnyLet) - browse.ts: organize imports - assets.ts, skills.ts, memory.ts, sessions.ts, session.ts, atomic-write.ts: biome format (line length, trailing commas) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(test): await async serveAsset/renderIndexHtml in dashboard smoke tests These functions now return Promises after the sync→async conversion, so the test calls must await them. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * style: remove banner separator comments in session.ts Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: eliminate TOCTOU race in memory file read Read the file directly instead of stat-then-read to avoid a window where the file could be deleted between the two calls. CodeQL flagged this as a potential file system race condition. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: HUQIANTAO <HUQIANTAO@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* feat(prompt): prefer MCP search tools over built-in defaults Add a `# Tool Selection` section to the default system prompt that instructs the model to prefer MCP-provided tools (e.g. Exa) over the built-in web_search/web_fetch. MCP tools typically offer higher quality — semantic search over keyword matching, date and domain filtering. The instruction includes a fallback to built-in tools when MCP tools are unavailable. This is a low-risk change: one paragraph of prompt text, no runtime overhead, and fully backward-compatible. * feat(prompt): prefer MCP search tools over built-in defaults * revert: cli/index.ts back to upstream original * feat(prompt): add MCP tool selection guidance to code system prompt
* fix(ink): add dependency arrays to useBoxMetrics and useTerminalViewport to prevent scroll jitter (#2076) - useBoxMetrics: add [ref.current] deps so measurement only runs when element changes - useTerminalViewport: add [elementRef.current, terminalSize] deps to skip expensive parent-chain walk on every render - App: memoize TerminalSizeContext.Provider value to keep reference stable During rapid mouse wheel scrolling (10-20 events/100ms on Windows), the missing dependency arrays caused each wheel event to trigger 3-5 cascading renders (30-80 renders/100ms), producing visible text jitter. * fix(ink): address PR #2095 review — remove ref.current anti-pattern from hook deps - useBoxMetrics: remove [ref.current] dep array (React anti-pattern); add 16ms throttle to limit measurement frequency during rapid scrolling - useTerminalViewport: remove elementRef.current from deps, keep only [terminalSize] as the reactive dependency - Add regression test verifying useBoxMetrics re-measures on parent resize
…urn callback (#2056 hotfix) (#2073) * feat(desktop): collapse intermediate reasoning + group consecutive tool calls * fix: open tool cards inside group when expanded * fix: independent collapse state per tool group * fix: lift ToolGroupShell to module scope, preserve shell live-streaming, rename defaultOpen prop * perf(desktop): replace messages.map with backwards-walk index replace in streaming handlers * perf(desktop): reduce transcript window 120->60 to halve rendered message nodes * perf(desktop): virtual list with Virtuoso for message thread — only render visible messages * Revert "perf(desktop): reduce transcript window 120->60 to halve rendered message nodes" This reverts commit 6d90d65. * perf(core): windowed AppendOnlyLog (200 msg) with lazy file fallback; add readTailMessages for backward JSONL scan * style: fix biome formatting + comment cleanup * fix: use fstatSync after openSync to avoid TOCTOU race (CodeQL) * fix: sort import order (biome) * fix: remove existsSync before openSync (TOCTOU race, CodeQL) * fix: toMessages() returns window only, add toFullHistory(); restore length to entries.length; update callers * style: method chain formatting * fix: add toFullHistory mock to ctx-breakdown test * fix: replace useAutoScroll with Virtuoso followOutput + scrollToIndex for scroll handling * fix: proper Virtuoso height via CSS height:0 + flex; move jump button outside thread; use position:fixed instead of sticky * Revert "fix: proper Virtuoso height via CSS height:0 + flex; move jump button outside thread; use position:fixed instead of sticky" This reverts commit c061398. * Revert "fix: replace useAutoScroll with Virtuoso followOutput + scrollToIndex for scroll handling" This reverts commit ffd48d6. * fix: replace useAutoScroll with Virtuoso followOutput + scrollToIndex; fix JumpBar onScrollToTurn callback * fix: initial scroll to bottom on session load with proper dep * fix: position absolute Virtuoso inside relative thread to fix height calc in flex layout * fix: move jump button outside .thread for correct positioning * fix: add minHeight 0 to Virtuoso; set thread height 100% * fix: use Virtuoso initialTopMostItemIndex + scrollerRef for scroll-to-bottom and persistence * fix: add key to Virtuoso assistant item for correct DiffStats re-render * fix: initialTopMostItemIndex for Virtuoso initial scroll to bottom * restore to upstream/main with single initialTopMostItemIndex fix * fix(jumpbar): onScrollToTurn callback uses Virtuoso scrollToIndex instead of querySelector (broken with virtual list) * fix: replace Virtuoso followOutput with atBottomRef + scrollToIndex for reliable streaming auto-scroll * Revert "fix: replace Virtuoso followOutput with atBottomRef + scrollToIndex for reliable streaming auto-scroll" This reverts commit 6060719. * fix: move error/warning render + pending-approval Footer back inside Virtuoso * Revert "fix: move error/warning render + pending-approval Footer back inside Virtuoso" This reverts commit a2477d7. * sync hotfix --------- Co-authored-by: wufengfan <wufengfan@wufengfandeMacBook-Air.local>
## What Add abortTurn(tab) in the plan_response cancel handler. ## Why When the user cancels a plan, the agent loop continues running. The model receives the cancellation signal via pauseGate but the in-progress turn is not aborted, causing the model to re-submit the plan or continue generating output that the user already rejected. ## How to verify 1. Start a session with plan mode enabled 2. Let the model submit a plan via submit_plan 3. Click Cancel in the plan approval 4. Confirm the agent loop stops immediately — no further streaming or tool calls from the rejected turn
… (#2228) When REASONIX.md or a global memory file is edited between sessions, the system prompt is rebuilt on next launch and the resumed session gets a full cache miss with no explanation. This adds a one-time warning on resume when the system prompt fingerprint differs from what was saved. - session.ts: add hashSystemPrompt(); add systemFingerprint to SessionMeta - App.tsx: save fingerprint on every turn; compare on resume and warn - i18n/types.ts + EN + zh-CN: systemPromptChanged + systemPromptChangedDetail
#2215) (#2229) By default api.deepseek.com is in NO_PROXY so clash/v2ray users avoid 403s from shared exit IPs. Corporate users whose firewall blocks direct egress get a silent 'fetch failed' with no guidance. Add a stderr hint when api.deepseek.com is bypassed, pointing users to REASONIX_PROXY_DEEPSEEK_DIRECT=0 or bypassDeepSeekDirect:false in config.
…lls compat (#2214) (#2230) Skills following the Anthropic Skills spec ship a references/ subdirectory with depth material. Reasonix only loaded SKILL.md, leaving [[references/...]] wikilinks as dead text and making the depth content invisible to the model. Append each references/*.md file to the skill body at load time under a '## Reference: <slug>' header (sorted alphabetically). This follows Option A from the issue: zero protocol overhead, all depth material available immediately. Only dir-layout skills (those with a SKILL.md) can have a sibling references/; flat <name>.md skills are unaffected.
…dmin) (#2239) The two symlinked-skill tests added in #2137 — "loads skills from symlinked directories (#2104)" and "skips broken symlinks gracefully" — call symlinkSync with no Windows guard, so `npm run verify` fails with EPERM for contributors on Windows that lack Developer Mode / admin. CI's Windows runner has the privilege so it slipped through. Add `.skipIf(process.platform === "win32")`, matching the #2124 symlink tests already in this file. Co-authored-by: yhh <yhh@yhhdeMac-mini.local>
…#2233) Claude Code .mcp.json files commonly use ${TOKEN_NAME} or ${env:TOKEN_NAME} in header values (e.g. Authorization: Bearer ${API_KEY}). Reasonix was passing these through as literal strings, making migration from Claude Code require manual header editing. Add expandEnvInRecord() which resolves ${VAR} and ${env:VAR} patterns in header records at normalization time. Unset variables are left as-is.
…2235) The scroll-follow useEffect had no dependency array, so it ran on every render but did not check atBottomRef — meaning it would try to re-pin even when the user had scrolled up to read earlier content, and conversely the missing dep array caused React to skip the effect in some batched renders during fast streaming. Add a guard on atBottomRef.current and a proper [messageItems] dependency so the effect only fires when new messages arrive and only scrolls when the user is already pinned to the bottom.
…ect (#2059) (#2091) Adds a top-level `shellAllowedGlobal` config list, auto-approved across ALL projects and merged (union) with the per-project allowlist when deciding whether a shell command needs approval. Manage it via a `--global` (or `-g`) flag on the existing `/permissions` subcommands: /permissions add --global <prefix> /permissions remove --global <prefix-or-N> /permissions clear --global confirm /permissions list # now shows a Global section above Project The flag is parsed as a flag (not a positional keyword), so command prefixes like `g` or `global` remain manageable from the slash UI. `shellAllowedGlobal` is registered in `STRING_ARRAY_FIELDS` so a malformed hand-edited value is sanitized on read instead of crashing the merge in `code/setup.ts`'s `extraAllowed` getter. Config accessors (load/add/remove/clearGlobalShellAllowed) mirror the project ones; EN/zh-CN/ja/de strings added (ru falls back to EN).
* feat(weixin): add trusted iLink channel * fix(weixin): constrain ilink endpoint
The theme system defines SURFACE.bg and SURFACE.bgInput but no component applied them — the entire UI rendered on the terminal's default background, causing: - Input text invisible when terminal bg differs from theme - No visual separation between card stream and input area - Theme surface colors completely unused Add backgroundColor to three layout containers: - App root Box → SURFACE.bg (app canvas) - ComposerArea wrapper → SURFACE.bgInput (input dock) - PromptInput bordered Box → SURFACE.bgInput (input field) Co-authored-by: HUQIANTAO <HUQIANTAO@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
## What New unified \`PlanPanel\` right-side component replacing the modal-overlay pattern. Covers five plan states: pending / refining / executing / checkpoint / revising. Layout changes: - App.tsx: side-by-side flex layout — left conversation column at 35% width, right PlanPanel at flexGrow=1 when plan is active - LiveActivityArea: new \`suppressPlanLiveRow\` prop avoids duplicate plan card - Refine flow: inline plan body display + text input instead of separate modal ## Why The current modal-overlay pattern replaces the composer area with plan modals, hiding the conversation. A persistent right panel keeps the conversation visible while showing plan detail, and the inline refine flow lets users reference the plan body while typing feedback instead of switching to a blank text input. ## How to verify 1. Start plan mode, let model submit a plan — panel opens on right 2. Click refine — plan body stays visible, input appears below 3. Click approve — panel persists showing step progress 4. Complete all steps — panel auto-closes 5. Confirm conversation still scrollable, composer accessible at bottom-left
Co-authored-by: Tulga Battogtokh <b.tulga@ondo.mn>
…2238) (#2243) Users who want a fresh session each time (e.g. agents calling reasonix in loops) had to manually pass --no-session every invocation. Add: - config.autoResumeSession (default true = existing behaviour) - /session-persist on|off slash command to toggle and persist the setting - resolveSession() respects the new flag: when false, skips the 'default' session fallback so each launch starts with a new timestamped session
* fix(desktop): persist prompt history across sessions * fix(desktop): use session logs for prompt history
…#2248) 侧边栏拖拽最小宽度从 160px 调整为 200px,防止拖拽时「新建会话」文字被隐藏(CSS 在 ≤190px 时隐藏文字)。 Increase sidebar minimum drag width from 160px to 200px to prevent the "New Chat" text from being hidden when dragging (CSS hides text at ≤190px container width). Closes #2166 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
Bing 搜索缺少 AbortSignal.timeout(),响应慢或被墙时请求会无限挂起, 导致 web search 工具卡死在 research 步骤。添加 15 秒超时并与外层 signal 组合。 fix(web): add 15s timeout to searchBing to prevent infinite hangs Bing search lacked AbortSignal.timeout(), causing infinite hangs on slow responses or blocked connections. This left the web search tool stuck in the research step. Add a 15s timeout combined with the outer signal. Closes #2241 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…2259) #2252 added a 15s AbortSignal.timeout to searchBing; the other engines (Searxng, Metaso, Baidu, Tavily, Perplexity, Exa, Ollama, Brave) still relied on opts.signal only and could hang indefinitely. Extract searchSignal() helper that combines the caller's abort signal with a per-request SEARCH_TIMEOUT_MS cap, and apply it uniformly.
…en keyframes (#2267) - Fix undefined @Keyframes 'caret' → 'stream-caret' (shell running caret was broken) - Fix undefined @Keyframes 'fade' → 'fade-in' (about modal mask was broken) - Remove shimmer animation from 'Running' label and ThinkingPill text (double animation with dots) - Remove pulse-soft breathing from PendingUserMsg background - Remove yolo-pulse breathing from YOLO mode border - Unify duplicate @Keyframes shimmer-bg into shim - Remove dead keyframes: pulse-soft, yolo-pulse - Wire tab status dots to actual busy/idle state (was hardcoded to 'running') Co-authored-by: HUQIANTAO <HUQIANTAO@users.noreply.github.com>
* feat(cache): add cache efficiency guardrails * fix(cache): hash sent tool snapshot for diagnostics
…ocale-independent (#2320) Follow-up polish to the cache-efficiency guardrails (#2314): - /status "cache detail" line was hard-coded English; route it through i18n (statusCacheDetail / statusCacheChurn) so it matches every other status row. EN + zh-CN translated; ja/de/ru inherit EN like the rest of their observability block. - sortToolSpecs used localeCompare, which is locale-sensitive and could let the host locale reshuffle the serialized tool prefix and reintroduce the very cache churn the sort is meant to prevent. Switch to a stable codepoint compare. No change for ASCII tool names (all existing tests pass). Co-authored-by: yhh <yhh@yhhdeMac-mini.local> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )