@h-ai/cli 0.1.0-alpha.60 → 0.1.0-alpha.61

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 (35) hide show
  1. package/README.en.md +10 -0
  2. package/README.ja.md +10 -0
  3. package/README.md +10 -0
  4. package/dist/{chunk-P6X63D3I.js → chunk-WW2MIO6T.js} +377 -124
  5. package/dist/chunk-WW2MIO6T.js.map +1 -0
  6. package/dist/cli-config-templates-QRF6B5T4.js +5 -0
  7. package/dist/{cli-config-templates-EFABFSCY.js.map → cli-config-templates-QRF6B5T4.js.map} +1 -1
  8. package/dist/index.js +24 -5
  9. package/dist/index.js.map +1 -1
  10. package/package.json +7 -7
  11. package/templates/README.md +6 -0
  12. package/templates/apps/api/.gitignore.hbs +1 -0
  13. package/templates/apps/fullstack/.gitignore.hbs +1 -0
  14. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +8 -3
  15. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_ai.yml.hbs +1 -0
  16. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_audit.yml.hbs +1 -3
  17. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_cache.yml.hbs +1 -2
  18. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +7 -0
  19. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_db.yml.hbs +1 -3
  20. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_deploy.yml.hbs +1 -0
  21. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_iam.yml.hbs +1 -67
  22. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_payment.yml.hbs +1 -0
  23. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +31 -0
  24. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_scheduler.yml.hbs +1 -0
  25. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +8 -0
  26. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_storage.yml.hbs +1 -3
  27. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_vecdb.yml.hbs +1 -0
  28. package/templates/apps/h5/src/routes/+layout.svelte.hbs +35 -23
  29. package/templates/base/.gitignore.hbs +1 -2
  30. package/templates/base/e2e/app.spec.ts.hbs +43 -1
  31. package/templates/base/package.json.hbs +1 -1
  32. package/templates/skills/hai-app-create/reference.md +10 -0
  33. package/templates/skills/hai-ui/reference.md +2 -0
  34. package/dist/chunk-P6X63D3I.js.map +0 -1
  35. package/dist/cli-config-templates-EFABFSCY.js +0 -5
@@ -37,9 +37,6 @@ function generateConfigFile(moduleKey, configs) {
37
37
  function generateCoreConfig(cfg) {
38
38
  const name = cfg?.name ?? "my-app";
39
39
  const locale = cfg?.defaultLocale ?? "zh-CN";
40
- const supportedLocales = locale === "en-US" ? ` - en-US
41
- - zh-CN` : ` - zh-CN
42
- - en-US`;
43
40
  return `# =============================================================================
44
41
  # \u5E94\u7528\u914D\u7F6E
45
42
  # =============================================================================
@@ -52,14 +49,18 @@ debug: false
52
49
  logging:
53
50
  level: info
54
51
  format: json
52
+ # context:
53
+ # service: api
55
54
  redact:
56
55
  - password
57
56
  - token
58
57
  - secret
59
58
 
60
59
  defaultLocale: ${locale}
61
- supportedLocales:
62
- ${supportedLocales}
60
+ # \u77ED ID \u751F\u6210\u9009\u9879\uFF1B\u8BED\u8A00\u5217\u8868\u5728\u524D\u7AEF project.inlang/settings.json \u4E2D\u7EF4\u62A4\u3002
61
+ # id:
62
+ # prefix: app_
63
+ # length: 21
63
64
  `;
64
65
  }
65
66
  function generateServConfig() {
@@ -67,19 +68,42 @@ function generateServConfig() {
67
68
  # Service / HTTP \u5165\u53E3\u914D\u7F6E
68
69
  # =============================================================================
69
70
 
71
+ server:
72
+ host: 127.0.0.1
73
+ port: 3000
74
+
70
75
  http:
71
76
  apiPrefix: /api/v1
72
77
  openapi:
73
78
  path: /openapi.json
74
79
  docs:
75
80
  path: /docs
81
+ # requireAuth: true
76
82
  health:
77
83
  path: /health
78
84
  readyPath: /ready
79
85
  rpc: false
86
+ # \u542F\u7528\u5185\u90E8 RPC \u65F6\u7528\u5BF9\u8C61\u66FF\u6362 false\uFF0Cgateway-only \u5FC5\u987B\u914D\u7F6E\u7F51\u5173\u5BC6\u94A5\u3002
87
+ # rpc:
88
+ # prefix: /api/rpc
89
+ # access: gateway-only # loopback | private-network | gateway-only
90
+ # gatewayHeader: X-Gateway-Key
91
+ # gatewaySecret: \${HAI_SERV_HTTP_RPC_GATEWAYSECRET}
92
+
93
+ # \u6309\u9700\u5F00\u542F\u8DE8\u57DF\u8BBF\u95EE\uFF0C\u751F\u4EA7\u73AF\u5883\u586B\u5199\u660E\u786E\u7684 Origin\u3002
94
+ # cors:
95
+ # origin: https://app.example.com
96
+ # nativeOrigins: capacitor://localhost,tauri://localhost
97
+ # allowedHeaders: [Authorization, Content-Type, X-Request-Id]
98
+ # exposedHeaders: [X-Request-Id]
99
+ # credentials: true
80
100
 
81
101
  # \u5F00\u53D1\u671F\u9ED8\u8BA4\u5173\u95ED transport\uFF1B\u542F\u7528 @h-ai/crypto \u540E\u53EF\u6309\u9700\u6539\u4E3A\u5BF9\u8C61\u914D\u7F6E
82
102
  transport: false
103
+ # transport:
104
+ # keyExchangePath: /_hai/key-exchange
105
+ # excludePaths: [/health, /ready]
106
+ # maxClients: 10000
83
107
  `;
84
108
  }
85
109
  function generateDbConfig(cfg) {
@@ -87,25 +111,19 @@ function generateDbConfig(cfg) {
87
111
  const database = cfg?.database ?? (dbType === "sqlite" ? "./data/app.db" : "hai");
88
112
  const host = cfg?.host ?? "localhost";
89
113
  const port = cfg?.port ?? (dbType === "postgresql" ? 5432 : 3306);
90
- if (dbType === "sqlite") {
91
- return `# =============================================================================
92
- # \u6570\u636E\u5E93\u914D\u7F6E
93
- # =============================================================================
94
-
95
- # \u6570\u636E\u5E93\u7C7B\u578B: sqlite | postgresql | mysql
96
- type: sqlite
97
-
98
- # SQLite \u6570\u636E\u5E93\u8DEF\u5F84
99
- database: ${database}
100
-
101
- # PostgreSQL/MySQL \u914D\u7F6E\uFF08\u53EF\u9009\uFF09
102
- # host: localhost
103
- # port: 5432
104
- # user: postgres
105
- # password: ''
106
- `;
107
- }
108
114
  const user = dbType === "postgresql" ? "postgres" : "root";
115
+ const connection = stringify({ host, port, user, password: "" }).trim();
116
+ const networkOptions = `# url: \${HAI_DB_URL} # \u53EF\u7528\u8FDE\u63A5\u4E32\u66FF\u4EE3 host/port/user/password
117
+ # ssl: false # false | true | require | prefer | allow | disable\uFF0C\u6216 TLS \u5BF9\u8C61
118
+ # pool:
119
+ # min: 1
120
+ # max: 10
121
+ # idleTimeout: 30000
122
+ # acquireTimeout: 10000
123
+ # MySQL \u4E13\u7528\uFF1BPostgreSQL \u65E0\u9700\u6B64\u5757\u3002
124
+ # mysql:
125
+ # charset: utf8mb4
126
+ # timezone: '+08:00'`;
109
127
  return `# =============================================================================
110
128
  # \u6570\u636E\u5E93\u914D\u7F6E
111
129
  # =============================================================================
@@ -113,48 +131,68 @@ database: ${database}
113
131
  # \u6570\u636E\u5E93\u7C7B\u578B: sqlite | postgresql | mysql
114
132
  type: ${dbType}
115
133
 
116
- # \u6570\u636E\u5E93\u540D\u79F0
117
- database: ${database}
118
-
119
- # \u8FDE\u63A5\u914D\u7F6E
120
- host: ${host}
121
- port: ${port}
122
- user: ${user}
123
- password: ''
134
+ # SQLite \u4F7F\u7528\u6587\u4EF6\u8DEF\u5F84\uFF0CPostgreSQL/MySQL \u4F7F\u7528\u6570\u636E\u5E93\u540D\u79F0\u3002
135
+ ${stringify({ database }).trim()}
136
+
137
+ ${dbType === "sqlite" ? `# SQLite \u9A71\u52A8\u9009\u9879\uFF1Bworker \u5C06\u67E5\u8BE2\u79FB\u5230\u5DE5\u4F5C\u7EBF\u7A0B\u3002
138
+ # sqlite:
139
+ # walMode: true
140
+ # readonly: false
141
+ # executor: sync # sync | worker
142
+ # workerConnectTimeoutMs: 10000
143
+
144
+ # \u5207\u6362\u5230 PostgreSQL/MySQL \u65F6\u4FEE\u6539 type\u3001database\uFF0C\u5E76\u53D6\u6D88\u8FDE\u63A5\u9879\u7684\u6CE8\u91CA\u3002
145
+ ${stringify({ host: "localhost", port: 5432, user: "postgres", password: "" }).trim().split("\n").map((line) => `# ${line}`).join("\n")}` : `# \u7F51\u7EDC\u6570\u636E\u5E93\u8FDE\u63A5\uFF1B\u51ED\u636E\u901A\u8FC7\u73AF\u5883\u53D8\u91CF\u6CE8\u5165\u3002
146
+ ${connection}
147
+ # SQLite \u66FF\u4EE3\u65B9\u6848\uFF1Atype: sqlite\uFF0Cdatabase: ./data/app.db
148
+ # sqlite:
149
+ # walMode: true
150
+ # readonly: false
151
+ # executor: sync
152
+ # workerConnectTimeoutMs: 10000`}
153
+ ${networkOptions}
154
+
155
+ # SQL \u65E5\u5FD7\u6309\u9700\u5F00\u542F\uFF1BmaxLength \u9650\u5236 SQL / \u53C2\u6570\u8F93\u51FA\u957F\u5EA6\u3002
156
+ # operationLog:
157
+ # read: false
158
+ # write: false
159
+ # maxLength: 1000
160
+ # level: debug # trace | debug | info
124
161
  `;
125
162
  }
126
163
  function generateCacheConfig(cfg) {
127
164
  const cacheType = cfg?.type ?? "memory";
128
- if (cacheType === "memory") {
129
- return `# =============================================================================
130
- # \u7F13\u5B58\u914D\u7F6E
131
- # =============================================================================
132
-
133
- # \u7F13\u5B58\u7C7B\u578B: memory | redis
134
- type: memory
135
-
136
- # Redis \u914D\u7F6E\uFF08\u5F53 type \u4E3A redis \u65F6\u4F7F\u7528\uFF09
137
- # url: redis://localhost:6379/0
138
- # host: localhost
139
- # port: 6379
140
- # password: ''
141
- # keyPrefix: 'hai:'
142
- `;
143
- }
144
165
  const host = cfg?.host ?? "localhost";
145
166
  const port = cfg?.port ?? 6379;
167
+ const connection = stringify({ host, port, password: "", keyPrefix: "hai:" }).trim();
146
168
  return `# =============================================================================
147
169
  # \u7F13\u5B58\u914D\u7F6E
148
170
  # =============================================================================
149
171
 
150
172
  # \u7F13\u5B58\u7C7B\u578B: memory | redis
151
- type: redis
173
+ type: ${cacheType}
152
174
 
153
- # Redis \u914D\u7F6E
154
- host: ${host}
155
- port: ${port}
156
- password: ''
157
- keyPrefix: 'hai:'
175
+ # Redis \u914D\u7F6E\uFF1Bmemory \u65F6\u5747\u4E0D\u751F\u6548\uFF0C\u5207\u6362 type \u540E\u53D6\u6D88\u9700\u8981\u7684\u6CE8\u91CA\u3002
176
+ ${cacheType === "redis" ? connection : connection.split("\n").map((line) => `# ${line}`).join("\n")}
177
+ # url: redis://localhost:6379/0
178
+ # db: 0
179
+ # connectTimeout: 10000
180
+ # commandTimeout: 5000
181
+ # tls: false
182
+ # maxRetries: 3
183
+ # retryDelay: 50
184
+ # readOnly: false
185
+ # \u96C6\u7FA4\u4E0E Sentinel \u4E8C\u9009\u4E00\uFF1B\u666E\u901A Redis \u4E0D\u9700\u8981\u8FD9\u4E24\u5757\u3002
186
+ # cluster:
187
+ # - host: redis-1.internal
188
+ # port: 6379
189
+ # - host: redis-2.internal
190
+ # port: 6379
191
+ # sentinel:
192
+ # sentinels:
193
+ # - host: sentinel.internal
194
+ # port: 26379
195
+ # name: mymaster
158
196
  `;
159
197
  }
160
198
  function generateIamConfig(cfg) {
@@ -169,6 +207,7 @@ login:
169
207
  password: ${loginPassword}
170
208
  otp: ${loginOtp}
171
209
  ldap: false
210
+ apikey: false
172
211
 
173
212
  # \u6CE8\u518C\u4E0E\u767B\u5F55\u5B89\u5168
174
213
  register:
@@ -178,15 +217,31 @@ security:
178
217
  maxLoginAttempts: 5
179
218
  lockoutDuration: 900
180
219
 
181
- # LDAP \u53EF\u9009\uFF1A\u5B89\u88C5 ldapts \u540E\u5F00\u542F login.ldap\uFF0C\u5E76\u58F0\u660E ldap \u8FDE\u63A5\u914D\u7F6E\uFF1B\u4E5F\u53EF\u6CE8\u5165\u5DE5\u5382\u3002
220
+ # LDAP \u53EF\u9009\uFF1A\u5B89\u88C5 ldapts \u540E\u5F00\u542F login.ldap\uFF1B\u4E5F\u53EF\u5728 iam.init \u4E2D\u6CE8\u5165 ldapClientFactory\u3002
221
+ # ldap:
222
+ # url: ldaps://ldap.example.com:636
223
+ # bindDn: cn=service,dc=example,dc=com
224
+ # bindPassword: \${HAI_IAM_LDAP_BINDPASSWORD}
225
+ # searchBase: ou=users,dc=example,dc=com
226
+ # searchFilter: '(uid={{username}})'
227
+ # usernameAttribute: uid
228
+ # emailAttribute: mail
229
+ # displayNameAttribute: cn
230
+ # useTls: false # ldap:// \u8FDE\u63A5\u53EF\u5F00\u542F STARTTLS\uFF1Bldaps:// \u5DF2\u4F7F\u7528 TLS
231
+ # connectTimeout: 5000
232
+ # API Key \u767B\u5F55\u53EF\u9009\uFF1B\u5BC6\u94A5\u7BA1\u7406\u5165\u53E3\u7531\u5E94\u7528\u6309\u6743\u9650\u63A5\u5165\u3002
233
+ # apikey:
234
+ # maxKeysPerUser: 10
235
+ # defaultExpirationDays: 0 # 0 \u8868\u793A\u4E0D\u9650\u5236\u6709\u6548\u671F
236
+ # prefix: hai_
182
237
  # OTP \u9700\u542F\u7528 login.otp\uFF0C\u5E76\u9009\u62E9 Reach \u6807\u51C6\u6A21\u677F\u6216\u81EA\u5B9A\u4E49\u53D1\u9001\u56DE\u8C03\u3002
183
- otp:
238
+ ${(loginOtp ? "" : "# \u4FDD\u7559\u9ED8\u8BA4\u7B56\u7565\u5165\u53E3\uFF0C\u5355\u72EC\u5207\u6362 login.otp \u5373\u53EF\u542F\u7528\u9A8C\u8BC1\u7801\u767B\u5F55\u3002\notp: {}\n# \u5B9A\u5236\u7B56\u7565\u65F6\u7528\u4E0B\u65B9\u914D\u7F6E\u5757\u66FF\u6362\u7A7A\u5BF9\u8C61\uFF0C\u6216\u901A\u8FC7 HAI_IAM_OTP \u6574\u4F53\u8986\u76D6\u3002\n") + `otp:
184
239
  email: true
185
240
  sms: true
186
241
  length: 6
187
242
  expiresIn: 300
188
243
  maxAttempts: 3
189
- resendInterval: 60
244
+ resendInterval: 60`.split("\n").map((line) => loginOtp ? line : `# ${line}`).join("\n")}
190
245
  passwordReset:
191
246
  enabled: true
192
247
  mode: email # phone \u4F7F\u7528 password_reset_sms \u6A21\u677F
@@ -224,6 +279,7 @@ password:
224
279
  requireLowercase: false
225
280
  requireNumber: false
226
281
  requireSpecialChar: false
282
+ expirationDays: 0 # 0 \u8868\u793A\u4E0D\u9650\u5236\u5BC6\u7801\u6709\u6548\u671F
227
283
 
228
284
  # \u4F1A\u8BDD\u914D\u7F6E
229
285
  session:
@@ -234,6 +290,8 @@ session:
234
290
 
235
291
  # RBAC \u914D\u7F6E
236
292
  rbac:
293
+ enabled: true
294
+ superAdminRole: super_admin
237
295
  defaultRole: user
238
296
 
239
297
  # \u662F\u5426\u81EA\u52A8\u521B\u5EFA\u9ED8\u8BA4\u6570\u636E
@@ -241,24 +299,35 @@ seedDefaultData: true
241
299
  `;
242
300
  }
243
301
  function generateStorageConfig(cfg) {
244
- if ((cfg?.type ?? "local") === "local") {
245
- return `# \u5B58\u50A8\u914D\u7F6E\uFF1BHAI_STORAGE \u53EF\u6574\u4F53\u66FF\u6362\u4E3A S3 \u914D\u7F6E\u3002
246
- type: local
247
- root: ${cfg?.localPath ?? "./data/uploads"}
248
- `;
249
- }
250
- return `# S3 \u5B58\u50A8\u914D\u7F6E
251
- type: s3
252
- bucket: ''
302
+ const type = cfg?.type ?? "local";
303
+ const local = `${stringify({ root: cfg?.localPath ?? "./data/uploads" }).trim()}
304
+ # directoryMode: 493 # 0o755
305
+ # fileMode: 420 # 0o644`;
306
+ const s3 = `bucket: ''
253
307
  region: us-east-1
254
308
  accessKeyId: ''
255
309
  secretAccessKey: ''
256
- endpoint: https://s3.amazonaws.com
257
- forcePathStyle: false
310
+ # endpoint: https://s3.amazonaws.com
311
+ # forcePathStyle: false
312
+ # prefix: ''
313
+ # publicUrl: https://cdn.example.com`;
314
+ return `# \u5B58\u50A8\u914D\u7F6E\uFF1BHAI_STORAGE \u53EF\u6574\u4F53\u66FF\u6362\u8FDE\u63A5\u914D\u7F6E\u3002
315
+ type: ${type}
316
+ ${type === "local" ? local : s3}
317
+
318
+ # \u5207\u6362 type \u540E\u4F7F\u7528\u53E6\u4E00\u79CD\u5B58\u50A8\u7684\u8FDE\u63A5\u9879\u3002
319
+ ${(type === "local" ? s3 : local).split("\n").map((line) => line.startsWith("#") ? line : `# ${line}`).join("\n")}
320
+
321
+ # operationLog:
322
+ # read: false
323
+ # write: false
324
+ # maxLength: 1000
325
+ # level: debug # trace | debug | info
258
326
  `;
259
327
  }
260
328
  function generateAiConfig(cfg) {
261
329
  const model = cfg?.model ?? "gpt-4o-mini";
330
+ const api = cfg?.defaultProvider === "anthropic" ? "anthropic" : "chat";
262
331
  return `# =============================================================================
263
332
  # AI \u914D\u7F6E
264
333
  # =============================================================================
@@ -270,18 +339,26 @@ llm:
270
339
  # Base URL\uFF08\u7EA6\u5B9A\u73AF\u5883\u53D8\u91CF HAI_AI_LLM_BASEURL \u4F18\u5148\uFF09
271
340
  # baseUrl: https://api.openai.com/v1
272
341
  # \u9ED8\u8BA4\u6A21\u578B
273
- model: ${model}
342
+ ${stringify({ model }).trim().split("\n").map((line) => ` ${line}`).join("\n")}
343
+ api: ${api} # chat | responses | anthropic
274
344
  # \u5168\u5C40\u6700\u5927 Token \u6570\uFF08\u9ED8\u8BA4 4096\uFF09
275
345
  # maxTokens: 4096
276
346
  # \u91C7\u6837\u6E29\u5EA6\uFF080-2\uFF0C\u9ED8\u8BA4 0.7\uFF09
277
347
  # temperature: 0.7
278
348
  # \u8BF7\u6C42\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF0C\u9ED8\u8BA4 60000\uFF09
279
349
  # timeout: 60000
350
+ # tempModelCacheTtl: 600000
280
351
 
281
352
  # \u591A\u6A21\u578B\u914D\u7F6E\uFF08\u53EF\u9009\uFF0C\u7528\u4E8E\u573A\u666F\u8DEF\u7531\uFF09
282
353
  # models:
283
354
  # - id: fast
284
355
  # model: gpt-4o-mini
356
+ # api: chat
357
+ # apiKey: ''
358
+ # baseUrl: https://api.openai.com/v1
359
+ # maxTokens: 4096
360
+ # temperature: 0.7
361
+ # timeout: 60000
285
362
  # - id: smart
286
363
  # model: gpt-4o
287
364
  # apiKey: ''
@@ -289,10 +366,134 @@ llm:
289
366
  # \u573A\u666F\u6A21\u578B\u6620\u5C04\uFF08\u53EF\u9009\uFF09
290
367
  # scenarios:
291
368
  # default: fast
292
- # analysis: smart
369
+ # chat: fast
370
+ # reasoning: smart
371
+ # plan: smart
372
+ # execute: fast
373
+ # extraction: fast
374
+ # summary: fast
375
+ # embedding: embedding
376
+ # rerank: rerank
377
+ # ocr: vision
378
+ # fast: fast
379
+ # embedding / rerank / vision \u987B\u5728 models \u4E2D\u58F0\u660E\u5BF9\u5E94\u5382\u5546\u6A21\u578B\uFF0C\u4E0D\u80FD\u53EA\u586B\u5199\u573A\u666F ID\u3002
380
+
381
+ # \u53EF\u9009\u5B50\u6A21\u5757\uFF1A\u53EA\u53D6\u6D88\u9700\u8981\u7684\u5757\u7684\u6CE8\u91CA\uFF0C\u6A21\u578B\u3001\u5411\u91CF\u5E93\u4E0E\u6570\u636E\u5E93\u4F9D\u8D56\u6309\u4F7F\u7528\u573A\u666F\u521D\u59CB\u5316\u3002
382
+ # mcp:
383
+ # server:
384
+ # name: my-app
385
+ # version: 1.0.0
386
+ # capabilities:
387
+ # tools: true
388
+ # resources: true
389
+ # prompts: true
390
+ # embedding:
391
+ # dimensions: 1536
392
+ # batchSize: 100
393
+ # knowledge:
394
+ # collection: hai_ai_knowledge
395
+ # dimension: 1536
396
+ # enableEntityExtraction: true
397
+ # entityBoostWeight: 0.15
398
+ # entityTypes: [person, organization, location]
399
+ # systemPrompt: 'Extract entities from the input.'
400
+ # cleanOptions:
401
+ # removeHtml: true
402
+ # removeUrls: false
403
+ # removeEmails: false
404
+ # normalizeWhitespace: true
405
+ # trim: true
406
+ # customReplacements:
407
+ # - pattern: '\\t+'
408
+ # replacement: ' '
409
+ # chunkOptions:
410
+ # mode: markdown # sentence | paragraph | markdown | page | word | character | custom
411
+ # maxSize: 1500
412
+ # overlap: 200
413
+ # separator: '\\n\\n' # \u4EC5 custom \u6A21\u5F0F\u4F7F\u7528
414
+ # markdownMinLevel: 2
415
+ # markdownKeepTitle: true
416
+ # memory:
417
+ # provider: native # native | mem0
418
+ # allowEphemeralFallback: false
419
+ # maxEntriesPerObject: 1000
420
+ # maxEntriesGlobal: 100000
421
+ # systemPrompt: 'Extract useful memories from the conversation.'
422
+ # recencyDecay: 0.95
423
+ # embeddingEnabled: true
424
+ # defaultTopK: 10
425
+ # candidateMultiplier: 5
426
+ # writebackRelatedTopK: 20
427
+ # token:
428
+ # tokenRatio: 0.25
429
+ # summary:
430
+ # systemPrompt: 'Summarize the conversation.'
431
+ # compress:
432
+ # defaultStrategy: hybrid # summary | sliding-window | hybrid
433
+ # defaultMaxTokens: 0
434
+ # preserveLastN: 4
435
+ # retrieval:
436
+ # sources:
437
+ # - id: docs
438
+ # collection: documentation
439
+ # name: Product documentation
440
+ # url: https://docs.example.com
441
+ # topK: 5
442
+ # minScore: 0.7
443
+ # filter:
444
+ # published: true
445
+ # file:
446
+ # systemPrompt: 'Extract text from the image.'
447
+ # a2a:
448
+ # agentCard:
449
+ # name: my-agent
450
+ # description: Application agent
451
+ # url: https://agent.example.com
452
+ # version: 1.0.0
453
+ # skills:
454
+ # - id: chat
455
+ # name: Chat
456
+ # description: General conversation
457
+ # tags: [chat]
458
+ # security:
459
+ # apiKey:
460
+ # in: header # header | query
461
+ # name: x-api-key
462
+ # audio:
463
+ # inheritLlmApiKey: false
464
+ # transcribeModel: asr
465
+ # synthesizeModel: tts
466
+ # maxAudioBytes: 10485760
467
+ # maxStreamDurationMs: 300000
468
+ # models:
469
+ # - id: asr
470
+ # provider: openai # openai | mimo | qwen | doubao | whisper | indextts
471
+ # model: whisper-1
472
+ # operations: [transcribe]
473
+ # apiKey: ''
474
+ # baseUrl: https://api.openai.com/v1
475
+ # timeout: 60000
476
+ # appKey: '' # \u8C46\u5305\u65E7\u7248\u63A7\u5236\u53F0 ASR \u4F7F\u7528
477
+ # accessKey: ''
478
+ # resourceId: ''
479
+ # workspaceId: '' # \u767E\u70BC\u4E1A\u52A1\u7A7A\u95F4
480
+ # - id: tts
481
+ # provider: openai
482
+ # model: tts-1
483
+ # operations: [synthesize]
484
+ # image:
485
+ # generateModel: image
486
+ # models:
487
+ # - id: image
488
+ # provider: openai # openai | google | qwen | seedream | pollinations
489
+ # model: gpt-image-1
490
+ # apiKey: ''
491
+ # baseUrl: https://api.openai.com/v1
492
+ # workspaceId: ''
493
+ # timeout: 120000
293
494
  `;
294
495
  }
295
- function generateEnvExample(features, configs) {
496
+ function generateEnvExample(features, configs, includeDisabled = false) {
296
497
  const sections = [];
297
498
  sections.push(`# =============================================================================
298
499
  # Environment Variables
@@ -300,6 +501,7 @@ function generateEnvExample(features, configs) {
300
501
  #
301
502
  # Copy this file to .env and fill in actual values.
302
503
  # Config files use literal defaults; matching HAI variables override YAML leaves.
504
+ # Uncomment the matching YAML keys before using leaf overrides; HAI_<module> replaces the whole object.
303
505
  #
304
506
  # Naming convention: HAI_<config name>_<YAML path>
305
507
  # =============================================================================`);
@@ -311,7 +513,7 @@ function generateEnvExample(features, configs) {
311
513
  HAI_CORE_ENV=development
312
514
  # Enable debug mode
313
515
  HAI_CORE_DEBUG=false`);
314
- if (features.includes("db")) {
516
+ if (features.includes("db") || includeDisabled) {
315
517
  const dbType = configs?.db?.type ?? "sqlite";
316
518
  const dbDatabase = configs?.db?.database ?? (dbType === "sqlite" ? "./data/app.db" : "hai");
317
519
  const isSqlite = dbType === "sqlite";
@@ -334,7 +536,7 @@ HAI_DB_PORT=${configs?.db?.port ?? (dbType === "postgresql" ? 5432 : 3306)}
334
536
  HAI_DB_USER=${dbType === "postgresql" ? "postgres" : "root"}
335
537
  HAI_DB_PASSWORD=`}`);
336
538
  }
337
- if (features.includes("iam")) {
539
+ if (features.includes("iam") || includeDisabled) {
338
540
  sections.push(`
339
541
  # =============================================================================
340
542
  # IAM (@h-ai/iam)
@@ -342,10 +544,13 @@ HAI_DB_PASSWORD=`}`);
342
544
  # HAI_IAM_PASSWORD_MINLENGTH=8
343
545
  # HAI_IAM_SESSION_MAXAGE=86400
344
546
  # HAI_IAM_SESSION_REFRESHTOKENMAXAGE=604800
547
+ # HAI_IAM_OTP={"email":true,"sms":true,"length":6,"expiresIn":300,"maxAttempts":3,"resendInterval":60}
548
+ # HAI_IAM_LDAP_BINDPASSWORD= # Enable login.ldap and uncomment the ldap block first.
549
+ # HAI_IAM_PASSWORDRESET_RESETURL=https://app.example.com/auth/reset-password
345
550
  # HAI_KIT_COOKIE_KEY= # 32-char hex for SM4-CBC cookie encryption
346
551
  `);
347
552
  }
348
- if (features.includes("cache")) {
553
+ if (features.includes("cache") || includeDisabled) {
349
554
  const cacheType = configs?.cache?.type ?? "memory";
350
555
  if (cacheType === "redis") {
351
556
  sections.push(`
@@ -360,9 +565,9 @@ HAI_CACHE_PORT=${configs?.cache?.port ?? 6379}
360
565
  HAI_CACHE_PASSWORD=
361
566
  # HAI_CACHE_URL=redis://localhost:6379/0
362
567
  # HAI_CACHE_DB=0
363
- # HAI_CACHE_CONNECT_TIMEOUT=10000
364
- # HAI_CACHE_COMMAND_TIMEOUT=5000
365
- # HAI_CACHE_KEY_PREFIX=hai:`);
568
+ # HAI_CACHE_CONNECTTIMEOUT=10000
569
+ # HAI_CACHE_COMMANDTIMEOUT=5000
570
+ # HAI_CACHE_KEYPREFIX=hai:`);
366
571
  } else {
367
572
  sections.push(`
368
573
  # =============================================================================
@@ -376,12 +581,12 @@ HAI_CACHE_TYPE=memory
376
581
  # HAI_CACHE_PORT=6379
377
582
  # HAI_CACHE_PASSWORD=
378
583
  # HAI_CACHE_DB=0
379
- # HAI_CACHE_CONNECT_TIMEOUT=10000
380
- # HAI_CACHE_COMMAND_TIMEOUT=5000
381
- # HAI_CACHE_KEY_PREFIX=hai:`);
584
+ # HAI_CACHE_CONNECTTIMEOUT=10000
585
+ # HAI_CACHE_COMMANDTIMEOUT=5000
586
+ # HAI_CACHE_KEYPREFIX=hai:`);
382
587
  }
383
588
  }
384
- if (features.includes("storage")) {
589
+ if (features.includes("storage") || includeDisabled) {
385
590
  const storageType = configs?.storage?.type ?? "local";
386
591
  if (storageType === "s3") {
387
592
  sections.push(`
@@ -417,46 +622,23 @@ HAI_STORAGE_ROOT=${configs?.storage?.localPath ?? "./data/uploads"}
417
622
  # HAI_STORAGE_FORCEPATHSTYLE=false`);
418
623
  }
419
624
  }
420
- if (features.includes("ai")) {
421
- const provider = configs?.ai?.defaultProvider ?? "openai";
422
- if (provider === "anthropic") {
423
- sections.push(`
424
- # =============================================================================
425
- # AI (@h-ai/ai)
426
- # =============================================================================
427
- # OpenAI-compatible API Key (Anthropic models via OpenAI-compatible proxy)
428
- HAI_AI_LLM_APIKEY=
429
- # HAI_AI_LLM_BASEURL= # Custom base URL
430
- # Optional compatibility fallback
431
- # OPENAI_API_KEY=`);
432
- } else if (provider === "openai") {
433
- sections.push(`
434
- # =============================================================================
435
- # AI (@h-ai/ai)
436
- # =============================================================================
437
- # OpenAI / OpenAI-compatible
438
- HAI_AI_LLM_APIKEY=
439
- # HAI_AI_LLM_BASEURL= # Custom base URL (e.g. local proxy, Azure)
440
- # Optional compatibility fallback
441
- # OPENAI_API_KEY=`);
442
- } else {
443
- sections.push(`
625
+ if (features.includes("ai") || includeDisabled) {
626
+ sections.push(`
444
627
  # =============================================================================
445
628
  # AI (@h-ai/ai)
446
629
  # =============================================================================
447
- # OpenAI-compatible provider
630
+ # Select chat / responses / anthropic in _ai.yml (llm.api).
448
631
  HAI_AI_LLM_APIKEY=
449
632
  # HAI_AI_LLM_BASEURL= # Custom base URL
450
633
  # Optional compatibility fallback
451
634
  # OPENAI_API_KEY=`);
452
- }
453
635
  }
454
- if (features.includes("vecdb")) {
636
+ if (features.includes("vecdb") || includeDisabled) {
455
637
  sections.push(`
456
638
  # =============================================================================
457
639
  # Vector Database (@h-ai/vecdb)
458
640
  # =============================================================================
459
- # Backend type: lancedb | pgvector | qdrant
641
+ # Backend type: lancedb | pgvector | qdrant | chroma
460
642
  HAI_VECDB_TYPE=lancedb
461
643
  # LanceDB data path
462
644
  HAI_VECDB_PATH=./data/vecdb
@@ -465,7 +647,7 @@ HAI_VECDB_PATH=./data/vecdb
465
647
  # HAI_VECDB_APIKEY=
466
648
  `);
467
649
  }
468
- if (features.includes("reach")) {
650
+ if (features.includes("reach") || includeDisabled) {
469
651
  sections.push(`
470
652
  # =============================================================================
471
653
  # Reach (@h-ai/reach)
@@ -476,9 +658,13 @@ HAI_VECDB_PATH=./data/vecdb
476
658
  # HAI_REACH_SMTP_USER=
477
659
  # HAI_REACH_SMTP_PASS=
478
660
  # HAI_REACH_SMTP_FROM=noreply@example.com
661
+ # HAI_REACH_SMS_ACCESS_KEY=
662
+ # HAI_REACH_SMS_SECRET_KEY=
663
+ # HAI_REACH_API_TOKEN=
664
+ # HAI_REACH_PROVIDERS= # JSON array replacing all providers, while retaining templates.
479
665
  `);
480
666
  }
481
- if (features.includes("payment")) {
667
+ if (features.includes("payment") || includeDisabled) {
482
668
  sections.push(`
483
669
  # =============================================================================
484
670
  # Payment (@h-ai/payment)
@@ -488,6 +674,7 @@ HAI_VECDB_PATH=./data/vecdb
488
674
  # HAI_PAYMENT_WECHAT_APIV3KEY=
489
675
  # HAI_PAYMENT_WECHAT_SERIALNO=
490
676
  # HAI_PAYMENT_WECHAT_PRIVATEKEY=
677
+ # HAI_PAYMENT_WECHAT_PLATFORMCERT=
491
678
  # HAI_PAYMENT_WECHAT_APPID=
492
679
  # Alipay
493
680
  # HAI_PAYMENT_ALIPAY_APPID=
@@ -496,6 +683,42 @@ HAI_VECDB_PATH=./data/vecdb
496
683
  # Stripe
497
684
  # HAI_PAYMENT_STRIPE_SECRETKEY=
498
685
  # HAI_PAYMENT_STRIPE_WEBHOOKSECRET=
686
+ `);
687
+ }
688
+ if (features.includes("deploy") || includeDisabled) {
689
+ sections.push(`
690
+ # =============================================================================
691
+ # Deployment (@h-ai/deploy)
692
+ # =============================================================================
693
+ # HAI_DEPLOY_VERCEL_TOKEN=
694
+ # HAI_DEPLOY_SSH_HOST=
695
+ # HAI_DEPLOY_SSH_KEY=
696
+ # HAI_DEPLOY_SSH_KNOWNHOSTSFILE=
697
+ # HAI_DEPLOY_NEON_API_KEY=
698
+ # HAI_DEPLOY_UPSTASH_EMAIL=
699
+ # HAI_DEPLOY_UPSTASH_API_KEY=
700
+ # HAI_DEPLOY_CF_ACCOUNT_ID=
701
+ # HAI_DEPLOY_CF_API_TOKEN=
702
+ # HAI_DEPLOY_R2_ACCESS_KEY_ID=
703
+ # HAI_DEPLOY_R2_SECRET_ACCESS_KEY=
704
+ # HAI_DEPLOY_RESEND_API_KEY=
705
+ # HAI_DEPLOY_RESEND_FROM=
706
+ # HAI_DEPLOY_ALIYUN_ACCESS_KEY_ID=
707
+ # HAI_DEPLOY_ALIYUN_ACCESS_KEY_SECRET=
708
+ # HAI_DEPLOY_ALIYUN_SIGN_NAME=
709
+ `);
710
+ }
711
+ if (includeDisabled) {
712
+ sections.push(`
713
+ # =============================================================================
714
+ # Service (@h-ai/serv)
715
+ # =============================================================================
716
+ # HOST=127.0.0.1 # HOST/PORT override _serv.yml server settings.
717
+ # PORT=3000
718
+ # HAI_CORS_ORIGIN=http://127.0.0.1:4173,http://localhost:4173
719
+ # HAI_CORS_NATIVEORIGINS=http://localhost,https://localhost,http://tauri.localhost,https://tauri.localhost,tauri://localhost,capacitor://localhost
720
+ # HAI_CORS_CREDENTIALS=true
721
+ # HAI_SERV_HTTP_RPC_GATEWAYSECRET= # Enable the gateway-only RPC block before setting this.
499
722
  `);
500
723
  }
501
724
  sections.push(`
@@ -505,7 +728,8 @@ HAI_VECDB_PATH=./data/vecdb
505
728
  # E2E test mode (relaxes rate limiting etc.)
506
729
  # HAI_E2E=1
507
730
  `);
508
- return sections.join("\n");
731
+ const content = sections.join("\n");
732
+ return includeDisabled ? content.split("\n").map((line) => line && !line.startsWith("#") ? `# ${line}` : line).join("\n") : content;
509
733
  }
510
734
  function generateDeployConfig() {
511
735
  return `# =============================================================================
@@ -531,6 +755,9 @@ provider:
531
755
  # port: 22
532
756
  # username: deploy
533
757
  # identityFile: \${HAI_DEPLOY_SSH_KEY} # \u79C1\u94A5\u6587\u4EF6\u8DEF\u5F84\uFF08\u7701\u7565\u5219\u7528 ssh-agent\uFF09
758
+ # knownHostsFile: \${HAI_DEPLOY_SSH_KNOWNHOSTSFILE}
759
+ # strictHostKeyChecking: true
760
+ # connectTimeoutSeconds: 10
534
761
  # remote:
535
762
  # baseDir: /opt/hai/apps
536
763
  # runtime: auto # auto \u4F18\u5148 podman\uFF0C\u5176\u6B21 docker
@@ -544,7 +771,7 @@ provider:
544
771
  # runtime: auto
545
772
 
546
773
  # \u57FA\u7840\u8BBE\u65BD\u670D\u52A1\uFF08\u6309\u9700\u5F00\u542F\uFF09
547
- services:
774
+ # services:
548
775
  # PostgreSQL \u6570\u636E\u5E93 (Neon)
549
776
  # db:
550
777
  # provisioner: neon
@@ -588,7 +815,7 @@ function generateVecdbConfig() {
588
815
  # \u5411\u91CF\u6570\u636E\u5E93\u914D\u7F6E (@h-ai/vecdb)
589
816
  # =============================================================================
590
817
 
591
- # \u6570\u636E\u5E93\u7C7B\u578B: lancedb | pgvector | qdrant
818
+ # \u6570\u636E\u5E93\u7C7B\u578B: lancedb | pgvector | qdrant | chroma
592
819
  type: lancedb
593
820
 
594
821
  # LanceDB \u6570\u636E\u76EE\u5F55
@@ -599,6 +826,7 @@ path: ./data/vecdb
599
826
 
600
827
  # pgvector \u914D\u7F6E\uFF08\u5F53 type \u4E3A pgvector \u65F6\u4F7F\u7528\uFF09
601
828
  # type: pgvector
829
+ # url: \${HAI_VECDB_URL}
602
830
  # host: localhost
603
831
  # port: 5432
604
832
  # database: hai
@@ -611,6 +839,22 @@ path: ./data/vecdb
611
839
  # type: qdrant
612
840
  # url: http://localhost:6333
613
841
  # apiKey: ''
842
+
843
+ # Chroma \u914D\u7F6E\uFF08\u66FF\u6362 type\uFF1Burl \u6307\u5411\u5DF2\u6709\u670D\u52A1\uFF0Cpath \u7528\u4E8E\u672C\u5730\u5B50\u8FDB\u7A0B\u6570\u636E\u76EE\u5F55\uFF09
844
+ # type: chroma
845
+ # path: ./data/chroma
846
+ # url: http://localhost:8000
847
+ # host: localhost
848
+ # port: 8000
849
+ # apiKey: ''
850
+ # serverCommand: chroma
851
+ # startupTimeout: 30000
852
+
853
+ # operationLog:
854
+ # read: false
855
+ # write: false
856
+ # maxLength: 1000
857
+ # level: debug # trace | debug | info
614
858
  `;
615
859
  }
616
860
  function generateReachConfig() {
@@ -639,6 +883,16 @@ providers:
639
883
  # accessKeyId: \${HAI_REACH_SMS_ACCESS_KEY}
640
884
  # accessKeySecret: \${HAI_REACH_SMS_SECRET_KEY}
641
885
  # signName: MyApp
886
+ # endpoint: dysmsapi.aliyuncs.com
887
+
888
+ # \u901A\u7528 API\uFF08\u6309\u9700\u5F00\u542F\uFF1B\u53EF\u5BF9\u63A5\u5E94\u7528\u81EA\u6709\u6295\u9012\u670D\u52A1\uFF09
889
+ # - name: custom
890
+ # type: api
891
+ # url: https://notify.example.com/send
892
+ # method: POST # POST | PUT
893
+ # headers:
894
+ # Authorization: 'Bearer \${HAI_REACH_API_TOKEN}'
895
+ # timeout: 10000
642
896
 
643
897
  # IAM \u6807\u51C6\u6A21\u677F\uFF1A\u4FDD\u7559\u7A7A\u6570\u7EC4\u4EE5\u652F\u6301 HAI_REACH_TEMPLATES \u6574\u4F53\u8986\u76D6\u3002
644
898
  templates: []
@@ -675,20 +929,17 @@ function generateSchedulerConfig() {
675
929
  # \u662F\u5426\u542F\u7528\u6570\u636E\u5E93\u65E5\u5FD7\uFF08\u9700\u8981 @h-ai/reldb\uFF09
676
930
  enableDb: true
677
931
 
678
- # \u6267\u884C\u65E5\u5FD7\u8868\u540D
679
- tableName: hai_scheduler_logs
680
-
681
- # \u4EFB\u52A1\u5B9A\u4E49\u8868\u540D
682
- taskTableName: hai_scheduler_tasks
683
-
684
- # \u5206\u5E03\u5F0F\u9501\u8868\u540D
685
- lockTableName: hai_scheduler_locks
686
-
687
932
  # \u68C0\u67E5\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09
688
933
  tickInterval: 1000
689
934
 
690
935
  # \u9501\u8FC7\u671F\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09
691
936
  lockExpireMs: 300000
937
+
938
+ # \u8282\u70B9 ID \u9ED8\u8BA4\u81EA\u52A8\u751F\u6210\uFF1B\u591A\u8282\u70B9\u90E8\u7F72\u65F6\u6BCF\u4E2A\u5B9E\u4F8B\u5E94\u4F7F\u7528\u72EC\u7ACB ID\u3002
939
+ # nodeId: worker-1
940
+ # \u6267\u884C\u65E5\u5FD7\u4FDD\u7559\u7B56\u7565\uFF08\u542F\u7528\u6570\u636E\u5E93\u65F6\u4F7F\u7528\uFF09
941
+ # maxLogs: 10000
942
+ # retentionDays: 30
692
943
  `;
693
944
  }
694
945
  function generateAuditConfig() {
@@ -717,6 +968,7 @@ function generatePaymentConfig() {
717
968
  # apiV3Key: ''
718
969
  # serialNo: ''
719
970
  # privateKey: ''
971
+ # platformCert: ''
720
972
  # appId: ''
721
973
 
722
974
  # \u652F\u4ED8\u5B9D\uFF08\u6309\u9700\u5F00\u542F\uFF09
@@ -731,9 +983,10 @@ function generatePaymentConfig() {
731
983
  # stripe:
732
984
  # secretKey: ''
733
985
  # webhookSecret: ''
986
+ # webhookToleranceSeconds: 300
734
987
  `;
735
988
  }
736
989
 
737
990
  export { generateConfigFile, generateEnvExample };
738
- //# sourceMappingURL=chunk-P6X63D3I.js.map
739
- //# sourceMappingURL=chunk-P6X63D3I.js.map
991
+ //# sourceMappingURL=chunk-WW2MIO6T.js.map
992
+ //# sourceMappingURL=chunk-WW2MIO6T.js.map