@microi.net/cli 5.3.7 → 5.3.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 (27) hide show
  1. package/.codebuddy-plugin/marketplace.json +2 -2
  2. package/.codebuddy-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.workbuddy-plugin/marketplace.json +2 -2
  5. package/.workbuddy-plugin/plugin.json +1 -1
  6. package/assets/build-meta.json +3 -3
  7. package/cordis.patch.yml +1 -1
  8. package/package.json +1 -1
  9. package/scripts/microi-skills.meta.json +200 -200
  10. package/skills/.microi-skills-version.json +2 -2
  11. package/skills/.progressive-disclosure-manifest.json +33 -33
  12. package/skills/microi-deployment/SKILL.md +3 -3
  13. package/skills/microi-form-engine/SKILL.md +5 -2
  14. package/skills/microi-form-engine/references/component-catalog.md +2 -1
  15. package/skills/microi-frontend-sdk/SKILL.md +5 -4
  16. package/skills/microi-uniapp-frontend/SKILL.md +3 -1
  17. package/skills/microi.v8.js +86 -86
  18. package/skills/ocr-engine/SKILL.md +113 -113
  19. package/skills/translate-engine/SKILL.md +140 -140
  20. package/skills/v8-file-upload/SKILL.md +11 -4
  21. package/skills/v8-file-upload/references/progressive-01-/345/205/254/346/234/211/346/241/266-vs-/347/247/201/346/234/211/346/241/266.md +9 -2
  22. package/skills/v8-file-upload/references/progressive-02-office-/346/226/207/344/273/266/345/234/250/347/272/277/347/274/226/350/276/221/347/211/210/346/234/254/345/217/267/350/247/204/345/210/231.md +1 -1
  23. package/skills/v8-security/SKILL.md +10 -4
  24. package/skills/v8-security/references/progressive-02-7-/346/227/245/345/277/227/350/256/260/345/275/225.md +123 -123
  25. package/skills/v8-utilities/SKILL.md +2 -1
  26. package/skills/v8-utilities/references/server-api-index.md +40 -10
  27. package/skills/workspace-conventions/SKILL.md +194 -194
@@ -1,113 +1,113 @@
1
- ---
2
- name: ocr-engine
3
- description: 为 Microi 吾码集成、配置、调用和验收通用 OCR 能力。处理 V8.OCR、/apiengine/platform-ocr-recognize、PaddleX/PaddleOCR 服务、SaaS 租户 OCR 配置、图片或 PDF 文字识别、OCR 安全边界、Docker 部署和多节点交付时使用。
4
- ---
5
-
6
- > **Codex 非阻塞自动更新:** 当前宿主为 Codex 时,吾码 CLI、Codex 插件与工作区 AI/MCP 由后台自动更新;需要诊断时读取 `../microi-codex-installer/SKILL.md`。更新失败、等待空闲或尚未重载均不得阻断当前、正在进行或新建任务。非 Codex 宿主跳过此项。
7
-
8
- # Microi OCR 引擎
9
-
10
- ## 先读取相关规范
11
-
12
- - 涉及租户配置时,读取 `../v8-saas-multi-tenant/SKILL.md`。
13
- - 涉及外部 OCR 服务时,读取 `../v8-http-integration/SKILL.md`。
14
- - 涉及 Base64、上传文件或私有文件时,读取 `../v8-file-upload/SKILL.md`。
15
- - 涉及权限、密钥、日志或匿名接口时,读取 `../v8-security/SKILL.md`。
16
- - 涉及数据库字段和表单 Tab 时,读取 `../microi-db-schema/SKILL.md`。
17
-
18
- ## 固定架构
19
-
20
- Microi 后端只实现统一 OCR 网关、租户隔离、协议适配和安全治理,不在 .NET 进程内训练或维护 OCR 模型。默认提供方为独立部署的 PaddleX OCR 服务;业务代码只能调用 `IMicroiOcr`、`V8.OCR` 或官方 Managed 接口 `/apiengine/platform-ocr-recognize`,不得直接读取 SaaS 密钥并自行拼接 HTTP 请求。
21
-
22
- 同步识别必须绑定当前请求和当前租户。批量、超大文件或长耗时 OCR 应进入共享数据库/MQ/outbox,以全局任务 Id 做幂等;不得把任务状态、队列或锁只放在单机内存中。
23
-
24
- ## SaaS 配置
25
-
26
- 配置位于 `sys_osclients` 的独立“OCR识别”Tab:
27
-
28
- | 字段 | 用途 | 默认值 |
29
- |---|---|---|
30
- | `OcrEnabled` | 租户总开关,默认关闭 | `0` |
31
- | `OcrProvider` | `PaddleX` 或 `PaddleXHighStability` | `PaddleX` |
32
- | `OcrEndpoint` | OCR 服务完整接口地址 | 空 |
33
- | `OcrApiKey` | 可选 Bearer 密钥,只允许后端使用 | 空 |
34
- | `OcrHeadersJson` | 可选服务端固定请求头 JSON | 空 |
35
- | `OcrTimeoutSeconds` | 单次超时秒数 | `60` |
36
- | `OcrMaxFileMB` | 单文件大小上限 | `20` |
37
- | `OcrMaxPages` | PDF 页数上限 | `10` |
38
- | `OcrMinConfidence` | 返回文本最低置信度 | `0` |
39
-
40
- 这些配置不得投影到 `V8.OsClientModel`,不得由前端请求覆盖,不得写入普通日志。没有启用、没有 endpoint 或配置无效时必须失败关闭。
41
-
42
- ## 调用
43
-
44
- 接口引擎或后端表单事件中:
45
-
46
- ```js
47
- var result = await V8.OCR.Recognize({
48
- FileByteBase64: V8.FilesByteBase64.invoice,
49
- FileName: 'invoice.png',
50
- UseDocOrientationClassify: true,
51
- UseDocUnwarping: true,
52
- UseTextlineOrientation: true,
53
- TextRecScoreThresh: 0.5,
54
- ReturnWordBox: false
55
- });
56
-
57
- if (result.Code !== 1) {
58
- return result;
59
- }
60
-
61
- return {
62
- Code: 1,
63
- Data: {
64
- Text: result.Data.Text,
65
- Pages: result.Data.Pages,
66
- Provider: result.Data.Provider
67
- }
68
- };
69
- ```
70
-
71
- 已登录客户端调用 `POST /apiengine/platform-ocr-recognize`,请求体与 `V8.OCR.Recognize` 一致,并携带正常登录 Token。`OsClient` 以 Token 解析结果为准。该接口由官方应用以 `Managed` 策略恢复;个性化逻辑只能写入租户 `platform-runtime-custom-hook`,且官方接口不会把文件 Base64、识别原文或密钥传给 Hook。
72
-
73
- 标准成功结果包含 `Provider`、`Text`、`Pages`、`ElapsedMilliseconds`。每页包含 `PageIndex`、`Text`、`Regions`,每个区域包含 `Text`、`Confidence` 和归一化后的 `Polygon`。
74
-
75
- ## 协议与输入边界
76
-
77
- - `PaddleX` 使用基础服务协议 `POST /ocr`。
78
- - `PaddleXHighStability` 使用 KServe 协议 `POST /v2/models/ocr/infer`。
79
- - 接受 PDF、PNG、JPEG、BMP、GIF、TIFF、WebP;同时检查文件扩展名、Base64 和文件魔数。
80
- - 固定 `visualize=false`,避免服务返回大体积可视化图片。
81
- - 由服务端限制文件大小、超时、PDF 页数、响应体大小和最低置信度。
82
- - 禁止接受调用方传入 endpoint、API key、任意请求头、代理地址或本地文件路径,防止 SSRF 和密钥绕过。
83
- - 日志只记录租户、提供方、状态码、耗时和安全裁剪后的错误,不记录文件 Base64、识别原文、API key 或完整响应。
84
-
85
- ## Docker 与多节点
86
-
87
- - OCR 模型服务独立部署,固定 PaddleX/PaddlePaddle/模型版本;不要使用浮动 `latest` 直接上线。
88
- - CPU 基线位于 `../../Microi.Server/Microi.OCR/deploy/paddlex/`,固定 PaddleX 3.6.1 与 PaddlePaddle 3.2.2;公开镜像固定为 `registry.cn-hangzhou.aliyuncs.com/microios/paddlex-ocr:3.6.1-paddle3.2.2-cpu`,当前只交付 `linux/amd64`。PaddlePaddle 3.3.0 存在 CPU oneDNN PIR 推理兼容问题,在完成真实图片回归前不得升级。
89
- - 发布镜像使用同目录 `publish-image.ps1`:它从根目录发布配置读取凭据,通过隔离 Docker 配置和 `--password-stdin` 登录,推送后退出并匿名回读公开摘要。不得在命令行、日志或文档中展开用户名/密码,也不得只凭 `docker push` 返回成功就宣布国内镜像可用。
90
- - 发布镜像时执行 `create_pipeline("OCR")` 预置默认产线模型。运行时使用 named volume 挂载 `/home/microi/.paddlex`,让 Docker 首次创建卷时从镜像复制模型;不要改成空宿主机 bind mount,否则会遮住镜像内的预置模型并触发重新下载。
91
- - OCR 宿主机端口只绑定 `127.0.0.1`;Docker 化 API 与 OCR 同时加入 external bridge 网络 `microi-ocr`,一键安装的内部 endpoint 固定为 `http://microi-install-ocr:8080/ocr`。不得通过公网/LAN 回环调用同机 OCR。
92
- - `install-microi.sh` 默认安装 OCR。必须依次满足“固定镜像拉取并回读为 amd64 → OCR healthy → API liveness → Upgrade29 的 9 个物理字段数据库回读 → 唯一活动主租户 → 配置写入后回读 → API 重启 readiness”才设置 `OcrEnabled=1`;任一步失败都保持失败关闭。API liveness 后立即回读字段,每秒一次且最多 15 秒;正常升级应首轮命中,镜像过旧或迁移失败应快速报错,禁止无意义等待 5 分钟。不要用安装脚本直接伪造 `diy_field` 元数据绕过 Upgrade29。
93
- - API/Web 官方浮动 `latest` 必须在 Compose 启动时强制回源拉取,避免旧本机镜像通过 liveness 却缺少 Upgrade29。字段门禁失败后可以输出已生成端口、密码、目录和容器状态供恢复,但必须明确标记“安装未完成”、保留非零退出码,并显示 OCR SaaS 配置未完成;恢复汇总不是启用 OCR 的依据。
94
- - OCR 使用固定不可变版本,不加入只跟踪 API/Web 浮动标签的 Watchtower 自动更新列表;升级镜像时先发布新 tag、匿名回读 digest/架构,再修改 Compose 与安装器。
95
- - 登录国内镜像源必须从本机发布配置读取凭据并走 `docker login --password-stdin`,不得输出密码。推送成功不是发布验收,必须使用隔离的匿名 Docker config 回读 manifest/digest,必要时再做匿名拉取。
96
- - 不要在内存不足的共享开发机上直接构建模型镜像。构建前检查物理内存、Docker 占用与同类进程;保留至少 `max(6 GB, 物理内存 20%)`,不足时延后构建而不是停止他人服务。
97
- - API 多节点共享同一个或同一组 OCR endpoint;每节点仅保留无状态 `HttpClient`。
98
- - OCR 服务至少配置 readiness、并发上限、CPU/GPU 资源上限、请求体上限和访问控制。
99
- - GPU 推理采用独立 Worker/服务池,避免 OCR 模型抢占 Microi API 内存。
100
- - 滚动升级时保持旧新 OCR 响应协议兼容;协议变更先扩展解析器,再升级服务。
101
-
102
- ## 验收门禁
103
-
104
- 交付时分别报告:
105
-
106
- 1. 源码:网关、V8、REST、SaaS 字段、密钥投影隔离是否齐全。
107
- 2. 定向测试:基础协议、高稳定协议、低置信度过滤、错误响应、配置隔离。
108
- 3. 数据库:目标 `OsClient` 的 Tab、字段和物理列经 MCP 写后回读。
109
- 4. 服务:真实 PNG/JPEG/PDF 至少各一例,包含中英文、旋转和多页场景。
110
- 5. 多节点:两个 API 节点同时调用,同租户限制一致,服务故障时均能超时/降级且不泄漏密钥。
111
- 6. UI:SaaS 配置表单能查看独立 Tab、保存配置,密码字段不出现在普通前端上下文。
112
-
113
- 没有真实 OCR endpoint、服务版本和样例识别结果时,只能声明“平台接入完成、运行验收待配置”,不能声明生产 OCR 已可用。
1
+ ---
2
+ name: ocr-engine
3
+ description: 为 Microi 吾码集成、配置、调用和验收通用 OCR 能力。处理 V8.OCR、/apiengine/platform-ocr-recognize、PaddleX/PaddleOCR 服务、SaaS 租户 OCR 配置、图片或 PDF 文字识别、OCR 安全边界、Docker 部署和多节点交付时使用。
4
+ ---
5
+
6
+ > **Codex 非阻塞自动更新:** 当前宿主为 Codex 时,吾码 CLI、Codex 插件与工作区 AI/MCP 由后台自动更新;需要诊断时读取 `../microi-codex-installer/SKILL.md`。更新失败、等待空闲或尚未重载均不得阻断当前、正在进行或新建任务。非 Codex 宿主跳过此项。
7
+
8
+ # Microi OCR 引擎
9
+
10
+ ## 先读取相关规范
11
+
12
+ - 涉及租户配置时,读取 `../v8-saas-multi-tenant/SKILL.md`。
13
+ - 涉及外部 OCR 服务时,读取 `../v8-http-integration/SKILL.md`。
14
+ - 涉及 Base64、上传文件或私有文件时,读取 `../v8-file-upload/SKILL.md`。
15
+ - 涉及权限、密钥、日志或匿名接口时,读取 `../v8-security/SKILL.md`。
16
+ - 涉及数据库字段和表单 Tab 时,读取 `../microi-db-schema/SKILL.md`。
17
+
18
+ ## 固定架构
19
+
20
+ Microi 后端只实现统一 OCR 网关、租户隔离、协议适配和安全治理,不在 .NET 进程内训练或维护 OCR 模型。默认提供方为独立部署的 PaddleX OCR 服务;业务代码只能调用 `IMicroiOcr`、`V8.OCR` 或官方 Managed 接口 `/apiengine/platform-ocr-recognize`,不得直接读取 SaaS 密钥并自行拼接 HTTP 请求。
21
+
22
+ 同步识别必须绑定当前请求和当前租户。批量、超大文件或长耗时 OCR 应进入共享数据库/MQ/outbox,以全局任务 Id 做幂等;不得把任务状态、队列或锁只放在单机内存中。
23
+
24
+ ## SaaS 配置
25
+
26
+ 配置位于 `sys_osclients` 的独立“OCR识别”Tab:
27
+
28
+ | 字段 | 用途 | 默认值 |
29
+ |---|---|---|
30
+ | `OcrEnabled` | 租户总开关,默认关闭 | `0` |
31
+ | `OcrProvider` | `PaddleX` 或 `PaddleXHighStability` | `PaddleX` |
32
+ | `OcrEndpoint` | OCR 服务完整接口地址 | 空 |
33
+ | `OcrApiKey` | 可选 Bearer 密钥,只允许后端使用 | 空 |
34
+ | `OcrHeadersJson` | 可选服务端固定请求头 JSON | 空 |
35
+ | `OcrTimeoutSeconds` | 单次超时秒数 | `60` |
36
+ | `OcrMaxFileMB` | 单文件大小上限 | `20` |
37
+ | `OcrMaxPages` | PDF 页数上限 | `10` |
38
+ | `OcrMinConfidence` | 返回文本最低置信度 | `0` |
39
+
40
+ 这些配置不得投影到 `V8.OsClientModel`,不得由前端请求覆盖,不得写入普通日志。没有启用、没有 endpoint 或配置无效时必须失败关闭。
41
+
42
+ ## 调用
43
+
44
+ 接口引擎或后端表单事件中:
45
+
46
+ ```js
47
+ var result = await V8.OCR.Recognize({
48
+ FileByteBase64: V8.FilesByteBase64.invoice,
49
+ FileName: 'invoice.png',
50
+ UseDocOrientationClassify: true,
51
+ UseDocUnwarping: true,
52
+ UseTextlineOrientation: true,
53
+ TextRecScoreThresh: 0.5,
54
+ ReturnWordBox: false
55
+ });
56
+
57
+ if (result.Code !== 1) {
58
+ return result;
59
+ }
60
+
61
+ return {
62
+ Code: 1,
63
+ Data: {
64
+ Text: result.Data.Text,
65
+ Pages: result.Data.Pages,
66
+ Provider: result.Data.Provider
67
+ }
68
+ };
69
+ ```
70
+
71
+ 已登录客户端调用 `POST /apiengine/platform-ocr-recognize`,请求体与 `V8.OCR.Recognize` 一致,并携带正常登录 Token。`OsClient` 以 Token 解析结果为准。该接口由官方应用以 `Managed` 策略恢复;个性化逻辑只能写入租户 `platform-runtime-custom-hook`,且官方接口不会把文件 Base64、识别原文或密钥传给 Hook。
72
+
73
+ 标准成功结果包含 `Provider`、`Text`、`Pages`、`ElapsedMilliseconds`。每页包含 `PageIndex`、`Text`、`Regions`,每个区域包含 `Text`、`Confidence` 和归一化后的 `Polygon`。
74
+
75
+ ## 协议与输入边界
76
+
77
+ - `PaddleX` 使用基础服务协议 `POST /ocr`。
78
+ - `PaddleXHighStability` 使用 KServe 协议 `POST /v2/models/ocr/infer`。
79
+ - 接受 PDF、PNG、JPEG、BMP、GIF、TIFF、WebP;同时检查文件扩展名、Base64 和文件魔数。
80
+ - 固定 `visualize=false`,避免服务返回大体积可视化图片。
81
+ - 由服务端限制文件大小、超时、PDF 页数、响应体大小和最低置信度。
82
+ - 禁止接受调用方传入 endpoint、API key、任意请求头、代理地址或本地文件路径,防止 SSRF 和密钥绕过。
83
+ - 日志只记录租户、提供方、状态码、耗时和安全裁剪后的错误,不记录文件 Base64、识别原文、API key 或完整响应。
84
+
85
+ ## Docker 与多节点
86
+
87
+ - OCR 模型服务独立部署,固定 PaddleX/PaddlePaddle/模型版本;不要使用浮动 `latest` 直接上线。
88
+ - CPU 基线位于 `../../Microi.Server/Microi.OCR/deploy/paddlex/`,固定 PaddleX 3.6.1 与 PaddlePaddle 3.2.2;公开镜像固定为 `registry.cn-hangzhou.aliyuncs.com/microios/paddlex-ocr:3.6.1-paddle3.2.2-cpu`,当前只交付 `linux/amd64`。PaddlePaddle 3.3.0 存在 CPU oneDNN PIR 推理兼容问题,在完成真实图片回归前不得升级。
89
+ - 发布镜像使用同目录 `publish-image.ps1`:它从根目录发布配置读取凭据,通过隔离 Docker 配置和 `--password-stdin` 登录,推送后退出并匿名回读公开摘要。不得在命令行、日志或文档中展开用户名/密码,也不得只凭 `docker push` 返回成功就宣布国内镜像可用。
90
+ - 发布镜像时执行 `create_pipeline("OCR")` 预置默认产线模型。运行时使用 named volume 挂载 `/home/microi/.paddlex`,让 Docker 首次创建卷时从镜像复制模型;不要改成空宿主机 bind mount,否则会遮住镜像内的预置模型并触发重新下载。
91
+ - OCR 宿主机端口只绑定 `127.0.0.1`;Docker 化 API 与 OCR 同时加入 external bridge 网络 `microi-ocr`,一键安装的内部 endpoint 固定为 `http://microi-install-ocr:8080/ocr`。不得通过公网/LAN 回环调用同机 OCR。
92
+ - `install-microi.sh` 默认尝试安装 OCR,但先部署 API/Web 并通过 liveness、完整 `ServerVersion` 升级链和 readiness。随后必须依次满足“固定镜像拉取并回读为 amd64 → OCR healthy → Upgrade29 的 9 个物理字段数据库回读 → 唯一活动主租户 → 配置写入后回读 → API 重启 readiness”才设置 `OcrEnabled=1`;任一步失败都保持 OCR 能力关闭并记录警告,但不得中断已经可用的核心平台。字段每秒回读一次且最多 15 秒;正常升级应首轮命中,镜像过旧或迁移失败应快速关闭 OCR,禁止无意义等待 5 分钟。不要用安装脚本直接伪造 `diy_field` 元数据绕过 Upgrade29。
93
+ - API/Web 官方浮动 `latest` 必须在 Compose 启动时强制回源拉取,避免旧本机镜像缺少 Upgrade29。核心门禁失败时输出“安装未完成”恢复汇总并保留非零退出码;OCR 字段、服务或配置门禁失败时,成功汇总明确显示“OCR SaaS 未启用”和附加能力警告。两种汇总都不是启用 OCR 的依据。
94
+ - OCR 使用固定不可变版本,不加入只跟踪 API/Web 浮动标签的 Watchtower 自动更新列表;升级镜像时先发布新 tag、匿名回读 digest/架构,再修改 Compose 与安装器。
95
+ - 登录国内镜像源必须从本机发布配置读取凭据并走 `docker login --password-stdin`,不得输出密码。推送成功不是发布验收,必须使用隔离的匿名 Docker config 回读 manifest/digest,必要时再做匿名拉取。
96
+ - 不要在内存不足的共享开发机上直接构建模型镜像。构建前检查物理内存、Docker 占用与同类进程;保留至少 `max(6 GB, 物理内存 20%)`,不足时延后构建而不是停止他人服务。
97
+ - API 多节点共享同一个或同一组 OCR endpoint;每节点仅保留无状态 `HttpClient`。
98
+ - OCR 服务至少配置 readiness、并发上限、CPU/GPU 资源上限、请求体上限和访问控制。
99
+ - GPU 推理采用独立 Worker/服务池,避免 OCR 模型抢占 Microi API 内存。
100
+ - 滚动升级时保持旧新 OCR 响应协议兼容;协议变更先扩展解析器,再升级服务。
101
+
102
+ ## 验收门禁
103
+
104
+ 交付时分别报告:
105
+
106
+ 1. 源码:网关、V8、REST、SaaS 字段、密钥投影隔离是否齐全。
107
+ 2. 定向测试:基础协议、高稳定协议、低置信度过滤、错误响应、配置隔离。
108
+ 3. 数据库:目标 `OsClient` 的 Tab、字段和物理列经 MCP 写后回读。
109
+ 4. 服务:真实 PNG/JPEG/PDF 至少各一例,包含中英文、旋转和多页场景。
110
+ 5. 多节点:两个 API 节点同时调用,同租户限制一致,服务故障时均能超时/降级且不泄漏密钥。
111
+ 6. UI:SaaS 配置表单能查看独立 Tab、保存配置,密码字段不出现在普通前端上下文。
112
+
113
+ 没有真实 OCR endpoint、服务版本和样例识别结果时,只能声明“平台接入完成、运行验收待配置”,不能声明生产 OCR 已可用。
@@ -1,140 +1,140 @@
1
- ---
2
- name: translate-engine
3
- description: Microi 翻译引擎与多语言词条规范。用于 V8.TranslateEngine 文本/批量/HTML/检测/语言列表/文件/建议/健康能力、HTTP 与 MCP 翻译调用、GetLang 词条、供应商配置、租户隔离、缓存和验收。
4
- ---
5
-
6
- > **Codex 非阻塞自动更新:** 当前宿主为 Codex 时,吾码 CLI、Codex 插件与工作区 AI/MCP 由后台自动更新;需要诊断时读取 `../microi-codex-installer/SKILL.md`。更新失败、等待空闲或尚未重载均不得阻断当前、正在进行或新建任务。非 Codex 宿主跳过此项。
7
-
8
- # Microi TranslateEngine
9
-
10
- 翻译运行时源码位于开源类库 `Microi.Server/Microi.Translate`,NuGet 包名为 `Microi.Translate`。可复用的供应商、租户隔离、缓存和模型契约必须维护在该类库;闭源 `Microi.net` 只允许保留 License 授权或平台私有装配边界,不能重新复制翻译业务实现。
11
-
12
- ## API
13
-
14
- ```js
15
- var r1 = V8.TranslateEngine.Translate('你好', 'en');
16
- var r2 = V8.TranslateEngine.Translate('hello', 'cn', 'en');
17
- var full = V8.TranslateEngine.TranslateText({
18
- SourceTexts: ['你好', '世界'], FromLang: 'auto', Lang: 'en',
19
- Format: 'text', Alternatives: 2
20
- });
21
- var detected = V8.TranslateEngine.Detect({ SourceText: 'Bonjour' });
22
- var languages = V8.TranslateEngine.GetLanguages();
23
- var health = V8.TranslateEngine.Health();
24
- var suggestion = V8.TranslateEngine.Suggest({
25
- SourceText: 'Hello', SuggestedText: '你好', FromLang: 'en', Lang: 'zh'
26
- });
27
- var text = V8.TranslateEngine.GetLang('NoAuth', 'cn');
28
- var item = V8.TranslateEngine.GetLangData('NoAuth');
29
- var code = V8.TranslateEngine.GetLangCode('NoAuth');
30
- ```
31
-
32
- `Translate` 返回 `DosResult`,`Data` 为兼容的单条译文字符串。`TranslateText` 返回包含单条/批量译文、检测语言、候选译文和格式的完整结构。其余业务方法:
33
-
34
- | 方法 | 契约 |
35
- |---|---|
36
- | `TranslateText` | `SourceText/SourceTexts` 二选一;`FromLang=auto`;`Format=text/html`;`Alternatives=0..10` |
37
- | `Detect` | 返回 `{Language, Confidence}[]` |
38
- | `GetLanguages` | 返回当前服务真实安装的 `{Code,Name,Targets}[]` |
39
- | `TranslateFile` | TXT/HTML/ODT/ODP/DOCX/PPTX/XLSX/EPUB/PDF Base64 输入,Base64 文件输出 |
40
- | `Suggest` | 写入启用了 suggestions 的 LibreTranslate 服务;不是多候选翻译 |
41
- | `Health` | 只返回健康和业务能力摘要,不返回 URL/Key |
42
- | `GetLang/GetLangData/GetLangCode` | 读取 `diy_lang`,不调用翻译供应商 |
43
-
44
- LibreTranslate 的 `/frontend/settings`、API Key 管理、`/metrics` 和 Web UI 是运维控制面,不得从普通 V8/HTTP/MCP 代理。
45
-
46
- 文件入口的完整名称是 `V8.TranslateEngine.TranslateFile({...})`,不要把叶子名误当全局函数。
47
-
48
- ## 租户与密钥
49
-
50
- - V8 调用统一绑定当前 `V8TenantContext`。普通租户传其它 `OsClient` 不会跨租户翻译或读取配置。
51
- - 普通租户未配置供应商时失败关闭,不得隐式回退借用主租户翻译地址、密钥或额度。
52
- - Provider、Endpoint、Key、Secret、ApiKey 等只保存在服务端租户配置;不得进入前端 `SysConfig`、日志、错误响应或业务表。
53
- - 主租户显式跨租户只允许可信控制面 C# 调用,不由 HTTP 参数建立信任。
54
-
55
- ## 词条优先
56
-
57
- 界面固定文案优先维护 `diy_lang` 词条,不要每次调用第三方翻译。Key 使用稳定英文标识,中文、英文等语言值统一回读。缺失词条应返回可诊断 fallback,而不是把密钥或供应商错误展示给用户。
58
-
59
- ## 动态翻译
60
-
61
- - 校验源语言和目标语言白名单。
62
- - 限制单条长度、批量条数、总字符数和超时。
63
- - 用户隐私、合同、身份证、Token、密码和内部提示词不应发送到未批准的第三方供应商。
64
- - 缓存 Key 包含 `OsClient + Provider + From + To + 文本哈希`;不要把原文直接作为 Redis Key 或日志。
65
- - 供应商限流/失败使用有上限重试和熔断;不要无限重试阻塞 V8。
66
-
67
- ## LibreTranslate 自托管
68
-
69
- LibreTranslate 是动态翻译供应商,不是 `diy_lang` 的替代品。一键安装默认部署;安装选择直接 Enter 等同 `1`,语言套餐直接 Enter 等同基础套餐 `1`。只有用户明确输入 `0` 才跳过编排。语言预设为:
70
-
71
- 1. `zh,zt,en`;
72
- 2. 预设 1 加 `ja,ko,vi,th,id,ms,tl`;
73
- 3. 安装脚本列出的全部语言。
74
-
75
- 用户可追加经过白名单校验的语言 Key。语言越多,首次模型下载越慢;一键安装不得等待模型下载或 HTTP 就绪。应先用同版本镜像独立初始化持久化 `api_keys.db`、写入并回读随机 API Key,再启动正式容器并确认其进入运行状态,让语言模型在容器中继续初始化,不阻塞吾码主体安装。
76
-
77
- 服务端统一从 SaaS 引擎租户配置读取 `TranslateProvider`、`TranslateUrl`(兼容 `TranslateApiUrl` / `LibreTranslateUrl`)、`TranslateApiKey`(兼容 `TranslateKey`)和 `TranslateTimeout`;不要再为翻译供应商增加 API 容器环境变量。密钥不得进入前端、日志或文档示例的固定默认值。
78
-
79
- 一键安装在 API Key 数据库预初始化成功、正式容器进入运行状态后,先启动平台 API,让共享升级租约中的幂等迁移补齐 `sys_osclients` 物理字段和 `diy_field` 元数据;API liveness 后立即回读 Upgrade31 的 4 个翻译物理字段,每秒一次且最多 15 秒,正常升级应首轮命中,镜像过旧或迁移失败应快速报错。只有数据库回读确认字段已存在,才能把当前 `OsClient` 的 `TranslateProvider=LibreTranslate`、Docker 内网 `TranslateUrl`、匹配的 `TranslateApiKey` 和超时写入并立即回读一致性。禁止在 API/Upgrade 启动前直接更新新字段,也禁止遇到 `Unknown column` 后由安装器伪造元数据。任一步失败都应终止安装。日志只显示 Provider 与 URL,禁止输出密钥。模型尚未完成时翻译能力可以暂时不可用,但不得拖住其它服务的安装。
80
-
81
- 吾码公开镜像固定为 `registry.cn-hangzhou.aliyuncs.com/microios/libretranslate:1.9.6-microi1`。该镜像基于 1.9.6 固定摘要,仅把与 `requests 2.31.0` 不兼容的 `chardet 7.x` 固定为 `5.2.0`,构建必须同时通过 `pip check` 和将 warning 视为 error 的 `import requests`。安装脚本不得通过隐藏所有 Python warning 来掩盖依赖漂移。
82
-
83
- 独立编排应使用 ASCII 目录和显式项目名 `docker compose -p microi-libretranslate`;只供平台 API 调用时,不默认开放 LibreTranslate 宿主机防火墙端口。需要公网调用时必须由运维显式配置 TLS、反向代理、访问控制、限流和强 API Key。
84
-
85
- ## HTTP 与 MCP
86
-
87
- 已登录 HTTP 入口统一为 `POST /apiengine/platform-translate-runtime`,通过请求体 `Action=TranslateText|Detect|Languages|TranslateFile|Suggest|Health` 选择能力。官方 Managed 接口使用验证后的 Token 绑定 `OsClient`,不得接受 endpoint/key/header;个性化逻辑只写入租户 `platform-runtime-custom-hook`,且原文、文件 Base64、供应商地址和密钥不会传给 Hook。
88
-
89
- MCP 固定工具:`microi_translate`、`microi_detect_language`、`microi_list_translate_languages`、`microi_translate_file`、`microi_suggest_translation`、`microi_get_translate_health`。文件翻译需要 `confirmExecution=TRANSLATE_FILE`,建议写入需要 `confirmExecution=TRANSLATE_SUGGEST`;审计只记录长度、SHA-256、语言和输出模式,不记录文本、文件内容、本机路径或凭据。大文件结果落到新的绝对路径,不允许覆盖已有文件。
90
-
91
- ## 安全硬上限
92
-
93
- - 单条文本 5 万字符,单批最多 50 条/20 万字符,候选最多 10 个;
94
- - 文件输入 20 MB、输出 25 MB;MCP 内联 Base64 额外限制为 2 MB;
95
- - Provider URL 必须是无内嵌凭据的绝对 HTTP(S) 地址;禁用自动重定向;文件下载只允许与配置服务同源;
96
- - 上游失败不回显响应体、堆栈、原文、内部 URL 或密钥;
97
- - 语言缓存可作为节点级优化,但 Key 必须使用 `OsClient + URL + API Key 哈希`,不能含密钥明文,也不能作为共享事实源。
98
-
99
- ## 批量与后台任务
100
-
101
- 大量内容翻译使用 Job/MQ/outbox。每条记录保存源文本版本与目标语言,只有源版本未变化时写回结果;事件用稳定 Id 幂等。后端 `setTimeout/Task.Run` 不是可靠后台任务。
102
-
103
- ## 配置与缓存更新
104
-
105
- 词条或供应商配置修改后:
106
-
107
- 1. 回读当前租户配置或 `diy_lang`。
108
- 2. 递增共享配置版本/清理租户缓存。
109
- 3. 在另一个 API 节点验证新值,无需重启。
110
- 4. 确认旧请求失败不会覆盖新翻译。
111
-
112
- ## 验收清单
113
-
114
- - [ ] `Microi.Translate` 能独立编译、打包并由发布脚本推送 NuGet,`Microi.net/TranslateEngine` 不再残留重复源码
115
- - [ ] `Translate` 的 `DosResult` 契约处理正确
116
- - [ ] 词条优先,动态翻译只用于动态内容
117
- - [ ] 普通租户无法伪造 `OsClient`
118
- - [ ] 密钥、原始隐私文本和供应商堆栈不泄露
119
- - [ ] 长度、批量、超时、限流和费用上限生效
120
- - [ ] 一路 Enter 默认部署 LibreTranslate 基础套餐 1;显式输入 0 才跳过
121
- - [ ] API Key 数据库预初始化成功且正式容器已启动
122
- - [ ] LibreTranslate 内部端口未被安装脚本默认加入防火墙放行列表
123
- - [ ] 翻译字段由幂等升级创建,安装器在 API 启动后最多 15 秒回读 schema 才写入配置
124
- - [ ] 缓存按租户/供应商/语言隔离
125
- - [ ] 多节点配置失效与批量幂等通过
126
- - [ ] V8、HTTP、MCP 六类业务入口一致,运维面未被代理
127
-
128
- ### 复盘:模型下载期间健康检查误报成功导致 API Key 注册失败
129
-
130
- - 触发场景:一键安装日志仍显示 `Updating Language models` / `Downloading ...`,脚本却已经进入 API Key 注册并报失败。
131
- - 根因:LibreTranslate 1.9.6 的 `scripts/healthcheck.py` 在 `/tmp/booting.flag` 存在时直接返回成功;这只表示容器仍处于受支持的启动阶段,不表示 HTTP 服务或 `api_keys.db` 已就绪。
132
- - 通用规则:不能把自带 healthcheck 当作模型和 HTTP 已就绪证明,也不能因此在一键安装中持续等待。安装器应在正式容器启动前独立创建并验证 API Key 数据库,容器启动只证明服务已安装;真实翻译可用性由运行期健康检查体现。
133
- - 自动化检查:用同版本镜像在不执行入口脚本、不下载模型的条件下创建临时 `api_keys.db`,回读 Key 后启动正式容器;断言安装脚本不存在模型等待循环,随后清理隔离容器与卷。
134
-
135
- ### 复盘:首次语言模型下载阻塞整套一键安装
136
-
137
- - 触发场景:国内服务器下载 LibreTranslate 语言模型极慢或网络不可达,一键安装每 30 秒输出一次等待状态,直到 3600 秒后失败,导致吾码其它服务无法继续安装。
138
- - 根因:安装脚本把“翻译服务容器已安装”与“全部语言模型和 HTTP 已可用”绑定成同一个同步完成条件,并把 API Key 数据库初始化放在模型下载之后。
139
- - 通用规则:API Key 数据库必须由同版本镜像在启动正式服务前预初始化并持久化;Compose 启动成功且容器进入运行状态后立即继续吾码安装。语言模型初始化属于服务自身后台过程,不得设置为主体安装的同步门禁,也不得循环输出累计等待秒数。
140
- - 自动化检查:静态断言脚本没有模型等待、3600 秒超时及真实翻译同步烟测;隔离运行密钥初始化命令,验证数据库非空、随机 Key 可回读且终端不输出 Key,再验证正式容器能够使用同一持久卷启动。
1
+ ---
2
+ name: translate-engine
3
+ description: Microi 翻译引擎与多语言词条规范。用于 V8.TranslateEngine 文本/批量/HTML/检测/语言列表/文件/建议/健康能力、HTTP 与 MCP 翻译调用、GetLang 词条、供应商配置、租户隔离、缓存和验收。
4
+ ---
5
+
6
+ > **Codex 非阻塞自动更新:** 当前宿主为 Codex 时,吾码 CLI、Codex 插件与工作区 AI/MCP 由后台自动更新;需要诊断时读取 `../microi-codex-installer/SKILL.md`。更新失败、等待空闲或尚未重载均不得阻断当前、正在进行或新建任务。非 Codex 宿主跳过此项。
7
+
8
+ # Microi TranslateEngine
9
+
10
+ 翻译运行时源码位于开源类库 `Microi.Server/Microi.Translate`,NuGet 包名为 `Microi.Translate`。可复用的供应商、租户隔离、缓存和模型契约必须维护在该类库;闭源 `Microi.net` 只允许保留 License 授权或平台私有装配边界,不能重新复制翻译业务实现。
11
+
12
+ ## API
13
+
14
+ ```js
15
+ var r1 = V8.TranslateEngine.Translate('你好', 'en');
16
+ var r2 = V8.TranslateEngine.Translate('hello', 'cn', 'en');
17
+ var full = V8.TranslateEngine.TranslateText({
18
+ SourceTexts: ['你好', '世界'], FromLang: 'auto', Lang: 'en',
19
+ Format: 'text', Alternatives: 2
20
+ });
21
+ var detected = V8.TranslateEngine.Detect({ SourceText: 'Bonjour' });
22
+ var languages = V8.TranslateEngine.GetLanguages();
23
+ var health = V8.TranslateEngine.Health();
24
+ var suggestion = V8.TranslateEngine.Suggest({
25
+ SourceText: 'Hello', SuggestedText: '你好', FromLang: 'en', Lang: 'zh'
26
+ });
27
+ var text = V8.TranslateEngine.GetLang('NoAuth', 'cn');
28
+ var item = V8.TranslateEngine.GetLangData('NoAuth');
29
+ var code = V8.TranslateEngine.GetLangCode('NoAuth');
30
+ ```
31
+
32
+ `Translate` 返回 `DosResult`,`Data` 为兼容的单条译文字符串。`TranslateText` 返回包含单条/批量译文、检测语言、候选译文和格式的完整结构。其余业务方法:
33
+
34
+ | 方法 | 契约 |
35
+ |---|---|
36
+ | `TranslateText` | `SourceText/SourceTexts` 二选一;`FromLang=auto`;`Format=text/html`;`Alternatives=0..10` |
37
+ | `Detect` | 返回 `{Language, Confidence}[]` |
38
+ | `GetLanguages` | 返回当前服务真实安装的 `{Code,Name,Targets}[]` |
39
+ | `TranslateFile` | TXT/HTML/ODT/ODP/DOCX/PPTX/XLSX/EPUB/PDF Base64 输入,Base64 文件输出 |
40
+ | `Suggest` | 写入启用了 suggestions 的 LibreTranslate 服务;不是多候选翻译 |
41
+ | `Health` | 只返回健康和业务能力摘要,不返回 URL/Key |
42
+ | `GetLang/GetLangData/GetLangCode` | 读取 `diy_lang`,不调用翻译供应商 |
43
+
44
+ LibreTranslate 的 `/frontend/settings`、API Key 管理、`/metrics` 和 Web UI 是运维控制面,不得从普通 V8/HTTP/MCP 代理。
45
+
46
+ 文件入口的完整名称是 `V8.TranslateEngine.TranslateFile({...})`,不要把叶子名误当全局函数。
47
+
48
+ ## 租户与密钥
49
+
50
+ - V8 调用统一绑定当前 `V8TenantContext`。普通租户传其它 `OsClient` 不会跨租户翻译或读取配置。
51
+ - 普通租户未配置供应商时失败关闭,不得隐式回退借用主租户翻译地址、密钥或额度。
52
+ - Provider、Endpoint、Key、Secret、ApiKey 等只保存在服务端租户配置;不得进入前端 `SysConfig`、日志、错误响应或业务表。
53
+ - 主租户显式跨租户只允许可信控制面 C# 调用,不由 HTTP 参数建立信任。
54
+
55
+ ## 词条优先
56
+
57
+ 界面固定文案优先维护 `diy_lang` 词条,不要每次调用第三方翻译。Key 使用稳定英文标识,中文、英文等语言值统一回读。缺失词条应返回可诊断 fallback,而不是把密钥或供应商错误展示给用户。
58
+
59
+ ## 动态翻译
60
+
61
+ - 校验源语言和目标语言白名单。
62
+ - 限制单条长度、批量条数、总字符数和超时。
63
+ - 用户隐私、合同、身份证、Token、密码和内部提示词不应发送到未批准的第三方供应商。
64
+ - 缓存 Key 包含 `OsClient + Provider + From + To + 文本哈希`;不要把原文直接作为 Redis Key 或日志。
65
+ - 供应商限流/失败使用有上限重试和熔断;不要无限重试阻塞 V8。
66
+
67
+ ## LibreTranslate 自托管
68
+
69
+ LibreTranslate 是动态翻译供应商,不是 `diy_lang` 的替代品。一键安装默认部署;安装选择直接 Enter 等同 `1`,语言套餐直接 Enter 等同基础套餐 `1`。只有用户明确输入 `0` 才跳过编排。语言预设为:
70
+
71
+ 1. `zh,zt,en`;
72
+ 2. 预设 1 加 `ja,ko,vi,th,id,ms,tl`;
73
+ 3. 安装脚本列出的全部语言。
74
+
75
+ 用户可追加经过白名单校验的语言 Key。语言越多,首次模型下载越慢;一键安装不得等待模型下载或 HTTP 就绪。应先用同版本镜像独立初始化持久化 `api_keys.db`、写入并回读随机 API Key,再启动正式容器并确认其进入运行状态,让语言模型在容器中继续初始化,不阻塞吾码主体安装。
76
+
77
+ 服务端统一从 SaaS 引擎租户配置读取 `TranslateProvider`、`TranslateUrl`(兼容 `TranslateApiUrl` / `LibreTranslateUrl`)、`TranslateApiKey`(兼容 `TranslateKey`)和 `TranslateTimeout`;不要再为翻译供应商增加 API 容器环境变量。密钥不得进入前端、日志或文档示例的固定默认值。
78
+
79
+ 一键安装先部署平台 API/Web,并通过 liveness、完整 `ServerVersion` 升级链和 readiness;随后才预初始化并回读 API Key 数据库、启动 LibreTranslate 容器,再回读 Upgrade31 的 4 个翻译物理字段。字段每秒回读一次且最多 15 秒,正常升级应首轮命中,镜像过旧或迁移失败应快速关闭翻译能力。只有数据库回读确认字段已存在,才能把当前 `OsClient` 的 `TranslateProvider=LibreTranslate`、Docker 内网 `TranslateUrl`、匹配的 `TranslateApiKey` 和超时写入并立即回读一致性。禁止在 API/Upgrade 启动前直接更新新字段,也禁止遇到 `Unknown column` 后由安装器伪造元数据。LibreTranslate 的网络、镜像、Key、容器、字段或配置任一步失败都应保持翻译能力未启用、记录附加能力警告并继续核心安装。日志只显示 Provider 与 URL,禁止输出密钥。模型尚未完成时翻译能力可以暂时不可用,但不得拖住其它服务的安装。
80
+
81
+ 吾码公开镜像固定为 `registry.cn-hangzhou.aliyuncs.com/microios/libretranslate:1.9.6-microi1`。该镜像基于 1.9.6 固定摘要,仅把与 `requests 2.31.0` 不兼容的 `chardet 7.x` 固定为 `5.2.0`,构建必须同时通过 `pip check` 和将 warning 视为 error 的 `import requests`。安装脚本不得通过隐藏所有 Python warning 来掩盖依赖漂移。
82
+
83
+ 独立编排应使用 ASCII 目录和显式项目名 `docker compose -p microi-libretranslate`;只供平台 API 调用时,不默认开放 LibreTranslate 宿主机防火墙端口。需要公网调用时必须由运维显式配置 TLS、反向代理、访问控制、限流和强 API Key。
84
+
85
+ ## HTTP 与 MCP
86
+
87
+ 已登录 HTTP 入口统一为 `POST /apiengine/platform-translate-runtime`,通过请求体 `Action=TranslateText|Detect|Languages|TranslateFile|Suggest|Health` 选择能力。官方 Managed 接口使用验证后的 Token 绑定 `OsClient`,不得接受 endpoint/key/header;个性化逻辑只写入租户 `platform-runtime-custom-hook`,且原文、文件 Base64、供应商地址和密钥不会传给 Hook。
88
+
89
+ MCP 固定工具:`microi_translate`、`microi_detect_language`、`microi_list_translate_languages`、`microi_translate_file`、`microi_suggest_translation`、`microi_get_translate_health`。文件翻译需要 `confirmExecution=TRANSLATE_FILE`,建议写入需要 `confirmExecution=TRANSLATE_SUGGEST`;审计只记录长度、SHA-256、语言和输出模式,不记录文本、文件内容、本机路径或凭据。大文件结果落到新的绝对路径,不允许覆盖已有文件。
90
+
91
+ ## 安全硬上限
92
+
93
+ - 单条文本 5 万字符,单批最多 50 条/20 万字符,候选最多 10 个;
94
+ - 文件输入 20 MB、输出 25 MB;MCP 内联 Base64 额外限制为 2 MB;
95
+ - Provider URL 必须是无内嵌凭据的绝对 HTTP(S) 地址;禁用自动重定向;文件下载只允许与配置服务同源;
96
+ - 上游失败不回显响应体、堆栈、原文、内部 URL 或密钥;
97
+ - 语言缓存可作为节点级优化,但 Key 必须使用 `OsClient + URL + API Key 哈希`,不能含密钥明文,也不能作为共享事实源。
98
+
99
+ ## 批量与后台任务
100
+
101
+ 大量内容翻译使用 Job/MQ/outbox。每条记录保存源文本版本与目标语言,只有源版本未变化时写回结果;事件用稳定 Id 幂等。后端 `setTimeout/Task.Run` 不是可靠后台任务。
102
+
103
+ ## 配置与缓存更新
104
+
105
+ 词条或供应商配置修改后:
106
+
107
+ 1. 回读当前租户配置或 `diy_lang`。
108
+ 2. 递增共享配置版本/清理租户缓存。
109
+ 3. 在另一个 API 节点验证新值,无需重启。
110
+ 4. 确认旧请求失败不会覆盖新翻译。
111
+
112
+ ## 验收清单
113
+
114
+ - [ ] `Microi.Translate` 能独立编译、打包并由发布脚本推送 NuGet,`Microi.net/TranslateEngine` 不再残留重复源码
115
+ - [ ] `Translate` 的 `DosResult` 契约处理正确
116
+ - [ ] 词条优先,动态翻译只用于动态内容
117
+ - [ ] 普通租户无法伪造 `OsClient`
118
+ - [ ] 密钥、原始隐私文本和供应商堆栈不泄露
119
+ - [ ] 长度、批量、超时、限流和费用上限生效
120
+ - [ ] 一路 Enter 默认部署 LibreTranslate 基础套餐 1;显式输入 0 才跳过
121
+ - [ ] API Key 数据库预初始化成功且正式容器已启动
122
+ - [ ] LibreTranslate 内部端口未被安装脚本默认加入防火墙放行列表
123
+ - [ ] 翻译字段由幂等升级创建,安装器在 API 启动后最多 15 秒回读 schema 才写入配置
124
+ - [ ] 缓存按租户/供应商/语言隔离
125
+ - [ ] 多节点配置失效与批量幂等通过
126
+ - [ ] V8、HTTP、MCP 六类业务入口一致,运维面未被代理
127
+
128
+ ### 复盘:模型下载期间健康检查误报成功导致 API Key 注册失败
129
+
130
+ - 触发场景:一键安装日志仍显示 `Updating Language models` / `Downloading ...`,脚本却已经进入 API Key 注册并报失败。
131
+ - 根因:LibreTranslate 1.9.6 的 `scripts/healthcheck.py` 在 `/tmp/booting.flag` 存在时直接返回成功;这只表示容器仍处于受支持的启动阶段,不表示 HTTP 服务或 `api_keys.db` 已就绪。
132
+ - 通用规则:不能把自带 healthcheck 当作模型和 HTTP 已就绪证明,也不能因此在一键安装中持续等待。安装器应在正式容器启动前独立创建并验证 API Key 数据库,容器启动只证明服务已安装;真实翻译可用性由运行期健康检查体现。
133
+ - 自动化检查:用同版本镜像在不执行入口脚本、不下载模型的条件下创建临时 `api_keys.db`,回读 Key 后启动正式容器;断言安装脚本不存在模型等待循环,随后清理隔离容器与卷。
134
+
135
+ ### 复盘:首次语言模型下载阻塞整套一键安装
136
+
137
+ - 触发场景:国内服务器下载 LibreTranslate 语言模型极慢或网络不可达,一键安装每 30 秒输出一次等待状态,直到 3600 秒后失败,导致吾码其它服务无法继续安装。
138
+ - 根因:安装脚本把“翻译服务容器已安装”与“全部语言模型和 HTTP 已可用”绑定成同一个同步完成条件,并把 API Key 数据库初始化放在模型下载之后。
139
+ - 通用规则:API Key 数据库必须由同版本镜像在启动正式服务前预初始化并持久化;Compose 启动成功且容器进入运行状态后立即继续吾码安装。语言模型初始化属于服务自身后台过程,不得设置为主体安装的同步门禁,也不得循环输出累计等待秒数。
140
+ - 自动化检查:静态断言脚本没有模型等待、3600 秒超时及真实翻译同步烟测;隔离运行密钥初始化命令,验证数据库非空、随机 Key 可回读且终端不输出 Key,再验证正式容器能够使用同一持久卷启动。
@@ -11,6 +11,13 @@ description: Microi V8 与 MCP 文件上传下载指南。用于处理流式 AI
11
11
 
12
12
  公开入口覆盖 `V8.uploadFile`、多文件 `V8.uploadFiles` 与 MCP `microi_upload_file_base64`。多文件上传必须限制并发、逐文件返回结果;Base64 工具只接受明确文件名、大小和租户内目标范围,写后回读路径、大小与哈希。
13
13
 
14
+ ## 表单字段的公有桶与私有桶(强制)
15
+
16
+ - `ImgUpload`、`FileUpload`、`RichText` 的“禁止匿名访问”是字段权威策略:`Limit=false` 写公有桶,`Limit=true` 写私有桶。普通用户只要通过当前菜单/表的新增或编辑动作授权,也必须按该字段配置执行;不得按用户等级把全部非超级管理员上传统一改成私有桶。
17
+ - 浏览器上传必须携带 `FormEngineKey + FieldId + SysMenuId`,编辑已有记录再带 `FormDataId`,TableChild 再带父子授权上下文。后端先用 FormEngine 校验动作权限,再从当前租户回读 `diy_field.Component/Config`,用权威 `Limit` 覆盖请求值,并把目录固定为 `ImgUpload→img`、`FileUpload→file`、`RichText→editor`。
18
+ - 客户端 `Limit`、`Path`、字段 Id 和菜单 Id 都只是待验证线索。没有可验证字段上下文的普通交互式上传继续强制私有并限制到安全一级目录;不能为了恢复公有字段语义而重新信任裸 `Limit=false`。
19
+ - 老 `ImgUpload/FileUpload` 缺失 `Limit` 时兼容为公有;老 `RichText` 缺失上传配置时默认私有。微信待审图片与裁剪/压缩 `_origin` 原图始终私有,字段公有配置不能放宽这些特殊边界。客户端保存与预览必须以上传响应的实际 `Limit` 为准。
20
+
14
21
  ## 交互式图片默认压缩(强制)
15
22
 
16
23
  - `ImgUpload`、PC、UniApp/H5/小程序以及 MCP 普通图片上传在未显式传 `Preview` 时,必须按 `Preview=true` 处理;字段设计器新配置默认开启。只有业务明确要求公开原始画质时才允许显式关闭,不能把“客户端漏传”解释为关闭。
@@ -30,11 +37,11 @@ description: Microi V8 与 MCP 文件上传下载指南。用于处理流式 AI
30
37
 
31
38
  ## 富文本图片、视频与附件(强制)
32
39
 
33
- - `RichText.Limit=false` 只用于需匿名长期访问的官网公告、商品详情等公开正文;内部内容用 `true`。普通交互式帐号即使传 `false`,后端仍可按安全策略强制私有,客户端必须以上传响应的实际 `Limit` 为准。
40
+ - `RichText.Limit=false` 只用于需匿名长期访问的官网公告、商品详情等公开正文;内部内容用 `true`。普通用户经表单新增/编辑授权后也按后端回读到的该字段配置选择桶;仅修改请求中的 `Limit` 不能改变策略,客户端必须以上传响应的实际 `Limit` 为准。
34
41
  - RichText 分别配置 `Image`、`Video`、`File` 的 `Enabled/MaxSize/MaxCount`;图片另传 `Preview/CompressMaxSize/CompressMaxWidth`,并继续遵循“原图私有、展示图公有或私有”的压缩链路。附件类型白名单用 `File.Accept` 进一步收紧,不能放宽服务端白名单。
35
42
  - 私有正文持久化 `/__microi_richtext_private__/...` 稳定对象标识,严禁保存对象存储签名 URL、`OpenPrivateFile` Ticket、DiyToken 或其它会过期的凭据。每次打开记录时携带 `FormEngineKey/FormDataId/FieldId/SysMenuId` 批量换取短效审计代理地址。
36
43
  - 私有文件后端授权必须重新校验当前租户、菜单、表、行和 RichText 字段,并确认所请求路径精确存在于 `img/video/source.src` 或 `a.href`;普通上传字段的对象/数组只认 `Path/FilePath/FilePathName`,不得递归把 `Name/Size/Metadata` 等任意标量当作路径。未经当前租户 FileServer 主机权威校验的绝对 HTTP(S) URL 不得等价为本地对象 Key;正文文字、`data-src/data-href`、脚本标签和前缀相似路径都必须失败关闭。
37
- - 外部匿名页面没有后台记录权限上下文,不能解析私有标识。公开文章必须由有权发布公有资产的超级管理员显式使用公有桶,不得通过延长私有 URL 有效期模拟公开资源。
44
+ - 外部匿名页面没有后台记录权限上下文,不能解析私有标识。公开文章应由设计者把 RichText 字段配置为 `Limit=false`,有该表单新增/编辑权限的用户即可按权威配置发布;不得通过延长私有 URL 有效期模拟公开资源。
38
45
 
39
46
  官网客户端读取私有文件统一调用 `/apiengine/platform-private-file-url`,提交 `FilePathName` 或有界 `FilePathNames`,并按资源类型提供权威定位参数:普通表单字段使用 `FormEngineKey + FormDataId + FieldId + SysMenuId`;用户头像使用 `ResourceKind=UserAvatar + ResourceId=用户Id`;菜单/部门导入模板分别使用 `MenuImportTemplate`、`DeptImportTemplate` 与对应记录 Id。CAD 私有派生预览使用 `ResourceKind=FormFieldDerivedPreview`,除表单四元组外必须同时提交字段中保存的 `OriginalFilePathName` 和单个派生 `FilePathName`;后端只接受同目录同 basename 的 DWG→`_preview.dxf`、STEP/STP→`_preview.stl` 唯一映射,并在对象存在后签名。文件柜对象使用 `ResourceKind=FileManagerObject`,`ResourceId` 必须与单个 `FilePathName` 大小写精确相同,并提交能力探针返回的当前租户权威 `SysMenuId`;此类签名只允许平台超级管理员 DiyToken 会话,访问密钥和普通菜单用户一律拒绝。后端会从权威字段或对象存储重新读取并精确匹配路径;管理员也不能只传裸路径绕过对象引用,普通客户端禁止换取私有文件原始 Byte/Stream。旧 `/api/HDFS/GetPrivateFileUrl` 与 `/api/HDFS/MallFileUrl` 只保留令牌格式兼容并转发同一 Managed 接口,新代码不得继续引用。
40
47
 
@@ -66,7 +73,7 @@ description: Microi V8 与 MCP 文件上传下载指南。用于处理流式 AI
66
73
  可信后端 V8 可用 `V8.Http.GetResponse({ Url: url }).RawBytes` 下载,再用 `System.Convert.ToBase64String` 和 `V8.Method.Upload` 上传。该路径同样必须校验域名、大小、Content-Type、后缀和最终重定向目标。
67
74
 
68
75
  <!-- /microi-progressive:chunk -->
69
- <!-- microi-progressive:chunk id=v8-file-upload-002 sha256=c20863b68d13b3bd41caee90a5e12878501a35b3d9f8d40a80efe3f6b46125a9 -->
76
+ <!-- microi-progressive:chunk id=v8-file-upload-002 sha256=ed7e727c51bd2416ae1f38cf3c4bd09491e616df08473a610372e0ca648e1298 -->
70
77
  ## 接收前端上传的文件
71
78
 
72
79
  前端发起文件上传时,平台自动把文件以 base64 形式注入到 `V8.FilesByteBase64`:
@@ -134,7 +141,7 @@ Unity `Data`、WASM、Windows 安装包、视频模型等发布资产不得进
134
141
  - 帐号与租户每日额度在共享 Redis 中用单次原子脚本预留,支持多节点;Redis 不可用时失败关闭,不能降级成无限上传。
135
142
  - 额度按 UTC 日期统计。为防并发重试绕过限制,后续对象存储失败也不退还已经预留的额度。
136
143
  - 每日额度只阻断短期滥用;对象存储必须另外配置租户/桶总容量、账单告警、生命周期与实际用量对账。Redis 计数不能作为长期容量事实源。
137
- - 普通交互式用户无论客户端是否传 `Limit:false`,服务端都强制使用私有桶,并只允许平台预定义安全一级目录;公有资产必须经过授权的发布流程或超级管理员。
144
+ - 标准表单字段上传按后端回读的 `diy_field.Config` 决定桶,不能按帐号等级覆盖字段策略。没有可验证字段上下文的普通交互式上传无论是否传 `Limit:false` 都强制私有,并只允许平台预定义安全一级目录;非表单公有资产使用受控发布流程或超级管理员入口。
138
145
  - 反向代理、Ingress/IIS 的请求体上限应与进程级 HTTP 解析硬顶协调。字段自身的类型、后缀、大小和数量配置只能进一步收紧当前租户有效值,不能替代平台硬顶。
139
146
 
140
147
  ### 复盘:“当前租户已停用文件上传”
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
4
 
5
- <!-- microi-progressive:chunk id=v8-file-upload-005 sha256=6136a38af209aad174ca1cacd61fcfc66e3428e1e8bf75be8a2490bcb094b71e -->
5
+ <!-- microi-progressive:chunk id=v8-file-upload-005 sha256=b09a96f25aef20eb8cbb204bd785cce370dcd2c9a28563c6f6d720fbdaa5218f -->
6
6
  ## 公有桶 vs 私有桶
7
7
 
8
8
  ### 应用商城 ZIP
@@ -63,13 +63,20 @@ var extractResult = V8.Method.ExtractZip({
63
63
  | 公有桶 | `false` | 直接拼接 `V8.SysConfig.FileServer + Path` | 产品图、Banner、公开文档 |
64
64
  | 私有桶 | `true` | 必须用 `V8.Method.GetPrivateFileUrl` 获取临时 URL | 合同、身份证、敏感数据 |
65
65
 
66
+ ### 表单字段存储策略
67
+
68
+ - 表单设计器的“禁止匿名访问”是服务端权威字段配置,不是管理员等级开关:未勾选即 `Limit=false`,勾选即 `Limit=true`。有当前表单新增/编辑权限的普通用户也可以按公有字段写入公有桶。
69
+ - PC 图片、文件、富文本上传提交 `FormEngineKey + FieldId + SysMenuId`;编辑记录附加 `FormDataId`,TableChild 附加父子授权链。后端校验动作权限并回读当前租户 `diy_field.Config` 后覆盖客户端 `Limit/Path`。客户端篡改 `Limit=false`、选择其它字段或提交任意目录都不能获得公有写入。
70
+ - 无字段上下文的普通上传保持私有;`ImgUpload/FileUpload` 老字段未保存 `Limit` 时兼容公有,`RichText` 缺失配置时默认私有。微信待审图片以及裁剪/压缩原图始终私有。
71
+ - 验收使用“普通用户 + 超级管理员 × 公有字段 + 私有字段 × 新增 + 编辑”矩阵,同时核对响应 `Limit`、实际对象桶、公有匿名读取与私有签名读取。单独用 HTTP 请求传 `Limit=false` 不能证明字段策略正确。
72
+
66
73
  ### 默认 MinIO 桶名与安装验收
67
74
 
68
75
  - Microi 一键安装的默认私有桶固定为 `mci-private`,默认公有桶固定为 `mci-public`;禁止使用 `mci-publish` 等近似名称。
69
76
  - `MinIOEndPointInternet` / `MinIOPrivateEndPoint` 同时兼容 `host:port` 与 `http(s)://host:port`。Provider 必须先归一化为 Host、Port、UseSsl,再调用 MinIO SDK 的 host/port 重载;不得把包含协议的整串 URL 直接作为 hostname,否则会出现 `Invalid URI: The hostname could not be parsed.`。显式 URL 的协议优先于历史 SSL 开关;端点禁止携带用户名密码、桶路径、查询或片段。
70
77
  - 安装脚本创建 `mci-public` 后必须设置匿名下载权限,并把 `HDFS=MinIO`、内外网端点、AccessKey/SecretKey、`MinIOPrivateBucketName=mci-private`、`MinIOPublicBucketName=mci-public` 同步写入当前租户的 `sys_osclients`。
71
78
  - 安装脚本还必须同步当前有效 `sys_config`:`ApiBase` 使用对外可访问的 API 端口,`FileServer` 使用 `http://<访问IP>:<MinIO API端口>/mci-public`。`ApiBase` 不能误用 Web 前端端口,因为 V8 代码会直接在其后拼接 `/api/...` 或 `/apiengine/...`。
72
- - 安装验收必须使用真实登录 Token 分别执行一次 `Limit=false` 和 `Limit=true` 上传:公有文件匿名访问应返回 `200`,私有文件匿名访问应返回 `403`,私有文件通过签名 URL 访问应返回 `200`,并核对下载内容与上传内容一致。
79
+ - 安装验收必须使用真实登录 Token 和两个权威字段分别执行一次公有、私有上传:公有字段的对象匿名访问应返回 `200`,私有字段对象匿名访问应返回 `403`,私有文件通过授权签名 URL 访问应返回 `200`,并核对下载内容与上传内容一致。超级管理员可另用直接上传验证桶初始化;普通用户只传 `Limit=false` 的裸请求应继续落入私有桶。
73
80
 
74
81
  ### 复盘:签名 HEAD 被代理转换为 GET 导致上传后回读误报
75
82