@lark-base-open/base-database-cli 1.1.0 → 1.3.7
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.
- package/CHANGELOG.md +86 -0
- package/LICENSE +6 -0
- package/README.md +55 -31
- package/dist/ai-functions.d.ts +42 -0
- package/dist/ai-functions.d.ts.map +1 -0
- package/dist/ai-functions.js +327 -0
- package/dist/ai-functions.js.map +1 -0
- package/dist/archive.d.ts +21 -0
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +65 -10
- package/dist/archive.js.map +1 -1
- package/dist/auth.d.ts +8 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +60 -6
- package/dist/auth.js.map +1 -1
- package/dist/check.d.ts +74 -0
- package/dist/check.d.ts.map +1 -0
- package/dist/check.js +283 -0
- package/dist/check.js.map +1 -0
- package/dist/dependency-policy.d.ts +10 -0
- package/dist/dependency-policy.d.ts.map +1 -0
- package/dist/dependency-policy.js +162 -0
- package/dist/dependency-policy.js.map +1 -0
- package/dist/deploy.d.ts +1 -0
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +122 -175
- package/dist/deploy.js.map +1 -1
- package/dist/environment-variables.d.ts +52 -0
- package/dist/environment-variables.d.ts.map +1 -0
- package/dist/environment-variables.js +563 -0
- package/dist/environment-variables.js.map +1 -0
- package/dist/environment.d.ts +1 -1
- package/dist/environment.js +1 -1
- package/dist/environment.js.map +1 -1
- package/dist/function-input-types.d.ts +10 -0
- package/dist/function-input-types.d.ts.map +1 -0
- package/dist/function-input-types.js +160 -0
- package/dist/function-input-types.js.map +1 -0
- package/dist/function-schema.d.ts.map +1 -1
- package/dist/function-schema.js +89 -36
- package/dist/function-schema.js.map +1 -1
- package/dist/init-field-retry.d.ts +17 -0
- package/dist/init-field-retry.d.ts.map +1 -0
- package/dist/init-field-retry.js +127 -0
- package/dist/init-field-retry.js.map +1 -0
- package/dist/init-journal.d.ts +98 -0
- package/dist/init-journal.d.ts.map +1 -0
- package/dist/init-journal.js +492 -0
- package/dist/init-journal.js.map +1 -0
- package/dist/init-schema.d.ts +8 -0
- package/dist/init-schema.d.ts.map +1 -0
- package/dist/init-schema.js +423 -0
- package/dist/init-schema.js.map +1 -0
- package/dist/init.d.ts +14 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +886 -243
- package/dist/init.js.map +1 -1
- package/dist/lark-cli-error.d.ts +46 -0
- package/dist/lark-cli-error.d.ts.map +1 -0
- package/dist/lark-cli-error.js +171 -0
- package/dist/lark-cli-error.js.map +1 -0
- package/dist/lark-cli.d.ts +2 -1
- package/dist/lark-cli.d.ts.map +1 -1
- package/dist/lark-cli.js +292 -29
- package/dist/lark-cli.js.map +1 -1
- package/dist/mutation-schema.d.ts +146 -0
- package/dist/mutation-schema.d.ts.map +1 -0
- package/dist/mutation-schema.js +153 -0
- package/dist/mutation-schema.js.map +1 -0
- package/dist/mutation.d.ts +10 -0
- package/dist/mutation.d.ts.map +1 -0
- package/dist/mutation.js +131 -0
- package/dist/mutation.js.map +1 -0
- package/dist/npm.d.ts +1 -0
- package/dist/npm.d.ts.map +1 -1
- package/dist/npm.js +2 -2
- package/dist/npm.js.map +1 -1
- package/dist/preview-receipt.d.ts.map +1 -1
- package/dist/preview-receipt.js +15 -5
- package/dist/preview-receipt.js.map +1 -1
- package/dist/process.d.ts +3 -1
- package/dist/process.d.ts.map +1 -1
- package/dist/process.js +16 -4
- package/dist/process.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +241 -42
- package/dist/program.js.map +1 -1
- package/dist/project-build.d.ts +25 -0
- package/dist/project-build.d.ts.map +1 -0
- package/dist/project-build.js +229 -0
- package/dist/project-build.js.map +1 -0
- package/dist/project-context.d.ts +344 -0
- package/dist/project-context.d.ts.map +1 -0
- package/dist/project-context.js +485 -0
- package/dist/project-context.js.map +1 -0
- package/dist/project-layout.d.ts +5 -0
- package/dist/project-layout.d.ts.map +1 -0
- package/dist/project-layout.js +24 -0
- package/dist/project-layout.js.map +1 -0
- package/dist/public-sql-error.d.ts +25 -0
- package/dist/public-sql-error.d.ts.map +1 -0
- package/dist/public-sql-error.js +81 -0
- package/dist/public-sql-error.js.map +1 -0
- package/dist/pull.d.ts.map +1 -1
- package/dist/pull.js +54 -15
- package/dist/pull.js.map +1 -1
- package/dist/site-readme.d.ts +3 -0
- package/dist/site-readme.d.ts.map +1 -0
- package/dist/site-readme.js +83 -0
- package/dist/site-readme.js.map +1 -0
- package/dist/workspace-fingerprint.d.ts +21 -1
- package/dist/workspace-fingerprint.d.ts.map +1 -1
- package/dist/workspace-fingerprint.js +81 -2
- package/dist/workspace-fingerprint.js.map +1 -1
- package/package.json +2 -1
- package/skills/lark-base-database/SKILL.md +70 -53
- package/skills/lark-base-database/references/ai-function.md +471 -0
- package/skills/lark-base-database/references/base-capability-routing.md +3 -3
- package/skills/lark-base-database/references/database-function-limitations.md +46 -0
- package/skills/lark-base-database/references/database-function.md +349 -0
- package/skills/lark-base-database/references/design/components/actions-fields.md +16 -0
- package/skills/lark-base-database/references/design/components/code/controls.css +122 -0
- package/skills/lark-base-database/references/design/components/code/controls.tsx +73 -0
- package/skills/lark-base-database/references/design/components/code/date-picker.tsx +42 -0
- package/skills/lark-base-database/references/design/components/code/floating.tsx +41 -0
- package/skills/lark-base-database/references/design/components/code/overlays.tsx +19 -0
- package/skills/lark-base-database/references/design/components/code/select.tsx +34 -0
- package/skills/lark-base-database/references/design/components/code/styles.d.ts +1 -0
- package/skills/lark-base-database/references/design/components/code/theme.css +49 -0
- package/skills/lark-base-database/references/design/components/code/usage.tsx +38 -0
- package/skills/lark-base-database/references/design/components/date-time-number.md +9 -0
- package/skills/lark-base-database/references/design/components/feedback-navigation.md +9 -0
- package/skills/lark-base-database/references/design/components/index.md +18 -0
- package/skills/lark-base-database/references/design/components/overlays.md +9 -0
- package/skills/lark-base-database/references/design/components/patterns/flat-business.md +7 -0
- package/skills/lark-base-database/references/design/components/selection.md +24 -0
- package/skills/lark-base-database/references/design/components.md +91 -0
- package/skills/lark-base-database/references/design/composition.md +90 -0
- package/skills/lark-base-database/references/design/control-recipes.md +107 -0
- package/skills/lark-base-database/references/design/examples.md +172 -0
- package/skills/lark-base-database/references/design/foundations.md +126 -0
- package/skills/lark-base-database/references/design/review.md +82 -0
- package/skills/lark-base-database/references/design/scenes/analysis-report.md +66 -0
- package/skills/lark-base-database/references/design/scenes/brand-showcase.md +70 -0
- package/skills/lark-base-database/references/design/scenes/business-operations.md +85 -0
- package/skills/lark-base-database/references/design/scenes/campaign-report.md +66 -0
- package/skills/lark-base-database/references/design/scenes/dashboard.md +77 -0
- package/skills/lark-base-database/references/design/scenes/festive-campaign.md +69 -0
- package/skills/lark-base-database/references/design/theme.md +27 -0
- package/skills/lark-base-database/references/design/typography.md +56 -0
- package/skills/lark-base-database/references/development.md +165 -32
- package/skills/lark-base-database/references/environment-variables.md +55 -0
- package/skills/lark-base-database/references/faas.md +41 -48
- package/skills/lark-base-database/references/file-transfer.md +25 -25
- package/skills/lark-base-database/references/frontend-design-guide.md +33 -77
- package/skills/lark-base-database/references/mutations.md +295 -0
- package/skills/lark-base-database/references/permission-design.md +24 -24
- package/skills/lark-base-database/references/release.md +54 -27
- package/skills/lark-base-database/references/style-guide.md +10 -67
- package/skills/lark-base-database/references/verification.md +17 -13
- package/skills/lark-base-database/references/workspace.md +71 -22
- package/templates/database-starter/README.md +34 -4
- package/templates/database-starter/database-functions/README.md +8 -0
- package/templates/database-starter/mutations/README.md +19 -0
- package/templates/database-starter/page/README.md +25 -19
- package/templates/database-starter/page/package-lock.json +8 -16
- package/templates/database-starter/page/package.json +2 -3
- package/templates/database-starter/page/src/App.tsx +23 -3
- package/templates/database-starter/page/src/components/UserSelectorEditor/index.tsx +32 -4
- package/templates/database-starter/page/src/components/UserSelectorPanel/index.tsx +104 -34
- package/templates/database-starter/page/src/components/UserSelectorPanel/user-search.test.ts +55 -11
- package/templates/database-starter/page/src/components/UserSelectorPanel/user-search.ts +68 -25
- package/templates/database-starter/page/src/components/database-runtime-ready.tsx +1 -1
- package/templates/database-starter/page/src/components/database-user-menu/index.tsx +4 -7
- package/templates/database-starter/page/src/components/feedback/page-state.tsx +40 -5
- package/templates/database-starter/page/src/components/floating-button/assets/edit-active.svg +3 -0
- package/templates/database-starter/page/src/components/floating-button/assets/edit-default.svg +3 -0
- package/templates/database-starter/page/src/components/floating-button/index.tsx +75 -112
- package/templates/database-starter/page/src/components/floating-button/utils/project-meta.test.ts +107 -37
- package/templates/database-starter/page/src/components/floating-button/utils/project-meta.ts +13 -50
- package/templates/database-starter/page/src/components/ui-language.test.tsx +101 -0
- package/templates/database-starter/page/src/examples/ai-function/ImageTaskOperation.tsx +202 -0
- package/templates/database-starter/page/src/examples/ai-function/README.md +14 -0
- package/templates/database-starter/page/src/examples/ai-function/TextStreamOperation.tsx +184 -0
- package/templates/database-starter/page/src/examples/ai-function/ai-copy.ts +173 -0
- package/templates/database-starter/page/src/examples/ai-function/ai-delta.test.ts +30 -0
- package/templates/database-starter/page/src/examples/ai-function/ai-delta.ts +26 -0
- package/templates/database-starter/page/src/examples/ai-function/ai-language.test.tsx +86 -0
- package/templates/database-starter/page/src/examples/ai-function/ai-media-panel.test.ts +201 -0
- package/templates/database-starter/page/src/examples/ai-function/ai-media-panel.tsx +382 -0
- package/templates/database-starter/page/src/lib/attachment-image.tsx +144 -0
- package/templates/database-starter/page/src/lib/database-function-inputs.generated.ts +4 -0
- package/templates/database-starter/page/src/lib/database-runtime-attachment.test.ts +180 -76
- package/templates/database-starter/page/src/lib/database-runtime.test.ts +130 -10
- package/templates/database-starter/page/src/lib/database-runtime.ts +484 -51
- package/templates/database-starter/page/src/lib/date-time.ts +61 -0
- package/templates/database-starter/page/src/lib/ui-language.ts +86 -0
- package/templates/database-starter/page/src/main.tsx +1 -1
- package/templates/database-starter/page/tsconfig.json +2 -2
- package/templates/database-starter/page/vite.config.ts +1 -2
- package/templates/database-starter/prettierignore +1 -1
- package/templates/database-starter/server-functions/README.md +2 -2
- package/templates/database-starter/server-functions/package-lock.json +4 -4
- package/templates/database-starter/server-functions/package.json +1 -1
- package/dist/agent-guide.d.ts +0 -19
- package/dist/agent-guide.d.ts.map +0 -1
- package/dist/agent-guide.js +0 -31
- package/dist/agent-guide.js.map +0 -1
- package/dist/database-skill.d.ts +0 -24
- package/dist/database-skill.d.ts.map +0 -1
- package/dist/database-skill.js +0 -151
- package/dist/database-skill.js.map +0 -1
- package/skills/lark-base-database/references/base-sql-unsupported.md +0 -42
- package/skills/lark-base-database/references/database-capability-skill.md +0 -40
- package/skills/lark-base-database/references/sql-function.md +0 -289
- package/templates/database-capability/SKILL.md.tmpl +0 -58
- package/templates/database-starter/page/src/components/floating-button/chatbot-entry.test.ts +0 -23
- package/templates/database-starter/page/src/components/floating-button/chatbot-entry.tsx +0 -873
- package/templates/database-starter/page/src/components/floating-button/local-chat-panel.test.ts +0 -25
- package/templates/database-starter/page/src/components/floating-button/local-chat-panel.tsx +0 -197
- package/templates/database-starter/page/src/components/floating-button/utils/env.ts +0 -18
- package/templates/database-starter/sql/README.md +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,91 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.7] - 2026-09-28
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- 支持通过 Mutation 创建、更新、删除记录及追加附件。
|
|
8
|
+
- AI Function 支持图片、视频、音频和 PDF 等多模态输入。
|
|
9
|
+
- 新增 Skill 前端设计指引。
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Database Function 参数对齐 TEXT、INT、DOUBLE、BOOL、TIMESTAMP、INTERVAL,支持一维数组和空值;不再接受 DURATION、USER_ID、GROUP_ID、RECORD_ID 声明。
|
|
14
|
+
- 完善 Skill 的 SQL 使用说明。
|
|
15
|
+
- 新建站点和 README 支持中英日语言。
|
|
16
|
+
- CLI 通用提示改为英文。
|
|
17
|
+
- 新建站点使用 Channel SDK 0.1.3。
|
|
18
|
+
- 更新新建站点的编辑入口。
|
|
19
|
+
|
|
20
|
+
### Removed
|
|
21
|
+
|
|
22
|
+
- 移除应用能力 Skill 及相关 CLI 入口。
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- 部署时跳过未变化的 Base 表绑定。
|
|
27
|
+
- SQL 请求失败时展示结构化错误及诊断信息。
|
|
28
|
+
- 修复附件封面和下载请求缺少站点身份的问题。
|
|
29
|
+
- 修复 AI Function 调试的能力类型判断。
|
|
30
|
+
- 保留 AI Function 批量请求失败时的诊断信息。
|
|
31
|
+
- 修复 Prod 发布结果中的制品信息误用本地 Preview 回执。
|
|
32
|
+
|
|
33
|
+
## [1.3.0] - 2026-09-22
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- 站点工程提供面向展示的 README 模板,记录用户诉求、已提供的业务能力和验证边界;README 随源码制品上传,并可从远端恢复。
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- Skill 引导 Agent 在每次部署前核对 README 与用户需求及当前实现,业务能力变化时先更新说明。
|
|
42
|
+
- `check` 和 `deploy` 要求 README 已填写且包含必要业务章节;旧 Preview 制品需重新生成后才能发布 Prod。
|
|
43
|
+
|
|
44
|
+
## [1.2.0] - 2026-09-21
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- 支持配置、同步和调用 AI Function,覆盖文本、流式及图片、视频等媒体任务。
|
|
49
|
+
- 支持声明、设置、清除和查看第三方 Agent 使用的 FaaS 环境变量,并避免在错误信息中回显变量值。
|
|
50
|
+
- 新增项目级 `check` 命令,在发布前检查并构建 Page、Database Function 与 FaaS。
|
|
51
|
+
- 初始化过程新增本地回执、字段级有限重试和 `--resume` 恢复能力,避免重复创建已确认资源。
|
|
52
|
+
- 为 Database Function 生成输入类型,并在 starter 中提供日期时区和附件图片处理能力。
|
|
53
|
+
- 新增 `context` 命令,汇总当前项目的资源、命令入口和开发上下文。
|
|
54
|
+
- `check` 支持结构化结果和增量检查,便于定位具体失败项。
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- 将 SQL Function 统一更名为 Database Function,并同步命令、文档与生成工程中的术语。
|
|
59
|
+
- 更新 Page starter 的 Channel runtime 接入与宿主组件集成,固定使用可发布的组合制品。
|
|
60
|
+
- 精简公开 npm 包内容,加入许可证并排除维护者内部文件。
|
|
61
|
+
- 生成工程将 Database Function 目录统一为 `database-functions/`,并兼容现有 `sql/` 目录。
|
|
62
|
+
|
|
63
|
+
### Removed
|
|
64
|
+
|
|
65
|
+
- 移除 starter 中的旧 Chatbot 集成;AI 场景统一使用 AI Function。
|
|
66
|
+
- 移除 starter 对 `base-site-js` 和页面 CSRF 注入插件的依赖。
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- 修复附件图片加载时的宿主 Blob 处理和错误透传。
|
|
71
|
+
- 修复初始化前 Schema 校验、部分结果保留及限流字段重试行为。
|
|
72
|
+
- 修复空 AI Function 配置的部署同步和 starter 兼容性检查。
|
|
73
|
+
- 修复应用身份授权缺少权限时的申请与诊断提示。
|
|
74
|
+
- 修复 AI Function 参数与用量契约、Database Function Schema 与交付结果不一致的问题。
|
|
75
|
+
- 修复生成工程依赖安装和部分预览重复构建问题。
|
|
76
|
+
|
|
77
|
+
## [1.1.1] - 2026-09-10
|
|
78
|
+
|
|
79
|
+
### Changed
|
|
80
|
+
|
|
81
|
+
- 应用搭建优先使用本地已安装的 CLI,未安装时仍可直接运行。
|
|
82
|
+
|
|
83
|
+
### Fixed
|
|
84
|
+
|
|
85
|
+
- 修复含自关联或相互关联数据表的应用初始化失败。
|
|
86
|
+
- 修复部分宿主环境下的账号识别与身份检查失败。
|
|
87
|
+
- 修复部分宿主环境下的应用部署和文件上传失败。
|
|
88
|
+
|
|
3
89
|
## [1.1.0] - 2026-09-10
|
|
4
90
|
|
|
5
91
|
### Added
|
package/LICENSE
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
©Lark Technologies Pte. Ltd. All rights reserved. Use is subject to the Legal Agreements outlined here:
|
|
2
|
+
[Feishu User Terms of Service](https://www.feishu.cn/terms)
|
|
3
|
+
[Feishu Privacy Policy](https://www.feishu.cn/privacy)
|
|
4
|
+
[Feishu Open Platform App Service Provider Security Management Specifications](https://open.feishu.cn/document/uAjLw4CM/uMzNwEjLzcDMx4yM3ATM/management-practice/app-service-provider-security-management-specifications)
|
|
5
|
+
[Lark User Terms of Service](https://www.larksuite.com/user-terms-of-service)
|
|
6
|
+
[Lark Privacy Policy](https://www.larksuite.com/privacy-policy)
|
package/README.md
CHANGED
|
@@ -10,12 +10,13 @@ Skill 和配套 CLI,用于基于飞书多维表格创建、开发并发布数
|
|
|
10
10
|
需要 Node.js 20.19 或更新版本,以及可用的 npm。首次安装到 Codex:
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
|
|
13
|
+
npm install -g @lark-base-open/base-database-cli@latest
|
|
14
|
+
base-database-cli install --target codex
|
|
14
15
|
```
|
|
15
16
|
|
|
16
|
-
安装器将自身版本安装到 npm 全局目录,再从全局包安装 Skill;已有同版本 CLI 时只安装 Skill。支持 `--target codex|claude|agents|all` 或 `--dir <skills 根目录>`。安装器也会同步上述受支持用户目录中可确认来源的公开版 Lark Base Database Skill,避免 Agent
|
|
17
|
+
安装器将自身版本安装到 npm 全局目录,再从全局包安装 Skill;已有同版本 CLI 时只安装 Skill。支持 `--target codex|claude|agents|all` 或 `--dir <skills 根目录>`。安装器也会同步上述受支持用户目录中可确认来源的公开版 Lark Base Database Skill,避免 Agent 读取另一份旧副本;自动发现跳过与当前 CLI 来源不匹配或来源不明的副本,不会为未安装的 Agent 新建副本。任一目标已有内容时需显式添加 `--force`,否则在更改 CLI 前停止。单独的 `skill install` 仍只处理所选目标。Codex 使用 `CODEX_HOME/skills`,未设置时使用 `~/.codex/skills`。
|
|
17
18
|
|
|
18
|
-
若已安装的 CLI
|
|
19
|
+
若已安装的 CLI 文件损坏,先用 `npm install -g @lark-base-open/base-database-cli@<精确版本>` 重装,再执行 `base-database-cli update --version <同一精确版本> --yes` 同步已安装的 Skills。测试或私有 registry 环境需在重装时保留对应 npm registry 配置。
|
|
19
20
|
|
|
20
21
|
成功结果包含 CLI 版本、实际入口和 Skill 目录。PATH 不通时输出需加入的目录及可直接运行的 Node/CLI 参数;命令入口缺失时提示检查 npm 的 bin-links 配置。不修改 shell 配置、npm prefix 或 Node 安装。npm 失败时保留错误并停止后续步骤。重新加载 Skill 后,日常直接运行 `base-database-cli …`。
|
|
21
22
|
|
|
@@ -47,6 +48,14 @@ CLI 版本来自包内 `package.json`;每份 Skill 的 `base-database-version.
|
|
|
47
48
|
|
|
48
49
|
## 创建、恢复并发布数据库应用
|
|
49
50
|
|
|
51
|
+
已有或待初始化的本地目录可以先读取一份紧凑、确定性的项目快照:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
base-database-cli context . --summary --json
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`context` 只读取本地配置、Catalog、Function metadata 和 init/Preview 回执。摘要保留环境、资源数量、readiness 与建议的下一步,不输出本地路径、fingerprint 值或逐项资源;排障时去掉 `--summary` 可读取完整快照。Preview freshness 只跟踪 `base-database.jsonc`、Page、Database Function、FaaS 和 AI Function 等部署输入,README、workflow 定义及验收材料不会触发无效重发。缺少 `base-database.jsonc` 时返回 `project.status=uninitialized`,不会报 project-not-found。该命令不读取认证凭证或环境变量值,不调用远端 API,也不执行 `doctor`、`check`、构建或发布;默认输出已经是 JSON,`--json` 用于显式声明机器读取。
|
|
58
|
+
|
|
50
59
|
### 复用 lark-cli profile
|
|
51
60
|
|
|
52
61
|
CLI 复用本机已有的 lark-cli profile,不另存应用密钥或用户 token。通过全局
|
|
@@ -81,6 +90,8 @@ base-database-cli init ./todo-database \
|
|
|
81
90
|
--env online
|
|
82
91
|
```
|
|
83
92
|
|
|
93
|
+
CLI 会先创建每张表的主字段,再在所有表都取得真实 ID 后按原顺序创建其余字段,因此 Schema 可以包含自关联和跨表关联字段。
|
|
94
|
+
|
|
84
95
|
已有 Base 时,不创建或修改 Base。CLI 会读取其中的全部 table,直接创建绑定该 Base 的新应用,获取 Catalog,并生成同样的工程:
|
|
85
96
|
|
|
86
97
|
```bash
|
|
@@ -100,13 +111,27 @@ base-database-cli init ./todo-database \
|
|
|
100
111
|
--description '供个人集中创建、跟踪和完成日常任务'
|
|
101
112
|
```
|
|
102
113
|
|
|
103
|
-
成功结果通过 `baseSource`、`databaseSource` 分别列出 Base 与应用来源,通过 `baseToken`、`appToken` 返回对应 token;新建或复用的应用信息位于 `created.database` 或 `reused.database`。结果同时列出数据表、binding、生成的工程目录、配置文件和 `catalog.json
|
|
114
|
+
成功结果通过 `baseSource`、`databaseSource` 分别列出 Base 与应用来源,通过 `baseToken`、`appToken` 返回对应 token;新建或复用的应用信息位于 `created.database` 或 `reused.database`。结果同时列出数据表、binding、生成的工程目录、配置文件和 `catalog.json`。`developmentReadiness` 明确标记初始化尚未准备 Page/FaaS 依赖或执行本地检查,`nextSteps` 按开发、`base-database-cli check --json`、Preview 发布给出后续命令。
|
|
115
|
+
|
|
116
|
+
初始化失败或在步骤之间中断时,CLI 保留 `.base-database-cli/state/init.json`。字段批次返回完整逐项结果且失败项明确为 `retryable=true` 时,CLI 只重试该字段,单字段最多执行 3 次,按 1 秒、2 秒退避且单次初始化的自动重试等待总计不超过 3 秒;成功后再继续从未尝试的字段。已创建字段不会重发;`retryable=false`、不完整响应、transport 错误和结果未知都不会自动重试,初始化以 `partial` 或 `unknown` 退出并保留回执。
|
|
117
|
+
|
|
118
|
+
确认回执没有结果未知或正在写入的步骤后,使用原命令和原参数追加 `--resume`;CLI 会先核对环境、profile、计划摘要及回执中的真实资源 ID,再跳过已确认步骤并执行尚未开始的步骤。字段批次只有在逐项结果完整且已创建字段 ID 与远端一致时才补剩余字段。参数变化、资源漂移、`unknown` 或写入中的 `running` 都会在恢复写入前停止;恢复不会按名称认领资源、自动删除资源或整体回滚。
|
|
104
119
|
|
|
105
|
-
|
|
120
|
+
```bash
|
|
121
|
+
base-database-cli init ./todo-database \
|
|
122
|
+
--resume \
|
|
123
|
+
--schema ./base-schema.json \
|
|
124
|
+
--name 'Todo 管理' \
|
|
125
|
+
--env online
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
生成项目的 `page/`、`server-functions/`、`database-functions/` 直接位于项目根目录;`base-database.jsonc` 和 `catalog.json` 也保留在根目录。`server-functions/` 是服务端 FaaS Functions 的源码与构建工作区。CLI 的 Preview 状态和发布临时制品统一写入被 Git 忽略的 `.base-database-cli/state/`。
|
|
106
129
|
|
|
107
130
|
### 恢复并修改已有数据库应用
|
|
108
131
|
|
|
109
|
-
已有数据库应用存在源码制品时,使用 `pull` 恢复可编辑工程,不要重新执行 `init`。目标目录必须为空;CLI 会下载当前 `page/`、`server-functions/` 和 `
|
|
132
|
+
已有数据库应用存在源码制品时,使用 `pull` 恢复可编辑工程,不要重新执行 `init`。目标目录必须为空;CLI 会下载当前 `page/`、`server-functions/` 和 `database-functions/` 源码,读取应用 Catalog,并重建 `base-database.jsonc` 与 `catalog.json`,不会创建或修改 Base、应用元信息和 binding:
|
|
133
|
+
|
|
134
|
+
旧制品中的 `sql/` 会在恢复时迁移为 `database-functions/`。本地旧工程仍可直接检查和发布,但不能同时保留两个目录。
|
|
110
135
|
|
|
111
136
|
```bash
|
|
112
137
|
base-database-cli pull ./todo-database \
|
|
@@ -118,10 +143,11 @@ base-database-cli pull ./todo-database \
|
|
|
118
143
|
|
|
119
144
|
### 发布 Preview 和正式版本
|
|
120
145
|
|
|
121
|
-
新建流程是 `init → deploy`;修改已有数据库应用时是 `pull → 修改 → deploy`。Agent 在每个阶段一次性获取所需上下文,根据 Catalog 完整实现 Page、
|
|
146
|
+
新建流程是 `init → 开发 → check → deploy`;修改已有数据库应用时是 `pull → 修改 → check → deploy`。Agent 在每个阶段一次性获取所需上下文,根据 Catalog 完整实现 Page、Database Function 和 FaaS,通过项目级本地检查后发布 Preview:
|
|
122
147
|
|
|
123
148
|
```bash
|
|
124
149
|
cd todo-database
|
|
150
|
+
base-database-cli check --json
|
|
125
151
|
base-database-cli deploy
|
|
126
152
|
```
|
|
127
153
|
|
|
@@ -137,25 +163,6 @@ Preview 回执会记录生成该制品时的工作区输入指纹。Preview 之
|
|
|
137
163
|
Preview 回执同时绑定有效的 lark-cli profile;切换 profile 或旧回执没有 profile
|
|
138
164
|
而当前使用本地 profile 时,需要重新发布 Preview,不能直接推广为正式版。
|
|
139
165
|
|
|
140
|
-
### 部署后的应用能力 Skill
|
|
141
|
-
|
|
142
|
-
每次部署成功后,CLI 自动将该应用的专属 Skill 安装或更新到当前用户的 `$CODEX_HOME/skills`,未配置时使用 `~/.codex/skills`。部署结果的 `agentGuide.skill` 包含安装状态、名称和路径;后续可直接让 Agent 查询或操作这个应用的数据,或输入 `$<skill.name>`。客户端若未刷新技能列表,开启新会话即可。
|
|
143
|
-
|
|
144
|
-
Skill 按需读取正式版的 Function 和参数 Schema,不依赖应用工程目录。Preview 发布也会更新 Skill,但不会把 Preview 当成正式版。安装不授予额外权限,也不会自动执行业务动作。
|
|
145
|
-
|
|
146
|
-
需要单独修复安装或指定其他 Agent 的用户技能目录时:
|
|
147
|
-
|
|
148
|
-
```bash
|
|
149
|
-
base-database-cli --profile <profile-name> database-skill install --app-token <app-token> --title '<应用名称>' --dir <skills-root>
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
只更新本工具管理的该应用 `SKILL.md`,不删除其他文件;安装失败会单独返回,不影响已经成功的应用发布。
|
|
153
|
-
|
|
154
|
-
能力 Skill 使用 `base-database-<hash>` 名称,通过 `database-skill` 命令安装和使用。
|
|
155
|
-
同一应用、环境和 profile 使用固定目录,每次部署更新本工具管理的 `SKILL.md`,保留附加文件。
|
|
156
|
-
生成的发现和调用命令显式携带 profile,不跟随 lark-cli 默认账号变化;托管凭证模式不写入 profile。
|
|
157
|
-
目标目录不受本工具管理或存在符号链接冲突时报告错误,不自动覆盖。
|
|
158
|
-
|
|
159
166
|
## 环境
|
|
160
167
|
|
|
161
168
|
CLI 只支持 `online`,`--env` 默认且仅接受 `online`。保留该参数是为了兼容现有自动化命令;传入其他值会直接失败。所有 lark-cli、OpenAPI、Accounts、应用管理后台和 Page 运行时请求都直接使用线上域名,不启动代理、不改写域名,也不向项目配置写入环境路由。
|
|
@@ -167,11 +174,18 @@ base-database-cli auth login --env online
|
|
|
167
174
|
base-database-cli doctor --env online
|
|
168
175
|
```
|
|
169
176
|
|
|
170
|
-
`auth login` 使用上述规则选中的 lark-cli profile
|
|
177
|
+
`auth login` 使用上述规则选中的 lark-cli profile,并申请多维表格相关的用户身份权限(`--domain base`),显式补充
|
|
178
|
+
`base:appmode:read`、`base:appmode:create`、`base:appmode:update`。仅未指定
|
|
171
179
|
profile 且 lark-cli 尚未配置时,才自动启动首次 `config init --new`;指定的 profile
|
|
172
180
|
不存在时直接报错,不创建或覆盖配置。
|
|
173
181
|
|
|
174
|
-
|
|
182
|
+
CLI 明确报告 scope 权限不足时,使用同一 profile 重新执行 `auth login`;若错误另有应用权限开通或额外 scope 的处理要求,按错误提示处理。正常业务调用不增加权限探测。
|
|
183
|
+
`doctor` 复用登录状态中的 scope 列表检查上述三个用户权限,缺少时列出 `missing_scopes` 并提示重新登录;未返回 scope 列表时报告 `unavailable`,托管授权报告 `host_managed`。此项不代替应用侧权限开通检查。
|
|
184
|
+
|
|
185
|
+
Base Database CLI 按 `PATH` 顺序选择第一个可识别的 `lark-cli`。可通过 `BASE_DATABASE_LARK_CLI_PATH` 指定已确认的可执行文件绝对路径;显式路径优先于 PATH。
|
|
186
|
+
|
|
187
|
+
宿主入口缺少 `config` 且未选择 profile 时,CLI 保留宿主认证上下文,不生成虚构的本地 profile;指定 profile 却无法核验时仍报错。缺少 `auth` 时,`doctor` 和 `auth whoami` 使用当前用户只读接口核验身份,`doctor` 还检查应用列表接口;认证失败和权限错误不会按命令缺失跳过。宿主登录、退出仍由宿主提供,不模拟成功。Skill 文档命令 `skills read` 缺失时可直接读取已安装文件,不影响业务执行。
|
|
188
|
+
|
|
175
189
|
|
|
176
190
|
## 项目配置
|
|
177
191
|
|
|
@@ -205,16 +219,26 @@ base-database-cli auth login|logout|whoami
|
|
|
205
219
|
base-database-cli doctor
|
|
206
220
|
base-database-cli init
|
|
207
221
|
base-database-cli pull
|
|
222
|
+
base-database-cli environment-variables list|declare|set|clear
|
|
223
|
+
base-database-cli check [directory] [--no-install | --force-install] [--force-build] [--json]
|
|
208
224
|
base-database-cli deploy
|
|
209
225
|
base-database-cli deployments status
|
|
210
226
|
base-database-cli lark-cli -- <arguments...>
|
|
211
227
|
```
|
|
212
228
|
|
|
213
|
-
`
|
|
229
|
+
`check` 用于开发期本地检查:验证工程配置、页面标题、Function metadata 和输入 Schema,先从 Database Function/FaaS metadata 生成 Page Function 输入类型,再使用 CLI 内置 npm 按依赖指纹准备 Page/FaaS 依赖并运行两者的 build(starter 的 build 包含类型检查)。默认目录为当前目录;`--no-install` 要求依赖已存在,`--force-install` 强制重装,两者不能同时使用。
|
|
230
|
+
|
|
231
|
+
成功的 Page 和 FaaS build 会分别按源码、lock、Node/npm、平台和构建环境指纹缓存在 `.base-database-cli/state/check-build/`。输入未变化时后续 `check` 直接复用对应结果;只有一侧失败时,修复重试会保留并复用另一侧的成功结果。`--force-build` 忽略这份构建缓存,`--force-install` 会同时重新安装并重新构建;`deploy` 仍执行完整 build,不复用本地 `check` 的构建结果。
|
|
232
|
+
|
|
233
|
+
使用 `--json` 时,成功或失败的 stdout 都是单个 JSON 文档,报告 `schemaVersion` 为 `2`;成功结果的 `functions["database-functions"]` 和 `functions["server-functions"]` 分别计数两类本地 Function。构建日志在失败时收敛到 `error.diagnostics`;失败结果还提供稳定的 `error.code`、`error.stage`、阶段状态和 `nextActions`,`cache.pageBuild` / `cache.faasBuild` 使用 `hit`、`miss`、`not_run` 单独表达缓存状态,不改变 `checks.*=passed` 的成功语义。不加该参数时保留面向终端的实时 npm/build 输出和文本错误。命令会更新 `page/src/lib/database-function-inputs.generated.ts`、生成本地缓存和构建输出,不调用应用 API、不修改 binding、不上传或发布,也不改写初始化和 Preview 回执。结果中的 `sqlValidation.status=not_run` 表示服务端查询语法、Catalog 与绑定校验未执行;本地通过不代表查询语句或业务运行态已通过。
|
|
234
|
+
|
|
235
|
+
`deploy` 在一次调用内先生成 Function metadata 并完成全部查询校验,通过后再检查依赖指纹、执行必要的依赖安装、Page/FaaS build、archive、Functions sync、Artifact upload、Preview publish 和状态轮询。CLI 会汇总全部未通过的 Database Function 后一次性报错;存在任一查询校验失败时不会安装依赖或执行 build。依赖指纹未变化且对应 `node_modules` 仍存在时,默认跳过该子项目的 `npm ci`;`--force-install` 强制重装,`--no-install` 无条件跳过安装。build 仍会在每次 Preview deploy 中执行;`check` 不替代发布门禁。FaaS 子项目必须保留可通过 `npm run build` 执行的构建脚本。
|
|
236
|
+
|
|
237
|
+
FaaS 中静态引用的 `process.env` 变量通过 `environment-variables` 命令管理。定义由 Preview 和 Prod 共享,两套值独立保存;Config 查询时明文返回,Secret 只返回脱敏值。`declare` 创建共享定义并默认拒绝覆盖同名但元数据不同的定义;确认影响后可用 `--force` 修改。声明必须显式传入 `--target`、`--type`,并用 `--required` 或 `--optional` 表明是否必填;`set` 和 `clear` 也必须显式指定目标环境。`set` 只接受 `--value-stdin`,CLI 不提供把值放入进程参数的 `--value`。保存后需重新发布才生效,保存动作不会自动发布。
|
|
214
238
|
|
|
215
|
-
初始化结果保留所绑定多维表格的 `baseUrl
|
|
239
|
+
初始化结果保留所绑定多维表格的 `baseUrl`。发布完成后,使用 CLI 返回的顶层 `baseAppUrl` 访问应用;发布成功但未返回访问入口时,CLI 会明确报错。CLI 校验并原样返回 DevCenter 在发布结果中给出的完整访问入口:Preview 入口由服务端提供 `mode=edit`,Production 入口由服务端提供正式访问地址。不要根据应用 token 猜测访问地址,也不要使用构建产物的静态资源地址作为应用入口。
|
|
216
240
|
|
|
217
|
-
`lark-cli` 子命令仅用于调试。先进入包含 `base-database.jsonc`
|
|
241
|
+
`lark-cli` 子命令仅用于调试。先进入包含 `base-database.jsonc` 的项目根目录;命令只读取当前目录,不接受额外项目路径。普通 JSON API 响应会统一输出到 stdout,兼容宿主将 JSON 正文落盘的行为;显式 `--output`、`--jq`、`--page-all`、非 JSON 格式及其他原生命令保留透传行为。正常初始化和发布无需调用:
|
|
218
242
|
|
|
219
243
|
```bash
|
|
220
244
|
base-database-cli lark-cli -- \
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type RuntimeProfile } from './environment.js';
|
|
2
|
+
export interface AIFunctionInput {
|
|
3
|
+
functionKey: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
configJson: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function collectLocalAIFunctions(workspace: string): AIFunctionInput[];
|
|
9
|
+
export declare function syncAIFunctionsFullCover(appToken: string, items: AIFunctionInput[], env: NodeJS.ProcessEnv, cwd?: string): Record<string, unknown>;
|
|
10
|
+
export declare function syncAIFunctionsForDeploy(appToken: string, items: AIFunctionInput[], env: NodeJS.ProcessEnv, cwd?: string): Record<string, unknown>;
|
|
11
|
+
export interface AIFunctionCommandOptions {
|
|
12
|
+
directory: string;
|
|
13
|
+
runtimeProfile?: RuntimeProfile;
|
|
14
|
+
}
|
|
15
|
+
export declare function listAIFunctions(options: AIFunctionCommandOptions): Promise<Record<string, unknown>>;
|
|
16
|
+
export declare function getAIFunction(functionKey: string, options: AIFunctionCommandOptions): Promise<Record<string, unknown>>;
|
|
17
|
+
export declare function syncAIFunctions(options: AIFunctionCommandOptions): Promise<Record<string, unknown>>;
|
|
18
|
+
export declare function validateAIFunction(functionKey: string, options: AIFunctionCommandOptions): Promise<Record<string, unknown>>;
|
|
19
|
+
export interface AIFunctionDebugOptions extends AIFunctionCommandOptions {
|
|
20
|
+
env: 'preview' | 'prod';
|
|
21
|
+
variables?: Record<string, unknown>;
|
|
22
|
+
messages?: Array<{
|
|
23
|
+
content: Array<Record<string, unknown>>;
|
|
24
|
+
role: string;
|
|
25
|
+
}>;
|
|
26
|
+
input?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
export declare function debugAIFunction(functionKey: string, options: AIFunctionDebugOptions): Promise<Record<string, unknown>>;
|
|
29
|
+
export interface AIFunctionTaskOptions extends AIFunctionCommandOptions {
|
|
30
|
+
env: 'preview' | 'prod';
|
|
31
|
+
}
|
|
32
|
+
export declare function getAIFunctionTask(functionKey: string, taskId: string, options: AIFunctionTaskOptions): Promise<Record<string, unknown>>;
|
|
33
|
+
export interface AIFunctionUsageOptions extends AIFunctionCommandOptions {
|
|
34
|
+
env?: string;
|
|
35
|
+
from?: string;
|
|
36
|
+
to?: string;
|
|
37
|
+
functionKey?: string;
|
|
38
|
+
model?: string;
|
|
39
|
+
capabilityType?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function getAIFunctionUsage(options: AIFunctionUsageOptions): Promise<Record<string, unknown>>;
|
|
42
|
+
//# sourceMappingURL=ai-functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-functions.d.ts","sourceRoot":"","sources":["../src/ai-functions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
3
|
+
import { readConfig } from './config.js';
|
|
4
|
+
import { assertProjectRuntimeProfile, ONLINE_RUNTIME_PROFILE, } from './environment.js';
|
|
5
|
+
import { LarkCliError } from './lark-cli-error.js';
|
|
6
|
+
import { responseData, runLarkCli } from './lark-cli.js';
|
|
7
|
+
// AI Function 是「功能清单」里的一类声明式资源(function_type=4):model/System Prompt/能力配置都在
|
|
8
|
+
// ai/<functionKey>/meta.json 里维护,随 deploy 走 OpenAPI 全量覆盖同步。不进 site.zip(不是部署代码,是配置)。
|
|
9
|
+
const FUNCTION_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
10
|
+
const MAX_AI_FUNCTIONS = 200;
|
|
11
|
+
const AI_FUNCTIONS_DIR = 'ai';
|
|
12
|
+
const CAPABILITY_TYPES = new Set(['text', 'vision', 'image', 'video']);
|
|
13
|
+
function stripPlatformManagedFields(config) {
|
|
14
|
+
const normalized = { ...config };
|
|
15
|
+
delete normalized.limits;
|
|
16
|
+
const text = config.text;
|
|
17
|
+
if (text && typeof text === 'object' && !Array.isArray(text)) {
|
|
18
|
+
const rest = { ...text };
|
|
19
|
+
delete rest.max_tokens;
|
|
20
|
+
normalized.text = rest;
|
|
21
|
+
}
|
|
22
|
+
return normalized;
|
|
23
|
+
}
|
|
24
|
+
function aiFunctionsRoot(workspace) {
|
|
25
|
+
return join(resolve(workspace), AI_FUNCTIONS_DIR);
|
|
26
|
+
}
|
|
27
|
+
function readAIFunctionMeta(path) {
|
|
28
|
+
const functionKey = basename(dirname(path));
|
|
29
|
+
if (functionKey.length < 1 ||
|
|
30
|
+
functionKey.length > 64 ||
|
|
31
|
+
!FUNCTION_ID_PATTERN.test(functionKey)) {
|
|
32
|
+
throw new Error(`Invalid AI Function key: ${functionKey}`);
|
|
33
|
+
}
|
|
34
|
+
const manifest = JSON.parse(readFileSync(path, 'utf8'));
|
|
35
|
+
if (typeof manifest.name !== 'string' || manifest.name === '') {
|
|
36
|
+
throw new Error(`AI Function name must be a non-empty string: ${path}`);
|
|
37
|
+
}
|
|
38
|
+
if (manifest.description !== undefined &&
|
|
39
|
+
typeof manifest.description !== 'string') {
|
|
40
|
+
throw new Error(`AI Function description must be a string: ${path}`);
|
|
41
|
+
}
|
|
42
|
+
if (!manifest.config || typeof manifest.config !== 'object') {
|
|
43
|
+
throw new Error(`AI Function config must be an object: ${path}`);
|
|
44
|
+
}
|
|
45
|
+
const config = stripPlatformManagedFields(manifest.config);
|
|
46
|
+
if (typeof config.capability_type !== 'string' ||
|
|
47
|
+
!CAPABILITY_TYPES.has(config.capability_type)) {
|
|
48
|
+
throw new Error(`AI Function capability_type must be one of text|vision|image|video: ${path}`);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
configJson: JSON.stringify(config),
|
|
52
|
+
description: manifest.description ?? '',
|
|
53
|
+
functionKey,
|
|
54
|
+
name: manifest.name,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// collectLocalAIFunctions 读取 ai/<key>/meta.json 全集(本地声明),供 deploy 全量覆盖同步与 sync 命令共用。
|
|
58
|
+
export function collectLocalAIFunctions(workspace) {
|
|
59
|
+
const root = aiFunctionsRoot(workspace);
|
|
60
|
+
if (!existsSync(root)) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const items = [];
|
|
64
|
+
const seen = new Set();
|
|
65
|
+
for (const entry of readdirSync(root, { withFileTypes: true })) {
|
|
66
|
+
if (!entry.isDirectory())
|
|
67
|
+
continue;
|
|
68
|
+
const path = join(root, entry.name, 'meta.json');
|
|
69
|
+
if (!existsSync(path) || !statSync(path).isFile())
|
|
70
|
+
continue;
|
|
71
|
+
const item = readAIFunctionMeta(path);
|
|
72
|
+
if (seen.has(item.functionKey)) {
|
|
73
|
+
throw new Error(`Duplicate AI Function key: ${item.functionKey}`);
|
|
74
|
+
}
|
|
75
|
+
seen.add(item.functionKey);
|
|
76
|
+
items.push(item);
|
|
77
|
+
}
|
|
78
|
+
if (items.length > MAX_AI_FUNCTIONS) {
|
|
79
|
+
throw new Error(`AI Functions cannot exceed ${MAX_AI_FUNCTIONS}`);
|
|
80
|
+
}
|
|
81
|
+
return items;
|
|
82
|
+
}
|
|
83
|
+
// buildUpdatePayload 把本地全集转成 OpenAPIUpsertAIFunctions 的全量覆盖请求体。
|
|
84
|
+
function buildUpdatePayload(items) {
|
|
85
|
+
return JSON.stringify({
|
|
86
|
+
ai_functions: items.map((item) => ({
|
|
87
|
+
config_json: item.configJson,
|
|
88
|
+
description: item.description,
|
|
89
|
+
function_key: item.functionKey,
|
|
90
|
+
name: item.name,
|
|
91
|
+
})),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// assertAIFunctionResultsOk 严格校验逐条结果:任一条 code != 0 立即抛错。
|
|
95
|
+
// 后端整批拒绝时会同时返回顶层失败和 data.results;调用方必须保留逐条诊断,
|
|
96
|
+
// 并阻止 deploy 继续上传产物或发布失败快照。
|
|
97
|
+
function assertAIFunctionResultsOk(data) {
|
|
98
|
+
const results = data.results ?? data.Results;
|
|
99
|
+
if (results === undefined || results === null) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (!Array.isArray(results)) {
|
|
103
|
+
throw new Error('AI Function sync returned an invalid results payload');
|
|
104
|
+
}
|
|
105
|
+
const failures = [];
|
|
106
|
+
for (const entry of results) {
|
|
107
|
+
if (!entry || typeof entry !== 'object')
|
|
108
|
+
continue;
|
|
109
|
+
const record = entry;
|
|
110
|
+
const code = record.code ?? record.Code;
|
|
111
|
+
if (typeof code === 'number' && code !== 0) {
|
|
112
|
+
const key = record.function_key ?? record.functionKey ?? record.FunctionKey;
|
|
113
|
+
const message = record.msg ?? record.Msg ?? record.message ?? '';
|
|
114
|
+
failures.push(`${String(key ?? '(unknown)')}: code=${code}${message ? ` ${String(message)}` : ''}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (failures.length > 0) {
|
|
118
|
+
throw new Error(`AI Function sync failed for ${failures.length} function(s): ${failures.join('; ')}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// syncAIFunctionsFullCover 走 OpenAPI 全量覆盖同步(对齐 update_functions 心智):传本地全集,服务端 diff 出
|
|
122
|
+
// add/update/delete + 逐条校验码。deploy 与 `ai sync` 命令共用。空集合仍会清空远端 AI Function(全量覆盖语义)。
|
|
123
|
+
// 任一条 results[].code != 0 立即抛错,避免 deploy 在 AI 同步失败后继续 artifact/publish。
|
|
124
|
+
export function syncAIFunctionsFullCover(appToken, items, env, cwd) {
|
|
125
|
+
const token = encodeURIComponent(appToken);
|
|
126
|
+
let response;
|
|
127
|
+
try {
|
|
128
|
+
response = runLarkCli([
|
|
129
|
+
'api',
|
|
130
|
+
'POST',
|
|
131
|
+
`/open-apis/base/v3/sites/${token}/ai_functions/update`,
|
|
132
|
+
'--data',
|
|
133
|
+
buildUpdatePayload(items),
|
|
134
|
+
], env, cwd);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
// 顶层失败不能覆盖服务端保留的逐条诊断。
|
|
138
|
+
if (error instanceof LarkCliError && error.details.results) {
|
|
139
|
+
assertAIFunctionResultsOk({ results: error.details.results });
|
|
140
|
+
}
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
const data = responseData(response);
|
|
144
|
+
assertAIFunctionResultsOk(data);
|
|
145
|
+
return data;
|
|
146
|
+
}
|
|
147
|
+
// deploy 只在本地声明了 AI Function 时同步。空集合不代表用户显式要求清空远端资源,
|
|
148
|
+
// 因而不能为普通 Page/Database Function/FaaS 发布额外请求尚未开放的 AI Function 接口。
|
|
149
|
+
// 显式 `ai sync` 仍直接调用 syncAIFunctionsFullCover,保留空集合全量清空语义。
|
|
150
|
+
export function syncAIFunctionsForDeploy(appToken, items, env, cwd) {
|
|
151
|
+
if (items.length === 0) {
|
|
152
|
+
return { skipped: true, reason: 'no_local_ai_functions' };
|
|
153
|
+
}
|
|
154
|
+
return syncAIFunctionsFullCover(appToken, items, env, cwd);
|
|
155
|
+
}
|
|
156
|
+
async function resolveEnv(workspace, runtimeProfile) {
|
|
157
|
+
const config = readConfig(workspace);
|
|
158
|
+
assertProjectRuntimeProfile(config.runtimeProfile, runtimeProfile);
|
|
159
|
+
const env = await runtimeProfile.commandEnvironment();
|
|
160
|
+
return { config, env };
|
|
161
|
+
}
|
|
162
|
+
// listAIFunctions 列出 Site 下 AI Function。
|
|
163
|
+
export async function listAIFunctions(options) {
|
|
164
|
+
const workspace = resolve(options.directory);
|
|
165
|
+
const runtimeProfile = options.runtimeProfile ?? ONLINE_RUNTIME_PROFILE;
|
|
166
|
+
const { config, env } = await resolveEnv(workspace, runtimeProfile);
|
|
167
|
+
const response = runLarkCli([
|
|
168
|
+
'api',
|
|
169
|
+
'GET',
|
|
170
|
+
`/open-apis/base/v3/sites/${encodeURIComponent(config.appToken)}/ai_functions`,
|
|
171
|
+
], env, workspace);
|
|
172
|
+
return responseData(response);
|
|
173
|
+
}
|
|
174
|
+
// getAIFunction 读取单个 AI Function 配置(用于本地编辑 / diff)。
|
|
175
|
+
export async function getAIFunction(functionKey, options) {
|
|
176
|
+
const workspace = resolve(options.directory);
|
|
177
|
+
const runtimeProfile = options.runtimeProfile ?? ONLINE_RUNTIME_PROFILE;
|
|
178
|
+
const { config, env } = await resolveEnv(workspace, runtimeProfile);
|
|
179
|
+
const response = runLarkCli([
|
|
180
|
+
'api',
|
|
181
|
+
'GET',
|
|
182
|
+
`/open-apis/base/v3/sites/${encodeURIComponent(config.appToken)}/ai_functions/${encodeURIComponent(functionKey)}`,
|
|
183
|
+
], env, workspace);
|
|
184
|
+
return responseData(response);
|
|
185
|
+
}
|
|
186
|
+
// syncAIFunctions 把本地 ai/ 全集全量覆盖同步到 Site。
|
|
187
|
+
export async function syncAIFunctions(options) {
|
|
188
|
+
const workspace = resolve(options.directory);
|
|
189
|
+
const runtimeProfile = options.runtimeProfile ?? ONLINE_RUNTIME_PROFILE;
|
|
190
|
+
const { config, env } = await resolveEnv(workspace, runtimeProfile);
|
|
191
|
+
const items = collectLocalAIFunctions(workspace);
|
|
192
|
+
const data = syncAIFunctionsFullCover(config.appToken, items, env, workspace);
|
|
193
|
+
return {
|
|
194
|
+
ok: true,
|
|
195
|
+
appToken: config.appToken,
|
|
196
|
+
count: items.length,
|
|
197
|
+
results: data,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
// validateAIFunction 静态校验单个本地 AI Function(保存/发布前,按能力分支),不落库。
|
|
201
|
+
export async function validateAIFunction(functionKey, options) {
|
|
202
|
+
const workspace = resolve(options.directory);
|
|
203
|
+
const runtimeProfile = options.runtimeProfile ?? ONLINE_RUNTIME_PROFILE;
|
|
204
|
+
const { config, env } = await resolveEnv(workspace, runtimeProfile);
|
|
205
|
+
const items = collectLocalAIFunctions(workspace);
|
|
206
|
+
const target = items.find((item) => item.functionKey === functionKey);
|
|
207
|
+
if (!target) {
|
|
208
|
+
throw new Error(`AI Function not found in ${AI_FUNCTIONS_DIR}/: ${functionKey}`);
|
|
209
|
+
}
|
|
210
|
+
const response = runLarkCli([
|
|
211
|
+
'api',
|
|
212
|
+
'POST',
|
|
213
|
+
`/open-apis/base/v3/sites/${encodeURIComponent(config.appToken)}/ai_functions/validate`,
|
|
214
|
+
'--data',
|
|
215
|
+
JSON.stringify({
|
|
216
|
+
function: {
|
|
217
|
+
config_json: target.configJson,
|
|
218
|
+
description: target.description,
|
|
219
|
+
function_key: target.functionKey,
|
|
220
|
+
name: target.name,
|
|
221
|
+
},
|
|
222
|
+
}),
|
|
223
|
+
], env, workspace);
|
|
224
|
+
const data = responseData(response);
|
|
225
|
+
if (data.is_success !== true) {
|
|
226
|
+
const message = String(data.err_msg ?? 'unknown validation error');
|
|
227
|
+
throw new Error(`AI Function validation failed: ${message}`);
|
|
228
|
+
}
|
|
229
|
+
return data;
|
|
230
|
+
}
|
|
231
|
+
function readCapabilityType(data) {
|
|
232
|
+
const value = data.function;
|
|
233
|
+
if (!value || typeof value !== 'object') {
|
|
234
|
+
throw new Error('AI Function detail does not contain function');
|
|
235
|
+
}
|
|
236
|
+
const view = value;
|
|
237
|
+
const raw = view.config_json;
|
|
238
|
+
if (typeof raw !== 'string' || raw === '') {
|
|
239
|
+
throw new Error('AI Function detail is missing config_json');
|
|
240
|
+
}
|
|
241
|
+
let parsed;
|
|
242
|
+
try {
|
|
243
|
+
parsed = JSON.parse(raw);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
throw new Error('AI Function detail config_json is not valid JSON');
|
|
247
|
+
}
|
|
248
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
249
|
+
throw new Error('AI Function detail config_json is not an object');
|
|
250
|
+
}
|
|
251
|
+
const capability = parsed.capability_type;
|
|
252
|
+
if (typeof capability !== 'string' || !CAPABILITY_TYPES.has(capability)) {
|
|
253
|
+
throw new Error('AI Function detail contains invalid capability_type');
|
|
254
|
+
}
|
|
255
|
+
return capability;
|
|
256
|
+
}
|
|
257
|
+
// debugAIFunction 调试 text/vision 时走 unary 聚合;image/video 走统一 tasks 提交接口。
|
|
258
|
+
export async function debugAIFunction(functionKey, options) {
|
|
259
|
+
const workspace = resolve(options.directory);
|
|
260
|
+
const runtimeProfile = options.runtimeProfile ?? ONLINE_RUNTIME_PROFILE;
|
|
261
|
+
const { config, env } = await resolveEnv(workspace, runtimeProfile);
|
|
262
|
+
const token = encodeURIComponent(config.appToken);
|
|
263
|
+
const key = encodeURIComponent(functionKey);
|
|
264
|
+
const detail = runLarkCli(['api', 'GET', `/open-apis/base/v3/sites/${token}/ai_functions/${key}`], env, workspace);
|
|
265
|
+
const capabilityType = readCapabilityType(responseData(detail));
|
|
266
|
+
const body = JSON.stringify({
|
|
267
|
+
input: options.input ?? {},
|
|
268
|
+
messages: options.messages ?? [],
|
|
269
|
+
variables: options.variables ?? {},
|
|
270
|
+
});
|
|
271
|
+
const response = runLarkCli([
|
|
272
|
+
'api',
|
|
273
|
+
'POST',
|
|
274
|
+
`/open-apis/base/v3/sites/${token}/ai_functions/${key}/${capabilityType === 'image' || capabilityType === 'video' ? 'tasks' : 'invoke'}`,
|
|
275
|
+
'--params',
|
|
276
|
+
JSON.stringify({ env: options.env }),
|
|
277
|
+
'--data',
|
|
278
|
+
body,
|
|
279
|
+
], env, workspace);
|
|
280
|
+
return responseData(response);
|
|
281
|
+
}
|
|
282
|
+
// getAIFunctionTask 查询 OpenAPI image/video 媒体任务状态。
|
|
283
|
+
export async function getAIFunctionTask(functionKey, taskId, options) {
|
|
284
|
+
const workspace = resolve(options.directory);
|
|
285
|
+
const runtimeProfile = options.runtimeProfile ?? ONLINE_RUNTIME_PROFILE;
|
|
286
|
+
const { config, env } = await resolveEnv(workspace, runtimeProfile);
|
|
287
|
+
const token = encodeURIComponent(config.appToken);
|
|
288
|
+
const key = encodeURIComponent(functionKey);
|
|
289
|
+
const task = encodeURIComponent(taskId);
|
|
290
|
+
const response = runLarkCli([
|
|
291
|
+
'api',
|
|
292
|
+
'GET',
|
|
293
|
+
`/open-apis/base/v3/sites/${token}/ai_functions/${key}/tasks/${task}`,
|
|
294
|
+
'--params',
|
|
295
|
+
JSON.stringify({ env: options.env }),
|
|
296
|
+
], env, workspace);
|
|
297
|
+
return responseData(response);
|
|
298
|
+
}
|
|
299
|
+
// getAIFunctionUsage 读天表聚合的 Owner 可见用量(总量 + 按日期/function/能力分布),走 OpenAPI usage/summary。
|
|
300
|
+
export async function getAIFunctionUsage(options) {
|
|
301
|
+
const workspace = resolve(options.directory);
|
|
302
|
+
const runtimeProfile = options.runtimeProfile ?? ONLINE_RUNTIME_PROFILE;
|
|
303
|
+
const { config, env } = await resolveEnv(workspace, runtimeProfile);
|
|
304
|
+
const token = encodeURIComponent(config.appToken);
|
|
305
|
+
const params = {};
|
|
306
|
+
if (options.from !== undefined)
|
|
307
|
+
params.from = options.from;
|
|
308
|
+
if (options.to !== undefined)
|
|
309
|
+
params.to = options.to;
|
|
310
|
+
if (options.env)
|
|
311
|
+
params.env = options.env;
|
|
312
|
+
if (options.functionKey)
|
|
313
|
+
params.function_key = options.functionKey;
|
|
314
|
+
if (options.model)
|
|
315
|
+
params.model = options.model;
|
|
316
|
+
if (options.capabilityType)
|
|
317
|
+
params.capability_type = options.capabilityType;
|
|
318
|
+
const response = runLarkCli([
|
|
319
|
+
'api',
|
|
320
|
+
'GET',
|
|
321
|
+
`/open-apis/base/v3/sites/${token}/ai_functions/usage/summary`,
|
|
322
|
+
'--params',
|
|
323
|
+
JSON.stringify(params),
|
|
324
|
+
], env, workspace);
|
|
325
|
+
return responseData(response);
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=ai-functions.js.map
|