Commit Graph

2179 Commits

Author SHA1 Message Date
程序员阿江(Relakkes) b7ceecc6f0 fix: merge QA-004 session index empty-page optimization 2026-10-01 17:40:05 +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
程序员阿江(Relakkes) cfc0559d1a fix(server): tolerate BOM and blank scheduled task files
A UTF-8 BOM (PowerShell 5.x) or a zero-filled file (crash mid-write on NTFS)
made every read of scheduled_tasks.json and scheduled_tasks_log.json throw, so
listing and creating scheduled tasks failed with 500 until the file was fixed
by hand.

Both readers now strip the BOM and treat a blank file as empty. Content that
has data but does not parse still throws and is never overwritten.

Refs #1400
2026-09-29 15:59:12 +08:00
程序员阿江(Relakkes) 3556e9e619 fix(desktop): keep malformed AskUserQuestion input from crashing the chat
A tool call the server rejected as invalid stays in the transcript, and its
card is rebuilt from that input on every replay. An option description that
came back as an object threw React #31 and replaced the whole app with the
error page, again on every launch because the open tab is restored.

AskUserQuestion now renders only the string fields it can show, and each
transcript row sits in its own error boundary so a bad record no longer takes
the whole window down.

Refs #1400
2026-09-29 15:59:12 +08:00
程序员阿江(Relakkes) 096e87619d fix(desktop): stop background tasks when closing a running session
The "Session running" dialog treats a running background task as the session
being busy, but Stop & Close only called stopGeneration, which interrupts the
foreground turn and Agent tasks. A background shell command (and its CLI) kept
running, so the reopened session spun again and asked the same question on the
next close.

Stop & Close now also stops every running background task, before the socket is
closed. "Is the session running" and "which tasks to stop" share one predicate
in backgroundTasks, so the dialog cannot offer a Stop that leaves the task that
raised it alive. Keep running sends nothing.

Refs #1398
2026-09-29 15:45:26 +08:00
程序员阿江(Relakkes) fba81834de fix: show the model's replies to background task notifications
Everything the assistant did between a <task-notification> turn and the next
real user message was hidden, so the reply a model gave once a background
command finished (and any tool work after it) never reached the chat, live or
after a reload, even though it was written to the transcript.

Drop that suppression from every session history projection (full, paged,
recovery, sub-agent lookup) and from the desktop store (history mapping and the
live-stream flag). Only the injected notification prompt stays hidden; the
background task cards still come from its notification data. The suppression
was added for #886 to quiet replies to stale notifications; the CLI already
avoids those at the source when the model has read the task's result.

Refs #1389
2026-09-29 15:45:10 +08:00
程序员阿江(Relakkes) 2ec845d084 fix(desktop): include configured Fable models in model selector 2026-09-28 02:29:56 +08:00
程序员阿江(Relakkes) 7a82ce9aec feat(skills): merge release announcement workflow 2026-09-28 02:19:43 +08:00
程序员阿江(Relakkes) 2ad56231d1 feat(skills): add release announcement workflow 2026-09-28 02:19:33 +08:00
程序员阿江(Relakkes) c37ab2da13 docs: correct Windows signing status in v0.6.7 release notes v0.6.7 2026-09-28 01:47:15 +08:00
程序员阿江(Relakkes) 92561bcb28 release: v0.6.7 2026-09-28 01:33:38 +08:00
程序员阿江(Relakkes) ab5f66f101 Merge commit '9d598003b' 2026-09-28 01:02:41 +08:00
程序员阿江(Relakkes) 9d598003b0 fix(runtime): recover malformed tool arguments through the agent loop 2026-09-28 01:02:36 +08:00
程序员阿江(Relakkes) ade9474096 fix(desktop): restore workspace side chat scrolling 2026-09-28 00:10:37 +08:00
程序员阿江(Relakkes) a7bc888a07 fix: use model decisions for automatic question answers 2026-09-28 00:00:16 +08:00
程序员阿江(Relakkes) 417ca5f283 fix(agent-teams): dismiss approved configuration and preserve runtime controls 2026-09-27 23:47:38 +08:00
程序员阿江(Relakkes) fadaa775ac fix(desktop): resolve output files against declared project roots
Keep explicit file identities across output cards and prose links, preserve
shell outputs without checkpoint evidence, and retain a file card when
video preview fails. Add cross-project path and opening regressions.
2026-09-27 23:22:40 +08:00
程序员阿江(Relakkes) e47e234987 fix(desktop): preserve local Markdown file link targets 2026-09-27 20:59:42 +08:00
程序员阿江(Relakkes) 45113d11df fix: finalize stopped teammates when roster removal fails 2026-09-27 19:24:52 +08:00
程序员阿江(Relakkes) d4e53a9fab fix(desktop): wrap activity profile names 2026-09-27 19:24:52 +08:00
程序员阿江(Relakkes) 700f7b9dcc fix: preserve Space Bunny images through OpenCode Go 2026-09-27 19:24:52 +08:00
程序员阿江(Relakkes) f8d0406d6e fix: preserve session metadata across oversized messages 2026-09-27 19:24:52 +08:00
程序员阿江(Relakkes) 26d3a3d558 fix: restore session model selections and normalize runtime effort 2026-09-27 19:24:52 +08:00
gugugaga 9ce414ae4c fix(provider): honor configured output budget for direct Anthropic providers (#1392)
* fix(provider): honor configured output budget for direct Anthropic providers

Anthropic-format providers connecting directly to an upstream could not set a
reply output budget: the field was hidden in the UI, stripped before
persistence, and dropped by a local-proxy-only gate at request build time, so
low-cap relay upstreams returned 400/truncation with no user recourse.

Surface the budget for Anthropic, persist it as a budget-only object so stale
OpenAI-compatibility options cannot leak, and remove only the numeric gate in
getConfiguredProviderOutputBudget. getOutputBudgetHeaders keeps its local-proxy
guard so the internal provenance header never reaches an external provider.

Adds kernel/desktop unit tests for the direct-budget path and the provenance
non-leak.

* fix(provider): disable optional manual thinking below its token minimum

---------

Co-authored-by: gugugaga <267102352+omazili-guga@users.noreply.github.com>
Co-authored-by: 程序员阿江(Relakkes) <relakkes@gmail.com>
2026-09-27 19:11:04 +08:00
yuehua-meng 3326a880e6 teamLib 里一半写路径绕过文件锁,且所有写都是非原子裸写 (#1387)
* fix(swarm): serialize team config writes under the file lock

Route every team config.json mutation through mutateTeamFileAsync so each update reads its snapshot inside the lock, and publish via a same-directory temp file + rename with bounded Windows retry instead of truncating the live file. Await the now-async writers in the UI and CLI callers.

* test(teams): cover TeamsDialog mode cycling and teammate removal

The changed-lines gate scored TeamsDialog.tsx as 0/20 because no test
imported it, so the new async removeMemberFromTeam/setMemberMode paths went
unrecorded in LCOV. Drive both the list and detail views through input
handlers and keybindings, including the rejection paths, to bring
changed-lines coverage from 84.91% to 93.53%.
2026-09-27 19:02:19 +08:00
MikhailTail 760a858e8e fix(computer-use): 修正 Windows 上垂直滚动方向相反 (#1378)
executor 的 delta 是平台原生的滚轮单位,正值向上滚(MOUSEEVENTF_WHEEL
的语义),macOS helper 也是同一套约定。但 handleScroll 把
scroll_direction "down" 映射成了正 dy,于是垂直方向整个反了:down 实际
向上滚,且目标面板已在顶部时表现为"完全无反应"。

只翻转垂直轴。水平轴的映射(right → +dx)与 MOUSEEVENTF_HWHEEL 的正值
语义一致,保持不变。

同时在 platformRouting.test.ts 的 win32 fixture 里记录 scroll 的 delta,
并断言 down → -amount、up → +amount,锁住该映射。

Co-authored-by: 程序员阿江-Relakkes <relakkes@gmail.com>
2026-09-27 19:01:57 +08:00
Logan-Luo 462a8dfde5 fix(title): budget thinking models in AI session title generation (#1340) (#1382)
Co-authored-by: realLoganLuo <realLoganLuo@users.noreply.github.com>
Co-authored-by: 程序员阿江-Relakkes <relakkes@gmail.com>
2026-09-27 18:57:01 +08:00
程序员阿江(Relakkes) 76619c9c64 fix(site): choose first-visit language from browser 2026-09-27 01:35:49 +08:00
程序员阿江(Relakkes) bb84a9621d feat(site): redesign landing page and documentation 2026-09-27 01:05:17 +08:00
程序员阿江(Relakkes) 1ee148e643 merge: integrate remote main with local development 2026-09-26 11:23:08 +08:00