mirror of
https://github.com/larksuite/cli.git
synced 2026-07-08 10:08:02 +08:00
docs/lark-shared-restructure
308 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
693e299589 |
docs(mail): clarify message read shortcuts (#1261)
* docs(mail): clarify message read shortcuts Update mail read shortcut help, docs, and triage guidance so single-message and multi-message reads are routed to the right commands. Add focused tests for help text, dry-run copy, triage stderr hints, and batch_get chunking behavior. sprint: S1 * docs(mail): align batch_get limit with gateway config * docs(mail): use shell-safe batch message id examples * docs(mail): trim batch_get pagination wording * docs(mail): use placeholder style for message ids * docs(mail): hide batch_get internals from help |
||
|
|
1cd7a88597 | fix: read release error_logs from data.error_logs in apps +release-get (#1436) | ||
|
|
7c64e63b9d |
feat(note): clarify note ownership with dedicated detail and transcript flows (#1435)
* feat: split note domain * fix: address note transcript review comments * fix: stabilize empty note detail detection |
||
|
|
8e60f01474 |
feat(im): unify sort flags into --sort field and --order direction (#1302)
The 4 im query commands had three inconsistent sort conventions and leaked upstream API jargon (ByCreateTimeAsc, member_count_desc) directly to users. This PR unifies them on a single rule — --sort selects a field, --order selects a direction, both from fixed enums — so an agent only ever picks from an enum, never constructs a string. Old flags (--sort-type, --sort-by, and --sort on messages/threads) are kept as hidden silent aliases (no deprecation warning), so existing scripts keep working byte-for-byte. |
||
|
|
510545f1e5 | refactor(vc): consolidate note handling back into the vc domain (#1417) | ||
|
|
c11cf3b716 |
feat: split note domain (#1345)
Add note shortcuts for note detail and unified transcript retrieval, route vc note detail parsing through the note domain, and update note/vc/minutes skill guidance for normal versus unified transcript handling. Includes dry-run E2E coverage for the new note shortcuts and documents the remaining live E2E fixture gap. |
||
|
|
9bc66cc445 | feat(apps): emit typed error envelopes across the apps domain (#1288) | ||
|
|
e53f9d999e |
feat(im): add --chat-modes filter to chat search (#1317)
Add a server-side --chat-modes filter to the im +chat-search shortcut so users can restrict results to regular groups and/or topic groups. Change-Id: Ia59c2c05fb2e8e45bd741c8531ca0e3ca69de2f3 |
||
|
|
dfa26c38f6 |
feat: exclude .git directory from apps +html-publish package (#1396)
* feat: exclude .git from html-publish package walk * docs: note .git auto-exclusion in html-publish reference * test: update html-publish e2e for .git exclusion * docs: simplify .git skip comment in html-publish walker |
||
|
|
154ecdb90f |
feat(wiki): emit typed error envelopes across the wiki domain (#1350)
Emit structured validation, API, network, file, and internal error envelopes for Wiki shortcuts so users and agents can recover from failed wiki workflows using stable type, subtype, param, and code fields. Add Wiki domain errscontract and golangci guards to prevent legacy envelope and common helper regressions. |
||
|
|
483043c88b |
fix: parsing empty whiteboard (#1391)
Change-Id: I10082f89c36ed77e77e1d016be263e0f7369b7b3 |
||
|
|
6d8dc402ac |
fix: support git credential dry-run (#1390)
* fix: support git credential dry-run * test: cover git credential dry-run output |
||
|
|
2c703f2fce |
feat: apps support multi dev modes (#1175)
* feat: add fullstack app-type and --message to apps +create (#1) * feat: accept fullstack app-type and require --message for it * feat: inject message into fullstack create request body * refactor: align fullstack message injection with existing body-build style * docs: document fullstack app-type and --message for apps +create * docs: keep scene numbering consistent in lark-apps-create reference * docs: add HTML/fullstack intent routing to lark-apps SKILL.md * docs: cover fullstack in lark-apps skill description and clarify HTML flow step * test: assert fullstack in allow-list error and reject wrong-cased fullstack * feat: drop --message from apps +create (#4) * feat: drop --message from apps +create * docs: drop --message and document agent-generated name/description for apps +create * feat: add apps local key-value file storage (#5) * feat: add Miaoda app git credential support (#9) * fix: remove APIError detail field dependency * docs(apps): expand lark-apps skill for local-dev & cloud-chat workflows (#3) Reframe lark-apps from an HTML-publish skill into a full Miaoda app dev tool covering three paths: local fullstack dev, HTML hosting, and cloud session dev. Builds on the fullstack create change already on this branch. - SKILL.md: 3-path routing table; mental models (code via native git, develop/main branch model, DB via +db-* through Miaoda, env auto-pulled by `npm dev run`, auto-managed credentials); command index for the new verbs; ambiguous-input fallback (infer app type from need, ask local vs cloud instead of assuming; default HTML when no signal) - add local-dev and cloud-dev playbooks - create: keep HTML/fullstack + required --message; add local/cloud scene routing and --enable-multi-env-db - list: usable by agents with --filter; app_id resolution order (user-provided / .spark/meta.json / +list --filter) Co-authored-by: wangjiangwen-gif <286006750+wangjiangwen-gif@users.noreply.github.com> Co-authored-by: raistlin042 <lvxinsheng@bytedance.com> * feat(apps): add 4 db CLI commands (table-list / table-schema / sql / dev-init) 妙搭 data CLI 4 条命令,复用存量 OpenAPI URL + 1 个新增 dev-init: - +db-table-list → GET /apps/{id}/tables(游标分页,AppTable 含预估行数/占用空间) - +db-table-schema → GET /apps/{id}/tables/{name}(默认结构化 schema;--format pretty 出建表 DDL) - +db-sql → POST /apps/{id}/sql_commands(?transactional=false DBA 模式) - +db-dev-init → POST /apps/{id}/db_dev_init(单库→online/dev,不可逆,high-risk-write) 要点: - sql result 兼容两种 wire 形态(结构化 [{sql_type,data,record_count}] 与 legacy ["rows-json"]) - 多语句失败:server 返 code:0 + ERROR 哨兵,CLI 升级成 typed api_error(exit 非 0), detail 带 statement_index/completed/rolled_back,防止 agent 误判 ok:true 假成功 - pretty 渲染对齐 miaoda:列间两空格、CJK 双宽、size 友好格式(KB/MB/GB) - 单测 + e2e dry-run 全覆盖;BOE 真机 e2e 验证通过(25 PASS) - SKILL.md 注册 4 条命令 + 4 篇 reference 注:内含的 BOE 联调专用 env 覆盖(LARK_CLI_OPEN_API_BASE / LARK_CLI_X_TT_ENV, internal/cmdutil + internal/envvars)未包含在本次提交,仅本地联调用。 Change-Id: I0fe4458086708a93941e2dee852fa6a10b53bd4a * docs(lark-apps): db 能力补进 SKILL.md description 的 WHEN 段 按 skill 质量规范(description 三段式 WHAT+WHEN+NOT,加载前唯一可见信息), 原 WHEN 仅"连数据库调试"含糊覆盖 db。补成「查看或操作应用数据库(看表结构 / 跑 SQL / 初始化 dev 环境)」,让 +db-table-schema / +db-sql / +db-dev-init 类查询能精确触发,净增 ~12 字无膨胀。 Change-Id: Id52819fa7d6b8ed0c1f174bf5946d55da7b893d7 * Feat/apps env pull (#11) * feat: add apps env-pull shortcut * fix: support array env_vars response in apps env-pull * fix(apps): improve env-pull merge and expiry output * feat: add keyword/scope/app-type query to apps +list and unhide it (#8) * feat: switch apps +create --app-type enum to lowercase html/full_stack * feat: add keyword/scope/app-type query to apps +list and unhide it * docs: document apps +list query params and lowercase app_type enum * test: update apps cli_e2e dry-run tests for lowercase app_type and +list filters * docs: trim redundant app_type case-sensitivity note in create skill * docs: single-source apps +list usage contract to SKILL.md * feat: add apps publish shortcuts (publish/status/history/error-log) (#12) * feat: add apps publish shared guard and NodeStatus mapping * test: cover json.Number path in injectStatusName * feat: add apps +publish shortcut Implements the `apps +publish` command with dry-run preview (upstream PSM path shown) and an Execute gated by ensurePublishWired() per the not-yet-deployed OpenAPI gateway constraint (publishAPIWired=false). * refactor: make apps publish path placeholders var to satisfy go vet Declare the four publishXxxPath constants as var instead of const so go vet's printf analyzer skips them while they are empty placeholders. Revert the Execute path-build in apps_publish.go from strings.Replace back to fmt.Sprintf (now safe because the format string is a var). * feat: add apps +publish-history shortcut * feat: add apps +publish-status shortcut * feat: add apps +publish-error-log shortcut * feat: register apps publish shortcuts Add AppsPublish, AppsPublishHistory, AppsPublishStatus, AppsPublishErrorLog to Shortcuts() and update count test from 6 → 10. * docs: add skill references for apps publish shortcuts * docs: surface apps publish shortcuts in lark-apps SKILL.md * docs: clarify publish instance id is not an approval instance * docs: nudge agent to run apps +publish --dry-run for release requests * feat: update apps publish shortcuts to v1.0.381 release protocol Rename concept instance→release across all 4 publish shortcuts and their tests: NodeStatus→ReleaseStatus enum, --instance-id→--release-id flag, pipelineTaskID→releaseID response field, errorJobs→errorLogs, and upstream HTTP path consts→RPC method name consts (PSM lark.apaas.devops v1.0.381). Dry-run now shows psm+rpc_method instead of an HTTP path. * docs: update apps publish skill docs to v1.0.381 release protocol * fix: soften apps publish unavailable hint to user-facing language * feat: update apps publish to v1.0.385 string status + --status filter - Remove obsolete int-enum machinery (releaseStatusName/toInt/injectStatusName) and their encoding/json + fmt imports from apps_publish_common.go - +publish Execute now returns status string alongside release_id - +publish-history gains --status Enum flag (publishing/finished/failed); buildHistoryBody gains status param, table column status_name→status - +publish-status Execute drops injectStatusName, pretty prints out["status"] - +publish-error-log shapeErrorLog is string passthrough (no status_name) - Unit tests updated: delete 3 obsolete common tests, update history/error-log * docs: update apps publish docs to v1.0.385 string status + --status filter * feat: wire apps publish shortcuts to final gateway paths (guard stays until deploy) Replace RPC-name placeholders with real OpenAPI paths (publishCreate/Get/ErrorLog/ListPath consts). Switch DryRun to idiomatic HTTP form (POST/GET + real URL + body/params). Fix body/query placement: publish body has no app_id (path-only); history switches from POST body to GET query with snake page_token. Fix Execute response reads to snake_case fields (release_id, created_at, updated_at, error_logs). publishAPIWired stays false; 1-line flip activates live calls. * docs: update apps publish docs to final gateway paths Replace RPC/PSM dry-run example with real HTTP form (POST/GET /open-apis/spark/v1/apps/:app_id/releases[/:release_id[/error_logs]]). Fix all response field names to snake_case (release_id, created_at, updated_at, error_log). Note --status/--limit/--page-token as HTTP query params in publish-history. * feat: enable apps publish gateway calls (remove not-deployed guard) * docs: remove not-deployed transition notes from apps publish docs * feat: use spark:app:publish scope for apps +publish * feat(apps): add +init shortcut to initialize Miaoda app repo (#6) * feat(apps): add command runner and credential redaction for +init * fix(apps): make credential redaction scheme matching case-insensitive * feat(apps): add +init shortcut declaration, validation, and dry-run * feat(apps): implement +init orchestration (credential-init, clone, checkout, conditional push) * fix(apps): redact full userinfo when repo URL contains literal @ * docs(apps): add +init skill reference * fix(apps): declare explicit empty Scopes on +init shortcut * fix(apps): consume repository_url from +git-credential-init in +init * feat(apps): add +init template flag and absolute-path dir resolution * refactor(apps): use shared charcheck for +init --dir validation * feat(apps): add meta.json, steering, and empty-repo helpers for +init * feat(apps): add +init npx scaffold orchestration (init/upgrade branches) * feat(apps): wire +init scaffold, already-initialized short-circuit, npx dep check * docs(apps): document +init npx scaffold, --template, --dir, already-initialized * docs(apps): correct stale +git-credential-init unreleased note in +init ref * fix(apps): reject all control chars in +init --dir * feat(apps): add +init progress logging and optional --template resolver * refactor(apps): inline constant in +init scaffold progress log * docs(apps): document +init optional --template and stderr progress contract * feat(apps): treat README-only repo as empty and commit with --no-verify in +init * docs(apps): explain README-seed match and --no-verify rationale in +init * docs(apps): document README-seed empty detection and commit --no-verify * feat(apps): add session conversation lifecycle shortcuts (#13) * feat(apps): add +session-create shortcut * fix(apps): remove unused sessionPath helper, assert empty +session-create body * feat(apps): add +session-list shortcut * feat(apps): add +session-read shortcut * feat(apps): add +session-stop shortcut * feat(apps): add +chat shortcut * feat(apps): register session lifecycle shortcuts * docs(apps): add session conversation skill reference * docs(apps): clarify fullstack session_id source and fallback * style(apps): gofmt apps_session_create.go * docs(apps): add conversation/session triggers to skill routing description * docs(apps): add conversation flow guidance (when to reuse vs new session, per-step user prompts) * docs(apps): slim session reference per skill quality standard (4047->1726 tok) * docs(apps): tighten session additions in SKILL.md (4394->4145 tok) * fix(apps): align +chat with v7.8 contract (async, no turn_id in response) * fix(apps): update +chat path to .../sessions/{id}/chat (backend endpoint change) * docs(apps): align SKILL.md session command shape with v7.8 contract * style(apps): gofmt apps_db_table_schema_dryrun_test.go Go 1.19+ gofmt 文档注释列表缩进新规则(普通缩进 → tab 对齐), 修复 fast-gate CI 的 gofmt 卡点。 Change-Id: Ic246a659e016d9d6216182199ef300ae6f00ef9d * feat(apps): split +init commit, plainer wording, align skill branches (#14) * refactor(apps): plainer +init progress/help wording, keep scaffold key * refactor(apps): add porcelain change classifier for +init commit split * feat(apps): split +init empty-repo commit into code + config, reword subjects * refactor(apps): scaffold-kind constants and pathspec assertions for +init split * docs(apps): use +init in Path A; align app-repo branch to sprint/default * docs(apps): align local-dev playbook to sprint/default + origin remote * docs(apps): document +init two-commit split and plainer init wording * docs(apps): require asking clone dir before +init, no assumed path * fix(apps): stage +init commits by exact paths to avoid gitignore error * refactor(apps): lowercase miaoda in +init commit subjects * test(apps): cover +init upgrade path with real git * fix: harden app git credential handling (#16) * fix: harden git credential refresh fallback (#18) * fix(apps): validate env-pull key names before writing to .env.local (#17) * fix(apps): validate env-pull key names before writing to .env.local S2 (medium-low) from security review: env-pull wrote server-returned env KEYs to .env.local without validation. A compromised or MITM'd backend could inject arbitrary lines via keys containing newlines. - Add envKeyPattern regex to validate keys match [A-Za-z_][A-Za-z0-9_]* - extractEnvPullVars now returns skippedKeys for invalid key names - Invalid keys are skipped (not hard-fail) so remaining valid keys are still pulled - writeEnvPullPretty prints a warning listing skipped keys * fix(skills): correct npm script syntax from 'npm dev run' to 'npm run dev' * fix(skills): align env-pull guidance with implementation 🤖 Generated with [Aiden x Claude Code] * test(apps): cover storage/git-credential error paths and fix tz-flaky env-pull tests (#19) The coverage and unit-test CI jobs failed on two timezone-dependent assertions in apps_env_pull_test.go: the code renders the database expiry via time.Local() while the tests hard-coded a CST literal, so they failed under CI's UTC. Compute the expected string from the same timestamp with Local() instead, making the assertions timezone-agnostic. Also add unit tests for the error branches codecov flagged as uncovered, taking storage.go and git_credential.go to 100%: - storage Read/Write/Delete/List filesystem-error paths - +git-credential-remove ConfigWarning output (pretty and JSON) - gitCredentialLocalError nil passthrough * fix(apps): silence +init forbidigo, npx app sync -y --prefer-online (#20) * fix(apps): add Subtype to env-pull error literals (#21) typed_error_completeness lint requires all errs.XxxError literals to set Problem.Subtype. Add the missing field to 11 error constructions: - ValidationError (user input checks): SubtypeInvalidArgument - ValidationError (API response parsing): SubtypeInvalidResponse - InternalError (filesystem ops): SubtypeUnknown * feat(apps): inject FORCE_DB_BRANCH=dev in env-pull output (#23) * feat(apps): inject FORCE_DB_BRANCH=dev in env-pull output Always write FORCE_DB_BRANCH="dev" into the resolved .env.local after extracting upstream env_vars, so downstream tooling pinning the dev database branch does not need a separate manual edit. Existing local values are overwritten in place via the canonical merge path. * docs(skills): document apps +env-pull in lark-apps skill Add the env-pull entry to the lark-apps SKILL index and ship the matching reference doc covering args, merge semantics, return shape, error envelope subtypes, and dry-run behavior so AI agents can route to it without reading the Go source. * feat(apps): surface is_published and online_url in +list pretty view (#22) * docs: refactor lark-apps skill per quality spec (#24) Slim SKILL.md and references against the lark-cli skill quality spec while preserving domain knowledge and safety guardrails. - Compress SKILL.md (drop the MUST-read prelude, full command-index tables, and content already owned by lark-shared: auth, scope, exit-10, risk policy, _notice); add version field; zero CRITICAL markers. - Defer flag enumeration in references to `--help`; convert narration-inducing prohibitions into positive defaults; de-duplicate the per-file error.hint relay into a single resident SKILL.md rule. - Fix stale facts found against shortcuts/apps source: drop the non-existent +create --message and --enable-multi-env-db flags, +list --filter (now --keyword), +db-multi-env-init (now +db-dev-init), and the removed html-publish cwd hard-reject. - Keep all safety guardrails: db-dev-init irreversibility/exit-10, db-sql non-transactional multi-statement, git-credential token handling, html-publish credential scan, access-scope confirmation. - Restore intent lost during slimming: release_id is not an approval instance (do not route to lark-approval); resolve access-scope targets via contact/im; ask the user before publishing as a side-effect; distinguish developing an existing app locally (+init) from creating a new one (+create). * test(apps): supplement shortcuts/apps unit-test coverage to 88% (#25) * test(apps): cover db-table-list numeric/byte formatting helpers * test(apps): cover db-sql cell/code/dml/error render helpers * test(apps): cover env-pull newline/expiry/extract-vars helpers * test(apps): cover db-sql render branches and env-pull expiry edge case * test(apps): cover init empty-dir/meta/ls-files error branches * test(apps): cover env-pull target/read/parent-dir error branches * test(apps): cover stage-and-commit and commit-push error branches * test(apps): cover access-scope target split and JSON validation * test(apps): cover html-publish decode error and scaffold sync failure * test(apps): cover apps-update body field combinations * test(apps): cover access-scope body build branches * feat(apps): pass --local to npx skills sync in +init (#26) * feat(apps): pass --local to all npx miaoda-cli calls in +init * feat(apps): pass --local only to npx skills sync in +init * docs(apps): surface +publish and +init dir-choice in local-dev flow (#27) * docs(apps): surface +publish as deploy action in skill routing * docs(apps): add explicit deploy-after-local-edit section to local-dev * docs(apps): promote +init dir-choice instruction to a domain rule * docs(apps): make dev-method a signal-driven entry gate before routing (#28) * docs(apps): restore three-path overview line in apps skill intro (#29) * feat(apps): add executable Examples to shortcut --help and error hints (#30) * test(apps): guard every shortcut has a help Example and no PII * feat(apps): add help Examples to all 24 apps shortcuts * feat(apps): add actionable hints to high-impact error paths * test(apps): cover withAppsHint set-if-empty hint behavior * feat(apps): use concrete enum value in access-scope-set Example * docs(apps): clarify db-sql/db-table-list json default output behavior 两处仅补充注释,不改逻辑: - +db-sql: data.results 在 json 默认路径原样透出全部行,CLI 不二次截断; server 对单条 SELECT 有 1000 行硬上限、超出直接返报错,非无界 token 黑洞。 - +db-table-list: json 默认透出含每表完整 columns[] 系产品设计(list 接口本就 返回列定义,json 消费方一次拿全量、免逐表再调 +db-table-schema),pretty 仅摘计数。 Change-Id: I1a49de8defc4428bfe1e774e4fd7adb45e59e3af * feat(apps): command-layer AI-friendliness governance (P0+P1) (#32) * fix(apps): normalize --app-type case to align with server * refactor(apps): migrate CallAPI to CallAPITyped for typed errors and retryable * feat(apps): trim icon_url and created_at from +list default output * feat(apps): add actionable hints to high-impact error paths * feat(apps): add 2-3 help Examples to +chat and +access-scope-set * docs(apps): add --jq filter tips to list/db commands * docs(apps): sync +list reference with trimmed output fields * test(apps): assert error hints and messages carry no secrets or PII * fix(apps): prefix --jq tips with .data. so they run against the response envelope * test(apps): expect --app-type uppercase normalization in create dry-run E2E (#33) * fix(apps): scaffold via @latest miaoda-cli instead of @alpha (#34) * feat(apps): rework lark-apps triggering, routing & confirm policy (#35) * feat(apps): results-oriented triggering, pre-auth floors, terminal URL Widen description WHEN to cover app-building openers (CRM/审批/HTML page) with no Miaoda signal word, WHAT still anchored to 妙搭应用开发与托管. Add a pre-authorization rule (auth words skip confirm) with two non-exempt floors: destructive DDL (DROP/TRUNCATE/ALTER drop|modify column) dry-run, and first public-URL publish (+publish/+html-publish) when no auth word. Exempt html app_type from the local-vs-cloud dev-method gate, and scope that gate to new-app creation only (existing-app ops route directly). Require an accessible URL as the end-to-end terminal step. * feat(apps): apply eval-fix behavior contracts across reference docs init/local-dev: end-to-end default-directory escape hatch; end-to-end new-build starts with +create. db-sql: additive DDL direct-exec when authorized, destructive DDL stays dry-run. local-dev/publish-status: return online_url via +list as the full_stack publish terminal step. cloud-dev: generation != shareable URL, +publish handoff, background until-poll snippet (sleep N && cmd intercepted; deprecate ScheduleWakeup), multi-turn publish precondition. publish/publish-error-log: transient failure (EAI_AGAIN/ETIMEDOUT/registry) discrimination, retry cap 2, honest receipt. env-pull: first-launch fallback. local-dev/db-dev-init: new full_stack ships dual DB, skip +db-dev-init. * refactor(apps): apply review feedback — semantic criteria, drop overfit/unverified content Per line-by-line review of the eval-fix changes: - Entry routing reframed to objective/semantic criteria (new-vs-existing = 'can an existing app be identified'; dev-method = who-writes-code preference), replacing keyword/example matching. - db-sql DDL gate restated by effect (data-loss / reversibility), not a keyword list. - Pre-authorization judged by expressed intent (not a word list); single non-exempt floor (destructive/irreversible DB dry-run); confirm policy in its own section, error.hint in 'failure handling'. - init.md slimmed to command facts (directory choice owned by local-dev, no init<->local-dev cycle); local-dev defers new-vs-existing to the entry. - Reverted unverified/redundant/runtime-coupled additions: cloud-dev session-read preview-URL claim + background-poll snippet + queued_count precondition; publish transient-retry/ScheduleWakeup; env-pull first-launch; db-dev-init positive restatement; SKILL terminal-URL mandate. - Fixed dangling section references after the rename. * fix(apps): scope pre-authorization to hands-off intent, not 'wants a result' (#36) Follow-up to #35. The merged pre-authorization rule treated 'wanting the final result' as authorization, so '先在本地跑起来让我看看' was read as pre-authorized and the agent silently picked a clone directory without asking. Re-state the criterion as the user's hands-off intent (explicit waiver, or an end-to-end directive), judged uniformly across the flow (directory/clone, publish) — not a per-decision carve-out. Merely wanting a result or asking to review is not authorization. * docs: clarify apps cloud dev publish state * fix(apps): require commit+push before publish, clarify deploy flow (#38) * fix(apps): require committing changes before publish in local-dev flow * fix(apps): make commit+push mandatory before publish in agent rules * fix(apps): scope selective-add caveat to incremental deploy, not new-app flow * fix(apps): make pre-publish commit conditional on local changes * fix(apps): tighten pre-publish commit wording in agent rules * fix(apps): cloud-dev does not auto-deploy, add explicit publish step * docs(apps): document +chat init vs incremental turn cost (#39) First +chat on a not-initialized app runs full design+gen server-side (~20-50 min); chat on an already-initialized app is incremental and finishes in minutes. Surface this in the +chat Go comment as a pointer and put the init-state check + matching polling cadence (5-10s vs 60-120s) in the lark-apps cloud-dev skill reference as the canonical source. Cloud-side init check uses +session-read committed-version info or +list is_published:true. * docs(apps): document +chat init vs incremental turn cost (#40) First +chat on a not-initialized app runs full design+gen server-side (~20-50 min); chat on an already-initialized app is incremental and finishes in minutes. Surface this in the +chat Go comment as a pointer and put the init-state check + matching polling cadence (5-10s vs 60-120s) in the lark-apps cloud-dev skill reference as the canonical source. Cloud-side init check uses +session-read committed-version info or +list is_published:true. * feat(apps): surface online_url/error_logs in +publish-status output (#41) * refactor(apps): extract shared release error-log table helper * fix(apps): keep error-log table byte-identical for null error_logs * feat(apps): surface online_url/error_logs in +publish-status output * docs(apps): read online_url/error_logs from +publish-status in publish flow * docs(apps): align local/cloud dev publish flow with +publish-status fields * refactor(apps): rename +db-dev-init→+db-env-create, trim db-table-list columns - +db-env-create(原 +db-dev-init):新增 --env 参数(调用方传入,目前只支持 dev), --sync-data 改为 true/false 取值;服务端 URL 仍走 db_dev_init。 - +db-table-list:json 默认用白名单投影(dbTableListItem)只输出产品要求字段, 每表 columns[] 折算成 column_count、不再透出完整列定义(与 +db-table-schema 重复且放大 token);要完整列定义/索引/约束用 +db-table-schema。 - 同步对齐 db 相关 skill 文档(命令名、column_count、env-create 参数)。 - 单测 + cli_e2e dry-run 全绿。 Change-Id: I116ab11807679f8f06ed18221f705bab426d015c * refactor(apps): rename +db-table-schema → +db-table-get 动词对齐 +db-table-list(list/get)。仅命令名 + 标识符 + 文档改名,行为/输出/URL 不变: - AppsDBTableSchema→AppsDBTableGet,文件/测试/cli_e2e test 重命名 - buildDBTableSchemaParams→buildDBTableGetParams - +db-sql / +db-table-list 里的交叉引用 hint、skill 文档同步 Change-Id: I36dfb8fd0d2613492a57dc7815bc58414c145480 * feat: auto-pull env vars after apps +init (#42) * test: route apps +env-pull to its own fake-runner key * feat(apps): add +env-pull envelope parsers for +init * feat(apps): add pullEnv helper invoking sibling +env-pull * feat(apps): +init auto-runs +env-pull after push (non-fatal) * docs(apps): clarify db-sql --query @path is relative-only, use stdin for absolute paths @path 受 lark-cli 全局文件安全策略约束,只接受 cwd 内相对路径;绝对路径 / cwd 不固定 场景改用 stdin(--query - < /abs/file.sql),无需先 cd。 Change-Id: Ib3453810cfc9303d72b4facf3493ad9688eeffd3 * docs(apps): refine db-sql --query path guidance wording 以 agent 视角重写:@ 仅接受工作目录内相对路径,绝对路径/越界路径被拒(CLI 文件访问统一约束); 工作目录外的文件经 stdin 传入。 Change-Id: Ic7db00934b3571368eb704451f4ce1776463806d * feat(apps): make +db-sql high-risk-write (require --yes) +db-sql 可含 DML/DDL,统一升级为 high-risk-write:框架对所有执行强制 --yes 确认关卡 (--dry-run 预览豁免),无 --yes 返 confirmation_required / exit 10。 - Risk: write → high-risk-write(去掉自定义门禁,直接用框架机制) - skill 文档:命令骨架标注 --yes 要求;Agent 规则改为「执行需 --yes,只读可直接带、 破坏性先 dry-run 确认再带」 - 单测所有执行调用补 --yes Change-Id: I57e78832b35fa170a485774e6fb7289109d678c3 * docs(apps): clarify app_ (Miaoda) vs cli_ (Feishu) app id (#46) * 优化云端开发skill,明确执行模型,参数解释 (#44) Co-authored-by: fushengdong.1 <fushengdong.1@bytedance.com> * refactor: rename apps publish commands to release and session-get (#45) * refactor(apps): drop +publish-error-log, rename release path constants * refactor(apps): rename +publish to +release-create * refactor(apps): rename +publish-history to +release-list, unify pagination to --page-size * refactor(apps): rename +publish-status to +release-get Renames apps +publish-status → +release-get (AppsPublishStatus → AppsReleaseGet), updates --release-id desc to reference +release-create, and fixes the Execute error hint to point at +release-list instead of +publish-history. * refactor(apps): rename +session-read to +session-get * docs(apps): rename publish references to release, +session-read to +session-get * refactor(apps): clean up residual publish/session-read references Fix six leftover references missed in Tasks 1-6: +publish-history in jq-tip test wantCmds map and common_test hint fixture (×3), +session-read in apps_chat.go comment+output string (×2), apps_session_stop.go flag desc (×1), apps_chat_test.go comment (×1), and +publish-status in lark-apps-list.md agent rule prose (×1). * docs(apps): clarify release-get link contract and session-get vs session-list * docs(apps): generalize release-list page-size rule to N records * feat(apps): rename +list --scope flag to --ownership (#47) * feat(apps): rename +list --scope flag to --ownership * test(apps): update +list cli_e2e dry-run for --ownership rename * docs(apps): document +list --ownership flag * feat(apps): align +release commands with new release API format (#48) * feat(apps): align +release-create scope to spark:app:write * feat(apps): raise +release-list --page-size documented max to 500 * feat(apps): show commit_id in +release-get pretty output * docs(apps): update release reference docs for page-size 500 and commit_id * test(apps): cover empty commit_id in +release-get pretty output * docs: align lark apps cloud dev release flow * feat(apps): redesign +db-sql → +db-execute (--sql/--file, default env dev) 按 db 子域命令最终设计重做执行入口: - 命令 +db-sql → +db-execute(动词收尾,对齐 +db-table-list/-get) - --query 拆为 --sql(内联/stdin)与 --file(.sql 文件路径),二选一互斥; --file 在 Validate 阶段读出归一化到 --sql - 默认 --env online → dev(打生产库需显式 --env online) - 文件/标识符/注册/测试/cli_e2e/skill 文档全部对齐重命名 - 新增测试:--sql/--file 互斥、--file 读取、默认 env=dev 不在本次范围:--transaction/--no-transaction(服务端 transactional 实为路径切换、 非真事务,需 dataloom 侧先支持真事务开关)、--max-rows/--timeout 等后续项。 Change-Id: I50c06faf83527471446e2a6651ccb51f6eedd6ff * docs(apps): clearer --env online wording for +db-execute 把口语化的「打生产库需显式」改为「需要操作线上环境数据库时,显式指定 --env online」; flag desc 同步去掉 hit production 措辞。 Change-Id: Iee82fccf17e08bddb4b760c3970a416746b10c4c * docs(apps): drop 'ad-hoc' jargon from +db-execute description 中文文档/英文 description 去掉术语 ad-hoc;SELECT/DML/DDL 已表意,含义不丢。 Change-Id: Ie2cccc5fc3491fe5f57190a87b93ecd70405b156 * docs(apps): trim +db-execute when-to-use and --file path wording - 何时用去掉「(查询 / 临时数据修复 / 应急 DDL)」枚举 - --file 路径说明去掉 .. /符号链接/统一约束 的技术化描述,改为「相对路径, 否则用 --sql - < 文件路径」的产品化口吻 Change-Id: Ie70e57895c78650230b6942b03d90a2d95c937f2 * docs(apps): note --file rejects absolute/cwd-escaping paths 简短补回 --file 的路径约束(绝对路径 / 经 ..、符号链接越界会被拒),去掉冗余评注。 Change-Id: I549893c82cafbe97529e08dcbc3ee5496927da18 * fix(apps): replace t.Chdir with os.Chdir in db-execute test (Go 1.23 compat) t.Chdir 是 Go 1.24 API,但 go.mod 为 go 1.23.0,CI(Go 1.23)报 "t.Chdir undefined"。改用 os.Chdir + t.Cleanup 还原,1.23 兼容。 Change-Id: I550611773e5088275be1c4344d4f8269610ce74a * feat(apps): refine +init description and refresh env on re-init * fix(apps): treat accessible-link requests as publish intent (#53) * refactor(apps): +db-env-create --sync-data string-enum → Type:bool 原实现用 string + Enum["true","false"] + == "true" 模拟 bool,啰嗦且非惯用。 改为 Type:bool(rctx.Bool):传 --sync-data 即开启、省略为 false。 同步更新测试、cli_e2e dry-run、skill 文档。 Change-Id: I3068e0577fa20a7cbaf414ca9af3d197f6ae8049 * fix(apps): declare --app-type as strict lowercase enum (#55) * docs(apps): front-load routing, dedupe, and trim lark-apps skill (#56) * docs(apps): front-load intent-routing table and dedupe skill body * docs(apps): dedupe publish guardrail and polling rules in cloud-dev * docs(apps): trim env-pull implementation detail to behavior contract * docs(apps): add +env-pull routing entry in SKILL.md * docs(apps): fix create.md cross-ref to actual SKILL.md section name * feat(apps): add error.hint to command failures and a consistency gate (#57) * feat(apps): add appIDListHint const and wrap 4 pure app-id command failure paths Adds shared `appIDListHint` recovery hint to common.go and wraps the CallAPITyped failure branch of session-create, session-list, update, and release-list to surface an actionable next-step hint on 4xx errors. Includes httpmock unit tests in apps_hints_more_test.go (TDD: red→green). * feat(apps): add sessionStopHint and createHint for session-stop and create commands Adds per-command recovery hints with specific guidance: sessionStopHint points at +session-list and +session-get; createHint explains valid --app-type values and permission failure. Wraps the CallAPITyped failure branch in both commands. * feat(apps): add recovery hints for db-env-create, db-table-get, db-table-list Adds dbEnvCreateHint, dbTableGetHint, and dbTableListHint with actionable cross-command guidance (e.g. pointing at +db-table-list for env conflicts, +db-env-create for missing dev env). Wraps only the CallAPITyped failure branch; requireAppID validation errors are left untouched. * refactor(apps): make session-stop hint runnable and align hint test names * test(apps): guard withAppsHint upstream-wins contract and new hint leak safety * test(apps): add help-skill command consistency gate --------- Co-authored-by: linchao5102 <linchao.5102@bytedance.com> Co-authored-by: Wang <wangjiangwen@bytedance.com> Co-authored-by: wangjiangwen-gif <286006750+wangjiangwen-gif@users.noreply.github.com> Co-authored-by: 陈兴炀 <chenxingyang.1019@bytedance.com> Co-authored-by: aihao-git <aihao.0331@bytedance.com> Co-authored-by: bali <bali@bytedance.com> Co-authored-by: hunnnnngry <chenxi.xichen@bytedance.com> Co-authored-by: shengdongyc <1135978761fsd@gmail.com> Co-authored-by: fushengdong.1 <fushengdong.1@bytedance.com> |
||
|
|
501bf539af |
feat(im): complete audio/post rendering and add opt-in --download-resources (#1245)
Block 1 — field completion: audio renders <audio key="..." duration="Xs"/> (falls back to [Voice: Xs]/[Voice]); post renders emotion -> :emoji_type:, applies text.style (bold/italic/underline/lineThrough), passes through md; sticker unchanged. Block 2 — opt-in --download-resources (default off) on +chat-messages-list, +messages-mget, +threads-messages-list: extract downloadable resource refs during formatting (image/file/audio/video/media + post-embedded; sticker excluded; merge_forward sub-items carry the top-level container message_id, since the resources endpoint rejects sub-item ids with "234003 File not in msg" and can only fetch a forwarded resource through the container; thread replies get their own block), then download each distinct (message_id, file_key) once into ./lark-im-resources/ with bounded concurrency (3), filling back local_path/size_bytes; single-resource failures are isolated (error:true + stderr warning). Path safety reuses normalizeDownloadOutputPath + ResolveSavePath. Batch download keys each file on disk by its unique file_key basename and only appends an extension (from the Content-Disposition filename or MIME type) — it does NOT substitute the server's Content-Disposition filename. Otherwise two resources whose servers return the same filename (e.g. download.bin) would resolve to the same ./lark-im-resources/ path and clobber each other concurrently. The friendly "adopt the server filename" behavior is kept only for an explicit +messages-resources-download with no --output. Resource ref extraction guards against self-referential / cyclic merge_forward prefetch maps (a real API sub-item list can include the container's own id or a back-pointing merge_forward) via a visited set, so extraction terminates instead of overflowing the stack. The container message_id is threaded through nested merge_forwards as the download owner. Also: document the feature (including the im:message:readonly scope requirement) in skills/lark-im — SKILL.md is generated from skill-template/domains/im.md (edit the source), plus the hand-written message-enrichment + 3 command references. Change-Id: I3a71d7d1b193130f551aaa2ec180ac1500d59ac4 Meego: https://meego.larkoffice.com/5e96d7bff4e7c525510f9156/story/detail/7331555925 |
||
|
|
e751a53f76 |
feat(markdown): emit typed error envelopes across the markdown domain (#1347)
Emit structured validation, API, network, file, and internal error envelopes for Markdown shortcuts so users and agents can recover from failed markdown workflows using stable type, subtype, param, and code fields. Add Markdown domain errscontract and golangci guards to prevent legacy envelope and common helper regressions. |
||
|
|
077b5e7180 |
feat: configure initial base table schema (#1377)
* feat: configure initial base table schema * fix: add base create table scopes |
||
|
|
0d20a02050 | feat: replace words for transcript (#1372) | ||
|
|
6b48a39d55 |
feat(slides): emit typed error envelopes across the slides domain (#1349)
Emit structured validation, API, network, file, and internal error envelopes for Slides shortcuts so users and agents can recover from failed presentation workflows using stable type, subtype, param, and code fields. Add Slides domain errscontract and golangci guards to prevent legacy envelope and common helper regressions. |
||
|
|
b07be60068 |
feat(sheets): emit typed error envelopes across the sheets domain (#1348)
Emit structured validation, API, network, file, and internal error envelopes for Sheets shortcuts so users and agents can recover from failed spreadsheet workflows using stable type, subtype, param, and code fields. Add Sheets domain errscontract and golangci guards to prevent legacy envelope and common helper regressions. |
||
|
|
201e3e016f |
feat(doc): emit typed error envelopes across the doc domain (#1346)
Emit structured validation, API, network, file, and internal error envelopes for Doc shortcuts so users and agents can recover from failed document workflows using stable type, subtype, param, and code fields. Add Doc domain errscontract and golangci guards to prevent legacy envelope and common helper regressions. |
||
|
|
eed711bb11 |
feat(sheets): guard +csv-put --csv against a path passed without @ (#1337)
+csv-put --csv data.csv (a forgotten @) was silently written as one-cell content, because any string parses as valid CSV — unlike malformed JSON it never errored, so the filename landed in the sheet instead of the file's contents. +csv-put's Validate now rejects a --csv value when it names a real file in the cwd subtree (guardCSVValueIsNotFilePath; fileIO.Stat, fail-open), hinting to use --csv @file or stdin (--csv -). Scoped to --csv only — no framework or other-flag change. Checking real existence (not name shape) lets inline content that merely ends in a filename pass through. Adds TestGuardCSVValueIsNotFilePath. |
||
|
|
2b4c6349a1 |
feat(event): emit typed error envelopes across the event domain (#1289)
Replace every command-facing error path in the event domain — the consume/schema command layer, the +subscribe shortcut, EventKey definitions, and the consume orchestration — with typed errs.* envelopes, so consumers get stable type, subtype, param, hint, and missing_scopes metadata for classification and recovery instead of free-form message text. - Input validation (--jq, --param, --output-dir, --filter, --route, unknown EventKey, EventKey params) reports validation / invalid_argument with the offending flag in param and an actionable hint. - Scope preflight reports authorization / missing_scope with the machine-readable missing_scopes list; console-subscription and single-bus preconditions report failed_precondition with recovery hints. - The consume API boundary passes already-typed errors through and classifies transport, non-JSON HTTP, and unparsable responses; the vc note-detail retry now matches the not-found code on typed errors (it silently never fired against the legacy envelope shape). - Previously-bare failures exited 1 with a plain-text "Error:" line and now exit with their category code (validation 2, auth 3, network 4, internal 5) alongside the typed stderr envelope. - forbidigo and errscontract guards now cover the event paths so regressions fail lint; AGENTS.md and the lark-event skill document the typed contract for agent consumers. Validation: make unit-test (race) green; event unit and e2e suites assert category/subtype/param/hint and cause preservation against the real binary; errscontract and golangci lint clean. |
||
|
|
7229baae40 | fix: clarify --block-id supports comma-separated batch delete in help text (#1336) | ||
|
|
170565c57e | fix: add @file/stdin support to drive +add-comment --content (#1343) | ||
|
|
03ea6e78b8 | feat(contact): emit typed error envelopes across the contact domain (#1287) | ||
|
|
ed3fe9337f |
fix(slides): build create URL locally instead of drive metas call (#1329)
slides +create finished by calling /drive/v1/metas/batch_query just to fetch the presentation URL. That call needs a drive scope the shortcut never declares, so it 403'd for users who only authorized slides scopes (both UserAccessToken re-auth and TenantAccessToken scope-not-opened), producing a large share of the shortcut's failure telemetry — even though the presentation itself was already created successfully. slides creation never otherwise touches drive, so rather than gating a drive-free operation behind a drive scope, build the URL locally from the token via common.BuildResourceURL (the same brand-standard-host fallback already used by drive +upload / wiki +node-create). The URL is now always returned, no extra scope is required, and creation never blocks. Tests are updated to match: drop the registerBatchQueryStub helper and its call sites (the httpmock Verify cleanup was failing on the now-unconsumed batch_query stubs), point url assertions at the brand-standard host, and replace TestSlidesCreateURLFetchBestEffort with TestSlidesCreateURLBuiltLocally, which asserts the url is produced with no drive call registered. |
||
|
|
99ceb2279c |
feat(markdown): harden create upload failures (#1325)
* feat(markdown): harden create upload failures * test(markdown): address AI review follow-ups |
||
|
|
281cdbd37c | feat(drive): harden inspect shortcut failures (#1324) | ||
|
|
076f4d579f |
feat(minutes,vc): emit typed error envelopes across both domains (#1234)
Failures from the minutes and video-conference commands now surface as structured, typed errors carrying a stable category and subtype — spanning input validation, missing permissions, network and file-I/O failures, and remote API errors — so callers can branch on the error kind instead of parsing free-form text. Batch commands report partial failures explicitly, emitting per-item results with a non-zero exit instead of masking them. |
||
|
|
0c2fd08d5a |
feat:remove docs v1 api (#1291)
Change-Id: I29d0af3e5325261f94949d3ab3f65051fb6bd52b |
||
|
|
e1bb9db552 | feat(im): format feed group error handling (#1308) | ||
|
|
7c50b3d9e3 |
feat: fetch official skills index (#1301)
lark-cli update currently discovers official skills by parsing unstable human-oriented `skills add --list` output. This prefers the stable official JSON index for skills discovery, while preserving the existing CLI-list fallback and full-install fallback for resilience. Changes: - Add official skills index JSON parsing in `internal/skillscheck/sync.go` - Prefer JSON index discovery before existing CLI list parsing in `internal/skillscheck/sync.go` - Add reason-chain details when both discovery layers fall back to `fallbackFullInstall` - Add bounded HTTPS fetch for `https://open.feishu.cn/.well-known/skills/index.json` in `internal/selfupdate/updater.go` - Add unit tests for parser behavior, discovery fallback order, and fallback detail reasons in `internal/skillscheck/sync_test.go` Co-authored-by: zhaoyukun.yk <zhaoyukun.yk@bytedance.com> |
||
|
|
5788a6c384 | feat(im): return typed error envelopes across the im domain (#1230) | ||
|
|
bd07859c90 |
feat(im): cli support feed group (#1102)
Add IM feed group support documentation for lark-cli, making the raw im feed.groups.* APIs discoverable and easier for agents to use correctly. |
||
|
|
8c3cba17b2 |
feat(task): emit typed error envelopes across the task domain (#1231)
Task commands now return structured, typed errors instead of the legacy exit-code envelope: every failure carries a stable category, subtype, and recovery hint, so callers can branch on the error class instead of parsing messages. Exit codes derive from the error category — input validation exits 2, a permission denial exits 3, other API errors exit 1. Batch operations (adding tasks to a tasklist, creating a tasklist with tasks) now report partial failure honestly: the per-item successes and failures stay on stdout and the command exits non-zero instead of masking failures as a success. |
||
|
|
6367aaa0f5 |
feat(okr,whiteboard): emit typed error envelopes across both domains (#1236)
The okr and whiteboard commands now report every failure as a typed error envelope. Invalid flags, malformed input, output-file conflicts, and API or transport failures alike carry a stable category, subtype, the offending flag or Lark error code, and a meaningful exit code — so scripts and agents can branch on the error shape instead of scraping message strings. |
||
|
|
be5527ca4e |
feat(im): add feed shortcut create, list, and remove shortcuts (#1273)
Adds feed shortcut management to the im domain: pin chats to the user's feed sidebar, list pinned entries, and unpin them. Three new shortcuts wrap the im/v2/feed_shortcuts OpenAPI routes, which currently expose CHAT-type entries only and accept user identity only. |
||
|
|
f3949f04c4 |
feat(calendar): emit typed error envelopes across the calendar domain (#1232)
Calendar commands now return structured, typed error envelopes for every failure mode — input validation, internal faults, and API responses — instead of legacy generic errors. Callers and AI agents get consistent exit codes and a machine-readable shape (type / subtype / code / hint), and can tell bad input, an internal fault, and an API rejection apart. Validation errors are attributed to the offending flag. Server-supplied error details (e.g. why an event time was rejected) are surfaced on the typed error's hint via a shared classifier improvement that benefits every domain. Multi-step operations (create-with-attendees rollback, multi-field update) preserve the real failure's classification and report which steps completed. The whole calendar domain is now lint-locked against reintroducing legacy error constructors. |
||
|
|
62364fc320 | fix(drive): use docs secure label read scope (#1281) | ||
|
|
3990151122 | feat(base): emit typed error envelopes across the base domain (#1248) | ||
|
|
ac116e7ca3 |
feat(drive): add drive preview and cover shortcuts and document quota details (#1259)
* feat: support get quota detail * feat: add drive preview and cover shortcuts - add `drive +preview` and `drive +cover` shortcuts - wrap `preview_result` output with stable preview item fields - support cover download via `preview_download` with validated preset mappings - update lark-drive skill references for preview and cover usage * fix(drive): classify cover 404 as failed precondition * fix(drive): show preview download step in dry-run * docs(drive): clarify quota details user-only usage * fix(drive): soften cover 404 guidance |
||
|
|
5e6a3eb857 |
feat(mail): return typed error envelopes across the mail domain (#1250)
* feat(mail): return typed error envelopes across the mail domain Replace every produced error path in shortcuts/mail with typed errs.* envelopes, so consumers get stable category, subtype, param/params, hint, retryable, and log_id metadata for classification and recovery instead of free-form message text. - Locally constructed mail errors move from output.Err* / output.Errorf / final fmt.Errorf / common legacy helpers to errs.* builders, with structured params on multi-flag validation and failed-precondition states kept non-retryable. - API-call failures move from runtime.CallAPI / DoAPIJSON legacy boundaries to runtime.CallAPITyped or runtime.ClassifyAPIResponse, and mail-specific enrichers read errs.ProblemOf so typed code, subtype, hint, and log_id metadata are preserved. - Batch draft-send partial failures now use runtime.OutPartialFailure so successful and failed draft sends stay in stdout while the command exits through a typed multi-status signal. - Add mail-domain typed helpers, mail API code metadata, and guard wiring to keep shortcuts/mail from reintroducing legacy envelopes or legacy API calls. - Keep genuine intermediate fmt.Errorf wraps in parser/builder layers annotated with nolint comments; command-facing paths wrap them into typed validation, API, network, or internal errors. * fix(mail): report aborted draft-send batches as a single failure result When an account-level failure interrupts a batch send after some drafts already went out, the command previously produced two machine-readable failure results: the partial-failure ledger on stdout and a second error envelope on stderr. Consumers could not tell which one to recover from. The batch ledger is now the only failure result for that case: it gains aborted and abort_error fields carrying the typed cause, so callers can see which drafts were sent, which failed, why the batch stopped, and how to recover — all from stdout. A --stop-on-error stop keeps these fields unset because stopping early there is the caller's own choice. |
||
|
|
a82a486508 |
feat(mail): preserve mailbox context in +triage output for public mailboxes (#1238)
When triaging a public/shared mailbox, downstream AI consumers (e.g.
mail +message) need the mailbox_id to construct correct API paths.
Previously the triage output only included message_id, causing
/user_mailboxes/me/messages/{id} lookups that fail for public mailboxes.
- Add mailbox_id field to every normalized message in structured output
- Add mailbox_id to top-level JSON/data output envelope
- Add mailbox_id to table rows when mailbox is not "me"
- Update stderr next-step tip to include --mailbox for non-me mailboxes
- Update next-page hint to include --mailbox for non-me mailboxes
- Add unit tests covering list, search, and public mailbox paths
- Update triage skill docs to show mailbox_id in output examples
|
||
|
|
b07a6003f9 |
feat(sheets): spec-driven shortcut refactor with backward-compatible package (#1220)
* refactor(sheets): rebuild lark-sheets on sheet-skill-spec canonical + One-OpenAPI
Restart lark-sheets as a spec-driven downstream. Skill content (SKILL.md
and 16 references covering 13 operations skills + 3 workflow skills,
including the standalone filter-view skill) is mirrored from the
sheet-skill-spec canonical-spec; do not hand-edit, change upstream and
rerun npm run sync:consumers.
Drop the 11 legacy shortcut sources (spreadsheet / sheet management,
cell ops, dropdown, filter-view, float image, etc.) and 10 associated
tests. Wire up the new sheet_ai/v2 One-OpenAPI single entry that
dispatches by tool_name with JSON-string input/output, and land the
first canonical shortcut +workbook-info as a template that exercises
the public token XOR pair, Risk tiering, and zero-side-effect DryRun.
sheet_ai_api.go provides callTool / invokeToolDryRun and bypasses
runtime.CallAPI's silent swallowing of non-envelope responses so
gateway and business errors from the new endpoint surface precisely.
The remaining 55 shortcuts will be designed and landed separately,
canonical skill by canonical skill.
* feat(sheets): implement lark_sheet_workbook shortcuts (B1)
Land the 8 modify_workbook_structure shortcuts that round out the
lark_sheet_workbook canonical skill alongside the existing +workbook-info:
+sheet-create / +sheet-delete / +sheet-rename / +sheet-move / +sheet-copy
/ +sheet-hide / +sheet-unhide / +sheet-set-tab-color. All eight call
modify_workbook_structure via the One-OpenAPI invoke_write endpoint,
dispatched by the `operation` enum.
Helpers in helpers.go grow publicSheetFlags() / resolveSheetSelector() /
sheetSelectorForToolInput() / sheetSelectorPlaceholder() so future
sheet-level shortcuts share the public --sheet-id / --sheet-name XOR
treatment. +sheet-create intentionally drops the sheet selector pair since
create has no existing-sheet anchor (matches the spec fix in
tool-shortcut-map.json).
+sheet-delete is the first high-risk-write shortcut in the canonical
package; the framework requires --yes (exit code 10 otherwise).
+sheet-move's tool requires source_index in addition to target_index. The
CLI accepts an optional --source-index override and falls back to a
single get_workbook_structure read to derive it (and to resolve sheet_id
from --sheet-name). DryRun stays network-free by rendering <resolve>
placeholders for any field that would need that read.
* feat(sheets): implement lark_sheet_sheet_structure shortcuts (B2)
Add 8 shortcuts under the lark_sheet_sheet_structure canonical skill:
+sheet-info (get_sheet_structure) plus +dim-insert / +dim-delete /
+dim-hide / +dim-unhide / +dim-freeze / +dim-group / +dim-ungroup
(modify_sheet_structure, dispatched by operation enum).
Two reusable conversion helpers cover the impedance mismatch between
the CLI surface and the tool input:
- dimRange / dimPosition translate the CLI's 0-based exclusive-end
range into the tool's 1-based A1 notation. row 5..8 becomes
position "6" + count 3 (insert) or range "6:8" (range ops); column
26..29 becomes "AA:AC".
- infoTypeFromInclude maps the fine-grained --include vocabulary
(row_heights / col_widths / merges / hidden_rows / hidden_cols /
groups / frozen) to the coarse info_type enum the tool accepts;
mixed categories collapse to "all".
+dim-delete is high-risk-write (irreversible row/column removal).
+dim-freeze --count 0 auto-dispatches to operation=unfreeze. +dim-group
accepts --depth for forward-compat with a future server-side nested
group endpoint but does not pass it through today.
* feat(sheets): implement read_data / search_replace / write_cells shortcuts (B3)
Land 11 shortcuts across three canonical skills:
- lark_sheet_read_data (3): +cells-get / +csv-get / +dropdown-get
- lark_sheet_search_replace (2): +cells-search / +cells-replace
- lark_sheet_write_cells (6): +cells-set / +cells-set-style / +csv-put
/ +dropdown-set / +dropdown-update / +dropdown-delete
+dropdown-get reads the data_validation field via get_cell_ranges with
the range carrying its own sheet prefix (no --sheet-id needed). The
fine-grained --include vocabulary (value / formula / style / comment /
data_validation) maps to the tool's coarse include_styles bool plus
value_render_option enum. +csv-get's --include-row-prefix=false strips
the [row=N] prefix client-side because the tool only emits the
annotated form.
+cells-search / +cells-replace flatten the tool's options sub-object
into four independent flags (--match-case / --match-entire-cell /
--regex / --include-formulas) per the flat-flag rule, then repack them on the way
in.
+cells-set takes a raw --data JSON body whose `cells` array must match
the --range dimensions. +cells-set-style fans a single --style block
out to every cell in the range via a new fillCellsMatrix helper; the
range parser (rangeDimensions / splitCellRef / letterToColumnIndex)
only accepts rectangular A1:B2 forms — whole-column / whole-row need
sheet totals and are deferred.
+dropdown-set fans the validation block out to one range; +dropdown-
update / +dropdown-delete iterate sheet-prefixed --ranges and call
set_cell_range sequentially (partial failure leaves earlier ranges
already mutated; the Tip calls this out). +dropdown-delete is
high-risk-write and requires --yes.
+cells-set-image stays deferred to the cli-only batch (needs the
shared local-file upload helper alongside +workbook-create / +dim-move
/ +workbook-export).
* refactor(sheets): move +dropdown-update / +dropdown-delete to lark_sheet_batch_update
Follow-up to B3 after the spec re-mapped these two shortcuts to the
batch_update tool (atomic multi-range CRUD) instead of fan-out via
set_cell_range. Drop their Go implementations + helper validateDropdownRanges
+ splitSheetPrefixedRange from lark_sheet_write_cells.go and remove the
registrations from Shortcuts(); the shortcuts will reappear under
lark_sheet_batch_update during B7.
Also pull in the re-rendered reference docs:
- skills/lark-sheets/references/lark-sheets-write-cells.md
- skills/lark-sheets/references/lark-sheets-batch-update.md
* feat(sheets): implement lark_sheet_range_operations shortcuts (B4)
Land 8 shortcuts across four canonical tools:
- clear_cell_range → +cells-clear (high-risk-write)
- merge_cells → +cells-merge / +cells-unmerge
- resize_range → +dim-resize
- transform_range → +range-move / +range-copy / +range-fill / +range-sort
Three CLI↔tool vocabulary bridges live in this file:
- +cells-clear: --scope content normalizes to the tool's clear_type
"contents" (singular/plural spec mismatch is absorbed in the CLI).
- +dim-resize: --size <px> wraps as resize_{height,width}:{value:N};
--reset wraps as {reset:true}. The two flags are mutually exclusive
and at least one is required.
- +range-fill: CLI's five-valued --series-type collapses to the tool's
binary fill_type — `copy` → "copyCells", anything else → "fillSeries"
(the actual series progression is inferred server-side from the
seed cells in --source-range).
- +range-copy: --paste-type {values, formulas, formats} maps to the
tool's {value_only, formula_only, format_only}; "all" omits the
field entirely so the server applies its default.
+cells-clear is the second high-risk-write shortcut in the package;
the framework enforces --yes with exit code 10 as usual.
* feat(sheets): implement object-list shortcuts (B5)
Land 7 read shortcuts, one per object skill — chart / pivot table /
conditional format / filter / filter view / sparkline / float image. All
share the same shape (public sheet selector + optional <obj>-id filter)
so they're declared via newObjectListShortcut + an objectListSpec.
Notes:
- +cond-format-list exposes --rule-id, which is renamed to
conditional_format_id on the wire (the tool's full field name).
- +sparkline-list exposes --group-id (the higher-level handle); the
tool also accepts sparkline_id, intentionally not surfaced.
- +filter-list takes no id filter — at most one sheet-level filter
per sheet, so the listing is already unique.
- +filter-view-list is `cli_status: cli-only` but get_filter_view_objects
is in mcp-tools.json and dispatches through the same One-OpenAPI
endpoint; no special path required.
* feat(sheets): implement object CRUD shortcuts (B6)
Land 21 shortcuts — three (create / update / delete) per object skill —
backed by the manage_<obj>_object tools dispatched on the operation
enum. Five standard objects (chart / cond-format / sparkline /
float-image / filter-view) share an objectCRUDSpec factory; pivot and
filter are special-cased.
Shared wire contract:
excel_id + sheet_id|sheet_name + operation + [<obj>_id] + [properties]
CLI --data is passed through as the tool's `properties` field as-is, so
callers shape it per each object's spec doc.
Special cases:
- pivot adds optional --target-sheet-id / --target-position on create
(siblings of properties, not inside it).
- cond-format exposes --rule-id (short CLI name) wired to the tool's
conditional_format_id on the wire.
- sparkline uses --group-id (higher-level object handle) instead of
sparkline_id.
- filter has no separate id flag — at most one filter per sheet, so
filter_id is implicit. +filter-create promotes --range to a first-
class flag (instead of burying it inside --data).
- filter-view CRUD are `cli_status: cli-only` but
manage_filter_view_object is in mcp-tools.json, so they go through
callTool / One-OpenAPI alongside everything else.
All delete shortcuts are high-risk-write and require --yes.
* feat(sheets): implement lark_sheet_batch_update shortcuts (B7)
Land 4 shortcuts that all funnel through the batch_update tool's atomic
operations array:
- +batch-update raw passthrough; --data carries the full
{ operations: [{tool, params}, ...] } payload
plus optional continue_on_error. high-risk-write
since the caller may stuff anything inside.
- +cells-batch-set-style --data is [{ranges, style}, ...]; CLI flattens
each (entry × range) pair into a set_cell_range
op with a fan-out cells matrix carrying
cell_styles + border_styles.
- +dropdown-update --ranges + --options (+ --colors / --multiple /
--highlight) — installs/replaces one dropdown
across many ranges, each becoming a separate
set_cell_range op with data_validation in cells.
- +dropdown-delete --ranges — clears data_validation across many
ranges (high-risk-write).
Default is strict transaction: if any sub-tool fails the whole batch rolls
back. +batch-update exposes --continue-on-error to flip the policy; the
three fan-out shortcuts leave it strict (they're meant to be all-or-nothing).
Reinstates validateDropdownRanges + splitSheetPrefixedRange that were
removed during B3 → B7 relocation.
* feat(sheets): implement cli-only shortcuts (B8) — 70/70 complete
Land the four cli-only shortcuts that can't route through the One-OpenAPI
dispatcher (their backing capabilities aren't in mcp-tools.json):
- +workbook-create POST /open-apis/sheets/v3/spreadsheets
+ optional set_cell_range follow-up that zips
--headers and --data into the first sheet starting
at A1.
- +workbook-export POST /open-apis/drive/v1/export_tasks (type=sheet)
→ poll /export_tasks/:ticket up to ~30s
→ optional GET /export_tasks/file/:file_token/download.
CSV mode requires --sheet-id (single sheet export).
- +dim-move POST /open-apis/sheets/v2/spreadsheets/:token
/dimension_range
CLI is 0-indexed inclusive (--start / --end); the v2
endpoint expects half-open [startIndex, endIndex)
so the body uses endIndex = --end + 1. --sheet-name
is resolved client-side to sheet_id via
lookupSheetIndex when needed.
- +cells-set-image common.UploadDriveMediaAll
(parent_type=sheet_image, parent_node=token)
then callTool set_cell_range with cells carrying
rich_text: [{type:"embed-image", attachment_token, attachment_name}].
--range must be exactly one cell.
All four use runtime.CallAPI / DoAPI directly; only +cells-set-image
combines a legacy upload with the new One-OpenAPI for the second step
(set_cell_range is in mcp-tools.json so callTool is the right path).
This closes the migration: 70 shortcuts × 17 canonical skills × matching
the sheet-skill-spec v0.5.0 tool-shortcut-map.
* test(sheets): cover all 70 shortcuts with dry-run + execute-path tests
Twelve _test.go files alongside the implementation, mirroring the legacy
package's coverage style:
- testhelpers_test.go shared rig: TestFactory + Mount + dry-run
capture + JSON-input decode + envelope helpers.
- lark_sheet_*_test.go one test file per implementation file (9
files), table-driven dry-run cases per shortcut
plus targeted validation guards.
- execute_paths_test.go end-to-end execute paths via httpmock stubs.
Covers callTool unwrap, JSON-string output
decoding, two-step lookup (+sheet-move),
batch_update fan-out, dropdown atomic writes,
and the legacy OAPI shortcuts (+workbook-create,
+dim-move) including CLI inclusive → API
half-open index conversion.
Test coverage on the sheets package is 60.5 % of statements with -race
clean, meeting the dev manual's ≥ 60 % patch-coverage gate.
* refactor(sheets): inline cli-only shortcuts into their canonical skill files
Two naming cleanups:
- lark_sheet_cli_only.go is gone. The four shortcuts it grouped
(+workbook-create / +workbook-export / +dim-move / +cells-set-image)
were bundled by their implementation pattern (legacy OAPI direct
calls) rather than by canonical skill. The whole sheets package IS
the CLI implementation, so "cli only" wasn't a meaningful grouping
at the Go layer. Each shortcut now lives next to its skill peers:
+workbook-create / +workbook-export → lark_sheet_workbook.go
+dim-move → lark_sheet_sheet_structure.go
+cells-set-image → lark_sheet_write_cells.go
Per-skill shortcut counts now match tool-shortcut-map.json exactly
(workbook: 11, sheet_structure: 9, write_cells: 5). Helpers
(buildInitialFillInput, pollExportTask, downloadExportFile,
dimMoveBody) move with their shortcuts; nothing else in the package
referenced them.
- testhelpers_test.go → helpers_test.go. The _test.go suffix already
conveys "test"; the leading "test" was redundant. Matches the
helpers.go naming convention.
Behavior unchanged. go test -race -cover stays at 60.5 %.
* refactor(sheets): sync shortcut flags with sheet-skill-spec v0.5.0
Upstream hoisted a batch of high-frequency scalar fields out of --data
into independent flags and renamed several composite-JSON flags to
match their semantic content. CLI catches up.
Renames (drop-in, same payload semantics):
- +cells-replace --replace → --replacement
- +cells-set --data → --cells
- +workbook-create --data → --values
- +batch-update --data → --operations (now a bare array;
still accepts the envelope form for
back-compat with continue_on_error)
Flat-flag hoists out of --style / --data:
- +cells-set-style / +cells-batch-set-style
--style JSON drops; replaced by 11 flat style flags
(--background-color / --font-color / --font-size / --font-style /
--font-weight / --font-line / --horizontal-alignment /
--vertical-alignment / --word-wrap / --number-format) plus
--border-styles for the one field that's still nested. Both
shortcuts share styleFlatFlags() + buildCellStyleFromFlags().
- +cells-batch-set-style also drops the [{ranges, style}] array shape
in favor of one --ranges + the same flat style flags applied to
all of them.
Object CRUD --data → --properties everywhere (chart / pivot / cond-format
/ filter / filter-view / sparkline / float-image). Per-skill scalar
hoists merged into properties via an enhanceCreate/UpdateInput callback:
- +pivot-create adds --source (required), --range
(and continues to expose --target-sheet-id /
--target-position at top level)
- +cond-format-{create,update}
adds --rule-type (enum) + --ranges (JSON array);
merged into properties.rule.type and
properties.ranges respectively
- +filter-view-{create,update}
adds --view-name and --range; both override
their properties.* counterparts
- +filter-update adds first-class --range (was buried in --data)
Float-image is fully hoisted — no --properties flag at all. Ten flat
flags (--image-name / --image-token | --image-uri / --position-row /
--position-col / --size-width / --size-height / --offset-row /
--offset-col / --z-index) compose the properties block. Implemented as
its own factory (newFloatImageWriteShortcut) since it diverges from the
shared CRUD spec.
Tests track every flag renamed and add explicit cases for the new flag
combos. go test -race -cover stays at 60.3 %.
* refactor(sheets): align batch_update + cells-set with synced reference docs
Sync to upstream reference doc updates for 9 skills:
- batch_update sub-ops: rewrite wire fields tool/params -> tool_name/input
in CellsBatchSetStyle and DropdownUpdate/Delete fan-out (the actual
server contract per Schemas section); update --operations flag desc
and tests.
- +cells-set --cells: accept bare 2D matrix [[{cell},...],...] instead
of envelope {"cells":[[...]]}; spec example shows bare-array form.
- sparkline createDataDesc enum: win_loss -> winLoss (camelCase).
All other doc changes (float-image flat flags, cond-format
--rule-type/--ranges, pivot create-only --source/--range, filter /
filter-view extra flags, chart --properties) were already aligned in
commit
|
||
|
|
03a589978f | feat(vc): forward invite call-id on meeting join (#1243) | ||
|
|
b3fcf55611 |
feat(common): emit typed validation errors from shared shortcut pre-checks (#1242)
Input pre-check failures shared by every shortcut — @file/stdin input resolution, enum validation, and unsupported --dry-run — now leave the CLI as typed validation envelopes naming the offending flag, so scripts and AI agents can branch on `param` instead of parsing prose. Wire type, exit code, and message text are unchanged; the new fields are additive. The shared layer also gains typed replacements for its legacy error-producing helpers, so each business domain can migrate to typed errors without rebuilding common plumbing, and a path-scoped lint guard keeps migrated domains from sliding back. Changes: - Shared pre-check failures (input flags, enum values, dry-run support) return typed validation errors carrying the offending flag as `param`. - Every legacy error-producing helper in shortcuts/common has a typed replacement that preserves the existing message text: validation and flag-group checks, chat/user ID validation (callers name the flag so `param` is ground truth), "me" open-id resolution, safe-path checks, input-stat and save-error wrapping. Legacy helpers stay for not-yet-migrated domains, marked deprecated — including the legacy API-result classifier, whose typed route is runtime.CallAPITyped. - A new errscontract rule rejects legacy common-helper calls on migrated paths, so a migrated domain cannot silently reintroduce legacy envelopes; drive is the first locked path and its last legacy ID-helper calls are replaced. |
||
|
|
2f35ce3724 |
feat: complete card message format (#1198)
The card message converter (shortcuts/im/convert_lib/card.go) previously rendered a subset of card fields and had several mode-gated behaviors that caused information to be silently dropped in concise mode. This PR audits every element handler and brings the output up to full fidelity: missing header fields are rendered, collapsible panels always expand, rich element metadata (images, audio, video, overflow URLs, person names) is no longer hidden behind cardModeDetailed, and several format bugs are fixed. Change-Id: I422474ab6b7505e48ab5697793900df035be6e29 |
||
|
|
7e7f716a82 |
feat(base): add base block shortcuts (#1044)
* feat(base): add base block shortcuts * fix(base): use block scopes for base block shortcuts * fix(base): split base block shortcut scopes * docs(base): consolidate base block help * docs(base): simplify block help wording * test(base): cover base block shortcut execution * feat(base): filter base block list by type * docs(base): clarify base block ids * docs(base): simplify docx block help * docs(base): refine base block agent help |
||
|
|
1670a794f6 |
feat(mail): add message_ids validation in +messages before batch_get (#1202)
Add CLI-side validation for --message-ids in the mail +messages shortcut to catch obviously invalid inputs before making any API call. The batch_get endpoint would otherwise only reject malformed IDs server-side, returning unclear errors. Validation rules: - Reject empty message-ids list - Reject entries exceeding the server-mirrored batch limit of 20 IDs - Reject entries with leading/trailing whitespace - Reject entries containing control characters, whitespace, or path separators - Reject duplicate message IDs sprint: S2 |
||
|
|
85c7280d8b |
feat(wiki): support appid member type (#1235)
CCM-Harness: code |