Skip to content

feat(cmdutil): support @file for --params/--data (issue #705)#715

Closed
liangshuo-1 wants to merge 2 commits intomainfrom
agent/claude/ed72ff9f
Closed

feat(cmdutil): support @file for --params/--data (issue #705)#715
liangshuo-1 wants to merge 2 commits intomainfrom
agent/claude/ed72ff9f

Conversation

@liangshuo-1
Copy link
Copy Markdown
Collaborator

@liangshuo-1 liangshuo-1 commented Apr 29, 2026

Summary

  • Extend cmdutil.ResolveInput with @<path> (read JSON from a file) and @@... (escape for a literal @-prefixed value), mirroring the shortcuts framework's resolveInputFlags semantics.
  • Both --params and --data now support @file everywhere they're used (lark-cli api ... via cmd/api, declarative service commands via cmd/service).
  • Update flag help text to advertise @file.
  • Add tests for file read, whitespace trim, missing file, empty path, empty content, @@ escape, and integration through ParseJSONMap / ParseOptionalBody.

Fixes the Windows PowerShell 5 CommandLineToArgvW quote-mangling bug reported in #705 — users can now write JSON to a file and pass --params @params.json on any shell, no .bat workaround needed. Both flags can come from files in a single invocation, which stdin (-) couldn't support.

Behaviour

Input Result
- read all bytes from stdin (existing)
@<path> read & trim file contents (new)
@@foo strip leading @@foo, no file read (new)
'…' strip surrounding single quotes (existing, cmd.exe)
other pass through (existing)

Backward compatibility

The only behaviour change is @… values are now resolved as files instead of being passed through as-is. This was previously undocumented; the @@ escape covers anyone relying on a literal @-prefixed JSON value.

Test plan

  • go test ./internal/cmdutil/... — all green, including new @file cases
  • go test ./cmd/api/... ./cmd/service/... — green
  • go build ./... — green
  • Smoke test: lark-cli api GET /open-apis/drive/v1/files --params @params.json --dry-run resolves the file and serialises the params correctly
  • Error path: missing file produces --params: cannot read file "...": no such file or directory
  • Help text shows (supports - for stdin, @file for file input)

Closes #705

Summary by CodeRabbit

  • New Features

    • Support for @ input for --params and --data, allowing file-sourced values as an alternative to stdin
    • @@ escape to supply a literal @-prefixed value without treating it as a file reference
  • Documentation

    • Updated CLI help text for --params and --data to describe file input and @@ escaping options

Inline JSON values for --params/--data are mangled by Windows
PowerShell 5's CommandLineToArgvW. Stdin (-) was the only escape
hatch but supports just one flag at a time.

Extend ResolveInput to accept @<path> (read JSON from a file) and
@@... (escape for a literal @-prefixed value), mirroring the
shortcuts framework's resolveInputFlags semantics. With this, both
--params and --data can be sourced from files in the same call,
sidestepping shell quoting on every platform.

- internal/cmdutil/resolve.go: add @path / @@ handling, trim file
  content like stdin does, error on empty path or empty file
- internal/cmdutil/resolve_test.go: cover file read, whitespace
  trim, missing file, empty path, empty content, @@ escape, plus
  ParseJSONMap / ParseOptionalBody integration through @file
- cmd/api/api.go, cmd/service/service.go: update --params/--data
  help text to mention @file

Change-Id: I366aa0f5783fbec6f05403f7f542505098a98c82
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

📝 Walkthrough

Walkthrough

Adds @file input support for --params and --data by introducing file-path resolution into input parsing (new fileIO plumbing), updating ResolveInput to read @<path> and @@-escape, threading fileIO into JSON/form parsers, and updating help text and tests accordingly.

Changes

Cohort / File(s) Summary
CLI help updates
cmd/api/api.go, cmd/service/service.go
Updated --params and --data flag descriptions to advertise @file input support alongside - (stdin).
Input resolution core
internal/cmdutil/resolve.go
Added @<path> file reading via provided fileio.FileIO, @@ escape to emit literal @..., whitespace trimming, and explicit errors for missing/empty inputs. Signature now accepts fileIO fileio.FileIO.
JSON/form parsing plumbing
internal/cmdutil/json.go
Threaded fileIO into ParseJSONMap and ParseOptionalBody and forwarded it to ResolveInput; no other parsing logic changed.
Command callers
cmd/api/api.go, cmd/service/service.go
Created/reused a single fileIO instance and passed it into ParseJSONMap, ParseOptionalBody, and multipart form building calls.
Tests
internal/cmdutil/resolve_test.go, internal/cmdutil/json_test.go
Adjusted tests to new function signatures, added file-backed resolution tests (success, trimming, errors, @@ escape), and updated integration tests for ParseJSONMap / ParseOptionalBody using localfileio.LocalFileIO.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • MaxHuang22

Poem

🐰 I found a file named with an @,
no more shell-quote acrobat,
JSON hops in neat and clean,
stdin and escapes relieved, so keen—
nibble, parse, and send: hooray! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main feature: @file support for --params/--data with reference to the issue.
Description check ✅ Passed The description follows the template with Summary, Changes, Test Plan sections completed. It provides clear motivation, implementation details, behavior table, backward compatibility notes, and comprehensive test verification.
Linked Issues check ✅ Passed All code changes align with #705 requirements: ResolveInput now supports @ file reading [resolve.go, resolve_test.go], @@ escape for literals [resolve.go], integrated into ParseJSONMap/ParseOptionalBody [json.go], advertised in help text [api.go, service.go], and fileIO abstraction used throughout.
Out of Scope Changes check ✅ Passed All changes are strictly scoped to implementing @file support for --params/--data: ResolveInput extension, fileIO integration into parsers, help text updates, and comprehensive test coverage. No extraneous modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/claude/ed72ff9f

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the size/L Large or sensitive change across domains or core paths label Apr 29, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/cmdutil/resolve.go`:
- Around line 54-57: Replace the direct os.ReadFile usage with input validation
and the vfs abstraction: call validate.SafeInputPath(path) and return its error
if any, then use vfs.ReadFile (or the repository's vfs equivalent) instead of
os.ReadFile to load the file into data, preserving the existing error wrapping
(e.g., fmt.Errorf("cannot read file %q: %w", path, err)). Update the code around
the existing data, err := os.ReadFile(path) site in resolve.go to perform these
two steps (validate.SafeInputPath and vfs.ReadFile) using the same path variable
and error-handling style.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 75b90dee-97b2-44f1-b10d-df9b19605d63

📥 Commits

Reviewing files that changed from the base of the PR and between 4181925 and 7f526bf.

📒 Files selected for processing (4)
  • cmd/api/api.go
  • cmd/service/service.go
  • internal/cmdutil/resolve.go
  • internal/cmdutil/resolve_test.go

Comment thread internal/cmdutil/resolve.go Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 29, 2026

Codecov Report

❌ Patch coverage is 90.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.15%. Comparing base (4181925) to head (60e19d7).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
internal/cmdutil/resolve.go 90.90% 1 Missing and 1 partial ⚠️
cmd/api/api.go 85.71% 1 Missing ⚠️
cmd/service/service.go 85.71% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #715      +/-   ##
==========================================
+ Coverage   64.14%   64.15%   +0.01%     
==========================================
  Files         504      504              
  Lines       44285    44308      +23     
==========================================
+ Hits        28406    28427      +21     
- Misses      13411    13412       +1     
- Partials     2468     2469       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 29, 2026

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@60e19d76b3f2b71f97951697efa1fd809c076583

🧩 Skill update

npx skills add larksuite/cli#agent/claude/ed72ff9f -y -g

The first cut of @file support called os.ReadFile directly inside
ResolveInput, bypassing the codebase's fileio.FileIO abstraction
(SafeInputPath validation, pluggable provider). That diverged from
how every other file-reading path works: BuildFormdata for --file
uploads and the shortcuts framework's resolveInputFlags both go
through fileio.FileIO.Open with explicit fileio.ErrPathValidation
handling.

Re-route @file through the same path:

- ResolveInput, ParseJSONMap, ParseOptionalBody now take a
  fileio.FileIO; @path uses fileIO.Open which goes through
  SafeInputPath (control-char rejection, abs-path rejection,
  symlink-escape check) — same security posture as --file
- cmd/api and cmd/service callsites pass
  Factory.ResolveFileIO(ctx); the upload path now reuses the
  resolved fileIO instead of resolving twice
- Path-validation errors surface as
  `--params: invalid file path "...": ...` distinct from
  `--params: cannot read file "...": ...` for genuine I/O errors
- Nil fileIO with an @path returns a clear
  "file input (@path) is not available" error
- Tests use localfileio.LocalFileIO with TestChdir(t, dir),
  matching the existing fileupload_test.go pattern; absolute-path
  rejection and nil-fileIO are covered

This makes the feature behave identically under any FileIO
provider (including server mode) instead of being silently bound
to the local filesystem.

Change-Id: I878c4e8fb03f43f1f19afad75ec3af9cdab7a7f9
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
internal/cmdutil/json_test.go (1)

26-26: Add one parser-level case with non-nil fileIO to lock in @file wiring.

These updates keep compilation green, but all current cases still pass nil for fileIO. Adding at least one @file case through ParseOptionalBody/ParseJSONMap would protect this new wiring from regression.

As per coding guidelines **/*.go: Every behavior change must have an accompanying test.

Also applies to: 56-56

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmdutil/json_test.go` at line 26, Add a parser-level test case that
passes a non-nil fileIO into ParseOptionalBody (and exercises ParseJSONMap via
an `@file` input) so the `@file` wiring is exercised; locate the test harness around
the call to ParseOptionalBody in json_test.go (the table-driven cases feeding
into got, err := ParseOptionalBody(...)) and add one case where method/data
include an "@file" reference and the fileIO argument is a non-nil implementation
(e.g., a small in-memory/mock that returns expected file contents), then assert
the parsed result matches the expected map and no error is returned.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/cmdutil/json_test.go`:
- Line 26: Add a parser-level test case that passes a non-nil fileIO into
ParseOptionalBody (and exercises ParseJSONMap via an `@file` input) so the `@file`
wiring is exercised; locate the test harness around the call to
ParseOptionalBody in json_test.go (the table-driven cases feeding into got, err
:= ParseOptionalBody(...)) and add one case where method/data include an "@file"
reference and the fileIO argument is a non-nil implementation (e.g., a small
in-memory/mock that returns expected file contents), then assert the parsed
result matches the expected map and no error is returned.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 794a85d3-a043-463d-8634-268f20492668

📥 Commits

Reviewing files that changed from the base of the PR and between 7f526bf and 60e19d7.

📒 Files selected for processing (6)
  • cmd/api/api.go
  • cmd/service/service.go
  • internal/cmdutil/json.go
  • internal/cmdutil/json_test.go
  • internal/cmdutil/resolve.go
  • internal/cmdutil/resolve_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • cmd/api/api.go
  • cmd/service/service.go
  • internal/cmdutil/resolve_test.go
  • internal/cmdutil/resolve.go

@liangshuo-1 liangshuo-1 deleted the agent/claude/ed72ff9f branch April 29, 2026 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--params / --data fail on Windows PowerShell 5 due to JSON quote mangling + feature request: @file support

1 participant