Commit Graph

2235 Commits

Author SHA1 Message Date
程序员阿江(Relakkes) c1ec601c00 fix(desktop): wrap the Agent Teams header in narrow panes
The header had a fixed 1180px minimum that scrolled sideways and let
flex squeeze button labels into vertical stacks. The controls now wrap
onto their own row, and buttons and timings never wrap.
2026-10-08 21:54:38 +08:00
程序员阿江(Relakkes) 9d25e6120c feat(desktop): order the token usage page usage, activity, then models
The per-model table moves below the activity heatmap and insights under
its own "Usage by model" heading.
2026-10-08 21:54:38 +08:00
程序员阿江(Relakkes) 273e5d9786 fix(desktop): place the browser edit bubble at the click and capture after it closes
- Picking an element that fills the view (such as <body>) squeezed the
  bubble to its 160px minimum at the bottom-left. It now opens at full
  height beside the click.
- The <webview> guest does not repaint before a native capture, so the
  selection screenshot still showed the closed bubble and no annotation.
  Hiding the page chrome now resolves after the next painted frame.
2026-10-08 21:54:38 +08:00
程序员阿江(Relakkes) 091c8602fa fix(desktop): show pressed sidebar toggles in the theme accent
A pressed sidebar button used the hover fill, so the task-view bell looked
the same on and hovered. It now takes the brand accent. Pressed buttons
also stop emitting the tone's resting text color, which won over the
pressed color by class order.
2026-10-08 21:54:38 +08:00
程序员阿江(Relakkes) ffc70c8fb5 fix(desktop): open the composer + submenu level with its row
The side panel was bottom-aligned to the root menu, so Skills and
Connectors both opened at the bottom. It now lines its title up with the
row that opened it and only moves to stay inside the window.
2026-10-08 21:54:37 +08:00
程序员阿江(Relakkes) b9fe74b9e2 fix(desktop): label the custom provider preset in the active locale
The custom preset showed the catalog's bare English "Custom" in every
language and prefilled it as the config name. It now reads "Custom API"
(自定义模型 API, etc.) on the chip and in the prefilled name.
2026-10-08 21:54:37 +08:00
程序员阿江-Relakkes 0a3b549d5e fix(desktop): settle background tasks from sessions the desktop never ran (#1471)
A session finished by another CLI run (official CLI, or one that has
exited) kept a background shell "running" forever: the sidebar spun, the
header said the session was active, and Stop failed with "CLI session is
not running".

The CLI records a task's end in several shapes depending on when the
notification was delivered, and history restore only read the user-turn
one:

- notifications drained mid-turn are queued_command attachments;
- notifications queued but never delivered survive only as a
  queue-operation;
- TaskStop/KillShell leave no notification, only their own tool result.

Read all of them, and when no CLI process exists, converge a Stop of a
history-only task to stopped instead of failing.
2026-10-08 18:30:43 +08:00
程序员阿江(Relakkes) 1c78154525 fix(desktop): show connector logos in the composer + menu
Connector rows in the + menu used a generic plug icon, while the extension
market shows each connector's logo from public/connectors/<id>.svg. The menu
now uses the same logo and falls back to the plug when it fails to load.
Market skill icons, which are absolute URLs, are no longer prefixed with
the app's base path.
2026-10-06 05:21:04 +08:00
程序员阿江-Relakkes b99bd1fb38 feat(desktop): reorganize the composer + menu around skills, connectors and run modes (#1462)
- Group the root into "for this task" (skills, connectors, files) and
  "how it runs" (Agent Teams and Computer Use switches); the rest moves
  under More tools.
- Open categories in a side panel on desktop; narrow windows and the
  phone sheet keep in-place navigation.
- Connectors list connected services, ones that need sign-in, and three
  fixed suggestions, each opening its detail in the extension market.
- Drop the Plugins entry: plugin skills show under Skills, MCP plugins
  under Connectors, the rest stay searchable.
- Skills show recently sent ones, all skills, and two curated market
  skills that install in place.
- Agent Teams arms the next message with a team instruction and a
  removable chip; the bubble and restored history show only the typed text.
- Turning Computer Use on from the menu goes through the same consent
  dialog and grants as Settings.
2026-10-06 05:05:04 +08:00
程序员阿江-Relakkes 50f784114b feat(desktop): start H5 phone tasks from a new-task sheet (#1461)
The phone home is now the session list alone. The docked composer took a
quarter of the screen and could not send until a project was picked, so a
New task button floats over the list instead and opens a full-height sheet.

- The sheet puts the project at the top, above the keyboard, and docks the
  composer to the bottom. Cancel, the system back gesture or pulling the bar
  down closes it; sending swaps it for the new session.
- The project defaults to the list's project filter, otherwise to the
  project of the most recently created task.
- On a tablet the button opens the new-session page beside the list.
2026-10-06 04:09:05 +08:00
程序员阿江-Relakkes 4fb4784b81 feat(desktop): rebuild the H5 phone and tablet shell around touch (#1460)
Replace the drawer-based mobile layout with a single navigation stack. Home
is the session list grouped by status (waiting for you, working, then by
day) with the new-task composer docked under it; a session, Settings and
subagent or team-member pages push on top, and the system back gesture
moves up one level. Touch tablets keep the list beside the page.

- Composer: one row (+, model, send); permission mode, context usage and
  the capability menu move into a + bottom sheet.
- Approvals: a waiting permission, question or plan takes the composer's
  place; the transcript keeps a one-line marker. Denying can carry a reason.
- Messages: press and hold for copy, select text, edit and branch instead
  of an always-visible icon row.
- Tool runs fold into one card per run and open the full timeline in a
  sheet; the turn change card opens a file's diff full screen.
- Activity: a pill in the session bar opens the activity sheet instead of
  auto-opening over the chat.
- Settings: one grouped list with the connection, provider, phone-editable
  preferences and the computer-only settings shown read-only.
- Server: GET /api/sessions/live-status reports every running or waiting
  session so the list can sort sessions the phone never opened.
2026-10-06 03:18:30 +08:00
程序员阿江-Relakkes 8ddf67390d fix(agent-teams): enforce task dependencies in approved teams (#1459)
An approved team handed every member its instructions at the same moment,
so members whose tasks depended on unfinished work started anyway: the
second and third layers of a plan ran before the first, a member could mark
a blocked task in progress, and results only ever went to the lead. The
official CLI states dependencies in tool prompts and nothing more, so the
plan the user approved was not what ran.

- A member whose tasks all wait on other tasks gets its instructions only
  once one of them is ready. What the lead or a teammate sends it before
  that waits in its inbox and arrives with the instructions; only the user
  writing to it, or a shutdown request, reaches it earlier. This survives a
  Stop and a server restart.
- TaskUpdate refuses a teammate that starts or completes a task while a
  task it is blocked by is unfinished. The lead is not held to it.
- Each member is told who waits on its tasks and to send them its result
  before completing, so a dependent member starts with that result in
  hand. A member that starts without one is told whose is missing.
- A member that exits after approving a shutdown request is no longer
  recorded as failed, and the lead gets no failure notice for it. The
  shutdown-approval schema keeps leaving out the desktop backend on
  purpose, now documented and tested.
- TeamPlan tells the lead that a dependent member's prompt is delivered
  when its dependencies are done.
2026-10-06 01:51:35 +08:00
gugugaga 8b2f9102a5 fix(runtime): converge background tasks on Stop and runtime loss (#1441)
* fix(server): reap background shell tasks on Stop and after runtime exit

A session's background shell task (Bash `run_in_background`, Dream, workflow)
is tracked as a non-Agent task, and nothing on the server ever bounded or
reaped one. A user Stop only interrupted the foreground turn and the Agent
tasks, so the shell kept running after the user had asked everything to stop.
A client disconnect let the CLI live forever, because the disconnect watcher
waits for `hasActiveBackgroundTasks` to clear and a task that never emits a
terminal notification never clears it. A hard runtime death published no
terminal state at all, so a later reconnect re-hydrated a ghost "Running"
entry that could never reach a terminal state.

This closes all three from one file of server bookkeeping:

- `handleStopGeneration` now reaps the session's non-Agent background tasks
  through the same `requestControl` stop path the panel's per-task Stop uses,
  and the 3-second force-kill guard watches them too. Programmatic stops
  (turn stop, runtime-config restart) keep the previous narrow behavior.
- A new 31-minute ceiling bounds a session that a disconnected client keeps
  alive through background tasks alone; when it elapses the shared runtime is
  stopped and terminal bookends are published. A reconnect clears the ceiling.
- `close()` and `closeStoppedAgentsAfterRuntimeExit` publish terminal bookends
  whenever the runtime is already gone but task records remain, instead of
  leaving them to be re-hydrated as "Running".

The new timer registry is released by `cleanupSessionRuntimeState` and
classified as `cleared` in the session-state cleanup guard, so a ceiling
scheduled for a session cannot outlive that session.

会话的后台 shell 任务(Bash `run_in_background`、Dream、workflow)登记为非 Agent 任务,
服务端一直没有收掉它们的路径:按停止键只断前台轮和 Agent 任务,shell 还在跑;客户端断开后
CLI 因为 `hasActiveBackgroundTasks` 恒为真而一直存活;运行时崩溃又不写终态,重连后又
变成幽灵 Running。这次在 handler 一处收掉这三种:

- 按停止键时一并停掉本会话的非 Agent 后台任务,走面板单任务 Stop 同一个 stop 通路,
  三秒强杀闸也一并盯住它们;程序化停止(停轮、重启换配置)仍走原来的窄路径。
- 新增 31 分钟硬上限:没有客户端、只靠后台任务续命的会话,到期就停掉共享运行时并写终态;
  重连则撤销该计时。
- 运行时已经没了但任务记录还在时,`close()` 与 `closeStoppedAgentsAfterRuntimeExit`
  直接写终态,不再留着让重连把 Running 灌回来。

Refs #1132

* fix(runtime): converge background tasks and reap orphaned shells

* fix(desktop): restore stopped shell tasks after cold history load

---------

Co-authored-by: gugugaga <267102352+omazili-guga@users.noreply.github.com>
Co-authored-by: 程序员阿江(Relakkes) <relakkes@gmail.com>
2026-10-05 22:33:35 +08:00
程序员阿江-Relakkes d0ba3d3bd0 fix(server): send images to OpenAI Chat models until the upstream rejects them (#1458)
The OpenAI Chat proxy decided image support from host and model names:
opencode.ai and DeepSeek hosts replaced every image with a text-only
placeholder unless the model id contained "vision" or was allowlisted.
Each new vision model on OpenCode Go (Kimi K3, Space Bunny, DeepSeek Flash)
therefore told users the endpoint could not read images.

Offer images to every model instead. When the upstream refuses a request
that carried images with a recognizable image-input rejection, resend it
once without images and, only if that succeeds, remember the endpoint and
model as text-only for 30 minutes and record an info diagnostic. Failures
about a particular image (format, MIME type, size, animation, image count)
surface unchanged so one bad image cannot disable images for the model.

The rejection matcher moves to a shared module used by the CLI error mapper
and the proxy, and now also recognizes vLLM and OpenAI wording.
2026-10-05 21:12:25 +08:00
程序员阿江-Relakkes 76af3f0e55 feat(desktop): turn dictation into a recording bar and offer it by default (#1457)
Recording:
- While dictating, the composer's toolbar row becomes a recording bar:
  cancel, a scrolling trace of what the microphone heard, the clock
  (a countdown in the last 15 s), stop, and send. Recording is no longer
  painted in the error color.
- Stop writes the text into the draft. Send writes it, then submits the
  draft through the composer's own path once the render carries the text.
  Text held back because the draft changed is never sent.
- Dictated text is tinted for a moment where it landed.
- The settings transcription test uses the same trace, clock and stop
  disc. VoiceWave is removed.

Default:
- Voice input is on by default for preferences that never saved it; a
  saved `false` is kept.
- In the desktop app the microphone shows before the model is downloaded
  and opens Settings > Voice input. The browser (H5) never offers it.
2026-10-05 21:08:47 +08:00
程序员阿江-Relakkes 72d6db6db9 fix(desktop): explain why a prompt cannot be edited instead of hiding it (#1456)
The edit-and-resend action disappeared whenever an edit could not start:
while a turn ran, while any background task (a dev server, a background
agent) was still running, while turn checkpoints loaded, or when they
failed. With nothing on screen it read as the feature being gone.

Completed prompts now keep the action, disabled, with the reason on hover
and as its accessible description. An open editor and its draft survive a
background task starting. Sessions past the checkpoint preview budget can
edit again by resolving each prompt through its transcript id; since that
mode already tells the user file undo is unavailable, those edits roll
back the conversation only.
2026-10-05 20:35:10 +08:00
程序员阿江-Relakkes 06e797d6dc fix(desktop): hide side chat entries until a session has a conversation (#1455)
A side chat forks the parent transcript, so the server rejects it for a
blank session. The new-session page still showed the side chat button in
its top-right corner, and every click only produced a "Start a
conversation before opening a side chat" toast.

Gate every way in on the session having a conversation: the top-right
button now only renders on mobile once the session has messages, and the
workspace launcher, its + menu and the /btw slash menu entry leave side
chat out of a blank session.
2026-10-05 18:24:27 +08:00
程序员阿江-Relakkes 760ee4e481 feat(desktop): redesign the desktop UI on the Porcelain visual system (#1452)
Rebuild every desktop page on one visual system, 「素 Porcelain」: a quiet
light theme with a tool-call timeline, bubbled user messages and a floating
composer card.

- Tokens: rewrite the white theme on Porcelain values and give all six
  themes one radius scale (4/6/8/12/16/20), one type scale
  (11/12/13/14/15/18/22/26), Inter up to semibold, JetBrains Mono at 400,
  and status colours by meaning (running = info, waiting = warning,
  done = success, failed = error). Terracotta is kept for the mark, the
  send key and selection.
- Icons: draw every icon from lucide and drop the Material Symbols font.
  The generic sparkle glyph is gone: a working turn shows the running
  ring, skills use the same box the @ and / menus use for SKILL.md.
- Chat: tool calls read as a timeline, user turns as bubbles, the composer
  as a floating card; cards, menus, dialogs and permission prompts share
  the same surfaces and shadows.
- Shell: session tabs and workspace tabs use one shared tab chip; the
  sidebar, workspace and settings follow the same grounds.
- Settings: the page frame is fluid up to 1120px for every pane, so
  explorer-style panes (memory, skills) are no longer squeezed into 700px.
- Guard: designSystem.test.ts fails on off-scale font sizes, weights above
  semibold, italic text, Material Symbols, Tailwind radius names and
  sparkle icon imports.
2026-10-05 12:55:18 +08:00
程序员阿江-Relakkes 9aaa53cbea fix(desktop): silence missing images and translate hardcoded text (#1450)
* fix(desktop): show no error for images that are not there

A reply named the screenshots it had taken as
`/tmp/cc-haha-ui-review/0*.png`, and a red "Unable to load image" tile
with a retry button appeared under it. The inline gallery took the glob
for a file: its absolute-path pattern accepted any character but
whitespace and quotes. Wildcards and substitutions (`*`, `?`, `{name}`,
`${id}`, `$NAME`, `%03d`) now end a path there. Brackets stay, since real
directories use them.

The tile was the larger problem. In the local session history we
checked, 45 of the 115 pictures the gallery tried to show were red tiles
and only 18 existed: files cleaned out of /tmp, outputs deleted since,
web routes, example paths. A retry fixes none of them. Every failure
went red because an <img> error carries no status, but the
authenticated fetch that follows it does. A 400, 403, 404 or 413 from
the file routes now means the picture is not there to show: the inline
tile disappears, and a Markdown image falls back to its alt text. A
server fault, a dropped connection, a refused credential or bytes that
do not decode still show the retryable error, whose hint now names
those causes.

The guessed-name versus spelled-out-path split from #1429 goes: why the
load failed decides, not how the path was written. A server test pins
the 404 for a file missing from an allowed root, which the rule relies
on.

* fix(desktop): translate text typed into components

The header over the pictures in a reply read "1 IMAGE" in every locale.
The text was typed into JSX, and the type of the locale files only
proves that every key has a translation, not that components use one.
A scan of the 246 components found more: Mermaid's error, loading text
and preview hint, "Untitled" in the sidebar, Computer Use's "Failed to
check status.", token counts in /context, labels in the trajectory
view, and screen-reader labels such as the sidebar region and the diff
grid. They now go through t(), reusing a key where one existed and
adding 15 to all five locales. The English text is unchanged.

untranslatedText.test.ts keeps it that way. It reads every component
and fails on JSX text, text-bearing attributes and string literals
rendered as children that skip t(). Key caps, code, icon ligatures and
t() fallbacks are not prose. Product names, units and example values
are listed per file with the reason, and a listed text the source no
longer has fails too. Modal's "Close dialog" stays a known gap: a ui
primitive cannot read the locale, so the label has to come from its
callers.
2026-10-04 22:22:13 +08:00
程序员阿江-Relakkes 5d61feee2e fix(api): explain interrupted provider streams with evidence (#1449)
When a provider closes a 200 stream before message_stop and every stream
retry fails, the error now names the upstream model provider as the cause,
states it is not a context-limit error, and records what the attempt
received: event count, last event, stop_reason, whether message_stop was
missing, open blocks, elapsed time and retries spent. That separates a
reply cut mid-block from one that only dropped message_stop.

The error carries a new upstream_stream_interrupted business code. The
desktop shows a localized explanation in all five locales and keeps the
raw evidence line under it.
2026-10-04 22:05:49 +08:00
程序员阿江-Relakkes 9623064b15 fix(agent-teams): keep a stopped team stopped and wake members after any failure (#1446)
* fix(agent-teams): keep a stopped team stopped and wake members after any failure

Stop killed every member, but the lead kept polling its mailbox: reports
sent before the Stop started hidden lead turns, and a single SendMessage
from one of them unpaused the whole team. Stop now sends team_plan_pause
so the lead holds teammate mail until the user's next message, and the
server only lets lead instructions written after that message resume the
team. A restart in flight when Stop arrives is stopped as well, and the
idle Stop button hides once every member is stopped.

Members that stopped on a usage limit, billing, network or crash failure
were only resumed if the lead happened to message them. The user's next
message now lists every stopped member with its failure and open tasks,
once per failure, whether or not Stop was pressed.

* feat(desktop): show where each team member stands on its tasks

A member that stopped or failed left its task reading "In progress" with
an animated bar, and its card said only "Stopped" or "Error". Tasks whose
owner stopped, failed or waits to retry now show that state without
animation, and the card says which task the member stopped on.

The member card chips tell done, current and next tasks apart, with the
subject on hover. The member drawer groups tasks into now, up next and
done, names the unfinished dependencies of blocked work, shows done as
3/5, and no longer prints +0:00 for a duration polling could not measure.
2026-10-04 19:31:10 +08:00
程序员阿江-Relakkes 5dc59c5892 fix(desktop): show files as outputs and links only on evidence (#1444)
A reply that summarised commits quoted `开题报告2.docx` and
`D:/资料/测试文档1.docx` from their messages. The turn only ran `git log`,
yet three Word cards appeared under it and every name was a link, all
opening "file not found". Being mentioned is not being produced, and a
guessed path is not a file.

Output cards now need the turn to have produced the file. A changed file
in the turn checkpoint still counts. A turn whose checkpoint lists no
unverified write source (only read-only shell, no MCP writes) has no
unseen output, so other mentions are dropped without touching the disk.
Otherwise a mention is shown only once the disk reports it exists and
was modified since the turn began, compared on the server's clock via a
new checkpoint `startedAt`. Cards wait while the checkpoint loads.

File links guessed from code spans and prose render as plain code until
the workspace confirms the file exists, and stay plain when it does not.
Links the reply wrote in Markdown are kept as written. Clicking a file
that is gone shows the existing "could not open" toast instead of a tab.

Both checks share one stat channel: GET /api/sessions/:id/workspace/stat
(at most 20 paths, same boundary as the file route, the workspace root
resolved once per request). The client batches every message that mounts
in a tick into one request, dedupes in-flight paths and caches answers
for 10 s, so a remounted message renders its final state at once and a
link just verified opens without another round trip.
2026-10-04 17:36:49 +08:00
程序员阿江(Relakkes) 4e1417877e docs: update README.md 2026-10-04 17:19:21 +08:00
程序员阿江-Relakkes 3754d1f2a5 feat(desktop): replace the settings trace list with an in-session trajectory view (#1443)
Sessions get a Chat / Trajectory switch in the header. The trajectory is a
dense one-line-per-event ledger (system prompt, user, injected context such
as skills and system reminders, assistant responses, tool calls) with a
three-lane minimap, turn folding, search, and a detail panel per row.

- CLI: record a deduplicated prompt snapshot sidecar for desktop sessions
  (system prompt, tool catalog, user context) without touching the transcript.
- Server: project transcript records into trajectory rows with bounded,
  cursor-paged reads, live appends, a turn index, row detail by byte range,
  snapshot blobs, and a time-window lookup into the raw trace capture.
- Desktop: windowed ledger, minimap, detail panel with a raw request summary,
  chat <-> trajectory navigation, subagent drill-in.
- Remove the Settings trace list, trace tabs and the standalone trace
  window; migrate persisted trace tabs to session tabs.
2026-10-04 17:14:07 +08:00
程序员阿江-Relakkes 5ae39d670c fix(desktop): default reasoning effort to low for new sessions (#1439)
The global effort default moves from max to low on both the server
(/api/effort fallback) and the desktop store. Users who already saved an
effort keep it.

ChatGPT Official and Grok Official are not in the saved provider list, so
their first draft selection carried no effort: the server ran the model
default while the selector showed the global value. Resolve the effort
against the model catalog for those providers too.
2026-10-04 13:42:14 +08:00
程序员阿江-Relakkes 195b406e91 docs(site): switch the promo film to the 62-second no-narration cut (#1438) 2026-10-04 13:22:17 +08:00
程序员阿江-Relakkes 7e50c31986 fix(desktop): composite the workspace browser with the app UI (#1437)
The workspace browser was a native WebContentsView, which always paints
above the DOM. Switching to the skills or settings page left the page
floating over it, and menus over the page needed a screenshot swap that
showed up clipped and flashed white.

Pages are now <webview> guests kept in a layer inside the session panel
that is never unmounted, so other pages, menus and dialogs draw over
them like any element. The main process adopts each guest and keeps all
in-page behaviour: navigation, history, find, zoom, capture, PDF,
downloads, shortcuts and annotation.

- Guard every attach in the main window: browser partition only, start
  at about:blank, preload and sandbox pinned, reported ids validated.
- Match the native page: drop the blank history entry, keep page zoom
  independent of app zoom, allow popups so they still become tabs.
- Keep app drags working over a page and close menus on a click into it.
- Tell the side dock it is off screen when the session page is hidden.
- Remove the overlay snapshot machinery and native bounds syncing.
2026-10-04 03:24:50 +08:00
程序员阿江-Relakkes 8a94f09663 docs(readme): make Chinese the default README and keep only the film (#1436)
- README.md is now Chinese; the English README moves to README.en.md.
- Drop the eight-screenshot grid and the Agent Teams loop; the film cover
  remains the single visual. Remove the now-unused thumbnails.
- Point PR triage, change policy, and the docs check at the new file names.
2026-10-04 03:12:59 +08:00
程序员阿江-Relakkes aff55ff38b docs: show Agent Teams and the promo film in README and on the site (#1435)
- README: add an Agent Teams loop cut from the promo film (subtitles cropped)
  and a cover that opens the 90-second film from the CDN.
- Site: add a click-to-play film section after the hero; the video element
  is only created on click, and the poster ships with the site.
2026-10-04 02:57:06 +08:00
程序员阿江-Relakkes 3c84b47483 fix(market): keep the skills market home on one page surface (#1434)
The catalog redesign put the title, disclaimer, categories and search on
a white band ruled off from a tinted canvas holding the cards. The
extensions frame, the plugins tab and the skill detail all sit on the
plain page surface, so the seam read as two pages glued together and the
canvas flashed on every home/detail switch.

Lay the controls and the grid in one column on --color-surface and
separate them by spacing; the cards keep their own border and shadow.
2026-10-04 01:52:05 +08:00
程序员阿江-Relakkes 795ff9d4df feat(desktop): add safe data directory migration (#1433) 2026-10-04 00:39:20 +08:00
程序员阿江-Relakkes c144148d20 feat(desktop): edit a sent prompt and rerun from there (#1343) (#1432)
* feat(desktop): edit a sent prompt and rerun from there (#1343)

Hovering a prompt the rewind API can already target now offers "Edit and
resend". The bubble turns into an inline editor; sending dry-runs the
existing rewind, confirms when later turns or restorable files are at
stake, rewinds with the same conversation/both modes as undo, reloads
history and sends the edited prompt. A failed rewind changes nothing and
keeps the draft; if the edit cannot be sent after a successful rewind it
is handed back to the composer.

Undo and edit share one rewind routine, the unused per-message
rewindAction prop is removed, and TextArea forwards its ref.

* fix(desktop): preserve edit-resend session and context
2026-10-04 00:31:38 +08:00
程序员阿江-Relakkes 54a77db95d fix(desktop): read CJK file names in prose whole, settled by the disk (#1431)
The prose scan excludes CJK so a verb is not swallowed into a path, which
cut an unquoted `测试文档1.docx` to `1.docx` and `D:/资料/测试文档1.docx` to
`1.docx`. A match that is recognisably the tail of a CJK name is now
widened to the whole token.

Names the text cannot bound are settled against what exists: `报告v2.docx`,
names glued together without a space, names with spaces or full-width
brackets, and names made only of CJK plus an extension. The extractor
offers the other readings; a changed file settles them, otherwise one
cached workspace listing per folder does, longest existing name first.
CJK-only names read like prose about formats (`后缀为.docx的文件`), so they
are never linked and appear as cards or images only once confirmed.

Fixes #1423
2026-10-03 22:27:55 +08:00
程序员阿江-Relakkes 66f9938f36 fix(sessions): stop full transcript parses on every session lookup (#1430)
Every session route resolves its transcript first, and that lookup parsed
the whole file to rank candidates even when only one file matched. The
desktop pages a long session's history request by request, so reopening
it cost one full parse per page and grew quadratically with file size.

Skip the content check when a single file matches, and stop a multi-file
check at the first conversation record. Ranking and API responses are
unchanged.
2026-10-03 21:58:11 +08:00
程序员阿江-Relakkes 3a9cf1073a fix(desktop): keep CJK file names whole and stop flagging guessed images (#1429)
Output cards scanned inline code spans as prose, which excludes CJK on
purpose, so `开题报告2.docx` became a `2.docx` card that opened a missing
file. Code spans are now parsed whole with the same Unicode-aware parser
the rendered chip uses.

An image the reply only named by a bare filename, with no changed file
corroborating its location, was resolved at the workdir root and showed a
red load error when it was not there. Such guesses now disappear on
failure; paths spelled out with a directory keep the error and retry.
2026-10-03 21:31:23 +08:00
程序员阿江-Relakkes fa28fb8b21 fix(desktop): stabilize virtual spacers at fractional zoom (#1428) 2026-10-03 20:22:42 +08:00
程序员阿江-Relakkes 363e59dda9 fix(voice): start the compiled recognizer worker on Windows (#1427) 2026-10-03 18:11:14 +08:00
程序员阿江-Relakkes fd42b0ca05 fix(agent-teams): keep long-running teams recoverable (#1426)
Long Agent Teams runs lost members for good: a truncated provider stream
ended a member's turn with nobody to wake it, the desktop Stop button and
every lead restart killed all members and marked the plan interrupted,
mail sent to a stopped member landed in an inbox nothing read, and a lead
kept inside one long turn never saw member reports. Aligned with the
official CLI 2.1.284 and verified with DeepSeek Flash through a
fault-injecting proxy.

Stream recovery
- Re-send a stream that breaks before any tool ran (proxy truncation,
  transport errors), with the existing retry budget and backoff; the
  desktop drops the discarded attempt's tool cards and todo update.

Desktop team runtime (teamPlanRuntime)
- The server supervises members: a stopped member restarts from its own
  transcript when messaged; transient failures continue automatically
  (15s/45s/2m/5m/10m) and only exhausted retries reach the lead; ready
  dependent tasks wake their owner; a crash-loop guard ignores user stops.
- Stop pauses the team instead of ending it; the lead's next user message
  is followed by a notice listing the stopped members and their open
  tasks. Lead restarts (model/permission switch, crash) keep members;
  server restarts re-own the team. Teams end on /clear or session delete.
- Approving a plan no longer races a concurrent plan read into
  "Launch ownership was lost".

Mailbox and messaging
- Atomic inbox writes, identity-based read marking, read history files,
  idle notifications with result/failureReason, and write failures
  reported instead of "Message sent". External builds keep the official
  between-turn delivery to the lead.
- SendMessage resumes non-running in-process teammates from their
  transcript, notes restarting desktop members, queues mail for members
  of a plan awaiting approval, and rejects unknown names.

CLI in-process teammates
- Compaction uses the teammate's own controller and real history and no
  longer kills it on error; failed turns are classified and continued;
  the turn-end mailbox drains as one batch; one durable transcript per
  teammate.

Lead behaviour
- An unmet /goal ends the lead turn while members work, so member reports
  arrive; WaitSessions on own team members returns immediately.

Desktop UI
- Member states for stopped, auto-retrying and failed, with reason,
  countdown and recovery hint in all five locales.

Tests and tooling
- Regression tests for every behaviour above; module mocks in four test
  files are restored after use so the single-process coverage run is not
  polluted; the desktop smoke asserts the new Stop semantics.
2026-10-03 17:07:30 +08:00
程序员阿江(Relakkes) 6d8071be8e release: v0.6.8 v0.6.8 2026-10-02 02:45:29 +08:00
程序员阿江(Relakkes) 4097fc6506 feat(market): curated skills catalog with categories and redesigned detail
Open the skills market on a bundled catalog of 398 curated ClawHub and
SkillHub skills in 13 categories instead of querying both registries live.
Live search stays available as an explicit "search all markets" scope
whose results are marked as not curated.

- Server: catalog scope (default) with category filter, filtering before
  pagination and batched install state; catalog metadata overlaid on live
  detail; per-scanner ClawHub reports, changelog and page URL; manual
  catalog refresh script.
- Pin ClawHub reads and installs to the card's owner so a same-slug copy
  by another author is never shown or installed in its place.
- Desktop: category chips, curated cards with tags, locale-aware summaries,
  detail page with stats, security report, changelog, capability panel and
  triggers; install confirmation requires acknowledgement for unaudited or
  flagged skills.
- Docs: rewrite the skills market section and refresh screenshots.
2026-10-02 02:25:26 +08:00
程序员阿江(Relakkes) 6b9d2aec1d feat(voice): let users pin the model download source
The downloader races Hugging Face against hf-mirror (and npmjs against
npmmirror) and keeps whichever answers first, so behind a rule-based
proxy the domestic mirror usually wins even though the configured
network proxy is in use. Add an auto/official/mirror preference that
pins one host without silent fallback, and show which network proxy
downloads go through with a link to General settings.
2026-10-02 01:01:30 +08:00
程序员阿江(Relakkes) 98fab14a8d fix(desktop): make zoom fit a distinct, action-only control
The fit button used the same Maximize2 icon as the workspace panel's
maximize control and stayed pressed while already fitted, where clicking
it did nothing. Give it its own icon (fit width: MoveHorizontal, fit
window: Scan) and disable it while the viewer is fitted, so it is only
clickable when there is a manual zoom to undo.
2026-10-02 00:23:17 +08:00
程序员阿江-Relakkes 7c7a977e15 fix(skills): offer bundled skills in composer @ mentions (#1420)
The @ mention list only loaded disk and plugin skills, so bundled skills
such as imagegen never appeared. imagegen is also gated on image provider
env that is injected into each session's CLI rather than the server, so
the mentions endpoint now accepts the session's providerId and evaluates
imagegen against that provider's runtime env.
2026-10-02 00:19:29 +08:00
程序员阿江(Relakkes) dc2a247095 feat(models): support GPT-6.1 Sol in desktop and Codex OAuth 2026-10-01 23:23:46 +08:00
程序员阿江(Relakkes) fac22488c8 fix: merge QA-006 permission mode module binding repair 2026-10-01 18:11:33 +08:00
程序员阿江(Relakkes) 8e141cfbef fix(permissions): use live module binding for mode updates 2026-10-01 18:10:57 +08:00
程序员阿江(Relakkes) dfa91d3278 fix: merge QA-002 image fallback compatibility follow-up 2026-10-01 17:59:58 +08:00
程序员阿江(Relakkes) dbda9a1787 fix(chat): preserve initial image fallback call shape 2026-10-01 17:57:00 +08:00
程序员阿江(Relakkes) c2a6db692e fix: merge QA-002 Markdown image errors and fresh retries 2026-10-01 17:50:11 +08:00
程序员阿江(Relakkes) a05bf7d859 fix(chat): show retryable errors for Markdown images 2026-10-01 17:49:44 +08:00