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

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 (254) hide show
  1. package/README.en.md +74 -154
  2. package/README.ja.md +74 -154
  3. package/README.md +74 -154
  4. package/dist/{chunk-AKV2CQZV.js → chunk-2ZL5ORQ2.js} +316 -97
  5. package/dist/chunk-2ZL5ORQ2.js.map +1 -0
  6. package/dist/{chunk-EF7WOFWZ.js → chunk-L53P43B2.js} +1312 -163
  7. package/dist/chunk-L53P43B2.js.map +1 -0
  8. package/dist/cli-config-templates-LWMD2I6V.js +5 -0
  9. package/dist/{cli-config-templates-HHFHNXBN.js.map → cli-config-templates-LWMD2I6V.js.map} +1 -1
  10. package/dist/{cli-skill-templates-PN4FLGBC.js → cli-skill-templates-D6S2OQ6X.js} +3 -3
  11. package/dist/{cli-skill-templates-PN4FLGBC.js.map → cli-skill-templates-D6S2OQ6X.js.map} +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js +30118 -3253
  14. package/dist/index.js.map +1 -1
  15. package/dist/metafile-esm.json +1 -1
  16. package/package.json +22 -18
  17. package/templates/README.md +45 -30
  18. package/templates/apps/admin/src/routes/+layout.svelte.hbs +16 -10
  19. package/templates/apps/admin/src/routes/+page.svelte.hbs +4 -4
  20. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +17 -7
  21. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +26 -6
  22. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +2 -2
  23. package/templates/apps/api/.dockerignore.hbs +10 -0
  24. package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +8 -0
  25. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +6 -1
  26. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +13 -5
  27. package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +13 -5
  28. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
  29. package/templates/apps/api/apps/{{projectName}}-serv/README.md.hbs +6 -2
  30. package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +24 -2
  31. package/templates/apps/api/apps/{{projectName}}-serv/package.json.hbs +4 -4
  32. package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +74 -24
  33. package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
  34. package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +153 -37
  35. package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +39 -13
  36. package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +106 -33
  37. package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +3 -1
  38. package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
  39. package/templates/apps/api/e2e/api-serv.spec.ts.hbs +20 -3
  40. package/templates/apps/api/e2e/capture-evidence.ts.hbs +4 -1
  41. package/templates/apps/api/eslint.config.js.hbs +3 -1
  42. package/templates/apps/api/images/serv.Dockerfile.hbs +15 -10
  43. package/templates/apps/api/playwright.config.ts.hbs +23 -19
  44. package/templates/apps/api/pnpm-workspace.yaml.hbs +27 -16
  45. package/templates/apps/fullstack/.dockerignore.hbs +10 -0
  46. package/templates/apps/fullstack/.gitignore.hbs +7 -2
  47. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +14 -12
  48. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +5 -3
  49. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +10 -2
  50. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +1 -1
  51. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +10 -2
  52. package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +0 -1
  53. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +0 -1
  54. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +4 -1
  55. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +16 -4
  56. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +10 -8
  57. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +3 -3
  58. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +8 -2
  59. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +0 -1
  60. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +0 -2
  61. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +4 -1
  62. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +16 -4
  63. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +2 -0
  64. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +9 -9
  65. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +10 -2
  66. package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +1 -0
  67. package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +0 -1
  68. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +0 -2
  69. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +4 -1
  70. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +19 -5
  71. package/templates/apps/fullstack/docs/security-configuration.md.hbs +4 -1
  72. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +140 -28
  73. package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +19 -5
  74. package/templates/apps/fullstack/eslint.config.js.hbs +3 -1
  75. package/templates/apps/fullstack/images/serv.Dockerfile.hbs +19 -11
  76. package/templates/apps/fullstack/images/web.Dockerfile.hbs +17 -8
  77. package/templates/apps/fullstack/package.json.hbs +2 -1
  78. package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +7 -5
  79. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +114 -23
  80. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +57 -11
  81. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
  82. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +17 -7
  83. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +13 -7
  84. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +17 -7
  85. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +10 -4
  86. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +65 -30
  87. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
  88. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +1 -2
  89. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +69 -21
  90. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +21 -5
  91. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +63 -11
  92. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +6 -1
  93. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +3 -1
  94. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +147 -33
  95. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +43 -12
  96. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +146 -30
  97. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +33 -10
  98. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +142 -26
  99. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +6 -2
  100. package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
  101. package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +48 -66
  102. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +1 -0
  103. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +1 -0
  104. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +1 -0
  105. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +9 -2
  106. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +0 -3
  107. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +15 -3
  108. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +33 -7
  109. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +16 -2
  110. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +104 -13
  111. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +37 -7
  112. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +9 -3
  113. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +25 -3
  114. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +133 -19
  115. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +14 -2
  116. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +66 -34
  117. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +132 -30
  118. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +8 -2
  119. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +23 -5
  120. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +143 -21
  121. package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -2
  122. package/templates/apps/fullstack/playwright.config.ts.hbs +25 -3
  123. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +30 -14
  124. package/templates/apps/h5/src/routes/+layout.svelte.hbs +74 -30
  125. package/templates/apps/h5/src/routes/+page.svelte.hbs +2 -2
  126. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +2 -2
  127. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +2 -2
  128. package/templates/apps/mobile-app/capacitor.config.ts.hbs +5 -2
  129. package/templates/apps/mobile-app/messages/en-US.json +2 -2
  130. package/templates/apps/mobile-app/messages/ja-JP.json +2 -2
  131. package/templates/apps/mobile-app/messages/zh-CN.json +2 -2
  132. package/templates/apps/mobile-app/src/App.svelte.hbs +17 -5
  133. package/templates/apps/mobile-app/src/lib/api.ts.hbs +20 -6
  134. package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +8 -1
  135. package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +6 -2
  136. package/templates/apps/mobile-app/src/lib/pages/profile.svelte.hbs +13 -1
  137. package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +5 -1
  138. package/templates/apps/website/scripts/static-website.mjs.hbs +19 -6
  139. package/templates/apps/website/src/routes/+layout.svelte.hbs +56 -29
  140. package/templates/apps/website/src/routes/+page.svelte.hbs +4 -4
  141. package/templates/apps/website/src/routes/about/+page.svelte.hbs +2 -2
  142. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +2 -2
  143. package/templates/apps/website/src/routes/services/+page.svelte.hbs +20 -5
  144. package/templates/base/.dockerignore.hbs +10 -0
  145. package/templates/base/.gitignore.hbs +7 -2
  146. package/templates/base/e2e/app.spec.ts.hbs +130 -36
  147. package/templates/base/eslint-rules.js +44 -25
  148. package/templates/base/eslint.config.js.hbs +3 -1
  149. package/templates/base/images/web.Dockerfile.hbs +25 -14
  150. package/templates/base/package.json.hbs +13 -7
  151. package/templates/base/patches/daisyui-5.7.50.patch +8 -0
  152. package/templates/base/patches/deepmerge-4.3.1.patch +51 -0
  153. package/templates/base/playwright.config.ts +3 -1
  154. package/templates/base/pnpm-workspace.yaml.hbs +33 -16
  155. package/templates/base/src/app.d.ts.hbs +1 -1
  156. package/templates/base/src/app.html.hbs +1 -0
  157. package/templates/base/src/hooks.server.ts.hbs +44 -33
  158. package/templates/base/src/lib/build-metadata.ts.hbs +0 -1
  159. package/templates/base/src/lib/server/init.ts.hbs +146 -35
  160. package/templates/base/src/lib/server/kit-config.ts.hbs +7 -4
  161. package/templates/base/src/routes/+layout.server.ts.hbs +2 -2
  162. package/templates/base/svelte.config.js.hbs +10 -100
  163. package/templates/base/tests/scaffold.test.ts.hbs +12 -3
  164. package/templates/base/tsconfig.json.hbs +7 -4
  165. package/templates/base/vite.config.ts.hbs +108 -14
  166. package/templates/base/vitest.config.ts.hbs +6 -2
  167. package/templates/features/ai/routes/api/chat/+server.ts +3 -1
  168. package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +3 -3
  169. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +3 -3
  170. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +3 -3
  171. package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +3 -3
  172. package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +3 -3
  173. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +3 -3
  174. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +3 -3
  175. package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +3 -3
  176. package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +3 -3
  177. package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +3 -3
  178. package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +3 -3
  179. package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +3 -3
  180. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +14 -3
  181. package/templates/shared/browser-check/startup.js +115 -0
  182. package/templates/shared/browser-check/update.css +37 -0
  183. package/templates/shared/browser-check/update.html +19 -0
  184. package/templates/shared/browser-startup.spec.ts +23 -0
  185. package/templates/shared/build-metadata.ts +18 -4
  186. package/templates/shared/e2e-env.ts +22 -6
  187. package/templates/shared/native-name.d.mts +5 -0
  188. package/templates/shared/native-name.mjs +94 -0
  189. package/templates/shared/public-base-path.mjs +17 -4
  190. package/templates/shared/run-e2e.mjs +46 -12
  191. package/templates/shared/run-node.mjs +56 -0
  192. package/templates/shared/run-tauri.mjs +74 -0
  193. package/templates/shared/vite-runtime-config.ts +9 -3
  194. package/templates/skills/AGENTS.md +10 -73
  195. package/templates/skills/bridges/admin/AGENTS.md +9 -65
  196. package/templates/skills/bridges/api/AGENTS.md +8 -59
  197. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +9 -54
  198. package/templates/skills/bridges/h5/AGENTS.md +8 -63
  199. package/templates/skills/bridges/mobile-app/AGENTS.md +8 -62
  200. package/templates/skills/bridges/website/AGENTS.md +8 -63
  201. package/templates/skills/hai-ai/SKILL.md +6 -2
  202. package/templates/skills/hai-ai/acp.md +153 -0
  203. package/templates/skills/hai-ai/guide.md +27 -12
  204. package/templates/skills/hai-ai/reference.md +24 -15
  205. package/templates/skills/hai-ai/resources.md +69 -0
  206. package/templates/skills/hai-api-client/SKILL.md +1 -1
  207. package/templates/skills/hai-api-client/reference.md +3 -1
  208. package/templates/skills/hai-app-create/collaboration.md +7 -0
  209. package/templates/skills/hai-app-create/development.md +19 -10
  210. package/templates/skills/hai-app-create/project.md +33 -0
  211. package/templates/skills/hai-app-create/reference.md +10 -10
  212. package/templates/skills/hai-app-tests/reference.md +1 -1
  213. package/templates/skills/hai-app-tests/validation.md +1 -0
  214. package/templates/skills/hai-build/SKILL.md +19 -9
  215. package/templates/skills/hai-build/paths.md +4 -2
  216. package/templates/skills/hai-build/reference.md +26 -8
  217. package/templates/skills/hai-cache/reference.md +6 -2
  218. package/templates/skills/hai-capacitor/SKILL.md +1 -0
  219. package/templates/skills/hai-capacitor/reference.md +24 -0
  220. package/templates/skills/hai-ci/SKILL.md +3 -0
  221. package/templates/skills/hai-core/SKILL.md +9 -4
  222. package/templates/skills/hai-core/reference.md +40 -10
  223. package/templates/skills/hai-core/request-access.md +2 -2
  224. package/templates/skills/hai-crypto/SKILL.md +2 -2
  225. package/templates/skills/hai-crypto/reference.md +7 -3
  226. package/templates/skills/hai-deploy/SKILL.md +41 -5
  227. package/templates/skills/hai-deploy/middleware.md +26 -14
  228. package/templates/skills/hai-framework-sync/SKILL.md +13 -9
  229. package/templates/skills/hai-framework-sync/sync.md +2 -0
  230. package/templates/skills/hai-iam/reference.md +2 -2
  231. package/templates/skills/hai-kit/SKILL.md +1 -1
  232. package/templates/skills/hai-kit/reference.md +19 -5
  233. package/templates/skills/hai-payment/reference.md +41 -17
  234. package/templates/skills/hai-reach/SKILL.md +3 -1
  235. package/templates/skills/hai-reach/reference.md +29 -9
  236. package/templates/skills/hai-reldb/SKILL.md +1 -1
  237. package/templates/skills/hai-reldb/reference.md +9 -2
  238. package/templates/skills/hai-scheduler/reference.md +1 -1
  239. package/templates/skills/hai-serv/SKILL.md +2 -1
  240. package/templates/skills/hai-serv/reference.md +26 -15
  241. package/templates/skills/hai-storage/reference.md +23 -6
  242. package/templates/skills/hai-ui/SKILL.md +11 -6
  243. package/templates/skills/hai-ui/charts.md +51 -0
  244. package/templates/skills/hai-ui/guide.md +1 -1
  245. package/templates/skills/hai-ui/reference.md +58 -38
  246. package/templates/skills/hai-vecdb/reference.md +8 -3
  247. package/dist/chunk-AKV2CQZV.js.map +0 -1
  248. package/dist/chunk-EF7WOFWZ.js.map +0 -1
  249. package/dist/chunk-MUHRBJSW.js +0 -29272
  250. package/dist/chunk-MUHRBJSW.js.map +0 -1
  251. package/dist/cli-config-templates-HHFHNXBN.js +0 -5
  252. package/dist/src-TEBHR5I5.js +0 -5
  253. package/dist/src-TEBHR5I5.js.map +0 -1
  254. package/templates/apps/fullstack/playwright.session-close.config.ts.hbs +0 -18
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@h-ai/cli",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.2",
4
+ "version": "1.0.0-beta.21",
5
5
  "description": "Hai Framework CLI for project scaffolding and code generation.",
6
6
  "license": "Apache-2.0",
7
7
  "keywords": [
@@ -30,36 +30,40 @@
30
30
  "node": "^22.23.4 || ^24.22.1 || ^26.12.1"
31
31
  },
32
32
  "dependencies": {
33
- "@h-ai/core": "1.0.0-beta.2",
34
- "cac": "^7.0.1",
33
+ "@h-ai/core": "1.0.0-beta.21",
34
+ "cac": "^7.1.0",
35
35
  "chalk": "^6.0.1",
36
36
  "fast-wrap-ansi": "^0.2.2",
37
37
  "fs-extra": "^11.4.1",
38
38
  "handlebars": "^4.7.10",
39
- "ora": "^9.4.1",
39
+ "ora": "^10.0.0",
40
40
  "prompts": "^2.4.2",
41
41
  "yaml": "^2.9.1"
42
42
  },
43
43
  "devDependencies": {
44
- "@h-ai/api-client": "1.0.0-beta.2",
45
- "@h-ai/cache": "1.0.0-beta.2",
46
- "@h-ai/crypto": "1.0.0-beta.2",
47
- "@h-ai/deploy": "1.0.0-beta.2",
48
- "@h-ai/feedback": "1.0.0-beta.2",
49
- "@h-ai/iam": "1.0.0-beta.2",
50
- "@h-ai/reach": "1.0.0-beta.2",
51
- "@h-ai/reldb": "1.0.0-beta.2",
52
- "@h-ai/storage": "1.0.0-beta.2",
44
+ "@h-ai/api-client": "1.0.0-beta.21",
45
+ "@h-ai/cache": "1.0.0-beta.21",
46
+ "@h-ai/crypto": "1.0.0-beta.21",
47
+ "@h-ai/deploy": "1.0.0-beta.21",
48
+ "@h-ai/feedback": "1.0.0-beta.21",
49
+ "@h-ai/iam": "1.0.0-beta.21",
50
+ "@h-ai/kit": "1.0.0-beta.21",
51
+ "@h-ai/payment": "1.0.0-beta.21",
52
+ "@h-ai/reach": "1.0.0-beta.21",
53
+ "@h-ai/reldb": "1.0.0-beta.21",
54
+ "@h-ai/storage": "1.0.0-beta.21",
55
+ "@h-ai/vecdb": "1.0.0-beta.21",
53
56
  "@types/fs-extra": "^11.0.4",
54
- "@types/node": "^26.6.5",
57
+ "@types/node": "^26.6.6",
55
58
  "@types/prompts": "^2.4.9",
56
59
  "altcha": "^3.5.0",
57
60
  "fast-string-width": "^3.0.2",
58
- "rimraf": "^6.1.3",
59
- "testcontainers": "^12.2.0",
60
- "tsup": "^8.5.1",
61
+ "rimraf": "^6.1.4",
62
+ "testcontainers": "^12.2.1",
63
+ "tsup": "^9.0.0",
61
64
  "typescript": "^6.0.3",
62
- "vitest": "^4.1.11"
65
+ "vitest": "^5.1.0",
66
+ "zod": "^4.6.7"
63
67
  },
64
68
  "scripts": {
65
69
  "build": "tsup",
@@ -1,55 +1,70 @@
1
1
  # CLI 项目模板
2
2
 
3
- ## 简介
3
+ 本目录供 `hai create/add/init` 组合应用源码、配置、脚本和AI指引;维护者在这里修改生成源,接入应用使用生成后的工程。模板不承担应用自身的业务授权和数据恢复。
4
4
 
5
- 这里保存 `hai create` 生成应用时使用的源码、配置和 AI 指引。维护模板后,需要生成真实项目验证,不能只检查模板文件本身。
5
+ ## 快速开始
6
6
 
7
- ## 核心功能清单
7
+ 在框架根构建CLI,再生成独立工程检查模板效果:
8
8
 
9
- - `admin`、`website`、`h5`:SvelteKit 应用。
10
- - `api`:共享 contract 与 API service 的 workspace。
11
- - `mobile-app`:Svelte + Vite + Capacitor 应用。
12
- - `fullstack`:contract、API、共享界面,以及按需选择的 Web/App/Desktop;miniapp 仅预留说明。
13
- - 后台工作区随窗口扩展;手机壳支持宽屏,表格在内部滚动,文章与认证表单保留阅读宽度。
14
- - 默认部署工具、独立镜像 Dockerfile、环境示例和可复制的 AI 技能。
9
+ ```sh
10
+ pnpm --filter @h-ai/cli build
11
+ node packages/cli/dist/index.js create ../template-probe --type website --defaults --no-install --no-git
12
+ ```
15
13
 
16
- ## 使用入门
14
+ 输入模板种类与工程名,输出新目录中的源码、README、配置、Dockerfile及适用技能。随后在该工程安装并验证;仅检查 `.hbs` 语法不能证明生成结果能运行。
15
+
16
+ ## 功能
17
17
 
18
18
  ### 文件如何组合
19
19
 
20
- | 目录 | 用途 |
21
- | -------------- | ------------------------------------------------------------------- |
22
- | `base/` | 普通应用共用的配置、脚本和入口 |
23
- | `apps/<类型>/` | 应用专属页面、workspace、原生壳与配置;API/fullstack 维护自己的骨架 |
24
- | `features/` | 按所选模块叠加的路由和页面 |
25
- | `i18n/` | Paraglide 工程配置 |
26
- | `skills/` | 完整的技能目录与各类型 AI 入口 |
20
+ | 目录 | 场景、输入与输出 |
21
+ | ------------------- | ------------------------------------------------------------------------------------- |
22
+ | base/ | 普通应用共享基础;输入渲染上下文,输出配置、脚本和入口 |
23
+ | apps/ | 按admin/website/h5/api/mobile-app/fullstack选择骨架;API/fullstack有独立workspace结构 |
24
+ | features/ | 叠加实际模块所需路由与页面;不把Serv套成SvelteKit文件路由 |
25
+ | i18n/ | 生成Paraglide工程与应用消息;默认中英日文 |
26
+ | shared/ | 原生显示名、Tauri入口及跨模板文件约定,避免各模板复制不同规则 |
27
+ | skills/ 与 bridges/ | 输出完整 `.agents/skills/` 及根AGENTS入口,工具配置只桥接共享规则 |
28
+
29
+ 普通文件复制,`.hbs` 由Handlebars渲染并去后缀。`cli-template-engine.ts` 选择目录/条件,`cli-create.ts` 编排配置、镜像与README生成。例如website输出Core/Kit/UI展示站,fullstack输出contract、Serv、共享UI及所选Web/App/Desktop;miniapp仅为预留说明。
30
+
31
+ ### 生成上下文与配置
32
+
33
+ 上下文含 `projectName/appType/features/hasUi/hasI18n/versions` 和 `api/fullstack` 形状,定义见[CLI类型](../src/cli-types.ts)。模块YAML使用 `moduleConfig` helper,字段和默认值由[配置生成器](../src/commands/cli-config-templates.ts)共同维护。
34
+
35
+ 输入启用模块后,输出对应依赖、有效配置及公共环境默认;未使用模块保留注释示例。新功能仍须接入校验、初始化、关闭和业务路由,不能仅取消YAML注释。`hai add/init` 补缺失项并保留自定义文件。
36
+
37
+ ### 构建、原生名称与部署
38
+
39
+ 部署工具默认是开发依赖,`--no-deploy` 可省略。`hai.json.build.images` 指向images内独立Dockerfile,Web资源在images/web。构建器生成images/dependencies,根gitignore忽略该缓存、运行数据和私有环境。
40
+
41
+ Dockerfile使用全局HAI_NODE_IMAGE/HAI_NGINX_IMAGE及构建阶段HAI_NPM_REGISTRY接收下载设置,代理只用于构建,不进入运行镜像。pnpm下载采用追加日志,Windows转发保留警告、错误和统一换行。[下载源契约](skills/hai-build/reference.md#下载源与代理)
27
42
 
28
- 普通文件直接复制,`.hbs` 经 Handlebars 渲染并去掉后缀。`cli-template-engine.ts` 决定适用目录与条件;`cli-create.ts` 完成配置、镜像定义和根 README 等生成工作。修改前先查实际调用路径,API/fullstack 不套用 SvelteKit 文件路由。
43
+ 产物使用工程标识,批次名为 `build-<工程>-<目标>-YYYYMMDD-HHmmss-<随机串>-<版本>`,latest保存相对批次名。输入一个Core展示名后,Capacitor的appName和Tauri产品/主窗口名使用该值;Fullstack读取Serv的Core,独立mobile读取自身Core。只投影名称,不下发完整配置。辅助窗口及后续显式Tauri配置保持自身优先级。[名称与构建](../../../docs/usage/getting-started/build.md#原生应用名称)
29
44
 
30
- ### 配置与构建
45
+ ### 服务端边界与页面
31
46
 
32
- 模板通过 `projectName`、`appType`、`features`、`hasUi`、`hasI18n`、`versions` 以及 `api`/`fullstack` 上下文渲染,完整字段见 [cli-types.ts](../src/cli-types.ts)。模块 YAML 使用 `moduleConfig` helper,与 [配置生成器](../src/commands/cli-config-templates.ts) 共用字段和默认值。
47
+ SvelteKit服务端固定加载Kit配置,根load只投影公开transport。选择crypto后,hooks从私有环境装配密钥环和registry;共享DB用于共享registry,内存仅开发/测试。纯客户端不生成服务端私钥。输入冲突路径策略或缺少required加密依赖时,创建宿主应失败。
33
48
 
34
- 部署默认启用,`--no-deploy` 可关闭;SDK 是开发依赖。每个镜像使用 `images/` 中独立 Dockerfile,Web 资源放 `images/web/`。`hai.json` 的 `build.images` 选择文件,`deploy` 保存项目级部署参数;依赖输入由构建器生成到 `images/dependencies/`。所有根 `.gitignore` 均忽略 `**/images/dependencies/`、运行数据和私有环境文件。
49
+ 页面文字走应用messages,认证复用AuthPanel及公开IAM配置,表单使用Form/FormLayout/FormField。输入无效表单时保留草稿、显示安全Toast和可访问错误关联;默认角色、流程和限额由业务决定,并在服务端授权。宽屏工作区可扩展,窄屏表格内部滚动,阅读内容保留合适宽度。
35
50
 
36
- Fullstack 服务端保留各模块的配置示例,未使用模块保持注释。安装依赖、校验和初始化、接入业务后才启用对应配置。修改公开 Schema 时同步配置生成器、环境变量说明、调用方与技能。
51
+ ### AI指引
37
52
 
38
- SvelteKit 的 `kit-config.ts` 在服务端读取并固定 `_kit.yml`,根 load 只投影公开 transport;选择 crypto 后,hooks 装配环境密钥环和 registry,布局安装浏览器传输。db 提供共享 registry,无 db 仅限开发/测试。路径规则可配置 IP、时段与 required/disabled 加密,规则冲突须在装配时失败。调整时同步三种 SSR 布局、服务端入口、私钥生成边界和实际生成工程的根/子目录门禁;纯客户端工程不生成服务端私钥。
53
+ 复制skill完整目录及其相对参考文件,并按应用架构排除不适用能力;引用不得回到框架私有目录。输入website或fullstack两种架构时,输出应各自形成可独立使用的引用闭包。Claude/Copilot/OpenCode仅引用AGENTS和共享规范,不复制长正文。调整公共契约时同步实现、配置、示例、调用方与skills。
39
54
 
40
- ### AI 指引
55
+ ## 配置
41
56
 
42
- `skills/hai-*` 的完整目录复制到生成应用 `.agents/skills/`,按应用架构排除不适用项。`bridges/<类型>/AGENTS.md` 提供根入口;Claude/Copilot/OpenCode 配置只引用共享规则。新增参考文件必须随 skill 一起复制,不能链接回框架私有路径。
57
+ 模板参数在生成阶段消费,生成应用通过自身 `config/`、环境与宿主参数配置运行。环境公共值与私有秘密分开,版本固定到CLI对应框架发布;pnpm补丁注册必须连同实际patch文件复制。[应用配置手册](../../../docs/usage/configuration/README.md)
43
58
 
44
- `hai add` / `hai init` 补齐缺失文件,保留应用已有的自定义内容。框架升级时按目标发布版本比较并合并,不直接覆盖应用规则。
59
+ 维护 `shared/.gitattributes`,使Dockerfile、dockerignore和POSIX脚本输出LF。原生工程名、API公开地址、网站basepath与服务器私密配置职责独立,不将完整服务端配置投影到浏览器或原生打包工具。
45
60
 
46
- ### 页面与文案
61
+ ## 错误处理
47
62
 
48
- 用户可见文本加入对应 messages。认证复用 AuthPanel 与服务端公开 IAM 配置;表单复用 Form/FormLayout/FormField。业务规则由应用需求决定,模板默认角色、流程和限额可调整,修改时同步授权、界面、测试和文档。
63
+ 模板渲染失败应指出文件/步骤并停止,不以部分产物当成功。生成后的校验或构建失败回到所属模板修复,不能只手工修一份测试工程。私钥、凭据和完整用户数据不进入错误正文。缺失依赖、非法路径、引用不完整和不支持的架构组合要明确拒绝。
49
64
 
50
65
  ## 开发测试
51
66
 
52
- 维护模板时保留 `shared/.gitattributes`,让生成工程的 `.dockerignore`、Dockerfile 和 POSIX 脚本统一使用 LF,保持跨平台输入一致并确保 Linux 脚本可运行。在仓库根执行:
67
+ 在仓库根按实际影响选择:
53
68
 
54
69
  ```sh
55
70
  pnpm --filter @h-ai/cli typecheck
@@ -61,7 +76,7 @@ pnpm --filter @h-ai/cli test:scaffold-gates
61
76
  pnpm --filter @h-ai/cli test:deploy-gates
62
77
  ```
63
78
 
64
- 脚手架门禁会生成项目并执行安装、类型检查、lint、构建、测试和浏览器流程。部署门禁另需可用 Podman/Docker,验证镜像构建、隔离服务器上的 SSH/人工部署与部分更新。原生安装包和真实第三方服务需要各自的验收环境。
79
+ 脚手架门禁真实安装、类型/lint、构建、测试和浏览器流程;部署门禁需可用Podman/Docker,并验证实际镜像、SSH/手工适用及部分更新。原生设备和第三方线上服务另需对应环境。仅文案改动不代表重跑过所有运行场景。
65
80
 
66
81
  ## 许可证
67
82
 
@@ -4,18 +4,15 @@
4
4
  * 管理后台根布局
5
5
  */
6
6
  import type { Snippet } from 'svelte'
7
- import { browser } from '$app/environment'
7
+ import { browser } from '$app/env'
8
8
  {{#if features.iam}}
9
- import { base } from '$app/paths'
9
+ import { resolve } from '$app/paths'
10
10
  {{else}}
11
11
  {{#if features.crypto}}
12
- import { base } from '$app/paths'
12
+ import { resolve } from '$app/paths'
13
13
  {{/if}}
14
14
  {{/if}}
15
15
  import { page } from '$app/state'
16
- {{#if hasI18n}}
17
- import { getLocale, setLocale } from '$lib/paraglide/runtime.js'
18
- {{/if}}
19
16
  {{#if features.crypto}}
20
17
  import { crypto } from '@h-ai/crypto'
21
18
  import { kit } from '@h-ai/kit'
@@ -31,6 +28,9 @@
31
28
  {{/if}}
32
29
  {{#if features.crypto}}
33
30
  import { untrack } from 'svelte'
31
+ {{/if}}
32
+ {{#if hasI18n}}
33
+ import { getLocale, setLocale } from '#lib/paraglide/runtime.js'
34
34
  {{/if}}
35
35
  import '../app.css'
36
36
 
@@ -40,10 +40,16 @@
40
40
 
41
41
  const { children }: Props = $props()
42
42
  {{#if features.crypto}}
43
- if (browser)
44
- kit.client.installBrowserTransport(untrack(() => page.data.kitConfig), { crypto, basePath: base })
43
+ if (browser) {
44
+ kit.client.installBrowserTransport(untrack(() => page.data.kitConfig), {
45
+ crypto,
46
+ basePath: resolve('/').replace(/\/$/, ''),
47
+ })
48
+ }
45
49
  {{/if}}
46
- const initialTheme = browser ? getSavedTheme() : 'light'
50
+ const initialTheme = browser
51
+ ? getSavedTheme()
52
+ : 'light'
47
53
  let currentTheme = $state(initialTheme)
48
54
  if (browser)
49
55
  applyTheme(initialTheme, false)
@@ -52,7 +58,7 @@
52
58
  applyTheme(theme)
53
59
  }
54
60
  {{#if features.iam}}
55
- const authActions = kit.client.createAuthActions({ basePath: `${base}/api/auth` })
61
+ const authActions = kit.client.createAuthActions({ basePath: `${resolve('/').replace(/\/$/, '')}/api/auth` })
56
62
  $effect(() => authActions.bindPageExit({ enabled: page.data.iamPublicConfig?.session.endOnPageHide }))
57
63
  {{/if}}
58
64
  {{#if hasI18n}}
@@ -5,10 +5,10 @@
5
5
  */
6
6
  import { resolve } from '$app/paths'
7
7
  import { page } from '$app/state'
8
+ import { Badge, Card } from '@h-ai/ui'
8
9
  {{#if hasI18n}}
9
- import * as m from '$lib/paraglide/messages'
10
+ import * as m from '#lib/paraglide/messages.js'
10
11
  {{/if}}
11
- import { Badge, Card } from '@h-ai/ui'
12
12
  </script>
13
13
 
14
14
  <svelte:head>
@@ -31,7 +31,7 @@
31
31
  <h1 class='mt-4 text-4xl font-black tracking-tight'>{page.data.appConfig.name}</h1>
32
32
  <p class='mt-3 text-base-content/60'>{m.page_home_subtitle()}</p>
33
33
  <div class='mt-8 flex flex-wrap gap-3 justify-center'>
34
- <a href={resolve('/admin', {})} class='btn btn-primary'>
34
+ <a href={resolve('admin')} class='btn btn-primary'>
35
35
  <span class='icon-[tabler--layout-dashboard] size-5'></span>
36
36
  {m.nav_admin()}
37
37
  </a>
@@ -46,7 +46,7 @@
46
46
  <h1 class='mt-4 text-4xl font-black tracking-tight'>{page.data.appConfig.name}</h1>
47
47
  <p class='mt-3 text-base-content/60'>基于 hai Agent Framework 构建</p>
48
48
  <div class='mt-8 flex flex-wrap gap-3 justify-center'>
49
- <a href={resolve('/admin', {})} class='btn btn-primary'>
49
+ <a href={resolve('admin')} class='btn btn-primary'>
50
50
  <span class='icon-[tabler--layout-dashboard] size-5'></span>
51
51
  进入后台
52
52
  </a>
@@ -6,10 +6,10 @@
6
6
  import type { Snippet } from 'svelte'
7
7
  import { resolve } from '$app/paths'
8
8
  import { page } from '$app/state'
9
+ import { WorkspaceLayout } from '@h-ai/ui'
9
10
  {{#if hasI18n}}
10
- import * as m from '$lib/paraglide/messages'
11
+ import * as m from '#lib/paraglide/messages.js'
11
12
  {{/if}}
12
- import { WorkspaceLayout } from '@h-ai/ui'
13
13
 
14
14
  interface Props {
15
15
  children: Snippet
@@ -31,11 +31,19 @@
31
31
 
32
32
  const navItems = $derived([
33
33
  {{#if hasI18n}}
34
- { path: '/admin', label: m.nav_dashboard(), icon: 'icon-[tabler--layout-dashboard]' },
35
- { path: '/admin/settings', label: m.nav_settings(), icon: 'icon-[tabler--settings]' },
34
+ {
35
+ path: resolve('admin'),
36
+ label: m.nav_dashboard(),
37
+ icon: 'icon-[tabler--layout-dashboard]',
38
+ },
39
+ {
40
+ path: resolve('admin/settings'),
41
+ label: m.nav_settings(),
42
+ icon: 'icon-[tabler--settings]',
43
+ },
36
44
  {{else}}
37
- { path: '/admin', label: '仪表盘', icon: 'icon-[tabler--layout-dashboard]' },
38
- { path: '/admin/settings', label: '设置', icon: 'icon-[tabler--settings]' },
45
+ { path: resolve('admin'), label: '仪表盘', icon: 'icon-[tabler--layout-dashboard]' },
46
+ { path: resolve('admin/settings'), label: '设置', icon: 'icon-[tabler--settings]' },
39
47
  {{/if}}
40
48
  ] as const)
41
49
  </script>
@@ -64,10 +72,12 @@
64
72
  <ul class='gap-1'>
65
73
  {#each navItems as item (item.path)}
66
74
  <li>
67
- <a href={resolve(item.path, {})} class:menu-active={page.url.pathname === resolve(item.path, {})} onclick={closeDrawer}>
75
+ <!-- eslint-disable svelte/no-navigation-without-resolve -- 菜单字段已由 resolve 生成完整挂载地址;规则无法追踪派生/筛选后的集合,不能二次添加前缀。 -->
76
+ <a href={item.path} class:menu-active={page.url.pathname === item.path} onclick={closeDrawer}>
68
77
  <span class='{item.icon} size-5'></span>
69
78
  {item.label}
70
79
  </a>
80
+ <!-- eslint-enable svelte/no-navigation-without-resolve -->
71
81
  </li>
72
82
  {/each}
73
83
  </ul>
@@ -3,17 +3,37 @@
3
3
  /**
4
4
  * 仪表盘页面
5
5
  */
6
+ import { Card, PageHeader } from '@h-ai/ui'
6
7
  {{#if hasI18n}}
7
- import * as m from '$lib/paraglide/messages'
8
+ import * as m from '#lib/paraglide/messages.js'
8
9
  {{/if}}
9
- import { Card, PageHeader } from '@h-ai/ui'
10
10
  {{#if hasI18n}}
11
11
 
12
12
  const stats = $derived([
13
- { label: m.page_dashboard_total_users(), value: '0', icon: 'icon-[tabler--users]', accent: 'text-primary' },
14
- { label: m.page_dashboard_today_active(), value: '0', icon: 'icon-[tabler--activity]', accent: 'text-success' },
15
- { label: m.page_dashboard_revenue(), value: '¥0', icon: 'icon-[tabler--coin]', accent: 'text-warning' },
16
- { label: m.page_dashboard_orders(), value: '0', icon: 'icon-[tabler--shopping-cart]', accent: 'text-info' },
13
+ {
14
+ label: m.page_dashboard_total_users(),
15
+ value: '0',
16
+ icon: 'icon-[tabler--users]',
17
+ accent: 'text-primary',
18
+ },
19
+ {
20
+ label: m.page_dashboard_today_active(),
21
+ value: '0',
22
+ icon: 'icon-[tabler--activity]',
23
+ accent: 'text-success',
24
+ },
25
+ {
26
+ label: m.page_dashboard_revenue(),
27
+ value: '¥0',
28
+ icon: 'icon-[tabler--coin]',
29
+ accent: 'text-warning',
30
+ },
31
+ {
32
+ label: m.page_dashboard_orders(),
33
+ value: '0',
34
+ icon: 'icon-[tabler--shopping-cart]',
35
+ accent: 'text-info',
36
+ },
17
37
  ])
18
38
  {{else}}
19
39
  const stats = [
@@ -3,10 +3,10 @@
3
3
  /**
4
4
  * 设置页面
5
5
  */
6
+ import { Card, PageHeader } from '@h-ai/ui'
6
7
  {{#if hasI18n}}
7
- import * as m from '$lib/paraglide/messages'
8
+ import * as m from '#lib/paraglide/messages.js'
8
9
  {{/if}}
9
- import { Card, PageHeader } from '@h-ai/ui'
10
10
  </script>
11
11
 
12
12
  <svelte:head>
@@ -23,3 +23,13 @@ tmp
23
23
  # 仅保留公共基础 .env;分环境配置、私有覆盖及已有交付包不进入构建上下文。
24
24
  **/.env.*
25
25
  **/.hai
26
+ # 部署证书和测试材料不进入镜像构建上下文。
27
+ **/*.pem
28
+ **/*.key
29
+ **/*.p12
30
+ **/*.pfx
31
+ **/tests
32
+ **/e2e
33
+ **/*.test.*
34
+ **/*.spec.*
35
+ docs
@@ -14,6 +14,14 @@
14
14
 
15
15
  ### 包含内容
16
16
 
17
+ 输入输出约定由Schema共享,客户端先检查 `success` 再取 `data`:
18
+
19
+ | 功能 | 输入示例 | 成功输出与边界 |
20
+ | --- | --- | --- |
21
+ | app.info | 无业务参数 | name/version/env/defaultLocale/uptimeMs/transportEnabled;只返回公开元信息 |
22
+ | app.echo | `{ message: 'hello' }`,1–2000字符 | 同一message及requestId/timestamp,可含userId;演示回显,不写业务数据 |
23
+ | 工程contract | 聚合应用与已启用模块契约 | Serv与typed client使用同一输入/输出类型;声明不替代服务端授权 |
24
+
17
25
  - `app-contract.ts`:应用级接口定义,业务 path 与一次性输出 Schema 就近内联
18
26
  - `app-schemas.ts`:跨接口、跨层复用的输入/数据 Zod Schema
19
27
  - `{{projectName}}-contract.ts`:工程级 contract 聚合入口
@@ -4,7 +4,12 @@ import { z } from 'zod'
4
4
  export const AppInfoOutputDataSchema = z.object({
5
5
  name: z.string(),
6
6
  version: z.string(),
7
- env: z.enum(['development', 'production', 'test', 'staging']),
7
+ env: z.enum([
8
+ 'development',
9
+ 'production',
10
+ 'test',
11
+ 'staging',
12
+ ]),
8
13
  defaultLocale: z.string(),
9
14
  uptimeMs: z.number().int().nonnegative(),
10
15
  transportEnabled: z.boolean(),
@@ -5,11 +5,19 @@ import { appContract } from './app-contract.js'
5
5
 
6
6
  /** 工程级应用 contract。 */
7
7
  export const {{api.contractExportName}} = apiContract.create({
8
- {{#if features.iam}} iam: apiContract.iam,
9
- {{/if}}{{#if features.storage}} storage: apiContract.storage,
10
- {{/if}}{{#if features.ai}} ai: apiContract.ai,
11
- {{/if}}{{#if features.feedback}} feedback: apiContract.feedback,
12
- {{/if}} // @hai-generator:contracts:entries
8
+ {{#if features.iam}}
9
+ iam: apiContract.iam,
10
+ {{/if}}
11
+ {{#if features.storage}}
12
+ storage: apiContract.storage,
13
+ {{/if}}
14
+ {{#if features.ai}}
15
+ ai: apiContract.ai,
16
+ {{/if}}
17
+ {{#if features.feedback}}
18
+ feedback: apiContract.feedback,
19
+ {{/if}}
20
+ // @hai-generator:contracts:entries
13
21
  app: appContract,
14
22
  })
15
23
 
@@ -5,14 +5,22 @@ describe('{{api.contractPackageName}}', () => {
5
5
  it('includes generated contract routes', () => {
6
6
  expect({{api.contractExportName}}.app.info).toBeDefined()
7
7
  expect({{api.contractExportName}}.app.echo).toBeDefined()
8
- {{#if features.iam}} expect({{api.contractExportName}}.iam.auth.login).toBeDefined()
9
- {{/if}}{{#if features.storage}} expect({{api.contractExportName}}.storage.presignedUrls.createUpload).toBeDefined()
10
- {{/if}}{{#if features.ai}} expect({{api.contractExportName}}.ai.chats.createCompletion).toBeDefined()
11
- {{/if}} })
8
+ {{#if features.iam}}
9
+ expect({{api.contractExportName}}.iam.auth.login).toBeDefined()
10
+ {{/if}}
11
+ {{#if features.storage}}
12
+ expect({{api.contractExportName}}.storage.presignedUrls.createUpload).toBeDefined()
13
+ {{/if}}
14
+ {{#if features.ai}}
15
+ expect({{api.contractExportName}}.ai.chats.createCompletion).toBeDefined()
16
+ {{/if}}
17
+ })
12
18
 
13
19
  it('validates app.echo input length', () => {
14
20
  expect(AppEchoInputSchema.safeParse({ message: 'hello' }).success).toBe(true)
15
21
  expect(AppEchoInputSchema.safeParse({ message: '' }).success).toBe(false)
16
- expect(AppEchoInputSchema.safeParse({ message: 'x'.repeat(2001) }).success).toBe(false)
22
+ expect(AppEchoInputSchema.safeParse({
23
+ message: 'x'.repeat(2001),
24
+ }).success).toBe(false)
17
25
  })
18
26
  })
@@ -6,6 +6,8 @@ export default defineConfig({
6
6
  target: 'node22',
7
7
  sourcemap: true,
8
8
  clean: true,
9
- dts: { compilerOptions: { ignoreDeprecations: '6.0' } },
9
+ dts: {
10
+ compilerOptions: { ignoreDeprecations: '6.0' },
11
+ },
10
12
  external: ['@h-ai/api-contract', 'zod'],
11
13
  })
@@ -19,15 +19,19 @@ pnpm --filter {{api.servPackageName}} dev
19
19
  pnpm --filter {{api.servPackageName}} test
20
20
  ```
21
21
 
22
+ 启动读取本服务配置并校验依赖。默认健康入口 `GET /health` 返回可达状态,`POST /api/v1/app/info` 返回公开服务信息;路径按 `_serv.yml` 调整。`app.echo` 输入 `{ message: 'hello' }`,成功输出相同message、请求编号和时间;按已装配客户端/传输协议调用,不把curl明文当启用加密后的通用调用方式。启用的认证/反馈/存储等模块按根目录及对应skill接入。
23
+
22
24
  ### 容器运行
23
25
 
24
26
 
25
- - 配置默认打包自本目录 `config/`,可在运行时只读挂载到 `/app/config`,敏感值通过环境变量注入。
27
+ - YAML配置默认打包自本目录 `config/`,镜像内位于 `/app/config`;SDK部署的私有 `.env.runtime` 另通过 `/run/hai/config` 只读挂载并在启动时读取。修改普通运行配置后重启,端口/网关/挂载变化需重新部署。
28
+ {{#if features.iam}}- 受控内网或 VPN 的生产 HTTP 入口可设置 `HAI_SERV_REFRESH_COOKIE_SECURE=false` 和实际 `HAI_SERV_CORS_ORIGIN`,重新部署后端后重新登录。刷新凭据会经 HTTP 明文传输。
29
+ {{/if}}
26
30
 
27
31
 
28
32
  ### 关键目录
29
33
 
30
- {{#if features.crypto}}启用 transport 时,`serverKeyRing` 与客户端 `keyStore` 都必须显式提供。CLI 在本服务 `.env.dev/.env.test/.env.prod` 中分别生成独立 ring,提交环境文件后克隆用户可共享,变量为 `HAI_CRYPTO_TRANSPORT_SERVERKEYRING`;运行时不生成密钥。部署直接复用所选环境文件的 ring,或由 Secret Manager 向所有节点分发相同受管 ring,配合共享数据库 registry。公钥/版本参与协商,私钥不进入普通 YAML、PUBLIC_/VITE_、日志或公开响应。轮换先分发新旧版本再切 activeKeyId,过渡期后撤销旧 ID;无需会话粘性。
34
+ {{#if features.crypto}}启用 transport 时,`serverKeyRing` 与客户端 `keyStore` 都必须显式提供。CLI 在本服务 `.env.dev.local/.env.test.local/.env.prod.local` 中分别生成独立 ring,私有文件不提交 Git,克隆后通过受保护配置或 Secret Manager 分发,变量为 `HAI_CRYPTO_TRANSPORT_SERVERKEYRING`;运行时不生成密钥。部署直接复用所选环境文件的 ring,或由 Secret Manager 向所有节点分发相同受管 ring,配合共享数据库 registry。公钥/版本参与协商,私钥不进入普通 YAML、PUBLIC_/VITE_、日志或公开响应。轮换先分发新旧版本再切 activeKeyId,过渡期后撤销旧 ID;无需会话粘性。
31
35
  {{#unless features.db}}本模板未选择 db,registry 仅在 development/test 显式使用内存;production/staging 会拒绝启动 transport。选择 db 并配置共享数据库后再部署,或显式关闭 transport。
32
36
  {{/unless}}{{/if}}
33
37
 
@@ -7,19 +7,33 @@ server:
7
7
  port: 3000
8
8
 
9
9
  http:
10
+ # auto 仅在受管私有 Compose 代理中采用容器网段;普通宿主忽略转发头。
11
+ trustedProxies: auto
12
+ access: false
13
+ # 独立文件与下方内联规则二选一,用所选配置块替换 access: false。
14
+ # access:
15
+ # file: ./config/security/request-access.yml
16
+ # access:
17
+ # global:
18
+ # timezone: UTC # 可用 HAI_SERV_HTTP_ACCESS_GLOBAL_TIMEZONE=Asia/Shanghai
19
+ # allowIps: []
20
+ # denyIps: []
21
+ # windows: []
22
+ # rules: []
10
23
  apiPrefix: /api/v1
11
24
  openapi:
12
25
  path: /openapi.json
26
+ # HAI_SERV_HTTP_DOCS=false 关闭文档;开启时再配置 path/requireAuth。
13
27
  docs:
14
28
  path: /docs
29
+ # requireAuth: true
15
30
  health:
16
31
  path: /health
17
32
  readyPath: /ready
18
- rpc: false
19
33
 
20
34
  cors:
21
35
  origin: ${HAI_SERV_CORS_ORIGIN:*}
22
- nativeOrigins: ${HAI_SERV_CORS_NATIVEORIGINS:http://localhost,https://tauri.localhost,tauri://localhost,capacitor://localhost}
36
+ nativeOrigins: ${HAI_SERV_CORS_NATIVEORIGINS:http://localhost,https://localhost,http://tauri.localhost,https://tauri.localhost,tauri://localhost,capacitor://localhost}
23
37
  {{#if features.iam}} credentials: ${HAI_SERV_CORS_CREDENTIALS:true}
24
38
  {{else}} credentials: ${HAI_SERV_CORS_CREDENTIALS:false}
25
39
  {{/if}} allowedHeaders:
@@ -43,6 +57,14 @@ cors:
43
57
  {{else}}
44
58
  maxPlaintextBytes: ${HAI_SERV_TRANSPORT_MAXPLAINTEXTBYTES:1048576}
45
59
  {{/if}}
60
+ # 传输时钟窗口,单位秒;允许领先 0~300 秒,请求有效期 1~600 秒。
61
+ maxFutureSkewSeconds: ${HAI_SERV_TRANSPORT_MAXFUTURESKEWSECONDS:30}
62
+ maxRequestAgeSeconds: ${HAI_SERV_TRANSPORT_MAXREQUESTAGESECONDS:300}
63
+ # HAI_SERV_TRANSPORT_ROUTEPLAINTEXTBYTES 可填 JSON 路径映射。
64
+ routePlaintextBytes: {}
65
+ # 单条路径需要更大请求体时填写字节数,* 只匹配一段路径。
66
+ # routePlaintextBytes:
67
+ # /api/v1/uploads/*: 8388608
46
68
  keyExchangePath: /_hai/key-exchange
47
69
  excludePaths:
48
70
  - /health
@@ -28,11 +28,11 @@
28
28
  "test": "vitest run",
29
29
  "test:watch": "vitest",
30
30
  "clean": "rimraf dist .turbo",
31
- "dev": "pnpm build && node --env-file=.env --env-file=.env.dev --env-file-if-exists=.env.local dist/index.js",
32
- "start": "node --env-file=.env --env-file=.env.prod --env-file-if-exists=.env.local dist/index.js",
33
- "dev:test": "pnpm build && node --env-file=.env --env-file=.env.test --env-file-if-exists=.env.local dist/index.js",
31
+ "dev": "pnpm build && node ../../scripts/run-node.mjs dev . dist/index.js",
32
+ "start": "node ../../scripts/run-node.mjs prod . dist/index.js",
33
+ "dev:test": "pnpm build && node ../../scripts/run-node.mjs test . dist/index.js",
34
34
  "dev:prod": "pnpm build && pnpm start",
35
- "start:test": "node --env-file=.env --env-file=.env.test --env-file-if-exists=.env.local dist/index.js",
35
+ "start:test": "node ../../scripts/run-node.mjs test . dist/index.js",
36
36
  "start:prod": "pnpm start"
37
37
  },
38
38
  "dependencies": {