Merge lark sheets development branch#1833
Conversation
Add a font_family field to cell_styles so a cell's font name can be set and read back through every style entry point: - +cells-set (--cells JSON) and +cells-set-style / +cells-batch-set-style gain a font_family field / --font-family flat flag - +workbook-create / +table-put --styles accept font_family in cell_styles - +cells-get returns font_family helpers.go buildCellStyleFromFlags reads the --font-family flag; lark_sheet_workbook.go allows font_family in the --styles cell_styles whitelist; data/ + skills/ are synced from sheet-skill-spec.
…criptions - Move cross-cutting editing rules and execution notes into the root SKILL.md and drop the now-redundant core-operations reference - Clarify flag descriptions: offset must be explicit inside +batch-update, range prefixes written bare (no quotes), chart requires a dim index, untyped --values lose date/number types, ungroup level semantics - Sync the corresponding reference docs
…1578) * perf(sheets): cap fan-out cell-matrix materialization to prevent OOM The +cells-set-style / +dropdown-set / +cells-batch-set-style / +dropdown-update shortcuts expand a single A1 range into a rows×cols matrix of per-cell maps client-side (the backing set_cell_range tool takes an explicit cells matrix). rangeDimensions() had no upper bound, so a tiny input like "A1:Z100000" balloons into ~2.6M heap maps (~900MB, doubled again by json.Marshal) and can OOM the process before the request is even sent. Add a 50000-cell safety cap (checkStampMatrixBudget) gating every fan-out materialization point, matching the documented but never-wired --max-cells default. Oversized ranges now fail fast with a clear validation error instead of allocating. Also preallocate the per-op slices now that the range count is known up front. Adds benchmarks + a boundary test as regression guards. * perf(sheets): cap table-put/batch fan-out materialization (siblings of the cell-matrix cap) The single-range fan-out cap (maxStampMatrixCells) left three sibling ingress paths uncapped, each able to materialize an unbounded matrix or op set in memory before the request leaves: - +table-put / +workbook-create --sheets/--values: buildSheetMatrix builds the whole rows×cols matrix before slicing it into per-write batches; tablePutMaxCellsPerWrite only bounds the batch size, not the total input. Add tablePayload.checkCellBudget (1M-cell guardrail), enforced in validate() and in buildValuesPayload (the --values path bypasses validate()). - batch fan-out (+cells-batch-set-style / +dropdown-update): per-range checkStampMatrixBudget can't stop many ranges from summing past the cap. Add an aggregate cell budget (checkBatchStampBudget) and a shared maxBatchRanges (100) count cap in validateDropdownRanges — covering all fan-out commands and replacing the now-redundant +dropdown-delete count check. - +batch-update: cap --operations at maxBatchOperations (100) in translateBatchOperations. Adds boundary regression tests for each cap. go vet + gofmt clean; full shortcuts/sheets + backward suites green. * test(sheets): measure table-put matrix materialization cost Add BenchmarkBuildSheetMatrix_* and TestTablePutMatrixPeakMemory mirroring the fan-out probes. Confirms the +table-put/+workbook-create ingress has the same OOM profile as the single-range stamp: 2.6M cells → ~917 MB / 5.3M allocs (+875 MB resident heap) materialized before the first write — now rejected up front by checkCellBudget.
+pivot-list 返回 info(page_range/content_range/error_state 等): 1) 判断目标单元格在透视表内(改配置 +pivot-update)还是区域外(改值 +cells-set); 2) 透视表展开后会覆盖已有数据,落点强烈优先默认自动新建子表; 3) 创建后用 info.error_state / content_range 校验有没有覆盖/冲突。
Wraps the new verify_formula read tool in a CLI shortcut so AI agents
can run write-then-zero-error verification end-to-end:
lark-cli sheets +formula-verify --url <url>
Scans formulas + cell error states across one or more sub-sheets and
returns a JSON status report (success / errors_found / partial).
Aggregates all 7 Excel error categories (#REF! / #DIV/0! / #VALUE! /
#NAME? / #NULL! / #NUM! / #N/A) plus compile failures into one
envelope; the tool always reports every error in the scan window —
callers needing a subset filter the returned error_summary
client-side. The internal scan cap is hidden from callers; when it
trips the response sets has_more=true and includes a warning_message
asking the caller to narrow --range / split --sheet-id and continue.
Flags follow the lark-sheets convention:
- --url / --spreadsheet-token (XOR public)
- --sheet-id / --sheet-name (repeat or comma-separate; mutually
exclusive)
- --range (repeatable A1)
- --max-locations (default 20)
- --exit-on-error (CI gate: status='errors_found' → exit 2 with
failed_precondition)
Generated artifacts (skills/lark-sheets/{SKILL.md, references/
lark-sheets-formula-verify.md}, shortcuts/sheets/data/flag-defs.json,
shortcuts/sheets/flag_defs_gen.go) are mirrored from sheet-skill-spec
generated/ via 'npm run sync:cli'. shortcuts.go registers
FormulaVerify alongside the other lark_sheet_formula_verify skill
shortcuts so +formula-verify is discoverable from
'lark-cli sheets --help'.
Tests cover the dry-run wire shape (excel_id + sheet_ids/sheet_names/
ranges/max_locations packing), the read scope (invoke_read URL), the
mutually-exclusive selector validation, the non-positive
--max-locations guard, and the --exit-on-error status matrix
(success/partial/errors_found/unknown).
feat(sheets): add +formula-verify shortcut for verify_formula tool
feat(pivot): lark-sheets pivot reference 补 +pivot-list info 说明与落点覆盖校验
…tatus shortcuts BE-1 + BE-2 (larksuite/cli lark-sheets) for spec sheet-history-revert. Three thin callTool wrappers over facade-agg history tools, following the existing sheets Validate/DryRun/Execute + --url/--spreadsheet-token(/--token) locator convention: - +history-list (read, history_list): passes the tool output through verbatim; facade-agg already does the minor_histories/4-field/RFC3339 transform. - +history-revert (write, history_revert): --history-version-id required, enforced at Validate stage with a typed *errs.ValidationError (no request on missing); returns the async receipt. - +history-revert-status (read, history_revert_status): polls in-progress / success / failure. Flags declared inline (not via *_gen.go) — flag_defs_gen.go / data/flag-defs.json are synced from sheet-skill-spec (BE-3) and must not be hand-edited. Notes: - history_revert / history_revert_status depend on facade-agg's downstream RPC wiring, a DEFERRED follow-up; the tools return a "not wired yet" guard today. These CLI wrappers are correct and go live when the backend follow-up lands. +history-list is fully functional now. - TestFlagDefsGen_MatchesJSON fails on baseline (pre-existing BE-3 gen/json drift); resolves once BE-3 sync:cli regenerates flag defs for these shortcuts. Validation: go build ./shortcuts/sheets/... PASS; new tests (TestHistoryShortcuts_DryRun, TestHistoryRevert_MissingVersionID) PASS. Spec source: active@2acd94a24ac3f835357a274a02344f78435bcc1c39ad0d695ce587f0cbddfb21
…kill-spec (BE-3) Synced artifacts for the history shortcuts from ee/sheet-skill-spec (SSOT), landed surgically (history-only) to avoid regressing this branch's newer skills/lark-sheets content: - skills/lark-sheets/references/lark-sheets-history.md (new, mirrored). - skills/lark-sheets/SKILL.md: + Lark Sheet History references-table row only. - shortcuts/sheets/data/flag-defs.json: + 3 history shortcuts (additive; no existing entries touched). - shortcuts/sheets/flag_defs_gen.go: regenerated via go generate ./shortcuts/sheets/... (this also resolves the pre-existing flag-defs/gen drift — TestFlagDefsGen_MatchesJSON now passes). NOT a full mirror: the rest of skills/lark-sheets/ + flag-schemas.json on this branch (feat/lark-sheets-develop) are NEWER than the sheet-skill-spec worktree's canonical (e.g. /wiki/ URL support, schema_version 3). A wholesale sync:cli would have reverted them, so only the history delta is taken here. Full re-sync should happen once sheet-skill-spec canonical is realigned with this branch. Validation: go generate clean; go test ./shortcuts/sheets/ (TestFlagDefsGen_MatchesJSON, TestHistory*) PASS. Spec source: active@2acd94a24ac3f835357a274a02344f78435bcc1c39ad0d695ce587f0cbddfb21
…sion id BE-2 gap surfaced by PPE E2E: +history-revert-status sent history_version_id, but the facade-agg history_revert_status tool keys on transaction_id (the async receipt returned by +history-revert), so it returned "[40400] transaction_id is required". Give the status shortcut its own --transaction-id flag + input (excel_id + transaction_id); revert keeps --history-version-id. Tests updated.
…tFlagsFor) TestFlagsFor_EveryRegisteredCommandHasDefs was RED: generated flag-defs drifted from the hand-written history shortcuts. - +history-revert-status: flag-defs had --history-version-id; the BE-2 fix switched the shortcut to --transaction-id. Updated the entry to transaction-id. - +history-revert / -status --history-version-id were marked required="required", but the inline flags are cobra-optional (requiredness enforced in Validate). Set required="optional" to match. Regenerated flag_defs_gen.go. NOTE: canonical source is sheet-skill-spec (BE-3); apply the same change upstream or the next sync:cli will regress this.
…nsaction-id) Mirror the upstream BE-2 fix in canonical-spec/references/lark_sheet_history/ cli-reference.md: +history-revert-status now uses --transaction-id (taken from the async receipt returned by +history-revert), and +history-revert's --history-version-id flips required→optional (Validate enforces requiredness at runtime). This file is the only history-only delta from the upstream sheet-skill-spec sync; the rest of skills/lark-sheets/ stays on the cli's newer baseline (/wiki/ URL support, +cells-set-image / +float-image-create, etc.) to match commit 8ae516d's history-only mirror policy. Spec source companion change: feat/sheet-history-revert in ee/sheet-skill-spec, canonical-spec/{tool-shortcut-map.json,references/ lark_sheet_history/cli-reference.md}.
Spec follow-up sheet-history-revert: thread the history_list pagination
contract through the +history-list shortcut.
- shortcuts/sheets/lark_sheet_history_list.go:
+ --end-version (int, optional). Mapped to the tool input's `end_version`
only when explicitly set (so the server treats absence as
"first page / latest"), via runtime.Changed / runtime.Int (matches the
+formula-verify --max-locations precedent).
+ Tip: pass next_end_version from the response on the next call;
capture exits the pagination loop when the server omits the field.
- shortcuts/sheets/lark_sheet_history_test.go: + dry-run case asserting
--end-version 12345 lands as input.end_version=12345 (post-JSON
unmarshal float64).
- skills/lark-sheets/references/lark-sheets-history.md: synced from
ee/sheet-skill-spec (commit 39c6b61). Adds the "倒序分页" caveat row +
--end-version flag + pagination Examples line. Drops the internal
MajorHistory.Version implementation detail per spec follow-up.
- shortcuts/sheets/data/flag-defs.json: synced from spec (+history-list
+--end-version int optional).
- shortcuts/sheets/flag_defs_gen.go: regenerated via
`go generate ./shortcuts/sheets/...`.
Companion changes:
- ee/sheet-skill-spec MR !37: spec-tables + tool-schemas pagination
contract (commits 09e8604, 39c6b61).
- ee/sheet-facade-agg MR !1028: history_list tool plumbs end_version,
emits next_end_version + has_more (omitted at earliest page),
defaults PageSize=20 to datarpc.
Validation:
- go build ./shortcuts/sheets/... PASS
- go test ./shortcuts/sheets/... PASS (sheets + backward)
- TestHistoryShortcuts_DryRun (5 cases incl. new --end-version case): PASS
- TestHistoryRevert_MissingRequiredFlag: PASS
- TestFlagsFor_EveryRegisteredCommandHasDefs: PASS
- TestFlagDefsGen_MatchesJSON: PASS
… + revert max-cells default drift Two issues surfaced during MR !37 review: 1) +history-revert --history-version-id requiredness was set as "optional" in the spec table (BE-2 fix dc5fe0e) so cobra wouldn't block before Validate. Per upstream review the flag should be required-by-cobra so the user gets the standard "required flag(s)" gate immediately and the runtime contract matches the JSON shape. - shortcuts/sheets/lark_sheet_history_revert.go: historyVersionIDFlag now sets Required: true. Validate keeps a trim/empty-string guard so '--history-version-id ""' still fails as a typed *errs.ValidationError (cobra accepts empty strings as "set"). - shortcuts/sheets/data/flag-defs.json: +history-revert --history-version-id required: optional -> required. - shortcuts/sheets/flag_defs_gen.go: regenerated. - shortcuts/sheets/lark_sheet_history_test.go: TestHistoryRevert_MissingRequiredFlag split into per-shortcut subtests; +history-revert asserts cobra's "required flag(s)" contract (raw err — the test rig calls cmd.Execute directly so it doesn't see the cmd dispatcher's typed envelope wrap); +history-revert-status keeps the typed *errs.ValidationError contract (its --transaction-id stays cobra-optional + Validate-enforced). 2) max-cells safety cap was accidentally rewritten from 200000 to 50000 by the last sync from sheet-skill-spec (the spec canonical side fell out of date — fixed separately on the spec MR follow-up). Restore desc: "Safety cap; default 200000" / default: "200000" so +cells-get / +csv-get keep the documented cap. Validation: - go test ./shortcuts/sheets/... PASS - TestHistoryRevert_MissingRequiredFlag (both subtests) PASS - TestHistoryShortcuts_DryRun (incl. +history-list pagination case) PASS - TestFlagsFor_EveryRegisteredCommandHasDefs PASS - TestFlagDefsGen_MatchesJSON PASS
…red (match +history-revert) Companion to commit 6ca35b0: same gating model now applies to both history receipts. - shortcuts/sheets/lark_sheet_history_revert.go: transactionIDFlag.Required=true. Validate keeps a trim/empty-string guard for '--transaction-id ""'. - shortcuts/sheets/data/flag-defs.json: +history-revert-status --transaction-id required: optional -> required (synced from sheet-skill-spec @9ca814d). - shortcuts/sheets/flag_defs_gen.go: regenerated. - shortcuts/sheets/lark_sheet_history_test.go: TestHistoryRevert_MissingRequiredFlag/+history-revert-status moved to the cobra "required flag(s)" text contract (the test rig invokes the shortcut via cmd.Execute, which sees the raw cobra error directly without the dispatcher's typed wrap). Drop now-unused `errors` and `errs` imports. Validation: - go test ./shortcuts/sheets/... PASS (sheets + backward) - TestFlagsFor_EveryRegisteredCommandHasDefs: PASS - TestFlagDefsGen_MatchesJSON: PASS - TestHistoryRevert_MissingRequiredFlag (both subtests): PASS
Companion to commit 9fa7331 (transaction-id) and 6ca35b0 (history-version-id): the two flag tables in skills/lark-sheets/references/lark-sheets-history.md still showed 'optional' even though the canonical contract — and shortcuts/sheets/data/ flag-defs.json — already moved to 'required'. The earlier syncs only picked up the data file from spec; the skill markdown drift slipped through. Pull in the spec-side regenerated reference (ee/sheet-skill-spec @9ca814d) so the human-readable doc matches the wire contract.
feat(sheets): add +history-list / +history-revert / +history-revert-status shortcuts
…e guidance in references
… chart/cond-format/filter rows - SKILL.md quick-reference: add a "read before acting" column pointing each intent at its reference doc; add chart / cond-format / filter rows. - Reframe number-vs-text decision to follow the data's nature (measure vs identifier), not whether the current task happens to sort/sum; a leaderboard/report "display only" use does not make a percentage text. - write-cells reference: mirror the same rule and the +cells-set fallback for layouts +table-put cannot express.
* feat(sheets): add +changeset-get shortcut for changeset review Wrap the get_changeset read tool: fetch the raw changeset (edit actions) between two versions to review whether an AI edit fulfilled the request. --start-revision required, --end-revision optional (defaults to latest), gap capped at 100. Adds flag-defs entry + regenerated gen, the ChangesetGet shortcut + tests, and skill docs. * feat(sheets): add +get-revision shortcut Return a spreadsheet's current document revision without pulling the full sub-sheet listing. +get-revision is a read-only derivative over get_workbook_structure (the lightest read — token only, no range) that projects the response down to the single revision field. Adds flag-defs entries and a unit test for the projection helper. * feat: 同步 spec 修改 * feat(sheets): rename +get-revision to +revision-get * feat: 移除 ppe 环境请求头 --------- Co-authored-by: wenzhuozhen <wenzhuozhen@bytedance.com>
The synthetic token prefix for imported office spreadsheets is being renamed from fake_office_ to local_office_. Accept either prefix when mapping a spreadsheet token to the drive media parent_type so image uploads keep working across the rename (main package and backward compat copy).
…nForFlag changesetRevisions called common.FlagErrorf, which does not exist, breaking the build. Use sheetsValidationForFlag so the errors carry the offending flag param like the rest of the sheets validation paths. Also reword two doc comments in lark_sheet_history_revert.go that used '' for an empty shell string: gofmt (Go 1.19+) rewrites '' in doc comments to a curly quote, leaving the file permanently unformatted.
|
Follow-up attribution notes from the review:
I opened #1839 only for the |
|
I found a few issues that look worth fixing before merging:
I also ran: go test ./shortcuts/sheets/...
go test ./shortcuts/common ./shortcuts |
|
@fangshuyu-768 Follow-up on items 1 and 3:
|
Local .xls files that are actually OOXML (an .xlsx exported or renamed to .xls) failed +workbook-import with a cryptic backend "xml_version_not_support" because the CLI trusted the file name extension. +workbook-import now sniffs the file's leading magic bytes (PK -> xlsx, OLE2 -> xls) and passes the true extension to the drive import core via a new optional ImportParams.FileExtension override, correcting both the file_extension and the staged media file name (the latter avoids the backend's "import file extension not match", code 1069910). A declared Excel file whose bytes match neither container is rejected locally with a prescriptive error instead of the opaque backend failure. The drive import core gains only the neutral FileExtension override (empty = infer from the file name, i.e. unchanged behavior for drive +import); all Excel sniffing/correction policy lives in the sheets shortcut.
1fe3805 to
8708ae4
Compare
439d214 to
9f93cce
Compare
Use generated flag defs for history revert commands, enforce control-character validation, and sync the refreshed lark-sheets references from sheet-skill-spec.
9f93cce to
74d65e6
Compare
5d9cb51 to
31a8b47
Compare
Summary
Testing
Summary by CodeRabbit
+revision-get,+changeset-get,+formula-verify, and+history-list/+history-revert/+history-revert-status.+rows-resize/+cols-resizewith--height/--width,--heights/--widthsmap form, plusfont-familysupport and expanded chart gradients.sheets --helpto hide deprecated aliases from listings while keeping them executable.+csv-putnon-interactive stdin fallback.