@h-ai/cli 1.0.0-beta.2 → 1.0.0-beta.3

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 (57) hide show
  1. package/README.en.md +20 -8
  2. package/README.ja.md +20 -8
  3. package/README.md +20 -8
  4. package/dist/{chunk-MUHRBJSW.js → chunk-K6RWTTHD.js} +546 -97
  5. package/dist/chunk-K6RWTTHD.js.map +1 -0
  6. package/dist/{chunk-AKV2CQZV.js → chunk-SWEU7KUE.js} +71 -59
  7. package/dist/chunk-SWEU7KUE.js.map +1 -0
  8. package/dist/{chunk-EF7WOFWZ.js → chunk-YVNNMC4H.js} +364 -136
  9. package/dist/chunk-YVNNMC4H.js.map +1 -0
  10. package/dist/cli-config-templates-LUJGDQNW.js +5 -0
  11. package/dist/{cli-config-templates-HHFHNXBN.js.map → cli-config-templates-LUJGDQNW.js.map} +1 -1
  12. package/dist/{cli-skill-templates-PN4FLGBC.js → cli-skill-templates-VV2XWYON.js} +3 -3
  13. package/dist/{cli-skill-templates-PN4FLGBC.js.map → cli-skill-templates-VV2XWYON.js.map} +1 -1
  14. package/dist/index.js +117 -208
  15. package/dist/index.js.map +1 -1
  16. package/dist/metafile-esm.json +1 -1
  17. package/dist/{src-TEBHR5I5.js → src-IR5AU43K.js} +3 -3
  18. package/dist/src-IR5AU43K.js.map +1 -0
  19. package/package.json +11 -11
  20. package/templates/apps/api/.dockerignore.hbs +10 -0
  21. package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +20 -1
  22. package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +6 -1
  23. package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +1 -1
  24. package/templates/apps/api/images/serv.Dockerfile.hbs +3 -2
  25. package/templates/apps/fullstack/.dockerignore.hbs +10 -0
  26. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +1 -1
  27. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +16 -2
  28. package/templates/apps/fullstack/images/serv.Dockerfile.hbs +6 -2
  29. package/templates/apps/fullstack/images/web.Dockerfile.hbs +6 -1
  30. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +1 -1
  31. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +10 -7
  32. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +14 -7
  33. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +6 -0
  34. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +1 -1
  35. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +7 -1
  36. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +1 -1
  37. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +1 -0
  38. package/templates/apps/website/scripts/static-website.mjs.hbs +3 -3
  39. package/templates/base/.dockerignore.hbs +10 -0
  40. package/templates/base/images/web.Dockerfile.hbs +4 -2
  41. package/templates/base/package.json.hbs +1 -1
  42. package/templates/base/src/hooks.server.ts.hbs +9 -7
  43. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +3 -1
  44. package/templates/skills/hai-ai/guide.md +5 -3
  45. package/templates/skills/hai-app-create/development.md +7 -3
  46. package/templates/skills/hai-app-create/reference.md +1 -1
  47. package/templates/skills/hai-build/SKILL.md +5 -5
  48. package/templates/skills/hai-build/paths.md +1 -1
  49. package/templates/skills/hai-build/reference.md +1 -1
  50. package/templates/skills/hai-deploy/SKILL.md +15 -3
  51. package/templates/skills/hai-deploy/middleware.md +4 -2
  52. package/templates/skills/hai-serv/reference.md +5 -8
  53. package/dist/chunk-AKV2CQZV.js.map +0 -1
  54. package/dist/chunk-EF7WOFWZ.js.map +0 -1
  55. package/dist/chunk-MUHRBJSW.js.map +0 -1
  56. package/dist/cli-config-templates-HHFHNXBN.js +0 -5
  57. package/dist/src-TEBHR5I5.js.map +0 -1
@@ -80,16 +80,18 @@ await ai.close()
80
80
 
81
81
  ## 配置要点
82
82
 
83
+ LLM 协议使用 `llm.protocol`、`llm.models[].protocol` 和 `tempModel.protocol`,值为 `chat | responses | anthropic`;环境变量使用 `HAI_AI_LLM_PROTOCOL`、`HAI_AI_LLM_MODELS_0_PROTOCOL` 等。旧 `api` 字段及旧协议变量会报迁移错误,密钥字段 `apiKey` 不变。
84
+
83
85
  ```yaml
84
86
  llm:
85
87
  apiKey: ''
86
88
  baseUrl: https://api.openai.com/v1
87
89
  model: gpt-4o-mini
88
- api: chat # chat(默认)| responses | anthropic——底层协议,对使用方透明
90
+ protocol: chat # chat(默认)| responses | anthropic——底层协议,对使用方透明
89
91
  timeout: 60000
90
92
  tempModelCacheTtl: 600000 # 临时模型客户端缓存 TTL(毫秒,默认 10 分钟)
91
93
  models: # 可为单个模型指定协议(responses / anthropic)
92
- - {id: claude, model: claude-3-5-sonnet-latest, api: anthropic}
94
+ - {id: claude, model: claude-3-5-sonnet-latest, protocol: anthropic}
93
95
  scenarios:
94
96
  chat: fast
95
97
  reasoning: strong
@@ -125,7 +127,7 @@ memory:
125
127
  | ------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
126
128
  | 非流式对话 | `ai.llm.chat({ messages })` | OpenAI 兼容 Chat Completion |
127
129
  | 流式对话 | `ai.llm.chatStream({ messages })` | 返回 `AsyncIterable` |
128
- | 多协议 | 模型 `api: chat/responses/anthropic` | 底层走 Chat Completions / Responses / Anthropic,公共形状不变 |
130
+ | 多协议 | 模型 `protocol: chat/responses/anthropic` | 底层走 Chat Completions / Responses / Anthropic,公共形状不变 |
129
131
  | 请求取消 | `ai.llm.chat({ messages, signal })` | 传 `AbortSignal`,`abort()` 立即停上游生成 |
130
132
  | 临时模型 | `ai.llm.chat({ messages, tempModel })` | 单次请求级临时端点,客户端按 TTL 缓存 |
131
133
  | 工具定义 | `ai.tools.define(...)` | Zod schema 转 JSON Schema;`handler(input, ctx)` 第二参为执行上下文 |
@@ -22,7 +22,9 @@ README 编辑先读章节,把功能说明与示例合并到对应章节;新
22
22
 
23
23
  ### 页面与布局
24
24
 
25
- 纯展示官网可用website模板加`--features none`明确空选择,默认模板行为不变;none不能与其他模块/空项混用。静态发布使用`HAI_BUILD_STATIC=1`及公开`PUBLIC_BASE_PATH`(如/hai-framework,无末尾/),先确认没有服务端业务模块/API/actions。它不启用数据库/IAM、不放宽生产守卫,也不赋予静态联系表单发送能力;构建和实际子路径验证按[hai-build](../hai-build/SKILL.md)。
25
+ 新建工程统一采用适用的完整模块和示例,服务端包含 AI、向量库、反馈等依赖;客户端仍按类型隔离服务端模块。安装体积相应增加,示例需按实际业务替换。`--template`、`--features`、`--examples/--no-examples` 已删除,`create --yes/-y` 改为 `--defaults`,旧参数明确报错;`deploy --yes` 保持原义。已有工程的模块选择不受影响。
26
+
27
+ website默认SSR;静态发布须先移除服务端业务依赖、初始化及API/actions。静态构建与实际路径验证按[hai-build](../hai-build/SKILL.md)。
26
28
 
27
29
  网站挂载到`/yyy/`等目录时,按[网站挂载目录](../hai-build/paths.md)同步资源、链接、认证端点和服务端守卫。SvelteKit在编译时固定base,Vite默认相对资源加hash导航;API基址单独配置。SDK子目录制品使用格式5,健康与增量检查随制品处理,不手工修改旧格式清单来代替重新构建。
28
30
 
@@ -72,9 +74,11 @@ Compose `env_file` 的变量在创建容器时固定,改文件后 `restart`
72
74
 
73
75
  Fullstack 的环境文件在工程根;service 脚本通过 `../../.env*` 加载,Web/App/Desktop 的 Vite 自动 dotenv 加载关闭(`envDir: false`),开发和预览由 `core.config.loadEnvFiles` 从工程根读取,构建不读取部署环境文件。API workspace 的环境文件在 `apps/<name>-serv/`。独立应用在各自根目录加载。静态 Web 通过 `runtime-config.js` 获取公开地址,部署环境覆盖无需重建镜像;原生包在复制静态资源前配置该入口。修改编译进客户端的默认值时仍需重新构建;fullstack 的公开应用元数据由 service `app.info` 返回。
74
76
 
77
+ Node后端的当前部署包默认重读发布.env.runtime,修改后restart容器即可;托管连接优先级不变,布局/Node参数与中间件仍需重新部署。长期修改同步回源环境;见[部署指引](../hai-deploy/SKILL.md#后端运行配置重载)。
78
+
75
79
  #### 迁移已有项目
76
80
 
77
- 先把原来被忽略的 `.env` 私有值迁入 `.env.local`,再提交公共基础和环境文件。本机文件只保留需要覆盖的值,避免整份复制示例后固定开发环境。旧的 `HAI_AI_LLM_API_KEY` / `HAI_AI_LLM_BASE_URL` 改为 `HAI_AI_LLM_APIKEY` / `HAI_AI_LLM_BASEURL`;音频和图像厂商回退变量同样使用 `APIKEY` 后缀。Reach 和 deploy 凭据按当前 YAML 路径命名,以项目 `.env.example` 为准,同步迁移部署平台变量和本机文件。
81
+ 先把原来被忽略的 `.env` 私有值迁入 `.env.local`,再提交公共基础和环境文件。本机文件只保留需要覆盖的值,避免整份复制示例后固定开发环境。旧的 `HAI_AI_LLM_PROTOCOL_KEY` / `HAI_AI_LLM_BASE_URL` 改为 `HAI_AI_LLM_APIKEY` / `HAI_AI_LLM_BASEURL`;音频和图像厂商回退变量同样使用 `APIKEY` 后缀。Reach 和 deploy 凭据按当前 YAML 路径命名,以项目 `.env.example` 为准,同步迁移部署平台变量和本机文件。
78
82
 
79
83
  原 `HAI_AI_ANTHROPIC_API_KEY` / `HAI_AI_ANTHROPIC_BASE_URL` 不再使用。默认协议为 `anthropic` 时改用标准 LLM 变量;混合模型池中有独立凭据或端点时,将 `apiKey` / `baseUrl` 配置在对应模型项。厂商回退 `ANTHROPIC_API_KEY` / `ANTHROPIC_BASE_URL` 保留,优先级以 AI 模块说明为准。
80
84
 
@@ -92,7 +96,7 @@ Fullstack 的环境文件在工程根;service 脚本通过 `../../.env*` 加
92
96
  | `HAI_CACHE_TYPE` / `HAI_CACHE_DB` | `memory \| redis`;DB 为整数 0–15;memory 仅单进程使用 |
93
97
  | `HAI_STORAGE_TYPE` | `local \| s3`;local 要求 root,s3 要求 bucket、region、accessKeyId、secretAccessKey |
94
98
  | `HAI_SERV_SERVER_HOST` / `HAI_SERV_SERVER_PORT` | HTTP 主机和整数端口 1–65535;部署平台 HOST/PORT 可覆盖 |
95
- | `HAI_AI_LLM_API` / `HAI_AI_LLM_TEMPERATURE` | `chat \| responses \| anthropic`;temperature 为数字 0–2 |
99
+ | `HAI_AI_LLM_PROTOCOL` / `HAI_AI_LLM_TEMPERATURE` | `chat \| responses \| anthropic`;temperature 为数字 0–2 |
96
100
  | `HAI_AI_LLM_APIKEY` / `HAI_AI_LLM_BASEURL` / `HAI_AI_LLM_MODEL` | 厂商密钥、服务 URL、实际可用模型名;启用时满足厂商要求 |
97
101
  | `HAI_ADMIN_DEFAULT_PASSWORD` | 首次创建管理员的密码,满足 IAM 密码策略;CLI 为 fullstack 的 `.env.dev/.env.test/.env.prod` 分别生成独立随机值 |
98
102
  | `PUBLIC_API_BASE` | 可公开的 API 地址,不得包含用户名、密码或 token |
@@ -339,7 +339,7 @@ core.init() → crypto.init() → reldb.init() → cache.init() → iam.init()
339
339
 
340
340
  - 保持脚手架 `images/*.Dockerfile`、`.dockerignore` 与 `package.json` 中 `build` / `compile` 命令与 hai.json 的 build/deploy 配置同步。保留 `.gitattributes`,让 `.dockerignore`、Dockerfile 和 POSIX 脚本统一使用 LF,保持跨平台输入一致并确保 Linux 脚本可运行。
341
341
  - Podman 多阶段构建保持 `--format docker --jobs=1`;前者保留 `HEALTHCHECK`,后者避免部分 Podman 5.8/Buildah 组合在并行 stage 构建时触发内部 semaphore panic。
342
- - 先复制 lockfile、workspace 配置与构建器准备的 `images/dependencies/` 安装输入执行 `pnpm fetch --ignore-scripts`,再复制源码并离线安装、构建;fetch、安装和 `pnpm pm deploy` 共用 pnpm store,安装与生产依赖整理共用 SQLite 驱动缓存,避免重复下载,兼容新增 workspace、本地归档与补丁。
342
+ - 先复制 lockfile、workspace 配置与构建器准备的 `images/dependencies/` 安装输入执行 `pnpm fetch --ignore-scripts`,再离线安装、复制源码并构建;fetch、安装和 `pnpm pm deploy` 共用 pnpm store,安装与生产依赖整理共用 SQLite 驱动缓存,使源码变化复用下载与安装层,兼容新增 workspace、本地归档与补丁。
343
343
  - 默认容器面向 CPU 运行或远程 AI 服务,Dockerfile 设置 `ONNXRUNTIME_NODE_INSTALL_CUDA=skip`,跳过额外 CUDA/TensorRT 下载;使用宿主机 GPU 时定制镜像和运行参数,不修改本机 npm 或全局 AI/GPU 配置。
344
344
  - SvelteKit 服务使用 Node adapter;纯 Vite 前端使用带 SPA fallback 的静态镜像;fullstack 的 Service 与 Web 分别交付,Service 直接监听且不增加转发进程。
345
345
  - Web 的 `PUBLIC_*` 部署配置在容器启动时生成静态运行时配置,不作为 build arg 烘焙,确保同一镜像可跨环境部署。
@@ -27,14 +27,14 @@ description: "构建或排查 hai 应用的源码、静态网站、容器镜像
27
27
 
28
28
  ## 构建与部署
29
29
 
30
- - website默认Node SSR;纯展示站点用`hai create <name> --type website --features none`明确不选可选业务模块,Core/Kit/UI与默认部署开发工具保留,fullstack仍保留架构必需模块。compile静态预渲染使用`HAI_BUILD_STATIC=1 PUBLIC_BASE_PATH=/docs-site`,docs-site替换为实际仓库名,各路径段仅ASCII字母、数字、_、.、-,不含末尾/、查询/片段或逃逸;省略/0保持SSR,根站路径留空。HAI_BUILD_STATIC仅用于compile;PUBLIC_BASE_PATH也支持docker网站构建,原生app/desktop拒绝网站目录。静态拒绝已选服务端业务模块、自定义API/actions和未预渲染页面,不放宽生产依赖守卫,不用SPA fallback;唯一默认健康端点不发布。构建不读根.env;static是公开目录,正常图片/字体等原样发布,禁止放私密内容,检测到.env/.env.*或符号链接会停止构建。上传build时include-hidden-files:true保留.nojekyll,验根/深链/刷新/资产与敏感哨兵。
30
+ - 新建website包含完整模块与示例,默认Node SSR;静态发布须先移除服务端业务依赖、初始化及API/actions,保留Core/Kit/UI。compile静态预渲染使用`HAI_BUILD_STATIC=1 PUBLIC_BASE_PATH=/docs-site`,docs-site替换为实际仓库名,各路径段仅ASCII字母、数字、_、.、-,无末尾/;省略/0保持SSR,根站路径留空。HAI_BUILD_STATIC仅用于compile,PUBLIC_BASE_PATH也支持image网站构建。静态拒绝服务端业务模块、自定义API/actions与未预渲染页面,不放宽生产守卫、不用SPA fallback;默认健康端点不发布。构建不读根.env,static为公开目录,拒绝.env/.env.*与符号链接。上传build使用include-hidden-files:true保留.nojekyll,验首页/深链/刷新/资产与敏感哨兵。
31
31
 
32
32
  - 创建默认包含开发期部署工具,可用 --no-deploy 关闭。每个镜像使用 images/ 中独立 Dockerfile,Web 配置位于 images/web/,不使用镜像阶段 target 配置。
33
- - 构建器生成 images/dependencies/ 安装输入;fetch、安装和生产依赖整理共用 pnpm store,安装与生产依赖整理共用 SQLite 驱动缓存,并复用依赖层。file: 归档、补丁、workspace 元数据必须进入下载上下文;原生依赖缓存按系统/架构/ABI 区分。基础镜像、中间件及工具指定版本,禁止 latest。
33
+ - 构建器生成 images/dependencies/ 安装输入;fetch、安装和生产依赖整理共用 pnpm store,安装与生产依赖整理共用 SQLite 驱动缓存,并复用依赖层;依赖安装在源码COPY前,前后端仅复制各自需要的源码。运行镜像去掉应用自身声明、source map和README。file: 归档、补丁、workspace 元数据必须进入下载上下文;原生依赖缓存按系统/架构/ABI 区分。基础镜像、中间件及工具指定版本,禁止 latest。
34
34
  - 默认容器面向 CPU 运行或远程 AI 服务,Dockerfile 设置 `ONNXRUNTIME_NODE_INSTALL_CUDA=skip`,跳过额外 CUDA/TensorRT 下载;使用宿主机 GPU 时定制镜像和运行参数,不修改本机 npm 或全局 AI/GPU 配置。
35
35
  - pnpm run deploy --build 显式串联构建、打包和发布;--bundle-only 只交付完整离线包与跨平台脚本;--services 以服务器成功状态为基线只更新选中服务。完整包自动包含自建中间件镜像,服务器禁止联网拉取。
36
- - `pnpm build` 默认仅编译源码(调用 compile);`pnpm build --target docker` 根据 hai.json.build.images 的 dockerfile 构建并导出 serv/web 镜像(可单独或组合),可用 --images web 只构建前端,auto 优先可达 Podman、其次 Docker,可用 --runtime 显式指定。
37
- - compile 交付源码编译结果,docker 交付镜像归档,desktop 交付 Tauri 系统安装包,app 交付 Capacitor 原生制品;每次选择一个 target。hai.json 的 build.images[].dockerfile 指向独立镜像文件,build.desktop/build.app 声明原生工程目录,deploy 保存整个项目的部署配置;参数和平台前置以当前 CLI 类型与工程 scripts 为准。cap:sync 只同步工程,不能作为已打包或已安装的证据。
36
+ - `pnpm build` 默认仅编译源码(调用 compile);`pnpm build --target image` 根据 hai.json.build.images 的 dockerfile 构建并导出 serv/web 镜像(可单独或组合),可用 --images web 只构建前端,默认最多两项并行,--concurrency 1可串行,auto 优先可达 Podman、其次 Docker,可用 --runtime 显式指定。
37
+ - compile 交付源码编译结果,image 交付镜像归档,desktop 交付 Tauri 系统安装包,app 交付 Capacitor 原生制品;每次选择一个 target。hai.json 的 build.images[].dockerfile 指向独立镜像文件,build.desktop/build.app 声明原生工程目录,deploy 保存整个项目的部署配置;参数和平台前置以当前 CLI 类型与工程 scripts 为准。cap:sync 只同步工程,不能作为已打包或已安装的证据。
38
38
  - Podman 的客户端代理通过预定义构建参数传递,覆盖 Windows/macOS 远程引擎的服务端默认值;代理地址必须能从构建容器访问,--no-http-proxy 禁止此传递。不要把代理写成 Dockerfile ENV 或固化进交付镜像。
39
39
  - --network 默认沿用引擎网络;只有实际构建网络无法访问依赖/代理时才显式选择网络,pasta 仅适用于 rootless Podman。build 与 run 的主机名解析可能不同,须验证构建网络中的可达性,不默认改成 host 网络。
40
40
  - 从运行build的应用根package.json.version读取版本,不能使用CLI/框架版本或服务子包版本代替。根目录清单version=4,非根目录version=5并记录webBasePath;appVersion为应用版本。servContainerPort/webContainerPort仅记录images配置显式填写的端口,部分构建也保留未选镜像端口,未填写时沿用部署默认值。镜像tar名含版本、buildId区分同版本构建,Tauri也接收根版本。不要手改清单或保留无版本的交付归档。
@@ -44,7 +44,7 @@ description: "构建或排查 hai 应用的源码、静态网站、容器镜像
44
44
  - 静态客户端通过 runtime-config.js 或原生宿主初始化脚本获取公开地址与元数据;仅投影公开白名单,禁止将完整 process.env、服务配置或密钥序列化到浏览器。预览与容器启动均须验证真实登录,不能依赖构建期 API 地址让 E2E 通过。
45
45
  - Fullstack Capacitor App 在 `public/runtime-config.js` 提供公开 API 地址,再编译并同步原生资源;Tauri 从启动进程的 PUBLIC_API_BASE 注入。不能把开发代理的 .env 配置当作已安装原生包的运行配置。
46
46
  - `pnpm build --target desktop --platform windows|linux|macos --arch x64|arm64` 调用对应工程的 Tauri build。要求在目标系统准备 Rust target、SDK 和打包工具,不假定跨系统编译。原生安装包必须按目标系统实测。
47
- - deploy 默认消费已有产物,--build 显式先构建,详见 [hai-deploy](../hai-deploy/SKILL.md)。网络不通时 --bundle-only 生成 tar,按说明手工搬运;packaged 不代表部署已运行。
47
+ - deploy 默认消费已有产物,--build 显式先构建,详见 [hai-deploy](../hai-deploy/SKILL.md)。网络不通时 --bundle-only 默认生成 tar.gz(显式--output release.tar保留未压缩格式),按说明手工搬运;packaged 不代表部署已运行。
48
48
  - 测试临时工程、镜像、容器、辅助进程和数据必须在 finally/teardown 自动清理,失败/取消也清理;日志、截图和报告保留到分析和交付结束再清理,不得提交测试产物或删除用户既有资源。
49
49
  - 浏览器测试的数据放入本轮独立临时目录;Windows 等子进程与服务退出后再删除数据库和上传文件,不依赖下一轮测试补清理。
50
50
 
@@ -20,7 +20,7 @@
20
20
 
21
21
  ## SDK容器交付
22
22
 
23
- - `PUBLIC_BASE_PATH=/yyy`用于compile或docker网站构建;HAI_BUILD_STATIC仍只用于website的compile静态预渲染。
23
+ - `PUBLIC_BASE_PATH=/yyy`用于compile或image网站构建;HAI_BUILD_STATIC仍只用于website的compile静态预渲染。
24
24
  - 根目录制品沿用格式4,非根目录制品使用格式5并记录webBasePath。使用支持格式5的CLI/Deploy;旧工具拒绝新格式,不能手改编号绕过。
25
25
  - SDK生成匹配的Nginx目录、运行配置入口、健康检查和访问URL。外部网关转发到此入口时保留目录,避免再次剥离。
26
26
  - 每次完整或部分构建保持同一PUBLIC_BASE_PATH,即使只构建serv。目录变化须全量部署;遗漏或改变目录的增量包会在替换前拒绝。失败恢复使用旧发布的健康路径;容器恢复不撤销业务数据。
@@ -46,7 +46,7 @@ pnpm 专属配置放在 `pnpm-workspace.yaml`,`.npmrc` 仅用于注册表与
46
46
 
47
47
  ### SvelteKit Adapter 模式
48
48
 
49
- CLI website模板默认Node SSR。纯展示站点通过`--features none`创建,在compile时使用`HAI_BUILD_STATIC=1`与可选`PUBLIC_BASE_PATH`切换完整静态预渲染,边界见本skill的静态网站说明;该模板没有使用下方VITE_ADAPTER工厂。静态产物用preview本机检查,上传build到Pages/CDN;生成的start/Docker配置属于普通SSR模式,不能用于运行静态HTML。切回SSR只需清除静态开关并重建,PUBLIC_BASE_PATH仍可按实际网站目录用于SSR或Docker;SvelteKit/Vite差异、制品格式和健康检查见[网站挂载目录](paths.md)。
49
+ CLI website模板默认Node SSR。新建工程包含完整模块和示例,静态发布须先移除服务端业务依赖、初始化和API/actions;在compile时使用`HAI_BUILD_STATIC=1`与可选`PUBLIC_BASE_PATH`切换完整静态预渲染,边界见本skill的静态网站说明;该模板没有使用下方VITE_ADAPTER工厂。静态产物用preview本机检查,上传build到Pages/CDN;生成的start/Docker配置属于普通SSR模式,不能用于运行静态HTML。切回SSR只需清除静态开关并重建,PUBLIC_BASE_PATH仍可按实际网站目录用于SSR或Docker;SvelteKit/Vite差异、制品格式和健康检查见[网站挂载目录](paths.md)。
50
50
 
51
51
  仅在项目实际使用 SvelteKit 和 `@h-ai/kit/adapter` 时使用;Vite SPA 不配置 SvelteKit adapter,fullstack 各前端按自身 scripts 构建。
52
52
 
@@ -41,14 +41,26 @@ description: "构建并发布或交付已有镜像:完整离线包、按服务
41
41
 
42
42
  成功后手工回退使用**当前 CLI**、旧应用 build 制品和匹配配置,省略 `--build`、`--services` 生成新全量 ID;离线也须重新打包,不能运行旧 bundle 或旧工具绕过账本。旧制品通常只保留 serv/web 镜像,中间件仍按当前 CLI 固定版本规划,不承诺精确回退全部中间件版本、DDL 或业务数据。确认主版本、Schema、拓扑和数据兼容并准备备份,再发布和验证。
43
43
 
44
+ ## 可选 HTTPS
45
+
46
+ 所有容器模板共用deploy.provider.expose.https,省略时HTTP。files指定domain、certificateFile、privateKeyFile(相对工程根),校验域名/期限/密钥并复制到私有包。letsencrypt指定domain、email、acceptTerms:true,HTTP hostPort必须80,公网DNS、80入站及CA出站须可达。固定版本官方Certbot申请并每12小时检查续期,Nginx自动重载。仅单域名HTTP-01,无DNS/通配符。HTTPS默认443、redirectHttp默认true;--yes复用配置。启停或改模式/域名/端口/本地证书需全量。状态在服务器https/acme及按域名隔离的https/certificates目录,需备份;续期失败保留旧证书并须及时处理,隔离目标用已有证书。打包/plan不申请证书。
47
+
48
+ 默认.tar.gz,显式--output release.tar为未压缩,README仅外层。镜像从解包目录导入,release只留配置/恢复状态;成功后清理本次incoming,失败保留诊断。中间件归档按镜像内容ID缓存且复用前验摘要。
49
+
50
+ ## 后端运行配置重载
51
+
52
+ Node 后端(Serv / SvelteKit SSR)默认在每次启动时重读发布目录的 `.env.runtime`,修改后 `docker restart <容器名>` 或 `podman restart <容器名>` 即可,无需重建镜像或额外 override。旧部署先用新版 CLI 发布一次。删除的字段不会从旧 Compose 注入中复活;服务器托管连接的 `middleware.env` 保持原有更高优先级,私有代理标记和 Node 启动参数仍由部署装配管理。静态 Web、中间件、端口/挂载和 Nginx 限额不在该重载范围。手工修改需备份;下一次后端发布会从工程环境重新生成,需要长期保留的配置同步回源环境。
53
+
54
+ 运行文件在后端实际挂载的releases/<后端发布ID>/.env.runtime;仅更新Web/中间件后current可能指向新记录,不能据此猜测后端文件,按容器Mounts中/run/hai/.env.runtime的Source确认。只读文件挂载,上级目录0700,容器非root可读,宿主所有者可修改。dotenv字面解析不执行shell;双引号支持JSON转义。单文件≤1MiB,缺失/不可读/超限在应用导入前失败。父HAI_SERV/HAI_KIT仍优先于叶字段。重启后验健康与配置影响的业务,失败恢复文件再重启。
55
+
44
56
  ## CLI
45
57
 
46
58
  ```sh
47
59
  pnpm run deploy --env prod --build
48
- pnpm build --target docker
60
+ pnpm build --target image
49
61
  pnpm run deploy --env prod --artifact-dir .hai/build/docker/<buildId>
50
62
  pnpm run deploy --env prod --bundle-only
51
- pnpm build --target docker --images web
63
+ pnpm build --target image --images web
52
64
  pnpm run deploy --env prod --services web
53
65
  ```
54
66
 
@@ -84,7 +96,7 @@ Linux 预备 Docker/Podman、支持 --pull never 的 Compose(Docker Compose v2
84
96
 
85
97
  按 [分轮验证与集中修复](../hai-app-tests/validation.md) 收集适用的 typecheck、lint、build、test、scaffold gates 和 test:deploy-gates,汇总后集中修复、再验证。实际验证无 registry 网络的首次部署、登录刷新、同版本重发、只更新 Web/API、停止/down 后增量恢复、缺密码隐藏输入、上传进度、损坏归档、缺基线、健康失败与恢复。Windows/Linux/macOS 上传入口分别执行验收;原生安装包在对应 OS 验证。测试临时工程、容器、镜像、数据和进程在 finally/teardown 清理,只清理测试拥有的资源;日志、截图和报告保留到分析和交付结束再清理。
86
98
 
87
- 部署前可 hai deploy --env prod --plan,只读校验真实制品和执行范围,显示项目/环境、版本/构建、配置文件及键名、保留范围、基线要求和恢复目录;不构建、不创建凭据、不连接或改变目标。远端 current 未读取标 not-inspected;不得把计划或本地打包当真实基线成功。数据库与业务数据不随 Compose 恢复回退。
99
+ 部署前可 hai deploy --env prod --plan,只读校验真实制品和执行范围,显示工程根root、服务源码/配置目录serviceDir、项目/环境、版本/构建、配置文件及键名、保留范围、基线要求和恢复目录;不构建、不创建凭据、不连接或改变目标。远端 current 未读取标 not-inspected;不得把计划或本地打包当真实基线成功。数据库与业务数据不随 Compose 恢复回退。
88
100
 
89
101
  需要核对目标真实基线时加 --inspect-remote(必须配合 --plan),仅 SSH 读取 current/成功发布目录,按 verified/missing/unavailable 与真实发布 ID 报告,不写目标;不能把未检查当作成功。
90
102
 
@@ -4,9 +4,9 @@
4
4
 
5
5
  ## 环境先行
6
6
 
7
- 自建 S3 还要区分内部 endpoint 和浏览器 publicEndpoint;后者是 HTTP(S) origin,无默认、不含桶或网站目录。全栈 Web Nginx 或 SSR/API gateway 将桶路径直接转至 storage,存储端口与控制台不直接发布。外层入口保持 Host/URI/query 并转发桶路径,精确 CORS 在实际 S3 设置。增加网关或改变自建访问配置需全量基线,应用增量仅复用原配置;外部 S3 不生成本地路由,local 不公开目录。操作与验证见 [Storage skill](../hai-storage/SKILL.md)。
7
+ 自建 S3 还要区分内部 endpoint 和浏览器 publicEndpoint;后者是 HTTP(S) origin 或带代理目录的入口,无默认且不含桶名。全栈 Web Nginx 或 SSR/API gateway 将桶路径直接转至 storage,存储端口与控制台不直接发布。外层入口保持 Host/URI/query,仅生成网关移除代理目录,精确 CORS 在实际 S3 设置。增加网关或改变自建访问配置需全量基线,应用增量仅复用原配置;外部 S3 不生成本地路由,local 不公开目录。操作与验证见 [Storage skill](../hai-storage/SKILL.md)。
8
8
 
9
- 默认部署名取工程根(最近的 `hai.json` 或锁文件所在目录)的 `package.json.name`,缺失时报错,再附加显式环境后缀。例如 fullstack 工程 `hai-delivery` 扫描 `packages/hai-delivery-serv`,`--env test` 生成 `/opt/hai/apps/hai-delivery-test` 和 `bundle-hai-delivery-test-<部署ID>-<版本>.tar`。远端目录、交付包、Compose 项目、API/Web/中间件容器、数据卷、服务器凭据状态及增量基线统一使用该名称;不会按字符串删除真实项目名中的 `-serv`。
9
+ 默认部署名取工程根(最近的 `hai.json` 或锁文件所在目录)的 `package.json.name`,缺失时报错,再附加显式环境后缀。例如 fullstack 工程 `hai-delivery` 扫描 `packages/hai-delivery-serv`,`--env test` 生成 `/opt/hai/apps/hai-delivery-test` 和 `bundle-hai-delivery-test-<部署ID>-<版本>.tar.gz`。远端目录、交付包、Compose 项目、API/Web/中间件容器、数据卷、服务器凭据状态及增量基线统一使用该名称;不会按字符串删除真实项目名中的 `-serv`。
10
10
 
11
11
  资源身份和制品格式沿用[构建技能](../hai-build/SKILL.md)及[网站挂载目录](../hai-build/paths.md):根目录格式4,非根目录格式5,两者都有primaryService/hasWeb;webBasePath仅格式5。旧工程同步镜像角色、Dockerfile、-serv包名与引用后重建,不手改清单。旧部署先核对项目名、卷和受管凭据,再建立完整基线;工具不跨项目迁移数据,改target目录不能完成迁移。
12
12
 
@@ -35,6 +35,8 @@ Podman 部署会主动执行容器已有的 healthcheck 并重新核对状态,
35
35
 
36
36
  ## 识别与逐项选择
37
37
 
38
+ 默认和自定义模式均从同后端的有效配置继续,不能按表单重建对象而丢掉未展示项。自建/云开通保留连接池、操作日志、公开端点/前缀、Redis 重试、向量检索、SMTP 发件人及 LDAP 属性映射,仅由实际服务定稿地址与认证;旧 URL、TLS/集群选择器不能覆盖新服务。切换后端清除不兼容字段。若旧向导已写出缺字段父 JSON,先从原配置/备份恢复最高优先级 `HAI_STORAGE` 的 `publicEndpoint` 等字段,再用修复版重建部署包;父 JSON 仍优先于 YAML 和叶变量,不自动猜测丢失值。
39
+
38
40
  框架 `HAI_*` 连接配置与镜像原生变量分开:PostgreSQL/MySQL/RustFS/MinIO/LDAP 的原生键必须按镜像契约命名,只写私有 `middleware-runtime.env`、只让中间件加载。不得改成镜像不识别的 HAI 前缀,也不得写回工程 `.env.<mode>` / 私有覆盖或注入应用 `.env.runtime`。应用的增量覆盖文件 `middleware.env` 只含 `HAI_*`。旧工程原生字段不自动删除,新应用环境忽略框架曾生成的已知原生键;不要批量过滤其他业务变量。
39
41
 
40
42
  数据库连接保存前复用所选后端的公开配置 Schema;MySQL `ssl` 仅 `false` 或严格对象,`{}` 默认验证证书链和 DNS 身份,`ca/cert/key` 为 PEM 内容且 `cert/key` 必须成对;私钥仅进入私有环境。PostgreSQL 保留其布尔值/字符串模式/对象契约。CLI 内联 `@h-ai/reldb/schemas` 与 Zod,无需为配置校验给目标应用额外安装数据库包或驱动;部署本身仍需已安装的 `@h-ai/deploy`,实际运行应用仍需其数据库依赖。
@@ -18,7 +18,7 @@
18
18
  - 使用 Node listener,或在满足包 Node 依赖的宿主/测试中注入标准 fetch handler
19
19
  - 自定义 `ServContext`(注入 session、tenant 等请求级数据)
20
20
  - 生成 OpenAPI 3.1 文档供外部工具消费
21
- - 通过 `config/_serv.yml` 管理 API 前缀、OpenAPI、docs、health、rpc 等 HTTP 挂载配置
21
+ - 通过 `config/_serv.yml` 管理 API 前缀、OpenAPI、docs、health 等 HTTP 挂载配置
22
22
  - 通过 `serv.createRuntimeSecurityPolicy(...)` 对生产 CORS Origin、原生 WebView Origin、Secure Cookie 与 API 文档暴露执行 fail-closed 策略
23
23
  - 启用传输加密:`serv.createApp({ transport: { crypto, serverKeyRing, keyStore } })`
24
24
  - 高级场景通过 `createApp({ middlewares })` 自定义 HTTP middleware,通过 `createContext` 注入请求级业务字段
@@ -276,7 +276,6 @@ http:
276
276
  health:
277
277
  path: /health
278
278
  readyPath: /ready
279
- rpc: false
280
279
 
281
280
  transport:
282
281
  keyExchangePath: /_hai/key-exchange
@@ -483,7 +482,7 @@ const app = serv.createApp({
483
482
  })
484
483
  ```
485
484
 
486
- 执行顺序为:`securityHeaders` → 内置 CORS 响应包装/握手和预检策略 → `transport`(若启用)/请求策略 → 普通 `middlewares` → health/refresh-cookie/OpenAPI/RPC/docs/oRPC routes。
485
+ 执行顺序为:`securityHeaders` → 内置 CORS 响应包装/握手和预检策略 → `transport`(若启用)/请求策略 → 普通 `middlewares` → health/refresh-cookie/OpenAPI/docs/oRPC routes。
487
486
 
488
487
  - 普通 `middlewares` 在解密和策略之后执行,提前响应仍受访问策略和响应加密约束。二进制端点显式加入 transport.excludePaths;内置 CORS 预检和密钥交换也执行策略。
489
488
  - 公开只读文件优先使用 `serv.storageAssets(...)`;应用仍须显式提供 key/MIME 白名单、缓存与跨域策略,框架不内置头像等业务概念。
@@ -549,7 +548,7 @@ HTTP 审计、限流、CORS、租户头校验等跨 route 能力继续放在
549
548
  | oRPC contract 输入 schema 校验失败(handler 之前) | 400 | 本地化失败体,`error.httpStatus=400` 与字段错误 |
550
549
  | handler 内 `serv.validateInputOrFail(...)` 失败 | 200 | 失败 HaiResult,`error.httpStatus=400` 与字段错误 |
551
550
 
552
- HTTP middleware、自定义 Response、refresh-cookie、OpenAPI/RPC 入口权限和 transport 协议错误分别按自身响应契约处理,可返回真实 HTTP 4xx/5xx。`@h-ai/api-client` 在真实 HTTP 401 或 HTTP 200 的有效失败 HaiResult(`success=false`、字符串 `error.code/message`、`error.httpStatus=401`)后自动刷新,成功后只重试一次;内置登录、注册和配置的刷新路径除外,403/500 不刷新。启用 transport 时刷新和重试复用加密链路,不能手写明文刷新请求。
551
+ HTTP middleware、自定义 Response、refresh-cookie、OpenAPI 入口权限和 transport 协议错误分别按自身响应契约处理,可返回真实 HTTP 4xx/5xx。`@h-ai/api-client` 在真实 HTTP 401 或 HTTP 200 的有效失败 HaiResult(`success=false`、字符串 `error.code/message`、`error.httpStatus=401`)后自动刷新,成功后只重试一次;内置登录、注册和配置的刷新路径除外,403/500 不刷新。启用 transport 时刷新和重试复用加密链路,不能手写明文刷新请求。
553
552
 
554
553
  SvelteKit 的 `kit.response.fromError` 根据 `error.httpStatus` 生成 HTTP Response;`kit.response.fromResult` 使用显式错误码映射,未命中默认 400。这些响应转换规则不能套用到 serv 普通 procedure。
555
554
 
@@ -584,7 +583,7 @@ const procedures = serv
584
583
 
585
584
  ### `serv.parseRequestContext` — 默认 Context 解析器
586
585
 
587
- 默认忽略转发头,缺少运行时对端时 IP 为 undefined。XFF 从右向左停在首个不可信地址,忽略左侧;可信链无效/过长时保留 IP 未知,不能回退为代理身份。Fetch 使用 `app.fetch(request, { remoteAddress: platformPeerAddress })`,对端必须来自可信平台 API。自定义 context 传递完整 input,保留已解析的 ip;内部 RPC 使用连接对端,转发头不能放宽来源限制。
586
+ 默认忽略转发头,缺少运行时对端时 IP 为 undefined。XFF 从右向左停在首个不可信地址,忽略左侧;可信链无效/过长时保留 IP 未知,不能回退为代理身份。Fetch 使用 `app.fetch(request, { remoteAddress: platformPeerAddress })`,对端必须来自可信平台 API。自定义 context 传递完整 input,保留已解析的 ip。
588
587
 
589
588
  从 HTTP 请求头自动解析:
590
589
 
@@ -615,8 +614,7 @@ const spec = await serv.generateSpec(contract, {
615
614
  | `apiPrefix` | `'/api/v1'` | oRPC OpenAPI handler 挂载前缀 |
616
615
  | `health` | `{ path: '/health', readyPath: '/ready' }` | 健康与就绪检查端点 |
617
616
  | `openapi` | `false` | OpenAPI JSON endpoint,显式开启 |
618
- | `docs` | `false` | Scalar 文档页,显式开启;启用后自动挂载 `/_hai/scalar.js` 本地脚本路由 |
619
- | `rpc` | `false` | 内部 RPC endpoint,显式开启;`loopback` / `private-network` 基于真实连接 IP,网关场景用 `gateway-only` |
617
+ | `docs` | `false` | Scalar 文档页,显式开启;在文档目录下挂载 `_hai/scalar.js`,页面使用相对脚本和 spec 地址;认证仍在后端执行 |
620
618
  | `transport` | `undefined` | 顶层配置;启用后默认挂载 `{apiPrefix}/_hai/key-exchange` |
621
619
 
622
620
  ```ts
@@ -627,7 +625,6 @@ const http: ServHttpConfigInput = {
627
625
  openapi: { path: '/openapi.json' },
628
626
  docs: { path: '/docs' },
629
627
  health: { path: '/health', readyPath: '/ready' },
630
- rpc: false,
631
628
  }
632
629
  ```
633
630