Skip to content

refactor: migrate vc/minutes shortcuts to FileIO#336

Merged
tuxedomm merged 3 commits intomainfrom
feat/fileio-migrate-vc-minutes
Apr 8, 2026
Merged

refactor: migrate vc/minutes shortcuts to FileIO#336
tuxedomm merged 3 commits intomainfrom
feat/fileio-migrate-vc-minutes

Conversation

@tuxedomm
Copy link
Copy Markdown
Collaborator

@tuxedomm tuxedomm commented Apr 8, 2026

Summary

  • minutes_download.go: SafeOutputPath + EnsureWritableFile + MkdirAll + AtomicWriteFromReaderFileIO.Stat (overwrite check) + FileIO.Save; safePathResolveSavePath
  • vc_notes.go: vfs.Stat + SafeOutputPath + MkdirAll + AtomicWriteFileIO.Stat + FileIO.Save; error messages preserved via structured error matching (ErrPathValidation / MkdirError)
  • common/runner.go: add WrapSaveErrorByCategory(err, category) helper for standardized save error mapping

Part of the FileIO shortcut migration series:

Test plan

  • go test ./shortcuts/vc/... — all pass
  • go test ./shortcuts/minutes/... — all pass
  • go test ./shortcuts/common/... — all pass
  • golangci-lint run — no new issues
  • Manual: lark-cli vc +notes --minute-tokens <token> with transcript download
  • Manual: lark-cli minutes +download --token <token> with overwrite check

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling for file save and download operations with clearer messages for invalid output paths, directory creation failures, and other write errors.
    • Preserved overwrite checks to avoid unintended file replacement during downloads and transcript saves.
  • Refactor
    • Switched to a unified file I/O approach for writing media and transcript files to streamline save logic and error reporting.

tuxedomm added 2 commits April 8, 2026 17:52
- vc_notes: replace vfs.Stat + validate.SafeOutputPath + validate.AtomicWrite
  with FileIO.Stat/Save for transcript download
- minutes_download: replace validate.SafeOutputPath + validate.AtomicWriteFromReader
  with FileIO.Save, use FileIO.Stat for overwrite checks
- Use WrapSaveError to preserve original error messages

Change-Id: I7cdeddf933b1ca76266d499ec2678eb8ce6875f3
FileIO.Save errors now distinguish path validation, mkdir, and write
failures to match the original stderr messages exactly.

Change-Id: Ic578a15fc72f68d893ee9717fd86a4b8c72192d0
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d68048a2-d1a7-47f8-85f3-d25fa84b3e5e

📥 Commits

Reviewing files that changed from the base of the PR and between d983302 and 6d36a82.

📒 Files selected for processing (1)
  • shortcuts/minutes/minutes_download.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • shortcuts/minutes/minutes_download.go

📝 Walkthrough

Walkthrough

Added a new error-wrapping utility for fileio.Save errors and migrated file-write flows in download and notes codepaths from internal vfs utilities to the extension/fileio abstraction, updating existence checks, save calls, and error handling.

Changes

Cohort / File(s) Summary
Error Handling Utility
shortcuts/common/runner.go
Added WrapSaveErrorByCategory(err error, category string) error to map fileio.Save errors to structured output errors: handles fileio.ErrPathValidation, *fileio.MkdirError, and a generic save failure case; preserves nil passthrough.
Minutes download migration
shortcuts/minutes/minutes_download.go
Replaced internal/vfs validation/atomic-write flow with extension/fileio: added fio fileio.FileIO on opts, use fio.Stat for existence checks, call fio.Save with content metadata, wrap save errors via WrapSaveErrorByCategory, and resolve output path with fio.ResolvePath.
VC notes migration
shortcuts/vc/vc_notes.go
Switched transcript write from vfs/atomic write utilities to runtime.FileIO().Save; use FileIO.Stat for overwrite checks; inspect fileio.Save errors (path validation, mkdir error, generic) instead of previous safe-path/atomic-write error branches; updated imports.

Sequence Diagram(s)

sequenceDiagram
  participant Cmd as CLI Command
  participant HTTP as HTTP Server
  participant FileIO as runtime.FileIO
  participant Out as output wrapper

  Cmd->>HTTP: GET media/transcript
  HTTP-->>Cmd: Response (body, Content-Type, Content-Length)
  Cmd->>FileIO: Stat(target) to check existence (if !--overwrite)
  FileIO-->>Cmd: exists / not found
  Cmd->>FileIO: Save(path, reader, options{ContentType, Size})
  alt Save succeeds
    FileIO-->>Cmd: saved path/size
    Cmd->>Out: return success result (resolved path, size)
  else Save fails
    FileIO-->>Cmd: error
    Cmd->>Out: WrapSaveErrorByCategory(err, category)
    Out-->>Cmd: structured output error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped from vfs to fileio's shore,
Saving bytes with a gentler roar.
Errors sorted, wrapped with care,
Paths resolved—soft spring air.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: migrating vc and minutes shortcuts to use the FileIO abstraction.
Description check ✅ Passed The description comprehensively covers all required sections: summary of changes, detailed implementation notes, test plan with checkmarks, and context within the larger FileIO migration series.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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 feat/fileio-migrate-vc-minutes

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

@github-actions github-actions Bot added domain/vc PR touches the vc domain size/L Large or sensitive change across domains or core paths labels Apr 8, 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.

🧹 Nitpick comments (1)
shortcuts/minutes/minutes_download.go (1)

284-295: Consider "io_error" category for file operations.

The error category "api_error" is semantically mismatched for file I/O failures. These are local filesystem errors, not API errors. Using a category like "io_error" would be more accurate.

Additionally, the ResolvePath call on line 291 is redundant — per localfileio.go, both Save and ResolvePath use SafeOutputPath internally, so they return the same canonical path. The fallback on line 292-293 handles this safely, but you could simplify by using outputPath directly (since Save succeeded, the path was valid).

🔧 Optional: use a more accurate category
 	if err != nil {
-		return nil, common.WrapSaveErrorByCategory(err, "api_error")
+		return nil, common.WrapSaveErrorByCategory(err, "io_error")
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/minutes/minutes_download.go` around lines 284 - 295, The error
returned from opts.fio.Save is a local filesystem/I/O failure; change
common.WrapSaveErrorByCategory(err, "api_error") to use an I/O category like
"io_error" and return that wrapped error; also remove the redundant ResolvePath
call and its fallback — after Save succeeds use outputPath directly as the
savedPath in the downloadResult (keep result.Size() for sizeBytes) so update the
return to &downloadResult{savedPath: outputPath, sizeBytes: result.Size()}.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@shortcuts/minutes/minutes_download.go`:
- Around line 284-295: The error returned from opts.fio.Save is a local
filesystem/I/O failure; change common.WrapSaveErrorByCategory(err, "api_error")
to use an I/O category like "io_error" and return that wrapped error; also
remove the redundant ResolvePath call and its fallback — after Save succeeds use
outputPath directly as the savedPath in the downloadResult (keep result.Size()
for sizeBytes) so update the return to &downloadResult{savedPath: outputPath,
sizeBytes: result.Size()}.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8e5e2f8c-1a51-47aa-874b-640c3d1db90b

📥 Commits

Reviewing files that changed from the base of the PR and between f5a8fbf and d983302.

📒 Files selected for processing (3)
  • shortcuts/common/runner.go
  • shortcuts/minutes/minutes_download.go
  • shortcuts/vc/vc_notes.go

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 8, 2026

Greptile Summary

This PR migrates vc/+notes and minutes/+download file-write paths from low-level SafeOutputPath/AtomicWrite calls to the FileIO abstraction, and adds the WrapSaveErrorByCategory helper in common/runner.go to standardize structured error mapping. The migration is mechanically correct: error categories, path-validation matching, and mkdir error detection all follow the established FileIO patterns used in previous migration PRs.

The \"api_error\" category concern flagged in earlier review rounds has been addressed — minutes_download.go now correctly passes \"io\" to WrapSaveErrorByCategory.

Confidence Score: 5/5

Safe to merge — the migration is mechanically sound, the previously flagged error-category bug is fixed, and all remaining open items are non-blocking P2.

No new P0 or P1 issues found. The critical "api_error" category regression from the prior review round is resolved (now correctly "io"). Remaining open items from previous threads (relative saved_path in vc_notes, ResolvePath error swallowed) are P2 quality/consistency concerns that do not affect correctness or safety of the primary download path. All three files score 5/5 individually.

No files require special attention.

Vulnerabilities

No security concerns identified. Path traversal is mitigated by FileIO's SafeOutputPath/SafeInputPath validation surfaced via ErrPathValidation. Download URLs are validated against SSRF via validate.ValidateDownloadSourceURL before use, and HTTPS→HTTP redirect downgrade is blocked in CheckRedirect. User-supplied --output-dir is validated by common.ValidateSafeOutputDir before joining with user-controlled title data.

Important Files Changed

Filename Overview
shortcuts/common/runner.go Adds WrapSaveErrorByCategory helper that maps FileIO save errors to structured output errors using a caller-provided category; well-structured with clear exit-code and error-type separation.
shortcuts/minutes/minutes_download.go Migrates media download path to FileIO.Stat + FileIO.Save; error category is correctly set to "io" for disk-level failures; ResolvePath fallback preserves backward-compatible saved-path output.
shortcuts/vc/vc_notes.go Migrates transcript download to FileIO.Stat + FileIO.Save; structured error matching for ErrPathValidation/MkdirError is consistent with the rest of the FileIO migration series.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User invokes download command] --> B{single or batch?}
    B -- single --> C[FileIO.Stat overwrite check]
    B -- batch --> D[FileIO.Stat: is --output a file?]
    D --> C
    C -- file exists & no overwrite --> E[ErrValidation: file already exists]
    C -- proceed --> F[HTTP stream download]
    F --> G[FileIO.Save]
    G -- ErrPathValidation --> H[WrapSaveErrorByCategory → ErrValidation exit 2]
    G -- MkdirError --> I[WrapSaveErrorByCategory → Errorf ExitInternal, io]
    G -- WriteError/other --> J[WrapSaveErrorByCategory default → Errorf ExitInternal, io]
    G -- success --> K[FileIO.ResolvePath]
    K -- ok --> L[Return absolute saved_path in JSON]
    K -- error/empty --> M[Fallback: return original outputPath]

    subgraph vc_notes transcript path
        N[downloadTranscriptFile] --> O[FileIO.Stat overwrite check]
        O -- exists & no overwrite --> P[Log warning, return relative transcriptPath]
        O -- proceed --> Q[DoAPI transcript download]
        Q --> R[FileIO.Save]
        R -- error --> S[Log to stderr, return empty string]
        R -- success --> T[Return relative transcriptPath]
    end
Loading

Reviews (2): Last reviewed commit: "fix: correct error category and handle R..." | Re-trigger Greptile

Comment thread shortcuts/minutes/minutes_download.go Outdated
Comment thread shortcuts/minutes/minutes_download.go Outdated
Comment thread shortcuts/vc/vc_notes.go
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 8, 2026

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@6d36a82ec17271512f2b659fe55d563bd648f38a

🧩 Skill update

npx skills add larksuite/cli#feat/fileio-migrate-vc-minutes -y -g

@tuxedomm tuxedomm requested review from Ren1104 and liangshuo-1 April 8, 2026 11:20
…ownload

- WrapSaveErrorByCategory: "api_error" → "io" for local file I/O failures
- ResolvePath: check returned error instead of discarding it

Change-Id: I49e5a667096a81f412816c4ef88b68db8ef4a45f
@tuxedomm tuxedomm merged commit 63ea52b into main Apr 8, 2026
14 checks passed
@tuxedomm tuxedomm deleted the feat/fileio-migrate-vc-minutes branch April 8, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain/vc PR touches the vc domain size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants