[codex] Respect --brand lark in config init --new#4
Open
jnuyao wants to merge 1 commit into
Open
Conversation
jnuyao
marked this pull request as ready for review
March 28, 2026 08:21
chanthuang
added a commit
that referenced
this pull request
Apr 15, 2026
- Escape sigID in BuildSignatureHTML to prevent HTML attribute injection - Add SSRF protection to downloadSignatureImage: enforce https, validate host, use context timeout (30s), do not send Bearer token — aligned with existing downloadAttachmentContent security practices - Add nil guard for child in removeMIMEPartByCID loop - Expose insert_signature/remove_signature in supported_ops flat list - Fix +send doc: remove "引用块之前" (new emails have no quote block) Note: CodeRabbit #4 (splitAtSignature boundary bug) is a false positive — FindMatchingCloseDiv returns the position AFTER </div>, so slice boundaries are correct. Change-Id: I5363d8a070e2e01200efdcb8235832627d1ff9a5 Co-Authored-By: AI
chanthuang
added a commit
that referenced
this pull request
Apr 15, 2026
- Escape sigID in BuildSignatureHTML to prevent HTML attribute injection - Add SSRF protection to downloadSignatureImage: enforce https, validate host, use context timeout (30s), do not send Bearer token — aligned with existing downloadAttachmentContent security practices - Add nil guard for child in removeMIMEPartByCID loop - Expose insert_signature/remove_signature in supported_ops flat list - Fix +send doc: remove "引用块之前" (new emails have no quote block) Note: CodeRabbit #4 (splitAtSignature boundary bug) is a false positive — FindMatchingCloseDiv returns the position AFTER </div>, so slice boundaries are correct. Change-Id: I5363d8a070e2e01200efdcb8235832627d1ff9a5 Co-Authored-By: AI
fangshuyu-768
added a commit
that referenced
this pull request
Apr 30, 2026
PR #467's review thread had three substantive comments (`fangshuyu-768`, 2026-04-21) that the prior reply messages claimed were fixed in commit 7d4b556 — but that commit no longer exists on the branch (lost in a rebase / squash), and the head still ships the original buggy code. This commit makes the fixes real. Three behavior fixes in shortcuts/doc/markdown_fix.go: 1. (#5) Tighten the type= and background-color= regex anchors. \b sits at any word/non-word boundary, and `-` is a non-word char, so `\btype=` also matched the suffix of `data-type=` — a tag like `<callout data-type="warning">` would emit a bogus light-yellow hint. Switched both regexes to `(?:^|\s)…` so a real attribute separator is required. The same anchor on background-color closes the symmetric case where a `data-background-color=` attribute would silently suppress the real hint. 2. (#4) WarnCalloutType is now a fence-aware line walker. Previously the regex ran over the entire markdown body, so a callout sample inside a documentation code fence (```markdown … ```) would generate a phantom stderr hint every time the docs mentioned the feature. The walker tracks fence state via the existing codeFenceOpenMarker / isCodeFenceClose helpers from docs_update_check.go, which handle both backtick and tilde fences per CommonMark §4.5. 3. (#3) Drop the ReplaceAllStringFunc-as-iterator pattern. The previous code routed callout iteration through a rewrite primitive whose rebuilt-string return value was discarded, then ran the same regex a second time inside the callback to recover the capture groups. New scanCalloutTagsForWarning helper uses FindAllStringSubmatch — one pass, no thrown-away allocation, intent matches the surface (read-only scan, not a mutator). Tests: 5 new TestWarnCalloutType subtests pin each contract: - data-type attribute does not trigger hint (#5) - data-background-color does not suppress hint (#5, symmetric) - callout inside backtick fence emits no hint (#4) - callout inside tilde fence emits no hint (#4) - callout after fence close still emits hint (#4, fence-state reset) All 14 TestWarnCalloutType cases pass; go vet / golangci-lint --new-from-rev=origin/main both clean.
fangshuyu-768
pushed a commit
that referenced
this pull request
Apr 30, 2026
* feat(doc): expand callout type= shorthand into background-color and border-color When users write <callout type="warning" emoji="📝"> without an explicit background-color, the Feishu doc renders the block with no color. This commit adds fixCalloutType() which maps the semantic type= attribute to the corresponding background-color/border-color pair accepted by create-doc. - warning → light-yellow/yellow - info/note → light-blue/blue - tip/success/check → light-green/green - error/danger → light-red/red - caution → light-orange/orange - important → light-purple/purple Explicit background-color or border-color attributes are always preserved. The fix is applied via prepareMarkdownForCreate() in both +create and +update paths, and also inside fixExportedMarkdown() for round-trip fidelity. * refactor(doc): replace silent callout type→color injection with hint output Per reviewer feedback (SunPeiYang996), silently rewriting user Markdown is the wrong layer for this adaptation. The type→color mapping is not part of the Feishu spec, and covert transforms make debugging harder. Replace fixCalloutType() (which rewrote the Markdown) with WarnCalloutType() which leaves the Markdown unchanged and instead writes a hint line to stderr for each callout tag that has type= but no background-color, telling the user the recommended explicit attributes to add: hint: callout type="warning" has no background-color; consider: background-color="light-yellow" border-color="yellow" Also fixes CodeRabbit feedback: the type= regex now accepts both single-quoted and double-quoted attribute values (type='warning' and type="warning"). * fix(doc): harden background-color detection in WarnCalloutType CodeRabbit flagged that the previous strings.Contains(attrs, "background-color=") check missed forms like 'background-color = "light-red"' with whitespace around the equals sign. Replace with a regex that tolerates optional whitespace, and add a regression test. * fix(doc): close real review gaps left over after rebase PR #467's review thread had three substantive comments (`fangshuyu-768`, 2026-04-21) that the prior reply messages claimed were fixed in commit 7d4b556 — but that commit no longer exists on the branch (lost in a rebase / squash), and the head still ships the original buggy code. This commit makes the fixes real. Three behavior fixes in shortcuts/doc/markdown_fix.go: 1. (#5) Tighten the type= and background-color= regex anchors. \b sits at any word/non-word boundary, and `-` is a non-word char, so `\btype=` also matched the suffix of `data-type=` — a tag like `<callout data-type="warning">` would emit a bogus light-yellow hint. Switched both regexes to `(?:^|\s)…` so a real attribute separator is required. The same anchor on background-color closes the symmetric case where a `data-background-color=` attribute would silently suppress the real hint. 2. (#4) WarnCalloutType is now a fence-aware line walker. Previously the regex ran over the entire markdown body, so a callout sample inside a documentation code fence (```markdown … ```) would generate a phantom stderr hint every time the docs mentioned the feature. The walker tracks fence state via the existing codeFenceOpenMarker / isCodeFenceClose helpers from docs_update_check.go, which handle both backtick and tilde fences per CommonMark §4.5. 3. (#3) Drop the ReplaceAllStringFunc-as-iterator pattern. The previous code routed callout iteration through a rewrite primitive whose rebuilt-string return value was discarded, then ran the same regex a second time inside the callback to recover the capture groups. New scanCalloutTagsForWarning helper uses FindAllStringSubmatch — one pass, no thrown-away allocation, intent matches the surface (read-only scan, not a mutator). Tests: 5 new TestWarnCalloutType subtests pin each contract: - data-type attribute does not trigger hint (#5) - data-background-color does not suppress hint (#5, symmetric) - callout inside backtick fence emits no hint (#4) - callout inside tilde fence emits no hint (#4) - callout after fence close still emits hint (#4, fence-state reset) All 14 TestWarnCalloutType cases pass; go vet / golangci-lint --new-from-rev=origin/main both clean.
HomyeeKing
pushed a commit
to HomyeeKing/cli
that referenced
this pull request
May 6, 2026
…ksuite#467) * feat(doc): expand callout type= shorthand into background-color and border-color When users write <callout type="warning" emoji="📝"> without an explicit background-color, the Feishu doc renders the block with no color. This commit adds fixCalloutType() which maps the semantic type= attribute to the corresponding background-color/border-color pair accepted by create-doc. - warning → light-yellow/yellow - info/note → light-blue/blue - tip/success/check → light-green/green - error/danger → light-red/red - caution → light-orange/orange - important → light-purple/purple Explicit background-color or border-color attributes are always preserved. The fix is applied via prepareMarkdownForCreate() in both +create and +update paths, and also inside fixExportedMarkdown() for round-trip fidelity. * refactor(doc): replace silent callout type→color injection with hint output Per reviewer feedback (SunPeiYang996), silently rewriting user Markdown is the wrong layer for this adaptation. The type→color mapping is not part of the Feishu spec, and covert transforms make debugging harder. Replace fixCalloutType() (which rewrote the Markdown) with WarnCalloutType() which leaves the Markdown unchanged and instead writes a hint line to stderr for each callout tag that has type= but no background-color, telling the user the recommended explicit attributes to add: hint: callout type="warning" has no background-color; consider: background-color="light-yellow" border-color="yellow" Also fixes CodeRabbit feedback: the type= regex now accepts both single-quoted and double-quoted attribute values (type='warning' and type="warning"). * fix(doc): harden background-color detection in WarnCalloutType CodeRabbit flagged that the previous strings.Contains(attrs, "background-color=") check missed forms like 'background-color = "light-red"' with whitespace around the equals sign. Replace with a regex that tolerates optional whitespace, and add a regression test. * fix(doc): close real review gaps left over after rebase PR larksuite#467's review thread had three substantive comments (`fangshuyu-768`, 2026-04-21) that the prior reply messages claimed were fixed in commit 7d4b556 — but that commit no longer exists on the branch (lost in a rebase / squash), and the head still ships the original buggy code. This commit makes the fixes real. Three behavior fixes in shortcuts/doc/markdown_fix.go: 1. (larksuite#5) Tighten the type= and background-color= regex anchors. \b sits at any word/non-word boundary, and `-` is a non-word char, so `\btype=` also matched the suffix of `data-type=` — a tag like `<callout data-type="warning">` would emit a bogus light-yellow hint. Switched both regexes to `(?:^|\s)…` so a real attribute separator is required. The same anchor on background-color closes the symmetric case where a `data-background-color=` attribute would silently suppress the real hint. 2. (larksuite#4) WarnCalloutType is now a fence-aware line walker. Previously the regex ran over the entire markdown body, so a callout sample inside a documentation code fence (```markdown … ```) would generate a phantom stderr hint every time the docs mentioned the feature. The walker tracks fence state via the existing codeFenceOpenMarker / isCodeFenceClose helpers from docs_update_check.go, which handle both backtick and tilde fences per CommonMark §4.5. 3. (larksuite#3) Drop the ReplaceAllStringFunc-as-iterator pattern. The previous code routed callout iteration through a rewrite primitive whose rebuilt-string return value was discarded, then ran the same regex a second time inside the callback to recover the capture groups. New scanCalloutTagsForWarning helper uses FindAllStringSubmatch — one pass, no thrown-away allocation, intent matches the surface (read-only scan, not a mutator). Tests: 5 new TestWarnCalloutType subtests pin each contract: - data-type attribute does not trigger hint (larksuite#5) - data-background-color does not suppress hint (larksuite#5, symmetric) - callout inside backtick fence emits no hint (larksuite#4) - callout inside tilde fence emits no hint (larksuite#4) - callout after fence close still emits hint (larksuite#4, fence-state reset) All 14 TestWarnCalloutType cases pass; go vet / golangci-lint --new-from-rev=origin/main both clean.
raistlin042
added a commit
that referenced
this pull request
May 21, 2026
…tput Address coderabbit threads #3/#4 + back-fill the 4 other cobra-Required sites with the same convention. Two-part change per site: 1. Exit code: assert.NotEqual(t, 0, result.ExitCode) -> result.AssertExitCode(t, 1). cobra's "required flag(s) ... not set" path always exits 1 (distinct from output.ErrValidation which exits 2); explicit code 1 catches a runner regression if either path silently shifts. 2. Output channel: result.Stderr -> result.Stdout+result.Stderr for the message contains-check. cobra writes the plain-text error to stderr today, but combining shields the test from a future runner that chose to route usage errors through the JSON envelope. Two new code comments at the first occurrence in apps_access_scope_get_dryrun_test.go and apps_create_dryrun_test.go document the cobra(1) vs Validate(2) split so future readers don't re-conflate the two paths. Note coderabbit's exit-code-2 suggestion was wrong: those sites are cobra Required failures, not output.ErrValidation, and exit 1. Tests would have gone red on adopting the suggestion as-is.
raistlin042
added a commit
that referenced
this pull request
May 21, 2026
…tput Address coderabbit threads #3/#4 + back-fill the 4 other cobra-Required sites with the same convention. Two-part change per site: 1. Exit code: assert.NotEqual(t, 0, result.ExitCode) -> result.AssertExitCode(t, 1). cobra's "required flag(s) ... not set" path always exits 1 (distinct from output.ErrValidation which exits 2); explicit code 1 catches a runner regression if either path silently shifts. 2. Output channel: result.Stderr -> result.Stdout+result.Stderr for the message contains-check. cobra writes the plain-text error to stderr today, but combining shields the test from a future runner that chose to route usage errors through the JSON envelope. Two new code comments at the first occurrence in apps_access_scope_get_dryrun_test.go and apps_create_dryrun_test.go document the cobra(1) vs Validate(2) split so future readers don't re-conflate the two paths. Note coderabbit's exit-code-2 suggestion was wrong: those sites are cobra Required failures, not output.ErrValidation, and exit 1. Tests would have gone red on adopting the suggestion as-is.
zhengzhijiej-tech
added a commit
that referenced
this pull request
May 21, 2026
Two latent bugs in the object_crud translator surfaced during BOE smoke testing of +batch-update. Both are schema-alignment fixes against manage_conditional_format_object / manage_filter_object as declared in sheet-skill-spec/canonical-spec/tool-schemas/mcp-tools.json. #4 +cond-format: rule_type path + enum vocabulary --------------------------------------------------- condFormatEnhance used to write the user's --rule-type value into `properties.rule.type` (nested under a `rule` object). The server schema actually puts it at flat `properties.rule_type` and silently drops the nested form — so every conditional-format create/update secretly built the wrong document. Worse, the CLI enum exposed via flag-defs.json was its own invented vocabulary (cellValue / formula / duplicate / unique / topBottom / aboveBelowAverage / dataBar / colorScale / iconSet / textContains / dateOccurring / blankCell / errorCell) — none of those values were the strings the server accepts. Fix: - condFormatEnhance now writes `properties.rule_type = <value>` directly (no nested `rule` object). - Synced flag-defs.json + lark-sheets-conditional-format.md enum vocabulary from base to match the server: duplicateValues, uniqueValues, cellIs, containsText, timePeriod, containsBlanks, notContainsBlanks, dataBar, colorScale, rank, aboveAverage, expression, iconSet. -⚠️ Breaking: scripts passing the old CLI-invented enum values (e.g. --rule-type cellValue) now get a cobra "invalid value … allowed: …" error listing the new vocabulary. No alias layer. - TestObjectCRUDShortcuts_DryRun's +cond-format-update case updated to assert the flat properties.rule_type shape + new enum. #5 +filter-{update,delete}: auto-inject filter_id = sheet_id ------------------------------------------------------------- manage_filter_object's contract is "filter_id === sheet_id" for the sheet-scoped filter (per per-tool description in mcp-tools.json), and update / delete operations MUST carry filter_id. Standalone filterUpdateInput / filterDeleteInput never set it, so the server rejected with "filter_id is required for update/delete operation" on every call — both standalone AND inside +batch-update. Fix: - filterUpdateInput / filterDeleteInput now set input["filter_id"] = sheetID. - Because filter_id must equal sheet_id (not sheet_name), update / delete reject when only --sheet-name is given — there's no network lookup available inside the builder. The friendly error points at +workbook-info for resolving sheet-name → sheet-id. - create still omits filter_id (server requires that — id is server-allocated on creation). - New tests: * TestObjectCRUDShortcuts_DryRun gains a +filter-update happy-path case asserting filter_id is auto-injected + --range hoisting. * +filter-delete case updated to assert filter_id presence. * TestBatchOp_RejectsBadSubOpInput gains two cases asserting both +filter-update and +filter-delete reject --sheet-name-only with the friendly error. Docs (#2 + #3 + #8) synced from sheet-skill-spec ------------------------------------------------- Companion doc fixes that landed via npm run generate:cli + sync:cli in sheet-skill-spec; included here because the regenerated flag-defs and references markdown are byte-tracked in this repo: - #2: lark-sheets-sheet-structure.md — +dim-{hide,unhide,group, ungroup} --start/--end desc changed from "(0-based, inclusive)" to "(0-based)" / "(exclusive)" to match the half-open range semantics the code has always implemented (requireDimRange: end > start; dimRange uses end - 1 for column end letters). - #3: lark-sheets-workbook.md — +sheet-move section gains a note about the batch-internal requirement to pass --sheet-id AND --source-index explicitly (sheetMoveBatchInput's constraint). - #8: lark-sheets-pivot-table.md — +pivot-create --properties example drops the stale data_range field (the actual server schema uses --source as a hoisted flag; properties only carries rows / columns / values / filters / show_*_grand_total).
raistlin042
added a commit
that referenced
this pull request
May 21, 2026
…tput Address coderabbit threads #3/#4 + back-fill the 4 other cobra-Required sites with the same convention. Two-part change per site: 1. Exit code: assert.NotEqual(t, 0, result.ExitCode) -> result.AssertExitCode(t, 1). cobra's "required flag(s) ... not set" path always exits 1 (distinct from output.ErrValidation which exits 2); explicit code 1 catches a runner regression if either path silently shifts. 2. Output channel: result.Stderr -> result.Stdout+result.Stderr for the message contains-check. cobra writes the plain-text error to stderr today, but combining shields the test from a future runner that chose to route usage errors through the JSON envelope. Two new code comments at the first occurrence in apps_access_scope_get_dryrun_test.go and apps_create_dryrun_test.go document the cobra(1) vs Validate(2) split so future readers don't re-conflate the two paths. Note coderabbit's exit-code-2 suggestion was wrong: those sites are cobra Required failures, not output.ErrValidation, and exit 1. Tests would have gone red on adopting the suggestion as-is.
6 tasks
zhengzhijiej-tech
added a commit
to zhengzhijiej-tech/cli
that referenced
this pull request
May 22, 2026
data/flag-defs.json is regenerated from the upstream sheet-skill-spec
canonical-spec; editing it here gets clobbered on the next sync. The
schema realignment for +dropdown-set / -update --colors / --highlight
removal needs to land on the base table first, then flow back through
sheet-skill-spec → larksuite-cli sync, not via a direct CLI-side edit.
Restore the previous flag entries verbatim. The Go-side change in
buildDropdownValidation still drops the wire fields, so:
- users passing --colors / --highlight today see the flag accepted
silently (no effect on the wire) until the upstream removal lands;
- after upstream removal + sync, both the flag declarations and the
Go-side handling will be in sync.
Functional fixes (larksuite#1 workbook-create, larksuite#3 dropdown-get, larksuite#4 dim-move,
larksuite#5 range-sort) and dropdown wire-shape rename (larksuite#2) are unaffected.
zhengzhijiej-tech
added a commit
to zhengzhijiej-tech/cli
that referenced
this pull request
May 22, 2026
These md files are sync targets generated from sheet-skill-spec; editing
them here gets clobbered on the next sync, same as data/flag-defs.json.
The --colors / --highlight row removals belong on the upstream base
table → canonical-spec sync, not here.
Restore the previous --colors / --highlight rows in both
lark-sheets-write-cells.md (+dropdown-set) and lark-sheets-batch-update.md
(+dropdown-update). The Go-side change in buildDropdownValidation still
drops the wire fields, so:
- users passing --colors / --highlight today see the flag accepted
silently (no effect on the wire) until upstream removes the flag;
- after upstream removal + sync, both flag declarations, ref docs, and
Go-side handling will be in sync.
Functional fixes (larksuite#1 workbook-create, larksuite#3 dropdown-get, larksuite#4 dim-move,
larksuite#5 range-sort) and dropdown wire-shape rename (larksuite#2) are unaffected.
zhengzhijiej-tech
added a commit
to zhengzhijiej-tech/cli
that referenced
this pull request
May 25, 2026
…ort with server schema Five separate E2E failures in shortcuts/sheets/ that all trace back to a CLI ↔ server contract mismatch. Each is independently scoped; bundling them because they share the test-report citation and the same one-line fix shape in most cases. larksuite#1 +workbook-create initial fill: omit sheet_id, use sheet_name "Sheet1" buildInitialFillInput sent {"sheet_id": ""} on the secondary set_cell_range call after creating the workbook. The empty value was a holdover from "...otherwise server picks first sheet" — but set_cell_range rejects an empty selector with "sheet_id or sheet_name is required" rather than falling back to the default sheet. Use sheet_name "Sheet1" instead. POST /sheets/v3/spreadsheets always creates that sheet on workbook creation, and set_cell_range accepts sheet_name as an equivalent selector — saves an extra get_workbook_structure round-trip just to learn the auto-generated id. larksuite#2 +dropdown-set / -update data_validation: 4 field renames + 2 deletes buildDropdownValidation emitted four fields that don't exist in the canonical set_cell_range.data_validation schema: - "values" (options list) → renamed to "items" - "multiple_values" → renamed to "support_multiple_values" - "colors" (per-option color) → removed (not in schema; flag also removed from data/flag-defs.json for +dropdown-set / -update) - "highlight_options" → removed (not in schema; flag also removed) The canonical schema lives at sheet-skill-spec/canonical-spec/tool- schemas/mcp-tools.json (set_cell_range tool, data_validation property); the colors / highlight knobs were CLI inventions the server never accepted, so removing the flags is correct (renaming would leave the flags broken). Skill reference docs (write-cells.md, batch-update.md) synced. validateDropdownOptionsColors lost its colors check; renamed to validateDropdownOptions to reflect the narrower contract. larksuite#3 +dropdown-get: split sheet prefix from range, pass via sheet selector dropdownGetInput sent "Sheet1!C2:C6" verbatim as a ranges[] entry. get_cell_ranges expects sheet_id / sheet_name as separate fields and ranges entries without the sheet prefix; the server bounced with "sheet not found, sheetId:" (empty). Use the existing splitSheetPrefixedRange helper (declared in lark_sheet_batch_update.go) to break "Sheet1!C2:C6" into ("Sheet1", "C2:C6"), then thread the sheet name through sheetSelectorForToolInput exactly like +cells-get does. larksuite#4 +dim-move: switch endpoint to /move_dimension + body key snake_case The shortcut was POSTing to /sheets/v2/spreadsheets/{token}/dimension_ range, which is the v2 insert-dimension endpoint and requires a top- level {"dimension": {...}} body. Move uses a separate endpoint: POST /sheets/v2/spreadsheets/{token}/move_dimension body: { "source": {...}, "destination_index": N } (camelCase "destinationIndex" → snake_case "destination_index" to match the v2 contract.) Both DryRun and Execute updated, plus the TestDimMove_DryRun and TestExecute_DimMove assertions. larksuite#5 +range-sort: pre-check sort_conditions[i].column + .ascending transform_range.sort_conditions[i] requires both `column` (string) and `ascending` (bool); rangeSortInput passed the --sort-keys array through to the server unvalidated, so missing fields surfaced as opaque "required property X missing" errors with no per-item context. Walk the parsed array client-side, reject with item-pointing messages. Test fixtures and a contract-test fixture switched from the historical {col, order} vocabulary (which the server has never accepted) to the correct {column, ascending}. Server-schema citations and test-report case mapping in this branch's plan file.
zhengzhijiej-tech
added a commit
to zhengzhijiej-tech/cli
that referenced
this pull request
May 25, 2026
data/flag-defs.json is regenerated from the upstream sheet-skill-spec
canonical-spec; editing it here gets clobbered on the next sync. The
schema realignment for +dropdown-set / -update --colors / --highlight
removal needs to land on the base table first, then flow back through
sheet-skill-spec → larksuite-cli sync, not via a direct CLI-side edit.
Restore the previous flag entries verbatim. The Go-side change in
buildDropdownValidation still drops the wire fields, so:
- users passing --colors / --highlight today see the flag accepted
silently (no effect on the wire) until the upstream removal lands;
- after upstream removal + sync, both the flag declarations and the
Go-side handling will be in sync.
Functional fixes (larksuite#1 workbook-create, larksuite#3 dropdown-get, larksuite#4 dim-move,
larksuite#5 range-sort) and dropdown wire-shape rename (larksuite#2) are unaffected.
zhengzhijiej-tech
added a commit
to zhengzhijiej-tech/cli
that referenced
this pull request
May 25, 2026
These md files are sync targets generated from sheet-skill-spec; editing
them here gets clobbered on the next sync, same as data/flag-defs.json.
The --colors / --highlight row removals belong on the upstream base
table → canonical-spec sync, not here.
Restore the previous --colors / --highlight rows in both
lark-sheets-write-cells.md (+dropdown-set) and lark-sheets-batch-update.md
(+dropdown-update). The Go-side change in buildDropdownValidation still
drops the wire fields, so:
- users passing --colors / --highlight today see the flag accepted
silently (no effect on the wire) until upstream removes the flag;
- after upstream removal + sync, both flag declarations, ref docs, and
Go-side handling will be in sync.
Functional fixes (larksuite#1 workbook-create, larksuite#3 dropdown-get, larksuite#4 dim-move,
larksuite#5 range-sort) and dropdown wire-shape rename (larksuite#2) are unaffected.
zhengzhijiej-tech
added a commit
to zhengzhijiej-tech/cli
that referenced
this pull request
May 25, 2026
data/flag-defs.json is regenerated from the upstream sheet-skill-spec
canonical-spec; editing it here gets clobbered on the next sync. The
schema realignment for +dropdown-set / -update --colors / --highlight
removal needs to land on the base table first, then flow back through
sheet-skill-spec → larksuite-cli sync, not via a direct CLI-side edit.
Restore the previous flag entries verbatim. The Go-side change in
buildDropdownValidation still drops the wire fields, so:
- users passing --colors / --highlight today see the flag accepted
silently (no effect on the wire) until the upstream removal lands;
- after upstream removal + sync, both the flag declarations and the
Go-side handling will be in sync.
Functional fixes (larksuite#1 workbook-create, larksuite#3 dropdown-get, larksuite#4 dim-move,
larksuite#5 range-sort) and dropdown wire-shape rename (larksuite#2) are unaffected.
zhengzhijiej-tech
added a commit
to zhengzhijiej-tech/cli
that referenced
this pull request
May 25, 2026
These md files are sync targets generated from sheet-skill-spec; editing
them here gets clobbered on the next sync, same as data/flag-defs.json.
The --colors / --highlight row removals belong on the upstream base
table → canonical-spec sync, not here.
Restore the previous --colors / --highlight rows in both
lark-sheets-write-cells.md (+dropdown-set) and lark-sheets-batch-update.md
(+dropdown-update). The Go-side change in buildDropdownValidation still
drops the wire fields, so:
- users passing --colors / --highlight today see the flag accepted
silently (no effect on the wire) until upstream removes the flag;
- after upstream removal + sync, both flag declarations, ref docs, and
Go-side handling will be in sync.
Functional fixes (larksuite#1 workbook-create, larksuite#3 dropdown-get, larksuite#4 dim-move,
larksuite#5 range-sort) and dropdown wire-shape rename (larksuite#2) are unaffected.
xiongyuanwen-byted
added a commit
that referenced
this pull request
Jun 3, 2026
…package (#1220) * refactor(sheets): rebuild lark-sheets on sheet-skill-spec canonical + One-OpenAPI Restart lark-sheets as a spec-driven downstream. Skill content (SKILL.md and 16 references covering 13 operations skills + 3 workflow skills, including the standalone filter-view skill) is mirrored from the sheet-skill-spec canonical-spec; do not hand-edit, change upstream and rerun npm run sync:consumers. Drop the 11 legacy shortcut sources (spreadsheet / sheet management, cell ops, dropdown, filter-view, float image, etc.) and 10 associated tests. Wire up the new sheet_ai/v2 One-OpenAPI single entry that dispatches by tool_name with JSON-string input/output, and land the first canonical shortcut +workbook-info as a template that exercises the public token XOR pair, Risk tiering, and zero-side-effect DryRun. sheet_ai_api.go provides callTool / invokeToolDryRun and bypasses runtime.CallAPI's silent swallowing of non-envelope responses so gateway and business errors from the new endpoint surface precisely. The remaining 55 shortcuts will be designed and landed separately, canonical skill by canonical skill. * feat(sheets): implement lark_sheet_workbook shortcuts (B1) Land the 8 modify_workbook_structure shortcuts that round out the lark_sheet_workbook canonical skill alongside the existing +workbook-info: +sheet-create / +sheet-delete / +sheet-rename / +sheet-move / +sheet-copy / +sheet-hide / +sheet-unhide / +sheet-set-tab-color. All eight call modify_workbook_structure via the One-OpenAPI invoke_write endpoint, dispatched by the `operation` enum. Helpers in helpers.go grow publicSheetFlags() / resolveSheetSelector() / sheetSelectorForToolInput() / sheetSelectorPlaceholder() so future sheet-level shortcuts share the public --sheet-id / --sheet-name XOR treatment. +sheet-create intentionally drops the sheet selector pair since create has no existing-sheet anchor (matches the spec fix in tool-shortcut-map.json). +sheet-delete is the first high-risk-write shortcut in the canonical package; the framework requires --yes (exit code 10 otherwise). +sheet-move's tool requires source_index in addition to target_index. The CLI accepts an optional --source-index override and falls back to a single get_workbook_structure read to derive it (and to resolve sheet_id from --sheet-name). DryRun stays network-free by rendering <resolve> placeholders for any field that would need that read. * feat(sheets): implement lark_sheet_sheet_structure shortcuts (B2) Add 8 shortcuts under the lark_sheet_sheet_structure canonical skill: +sheet-info (get_sheet_structure) plus +dim-insert / +dim-delete / +dim-hide / +dim-unhide / +dim-freeze / +dim-group / +dim-ungroup (modify_sheet_structure, dispatched by operation enum). Two reusable conversion helpers cover the impedance mismatch between the CLI surface and the tool input: - dimRange / dimPosition translate the CLI's 0-based exclusive-end range into the tool's 1-based A1 notation. row 5..8 becomes position "6" + count 3 (insert) or range "6:8" (range ops); column 26..29 becomes "AA:AC". - infoTypeFromInclude maps the fine-grained --include vocabulary (row_heights / col_widths / merges / hidden_rows / hidden_cols / groups / frozen) to the coarse info_type enum the tool accepts; mixed categories collapse to "all". +dim-delete is high-risk-write (irreversible row/column removal). +dim-freeze --count 0 auto-dispatches to operation=unfreeze. +dim-group accepts --depth for forward-compat with a future server-side nested group endpoint but does not pass it through today. * feat(sheets): implement read_data / search_replace / write_cells shortcuts (B3) Land 11 shortcuts across three canonical skills: - lark_sheet_read_data (3): +cells-get / +csv-get / +dropdown-get - lark_sheet_search_replace (2): +cells-search / +cells-replace - lark_sheet_write_cells (6): +cells-set / +cells-set-style / +csv-put / +dropdown-set / +dropdown-update / +dropdown-delete +dropdown-get reads the data_validation field via get_cell_ranges with the range carrying its own sheet prefix (no --sheet-id needed). The fine-grained --include vocabulary (value / formula / style / comment / data_validation) maps to the tool's coarse include_styles bool plus value_render_option enum. +csv-get's --include-row-prefix=false strips the [row=N] prefix client-side because the tool only emits the annotated form. +cells-search / +cells-replace flatten the tool's options sub-object into four independent flags (--match-case / --match-entire-cell / --regex / --include-formulas) per the flat-flag rule, then repack them on the way in. +cells-set takes a raw --data JSON body whose `cells` array must match the --range dimensions. +cells-set-style fans a single --style block out to every cell in the range via a new fillCellsMatrix helper; the range parser (rangeDimensions / splitCellRef / letterToColumnIndex) only accepts rectangular A1:B2 forms — whole-column / whole-row need sheet totals and are deferred. +dropdown-set fans the validation block out to one range; +dropdown- update / +dropdown-delete iterate sheet-prefixed --ranges and call set_cell_range sequentially (partial failure leaves earlier ranges already mutated; the Tip calls this out). +dropdown-delete is high-risk-write and requires --yes. +cells-set-image stays deferred to the cli-only batch (needs the shared local-file upload helper alongside +workbook-create / +dim-move / +workbook-export). * refactor(sheets): move +dropdown-update / +dropdown-delete to lark_sheet_batch_update Follow-up to B3 after the spec re-mapped these two shortcuts to the batch_update tool (atomic multi-range CRUD) instead of fan-out via set_cell_range. Drop their Go implementations + helper validateDropdownRanges + splitSheetPrefixedRange from lark_sheet_write_cells.go and remove the registrations from Shortcuts(); the shortcuts will reappear under lark_sheet_batch_update during B7. Also pull in the re-rendered reference docs: - skills/lark-sheets/references/lark-sheets-write-cells.md - skills/lark-sheets/references/lark-sheets-batch-update.md * feat(sheets): implement lark_sheet_range_operations shortcuts (B4) Land 8 shortcuts across four canonical tools: - clear_cell_range → +cells-clear (high-risk-write) - merge_cells → +cells-merge / +cells-unmerge - resize_range → +dim-resize - transform_range → +range-move / +range-copy / +range-fill / +range-sort Three CLI↔tool vocabulary bridges live in this file: - +cells-clear: --scope content normalizes to the tool's clear_type "contents" (singular/plural spec mismatch is absorbed in the CLI). - +dim-resize: --size <px> wraps as resize_{height,width}:{value:N}; --reset wraps as {reset:true}. The two flags are mutually exclusive and at least one is required. - +range-fill: CLI's five-valued --series-type collapses to the tool's binary fill_type — `copy` → "copyCells", anything else → "fillSeries" (the actual series progression is inferred server-side from the seed cells in --source-range). - +range-copy: --paste-type {values, formulas, formats} maps to the tool's {value_only, formula_only, format_only}; "all" omits the field entirely so the server applies its default. +cells-clear is the second high-risk-write shortcut in the package; the framework enforces --yes with exit code 10 as usual. * feat(sheets): implement object-list shortcuts (B5) Land 7 read shortcuts, one per object skill — chart / pivot table / conditional format / filter / filter view / sparkline / float image. All share the same shape (public sheet selector + optional <obj>-id filter) so they're declared via newObjectListShortcut + an objectListSpec. Notes: - +cond-format-list exposes --rule-id, which is renamed to conditional_format_id on the wire (the tool's full field name). - +sparkline-list exposes --group-id (the higher-level handle); the tool also accepts sparkline_id, intentionally not surfaced. - +filter-list takes no id filter — at most one sheet-level filter per sheet, so the listing is already unique. - +filter-view-list is `cli_status: cli-only` but get_filter_view_objects is in mcp-tools.json and dispatches through the same One-OpenAPI endpoint; no special path required. * feat(sheets): implement object CRUD shortcuts (B6) Land 21 shortcuts — three (create / update / delete) per object skill — backed by the manage_<obj>_object tools dispatched on the operation enum. Five standard objects (chart / cond-format / sparkline / float-image / filter-view) share an objectCRUDSpec factory; pivot and filter are special-cased. Shared wire contract: excel_id + sheet_id|sheet_name + operation + [<obj>_id] + [properties] CLI --data is passed through as the tool's `properties` field as-is, so callers shape it per each object's spec doc. Special cases: - pivot adds optional --target-sheet-id / --target-position on create (siblings of properties, not inside it). - cond-format exposes --rule-id (short CLI name) wired to the tool's conditional_format_id on the wire. - sparkline uses --group-id (higher-level object handle) instead of sparkline_id. - filter has no separate id flag — at most one filter per sheet, so filter_id is implicit. +filter-create promotes --range to a first- class flag (instead of burying it inside --data). - filter-view CRUD are `cli_status: cli-only` but manage_filter_view_object is in mcp-tools.json, so they go through callTool / One-OpenAPI alongside everything else. All delete shortcuts are high-risk-write and require --yes. * feat(sheets): implement lark_sheet_batch_update shortcuts (B7) Land 4 shortcuts that all funnel through the batch_update tool's atomic operations array: - +batch-update raw passthrough; --data carries the full { operations: [{tool, params}, ...] } payload plus optional continue_on_error. high-risk-write since the caller may stuff anything inside. - +cells-batch-set-style --data is [{ranges, style}, ...]; CLI flattens each (entry × range) pair into a set_cell_range op with a fan-out cells matrix carrying cell_styles + border_styles. - +dropdown-update --ranges + --options (+ --colors / --multiple / --highlight) — installs/replaces one dropdown across many ranges, each becoming a separate set_cell_range op with data_validation in cells. - +dropdown-delete --ranges — clears data_validation across many ranges (high-risk-write). Default is strict transaction: if any sub-tool fails the whole batch rolls back. +batch-update exposes --continue-on-error to flip the policy; the three fan-out shortcuts leave it strict (they're meant to be all-or-nothing). Reinstates validateDropdownRanges + splitSheetPrefixedRange that were removed during B3 → B7 relocation. * feat(sheets): implement cli-only shortcuts (B8) — 70/70 complete Land the four cli-only shortcuts that can't route through the One-OpenAPI dispatcher (their backing capabilities aren't in mcp-tools.json): - +workbook-create POST /open-apis/sheets/v3/spreadsheets + optional set_cell_range follow-up that zips --headers and --data into the first sheet starting at A1. - +workbook-export POST /open-apis/drive/v1/export_tasks (type=sheet) → poll /export_tasks/:ticket up to ~30s → optional GET /export_tasks/file/:file_token/download. CSV mode requires --sheet-id (single sheet export). - +dim-move POST /open-apis/sheets/v2/spreadsheets/:token /dimension_range CLI is 0-indexed inclusive (--start / --end); the v2 endpoint expects half-open [startIndex, endIndex) so the body uses endIndex = --end + 1. --sheet-name is resolved client-side to sheet_id via lookupSheetIndex when needed. - +cells-set-image common.UploadDriveMediaAll (parent_type=sheet_image, parent_node=token) then callTool set_cell_range with cells carrying rich_text: [{type:"embed-image", attachment_token, attachment_name}]. --range must be exactly one cell. All four use runtime.CallAPI / DoAPI directly; only +cells-set-image combines a legacy upload with the new One-OpenAPI for the second step (set_cell_range is in mcp-tools.json so callTool is the right path). This closes the migration: 70 shortcuts × 17 canonical skills × matching the sheet-skill-spec v0.5.0 tool-shortcut-map. * test(sheets): cover all 70 shortcuts with dry-run + execute-path tests Twelve _test.go files alongside the implementation, mirroring the legacy package's coverage style: - testhelpers_test.go shared rig: TestFactory + Mount + dry-run capture + JSON-input decode + envelope helpers. - lark_sheet_*_test.go one test file per implementation file (9 files), table-driven dry-run cases per shortcut plus targeted validation guards. - execute_paths_test.go end-to-end execute paths via httpmock stubs. Covers callTool unwrap, JSON-string output decoding, two-step lookup (+sheet-move), batch_update fan-out, dropdown atomic writes, and the legacy OAPI shortcuts (+workbook-create, +dim-move) including CLI inclusive → API half-open index conversion. Test coverage on the sheets package is 60.5 % of statements with -race clean, meeting the dev manual's ≥ 60 % patch-coverage gate. * refactor(sheets): inline cli-only shortcuts into their canonical skill files Two naming cleanups: - lark_sheet_cli_only.go is gone. The four shortcuts it grouped (+workbook-create / +workbook-export / +dim-move / +cells-set-image) were bundled by their implementation pattern (legacy OAPI direct calls) rather than by canonical skill. The whole sheets package IS the CLI implementation, so "cli only" wasn't a meaningful grouping at the Go layer. Each shortcut now lives next to its skill peers: +workbook-create / +workbook-export → lark_sheet_workbook.go +dim-move → lark_sheet_sheet_structure.go +cells-set-image → lark_sheet_write_cells.go Per-skill shortcut counts now match tool-shortcut-map.json exactly (workbook: 11, sheet_structure: 9, write_cells: 5). Helpers (buildInitialFillInput, pollExportTask, downloadExportFile, dimMoveBody) move with their shortcuts; nothing else in the package referenced them. - testhelpers_test.go → helpers_test.go. The _test.go suffix already conveys "test"; the leading "test" was redundant. Matches the helpers.go naming convention. Behavior unchanged. go test -race -cover stays at 60.5 %. * refactor(sheets): sync shortcut flags with sheet-skill-spec v0.5.0 Upstream hoisted a batch of high-frequency scalar fields out of --data into independent flags and renamed several composite-JSON flags to match their semantic content. CLI catches up. Renames (drop-in, same payload semantics): - +cells-replace --replace → --replacement - +cells-set --data → --cells - +workbook-create --data → --values - +batch-update --data → --operations (now a bare array; still accepts the envelope form for back-compat with continue_on_error) Flat-flag hoists out of --style / --data: - +cells-set-style / +cells-batch-set-style --style JSON drops; replaced by 11 flat style flags (--background-color / --font-color / --font-size / --font-style / --font-weight / --font-line / --horizontal-alignment / --vertical-alignment / --word-wrap / --number-format) plus --border-styles for the one field that's still nested. Both shortcuts share styleFlatFlags() + buildCellStyleFromFlags(). - +cells-batch-set-style also drops the [{ranges, style}] array shape in favor of one --ranges + the same flat style flags applied to all of them. Object CRUD --data → --properties everywhere (chart / pivot / cond-format / filter / filter-view / sparkline / float-image). Per-skill scalar hoists merged into properties via an enhanceCreate/UpdateInput callback: - +pivot-create adds --source (required), --range (and continues to expose --target-sheet-id / --target-position at top level) - +cond-format-{create,update} adds --rule-type (enum) + --ranges (JSON array); merged into properties.rule.type and properties.ranges respectively - +filter-view-{create,update} adds --view-name and --range; both override their properties.* counterparts - +filter-update adds first-class --range (was buried in --data) Float-image is fully hoisted — no --properties flag at all. Ten flat flags (--image-name / --image-token | --image-uri / --position-row / --position-col / --size-width / --size-height / --offset-row / --offset-col / --z-index) compose the properties block. Implemented as its own factory (newFloatImageWriteShortcut) since it diverges from the shared CRUD spec. Tests track every flag renamed and add explicit cases for the new flag combos. go test -race -cover stays at 60.3 %. * refactor(sheets): align batch_update + cells-set with synced reference docs Sync to upstream reference doc updates for 9 skills: - batch_update sub-ops: rewrite wire fields tool/params -> tool_name/input in CellsBatchSetStyle and DropdownUpdate/Delete fan-out (the actual server contract per Schemas section); update --operations flag desc and tests. - +cells-set --cells: accept bare 2D matrix [[{cell},...],...] instead of envelope {"cells":[[...]]}; spec example shows bare-array form. - sparkline createDataDesc enum: win_loss -> winLoss (camelCase). All other doc changes (float-image flat flags, cond-format --rule-type/--ranges, pivot create-only --source/--range, filter / filter-view extra flags, chart --properties) were already aligned in commit ce33315. * fix(sheets): repair cells-set-image rich_text embed payload The server rejected set_cell_range calls from +cells-set-image with three distinct errors: missing "text" property, missing image_width/image_height, and unknown attachment_token field. Realign the rich_text element to the embed-image schema (text/image_token/image_width/image_height) and decode PNG/JPEG/GIF dimensions from the local file before the write. * refactor(sheets)!: split +dim-resize into +rows-resize and +cols-resize Sync to upstream spec change that splits the legacy +dim-resize shortcut into +rows-resize and +cols-resize. Reasoning is that row vs column resize has divergent semantics (only rows support auto-fit) and the shared --dimension flag was hiding that. Behavior changes (BREAKING): - +dim-resize is removed; use +rows-resize or +cols-resize. - --dimension and --reset flags are gone. - --type enum replaces --size/--reset: pixel (requires --size) standard (reset to sheet default; no --size) auto (auto-fit row height; +rows-resize only) - --end is now inclusive (was exclusive). Old "--start 0 --end 5" (5 rows) becomes "--start 0 --end 4". - Wire payload for resize_height / resize_width changes from {value: N} | {reset: true} to {type: "pixel", value: N} | {type: "standard"} | {type: "auto"}. Tests cover both shortcuts across pixel / standard / auto and the new guard surface (--type pixel needs --size; standard/auto reject --size; +cols-resize rejects --type auto; --end < --start). Also pulls in synced reference docs for 5 skills (batch-update, core-operations, range-operations, sheet-structure, visual-standards) that update prose mentions of +dim-resize. * feat(sheets): add --print-schema runtime introspection for composite JSON flags Composite JSON flags (--cells / --properties / --operations / --border-styles / --sort-keys / --options) carry non-trivial structured payloads. Reference docs cover top-level fields but agents writing those flags often need the full JSON Schema to build a valid payload. This adds a system-level introspection contract so any shortcut whose flags are tracked upstream can serve its schemas locally: lark-cli sheets <shortcut> --print-schema --flag-name <name> lark-cli sheets <shortcut> --print-schema # list flags The schema data is embedded at build time from a synced artifact (shortcuts/sheets/data/flag-schemas.json). Upstream is the source of truth — never hand-edit the JSON; update the source Base table and rerun the sheet-skill-spec sync. Framework changes (shortcuts/common): - types.go: Shortcut gains an opt-in PrintFlagSchema hook (flagName -> bytes/error). When non-nil the framework auto-injects --print-schema / --flag-name and short-circuits Validate/Execute. - runner.go: register the two system flags when PrintFlagSchema is set; intercept in runShortcut before identity/scope/config so pure-local lookups don't trigger auth or network. Install a PreRunE that relaxes cobra's required-flag gate when --print-schema is set, since asking for a schema shouldn't need unrelated required flags. Sheets surface (shortcuts/sheets): - flag_schema.go (new): go:embed data/flag-schemas.json; expose printFlagSchemaFor(command) closure. When flagName is empty it emits a JSON listing of introspectable flags for discovery; otherwise it returns the schema subtree as pretty JSON. - flag_schema_test.go (new): cover embed parsing, listing / by-name lookup, unknown-flag error path, registration via Shortcuts(), and the full system-flag short-circuit through cobra (required flags relaxed, schema printed on stdout). - shortcuts.go: Shortcuts() now wraps shortcutList() and attaches PrintFlagSchema to every command present in flag-schemas.json, so shortcuts opt in by being listed upstream — no per-shortcut boilerplate. - data/flag-schemas.json (new, synced from sheet-skill-spec): 19 entries, schema_version "2". Generated upstream from the Lark Base source-of-truth (see sheet-skill-spec scripts/fetch_cli_flag_schema_map.mjs); ships only per-flag subtrees (not the full mcp-tools.json) to keep tool internals out of the open-source repo. Skill docs (skills/lark-sheets): - SKILL.md: system-flag table gains --print-schema / --flag-name and an "Agent 使用提示" note steering agents to prefer --print-schema over guessing JSON shape from the cheatsheet. - references/*.md: regenerated by upstream sync (Schemas-section boilerplate updated, plus accumulated upstream prose refinements). * docs(sheets): remove sandbox references and normalize tool names to CLI shortcuts Replace export_sheet_to_sandbox / import_sandbox_to_sheet / doubao_code_interpreter with local-script + batch csv-get/csv-put workflows; unify legacy MCP tool names (set_cell_range, get_range_as_csv, etc.) to CLI shortcut format (+cells-set, +csv-get). * feat(sheets): add flag-descriptions.en.json and wire applyFlagDescs into Shortcuts() Embed data/flag-descriptions.en.json (synced from upstream spec) and apply it at shortcut assembly time so every Flag.Desc is sourced from the canonical JSON rather than hardcoded Go strings. Existing hardcoded Desc values serve as fallback for flags not yet in the JSON. Also sync reference doc updates from upstream. * feat(shortcuts): support int64 and float64 flag types Flag.Type previously could not express non-integer numbers. Add int64 and float64 cases to flag registration plus Int64/Float64 runtime accessors. * refactor(sheets): build shortcut flags generically from flag-defs.json Replace flag-descriptions.en.json with the richer flag-defs.json (full flag definitions: type / default / enum / input / hidden / required / kind) synced from sheet-skill-spec. Add flagsFor(command) to materialize each shortcut's []common.Flag straight from the JSON, skipping system-kind flags the framework injects. Migrate every sheets shortcut (including the CRUD/list/dim/merge/ visibility factories) to Flags: flagsFor("+command"), dropping all hand-written flag literals plus the now-dead publicTokenFlags / publicSheetFlags / styleFlatFlags helpers and enum vars. A coverage test locks the Go-flags-match-JSON contract. Align Go with the new spec where they diverged: +cells-get --ranges → --range, font-size int → float64, +filter-view-create --range now required, +sheet-create row/col-count defaults 200/20. * docs(sheets): sync +batch-update CLI override schema (shortcut/input form) Pulled from sheet-skill-spec: - skills/lark-sheets/references/lark-sheets-batch-update.md: --operations now documents the {shortcut, input} form; tool_name references gone - shortcuts/sheets/data/flag-schemas.json: --operations resolves to the CLI-side array<{shortcut(enum), input}> schema, sourced from spec's canonical-spec/tool-schemas/cli-schemas.json (cli: prefix). +dropdown --options also drilled one level deeper NOTE: the binary still raw-passes --operations to MCP batch_update which expects {tool_name, input}. A follow-up will add a shortcut→tool_name translation layer (with per-shortcut operation field) before the docs become actionable. * feat(sheets): translate +batch-update sub-ops {shortcut,input} → MCP shape Users now hand +batch-update --operations a CLI-shape array ([{shortcut, input}, ...]) and the binary translates each sub-op to the underlying MCP batch_update shape ({tool_name, input(+operation)}) via a new dispatch table in shortcuts/sheets/batch_op_dispatch.go. Dispatch table covers 50 batchable write shortcuts. Excluded by design: - all read ops - fan-out wrappers (+batch-update self, +cells-batch-set-style, +dropdown-update, +dropdown-delete) — nesting these = nested batch - +dim-move — single shortcut uses legacy v2 /dimension_range endpoint, not MCP, can't be batched - +cells-set-image — multi-step image upload, not atomic-batch friendly - +workbook-create — new workbook, not batch-on-existing semantics Translator also rejects sub-ops that hand-fill input.operation (implied by shortcut name) or input.excel_id / spreadsheet_token / url (set once at +batch-update top level). +dim-freeze always injects operation=freeze; the count==0 unfreeze path of the single shortcut is intentionally not supported in batch — callers should use the single shortcut for unfreeze. Tests cover: end-to-end translation, --continue-on-error propagation, 13 rejection cases (banned shortcuts, malformed shapes, reserved keys). Sync'd from sheet-skill-spec: skills/lark-sheets/references/ lark-sheets-batch-update.md + shortcuts/sheets/data/flag-schemas.json pick up the corrected enum (+cells-set-style / +dropdown-set added, +dim-move removed). * fix(sheets): make +batch-update sub-ops reuse standalone flag→body translators Sub-ops previously near-passed-through their input, so any shortcut whose standalone translator renames fields broke inside a batch: +range-copy lost range/destination_range (transform_range errored "range missing") and +rows-resize lost range/resize_height ("No resize operation specified"). Introduce a flagView interface (satisfied by *common.RuntimeContext) and a map-backed mapFlagView, then route every batchable sub-op through the SAME *Input builder the standalone shortcut uses. mapFlagView seeds flag-defs.json defaults for value reads while keeping Changed() user-driven, so a sub-op body is byte-identical to the standalone body — locked by a batch-vs-standalone contract test over all ~40 batchable shortcuts. Also fix single-row/column resize: start==end now formats as "23:23" / "C:C" (resize_range rejects a bare "23"); dimRangeFull keeps both sides while dimRange's collapse stays for modify_sheet_structure consumers. * fix(sheets): align +cells-get/+csv-get range flags with synced spec sheet-skill-spec now declares +cells-get --range as a single string (was string_array) and +csv-get --range as required. Match the flag→body translators: - +cells-get wraps the single --range into the tool's `ranges` array and validates with Str() instead of StrArray(), which silently returned nil against the now-String flag and broke the command. - +csv-get gains a trim-based required-range guard. Update read-data dry-run tests to single-range form and add a guard test for the empty --range path. * fix(sheets): push +batch-update sub-op validation down into xxxInput builders Sub-ops that omit --sheet-id (or any other required flag) used to slip past CLI validation — Validate ran only against the standalone shortcut path, and batchOpDispatch's translators built bodies from whatever flagView returned, so a structurally broken sub-op surfaced as an opaque server "sheet undefined not found" after a network round-trip. Push each batchable shortcut's check trio down into its xxxInput builder: 1. resolveSpreadsheetToken — stays in Validate (batch already does it once at the top level; sub-ops don't repeat). 2. requireSheetSelector(sheetID, sheetName) — new helper; flagView- agnostic XOR + control-char check, called at the top of every xxxInput. 3. shortcut-specific required / range / enum checks (--dimension, --range, --start <= --end, --type pixel needs --size, --float-image-id, image-token XOR image-uri, ...) — moved out of Validate into the builder body. All ~30 batchable xxxInput builders now return (map, error). Standalone Validate shrinks to validateViaInput(xxxInput); DryRun / Execute propagate the error. batch_op_dispatch entries drop the noErrTranslate wrapper and pass the builder directly — its error bubbles up wrapped with "operations[N] (+shortcut):" context. Tests: - TestBatchOp_ErrorEquivalence (7 cases): XOR / logical-constraint errors fire identically from standalone and batch sub-op paths. - TestBatchOp_RejectsBadSubOpInput (8 cases): cobra-required flags that standalone catches via MarkFlagRequired now also get rejected CLI-side on the batch path (where cobra is not in the loop). - TestBatchOp_BodyMatchesStandalone (~40 cases) and TestBatchOp_DispatchCoversReportedBugs continue to pass — bodies stay byte-identical. - BOE smoke (spreadsheet ICFwstkUGheyfptGWS2bB7RgcDf, sheet 51991c): +batch-update with a sub-op missing --sheet-id now returns "operations[0] (+dim-insert): specify at least one of --sheet-id or --sheet-name" before any network call. sheetMoveBatchInput (xiongyuanwen's batch-only explicit-source-index requirement) is preserved — it's an orthogonal batch-specific constraint not affected by this push-down. * fix(sheets): align +cond-format / +filter with server schema (#4 + #5) Two latent bugs in the object_crud translator surfaced during BOE smoke testing of +batch-update. Both are schema-alignment fixes against manage_conditional_format_object / manage_filter_object as declared in sheet-skill-spec/canonical-spec/tool-schemas/mcp-tools.json. #4 +cond-format: rule_type path + enum vocabulary --------------------------------------------------- condFormatEnhance used to write the user's --rule-type value into `properties.rule.type` (nested under a `rule` object). The server schema actually puts it at flat `properties.rule_type` and silently drops the nested form — so every conditional-format create/update secretly built the wrong document. Worse, the CLI enum exposed via flag-defs.json was its own invented vocabulary (cellValue / formula / duplicate / unique / topBottom / aboveBelowAverage / dataBar / colorScale / iconSet / textContains / dateOccurring / blankCell / errorCell) — none of those values were the strings the server accepts. Fix: - condFormatEnhance now writes `properties.rule_type = <value>` directly (no nested `rule` object). - Synced flag-defs.json + lark-sheets-conditional-format.md enum vocabulary from base to match the server: duplicateValues, uniqueValues, cellIs, containsText, timePeriod, containsBlanks, notContainsBlanks, dataBar, colorScale, rank, aboveAverage, expression, iconSet. - ⚠️ Breaking: scripts passing the old CLI-invented enum values (e.g. --rule-type cellValue) now get a cobra "invalid value … allowed: …" error listing the new vocabulary. No alias layer. - TestObjectCRUDShortcuts_DryRun's +cond-format-update case updated to assert the flat properties.rule_type shape + new enum. #5 +filter-{update,delete}: auto-inject filter_id = sheet_id ------------------------------------------------------------- manage_filter_object's contract is "filter_id === sheet_id" for the sheet-scoped filter (per per-tool description in mcp-tools.json), and update / delete operations MUST carry filter_id. Standalone filterUpdateInput / filterDeleteInput never set it, so the server rejected with "filter_id is required for update/delete operation" on every call — both standalone AND inside +batch-update. Fix: - filterUpdateInput / filterDeleteInput now set input["filter_id"] = sheetID. - Because filter_id must equal sheet_id (not sheet_name), update / delete reject when only --sheet-name is given — there's no network lookup available inside the builder. The friendly error points at +workbook-info for resolving sheet-name → sheet-id. - create still omits filter_id (server requires that — id is server-allocated on creation). - New tests: * TestObjectCRUDShortcuts_DryRun gains a +filter-update happy-path case asserting filter_id is auto-injected + --range hoisting. * +filter-delete case updated to assert filter_id presence. * TestBatchOp_RejectsBadSubOpInput gains two cases asserting both +filter-update and +filter-delete reject --sheet-name-only with the friendly error. Docs (#2 + #3 + #8) synced from sheet-skill-spec ------------------------------------------------- Companion doc fixes that landed via npm run generate:cli + sync:cli in sheet-skill-spec; included here because the regenerated flag-defs and references markdown are byte-tracked in this repo: - #2: lark-sheets-sheet-structure.md — +dim-{hide,unhide,group, ungroup} --start/--end desc changed from "(0-based, inclusive)" to "(0-based)" / "(exclusive)" to match the half-open range semantics the code has always implemented (requireDimRange: end > start; dimRange uses end - 1 for column end letters). - #3: lark-sheets-workbook.md — +sheet-move section gains a note about the batch-internal requirement to pass --sheet-id AND --source-index explicitly (sheetMoveBatchInput's constraint). - #8: lark-sheets-pivot-table.md — +pivot-create --properties example drops the stale data_range field (the actual server schema uses --source as a hoisted flag; properties only carries rows / columns / values / filters / show_*_grand_total). * feat(sheets): add +cells-batch-clear fan-out over batch_update Clear content/formats across many sheet-prefixed ranges in a single atomic batch_update (one clear_cell_range op per range), mirroring the existing +cells-batch-set-style / +dropdown-{update,delete} fan-out wrappers. The --scope to clear_type normalization is shared with standalone +cells-clear (normalizeClearType) so the two stay in lockstep. high-risk-write (requires --yes); rejected as a batch sub-op like the other fan-out wrappers. flag-defs/flag-schemas and skill docs updated to match. * docs(sheets): sync stdin guidance and sparkline reference - skills/lark-shared/SKILL.md: drop the generic "prefer stdin" section - skills/lark-sheets/SKILL.md: add expanded stdin guidance (use stdin over @file abs paths; don't cd or write into the project dir) - skills/lark-sheets/references/lark-sheets-sparkline.md: document the group_id / sparkline_id two-tier model with worked examples * fix(sheets): require sparkline_id on +sparkline-update items (#6) manage_sparkline_object uses two layers of IDs: --group-id picks the sparkline group, and properties.sparklines[i].sparkline_id picks each item inside the group. The server contract requires sparkline_id on every update item (server maps each entry back to an existing sparkline by this id). Agents that called +sparkline-update without the per-item ids hit an opaque server-side rejection that didn't mention sparkline_id at all, then got stuck in a try-fail-list-retry loop. Pre-check CLI-side in objectUpdateInput via a new validateUpdateInput hook on objectCRUDSpec. sparklineSpec wires validateSparklineUpdateItems, which walks properties.sparklines[] and rejects with a message that points at +sparkline-list: +sparkline-update properties.sparklines[N] missing sparkline_id (run `+sparkline-list --group-id <id>` first to read sparkline_id for each item, then echo each id back on the corresponding update entry) Scope is update-only. config-only updates (properties.config without sparklines) stay legal — the validator skips when sparklines is absent. Delete is not pre-checked: objectDeleteInput doesn't pass properties through, so the partial-delete branch can't be reached today (separate follow-up). Tests: - TestObjectCRUDShortcuts_DryRun: positive case for update with sparkline_id present. - TestSparklineUpdate_MissingSparklineID: standalone path — error contains both "missing sparkline_id" and "+sparkline-list". - TestBatchOp_RejectsBadSubOpInput: batch sub-op missing sparkline_id rejected with the same friendly error. Docs synced from sheet-skill-spec (canonical change committed there): skills/lark-sheets/references/lark-sheets-sparkline.md documents the two-layer id model, the three "+sparkline-list first" cases, and both delete modes. * docs(sheets): sync lark-sheets skill from spec (audit 20260521) Pull latest spec from sheet-skill-spec (PR ee/sheet-skill-spec!6 + earlier develop commits) into skills/lark-sheets/ and shortcuts/sheets/data/. Audit findings now reflected in CLI docs: - A2 +cond-format-create example: --rule-type duplicate → duplicateValues - A3 +cond-format-create Validate: cellValue/formula → cellIs/expression - A5 +csv-put examples: --range → --start-cell; drop redundant --allow-overwrite - A7 +sparkline-create: Validate / Examples aligned with real schema (config/sparklines), executable JSON example added - B13 cross-doc dead links: lark_sheet_*/cli-shortcuts.md → lark-sheets-*.md - C2 +csv-put: `=` literal warning next to Examples - CC5 +rows-resize/+cols-resize --type auto: single point of truth in range-operations reference flag-defs.json description / required sync (from base): - A4 +float-image-update: image-name/position-*/size-* required → optional (patch mode) - A8 +dim-move --start/--end description cleanup - B3 +pivot-create --properties: data_range → source (real field name) Also picks up the +cells-batch-clear shortcut doc (introduced in spec develop). Go-side implementation for that shortcut is intentionally not in this PR — docs-only preview; runtime dispatch will land in a follow-up. `go test ./shortcuts/sheets/...` passes. * feat(sheets): add +cells-set --copy-to-range and sync skill spec Sync lark-sheets skill references and flag schemas from upstream sheet-skill-spec, and wire the newly-specced --copy-to-range flag into +cells-set: it passes copy_to_range to the set_cell_range tool so a template block written via --cells fans out across a larger range with auto-shifted formula refs. * docs(sheets): sync lark-sheets skill spec (chart/pivot wire mappings, --end semantics) Sync skill references and flag-defs descriptions from upstream sheet-skill-spec: clarify +chart-create properties structure (snapshot.data), +pivot-create --target-position / --range wire-field mappings, add a cross-command --end endpoint-semantics table (insert/delete/hide/group exclusive vs move/resize inclusive), note --group-state default, and rename reference identifiers to lark-sheets-*. Description-only refinement; the existing CLI implementation already matches the clarified wire mappings and --end semantics. * fix(sheets): make --max-chars the single read cap for +cells-get / +csv-get Drop --cell-limit (+cells-get) and --max-rows (+csv-get) from the CLI surface and pin the underlying tool's cell_limit / max_rows to a very large sentinel so the tool's own defaults never truncate before --max-chars. --max-chars stays the only knob (default 200000, unchanged). - lark_sheet_read_data.go: add unboundedReadLimit (1e9); cellsGetInput pins cell_limit, csvGetInput pins max_rows; --max-chars still passed through - data/flag-defs.json: synced from spec (drops the two flags) - tests: spot-check moved to --max-chars; dry-run wantInput asserts cell_limit / max_rows are pinned high Mirrors sheet-skill-spec (Base flag records removed). go build ./... + go test ./shortcuts/sheets/ green. * docs(sheets): sync lark-sheets read docs — --max-chars as single read cap Sync skills/lark-sheets references from spec: drop --cell-limit / --max-rows guidance; 大表分批读 switches to --range row windows + --max-chars auto cap + has_more. Mirrors sheet-skill-spec 58e7456 and handler change 2befc49. * docs(sheets): sync lark-sheets skill spec from upstream Refine reference docs and flag-defs descriptions from upstream sheet-skill-spec (--depth wording for +dim-group / +dim-ungroup, plus assorted reference clarifications). Description-only; no CLI behavior or flag surface change. * docs(sheets): sync chart properties schema (position/size required) Regenerate flag-schemas.json from upstream sheet-skill-spec: the chart properties schema now marks position and size as required, and the chart reference doc reflects the same. flag-schemas.json is print-schema-only (no client-side validation), so this is a generated-artifact + doc sync with no CLI behavior change. * docs(sheets): sync lark-sheets skill spec from upstream Refine reference docs and flag-defs descriptions from upstream sheet-skill-spec: clarify +workbook-export sheet flag scope, +filter-* --properties optionality (omitted => empty filter on --range; rules must be non-empty when provided), float-image reference_id wording, and assorted reference cleanups. Description-only; existing CLI behavior (filter passthrough, properties optional) already matches. * docs(sheets): sync lark-sheets skill spec from upstream Trim and refine reference docs from upstream sheet-skill-spec (condense core-operations workflow, tidy write-cells / range-operations / float-image / SKILL guidance). Description-only; no flag or CLI behavior change. * docs(sheets): sync lark-sheets skill spec from upstream Refine reference docs from upstream sheet-skill-spec (core-operations, formula-translation, visual-standards, SKILL guidance). Description-only; no flag or CLI behavior change. * fix(sheets): correct +workbook-create initial fill and +dim-move endpoint +workbook-create: the v3 create response does not echo the default sheet's id, so the initial-fill set_cell_range was sent with an empty sheet_id and rejected ("sheet_id or sheet_name is required"). Resolve the workbook's first sheet via get_workbook_structure before filling. +dim-move: the move request was POSTed to the v2 dimension_range endpoint (the add/update/delete surface, which requires a `dimension` object) and rejected with "[9499] Missing required parameter: Dimension". Switch to the native v3 move_dimension endpoint (sheet_id in path; snake_case source.{major_dimension,start_index,end_index} + destination_index). CLI --end and v3 end_index are both 0-based inclusive, so they pass through unchanged. * fix(sheets): align +workbook-create, +dropdown-*, +dim-move, +range-sort with server schema Five separate E2E failures in shortcuts/sheets/ that all trace back to a CLI ↔ server contract mismatch. Each is independently scoped; bundling them because they share the test-report citation and the same one-line fix shape in most cases. buildInitialFillInput sent {"sheet_id": ""} on the secondary set_cell_range call after creating the workbook. The empty value was a holdover from "...otherwise server picks first sheet" — but set_cell_range rejects an empty selector with "sheet_id or sheet_name is required" rather than falling back to the default sheet. Use sheet_name "Sheet1" instead. POST /sheets/v3/spreadsheets always creates that sheet on workbook creation, and set_cell_range accepts sheet_name as an equivalent selector — saves an extra get_workbook_structure round-trip just to learn the auto-generated id. buildDropdownValidation emitted four fields that don't exist in the canonical set_cell_range.data_validation schema: - "values" (options list) → renamed to "items" - "multiple_values" → renamed to "support_multiple_values" - "colors" (per-option color) → removed (not in schema; flag also removed from data/flag-defs.json for +dropdown-set / -update) - "highlight_options" → removed (not in schema; flag also removed) The canonical schema lives at sheet-skill-spec/canonical-spec/tool- schemas/mcp-tools.json (set_cell_range tool, data_validation property); the colors / highlight knobs were CLI inventions the server never accepted, so removing the flags is correct (renaming would leave the flags broken). Skill reference docs (write-cells.md, batch-update.md) synced. validateDropdownOptionsColors lost its colors check; renamed to validateDropdownOptions to reflect the narrower contract. dropdownGetInput sent "Sheet1!C2:C6" verbatim as a ranges[] entry. get_cell_ranges expects sheet_id / sheet_name as separate fields and ranges entries without the sheet prefix; the server bounced with "sheet not found, sheetId:" (empty). Use the existing splitSheetPrefixedRange helper (declared in lark_sheet_batch_update.go) to break "Sheet1!C2:C6" into ("Sheet1", "C2:C6"), then thread the sheet name through sheetSelectorForToolInput exactly like +cells-get does. The shortcut was POSTing to /sheets/v2/spreadsheets/{token}/dimension_ range, which is the v2 insert-dimension endpoint and requires a top- level {"dimension": {...}} body. Move uses a separate endpoint: POST /sheets/v2/spreadsheets/{token}/move_dimension body: { "source": {...}, "destination_index": N } (camelCase "destinationIndex" → snake_case "destination_index" to match the v2 contract.) Both DryRun and Execute updated, plus the TestDimMove_DryRun and TestExecute_DimMove assertions. transform_range.sort_conditions[i] requires both `column` (string) and `ascending` (bool); rangeSortInput passed the --sort-keys array through to the server unvalidated, so missing fields surfaced as opaque "required property X missing" errors with no per-item context. Walk the parsed array client-side, reject with item-pointing messages. Test fixtures and a contract-test fixture switched from the historical {col, order} vocabulary (which the server has never accepted) to the correct {column, ascending}. Server-schema citations and test-report case mapping in this branch's plan file. * revert(sheets): drop direct flag-defs.json edits — generated from spec data/flag-defs.json is regenerated from the upstream sheet-skill-spec canonical-spec; editing it here gets clobbered on the next sync. The schema realignment for +dropdown-set / -update --colors / --highlight removal needs to land on the base table first, then flow back through sheet-skill-spec → larksuite-cli sync, not via a direct CLI-side edit. Restore the previous flag entries verbatim. The Go-side change in buildDropdownValidation still drops the wire fields, so: - users passing --colors / --highlight today see the flag accepted silently (no effect on the wire) until the upstream removal lands; - after upstream removal + sync, both the flag declarations and the Go-side handling will be in sync. Functional fixes (#1 workbook-create, #3 dropdown-get, #4 dim-move, #5 range-sort) and dropdown wire-shape rename (#2) are unaffected. * revert(sheets): drop direct edits to skills/lark-sheets/references/ These md files are sync targets generated from sheet-skill-spec; editing them here gets clobbered on the next sync, same as data/flag-defs.json. The --colors / --highlight row removals belong on the upstream base table → canonical-spec sync, not here. Restore the previous --colors / --highlight rows in both lark-sheets-write-cells.md (+dropdown-set) and lark-sheets-batch-update.md (+dropdown-update). The Go-side change in buildDropdownValidation still drops the wire fields, so: - users passing --colors / --highlight today see the flag accepted silently (no effect on the wire) until upstream removes the flag; - after upstream removal + sync, both flag declarations, ref docs, and Go-side handling will be in sync. Functional fixes (#1 workbook-create, #3 dropdown-get, #4 dim-move, #5 range-sort) and dropdown wire-shape rename (#2) are unaffected. * docs(sheets): sync from sheet-skill-spec — remove dropdown --colors / --highlight Upstream sheet-skill-spec base table deleted the --colors and --highlight flags on +dropdown-set / +dropdown-update (the corresponding wire fields data_validation.colors / .highlight_options were never accepted by the server schema; see prior fix in this branch). Re-running the sync from canonical-spec brings the CLI flag-defs and skill reference docs back in line with the Go-side handling that already drops these fields. Generated by `npm run sync:cli` in sheet-skill-spec @ ac7acef. * fix(sheets): restore +dropdown --colors / --highlight, map to canonical fields Reverses the --colors / --highlight removal from 7932ab2 (item #2 of the batch-1 schema-alignment commit). That commit dropped both flags after the test report flagged data_validation.colors / highlight_options as "unexpected property" — at the time the canonical set_cell_range.data_validation schema listed only help_text / items / operator / range / support_multiple_values / type / values, so the flags had no server-side target and the removal was correct. Since then, set_cell_range.data_validation has gained two fields explicitly modelling the dropdown highlight UI (mcp-tools.json in sheet-skill-spec 2026-05-22 base sync): enable_highlight (bool) — show pill backgrounds highlight_colors (string[]) — hex pill colors, length must match items So the flags are back, but rewired: --colors -> data_validation.highlight_colors (was: colors) --highlight -> data_validation.enable_highlight (was: highlight_options) --options -> items and --multiple -> support_multiple_values renames from 7932ab2 are kept. Changes: - buildDropdownValidation: re-add --colors / --highlight handling against the new field names; --colors length check stays inline (so dropdownSetInput Validate path catches it via validateViaInput, no separate guard needed). - validateDropdownOptions -> validateDropdownOptionsColors: restore the Validate-time --colors length check on +dropdown-update / +dropdown-delete (called from lark_sheet_batch_update.go). - TestDropdownSet_CellsShape: extend to assert highlight_colors / enable_highlight emitted; assert legacy `colors` / `highlight_options` absent. - TestDropdownSet_ColorsLengthMismatch: new — covers the early Validate error path. - TestDropdownUpdate_BatchPayload: extend to cover dropdownBatchInput propagation of --colors / --highlight through batch_update. - skills/lark-sheets/references/lark-sheets-{write-cells,batch-update}.md, shortcuts/sheets/data/flag-defs.json, flag-schemas.json: synced from sheet-skill-spec generate output (MR !7). * chore(sheets): re-sync from spec + loosen --colors length check Catches up to sheet-skill-spec's 2026-05-25 base sync (MR !7) after rebasing onto upstream feat/lark-sheets-refactor (12 new upstream commits including the lark-sheets skill refactor + tools-schema migration). Spec changes flowing in: - highlight_colors description loosened: length may be **shorter than** --options (server cycles remaining slots through a built-in 10-color palette); previously the tool errored on any length mismatch. - shortcuts/sheets/data/flag-schemas.json: mass re-mirror — generator now emits `type` before `properties` and adds explicit `additionalProperties: false` on object schemas (cosmetic, no behavior change). - skills/lark-sheets/references/lark-sheets-{batch-update,chart,write-cells}.md: --options gains the type='list' tag; data_validation inline field-count goes 7 → 9 (catches up the highlight schema in the summary); chart position / size marked optional per upstream. Go-side adjustment: - buildDropdownValidation / validateDropdownOptionsColors: change the --colors length check from strict-equal to "must not exceed --options" to match the relaxed schema. - TestDropdownSet_ColorsLengthMismatch -> TestDropdownSet_ColorsLongerThanOptions (now hits the overflow path with 3 colors vs 2 options). - New TestDropdownSet_ColorsShorterAccepted: 2 colors vs 4 options is legal and forwarded as-is. * docs(sheets): sync dropdown --colors/--highlight clarification from spec Mirrors sheet-skill-spec MR !7 changes: - skills/lark-sheets/references/lark-sheets-write-cells.md: new "Dropdown 配色" section explaining how --colors (→ data_validation.highlight_colors) and --highlight (→ data_validation.enable_highlight) compose — length rule (shorter ok, longer rejected), --highlight gating, palette fallback behavior, minimal +dropdown-set example. - skills/lark-sheets/references/lark-sheets-batch-update.md: one-line pointer to the write_cells section for +dropdown-update / -delete (same rules). - shortcuts/sheets/data/flag-defs.json: --colors / --highlight `desc` fields gain the long-form server-field / length-rule descriptions used by `--help`. No Go-side change — earlier commit 538eb2e already loosened the buildDropdownValidation length check to "must not exceed"; this PR step just makes the docs / `--help` text catch up. * feat(sheets): +dropdown-set/-update --source-range for listFromRange mode Previously +dropdown-set / +dropdown-update only emitted data_validation.type=list — agents wanting listFromRange (dropdown options sourced from existing cells, kept in sync with that range) had to drop down to +cells-set and hand-build a data_validation map. The flag now exposes it natively as --source-range, paired with --options under XOR. CLI changes: - shortcuts/sheets/lark_sheet_write_cells.go: * new dropdownTypeAndItems(runtime) — central XOR resolver: rejects 0 or 2 of {--options, --source-range}, returns (sourceSize, partial dv with type+items|range filled in). Source size = options length for list mode, rangeDimensions(--source-range) cell count for listFromRange. * buildDropdownValidation rewritten to call the resolver, then layer --colors / --multiple / --highlight on top — semantics unchanged for callers, just two modes instead of one. * validateDropdownOptions / -Colors renamed to validateDropdownSourceOrOptions so the XOR + length check fires at +dropdown-update Validate time too. * --colors length error message generalized: "must not exceed dropdown source size (N)" (covers both modes). - shortcuts/sheets/lark_sheet_batch_update.go: rename call site. - shortcuts/sheets/lark_sheet_write_cells_test.go: 4 new tests — ListFromRange (happy path: range + items absent + colors + highlight all emit), ListFromRange_ColorsLongerThanCells (overflow against T1:T3 cell count), XorBothSet, XorNeitherSet. Updated the existing ColorsLongerThanOptions assertion to match the new "source size" wording. Spec-driven changes (synced via npm run sync:cli from sheet-skill-spec MR !7 2c298b6): - shortcuts/sheets/data/flag-defs.json: --options Required flips to xor on +dropdown-set/-update; new --source-range row gains long-form description pointing at server data_validation.range + the XOR semantics. - skills/lark-sheets/references/lark-sheets-write-cells.md: "Dropdown 配色" section reorganized into "Dropdown 选项 + 配色" — XOR comparison table (list vs listFromRange), shared config flag table (--highlight / --colors), explicit length rule covering both modes, side-by-side minimal examples, server-range-normalization gotcha callout. - skills/lark-sheets/references/lark-sheets-batch-update.md pointer updated to mention both modes + that +dropdown-delete is unaffected. PPE smoke (ppe_lark_cli_sheet) on UFJxszjrZhZ1LVtc9FdcICSbn6b C column: - +cells-set C1 → "性别" (bold + centered): updated_cells_count=1 - +dropdown-set --range C2:C21 --source-range "Sheet1!T1:T3" --colors '["#cce8ff","#ffd6e7","#e6e6e6"]' --highlight: updated_cells_count=20 - read-back: data_validation.type=listFromRange + range=$T$1:$T$3 (server normalizes the prefix away on storage; highlight_colors / enable_highlight not echoed by get_cell_ranges, see byted-sheet read projection TODO). - error-path replay (both XOR violations + colors > source-size) all rejected at Validate stage with the expected messages. * docs(sheets): sync agent-voice rewrite of Dropdown 选项+配色 from spec Mirrors sheet-skill-spec MR !7 60df610 — narrative now describes how the flags interact (XOR, colors length rule, highlight gating, sheet-prefix read-back gotcha) without exposing the underlying data_validation field names or server-side normalization details that agents don't act on. No Go-side change, no shortcut behavior change. * chore(sheets): restore --colors in parseJSONFlag docstring example list The earlier commit 49104ec swapped --colors out of parseJSONFlag's "Used by" example list when it deleted the flag (item #2 there removed --colors / --highlight from +dropdown-set/-update). Subsequent commits 8672d8e / 538eb2e / fb90c8b reinstated --colors (and added --source-range) but did not roll back this docstring tweak — leaving an orphan reference to --properties where --colors used to be. This restores the example list to its pre-49104ec form so the docstring matches what the helper actually services on this branch's HEAD. Pure docstring change — function behavior unaffected, no test movement. * fix(sheets): post-rebase test fixups after dropping superseded fix #1 Two test fallouts from rebasing onto upstream 4be06c8 (which independently re-fixed +workbook-create and +dim-move with a more thorough approach): - shortcuts/sheets/lark_sheet_workbook_test.go: our PR's earlier TestWorkbookCreate_DryRun "with headers and data → 2-step plan" subtest asserted the expedient sheet_name="Sheet1" / no-sheet_id wire body that matched our dropped fix #1 implementation. Upstream's fix #1 resolves the workbook's first sheet via get_workbook_structure and fills with the real sheet_id instead. Reset this file to upstream's version — our superseded assertions disappear, upstream's tests cover the new wire shape. - shortcuts/sheets/execute_paths_test.go: TestExecute_RangeSort fixture still used the legacy {col, order} sort-key shape because the rebase resolution picked the upstream version of this file wholesale (it contained other unrelated changes). Re-apply just the one fixture update to {column, ascending} so fix #5's CLI-side rejection logic exercises a valid input — server-side sort_conditions has required fields `column` (string) and `ascending` (bool); the historical {col, order} vocabulary was never accepted. go build ./... + go test ./shortcuts/sheets/... -count=1 both green. * feat(sheets): +dropdown --highlight tri-state via Changed() for opt-out The server-side default for data_validation.enable_highlight flipped from false to true (aligning with the UI behavior). With the previous code path if runtime.Bool("highlight") { dv["enable_highlight"] = true } omitting --highlight and passing --highlight=false both produced the same "enable_highlight key absent" body, leaving CLI users with no way to opt out of the (now-default) highlighting. Switch to runtime.Changed() so the translator can distinguish all three input shapes: - omitted -> no enable_highlight key (server applies default=true) - --highlight=true -> enable_highlight: true (explicit no-op vs default) - --highlight=false -> enable_highlight: false (the only opt-out path) flagView already exposes Changed() and mapFlagView (the +batch-update sub-op adapter) implements it via raw-key presence — same pattern other translators use for "Changed-only" branching (e.g. omit target_index unless --index was set), so no interface surface change is needed. Test coverage: - TestDropdownSet_HighlightTriState pins all four shapes (omit / presence form / explicit true / explicit false) and asserts the enable_highlight key's presence/value - TestBatchOp_BodyMatchesStandalone adds a --highlight=false sub-op case so the batch sub-op path produces a body byte-identical to the standalone +dropdown-set --highlight=false body * chore(sheets): sync +dropdown flag desc + write-cells narrative from spec Mirror sheet-skill-spec generated/ into shortcuts/sheets/data/ and skills/lark-sheets/ for the +dropdown-set / +dropdown-update path. No hand edits in this repo. The +dropdown flag desc and the Dropdown 配色 narrative now match the server-side enable_highlight default flip (true) and the tri-state --highlight semantics introduced in the sibling commit: * --highlight desc: 不传 = 开(按内置 10 色色板循环上色), --highlight=false 关闭得到纯白下拉 * --colors desc: 单独传即生效(高亮默认开),--highlight=false 时忽略 * write-cells reference: 三种意图三条线(默认色板 / 指定颜色 / 纯白下拉)+ 新增 --highlight=false 示例 Source upstream: sheet-skill-spec MR !8. * fix(sheets): validate +cells-set-image --image path in Validate The unsafe-path check only ran at Execute (via FileIO.Stat), so --dry-run printed a misleading success preview for an absolute / out-of-cwd --image path that a real run would then reject. Move the path-safety check into Validate (validate.SafeLocalFlagPath), so --dry-run and Execute fail identically and both name the real --image flag. File existence stays deferred to Execute, so legitimate relative paths still preview cleanly. Add TestCellsSetImage_DryRunRejectsUnsafePath. * feat(sheets): support local --image in +float-image-create +float-image-create now accepts a local file via --image (XOR with --image-token / --image-uri): the CLI uploads it as a sheet_image and embeds the returned file_token, removing the previous "upload elsewhere to get a token first" workaround. Path safety is checked in Validate, --dry-run previews the extra upload step, and +batch-update rejects --image (no upload phase). +float-image-update is unchanged (it does not register --image). Also syncs the lark-sheets skill docs/flag-defs from sheet-skill-spec: the new --image flag, partial-merge / border-per-side / bare sheet-prefix clarifications, and refreshed dropdown --colors/--highlight descriptions (already pending in the source Base table). * fix(sheets): +dropdown-get accepts --sheet-id/--sheet-name + bare --range Align +dropdown-get with its get_cell_ranges siblings (+cells-get / +csv-get): sheet selection is now via --sheet-id / --sheet-name (XOR) and --range is a bare A1 reference. The previous shape required the sheet prefix inside --range (e.g. "Sheet1!A2:A100") and was the odd one out among the read-data wrappers; callers pasting the sheet-id form straight from the URL hit a misleading "sheet not found, sheetId: , sheetName: <id>" error because the prefix was unconditionally treated as sheet_name. Flag schema + skill reference regenerated from the upstream Lark Base Shortcut-flags table. * fix(sheets): drop Sheet1! prefix from +cells-get / +csv-get / +csv-put flag examples Server tools-schema.json for get_cell_ranges, get_range_as_csv and set_range_from_csv does not accept a sheet prefix on --range / --start-cell; the sheet is selected via --sheet-id / --sheet-name. +csv-put --start-cell also now states it must be a single cell (no range notation). Synced from spec repo. * feat: 把环境变量提交上去 * fix(sheets): clarify batch --ranges prefix must be sheet display name E2E test cases repeatedly trip on this: $ lark-cli sheets +cells-batch-set-style \ --ranges '["7f8fba!A2:B3","7f8fba!C2:D3"]' --font-color '#3366FF' ... → tool "batch_update" failed: [900015206] sheet "7f8fba" not foun…
tuxedomm
pushed a commit
to zhumiaoxin/cli
that referenced
this pull request
Jun 6, 2026
…ksuite#467) * feat(doc): expand callout type= shorthand into background-color and border-color When users write <callout type="warning" emoji="📝"> without an explicit background-color, the Feishu doc renders the block with no color. This commit adds fixCalloutType() which maps the semantic type= attribute to the corresponding background-color/border-color pair accepted by create-doc. - warning → light-yellow/yellow - info/note → light-blue/blue - tip/success/check → light-green/green - error/danger → light-red/red - caution → light-orange/orange - important → light-purple/purple Explicit background-color or border-color attributes are always preserved. The fix is applied via prepareMarkdownForCreate() in both +create and +update paths, and also inside fixExportedMarkdown() for round-trip fidelity. * refactor(doc): replace silent callout type→color injection with hint output Per reviewer feedback (SunPeiYang996), silently rewriting user Markdown is the wrong layer for this adaptation. The type→color mapping is not part of the Feishu spec, and covert transforms make debugging harder. Replace fixCalloutType() (which rewrote the Markdown) with WarnCalloutType() which leaves the Markdown unchanged and instead writes a hint line to stderr for each callout tag that has type= but no background-color, telling the user the recommended explicit attributes to add: hint: callout type="warning" has no background-color; consider: background-color="light-yellow" border-color="yellow" Also fixes CodeRabbit feedback: the type= regex now accepts both single-quoted and double-quoted attribute values (type='warning' and type="warning"). * fix(doc): harden background-color detection in WarnCalloutType CodeRabbit flagged that the previous strings.Contains(attrs, "background-color=") check missed forms like 'background-color = "light-red"' with whitespace around the equals sign. Replace with a regex that tolerates optional whitespace, and add a regression test. * fix(doc): close real review gaps left over after rebase PR larksuite#467's review thread had three substantive comments (`fangshuyu-768`, 2026-04-21) that the prior reply messages claimed were fixed in commit 7d4b556 — but that commit no longer exists on the branch (lost in a rebase / squash), and the head still ships the original buggy code. This commit makes the fixes real. Three behavior fixes in shortcuts/doc/markdown_fix.go: 1. (larksuite#5) Tighten the type= and background-color= regex anchors. \b sits at any word/non-word boundary, and `-` is a non-word char, so `\btype=` also matched the suffix of `data-type=` — a tag like `<callout data-type="warning">` would emit a bogus light-yellow hint. Switched both regexes to `(?:^|\s)…` so a real attribute separator is required. The same anchor on background-color closes the symmetric case where a `data-background-color=` attribute would silently suppress the real hint. 2. (larksuite#4) WarnCalloutType is now a fence-aware line walker. Previously the regex ran over the entire markdown body, so a callout sample inside a documentation code fence (```markdown … ```) would generate a phantom stderr hint every time the docs mentioned the feature. The walker tracks fence state via the existing codeFenceOpenMarker / isCodeFenceClose helpers from docs_update_check.go, which handle both backtick and tilde fences per CommonMark §4.5. 3. (larksuite#3) Drop the ReplaceAllStringFunc-as-iterator pattern. The previous code routed callout iteration through a rewrite primitive whose rebuilt-string return value was discarded, then ran the same regex a second time inside the callback to recover the capture groups. New scanCalloutTagsForWarning helper uses FindAllStringSubmatch — one pass, no thrown-away allocation, intent matches the surface (read-only scan, not a mutator). Tests: 5 new TestWarnCalloutType subtests pin each contract: - data-type attribute does not trigger hint (larksuite#5) - data-background-color does not suppress hint (larksuite#5, symmetric) - callout inside backtick fence emits no hint (larksuite#4) - callout inside tilde fence emits no hint (larksuite#4) - callout after fence close still emits hint (larksuite#4, fence-state reset) All 14 TestWarnCalloutType cases pass; go vet / golangci-lint --new-from-rev=origin/main both clean.
tuxedomm
pushed a commit
to zhumiaoxin/cli
that referenced
this pull request
Jun 6, 2026
…package (larksuite#1220) * refactor(sheets): rebuild lark-sheets on sheet-skill-spec canonical + One-OpenAPI Restart lark-sheets as a spec-driven downstream. Skill content (SKILL.md and 16 references covering 13 operations skills + 3 workflow skills, including the standalone filter-view skill) is mirrored from the sheet-skill-spec canonical-spec; do not hand-edit, change upstream and rerun npm run sync:consumers. Drop the 11 legacy shortcut sources (spreadsheet / sheet management, cell ops, dropdown, filter-view, float image, etc.) and 10 associated tests. Wire up the new sheet_ai/v2 One-OpenAPI single entry that dispatches by tool_name with JSON-string input/output, and land the first canonical shortcut +workbook-info as a template that exercises the public token XOR pair, Risk tiering, and zero-side-effect DryRun. sheet_ai_api.go provides callTool / invokeToolDryRun and bypasses runtime.CallAPI's silent swallowing of non-envelope responses so gateway and business errors from the new endpoint surface precisely. The remaining 55 shortcuts will be designed and landed separately, canonical skill by canonical skill. * feat(sheets): implement lark_sheet_workbook shortcuts (B1) Land the 8 modify_workbook_structure shortcuts that round out the lark_sheet_workbook canonical skill alongside the existing +workbook-info: +sheet-create / +sheet-delete / +sheet-rename / +sheet-move / +sheet-copy / +sheet-hide / +sheet-unhide / +sheet-set-tab-color. All eight call modify_workbook_structure via the One-OpenAPI invoke_write endpoint, dispatched by the `operation` enum. Helpers in helpers.go grow publicSheetFlags() / resolveSheetSelector() / sheetSelectorForToolInput() / sheetSelectorPlaceholder() so future sheet-level shortcuts share the public --sheet-id / --sheet-name XOR treatment. +sheet-create intentionally drops the sheet selector pair since create has no existing-sheet anchor (matches the spec fix in tool-shortcut-map.json). +sheet-delete is the first high-risk-write shortcut in the canonical package; the framework requires --yes (exit code 10 otherwise). +sheet-move's tool requires source_index in addition to target_index. The CLI accepts an optional --source-index override and falls back to a single get_workbook_structure read to derive it (and to resolve sheet_id from --sheet-name). DryRun stays network-free by rendering <resolve> placeholders for any field that would need that read. * feat(sheets): implement lark_sheet_sheet_structure shortcuts (B2) Add 8 shortcuts under the lark_sheet_sheet_structure canonical skill: +sheet-info (get_sheet_structure) plus +dim-insert / +dim-delete / +dim-hide / +dim-unhide / +dim-freeze / +dim-group / +dim-ungroup (modify_sheet_structure, dispatched by operation enum). Two reusable conversion helpers cover the impedance mismatch between the CLI surface and the tool input: - dimRange / dimPosition translate the CLI's 0-based exclusive-end range into the tool's 1-based A1 notation. row 5..8 becomes position "6" + count 3 (insert) or range "6:8" (range ops); column 26..29 becomes "AA:AC". - infoTypeFromInclude maps the fine-grained --include vocabulary (row_heights / col_widths / merges / hidden_rows / hidden_cols / groups / frozen) to the coarse info_type enum the tool accepts; mixed categories collapse to "all". +dim-delete is high-risk-write (irreversible row/column removal). +dim-freeze --count 0 auto-dispatches to operation=unfreeze. +dim-group accepts --depth for forward-compat with a future server-side nested group endpoint but does not pass it through today. * feat(sheets): implement read_data / search_replace / write_cells shortcuts (B3) Land 11 shortcuts across three canonical skills: - lark_sheet_read_data (3): +cells-get / +csv-get / +dropdown-get - lark_sheet_search_replace (2): +cells-search / +cells-replace - lark_sheet_write_cells (6): +cells-set / +cells-set-style / +csv-put / +dropdown-set / +dropdown-update / +dropdown-delete +dropdown-get reads the data_validation field via get_cell_ranges with the range carrying its own sheet prefix (no --sheet-id needed). The fine-grained --include vocabulary (value / formula / style / comment / data_validation) maps to the tool's coarse include_styles bool plus value_render_option enum. +csv-get's --include-row-prefix=false strips the [row=N] prefix client-side because the tool only emits the annotated form. +cells-search / +cells-replace flatten the tool's options sub-object into four independent flags (--match-case / --match-entire-cell / --regex / --include-formulas) per the flat-flag rule, then repack them on the way in. +cells-set takes a raw --data JSON body whose `cells` array must match the --range dimensions. +cells-set-style fans a single --style block out to every cell in the range via a new fillCellsMatrix helper; the range parser (rangeDimensions / splitCellRef / letterToColumnIndex) only accepts rectangular A1:B2 forms — whole-column / whole-row need sheet totals and are deferred. +dropdown-set fans the validation block out to one range; +dropdown- update / +dropdown-delete iterate sheet-prefixed --ranges and call set_cell_range sequentially (partial failure leaves earlier ranges already mutated; the Tip calls this out). +dropdown-delete is high-risk-write and requires --yes. +cells-set-image stays deferred to the cli-only batch (needs the shared local-file upload helper alongside +workbook-create / +dim-move / +workbook-export). * refactor(sheets): move +dropdown-update / +dropdown-delete to lark_sheet_batch_update Follow-up to B3 after the spec re-mapped these two shortcuts to the batch_update tool (atomic multi-range CRUD) instead of fan-out via set_cell_range. Drop their Go implementations + helper validateDropdownRanges + splitSheetPrefixedRange from lark_sheet_write_cells.go and remove the registrations from Shortcuts(); the shortcuts will reappear under lark_sheet_batch_update during B7. Also pull in the re-rendered reference docs: - skills/lark-sheets/references/lark-sheets-write-cells.md - skills/lark-sheets/references/lark-sheets-batch-update.md * feat(sheets): implement lark_sheet_range_operations shortcuts (B4) Land 8 shortcuts across four canonical tools: - clear_cell_range → +cells-clear (high-risk-write) - merge_cells → +cells-merge / +cells-unmerge - resize_range → +dim-resize - transform_range → +range-move / +range-copy / +range-fill / +range-sort Three CLI↔tool vocabulary bridges live in this file: - +cells-clear: --scope content normalizes to the tool's clear_type "contents" (singular/plural spec mismatch is absorbed in the CLI). - +dim-resize: --size <px> wraps as resize_{height,width}:{value:N}; --reset wraps as {reset:true}. The two flags are mutually exclusive and at least one is required. - +range-fill: CLI's five-valued --series-type collapses to the tool's binary fill_type — `copy` → "copyCells", anything else → "fillSeries" (the actual series progression is inferred server-side from the seed cells in --source-range). - +range-copy: --paste-type {values, formulas, formats} maps to the tool's {value_only, formula_only, format_only}; "all" omits the field entirely so the server applies its default. +cells-clear is the second high-risk-write shortcut in the package; the framework enforces --yes with exit code 10 as usual. * feat(sheets): implement object-list shortcuts (B5) Land 7 read shortcuts, one per object skill — chart / pivot table / conditional format / filter / filter view / sparkline / float image. All share the same shape (public sheet selector + optional <obj>-id filter) so they're declared via newObjectListShortcut + an objectListSpec. Notes: - +cond-format-list exposes --rule-id, which is renamed to conditional_format_id on the wire (the tool's full field name). - +sparkline-list exposes --group-id (the higher-level handle); the tool also accepts sparkline_id, intentionally not surfaced. - +filter-list takes no id filter — at most one sheet-level filter per sheet, so the listing is already unique. - +filter-view-list is `cli_status: cli-only` but get_filter_view_objects is in mcp-tools.json and dispatches through the same One-OpenAPI endpoint; no special path required. * feat(sheets): implement object CRUD shortcuts (B6) Land 21 shortcuts — three (create / update / delete) per object skill — backed by the manage_<obj>_object tools dispatched on the operation enum. Five standard objects (chart / cond-format / sparkline / float-image / filter-view) share an objectCRUDSpec factory; pivot and filter are special-cased. Shared wire contract: excel_id + sheet_id|sheet_name + operation + [<obj>_id] + [properties] CLI --data is passed through as the tool's `properties` field as-is, so callers shape it per each object's spec doc. Special cases: - pivot adds optional --target-sheet-id / --target-position on create (siblings of properties, not inside it). - cond-format exposes --rule-id (short CLI name) wired to the tool's conditional_format_id on the wire. - sparkline uses --group-id (higher-level object handle) instead of sparkline_id. - filter has no separate id flag — at most one filter per sheet, so filter_id is implicit. +filter-create promotes --range to a first- class flag (instead of burying it inside --data). - filter-view CRUD are `cli_status: cli-only` but manage_filter_view_object is in mcp-tools.json, so they go through callTool / One-OpenAPI alongside everything else. All delete shortcuts are high-risk-write and require --yes. * feat(sheets): implement lark_sheet_batch_update shortcuts (B7) Land 4 shortcuts that all funnel through the batch_update tool's atomic operations array: - +batch-update raw passthrough; --data carries the full { operations: [{tool, params}, ...] } payload plus optional continue_on_error. high-risk-write since the caller may stuff anything inside. - +cells-batch-set-style --data is [{ranges, style}, ...]; CLI flattens each (entry × range) pair into a set_cell_range op with a fan-out cells matrix carrying cell_styles + border_styles. - +dropdown-update --ranges + --options (+ --colors / --multiple / --highlight) — installs/replaces one dropdown across many ranges, each becoming a separate set_cell_range op with data_validation in cells. - +dropdown-delete --ranges — clears data_validation across many ranges (high-risk-write). Default is strict transaction: if any sub-tool fails the whole batch rolls back. +batch-update exposes --continue-on-error to flip the policy; the three fan-out shortcuts leave it strict (they're meant to be all-or-nothing). Reinstates validateDropdownRanges + splitSheetPrefixedRange that were removed during B3 → B7 relocation. * feat(sheets): implement cli-only shortcuts (B8) — 70/70 complete Land the four cli-only shortcuts that can't route through the One-OpenAPI dispatcher (their backing capabilities aren't in mcp-tools.json): - +workbook-create POST /open-apis/sheets/v3/spreadsheets + optional set_cell_range follow-up that zips --headers and --data into the first sheet starting at A1. - +workbook-export POST /open-apis/drive/v1/export_tasks (type=sheet) → poll /export_tasks/:ticket up to ~30s → optional GET /export_tasks/file/:file_token/download. CSV mode requires --sheet-id (single sheet export). - +dim-move POST /open-apis/sheets/v2/spreadsheets/:token /dimension_range CLI is 0-indexed inclusive (--start / --end); the v2 endpoint expects half-open [startIndex, endIndex) so the body uses endIndex = --end + 1. --sheet-name is resolved client-side to sheet_id via lookupSheetIndex when needed. - +cells-set-image common.UploadDriveMediaAll (parent_type=sheet_image, parent_node=token) then callTool set_cell_range with cells carrying rich_text: [{type:"embed-image", attachment_token, attachment_name}]. --range must be exactly one cell. All four use runtime.CallAPI / DoAPI directly; only +cells-set-image combines a legacy upload with the new One-OpenAPI for the second step (set_cell_range is in mcp-tools.json so callTool is the right path). This closes the migration: 70 shortcuts × 17 canonical skills × matching the sheet-skill-spec v0.5.0 tool-shortcut-map. * test(sheets): cover all 70 shortcuts with dry-run + execute-path tests Twelve _test.go files alongside the implementation, mirroring the legacy package's coverage style: - testhelpers_test.go shared rig: TestFactory + Mount + dry-run capture + JSON-input decode + envelope helpers. - lark_sheet_*_test.go one test file per implementation file (9 files), table-driven dry-run cases per shortcut plus targeted validation guards. - execute_paths_test.go end-to-end execute paths via httpmock stubs. Covers callTool unwrap, JSON-string output decoding, two-step lookup (+sheet-move), batch_update fan-out, dropdown atomic writes, and the legacy OAPI shortcuts (+workbook-create, +dim-move) including CLI inclusive → API half-open index conversion. Test coverage on the sheets package is 60.5 % of statements with -race clean, meeting the dev manual's ≥ 60 % patch-coverage gate. * refactor(sheets): inline cli-only shortcuts into their canonical skill files Two naming cleanups: - lark_sheet_cli_only.go is gone. The four shortcuts it grouped (+workbook-create / +workbook-export / +dim-move / +cells-set-image) were bundled by their implementation pattern (legacy OAPI direct calls) rather than by canonical skill. The whole sheets package IS the CLI implementation, so "cli only" wasn't a meaningful grouping at the Go layer. Each shortcut now lives next to its skill peers: +workbook-create / +workbook-export → lark_sheet_workbook.go +dim-move → lark_sheet_sheet_structure.go +cells-set-image → lark_sheet_write_cells.go Per-skill shortcut counts now match tool-shortcut-map.json exactly (workbook: 11, sheet_structure: 9, write_cells: 5). Helpers (buildInitialFillInput, pollExportTask, downloadExportFile, dimMoveBody) move with their shortcuts; nothing else in the package referenced them. - testhelpers_test.go → helpers_test.go. The _test.go suffix already conveys "test"; the leading "test" was redundant. Matches the helpers.go naming convention. Behavior unchanged. go test -race -cover stays at 60.5 %. * refactor(sheets): sync shortcut flags with sheet-skill-spec v0.5.0 Upstream hoisted a batch of high-frequency scalar fields out of --data into independent flags and renamed several composite-JSON flags to match their semantic content. CLI catches up. Renames (drop-in, same payload semantics): - +cells-replace --replace → --replacement - +cells-set --data → --cells - +workbook-create --data → --values - +batch-update --data → --operations (now a bare array; still accepts the envelope form for back-compat with continue_on_error) Flat-flag hoists out of --style / --data: - +cells-set-style / +cells-batch-set-style --style JSON drops; replaced by 11 flat style flags (--background-color / --font-color / --font-size / --font-style / --font-weight / --font-line / --horizontal-alignment / --vertical-alignment / --word-wrap / --number-format) plus --border-styles for the one field that's still nested. Both shortcuts share styleFlatFlags() + buildCellStyleFromFlags(). - +cells-batch-set-style also drops the [{ranges, style}] array shape in favor of one --ranges + the same flat style flags applied to all of them. Object CRUD --data → --properties everywhere (chart / pivot / cond-format / filter / filter-view / sparkline / float-image). Per-skill scalar hoists merged into properties via an enhanceCreate/UpdateInput callback: - +pivot-create adds --source (required), --range (and continues to expose --target-sheet-id / --target-position at top level) - +cond-format-{create,update} adds --rule-type (enum) + --ranges (JSON array); merged into properties.rule.type and properties.ranges respectively - +filter-view-{create,update} adds --view-name and --range; both override their properties.* counterparts - +filter-update adds first-class --range (was buried in --data) Float-image is fully hoisted — no --properties flag at all. Ten flat flags (--image-name / --image-token | --image-uri / --position-row / --position-col / --size-width / --size-height / --offset-row / --offset-col / --z-index) compose the properties block. Implemented as its own factory (newFloatImageWriteShortcut) since it diverges from the shared CRUD spec. Tests track every flag renamed and add explicit cases for the new flag combos. go test -race -cover stays at 60.3 %. * refactor(sheets): align batch_update + cells-set with synced reference docs Sync to upstream reference doc updates for 9 skills: - batch_update sub-ops: rewrite wire fields tool/params -> tool_name/input in CellsBatchSetStyle and DropdownUpdate/Delete fan-out (the actual server contract per Schemas section); update --operations flag desc and tests. - +cells-set --cells: accept bare 2D matrix [[{cell},...],...] instead of envelope {"cells":[[...]]}; spec example shows bare-array form. - sparkline createDataDesc enum: win_loss -> winLoss (camelCase). All other doc changes (float-image flat flags, cond-format --rule-type/--ranges, pivot create-only --source/--range, filter / filter-view extra flags, chart --properties) were already aligned in commit ce33315. * fix(sheets): repair cells-set-image rich_text embed payload The server rejected set_cell_range calls from +cells-set-image with three distinct errors: missing "text" property, missing image_width/image_height, and unknown attachment_token field. Realign the rich_text element to the embed-image schema (text/image_token/image_width/image_height) and decode PNG/JPEG/GIF dimensions from the local file before the write. * refactor(sheets)!: split +dim-resize into +rows-resize and +cols-resize Sync to upstream spec change that splits the legacy +dim-resize shortcut into +rows-resize and +cols-resize. Reasoning is that row vs column resize has divergent semantics (only rows support auto-fit) and the shared --dimension flag was hiding that. Behavior changes (BREAKING): - +dim-resize is removed; use +rows-resize or +cols-resize. - --dimension and --reset flags are gone. - --type enum replaces --size/--reset: pixel (requires --size) standard (reset to sheet default; no --size) auto (auto-fit row height; +rows-resize only) - --end is now inclusive (was exclusive). Old "--start 0 --end 5" (5 rows) becomes "--start 0 --end 4". - Wire payload for resize_height / resize_width changes from {value: N} | {reset: true} to {type: "pixel", value: N} | {type: "standard"} | {type: "auto"}. Tests cover both shortcuts across pixel / standard / auto and the new guard surface (--type pixel needs --size; standard/auto reject --size; +cols-resize rejects --type auto; --end < --start). Also pulls in synced reference docs for 5 skills (batch-update, core-operations, range-operations, sheet-structure, visual-standards) that update prose mentions of +dim-resize. * feat(sheets): add --print-schema runtime introspection for composite JSON flags Composite JSON flags (--cells / --properties / --operations / --border-styles / --sort-keys / --options) carry non-trivial structured payloads. Reference docs cover top-level fields but agents writing those flags often need the full JSON Schema to build a valid payload. This adds a system-level introspection contract so any shortcut whose flags are tracked upstream can serve its schemas locally: lark-cli sheets <shortcut> --print-schema --flag-name <name> lark-cli sheets <shortcut> --print-schema # list flags The schema data is embedded at build time from a synced artifact (shortcuts/sheets/data/flag-schemas.json). Upstream is the source of truth — never hand-edit the JSON; update the source Base table and rerun the sheet-skill-spec sync. Framework changes (shortcuts/common): - types.go: Shortcut gains an opt-in PrintFlagSchema hook (flagName -> bytes/error). When non-nil the framework auto-injects --print-schema / --flag-name and short-circuits Validate/Execute. - runner.go: register the two system flags when PrintFlagSchema is set; intercept in runShortcut before identity/scope/config so pure-local lookups don't trigger auth or network. Install a PreRunE that relaxes cobra's required-flag gate when --print-schema is set, since asking for a schema shouldn't need unrelated required flags. Sheets surface (shortcuts/sheets): - flag_schema.go (new): go:embed data/flag-schemas.json; expose printFlagSchemaFor(command) closure. When flagName is empty it emits a JSON listing of introspectable flags for discovery; otherwise it returns the schema subtree as pretty JSON. - flag_schema_test.go (new): cover embed parsing, listing / by-name lookup, unknown-flag error path, registration via Shortcuts(), and the full system-flag short-circuit through cobra (required flags relaxed, schema printed on stdout). - shortcuts.go: Shortcuts() now wraps shortcutList() and attaches PrintFlagSchema to every command present in flag-schemas.json, so shortcuts opt in by being listed upstream — no per-shortcut boilerplate. - data/flag-schemas.json (new, synced from sheet-skill-spec): 19 entries, schema_version "2". Generated upstream from the Lark Base source-of-truth (see sheet-skill-spec scripts/fetch_cli_flag_schema_map.mjs); ships only per-flag subtrees (not the full mcp-tools.json) to keep tool internals out of the open-source repo. Skill docs (skills/lark-sheets): - SKILL.md: system-flag table gains --print-schema / --flag-name and an "Agent 使用提示" note steering agents to prefer --print-schema over guessing JSON shape from the cheatsheet. - references/*.md: regenerated by upstream sync (Schemas-section boilerplate updated, plus accumulated upstream prose refinements). * docs(sheets): remove sandbox references and normalize tool names to CLI shortcuts Replace export_sheet_to_sandbox / import_sandbox_to_sheet / doubao_code_interpreter with local-script + batch csv-get/csv-put workflows; unify legacy MCP tool names (set_cell_range, get_range_as_csv, etc.) to CLI shortcut format (+cells-set, +csv-get). * feat(sheets): add flag-descriptions.en.json and wire applyFlagDescs into Shortcuts() Embed data/flag-descriptions.en.json (synced from upstream spec) and apply it at shortcut assembly time so every Flag.Desc is sourced from the canonical JSON rather than hardcoded Go strings. Existing hardcoded Desc values serve as fallback for flags not yet in the JSON. Also sync reference doc updates from upstream. * feat(shortcuts): support int64 and float64 flag types Flag.Type previously could not express non-integer numbers. Add int64 and float64 cases to flag registration plus Int64/Float64 runtime accessors. * refactor(sheets): build shortcut flags generically from flag-defs.json Replace flag-descriptions.en.json with the richer flag-defs.json (full flag definitions: type / default / enum / input / hidden / required / kind) synced from sheet-skill-spec. Add flagsFor(command) to materialize each shortcut's []common.Flag straight from the JSON, skipping system-kind flags the framework injects. Migrate every sheets shortcut (including the CRUD/list/dim/merge/ visibility factories) to Flags: flagsFor("+command"), dropping all hand-written flag literals plus the now-dead publicTokenFlags / publicSheetFlags / styleFlatFlags helpers and enum vars. A coverage test locks the Go-flags-match-JSON contract. Align Go with the new spec where they diverged: +cells-get --ranges → --range, font-size int → float64, +filter-view-create --range now required, +sheet-create row/col-count defaults 200/20. * docs(sheets): sync +batch-update CLI override schema (shortcut/input form) Pulled from sheet-skill-spec: - skills/lark-sheets/references/lark-sheets-batch-update.md: --operations now documents the {shortcut, input} form; tool_name references gone - shortcuts/sheets/data/flag-schemas.json: --operations resolves to the CLI-side array<{shortcut(enum), input}> schema, sourced from spec's canonical-spec/tool-schemas/cli-schemas.json (cli: prefix). +dropdown --options also drilled one level deeper NOTE: the binary still raw-passes --operations to MCP batch_update which expects {tool_name, input}. A follow-up will add a shortcut→tool_name translation layer (with per-shortcut operation field) before the docs become actionable. * feat(sheets): translate +batch-update sub-ops {shortcut,input} → MCP shape Users now hand +batch-update --operations a CLI-shape array ([{shortcut, input}, ...]) and the binary translates each sub-op to the underlying MCP batch_update shape ({tool_name, input(+operation)}) via a new dispatch table in shortcuts/sheets/batch_op_dispatch.go. Dispatch table covers 50 batchable write shortcuts. Excluded by design: - all read ops - fan-out wrappers (+batch-update self, +cells-batch-set-style, +dropdown-update, +dropdown-delete) — nesting these = nested batch - +dim-move — single shortcut uses legacy v2 /dimension_range endpoint, not MCP, can't be batched - +cells-set-image — multi-step image upload, not atomic-batch friendly - +workbook-create — new workbook, not batch-on-existing semantics Translator also rejects sub-ops that hand-fill input.operation (implied by shortcut name) or input.excel_id / spreadsheet_token / url (set once at +batch-update top level). +dim-freeze always injects operation=freeze; the count==0 unfreeze path of the single shortcut is intentionally not supported in batch — callers should use the single shortcut for unfreeze. Tests cover: end-to-end translation, --continue-on-error propagation, 13 rejection cases (banned shortcuts, malformed shapes, reserved keys). Sync'd from sheet-skill-spec: skills/lark-sheets/references/ lark-sheets-batch-update.md + shortcuts/sheets/data/flag-schemas.json pick up the corrected enum (+cells-set-style / +dropdown-set added, +dim-move removed). * fix(sheets): make +batch-update sub-ops reuse standalone flag→body translators Sub-ops previously near-passed-through their input, so any shortcut whose standalone translator renames fields broke inside a batch: +range-copy lost range/destination_range (transform_range errored "range missing") and +rows-resize lost range/resize_height ("No resize operation specified"). Introduce a flagView interface (satisfied by *common.RuntimeContext) and a map-backed mapFlagView, then route every batchable sub-op through the SAME *Input builder the standalone shortcut uses. mapFlagView seeds flag-defs.json defaults for value reads while keeping Changed() user-driven, so a sub-op body is byte-identical to the standalone body — locked by a batch-vs-standalone contract test over all ~40 batchable shortcuts. Also fix single-row/column resize: start==end now formats as "23:23" / "C:C" (resize_range rejects a bare "23"); dimRangeFull keeps both sides while dimRange's collapse stays for modify_sheet_structure consumers. * fix(sheets): align +cells-get/+csv-get range flags with synced spec sheet-skill-spec now declares +cells-get --range as a single string (was string_array) and +csv-get --range as required. Match the flag→body translators: - +cells-get wraps the single --range into the tool's `ranges` array and validates with Str() instead of StrArray(), which silently returned nil against the now-String flag and broke the command. - +csv-get gains a trim-based required-range guard. Update read-data dry-run tests to single-range form and add a guard test for the empty --range path. * fix(sheets): push +batch-update sub-op validation down into xxxInput builders Sub-ops that omit --sheet-id (or any other required flag) used to slip past CLI validation — Validate ran only against the standalone shortcut path, and batchOpDispatch's translators built bodies from whatever flagView returned, so a structurally broken sub-op surfaced as an opaque server "sheet undefined not found" after a network round-trip. Push each batchable shortcut's check trio down into its xxxInput builder: 1. resolveSpreadsheetToken — stays in Validate (batch already does it once at the top level; sub-ops don't repeat). 2. requireSheetSelector(sheetID, sheetName) — new helper; flagView- agnostic XOR + control-char check, called at the top of every xxxInput. 3. shortcut-specific required / range / enum checks (--dimension, --range, --start <= --end, --type pixel needs --size, --float-image-id, image-token XOR image-uri, ...) — moved out of Validate into the builder body. All ~30 batchable xxxInput builders now return (map, error). Standalone Validate shrinks to validateViaInput(xxxInput); DryRun / Execute propagate the error. batch_op_dispatch entries drop the noErrTranslate wrapper and pass the builder directly — its error bubbles up wrapped with "operations[N] (+shortcut):" context. Tests: - TestBatchOp_ErrorEquivalence (7 cases): XOR / logical-constraint errors fire identically from standalone and batch sub-op paths. - TestBatchOp_RejectsBadSubOpInput (8 cases): cobra-required flags that standalone catches via MarkFlagRequired now also get rejected CLI-side on the batch path (where cobra is not in the loop). - TestBatchOp_BodyMatchesStandalone (~40 cases) and TestBatchOp_DispatchCoversReportedBugs continue to pass — bodies stay byte-identical. - BOE smoke (spreadsheet ICFwstkUGheyfptGWS2bB7RgcDf, sheet 51991c): +batch-update with a sub-op missing --sheet-id now returns "operations[0] (+dim-insert): specify at least one of --sheet-id or --sheet-name" before any network call. sheetMoveBatchInput (xiongyuanwen's batch-only explicit-source-index requirement) is preserved — it's an orthogonal batch-specific constraint not affected by this push-down. * fix(sheets): align +cond-format / +filter with server schema (#4 + #5) Two latent bugs in the object_crud translator surfaced during BOE smoke testing of +batch-update. Both are schema-alignment fixes against manage_conditional_format_object / manage_filter_object as declared in sheet-skill-spec/canonical-spec/tool-schemas/mcp-tools.json. #4 +cond-format: rule_type path + enum vocabulary --------------------------------------------------- condFormatEnhance used to write the user's --rule-type value into `properties.rule.type` (nested under a `rule` object). The server schema actually puts it at flat `properties.rule_type` and silently drops the nested form — so every conditional-format create/update secretly built the wrong document. Worse, the CLI enum exposed via flag-defs.json was its own invented vocabulary (cellValue / formula / duplicate / unique / topBottom / aboveBelowAverage / dataBar / colorScale / iconSet / textContains / dateOccurring / blankCell / errorCell) — none of those values were the strings the server accepts. Fix: - condFormatEnhance now writes `properties.rule_type = <value>` directly (no nested `rule` object). - Synced flag-defs.json + lark-sheets-conditional-format.md enum vocabulary from base to match the server: duplicateValues, uniqueValues, cellIs, containsText, timePeriod, containsBlanks, notContainsBlanks, dataBar, colorScale, rank, aboveAverage, expression, iconSet. - ⚠️ Breaking: scripts passing the old CLI-invented enum values (e.g. --rule-type cellValue) now get a cobra "invalid value … allowed: …" error listing the new vocabulary. No alias layer. - TestObjectCRUDShortcuts_DryRun's +cond-format-update case updated to assert the flat properties.rule_type shape + new enum. #5 +filter-{update,delete}: auto-inject filter_id = sheet_id ------------------------------------------------------------- manage_filter_object's contract is "filter_id === sheet_id" for the sheet-scoped filter (per per-tool description in mcp-tools.json), and update / delete operations MUST carry filter_id. Standalone filterUpdateInput / filterDeleteInput never set it, so the server rejected with "filter_id is required for update/delete operation" on every call — both standalone AND inside +batch-update. Fix: - filterUpdateInput / filterDeleteInput now set input["filter_id"] = sheetID. - Because filter_id must equal sheet_id (not sheet_name), update / delete reject when only --sheet-name is given — there's no network lookup available inside the builder. The friendly error points at +workbook-info for resolving sheet-name → sheet-id. - create still omits filter_id (server requires that — id is server-allocated on creation). - New tests: * TestObjectCRUDShortcuts_DryRun gains a +filter-update happy-path case asserting filter_id is auto-injected + --range hoisting. * +filter-delete case updated to assert filter_id presence. * TestBatchOp_RejectsBadSubOpInput gains two cases asserting both +filter-update and +filter-delete reject --sheet-name-only with the friendly error. Docs (#2 + #3 + #8) synced from sheet-skill-spec ------------------------------------------------- Companion doc fixes that landed via npm run generate:cli + sync:cli in sheet-skill-spec; included here because the regenerated flag-defs and references markdown are byte-tracked in this repo: - #2: lark-sheets-sheet-structure.md — +dim-{hide,unhide,group, ungroup} --start/--end desc changed from "(0-based, inclusive)" to "(0-based)" / "(exclusive)" to match the half-open range semantics the code has always implemented (requireDimRange: end > start; dimRange uses end - 1 for column end letters). - #3: lark-sheets-workbook.md — +sheet-move section gains a note about the batch-internal requirement to pass --sheet-id AND --source-index explicitly (sheetMoveBatchInput's constraint). - #8: lark-sheets-pivot-table.md — +pivot-create --properties example drops the stale data_range field (the actual server schema uses --source as a hoisted flag; properties only carries rows / columns / values / filters / show_*_grand_total). * feat(sheets): add +cells-batch-clear fan-out over batch_update Clear content/formats across many sheet-prefixed ranges in a single atomic batch_update (one clear_cell_range op per range), mirroring the existing +cells-batch-set-style / +dropdown-{update,delete} fan-out wrappers. The --scope to clear_type normalization is shared with standalone +cells-clear (normalizeClearType) so the two stay in lockstep. high-risk-write (requires --yes); rejected as a batch sub-op like the other fan-out wrappers. flag-defs/flag-schemas and skill docs updated to match. * docs(sheets): sync stdin guidance and sparkline reference - skills/lark-shared/SKILL.md: drop the generic "prefer stdin" section - skills/lark-sheets/SKILL.md: add expanded stdin guidance (use stdin over @file abs paths; don't cd or write into the project dir) - skills/lark-sheets/references/lark-sheets-sparkline.md: document the group_id / sparkline_id two-tier model with worked examples * fix(sheets): require sparkline_id on +sparkline-update items (#6) manage_sparkline_object uses two layers of IDs: --group-id picks the sparkline group, and properties.sparklines[i].sparkline_id picks each item inside the group. The server contract requires sparkline_id on every update item (server maps each entry back to an existing sparkline by this id). Agents that called +sparkline-update without the per-item ids hit an opaque server-side rejection that didn't mention sparkline_id at all, then got stuck in a try-fail-list-retry loop. Pre-check CLI-side in objectUpdateInput via a new validateUpdateInput hook on objectCRUDSpec. sparklineSpec wires validateSparklineUpdateItems, which walks properties.sparklines[] and rejects with a message that points at +sparkline-list: +sparkline-update properties.sparklines[N] missing sparkline_id (run `+sparkline-list --group-id <id>` first to read sparkline_id for each item, then echo each id back on the corresponding update entry) Scope is update-only. config-only updates (properties.config without sparklines) stay legal — the validator skips when sparklines is absent. Delete is not pre-checked: objectDeleteInput doesn't pass properties through, so the partial-delete branch can't be reached today (separate follow-up). Tests: - TestObjectCRUDShortcuts_DryRun: positive case for update with sparkline_id present. - TestSparklineUpdate_MissingSparklineID: standalone path — error contains both "missing sparkline_id" and "+sparkline-list". - TestBatchOp_RejectsBadSubOpInput: batch sub-op missing sparkline_id rejected with the same friendly error. Docs synced from sheet-skill-spec (canonical change committed there): skills/lark-sheets/references/lark-sheets-sparkline.md documents the two-layer id model, the three "+sparkline-list first" cases, and both delete modes. * docs(sheets): sync lark-sheets skill from spec (audit 20260521) Pull latest spec from sheet-skill-spec (PR ee/sheet-skill-spec!6 + earlier develop commits) into skills/lark-sheets/ and shortcuts/sheets/data/. Audit findings now reflected in CLI docs: - A2 +cond-format-create example: --rule-type duplicate → duplicateValues - A3 +cond-format-create Validate: cellValue/formula → cellIs/expression - A5 +csv-put examples: --range → --start-cell; drop redundant --allow-overwrite - A7 +sparkline-create: Validate / Examples aligned with real schema (config/sparklines), executable JSON example added - B13 cross-doc dead links: lark_sheet_*/cli-shortcuts.md → lark-sheets-*.md - C2 +csv-put: `=` literal warning next to Examples - CC5 +rows-resize/+cols-resize --type auto: single point of truth in range-operations reference flag-defs.json description / required sync (from base): - A4 +float-image-update: image-name/position-*/size-* required → optional (patch mode) - A8 +dim-move --start/--end description cleanup - B3 +pivot-create --properties: data_range → source (real field name) Also picks up the +cells-batch-clear shortcut doc (introduced in spec develop). Go-side implementation for that shortcut is intentionally not in this PR — docs-only preview; runtime dispatch will land in a follow-up. `go test ./shortcuts/sheets/...` passes. * feat(sheets): add +cells-set --copy-to-range and sync skill spec Sync lark-sheets skill references and flag schemas from upstream sheet-skill-spec, and wire the newly-specced --copy-to-range flag into +cells-set: it passes copy_to_range to the set_cell_range tool so a template block written via --cells fans out across a larger range with auto-shifted formula refs. * docs(sheets): sync lark-sheets skill spec (chart/pivot wire mappings, --end semantics) Sync skill references and flag-defs descriptions from upstream sheet-skill-spec: clarify +chart-create properties structure (snapshot.data), +pivot-create --target-position / --range wire-field mappings, add a cross-command --end endpoint-semantics table (insert/delete/hide/group exclusive vs move/resize inclusive), note --group-state default, and rename reference identifiers to lark-sheets-*. Description-only refinement; the existing CLI implementation already matches the clarified wire mappings and --end semantics. * fix(sheets): make --max-chars the single read cap for +cells-get / +csv-get Drop --cell-limit (+cells-get) and --max-rows (+csv-get) from the CLI surface and pin the underlying tool's cell_limit / max_rows to a very large sentinel so the tool's own defaults never truncate before --max-chars. --max-chars stays the only knob (default 200000, unchanged). - lark_sheet_read_data.go: add unboundedReadLimit (1e9); cellsGetInput pins cell_limit, csvGetInput pins max_rows; --max-chars still passed through - data/flag-defs.json: synced from spec (drops the two flags) - tests: spot-check moved to --max-chars; dry-run wantInput asserts cell_limit / max_rows are pinned high Mirrors sheet-skill-spec (Base flag records removed). go build ./... + go test ./shortcuts/sheets/ green. * docs(sheets): sync lark-sheets read docs — --max-chars as single read cap Sync skills/lark-sheets references from spec: drop --cell-limit / --max-rows guidance; 大表分批读 switches to --range row windows + --max-chars auto cap + has_more. Mirrors sheet-skill-spec 58e7456 and handler change 2befc49. * docs(sheets): sync lark-sheets skill spec from upstream Refine reference docs and flag-defs descriptions from upstream sheet-skill-spec (--depth wording for +dim-group / +dim-ungroup, plus assorted reference clarifications). Description-only; no CLI behavior or flag surface change. * docs(sheets): sync chart properties schema (position/size required) Regenerate flag-schemas.json from upstream sheet-skill-spec: the chart properties schema now marks position and size as required, and the chart reference doc reflects the same. flag-schemas.json is print-schema-only (no client-side validation), so this is a generated-artifact + doc sync with no CLI behavior change. * docs(sheets): sync lark-sheets skill spec from upstream Refine reference docs and flag-defs descriptions from upstream sheet-skill-spec: clarify +workbook-export sheet flag scope, +filter-* --properties optionality (omitted => empty filter on --range; rules must be non-empty when provided), float-image reference_id wording, and assorted reference cleanups. Description-only; existing CLI behavior (filter passthrough, properties optional) already matches. * docs(sheets): sync lark-sheets skill spec from upstream Trim and refine reference docs from upstream sheet-skill-spec (condense core-operations workflow, tidy write-cells / range-operations / float-image / SKILL guidance). Description-only; no flag or CLI behavior change. * docs(sheets): sync lark-sheets skill spec from upstream Refine reference docs from upstream sheet-skill-spec (core-operations, formula-translation, visual-standards, SKILL guidance). Description-only; no flag or CLI behavior change. * fix(sheets): correct +workbook-create initial fill and +dim-move endpoint +workbook-create: the v3 create response does not echo the default sheet's id, so the initial-fill set_cell_range was sent with an empty sheet_id and rejected ("sheet_id or sheet_name is required"). Resolve the workbook's first sheet via get_workbook_structure before filling. +dim-move: the move request was POSTed to the v2 dimension_range endpoint (the add/update/delete surface, which requires a `dimension` object) and rejected with "[9499] Missing required parameter: Dimension". Switch to the native v3 move_dimension endpoint (sheet_id in path; snake_case source.{major_dimension,start_index,end_index} + destination_index). CLI --end and v3 end_index are both 0-based inclusive, so they pass through unchanged. * fix(sheets): align +workbook-create, +dropdown-*, +dim-move, +range-sort with server schema Five separate E2E failures in shortcuts/sheets/ that all trace back to a CLI ↔ server contract mismatch. Each is independently scoped; bundling them because they share the test-report citation and the same one-line fix shape in most cases. buildInitialFillInput sent {"sheet_id": ""} on the secondary set_cell_range call after creating the workbook. The empty value was a holdover from "...otherwise server picks first sheet" — but set_cell_range rejects an empty selector with "sheet_id or sheet_name is required" rather than falling back to the default sheet. Use sheet_name "Sheet1" instead. POST /sheets/v3/spreadsheets always creates that sheet on workbook creation, and set_cell_range accepts sheet_name as an equivalent selector — saves an extra get_workbook_structure round-trip just to learn the auto-generated id. buildDropdownValidation emitted four fields that don't exist in the canonical set_cell_range.data_validation schema: - "values" (options list) → renamed to "items" - "multiple_values" → renamed to "support_multiple_values" - "colors" (per-option color) → removed (not in schema; flag also removed from data/flag-defs.json for +dropdown-set / -update) - "highlight_options" → removed (not in schema; flag also removed) The canonical schema lives at sheet-skill-spec/canonical-spec/tool- schemas/mcp-tools.json (set_cell_range tool, data_validation property); the colors / highlight knobs were CLI inventions the server never accepted, so removing the flags is correct (renaming would leave the flags broken). Skill reference docs (write-cells.md, batch-update.md) synced. validateDropdownOptionsColors lost its colors check; renamed to validateDropdownOptions to reflect the narrower contract. dropdownGetInput sent "Sheet1!C2:C6" verbatim as a ranges[] entry. get_cell_ranges expects sheet_id / sheet_name as separate fields and ranges entries without the sheet prefix; the server bounced with "sheet not found, sheetId:" (empty). Use the existing splitSheetPrefixedRange helper (declared in lark_sheet_batch_update.go) to break "Sheet1!C2:C6" into ("Sheet1", "C2:C6"), then thread the sheet name through sheetSelectorForToolInput exactly like +cells-get does. The shortcut was POSTing to /sheets/v2/spreadsheets/{token}/dimension_ range, which is the v2 insert-dimension endpoint and requires a top- level {"dimension": {...}} body. Move uses a separate endpoint: POST /sheets/v2/spreadsheets/{token}/move_dimension body: { "source": {...}, "destination_index": N } (camelCase "destinationIndex" → snake_case "destination_index" to match the v2 contract.) Both DryRun and Execute updated, plus the TestDimMove_DryRun and TestExecute_DimMove assertions. transform_range.sort_conditions[i] requires both `column` (string) and `ascending` (bool); rangeSortInput passed the --sort-keys array through to the server unvalidated, so missing fields surfaced as opaque "required property X missing" errors with no per-item context. Walk the parsed array client-side, reject with item-pointing messages. Test fixtures and a contract-test fixture switched from the historical {col, order} vocabulary (which the server has never accepted) to the correct {column, ascending}. Server-schema citations and test-report case mapping in this branch's plan file. * revert(sheets): drop direct flag-defs.json edits — generated from spec data/flag-defs.json is regenerated from the upstream sheet-skill-spec canonical-spec; editing it here gets clobbered on the next sync. The schema realignment for +dropdown-set / -update --colors / --highlight removal needs to land on the base table first, then flow back through sheet-skill-spec → larksuite-cli sync, not via a direct CLI-side edit. Restore the previous flag entries verbatim. The Go-side change in buildDropdownValidation still drops the wire fields, so: - users passing --colors / --highlight today see the flag accepted silently (no effect on the wire) until the upstream removal lands; - after upstream removal + sync, both the flag declarations and the Go-side handling will be in sync. Functional fixes (#1 workbook-create, #3 dropdown-get, #4 dim-move, #5 range-sort) and dropdown wire-shape rename (#2) are unaffected. * revert(sheets): drop direct edits to skills/lark-sheets/references/ These md files are sync targets generated from sheet-skill-spec; editing them here gets clobbered on the next sync, same as data/flag-defs.json. The --colors / --highlight row removals belong on the upstream base table → canonical-spec sync, not here. Restore the previous --colors / --highlight rows in both lark-sheets-write-cells.md (+dropdown-set) and lark-sheets-batch-update.md (+dropdown-update). The Go-side change in buildDropdownValidation still drops the wire fields, so: - users passing --colors / --highlight today see the flag accepted silently (no effect on the wire) until upstream removes the flag; - after upstream removal + sync, both flag declarations, ref docs, and Go-side handling will be in sync. Functional fixes (#1 workbook-create, #3 dropdown-get, #4 dim-move, #5 range-sort) and dropdown wire-shape rename (#2) are unaffected. * docs(sheets): sync from sheet-skill-spec — remove dropdown --colors / --highlight Upstream sheet-skill-spec base table deleted the --colors and --highlight flags on +dropdown-set / +dropdown-update (the corresponding wire fields data_validation.colors / .highlight_options were never accepted by the server schema; see prior fix in this branch). Re-running the sync from canonical-spec brings the CLI flag-defs and skill reference docs back in line with the Go-side handling that already drops these fields. Generated by `npm run sync:cli` in sheet-skill-spec @ ac7acef. * fix(sheets): restore +dropdown --colors / --highlight, map to canonical fields Reverses the --colors / --highlight removal from 7932ab2 (item #2 of the batch-1 schema-alignment commit). That commit dropped both flags after the test report flagged data_validation.colors / highlight_options as "unexpected property" — at the time the canonical set_cell_range.data_validation schema listed only help_text / items / operator / range / support_multiple_values / type / values, so the flags had no server-side target and the removal was correct. Since then, set_cell_range.data_validation has gained two fields explicitly modelling the dropdown highlight UI (mcp-tools.json in sheet-skill-spec 2026-05-22 base sync): enable_highlight (bool) — show pill backgrounds highlight_colors (string[]) — hex pill colors, length must match items So the flags are back, but rewired: --colors -> data_validation.highlight_colors (was: colors) --highlight -> data_validation.enable_highlight (was: highlight_options) --options -> items and --multiple -> support_multiple_values renames from 7932ab2 are kept. Changes: - buildDropdownValidation: re-add --colors / --highlight handling against the new field names; --colors length check stays inline (so dropdownSetInput Validate path catches it via validateViaInput, no separate guard needed). - validateDropdownOptions -> validateDropdownOptionsColors: restore the Validate-time --colors length check on +dropdown-update / +dropdown-delete (called from lark_sheet_batch_update.go). - TestDropdownSet_CellsShape: extend to assert highlight_colors / enable_highlight emitted; assert legacy `colors` / `highlight_options` absent. - TestDropdownSet_ColorsLengthMismatch: new — covers the early Validate error path. - TestDropdownUpdate_BatchPayload: extend to cover dropdownBatchInput propagation of --colors / --highlight through batch_update. - skills/lark-sheets/references/lark-sheets-{write-cells,batch-update}.md, shortcuts/sheets/data/flag-defs.json, flag-schemas.json: synced from sheet-skill-spec generate output (MR !7). * chore(sheets): re-sync from spec + loosen --colors length check Catches up to sheet-skill-spec's 2026-05-25 base sync (MR !7) after rebasing onto upstream feat/lark-sheets-refactor (12 new upstream commits including the lark-sheets skill refactor + tools-schema migration). Spec changes flowing in: - highlight_colors description loosened: length may be **shorter than** --options (server cycles remaining slots through a built-in 10-color palette); previously the tool errored on any length mismatch. - shortcuts/sheets/data/flag-schemas.json: mass re-mirror — generator now emits `type` before `properties` and adds explicit `additionalProperties: false` on object schemas (cosmetic, no behavior change). - skills/lark-sheets/references/lark-sheets-{batch-update,chart,write-cells}.md: --options gains the type='list' tag; data_validation inline field-count goes 7 → 9 (catches up the highlight schema in the summary); chart position / size marked optional per upstream. Go-side adjustment: - buildDropdownValidation / validateDropdownOptionsColors: change the --colors length check from strict-equal to "must not exceed --options" to match the relaxed schema. - TestDropdownSet_ColorsLengthMismatch -> TestDropdownSet_ColorsLongerThanOptions (now hits the overflow path with 3 colors vs 2 options). - New TestDropdownSet_ColorsShorterAccepted: 2 colors vs 4 options is legal and forwarded as-is. * docs(sheets): sync dropdown --colors/--highlight clarification from spec Mirrors sheet-skill-spec MR !7 changes: - skills/lark-sheets/references/lark-sheets-write-cells.md: new "Dropdown 配色" section explaining how --colors (→ data_validation.highlight_colors) and --highlight (→ data_validation.enable_highlight) compose — length rule (shorter ok, longer rejected), --highlight gating, palette fallback behavior, minimal +dropdown-set example. - skills/lark-sheets/references/lark-sheets-batch-update.md: one-line pointer to the write_cells section for +dropdown-update / -delete (same rules). - shortcuts/sheets/data/flag-defs.json: --colors / --highlight `desc` fields gain the long-form server-field / length-rule descriptions used by `--help`. No Go-side change — earlier commit 538eb2e already loosened the buildDropdownValidation length check to "must not exceed"; this PR step just makes the docs / `--help` text catch up. * feat(sheets): +dropdown-set/-update --source-range for listFromRange mode Previously +dropdown-set / +dropdown-update only emitted data_validation.type=list — agents wanting listFromRange (dropdown options sourced from existing cells, kept in sync with that range) had to drop down to +cells-set and hand-build a data_validation map. The flag now exposes it natively as --source-range, paired with --options under XOR. CLI changes: - shortcuts/sheets/lark_sheet_write_cells.go: * new dropdownTypeAndItems(runtime) — central XOR resolver: rejects 0 or 2 of {--options, --source-range}, returns (sourceSize, partial dv with type+items|range filled in). Source size = options length for list mode, rangeDimensions(--source-range) cell count for listFromRange. * buildDropdownValidation rewritten to call the resolver, then layer --colors / --multiple / --highlight on top — semantics unchanged for callers, just two modes instead of one. * validateDropdownOptions / -Colors renamed to validateDropdownSourceOrOptions so the XOR + length check fires at +dropdown-update Validate time too. * --colors length error message generalized: "must not exceed dropdown source size (N)" (covers both modes). - shortcuts/sheets/lark_sheet_batch_update.go: rename call site. - shortcuts/sheets/lark_sheet_write_cells_test.go: 4 new tests — ListFromRange (happy path: range + items absent + colors + highlight all emit), ListFromRange_ColorsLongerThanCells (overflow against T1:T3 cell count), XorBothSet, XorNeitherSet. Updated the existing ColorsLongerThanOptions assertion to match the new "source size" wording. Spec-driven changes (synced via npm run sync:cli from sheet-skill-spec MR !7 2c298b6): - shortcuts/sheets/data/flag-defs.json: --options Required flips to xor on +dropdown-set/-update; new --source-range row gains long-form description pointing at server data_validation.range + the XOR semantics. - skills/lark-sheets/references/lark-sheets-write-cells.md: "Dropdown 配色" section reorganized into "Dropdown 选项 + 配色" — XOR comparison table (list vs listFromRange), shared config flag table (--highlight / --colors), explicit length rule covering both modes, side-by-side minimal examples, server-range-normalization gotcha callout. - skills/lark-sheets/references/lark-sheets-batch-update.md pointer updated to mention both modes + that +dropdown-delete is unaffected. PPE smoke (ppe_lark_cli_sheet) on UFJxszjrZhZ1LVtc9FdcICSbn6b C column: - +cells-set C1 → "性别" (bold + centered): updated_cells_count=1 - +dropdown-set --range C2:C21 --source-range "Sheet1!T1:T3" --colors '["#cce8ff","#ffd6e7","#e6e6e6"]' --highlight: updated_cells_count=20 - read-back: data_validation.type=listFromRange + range=$T$1:$T$3 (server normalizes the prefix away on storage; highlight_colors / enable_highlight not echoed by get_cell_ranges, see byted-sheet read projection TODO). - error-path replay (both XOR violations + colors > source-size) all rejected at Validate stage with the expected messages. * docs(sheets): sync agent-voice rewrite of Dropdown 选项+配色 from spec Mirrors sheet-skill-spec MR !7 60df610 — narrative now describes how the flags interact (XOR, colors length rule, highlight gating, sheet-prefix read-back gotcha) without exposing the underlying data_validation field names or server-side normalization details that agents don't act on. No Go-side change, no shortcut behavior change. * chore(sheets): restore --colors in parseJSONFlag docstring example list The earlier commit 49104ec swapped --colors out of parseJSONFlag's "Used by" example list when it deleted the flag (item #2 there removed --colors / --highlight from +dropdown-set/-update). Subsequent commits 8672d8e / 538eb2e / fb90c8b reinstated --colors (and added --source-range) but did not roll back this docstring tweak — leaving an orphan reference to --properties where --colors used to be. This restores the example list to its pre-49104ec form so the docstring matches what the helper actually services on this branch's HEAD. Pure docstring change — function behavior unaffected, no test movement. * fix(sheets): post-rebase test fixups after dropping superseded fix #1 Two test fallouts from rebasing onto upstream 4be06c8 (which independently re-fixed +workbook-create and +dim-move with a more thorough approach): - shortcuts/sheets/lark_sheet_workbook_test.go: our PR's earlier TestWorkbookCreate_DryRun "with headers and data → 2-step plan" subtest asserted the expedient sheet_name="Sheet1" / no-sheet_id wire body that matched our dropped fix #1 implementation. Upstream's fix #1 resolves the workbook's first sheet via get_workbook_structure and fills with the real sheet_id instead. Reset this file to upstream's version — our superseded assertions disappear, upstream's tests cover the new wire shape. - shortcuts/sheets/execute_paths_test.go: TestExecute_RangeSort fixture still used the legacy {col, order} sort-key shape because the rebase resolution picked the upstream version of this file wholesale (it contained other unrelated changes). Re-apply just the one fixture update to {column, ascending} so fix #5's CLI-side rejection logic exercises a valid input — server-side sort_conditions has required fields `column` (string) and `ascending` (bool); the historical {col, order} vocabulary was never accepted. go build ./... + go test ./shortcuts/sheets/... -count=1 both green. * feat(sheets): +dropdown --highlight tri-state via Changed() for opt-out The server-side default for data_validation.enable_highlight flipped from false to true (aligning with the UI behavior). With the previous code path if runtime.Bool("highlight") { dv["enable_highlight"] = true } omitting --highlight and passing --highlight=false both produced the same "enable_highlight key absent" body, leaving CLI users with no way to opt out of the (now-default) highlighting. Switch to runtime.Changed() so the translator can distinguish all three input shapes: - omitted -> no enable_highlight key (server applies default=true) - --highlight=true -> enable_highlight: true (explicit no-op vs default) - --highlight=false -> enable_highlight: false (the only opt-out path) flagView already exposes Changed() and mapFlagView (the +batch-update sub-op adapter) implements it via raw-key presence — same pattern other translators use for "Changed-only" branching (e.g. omit target_index unless --index was set), so no interface surface change is needed. Test coverage: - TestDropdownSet_HighlightTriState pins all four shapes (omit / presence form / explicit true / explicit false) and asserts the enable_highlight key's presence/value - TestBatchOp_BodyMatchesStandalone adds a --highlight=false sub-op case so the batch sub-op path produces a body byte-identical to the standalone +dropdown-set --highlight=false body * chore(sheets): sync +dropdown flag desc + write-cells narrative from spec Mirror sheet-skill-spec generated/ into shortcuts/sheets/data/ and skills/lark-sheets/ for the +dropdown-set / +dropdown-update path. No hand edits in this repo. The +dropdown flag desc and the Dropdown 配色 narrative now match the server-side enable_highlight default flip (true) and the tri-state --highlight semantics introduced in the sibling commit: * --highlight desc: 不传 = 开(按内置 10 色色板循环上色), --highlight=false 关闭得到纯白下拉 * --colors desc: 单独传即生效(高亮默认开),--highlight=false 时忽略 * write-cells reference: 三种意图三条线(默认色板 / 指定颜色 / 纯白下拉)+ 新增 --highlight=false 示例 Source upstream: sheet-skill-spec MR !8. * fix(sheets): validate +cells-set-image --image path in Validate The unsafe-path check only ran at Execute (via FileIO.Stat), so --dry-run printed a misleading success preview for an absolute / out-of-cwd --image path that a real run would then reject. Move the path-safety check into Validate (validate.SafeLocalFlagPath), so --dry-run and Execute fail identically and both name the real --image flag. File existence stays deferred to Execute, so legitimate relative paths still preview cleanly. Add TestCellsSetImage_DryRunRejectsUnsafePath. * feat(sheets): support local --image in +float-image-create +float-image-create now accepts a local file via --image (XOR with --image-token / --image-uri): the CLI uploads it as a sheet_image and embeds the returned file_token, removing the previous "upload elsewhere to get a token first" workaround. Path safety is checked in Validate, --dry-run previews the extra upload step, and +batch-update rejects --image (no upload phase). +float-image-update is unchanged (it does not register --image). Also syncs the lark-sheets skill docs/flag-defs from sheet-skill-spec: the new --image flag, partial-merge / border-per-side / bare sheet-prefix clarifications, and refreshed dropdown --colors/--highlight descriptions (already pending in the source Base table). * fix(sheets): +dropdown-get accepts --sheet-id/--sheet-name + bare --range Align +dropdown-get with its get_cell_ranges siblings (+cells-get / +csv-get): sheet selection is now via --sheet-id / --sheet-name (XOR) and --range is a bare A1 reference. The previous shape required the sheet prefix inside --range (e.g. "Sheet1!A2:A100") and was the odd one out among the read-data wrappers; callers pasting the sheet-id form straight from the URL hit a misleading "sheet not found, sheetId: , sheetName: <id>" error because the prefix was unconditionally treated as sheet_name. Flag schema + skill reference regenerated from the upstream Lark Base Shortcut-flags table. * fix(sheets): drop Sheet1! prefix from +cells-get / +csv-get / +csv-put flag examples Server tools-schema.json for get_cell_ranges, get_range_as_csv and set_range_from_csv does not accept a sheet prefix on --range / --start-cell; the sheet is selected via --sheet-id / --sheet-name. +csv-put --start-cell also now states it must be a single cell (no range notation). Synced from spec repo. * feat: 把环境变量提交上去 * fix(sheets): clarify batch --ranges prefix must be sheet display name E2E test cases repeatedly trip on this: $ lark-cli sheets +cells-batch-set-style \ --ranges '["7f8fba!A2:B3","7f8fba!C2:D3"]' --font-color '#3366FF' ... → tool "batch_update" failed: [900015206] sheet "7f8fba" not foun…
raistlin042
added a commit
that referenced
this pull request
Jun 10, 2026
* feat: add fullstack app-type and --message to apps +create (#1) * feat: accept fullstack app-type and require --message for it * feat: inject message into fullstack create request body * refactor: align fullstack message injection with existing body-build style * docs: document fullstack app-type and --message for apps +create * docs: keep scene numbering consistent in lark-apps-create reference * docs: add HTML/fullstack intent routing to lark-apps SKILL.md * docs: cover fullstack in lark-apps skill description and clarify HTML flow step * test: assert fullstack in allow-list error and reject wrong-cased fullstack * feat: drop --message from apps +create (#4) * feat: drop --message from apps +create * docs: drop --message and document agent-generated name/description for apps +create * feat: add apps local key-value file storage (#5) * feat: add Miaoda app git credential support (#9) * fix: remove APIError detail field dependency * docs(apps): expand lark-apps skill for local-dev & cloud-chat workflows (#3) Reframe lark-apps from an HTML-publish skill into a full Miaoda app dev tool covering three paths: local fullstack dev, HTML hosting, and cloud session dev. Builds on the fullstack create change already on this branch. - SKILL.md: 3-path routing table; mental models (code via native git, develop/main branch model, DB via +db-* through Miaoda, env auto-pulled by `npm dev run`, auto-managed credentials); command index for the new verbs; ambiguous-input fallback (infer app type from need, ask local vs cloud instead of assuming; default HTML when no signal) - add local-dev and cloud-dev playbooks - create: keep HTML/fullstack + required --message; add local/cloud scene routing and --enable-multi-env-db - list: usable by agents with --filter; app_id resolution order (user-provided / .spark/meta.json / +list --filter) Co-authored-by: wangjiangwen-gif <286006750+wangjiangwen-gif@users.noreply.github.com> Co-authored-by: raistlin042 <lvxinsheng@bytedance.com> * feat(apps): add 4 db CLI commands (table-list / table-schema / sql / dev-init) 妙搭 data CLI 4 条命令,复用存量 OpenAPI URL + 1 个新增 dev-init: - +db-table-list → GET /apps/{id}/tables(游标分页,AppTable 含预估行数/占用空间) - +db-table-schema → GET /apps/{id}/tables/{name}(默认结构化 schema;--format pretty 出建表 DDL) - +db-sql → POST /apps/{id}/sql_commands(?transactional=false DBA 模式) - +db-dev-init → POST /apps/{id}/db_dev_init(单库→online/dev,不可逆,high-risk-write) 要点: - sql result 兼容两种 wire 形态(结构化 [{sql_type,data,record_count}] 与 legacy ["rows-json"]) - 多语句失败:server 返 code:0 + ERROR 哨兵,CLI 升级成 typed api_error(exit 非 0), detail 带 statement_index/completed/rolled_back,防止 agent 误判 ok:true 假成功 - pretty 渲染对齐 miaoda:列间两空格、CJK 双宽、size 友好格式(KB/MB/GB) - 单测 + e2e dry-run 全覆盖;BOE 真机 e2e 验证通过(25 PASS) - SKILL.md 注册 4 条命令 + 4 篇 reference 注:内含的 BOE 联调专用 env 覆盖(LARK_CLI_OPEN_API_BASE / LARK_CLI_X_TT_ENV, internal/cmdutil + internal/envvars)未包含在本次提交,仅本地联调用。 Change-Id: I0fe4458086708a93941e2dee852fa6a10b53bd4a * docs(lark-apps): db 能力补进 SKILL.md description 的 WHEN 段 按 skill 质量规范(description 三段式 WHAT+WHEN+NOT,加载前唯一可见信息), 原 WHEN 仅"连数据库调试"含糊覆盖 db。补成「查看或操作应用数据库(看表结构 / 跑 SQL / 初始化 dev 环境)」,让 +db-table-schema / +db-sql / +db-dev-init 类查询能精确触发,净增 ~12 字无膨胀。 Change-Id: Id52819fa7d6b8ed0c1f174bf5946d55da7b893d7 * Feat/apps env pull (#11) * feat: add apps env-pull shortcut * fix: support array env_vars response in apps env-pull * fix(apps): improve env-pull merge and expiry output * feat: add keyword/scope/app-type query to apps +list and unhide it (#8) * feat: switch apps +create --app-type enum to lowercase html/full_stack * feat: add keyword/scope/app-type query to apps +list and unhide it * docs: document apps +list query params and lowercase app_type enum * test: update apps cli_e2e dry-run tests for lowercase app_type and +list filters * docs: trim redundant app_type case-sensitivity note in create skill * docs: single-source apps +list usage contract to SKILL.md * feat: add apps publish shortcuts (publish/status/history/error-log) (#12) * feat: add apps publish shared guard and NodeStatus mapping * test: cover json.Number path in injectStatusName * feat: add apps +publish shortcut Implements the `apps +publish` command with dry-run preview (upstream PSM path shown) and an Execute gated by ensurePublishWired() per the not-yet-deployed OpenAPI gateway constraint (publishAPIWired=false). * refactor: make apps publish path placeholders var to satisfy go vet Declare the four publishXxxPath constants as var instead of const so go vet's printf analyzer skips them while they are empty placeholders. Revert the Execute path-build in apps_publish.go from strings.Replace back to fmt.Sprintf (now safe because the format string is a var). * feat: add apps +publish-history shortcut * feat: add apps +publish-status shortcut * feat: add apps +publish-error-log shortcut * feat: register apps publish shortcuts Add AppsPublish, AppsPublishHistory, AppsPublishStatus, AppsPublishErrorLog to Shortcuts() and update count test from 6 → 10. * docs: add skill references for apps publish shortcuts * docs: surface apps publish shortcuts in lark-apps SKILL.md * docs: clarify publish instance id is not an approval instance * docs: nudge agent to run apps +publish --dry-run for release requests * feat: update apps publish shortcuts to v1.0.381 release protocol Rename concept instance→release across all 4 publish shortcuts and their tests: NodeStatus→ReleaseStatus enum, --instance-id→--release-id flag, pipelineTaskID→releaseID response field, errorJobs→errorLogs, and upstream HTTP path consts→RPC method name consts (PSM lark.apaas.devops v1.0.381). Dry-run now shows psm+rpc_method instead of an HTTP path. * docs: update apps publish skill docs to v1.0.381 release protocol * fix: soften apps publish unavailable hint to user-facing language * feat: update apps publish to v1.0.385 string status + --status filter - Remove obsolete int-enum machinery (releaseStatusName/toInt/injectStatusName) and their encoding/json + fmt imports from apps_publish_common.go - +publish Execute now returns status string alongside release_id - +publish-history gains --status Enum flag (publishing/finished/failed); buildHistoryBody gains status param, table column status_name→status - +publish-status Execute drops injectStatusName, pretty prints out["status"] - +publish-error-log shapeErrorLog is string passthrough (no status_name) - Unit tests updated: delete 3 obsolete common tests, update history/error-log * docs: update apps publish docs to v1.0.385 string status + --status filter * feat: wire apps publish shortcuts to final gateway paths (guard stays until deploy) Replace RPC-name placeholders with real OpenAPI paths (publishCreate/Get/ErrorLog/ListPath consts). Switch DryRun to idiomatic HTTP form (POST/GET + real URL + body/params). Fix body/query placement: publish body has no app_id (path-only); history switches from POST body to GET query with snake page_token. Fix Execute response reads to snake_case fields (release_id, created_at, updated_at, error_logs). publishAPIWired stays false; 1-line flip activates live calls. * docs: update apps publish docs to final gateway paths Replace RPC/PSM dry-run example with real HTTP form (POST/GET /open-apis/spark/v1/apps/:app_id/releases[/:release_id[/error_logs]]). Fix all response field names to snake_case (release_id, created_at, updated_at, error_log). Note --status/--limit/--page-token as HTTP query params in publish-history. * feat: enable apps publish gateway calls (remove not-deployed guard) * docs: remove not-deployed transition notes from apps publish docs * feat: use spark:app:publish scope for apps +publish * feat(apps): add +init shortcut to initialize Miaoda app repo (#6) * feat(apps): add command runner and credential redaction for +init * fix(apps): make credential redaction scheme matching case-insensitive * feat(apps): add +init shortcut declaration, validation, and dry-run * feat(apps): implement +init orchestration (credential-init, clone, checkout, conditional push) * fix(apps): redact full userinfo when repo URL contains literal @ * docs(apps): add +init skill reference * fix(apps): declare explicit empty Scopes on +init shortcut * fix(apps): consume repository_url from +git-credential-init in +init * feat(apps): add +init template flag and absolute-path dir resolution * refactor(apps): use shared charcheck for +init --dir validation * feat(apps): add meta.json, steering, and empty-repo helpers for +init * feat(apps): add +init npx scaffold orchestration (init/upgrade branches) * feat(apps): wire +init scaffold, already-initialized short-circuit, npx dep check * docs(apps): document +init npx scaffold, --template, --dir, already-initialized * docs(apps): correct stale +git-credential-init unreleased note in +init ref * fix(apps): reject all control chars in +init --dir * feat(apps): add +init progress logging and optional --template resolver * refactor(apps): inline constant in +init scaffold progress log * docs(apps): document +init optional --template and stderr progress contract * feat(apps): treat README-only repo as empty and commit with --no-verify in +init * docs(apps): explain README-seed match and --no-verify rationale in +init * docs(apps): document README-seed empty detection and commit --no-verify * feat(apps): add session conversation lifecycle shortcuts (#13) * feat(apps): add +session-create shortcut * fix(apps): remove unused sessionPath helper, assert empty +session-create body * feat(apps): add +session-list shortcut * feat(apps): add +session-read shortcut * feat(apps): add +session-stop shortcut * feat(apps): add +chat shortcut * feat(apps): register session lifecycle shortcuts * docs(apps): add session conversation skill reference * docs(apps): clarify fullstack session_id source and fallback * style(apps): gofmt apps_session_create.go * docs(apps): add conversation/session triggers to skill routing description * docs(apps): add conversation flow guidance (when to reuse vs new session, per-step user prompts) * docs(apps): slim session reference per skill quality standard (4047->1726 tok) * docs(apps): tighten session additions in SKILL.md (4394->4145 tok) * fix(apps): align +chat with v7.8 contract (async, no turn_id in response) * fix(apps): update +chat path to .../sessions/{id}/chat (backend endpoint change) * docs(apps): align SKILL.md session command shape with v7.8 contract * style(apps): gofmt apps_db_table_schema_dryrun_test.go Go 1.19+ gofmt 文档注释列表缩进新规则(普通缩进 → tab 对齐), 修复 fast-gate CI 的 gofmt 卡点。 Change-Id: Ic246a659e016d9d6216182199ef300ae6f00ef9d * feat(apps): split +init commit, plainer wording, align skill branches (#14) * refactor(apps): plainer +init progress/help wording, keep scaffold key * refactor(apps): add porcelain change classifier for +init commit split * feat(apps): split +init empty-repo commit into code + config, reword subjects * refactor(apps): scaffold-kind constants and pathspec assertions for +init split * docs(apps): use +init in Path A; align app-repo branch to sprint/default * docs(apps): align local-dev playbook to sprint/default + origin remote * docs(apps): document +init two-commit split and plainer init wording * docs(apps): require asking clone dir before +init, no assumed path * fix(apps): stage +init commits by exact paths to avoid gitignore error * refactor(apps): lowercase miaoda in +init commit subjects * test(apps): cover +init upgrade path with real git * fix: harden app git credential handling (#16) * fix: harden git credential refresh fallback (#18) * fix(apps): validate env-pull key names before writing to .env.local (#17) * fix(apps): validate env-pull key names before writing to .env.local S2 (medium-low) from security review: env-pull wrote server-returned env KEYs to .env.local without validation. A compromised or MITM'd backend could inject arbitrary lines via keys containing newlines. - Add envKeyPattern regex to validate keys match [A-Za-z_][A-Za-z0-9_]* - extractEnvPullVars now returns skippedKeys for invalid key names - Invalid keys are skipped (not hard-fail) so remaining valid keys are still pulled - writeEnvPullPretty prints a warning listing skipped keys * fix(skills): correct npm script syntax from 'npm dev run' to 'npm run dev' * fix(skills): align env-pull guidance with implementation 🤖 Generated with [Aiden x Claude Code] * test(apps): cover storage/git-credential error paths and fix tz-flaky env-pull tests (#19) The coverage and unit-test CI jobs failed on two timezone-dependent assertions in apps_env_pull_test.go: the code renders the database expiry via time.Local() while the tests hard-coded a CST literal, so they failed under CI's UTC. Compute the expected string from the same timestamp with Local() instead, making the assertions timezone-agnostic. Also add unit tests for the error branches codecov flagged as uncovered, taking storage.go and git_credential.go to 100%: - storage Read/Write/Delete/List filesystem-error paths - +git-credential-remove ConfigWarning output (pretty and JSON) - gitCredentialLocalError nil passthrough * fix(apps): silence +init forbidigo, npx app sync -y --prefer-online (#20) * fix(apps): add Subtype to env-pull error literals (#21) typed_error_completeness lint requires all errs.XxxError literals to set Problem.Subtype. Add the missing field to 11 error constructions: - ValidationError (user input checks): SubtypeInvalidArgument - ValidationError (API response parsing): SubtypeInvalidResponse - InternalError (filesystem ops): SubtypeUnknown * feat(apps): inject FORCE_DB_BRANCH=dev in env-pull output (#23) * feat(apps): inject FORCE_DB_BRANCH=dev in env-pull output Always write FORCE_DB_BRANCH="dev" into the resolved .env.local after extracting upstream env_vars, so downstream tooling pinning the dev database branch does not need a separate manual edit. Existing local values are overwritten in place via the canonical merge path. * docs(skills): document apps +env-pull in lark-apps skill Add the env-pull entry to the lark-apps SKILL index and ship the matching reference doc covering args, merge semantics, return shape, error envelope subtypes, and dry-run behavior so AI agents can route to it without reading the Go source. * feat(apps): surface is_published and online_url in +list pretty view (#22) * docs: refactor lark-apps skill per quality spec (#24) Slim SKILL.md and references against the lark-cli skill quality spec while preserving domain knowledge and safety guardrails. - Compress SKILL.md (drop the MUST-read prelude, full command-index tables, and content already owned by lark-shared: auth, scope, exit-10, risk policy, _notice); add version field; zero CRITICAL markers. - Defer flag enumeration in references to `--help`; convert narration-inducing prohibitions into positive defaults; de-duplicate the per-file error.hint relay into a single resident SKILL.md rule. - Fix stale facts found against shortcuts/apps source: drop the non-existent +create --message and --enable-multi-env-db flags, +list --filter (now --keyword), +db-multi-env-init (now +db-dev-init), and the removed html-publish cwd hard-reject. - Keep all safety guardrails: db-dev-init irreversibility/exit-10, db-sql non-transactional multi-statement, git-credential token handling, html-publish credential scan, access-scope confirmation. - Restore intent lost during slimming: release_id is not an approval instance (do not route to lark-approval); resolve access-scope targets via contact/im; ask the user before publishing as a side-effect; distinguish developing an existing app locally (+init) from creating a new one (+create). * test(apps): supplement shortcuts/apps unit-test coverage to 88% (#25) * test(apps): cover db-table-list numeric/byte formatting helpers * test(apps): cover db-sql cell/code/dml/error render helpers * test(apps): cover env-pull newline/expiry/extract-vars helpers * test(apps): cover db-sql render branches and env-pull expiry edge case * test(apps): cover init empty-dir/meta/ls-files error branches * test(apps): cover env-pull target/read/parent-dir error branches * test(apps): cover stage-and-commit and commit-push error branches * test(apps): cover access-scope target split and JSON validation * test(apps): cover html-publish decode error and scaffold sync failure * test(apps): cover apps-update body field combinations * test(apps): cover access-scope body build branches * feat(apps): pass --local to npx skills sync in +init (#26) * feat(apps): pass --local to all npx miaoda-cli calls in +init * feat(apps): pass --local only to npx skills sync in +init * docs(apps): surface +publish and +init dir-choice in local-dev flow (#27) * docs(apps): surface +publish as deploy action in skill routing * docs(apps): add explicit deploy-after-local-edit section to local-dev * docs(apps): promote +init dir-choice instruction to a domain rule * docs(apps): make dev-method a signal-driven entry gate before routing (#28) * docs(apps): restore three-path overview line in apps skill intro (#29) * feat(apps): add executable Examples to shortcut --help and error hints (#30) * test(apps): guard every shortcut has a help Example and no PII * feat(apps): add help Examples to all 24 apps shortcuts * feat(apps): add actionable hints to high-impact error paths * test(apps): cover withAppsHint set-if-empty hint behavior * feat(apps): use concrete enum value in access-scope-set Example * docs(apps): clarify db-sql/db-table-list json default output behavior 两处仅补充注释,不改逻辑: - +db-sql: data.results 在 json 默认路径原样透出全部行,CLI 不二次截断; server 对单条 SELECT 有 1000 行硬上限、超出直接返报错,非无界 token 黑洞。 - +db-table-list: json 默认透出含每表完整 columns[] 系产品设计(list 接口本就 返回列定义,json 消费方一次拿全量、免逐表再调 +db-table-schema),pretty 仅摘计数。 Change-Id: I1a49de8defc4428bfe1e774e4fd7adb45e59e3af * feat(apps): command-layer AI-friendliness governance (P0+P1) (#32) * fix(apps): normalize --app-type case to align with server * refactor(apps): migrate CallAPI to CallAPITyped for typed errors and retryable * feat(apps): trim icon_url and created_at from +list default output * feat(apps): add actionable hints to high-impact error paths * feat(apps): add 2-3 help Examples to +chat and +access-scope-set * docs(apps): add --jq filter tips to list/db commands * docs(apps): sync +list reference with trimmed output fields * test(apps): assert error hints and messages carry no secrets or PII * fix(apps): prefix --jq tips with .data. so they run against the response envelope * test(apps): expect --app-type uppercase normalization in create dry-run E2E (#33) * fix(apps): scaffold via @latest miaoda-cli instead of @Alpha (#34) * feat(apps): rework lark-apps triggering, routing & confirm policy (#35) * feat(apps): results-oriented triggering, pre-auth floors, terminal URL Widen description WHEN to cover app-building openers (CRM/审批/HTML page) with no Miaoda signal word, WHAT still anchored to 妙搭应用开发与托管. Add a pre-authorization rule (auth words skip confirm) with two non-exempt floors: destructive DDL (DROP/TRUNCATE/ALTER drop|modify column) dry-run, and first public-URL publish (+publish/+html-publish) when no auth word. Exempt html app_type from the local-vs-cloud dev-method gate, and scope that gate to new-app creation only (existing-app ops route directly). Require an accessible URL as the end-to-end terminal step. * feat(apps): apply eval-fix behavior contracts across reference docs init/local-dev: end-to-end default-directory escape hatch; end-to-end new-build starts with +create. db-sql: additive DDL direct-exec when authorized, destructive DDL stays dry-run. local-dev/publish-status: return online_url via +list as the full_stack publish terminal step. cloud-dev: generation != shareable URL, +publish handoff, background until-poll snippet (sleep N && cmd intercepted; deprecate ScheduleWakeup), multi-turn publish precondition. publish/publish-error-log: transient failure (EAI_AGAIN/ETIMEDOUT/registry) discrimination, retry cap 2, honest receipt. env-pull: first-launch fallback. local-dev/db-dev-init: new full_stack ships dual DB, skip +db-dev-init. * refactor(apps): apply review feedback — semantic criteria, drop overfit/unverified content Per line-by-line review of the eval-fix changes: - Entry routing reframed to objective/semantic criteria (new-vs-existing = 'can an existing app be identified'; dev-method = who-writes-code preference), replacing keyword/example matching. - db-sql DDL gate restated by effect (data-loss / reversibility), not a keyword list. - Pre-authorization judged by expressed intent (not a word list); single non-exempt floor (destructive/irreversible DB dry-run); confirm policy in its own section, error.hint in 'failure handling'. - init.md slimmed to command facts (directory choice owned by local-dev, no init<->local-dev cycle); local-dev defers new-vs-existing to the entry. - Reverted unverified/redundant/runtime-coupled additions: cloud-dev session-read preview-URL claim + background-poll snippet + queued_count precondition; publish transient-retry/ScheduleWakeup; env-pull first-launch; db-dev-init positive restatement; SKILL terminal-URL mandate. - Fixed dangling section references after the rename. * fix(apps): scope pre-authorization to hands-off intent, not 'wants a result' (#36) Follow-up to #35. The merged pre-authorization rule treated 'wanting the final result' as authorization, so '先在本地跑起来让我看看' was read as pre-authorized and the agent silently picked a clone directory without asking. Re-state the criterion as the user's hands-off intent (explicit waiver, or an end-to-end directive), judged uniformly across the flow (directory/clone, publish) — not a per-decision carve-out. Merely wanting a result or asking to review is not authorization. * docs: clarify apps cloud dev publish state * fix(apps): require commit+push before publish, clarify deploy flow (#38) * fix(apps): require committing changes before publish in local-dev flow * fix(apps): make commit+push mandatory before publish in agent rules * fix(apps): scope selective-add caveat to incremental deploy, not new-app flow * fix(apps): make pre-publish commit conditional on local changes * fix(apps): tighten pre-publish commit wording in agent rules * fix(apps): cloud-dev does not auto-deploy, add explicit publish step * docs(apps): document +chat init vs incremental turn cost (#39) First +chat on a not-initialized app runs full design+gen server-side (~20-50 min); chat on an already-initialized app is incremental and finishes in minutes. Surface this in the +chat Go comment as a pointer and put the init-state check + matching polling cadence (5-10s vs 60-120s) in the lark-apps cloud-dev skill reference as the canonical source. Cloud-side init check uses +session-read committed-version info or +list is_published:true. * docs(apps): document +chat init vs incremental turn cost (#40) First +chat on a not-initialized app runs full design+gen server-side (~20-50 min); chat on an already-initialized app is incremental and finishes in minutes. Surface this in the +chat Go comment as a pointer and put the init-state check + matching polling cadence (5-10s vs 60-120s) in the lark-apps cloud-dev skill reference as the canonical source. Cloud-side init check uses +session-read committed-version info or +list is_published:true. * feat(apps): surface online_url/error_logs in +publish-status output (#41) * refactor(apps): extract shared release error-log table helper * fix(apps): keep error-log table byte-identical for null error_logs * feat(apps): surface online_url/error_logs in +publish-status output * docs(apps): read online_url/error_logs from +publish-status in publish flow * docs(apps): align local/cloud dev publish flow with +publish-status fields * refactor(apps): rename +db-dev-init→+db-env-create, trim db-table-list columns - +db-env-create(原 +db-dev-init):新增 --env 参数(调用方传入,目前只支持 dev), --sync-data 改为 true/false 取值;服务端 URL 仍走 db_dev_init。 - +db-table-list:json 默认用白名单投影(dbTableListItem)只输出产品要求字段, 每表 columns[] 折算成 column_count、不再透出完整列定义(与 +db-table-schema 重复且放大 token);要完整列定义/索引/约束用 +db-table-schema。 - 同步对齐 db 相关 skill 文档(命令名、column_count、env-create 参数)。 - 单测 + cli_e2e dry-run 全绿。 Change-Id: I116ab11807679f8f06ed18221f705bab426d015c * refactor(apps): rename +db-table-schema → +db-table-get 动词对齐 +db-table-list(list/get)。仅命令名 + 标识符 + 文档改名,行为/输出/URL 不变: - AppsDBTableSchema→AppsDBTableGet,文件/测试/cli_e2e test 重命名 - buildDBTableSchemaParams→buildDBTableGetParams - +db-sql / +db-table-list 里的交叉引用 hint、skill 文档同步 Change-Id: I36dfb8fd0d2613492a57dc7815bc58414c145480 * feat: auto-pull env vars after apps +init (#42) * test: route apps +env-pull to its own fake-runner key * feat(apps): add +env-pull envelope parsers for +init * feat(apps): add pullEnv helper invoking sibling +env-pull * feat(apps): +init auto-runs +env-pull after push (non-fatal) * docs(apps): clarify db-sql --query @path is relative-only, use stdin for absolute paths @path 受 lark-cli 全局文件安全策略约束,只接受 cwd 内相对路径;绝对路径 / cwd 不固定 场景改用 stdin(--query - < /abs/file.sql),无需先 cd。 Change-Id: Ib3453810cfc9303d72b4facf3493ad9688eeffd3 * docs(apps): refine db-sql --query path guidance wording 以 agent 视角重写:@ 仅接受工作目录内相对路径,绝对路径/越界路径被拒(CLI 文件访问统一约束); 工作目录外的文件经 stdin 传入。 Change-Id: Ic7db00934b3571368eb704451f4ce1776463806d * feat(apps): make +db-sql high-risk-write (require --yes) +db-sql 可含 DML/DDL,统一升级为 high-risk-write:框架对所有执行强制 --yes 确认关卡 (--dry-run 预览豁免),无 --yes 返 confirmation_required / exit 10。 - Risk: write → high-risk-write(去掉自定义门禁,直接用框架机制) - skill 文档:命令骨架标注 --yes 要求;Agent 规则改为「执行需 --yes,只读可直接带、 破坏性先 dry-run 确认再带」 - 单测所有执行调用补 --yes Change-Id: I57e78832b35fa170a485774e6fb7289109d678c3 * docs(apps): clarify app_ (Miaoda) vs cli_ (Feishu) app id (#46) * 优化云端开发skill,明确执行模型,参数解释 (#44) Co-authored-by: fushengdong.1 <fushengdong.1@bytedance.com> * refactor: rename apps publish commands to release and session-get (#45) * refactor(apps): drop +publish-error-log, rename release path constants * refactor(apps): rename +publish to +release-create * refactor(apps): rename +publish-history to +release-list, unify pagination to --page-size * refactor(apps): rename +publish-status to +release-get Renames apps +publish-status → +release-get (AppsPublishStatus → AppsReleaseGet), updates --release-id desc to reference +release-create, and fixes the Execute error hint to point at +release-list instead of +publish-history. * refactor(apps): rename +session-read to +session-get * docs(apps): rename publish references to release, +session-read to +session-get * refactor(apps): clean up residual publish/session-read references Fix six leftover references missed in Tasks 1-6: +publish-history in jq-tip test wantCmds map and common_test hint fixture (×3), +session-read in apps_chat.go comment+output string (×2), apps_session_stop.go flag desc (×1), apps_chat_test.go comment (×1), and +publish-status in lark-apps-list.md agent rule prose (×1). * docs(apps): clarify release-get link contract and session-get vs session-list * docs(apps): generalize release-list page-size rule to N records * feat(apps): rename +list --scope flag to --ownership (#47) * feat(apps): rename +list --scope flag to --ownership * test(apps): update +list cli_e2e dry-run for --ownership rename * docs(apps): document +list --ownership flag * feat(apps): align +release commands with new release API format (#48) * feat(apps): align +release-create scope to spark:app:write * feat(apps): raise +release-list --page-size documented max to 500 * feat(apps): show commit_id in +release-get pretty output * docs(apps): update release reference docs for page-size 500 and commit_id * test(apps): cover empty commit_id in +release-get pretty output * docs: align lark apps cloud dev release flow * feat(apps): redesign +db-sql → +db-execute (--sql/--file, default env dev) 按 db 子域命令最终设计重做执行入口: - 命令 +db-sql → +db-execute(动词收尾,对齐 +db-table-list/-get) - --query 拆为 --sql(内联/stdin)与 --file(.sql 文件路径),二选一互斥; --file 在 Validate 阶段读出归一化到 --sql - 默认 --env online → dev(打生产库需显式 --env online) - 文件/标识符/注册/测试/cli_e2e/skill 文档全部对齐重命名 - 新增测试:--sql/--file 互斥、--file 读取、默认 env=dev 不在本次范围:--transaction/--no-transaction(服务端 transactional 实为路径切换、 非真事务,需 dataloom 侧先支持真事务开关)、--max-rows/--timeout 等后续项。 Change-Id: I50c06faf83527471446e2a6651ccb51f6eedd6ff * docs(apps): clearer --env online wording for +db-execute 把口语化的「打生产库需显式」改为「需要操作线上环境数据库时,显式指定 --env online」; flag desc 同步去掉 hit production 措辞。 Change-Id: Iee82fccf17e08bddb4b760c3970a416746b10c4c * docs(apps): drop 'ad-hoc' jargon from +db-execute description 中文文档/英文 description 去掉术语 ad-hoc;SELECT/DML/DDL 已表意,含义不丢。 Change-Id: Ie2cccc5fc3491fe5f57190a87b93ecd70405b156 * docs(apps): trim +db-execute when-to-use and --file path wording - 何时用去掉「(查询 / 临时数据修复 / 应急 DDL)」枚举 - --file 路径说明去掉 .. /符号链接/统一约束 的技术化描述,改为「相对路径, 否则用 --sql - < 文件路径」的产品化口吻 Change-Id: Ie70e57895c78650230b6942b03d90a2d95c937f2 * docs(apps): note --file rejects absolute/cwd-escaping paths 简短补回 --file 的路径约束(绝对路径 / 经 ..、符号链接越界会被拒),去掉冗余评注。 Change-Id: I549893c82cafbe97529e08dcbc3ee5496927da18 * fix(apps): replace t.Chdir with os.Chdir in db-execute test (Go 1.23 compat) t.Chdir 是 Go 1.24 API,但 go.mod 为 go 1.23.0,CI(Go 1.23)报 "t.Chdir undefined"。改用 os.Chdir + t.Cleanup 还原,1.23 兼容。 Change-Id: I550611773e5088275be1c4344d4f8269610ce74a * feat(apps): refine +init description and refresh env on re-init * fix(apps): treat accessible-link requests as publish intent (#53) * refactor(apps): +db-env-create --sync-data string-enum → Type:bool 原实现用 string + Enum["true","false"] + == "true" 模拟 bool,啰嗦且非惯用。 改为 Type:bool(rctx.Bool):传 --sync-data 即开启、省略为 false。 同步更新测试、cli_e2e dry-run、skill 文档。 Change-Id: I3068e0577fa20a7cbaf414ca9af3d197f6ae8049 * fix(apps): declare --app-type as strict lowercase enum (#55) * docs(apps): front-load routing, dedupe, and trim lark-apps skill (#56) * docs(apps): front-load intent-routing table and dedupe skill body * docs(apps): dedupe publish guardrail and polling rules in cloud-dev * docs(apps): trim env-pull implementation detail to behavior contract * docs(apps): add +env-pull routing entry in SKILL.md * docs(apps): fix create.md cross-ref to actual SKILL.md section name * feat(apps): add error.hint to command failures and a consistency gate (#57) * feat(apps): add appIDListHint const and wrap 4 pure app-id command failure paths Adds shared `appIDListHint` recovery hint to common.go and wraps the CallAPITyped failure branch of session-create, session-list, update, and release-list to surface an actionable next-step hint on 4xx errors. Includes httpmock unit tests in apps_hints_more_test.go (TDD: red→green). * feat(apps): add sessionStopHint and createHint for session-stop and create commands Adds per-command recovery hints with specific guidance: sessionStopHint points at +session-list and +session-get; createHint explains valid --app-type values and permission failure. Wraps the CallAPITyped failure branch in both commands. * feat(apps): add recovery hints for db-env-create, db-table-get, db-table-list Adds dbEnvCreateHint, dbTableGetHint, and dbTableListHint with actionable cross-command guidance (e.g. pointing at +db-table-list for env conflicts, +db-env-create for missing dev env). Wraps only the CallAPITyped failure branch; requireAppID validation errors are left untouched. * refactor(apps): make session-stop hint runnable and align hint test names * test(apps): guard withAppsHint upstream-wins contract and new hint leak safety * test(apps): add help-skill command consistency gate --------- Co-authored-by: linchao5102 <linchao.5102@bytedance.com> Co-authored-by: Wang <wangjiangwen@bytedance.com> Co-authored-by: wangjiangwen-gif <286006750+wangjiangwen-gif@users.noreply.github.com> Co-authored-by: 陈兴炀 <chenxingyang.1019@bytedance.com> Co-authored-by: aihao-git <aihao.0331@bytedance.com> Co-authored-by: bali <bali@bytedance.com> Co-authored-by: hunnnnngry <chenxi.xichen@bytedance.com> Co-authored-by: shengdongyc <1135978761fsd@gmail.com> Co-authored-by: fushengdong.1 <fushengdong.1@bytedance.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--brand larkinconfig init --new--new --brand larkpathRoot cause
config init --newhard-codedcore.BrandFeishuwhen entering the create-app flow, so the requested brand never reached the setup URL generation path.Testing
go test ./cmd/configgo test ./internal/auth ./internal/corego test ./...internal/registryon pre-existing tests:TestColdStart_UsesEmbeddedTestCacheHit_WithinTTL