mirror of
https://github.com/larksuite/cli.git
synced 2026-09-14 18:42:53 +08:00
codex/fix-docs-content-encoding
190 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ac6d7ce4f8 | feat: propagate credential metadata (#2305) | ||
|
|
1e87f67244 |
fix(apps): friendly-ize "Container not exists" for observability commands (#2302)
* fix(apps): friendly-ize "Container not exists" for observability commands
+metric-list and +analytics-list passed the upstream business code 400002655
("Container not exists") through verbatim. The message reads like an
infrastructure fault and misleads callers (including AI agents) into retrying a
non-retryable, expected business state: an app with no running container simply
has no metrics/analytics to query yet.
Rewrite it at a scoped observability helper (withObservabilityHint) into a
user-facing explanation plus a deploy-then-retry next step, mirroring the
existing isAppNoDatabaseError override. Detection is code-OR-message so a server
renumber alone does not silently drop the rewrite. Classification, code, and the
wrapped cause are preserved; unrelated failures still fall through to the shared
app-id recovery hint (and its own no-database override).
* test(apps): add execution-path regression tests for observability container hint
common_test.go proves withObservabilityHint in isolation but stays green if a
call site reverts to withAppsHint. Drive +metric-list and +analytics-list
Execute with a mocked 400002655 "Container not exists" envelope and assert the
container-specific message/hint/code, so a revert fails the build. Also closes
the two uncovered call-site lines flagged by coverage.
* fix(errclass): classify no-container code as validation/failed_precondition
Register 400002655 in sparkCodeMeta mirroring its no-database twin
(400002465) so both "expected precondition not met" business states expose
the same validation/failed_precondition classification to machine consumers,
instead of falling back to api/unknown. The shortcut-layer message rewrite
already keyed off the raw code, so this only aligns the typed envelope's
category/subtype; update the execution-path tests to pin the new
classification.
* fix(apps): gate the no-container hint's release behind user authorization
The no-container hint told a harness to deploy via +release-create, a "write"
that takes the whole app live and can affect existing production traffic —
without the user-confirmation gate its no-database twin deliberately carries.
Since the hint's audience is an AI agent that acts on it, a failed metrics read
could trigger an unconfirmed go-live. Lead with a read-only +release-list
status check and gate +release-create behind an explicit user confirmation,
mirroring appNoDatabaseHint.
|
||
|
|
7436a53afc | feat(slides): inline slides reference docs into help output (#2181) | ||
|
|
4488da0b14 |
feat(apps): add +user-id-convert shortcut for Miaoda↔Feishu ID conversion (#2270)
* feat(apps): add +user-id-convert shortcut for Miaoda↔Feishu ID conversion
Wrap the platform id_convert OpenAPI as a read-only shortcut that maps
Miaoda user_id ↔ Feishu open platform IDs (open_id / union_id / Feishu
user_id). It does one thing — conversion — with no local mapping table,
caching, permission pre-check, or direction guessing.
- --convert-type enum → server id_convert_type (10/11/20/21/40)
- --ids: csv / @file / stdin, 1-100 per call, not de-duped, input order
- reconstructs data.missed by diffing input positions against returned
source_ids (server silently drops unresolved IDs), keyed by 0-based index
- meta counters (total/hit_count/missed_count) via pointer fields on
output.Meta so an explicit missed_count: 0 survives omitempty
* test(apps): address review feedback on +user-id-convert
- reject empty --ids CSV entries (e.g. "a,,b") with a typed validation
error instead of silently dropping them, since a dropped entry shifts
every later result's 0-based index and breaks the position-keyed
items/missed contract; add an interior-empty-element test
- reuse common.GetSlice / common.GetString for response projection
(house convention) instead of local asSlice/asString helpers
- requireConvertValidation now asserts CategoryValidation +
SubtypeInvalidArgument via errs.ProblemOf, keeping ValidationError.Param
- table-drive TestResolveConvertType over all five directions so every
--convert-type → id_convert_type mapping (10/11/20/21/40) is protected
* fix(apps): split newline-delimited --ids for +user-id-convert @file/stdin
@file and - (stdin) input arrives verbatim from the framework as
one-ID-per-line text, but parseConvertIDs only split on commas, so such a
block was sent as a single malformed request ID. Treat a newline as
equivalent to a comma, tolerating a file's trailing newline while still
rejecting interior empty entries so position-keyed result indices stay
aligned. Add @file and stdin tests asserting the request body's ids are
split into discrete IDs.
* fix(apps): stringify numeric JSON IDs in +user-id-convert results
Responses decode with json.Number (client.ParseJSONResponse uses
dec.UseNumber()), so a server that emits source_id/target_id as bare
numbers — plausible for the numeric Miaoda user_id form — was silently
coerced to "" by buildConvertResult's strict string assertion: the
source_id got dropped (false not_found) and the target_id blanked
(false success).
Add common.GetStringLoose, which stringifies string/json.Number/int64/
float64 via literal text (large integer IDs keep full precision, never
routed through a lossy float64), and use it for both id reads. Cover it
with a package-level table test plus an end-to-end regression asserting a
numeric-JSON response yields intact, non-blank ids and no false miss.
Also exercise resolveConvertType's non-empty "not a valid direction"
branch directly, since the runner's enum gate preempts it in normal flow.
* test(common): tighten GetStringLoose numeric coverage
Add an int-branch case (was only covering int64) and swap the float64
fixture from 42 — which no formatter would render in exponent form — to
1e-7, whose fixed-point rendering "0.0000001" fails under the 'g' verb.
This turns the "no scientific notation" case into a real guard for the
'f' verb choice, per CodeRabbit review on
|
||
|
|
158d15b3fd |
feat: add apps database sync shortcuts for Base-to-database import (#2251)
* feat: add apps database sync shortcuts Add Base-to-database sync shortcuts for preview, create, list, get, enable, disable, update, and delete flows. Cover OpenAPI request contracts, typed sync error classification, dry-run E2E coverage, and lark-apps skill guidance. Co-authored-by: TRAE CLI <noreply@bytedance.com> * fix(apps): send db-sync task_id and config in request body The enable/disable/delete/update sync commands placed task_id (and update's config) in query params, but the OpenAPI contract binds these fields via api.json (request body). BOE testing returned "field validation failed" (99992402) because the body was empty. Move task_id to the request body for enable/disable/delete, and move both task_id and config to the body for update. Dry-run previews now render these under body, and unit tests pin the body binding so a regression to query params fails. * fix(apps): use POST for db-sync-delete action endpoint The delete command issued an HTTP DELETE to db/sync_del, but the action-style endpoint is registered as POST (like sync_create and sync_disable). The method mismatch made the gateway return a plaintext 404, surfacing as "API returned a non-object JSON response". Switch the request and dry-run preview to POST, and pin the method in the delete unit tests so a regression to DELETE fails. * test: pin db-sync update base_url as optional contract * test: pin db-sync update omits base_url without silent default * docs(skills): clarify db-sync source.base_url create-required update-optional contract * fix(apps): send db-sync env in request body not query params The +db-sync-create and +db-sync-update endpoints read env from the request body (peer of config/preview/task_id), not the query string. Placing env in query params left the body env empty, so the server treated every request as online and rejected DDL operations (code 500002776: forbid ddl/dcl operation in online env), making it impossible to create/update sync tasks against a dev environment. Move env into the request body via a new dbEnvBody helper that mirrors dbEnvParams' omit-empty contract, so unset env still lets the server auto-select the branch. Pin the contract in unit and e2e dry-run tests by asserting body.env and that env is absent from query params. * test: align db-sync operate/delete e2e with request-body contract The enable/disable/delete dry-run e2e still asserted the pre-migration wire shape: delete on DELETE and task_id in query params. The shortcuts now POST these actions with task_id in the request body (commits moving task_id and the delete verb), so the stale assertions failed against a current binary. Assert POST + body.task_id and that task_id is absent from query params, pinning the same body-over-query contract the env fix established. * fix(apps): improve db-sync create ergonomics and error guidance Refine +db-sync-create/update validation, error hints, and docs so AI agents recover from common Base-to-database sync failures without guessing: - source.table.name: document that a user-named table must be set, name takes precedence over the base_url ?table= token; fix test fixtures that used a fictional source.table.url instead of source.base_url. - Preflight source table locate: reject create locally when base_url has no ?table= and source.table.name is empty, pointing at base +table-list. - Online DDL ban: attach a precise hint for code 500002776 + subcode k_dl_4000001 telling multi-env apps to create tables on --environment dev. - Missing record-id column: extend the 500002783 hint to add a unique text column via +db-execute before retrying. - Optional field_maps on create: allow omitted or empty field_maps so the server auto-matches and creates the task; keep update requiring an enabled mapping and still reject an all-disabled array. - Environment default: db-sync commands use online when --environment is omitted; align help text, comments, and skill docs. * fix(apps): migrate db-sync error codes to the 4xx client-error range The backend moved the seven db-sync error codes from the 5000027xx server-error range to the 4000024xx client-input range to reflect that they are client-input errors. Mirror the new codes in the CLI so error classification and recovery hints keep matching: - 500002783 -> 400002477 (mapping invalid) - 500002784 -> 400002478 (target schema mismatch) - 500002785 -> 400002479 (operation not allowed) - 500002786 -> 400002480 (task not found) - 500002787 -> 400002481 (invalid task id) - 500002788 -> 400002482 (source table not found) - 500002789 -> 400002483 (target table not found) Category, subtype, hint text, and behavior are unchanged; 500002776 (online DDL ban) is untouched. * fix(apps): tighten db-sync preview validation and pretty output Address review follow-ups on the db-sync shortcuts: - +db-sync-get pretty output no longer prints <nil> for a missing schema_only nor Go map syntax for statistics; render a bare bool and deterministic key=value pairs instead. - Reject a non-array field_maps in +db-sync-create --preview as well as commit, so the malformed shape is caught locally rather than forwarded to the backend. - Clarify in lark-apps-db.md that +db-sync-create --preview needs no confirmation and only a real create requires --yes. - Harden the db-sync dry-run validation tests to assert exit code 2 and the structured stderr envelope (type/subtype/param), and add coverage for the preview non-array field_maps rejection and batch pretty output. * fix(apps): guard db-sync preview output and neutralize update hint Address the next db-sync review round: - +db-sync-create --preview --output no longer writes a "null" file and exits success when the response omits data.config; project config into a typed object and return internal/invalid_response without writing. - Make the 400002482 code hint command-neutral so +db-sync-update is not steered into a create-only recovery path that risks duplicate tasks. - lark-apps-db.md: carry --environment on the update lifecycle examples and split failure recovery by streaming (can update) vs batch (cannot update; recreate instead), removing the batch/update contradiction. --------- Co-authored-by: TRAE CLI <noreply@bytedance.com> |
||
|
|
79eb16c50b |
feat(affordance): support domain skill lists (#2291)
Co-authored-by: liangshuo-1 <266696938+liangshuo-1@users.noreply.github.com> |
||
|
|
82e628bf79 | fix(drive): harden export and push failure recovery (#2279) | ||
|
|
5b734238d7 |
feat: report upload file events (#2093)
* feat: report upload file events * test(drive): skip import workflow without tenant token * docs: document upload report helpers * docs: improve function documentation coverage * docs: complete incremental function documentation * docs: complete function documentation coverage * fix: report every upload file event * refactor: move file event reporting to internal package * fix: harden upload file event reporting * fix: omit upload mode from file event reports * test: fix workbook import dry-run token assertion |
||
|
|
a6f3e635d4 |
feat(docs): add local authoring and resource workflows (#1921)
* feat(docs): add local authoring and resource workflows Add docs +script workflows for isolated draft initialization and tolerant XML/Markdown profiling. Support local and remote document resources across create and update flows with safe, bounded-concurrency uploads, binding verification, and cleanup. Synchronize shared credential-source selection during concurrent uploads, refresh lark-doc guidance, and expand unit, dry-run, and live E2E coverage. * docs(lark-doc): clarify genre reference paths * fix(docs): address PR validation feedback * docs(lark-doc): clarify remote image handling * feat: streamline docs draft workflow * fix(docs): clarify script input and resource cleanup * fix(docs): align script dry-run test with auth flow * fix(docs): authenticate local script e2e test * fix(docs): refine script diagnostics and image preflight * fix(docs): align draft workspace cleanup with VFS * fix(docs): route workspace cleanup through FileIO * docs(lark-doc): simplify profile check guidance |
||
|
|
0d6f2c65d7 | fix(im): harden resource downloads with validated ranged streams (#2223) | ||
|
|
7c4f6c023f |
fix(base): improve field creation and query guidance (#2114)
* fix(base): improve field creation and query guidance
1. Document batch field creation in shortcut help and the delivered Base skill.
2. Choose field types from stored values instead of business-purpose names.
3. Add generic common filter values to the data-query quick guide with contract tests.
说明:
- Combines the accepted fixes for base_table_096, base_table_028, and base_table_087;
MR 1275 contributes round 4 only.
```ai-signature
改动范围: Base field-create 帮助与 Skill 指南、data-query 快速指南,以及对应的 shortcuts/base 契约测试
思考过程: 保留三个实验的最终通用规则,合并 public main 上新增的字段读回提示,并排除没有 benchmark 支撑的 MR 1275 round6
改动原因: 让代理发现批量字段接口、按存储值选择字段类型,并用常见通用形状构造 data-query 过滤条件
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: a53fdb6b6b82d74e4deff5e6d32591ec897cd2dc6ad662885c961a27e67d4666
* test(base): strengthen guidance contracts
1. Assert every common filter fragment introduced by the data-query quick guide.
2. Keep the field-create argument table compliant with markdown table spacing.
```ai-signature
改动范围: data-query 指南契约测试与 field-create Markdown 表格后的空行
思考过程: 逐条核对 CodeRabbit 建议,只补会防止新增指南片段回退的断言和确定性的 MD058 格式问题,不改生产提示语义
改动原因: 关闭 PR 2114 的两条有效自动审查意见并保持变更可回归
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: 81096f474001f2c9c59af48ee64150f205101710ebcf3b909ab9d300a019f46f
* fix(base): generalize data-query filter guidance
1. Replace the date-and-status scenario template with reusable Condition.value shape rules.
2. Update the contract test to require relative-date guidance and reject evaluation-shaped placehold
ers.
```ai-signature
改动范围: lark-base data-query quick guide 与对应 shortcuts/base 契约测试
思考过程: 保留 select、datetime、empty 的通用 value shape,删除日期字段和状态字段组合模板,避免将 base_table_087 的解题路径固化到公共指南
改动原因: benchmark 显示当前文案能引导目标题,但组合示例与测试过度贴合单题,需要收敛为跨场景可复用的不变量
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: 7b6916f05dccf6489dce65610fe757f7b346bcd0f8f5500cfbfb1f30c60471f3
* fix(base): generalize creation guidance
* fix(base): report partial field-create results
* fix(base): preserve partial field-create recovery metadata
* fix(base): separate partial field recovery
* perf(base): 缩短字段批量创建的空等
1. 将固定 1 秒批次等待改为 500ms 最小请求起点间隔,并让请求耗时抵扣等待
2. 新增节流计算契约测试,覆盖首次请求、快速响应和慢响应
3. 同输入 150 字段 A/B 从 269.64s 降至 118.80s,且两侧均创建 150/150
说明:
- 保持同表写入串行和 partial failure 输出不变
```ai-signature
改动范围: shortcuts/base/field_ops.go 与 shortcuts/base/base_execute_test.go,仅调整 field-create 数组批次的串行节流计算和回归测试
思考过程: 保留同表串行写入,以 500ms 作为请求起点最小间隔,并把请求耗时计入间隔,避免固定空等同时降低写冲突风险
改动原因: PR 引导 Agent 使用数组批量创建后触发既有每项固定 1 秒等待,导致 150 字段用例产生约 149 秒可归因耗时回退
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: 69b888d362d2f484c4ce6ad050bdbfe2de7368948eb79ba516bcaa6806ec9107
* fix(base): 收紧不支持字段行为的终止边界
1. 派生、自动、同步或回填行为只使用已记录能力,无法实现时禁止探测、占位或虚假完成
2. 删除 data-query 契约测试对旧题模板占位符的反向黑名单,只保留原子规则和真实 case 污染检查
3. field-create 指引替换前后均为 36 个英文词,不扩大该帮助项的词数
```ai-signature
改动范围: shortcuts/base/field_create.go、base_shortcuts_test.go 与 data_query_guide_contract_test.go,仅收口通用终止规则和测试泛化
思考过程: 采纳 review 中可独立闭环的两点,不增加翻译专用规则,不修改运行时能力;用等词数替换避免帮助上下文继续增长
改动原因: 当前规则能阻止按业务名猜字段类型,却仍允许退化成普通文本占位;同时测试记住旧题模板会阻碍未来合理示例
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: 759b7f4044c6381b963c8ea299b70967e634ab9d43b6ebfbe94ef38bb69ba46a
* perf(base): 压缩字段批量创建的评测开销
1. 批量成功与部分失败仅返回字段 id/name/type,保留恢复所需身份并减少大响应上下文
2. 引导数组在调用方超时范围内一次提交,并为生成的大数组推荐 @file 或 argv-safe 调用
3. 字段列表默认页大小提升到 API 上限 200,避免百字段以上场景的帮助查询与重试
说明:
- 同口径 case032:raw token 432292→428304,weighted token 126408→117761,耗时 272675ms→235022ms,两侧均读回 154 字段
```ai-signature
改动范围: Base field-create 批量输出、帮助提示、field-list 默认分页及对应契约测试与 Skill 返回说明
思考过程: 从同口径 trace 定位固定分块、大字段对象回传、100 条分页和 shell 双重转义四个确定性开销,保持单字段与部分失败恢复语义不变并逐项用测试锁定
改动原因: PR 引导数组批量创建后虽降低耗时,但多回合大输出会推高 raw token;需要在不牺牲正确率和恢复信息的前提下同时压缩 token 与耗时
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: 8a2bd2d79c9abdb1e36ae45822dd04b2a3384498a1dc268cffcd47cff00d94ed
* perf(base): 收敛字段批量创建的上下文
1. 大数组成功路径推荐保留摘要的 --jq 投影,失败路径仍原样保留部分失败明细
2. 为一个或多个简单 text 字段提供 help fast path,并让 next_step:done 终止默认回读
3. 补充 Skill、帮助与执行结果契约测试,锁定有界输出和可恢复失败语义
说明:
- 最新 main 同题 A/B:两侧均回读 154 字段,raw token 下降 5.9%,耗时下降 19.3%,峰值上下文下降 13.3%,工具调用下降 20%
```ai-signature
改动范围: Base field-create 帮助、简单字段成功提示、lark-base Skill 路由与对应契约测试
思考过程: 从最终 A/B trace 分别定位批量成功展开 150 项、简单 text 读取冗余指南和成功后整表回读三类可控上下文开销,用成功摘要与失败全量明细分流来保留恢复能力
改动原因: 继续优化 PR 2114 的 token 和耗时,同时要求任何回退不能归因到 PR;需要让大批量成功路径有界且不削弱正确性或部分失败恢复
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: 626b288a7f5444dfecb872e6cd29d4fe0788404f5001dcb47aac64e2d55d9b5a
* fix(base): 恢复批量字段输出与分页默认契约
1. 批量创建完整成功时保留服务端字段元数据,部分失败仍返回精简 identity
2. 将 +field-list 默认页大小恢复为 100,继续支持显式 --limit 200
3. 补充回归测试与字段创建文档,保留 --jq 有界输出指导
说明:
- 定向、Base 全量、race、仓库单测、构建、vet 与 lint 均通过
```ai-signature
改动范围: Base 批量字段创建成功输出、字段列表默认分页、对应测试与文档
思考过程: 先用契约测试复现完整字段元数据丢失和默认分页翻倍,再只恢复主干既有成功输出与默认值,同时锁定部分失败精简输出不变
改动原因: 移除可归因到 PR 的兼容性和 token 回退,并保留显式 jq 投影、节流、快速路径及部分失败恢复带来的通用收益
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: 6351ed9d228611e3b6f5bc30faf278835b463e07f4eb020f225abd41e264399c
* fix(base): present batch field errors before partial output
1. Project the typed field-create error through Runtime.PresentError before copying result fields
2. Read Error, ProblemOf, and permission extensions from the presented clone
3. Cover visible scoped authorization and concealed recovery without fabricating missing_scopes
说明:
- Targeted, Base, full race, build, vet, format, lint, and module checks pass
```ai-signature
改动范围: Base 批量字段创建部分失败的错误呈现,以及 visible 和 concealed 恢复契约测试
思考过程: 先在最新 main 合并树上复现无 scope 授权提示和隐藏命令泄露,再复用兄弟批量命令的 PresentError 边界,仅替换 payload 复制时的错误来源
改动原因: OutPartialFailure 不会再次呈现根错误,必须在复制 typed error 字段前应用命令 scope 与发行隐藏策略
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: deee600dc8d4bb889629895178c1f217ba7762fbd5b3163da3b9d621c8585ac0
* fix(base): allow recovery before retrying failed field writes
1. Clarify that retryable gates unchanged automatic retries, not corrected resubmissions
2. Classify Base error 1254291 as a retryable conflict with canonical wait guidance
3. Cover authorization recovery, write conflicts, and reference contract consistency
```ai-signature
改动范围: internal/errclass/codemeta_base.go、shortcuts/base/field_ops.go、对应 Base 回归测试与 field-create 参考文档
思考过程: 将 retryable 限定为同一请求原样自动重试资格,保留授权或输入修正后重新提交,并复用现有 conflict 恢复提示
改动原因: 部分失败顶层提示会与权限恢复 hint 冲突,且 1254291 未分类导致等待重试规则无法由结构化错误驱动
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: 65cd95f24968c5e0b0c43cf858ed787eabb6d9d63b3d5199a294bd284816c35e
* fix(base): preserve partial field recovery contracts
1. Preserve presented typed-error extensions without allowing them to overwrite batch ledger fields
2. Align field creation guidance with command-specific name semantics and caller-timeout recovery
3. Cover security challenges, extension collisions, and storage-type selection with regression tests
```ai-signature
改动范围: shortcuts/base 的 field-create 部分失败输出、命令提示、Base Skill 写入规则、field-create reference 与对应回归测试
思考过程: 复用 Runtime.PresentError 后 concrete typed error 的 JSON wire shape 作为扩展字段单源;对批次账本自有键统一生成无冲突 error_ 别名,并只收敛已证实的同名、fast path 与 timeout 契约矛盾
改动原因: 部分失败会丢失 challenge_url 等恢复字段,自定义 typed error 还可覆盖 status/index/error 导致错误账本;过度绝对的字段类型、同名和超时文案也会形成可归因正确率回退
Break Change: 否
```
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
AI-SHA256: 02377560f14202ea652f530389ac102647189923e45548337814ec3871f5a4de
---------
Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
|
||
|
|
6402080328 |
fix(apps): detect the no-database failure by code or message (#2217)
* fix(apps): detect the no-database failure by code or message The recovery flow for "db command against an app that has no database" keyed on one business code (500002759). The server has since renumbered that case to 400002465, which silently disabled the flow: users now see the raw internal message about workspace / app-id mapping and lose the cloud-development recovery steps entirely. Nothing catches the regression. There is no compile error, the unit tests compare against the same constant they set, and the dry-run E2E does not exercise a real response — the failure only shows up against a server that has already renumbered. Detect on code OR message instead. Both known codes are kept, plus narrow lowercase markers of the server's internal wording. The two channels have opposite failure modes: a code is precise but gets renumbered, a message survives renumbering but breaks on rewording or localization. Requiring either to match means one channel changing degrades nothing, and only a simultaneous change of both regresses. Markers stay deliberately narrow. "no db branch" in particular must not also swallow env-pull's "invalid db branch" case, which needs its own hint; a comment records that widening them requires a test proving the neighbours still pass through. Classification and the cause chain are untouched: the helper still mutates the problem in place and returns the same error value. * test(apps): assert the full typed-error contract in no-database cases Review feedback: the new subtests checked only Message and Hint, so a change that reclassified the failure — or replaced the error value and dropped the cause chain — would still have passed. Each case now asserts Category, Subtype and Code are untouched by the rewrite, and that the helper returns the same error value. Inputs use a concrete subtype rather than Unknown, so a clobbered classification is actually observable. One new case wraps a cause and asserts errors.Is still finds it through the rewrite. Also covers the predicate's defensive nil guard, which withAppsHint cannot reach on its own (ProblemOf returns ok=false for untyped errors), closing the two uncovered lines the coverage report flagged. Both withAppsHint and isAppNoDatabaseError are now at 100%. * fix(errclass): classify the db-domain business codes Three codes reaching the Apps db commands were absent from the Spark table, so BuildAPIError fell through to the CategoryAPI + SubtypeUnknown catch-all and the envelope carried no usable classification. "App has no database yet" registers as Validation / FailedPrecondition: the app resolves fine and the request is well-formed, but a prerequisite the caller must create first is missing, so retrying unchanged can never succeed. This moves its exit code from 1 to 2 — "fix the state" rather than "the call failed" — and a test pins that so a future reclassification has to be deliberate. Two codes cover it because the server renumbered the case into the 4xx band; the legacy one stays for older servers. "Table does not exist" registers as API / NotFound, an ordinary missing-resource lookup with no exit-code change. SubtypeNotFound has no APIHint default, which matters here: the Apps layer fills its command-scoped hint only when the classifier left Hint empty, so a context-free default would displace the more actionable one. A test guards that too. |
||
|
|
be2a96f490 |
feat(sheets): harden error prescriptions, batch updates, and read workflows
Aggregate the sheets work from feat/lark-sheets-develop: - Improve validation errors with schema hints, aggregated issues, enum guidance, and prescriptive flag/style-field messages. - Harden +batch-update input contracts, key normalization, style vocabulary handling, and resource-budget checks. - Add read offload and truncation handling for cells, csv, and table-get, with typed output-path errors and safer jq/output-path semantics. - Correct freeze semantics by emitting full-state freeze/unfreeze operations and adding --rows/--cols for +dim-freeze. - Improve +styles-put and shared --styles parsing for styles, merges, row/column sizing, freeze, and sheet-prefixed range validation. - Fix dim-insert inherit-style mapping, table-get date/time handling, table-put style anchors, and CSV path-shaped input guards. - Update lark-sheets skill docs, scripts, tests, and generated flag data. Tested with: - go test ./shortcuts/common ./shortcuts/sheets/... - go test ./shortcuts/... ./internal/... - python3 -m py_compile skills/lark-sheets/scripts/*.py |
||
|
|
164d3ccd27 |
fix(registry): describe the attendance and mindnotes domains (#2210)
Both are registered, reachable business domains — `lark-cli attendance user_tasks query` and `lark-cli mindnotes nodes create` run, and both appear in `auth login --domain` — but neither had an entry in service_descriptions.json. GetServiceTitle/GetServiceDescription returned "", so buildDomainMeta fell back to the typed service spec, which carries one string for both languages. The result was visible in `--help`: mindnotes rendered its Chinese description in the English domain list, and attendance rendered "attendance record query", a lowercase fragment shown in both locales. Both keep their own scope namespaces (attendance:task:readonly, mindnote:node:create/read) and stay independent auth domains, so no auth_domain is set. whiteboard remains the only domain folded into docs. TestGetDomainMetadata_HasTitleAndDescription could not catch this: it asserts on buildDomainMeta's output, which the fallback had already made non-empty. The new reconciliation test walks EmbeddedServicesTyped plus AllShortcuts and asserts both languages resolve from the config itself, before any fallback. EmbeddedServicesTyped is the overlay-free parse, so the test does not depend on what remote_meta.json happens to hold on the machine — a domain that only ever arrives via remote overlay stays out of its reach. |
||
|
|
9f713e60f7 |
fix(auth): harden token refresh and concurrency handling (#2135)
1. Improve retry behavior for refresh failures. 2. Improve authentication token refresh reliability during concurrent activity. - Add a token-storage writability probe before refresh. - Add generation-safe token updates. - Add lock for all set/update/delete token operation. |
||
|
|
9759167542 |
fix(im): unpin search identity after bot support landed (#2208)
#2194 extended `im +messages-search` to `AuthTypes: {user, bot}` but left the affordance example and the skill reference asserting user-only, so the dual-identity guard added by #2199 fails on main. |
||
|
|
fcdef499bb | feat(event): compile the catalog and harden the consume pipeline (#2142) | ||
|
|
43fe6c8787 |
fix: surface retry metadata for TAT rate limits (#2200)
Co-authored-by: liangshuo-1 <266696938+liangshuo-1@users.noreply.github.com> |
||
|
|
960bdf6d71 | feat: migrate application and IM guidance to affordance (#2199) | ||
|
|
47c9741ce0 | feat: profile selection from environment with source-aware errors (#2198) | ||
|
|
09feefe96b | fix: make agent recovery and concealment reliable (#2189) | ||
|
|
8e884928f6 |
feat: add Base table copy shortcuts (#2019)
* feat: add Base table copy shortcuts * test: cover Base table copy edge cases * fix: preserve table copy task state * fix: align table copy recovery with API errors * fix: preserve table copy auth recovery * test: verify copied table schema --------- Co-authored-by: fongwave <272393974+fongwave@users.noreply.github.com> |
||
|
|
ebdeda854d | feat(extension): present restricted commands as absent and trim skills (#1837) | ||
|
|
2a1613484a |
feat: add framework flag aliases and unified IM pagination (#2146)
* feat: add framework flag aliases and unified IM pagination Introduce declarative exact-name flag aliases at the shortcut framework boundary while keeping semantic compatibility domain-owned. Add a shared, format-aware IM pagination pipeline with consistent flags, metadata, safety bounds, resumable cursors, and request throttling. * fix: align alias attribution and pagination contracts * fix: align alias contracts and documentation * test: remove environment-dependent contact bot e2e * test: restore contact bot e2e * docs: reduce IM pagination guidance noise --------- Co-authored-by: liangshuo-1 <266696938+liangshuo-1@users.noreply.github.com> |
||
|
|
40a0a9de66 | feat(enhancement): centralize HTTP transport policies (#2021) | ||
|
|
cfe76ad56a |
ci: add protected public domain allowlists (#2111)
Co-authored-by: HanShaoshuai-k <268785735+HanShaoshuai-k@users.noreply.github.com> |
||
|
|
4a16139348 |
fix(base): resolve Base URL block types accurately (#2099)
* fix: resolve Base URL block types accurately * fix: resolve Base block selection from Wiki URLs * fix(base): guide resolved folder and docx blocks * fix(base): avoid field fallback for untyped URL blocks * docs(base): specify URL example fence language * test(base): cover unmatched URL block resolution |
||
|
|
c167163d70 | feat: propagate invocation metadata (#2097) | ||
|
|
e7d5ecdd01 |
feat: add risk-control protection (#1910)
1. Add baseline safe protection for Feishu/Lark API endpoints. 2. Add lark-cli config risk-control on|off|default command for workspace-level safety protection control. |
||
|
|
b8f56dbc0b | feat(apps): support absolute and relative upload paths (#2005) | ||
|
|
4c1a92caa6 |
refactor: converge success output through a single Emitter that owns the write (#1899)
* refactor: add output emitter contract and differential harness Introduce a leaf Emitter in internal/output that composes the existing output primitives (content-safety scan, envelope, jq, format rendering, notice) behind a single command-scoped port. The emitter is unwired: no production caller is migrated, so CLI output stays byte-for-byte unchanged. A differential test harness drives the real legacy entry points (RuntimeContext.Out/OutRaw/OutFormat/..., WriteSuccessEnvelope and the pagination formatter) and asserts byte-identical stdout/stderr plus typed errors, locking behavior before later slices migrate callers. * refactor: tighten emitter API and cover pagination with real tests - split Emitter.Success/PartialFailure and drop EmitOptions.OK so a missing ok flag can no longer silently emit ok:false - give StreamPage its own StreamOptions (format + pretty) instead of reusing EmitOptions, making "jq needs aggregation" a compile-time fact - pin the Emitter jq-error contract (returns error, writes no stderr); the caller adapter re-emits the legacy stderr line on migration - add in-package tests driving the real apiPaginate/servicePaginate over a mock transport: multi-page aggregation, empty-result fallback, MarkRaw handling, and the business-error raw-response red line * test: use standard TestFactory harness for pagination tests Replace the hand-rolled RoundTripper + APIClient construction in the apiPaginate/servicePaginate tests with cmdutil.TestFactory and its httpmock.Registry, and isolate LARKSUITE_CLI_CONFIG_DIR to t.TempDir(), matching the repo's standard HTTP-mocked test convention. Assertions and coverage (multi-page aggregation, empty-result fallback, MarkRaw, and the business-error raw-response red line) are unchanged. * refactor: route success output through the single Emitter port Migrate the success-output surfaces onto internal/output's Emitter, byte-for-byte identical (proven by frozen golden diffs and the real paginate/HandleResponse tests): - RuntimeContext.Out/OutRaw/OutFormat/OutFormatRaw/OutPartialFailure now build an Emitter and call Success/PartialFailure; emit and outFormat are removed. An adapter maps the returned error back to the legacy outputErrOnce / jq-error stderr / exit-code behavior. - WriteSuccessEnvelope degrades to a thin Emitter.Success delegate; its 8 callers are unchanged. - apiPaginate/servicePaginate stream pages via Emitter.StreamPage; the aggregate and business-error raw-response branches are untouched. - HandleResponse routes its non-JSON structured-response branch through Emitter.Success. Frozen golden fixtures replace the runtime legacy oracles so the differential harness cannot go self-referential after migration. * fix: keep _notice on struct payloads in Emitter's unknown-format fallback printLegacyDataJSON now normalizes via toGeneric first (matching FormatValue), so a struct / named-map payload retains its injected _notice on the unknown-format -> JSON fallback rather than dropping it silently. Add a regression test that fails against the pre-fix path. * refactor: make the Emitter own write failures and stop mutating inputs Route every Emitter stdout path through a render-to-buffer-then-copy helper so a marshal/render failure leaves stdout empty and surfaces a typed internal error (with cause), and a stdout write failure is propagated instead of silently swallowed. Leaf writers gain error-returning Write* cores; the legacy Print*/FormatValue wrappers keep their exact behavior for unmigrated callers. - handleEmitterError now captures every error, not only the jq/safety branches; flip OutRaw's write-error test to assert propagation. - Clone the map before injecting _notice so a caller's payload is never mutated and an existing _notice is never overwritten. - Preserve jq's own typed error (validation/api) on a bad expression or runtime failure; only wrap genuine stdout write failures. - Split tests: normative emitter_contract_test.go vs frozen emitter_legacy_compat_test.go (base SHA recorded, self-update env vars removed). * fix: satisfy license-header and forbidigo lint on the emitter changes - Move the base-SHA note below the copyright header in the renamed legacy-compat test so the license-header check sees a valid header at the top. - Route the leaf wrappers' marshal/format stderr messages through a single legacyStderrf helper (one //nolint:forbidigo) instead of bare os.Stderr, preserving exact legacy behavior for unmigrated direct callers while passing forbidigo; drop the now-unused os imports. * fix: stop legacy CSV wrappers reporting write failures to stderr Align FormatAsCSV/FormatAsCSVPaginated and FormatValue/FormatPage's CSV branch with the other leaf wrappers: report only marshal failures, swallow write failures. Previously they emitted a 'csv write error' for the (empty) line and the JSON-fallback write failures that the pre-refactor code ignored, and mislabeled a JSON write failure as a CSV one. Failure-path only; success output is unchanged (golden double-diff still byte-for-byte). |
||
|
|
577ff035c3 | fix: allow jq examples in quality gate dry-runs | ||
|
|
d8fb368ce4 | test: isolate unit tests from user state (#1883) | ||
|
|
9dd355a52d | test: synchronize temporary Git maintenance (#1946) | ||
|
|
21cff2e2dd | fix: reduce public content credential fixture false positives | ||
|
|
baf6050f8e | feat(apps): add role management shortcuts (#1881) | ||
|
|
37d490a198 |
fix: unify dry-run output contract (#1870)
* fix: unify dry-run output contract
* fix: address dry-run review feedback
* fix(dryrun): tighten preview contract and unify data shape
- transcribe HTTP method verbatim in previews (HEAD/OPTIONS were
reported as GET); reject an empty method in api with a typed error
- unify the dry-run data payload across api/service/shortcut paths:
{api, context?: {app_id, user_open_id}}; drop data.as — the envelope
top-level identity is the single identity source
- mark pretty dry-run stdout with '# dry-run: request not sent' so logs
that drop stderr still show it was a preview
- extract the shared preview builder, collapse PrintDryRunWithFile's
loose params into FileUploadMeta, and fail loudly on nil previews
- revert description-marker identity parsing: stale prose must not
override corrected accessTokens (blocks legal user calls on
images.create); identity gating keys off accessTokens only
- pin the new contracts with tests: verbatim method, three-way context
parity, nil-preview error, empty-context omission, marker line
* docs(agents): add typed-data, faithful-transcription, and contract-test conventions
- typed struct at the boundary over map[string]interface{} threading;
distinct types where values could swap silently (internal/meta.Token)
- transcribe input verbatim in previews/transformations; reject
unhonorable flag combinations with typed errors instead of silently
substituting behavior
- contract tests must fail when the implementation is reverted
* test: migrate dry-run tests grown on main to the envelope format
main gained raw-format dry-run readers while the PR was in flight
(wiki drive export #1802, drive list comments #1845, slash commands,
sheets history, docs fetch, mail draft-send/triage, vc meeting events).
Migrate them to the envelope accessors (clie2e.DryRunGet / data-wrapped
decoders) and drop the now-redundant DryRunData extractions in files
unified on DryRunGet.
---------
Co-authored-by: guokexin.02 <264159873+Tantanz20020918@users.noreply.github.com>
|
||
|
|
e79d49e7e4 |
Merge lark sheets development branch (#1833)
* feat(sheets): support font_family in cell styles (#1549) Add a font_family field to cell_styles so a cell's font name can be set and read back through every style entry point: - +cells-set (--cells JSON) and +cells-set-style / +cells-batch-set-style gain a font_family field / --font-family flat flag - +workbook-create / +table-put --styles accept font_family in cell_styles - +cells-get returns font_family helpers.go buildCellStyleFromFlags reads the --font-family flag; lark_sheet_workbook.go allows font_family in the --styles cell_styles whitelist; data/ + skills/ are synced from sheet-skill-spec. * docs(sheets): inline editing rules into SKILL.md and clarify flag descriptions - Move cross-cutting editing rules and execution notes into the root SKILL.md and drop the now-redundant core-operations reference - Clarify flag descriptions: offset must be explicit inside +batch-update, range prefixes written bare (no quotes), chart requires a dim index, untyped --values lose date/number types, ungroup level semantics - Sync the corresponding reference docs * feat(sheets): add --type bitable to +sheet-create for creating bitable sub-sheets (#1520) * perf(sheets): cap fan-out cell-matrix materialization to prevent OOM (#1578) * perf(sheets): cap fan-out cell-matrix materialization to prevent OOM The +cells-set-style / +dropdown-set / +cells-batch-set-style / +dropdown-update shortcuts expand a single A1 range into a rows×cols matrix of per-cell maps client-side (the backing set_cell_range tool takes an explicit cells matrix). rangeDimensions() had no upper bound, so a tiny input like "A1:Z100000" balloons into ~2.6M heap maps (~900MB, doubled again by json.Marshal) and can OOM the process before the request is even sent. Add a 50000-cell safety cap (checkStampMatrixBudget) gating every fan-out materialization point, matching the documented but never-wired --max-cells default. Oversized ranges now fail fast with a clear validation error instead of allocating. Also preallocate the per-op slices now that the range count is known up front. Adds benchmarks + a boundary test as regression guards. * perf(sheets): cap table-put/batch fan-out materialization (siblings of the cell-matrix cap) The single-range fan-out cap (maxStampMatrixCells) left three sibling ingress paths uncapped, each able to materialize an unbounded matrix or op set in memory before the request leaves: - +table-put / +workbook-create --sheets/--values: buildSheetMatrix builds the whole rows×cols matrix before slicing it into per-write batches; tablePutMaxCellsPerWrite only bounds the batch size, not the total input. Add tablePayload.checkCellBudget (1M-cell guardrail), enforced in validate() and in buildValuesPayload (the --values path bypasses validate()). - batch fan-out (+cells-batch-set-style / +dropdown-update): per-range checkStampMatrixBudget can't stop many ranges from summing past the cap. Add an aggregate cell budget (checkBatchStampBudget) and a shared maxBatchRanges (100) count cap in validateDropdownRanges — covering all fan-out commands and replacing the now-redundant +dropdown-delete count check. - +batch-update: cap --operations at maxBatchOperations (100) in translateBatchOperations. Adds boundary regression tests for each cap. go vet + gofmt clean; full shortcuts/sheets + backward suites green. * test(sheets): measure table-put matrix materialization cost Add BenchmarkBuildSheetMatrix_* and TestTablePutMatrixPeakMemory mirroring the fan-out probes. Confirms the +table-put/+workbook-create ingress has the same OOM profile as the single-range stamp: 2.6M cells → ~917 MB / 5.3M allocs (+875 MB resident heap) materialized before the first write — now rejected up front by checkCellBudget. * feat(pivot): lark-sheets pivot reference 补 +pivot-list info 说明与落点覆盖校验 +pivot-list 返回 info(page_range/content_range/error_state 等): 1) 判断目标单元格在透视表内(改配置 +pivot-update)还是区域外(改值 +cells-set); 2) 透视表展开后会覆盖已有数据,落点强烈优先默认自动新建子表; 3) 创建后用 info.error_state / content_range 校验有没有覆盖/冲突。 * feat(sheets): add +formula-verify shortcut for verify_formula tool Wraps the new verify_formula read tool in a CLI shortcut so AI agents can run write-then-zero-error verification end-to-end: lark-cli sheets +formula-verify --url <url> Scans formulas + cell error states across one or more sub-sheets and returns a JSON status report (success / errors_found / partial). Aggregates all 7 Excel error categories (#REF! / #DIV/0! / #VALUE! / #NAME? / #NULL! / #NUM! / #N/A) plus compile failures into one envelope; the tool always reports every error in the scan window — callers needing a subset filter the returned error_summary client-side. The internal scan cap is hidden from callers; when it trips the response sets has_more=true and includes a warning_message asking the caller to narrow --range / split --sheet-id and continue. Flags follow the lark-sheets convention: - --url / --spreadsheet-token (XOR public) - --sheet-id / --sheet-name (repeat or comma-separate; mutually exclusive) - --range (repeatable A1) - --max-locations (default 20) - --exit-on-error (CI gate: status='errors_found' → exit 2 with failed_precondition) Generated artifacts (skills/lark-sheets/{SKILL.md, references/ lark-sheets-formula-verify.md}, shortcuts/sheets/data/flag-defs.json, shortcuts/sheets/flag_defs_gen.go) are mirrored from sheet-skill-spec generated/ via 'npm run sync:cli'. shortcuts.go registers FormulaVerify alongside the other lark_sheet_formula_verify skill shortcuts so +formula-verify is discoverable from 'lark-cli sheets --help'. Tests cover the dry-run wire shape (excel_id + sheet_ids/sheet_names/ ranges/max_locations packing), the read scope (invoke_read URL), the mutually-exclusive selector validation, the non-positive --max-locations guard, and the --exit-on-error status matrix (success/partial/errors_found/unknown). * feat(sheets): add +history-list / +history-revert / +history-revert-status shortcuts BE-1 + BE-2 (larksuite/cli lark-sheets) for spec sheet-history-revert. Three thin callTool wrappers over facade-agg history tools, following the existing sheets Validate/DryRun/Execute + --url/--spreadsheet-token(/--token) locator convention: - +history-list (read, history_list): passes the tool output through verbatim; facade-agg already does the minor_histories/4-field/RFC3339 transform. - +history-revert (write, history_revert): --history-version-id required, enforced at Validate stage with a typed *errs.ValidationError (no request on missing); returns the async receipt. - +history-revert-status (read, history_revert_status): polls in-progress / success / failure. Flags declared inline (not via *_gen.go) — flag_defs_gen.go / data/flag-defs.json are synced from sheet-skill-spec (BE-3) and must not be hand-edited. Notes: - history_revert / history_revert_status depend on facade-agg's downstream RPC wiring, a DEFERRED follow-up; the tools return a "not wired yet" guard today. These CLI wrappers are correct and go live when the backend follow-up lands. +history-list is fully functional now. - TestFlagDefsGen_MatchesJSON fails on baseline (pre-existing BE-3 gen/json drift); resolves once BE-3 sync:cli regenerates flag defs for these shortcuts. Validation: go build ./shortcuts/sheets/... PASS; new tests (TestHistoryShortcuts_DryRun, TestHistoryRevert_MissingVersionID) PASS. Spec source: active@2acd94a24ac3f835357a274a02344f78435bcc1c39ad0d695ce587f0cbddfb21 * chore(sheets): sync lark_sheet_history skill + flag defs from sheet-skill-spec (BE-3) Synced artifacts for the history shortcuts from ee/sheet-skill-spec (SSOT), landed surgically (history-only) to avoid regressing this branch's newer skills/lark-sheets content: - skills/lark-sheets/references/lark-sheets-history.md (new, mirrored). - skills/lark-sheets/SKILL.md: + Lark Sheet History references-table row only. - shortcuts/sheets/data/flag-defs.json: + 3 history shortcuts (additive; no existing entries touched). - shortcuts/sheets/flag_defs_gen.go: regenerated via go generate ./shortcuts/sheets/... (this also resolves the pre-existing flag-defs/gen drift — TestFlagDefsGen_MatchesJSON now passes). NOT a full mirror: the rest of skills/lark-sheets/ + flag-schemas.json on this branch (feat/lark-sheets-develop) are NEWER than the sheet-skill-spec worktree's canonical (e.g. /wiki/ URL support, schema_version 3). A wholesale sync:cli would have reverted them, so only the history delta is taken here. Full re-sync should happen once sheet-skill-spec canonical is realigned with this branch. Validation: go generate clean; go test ./shortcuts/sheets/ (TestFlagDefsGen_MatchesJSON, TestHistory*) PASS. Spec source: active@2acd94a24ac3f835357a274a02344f78435bcc1c39ad0d695ce587f0cbddfb21 * fix(sheets): +history-revert-status keys on --transaction-id, not version id BE-2 gap surfaced by PPE E2E: +history-revert-status sent history_version_id, but the facade-agg history_revert_status tool keys on transaction_id (the async receipt returned by +history-revert), so it returned "[40400] transaction_id is required". Give the status shortcut its own --transaction-id flag + input (excel_id + transaction_id); revert keeps --history-version-id. Tests updated. * fix(sheets): align history flag-defs with inline shortcuts (green TestFlagsFor) TestFlagsFor_EveryRegisteredCommandHasDefs was RED: generated flag-defs drifted from the hand-written history shortcuts. - +history-revert-status: flag-defs had --history-version-id; the BE-2 fix switched the shortcut to --transaction-id. Updated the entry to transaction-id. - +history-revert / -status --history-version-id were marked required="required", but the inline flags are cobra-optional (requiredness enforced in Validate). Set required="optional" to match. Regenerated flag_defs_gen.go. NOTE: canonical source is sheet-skill-spec (BE-3); apply the same change upstream or the next sync:cli will regress this. * chore(sheets): sync lark-sheets-history reference from spec (BE-2 transaction-id) Mirror the upstream BE-2 fix in canonical-spec/references/lark_sheet_history/ cli-reference.md: +history-revert-status now uses --transaction-id (taken from the async receipt returned by +history-revert), and +history-revert's --history-version-id flips required→optional (Validate enforces requiredness at runtime). This file is the only history-only delta from the upstream sheet-skill-spec sync; the rest of skills/lark-sheets/ stays on the cli's newer baseline (/wiki/ URL support, +cells-set-image / +float-image-create, etc.) to match commit 8ae516db's history-only mirror policy. Spec source companion change: feat/sheet-history-revert in ee/sheet-skill-spec, canonical-spec/{tool-shortcut-map.json,references/ lark_sheet_history/cli-reference.md}. * feat(sheets): +history-list --end-version for backward pagination Spec follow-up sheet-history-revert: thread the history_list pagination contract through the +history-list shortcut. - shortcuts/sheets/lark_sheet_history_list.go: + --end-version (int, optional). Mapped to the tool input's `end_version` only when explicitly set (so the server treats absence as "first page / latest"), via runtime.Changed / runtime.Int (matches the +formula-verify --max-locations precedent). + Tip: pass next_end_version from the response on the next call; capture exits the pagination loop when the server omits the field. - shortcuts/sheets/lark_sheet_history_test.go: + dry-run case asserting --end-version 12345 lands as input.end_version=12345 (post-JSON unmarshal float64). - skills/lark-sheets/references/lark-sheets-history.md: synced from ee/sheet-skill-spec (commit 39c6b61). Adds the "倒序分页" caveat row + --end-version flag + pagination Examples line. Drops the internal MajorHistory.Version implementation detail per spec follow-up. - shortcuts/sheets/data/flag-defs.json: synced from spec (+history-list +--end-version int optional). - shortcuts/sheets/flag_defs_gen.go: regenerated via `go generate ./shortcuts/sheets/...`. Companion changes: - ee/sheet-skill-spec MR !37: spec-tables + tool-schemas pagination contract (commits 09e8604, 39c6b61). - ee/sheet-facade-agg MR !1028: history_list tool plumbs end_version, emits next_end_version + has_more (omitted at earliest page), defaults PageSize=20 to datarpc. Validation: - go build ./shortcuts/sheets/... PASS - go test ./shortcuts/sheets/... PASS (sheets + backward) - TestHistoryShortcuts_DryRun (5 cases incl. new --end-version case): PASS - TestHistoryRevert_MissingRequiredFlag: PASS - TestFlagsFor_EveryRegisteredCommandHasDefs: PASS - TestFlagDefsGen_MatchesJSON: PASS * fix(sheets): make +history-revert --history-version-id cobra-required + revert max-cells default drift Two issues surfaced during MR !37 review: 1) +history-revert --history-version-id requiredness was set as "optional" in the spec table (BE-2 fix dc5fe0ea) so cobra wouldn't block before Validate. Per upstream review the flag should be required-by-cobra so the user gets the standard "required flag(s)" gate immediately and the runtime contract matches the JSON shape. - shortcuts/sheets/lark_sheet_history_revert.go: historyVersionIDFlag now sets Required: true. Validate keeps a trim/empty-string guard so '--history-version-id ""' still fails as a typed *errs.ValidationError (cobra accepts empty strings as "set"). - shortcuts/sheets/data/flag-defs.json: +history-revert --history-version-id required: optional -> required. - shortcuts/sheets/flag_defs_gen.go: regenerated. - shortcuts/sheets/lark_sheet_history_test.go: TestHistoryRevert_MissingRequiredFlag split into per-shortcut subtests; +history-revert asserts cobra's "required flag(s)" contract (raw err — the test rig calls cmd.Execute directly so it doesn't see the cmd dispatcher's typed envelope wrap); +history-revert-status keeps the typed *errs.ValidationError contract (its --transaction-id stays cobra-optional + Validate-enforced). 2) max-cells safety cap was accidentally rewritten from 200000 to 50000 by the last sync from sheet-skill-spec (the spec canonical side fell out of date — fixed separately on the spec MR follow-up). Restore desc: "Safety cap; default 200000" / default: "200000" so +cells-get / +csv-get keep the documented cap. Validation: - go test ./shortcuts/sheets/... PASS - TestHistoryRevert_MissingRequiredFlag (both subtests) PASS - TestHistoryShortcuts_DryRun (incl. +history-list pagination case) PASS - TestFlagsFor_EveryRegisteredCommandHasDefs PASS - TestFlagDefsGen_MatchesJSON PASS * fix(sheets): make +history-revert-status --transaction-id cobra-required (match +history-revert) Companion to commit 6ca35b06: same gating model now applies to both history receipts. - shortcuts/sheets/lark_sheet_history_revert.go: transactionIDFlag.Required=true. Validate keeps a trim/empty-string guard for '--transaction-id ""'. - shortcuts/sheets/data/flag-defs.json: +history-revert-status --transaction-id required: optional -> required (synced from sheet-skill-spec @9ca814d). - shortcuts/sheets/flag_defs_gen.go: regenerated. - shortcuts/sheets/lark_sheet_history_test.go: TestHistoryRevert_MissingRequiredFlag/+history-revert-status moved to the cobra "required flag(s)" text contract (the test rig invokes the shortcut via cmd.Execute, which sees the raw cobra error directly without the dispatcher's typed wrap). Drop now-unused `errors` and `errs` imports. Validation: - go test ./shortcuts/sheets/... PASS (sheets + backward) - TestFlagsFor_EveryRegisteredCommandHasDefs: PASS - TestFlagDefsGen_MatchesJSON: PASS - TestHistoryRevert_MissingRequiredFlag (both subtests): PASS * docs(sheets): sync history skill reference required badges from spec Companion to commit 9fa73312 (transaction-id) and 6ca35b06 (history-version-id): the two flag tables in skills/lark-sheets/references/lark-sheets-history.md still showed 'optional' even though the canonical contract — and shortcuts/sheets/data/ flag-defs.json — already moved to 'required'. The earlier syncs only picked up the data file from spec; the skill markdown drift slipped through. Pull in the spec-side regenerated reference (ee/sheet-skill-spec @9ca814d) so the human-readable doc matches the wire contract. * fix(sheets): lower cells-set --max-cells default to 50000 * docs(sheets): clarify workbook-import over read-then-recreate in skill * docs(sheets): bump lark-sheets skill version to 3.0.1 * docs(sheets): clarify number-vs-text typing and copy-to-range template guidance in references * docs(sheets): type by data nature, add pre-write reference column and chart/cond-format/filter rows - SKILL.md quick-reference: add a "read before acting" column pointing each intent at its reference doc; add chart / cond-format / filter rows. - Reframe number-vs-text decision to follow the data's nature (measure vs identifier), not whether the current task happens to sort/sum; a leaderboard/report "display only" use does not make a percentage text. - write-cells reference: mirror the same rule and the +cells-set fallback for layouts +table-put cannot express. * docs(sheets): tighten number-vs-text guidance and dedupe write-cells reference * Feat/lark sheets develop wzz (#1719) * feat(sheets): add +changeset-get shortcut for changeset review Wrap the get_changeset read tool: fetch the raw changeset (edit actions) between two versions to review whether an AI edit fulfilled the request. --start-revision required, --end-revision optional (defaults to latest), gap capped at 100. Adds flag-defs entry + regenerated gen, the ChangesetGet shortcut + tests, and skill docs. * feat(sheets): add +get-revision shortcut Return a spreadsheet's current document revision without pulling the full sub-sheet listing. +get-revision is a read-only derivative over get_workbook_structure (the lightest read — token only, no range) that projects the response down to the single revision field. Adds flag-defs entries and a unit test for the projection helper. * feat: 同步 spec 修改 * feat(sheets): rename +get-revision to +revision-get * feat: 移除 ppe 环境请求头 --------- Co-authored-by: wenzhuozhen <wenzhuozhen@bytedance.com> * docs(sheets): dedupe +changeset-get flag def and skill reference entry * feat(sheets): accept local_office_ token prefix for image parent_type The synthetic token prefix for imported office spreadsheets is being renamed from fake_office_ to local_office_. Accept either prefix when mapping a spreadsheet token to the drive media parent_type so image uploads keep working across the rename (main package and backward compat copy). * fix(sheets): replace undefined common.FlagErrorf with sheetsValidationForFlag changesetRevisions called common.FlagErrorf, which does not exist, breaking the build. Use sheetsValidationForFlag so the errors carry the offending flag param like the rest of the sheets validation paths. Also reword two doc comments in lark_sheet_history_revert.go that used '' for an empty shell string: gofmt (Go 1.19+) rewrites '' in doc comments to a curly quote, leaving the file permanently unformatted. * fix(sheets): satisfy errs-no-bare-wrap forbidigo and errorlint rules from main main introduced the errs-no-bare-wrap forbidigo rule and errorlint coverage that flag 27 issues in existing sheets code after the merge: - Replace direct *errs.ValidationError type assertions with errors.As in sheetsInputStatError and validateSheetMediaUploadFile so wrapped errors still match (errorlint). - Type the embedded flag-schemas.json parse failure as an InternalError with cause; it reaches the user directly via --print-schema. - Annotate genuine intermediate errors (recursive schema validator, batch sub-op raw type checks, A1 range/position parsers) with //nolint:forbidigo; every caller wraps them into typed flag validation errors. * docs: tighten formula verify workflow guidance * docs: align formula verify refs with file names * feat(sheets): let typed writes style blank cells past the data extent +workbook-create / +table-put apply cell_styles by writing them into the in-memory matrix, whose size was fixed to the data (cols × rows). A style range reaching past that extent was rejected as "outside the write range", so blank cells (reserved regions, decorative headers, empty borders) could not be styled on the typed --sheets path — only the untyped --values path padded for it. Pad the matrix down/right to cover every cell_styles range before applying (empty cells appended for the uncovered positions), mirroring the --values behavior. writeSheetData now derives the written width/range from the padded matrix; both dry-run previews and sheetCreateDims account for the style extent so the physical grid and the plan match Execute. Ranges above/left of the write anchor stay rejected (the matrix only grows down/right). * docs(sheets): warn that +csv-put silently coerces numeric-looking labels Add guidance that +csv-put numericizes date-like/ID-like columns whose values are all digits (12.10 becomes 12.1 losing the trailing zero, 001 becomes 1 losing the leading zero); recommend +table-put with dtypes=object/datetime64 or +cells-set + number_format="@". Also fix the batch-update example to use sheet_name instead of sheet_id. * docs(sheets): steer import-vs-append onto sheet-copy for existing workbooks * docs(sheets): warn that cells-clear --scope all is irreversibly destructive * docs(sheets): sync chart schema and labels guidance (#1716) * chore(sheets): update chart flag schema * docs(sheets): clarify chart labels field is presence-toggle, not value-toggle Synced from sheet-skill-spec. Chart labels (plotArea.plot.labels and per-series labels) are toggled by object existence — passing labels at all turns data labels on, even when value/category/series/percentage are all false (server falls back to showing value). Models repeatedly try `{ value: false, category: false, series: false }` to disable, which silently shows the value fallback. The reference doc now spells out both directions: pass labels to show, omit the whole labels field to hide. Also picks up earlier spec-side drift not yet propagated: - pivot-table reference: +pivot-list info return + overlap validation - flag-defs: cell-matrix fan-out cap default 200000 -> 50000 (#1578) * feat(sheets): drop pre-refactor aliases from `sheets --help` listing The refactored + commands have been the default for over a month. Hide the deprecated pre-refactor aliases from `sheets --help` via a custom cobra usage template that skips the deprecated group. Aliases stay registered and executable: their own `sheets <alias> --help` still shows the (→ +new-command) pointer, unknown-subcommand suggestions still span them, and execution still returns the _notice. * feat(sheets): let +csv-put fall back to piped stdin when --csv is omitted Agents routinely redirect a CSV into stdin but forget the `--csv -`, so `+csv-put ... < data.csv` failed its first try on a missing --csv and cost an extra round-trip (error, then --help, then retry). Relax --csv's cobra required-gate in the shortcut's PostMount and install a PreRunE that defaults an omitted --csv to "-" when stdin is a non-interactive pipe, so the standard stdin-resolution path reads it. The pipe guard keeps an interactive terminal from blocking on stdin, and a genuine miss (no piped data) still surfaces csvPutInput's typed "--csv is required" instead of cobra's bare "required flag(s) ... not set". Scoped entirely to the sheets domain — no changes to the shared runner or the flag schema. * feat(sheets): rework +rows-resize / +cols-resize to --height / --width 从上游 sheet-skill-spec 同步:+cols-resize 用 --width、+rows-resize 用 --height 直接给像素值, --type 变为可选(省略等价于 pixel)。--type standard/auto 走非像素模式,不能与像素 flag 同传; --type pixel 与 --width/--height 共存时视为等价形式。--size 已删除。 * docs(sheets): 更新 lark-sheets skill 版本至 3.0.2 将 SKILL.md 版本号从 3.0.1 升至 3.0.2,同步近期 sheets 命令改动(+rows-resize/+cols-resize 改 --height/--width、 +csv-put 支持 stdin 回退等)后的技能版本。 * feat(sheets): add --widths / --heights map form for per-column/row sizes 从上游 sheet-skill-spec 同步:+cols-resize --widths / +rows-resize --heights 接收 JSON map(键为单行列或闭区间,值为像素或 "standard"/"auto"),CLI 按起始位置排序后 展开为一次原子 batch_update 的多个 resize_range 操作,多列不同宽 / 多行不同高一次 调用完成,不再需要 +batch-update。map 形态与 --range/--width/--height/--type 互斥, 不可作为 +batch-update 子操作嵌入(batch_update 不支持嵌套)。列宽 < 20px 拒绝并提示 Excel 字符单位换算(px ≈ 字符数×8+16);--print-schema --flag-name widths/heights 可查 schema。 * fix(sheets): sync flag input/enum fixes from sheet-skill-spec 上游修复 spec-table 的 Input/Enum 字符串惯例后重新生成:--widths/--heights 现在带 file/stdin 输入声明,+sheet-create --type 的枚举正确进入 flag defs 与文档。 * feat(sheets): add sheets-scoped flag ergonomics via PostMount Two recovery loops from the edit-eval traces burn agent round-trips: hallucinated flag names (--cols for --range) whose unknown-flag error only points at --help, and enum values imported from CSS/Excel vocabulary ("center" for the vertical alignment Lark spells "middle"). - unknown-flag errors now inline the full valid-flag list (semantic guesses aren't rankable by edit distance; kills the --help round trip) - enum values with an unambiguous canonical form (casing, known alias) are normalized in place and the call proceeds; edit-distance typos stay errors with a did-you-mean hint and are never auto-applied Both ride the existing PostMount composition (same pattern as withTokenAlias), so the common framework is untouched and no other domain's behavior shifts. * feat(sheets): make validation errors prescriptive for hot failure modes Driven by the edit-eval-extra-35Q reports: ~70% of lark-cli sheets errors were missing-required / JSON-shape / wrong-value classes whose messages said what broke but not how to fix it, pushing agents into --help / --print-schema probe loops. - composite JSON shape errors inline a compact skeleton auto-generated from the schema (e.g. --cells -> [[{"value": ...}]]) when the type mismatch is shallow container confusion - +batch-update: missing 'shortcut' shows the entry template; a disallowed shortcut inlines the full allow-list; exceeding the 100-op cap says how many batches to split into; sub-op translator failures append the shortcut's complete input-key contract - +table-put: dtypes/formats keys that miss every column call out the A1-letter habit and inline the declared column names; empty cells in a date-typed column name the three ways out - schema enum errors suggest across casing, vocabulary aliases, and edit distance * fix(common): steer rejected @file paths to stdin instead of cd The absolute-path rejection hint said "cd to the target directory first" - advice the lark-sheets skill explicitly tells agents not to follow (it pollutes the working directory). The stdin-contention hint also demonstrated @file with an absolute path, which would itself be rejected. - @file failures on stdin-capable flags now show the equivalent stdin invocation (--csv - < /tmp/x.csv) - the path error recommends a relative path or stdin, not cd - the stdin-contention example uses a relative @file path Message-text only; no control-flow change for any domain. * chore(sheets): suppress forbidigo on csv-put stdin pipe detection os.Stdin.Stat is intentional here - pipe detection needs the real process fd; IOStreams.In is a plain io.Reader without Stat. Clears the lint failure left by the stdin-fallback commit. * fix(sheets): pass spreadsheet token to changeset tool (#1839) * fix(sheets): hide bitable sheet creation (#1843) * fix(sheets): resolve revision wiki URLs * fix(sheets): reject overlapping resize ranges * fix(sheets): address remaining review feedback * fix(sheets): avoid credential scanner false positive * fix(sheets): import mislabeled .xls workbooks by sniffing content Local .xls files that are actually OOXML (an .xlsx exported or renamed to .xls) failed +workbook-import with a cryptic backend "xml_version_not_support" because the CLI trusted the file name extension. +workbook-import now sniffs the file's leading magic bytes (PK -> xlsx, OLE2 -> xls) and passes the true extension to the drive import core via a new optional ImportParams.FileExtension override, correcting both the file_extension and the staged media file name (the latter avoids the backend's "import file extension not match", code 1069910). A declared Excel file whose bytes match neither container is rejected locally with a prescriptive error instead of the opaque backend failure. The drive import core gains only the neutral FileExtension override (empty = infer from the file name, i.e. unchanged behavior for drive +import); all Excel sniffing/correction policy lives in the sheets shortcut. * fix(ci): keep semantic waiver fixture active * fix(sheets): close remaining safety gaps * fix(sheets): align history shortcuts with generated flags Use generated flag defs for history revert commands, enforce control-character validation, and sync the refreshed lark-sheets references from sheet-skill-spec. * fix(sheets): require confirmation for history revert * fix(sheets): require explicit csv input --------- Co-authored-by: xiongyuanwen-byted <xiongyuanwen@bytedance.com> Co-authored-by: wuyanchun.anunwu <wuyanchun.anunwu@bytedance.com> Co-authored-by: wenzhuozhen <wenzhuozhen@bytedance.com> |
||
|
|
fc8d212a4f | feat: add application domain with slash command management shortcuts (#1806) | ||
|
|
e96c4fa581 | test: isolate semantic waiver fixtures from wall clock | ||
|
|
4847f06ca8 | fix: route brand-sensitive endpoints through the resolver (#1836) | ||
|
|
80fadf1801 | fix(drive): abort push on parent sibling limit (#1813) | ||
|
|
cdd9d3409b | feat(affordance): usage guidance for shortcuts and per-command skills (#1793) | ||
|
|
06f6b0b18c |
fix: preserve original filename in multipart file upload (#1767)
* chore: bump oapi-sdk-go/v3 to v3.7.2 for filename-aware multipart upload * fix: preserve original filename in multipart file upload BuildFormdata read local files into a bytes.Reader before handing them to the SDK, so the SDK's part-filename detection (which only reads *os.File) fell back to "unknown-file" for every local --file upload. Use AddFileWithName with the file's basename instead. |
||
|
|
f98dbfe247 | Improve agent-facing error guidance for drive, markdown, and wiki (#1779) | ||
|
|
f0b6f35fee |
fix: resolve schema against runtime metadata in plugin builds; gate cache overlay by version (#1764)
* fix(schema): fall back to runtime catalog when no embedded metadata Binaries built from the bare Go module (plugin builds) embed only the empty meta_data_default.json stub because meta_data.json is gitignored and fetched at build time. The schema command, its completion, and the affordance command-form resolver read the embedded-only catalog, so every schema lookup failed with "Unknown service" even though the runtime registry had already sync-fetched full metadata. Add registry.SchemaCatalog(): embedded when compiled in (official builds unchanged, still deterministic), otherwise the merged runtime catalog seeded from cache or remote fetch. When neither source has data (offline plugin build with a cold cache), schema now returns a failed_precondition error with an actionable hint instead of "Unknown service" with an empty candidate list. * fix(registry): gate cached meta overlay on version newer than embedded The cached remote meta was overlaid onto the embedded meta_data.json unconditionally, so after a CLI upgrade an equal- or older-version cache kept shadowing the freshly shipped embedded definitions until a later refresh happened to rewrite it. Only overlay when the cache version is strictly newer than the embedded baseline. The bare-module stub baseline is "0.0.0", so plugin builds without compiled metadata still take any real cached version (TestOverlayGate_StubEmbedded_OverlaysRealCache) and the schema runtime fallback keeps working offline from a warm cache. Ports #1376 onto the typed meta model. --------- Co-authored-by: liangshuo-1 <266696938+liangshuo-1@users.noreply.github.com> |
||
|
|
91d785f92f |
refactor(envvars): consolidate agent env value access (#1757)
* feat(envvars): add LARKSUITE_CLI_AGENT_NAME accessor envvars.AgentName() reads LARKSUITE_CLI_AGENT_NAME so business code can identify the agent driving the CLI. Value is sanitised (trim, reject control chars, 128-byte cap) and returns "" when unset or invalid. Local-only; not sent to the server. * refactor(envvars): consolidate agent env accessors, dedupe sanitize Move agent-trace reading from cmdutil.AgentTraceValue into envvars.AgentTrace(), symmetric with AgentName and sharing one sanitizeSingleLine. secheader.go now only assembles headers (BaseSecurityHeaders calls envvars.AgentTrace()); the duplicated sanitize and its os/unicode imports are gone. The X-Agent-Trace header and its behaviour are unchanged. --------- Co-authored-by: liangshuo-1 <266696938+liangshuo-1@users.noreply.github.com> |
||
|
|
e621c6e50f | fix: support pnpm global installs in self-update (#1705) | ||
|
|
efa3439e01 |
fix(update): increase npm registry fetch timeout from 5s to 15s (#1724)
The update checker fetches https://registry.npmjs.org/@larksuite/cli/latest with a 5-second HTTP client timeout. Under high-latency network conditions (TUN-mode proxies, VPNs, transcontinental routes), TLS handshake alone can take 4-6 seconds, causing the check to fail with: context deadline exceeded (Client.Timeout exceeded while awaiting headers) Measured example behind a Clash TUN proxy (US node from China): DNS resolve: ~0ms (fake-ip) TCP connect: ~0ms (local TUN) TLS handshake: 4.3-5.9s <-- bottleneck Total: 4.7-6.3s curl succeeds because it has no default connect timeout, but the Go HTTP client with Timeout=5s is too tight. The registry endpoint returns a tiny JSON payload (<1KB), so 15s is more than enough headroom while still failing fast on genuinely unreachable networks. Co-authored-by: 王伟达 <weida.wang@m.com> |
||
|
|
578e2db4e0 | fix: point permission-apply link at official /page/scope-apply entry (#1722) |