@lark-base-open/base-database-cli 1.4.6 → 1.4.8

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 (130) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +16 -28
  3. package/dist/ai-functions.d.ts +7 -13
  4. package/dist/ai-functions.d.ts.map +1 -1
  5. package/dist/ai-functions.js +253 -105
  6. package/dist/ai-functions.js.map +1 -1
  7. package/dist/archive.d.ts +5 -4
  8. package/dist/archive.d.ts.map +1 -1
  9. package/dist/archive.js +19 -0
  10. package/dist/archive.js.map +1 -1
  11. package/dist/auth.d.ts +10 -0
  12. package/dist/auth.d.ts.map +1 -1
  13. package/dist/auth.js +23 -1
  14. package/dist/auth.js.map +1 -1
  15. package/dist/check.d.ts +23 -7
  16. package/dist/check.d.ts.map +1 -1
  17. package/dist/check.js +149 -20
  18. package/dist/check.js.map +1 -1
  19. package/dist/contract-conversion.d.ts +39 -0
  20. package/dist/contract-conversion.d.ts.map +1 -0
  21. package/dist/contract-conversion.js +92 -0
  22. package/dist/contract-conversion.js.map +1 -0
  23. package/dist/contract-extractor.d.ts +2 -5
  24. package/dist/contract-extractor.d.ts.map +1 -1
  25. package/dist/contract-extractor.js +68 -80
  26. package/dist/contract-extractor.js.map +1 -1
  27. package/dist/dependency-policy.d.ts +2 -0
  28. package/dist/dependency-policy.d.ts.map +1 -1
  29. package/dist/dependency-policy.js +24 -1
  30. package/dist/dependency-policy.js.map +1 -1
  31. package/dist/deploy.d.ts +1 -0
  32. package/dist/deploy.d.ts.map +1 -1
  33. package/dist/deploy.js +147 -118
  34. package/dist/deploy.js.map +1 -1
  35. package/dist/dev-watch.d.ts.map +1 -1
  36. package/dist/dev-watch.js +5 -1
  37. package/dist/dev-watch.js.map +1 -1
  38. package/dist/draft-publication.d.ts +9 -0
  39. package/dist/draft-publication.d.ts.map +1 -0
  40. package/dist/draft-publication.js +36 -0
  41. package/dist/draft-publication.js.map +1 -0
  42. package/dist/draft-state.d.ts +48 -0
  43. package/dist/draft-state.d.ts.map +1 -0
  44. package/dist/draft-state.js +167 -0
  45. package/dist/draft-state.js.map +1 -0
  46. package/dist/draft-submit.d.ts +39 -0
  47. package/dist/draft-submit.d.ts.map +1 -0
  48. package/dist/draft-submit.js +101 -0
  49. package/dist/draft-submit.js.map +1 -0
  50. package/dist/function-contracts.d.ts.map +1 -1
  51. package/dist/function-contracts.js +5 -5
  52. package/dist/function-contracts.js.map +1 -1
  53. package/dist/function-input-types.d.ts.map +1 -1
  54. package/dist/function-input-types.js +1 -15
  55. package/dist/function-input-types.js.map +1 -1
  56. package/dist/function-write-request.d.ts +17 -0
  57. package/dist/function-write-request.d.ts.map +1 -0
  58. package/dist/function-write-request.js +39 -0
  59. package/dist/function-write-request.js.map +1 -0
  60. package/dist/init.d.ts +1 -1
  61. package/dist/init.d.ts.map +1 -1
  62. package/dist/init.js +32 -5
  63. package/dist/init.js.map +1 -1
  64. package/dist/lark-cli-error.d.ts +3 -0
  65. package/dist/lark-cli-error.d.ts.map +1 -1
  66. package/dist/lark-cli-error.js +60 -0
  67. package/dist/lark-cli-error.js.map +1 -1
  68. package/dist/lark-cli.d.ts.map +1 -1
  69. package/dist/lark-cli.js +5 -5
  70. package/dist/lark-cli.js.map +1 -1
  71. package/dist/link-guard-check.d.ts +1 -1
  72. package/dist/link-guard-check.d.ts.map +1 -1
  73. package/dist/link-guard-check.js.map +1 -1
  74. package/dist/managed-agent-docs.js +1 -1
  75. package/dist/managed-agent-docs.js.map +1 -1
  76. package/dist/npm.d.ts +13 -0
  77. package/dist/npm.d.ts.map +1 -1
  78. package/dist/npm.js +99 -0
  79. package/dist/npm.js.map +1 -1
  80. package/dist/preview-receipt.d.ts +7 -2
  81. package/dist/preview-receipt.d.ts.map +1 -1
  82. package/dist/preview-receipt.js +21 -1
  83. package/dist/preview-receipt.js.map +1 -1
  84. package/dist/program.d.ts.map +1 -1
  85. package/dist/program.js +59 -33
  86. package/dist/program.js.map +1 -1
  87. package/dist/project-context.d.ts.map +1 -1
  88. package/dist/project-context.js +7 -14
  89. package/dist/project-context.js.map +1 -1
  90. package/dist/pull.d.ts +21 -1
  91. package/dist/pull.d.ts.map +1 -1
  92. package/dist/pull.js +64 -6
  93. package/dist/pull.js.map +1 -1
  94. package/dist/sdk-compatibility.d.ts +23 -0
  95. package/dist/sdk-compatibility.d.ts.map +1 -0
  96. package/dist/sdk-compatibility.js +75 -0
  97. package/dist/sdk-compatibility.js.map +1 -0
  98. package/dist/sdk-install.d.ts +2 -1
  99. package/dist/sdk-install.d.ts.map +1 -1
  100. package/dist/sdk-install.js +8 -5
  101. package/dist/sdk-install.js.map +1 -1
  102. package/dist/source-alignment.d.ts +3 -0
  103. package/dist/source-alignment.d.ts.map +1 -0
  104. package/dist/source-alignment.js +124 -0
  105. package/dist/source-alignment.js.map +1 -0
  106. package/dist/unified-functions.d.ts +10 -1
  107. package/dist/unified-functions.d.ts.map +1 -1
  108. package/dist/unified-functions.js +27 -7
  109. package/dist/unified-functions.js.map +1 -1
  110. package/package.json +1 -1
  111. package/skills/lark-base-database/SKILL.md +6 -6
  112. package/skills/lark-base-database/references/agent-tool-design.md +1 -1
  113. package/skills/lark-base-database/references/agent-tools.md +4 -6
  114. package/skills/lark-base-database/references/ai-function.md +143 -277
  115. package/skills/lark-base-database/references/base-capability-routing.md +2 -2
  116. package/skills/lark-base-database/references/database-function.md +7 -3
  117. package/skills/lark-base-database/references/development.md +29 -11
  118. package/skills/lark-base-database/references/faas.md +1 -2
  119. package/skills/lark-base-database/references/legacy-ai-function.md +3 -3
  120. package/skills/lark-base-database/references/legacy-development.md +2 -2
  121. package/skills/lark-base-database/references/mutations.md +14 -9
  122. package/skills/lark-base-database/references/release.md +7 -7
  123. package/skills/lark-base-database/references/verification.md +12 -21
  124. package/skills/lark-base-database/references/workspace-migration.md +5 -14
  125. package/skills/lark-base-database/references/workspace.md +17 -3
  126. package/templates/database-starter/page/README.md +1 -1
  127. package/templates/database-starter-v2/README.md +2 -2
  128. package/templates/database-starter-v2/package-lock.json +5 -5
  129. package/templates/database-starter-v2/page/package.json +1 -1
  130. package/templates/database-starter-v2/server/package.json +1 -1
@@ -1,41 +1,37 @@
1
1
  # Base Database AI Function
2
2
 
3
- 本参考中的 SDK 页面 API 仅适用于工程已安装 `@lark-base-open/base-database-app-sdk` 的情况;未安装时不得按 SDK 示例新增依赖或替换原实现,继续使用[冻结的classic AI Function 参考](legacy-ai-function.md)。
3
+ 需求需要模型参与页面业务流程时读取本文。工程恢复、Function 写入、公共 invoke 与发布沿用通用流程;本文只说明 AI Function 的选择、配置、Page 调用、多模态输入和失败边界。
4
4
 
5
- 本文说明如何在 Page 中配置和调用 AI Function。AI Function 是随应用版本发布的 AI 能力:文本可以按页面需要使用流式或一次性结果;图像和视频生成始终先创建任务、再轮询结果。页面只按 `functionKey` 调用平台 AI 能力;Base 数据读取仍使用 Database Function,写入按[Mutation 与 FaaS 分工](mutations.md#写入方式选择)选择。
5
+ 本参考中的 SDK 页面 API 仅适用于已经安装 `@lark-base-open/base-database-app-sdk` 的工程。新建工程已包含所需 SDK,不需要安装、替换或选择 SDK,也不因新增 AI Function 自行改依赖;未安装 SDK 的存量工程继续使用[冻结的 classic AI Function 参考](legacy-ai-function.md)。
6
6
 
7
- AI Function 是按需可选能力:需求不涉及模型或 AI 时不要创建 `ai/`,也不需要执行本文任何命令或开通 AI 能力;普通 `deploy` 在空 `ai/` 时自动跳过 AI Function 同步。只有需求包含 AI 对话、生成、分类、总结、文生图、文生视频或“查数据后让模型分析”时才读取本文。
7
+ ## 定位与选择
8
8
 
9
- 每个 AI Function 的配置保存在 `ai/<functionKey>/meta.json`。配置决定模型、System Prompt、思考深度、尺寸、时长和变量;页面只传入 `functionKey`、本次的 `params` 与 `messages` 或 `input`。
9
+ AI Function 是按需能力。需求不涉及模型或 AI 时不要创建;需要 AI 对话、分类、总结、生成、文生图、文生视频或“查数据后让模型分析”时,把 AI 调用作为独立的业务动作。
10
10
 
11
- ## 阅读路径
11
+ | 业务动作 | 数据路径 | Page 职责 |
12
+ | --- | --- | --- |
13
+ | 读取 Base | Page → Database Function | 使用固定 Function ID,校验并裁剪查询结果 |
14
+ | AI 对话或生成 | Page → AI Function | 传 `functionKey` 与本次输入,消费文本或媒体任务结果 |
15
+ | 写回 Base | Page → Mutation 或 FaaS | 普通单表写入用 Mutation,需要业务校验或编排时用 FaaS |
12
16
 
13
- 1. 第一次实现时先执行[零背景最短闭环](#零背景最短闭环)。
14
- 2. 再按需求读取[四类能力与配置契约](#四类能力与配置契约)和[Page 调用方式](#page-调用方式)。
15
- 3. 修改已有应用时,工程若来自 `pull`,`ai/` 已与远端一致;工程不是 `pull` 得到而 `ai/` 又非空时,按[恢复已有 AI Function](#恢复已有-ai-function)核对。
16
- 4. 实现按[页面实现检查](#页面实现检查)核对;用户要求运行态验收时,按[AI 验收判定](verification.md#ai-验收判定)执行。
17
+ 需要先查 Base 再问模型时,先用 Database Function 读取,在 Page 内只保留完成当前任务所需的字段和记录,再调用 AI Function。需要把结果写回 Base 时,按[写入方式选择](mutations.md#写入方式选择)选 Mutation 或 FaaS。不要创建 FaaS 模型代理,也不要让 Page 直连模型域名。
17
18
 
18
- ## 零背景最短闭环
19
+ 例如点餐系统根据口味、预算、人数和菜单自动推荐菜品:Database Function 读取菜单,Page 裁剪并组合用餐条件,text AI Function 生成推荐,后续订单写入再按 Mutation/FaaS 分工处理。
19
20
 
20
- 开始前,先完成主流程的 `init` 或已有工程恢复,并在项目根目录确认存在 `base-database.jsonc`、`catalog.json` 和 `page/`。新建工程已经包含所需 Channel SDK;不要为了使用 AI Function 单独安装或替换 SDK。
21
+ AI Function 和 Database Function 一样按应用版本保存:Preview 读取草稿版本,Prod 读取已发布版本。每个 AI Function 的本地声明位于 `ai/<functionKey>/meta.json`,Page 只按同一个 `functionKey` 调用。
21
22
 
22
- AI Function 不是 FaaS 代码,也不是页面直接请求模型。一个可运行的 AI 功能必须同时有两部分:
23
+ ## 最短闭环
23
24
 
24
- ```text
25
- ai/<functionKey>/meta.json # 应用版本中的配置
26
- page/... # 使用同一个 functionKey 的页面调用代码
27
- ```
25
+ 开始前完成普通 `init` 或公共 `pull`,并确认项目根目录有 `base-database.jsonc`、`catalog.json` 和 `page/`。从项目根目录执行:
28
26
 
29
- 从项目根目录按以下顺序完成:
27
+ 1. 运行 `base-database-cli ai-functions models`,按 `capability` 和 `input_modalities` 选择真实 `profiles[].profile_id`;禁止猜测示例 ID。
28
+ 2. 创建严格 JSON 文件 `ai/<functionKey>/meta.json`。`functionKey` 长度为 1~64,只能包含字母、数字、下划线和连字符。
29
+ 3. 在 Page 中使用相同 `functionKey`;调用 `callSiteAIFunction` 时显式传 `capability`。
30
+ 4. 执行普通 `base-database-cli deploy`;不再单独同步 AI Function。
30
31
 
31
- 1. 修改已有应用且工程不是 `pull` 得到时,先按[恢复已有 AI Function](#恢复已有-ai-function)核对远端配置;新建应用或 `pull` 得到的工程继续下一步。
32
- 2. 查询 `model_profiles`,按 `capability` 选择真实 `profile_id`;禁止猜测示例 ID。
33
- 3. 为每个 AI 功能选择唯一、稳定的 `functionKey`,创建严格 JSON 文件 `ai/<functionKey>/meta.json`。`functionKey` 只能含字母、数字、下划线和连字符,长度 1~64;目录名就是调用 key。
34
- 4. 在 workspace Page 中从 `@lark-base-open/base-database-app-sdk/page` 导入 SDK,使用完全相同的 `functionKey`。调用 `callSiteAIFunction` 时显式传 `capability`;不要依赖 SDK 按 `messages` 或 `input` 猜调用链路。
35
- 5. 执行一次普通 `deploy`。发布顺序与 skip/Prod 行为按[发布参考](release.md#function-发布顺序与错误边界)执行。
36
- 6. 运行态未检查时列为未验证;用户要求验收时按[AI 验收判定](verification.md#ai-验收判定)执行,Prod 是否验证按用户诉求决定。
32
+ `ai_function_parameters` 是模型动态配置的唯一事实源。只使用所选 profile 对应 `text`、`image` 或 `video` 子对象声明的值;不要从示例、旧 Chat 元数据或其他 profile 推断。存在本地 `ai/` 根时,默认 `check` 与 deploy 使用同一份包含 AI 的 Function payload;check 通过统一 Validate 无副作用校验当前 model profile 和配置,deploy 的草稿提交在落库前再次执行同一套服务端规则。空根是明确空集合。旧工程缺少整个根时保留远端 AI 并提示先执行公共 `pull`,显式 `--skip-ai-functions` 也会排除 AI;两者都不能据此声明 AI 配置已校验或同步。
37
33
 
38
- 最小文本配置与页面调用如下。把 `replace-with-profile-id` 换成 `model_profiles` 返回的真实值。`showAnswer` 是你的页面状态更新函数,需要替换为实际 UI 代码:
34
+ 最小 text 声明不写 profile 可选参数;需要思考深度、temperature 等能力时,再从 `ai_function_parameters` 中选择:
39
35
 
40
36
  ```json
41
37
  {
@@ -47,331 +43,201 @@ page/... # 使用同一个 functionKey 的页面调用
47
43
  "system_prompt": "只推荐 {{menu}} 中的菜品。",
48
44
  "input_schema": {
49
45
  "type": "object",
50
- "properties": { "menu": { "type": "string" } },
46
+ "properties": {
47
+ "menu": {
48
+ "type": "string",
49
+ "description": "可供推荐的菜品菜单内容"
50
+ }
51
+ },
51
52
  "required": ["menu"]
52
- },
53
- "text": {
54
- "reasoning_depth": "standard",
55
- "temperature": 0.7
56
53
  }
57
54
  }
58
55
  }
59
56
  ```
60
57
 
61
- ```ts
62
- import { callSiteAIFunction } from '@lark-base-open/base-database-app-sdk/page';
63
-
64
- const result = await callSiteAIFunction({
65
- functionKey: 'recommend_dishes',
66
- capability: 'text',
67
- params: { menu: '番茄炒蛋、宫保鸡丁、青椒肉丝' },
68
- messages: [
69
- {
70
- role: 'user',
71
- content: [{ type: 'text', text: '预算 100 元,推荐两道菜' }],
72
- },
73
- ],
74
- });
75
- if (result.type === 'text') showAnswer(result.content);
76
- ```
77
-
78
- ## AI Function 配置与验证
79
-
80
- AI Function 和 Database Function 一样按应用版本保存:Preview 读取草稿版本,Prod 读取已发布版本。实现 AI 需求时,把每个 AI 功能建模为 `ai/<functionKey>/meta.json`,执行 `deploy` 后由 CLI 将 AI Function 全量同步到当前草稿版本。
81
-
82
- 部署校验的适用条件、顺序和失败边界见[验证方法](verification.md#验证方法)。
83
-
84
- 配置要求:`functionKey`、`capability_type`、`input_schema`、`model_profile_id`、变量声明、System Prompt 占位符和能力专属参数都必须符合当前服务端契约。运行态调用进入鉴权、额度、并发和模型调用链路;目标 Function 必须存在,且配置没有设置 `disabled: true`。
85
-
86
- 运行态未检查时列为未验证;用户要求验收时按[AI 验收判定](verification.md#ai-验收判定)执行,Prod 是否验证按用户诉求决定。
87
-
88
- ### 调用排障
89
-
90
- 目标 Function 不存在时检查本地声明和 Functions 同步结果;返回 `ai function is disabled` 时检查该 Function 的 `disabled` 配置;模型不可用时重新查询 `model_profiles` 并校验配置;额度、并发或服务错误按实际错误码处理。无法通过应用配置解决时,保留 `requestId` 和脱敏错误摘要,向平台支持反馈。
91
-
92
- ### 恢复已有 AI Function
93
-
94
- `pull` 恢复源码制品的同时,会读取远端 AI Function 草稿并写回 `ai/<functionKey>/meta.json`,返回 `aiFunctions.status` 为 `restored` 或 `not_enabled`;当前账号未开通时不落 `ai/`,此后 deploy 不触碰远端 AI Function。`deploy` 在本地 `ai/` 非空时先核对远端已有 key 是否都在本地,缺失则拒绝并列出 key,不会静默删除;`ai-functions sync` 则把本地 `ai/` 当作全集立即全量覆盖(含空集合)。因此只有工程不是 `pull` 得到、且 `ai/` 非空时,才需要手工执行下列恢复:
95
-
96
- 1. `ai-functions list` 取得草稿版本全部远端 key。
97
- 2. 对每个 key 执行 `ai-functions pull <functionKey>`。该命令读取 preview 详情中的 `spec`,解析配置并写入 `ai/<functionKey>/meta.json`;仅查看时使用 `ai-functions get <functionKey>`。`disabled` 位于这个 `config` 对象内,不在 `meta.json` 顶层。
98
- 3. 比较远端 key 集合与本地 `ai/` 目录。需求外的远端 Function 必须保留所有配置值;JSON 缩进和字段顺序不影响语义。本地缺少任一远端 key,或 `spec` 缺失或无法解析时,禁止 `ai-functions sync` 和显式删除操作,`deploy` 前也必须补齐。
99
- 4. 只有用户明确授权删除具体 Function 后,才能让该 key 从本地全集缺失并执行全量同步。
100
-
101
- deploy 的 AI 同步、skip 行为、Prod 提升与显式 sync 的区别统一见[发布顺序与错误边界](release.md#function-发布顺序与错误边界)。
102
-
103
- ## 选择 AI Function
104
-
105
- 需求包含 AI 对话、总结、分类、生成、文生图、文生视频或“查数据后让模型分析”时,把 AI 调用作为独立的业务动作。只要 AI 需要使用当前页面输入、当前记录、筛选条件或绑定 Base 数据,并把结果展示在页面中或进入后续业务动作,就使用 AI Function。
106
-
107
- | 业务动作 | 数据路径 | 页面职责 |
108
- | -------------- | -------------------------- | ------------------------------------------------------------------- |
109
- | 查询 | Page → Database Function | 固定 Function ID,校验查询结果 |
110
- | 写入 | Page → Mutation 或 FaaS | 按[写入方式选择](mutations.md#写入方式选择):普通单表写入用 Mutation,需要业务校验或编排时用 FaaS |
111
- | AI 对话 / 生成 | Page → AI Function | 传 functionKey + params + messages/input,消费结果,维护会话状态 |
112
-
113
- 需要先查 Base 再问模型时,先完成 Database Function 查询,在 Page 内把经过裁剪的结果放入 `messages` 或 `params`,再按 `functionKey` 调用 AI Function。需要把 AI 结果写回 Base 时,按[写入方式选择](mutations.md#写入方式选择)选用 Mutation 或 FaaS。
114
-
115
- 典型路由:
116
-
117
- | 用户诉求 | 选择 | 原因 |
118
- | ---------------------------------------------- | -------------------- | ---------------------------------------------------------------------------- |
119
- | 点餐系统根据口味、预算、人数和菜单自动推荐菜品 | AI Function(text) | Page 收集条件,Database Function 读取菜单,AI 生成推荐,后续可写购物车或订单 |
120
- | CRM 按当前筛选出的客户生成跟进建议 | AI Function(text) | 输入来自页面筛选和 Base 查询结果,输出服务当前业务流程 |
121
- | 根据描述和可选参考图生成单图或组图 | AI Function(image) | 图片生成能力,异步任务返回一张或多张图片资源 |
122
- | 根据脚本生成宣传短视频 | AI Function(video) | 文生视频能力,异步任务提交 + 轮询 |
123
-
124
- ## 四类能力与配置契约
125
-
126
- 一个 AI Function 只承载一种能力,由 `capability_type` 决定用哪条运行链路与哪组配置字段:
58
+ `meta.json` 必须是严格 JSON,不能包含注释、尾逗号或 Markdown 占位符。`input_schema` 描述 Page 传入的 `params` object;字段与 System Prompt 占位符由服务端统一校验,不在 Skill 复制完整 Schema 关键字或模型参数清单。
127
59
 
128
- | capability_type | mode | 运行链路 | 专属配置字段 |
129
- | --------------- | -------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
130
- | `text` | `stream` | 通过 SDK 获取文本流或完整文本 | `text.reasoning_depth`(off/light/standard/deep) / `text.temperature` |
131
- | `vision` | `stream` | 多模态理解;输入受下文 SDK 类型限制 | 同 text,且模型 Profile 必须声明本次使用的 image / video / audio / file 输入 |
132
- | `image` | `task` | 创建图片任务并轮询结果 | `image.size` / `image.response_format`(url/b64_json) / `image.sequential_image_generation`(auto/disabled) / `image.max_images` / `image.watermark` |
133
- | `video` | `task` | 创建视频任务并轮询结果 | `video.resolution` / `video.ratio` / `video.duration` / `video.watermark` / `video.seed` |
134
-
135
- `AIFunctionConfig` 结构(落 `ai/<functionKey>/meta.json` 的 `config` 字段):
136
-
137
- `meta.json` 必须是严格 JSON,不能包含注释、尾逗号或 Markdown 占位符:
60
+ 图片尺寸写入 `config.image.size`,视频时长写入 `config.video.duration`。以下是两份最小完整声明;先将 `model_profile_id` 替换为 `ai-functions models` 返回的同能力 Profile,并按该 Profile 的 `ai_function_parameters` 调整示例尺寸或时长:
138
61
 
139
62
  ```json
140
63
  {
141
- "name": "菜品推荐",
142
- "description": "根据口味/预算/人数和菜单推荐菜品",
143
- "config": {
144
- "capability_type": "text",
145
- "model_profile_id": "replace-with-text-profile-id",
146
- "system_prompt": "你是点餐助手,只推荐 {{menu}} 中的菜品。",
147
- "input_schema": {
148
- "type": "object",
149
- "properties": { "menu": { "type": "string" } },
150
- "required": ["menu"]
151
- },
152
- "text": {
153
- "reasoning_depth": "standard",
154
- "temperature": 0.7
155
- }
156
- }
157
- }
158
- ```
159
-
160
- 配置合法性要求(由 deploy 校验,按能力分支):`capability_type` 合法;`model_profile_id` 来自可用模型列表且能力匹配(文本模型不能配给文生图);`system_prompt` 里的 `{{var}}` 都在 `input_schema.properties` 声明;`input_schema` 属性类型合法,required 列表引用已声明属性;文本 `temperature` 必须在 0~2 内;vision 要求 profile 至少声明 image / video / audio / file 中一种媒体输入,调用时每个 content part 还必须命中该 profile 的 `input_modalities`;image `max_images` 与 video `duration` 不超平台上限,video `seed` 必须为 -1 或更大。
161
-
162
- `input_schema` 是描述 `params` 的 object JSON Schema,支持 type、properties、required、additionalProperties、items、prefixItems、enum、数值/长度限制、oneOf、anyOf、pattern 和 default。pattern 使用 RE2;不支持 $ref 或外部加载。作者 Schema 最大 32 KiB、256 个节点、16 层。default 使用真实 JSON 值;有有效 default 的顶层属性无需 required。缺失属性由执行器补默认值,显式 null 只有 Schema 允许才合法,且不会触发默认值。`system_prompt` 适用于四类能力;媒体 `input.prompt` 追加到基础提示词。
163
-
164
- `disabled` 是 `config.disabled`,省略或 `false` 表示可调用,`true` 表示保留配置但停止调用。`video.seed=-1` 表示随机种子。
165
-
166
- 图片生成和文生视频的最小配置分别如下。Page 对 image/video 创建任务并轮询,mode 由服务端按能力推导。
167
-
168
- ```json
169
- {
170
- "name": "生成海报",
171
- "description": "根据商品描述生成海报",
64
+ "name": "内容配图生成",
65
+ "description": "根据画面描述生成供内容运营保存的配图",
172
66
  "config": {
173
67
  "capability_type": "image",
174
- "input_schema": { "type": "object", "properties": {} },
175
68
  "model_profile_id": "replace-with-image-profile-id",
176
- "system_prompt": "生成适合商品展示的图片。",
177
- "image": {
178
- "size": "2048x2048",
179
- "response_format": "url",
180
- "sequential_image_generation": "disabled",
181
- "max_images": 1,
182
- "watermark": true
183
- }
69
+ "input_schema": { "type": "object", "properties": {} },
70
+ "image": { "size": "2048x2048" }
184
71
  }
185
72
  }
186
73
  ```
187
74
 
188
75
  ```json
189
76
  {
190
- "name": "生成宣传视频",
191
- "description": "根据脚本生成短视频",
77
+ "name": "场景短视频生成",
78
+ "description": "根据场景描述生成供活动运营剪辑的短视频",
192
79
  "config": {
193
80
  "capability_type": "video",
194
- "input_schema": { "type": "object", "properties": {} },
195
81
  "model_profile_id": "replace-with-video-profile-id",
196
- "system_prompt": "生成简洁、自然的宣传短视频。",
197
- "video": {
198
- "resolution": "720p",
199
- "ratio": "16:9",
200
- "duration": 5,
201
- "watermark": true,
202
- "seed": -1
203
- }
82
+ "input_schema": { "type": "object", "properties": {} },
83
+ "video": { "duration": 5 }
204
84
  }
205
85
  }
206
86
  ```
207
87
 
208
- 示例里的尺寸、时长和其他参数只是结构演示,必须根据 `model_profiles` 返回的能力与业务要求调整,由 `deploy` 完成服务端校验,编辑期可选 `ai-functions validate` 自检。
88
+ 最小聚合调用:
209
89
 
210
- 图片尺寸、像素与数量上限按实际选择的 model_profiles 和服务端校验反馈确定,不将某一模型版本的限制推广到其他模型。示例参数只演示结构;缺少范围说明时先用编辑期 `ai-functions validate` 获取明确校验反馈,修正参数后再发布,不靠反复模型调用试探限制。
90
+ ```ts
91
+ import { callSiteAIFunction } from '@lark-base-open/base-database-app-sdk/page';
211
92
 
212
- `image.sequential_image_generation` 选择单图(disabled)或组图(auto);参考图使用 `input.image`,输入格式按下表。`image.max_images` 的可选范围、参考图数量与输出数量之间的约束以当前模型和服务端校验反馈为准,不从示例中的数量推断所有模型上限。
93
+ const result = await callSiteAIFunction({
94
+ functionKey: 'recommend_dishes',
95
+ capability: 'text',
96
+ params: { menu: '番茄炒蛋、宫保鸡丁、青椒肉丝' },
97
+ messages: [{ role: 'user', content: [{ type: 'text', text: '预算 100 元,推荐两道菜' }] }],
98
+ });
99
+ if (result.type === 'text') showAnswer(result.content);
100
+ ```
213
101
 
214
- 参考图属于每次调用输入,不是 AI Function 固定配置;使用可访问 URL / data:image/...;base64,... 字符串或非空字符串数组。接入类型以 SDK 的 SiteAIImageGenerationInput 为准。
102
+ `showAnswer` 是页面自己的状态更新函数,需要替换成实际 UI 实现。
215
103
 
216
- ### 参考图来源与传参
104
+ ## 能力与调用入口
217
105
 
218
- 先把源图转换为模型上游可读取的字符串引用,再放入 `input.image`。AI Function 接口接收 JSON,不接收 multipart 文件,也不把 Base `file_token` 自动转换成 URL。
106
+ | 能力 | Page 入口 | 完成判定 |
107
+ | --- | --- | --- |
108
+ | text / vision 流式 | `invokeSiteAIFunctionStream` | 多次 `onMessage`,最终一次 `onDone`;失败为 `onError` |
109
+ | text / vision 聚合 | `callSiteAIFunction` | `{type:'text', content}` |
110
+ | image / video | `createSiteAIFunctionTask` + `getSiteAIFunctionTask` | 轮询到 `succeeded`、`failed` 或 `cancelled` |
219
111
 
220
- | 源图来源 | `input.image` 的值 |
221
- | ----------------- | ------------------------------------------------------------------------------------------------ |
222
- | 公网可访问图片 | HTTPS URL |
223
- | 浏览器本地 `File` | 用 `FileReader.readAsDataURL` 转成完整的 `data:image/...;base64,...`;只用于满足请求体限制的小图 |
224
- | Base 附件 | 用 `fetchAttachmentDownloadUrl(context, ref)` 换取短时效 URL |
225
- | 多张参考图 | 由上述字符串组成的非空数组,数量先按服务端契约校验 |
112
+ text/vision 的 model、System Prompt 与可调参数来自 `meta.json`;Page 只传 `params` 和 `messages`。image/video 的固定生成配置同样在 `meta.json`,Page 每次传 prompt 与允许的参考输入。Ark Chat 的 `choices.message.content` / `choices.delta.content` 是文本,因此 vision 是多模态输入、文本输出;媒体输出必须走 image/video 任务。
226
113
 
227
- `file_token` 只是附件资源标识,不能直接传给模型;浏览器 `blob:` URL 也不能使用,因为它只在当前页面上下文有效。不要手工拼 Box 下载地址。Base 附件场景同时读取[文件传输](file-transfer.md#展示与下载),使用真实的 `tableId`、`fieldId`、`recordId` 和 `fileToken` 证明附件位置:
114
+ 流式 UI 同时消费思考过程和最终答案,结构化解析只基于最终 answer:
228
115
 
229
116
  ```ts
230
- import {
231
- createSiteAIFunctionTask,
232
- fetchAttachmentDownloadUrl,
233
- resolveDatabaseContext,
234
- } from '@lark-base-open/base-database-app-sdk/page';
117
+ import { invokeSiteAIFunctionStream } from '@lark-base-open/base-database-app-sdk/page';
235
118
 
236
- const context = await resolveDatabaseContext();
237
- const sourceImageUrl = await fetchAttachmentDownloadUrl(context, {
238
- tableId,
239
- fieldId,
240
- recordId,
241
- fileToken,
119
+ let finalAnswer = '';
120
+ const stream = invokeSiteAIFunctionStream({
121
+ functionKey: 'recommend_dishes',
122
+ params: { menu },
123
+ messages: [{ role: 'user', content: [{ type: 'text', text: question }] }],
242
124
  });
243
-
244
- const task = await createSiteAIFunctionTask({
245
- functionKey: 'generate_poster',
246
- capability: 'image',
247
- input: {
248
- prompt: '保留主体,生成夏日海报',
249
- image: sourceImageUrl,
250
- },
125
+ stream.onMessage((delta) => {
126
+ if (delta.reasoningContent) appendReasoning(delta.reasoningContent);
127
+ if (delta.content) {
128
+ finalAnswer += delta.content;
129
+ appendAnswer(delta.content);
130
+ }
131
+ });
132
+ stream.onError((error) => {
133
+ setLoading(false);
134
+ showError(error.message);
135
+ });
136
+ stream.onDone(() => {
137
+ setLoading(false);
138
+ showItems(parseAnswer(finalAnswer));
251
139
  });
252
- // 使用 getSiteAIFunctionTask(functionKey, task.taskId) 继续轮询。
253
- ```
254
-
255
- helper 负责提交附件位置并获取经过权限校验的临时 URL,页面不手工拼接下载地址或注入凭证。临时 URL 不持久化、不记录日志;在目标环境验证它无需浏览器 Cookie、可由模型访问且有效期覆盖模型读取。不满足时报告附件不可作为当前模型输入;用户同意改用其他来源后再处理,不能退回传 `file_token`。
256
-
257
- 新建 Page 默认使用 `response_format: "url"`。平台配置层也接受 `b64_json`,但当前 Page helper 的媒体结果只暴露 `imageAssets[].url/token`,没有可直接渲染的 base64 字段;没有额外、已验证的附件展示链路时,不要选择 `b64_json`。
258
-
259
- ## 可用模型 Profile
260
-
261
- 需要选择模型或确认可用参数时,先通过 OpenAPI 获取当前应用可用的模型列表,不要猜 Profile ID:
262
140
 
263
- ```bash
264
- APP_TOKEN='<appToken-from-base-database.jsonc>'
265
- base-database-cli lark-cli -- \
266
- api GET "/open-apis/base/v3/sites/${APP_TOKEN}/ai/model_profiles" \
267
- --json
141
+ // 仅在用户取消、新请求替代旧请求或组件卸载时调用。
142
+ const cancel = () => stream.destroy();
268
143
  ```
269
144
 
270
- `APP_TOKEN` 必须取当前 `base-database.jsonc` 中的 `appToken`;对应接口模板是 `/open-apis/base/v3/sites/:token/ai/model_profiles`,其中兼容路径参数 `:token` 表示应用 appToken。查询必须带上当前应用的 token,不能省略该路径参数。
145
+ `appendReasoning`、`appendAnswer`、`setLoading`、`showError`、`showItems` 和 `parseAnswer` 都是页面自己的状态更新函数。不要在注册回调后立即销毁;每个交互实例只保留一条活动流。
271
146
 
272
- 响应中的 `profiles[].profile_id` 才能作为 `model_profile_id`;每个 profile 带 `capability` 标记(text/vision/image/video)和 `input_modalities`。image/video 生成能力必须匹配同能力 Profile;vision 可使用 vision Profile,或使用声明了 image / video / audio / file 中至少一种媒体输入的 text Profile。页面只提交该 Profile 声明支持的 content parts,不需要模型服务地址或模型凭证。
147
+ 优先复用 starter 的 `page/src/examples/ai-function/TextStreamOperation.tsx`、`ai-media-panel.tsx` 中的 `AIImagePanel` / `AIVideoPanel`,而不是重新实现流式状态和媒体轮询。页面 API 以已安装 SDK 的 `docs/README.md` 为准;starter 的 `page/src/lib/database-runtime.ts` 是当前工程的统一封装入口。
273
148
 
274
- **profile 字段与 AI Function 配置字段不是一一对应**:profile 里的 `thinking_levels`(如 `off/minimal/low/medium/high/max`)描述的是上游模型自身能力,不能直接填进 `meta.json`。AI Function 配置只接受本文档列出的枚举值:`text.reasoning_depth` 只能是 `off` / `light` / `standard` / `deep`。把 profile 的其他 `thinking_levels` 值(例如 `low`)当作 `reasoning_depth` 会被 `ai-functions validate` 拒绝并返回 `[code=800004006] invalid reasoning_depth`。选参数看 profile 能力,配 `reasoning_depth` 用本文档枚举,两者不要混。
149
+ `task_id` 是不透明的任务标识,SDK 映射为 `taskId`。原样保存 Function key、环境与 task ID;不要解析它或用 Base record ID 替代。查询成功不等于生成成功;总轮询必须有时限,失败或取消后停止,不要用没有总时限或取消处理的 `while` 轮询,也不要因超时自动重新提交。
275
150
 
276
- `reasoning_depth: "off"` 表示请求关闭深度思考,以缩短模型响应时间。只有所选 Profile 的 `thinking_levels` 包含 `off` 时才会真正向上游发送 `thinking.type=disabled`;如果该模型必须深度思考,服务端会忽略关闭意图并使用 Profile 的 `default_thinking_level` 保持思考开启。搭建页也只会为支持 `off` 的模型展示关闭选项;从可关闭模型切到强制思考模型时,页面改用“模型默认”,不把 `max` / `xhigh` / `minimal` 近似改写成可能不受支持的 `deep` / `light`。
277
-
278
- `ai-functions validate` 校验的是跨 Profile 配置枚举,因此强制思考模型配置 `off` 仍会校验成功;这不代表关闭已经生效。CLI 搭建前必须同时检查 `model_profiles`:目标 Profile 不含 `off` 时,运行态会保持思考开启。平台后续新增或移除某个 Profile 的 `off` 会改变已持久化 `off` 配置的实际行为;发布这类 Profile 变更前先盘点对应 AI Function,并在目标环境回归原始 SSE 的 `reasoning_content` / `reasoning_tokens`。
279
-
280
- ## CLI 建模与调试
281
-
282
- AI Function 在本地以声明式目录维护:每个 `ai/<functionKey>/meta.json` 声明一个 AI Function,`deploy` 时随发布走**全量覆盖**同步(适用条件与发布顺序见[发布参考](release.md#function-发布顺序与错误边界))。
151
+ 没有公共等价能力的辅助命令只有:
283
152
 
284
153
  ```bash
285
- # 列出应用中的 AI Function
286
- base-database-cli ai-functions list
287
-
288
- # 查看草稿配置;--env prod 仅显示已发布公开契约
289
- base-database-cli ai-functions get <functionKey>
290
-
291
- # 恢复草稿配置到本地文件
292
- base-database-cli ai-functions pull <functionKey>
293
-
294
- # 全量覆盖同步本地 ai/ 声明
295
- base-database-cli ai-functions sync
296
-
297
- # 编辑期可选:静态校验单个 AI Function
298
- base-database-cli ai-functions validate <functionKey>
299
-
300
- # 调试 text/vision:聚合返回完整文本与 firstTokenMs
301
- base-database-cli ai-functions debug <functionKey> \
302
- --env preview --messages '[{"role":"user","content":[{"type":"text","text":"概括缺货风险"}]}]' --params '{"menu":"..."}'
154
+ # 模型 profile 与自描述参数
155
+ base-database-cli ai-functions models
303
156
 
304
- # 调试 image/video:两者都提交媒体任务并返回 task_id;image 可带一张或多张参考图
305
- base-database-cli ai-functions debug <functionKey> \
306
- --env preview \
307
- --input '{"prompt":"保持角色一致,生成一组新品海报","image":["https://example.com/ref-1.png","https://example.com/ref-2.png"]}' \
308
- --params '{}'
309
-
310
- # 查询文生图 / 文生视频任务
157
+ # 查询原媒体任务
311
158
  base-database-cli ai-functions task <functionKey> <task_id> --env preview
312
159
 
313
- # 查看用量汇总(总量 + 按日期分布 + 按 Function/能力/错误码分维度)
160
+ # 查询应用 owner 的用量汇总
314
161
  base-database-cli ai-functions usage \
315
- --env prod --from 20260901 --to 20260908 --function-key <functionKey> \
316
- --model <profileId> --capability-type text
162
+ --env prod --from 20260901 --to 20260908 \
163
+ --function-key <functionKey> --model <profileId> --capability-type text
317
164
  ```
318
165
 
319
- CLI 调试对 text/vision 返回聚合文本,对 image/video 返回 task_id;随后使用 `ai-functions task` 查询任务。验证页面逐帧显示时,使用 `invokeSiteAIFunctionStream` 并观察回调。
320
-
321
- 应用所有者可用 `ai-functions usage` 查询用量汇总。对应接口 `GET /open-apis/base/v3/sites/:token/ai_functions/usage/summary` 返回总量、`by_date`(Key 为 `YYYYMMDD`)、`by_function`、`by_capability`、`error_dist`。`from/to` 为 `YYYYMMDD` 区间(含),不传则聚合全部历史。`--model` 接受 `model_profiles` 返回的 `profiles[].profile_id`。
166
+ `disabled` 是 `config.disabled`;省略或 `false` 表示可调用,`true` 表示保留配置但停止调用。
322
167
 
323
- ## 任务受理与完成
168
+ ## 参考图与多模态输入
324
169
 
325
- image / video 创建任务后返回 `task_id` 和状态。使用同一应用、Function 与环境轮询,处理 `queued`、`running`、`succeeded`、`failed`、`cancelled`,仅在成功终态读取生成资源。平台会在应用绑定的 Base 中维护任务记录;页面通过任务接口读状态,不直接修改这些记录。
170
+ 只提交所选 profile 的 `input_modalities` 声明支持的类型。可能出现的类型为 `text`、`image`、`video`、`audio`、`file`;具体 content part 结构以当前 SDK 类型为准,不能把对象位置改成裸字符串。vision profile 必须声明 image / video / audio / file 中至少一种媒体输入。
326
171
 
327
- `task_id` 是不透明的任务标识,原样传给查询接口;不要解析它或用 Base record ID 替代。创建失败时报告错误,不凭空构造 task_id。
172
+ 参考图先转换为模型上游可读取的字符串引用,再放入 `input.image`:
328
173
 
329
- ## Page 调用方式
174
+ | 来源 | 传入值 |
175
+ | --- | --- |
176
+ | 公网可访问图片 | HTTPS URL |
177
+ | 浏览器本地 `File` | `FileReader.readAsDataURL` 得到的完整 `data:image/...;base64,...` |
178
+ | Base 附件 | `fetchAttachmentDownloadUrl(context, ref)` 返回的短时效 URL |
179
+ | 多张参考图 | 上述字符串组成的非空数组 |
330
180
 
331
- 页面运行时 API 用法以工程已安装的 SDK 文档为准:读取 `node_modules/@lark-base-open/base-database-app-sdk/docs/README.md`,再按索引查看对应页面文档;旧模板可查[冻结的 AI 参考](legacy-ai-function.md#page-调用方式)。AI Function 的 Page 输入、能力与任务结果约束仍按本页前文执行。若工程使用 `defineFunction`,CLI 生成的 `meta.inputSchema` 是 Agent 开放能力的 schema;已有工程手写的 `meta.json` `inputSchema` 保持兼容,不要求迁移。
181
+ `file_token` 只是附件资源标识,不能直接传给模型;浏览器 `blob:` URL 也不能使用,因为它只在当前页面上下文有效。不要手工拼接下载地址:
332
182
 
333
- ## System prompt 与数据边界
183
+ ```ts
184
+ import {
185
+ createSiteAIFunctionTask,
186
+ fetchAttachmentDownloadUrl,
187
+ resolveDatabaseContext,
188
+ } from '@lark-base-open/base-database-app-sdk/page';
334
189
 
335
- System Prompt 在 **AI Function 配置**里维护,随版本快照进入线上;平台不代管、不隐藏,也**不承诺保护 System Prompt**,因此不得放入密钥、Token、内部凭据或不可向最终访问者暴露的内容。页面通过 `params` 注入运行时值,占位符 `{{var}}` 由服务端渲染。
190
+ const context = await resolveDatabaseContext();
191
+ const sourceImageUrl = await fetchAttachmentDownloadUrl(context, {
192
+ tableId,
193
+ fieldId,
194
+ recordId,
195
+ fileToken,
196
+ });
197
+ const task = await createSiteAIFunctionTask({
198
+ functionKey: 'generate_poster',
199
+ capability: 'image',
200
+ input: { prompt: '保留主体,生成夏日海报', image: sourceImageUrl },
201
+ });
202
+ ```
336
203
 
337
- 传给模型的数据遵循最小必要原则。Database Function 查询结果先在 Page 内筛选字段和记录,只发送完成当前任务所需的内容;不得把整个 Catalog、整表数据、登录凭证或原始下游响应无差别塞入 `messages` / `params`。
204
+ helper 负责获取经过权限校验的临时 URL。URL 不持久化、不记录日志;确认它无需浏览器 Cookie、有效期覆盖模型读取。条件不满足时报告当前附件不可作为模型输入,不能退回传 `file_token`。
338
205
 
339
- ## 计费与失败处理
206
+ 参考图和输出数量上限按实际选择的 model_profiles 和服务端校验反馈确定,不从示例推断。平台配置可能接受 `b64_json`,但当前 Page helper 没有可直接渲染的 base64 字段;没有已验证的展示链路时使用 URL。
340
207
 
341
- - 模型/媒体用量计费到当前应用 owner;访问者发起请求不改变计费主体。页面文案如展示用量归属,应明确这一点。
342
- - 平台还可能因 AI credit 耗尽、并发已满或调用超时而拒绝调用。页面仍需防止重复提交。
343
- - 一个交互实例只维护一条活动流。发送期间禁用重复提交;用户取消、组件卸载或新请求替代旧请求时调用 `destroy()`。`onDone` / 返回结果表示正常结束;`onError` 表示失败;两者都必须结束 loading。
208
+ ## 数据与安全边界
344
209
 
345
- ### 未开通 AI Function 时
210
+ System Prompt 只能由 AI Function 配置管理,随版本快照进入线上;平台不代管、不隐藏,也不承诺保护 System Prompt。不得放入密钥、Token、内部凭据或不可向最终访问者暴露的内容。
346
211
 
347
- AI Function 的管理接口(`ai-functions list/pull/validate/sync/usage` 以及 `deploy` 内的同步)按当前用户做 feature gate。未开通的用户会收到业务码 `800004011`、消息 `ai function feature is not enabled`;CLI 会把它翻译为带降级路径的错误。它不是 scope 缺失,重新 `auth login` 不会改变结果,不要循环授权或重试。
212
+ 传给模型的数据遵循最小必要原则。Database Function 结果先在 Page 内筛选字段和记录,不把整个 Catalog、整表数据、登录凭证或原始下游响应无差别放入 `messages` / `params`。
348
213
 
349
- 处理方式:向用户说明当前账号未开通 AI Function;需求中的 AI 部分标记为阻塞,恢复条件是账号开通后重新 `deploy`。其余 Page、Database Function、FaaS 用 `deploy --skip-ai-functions` 正常发布,交付报告写明 AI Function 未同步、页面中的 AI 入口在开通前不可用。降级前按[发布错误边界](release.md#function-发布顺序与错误边界)核对已执行步骤;未知写入先只读确认,不能盲目重跑。
214
+ 模型和媒体用量计费到当前应用 owner;访问者发起请求不改变计费主体。
350
215
 
351
- ### 页面如何处理运行态错误
216
+ ## 失败处理
352
217
 
353
- 参阅已安装 SDK 文档,入口见[Page 调用方式](#page-调用方式)。
218
+ - 一个交互实例只维护一条活动流。发送期间禁用重复提交;用户取消、组件卸载或新请求替代旧请求时调用 `destroy()`。`onDone` 与 `onError` 都必须结束 loading。
219
+ - 页面只能通过宿主 broker 调用,不能直连模型域名或在代理失败时绕过宿主。
220
+ - 超时、断网或返回未知时可能已经执行并计费;保留 `requestId` / LogID,先只读确认,不自动重试。
354
221
 
355
- ## 页面实现检查
222
+ | 失败 | 排查方向 |
223
+ | --- | --- |
224
+ | `AI credit is exhausted` | 应用 owner 的 AI credit 已耗尽;停止提交并提示补充额度 |
225
+ | Function 不存在 | 核对本地声明、目标环境与本次草稿原子提交结果 |
226
+ | `ai function is disabled` | 检查该 Function 的 `disabled: true` 配置 |
227
+ | 模型不可用或参数不支持 | 重新运行 `ai-functions models`,按当前 profile 自描述修正配置 |
228
+ | `800004011` 且明确返回 `ai function feature is not enabled` | 账号未开通 AI Function;这不是 scope 问题,重新 `auth login` 无效 |
229
+ | 并发限制或服务错误 | 保留脱敏错误、`requestId` / LogID,并按实际错误处理 |
356
230
 
357
- 按工程已安装的 SDK 文档验证调用、取消、错误与输出语义;老模板参考[冻结检查](legacy-ai-function.md#页面实现检查)。AI Function 页面只能通过宿主 broker 调用,不能直连模型域名或在代理失败时绕过宿主。
231
+ 统一 Function 接口可能只返回 `800004011`、`function write failed` 与 LogID;CLI 无法读取服务端日志,也不能从 LogID 推断是哪一个 capability / feature gate。此时保留 LogID 供后端支持排查,不把它解释成 AI Function 门禁,不重登,也不自动 skip。只有公开回执明确给出 AI Function feature gate 原因、且用户明确接受“本次不对齐远端 AI Function,继续发布其他能力”后,才可使用 `deploy --skip-ai-functions`;不得自动追加参数重试,并在交付中标记 AI Function 未同步、未验证。
358
232
 
359
- 配置校验、运行态调用与 UI 流式成功的区别见[AI 验收判定](verification.md#ai-验收判定)。
233
+ 执行显式 skip 后,命令失败或没有返回本次 publish ID 时,不因缺少目录参数等猜测改写命令重试,也不查询历史 publish ID 代替本次结果。只有回执明确证明未执行任何部署写入时,才报告 Page 和其他 Function 未发布;超时、断网、响应丢失或其他未知结果统一报告远端状态未知,保留原错误与 LogID,并按[发布参考](release.md#function-发布顺序与错误边界)有限只读核对。两种情况都标记 AI Function 未同步且未验证。
360
234
 
361
- ## AI Function 交付 checklist
235
+ 配置写入成功、公共 invoke 成功、页面流式成功是三层不同证据,不能互相替代;统一判定见[验证方法与 Function 证据分层](verification.md#function-证据分层)。运行态未检查时列为未验证,Prod 是否验证按用户诉求决定。
362
236
 
363
- ```text
364
- 1. 查询 model_profiles,选择 capability 匹配的 profile_id。
365
- 2. 写 ai/<functionKey>/meta.json,由 deploy 校验(reasoning_depth 用 off/light/standard/deep;仅当 profile 的 thinking_levels 含 off 时关闭才生效)。
366
- 3. 文本流式 UI 同时消费 delta.reasoningContent 与 delta.content。
367
- 4. `callSiteAIFunction` 显式传 capability;文生图/文生视频使用 create task + poll task,不走文本 stream。
368
- 5. 修改已有应用时,远端全部 key 已恢复到本地,未意外触发全量删除。
369
- 6. record_id 不依赖短长度(^rec[A-Za-z0-9]{1,32}$)。
370
- 7. 运行态未检查即列未验证;用户要求验收时按下述 AI 验收判定执行,Prod 验证按用户诉求决定。
371
- ```
237
+ ## 同步与恢复
372
238
 
373
- CLI 的 list/get/debug/task 默认 `--env preview`;prod 只读已发布版本,不作为草稿编辑依据。env 是函数版本,不是 CLI 运行环境。list 会读取全部分页后筛选 AI,pull 缺少 spec 或权限失败时停止。validate 仅验证指定本地项,不写入、不调用模型;sync 使用 kinds=[ai] 全覆盖,管理写入与校验不传 env。
239
+ AI Function 与其他 Function 一样由公共 `pull` 恢复完整工程,不按 Function 类型分别拉取;当前 `source_code` 恢复规则只在[工程恢复](workspace.md#先选择工程来源)维护。
374
240
 
375
- 运行态验收方法见[AI 验收判定](verification.md#ai-验收判定)。
241
+ 新增、修改或删除 AI Function 时先修改本地声明,再执行普通 Preview deploy;统一写入、删除与未知结果恢复只在[Function 发布顺序与错误边界](release.md#function-发布顺序与错误边界)维护。
376
242
 
377
- CLI debug 使用 `--params` 对象:text/vision 发送 `{params,messages}`,image/video 发送 `{params,input}`;不能混用 messages 和 input。新请求不传 mode/output_mode。媒体任务回执 `task_id` 仅表示受理,保存 key/env 后续查原任务;查询成功不表示生成成功,failed/cancelled 停止并报告错误,不重新提交。SDK 对页面保持 `taskId` 字段。超时/断网可能已执行和计费,结果未知时保留 requestId/LogID,不自动重试。
243
+ Prod 沿用公共流程提升已确认的同一 Preview 制品;不为 AI Function 另建恢复、同步或发布流程。
@@ -6,7 +6,7 @@
6
6
 
7
7
  能力归属无法确认时,在以下动作之前强制执行能力发现:
8
8
 
9
- - 选择 Page、Database Function、Mutation、FaaS 或原生 Base 的实现归属;
9
+ - 选择 Page、Database Function、Mutation、FaaS、AI Function 或原生 Base 的实现归属;
10
10
  - 删除、简化或降级一项用户需求;
11
11
  - 声称多维表格、Base Database 或 `lark-cli` 不支持某项能力;
12
12
  - 用 FaaS 模拟定时触发、记录变化触发、提醒、通知、权限控制等 Base 本体行为。
@@ -54,7 +54,7 @@ lark-cli base +<resource-list-or-get> ... --as user
54
54
  查询完成后只选择以下一种结论:
55
55
 
56
56
  1. **原生 Base 实现**:能力由多维表格本体提供。通过 `lark-cli base +...` 配置,应用只提供需要的交互页面。
57
- 2. **Base Database 实现**:能力属于页面交互、Database Function 读取或由 Page 主动发起的即时业务写入,按 Page/Database Function 与[Mutation/FaaS 选择](mutations.md#写入方式选择)实现。
57
+ 2. **Base Database 实现**:能力属于页面交互、Database Function 读取、AI Function 模型能力,或由 Page 主动发起的即时业务写入;按 Page/Database Function、[AI Function](ai-function.md) 与[Mutation/FaaS 选择](mutations.md#写入方式选择)实现。
58
58
  3. **组合实现**:例如 Page 调用 Mutation/FaaS 创建记录,原生 workflow 监听记录并通知;分别配置并独立验收两段链路。
59
59
  4. **已证实的缺口或阻塞**:找不到当前 CLI 入口、命令明确不支持,或遇到权限或环境阻塞。准确描述为“当前 `lark-cli` 未暴露”“原生能力明确不支持”或“当前身份无权限”,不要互相替代。
60
60
 
@@ -180,11 +180,13 @@ LIMIT 30
180
180
  6.0 多选按名称筛选使用 `(多选字段).name @> $n`,将 `$n` 声明为 `TEXT[]`。数组作为一个参数传入,例如声明 `{"name":"tags","kind":"TEXT[]","description":"要包含的多选选项名称列表"}`,Page 传 `params: { tags: ["选项名"] }`,不拆成多个标量;空数组不要求任何选项,但仍只匹配多选值非 NULL 的行。整体 NULL 参数或含 NULL 成员的参数数组不匹配任何行。单个非 NULL 名称也可使用 `(多选字段).name @> ARRAY[$n]`,其中 `$n` 声明为 `TEXT`;该写法传 NULL 会被拒绝。
181
181
 
182
182
 
183
+ Page API 示例适用版本:SDK 0.2.0 起;其他版本以工程已安装 SDK 包内 docs 为准,升级见[SDK 升级流程](development.md#工程迁移与-sdk-升级)。
184
+
183
185
  <!-- example: sql-named-array -->
184
186
  ```ts
185
187
  import { invokeDatabaseFunction } from '@lark-base-open/base-database-app-sdk/page';
186
188
  export const loadByTags = () =>
187
- invokeDatabaseFunction<{ rows: unknown[] }>('listByTags', { tags: ['选项名'] });
189
+ invokeDatabaseFunction('listByTags', { tags: ['选项名'] });
188
190
  ```
189
191
 
190
192
  示例中的 listByTags 必须声明上述 tags 参数;SQL 内将该一维数组映射到单个 `$n`,不是把 Page 请求改成位置数组。
@@ -312,10 +314,12 @@ LIMIT 20
312
314
 
313
315
  命名路由 Page 与外部 Agent 按冻结名称传对象;FaaS 内部 context 仍按 `meta.params` 顺序传数组。Page 使用 starter 的 runtime client,不传 projectId:
314
316
 
317
+ Page API 示例适用版本:SDK 0.2.0 起;其他版本以工程已安装 SDK 包内 docs 为准,升级见[SDK 升级流程](development.md#工程迁移与-sdk-升级)。
318
+
315
319
  ```ts
316
320
  import { invokeDatabaseFunction } from '@lark-base-open/base-database-app-sdk/page'
317
321
 
318
- await invokeDatabaseFunction<{ rows: unknown[] }>(
322
+ await invokeDatabaseFunction(
319
323
  'searchTasks',
320
324
  { keyword: '%评审%', status: '待处理', limit: 20 },
321
325
  )
@@ -365,7 +369,7 @@ Page 新入口 HTTP body:
365
369
  }
366
370
  ```
367
371
 
368
- 先检查 `code===0` 和 `data`,再验证 `data.rows` 以及每一行的数据结构。
372
+ 先检查 `code===0` 和 `data`,运行时确认 `data.rows` 是数组,再按 codegen 类型使用;行内业务字段由应用按实际查询契约验证,不在通用示例中逐行猜测类型。
369
373
 
370
374
  ## 校验
371
375