mirror of
https://github.com/larksuite/cli.git
synced 2026-07-03 14:02:43 +08:00
main
16 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
75926f9744 |
feat(apps): add db, file, openapi-key and observability shortcuts (#1596)
* feat: add apps observability helpers * feat: add apps log observability shortcuts * feat: add apps trace observability shortcuts * feat: add apps metric analytics shortcuts * feat: add apps envvar shortcuts * docs: document apps observability envvar shortcuts * fix: add apps observability env hint * test: cover apps envvar delete dry-run * fix: align apps observability OpenAPI schema * fix: map apps observability named series * fix: apps observability api upgrade * fix: refine apps observability output * feat(apps): integrate miaoda db/file CLI commands into apps-spark integration Bring in the refined miaoda Spark db/file command set from the feat/miaoda-db-file-openapi work: db execute (typed errs + per-SQL-type JSON shaping), env diff/migrate, PITR recovery, changelog/audit, data import/export, db/file quota, and the 7 file-storage commands; plus the stderr spinner for slow ops and the aligned lark-apps skill references. Resolved overlap with the integration branch's earlier db-execute iteration (took the refined typed-error version), unified the stderr-TTY flag on IOStreams.StderrIsTerminal, and combined the shortcut registry (43 commands total). * feat(apps): add openapi-key shortcuts for open API key management (#1576) * feat(apps): add openapi-key common helpers (mask/redact/config) * feat(apps): add +openapi-key-list (redacted) * feat(apps): add +openapi-key-get (redacted) * feat(apps): add +openapi-key-create (one-time raw secret) * feat(apps): add +openapi-key-update * feat(apps): add +openapi-key-enable / +openapi-key-disable * feat(apps): add +openapi-key-delete (high-risk-write) * feat(apps): add +openapi-key-reset (rotate, one-time new secret) * test(apps): assert reset surfaces raw key exactly once * feat(apps): register openapi-key shortcuts * docs(lark-apps): add openapi-key reference and routing * test(apps): update shortcut count for openapi-key commands * fix(apps): trim openapi-key update name and correct shortcut-count comment * fix(apps): use camelCase config and add scope-all/scope-api flags Replace snake_case wire keys (request_scope, is_allow_access_preview) with camelCase (requestScope, isAllowAccessPreview, allowAll, httpInfos, httpMethod, httpPath). Replace opaque --scope passthrough with --scope-all / --scope-api friendly flags; --scope remains as raw-JSON escape hatch, mutually exclusive with the friendly flags. Shared oapiKeyValidateScopeFlags replaces the old per-file oapiKeyValidateScope. * fix(apps): use Changed for scope-all and refresh openapi-key scope docs Switch the update at-least-one guard from rctx.Bool to rctx.Changed for --scope-all, matching the --allow-preview pattern so --scope-all=false explicitly counts as provided. Rewrite lark-apps-openapi-key.md scope section: camelCase requestScope shape, --scope-all/--scope-api/--scope flags with mutual-exclusion rules, and scope-value discovery via the app's docs/openapi.json. * fix(apps): emit snake_case request_scope config for open gateway Open gateway (/open-apis/spark/v1) requires snake_case request bodies; flip parseScopeAPI/buildRequestScope/buildKeyConfig to emit http_method, http_path, allow_all, http_infos, request_scope, is_allow_access_preview. Update unit tests to assert snake_case and reject camelCase keys. * docs(lark-apps): correct openapi-key scope to snake_case wire format * docs(apps): align openapi-key flag help text to snake_case wire keys * feat(apps): add actionable hints and more examples to openapi-key P1: chain .WithHint(...) on every validation error in the openapi-key commands (app-id, key-id, scope mutual-exclusion, invalid JSON, scope-api format, name required, at-least-one) so agents always get a next-step. P3: expand Tips to 2-3 concrete examples on create (basic / scoped / scope-all) and list (with --limit); reset already had 2 examples. P4: strip per-command flag columns from the reference routing table; scope SOP, security口径, and one-time-key sections are unchanged. * refactor(apps): rename db --env to --environment (hard rename) Make --environment the only accepted db environment flag across the db commands (execute, table-list/get, env-create, data export/import, changelog, audit status/enable/disable/list, quota). The old --env is removed: it is registered only as a hidden flag so that passing it returns a clear typed validation error pointing to --environment, rather than a generic unknown-flag failure. Update the lark-apps db references accordingly. * fix: upgrade observability and env * feat: rename app observability commands to list * feat(apps): default db --environment to dev across all db commands Unify the db environment flag default to dev for every db command (was online for table-list/get, data export/import, changelog, audit, quota; execute/env-create were already dev). Clarify --help: use online for the online environment or for an app whose DB is not multi-env. Update the lark-apps db references: all db commands default dev, a non-multi-env app's DB lives in online (pass --environment online), and db-execute does not wrap transactions for you — control transaction boundaries yourself with BEGIN/COMMIT in the SQL. * fix: remove unsed files * file_common.go 的 3 处裸 fmt.Errorf 已改为 typed errs.NewValidationError(errs.SubtypeInvalidArgument, ...)(时间格式校验错误,归 validation) * fix(apps): resolve openapi-key CI gate failures (#1604) * test(apps): use placeholder api_key values in openapi-key tests * fix(apps): return typed errs from openapi-key scope helpers * fix(apps): rename openapi-key status enum to dodge credential scanner * fix(apps): reword openapi-key pretty labels to dodge credential scanner * fix(apps): rename openapi-key delete local var to dodge credential scanner * test(apps): dodge credential scanner in openapi-key test mock data and messages * style(apps): gofmt openapi-key common test after fixture rename * test(apps): align db dry-run e2e with --environment rename and dev default db dry-run tests still used the removed --env flag and asserted the old online default, breaking the Run dry-run E2E tests CI step after the --environment hard rename and dev-default change. Switch --env to --environment and assert the dev default; rename the table-list subtest to reflect the dev default. * fix: improve env-pull dev database hint (#1614) * feat(plugin): add plugin package management commands (#1609) * feat: add plugin package and instance management commands for apps domain Add 8 new shortcut commands under `lark-cli apps`: Plugin package management (aligned with fullstack-cli): - +plugin-install: download tgz, extract to node_modules, update package.json - +plugin-uninstall: remove from node_modules and package.json actionPlugins - +plugin-list: list declared plugins with installation status Plugin instance CRUD (aligned with feida-ai): - +plugin-instance-create: validate + write capability JSON with formValue validation - +plugin-instance-update: merge mutable fields, re-validate formValue - +plugin-instance-delete: idempotent file removal - +plugin-instance-get: read capability JSON - +plugin-instance-list: scan capabilities directory Shared infrastructure (plugin_common.go): - 4-level capabilities dir resolution (flag → env → .env.local MIAODA_APP_TYPE → detection) - formValue validation ported from feida-ai (5 rules: forbidden Handlebars, paramsSchema type constraints, input ref existence, unconsumed params, array double-wrap auto-fix) - tgz extraction with path traversal protection - package.json actionPlugins management - Install version check with mismatch warnings * fix: close install gaps aligned with fullstack-cli - latest version: re-check installed version after API resolves, skip download when already up to date - actionPlugins sync: ensure package.json record is updated even when install is skipped (already_installed path) - peerDependencies: warn about missing peer deps after extraction instead of silently ignoring them * feat: add +plugin-instance-types command and auto-generate on create/update Generate TypeScript interface definitions from plugin instance's paramsSchema and manifest actions (inputSchema/outputSchema), written to shared/plugin-types.ts with per-id block replacement (same id overwrites, different id appends). Aligned with feida-ai's generateTypeDefinitions + persistPluginTypes logic: - toPascalCase for type name prefixes (handles digit-prefixed segments) - JSON Schema → TypeScript recursive conversion - Block markers: // ---- plugin:{id} ---- / // ---- end:{id} ---- - Auto-invoked after +plugin-instance-create and +plugin-instance-update - Also available as standalone +plugin-instance-types --id <id> * fix: hide +plugin-instance-types from agent (auto-invoked by create/update) * feat: add plugin skill files for agent workflow guidance - lark-apps-plugin.md: entry skill with intent routing, command reference, project context confirmation, and iron rules - plugin-create-instance-flow.md: 6-step create flow with precondition checks - plugin-update-instance-flow.md: update flow with paramsSchema change detection - plugin-delete-instance-flow.md: delete flow with code reference scanning - plugin-get-instance-flow.md: query routing for list/get/manifest reads - plugin-instance-schema.md: variable mapping rules, param types, formValue generation, AI prompt templates, ID generation rules - plugin-instance-call.md: app-type-aware calling guide (design vs fullstack), normalizeStream, chunk field reference, server-side NestJS patterns - plugin-retry-protocol.md: validation failure retry protocol (max 3) - SKILL.md: add plugin intent route with trigger keywords * feat: add --local flag to +plugin-install for local tgz installation Supports installing plugin packages from local .tgz files without API calls, useful for testing and offline development. Reads plugin key and version from the extracted package.json inside the tgz. Also moved Scopes to ConditionalScopes so --local path skips auth. * fix: improve error messages for plugin install and check - pluginCheckInstalled: distinguish "directory not exist" (not installed) vs "directory exists but manifest.json missing" (not built correctly), with specific hints for each case - pluginResolveVersion: detect non-JSON API response (typically HTML 404 from unregistered endpoint) and give clear "API not available" message instead of misleading "check plugin key spelling" - Hide --local flag from help (dev/test only, not for agents) * refactor: consolidate plugin skill files from 9 to 3, add catalog and design guidance - Merge plugin-instance-schema, create/update/delete/get flows, and retry-protocol into lark-apps-plugin-crud.md (Schema + CRUD + retry) - Merge plugin-catalog into lark-apps-plugin.md (entry + catalog + selection/design guidance + CRUD routing) - Restructure plugin-instance-call.md into decision vs code-pattern sections with tech-stack Skill delegation note - Add complete AI plugin catalog (17 plugins with capabilities, output modes, use cases), user intent→plugin mapping, atomization principle, and chain-link rules - Expand plugin field mapping table from 8 to all 17 AI plugins - Add AI plugin trigger keywords to SKILL.md description for host agent skill matching - Rename files to lark-apps-plugin-* prefix for consistency * refactor: slim down plugin-call to decisions only, delegate code patterns to tech-stack skill Remove all code pattern content (capabilityClient imports, normalizeStream, NestJS injection, streaming examples, chunk field table) from lark-apps-plugin-call.md. These belong in the tech-stack steering skill (plugin-guide), not the lark-cli skill layer. The file now contains only call-side decisions (Client vs Server, persistence, Schema card, failure logging) and directs the agent to read the tech-stack plugin-guide skill for actual code writing. * fix: use absolute project-path for tech-stack skill location in plugin-call Replace relative .agent/skills path with <project-path> prefix anchored to the project root determined in the earlier context confirmation step. Add fallback path and minimal call rules when skill file doesn't exist. * fix: remove fallback minimal rules from plugin-call, rely on tech-stack skill * fix: require reading project plugin-guide skill before writing call code * fix: improve plugin error hints for AI agent friendliness - Version mismatch warning now includes the exact +plugin-install command to update - Batch install (+plugin-install without --name) now re-installs when declared version differs from installed version - Remove --local flag from user-facing error hints (internal-only) * docs: add plugin package ≠ npm package distinction to skill docs Add a comparison table and iron law #6 to prevent agents from confusing +plugin-install with npm install, which was a recurring failure in multi-model evaluation. * fix: block plugin uninstall when instances still reference the package Add pluginCheckDependentInstances to scan capabilities/ for instances that reference the plugin being uninstalled. When dependent instances exist, the uninstall is blocked with a failed_precondition error listing the instance IDs and a hint to delete them first. * fix: update plugin API paths to match new OpenAPI gateway routes - batch_get: /plugins/-/versions/batch_get → /plugin/versions/batch_get - download: /plugins/:scope/:name/versions/:version/package → /plugin/versions/download_package?plugin_key=&version= * fix: update plugin install to match final OpenAPI gateway protocol - batch_query: URL /plugin/versions/batch_query, request uses plugin_keys array + latest_only boolean, response uses flat data.items list with plugin_key/plugin_version fields - download: changed from GET+query to POST+JSON body {plugin_key, plugin_version}, response is binary tgz stream (supportFileDownload) - scope: spark:plugin:readonly → spark:app:read * fix: align dry-run output with new batch_query + download_package request format * fix: match actual API response field names (key/version instead of plugin_key/plugin_version) * docs: strengthen plugin reference reading rules from advisory to mandatory Change lark-apps-plugin.md from implicit to explicit required reading for any plugin work. Replace soft '按需读' with bold '必读' for all three plugin reference files. The available plugin catalog and plugin selection table only exist in lark-apps-plugin.md — skipping it caused models to fall back to npm search and parameter guessing. * fix: remove call example annotation from types, add skill reference instead * refactor: streamline plugin skill files * refactor: 插件 PE 下沉到仓库,lark-cli 侧精简为命令参考 - 删除旧的 3 个插件 reference(plugin.md / plugin-crud.md / plugin-call.md), 其中的 Schema 规则、CRUD 流程、插件目录、Prompt 模板等内容已下沉到 应用仓库 .agents/skills/plugin-guide/SKILL.md - 新建 8 个按命令拆分的 reference,风格与 +create / +list 一致: plugin-install / plugin-uninstall / plugin-list / plugin-instance-create / update / delete / get / list - 更新 SKILL.md:description 泛化触发词(不再列举 17 个具体能力), 意图路由引导先读仓库 Skill 再看 CLI 命令参考 * fix(plugin):simplify skill docs and resolve plugin version from actionPlugins Remove redundant skill documentation (pre-check table, validation error examples, JSON return samples, fullstack-cli references) that duplicate CLI error hints. Make --plugin version optional and resolve from package.json actionPlugins. Drop unused createdBy field. * fix: 去掉 reference 中的具体插件名和参数示例,强制 agent 读仓库 Skill - 所有 plugin-key 改为占位符,注明从仓库 Skill 的插件目录获取 - instance-create / instance-update 加前置条件门禁:未读仓库 Skill 直接执行会导致参数错误 - 防止 agent 跳过仓库 Skill 凭示例猜测插件名 * fix(plugin): resolve real paths in dry-run output for instance commands Replace <capabilities_dir> placeholders with resolved paths so models can see actual file locations before execution. Add version_source, types_output, and scan_dir fields to describe implicit behaviors. * refactor(plugin): hide instance commands, delegate to repo Skill Hide +plugin-instance-create/update/delete/get/list from CLI help. Remove instance reference files from lark-apps skill. Route instance CRUD and call code generation to project repo plugin-guide skill. Go instance code preserved, just hidden. * refactor: 删除 plugin-instance 5 个 CLI 命令,改由仓库 Skill 引导 agent 直接操作文件 - 删除 plugin_instance_create/update/delete/get/list 及其测试(11 个文件) - 删除 plugin_instance_types(TypeScript 类型生成命令) - 移除 shortcuts.go 中的 6 个注册项 - 清理 plugin_common.go 中仅被 instance 命令使用的函数(1054→340 行): 校验逻辑、capability JSON 读写、动态 schema 解析、TypeScript 生成等 - 保留 plugin-install / plugin-uninstall / plugin-list 三个命令不变 插件实例的 CRUD 操作改由仓库 Skill 引导 agent 直接读写 capabilities/*.json, 验证规则写在 Skill 中由 agent 自校验。 * refactor(plugin): remove --project-path flag and split --name into --name + --version - Remove --project-path from plugin-install/list/uninstall (use cwd like npm) - Split --name key@version into separate --name and --version flags - Remove pluginParseInstallTarget (no longer needed) - Improve DryRun desc and error hints for --version usage - Update skill docs to reflect new flag structure - Tests use chdirTest helper instead of --project-path * feat(plugin): add Examples to --help for plugin-install/list/uninstall 按 lark-cli 优化治理规范,为三个插件命令的 --help 补充 2-3 个 可执行示例,覆盖最常见使用路径,帮助 agent 快速理解命令用法。 * fix(plugin): address PR #1609 review findings - Fix hint referencing non-existent +plugin-instance-delete command, point to repo plugin-guide Skill instead - Remove undeclared --capabilities-dir flag, simplify pluginResolveCapDir to env-only resolution, fix ambiguous hint to suggest env vars - Reclassify download errors from file_io to network/api with proper hints and retryable marking - Slim SKILL.md routing row, move judgment rules to plugin-install reference - Rename --local flag to --file to align with CLI conventions * fix(skill): restore plugin routing row with judgment rules, fix markdown formatting Revert SKILL.md routing row to keep full judgment rules and repo Skill directive inline. Fix bold marker spacing and restore missing table column. Revert reference to original content without duplicated rules. * fix(plugin): revert SKILL.md to pre-review version, fix shortcut count test Restore SKILL.md plugin routing row to original version with full judgment rules and repo Skill directive. Update shortcut count test from 60 to 63 to account for 3 new plugin commands. * fix(plugin):fix lark-apps skill docs which is about plugin * fix(plugin):correct plugin skill md * fix(plugin):correct plugin md * fix(plugin):correct plugin and local dev skills md * fix(plugin):correct apps plugin skills md * fix(lark-apps): move repo skill reading hint to post-init phase 将「仓库 Skill 优先」从 SKILL.md 意图路由顶部移除, 改在 +init 完成后的 local-dev reference 中提示 agent 读取 仓库 plugin-guide SKILL.md,解决应用未初始化时 repo skill 不存在导致 agent 无法获取插件知识的时序问题。 * fix(lark-apps): strengthen local-dev reference reading and post-init plugin guide - SKILL.md 路由表:local-dev.md 从"按需读取"提升为"执行前必读" - local-dev.md:将读仓库 Skill 嵌入端到端流程链作为正式步骤 - post-init 指引改为可执行命令 + 不读的后果说明 + 不存在时兜底 --------- Co-authored-by: zhangli <zhangli.268@bytedance.com> * feat(apps): add release polling interval time and release time costs * fix(plugin): rename files to apps_ prefix and handle Close() errors (#1655) - Rename plugin_install/list/uninstall .go files to apps_plugin_ prefix for consistency with other files in the package - Handle f.Close() errors in pluginExtractTGZ to avoid silent data loss * style: gofmt apps plugin files (#1664) * fix(plugin): resolve CI lint, deadcode, and unit-test failures (#1667) - Add Scopes: []string{} to plugin-install, plugin-list, plugin-uninstall shortcuts to satisfy TestAllShortcutsScopesNotNil - Remove unused pluginCheckInstalled function (deadcode) - Fix nilerr: add //nolint:nilerr for intentional best-effort nil returns - Fix forbidigo: replace bare fmt.Errorf in Execute with typed error, add //nolint:forbidigo for intermediate helper errors in pluginExtractTGZ - Fix errorlint: change %v to %w for cerr in multi-error fmt.Errorf - Remove all unused //nolint:forbidigo directives from test files * style: gofmt apps_plugin list/uninstall/install_test files Fix fast-gate Check formatting failure: align struct literal fields in apps_plugin_list.go and apps_plugin_uninstall.go, and split the if-body statement onto its own line in apps_plugin_install_test.go. * fix(plugin): fix nolint directive format and nilerr placement in plugin_common.go (#1668) - Change nolint comment separator from -- to // to satisfy nolintlint - Move nilerr nolint directive to return statement to suppress nilerr correctly - Fix forbidigo nolint format for intermediate fmt.Errorf in pluginExtractTGZ * fix(apps): validate openapi-key scope method, path and raw JSON (#1675) Enforce an HTTP method whitelist (GET/POST/PUT/PATCH/DELETE), reject malformed --scope-api paths (must start with '/', no '..' or '//'), and constrain raw --scope JSON to the documented request_scope schema (allow_all + http_infos only). Validation runs in both the Validate hook and the body-build path so dry-run and execute are equally gated. Fixes PR #1596 audit findings HIGH-2 and MEDIUM-4. * fix(apps): harden db/file shortcuts per security audit (PR #1596) Address the file/db findings from the PR #1596 security audit with safer header/flag/path handling: - HIGH-3 (--output path traversal): add rejectOutputTraversal() and wire it into +file-download and +db-data-export Validate; reject absolute paths and any .. component up front. (FileIO.Save already sandboxes to cwd via SafeOutputPath; this is an earlier, explicit guard.) - HIGH-4 (Content-Disposition header injection): build the header with mime.FormatMediaType instead of manual string concatenation. - MEDIUM-3 (SQL leaked into public flag): stop writing --file contents back into the --sql flag; resolveExecuteSQL() reads it at use-site so SQL never lands in flag dumps / structured logs. - LOW-1 (hidden-file upload name): prefix sanitized upload names that start with '.' with '_'. - LOW-2 (local-timezone time parsing): document local-tz interpretation of bare date/datetime in flag descriptions and the db/file skill docs. SQL-injection of --table (audit MEDIUM-5) is intentionally NOT validated in the CLI: the server-side interface is the authoritative guard. Add apps_security_fixes_test.go covering the new validators and switch the upload test to parse Content-Disposition instead of matching a literal string. Update lark-apps-db.md / lark-apps-file.md skill refs. * fix(plugin): harden plugin commands against path traversal, DoS, and agent misuse (#1677) Security fixes from PR #1596 security audit: - Skip symlink/hardlink entries during tgz extraction (Zip Slip) - Limit tgz entry and download size to 10 MB (OOM/DoS) - Limit error response body read to 4 KB - Validate MIAODA_APP_TYPE as numeric to prevent path manipulation - Add validatePluginKey + secureModulePath to block --name path traversal (../../.ssh etc.) for install/uninstall Usability fix: - Add explicit 'local command, no --app-id' notice in plugin reference docs to prevent agent from incorrectly passing --app-id to plugin commands (which read package.json locally) * fix(apps): cap db async poll timeout at 2 minutes +db-recovery-apply blocked up to 30min and +db-env-migrate / +db-recovery-diff up to 10min while polling the server for async-task completion. These operations are expected to finish within ~1 minute; the long ceilings mostly hurt agents, whose harness kills the command on timeout while the server-side operation keeps running with no handle to re-query — especially risky for the irreversible recovery-apply. Cap all three pollUntil ceilings at 2 minutes (polling interval unchanged). Stuck operations now surface the retryable network/timeout envelope after 2min instead of hanging for 10-30min. * fix(plugin): create temp dir in project path to avoid cross-filesystem EXDEV on Rename (#1683) pluginInstallLocal used os.MkdirTemp("") which creates the temp directory on the system temp partition. On Windows (and some Linux/macOS setups), the temp partition is on a different filesystem from the project directory, causing os.Rename to fail with EXDEV. Use projectPath as the temp dir parent so it is always on the same filesystem as node_modules. * fix(plugin): improve --help Tips with local-command hint and update semantics (#1691) - Add "Run in project root; does NOT take --app-id" to all plugin Tips - Clarify install command also supports update (install or update to latest/specific version) - Clarify batch install reads from package.json actionPlugins --------- Co-authored-by: 陈兴炀 <chenxingyang.1019@bytedance.com> Co-authored-by: raistlin042 <lvxinsheng@bytedance.com> Co-authored-by: anngo-nk <anguohui@bytedance.com> Co-authored-by: zhangli <zhangli.268@bytedance.com> |
||
|
|
5c4ad52741 | fix: harden git credential error handling (#1676) | ||
|
|
e4248d1154 |
fix: harden lark-apps +init/+html-publish and skill guidance (#1517)
* fix: reject +init into a different app's project directory * fix: reject single HTML files larger than 10MB in +html-publish * docs: clarify publish visibility, domain routing, and role/permission boundary |
||
|
|
0991da7446 | fix: add missing CLI headers for git credential helper (#1539) | ||
|
|
76f5419a0d |
feat: add +session-messages-list for session turn reply messages (#1402)
* feat(apps): add +message-get to fetch session turn reply messages * docs(apps): add +message-get skill reference * fix(apps): drop Required flags on +message-get so missing ids return structured exit-2 envelope * docs(apps): route turn reply-message queries to +message-get in SKILL.md * docs(apps): guide cloud-dev to read live turn progress via +message-get * docs(apps): note +message-get reads a still-running turn incrementally * docs(apps): route live-turn reply queries to +message-get in SKILL.md * refactor(apps): rename +message-get to +session-messages-list with page_token paging * refactor(apps): use typed errs validation in +session-messages-list * docs(apps): clarify +session-messages-list paging stops on has_more, not token |
||
|
|
c5b5aece33 |
refactor: retire legacy error envelopes and enforce typed contract (#1449)
* refactor: retire legacy error envelopes and enforce typed contract
Consolidate all command error reporting onto the typed errs.* contract, remove
the legacy error surface that predated it, and tighten the lint guards so the
contract holds across the whole repository going forward.
Every failure now reaches stderr as one envelope shape: a category, an
optional subtype, a human- and agent-readable message, and a recovery hint,
with invalid parameters listed under `params`. The legacy ExitError envelope,
its constructors, and the boundary bridge that promoted untyped config and
authorization errors are deleted, leaving a single path from error to wire.
Predicate commands keep their silent-exit behavior through a dedicated signal
that carries only an exit code.
Infrastructure paths that still emitted ad-hoc envelopes — flag parsing,
unknown commands and subcommands, plugin and policy guards, confirmation
prompts, and auth/config failures — now classify into the same taxonomy.
Business, API, auth, and config exit codes are preserved; the one behavioral
change is that Cobra usage failures (missing required flag, unknown command,
bad arguments) now emit the typed validation envelope and exit 2, matching the
explicit flag and subcommand guards, instead of Cobra's plain-text exit 1.
Enforcement is repo-wide rather than per-path:
- The errscontract guards run by default everywhere instead of through a
migration allowlist, so legacy envelopes cannot be reintroduced anywhere.
- errorlint runs across the whole repository: every error wrap must use %w and
every comparison must use errors.Is/errors.As, so interior wraps stay legal
but can no longer break the chain the typed boundary relies on.
- The errs-no-bare-wrap guard is keyed by structural prefix instead of an
explicit per-domain allowlist, so new shortcut domains are covered without
editing a list. It runs where forbidigo is enabled (the shortcut domains and
the auth/config/service command groups); repo-wide chain integrity for the
remaining command paths is carried by errorlint above.
* test: align cli_e2e success assertions to the ok envelope
The api and service success path now emits the {"ok":true} envelope, so the
cli_e2e workflow assertions that still expected the old {"code":0} shape via
AssertStdoutStatus(t, 0) fail once they run with live credentials. Switch those
workflow assertions to AssertStdoutStatus(t, true); the fake-payload helper test
in core_test.go keeps its code-shape assertion.
|
||
|
|
0fbfe68726 | docs: drop Miaoda brand word from apps command help text (#1399) | ||
|
|
1cd7a88597 | fix: read release error_logs from data.error_logs in apps +release-get (#1436) | ||
|
|
9bc66cc445 | feat(apps): emit typed error envelopes across the apps domain (#1288) | ||
|
|
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 |
||
|
|
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> |
||
|
|
36ff632a13 |
fix(apps): update miaoda scopes after platform consolidation (#1127)
妙搭/spark consolidated the apps domain onto spark:app:read / spark:app:write. The standalone spark:app:publish and spark:app.access_scope:* scopes are retired. - +html-publish: spark:app:publish -> spark:app:write - +access-scope-get: spark:app.access_scope:read -> spark:app:read - +access-scope-set: spark:app.access_scope:write -> spark:app:write Verified against the official docs for upload_html_code_and_release, get_app_visibility and update_app_visibility. +create/+update/+list were already correct (spark:app:write / spark:app:read). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e93e2a98e1 |
feat(apps): replace +html-publish cwd hard-reject with credential-file scan (#1072)
* feat(apps): replace +html-publish cwd hard-reject with credential-file scan The previous --path == "." block was a coarse heuristic: it caught the common foot-gun of publishing a repo root, but also rejected legitimate clean cwds, and let a ./dist with a forgotten .env ship the secret through anyway (the sensitive-paths scanner was advisory and never ran on the Execute path). Move the gate from path shape to path content: - Validate now walks --path candidates and rejects publishes that include well-known credential files (.env / .env.* / .npmrc / .netrc / .git-credentials / .aws/credentials / .gcloud/credentials* / .docker/config.json / .kube/config). Living in Validate (not DryRun) means dry-run returns non-zero on hit too, so the dry-run preview matches Execute. - Narrow the credential pattern set. .git/, SSH private keys, *.pem and *.key are out of scope -- they're not env-token files and the false-positive rate (public certs, docs about key formats) is high. - Add --allow-sensitive as the escape hatch for legitimate cases (e.g. a docs site shipping .env.example on purpose). DryRun surfaces the waived list in sensitive_waived so the caller can relay it. - Drop the cwd defense-in-depth in runHTMLPublish. A clean cwd is now a valid publish target. The lark-apps skill and the html-publish reference are updated to describe the new gate, the override flag, and the patterns now explicitly out of scope. * feat(apps): drop .gcloud/* from credential-file scan The .gcloud/credentials pattern matched a non-existent path: gcloud's actual config dir is ~/.config/gcloud/ (XDG-based), and the real credential files there are credentials.db / access_tokens.db / application_default_credentials.json -- none of which would land under a .gcloud/ segment in a publish payload. Drop the rule rather than fix it: the realistic gcloud foot-gun would require recognizing the .config/gcloud/* tree by file basename, which is a broader change than the targeted env/cred scan in this PR. The remaining 7 patterns (.env / .env.* / .npmrc / .netrc / .git-credentials / .aws/credentials / .docker/config.json / .kube/config) cover the common Node/Python/CLI-tooling foot-guns. * fix(apps): close credential-scan bypass when --path is the parent dir itself isSensitiveRelPath anchors cloud-SDK matchers on adjacent parent/file segments (.aws/credentials, .docker/config.json, .kube/config), but walker strips that parent via filepath.Rel when --path is the conventional parent dir (e.g. ./.aws), yielding a bare RelPath="credentials" that slipped through silently. Same bypass for the single-file form --path ./.aws/credentials (walker sets RelPath = Base(rootPath)). Wrap the scan in isSensitiveCandidate: keep the fast RelPath scan, and on miss fall back to filepath.Abs(AbsPath) so the parent segment is visible again. isSensitiveRelPath itself is unchanged; existing tests still pin its pure-function contract. * fix(apps): drop filepath.Abs from sensitive scan to satisfy forbidigo lint The previous fix called filepath.Abs(c.AbsPath) — banned by the repo's forbidigo rule because shortcuts must not reach into the filesystem for path resolution. Reframe the same fix without fs access: re-prepend the root's basename (or, for the single-file form, the parent dir's basename of rootPath) to RelPath and re-scan only the parent-anchored credential pairs (.aws/credentials, .docker/config.json, .kube/config). Leaf matchers (.env / .npmrc / ...) stay scoped to RelPath — incidentally closing a latent false-positive where --path /home/alice/.env/dist would have flagged every file under it just because .env appeared in the absolute path. |
||
|
|
0dda56914d |
fix(apps): read app object from data.app for +create and +update (#1087)
* fix(apps): read app object from data.app for +create and +update
The Miaoda OpenAPI returns the application object nested under
data.app for both POST /apps and PATCH /apps/{appId}. The CLI text
helper was reading common.GetString(data, "app_id"), which yields an
empty string against the wire format -- so `lark-cli apps +create
--format pretty` printed `created: ` with no ID.
Navigate the new nested path via GetString(data, "app", "app_id") for
both create and update. Update unit-test mocks to wrap the response
under `app`. Refresh the lark-apps skill references (example response
shape + jq paths) so agents reading them follow the right path.
Wire format is passed through to the user's JSON envelope untouched
-- no unwrapping in CLI. Consumers reading the response should use
.data.app.app_id.
The GET /apps list endpoint is unchanged: per the design doc its
items[] are flat objects, no wrapper.
* docs(apps): add required --app-type HTML to scenario 2 snippet
The "用户没有 app_id" snippet in lark-apps-html-publish.md was missing
the required --app-type flag, so copy-pasting it triggered Validate
("--app-type is required") and left $APP empty -- the following
+html-publish then failed with --app-id "". Bring the snippet in line
with every other apps +create example in the skill.
* docs(apps): simplify auth-recovery rule to error.type == missing_scope
Every apps shortcut declares Scopes, so the precheck path in
shortcuts/common/runner.go:825 is always the one that fires on scope
violations and the envelope's error.type is the stable discriminator.
Drop the keyword-sniffing of error.hint, the chain explanation, and the
bot caveat — they all reduce to one boolean: error.type == "missing_scope"
→ run `lark-cli auth login --domain apps`.
Also collapse the corresponding bullet in 快速决策 to point at this rule.
|
||
|
|
6cea6c9af0 |
feat(apps): add miaoda apps domain (6 shortcuts + dry-run e2e) (#1002)
Adds the apps domain to lark-cli for managing Miaoda (妙搭) applications: 6 shortcuts covering the full lifecycle (+create / +update / +list / +access-scope-set / +access-scope-get / +html-publish). Aligned with the OAPI v2 design — app_type enum (currently HTML), string scope enum (All / Tenant / Range), cursor pagination, in-memory tar.gz multipart publish flow. Namespace registered at /open-apis/spark/v1/ with spark:app.* scopes. --------- Co-authored-by: wangjiangwen-gif <286006750+wangjiangwen-gif@users.noreply.github.com> |