@h-ai/cli 1.0.0-beta.18 → 1.0.0-beta.19

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 (194) hide show
  1. package/README.en.md +4 -0
  2. package/README.ja.md +4 -0
  3. package/README.md +4 -0
  4. package/dist/{chunk-6YZBC5MO.js → chunk-2ZL5ORQ2.js} +85 -25
  5. package/dist/chunk-2ZL5ORQ2.js.map +1 -0
  6. package/dist/{chunk-7NVRYYHN.js → chunk-L53P43B2.js} +129 -31
  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-QG5HOYR5.js.map → cli-config-templates-LWMD2I6V.js.map} +1 -1
  10. package/dist/{cli-skill-templates-W4I6ZKYW.js → cli-skill-templates-D6S2OQ6X.js} +3 -3
  11. package/dist/{cli-skill-templates-W4I6ZKYW.js.map → cli-skill-templates-D6S2OQ6X.js.map} +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js +2747 -671
  14. package/dist/index.js.map +1 -1
  15. package/dist/metafile-esm.json +1 -1
  16. package/package.json +22 -22
  17. package/templates/apps/admin/src/routes/+layout.svelte.hbs +16 -10
  18. package/templates/apps/admin/src/routes/+page.svelte.hbs +4 -4
  19. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +17 -7
  20. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +26 -6
  21. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +2 -2
  22. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +6 -1
  23. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +13 -5
  24. package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +13 -5
  25. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
  26. package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +71 -32
  27. package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
  28. package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +131 -54
  29. package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +39 -13
  30. package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +78 -31
  31. package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +3 -1
  32. package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
  33. package/templates/apps/api/e2e/api-serv.spec.ts.hbs +20 -3
  34. package/templates/apps/api/e2e/capture-evidence.ts.hbs +4 -1
  35. package/templates/apps/api/eslint.config.js.hbs +3 -1
  36. package/templates/apps/api/images/serv.Dockerfile.hbs +3 -4
  37. package/templates/apps/api/playwright.config.ts.hbs +23 -19
  38. package/templates/apps/api/pnpm-workspace.yaml.hbs +27 -16
  39. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +1 -3
  40. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +10 -2
  41. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +10 -2
  42. package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +0 -1
  43. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +0 -1
  44. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +4 -1
  45. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +16 -4
  46. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +8 -2
  47. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +0 -1
  48. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +4 -1
  49. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +16 -4
  50. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +10 -2
  51. package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +0 -1
  52. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +0 -2
  53. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +4 -1
  54. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +19 -5
  55. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +111 -26
  56. package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +19 -5
  57. package/templates/apps/fullstack/eslint.config.js.hbs +3 -1
  58. package/templates/apps/fullstack/images/serv.Dockerfile.hbs +3 -4
  59. package/templates/apps/fullstack/images/web.Dockerfile.hbs +0 -2
  60. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +114 -23
  61. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +57 -11
  62. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
  63. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +65 -30
  64. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
  65. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +69 -21
  66. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +21 -5
  67. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +63 -11
  68. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +6 -1
  69. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +3 -1
  70. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +139 -49
  71. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +43 -12
  72. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +139 -28
  73. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +33 -10
  74. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +141 -25
  75. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +6 -2
  76. package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
  77. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +9 -2
  78. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +0 -3
  79. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +15 -3
  80. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +33 -7
  81. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +16 -2
  82. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +104 -13
  83. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +37 -7
  84. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +9 -3
  85. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +25 -3
  86. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +133 -19
  87. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +14 -2
  88. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +66 -34
  89. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +132 -30
  90. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +8 -2
  91. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +23 -5
  92. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +143 -21
  93. package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -2
  94. package/templates/apps/fullstack/playwright.config.ts.hbs +9 -3
  95. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +30 -15
  96. package/templates/apps/h5/src/routes/+layout.svelte.hbs +57 -21
  97. package/templates/apps/h5/src/routes/+page.svelte.hbs +2 -2
  98. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +2 -2
  99. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +2 -2
  100. package/templates/apps/mobile-app/src/App.svelte.hbs +17 -5
  101. package/templates/apps/mobile-app/src/lib/api.ts.hbs +14 -3
  102. package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +8 -1
  103. package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +6 -2
  104. package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +5 -1
  105. package/templates/apps/website/scripts/static-website.mjs.hbs +16 -3
  106. package/templates/apps/website/src/routes/+layout.svelte.hbs +44 -23
  107. package/templates/apps/website/src/routes/+page.svelte.hbs +4 -4
  108. package/templates/apps/website/src/routes/about/+page.svelte.hbs +2 -2
  109. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +2 -2
  110. package/templates/apps/website/src/routes/services/+page.svelte.hbs +20 -5
  111. package/templates/base/e2e/app.spec.ts.hbs +49 -16
  112. package/templates/base/eslint-rules.js +44 -25
  113. package/templates/base/eslint.config.js.hbs +3 -1
  114. package/templates/base/images/web.Dockerfile.hbs +3 -4
  115. package/templates/base/package.json.hbs +5 -4
  116. package/templates/base/patches/daisyui-5.7.50.patch +8 -0
  117. package/templates/base/patches/deepmerge-4.3.1.patch +51 -0
  118. package/templates/base/playwright.config.ts +3 -1
  119. package/templates/base/pnpm-workspace.yaml.hbs +33 -16
  120. package/templates/base/src/app.d.ts.hbs +1 -1
  121. package/templates/base/src/hooks.server.ts.hbs +36 -27
  122. package/templates/base/src/lib/build-metadata.ts.hbs +0 -1
  123. package/templates/base/src/lib/server/init.ts.hbs +124 -51
  124. package/templates/base/src/lib/server/kit-config.ts.hbs +7 -4
  125. package/templates/base/src/routes/+layout.server.ts.hbs +2 -2
  126. package/templates/base/svelte.config.js.hbs +10 -100
  127. package/templates/base/tests/scaffold.test.ts.hbs +12 -3
  128. package/templates/base/tsconfig.json.hbs +7 -4
  129. package/templates/base/vite.config.ts.hbs +108 -14
  130. package/templates/base/vitest.config.ts.hbs +6 -2
  131. package/templates/features/ai/routes/api/chat/+server.ts +3 -1
  132. package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +3 -3
  133. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +3 -3
  134. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +3 -3
  135. package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +3 -3
  136. package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +3 -3
  137. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +3 -3
  138. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +3 -3
  139. package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +3 -3
  140. package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +3 -3
  141. package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +3 -3
  142. package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +3 -3
  143. package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +3 -3
  144. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +11 -2
  145. package/templates/shared/browser-check/startup.js +32 -6
  146. package/templates/shared/browser-startup.spec.ts +3 -1
  147. package/templates/shared/build-metadata.ts +18 -4
  148. package/templates/shared/e2e-env.ts +22 -6
  149. package/templates/shared/native-name.mjs +9 -2
  150. package/templates/shared/public-base-path.mjs +17 -4
  151. package/templates/shared/run-e2e.mjs +40 -9
  152. package/templates/shared/run-node.mjs +15 -4
  153. package/templates/shared/run-tauri.mjs +37 -8
  154. package/templates/shared/vite-runtime-config.ts +9 -3
  155. package/templates/skills/AGENTS.md +10 -73
  156. package/templates/skills/bridges/admin/AGENTS.md +9 -65
  157. package/templates/skills/bridges/api/AGENTS.md +8 -59
  158. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +9 -54
  159. package/templates/skills/bridges/h5/AGENTS.md +8 -63
  160. package/templates/skills/bridges/mobile-app/AGENTS.md +8 -62
  161. package/templates/skills/bridges/website/AGENTS.md +8 -63
  162. package/templates/skills/hai-ai/acp.md +2 -0
  163. package/templates/skills/hai-ai/guide.md +17 -6
  164. package/templates/skills/hai-ai/reference.md +21 -12
  165. package/templates/skills/hai-api-client/reference.md +1 -1
  166. package/templates/skills/hai-app-create/development.md +3 -1
  167. package/templates/skills/hai-app-create/project.md +33 -0
  168. package/templates/skills/hai-app-create/reference.md +8 -8
  169. package/templates/skills/hai-app-tests/reference.md +1 -1
  170. package/templates/skills/hai-build/SKILL.md +2 -2
  171. package/templates/skills/hai-build/paths.md +1 -1
  172. package/templates/skills/hai-build/reference.md +11 -7
  173. package/templates/skills/hai-capacitor/reference.md +2 -0
  174. package/templates/skills/hai-ci/SKILL.md +1 -0
  175. package/templates/skills/hai-core/reference.md +3 -0
  176. package/templates/skills/hai-crypto/reference.md +2 -0
  177. package/templates/skills/hai-deploy/SKILL.md +7 -1
  178. package/templates/skills/hai-deploy/middleware.md +3 -1
  179. package/templates/skills/hai-framework-sync/sync.md +2 -0
  180. package/templates/skills/hai-kit/reference.md +16 -4
  181. package/templates/skills/hai-payment/reference.md +2 -0
  182. package/templates/skills/hai-reach/SKILL.md +2 -1
  183. package/templates/skills/hai-reach/reference.md +1 -1
  184. package/templates/skills/hai-reldb/SKILL.md +1 -1
  185. package/templates/skills/hai-reldb/reference.md +4 -0
  186. package/templates/skills/hai-serv/reference.md +12 -2
  187. package/templates/skills/hai-storage/reference.md +12 -3
  188. package/templates/skills/hai-ui/SKILL.md +3 -2
  189. package/templates/skills/hai-ui/guide.md +1 -1
  190. package/templates/skills/hai-ui/reference.md +23 -35
  191. package/templates/skills/hai-vecdb/reference.md +1 -1
  192. package/dist/chunk-6YZBC5MO.js.map +0 -1
  193. package/dist/chunk-7NVRYYHN.js.map +0 -1
  194. package/dist/cli-config-templates-QG5HOYR5.js +0 -5
@@ -2,6 +2,11 @@ import { svelte } from '@sveltejs/vite-plugin-svelte'
2
2
  import { defineConfig } from 'vitest/config'
3
3
 
4
4
  export default defineConfig({
5
- plugins: [svelte()],
6
- test: { environment: 'node', include: ['tests/**/*.test.ts'] },
5
+ plugins: [
6
+ svelte(),
7
+ ],
8
+ test: {
9
+ environment: 'node',
10
+ include: ['tests/**/*.test.ts'],
11
+ },
7
12
  })
@@ -44,7 +44,9 @@ function resolvePortFromBaseUrl(urlString: string, fallbackPort: string): string
44
44
  return url.port
45
45
  }
46
46
 
47
- return url.protocol === 'https:' ? '443' : '80'
47
+ return url.protocol === 'https:'
48
+ ? '443'
49
+ : '80'
48
50
  }
49
51
  catch {
50
52
  return fallbackPort
@@ -54,7 +56,9 @@ function resolvePortFromBaseUrl(urlString: string, fallbackPort: string): string
54
56
  export default defineConfig({
55
57
  testDir: './e2e',
56
58
  {{#if fullstack.e2eFrontend}}
57
- ...(sessionClose ? { testMatch: '**/session-close.spec.ts' } : { testIgnore: '**/session-close.spec.ts' }),
59
+ ...(sessionClose
60
+ ? { testMatch: '**/session-close.spec.ts' }
61
+ : { testIgnore: '**/session-close.spec.ts' }),
58
62
  {{/if}}
59
63
  // 多个界面验收共用管理员资料与引导状态,保留串行以免互相覆盖。
60
64
  fullyParallel: false,
@@ -116,7 +120,9 @@ export default defineConfig({
116
120
  timeout: 120_000,
117
121
  },
118
122
  ...frontends.map((frontend) => {
119
- const url = frontend.target === primaryFrontend ? baseURL : frontend.url
123
+ const url = frontend.target === primaryFrontend
124
+ ? baseURL
125
+ : frontend.url
120
126
  return {
121
127
  name: frontend.name,
122
128
  command: `pnpm --filter ${frontend.name} exec vite preview --host ${resolveHostFromBaseUrl(url, '127.0.0.1')} --port ${resolvePortFromBaseUrl(url, '3000')} --strictPort`,
@@ -1,5 +1,5 @@
1
1
  {{! @skipIfEmpty }}
2
- shellEmulator: true
2
+ minimumReleaseAgeExcludePrune: true
3
3
 
4
4
  trustPolicy: no-downgrade
5
5
  # 上游构建工具仍要求 4.x;4.0.3 tarball 已核对原 lockfile 的 SHA-512。
@@ -8,32 +8,47 @@ trustPolicyExclude:
8
8
 
9
9
  # pnpm 12 配置;原生依赖仅运行明确列出的安装脚本。
10
10
  nodeLinker: hoisted
11
- allowBuilds:
12
- onnxruntime-node: true
13
- protobufjs: true
14
- vue-demi: true
15
- better-sqlite3: true
16
- esbuild: true
17
- core-js: false
11
+ shellEmulator: true
12
+
13
+ packages:
14
+ - packages/*
15
+ - apps/*
18
16
 
17
+ # 构建与浏览器依赖的安全修复;版本与框架工作区同步维护。
19
18
  overrides:
20
- "@ai-sdk/provider-utils@>=4.0.0 <4.0.33": 4.0.57
19
+ '@ai-sdk/provider-utils@>=4.0.0 <4.0.33': 4.0.57
20
+ '@types/node': {{versions.nodeTypes}}
21
+ body-parser@>=2 <2.4.0: 2.4.0
21
22
  cookie@<0.7.0: 0.7.2
23
+ dompurify@>=3 <3.4.17: 3.4.17
22
24
  esbuild@<0.28.1: 0.28.2
25
+ fast-uri@>=3 <3.1.9: 3.1.9
26
+ follow-redirects@>=1.16.0 <1.16.2: 1.16.2
27
+ glob@>=9 <=14.0.1: 14.0.4
28
+ ip-address@<=10.7.3: 10.7.6
23
29
  katex@<0.18.2: 0.18.10
30
+ minimatch@>=7 <11.0.1: 11.0.5
31
+ parse5@>=8 <8.1.0: 8.1.0
32
+ qs@>=6.7 <6.16.1: 6.17.1
33
+ runed@<0.38.0: 0.38.0
24
34
  sharp@<0.35.5: 0.35.5
25
35
  tinypool@<2.1.2: 2.2.0
26
- '@qdrant/js-client-rest>undici': 7.30.0
27
36
  xcode>uuid: 11.1.1
28
- "@types/node": "{{versions.nodeTypes}}"
29
37
 
30
- packages:
31
- - packages/*
32
- - apps/*
38
+ patchedDependencies:
39
+ daisyui@5.7.50: patches/daisyui-5.7.50.patch
40
+ deepmerge@4.3.1: patches/deepmerge-4.3.1.patch
41
+
42
+ allowBuilds:
43
+ core-js: false
44
+ esbuild: true
45
+ onnxruntime-node: true
46
+ protobufjs: true
47
+ vue-demi: true
33
48
 
34
49
  {{#if useCatalogProtocol}}
35
50
  catalog:
36
51
  {{#each haiCatalogPackages}}
37
- '{{@key}}': {{this}}
52
+ {{{yaml @key this}}}
38
53
  {{/each}}
39
54
  {{/if}}
@@ -5,14 +5,10 @@
5
5
  */
6
6
  import type { BottomNavItem } from '@h-ai/ui'
7
7
  import type { Snippet } from 'svelte'
8
- import { browser } from '$app/environment'
8
+ import { browser } from '$app/env'
9
9
  import { goto } from '$app/navigation'
10
- import { base, resolve } from '$app/paths'
10
+ import { resolve } from '$app/paths'
11
11
  import { page } from '$app/state'
12
- {{#if hasI18n}}
13
- import * as m from '$lib/paraglide/messages'
14
- import { getLocale, setLocale } from '$lib/paraglide/runtime.js'
15
- {{/if}}
16
12
  {{#if features.crypto}}
17
13
  import { crypto } from '@h-ai/crypto'
18
14
  import { kit } from '@h-ai/kit'
@@ -29,6 +25,10 @@
29
25
  import { applyTheme, getSavedTheme } from '@h-ai/ui/theme'
30
26
  {{#if features.crypto}}
31
27
  import { untrack } from 'svelte'
28
+ {{/if}}
29
+ {{#if hasI18n}}
30
+ import * as m from '#lib/paraglide/messages.js'
31
+ import { getLocale, setLocale } from '#lib/paraglide/runtime.js'
32
32
  {{/if}}
33
33
  import '../app.css'
34
34
 
@@ -37,7 +37,9 @@
37
37
  }
38
38
 
39
39
  const { children }: Props = $props()
40
- const initialTheme = browser ? getSavedTheme() : 'light'
40
+ const initialTheme = browser
41
+ ? getSavedTheme()
42
+ : 'light'
41
43
  let currentTheme = $state(initialTheme)
42
44
  if (browser)
43
45
  applyTheme(initialTheme, false)
@@ -46,37 +48,71 @@
46
48
  currentTheme = theme
47
49
  applyTheme(theme)
48
50
  }
49
-
50
51
  {{#if features.crypto}}
51
- if (browser)
52
- kit.client.installBrowserTransport(untrack(() => page.data.kitConfig), { crypto, basePath: base })
52
+ if (browser) {
53
+ kit.client.installBrowserTransport(untrack(() => page.data.kitConfig), {
54
+ crypto,
55
+ basePath: resolve('/').replace(/\/$/, ''),
56
+ })
57
+ }
53
58
  {{/if}}
54
59
  {{#if features.iam}}
55
- const authActions = kit.client.createAuthActions({ basePath: `${base}/api/auth` })
60
+ const authActions = kit.client.createAuthActions({ basePath: `${resolve('/').replace(/\/$/, '')}/api/auth` })
56
61
  $effect(() => authActions.bindPageExit({ enabled: page.data.iamPublicConfig?.session.endOnPageHide }))
57
62
  {{/if}}
58
63
 
59
- const navItems: (BottomNavItem & { path: '/' | '/discover' | '/profile' })[] = [
64
+ const navItems: (BottomNavItem & { path: ReturnType<typeof resolve> })[] = [
60
65
  {{#if hasI18n}}
61
- { id: 'home', path: '/', label: m.nav_home(), iconClass: 'icon-[tabler--home]' },
62
- { id: 'discover', path: '/discover', label: m.nav_discover(), iconClass: 'icon-[tabler--compass]' },
63
- { id: 'profile', path: '/profile', label: m.nav_profile(), iconClass: 'icon-[tabler--user]' },
66
+ {
67
+ id: 'home',
68
+ path: resolve('/'),
69
+ label: m.nav_home(),
70
+ iconClass: 'icon-[tabler--home]',
71
+ },
72
+ {
73
+ id: 'discover',
74
+ path: resolve('discover'),
75
+ label: m.nav_discover(),
76
+ iconClass: 'icon-[tabler--compass]',
77
+ },
78
+ {
79
+ id: 'profile',
80
+ path: resolve('profile'),
81
+ label: m.nav_profile(),
82
+ iconClass: 'icon-[tabler--user]',
83
+ },
64
84
  {{else}}
65
- { id: 'home', path: '/', label: '首页', iconClass: 'icon-[tabler--home]' },
66
- { id: 'discover', path: '/discover', label: '发现', iconClass: 'icon-[tabler--compass]' },
67
- { id: 'profile', path: '/profile', label: '我的', iconClass: 'icon-[tabler--user]' },
85
+ {
86
+ id: 'home',
87
+ path: resolve('/'),
88
+ label: '首页',
89
+ iconClass: 'icon-[tabler--home]',
90
+ },
91
+ {
92
+ id: 'discover',
93
+ path: resolve('discover'),
94
+ label: '发现',
95
+ iconClass: 'icon-[tabler--compass]',
96
+ },
97
+ {
98
+ id: 'profile',
99
+ path: resolve('profile'),
100
+ label: '我的',
101
+ iconClass: 'icon-[tabler--user]',
102
+ },
68
103
  {{/if}}
69
104
  ]
70
105
 
71
- const localPath = $derived(page.url.pathname.slice(base.length) || '/')
72
- const activeNav = $derived(navItems.find(item => item.path === localPath)?.id)
106
+ const localPath = $derived(page.url.pathname.slice(resolve('/').replace(/\/$/, '').length) || '/')
107
+ const activeNav = $derived(navItems.find(item => item.path === page.url.pathname)?.id)
73
108
  // 所有页面共用页头页脚;仅业务页面显示底部导航。
74
109
  const isAuthPage = $derived(localPath.startsWith('/auth'))
75
110
 
76
111
  function handleNavigation(id: string) {
77
112
  const item = navItems.find(item => item.id === id)
78
113
  if (item)
79
- void goto(resolve(item.path, {}))
114
+ // eslint-disable-next-line svelte/no-navigation-without-resolve -- path 仅来自上方 resolve 构造的导航表,不能二次添加挂载前缀。
115
+ void goto(item.path)
80
116
  }
81
117
  {{#if hasI18n}}
82
118
 
@@ -4,10 +4,10 @@
4
4
  /**
5
5
  * H5 首页
6
6
  */
7
+ import { Card } from '@h-ai/ui'
7
8
  {{#if hasI18n}}
8
- import * as m from '$lib/paraglide/messages'
9
+ import * as m from '#lib/paraglide/messages.js'
9
10
  {{/if}}
10
- import { Card } from '@h-ai/ui'
11
11
  </script>
12
12
 
13
13
  <svelte:head>
@@ -3,10 +3,10 @@
3
3
  /**
4
4
  * 发现页面
5
5
  */
6
+ import { Card } 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 } from '@h-ai/ui'
10
10
  </script>
11
11
 
12
12
  <svelte:head>
@@ -3,10 +3,10 @@
3
3
  /**
4
4
  * 个人中心页面
5
5
  */
6
+ import { Card } 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 } from '@h-ai/ui'
10
10
  </script>
11
11
 
12
12
  <svelte:head>
@@ -48,9 +48,21 @@
48
48
  let nativeTokenStorage = $state(false)
49
49
 
50
50
  const navItems = $derived([
51
- { id: 'home', label: m.nav_home(), iconClass: 'icon-[tabler--layout-dashboard]' },
52
- { id: 'tasks', label: m.nav_tasks(), iconClass: 'icon-[tabler--checkbox]' },
53
- { id: 'profile', label: m.nav_profile(), iconClass: 'icon-[tabler--user-circle]' },
51
+ {
52
+ id: 'home',
53
+ label: m.nav_home(),
54
+ iconClass: 'icon-[tabler--layout-dashboard]',
55
+ },
56
+ {
57
+ id: 'tasks',
58
+ label: m.nav_tasks(),
59
+ iconClass: 'icon-[tabler--checkbox]',
60
+ },
61
+ {
62
+ id: 'profile',
63
+ label: m.nav_profile(),
64
+ iconClass: 'icon-[tabler--user-circle]',
65
+ },
54
66
  ])
55
67
 
56
68
  async function bootstrap(): Promise<void> {
@@ -143,10 +155,10 @@
143
155
  </footer>
144
156
  {{#if features.iam}}
145
157
  {#if authenticated && !booting && !bootError}
146
- {{/if}}
147
158
  <BottomNav items={navItems} active={router.path.slice(1)} onchange={handleTabChange} safeArea centered maxWidth='none' />
148
- {{#if features.iam}}
149
159
  {/if}
160
+ {{else}}
161
+ <BottomNav items={navItems} active={router.path.slice(1)} onchange={handleTabChange} safeArea centered maxWidth='none' />
150
162
  {{/if}}
151
163
  </div>
152
164
  </div>
@@ -151,9 +151,13 @@ async function initialize(): Promise<void> {
151
151
  const result = await apiClient.init({
152
152
  baseUrl: resolveApiBase(),
153
153
  clientName: 'hai-mobile-app',
154
- headers: native ? { 'x-hai-token-transport': 'body' } : {},
154
+ headers: native
155
+ ? { 'x-hai-token-transport': 'body' }
156
+ : {},
155
157
  auth: { storage },
156
- ...(transport ? { transport } : {}),
158
+ ...(transport
159
+ ? { transport }
160
+ : {}),
157
161
  })
158
162
  if (!result.success)
159
163
  throw new Error(result.error.message)
@@ -172,7 +176,14 @@ async function initialize(): Promise<void> {
172
176
  throw error
173
177
  }
174
178
  {{else}}
175
- const result = await apiClient.init({ baseUrl: resolveApiBase(), clientName: 'hai-mobile-app', headers: native ? { 'x-hai-token-transport': 'body' } : {}, auth: { storage } })
179
+ const result = await apiClient.init({
180
+ baseUrl: resolveApiBase(),
181
+ clientName: 'hai-mobile-app',
182
+ headers: native
183
+ ? { 'x-hai-token-transport': 'body' }
184
+ : {},
185
+ auth: { storage },
186
+ })
176
187
  if (!result.success)
177
188
  throw new Error(result.error.message)
178
189
  initialized = true
@@ -7,7 +7,14 @@ declare const __APP_CORE_CONFIG__: Pick<CoreConfig, 'name' | 'version' | 'env' |
7
7
 
8
8
  /** 构建包含公开默认值;预览或容器启动时的公开配置覆盖默认值,不重建静态资源。 */
9
9
  const runtime = (globalThis as typeof globalThis & { __HAI_PUBLIC_CONFIG__?: { core?: Partial<typeof __APP_CORE_CONFIG__> } }).__HAI_PUBLIC_CONFIG__?.core
10
- export const appConfig = { ...__APP_CORE_CONFIG__, ...runtime, logging: { ...__APP_CORE_CONFIG__.logging, ...runtime?.logging } }
10
+ export const appConfig = {
11
+ ...__APP_CORE_CONFIG__,
12
+ ...runtime,
13
+ logging: {
14
+ ...__APP_CORE_CONFIG__.logging,
15
+ ...runtime?.logging,
16
+ },
17
+ }
11
18
 
12
19
  export function initClientCore(): void {
13
20
  core.init({ logging: appConfig.logging })
@@ -46,12 +46,16 @@
46
46
  <div>
47
47
  <p class='text-base-content/50'>{m.status_runtime_label()}</p>
48
48
  <Badge variant={nativeRuntime ? 'success' : 'warning'} size='sm'>
49
- {nativeRuntime ? m.status_runtime_native() : m.status_runtime_web()}
49
+ {nativeRuntime
50
+ ? m.status_runtime_native()
51
+ : m.status_runtime_web()}
50
52
  </Badge>
51
53
  </div>
52
54
  <div class='col-span-2'>
53
55
  <p class='text-base-content/50'>{m.status_token_label()}</p>
54
- <p class='font-medium'>{nativeTokenStorage ? m.status_token_native() : m.status_token_memory()}</p>
56
+ <p class='font-medium'>{nativeTokenStorage
57
+ ? m.status_token_native()
58
+ : m.status_token_memory()}</p>
55
59
  </div>
56
60
  </div>
57
61
  </Card>
@@ -5,7 +5,11 @@
5
5
  <section class='space-y-4 p-4 pb-6'>
6
6
  <Card title={m.tasks_title()} shadow='sm'>
7
7
  <div class='space-y-3'>
8
- {#each [m.tasks_sync(), m.tasks_polish(), m.tasks_release()] as task (task)}
8
+ {#each [
9
+ m.tasks_sync(),
10
+ m.tasks_polish(),
11
+ m.tasks_release(),
12
+ ] as task (task)}
9
13
  <div class='bg-base-200 rounded-xl flex items-center gap-3 p-3'>
10
14
  <span class='icon-[tabler--circle-check] text-success text-xl'></span>
11
15
  <span class='text-sm font-medium'>{task}</span>
@@ -28,9 +28,22 @@ const message = core.i18n.createMessageGetter({
28
28
  assets: 'staticは公開資産ディレクトリーです。非公開.envファイルやシンボリックリンクを置かず、非公開内容を移動してから構築してください。',
29
29
  },
30
30
  })
31
- const serverFeatures = [{{#each websiteServerFeatures}}'{{this}}'{{#unless @last}}, {{/unless}}{{/each}}]
32
- const requestedLocale = [process.env.HAI_CORE_DEFAULTLOCALE, process.env.LC_ALL, process.env.LC_MESSAGES, process.env.LANG].find(value => value?.trim())?.split(/[_.-]/)[0]?.toLowerCase()
33
- const locale = requestedLocale === 'en' || requestedLocale === 'c' || requestedLocale === 'posix' ? 'en-US' : requestedLocale === 'ja' ? 'ja-JP' : 'zh-CN'
31
+ const serverFeatures = [
32
+ {{#each websiteServerFeatures}}
33
+ '{{this}}',
34
+ {{/each}}
35
+ ]
36
+ const requestedLocale = [
37
+ process.env.HAI_CORE_DEFAULTLOCALE,
38
+ process.env.LC_ALL,
39
+ process.env.LC_MESSAGES,
40
+ process.env.LANG,
41
+ ].find(value => value?.trim())?.split(/[_.-]/)[0]?.toLowerCase()
42
+ const locale = requestedLocale === 'en' || requestedLocale === 'c' || requestedLocale === 'posix'
43
+ ? 'en-US'
44
+ : requestedLocale === 'ja'
45
+ ? 'ja-JP'
46
+ : 'zh-CN'
34
47
 
35
48
  /** 只读取显式构建值,不加载dotenv和服务端秘密。 */
36
49
  export function resolveStaticWebsite() {
@@ -4,13 +4,9 @@
4
4
  * 官网根布局
5
5
  */
6
6
  import type { Snippet } from 'svelte'
7
- import { browser } from '$app/environment'
8
- import { {{#if features.iam}}base, {{else}}{{#if features.crypto}}base, {{/if}}{{/if}}resolve } from '$app/paths'
7
+ import { browser } from '$app/env'
8
+ import { resolve } from '$app/paths'
9
9
  import { page } from '$app/state'
10
- {{#if hasI18n}}
11
- import * as m from '$lib/paraglide/messages'
12
- import { getLocale, setLocale } from '$lib/paraglide/runtime.js'
13
- {{/if}}
14
10
  {{#if features.crypto}}
15
11
  import { crypto } from '@h-ai/crypto'
16
12
  import { kit } from '@h-ai/kit'
@@ -27,6 +23,10 @@
27
23
  import { applyTheme, getSavedTheme } from '@h-ai/ui/theme'
28
24
  {{#if features.crypto}}
29
25
  import { untrack } from 'svelte'
26
+ {{/if}}
27
+ {{#if hasI18n}}
28
+ import * as m from '#lib/paraglide/messages.js'
29
+ import { getLocale, setLocale } from '#lib/paraglide/runtime.js'
30
30
  {{/if}}
31
31
  import '../app.css'
32
32
 
@@ -35,7 +35,9 @@
35
35
  }
36
36
 
37
37
  const { children }: Props = $props()
38
- const initialTheme = browser ? getSavedTheme() : 'light'
38
+ const initialTheme = browser
39
+ ? getSavedTheme()
40
+ : 'light'
39
41
  let currentTheme = $state(initialTheme)
40
42
  if (browser)
41
43
  applyTheme(initialTheme, false)
@@ -44,27 +46,42 @@
44
46
  currentTheme = theme
45
47
  applyTheme(theme)
46
48
  }
47
-
48
49
  {{#if features.crypto}}
49
- if (browser)
50
- kit.client.installBrowserTransport(untrack(() => page.data.kitConfig), { crypto, basePath: base })
50
+ if (browser) {
51
+ kit.client.installBrowserTransport(untrack(() => page.data.kitConfig), {
52
+ crypto,
53
+ basePath: resolve('/').replace(/\/$/, ''),
54
+ })
55
+ }
51
56
  {{/if}}
52
57
  {{#if features.iam}}
53
- const authActions = kit.client.createAuthActions({ basePath: `${base}/api/auth` })
58
+ const authActions = kit.client.createAuthActions({ basePath: `${resolve('/').replace(/\/$/, '')}/api/auth` })
54
59
  $effect(() => authActions.bindPageExit({ enabled: page.data.iamPublicConfig?.session.endOnPageHide }))
55
60
  {{/if}}
56
61
 
57
62
  const navItems = [
58
63
  {{#if hasI18n}}
59
- { path: '/', label: m.nav_home() },
60
- { path: '/about', label: m.nav_about() },
61
- { path: '/services', label: m.nav_services() },
62
- { path: '/contact', label: m.nav_contact() },
64
+ {
65
+ path: resolve('/'),
66
+ label: m.nav_home(),
67
+ },
68
+ {
69
+ path: resolve('about'),
70
+ label: m.nav_about(),
71
+ },
72
+ {
73
+ path: resolve('services'),
74
+ label: m.nav_services(),
75
+ },
76
+ {
77
+ path: resolve('contact'),
78
+ label: m.nav_contact(),
79
+ },
63
80
  {{else}}
64
- { path: '/', label: '首页' },
65
- { path: '/about', label: '关于' },
66
- { path: '/services', label: '服务' },
67
- { path: '/contact', label: '联系我们' },
81
+ { path: resolve('/'), label: '首页' },
82
+ { path: resolve('about'), label: '关于' },
83
+ { path: resolve('services'), label: '服务' },
84
+ { path: resolve('contact'), label: '联系我们' },
68
85
  {{/if}}
69
86
  ] as const
70
87
  {{#if hasI18n}}
@@ -89,15 +106,17 @@
89
106
  <header class='navbar flex-wrap bg-base-100 shadow-sm'>
90
107
  <div class='flex-1'>
91
108
  {{#if hasI18n}}
92
- <a href={resolve('/', {})} class='btn btn-ghost text-xl font-black tracking-tight'>{page.data.appConfig.name}</a>
109
+ <a href={resolve('/')} class='btn btn-ghost text-xl font-black tracking-tight'>{page.data.appConfig.name}</a>
93
110
  {{else}}
94
- <a href={resolve('/', {})} class='btn btn-ghost text-xl font-black tracking-tight'>{page.data.appConfig.name}</a>
111
+ <a href={resolve('/')} class='btn btn-ghost text-xl font-black tracking-tight'>{page.data.appConfig.name}</a>
95
112
  {{/if}}
96
113
  </div>
97
114
  <nav class='w-full flex-none sm:w-auto'>
98
115
  <ul class='menu menu-horizontal flex-wrap px-1'>
99
116
  {#each navItems as item (item.path)}
100
- <li><a href={resolve(item.path, {})}>{item.label}</a></li>
117
+ <li><!-- eslint-disable svelte/no-navigation-without-resolve -- 菜单字段已由 resolve 生成完整挂载地址;规则无法追踪派生/筛选后的集合,不能二次添加前缀。 -->
118
+ <a href={item.path}>{item.label}</a>
119
+ <!-- eslint-enable svelte/no-navigation-without-resolve --></li>
101
120
  {/each}
102
121
  </ul>
103
122
  </nav>
@@ -114,7 +133,9 @@
114
133
  <footer class='footer footer-center p-4 bg-base-300 text-base-content'>
115
134
  <span>{page.data.appConfig.name} · {page.data.appConfig.version} · {page.data.appConfig.env}</span>
116
135
  {{#if hasI18n}}
117
- <p>{m.footer_copyright({ year: new Date().getFullYear() })}</p>
136
+ <p>{m.footer_copyright({
137
+ year: new Date().getFullYear(),
138
+ })}</p>
118
139
  {{else}}
119
140
  <p>Copyright © 2025 - All rights reserved</p>
120
141
  {{/if}}
@@ -5,10 +5,10 @@
5
5
  */
6
6
  import { resolve } from '$app/paths'
7
7
  import { page } from '$app/state'
8
+ import { Badge } 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 } from '@h-ai/ui'
12
12
  </script>
13
13
 
14
14
  <svelte:head>
@@ -35,14 +35,14 @@
35
35
  {{#if hasI18n}}
36
36
  <h1 class='mt-5 text-5xl font-black tracking-tight'>{m.page_home_title()}</h1>
37
37
  <p class='py-6 text-base-content/60'>{m.page_home_subtitle()}</p>
38
- <a href={resolve('/about', {})} class='btn btn-primary'>
38
+ <a href={resolve('about')} class='btn btn-primary'>
39
39
  <span class='icon-[tabler--arrow-right] size-5'></span>
40
40
  {m.page_home_cta()}
41
41
  </a>
42
42
  {{else}}
43
43
  <h1 class='mt-5 text-5xl font-black tracking-tight'>欢迎</h1>
44
44
  <p class='py-6 text-base-content/60'>基于 hai Agent Framework 构建</p>
45
- <a href={resolve('/about', {})} class='btn btn-primary'>
45
+ <a href={resolve('about')} class='btn btn-primary'>
46
46
  <span class='icon-[tabler--arrow-right] size-5'></span>
47
47
  了解更多
48
48
  </a>
@@ -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>
@@ -3,10 +3,10 @@
3
3
  /**
4
4
  * 联系我们页面
5
5
  */
6
+ import { Button, Card, FormField, FormLayout, Input, notifyWarning, PageHeader, Textarea } 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 { Button, Card, FormField, FormLayout, Input, notifyWarning, PageHeader, Textarea } from '@h-ai/ui'
10
10
 
11
11
  let name = $state('')
12
12
  let email = $state('')
@@ -3,16 +3,31 @@
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
 
11
11
  {{#if hasI18n}}
12
12
  const services = $derived([
13
- { id: 'consulting', title: m.page_services_item1(), desc: m.page_services_desc(), icon: 'icon-[tabler--message-circle]' },
14
- { id: 'development', title: m.page_services_item2(), desc: m.page_services_desc(), icon: 'icon-[tabler--code]' },
15
- { id: 'operations', title: m.page_services_item3(), desc: m.page_services_desc(), icon: 'icon-[tabler--server-cog]' },
13
+ {
14
+ id: 'consulting',
15
+ title: m.page_services_item1(),
16
+ desc: m.page_services_desc(),
17
+ icon: 'icon-[tabler--message-circle]',
18
+ },
19
+ {
20
+ id: 'development',
21
+ title: m.page_services_item2(),
22
+ desc: m.page_services_desc(),
23
+ icon: 'icon-[tabler--code]',
24
+ },
25
+ {
26
+ id: 'operations',
27
+ title: m.page_services_item3(),
28
+ desc: m.page_services_desc(),
29
+ icon: 'icon-[tabler--server-cog]',
30
+ },
16
31
  ])
17
32
  {{else}}
18
33
  const services = [