Commit Graph

2207 Commits

Author SHA1 Message Date
程序员阿江-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
程序员阿江(Relakkes) 77bac15e2b fix: merge QA-001 PDF read and overwrite protection 2026-10-01 17:47:18 +08:00
程序员阿江(Relakkes) 7fa492a71b fix(tools): preserve PDF read-before-write state 2026-10-01 17:45:25 +08:00
程序员阿江(Relakkes) 82de002b16 fix: merge QA-003 home-relative Markdown image paths 2026-10-01 17:44:28 +08:00
程序员阿江(Relakkes) ce57778fb2 fix: merge QA-005 oversized history workspace fallback 2026-10-01 17:44:20 +08:00
程序员阿江(Relakkes) b7ceecc6f0 fix: merge QA-004 session index empty-page optimization 2026-10-01 17:40:05 +08:00
程序员阿江(Relakkes) 19b33755bf fix(chat): retain workspace changes for oversized history 2026-10-01 17:39:52 +08:00
程序员阿江(Relakkes) e9127908f6 fix(markdown): resolve home-relative image parent paths 2026-10-01 17:38:35 +08:00
程序员阿江(Relakkes) 23eda7bf8d fix(sessions): avoid history scans for empty indexed pages 2026-10-01 17:37:15 +08:00
程序员阿江(Relakkes) 9fd95f6fac fix(grok): align CLI identity with 1.0.46 to clear HTTP 426
The CLI proxy now rejects clients below 1.0.13. Advertise 1.0.46, use the official interactive grok-pager/grok-shell user agent, and send the client identifier and authenticate-response headers.
2026-10-01 15:23:21 +08:00
程序员阿江(Relakkes) d0358e72d6 fix(sessions): keep session lists on the local index when single transcripts fail
A single transcript the index could not project flipped the whole index to
degraded, and every session list request then fell back to a full JSONL
scan (about 1.8 GB here, 3.6-5 s of CPU on each cold start).

- Stream records over 8 MiB (Read-tool image results store their base64
  twice) into a bounded skeleton instead of rejecting the transcript. The
  selection logic is shared with the metadata reader via
  boundedJsonProjection.
- Treat budget, changed-during-read and transient I/O failures as
  source-scoped: list and sidebar reads keep serving the index and read
  only those transcripts from disk. Index-wide failures still fall back.
- Persist budget failures in source_files.state so the next launch knows
  them before its first read, and stop rereading them on appends.
- A targeted entry read that misses one transcript no longer cools down
  index reads for every other session.
2026-10-01 15:23:21 +08:00
程序员阿江(Relakkes) 6d75fac69e feat(desktop): add local voice dictation to the chat composer
Adds a microphone button beside the composer. Click to record, click to stop; the audio is resampled to 16 kHz mono PCM16 WAV, posted to the local server and transcribed by a SenseVoice worker process, and the text lands in the draft without being sent. If the draft changed or an IME is composing, the result is held behind an insert button instead of overwriting the user's text.

Server: a small provider registry behind /api/voice/* (catalog, preferences, prepare/cancel/status/remove, transcribe). The engine and model are downloaded at runtime to <config>/cc-haha/voice with pinned sha256/sha512, HuggingFace plus hf-mirror and npm plus npmmirror, HTTP Range resume, automatic retry after interruptions, and a partial file kept across cancels. Recognition runs in a separate worker process (sidecar --voice-worker), started on demand and reclaimed when idle.

Desktop: an independent Voice input settings tab with enable switch, model download progress and resume, language, microphone selection and a transcription test with a live waveform. Uses the shared Dropdown/Card/Button components; adds a danger-ghost Button variant. Preferences live in desktop-ui.json (schemaVersion 6); the microphone device id stays in localStorage.

Electron: main-window media permission handler limited to app pages, main frame and audio only, plus the audio-input entitlement and NSMicrophoneUsageDescription.

Scope: Electron desktop only. Not verified on Windows or Linux, with a real microphone, or in a signed and notarized package.
2026-10-01 15:23:21 +08:00
程序员阿江-Relakkes 8d1548e62c feat(desktop): per-format file icons, and fixes for workspace open, web images and xlsx widths (#1419)
* feat(desktop): show per-format file icons on chat file cards

Generated-file cards, the turn change card and message attachments used
one grey Material glyph for every file. They now render a folded-corner
document icon with a colored body and the extension label (PDF red,
Word blue, Markdown blue, Excel green, PowerPoint orange, archives
amber, code purple, ...), built on react-file-icon instead of
hand-drawn art. Extensions the library does not know are mapped to a
close sibling or to a category color, and jsonl now counts as code.

Brand colors live in lib/fileTypePalette.ts because react-file-icon
writes them into SVG attributes, where CSS variables are not reliable.

* fix(desktop): open workspace documents written through a symlinked path

Clicking an output card for /tmp/app/report.pdf opened the system app
instead of the workspace preview when the session's canonical workdir is
/private/tmp/app. The gate compared path strings, so a symlinked form,
a workdir that had not loaded yet, or a registered access root all
looked like "outside the workspace".

The string check stays as the fast path. When it says "outside", ask the
server through getWorkspaceFile, which resolves real paths: an accepted
document opens in the workspace, a 403 still goes to the system app.

* fix(desktop): load local images in the web UI and H5

A bare <img src> cannot send Authorization, and the server refuses a
credential-less cross-site subresource load, so the browser blocked the
response (net::ERR_BLOCKED_BY_ORB) and chat showed "unable to load
image". Only the Electron shell worked, because its main process injects
the credential for an allowlist of media routes.

When an <img> fails, retry once through the credentialed client and show
the result as a blob: URL; the failure notice appears only if that also
fails. Covers the inline image gallery, the lightbox, image generation
slots and Markdown images. The credential is only ever sent to the local
server's own origin.

* fix(desktop): keep spreadsheet numbers whole in the workspace preview

Columns without a stored width fell back to a fixed 72px, and stored
widths were chosen for Excel's font, which is narrower than the
preview's. Values such as 12,000.00 were clipped to "12,000...".

A column the file gives no width now fits its widest cell, and a number
column never ends up narrower than its numbers. Text in a column whose
width the file sets is still clipped, as Excel clips it, and merged
headings that spill over their span do not widen a column.
2026-10-01 15:22:13 +08:00
程序员阿江-Relakkes da51feb8cf Merge pull request #1418 from NanmiCoder/fix/integrate-1363-1401
fix: preserve history completeness and recover failed inline images
2026-09-30 17:50:19 +08:00
Mi Nan 24dda65f2e fix: preserve bounded history completeness and image load recovery 2026-09-30 09:20:46 +00:00
程序员阿江(Relakkes) acd57a4905 fix(desktop): preserve merged spreadsheet title dimensions 2026-09-30 02:38:30 +08:00
程序员阿江(Relakkes) e81890cf89 chore: integrate main updates into workspace document preview 2026-09-30 02:37:25 +08:00
程序员阿江(Relakkes) 6bab6fbe97 feat(desktop): preview documents in the workspace and images in chat
Documents the agent writes open in the workspace panel instead of another
application, and local images the agent mentions show up in the conversation.

Workspace preview
- PDF (pdf.js with its own layout and text layer), Word (docx-preview inside a
  scripts-disabled sandboxed iframe) and Excel (SheetJS; .xlsx, .xlsm, .xls) open
  in the side panel with zoom and fit, per-file scroll/zoom/sheet memory, and a
  refresh when the agent rewrites the file. The engines load lazily.
- Bytes come from a new GET /api/sessions/:id/workspace/raw route, with an
  extension allowlist, size caps, the workspace boundary and canonical-path
  checks. The file endpoint returns metadata and a version for documents. The
  client fetches with the bearer credential, so it works in Electron, LAN H5 and
  remote access alike.
- Chat links, output cards and the change card open pdf/docx/xlsx in the
  workspace; documents outside the workdir still go to the system application.
- Image viewer with fit, zoom and pan, and "open in system app".

Chat images
- Markdown images outside the workdir, at ~/, C:\ and file:// paths render, open
  in the viewer, and offer "open original" (pictures only).
- Images returned by tools such as Read appear as thumbnails under the call.

Hardening found in review
- previewFsUrl escapes each path segment; a double-escaped %2e%2e used to leave
  /preview-fs/<session>/.
- The CORS, API timing and remote-access header decorators set headers in place.
  Rebuilding the response buffered whole files in memory and dropped
  Content-Length.
- The engine owns the pdf.js worker, so closing one document no longer fails the
  next open.
- Office archives are inflated in steps to check their real sizes, not the sizes
  they declare.
- A viewer that fails to load stays in its panel instead of taking the window down.

Adds pdfjs-dist, docx-preview, xlsx (SheetJS 0.20.3 tarball) and fflate as
renderer dev dependencies; Vite bundles them.

Refs #1397
2026-09-30 01:53:47 +08:00
程序员阿江(Relakkes) b8c4109c42 Merge branch 'worktree-20260929-fix-issue-1400' 2026-09-29 17:45:05 +08:00
程序员阿江(Relakkes) 2909b50ef2 Merge branch 'worktree-20260929-fix-issue-1399' 2026-09-29 17:36:56 +08:00
程序员阿江(Relakkes) c5347830f4 Merge branch 'worktree-20260929-feature-tab-notify-support' 2026-09-29 17:13:18 +08:00
程序员阿江(Relakkes) 591e84acd6 feat(desktop): highlight sessions waiting for attention 2026-09-29 17:06:59 +08:00
程序员阿江(Relakkes) 58662a0c4e test(coverage): exclude desktop test helpers from changed lines 2026-09-29 16:48:42 +08:00
程序员阿江(Relakkes) baf472c255 test(desktop): use jsdom storage for event fixtures 2026-09-29 16:42:27 +08:00
程序员阿江(Relakkes) a536c352d9 test(skills): isolate missing agents root fixture 2026-09-29 16:33:51 +08:00
程序员阿江(Relakkes) 5b309646d2 Merge branch 'worktree-20260929-feature-sonnet55-support' 2026-09-29 16:25:33 +08:00
程序员阿江(Relakkes) 6d9a3a9364 feat(models): support Sonnet 5.5 and refresh Claude defaults 2026-09-29 16:25:20 +08:00
程序员阿江(Relakkes) 24ca1bc7a7 fix(desktop): describe request-too-large rejections accurately
The localized copy for a request-too-large rejection blamed the selected model
and told users to delete large files. The limit belongs to the provider or
relay, and the runtime now removes earlier images and documents by itself on
the next message, so say that and point to compacting or a new session if the
request still fails.

Refs #1399
2026-09-29 16:19:03 +08:00
程序员阿江(Relakkes) eb322bb4cf fix(runtime): report measured size on 413 and recover stuck sessions
A 413 from the API or a relay was reported as "Request too large (max 20MB)",
which is the PDF-only limit, and the only recovery stripped top-level media
from the single turn before the error. When the bytes sat in tool results,
@-mentioned images or older turns, nothing shrank and every later message
failed the same way.

The error now reports the size of what was sent and how much of it is images or
documents, names the provider or relay as the side that rejected it, and keeps
the upstream's own text in errorDetails. After the error, images and documents
in everything the failed request carried are replaced with placeholders,
including media nested in tool results and from @-mentioned attachments. The
rejection carries no sourceModel, so it still applies after a model switch.
Transcripts saved with the old wording keep working, and compaction shares the
placeholder logic instead of keeping its own copy.

Refs #1399
2026-09-29 16:19:03 +08:00