@amaster.ai/pi-lark 0.1.2-beta.46 → 0.1.2-beta.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +5 -1
  2. package/dist/config.d.ts +1 -1
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +2 -2
  5. package/dist/config.js.map +1 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +2 -1
  8. package/dist/index.js.map +1 -1
  9. package/package.json +3 -3
  10. package/skills/lark-base/SKILL.md +5 -3
  11. package/skills/lark-base/references/lark-base-filter-condition.md +179 -0
  12. package/skills/lark-base/references/lark-base-form-questions-create.md +34 -4
  13. package/skills/lark-base/references/lark-base-form-questions-update.md +73 -20
  14. package/skills/lark-base/references/lark-base-view-set-filter.md +11 -137
  15. package/skills/lark-calendar/SKILL.md +12 -6
  16. package/skills/lark-calendar/references/lark-calendar-create.md +6 -6
  17. package/skills/lark-calendar/references/lark-calendar-room-find.md +2 -1
  18. package/skills/lark-calendar/references/lark-calendar-schedule-clear-time.md +1 -0
  19. package/skills/lark-calendar/references/lark-calendar-suggestion.md +1 -1
  20. package/skills/lark-calendar/references/lark-calendar-update.md +7 -4
  21. package/skills/lark-contact/SKILL.md +18 -2
  22. package/skills/lark-contact/references/lark-contact-search-bot.md +60 -0
  23. package/skills/lark-drive/SKILL.md +5 -1
  24. package/skills/lark-drive/references/lark-drive-member-list.md +65 -0
  25. package/skills/lark-drive/references/lark-drive-permission-get-setting.md +48 -0
  26. package/skills/lark-drive/references/lark-drive-search.md +6 -1
  27. package/skills/lark-drive/references/lark-drive-secure-label.md +1 -1
  28. package/skills/lark-drive/references/lark-drive-workflow-permission-governance-commands.md +38 -8
  29. package/skills/lark-drive/references/lark-drive-workflow-permission-governance-outputs.md +10 -10
  30. package/skills/lark-drive/references/lark-drive-workflow-permission-governance.md +22 -20
  31. package/skills/lark-slides/SKILL.md +16 -26
  32. package/skills/lark-slides/references/lark-slides-create.md +14 -5
  33. package/skills/lark-slides/references/slides_xml_schema_definition.xml +491 -31
  34. package/skills/lark-slides/references/xml-schema-quick-ref.md +39 -0
  35. package/skills/lark-slides/scripts/xml_text_overlap_lint.py +424 -32
  36. package/skills/lark-slides/scripts/xml_text_overlap_lint_test.py +840 -58
  37. package/skills/lark-task/references/lark-task-create.md +9 -0
package/README.md CHANGED
@@ -12,7 +12,11 @@ Pi extension for [Lark/Feishu](https://www.feishu.cn/) workspace — calendar, d
12
12
 
13
13
  ## Configuration
14
14
 
15
- Add to your `.pi/settings.json`:
15
+ Add to `~/.pi/agent/settings.json` or a trusted project's `.pi/settings.json`:
16
+
17
+ Project settings are loaded only after project trust is accepted. For
18
+ environment-backed credentials, use user or agent settings because project
19
+ settings do not expand `${ENV_VAR}`.
16
20
 
17
21
  ```json
18
22
  {
package/dist/config.d.ts CHANGED
@@ -3,5 +3,5 @@ export type LarkConfig = {
3
3
  appSecret?: string;
4
4
  domain?: 'feishu' | 'lark' | string;
5
5
  };
6
- export declare function loadLarkConfig(cwd: string): LarkConfig | undefined;
6
+ export declare function loadLarkConfig(cwd: string, projectTrusted?: boolean): LarkConfig | undefined;
7
7
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;CACrC,CAAC;AAIF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAIlE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;CACrC,CAAC;AAIF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,UAAQ,GAAG,UAAU,GAAG,SAAS,CAI1F"}
package/dist/config.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { loadPiSettings } from '@amaster.ai/pi-shared/settings';
2
2
  const SETTINGS_KEY = 'pi-lark';
3
- export function loadLarkConfig(cwd) {
4
- const config = loadPiSettings(SETTINGS_KEY, { cwd });
3
+ export function loadLarkConfig(cwd, projectTrusted = false) {
4
+ const config = loadPiSettings(SETTINGS_KEY, { cwd, projectTrusted });
5
5
  if (!config || (!config.appId && !config.appSecret))
6
6
  return undefined;
7
7
  return config;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAQhE,MAAM,YAAY,GAAG,SAAS,CAAC;AAE/B,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,MAAM,GAAG,cAAc,CAAa,YAAY,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAQhE,MAAM,YAAY,GAAG,SAAS,CAAC;AAE/B,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,cAAc,GAAG,KAAK;IAChE,MAAM,MAAM,GAAG,cAAc,CAAa,YAAY,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,CAAC,CAAC;IACjF,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;AActF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAoC9D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;AActF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAoC9D"}
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { dirname, join } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
+ import { isProjectTrusted } from '@amaster.ai/pi-shared/settings';
4
5
  import { ensureLarkCli, getLarkCliSkillsDir, initLarkCli } from './cli.js';
5
6
  import { loadLarkConfig } from './config.js';
6
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -16,7 +17,7 @@ async function resolveSkillsDir() {
16
17
  export default function piLarkExtension(pi) {
17
18
  let skillsDir;
18
19
  pi.on('session_start', async (_event, ctx) => {
19
- const config = loadLarkConfig(ctx.cwd);
20
+ const config = loadLarkConfig(ctx.cwd, isProjectTrusted(ctx));
20
21
  if (!config?.appId || !config?.appSecret)
21
22
  return;
22
23
  if (existsSync(BUNDLED_SKILLS_DIR)) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AAE3D,KAAK,UAAU,gBAAgB;IAC7B,MAAM,SAAS,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC9C,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,IAAI,UAAU,CAAC,kBAAkB,CAAC;QAAE,OAAO,kBAAkB,CAAC;IAC9D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAgB;IACtD,IAAI,SAA6B,CAAC;IAElC,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,MAAe,EAAE,GAAqB,EAAE,EAAE;QACtE,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,MAAM,EAAE,SAAS;YAAE,OAAO;QAEjD,IAAI,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACnC,SAAS,GAAG,kBAAkB,CAAC;QACjC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAC;YACxC,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;gBAC1B,SAAS,GAAG,MAAM,gBAAgB,EAAE,CAAC;gBACrC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,EAAE,CAAC,MAAM,CACX,oBAAoB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EACtE,SAAS,CACV,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC/B,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;QACrC,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;QACnC,SAAS,GAAG,SAAS,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AAE3D,KAAK,UAAU,gBAAgB;IAC7B,MAAM,SAAS,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC9C,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,IAAI,UAAU,CAAC,kBAAkB,CAAC;QAAE,OAAO,kBAAkB,CAAC;IAC9D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAgB;IACtD,IAAI,SAA6B,CAAC;IAElC,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,MAAe,EAAE,GAAqB,EAAE,EAAE;QACtE,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,MAAM,EAAE,SAAS;YAAE,OAAO;QAEjD,IAAI,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACnC,SAAS,GAAG,kBAAkB,CAAC;QACjC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAC;YACxC,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;gBAC1B,SAAS,GAAG,MAAM,gBAAgB,EAAE,CAAC;gBACrC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,EAAE,CAAC,MAAM,CACX,oBAAoB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EACtE,SAAS,CACV,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC/B,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;QACrC,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;QACnC,SAAS,GAAG,SAAS,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amaster.ai/pi-lark",
3
- "version": "0.1.2-beta.46",
3
+ "version": "0.1.2-beta.48",
4
4
  "description": "Pi extension for Lark/Feishu workspace — calendar, docs, drive, sheets, tasks, mail and more via lark-cli.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -44,7 +44,7 @@
44
44
  "directory": "packages/pi-lark"
45
45
  },
46
46
  "peerDependencies": {
47
- "@earendil-works/pi-coding-agent": ">=0.74.0",
47
+ "@earendil-works/pi-coding-agent": ">=0.79.1",
48
48
  "typebox": "*"
49
49
  },
50
50
  "peerDependenciesMeta": {
@@ -61,7 +61,7 @@
61
61
  "vitest": "^4.0.0"
62
62
  },
63
63
  "dependencies": {
64
- "@amaster.ai/pi-shared": "0.1.2-beta.46"
64
+ "@amaster.ai/pi-shared": "0.1.2-beta.48"
65
65
  },
66
66
  "scripts": {
67
67
  "fetch-skills": "node scripts/fetch-skills.mjs",
@@ -57,12 +57,12 @@ metadata:
57
57
  | 写记录 | `+record-upsert` / `+record-batch-create` / `+record-batch-update` | 必读 [lark-base-record-upsert.md](references/lark-base-record-upsert.md) / [lark-base-record-batch-create.md](references/lark-base-record-batch-create.md) / [lark-base-record-batch-update.md](references/lark-base-record-batch-update.md) 和 [lark-base-cell-value.md](references/lark-base-cell-value.md) |
58
58
  | 附件字段 | `+record-upload-attachment` / `+record-download-attachment` / `+record-remove-attachment` | 附件不要伪造成普通 CellValue;上传走本地文件,下载/删除按 file token 或字段定位 |
59
59
  | 删除记录 / 分享记录链接 / 历史 | `+record-delete` / `+record-share-link-create` / `+record-history-list` | 删除前确认 record;分享链接最多 100 条;历史读 [lark-base-record-history-list.md](references/lark-base-record-history-list.md),只查单条记录,不做整表审计 |
60
- | 管理视图 | `+view-*` | `+view-set-filter` 读 [lark-base-view-set-filter.md](references/lark-base-view-set-filter.md);其余配置先 get 现状,再按返回结构更新 |
60
+ | 管理视图 | `+view-*` | `+view-set-filter` 读 [lark-base-view-set-filter.md](references/lark-base-view-set-filter.md)(filter 条件结构见公共协议 [lark-base-filter-condition.md](references/lark-base-filter-condition.md));其余配置先 get 现状,再按返回结构更新 |
61
61
  | 一次性聚合统计 | `+data-query` | 必读 [lark-base-data-analysis-sop.md](references/lark-base-data-analysis-sop.md) 和入口 [lark-base-data-query-guide.md](references/lark-base-data-query-guide.md);完整 DSL 再读 [lark-base-data-query.md](references/lark-base-data-query.md) |
62
62
  | 公式字段 | `+field-create/update --json '{"type":"formula",...}'` | 必读 [formula-field-guide.md](references/formula-field-guide.md),读后再加隐藏确认 flag `--i-have-read-guide` |
63
63
  | Lookup 字段 | `+field-create/update --json '{"type":"lookup",...}'` | 必读 [lookup-field-guide.md](references/lookup-field-guide.md),读后再加隐藏确认 flag `--i-have-read-guide` |
64
64
  | 表单提交 | `+form-submit` | 先读 [lark-base-form-detail.md](references/lark-base-form-detail.md) 获取题目、filter 和附件所需 `base_token`;提交 JSON 读 [lark-base-form-submit.md](references/lark-base-form-submit.md) |
65
- | 表单题目创建/更新 | `+form-questions-create` / `+form-questions-update` | 读 [lark-base-form-questions-create.md](references/lark-base-form-questions-create.md) / [lark-base-form-questions-update.md](references/lark-base-form-questions-update.md) |
65
+ | 表单题目创建/更新 | `+form-questions-create` / `+form-questions-update` | 读 [lark-base-form-questions-create.md](references/lark-base-form-questions-create.md) / [lark-base-form-questions-update.md](references/lark-base-form-questions-update.md);题目显隐条件 `visible_rule` 结构见公共协议 [lark-base-filter-condition.md](references/lark-base-filter-condition.md) |
66
66
  | 其他表单管理 | `+form-list/get/detail/create/update/delete` / `+form-questions-list/delete` | `+form-detail` 读 [lark-base-form-detail.md](references/lark-base-form-detail.md);删除前确认目标表单 |
67
67
  | 仪表盘与组件 | `+dashboard-*` / `+dashboard-block-*` | 提到图表/看板/block 时先读 [lark-base-dashboard.md](references/lark-base-dashboard.md);组件 `data_config` 读 [dashboard-block-data-config.md](references/dashboard-block-data-config.md);读取图表计算结果用 `+dashboard-block-get-data` |
68
68
  | Workflow | `+workflow-*` | 创建/更新或理解 steps 时读入口 [lark-base-workflow-guide.md](references/lark-base-workflow-guide.md) 和 steps JSON SSOT [lark-base-workflow-schema.md](references/lark-base-workflow-schema.md);list/get/enable/disable 只处理 workflow ID 与启停状态 |
@@ -116,6 +116,7 @@ metadata:
116
116
  ## 表单与视图细节
117
117
 
118
118
  - `+form-submit` 是高风险写操作,必须带 `--yes` 确认;调用前必须先跑 `+form-detail`,读取 `questions[].type`、`required`、`filter` 和附件场景需要的 `base_token`;不要填写被 filter 隐藏的问题。
119
+ - `+form-questions-update` 是题目配置全量覆盖,不是 patch;未传字段会回落默认值,传空字符串 / `null` / 空数组会直接写入空或清空。更新前先 `+form-questions-list` 读取当前题目,把要保留的 `title` / `description` / `required` / `option_display_mode` / `visible_rule` 等字段带回请求。
119
120
  - 表单附件不要写进 `fields`,放在 `--json.attachments`;提交附件时必须同时传表单所属 Base 的 `--base-token`。
120
121
  - `+view-set-filter` 是唯一保留的 view reference;sort/group/card/timebar/visible-fields 这类配置先用对应 get 命令读现状,保留未修改字段,只替换用户要求变更的配置。
121
122
  - 视图适合持久化、共享和 UI 复用;一次性筛选/排序可先用 `+record-list` / `+record-search` 的 filter/sort 验证结果,再按需要沉淀为持久视图。
@@ -146,13 +147,14 @@ metadata:
146
147
  ## 保留 Reference
147
148
 
148
149
  - [lark-base-data-analysis-sop.md](references/lark-base-data-analysis-sop.md):查询/统计/全局结论的选路 SOP
149
- - [lark-base-data-query-guide.md](references/lark-base-data-query-guide.md) / [lark-base-data-query.md](references/lark-base-data-query.md):聚合查询入口 fewshot 与 DSL SSOT
150
+ - [lark-base-data-query-guide.md](references/lark-base-data-query-guide.md) / [lark-base-data-query.md](references/lark-base-data-query.md):聚合查询入口 fewshot 与 DSL SSOT;`+data-query` 的 `filters` 结构是独立对象 DSL,不使用公共 tuple filter 协议
150
151
  - [lark-base-cell-value.md](references/lark-base-cell-value.md):记录 CellValue 构造
151
152
  - [lark-base-field-json.md](references/lark-base-field-json.md):字段 JSON 构造
152
153
  - [formula-field-guide.md](references/formula-field-guide.md) / [lookup-field-guide.md](references/lookup-field-guide.md):公式与 lookup 字段
153
154
  - [lark-base-field-create.md](references/lark-base-field-create.md) / [lark-base-field-update.md](references/lark-base-field-update.md):字段创建/更新命令级补充
154
155
  - [lark-base-record-upsert.md](references/lark-base-record-upsert.md) / [lark-base-record-batch-create.md](references/lark-base-record-batch-create.md) / [lark-base-record-batch-update.md](references/lark-base-record-batch-update.md) / [lark-base-record-history-list.md](references/lark-base-record-history-list.md):记录写入 JSON 与历史返回解释
155
156
  - [lark-base-view-set-filter.md](references/lark-base-view-set-filter.md):视图筛选 JSON
157
+ - [lark-base-filter-condition.md](references/lark-base-filter-condition.md):视图 filter、记录 `--filter-json`、表单 `visible_rule` 的 tuple 条件结构公共协议 SSOT;不适用于 `+data-query`
156
158
  - [lark-base-form-detail.md](references/lark-base-form-detail.md) / [lark-base-form-submit.md](references/lark-base-form-submit.md) / [lark-base-form-questions-create.md](references/lark-base-form-questions-create.md) / [lark-base-form-questions-update.md](references/lark-base-form-questions-update.md):表单详情、提交和复杂 JSON
157
159
  - [lark-base-dashboard.md](references/lark-base-dashboard.md) / [dashboard-block-data-config.md](references/dashboard-block-data-config.md) / [lark-base-dashboard-block-get-data.md](references/lark-base-dashboard-block-get-data.md):仪表盘、组件配置与图表结果协议
158
160
  - [lark-base-workflow-guide.md](references/lark-base-workflow-guide.md) / [lark-base-workflow-schema.md](references/lark-base-workflow-schema.md):workflow 入口与 steps JSON SSOT
@@ -0,0 +1,179 @@
1
+ # Base Filter 条件结构(公共协议)
2
+
3
+ Filter 是一组「字段/操作符/值」条件的组合,用 `logic`(`and` / `or`)把多条 `conditions` 连接起来,用于描述「满足什么条件」。视图筛选 `filter`、记录读取/搜索的 `--filter-json`、表单题目显隐条件 `visible_rule` 复用同一套 tuple 结构,本文件是其公共协议(SSOT)。
4
+
5
+ ## 0. 适用范围
6
+
7
+ 本协议只适用于以下场景:
8
+
9
+ - `+view-set-filter` / `+view-get-filter` 的视图筛选配置。
10
+ - `+record-list --filter-json` / `+record-search --filter-json` 的结构化记录筛选。
11
+ - `+form-questions-create` / `+form-questions-update` 中的 `visible_rule` 显隐条件。
12
+
13
+ 本协议**不适用于 `+data-query`**。`+data-query` 支持过滤,但使用的是 LiteQuery DSL 的 `filters` 对象结构:`{"type":1,"conjunction":"and","conditions":[{"field_name":"状态","operator":"is","value":["有效"]}]}`,不是这里的 tuple 条件 `["状态","==","有效"]`。构造 `+data-query --dsl` 时请阅读 [lark-base-data-query.md](lark-base-data-query.md) 的 FilterGroup / Condition 章节。
14
+
15
+ ## 1. 顶层结构
16
+
17
+ - 必须是 JSON 对象。
18
+ - 顶层结构是 `{logic?, conditions?}`。
19
+ - `logic` 默认 `and`;推荐只用 canonical 值 `and` / `or`。
20
+ - `conditions` 默认空数组。
21
+ - 每条条件写成 tuple:`[field, operator, value?]`。
22
+ - `empty` / `non_empty` 可写成 2 项:`[field, "empty"]`、`[field, "non_empty"]`。
23
+
24
+ ```json
25
+ {
26
+ "logic": "and",
27
+ "conditions": [
28
+ ["状态", "intersects", ["Doing"]],
29
+ ["负责人", "intersects", [{ "id": "ou_xxx" }]],
30
+ ["截止时间", "empty"]
31
+ ]
32
+ }
33
+ ```
34
+
35
+ 清空写法:
36
+
37
+ ```json
38
+ {
39
+ "conditions": []
40
+ }
41
+ ```
42
+
43
+ ## 2. operator
44
+
45
+ 可用 operator:
46
+ - `==`
47
+ - `!=`
48
+ - `>`
49
+ - `>=`
50
+ - `<`
51
+ - `<=`
52
+ - `intersects`
53
+ - `disjoint`
54
+ - `empty`
55
+ - `non_empty`
56
+
57
+ ## 3. value 写法
58
+
59
+ value 类型取决于条件引用对象(字段 / 题目)的类型。
60
+
61
+ ### `text`
62
+
63
+ 用字符串:
64
+
65
+ ```json
66
+ ["标题", "intersects", "发布"]
67
+ ```
68
+
69
+ ### `location`
70
+
71
+ location 筛选只按 `full_address` 字符串匹配,不能直接按经纬度筛选;优先使用 `intersects` 做包含匹配,例如查深圳:
72
+
73
+ ```json
74
+ ["位置", "intersects", "深圳"]
75
+ ```
76
+
77
+ 不推荐写 `["位置", "==", "深圳"]` 这类精确匹配,除非确保筛选值与完整 `full_address` 完全一致。
78
+
79
+ ### `number` / `auto_number`
80
+
81
+ 用数字:
82
+
83
+ ```json
84
+ ["工时", ">=", 3.5]
85
+ ```
86
+
87
+ ### `select`
88
+
89
+ 用选项名数组:
90
+
91
+ ```json
92
+ ["状态", "intersects", ["Doing", "Blocked"]]
93
+ ```
94
+
95
+ ### `user` / `created_by` / `updated_by`
96
+
97
+ 用对象数组:
98
+
99
+ > **人员筛选:不要猜 ID。** 不知道 `open_id` 时,先用 `lark-contact` 查 id:`lark-cli contact +search-user --query "<姓名/邮箱/手机号>" --as user`。
100
+
101
+ ```json
102
+ ["负责人", "intersects", [{ "id": "ou_xxx" }]]
103
+ ```
104
+
105
+ ### `group_chat`
106
+
107
+ 用对象数组:
108
+
109
+ > **群组筛选:不要猜 ID。** 不知道 `chat_id` 时,先用 `lark-im` 搜群:`lark-cli im +chat-search --query "<群名关键词>" --as user`;取结果里的 `oc_xxx`。
110
+
111
+ ```json
112
+ ["负责群", "intersects", [{ "id": "oc_xxx" }]]
113
+ ```
114
+
115
+ ### `link`
116
+
117
+ 用记录 id 对象数组:
118
+
119
+ ```json
120
+ ["关联任务", "intersects", [{ "id": "rec_xxx" }]]
121
+ ```
122
+
123
+ ### `checkbox`
124
+
125
+ 用布尔值:
126
+
127
+ ```json
128
+ ["完成", "==", true]
129
+ ```
130
+
131
+ ### `datetime` / `created_at` / `updated_at`
132
+
133
+ 用相对时间关键字或 `ExactDate(...)`:
134
+
135
+ ```json
136
+ ["截止时间", "==", "ExactDate(2026-01-01)"]
137
+ ```
138
+
139
+ ```json
140
+ ["截止时间", "==", "ExactDate(2026-01-01 11:30)"]
141
+ ```
142
+
143
+ ```json
144
+ ["截止时间", "==", "Today"]
145
+ ```
146
+
147
+ 可用关键字:
148
+ - `Today`
149
+ - `Yesterday`
150
+ - `Tomorrow`
151
+
152
+ ### `formula` / `lookup`
153
+
154
+ - 筛选值类型由字段计算结果类型动态决定。
155
+ - 拿不准时,先把 `value` 当作单个字符串填入做一次尝试。
156
+ - 如果报错,再按错误提示把 `value` 改成对应类型。
157
+
158
+ 字符串示例:
159
+
160
+ ```json
161
+ ["风险说明", "intersects", "高风险"]
162
+ ```
163
+
164
+ 数字示例:
165
+
166
+ ```json
167
+ ["汇总分", ">=", 80]
168
+ ```
169
+
170
+ ## 4. 易错点
171
+
172
+ - 不要再写旧对象风格:`{"field_name":...,"operator":...}`。
173
+ - `user` / `group_chat` / `link` 不要写成单个标量。
174
+ - `empty` / `non_empty` 不要硬塞无意义的 value。
175
+ - 日期条件稳定写法用 `ExactDate(...)` 或 `Today` / `Yesterday` / `Tomorrow`。
176
+ - `formula` / `lookup` 的 value 形状不固定;拿不准时先读当前配置或字段定义,或根据错误提示修正类型。
177
+
178
+ ## 5. 参考
179
+ - [lookup-field-guide.md](lookup-field-guide.md)
@@ -19,10 +19,7 @@ lark-cli base +form-questions-create \
19
19
  --base-token <base_token> \
20
20
  --table-id <table_id> \
21
21
  --form-id <form_id> \
22
- --questions '[
23
- {"type":"text","title":"您的姓名是?","required":true},
24
- {"type":"text","title":"您的联系方式是?","required":false}
25
- ]'
22
+ --questions '[{"type":"text","title":"您的姓名是?","required":true},{"type":"text","title":"您的联系方式是?","required":false}]'
26
23
 
27
24
  # 添加单选题(带选项)
28
25
  lark-cli base +form-questions-create \
@@ -50,6 +47,13 @@ lark-cli base +form-questions-create \
50
47
  --table-id <table_id> \
51
48
  --form-id <form_id> \
52
49
  --questions '[{"type":"text","title":"反馈建议","description":"更多详情请查看[帮助文档](https://example.com/help)"}]'
50
+
51
+ # 添加带显隐条件(visible_rule)的问题:当「是否需要发票」选择「是」时才显示「发票抬头」
52
+ lark-cli base +form-questions-create \
53
+ --base-token <base_token> \
54
+ --table-id <table_id> \
55
+ --form-id <form_id> \
56
+ --questions '[{"type":"select","title":"是否需要发票","required":true,"options":[{"name":"是","hue":"Blue"},{"name":"否","hue":"Gray"}]},{"type":"text","title":"发票抬头","visible_rule":{"logic":"and","conditions":[["是否需要发票","==","是"]]}}]'
53
57
  ```
54
58
 
55
59
  ## 参数
@@ -78,6 +82,7 @@ lark-cli base +form-questions-create \
78
82
  | `multiple` | 否 | 是否多选(`select`/`user` 类型有效,bool) |
79
83
  | `options` | 否 | 选项列表(仅 `select` 有效):`[{"name":"选项1","hue":"Blue"}]`,hue 可选:`Red`/`Orange`/`Yellow`/`Green`/`Blue`/`Purple`/`Gray` |
80
84
  | `style` | 否 | 字段样式配置(见下方说明) |
85
+ | `visible_rule` | 否 | 题目显隐条件(见下方「`visible_rule` 显隐条件」) |
81
86
 
82
87
  ### `style` 字段说明
83
88
 
@@ -88,6 +93,30 @@ lark-cli base +form-questions-create \
88
93
  | `number`(评分) | `{"type":"rating","icon":"star","min":1,"max":5}` | icon 可选:`star`/`heart`/`thumbsup`/`fire`/`smile`/`lightning`/`flower`/`number` |
89
94
  | `datetime` | `{"format":"yyyy/MM/dd"}` | format 可选:`yyyy/MM/dd`、`yyyy/MM/dd HH:mm`、`MM-dd`、`MM/dd/yyyy`、`dd/MM/yyyy` |
90
95
 
96
+ ### `visible_rule` 显隐条件
97
+
98
+ > **仅当用户明确要求为题目设置显隐条件(显示/隐藏逻辑)时,才需要读下面的结构说明;否则忽略本节。**
99
+
100
+ `visible_rule` 控制题目在表单中的显示/隐藏:当条件满足时题目显示,不满足时隐藏;不传或 `conditions` 为空数组则题目始终显示。
101
+
102
+ - **结构与视图筛选 `filter` 完全一致**,即 `{logic?, conditions?}`,共用同一套公共协议。
103
+ - 与视图 `filter` 唯一的区别:`conditions` 中的 `field` 引用的是**同一表单内其他题目的题目名称或题目 ID**(推荐用题目 ID 以避免重名歧义),而不是数据表字段。
104
+ - **只能引用前序题目**:条件只能引用排在当前题目之前的题目——创建时按 `questions` 数组顺序判定(可引用同批次更靠前的新题目或表单中已有题目),不支持循环引用。
105
+ - 引用的题目必须真实存在,否则会报错。
106
+ - 列出题目(`+form-questions-list`)会在每个题目对象中**原样返回** `visible_rule`;未设置显隐条件的题目返回 `null` 或 `conditions` 为空数组。
107
+
108
+ ```json
109
+ {
110
+ "logic": "and",
111
+ "conditions": [
112
+ ["是否需要发票", "==", "是"],
113
+ ["报销金额", ">=", 1000]
114
+ ]
115
+ }
116
+ ```
117
+
118
+ 详细的 `visible_rule` 结构(顶层规则、operator 列表、各题目类型的 value 写法)请阅读 [lark-base-filter-condition.md](lark-base-filter-condition.md)。
119
+
91
120
  ## 输出格式
92
121
 
93
122
  返回创建成功的问题列表:
@@ -115,4 +144,5 @@ lark-cli base +form-questions-create \
115
144
  ## 参考
116
145
 
117
146
  - [lark-base](../SKILL.md) — 多维表格全部命令
147
+ - [lark-base-filter-condition.md](lark-base-filter-condition.md) — `visible_rule` / `filter` 条件结构公共协议
118
148
  - [lark-shared](../../lark-shared/SKILL.md) — 认证和全局参数
@@ -2,40 +2,60 @@
2
2
 
3
3
  > **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。
4
4
 
5
- 批量更新多维表格表单/问卷中的问题(标题、描述、是否必填)。
5
+ 批量更新多维表格表单/问卷中的问题配置(标题、描述、是否必填、显隐条件等)。
6
+
7
+ > [!CAUTION]
8
+ > `+form-questions-update` 是**题目配置全量覆盖**,不是 patch。对每个传入的题目,未携带的属性会回落为默认值,显式传空字符串 / `null` / 空数组会直接写入空或清空;如果要保留现有属性,必须先用 `+form-questions-list` 查出现状,再把要保留的字段一起带回 `--questions`。
6
9
 
7
10
  ## 命令
8
11
 
9
12
  ```bash
10
- # 更新一个问题的标题
13
+ # 先读取现有题目配置,作为 read-modify-write 的基线
14
+ lark-cli base +form-questions-list \
15
+ --base-token <base_token> \
16
+ --table-id <table_id> \
17
+ --form-id <form_id>
18
+
19
+ # 更新一个问题的标题,同时带回要保留的 required / description / visible_rule 等字段
11
20
  lark-cli base +form-questions-update \
12
21
  --base-token <base_token> \
13
22
  --table-id <table_id> \
14
23
  --form-id <form_id> \
15
- --questions '[{"id":"q_001","title":"您的真实姓名是?"}]'
24
+ --questions '[{"id":"q_001","title":"您的真实姓名是?","description":"请填写真实姓名","required":true,"visible_rule":null}]'
16
25
 
17
- # 同时更新多个问题
26
+ # 同时更新多个问题;每个对象都应是该题目的目标完整配置
18
27
  lark-cli base +form-questions-update \
19
28
  --base-token <base_token> \
20
29
  --table-id <table_id> \
21
30
  --form-id <form_id> \
22
- --questions '[
23
- {"id":"q_001","title":"姓名(必填)","required":true},
24
- {"id":"q_002","title":"联系方式","required":false}
25
- ]'
31
+ --questions '[{"id":"q_001","title":"姓名(必填)","required":true},{"id":"q_002","title":"联系方式","required":false}]'
26
32
 
27
- # 更新问题描述(纯文本)
33
+ # 更新问题描述(纯文本),同时带回要保留的 title / required / visible_rule
34
+ lark-cli base +form-questions-update \
35
+ --base-token <base_token> \
36
+ --table-id <table_id> \
37
+ --form-id <form_id> \
38
+ --questions '[{"id":"q_001","title":"您的姓名","description":"请填写您的真实姓名","required":true,"visible_rule":null}]'
39
+ # 更新问题描述(含链接),同时带回要保留的 title / required / visible_rule
28
40
  lark-cli base +form-questions-update \
29
41
  --base-token <base_token> \
30
42
  --table-id <table_id> \
31
43
  --form-id <form_id> \
32
- --questions '[{"id":"q_001","description":"请填写您的真实姓名"}]'
33
- # 更新问题描述(含链接)
44
+ --questions '[{"id":"q_001","title":"反馈建议","description":"更多说明请参考[帮助文档](https://example.com/help)","required":false,"visible_rule":null}]'
45
+
46
+ # 更新题目显隐条件(visible_rule),同时带回要保留的 title / description / required
34
47
  lark-cli base +form-questions-update \
35
48
  --base-token <base_token> \
36
49
  --table-id <table_id> \
37
50
  --form-id <form_id> \
38
- --questions '[{"id":"q_001","description":"更多说明请参考[帮助文档](https://example.com/help)"}]'
51
+ --questions '[{"id":"q_002","title":"发票抬头","description":"","required":false,"visible_rule":{"logic":"and","conditions":[["q_001","==","是"]]}}]'
52
+
53
+ # 清空题目显隐条件(使题目始终显示),同时带回要保留的 title / description / required
54
+ lark-cli base +form-questions-update \
55
+ --base-token <base_token> \
56
+ --table-id <table_id> \
57
+ --form-id <form_id> \
58
+ --questions '[{"id":"q_002","title":"发票抬头","description":"","required":false,"visible_rule":null}]'
39
59
  ```
40
60
 
41
61
  ## 参数
@@ -52,15 +72,46 @@ lark-cli base +form-questions-update \
52
72
 
53
73
  ## `--questions` 格式
54
74
 
55
- 每个问题对象必须包含 `id`,其余字段按需传入:
75
+ 每个问题对象必须包含 `id`。注意:对象不是增量 patch,而是该题目的目标完整配置;未携带字段会按服务端默认值重建。
56
76
 
57
77
  | 字段 | 必填 | 说明 |
58
78
  |------|------|------|
59
79
  | `id` | **是** | 问题 ID(field_id),不可修改 |
60
- | `title` | 否 | 新的问题标题 |
61
- | `description` | 否 | 新的问题描述(纯文本或 Markdown 链接,如 `[文本](https://example.com)`) |
62
- | `required` | 否 | 是否必填 |
63
- | `option_display_mode` | 否 | 选项展示方式(仅 `select` 有效):`0`=下拉,`1`=纵向(默认),`2`=横向 |
80
+ | `title` | 否 | 目标问题标题;省略会回落为字段名,传空字符串会写入空标题(若服务端允许) |
81
+ | `description` | 否 | 目标问题描述(纯文本或 Markdown 链接,如 `[文本](https://example.com)`);省略或传空字符串都会清空描述 |
82
+ | `required` | 否 | 目标是否必填;省略会回落为 `false` |
83
+ | `option_display_mode` | 否 | 目标选项展示方式(仅 `select` 有效):`0`=下拉,`1`=纵向(默认),`2`=横向;省略会回落默认展示方式 |
84
+ | `visible_rule` | 否 | 目标题目显隐条件;传完整 `{logic, conditions}` 对象覆盖,传 `null` 或省略都会清空(见下方说明) |
85
+
86
+ ## 全量覆盖语义
87
+
88
+ - 先执行 `+form-questions-list`,读取被更新题目的当前 `id`、`title`、`description`、`required`、`option_display_mode`、`visible_rule`。
89
+ - 构造 `--questions` 时,只改用户明确要求变化的字段;所有仍要保留的字段必须按当前值一并传回。
90
+ - 不要用“只传要改的字段”的方式更新题目。比如只传 `{"id":"q_002","title":"新标题"}` 会让 `description` 清空、`required` 回落为 `false`、`visible_rule` 清空。
91
+ - 用户明确要求清空时才传空值:`description:""` 清空描述,`visible_rule:null` 清空显隐条件,`conditions:[]` 也表示无条件显示。
92
+
93
+ ### `visible_rule` 显隐条件
94
+
95
+ > **仅当用户明确要求为题目设置或修改显隐条件(显示/隐藏逻辑)时,才需要读下面的结构说明;否则忽略本节。**
96
+
97
+ `visible_rule` 控制题目显示/隐藏,**结构与视图筛选 `filter` 完全一致**(`{logic?, conditions?}`),共用同一套公共协议。
98
+
99
+ - `conditions` 中的 `field` 引用**同一表单内其他题目的题目名称或题目 ID**(推荐用题目 ID)。
100
+ - 更新时按表单中题目的**实际顺序**判定,只能引用排在当前题目之前的题目;不支持循环引用。
101
+ - 更新 `visible_rule` 需传**完整**的 `{logic, conditions}` 对象(整体覆盖);要保留现有显隐条件就必须把当前 `visible_rule` 原样带回;传 `null`、省略 `visible_rule` 或传空 `conditions` 都会使题目始终显示。
102
+ - 列出题目(`+form-questions-list`)会在每个题目对象中**原样返回** `visible_rule`;未设置显隐条件的题目返回 `null` 或 `conditions` 为空数组。
103
+
104
+ ```json
105
+ {
106
+ "logic": "and",
107
+ "conditions": [
108
+ ["q_001", "==", "是"],
109
+ ["q_003", ">=", 1000]
110
+ ]
111
+ }
112
+ ```
113
+
114
+ 详细的 `visible_rule` 结构(顶层规则、operator 列表、各题目类型的 value 写法)请阅读 [lark-base-filter-condition.md](lark-base-filter-condition.md)。
64
115
 
65
116
  ## 输出格式
66
117
 
@@ -82,11 +133,13 @@ lark-cli base +form-questions-update \
82
133
  > [!CAUTION]
83
134
  > 这是**写入操作** — 执行前必须向用户确认。
84
135
 
85
- 1. 先用 `+form-questions-list` 获取现有问题及其 `id`
86
- 2. 构造包含 `id` 的更新数组
87
- 3. 执行命令并报告更新结果
136
+ 1. 先用 `+form-questions-list` 获取现有问题及其 `id` 和完整配置。
137
+ 2. 以现有配置为基线,只修改用户明确要求变化的字段;要保留的字段必须原样带回。
138
+ 3. 构造包含 `id` 和目标完整配置的更新数组。
139
+ 4. 执行命令并报告更新结果。
88
140
 
89
141
  ## 参考
90
142
 
91
143
  - [lark-base](../SKILL.md) — 多维表格全部命令
144
+ - [lark-base-filter-condition.md](lark-base-filter-condition.md) — `visible_rule` / `filter` 条件结构公共协议
92
145
  - [lark-shared](../../lark-shared/SKILL.md) — 认证和全局参数