4 months ago
3bf5455* fix(canvas): prevent hooks-order crash and markdown round-trip data loss
Canvas is mounted unkeyed, so switching a markdown/text file to a csv/xlsx/pptx re-rendered the same instance with early returns sitting above 7 useEffect/useCallback hooks, crashing React ("rendered fewer hooks than expected"). Move the spreadsheet/pptx returns below all hooks and guard the editor-only effects so preview behavior is unchanged.
Also fix lossy markdown editing: nodeToMarkdown emitted "-" for ordered <li> (numbered lists silently became bullets) and markdownToHtml treated `*emphasis*`/`-text` lines as list items; require whitespace after list markers and serialize <ol> items as "N.". Harden link hrefs against javascript:/data: schemes.
Add canvasMarkdown unit tests and a hooks-stability regression test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(canvas): editable Excel-like spreadsheet with lossless cell writes
Add direct cell editing to the canvas spreadsheet view via a new cowork/workspace/spreadsheet/edit JSON-RPC method. CSV edits use a quote-aware round trip that preserves BOM, line terminator, and trailing-newline state. XLSX edits are a surgical zip patch (jszip + fast-xml-parser): only the target worksheet XML is rewritten and the cell keeps its style index, so fonts, number formats, charts, and other sheets stay byte-identical — SheetJS's community build cannot write styles, so the workbook is never round-tripped through it.
Rework SpreadsheetPreview into an Excel-like grid: formula/value bar, click-to-select, inline editing (double-click/Enter/F2/type), Esc/Enter/Tab semantics, and arrow/Tab/Enter navigation with viewport auto-paging; commits optimistically then refetches. Add an in-app Maximize/Restore full-bleed layout alongside the existing pop-out window.
Wire the client store action + socket helper, document the method in websocket-protocol.md, regenerate the JSON-RPC artifacts, and add backend (lossless CSV/XLSX) and UI (edit/formula-bar/navigation/maximize) tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix artifacts
* update
* fix(canvas): polish spreadsheet workbook preview
* fix(canvas): simplify spreadsheet preview chrome
* fix(canvas): harden spreadsheet objects and styling
* fix(canvas): keep workbook links inside electron
* feat(canvas): improve spreadsheet editing
* more
* feat: replace spreadsheet canvas with Univer
* fix: suppress noisy Univer text warnings
* Add spreadsheet autosave and external refresh
* fix(spreadsheet): apply batch patches as one atomic read-modify-write
patchSpreadsheetBatch previously delegated each operation to
editSpreadsheetCell/formatSpreadsheetRange, so every op independently
re-read and re-wrote the whole file (zip load + generate). A bulk paste
from the Univer canvas (one op per changed cell) meant N full-file
rewrites, and a mid-batch failure left ops 1..N-1 persisted with no
rollback. Concurrent batches to the same file could also lose edits via
read-modify-write races.
Introduce a shared in-memory editing core: the file is read/unzipped
once, all cell and format ops apply to cached worksheet XML + a single
parsed stylesheet, then the result is validated and written exactly
once. Single-cell edit, range format, and batch patch all route through
the same core, so behavior stays identical while batches become atomic.
A per-file write lock serializes concurrent read-modify-write cycles
against the same resolved path so neither edit is lost.
Also use the semantic `text-primary` token for the dirty save-state
icon instead of the raw `text-[var(--accent)]` arbitrary value.
Adds regression tests for mid-batch atomicity (file stays byte-identical
on failure) and concurrent-edit serialization.
https://claude.ai/code/session_01VAPGeo1v6uzu9MG7u4DnGN
* fix(desktop): clear biome lint errors in canvas spreadsheet UI
The Lint CI lane was red on pre-existing biome findings in the canvas
spreadsheet code:
- univerSpreadsheet.ts: drop an unused type import and replace an
assignment-in-expression (`??=` inside a binding) with an explicit
initialise-then-store.
- styles.css: annotate the deliberate Univer formula-bar `!important`
override with a biome-ignore, and move the universal `box-sizing`
reset above the `[data-cowork-univer-canvas] *` rule to fix descending
specificity.
- SpreadsheetPreview.tsx: give the formatting toolbar `role="toolbar"`
and the color groups `role="group"` so their `aria-label`s are valid
(a sub-group inside a toolbar is the correct ARIA pattern, so the
redundant useSemanticElements suggestion is suppressed with a reason).
https://claude.ai/code/session_01VAPGeo1v6uzu9MG7u4DnGN
* fix(spreadsheet): no-op empty batches and attribute batch errors correctly
Addresses two review findings on the atomic-batch refactor:
- An empty `operations` array now short-circuits to success before
touching disk. Previously it flowed into the executor, which re-zipped
the XLSX (changing the fingerprint) or re-quoted the CSV (possibly
changing line endings/quotes) despite no edits.
- A throw inside an operation (e.g. an invalid color reaching
normalizeColor) is now attributed to that operation's index instead of
a hard-coded 0, so the batch no longer reports "Operation 1 failed"
when a later op is the culprit. Failures not tied to a specific op
(file read/write, post-batch validation, unsupported type) carry a
null index and report without an operation prefix. As a bonus the XLSX
path skips the rewrite when no operation actually mutated the workbook.
Adds regression tests for the empty-batch no-op (file stays byte- and
mtime-identical) and for correct operation-index attribution on a
mid-batch throw.
https://claude.ai/code/session_01VAPGeo1v6uzu9MG7u4DnGN
* style: satisfy biome check (format + import ordering) for the Lint CI lane
The CI "Lint" job runs `bun run check` (biome lint + format + organize
imports), not just `biome lint`, so pre-existing format and import-order
drift in the canvas spreadsheet files (plus the notarization helper
carried over from main) kept the lane red. Applied biome's safe
formatting and import-ordering fixes; no behavior changes.
https://claude.ai/code/session_01VAPGeo1v6uzu9MG7u4DnGN
* fix: guard referenced context and large file reads
Keep queued steer reference context attached to the steer that supplied it, cap forced skill injection by per-skill and total byte limits, and prevent desktop readFile from loading oversized files.
Show a Canvas truncation banner when preview reads are partial so large files remain read-only with visible user guidance.
Tests: bun test test/session/agentSession.messaging.test.ts test/session.syntheticSkillInjection.test.ts; bun test apps/desktop/test/ipc-files.test.ts apps/desktop/test/canvas-hooks-stability.test.tsx; bun run typecheck; bun run docs:check; bun lint; bun test --max-concurrency 1
* refactor(spreadsheet): remove legacy preview surface
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(desktop): render spreadsheet canvas requests as a chat bubble
Parse the <spreadsheet_canvas_request> envelope the Univer canvas sends
and show a compact file/sheet/region header above the user's request
instead of the raw XML blob. Falls through cleanly for plain and legacy
canvas-edit messages.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(desktop): unify all canvas requests into one chat bubble
Emit the structured XML envelope from the document/text/slide canvas too
(not just spreadsheets) and parse every canvas request through a single
parseCanvasRequest + CanvasRequestBody, with a legacy markdown fallback so
historical transcripts render the same compact file/region header.
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(desktop): share canvas request envelope helpers
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(spreadsheet): preserve canvas prompts and number formats
* fix(spreadsheet): persist canvas merge patches
* fix(spreadsheet): protect failed canvas saves
* fix(spreadsheet): refresh canvas prompt context
* fix(spreadsheet): serialize canvas saves
* fix(spreadsheet): keep canvas context live
* fix(desktop): wire canvas maximize control
* fix(desktop): harden spreadsheet canvas saves
* fix(server): harden canvas previews
* fix(spreadsheet): persist column resets
* fix(spreadsheet): preserve workbook date and style metadata
* fix(desktop): preserve canvas editor lifecycle
* fix(spreadsheet): harden canvas save bounds
* fix(desktop): avoid spreadsheet canvas ownership conflicts
* fix(desktop): report spreadsheet unload save failures
* fix(desktop): preserve Windows markdown links
* fix(desktop): keep maximized canvas unclipped
* test(desktop): isolate canvas lifecycle mocks
* fix: refresh stale workspace tools skills
* feat: detect marketplace extension updates
* fix: guard spreadsheet saves and plugin update state
* chore: format marketplace update changes
* fix: rebase spreadsheet saves after disk conflicts
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>Parent57c99a5