Skip to content

feat: 对齐 lark-cli——搜索 enrich + 输出工程化 + 多维表格/表格/vc/mail/markdown 全套补全#158

Draft
nengqi wants to merge 16 commits into
riba2534:mainfrom
nengqi:feat/lark-parity
Draft

feat: 对齐 lark-cli——搜索 enrich + 输出工程化 + 多维表格/表格/vc/mail/markdown 全套补全#158
nengqi wants to merge 16 commits into
riba2534:mainfrom
nengqi:feat/lark-parity

Conversation

@nengqi
Copy link
Copy Markdown
Contributor

@nengqi nengqi commented May 28, 2026

背景

进一步对齐 lark-cli,把此前需回退 lark-cli 的场景补齐到 feishu-cli:消息搜索结果 enrich、输出工程化(jq/表格)、多维表格全套、电子表格高级、vc/mail/markdown 补全。基于 main 增量实现,不改既有命令默认行为(无不兼容变更)。

改了什么

① 消息搜索 enrich(search messages

  • 新增 --enrich opt-in:补全 内容/发送者/群名/时间(对齐 lark +messages-search
  • 默认行为不变:-o json 仍返回 {MessageIDs,HasMore,PageToken} 旧 schema(完全向后兼容

② 输出工程化 + api 增强

  • 新增 internal/output 包:--format json|pretty|table|ndjson|csv + --jq(内置 gojq v0.12.17 纯 Go,pin 保持 go 1.21
  • api 命令新增 --format/--jq(显式指定才走内置渲染,否则保留原 pretty/raw + -o/--include-headers/--timeout/业务错误码处理)
  • 大整数精度:渲染链路用 json.Number,飞书 19 位 message_id/chat_id 不被 float64 截断

③ 多维表格补全(bitable

  • dashboard create/get/update/delete/arrange + block create/get/list/update/delete
  • form create/delete/detail/submit + form field(别名 questions) list/patch/create/delete
  • workflow create/get/update(原有 list/enable/disable)
  • record 附件 upload/download/remove + share-link + batch-get
  • role member 全套、update
  • 新增 internal/client/bitable_v1.go:dashboard copy / role-member / app update 等 base/v3 无对应端点的走 bitable/v1

④ 电子表格高级(sheet

  • 浮动图片 get/update/media-upload/write-image
  • filter-view get/update + filter-view condition create/get/update/delete/list
  • dropdown get/update/delete、batch-set-style

⑤ vc / mail / markdown

  • vc bot meeting-join/leave/events
  • mail signature
  • markdown diff(本地 unified diff:远端最新 vs 本地文件 / 远端版本对比;自带 LCS,无外部依赖)

验证

  • go build/vet/test ./... 全绿;新增单测覆盖输出格式化(大整数/jq/table CJK/csv)、enrich、bitable/sheet/vc/mail/markdown 命令的请求构造与边界。
  • 真 e2e(临时 base/表实跑):dashboard CRUD/block create、form create + questions patch、workflow list、record download-attachment(确认走 get_attachments + extra)、mail signature、sheet filter-view/dropdown、markdown diff mode1 等,下载内容 byte-for-byte 校验一致。
  • 多轮 review:多 agent 代码审查(逐条对照 lark-cli --dry-run 端点)+ codex 独立 review 两轮 + 复核,修复 12+ findings(端点路由、LCS 内存上限、download 业务错误检查、附件 extra、时间数值比较、边界校验等)。

几处端点与 lark-cli 现状不同(已实测核对)

  • workflow 启停走 base/v3 .../workflows/{id}/enable|disable(无 body),form questions update 走 collection 端点 .../forms/{id}/questions + {questions:[...]},record 附件下载总是先 get_attachmentsextra_info 再带 extra 下载——均与 lark-cli --dry-run 实证一致。
  • mail signature.../user_mailboxes/{id}/settings/signatures实测返回 200,而 lark-cli 的 me/signatures(无 settings)实测 404——飞书 API 已演进,采用前者。

依赖

新增 github.com/itchyny/gojq v0.12.17(pin 保持 go 1.21 兼容,未抬升 go directive)。

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b6667c6b4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cmd/bitable_workflow.go Outdated
}
body := map[string]any{"status": status}
return bitableRun(cmd, func(bt string) bitableReq {
return bitableReq{method: "PUT", path: client.BitableV1Path("apps", bt, "workflows", workflowID), body: body, useV1: true}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Call the Base v3 workflow toggle endpoints

When bitable workflow enable or disable is run, this sends PUT /open-apis/bitable/v1/apps/{app_token}/workflows/{workflow_id} with a status body, but the current Lark base workflow shortcuts document the toggle APIs as PATCH /open-apis/base/v3/bases/:base_token/workflows/:workflow_id/enable and /disable (see github.com/larksuite/cli/shortcuts/base). In practice these new commands will hit the wrong service/path and fail to toggle workflows; route through BaseV3Call and append the status action to the path instead.

Useful? React with 👍 / 👎.

Comment thread cmd/bitable_form.go Outdated
return fmt.Errorf("解析 --config 失败: %w", err)
}
return bitableRun(cmd, func(bt string) bitableReq {
return bitableReq{method: "PATCH", path: formPath(bt, tableID, formID, "questions", questionID), body: body}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Patch form questions at the collection path

When bitable form field patch is used, the request goes to /forms/{form_id}/questions/{question_id} with the raw config as the body, but the Base v3 form-question update shortcut is PATCH /open-apis/base/v3/bases/:base_token/tables/:table_id/forms/:form_id/questions and expects a questions array whose item includes the id. The per-question path is not the documented endpoint, so this command will 404 or fail validation instead of updating the question; wrap the supplied fields with the questionID and call the collection endpoint.

Useful? React with 👍 / 👎.

@nengqi nengqi marked this pull request as draft May 28, 2026 14:44
nengqi added 16 commits May 28, 2026 22:54
提供 lark-cli 风格输出能力,供 api / search / bitable 新命令统一消费:
- --format json|pretty|table|ndjson|csv
- --jq <expr>(内置 gojq v0.12.17,纯 Go,无需外部 jq;pin 该版本保持 go 1.21 兼容)
- 大整数精度:json.Number 链路,飞书 19 位 ID 不被 float64 截断
- table/csv:CJK 宽度对齐 + 单元格换行净化
带 13+ 单测(格式化/jq/大整数/CJK/csv)。
在既有 api 透传命令上增量加 --format json|pretty|table|ndjson|csv + --jq(走 internal/output):
- 显式指定 --format/--jq 时走内置渲染(含大整数保精度);否则保持原 pretty/raw 行为不变
- 保留既有鉴权/dry-run/-o/include-headers/timeout/业务错误码处理
对齐 lark-cli +messages-search。原命令只返回消息 ID,现默认 enrich:
- search → 消息 ID → BatchGetMessages 取详情 → 解析发送者名/群名 → 人类可读视图
- --ids-only 退回纯 ID(省额外 API 调用)
- --format/--jq 结构化输出;--page-all/--page-limit 自动翻页
- 不兼容:-o json 输出从 {MessageIDs,...} 对象变 []EnrichedMessage 数组(详见 CHANGELOG)
带纯转换单测 + mock 集成测试。
…tch-get

补齐公开 API 支持、此前缺失的多维表格命令:
- dashboard list|copy;form get|patch + form field list|patch
- role member list|create|delete|batch-create|batch-delete
- workflow enable|disable;bitable update(重命名/高级权限);record batch-get
- 新增 internal/client/bitable_v1.go(dashboard copy/role-member/app update/workflow 启停走 bitable/v1,base/v3 无对应端点)
- 统一执行器 bitableRun + 请求描述符 bitableReq 路由 base/v3 与 bitable/v1,写命令支持 --dry-run
- 新命令统一接 internal/output(--format/--jq)
带 BitableV1Call mock 单测 + dry-run/form patch body 构造单测。
- README 全功能覆盖表:加 Raw API 行、多维表格行补全、搜索行标 enrich;技能数 25→26 + 加 feishu-cli-api 行
- CHANGELOG Unreleased 条目:三类新增详述 + search -o json breaking change 标注
- repo CLAUDE.md 命令速查:bitable 新命令 + search enrich + api --jq/--format
- 新增 skills/feishu-cli-api/SKILL.md(裸调 API 子技能)
…lection 批量端点

响应 codex P1 review:
- workflow enable/disable 原走 bitable/v1 PUT apps/{token}/workflows/{id}+status(错误路径),
  改为 base/v3 PATCH .../workflows/{id}/enable|disable(无 body),对齐 lark-cli base +workflow-enable/disable
- form-questions-update 原走 per-question 路径 .../questions/{qid}(不存在),
  改为 collection 端点 .../questions + {questions:[{id,...}]} 数组(单次≤10),加 --questions flag
- 补回归单测锁住正确端点路径
默认走 collectMessageIDs:人类可读 ID 列表 + -o json 返回旧 schema
{MessageIDs,HasMore,PageToken},与升级前完全一致。--enrich 才走
collectEnrichedMessages 补全内容/发送者/群名/时间。去掉 --ids-only。
card-content-type 校验下沉到 --enrich 路径。
端点全走 base/v3,与 lark-cli base +dashboard-* --dry-run 逐个印证。
theme-style 嵌套 body.theme.theme_style;block create type 枚举校验;
读命令无 dry-run、写命令带 dry-run+config 全量覆盖。新增独立文件不动现有命令。
…record 附件

form create/delete + detail/submit(按 share_token 端点) + questions create/delete(collection 端点)
workflow create/get/update(base/v3, update=PUT 整体替换)
record upload/download/remove-attachment(table 级 append/get/remove_attachments + drive medias)
form questions 组加 questions 别名;端点全部经 lark-cli dry-run 双重印证
- image get/update/media-upload/write-image(v3 float_images get/PATCH + drive medias/upload_all sheet_image + v2 values_image)
- filter-view get/update(v3 filter_views GET/PATCH)
- filter-view condition create/get/update/delete/list(v3 filter_views/:id/conditions,create 带 condition_id、update 走 PUT 由路径携带)
- dropdown get/update/delete(v2 dataValidation GET?range + PUT/:sheet_id + DELETE)
- batch-set-style(v2 styles_batch_update,复用 SetCellStyleBatch)
- 全部新文件,helper 加 sheet 前缀,不改 go.mod/go.sum 及现有命令;端点经 lark-cli strings+help+dry-run 双重印证;新增单测 + 真实只读路径 e2e 验证
… diff

vc bot meeting-join/leave/events 对齐 lark vc bots 域(POST bots/join+leave、GET bots/events)
mail signature 读 user_mailboxes settings/signatures 列表,支持 --detail 筛单条
markdown diff 下载远端内容本地算 unified diff(远端版本互比 / 远端 vs 本地文件),不改远端
端点经 lark-cli strings+help 双重印证;新命令均带 dry-run + 单测,go.mod 未动
…vc bot + mail signature + markdown diff 到 CHANGELOG/README/skill
1. markdown diff 远端版本下载改用 files/{token}/download?version=N(同 token+version 查询参数,不再 GetFileVersion 拿 token 当下载目标),新增 client.DownloadFileVersion(raw ApiReq+Do,SDK builder 丢 QueryParams)+ FetchFileVersionContent
2. sheet UpdateFloatImage offset-x/-y 改 *float64 指针表达「是否更新」,0 为合法值;cmd 层用 Changed() 区分未传 vs 显式 0
3. vc events page-size 校验改 pageSize!=0 && (<20||>100),拒绝 1-19
4. bitable download-attachment 总是先 get_attachments 拿 extra_info,再带 extra 下载(与 lark 一致,防 403)
5. bitable question-ids 兼容 JSON 数组与 CSV
6. sheet dropdown get 删冗余 output 分支
7. vc events dry-run 只展示非空参数

更新 offset/page-size/question-ids/attachment 单测
…md 限制提示

- download-attachment 不再注册 --format/--jq(避免 output.ParseOptions 抢用 --output 把结果 JSON 覆盖下载的附件),结果改 printJSON 到 stdout,--output 专用于附件保存目标(e2e 实测 clobber bug)
- markdown diff Long + 版本下载错误补提示:模式2/3 版本对比需文件有版本快照,普通 .md 无数字版本会 404,仅 docx/sheet/bitable 等支持(mode1 不受影响)
…l+边界校验)

- H1 DownloadFileVersion: HTTP 200 + JSON 业务错误体 {code,msg} 不再当二进制写盘,优先 Content-Type 判 JSON、'{' 前缀作辅助且须 parse 出 code!=0
- H2 markdown diff: 加 maxDiffLines=50000 上限,算 LCS 前拦截超大内容防 OOM
- M2 download-attachment: 多 --file-token 部分缺失打 stderr 警告并继续下载已匹配的,仅全空才报错
- M3 vc meeting-events: --start/--end 改 int64 数值比较,修字典序在位数不同时误判先后
- M1 DownloadFileVersion: 补注释说明 size 检查为非流式内存载入后防超大写盘
- L1 UpdateFloatImage: image==nil 防御
- L3 sheet image update: width/height 显式设置时校验≥20、offset≥0,与 help 一致
- L2 vc page-size: flag/help 注明不传或 0=默认 20
- 补 H2/M2/M3/L1/L3/H1 单测
…-width 0 报错

- [CRITICAL] markdown checkDiffSize 加 n*m 乘积上限 maxDiffCells(单侧降到 20000):原单侧 50000 不约束 LCS 矩阵内存,两侧各 50000 行=25亿 int≈10GB OOM
- [WARN] parseDownloadJSONError 改只信 Content-Type(去掉 RawBody 前缀辅助路径):避免把内容恰为 {code:N} 的合法文件误判为业务错误;注明 DownloadFileVersion 仅用于 markdown 文本下载
- [MINOR] sheet image update 前置 guard 改用 Changed() 判断 width/height:--width 0 现报 width<20 而非误报未指定字段
- 同步更新 TestCheckDiffSize(新增乘积超限断言)/TestParseDownloadJSONError(只信 CT)
@nengqi nengqi force-pushed the feat/lark-parity branch from 5b6667c to 28bc88a Compare May 28, 2026 17:42
@nengqi nengqi changed the title feat: 消息搜索 enrich + 多维表格补全 + 输出工程化(jq/表格) + api --jq/--format feat: 对齐 lark-cli——搜索 enrich + 输出工程化 + 多维表格/表格/vc/mail/markdown 全套补全 May 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant