Replace hardcoded flag defaults in the fetch test helpers with
fetchDefault() / fetchDefaultInt() helpers that read the declared
defaults from v2FetchFlags(). This prevents future drift between
production flag defaults and test setup, and panics loudly if a
flag name is misspelled rather than silently returning "".
The tests now correctly avoid hardcoding doc-format, but other
flag defaults (detail, revision-id, scope, etc.) were still
duplicated here. Deriving all defaults from v2FetchFlags() keeps
the whole test command definition aligned with production.
Co-authored-by: TraeCli (Doubao-Seed-Dogfooding) <trae@bytedance.com>
Co-authored-by: fangshuyu <fangshuyu@bytedance.com>
* feat: support docs create title option
Change-Id: I6fd840fe813e5e664ea9ec680765fd41375cdebf
* docs: refine docs title guidance
Change-Id: I2f986a4606729bc791a1bff6c03aaa198b0798dc
* docs: keep lark doc skill create example
Change-Id: Ic7005e015c9e71a4582c1f4a8ac8222d552426d4
* test: allow docs create title flag in help
Change-Id: I0226e20c6bf2187eb6c4f0d2d5e37ab9225d4171
* refactor: retire legacy error envelopes and enforce typed contract
Consolidate all command error reporting onto the typed errs.* contract, remove
the legacy error surface that predated it, and tighten the lint guards so the
contract holds across the whole repository going forward.
Every failure now reaches stderr as one envelope shape: a category, an
optional subtype, a human- and agent-readable message, and a recovery hint,
with invalid parameters listed under `params`. The legacy ExitError envelope,
its constructors, and the boundary bridge that promoted untyped config and
authorization errors are deleted, leaving a single path from error to wire.
Predicate commands keep their silent-exit behavior through a dedicated signal
that carries only an exit code.
Infrastructure paths that still emitted ad-hoc envelopes — flag parsing,
unknown commands and subcommands, plugin and policy guards, confirmation
prompts, and auth/config failures — now classify into the same taxonomy.
Business, API, auth, and config exit codes are preserved; the one behavioral
change is that Cobra usage failures (missing required flag, unknown command,
bad arguments) now emit the typed validation envelope and exit 2, matching the
explicit flag and subcommand guards, instead of Cobra's plain-text exit 1.
Enforcement is repo-wide rather than per-path:
- The errscontract guards run by default everywhere instead of through a
migration allowlist, so legacy envelopes cannot be reintroduced anywhere.
- errorlint runs across the whole repository: every error wrap must use %w and
every comparison must use errors.Is/errors.As, so interior wraps stay legal
but can no longer break the chain the typed boundary relies on.
- The errs-no-bare-wrap guard is keyed by structural prefix instead of an
explicit per-domain allowlist, so new shortcut domains are covered without
editing a list. It runs where forbidigo is enabled (the shortcut domains and
the auth/config/service command groups); repo-wide chain integrity for the
remaining command paths is carried by errorlint above.
* test: align cli_e2e success assertions to the ok envelope
The api and service success path now emits the {"ok":true} envelope, so the
cli_e2e workflow assertions that still expected the old {"code":0} shape via
AssertStdoutStatus(t, 0) fail once they run with live credentials. Switch those
workflow assertions to AssertStdoutStatus(t, true); the fake-payload helper test
in core_test.go keeps its code-shape assertion.
Emit structured validation, API, network, file, and internal error envelopes for Doc shortcuts so users and agents can recover from failed document workflows using stable type, subtype, param, and code fields.
Add Doc domain errscontract and golangci guards to prevent legacy envelope and common helper regressions.
When a resource is created with bot identity, the CLI attempts to
auto-grant full_access to the current user. If the user open_id is
missing or the grant API call fails, the result was only written to
the JSON permission_grant field and easily overlooked.
Changes:
- Add stderr warnings when auto-grant is skipped or fails
- Add 'hint' field to permission_grant JSON output with failure reason
and actionable next step (e.g. auth login, check scope, retry)
- Add end-to-end skipped/failed tests across all affected shortcuts
(doc, drive, sheets, slides, wiki, markdown, base)
Closes#963
* feat(doc): warn before overwrite when document contains whiteboard or file blocks
Before executing an overwrite in v1 mode, pre-fetch the current document
and scan the Markdown for <whiteboard> and <file> resource blocks. If any
are found, print a warning to stderr listing the counts and suggesting the
user take a backup with `docs +fetch` first.
Overwrite replaces the entire document and cannot reconstruct these blocks
from Markdown; previously the data was lost with no indication to the caller.
The check is best-effort: a failed pre-fetch silently skips the guard rather
than blocking the overwrite.
* test(doc): add validateSelectionByTitleV1 tests and drop redundant empty-md guard in warnOverwriteResourceBlocks
* fix(doc): use regex for resource block detection, add latency/coverage comments, document skip_task_detail purpose
* feat(doc): add width/height params to buildBatchUpdateData
Extend buildBatchUpdateData signature with width and height int params.
When mediaType is "image" and either dimension is positive, the value is
included in the replace_image payload. Existing call sites pass 0, 0.
* feat(doc): add --width/--height flags with validation to docs +media-insert
* feat(doc): add aspect-ratio auto-calculation helpers
Add computeMissingDimension (pure ratio math) and detectImageDimensions
(header-only image.DecodeConfig) with PNG/JPEG/GIF blank-import decoders,
plus imageDimensions struct; drive with two new TDD tests.
* feat(doc): wire --width/--height into Execute with aspect-ratio calculation
* feat(doc): add best-effort dimension computation to DryRun
* docs: add --width/--height to docs +media-insert SKILL.md
* fix: add SafeInputPath validation to detectImageDimensionsFromPath
* fix: guard computeMissingDimension against division by zero and add rounding
* fix: add dimension upper bound, fix err variable reuse in Execute
* refactor: use early-return guard for zero native dimensions per review
* fix: add pixels unit to dimension validation error messages
* fix: surface dimension detection failures in dry-run to match Execute behavior
* fix: move dimension detection before upload to fail fast
* fix: restore withRollbackWarning on dimension detection errors in Execute
Dimension detection runs after the placeholder block is created (Step 2),
so failures must clean up the block to avoid leaving an empty placeholder
in the document.
* 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.
## Summary
Add explicit guidance on the parent `docs` command so agents pick the right
lark-doc API version. Without this, agents that have an older lark-doc skill
installed can mistakenly mix v2 flags into a v1 flow.
## Changes
- Add `--api-version` help flag and a Tips section to `docs` so `lark docs --help`
(and `--api-version v2`) explain when v2 should be used.
- Refresh the lark-doc skill references and `docs_fetch_v2` keyword flag
description for clarity.
- Add `shortcuts/register_test.go` covering the new docs help wiring.
## Test Plan
- [x] Unit tests pass (`go test ./shortcuts/...`)
- [x] Manual local verification confirms the `lark docs --help` and
`lark docs --help --api-version v2` commands work as expected
## Related Issues
- None
Change-Id: Id3b3196e6a069bb52f95a6fc679b8258313faf3d
Add BuildResourceURL helper and wire it into doc/sheets/drive/base/wiki
create paths so callers always receive a clickable link, even when the
backend response (MCP degraded path or upstream OpenAPI) returns an
empty URL field. The fallback uses the brand-standard host
(www.feishu.cn / www.larksuite.com), which redirects to the tenant
domain.
Affected entries:
- docs +create v1 / v2
- sheets +create
- drive +create-folder / +import / +upload (newly exposes url)
- wiki +node-create (newly exposes url)
drive +create-shortcut is intentionally skipped because the URL form
depends on the underlying file kind, which the shortcut payload does
not carry.
Adds an `--api-version v2` path to the docs shortcuts, backed by the
`docs_ai/v1/documents` OpenAPI. DocxXML is the default document format
and Markdown is available as an alternative. Content input is unified
across the three shortcuts via `--content` + `--doc-format`. The v1
(MCP) path is preserved for backward compatibility and now prints a
deprecation notice on use.
Shortcuts:
- `docs +create --api-version v2`: create a document from XML or
Markdown, with optional `--parent-token` or `--parent-position`.
Bot identity continues to auto-grant the current CLI user
full_access on the new document.
- `docs +fetch --api-version v2`: adds `--detail simple|with-ids|full`
for export granularity and `--scope full|outline|range|keyword|section`
for partial reads, along with `--context-before` / `--context-after`,
`--max-depth`, and `--revision-id`.
- `docs +update --api-version v2`: introduces structured operations
via `--command`: `str_replace`, `block_delete`, `block_insert_after`,
`block_copy_insert_after`, `block_replace`, `block_move_after`,
`overwrite`, `append`.
Framework support in `shortcuts/common`:
- `OutRaw` / `OutFormatRaw` emit the JSON envelope with HTML escaping
disabled so XML/HTML document bodies are preserved verbatim.
- New `Shortcut.PostMount` hook runs after a cobra.Command is fully
configured; used here to install a version-aware help function
that hides flags belonging to the inactive `--api-version`.
Also refreshes the lark-doc skill pack (SKILL.md, create/fetch/update
references, new lark-doc-xml and lark-doc-md references, style and
workflow guides), README examples, and downstream skill call sites
(lark-drive, lark-vc, lark-whiteboard, lark-workflow-meeting-summary,
lark-event).
Change-Id: Ide2d86b190a4e21095ae29096e7fb00031d80489
* feat(doc): add --from-clipboard flag to docs +media-insert
Allow users to upload the current clipboard image directly to a Lark
document without saving to a local file first.
- New --from-clipboard bool flag (mutually exclusive with --file)
- shortcuts/doc/clipboard.go: readClipboardToTempFile() with per-OS impl
macOS — osascript (built-in, no extra deps)
Windows — PowerShell + System.Windows.Forms (built-in)
Linux — tries xclip / wl-paste / xsel in order; clear install hint
on failure
- No new Go dependencies, no Cgo
- Temp file is created before upload and removed via defer cleanup()
- --file changed from Required:true to optional; Validate enforces
exactly-one of --file / --from-clipboard
* fix(doc): fix clipboard image read on macOS for screenshots and browser-copied images
- Add TIFF fallback (macOS screenshots default to TIFF, not PNG)
- Add HTML base64 fallback (images copied from Feishu/browser embed data URI)
- Use current directory for temp file so FileIO path validation passes
* fix(doc): scan HTML/RTF/text clipboard formats for base64 image data URIs
Extend attempt-3 fallback to iterate all text-based clipboard formats
(HTML, RTF, UTF-8, plain text) rather than only HTML. Any format that
contains a "data:<mime>;base64,<data>" pattern is accepted, covering
images copied from Feishu, Chrome, Safari, and other apps that embed
base64 in non-HTML clipboard slots. Also handle URL-safe base64.
* test(doc): add unit tests for clipboard helpers to meet 60% coverage threshold
Cover decodeHex, hexVal, decodeOsascriptData, reBase64DataURI, and
extractBase64ImageFromClipboard (via fake osascript on PATH).
Package coverage: 57% → 61.2%.
* fix(doc): address CodeRabbit review comments on clipboard feature
- Extend reBase64DataURI regex to cover URL-safe base64 chars (-_) so
URL-safe payloads are matched before decoding is attempted
- Fix readClipboardLinux to continue to next tool when a found tool
returns empty output instead of failing immediately
- Guard fake-osascript test with runtime.GOOS == "darwin" skip
- Use os.PathListSeparator instead of hardcoded ":" in test PATH setup
* fix(doc): replace os.* temp-file clipboard path with in-memory streaming
Fixes forbidigo lint violations in shortcuts/doc: os.CreateTemp, os.Remove,
os.Stat, os.WriteFile are banned in shortcuts/; replaced with vfs.* equivalents
for sips TIFF→PNG conversion, and eliminated temp files entirely elsewhere by
having platform clipboard readers return []byte directly.
- readClipboardDarwin: osascript outputs hex literals decoded in Go (no file I/O)
- readClipboardWindows: PowerShell outputs base64 to stdout, decoded in Go
- readClipboardLinux: tool stdout bytes returned directly
- convertTIFFToPNGViaSips: still needs temp files — uses vfs.CreateTemp/Remove
- DriveMediaUploadAllConfig/DriveMediaMultipartUploadConfig: add Content io.Reader
field so in-memory clipboard bytes skip FileIO.Open() path
- Fix ineffassign in clipboard_test.go (scriptBody double-assignment)
- Update TestReadClipboardLinux_NoToolsReturnsError for new signature
* fix(doc): address CodeRabbit review comments on Linux clipboard path
- Update --from-clipboard flag description to list xclip, xsel and wl-paste
- Preserve last backend-specific error in readClipboardLinux so users see
a meaningful message when a tool is found but fails
- Validate PNG magic bytes for xsel output (xsel cannot negotiate MIME types)
- Add URL-safe base64 regression test for reBase64DataURI
* fix(doc): strip whitespace from base64 payload before decoding clipboard data URI
HTML and RTF clipboard content often line-wraps base64 at 76 characters.
FindSubmatch returns the raw wrapped token so direct decode would fail.
Normalize whitespace with strings.Fields before passing to base64.Decode.
* fix(doc): drop TIFF fallback and internal/vfs import on macOS clipboard
depguard rule shortcuts-no-vfs forbids shortcuts/ from importing
internal/vfs directly. The only caller was the sips TIFF→PNG
conversion, which was already a fragile best-effort fallback that
required temp files.
Remove the TIFF fallback entirely; the remaining two attempts cover
the real-world cases:
1. osascript → PNG hex literal — native screenshots and most apps
2. scan text clipboard formats for base64 data URI — Feishu/browsers
* test(doc): cover readClipboardLinux xsel PNG validation and dispatcher path
Added tests:
- TestReadClipboardLinux_XselRejectsNonPNG: fake xsel that returns plain
text is rejected by the PNG-magic check, preventing text from being
uploaded as an "image".
- TestHasPNGMagic: table-driven coverage of the PNG signature check.
- TestReadClipboardImageBytes_UnsupportedPlatform: exercises the shared
dispatcher post-processing and asserts the (nil, nil) invariant.
Raises clipboard.go diff coverage and brings the package from 61.6% to
63.8% overall.
* test: cover in-memory Content upload paths for clipboard feature
Adds unit tests for the new Content io.Reader branches introduced by
the clipboard feature:
- UploadDriveMediaAll with in-memory Content (drive_media_upload.go 87.5%)
- UploadDriveMediaMultipart with in-memory Content (84.6%)
- uploadDocMediaFile single-part and multipart with clipboard bytes
(doc_media_upload.go 0% -> 88.9%)
Adds TestNewRuntimeContextForAPI helper that wires Factory, context,
and bot identity so package tests can invoke DoAPI without mounting
the full cobra command tree.
* test: cover clipboard Validate/DryRun branches and testing helper
Adds unit tests for the clipboard-related Validate/DryRun paths that
Codecov patch-coverage was flagging as uncovered:
- Validate error when neither --file nor --from-clipboard is supplied
- Validate error when both are supplied (mutual exclusion)
- DryRun output contains <clipboard image> placeholder
- Self-test for TestNewRuntimeContextForAPI so shortcuts/common
sees coverage for the new helper (not just shortcuts/doc)
* test: cover Execute clipboard branch via injectable readClipboardImage
Makes readClipboardImageBytes swappable in tests by routing the call
through a package-level variable readClipboardImage. Tests inject a
synthetic PNG payload so the full Execute clipboard flow
(resolve → create block → upload in-memory bytes → bind) runs under
unit test without a real pasteboard.
Covers:
- TestDocMediaInsertExecuteFromClipboard: end-to-end happy path
- TestDocMediaInsertExecuteClipboardReadError: early-return on
readClipboardImage() failure
* ci: re-trigger pull_request workflow for PR #508
Previous push to 9dedb7a did not trigger the main CI workflow via
the pull_request event (only PR Labels ran). The workflow_dispatch
run I triggered manually lacks PR-scoped secrets so security and
e2e-live failed. An empty commit replays the pull_request event so
the full matrix (deadcode, license-header, security, e2e-live) runs
with proper context.
* test(doc): guard info.Size() behind err check to prevent nil-deref
CodeRabbit flagged that 't.Fatalf("... size=%d err=%v", info.Size(), err)'
evaluates info.Size() even when os.Stat returned (nil, err), which nil-derefs.
Split the check into two stages so the error-path t.Fatalf does not touch
info.
* fix(doc): address fangshuyu-768 review on clipboard PR
Seven code changes driven by review feedback:
1. clipboard.go: stop using CombinedOutput() on osascript / powershell.
Stdout is decoded, stderr is captured separately via cmd.Stderr and
surfaced in the terminal error message, so locale warnings or
AppleEvent permission prompts no longer pollute the hex/base64
payload or mask the real failure.
2. clipboard.go: validate decoded base64 data URI bytes against known
image magic headers (PNG/JPEG/GIF/WebP/BMP). A text clipboard that
happens to contain a literal 'data:image/...;base64,...' fragment
(documentation, tutorials, pasted HTML source) no longer silently
becomes an image upload.
3. clipboard.go: simplify the Linux 'no tool found' install hint to a
distro-agnostic phrasing instead of apt/yum only.
4. clipboard_test.go: delete the stale TestReadClipboardToTempFile_*
tests. They referenced a readClipboardToTempFile function that no
longer exists and only exercised os.CreateTemp/os.Remove. Replace
with TestReadClipboardImageBytes_EmptyResultReturnsError which
actually locks in the 'empty clipboard' → error contract of the
current API (Linux-only since mac/Windows need a real pasteboard).
5. doc_media_upload.go: introduce UploadDocMediaFileConfig struct so
uploadDocMediaFile takes a named config instead of 8 positional
params. Drops the //nolint:lll the old call site had to carry.
6. doc_media_insert.go: convert the clipboard upload call to the new
config struct and only set Config.Content when the clipboard branch
actually produced bytes — this also fixes a latent typed-nil bug
where a nil *bytes.Reader was being passed through an io.Reader
parameter, which tripped the 'if cfg.Content != nil' check in
UploadDriveMediaAll and crashed --file uploads.
7. shortcuts/common/testing.go: TestNewRuntimeContextForAPI now takes
the identity as an explicit core.Identity parameter instead of
hardcoding core.AsBot, and its self-test covers both AsBot and
AsUser. Existing call sites pass core.AsBot explicitly.
Also annotates DryRun output with an 'upload_size_note' when
--from-clipboard is set, since DryRun never reads the pasteboard and
can't predict whether the payload will take the single-part or
multipart path.
* fix(doc): capture line-wrapped base64 in clipboard data URI regex (#586)
HTML and RTF clipboard content commonly folds base64 payloads at
76 chars (standard MIME folding). The previous character class
[A-Za-z0-9+/\-_]+=* stopped at the first \n, so the downstream
strings.Fields normalisation was a no-op (nothing to strip) and
extractBase64ImageFromClipboard silently uploaded a truncated
payload whose 8-byte prefix happened to pass hasKnownImageMagic.
Extend the class to include \s so the Fields strip actually has
whitespace to remove before base64 decoding. Terminators (", <,
), ;) remain outside the class so the match still ends at the
URI boundary.
Add TestReBase64DataURI_LineWrapped covering \n, \r\n, and \t
folds, full round-trip byte-equality, and the terminator-boundary
invariant so any future regression trips a failing test.
* docs(skill): add clipboard-empty fallback guidance for +media-insert
When --from-clipboard returns 'no image data' (empty clipboard, non-image
content, or Linux without xclip/wl-paste/xsel), the agent must NOT silently
swallow the error. It should tell the user the clipboard had no image, ask
for a local file path, then retry the same insert command with --file.
Lists three anti-patterns (silent success, guessing a file path, pre-emptive
save-then-file workaround) that agents have been tempted into.
* docs(skill): user-stated source trumps clipboard/file heuristic
The heuristic table (prefer --from-clipboard when image is on the
clipboard) is a fallback for when the user is vague. If the user
explicitly says 'use the screenshot I just copied' → clipboard; if
they give a path → --file. Agent must not silently swap sources even
when the other looks 'better'.
---------
Co-authored-by: fangshuyu-768 <shuyufang768@outlook.com>
* fix(docs): validate --selection-by-title format early
* fix(docs): reject multiline selection-by-title before prefix check
* chore: refresh CI against current main (no code change)
* test(doc): cover DocsUpdate.Validate integration for selection-by-title
codecov/patch was at 27.27% because the PR added three lines to the
Validate closure (the `if err := validateSelectionByTitle(selTitle); err
!= nil { return err }` block) but nothing in the test file exercised
that closure — only the helper function was tested directly.
TestDocsUpdateValidate now builds a bare RuntimeContext via
common.TestNewRuntimeContext, sets the relevant flags on a cobra
command, and calls DocsUpdate.Validate(ctx, rt) across five cases:
1. Heading-style selection-by-title passes — covers the happy path
through the new call site and the final `return nil`.
2. Plain-text title is rejected with heading-prefix guidance —
covers the new error branch.
3. Multi-line title is rejected as not a single heading line —
covers the other error branch inside the helper.
4. Invalid --mode is still rejected first — proves the new check
doesn't swallow pre-existing validation.
5. Conflicting --selection-with-ellipsis + --selection-by-title is
rejected at the mutual-exclusion check — same ordering contract.
Coverage profile confirms the three added production lines
(docs_update.go L65-67) are now hit: condition 3x, error branch 2x,
happy path via the closure's return nil 1x.
* feat(doc): add pre-write semantic warnings to docs +update
Two static checks run before the MCP update-doc call:
1. replace_* + blank-line markdown: replace_range / replace_all only
swap text inside an existing block — a \n\n in the payload will
render as literal text, not a paragraph break. Hint to use
delete_range + insert_before instead.
2. Combined bold+italic emphases (***text***, **_text_**, _**text**_)
cannot round-trip through Lark and are silently downgraded to a
single emphasis. Hint to split into two separate emphases.
Both warnings go to stderr and never block the update — they inform,
not gate. Adds table-driven tests for each check plus an aggregation
test, and wires the checks into Execute right before CallMCPTool.
Closes the first batch of items from the docs +update pitfalls
review (Cases 1 and 5).
* fix(doc): exclude code regions and escaped markers from docs +update checks (#578)
* fix(doc): exclude code regions and escaped markers from docs +update checks
Addresses the three review comments on #569: the blank-line paragraph
check and the bold+italic emphasis check both operate on the raw
markdown string, so fenced code blocks / inline code spans / literal
escaped markers produce false-positive warnings on content users
expect to pass through verbatim.
Changes:
- Add proseHasBlankLine(): fence-aware detector that returns true only
when a blank line sits outside of ```...``` or ~~~...~~~ regions.
Replaces the raw strings.Contains("\n\n") check in
checkDocsUpdateReplaceMultilineMarkdown.
- Add stripMarkdownCodeRegions(): blanks out fenced code lines and
masks inline code spans (via scanInlineCodeSpans from markdown_fix.go)
with equal-length whitespace so byte offsets outside the stripped
regions are preserved.
- Add stripEscapedEmphasisMarkers(): removes "\*" and "\_" so literal
sequences like "\***text***" — which CommonMark renders as a literal
asterisk plus bold — don't match the combined bold+italic regex.
- Wire both helpers into checkDocsUpdateBoldItalic(): the regex now runs
on stripEscapedEmphasisMarkers(stripMarkdownCodeRegions(markdown)),
so code samples and escaped markers are sanitized away before
detection.
Shared fence-parsing helpers (codeFenceOpenMarker, isCodeFenceClose,
leadingRun) are kept local to this file to avoid touching files outside
the scope of the reviewed PR. If a future change wants to reuse them
across the doc package, they can be promoted then.
Tests:
- TestCheckDocsUpdateReplaceMultilineMarkdown: add 4 negative/positive
cases — blank line inside backtick and tilde fences (no flag), blank
line in prose while fence also has blanks (flag wins), fenced code
with no blank lines (no flag).
- TestCheckDocsUpdateBoldItalic: add 9 cases — ***text*** / **_text_** /
_**text**_ inside fenced code (backtick and tilde), inside inline
code spans, and escaped \***text*** / \*\*_text_\*\* (none flagged);
plus two positive cases to verify the strip doesn't over-sanitize
(real emphasis in prose still fires when inline/fenced code is nearby).
* fix(doc): close CommonMark gaps and add three more combined-emphasis shapes
Self-review of the first commit turned up three issues:
- isCodeFenceClose was strict on exact marker length. Per CommonMark
§4.5, a closing fence must be at least as long as the opener, not
exactly the same length. A 3-backtick open legitimately closed by a
4-backtick closer (used to embed triple-backticks inside the code
sample) was left open-ended, causing the rest of the document to be
treated as code and both checks to silently skip it.
- Both fence helpers accepted any amount of leading whitespace because
they ran on strings.TrimSpace(line). CommonMark allows 0..3 leading
spaces before a fence marker; 4+ spaces (or any tab in leading
position, which expands to 4 columns) makes the line indented code
block content, not a fence open/close. Indented fence-like lines now
correctly remain prose and blank lines around them are detected.
- The bold/italic check only covered three of the six documented
combined-emphasis shapes. Added ___text___, __*text*__, and
*__text__* so parity with the asterisk variants is complete. The
regex set is now table-driven (combinedEmphasisPatterns) to make
adding future shapes a one-line change.
Implementation changes:
- New fenceIndentOK(line) helper: returns (body, true) for 0..3 leading
spaces with no tabs, else (_, false). Used by both codeFenceOpenMarker
and isCodeFenceClose.
- isCodeFenceClose now counts the fence-char run and accepts any run
length >= len(marker), with trailing whitespace only.
- checkDocsUpdateBoldItalic replaced three named var regexes with a
table of six {shape, re} entries and a single early-exit loop.
- Updated docsUpdateWarnings top docstring to list all six shapes.
- Noted the known limitation of stripEscapedEmphasisMarkers around
doubled backslash escapes ("\\***text***"), which is a false negative
we accept in exchange for keeping this a simple string replace.
Test additions (docs_update_check_test.go):
- Fence close: longer-marker close correctly ends fence; real prose
blank after a longer-close fence is still detected.
- Indentation: 4-space indented fence-like line is not a fence open,
so a surrounding blank line still flags; tab-indented variant same;
3-space indented fence is still a real fence.
- New shapes: ___text___ positive + all three negative-guards (fenced
code, inline code, escaped); __*text*__ and *__text__* positive +
fenced/inline negative-guards; plus two composition tests to ensure
the strip does not over-sanitize across the six-regex alternative set.
All 53 sub-tests in this file pass; go vet and gofmt are clean.
---------
Co-authored-by: fangshuyu-768 <shuyufang768@outlook.com>
* fix(doc): address CodeRabbit review on docs +update warnings (#581)
Two CodeRabbit nits from #569:
1. Unit test hint assertion only checked for `delete_range` in the
remediation message; the companion `insert_before` half of the
guidance could regress undetected. Broaden the assertion to require
both tokens so a future edit that drops half the remediation
produces an immediate test failure.
2. No E2E coverage proved the dry-run contract in the PR description
("Not emitted in dry-run mode — kept quiet during planning"). The
helper itself is unit-tested, but nothing caught a regression where
a later refactor wired docsUpdateWarnings into the DryRun path.
Add tests/cli_e2e/docs/docs_update_dryrun_test.go:
TestDocs_UpdateDryRunSuppressesSemanticWarnings invokes
`docs +update --dry-run --mode=replace_range --markdown "***x***\n\nb"`
— an input crafted to trip BOTH pre-write warnings — and asserts
neither the "warning:" prefix, the blank-line message, nor the
combined-emphasis message appears on stdout or stderr.
Note: the file needs -f to add because .gitignore has a bare
`docs/` rule that accidentally matches tests/cli_e2e/docs/. The
existing tracked files under that directory predate the rule; new
additions have to be force-added until the ignore pattern is
narrowed. Not worth rewriting .gitignore for one file.
Verified manually that the new E2E fails cleanly when warnings are
injected into DryRun and passes again after reverting — the test has
real regression-detection power, not just a sticker.
Co-authored-by: fangshuyu-768 <shuyufang768@outlook.com>
- Register DocMediaUpload in doc/shortcuts.go (was defined but never
registered, so lark-cli docs +media-upload was unavailable)
- Rename MediaUpload to DocMediaUpload for consistency with
DocMediaInsert/DocMediaPreview/DocMediaDownload
- Add whiteboard to --parent-type flag description
- Update --parent-node description to mention board_token for whiteboard
Drive +upload (parent_type=explorer) produces file tokens that the
whiteboard API does not recognize (500 error). The correct approach
is docs +media-upload with parent_type=whiteboard.
* feat(doc): add --after-keyword/--before-keyword flags to +media-insert
Allows inserting images/files at a position relative to the first block
whose plain text matches a keyword (case-insensitive substring match).
- Add --after-keyword: insert after the matched root-level block
- Add --before-keyword: insert before the matched root-level block
- Flags are mutually exclusive; default behavior (append to end) unchanged
- fetchAllBlocks: paginated block listing (up to 50 pages × 200 blocks)
- extractBlockPlainText: covers text, heading1-9, bullet, ordered, todo, code, quote
- findInsertIndexByKeyword: walks parent_id chain to resolve nested blocks to their root-level ancestor
- DryRun updated to show block-listing step when keyword flag is set
* test(doc): add fetchAllBlocks pagination and keyword dry-run coverage
- TestFetchAllBlocksPaginationViaExecute: exercises fetchAllBlocks via a
full Execute flow with --after-keyword, covering multi-page block listing
(fetchAllBlocks was previously at 0% coverage)
- TestDocMediaInsertDryRunWithAfterKeyword: verifies that the dry-run output
includes a block-listing step and mentions "search blocks" in the
description when --after-keyword is provided
fetchAllBlocks coverage: 0% → 76.2%
* refactor(doc): use MCP locate-doc for keyword-based block positioning
Replace fetchAllBlocks + keyword scan with MCP locate-doc tool,
consistent with DriveAddComment. Flags changed from --after-keyword /
--before-keyword to --selection-with-ellipsis + --before.
* fix(doc): show <locate_index> in dry-run create-block when selection is set
When --selection-with-ellipsis is provided, the create-block step in dry-run
now shows index: "<locate_index>" instead of "<children_len>" to accurately
reflect that the insertion position is computed from MCP locate-doc, not
appended to end.
* fix(doc): address CodeRabbit review on +media-insert selection feature
- Validate: reject blank/whitespace --selection-with-ellipsis unconditionally
so a mis-typed empty value cannot silently fall back to append-mode.
- Redact the raw selection string when logging to stderr and when emitting
error messages. --selection-with-ellipsis is copied verbatim from document
content and may contain confidential text; the new redactSelection helper
keeps a short prefix and rune count so operators can still identify the
failing selection.
- Harden the after/before mode tests: root children now have three entries
so the two modes land on different indices, and the tests decode the
create-block request body to assert the computed `index` actually reaches
the /children API. A regression that ignored --before would now fail.
- Harden the nested-block test so it exercises the fallback parent-walk:
the anchor is now two levels deep (blk_grandchild under blk_section_child
under blk_section), which forces the walk to fetch the intermediate block
via GET /blocks/{id} to discover the root-level ancestor.
* fix(doc): harden +media-insert selection UX on top of #335 (#577)
Follow-up to #335 review: closes a handful of UX and robustness gaps in
the new --selection-with-ellipsis flow.
- Flag description rewritten to make the "insert at the top-level
ancestor" semantics explicit — when the selection is inside a callout,
table cell, or nested list, media lands outside that container, not
inside. Also calls out the 'start...end' disambiguator.
- locate-doc is now called with limit=2 so an ambiguous selection
(same phrase in more than one block) surfaces a stderr warning
pointing at 'start...end', instead of silently picking the first
match. The first-match return behaviour is unchanged.
- When the anchor is nested below the root, locateInsertIndex now
logs a note to stderr naming the walk depth and the root-level
ancestor's insert index. Users don't have to guess why the image
landed outside the callout they were editing.
- maxDepth bumped 8 → 32 with a comment explaining the invariants:
`visited` is the real cycle guard, `maxDepth` is belt-and-suspenders.
32 comfortably exceeds real docx nesting depth so a deeply-nested
but well-formed anchor is no longer silently rejected.
- Comment added before the parent-walk loop noting why the API calls
are serial (each level's parent_id is only known after the previous
GET returns; can't be batched or parallelised).
Tests:
- TestLocateInsertIndexWarnsOnMultipleMatches: stubs two matches,
asserts the stderr warning names the ambiguity and mentions
'start...end', and that the first-match insert index is unchanged.
- TestLocateInsertIndexLogsNestedAnchor: anchor two levels below root,
asserts stderr carries the "nested … top-level ancestor" note.
- TestLocateInsertIndexCycleDetection: malformed parent chain with
blk_x.parent = blk_y and blk_y.parent = blk_x, neither reachable
from root. Registering a single GET /blocks/blk_y stub also bounds
the call count — a regression that broke `visited` tracking would
either hang or fail via httpmock's extra-call guard.
Co-authored-by: fangshuyu-768 <shuyufang768@outlook.com>
Adds 5 invariant-level tests on top of #469's transforms:
- TestFixExportedMarkdownIdempotent — f(f(x)) == f(x) across rich
fixtures (kitchen sink, CJK, nested containers). Protects the core
round-trip promise from future transform interactions that rewrite
their own output.
- TestFixExportedMarkdownPreservesFencedCodeByteForByte — packs every
pipeline-touching shape into a fence and asserts byte-identical output.
Code samples must never be silently rewritten by a formatting pass.
- TestFixExportedMarkdownPreservesCRLF — CRLF input preserves line
endings AND still triggers transforms. Windows-authored markdown
should not be silently LF-normalized.
- TestFixExportedMarkdownTransformInteractions — composition regressions:
nested-list + trailing-space bold, text→list transition, callout
containing list with emphasis, heading vs paragraph bold.
- TestNormalizeNestedListIndentationDocumentedSkips — locks in the
deliberate no-op branches (odd-space indent, blank-line loose-list
sibling, 4-space indented code block, parentless two-space) as an
explicit spec so future heuristic tweaks surface in the test diff.
All transforms, fixtures, and expectations are derived from the head of
PR #469. No production code changes.
Co-authored-by: fangshuyu-768 <shuyufang768@outlook.com>
* fix(doc): preserve round-trip formatting in fetch output
- trim leading spaces inside bold and italic emphasis exported by docs +fetch
- normalize nested list indentation to avoid flattening and literal text on re-import
- add regression tests for emphasis spacing and nested list indentation
* fix(doc): avoid false positives in markdown spacing fixes
- keep literal * x * and ** x ** text unchanged
- only normalize indented nested list markers when a parent list item exists
- add regression coverage for both CodeRabbit findings
* fix(doc): 修正嵌套列表缩进的空行误判
- 遇到空行时停止向上查找父级列表项,避免把 loose list sibling 误改成嵌套列表
- 避免把列表项中的四空格缩进代码块误改成 tab 缩进列表项
- 补充两个回归测试,并更新 fixBoldSpacing 注释使其与当前实现一致
* fix(doc): 修复 Markdown emphasis 空格回写
- 将 fixBoldSpacingLine 改为按星号 run 扫描,修复 ** hello **、* hello * 和同一行多个 italic span 的空格清理
- 保留 inline code、heading 和 *** hello** 这类近邻字面量,避免误改 emphasis nesting
* feat(doc): add --file-view flag to +media-insert for file block rendering
The docx File block supports three render modes via view_type
(1=card, 2=preview inline player, 3=inline), but --type=file today
always creates with the default card view. Because view_type can only
be set at creation time (PATCH replace_file ignores it), callers
wanting an inline audio/video player had to abandon the shortcut and
reimplement the full 4-step orchestration manually.
Add --file-view card|preview|inline that threads into file.view_type
on block creation. Omitting the flag preserves the exact request body
that the shortcut sends today, so existing users are unaffected.
--file-view is rejected when combined with --type=image (images have
their own rendering) and when an unknown value is passed.
* refactor(doc): narrow view_type gate and relax file-view test
Address review feedback from automated reviewers on #419:
- Replace `fileViewType > 0` with an explicit 1|2|3 whitelist inside
buildCreateBlockData so a stray positive int cannot escape into the
request payload if a future caller bypasses Validate.
- Relax TestFileViewMapCoversDocumentedValues to assert only the
documented keys rather than full-map equality, so future aliases
(e.g. a "player" synonym for preview) do not falsely break the test.
No behaviour change for any existing --file-view input.
* test(doc): cover --file-view Validate contract and explicit card path
Pins down the two CLI guard branches (unknown --file-view value and
--file-view passed with --type!=file) that were previously only covered
indirectly through buildCreateBlockData. Also adds the --file-view card
case so the explicit view_type=1 payload (different from the legacy
file: {} shape when the flag is omitted) is locked in as part of the
public flag contract.
* fix: repair unit tests
Change-Id: I8c6bb69bfa22c9455a2cbb0f46b401e2cbe87762
---------
Co-authored-by: Nick Zhang <nickzhangcomes@users.noreply.github.com>
Co-authored-by: wangweiming <wangweiming@bytedance.com>
+update already calls normalizeDocsUpdateResult to surface board_tokens when
markdown contains mermaid/plantuml/whiteboard blocks. +create was missing the
same call, so callers could not know how many whiteboards were created or
retrieve their tokens. One-line fix: call normalizeDocsUpdateResult after
CallMCPTool in DocsCreate.Execute.
* feat: add strict mode identity filter, profile management and credential extension
Port changes from feat/strict-mode-identity-filter_3 branch:
- Add strict mode for identity filtering and configuration
- Add profile management commands (add/list/remove/rename/use)
- Add credential extension framework (registry, env provider)
- Add VFS abstraction layer
- Refactor factory default and client options
- Update shortcuts to use new credential and validation patterns
Change-Id: I8c104c6b147e1901d94aefcefe35a174932c742b
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: go mod tidy
Change-Id: I0f610ccea6bc874248e84c24770944a3071dcc57
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: fix test failures from credential provider migration
- Remove unused TAT stub registrations in api and service tests
(CredentialProvider manages tokens, SDK no longer calls TAT endpoint)
- Update strict mode integration test: +chat-create now supports user
identity, so it should succeed under strict mode user
Change-Id: Iab51c2e12a97995e0b95dcd71df212d2d1f76570
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: migrate remaining os calls to internal/vfs
Replace direct os.Stat/Open/MkdirAll/OpenFile/Remove/ReadDir/UserHomeDir
with vfs equivalents in shortcuts/minutes, shortcuts/drive, and
internal/keychain. Add ReadDir to the vfs interface and OsFs implementation.
Change-Id: I8f97e5fb3e1731b4684d276644fcb10fae823067
* fix: resolve gofmt and goimports formatting issues
Change-Id: If61578631f5698f7ca2d9a946ca59753651463fb
* feat: add Flag.Input support for @file and stdin input sources
Add framework-level support for reading flag values from files (@path)
or stdin (-), solving the fundamental problem of passing complex text
(markdown, multi-line content) via CLI arguments where shell escaping
breaks content. Closes#239, fixes#163.
- Add File/Stdin constants and Input field to Flag struct
- Add resolveInputFlags() in runner pipeline (pre-Validate)
- Support @@ escape for literal @ prefix
- Guard against multiple stdin consumers
- Auto-append "(supports @file, - for stdin)" to help text
- Apply to: docs +create/+update --markdown, im +messages-send/+reply
--text/--markdown/--content, task +comment --content,
drive +add-comment --content
Change-Id: I305a326d972417542aeadd70f37b74ea456461ef
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: fix pre-existing test failures in task, minutes, and registry
- task/minutes: remove unused tenant_access_token httpmock stubs
(TestFactory's testDefaultToken provides tokens directly, so the
HTTP stub was never consumed and failed verification)
- registry: fix hasEmbeddedData() to check for actual services instead
of just byte length (meta_data_default.json has empty services array)
Change-Id: Ic7b5fc7f9de09137a7254fe1ddf47d24ade40587
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: suppress nilerr lint for intentional nil returns
Both cases intentionally return nil on error for graceful degradation:
- profile list: show friendly message when config is not initialized
- service: skip scope check when token resolution fails
Change-Id: I7285c37277c9b0361a421ab00359244c2cd150b3
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address CodeRabbit review feedback
- runner.go: fail fast when Input is used on non-string flags
- remote_test.go: rename hasEmbeddedData → hasEmbeddedServices
- profile/list.go: add omitempty to optional JSON fields
- service.go: surface context cancellation errors in scope check
Change-Id: I7072d41f8c711b4b37c542e32dfd8150f42b13c0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: tighten credential resolution and profile flows
Change-Id: I83f6d424540eab9b1708944b9b6e26e8477cc60d
* refactor: centralize identity hint resolution
Change-Id: I38d5f98160b92adb62dc929ae73697ae5b3d64f8
* fix: surface unverified extension identities
Change-Id: Ia86d9bd19add9010176339ec4cc89deb033f5b4f
* fix: honor runtime credential sources in config views
Change-Id: I40b2ffedc5c1db5e08e86b9472ea2b84fa02bb29
* fix: prefer runtime values in config show commands
Change-Id: I5663a53e147577f0f1f533f67d12bea504e6b839
* Revert "fix: prefer runtime values in config show commands"
This reverts commit 4f9db3a227.
* Revert "fix: honor runtime credential sources in config views"
This reverts commit b3bfd526c5.
* fix: harden profile flows and credential boundaries
Change-Id: Ica61cd2730a639f71516cb1b237a639cb6511f7a
* fix: optimize profile and config inspection for agents
Change-Id: I19c368102f19654952638180ab947788a6971563
* refactor: unify credential env contracts
Change-Id: I0ff2c0a650ea53589a0626333e8f6e628ef10a54
* docs: expand AGENTS guidance
Change-Id: I289027dfd364c92205012feef6f05037066c035b
* fix: resolve regression bugs found during PR #252 review
- im: fix double SafeInputPath in resolveLocalMedia → uploadImageToIM/
uploadFileToIM chain that rejected all local image/file uploads
- credential: stop writing plain-text warnings to stderr, preserving
JSON envelope contract for AI agent consumers
- profile add: reject duplicate app-id to prevent keychain credential
collisions across profiles
- profile rename: exclude self when checking name uniqueness so renaming
to own appId works correctly
- config: replace bare fmt.Errorf with output.Errorf in save-failure
paths (default_as, strict_mode ×2, profile add)
- factory: remove unused resolveDefaultAs method (lint)
Change-Id: I6aa0d064414016f367f1edb08dd0604adf7bf13d
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove flaky TestColdStart_UsesEmbedded (race in registry)
The test triggers a data race: resetInit() writes package globals while
a background goroutine from a previous test may still be reading them.
The embedded-data path is covered by other tests.
Change-Id: I7a0c3bf85a9fb337b9279c9053697f40a0c0a0d4
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: type-strengthen Brand and DefaultAs across credential chain
Replace raw string fields with typed enums for compile-time safety:
- extension/credential: add Brand and Identity named types
- internal/core: AppConfig.DefaultAs and CliConfig.DefaultAs → Identity
- internal/credential: Account.DefaultAs and IdentityHint.DefaultAs → core.Identity
The full data flow is now typed end-to-end:
extcred.Brand → core.LarkBrand (named-type cast)
extcred.Identity → core.Identity (named-type cast)
No string intermediaries, no implicit conversions.
Change-Id: I715b3b3f033fcb624010f1af9619e3562740ef08
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: fix gofmt alignment in extension/credential/types.go
Change-Id: Ibfac0703a5a28f3c6ba4a47bf40696028d0f3b90
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove file/stdin input support from task comment content flag
Change-Id: If49704ca4612465a23bd30b755d6e72a35fc2349
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(cmdutil): remove dead code autoDetectIdentity
autoDetectIdentity() is only called from tests, never from production
code. Remove it along with its 3 test cases to reduce surface area
before the upcoming ctx propagation refactor.
Change-Id: I35a188860f17656f3e1fe9874f87f284985ae196
* refactor(cmdutil): add ctx parameter to resolveIdentityHint
Private method resolveIdentityHint now accepts context.Context and
passes it to CredentialProvider.ResolveIdentityHint instead of using
context.Background(). The caller (ResolveAs) still uses
context.Background() temporarily until its own signature is updated.
Change-Id: I14634a4e0dc1d657d56936ba61a7b7a206da8ac4
* refactor(cmdutil): add ctx parameter to ResolveStrictMode
ResolveStrictMode now accepts context.Context and passes it to
CredentialProvider.ResolveAccount instead of using context.Background().
Callers in cobra RunE pass cmd.Context(); callers outside RunE
(cmd/root.go startup, tests) use context.Background() explicitly.
Change-Id: I31be48e548ac5ac5640a65f3bfdde4a53ed1dc7e
* refactor(cmdutil): add ctx parameter to CheckStrictMode
CheckStrictMode now accepts context.Context and forwards it to
ResolveStrictMode. Callers pass cmd.Context() (cobra RunE) or
opts.Ctx (APIOptions/ServiceMethodOptions).
Change-Id: I47888519d4cae8c94054771c32aff075565a8cdc
* refactor(cmdutil): add ctx parameter to ResolveAs
ResolveAs now accepts context.Context as first parameter and forwards
it to ResolveStrictMode and resolveIdentityHint. This completes the
ctx propagation chain: all Factory methods that call
CredentialProvider now receive ctx from cobra cmd.Context().
No more context.Background() calls remain in factory.go for
credential provider operations.
Change-Id: I6d10b6350e3b149470660de3e7855614314e8b29
* test: fix gofmt in cmdutil factory tests
Change-Id: I4a87d5a815b959f14cc4371b73dee4aae106932f
* fix: remove file/stdin input support from im send/reply and drive comment
The Input (file/stdin) feature is not yet ready for these flags:
- im send/reply: --content, --text, --markdown
- drive add-comment: --content
Retained only in doc create/update where markdown from file is essential.
Change-Id: I582b6349528fccb639ad9edc84650cca3b68535c
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: liushiyao <liushiyao.1206@bytedance.com>