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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.en.md +20 -8
  2. package/README.ja.md +20 -8
  3. package/README.md +20 -8
  4. package/dist/{chunk-MUHRBJSW.js → chunk-K6RWTTHD.js} +546 -97
  5. package/dist/chunk-K6RWTTHD.js.map +1 -0
  6. package/dist/{chunk-AKV2CQZV.js → chunk-SWEU7KUE.js} +71 -59
  7. package/dist/chunk-SWEU7KUE.js.map +1 -0
  8. package/dist/{chunk-EF7WOFWZ.js → chunk-YVNNMC4H.js} +364 -136
  9. package/dist/chunk-YVNNMC4H.js.map +1 -0
  10. package/dist/cli-config-templates-LUJGDQNW.js +5 -0
  11. package/dist/{cli-config-templates-HHFHNXBN.js.map → cli-config-templates-LUJGDQNW.js.map} +1 -1
  12. package/dist/{cli-skill-templates-PN4FLGBC.js → cli-skill-templates-VV2XWYON.js} +3 -3
  13. package/dist/{cli-skill-templates-PN4FLGBC.js.map → cli-skill-templates-VV2XWYON.js.map} +1 -1
  14. package/dist/index.js +117 -208
  15. package/dist/index.js.map +1 -1
  16. package/dist/metafile-esm.json +1 -1
  17. package/dist/{src-TEBHR5I5.js → src-IR5AU43K.js} +3 -3
  18. package/dist/src-IR5AU43K.js.map +1 -0
  19. package/package.json +11 -11
  20. package/templates/apps/api/.dockerignore.hbs +10 -0
  21. package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +20 -1
  22. package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +6 -1
  23. package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +1 -1
  24. package/templates/apps/api/images/serv.Dockerfile.hbs +3 -2
  25. package/templates/apps/fullstack/.dockerignore.hbs +10 -0
  26. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +1 -1
  27. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +16 -2
  28. package/templates/apps/fullstack/images/serv.Dockerfile.hbs +6 -2
  29. package/templates/apps/fullstack/images/web.Dockerfile.hbs +6 -1
  30. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +1 -1
  31. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +10 -7
  32. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +14 -7
  33. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +6 -0
  34. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +1 -1
  35. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +7 -1
  36. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +1 -1
  37. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +1 -0
  38. package/templates/apps/website/scripts/static-website.mjs.hbs +3 -3
  39. package/templates/base/.dockerignore.hbs +10 -0
  40. package/templates/base/images/web.Dockerfile.hbs +4 -2
  41. package/templates/base/package.json.hbs +1 -1
  42. package/templates/base/src/hooks.server.ts.hbs +9 -7
  43. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +3 -1
  44. package/templates/skills/hai-ai/guide.md +5 -3
  45. package/templates/skills/hai-app-create/development.md +7 -3
  46. package/templates/skills/hai-app-create/reference.md +1 -1
  47. package/templates/skills/hai-build/SKILL.md +5 -5
  48. package/templates/skills/hai-build/paths.md +1 -1
  49. package/templates/skills/hai-build/reference.md +1 -1
  50. package/templates/skills/hai-deploy/SKILL.md +15 -3
  51. package/templates/skills/hai-deploy/middleware.md +4 -2
  52. package/templates/skills/hai-serv/reference.md +5 -8
  53. package/dist/chunk-AKV2CQZV.js.map +0 -1
  54. package/dist/chunk-EF7WOFWZ.js.map +0 -1
  55. package/dist/chunk-MUHRBJSW.js.map +0 -1
  56. package/dist/cli-config-templates-HHFHNXBN.js +0 -5
  57. package/dist/src-TEBHR5I5.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { parseDocument, isScalar, stringify, isMap, isSeq, Scalar } from 'yaml';
2
+ import { parseDocument, LineCounter, isScalar, stringify, isMap, isSeq, Scalar } from 'yaml';
3
3
 
4
4
  // src/commands/cli-config-catalog.json
5
5
  var cli_config_catalog_default = [
@@ -859,19 +859,11 @@ var cli_config_catalog_default = [
859
859
  value: "",
860
860
  constraint: "JSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9"
861
861
  },
862
- {
863
- name: "HAI_AI_LLM_API",
864
- module: "ai",
865
- path: "ai.llm.api",
866
- description: "\u5168\u5C40 API \u534F\u8BAE\uFF08\u5404\u6A21\u578B fallback\uFF0C\u9ED8\u8BA4 `'chat'`\uFF1B\u53EF\u9009 `chat` / `responses` / `anthropic`\uFF09",
867
- value: "chat",
868
- constraint: "\u5B57\u7B26\u4E32\uFF1B\u53D6\u503C\uFF1Achat | responses | anthropic"
869
- },
870
862
  {
871
863
  name: "HAI_AI_LLM_APIKEY",
872
864
  module: "ai",
873
865
  path: "ai.llm.apiKey",
874
- description: "\u5168\u5C40 API Key\uFF08\u5404\u6A21\u578B fallback\uFF1B\u672A\u63D0\u4F9B\u65F6\u56DE\u9000\u5230 `process.env.HAI_AI_LLM_APIKEY` \u6216 `process.env.OPENAI_API_KEY`\uFF09",
866
+ description: "\u9ED8\u8BA4\u670D\u52A1\u5BC6\u94A5\uFF1B\u6A21\u578B\u9879\u53EF\u5355\u72EC\u8986\u76D6\u3002\u672A\u586B\u5199\u65F6\u8BFB\u53D6 HAI_AI_LLM_APIKEY \u6216\u5BF9\u5E94\u4F9B\u5E94\u5546\u5BC6\u94A5\u53D8\u91CF\uFF0C\u771F\u5B9E\u503C\u53EA\u653E\u670D\u52A1\u7AEF\u3002",
875
867
  value: "",
876
868
  constraint: "string,null"
877
869
  },
@@ -879,7 +871,7 @@ var cli_config_catalog_default = [
879
871
  name: "HAI_AI_LLM_BASEURL",
880
872
  module: "ai",
881
873
  path: "ai.llm.baseUrl",
882
- description: "\u5168\u5C40 API \u57FA\u7840 URL\uFF08\u5404\u6A21\u578B fallback\uFF1B\u672A\u63D0\u4F9B\u65F6\u56DE\u9000\u5230 `process.env.HAI_AI_LLM_BASEURL` \u6216 `process.env.OPENAI_BASE_URL`\uFF09",
874
+ description: "\u9ED8\u8BA4\u6A21\u578B\u670D\u52A1\u5730\u5740\uFF1B\u4F7F\u7528\u4EE3\u7406\u65F6\u586B\u5199\uFF0C\u6A21\u578B\u9879\u53EF\u8986\u76D6\u3002\u672A\u586B\u5199\u65F6\u6309\u534F\u8BAE\u8BFB\u53D6\u73AF\u5883\u5730\u5740\u6216\u4F7F\u7528\u4F9B\u5E94\u5546\u9ED8\u8BA4\u5730\u5740\u3002",
883
875
  value: "",
884
876
  constraint: "\u5B57\u7B26\u4E32\uFF1B\u683C\u5F0F uri"
885
877
  },
@@ -887,7 +879,7 @@ var cli_config_catalog_default = [
887
879
  name: "HAI_AI_LLM_MAXTOKENS",
888
880
  module: "ai",
889
881
  path: "ai.llm.maxTokens",
890
- description: "\u5168\u5C40\u6700\u5927 Token \u6570\uFF08\u5404\u6A21\u578B fallback\uFF0C\u9ED8\u8BA4 `4096`\uFF09",
882
+ description: "\u5355\u6B21\u56DE\u7B54\u6700\u591A\u751F\u6210\u591A\u5C11 Token\uFF0C\u9ED8\u8BA4 4096\uFF1B\u6A21\u578B\u9879\u53EF\u8986\u76D6\uFF0C\u9700\u7B26\u5408\u4F9B\u5E94\u5546\u9650\u5236\u3002",
891
883
  value: "4096",
892
884
  constraint: "\u6570\u5B57\uFF1B> 0"
893
885
  },
@@ -915,14 +907,6 @@ var cli_config_catalog_default = [
915
907
  value: "",
916
908
  constraint: "JSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9"
917
909
  },
918
- {
919
- name: "HAI_AI_LLM_MODELS_0_API",
920
- module: "ai",
921
- path: "ai.llm.models.0.api",
922
- description: "API \u534F\u8BAE\uFF08\u53EF\u9009\uFF0C\u672A\u6307\u5B9A\u65F6\u56DE\u9000\u5168\u5C40 `api`\uFF0C\u518D\u56DE\u9000 `chat`\uFF1B\u51B3\u5B9A\u8D70 Chat Completions / Responses / Anthropic\uFF09",
923
- value: "chat",
924
- constraint: "\u5B57\u7B26\u4E32\uFF1B\u53D6\u503C\uFF1Achat | responses | anthropic"
925
- },
926
910
  {
927
911
  name: "HAI_AI_LLM_MODELS_0_APIKEY",
928
912
  module: "ai",
@@ -963,6 +947,14 @@ var cli_config_catalog_default = [
963
947
  value: "",
964
948
  constraint: "\u5B57\u7B26\u4E32"
965
949
  },
950
+ {
951
+ name: "HAI_AI_LLM_MODELS_0_PROTOCOL",
952
+ module: "ai",
953
+ path: "ai.llm.models.0.protocol",
954
+ description: "API \u534F\u8BAE\uFF08\u53EF\u9009\uFF0C\u672A\u6307\u5B9A\u65F6\u56DE\u9000\u5168\u5C40 `protocol`\uFF0C\u518D\u56DE\u9000 `chat`\uFF1B\u51B3\u5B9A\u8D70 Chat Completions / Responses / Anthropic\uFF09",
955
+ value: "chat",
956
+ constraint: "\u5B57\u7B26\u4E32\uFF1B\u53D6\u503C\uFF1Achat | responses | anthropic"
957
+ },
966
958
  {
967
959
  name: "HAI_AI_LLM_MODELS_0_TEMPERATURE",
968
960
  module: "ai",
@@ -979,6 +971,14 @@ var cli_config_catalog_default = [
979
971
  value: "",
980
972
  constraint: "\u6570\u5B57\uFF1B> 0"
981
973
  },
974
+ {
975
+ name: "HAI_AI_LLM_PROTOCOL",
976
+ module: "ai",
977
+ path: "ai.llm.protocol",
978
+ description: "\u9ED8\u8BA4\u8BF7\u6C42\u683C\u5F0F\uFF1Achat \u4E3A Chat Completions\uFF0Cresponses \u4E3A OpenAI Responses\uFF0Canthropic \u4E3A Anthropic Messages\uFF1B\u6A21\u578B\u9879\u53EF\u8986\u76D6\u3002",
979
+ value: "chat",
980
+ constraint: "\u5B57\u7B26\u4E32\uFF1B\u53D6\u503C\uFF1Achat | responses | anthropic"
981
+ },
982
982
  {
983
983
  name: "HAI_AI_LLM_SCENARIOS",
984
984
  module: "ai",
@@ -1079,7 +1079,7 @@ var cli_config_catalog_default = [
1079
1079
  name: "HAI_AI_LLM_TEMPERATURE",
1080
1080
  module: "ai",
1081
1081
  path: "ai.llm.temperature",
1082
- description: "\u5168\u5C40\u91C7\u6837\u6E29\u5EA6\uFF08\u5404\u6A21\u578B fallback\uFF0C\u8303\u56F4 `[0, 2]`\uFF0C\u9ED8\u8BA4 `0.7`\uFF09",
1082
+ description: "\u56DE\u7B54\u7684\u968F\u673A\u7A0B\u5EA6\uFF0C0\u20132\uFF0C\u9ED8\u8BA4 0.7\uFF1B\u8F83\u4F4E\u901A\u5E38\u66F4\u7A33\u5B9A\uFF0C\u6A21\u578B\u9879\u53EF\u8986\u76D6\uFF0C\u90E8\u5206\u6A21\u578B\u4E0D\u652F\u6301\u81EA\u5B9A\u4E49\u3002",
1083
1083
  value: "0.7",
1084
1084
  constraint: "\u6570\u5B57\uFF1B>= 0\uFF1B<= 2"
1085
1085
  },
@@ -1095,7 +1095,7 @@ var cli_config_catalog_default = [
1095
1095
  name: "HAI_AI_LLM_TIMEOUT",
1096
1096
  module: "ai",
1097
1097
  path: "ai.llm.timeout",
1098
- description: "\u5168\u5C40\u8BF7\u6C42\u8D85\u65F6\u65F6\u95F4\uFF08\u5404\u6A21\u578B fallback\uFF0C\u6BEB\u79D2\uFF0C\u9ED8\u8BA4 `60000`\uFF09",
1098
+ description: "\u4E00\u6B21\u6A21\u578B\u8BF7\u6C42\u6700\u591A\u7B49\u5F85\u591A\u5C11\u6BEB\u79D2\uFF0C\u9ED8\u8BA4 60000\uFF1B\u6A21\u578B\u9879\u53EF\u8986\u76D6\u3002",
1099
1099
  value: "60000",
1100
1100
  constraint: "\u6570\u5B57\uFF1B> 0"
1101
1101
  },
@@ -2031,7 +2031,7 @@ var cli_config_catalog_default = [
2031
2031
  name: "HAI_CORE_LOGGING_REDACT",
2032
2032
  module: "core",
2033
2033
  path: "core.logging.redact",
2034
- description: "\u8981\u8131\u654F\u7684\u5B57\u6BB5\u8DEF\u5F84\u5217\u8868\uFF08\u5982 ['password', 'token']\uFF0C\u9ED8\u8BA4 []\uFF09",
2034
+ description: "\u989D\u5916\u4E1A\u52A1\u9690\u79C1\u7684\u65E5\u5FD7\u5B57\u6BB5\u8DEF\u5F84\uFF0C\u5982 customer.email\u3001recipients[*].phone\uFF1B* \u5339\u914D\u4E00\u5C42\uFF0C\u533A\u5206\u5927\u5C0F\u5199\uFF0C\u9ED8\u8BA4 []\u3002\u5DF2\u77E5\u5BC6\u7801/\u4EE4\u724C\u59CB\u7EC8\u8131\u654F\u3002",
2035
2035
  value: "[]",
2036
2036
  constraint: "JSON \u6570\u7EC4\uFF1B\u7D22\u5F15\u53EF\u6309 0\u30011\u30012 \u6269\u5C55"
2037
2037
  },
@@ -2039,7 +2039,7 @@ var cli_config_catalog_default = [
2039
2039
  name: "HAI_CORE_LOGGING_REDACT_0",
2040
2040
  module: "core",
2041
2041
  path: "core.logging.redact.0",
2042
- description: "\u8981\u8131\u654F\u7684\u5B57\u6BB5\u8DEF\u5F84\u5217\u8868\uFF08\u5982 ['password', 'token']\uFF0C\u9ED8\u8BA4 []\uFF09\uFF1B\u6B64\u53D8\u91CF\u6574\u4F53\u66FF\u6362\u5355\u4E2A\u6570\u7EC4\u9879",
2042
+ description: "\u989D\u5916\u4E1A\u52A1\u9690\u79C1\u7684\u65E5\u5FD7\u5B57\u6BB5\u8DEF\u5F84\uFF0C\u5982 customer.email\u3001recipients[*].phone\uFF1B* \u5339\u914D\u4E00\u5C42\uFF0C\u533A\u5206\u5927\u5C0F\u5199\uFF0C\u9ED8\u8BA4 []\u3002\u5DF2\u77E5\u5BC6\u7801/\u4EE4\u724C\u59CB\u7EC8\u8131\u654F\u3002\uFF1B\u6B64\u53D8\u91CF\u6574\u4F53\u66FF\u6362\u5355\u4E2A\u6570\u7EC4\u9879",
2043
2043
  value: "",
2044
2044
  constraint: "\u5B57\u7B26\u4E32"
2045
2045
  },
@@ -2419,6 +2419,78 @@ var cli_config_catalog_default = [
2419
2419
  value: "18080",
2420
2420
  constraint: "\u6574\u6570\uFF1B>= 1\uFF1B<= 65535"
2421
2421
  },
2422
+ {
2423
+ name: "HAI_DEPLOY_PROVIDER_EXPOSE_HTTPS",
2424
+ module: "deploy",
2425
+ path: "deploy.provider.expose.https",
2426
+ description: "\u53EF\u9009 HTTPS \u5165\u53E3\uFF1Bfiles \u4F7F\u7528\u5DF2\u6709\u8BC1\u4E66\uFF0Cletsencrypt \u4F7F\u7528\u5B98\u65B9 Certbot \u7533\u8BF7\u7EED\u671F\uFF0C\u7701\u7565\u4FDD\u6301 HTTP",
2427
+ value: "",
2428
+ constraint: "JSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9"
2429
+ },
2430
+ {
2431
+ name: "HAI_DEPLOY_PROVIDER_EXPOSE_HTTPS_ACCEPTTERMS",
2432
+ module: "deploy",
2433
+ path: "deploy.provider.expose.https.acceptTerms",
2434
+ description: "\u660E\u786E\u540C\u610F Let\u2019s Encrypt \u670D\u52A1\u6761\u6B3E\u540E\u624D\u53EF\u8BBE\u7F6E\u4E3A true",
2435
+ value: "true",
2436
+ constraint: "true\uFF1B\u53D6\u503C\uFF1Atrue"
2437
+ },
2438
+ {
2439
+ name: "HAI_DEPLOY_PROVIDER_EXPOSE_HTTPS_CERTIFICATEFILE",
2440
+ module: "deploy",
2441
+ path: "deploy.provider.expose.https.certificateFile",
2442
+ description: "PEM \u5B8C\u6574\u8BC1\u4E66\u94FE\u8DEF\u5F84\uFF0C\u76F8\u5BF9\u5DE5\u7A0B\u6839\u6216\u7EDD\u5BF9\u8DEF\u5F84\uFF1B\u6253\u5305\u65F6\u590D\u5236\u5230\u79C1\u6709\u53D1\u5E03\u76EE\u5F55",
2443
+ value: "",
2444
+ constraint: "\u5B57\u7B26\u4E32\uFF1B\u6700\u5C0F\u5B57\u7B26\u6570 1"
2445
+ },
2446
+ {
2447
+ name: "HAI_DEPLOY_PROVIDER_EXPOSE_HTTPS_DOMAIN",
2448
+ module: "deploy",
2449
+ path: "deploy.provider.expose.https.domain",
2450
+ description: "HTTPS \u516C\u5F00\u57DF\u540D\uFF1B\u8BC1\u4E66\u5FC5\u987B\u5339\u914D\u8BE5\u57DF\u540D",
2451
+ value: "",
2452
+ constraint: "\u5B57\u7B26\u4E32\uFF1B\u6700\u5927\u5B57\u7B26\u6570 253\uFF1B\u6B63\u5219 ^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$"
2453
+ },
2454
+ {
2455
+ name: "HAI_DEPLOY_PROVIDER_EXPOSE_HTTPS_EMAIL",
2456
+ module: "deploy",
2457
+ path: "deploy.provider.expose.https.email",
2458
+ description: "Let\u2019s Encrypt \u8D26\u53F7\u8054\u7CFB\u90AE\u7BB1",
2459
+ value: "",
2460
+ constraint: "\u5B57\u7B26\u4E32\uFF1B\u683C\u5F0F email\uFF1B\u6B63\u5219 ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
2461
+ },
2462
+ {
2463
+ name: "HAI_DEPLOY_PROVIDER_EXPOSE_HTTPS_PORT",
2464
+ module: "deploy",
2465
+ path: "deploy.provider.expose.https.port",
2466
+ description: "HTTPS \u5BBF\u4E3B\u7AEF\u53E3\uFF0C\u9ED8\u8BA4 443\uFF0C\u987B\u4E0E HTTP \u7AEF\u53E3\u4E0D\u540C",
2467
+ value: "443",
2468
+ constraint: "\u6574\u6570\uFF1B>= 1\uFF1B<= 65535"
2469
+ },
2470
+ {
2471
+ name: "HAI_DEPLOY_PROVIDER_EXPOSE_HTTPS_PRIVATEKEYFILE",
2472
+ module: "deploy",
2473
+ path: "deploy.provider.expose.https.privateKeyFile",
2474
+ description: "\u672A\u52A0\u5BC6 PEM \u79C1\u94A5\u8DEF\u5F84\uFF0C\u76F8\u5BF9\u5DE5\u7A0B\u6839\u6216\u7EDD\u5BF9\u8DEF\u5F84\uFF1B\u5FC5\u987B\u4E0E\u8BC1\u4E66\u5339\u914D",
2475
+ value: "",
2476
+ constraint: "\u5B57\u7B26\u4E32\uFF1B\u6700\u5C0F\u5B57\u7B26\u6570 1"
2477
+ },
2478
+ {
2479
+ name: "HAI_DEPLOY_PROVIDER_EXPOSE_HTTPS_REDIRECTHTTP",
2480
+ module: "deploy",
2481
+ path: "deploy.provider.expose.https.redirectHttp",
2482
+ description: "\u666E\u901A HTTP \u8BF7\u6C42\u662F\u5426\u4EE5 308 \u8DF3\u8F6C\u81F3 HTTPS\uFF0C\u5065\u5EB7\u68C0\u67E5\u548C ACME \u6311\u6218\u9664\u5916",
2483
+ value: "true",
2484
+ constraint: "true | false"
2485
+ },
2486
+ {
2487
+ name: "HAI_DEPLOY_PROVIDER_EXPOSE_HTTPS_TYPE",
2488
+ module: "deploy",
2489
+ path: "deploy.provider.expose.https.type",
2490
+ description: "\u5E94\u7528\u90E8\u7F72\uFF1A\u5E73\u53F0/\u66B4\u9732\u65B9\u5F0F\uFF0C\u6309\u6240\u5728\u8282\u70B9\u7684\u679A\u4E3E\u9009\u62E9",
2491
+ value: "files",
2492
+ constraint: "\u5B57\u7B26\u4E32\uFF1B\u53D6\u503C\uFF1Afiles | letsencrypt"
2493
+ },
2422
2494
  {
2423
2495
  name: "HAI_DEPLOY_PROVIDER_EXPOSE_TYPE",
2424
2496
  module: "deploy",
@@ -3977,7 +4049,7 @@ var cli_config_catalog_default = [
3977
4049
  path: "kit.access",
3978
4050
  description: "\u6BCF\u6B21\u8BF7\u6C42\u7684\u8DEF\u5F84/IP/\u65F6\u95F4\u7B56\u7565\uFF1Bfalse \u5173\u95ED\uFF0C\u5185\u8054\u89C4\u5219\u4E0E\u72EC\u7ACB YAML \u6587\u4EF6\u5F15\u7528\u4E0D\u80FD\u6DF7\u7528",
3979
4051
  value: "false",
3980
- constraint: "true | false\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
4052
+ constraint: "true | false\uFF1Bfalse\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
3981
4053
  },
3982
4054
  {
3983
4055
  name: "HAI_KIT_ACCESS_FILE",
@@ -4273,7 +4345,7 @@ var cli_config_catalog_default = [
4273
4345
  path: "kit.transport",
4274
4346
  description: "\u4F20\u8F93\u52A0\u5BC6\u5F00\u5173\u6216\u5BC6\u94A5\u534F\u5546\u914D\u7F6E",
4275
4347
  value: "false",
4276
- constraint: "true | false\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
4348
+ constraint: "false\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
4277
4349
  },
4278
4350
  {
4279
4351
  name: "HAI_KIT_TRANSPORT_EXCLUDEPATHS",
@@ -4707,14 +4779,6 @@ var cli_config_catalog_default = [
4707
4779
  value: "",
4708
4780
  constraint: "JSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9"
4709
4781
  },
4710
- {
4711
- name: "HAI_REACH_PROVIDERS_0_HEADERS_AUTHORIZATION",
4712
- module: "reach",
4713
- path: "HAI_REACH_PROVIDERS_0_HEADERS_AUTHORIZATION",
4714
- description: "API \u901A\u77E5 Provider \u7684\u5B8C\u6574 Authorization \u8BF7\u6C42\u5934",
4715
- value: "",
4716
- constraint: "\u654F\u611F\u5B57\u7B26\u4E32\uFF0C\u5305\u542B\u8BA4\u8BC1\u65B9\u6848\u53CA\u51ED\u636E\uFF0C\u4F8B\u5982 Bearer <token>"
4717
- },
4718
4782
  {
4719
4783
  name: "HAI_REACH_PROVIDERS_0_HOST",
4720
4784
  module: "reach",
@@ -4827,6 +4891,22 @@ var cli_config_catalog_default = [
4827
4891
  value: "",
4828
4892
  constraint: "\u5B57\u7B26\u4E32"
4829
4893
  },
4894
+ {
4895
+ name: "HAI_REACH_PROVIDERS_1_ACCESSKEYID",
4896
+ module: "reach",
4897
+ path: "HAI_REACH_PROVIDERS_1_ACCESSKEYID",
4898
+ description: "\u963F\u91CC\u4E91 AccessKey ID",
4899
+ value: "",
4900
+ constraint: "\u5B57\u7B26\u4E32\uFF1B\u6700\u5C0F\u5B57\u7B26\u6570 1"
4901
+ },
4902
+ {
4903
+ name: "HAI_REACH_PROVIDERS_1_ACCESSKEYSECRET",
4904
+ module: "reach",
4905
+ path: "HAI_REACH_PROVIDERS_1_ACCESSKEYSECRET",
4906
+ description: "\u963F\u91CC\u4E91 AccessKey Secret",
4907
+ value: "",
4908
+ constraint: "\u5B57\u7B26\u4E32\uFF1B\u6700\u5C0F\u5B57\u7B26\u6570 1"
4909
+ },
4830
4910
  {
4831
4911
  name: "HAI_REACH_PROVIDERS_1_TYPE",
4832
4912
  module: "reach",
@@ -4835,6 +4915,22 @@ var cli_config_catalog_default = [
4835
4915
  value: "console",
4836
4916
  constraint: "\u5B57\u7B26\u4E32\uFF1B\u53D6\u503C\uFF1Aconsole | smtp | aliyun-sms | api"
4837
4917
  },
4918
+ {
4919
+ name: "HAI_REACH_PROVIDERS_2_HEADERS_AUTHORIZATION",
4920
+ module: "reach",
4921
+ path: "HAI_REACH_PROVIDERS_2_HEADERS_AUTHORIZATION",
4922
+ description: "\u51ED\u636E\u8F93\u5165\uFF1B\u4F7F\u7528\u4F4D\u7F6E packages/cli/src/commands/cli-config-templates.ts",
4923
+ value: "",
4924
+ constraint: "\u654F\u611F\u5B57\u7B26\u4E32\uFF1B\u542F\u7528\u76F8\u5E94\u529F\u80FD\u65F6\u5FC5\u586B\uFF0C\u4E0D\u5F97\u63D0\u4EA4\u771F\u5B9E\u503C"
4925
+ },
4926
+ {
4927
+ name: "HAI_REACH_PROVIDERS_2_IDEMPOTENT",
4928
+ module: "reach",
4929
+ path: "HAI_REACH_PROVIDERS_2_IDEMPOTENT",
4930
+ description: "\u63A5\u6536\u7AEF\u6309 Idempotency-Key \u539F\u5B50\u6301\u4E45\u53BB\u91CD\uFF0C\u4E14\u8986\u76D6\u6240\u6709\u91CD\u8BD5\u4E0E\u65E7\u8282\u70B9\u8FDF\u5230\u8BF7\u6C42\u65F6\u624D\u542F\u7528\uFF1B\u9ED8\u8BA4 false\u3002",
4931
+ value: "false",
4932
+ constraint: "true | false"
4933
+ },
4838
4934
  {
4839
4935
  name: "HAI_REACH_QUEUE",
4840
4936
  module: "reach",
@@ -4847,7 +4943,7 @@ var cli_config_catalog_default = [
4847
4943
  name: "HAI_REACH_QUEUE_MAXATTEMPTS",
4848
4944
  module: "reach",
4849
4945
  path: "reach.queue.maxAttempts",
4850
- description: "\u81EA\u52A8\u9886\u53D6\u6B21\u6570\u4E0A\u9650\uFF08\u542B\u9996\u6B21\u53CA\u5D29\u6E83\u6062\u590D\uFF0C\u9ED8\u8BA4 5\uFF0C\u8303\u56F4 1\u2013100\uFF09\u3002",
4946
+ description: "\u6BCF\u6761\u961F\u5217\u6D88\u606F\u6700\u591A\u5904\u7406\u591A\u5C11\u6B21\uFF0C\u5305\u542B\u9996\u6B21\u53D1\u9001\u3001\u5931\u8D25\u91CD\u8BD5\u548C\u5F02\u5E38\u9000\u51FA\u540E\u7684\u91CD\u65B0\u5904\u7406\uFF1B\u9ED8\u8BA4 5\uFF0C\u8303\u56F4 1\u2013100\u3002",
4851
4947
  value: "5",
4852
4948
  constraint: "\u6574\u6570\uFF1B>= 1\uFF1B<= 100"
4853
4949
  },
@@ -4855,7 +4951,7 @@ var cli_config_catalog_default = [
4855
4951
  name: "HAI_REACH_QUEUE_MAXRETRYDELAYMS",
4856
4952
  module: "reach",
4857
4953
  path: "reach.queue.maxRetryDelayMs",
4858
- description: "\u6307\u6570\u9000\u907F\u4E0A\u9650\u6BEB\u79D2\u6570\uFF0C\u4E0D\u5F97\u5C0F\u4E8E retryDelayMs\uFF08\u9ED8\u8BA4 3600000\uFF09\u3002",
4954
+ description: "\u540E\u7EED\u5931\u8D25\u65F6\u7B49\u5F85\u65F6\u95F4\u9010\u6B21\u52A0\u500D\uFF0C\u4F46\u4E0D\u8D85\u8FC7\u6B64\u503C\uFF1B\u9ED8\u8BA4 3600000\uFF081 \u5C0F\u65F6\uFF09\uFF0C\u4E0D\u5F97\u5C0F\u4E8E retryDelayMs\u3002",
4859
4955
  value: "3600000",
4860
4956
  constraint: "\u6574\u6570\uFF1B>= 1000\uFF1B<= 86400000"
4861
4957
  },
@@ -4863,7 +4959,7 @@ var cli_config_catalog_default = [
4863
4959
  name: "HAI_REACH_QUEUE_RETRYDELAYMS",
4864
4960
  module: "reach",
4865
4961
  path: "reach.queue.retryDelayMs",
4866
- description: "\u9996\u6B21\u5931\u8D25\u540E\u7684\u9000\u907F\u6BEB\u79D2\u6570\uFF08\u9ED8\u8BA4 60000\uFF0C\u8303\u56F4 1000\u201386400000\uFF09\u3002",
4962
+ description: "\u7B2C\u4E00\u6B21\u53D1\u9001\u5931\u8D25\u540E\uFF0C\u7B49\u5F85\u591A\u5C11\u6BEB\u79D2\u518D\u8BD5\uFF1B\u9ED8\u8BA4 60000\uFF081 \u5206\u949F\uFF09\uFF0C\u8303\u56F4 1000\u201386400000\u3002",
4867
4963
  value: "60000",
4868
4964
  constraint: "\u6574\u6570\uFF1B>= 1000\uFF1B<= 86400000"
4869
4965
  },
@@ -5433,7 +5529,7 @@ var cli_config_catalog_default = [
5433
5529
  path: "scheduler.enableDb",
5434
5530
  description: "\u5FC5\u987B\u4F7F\u7528\u5171\u4EAB\u6570\u636E\u5E93\u4FDD\u5B58\u6267\u884C\u72B6\u6001\uFF1Bfalse \u4E0D\u518D\u5141\u8BB8\uFF0C\u9700\u8981\u5148\u521D\u59CB\u5316",
5435
5531
  value: "true",
5436
- constraint: "true | false\uFF1B\u53D6\u503C\uFF1Atrue"
5532
+ constraint: "true\uFF1B\u53D6\u503C\uFF1Atrue"
5437
5533
  },
5438
5534
  {
5439
5535
  name: "HAI_SCHEDULER_LEASEMS",
@@ -5641,7 +5737,7 @@ var cli_config_catalog_default = [
5641
5737
  path: "serv.http.access",
5642
5738
  description: "\u6BCF\u6B21\u8BF7\u6C42\u7684\u8DEF\u5F84/IP/\u65F6\u95F4\u7B56\u7565\uFF1Bfalse \u5173\u95ED\uFF0C\u5185\u8054\u89C4\u5219\u4E0E\u72EC\u7ACB YAML \u6587\u4EF6\u5F15\u7528\u4E0D\u80FD\u6DF7\u7528",
5643
5739
  value: "false",
5644
- constraint: "true | false\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
5740
+ constraint: "true | false\uFF1Bfalse\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
5645
5741
  },
5646
5742
  {
5647
5743
  name: "HAI_SERV_HTTP_ACCESS_FILE",
@@ -5913,7 +6009,7 @@ var cli_config_catalog_default = [
5913
6009
  path: "serv.http.docs",
5914
6010
  description: "HTTP API \u6587\u6863\u529F\u80FD\u5F00\u5173\u6216\u6587\u6863\u8BBF\u95EE\u914D\u7F6E",
5915
6011
  value: "false",
5916
- constraint: "true | false\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
6012
+ constraint: "true | false\uFF1Bfalse\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
5917
6013
  },
5918
6014
  {
5919
6015
  name: "HAI_SERV_HTTP_DOCS_PATH",
@@ -5937,7 +6033,7 @@ var cli_config_catalog_default = [
5937
6033
  path: "serv.http.health",
5938
6034
  description: "HTTP \u5065\u5EB7\u68C0\u67E5\u5F00\u5173\u6216\u68C0\u67E5\u914D\u7F6E",
5939
6035
  value: '{"path":"/health","readyPath":"/ready"}',
5940
- constraint: "JSON \u5BF9\u8C61\uFF1Btrue | false\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
6036
+ constraint: "JSON \u5BF9\u8C61\uFF1Bfalse\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
5941
6037
  },
5942
6038
  {
5943
6039
  name: "HAI_SERV_HTTP_HEALTH_PATH",
@@ -5961,7 +6057,7 @@ var cli_config_catalog_default = [
5961
6057
  path: "serv.http.openapi",
5962
6058
  description: "OpenAPI \u7AEF\u70B9\u5F00\u5173\u6216\u7AEF\u70B9\u914D\u7F6E",
5963
6059
  value: "false",
5964
- constraint: "true | false\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
6060
+ constraint: "true | false\uFF1Bfalse\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
5965
6061
  },
5966
6062
  {
5967
6063
  name: "HAI_SERV_HTTP_OPENAPI_PATH",
@@ -5971,46 +6067,6 @@ var cli_config_catalog_default = [
5971
6067
  value: "/openapi.json",
5972
6068
  constraint: "\u5B57\u7B26\u4E32\uFF1B\u4EE5 / \u5F00\u5934\u7684\u8DEF\u5F84\u5B57\u7B26\u4E32"
5973
6069
  },
5974
- {
5975
- name: "HAI_SERV_HTTP_RPC",
5976
- module: "serv",
5977
- path: "serv.http.rpc",
5978
- description: "RPC \u7AEF\u70B9\u5F00\u5173\u6216\u8BBF\u95EE\u914D\u7F6E",
5979
- value: "false",
5980
- constraint: "true | false\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
5981
- },
5982
- {
5983
- name: "HAI_SERV_HTTP_RPC_ACCESS",
5984
- module: "serv",
5985
- path: "serv.http.rpc.access",
5986
- description: "RPC \u5BF9\u5916\u8BBF\u95EE\u7B56\u7565",
5987
- value: "loopback",
5988
- constraint: "\u5B57\u7B26\u4E32\uFF1B\u53D6\u503C\uFF1Aloopback | private-network | gateway-only"
5989
- },
5990
- {
5991
- name: "HAI_SERV_HTTP_RPC_GATEWAYHEADER",
5992
- module: "serv",
5993
- path: "serv.http.rpc.gatewayHeader",
5994
- description: "\u53D7\u4FE1\u7F51\u5173\u8BA4\u8BC1\u8BF7\u6C42\u5934\u540D\u79F0",
5995
- value: "",
5996
- constraint: "\u5B57\u7B26\u4E32"
5997
- },
5998
- {
5999
- name: "HAI_SERV_HTTP_RPC_GATEWAYSECRET",
6000
- module: "serv",
6001
- path: "serv.http.rpc.gatewaySecret",
6002
- description: "\u53D7\u4FE1\u7F51\u5173\u8BA4\u8BC1\u5BC6\u94A5",
6003
- value: "",
6004
- constraint: "\u5B57\u7B26\u4E32"
6005
- },
6006
- {
6007
- name: "HAI_SERV_HTTP_RPC_PREFIX",
6008
- module: "serv",
6009
- path: "serv.http.rpc.prefix",
6010
- description: "RPC \u7AEF\u70B9\u7684\u8DEF\u5F84\u524D\u7F00",
6011
- value: "/rpc",
6012
- constraint: "\u5B57\u7B26\u4E32\uFF1B\u4EE5 / \u5F00\u5934\u7684\u8DEF\u5F84\u5B57\u7B26\u4E32"
6013
- },
6014
6070
  {
6015
6071
  name: "HAI_SERV_HTTP_TRUSTEDPROXIES",
6016
6072
  module: "serv",
@@ -6057,7 +6113,7 @@ var cli_config_catalog_default = [
6057
6113
  path: "serv.transport",
6058
6114
  description: "\u4F20\u8F93\u52A0\u5BC6\u5F00\u5173\u6216\u5BC6\u94A5\u534F\u5546\u914D\u7F6E",
6059
6115
  value: "false",
6060
- constraint: "true | false\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
6116
+ constraint: "false\uFF1BJSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9\uFF1B\u53D6\u503C\uFF1Afalse"
6061
6117
  },
6062
6118
  {
6063
6119
  name: "HAI_SERV_TRANSPORT_EXCLUDEPATHS",
@@ -6472,7 +6528,50 @@ var cli_config_catalog_default = [
6472
6528
  // src/commands/cli-config-environment.ts
6473
6529
  var catalogByName = new Map(cli_config_catalog_default.map((entry) => [entry.name, entry]));
6474
6530
  var catalogByPath = new Map(cli_config_catalog_default.map((entry) => [entry.path, entry]));
6531
+ function configurationConstraint(value) {
6532
+ return value.replaceAll("JSON \u5BF9\u8C61\uFF1B\u6574\u4F53\u8986\u76D6\u65F6\u66FF\u6362\u8BE5\u8282\u70B9", "\u914D\u7F6E\u5757\uFF08\u586B\u5199\u4E0B\u65B9\u7F29\u8FDB\u5B57\u6BB5\uFF09").replaceAll("JSON \u6570\u7EC4\uFF1B\u7D22\u5F15\u53EF\u6309 0\u30011\u30012 \u6269\u5C55", "\u5217\u8868\uFF08\u6BCF\u9879\u4EE5 - \u5F00\u5934\uFF09").replaceAll("string,null", "\u5B57\u7B26\u4E32\u6216\u7A7A\u503C").replaceAll("\uFF1B<= 9007199254740991", "");
6533
+ }
6534
+ function withoutGeneratedDocumentation(content) {
6535
+ const { lines, document: optional, counter } = readOptionalConfig(content);
6536
+ const starts = [];
6537
+ let offset = 0;
6538
+ for (const line of lines) {
6539
+ starts.push(offset);
6540
+ offset += line.length + 1;
6541
+ }
6542
+ const ranges = [];
6543
+ function originalOffset(position, end) {
6544
+ const location = counter.linePos(position);
6545
+ const line = lines[location.line - 1] ?? "";
6546
+ const prefix = /^(\s*)# (?=\s*(?:[a-z][\w-]*:|-\s))/i.exec(line);
6547
+ const column = location.col - 1;
6548
+ const removed = prefix && (column > prefix[1].length || !end && column === prefix[1].length) ? 2 : 0;
6549
+ return (starts[location.line - 1] ?? content.length) + column + removed;
6550
+ }
6551
+ function collect(node, virtual) {
6552
+ if (isMap(node)) {
6553
+ for (const pair of node.items)
6554
+ collect(pair.value, virtual);
6555
+ } else if (isSeq(node)) {
6556
+ node.items.forEach((item) => collect(item, virtual));
6557
+ } else if (isScalar(node) && node.range) {
6558
+ ranges.push(virtual ? [originalOffset(node.range[0], false), originalOffset(node.range[1], true)] : [node.range[0], node.range[1]]);
6559
+ }
6560
+ }
6561
+ collect(parseDocument(content).contents, false);
6562
+ if (!optional.errors.length)
6563
+ collect(optional.contents, true);
6564
+ const protectedAt = (position) => ranges.some(([start, end]) => position >= start && position < end);
6565
+ return lines.flatMap((line, index) => {
6566
+ const metadata = /^(\s*)#\s*(?:用途|说明|取值):/.exec(line);
6567
+ if (metadata && !protectedAt(starts[index] + metadata[1].length))
6568
+ return [];
6569
+ const suffix = line.lastIndexOf(" # \u8BF4\u660E\uFF1A");
6570
+ return [suffix >= 0 && !protectedAt(starts[index] + suffix + 1) ? line.slice(0, suffix) : line];
6571
+ }).join("\n");
6572
+ }
6475
6573
  function documentConfig(name, content) {
6574
+ content = withoutGeneratedDocumentation(content);
6476
6575
  const document = parseDocument(content);
6477
6576
  if (document.errors.length)
6478
6577
  throw new Error(`Invalid ${name} configuration documentation source`);
@@ -6483,7 +6582,7 @@ function documentConfig(name, content) {
6483
6582
  const previous = node[field];
6484
6583
  if (!previous)
6485
6584
  continue;
6486
- const kept = previous.split("\n").filter((line) => !/^\s*用途:/.test(line)).join("\n") || null;
6585
+ const kept = previous.split("\n").filter((line) => !/^\s*(?:用途|说明|取值):/.test(line)).join("\n") || null;
6487
6586
  if (kept !== previous) {
6488
6587
  node[field] = kept;
6489
6588
  changed = true;
@@ -6502,7 +6601,8 @@ function documentConfig(name, content) {
6502
6601
  const description = catalogByPath.get([name, ...field].join(".").replace(/\.\d+(?=\.|$)/g, ".0"))?.description;
6503
6602
  if (description) {
6504
6603
  const target = sequenceItem && index === 0 ? node : pair.key;
6505
- const comment = [target.commentBefore, ` \u7528\u9014\uFF1A${description}`].filter(Boolean).join("\n");
6604
+ const entry = catalogByPath.get([name, ...field].join(".").replace(/\.\d+(?=\.|$)/g, ".0"));
6605
+ const comment = [target.commentBefore, ` \u8BF4\u660E\uFF1A${description}`, entry?.constraint ? ` \u53D6\u503C\uFF1A${configurationConstraint(entry.constraint)}` : void 0].filter(Boolean).join("\n");
6506
6606
  if (target.commentBefore !== comment) {
6507
6607
  target.commentBefore = comment;
6508
6608
  changed = true;
@@ -6515,14 +6615,50 @@ function documentConfig(name, content) {
6515
6615
  }
6516
6616
  }
6517
6617
  walk(document.contents, []);
6518
- return changed ? document.toString({ lineWidth: 0 }) : content;
6618
+ return documentOptionalConfig(name, changed ? document.toString({ lineWidth: 0 }) : content);
6619
+ }
6620
+ function documentOptionalConfig(name, content) {
6621
+ const { lines, document, counter } = readOptionalConfig(content);
6622
+ if (document.errors.length)
6623
+ return content;
6624
+ const additions = /* @__PURE__ */ new Map();
6625
+ function walk(node, path) {
6626
+ if (isMap(node)) {
6627
+ for (const pair of node.items) {
6628
+ if (!isScalar(pair.key))
6629
+ continue;
6630
+ const segments = [...path, String(pair.key.value)];
6631
+ const entry = catalogByPath.get([name, ...segments].join(".").replace(/\.\d+(?=\.|$)/g, ".0"));
6632
+ if (entry && pair.key.range) {
6633
+ const line = counter.linePos(pair.key.range[0]).line - 1;
6634
+ const prefix = /^(\s*#\s*)(?:-\s*)?[A-Z][\w-]*:/i.exec(lines[line])?.[1];
6635
+ if (prefix && !additions.has(line))
6636
+ additions.set(line, ` # \u8BF4\u660E\uFF1A${entry.description}\uFF1B\u53D6\u503C\uFF1A${configurationConstraint(entry.constraint)}`);
6637
+ }
6638
+ walk(pair.value, segments);
6639
+ }
6640
+ } else if (isSeq(node)) {
6641
+ node.items.forEach((item, index) => walk(item, [...path, String(index)]));
6642
+ }
6643
+ }
6644
+ walk(document.contents, []);
6645
+ return lines.map((line, index) => line + (additions.get(index) ?? "")).join("\n");
6646
+ }
6647
+ function readOptionalConfig(content) {
6648
+ const lines = content.split("\n");
6649
+ const virtual = lines.map((line) => line.replace(/^(\s*)# (?=\s*(?:[A-Z][\w-]*:|-\s))/i, "$1")).join("\n");
6650
+ const counter = new LineCounter();
6651
+ const document = parseDocument(virtual, { uniqueKeys: false, lineCounter: counter });
6652
+ return { lines, document, counter };
6519
6653
  }
6520
6654
  function parameterizeConfig(name, content) {
6655
+ content = parameterizeOptionalConfig(name, content);
6521
6656
  const document = parseDocument(content);
6522
6657
  if (document.errors.length > 0)
6523
6658
  throw new Error(`Invalid ${name} configuration template`);
6524
6659
  if (!document.contents || isScalar(document.contents) && document.contents.value === null)
6525
6660
  return content;
6661
+ let changed = false;
6526
6662
  function walk(node, path) {
6527
6663
  if (["templates", "supportedLocales", "id"].includes(path[0]) || path.includes("redact") || name === "audit" && /^(?:userTable|userIdColumn|userNameColumn)$/.test(path[0] ?? "") || name === "iam" && ["ui", "agreements", "rbac"].includes(path[0]) && !(path.at(-1) ?? "").endsWith("Url") || ["id", "name", "operations"].includes(path.at(-1) ?? "") && path.some((segment) => /^\d+$/.test(segment))) {
6528
6664
  return;
@@ -6543,14 +6679,54 @@ function parameterizeConfig(name, content) {
6543
6679
  const fallback = typeof node.value === "string" && value !== "" && (parsed.errors.length > 0 || !isScalar(parsed.contents) || parsed.contents.value !== value) ? JSON.stringify(value) : value;
6544
6680
  node.value = `\${${variable}:${fallback}}`;
6545
6681
  node.type = Scalar.PLAIN;
6682
+ changed = true;
6546
6683
  }
6547
6684
  }
6548
6685
  walk(document.contents, []);
6549
- return document.toString({ lineWidth: 0 });
6686
+ return changed ? document.toString({ lineWidth: 0 }) : content;
6687
+ }
6688
+ function parameterizeOptionalConfig(name, content) {
6689
+ const { lines, document, counter } = readOptionalConfig(content);
6690
+ if (document.errors.length)
6691
+ return content;
6692
+ const edits = /* @__PURE__ */ new Map();
6693
+ function walk(node, segments) {
6694
+ if (isMap(node)) {
6695
+ for (const pair of node.items) {
6696
+ if (isScalar(pair.key))
6697
+ walk(pair.value, [...segments, String(pair.key.value)]);
6698
+ }
6699
+ } else if (isSeq(node)) {
6700
+ node.items.forEach((item, index) => walk(item, [...segments, String(index)]));
6701
+ } else if (isScalar(node) && node.range && node.value !== null && node.value !== void 0) {
6702
+ const location = counter.linePos(node.range[0]);
6703
+ const line = lines[location.line - 1];
6704
+ if (!/^\s*# /.test(line) || /[\n\r}]/.test(String(node.value)) || String(node.value).includes("${"))
6705
+ return;
6706
+ const field = [name, ...segments].join(".").replace(/\.\d+(?=\.|$)/g, ".0");
6707
+ if (!catalogByPath.has(field) || ["id", "name", "operations"].includes(segments.at(-1) ?? "") || segments.includes("templates") || segments.includes("redact"))
6708
+ return;
6709
+ const variable = ["HAI", name, ...segments].map((part) => part.replace(/[^a-z0-9]+/gi, "_").replace(/^_+|_+$/g, "").toUpperCase()).join("_");
6710
+ const text = String(node.value);
6711
+ const parsed = parseDocument(text);
6712
+ const fallback = typeof node.value === "string" && text !== "" && (parsed.errors.length > 0 || !isScalar(parsed.contents) || parsed.contents.value !== text) ? JSON.stringify(text) : text;
6713
+ const replacement = `\${${variable}:${fallback}}`;
6714
+ const list = edits.get(location.line - 1) ?? [];
6715
+ list.push({ start: location.col + 1, end: location.col + 1 + node.range[1] - node.range[0], value: JSON.stringify(replacement) });
6716
+ edits.set(location.line - 1, list);
6717
+ }
6718
+ }
6719
+ walk(document.contents, []);
6720
+ for (const [index, replacements] of edits) {
6721
+ for (const edit of replacements.sort((a, b) => b.start - a.start))
6722
+ lines[index] = lines[index].slice(0, edit.start) + edit.value + lines[index].slice(edit.end);
6723
+ }
6724
+ return lines.join("\n");
6550
6725
  }
6551
6726
  function configEnvironmentVariables(name, content) {
6552
6727
  const variables = /* @__PURE__ */ new Map();
6553
6728
  const locations = /* @__PURE__ */ new Map();
6729
+ const activeValues = /* @__PURE__ */ new Map();
6554
6730
  function locate(node, path) {
6555
6731
  if (isMap(node)) {
6556
6732
  for (const pair of node.items) {
@@ -6560,25 +6736,35 @@ function configEnvironmentVariables(name, content) {
6560
6736
  } else if (isSeq(node)) {
6561
6737
  node.items.forEach((item, index) => locate(item, [...path, String(index)]));
6562
6738
  } else if (isScalar(node) && typeof node.value === "string") {
6563
- for (const match of node.value.matchAll(/\$\{([^}:]+)/g))
6739
+ for (const match of node.value.matchAll(/\$\{([^}:]+)(?::([^}]*))?\}/g)) {
6564
6740
  locations.set(match[1], [name, ...path].join("."));
6741
+ if (!activeValues.has(match[1]))
6742
+ activeValues.set(match[1], match[2] ?? "");
6743
+ }
6565
6744
  }
6566
6745
  }
6567
6746
  locate(parseDocument(content).contents, []);
6568
6747
  for (const match of content.matchAll(/\$\{((?:HAI_|PUBLIC_|VITE_|AI_|OPENAI_|GEMINI_|DASHSCOPE_|ARK_|LDAP_)[A-Z0-9_]*)(?::([^}]*))?\}/g)) {
6569
6748
  const [, variable, value = ""] = match;
6749
+ if (variables.has(variable))
6750
+ continue;
6751
+ const normalized = catalogByName.get(variable.replace(/_\d+(?=_|$)/g, "_0"));
6752
+ const entry = catalogByName.get(variable) ?? normalized;
6753
+ const indices = [...variable.matchAll(/_(\d+)(?=_|$)/g)].map((item) => item[1]);
6754
+ const catalogPath = (entry?.path === variable ? normalized?.path : entry?.path)?.replace(/\.0(?=\.|$)/g, () => `.${indices.shift() ?? "0"}`);
6570
6755
  variables.set(variable, {
6571
6756
  name: variable,
6572
- path: locations.get(variable) ?? `${name} (${variable}\uFF0C\u53EF\u9009\u5757)`,
6573
- value,
6757
+ path: locations.get(variable) ?? catalogPath ?? `${name} (${variable}\uFF0C\u53EF\u9009\u5757)`,
6758
+ value: activeValues.get(variable) ?? value,
6574
6759
  constraint: variableConstraint(variable, value),
6575
- description: catalogByName.get(variable)?.description
6760
+ description: entry?.description,
6761
+ optional: !locations.has(variable)
6576
6762
  });
6577
6763
  }
6578
6764
  return [...variables.values()];
6579
6765
  }
6580
6766
  function variableConstraint(name, value) {
6581
- const known = catalogByName.get(name);
6767
+ const known = catalogByName.get(name) ?? catalogByName.get(name.replace(/_\d+(?=_|$)/g, "_0"));
6582
6768
  if (known)
6583
6769
  return known.constraint;
6584
6770
  const enums = {
@@ -6589,7 +6775,7 @@ function variableConstraint(name, value) {
6589
6775
  HAI_CACHE_TYPE: "memory | redis",
6590
6776
  HAI_STORAGE_TYPE: "local | s3",
6591
6777
  HAI_VECDB_TYPE: "lancedb | pgvector | qdrant | chroma",
6592
- HAI_AI_LLM_API: "chat | responses | anthropic",
6778
+ HAI_AI_LLM_PROTOCOL: "chat | responses | anthropic",
6593
6779
  HAI_DB_SSL: "MySQL\uFF1Afalse \u6216\u4E25\u683C TLS \u5BF9\u8C61\uFF08{} \u9ED8\u8BA4\u6821\u9A8C\u8BC1\u4E66\u94FE\u548C DNS \u8EAB\u4EFD\uFF09\uFF1BPostgreSQL\uFF1A\u5E03\u5C14\u503C\u3001require/prefer/allow/disable \u6216 TLS \u5BF9\u8C61",
6594
6780
  HAI_IAM_PASSWORD_MINLENGTH: "\u6574\u6570 >= 1\uFF0C\u4E14\u4E0D\u5927\u4E8E maxLength",
6595
6781
  HAI_IAM_PASSWORD_MAXLENGTH: "\u6574\u6570 1\u2013256\uFF0C\u4E14\u4E0D\u5C0F\u4E8E minLength",
@@ -6709,6 +6895,8 @@ logging:
6709
6895
  format: pretty
6710
6896
  # context:
6711
6897
  # service: api
6898
+ # redact \u586B\u65E5\u5FD7\u5B57\u6BB5\u8DEF\u5F84\uFF1Bcustomer.email \u906E\u76D6\u5BA2\u6237\u90AE\u7BB1\uFF0Crecipients[*].phone \u906E\u76D6\u6570\u7EC4\u4E2D\u7684\u7535\u8BDD\u3002
6899
+ # \u53EA\u5339\u914D\u6307\u5B9A\u5C42\u7EA7\uFF0C* \u5339\u914D\u4E00\u5C42\uFF1B\u5BC6\u7801\u548C\u4EE4\u724C\u7B49\u5DF2\u77E5\u51ED\u636E\u9ED8\u8BA4\u4ECD\u4F1A\u8131\u654F\u3002
6712
6900
  redact:
6713
6901
  - password
6714
6902
  - token
@@ -6745,22 +6933,24 @@ http:
6745
6933
  access: false
6746
6934
  # access:
6747
6935
  # file: ./config/security/request-access.yml
6936
+ # \u6216\u5C06 access: false \u66FF\u6362\u4E3A\u4E0B\u5217\u5185\u8054\u914D\u7F6E\uFF1B\u4E0E file \u4E8C\u9009\u4E00\u3002
6937
+ # access:
6938
+ # global:
6939
+ # timezone: UTC # \u53EF\u7528 HAI_SERV_HTTP_ACCESS_GLOBAL_TIMEZONE=Asia/Shanghai
6940
+ # allowIps: []
6941
+ # denyIps: []
6942
+ # windows: []
6943
+ # rules: []
6748
6944
  apiPrefix: /api/v1
6749
6945
  openapi:
6750
6946
  path: /openapi.json
6947
+ # HAI_SERV_HTTP_DOCS=false \u5173\u95ED\u6587\u6863\uFF1B\u5F00\u542F\u65F6\u518D\u914D\u7F6E path/requireAuth\u3002
6751
6948
  docs:
6752
6949
  path: /docs
6753
6950
  # requireAuth: true
6754
6951
  health:
6755
6952
  path: /health
6756
6953
  readyPath: /ready
6757
- rpc: false
6758
- # \u542F\u7528\u5185\u90E8 RPC \u65F6\u7528\u5BF9\u8C61\u66FF\u6362 false\uFF0Cgateway-only \u5FC5\u987B\u914D\u7F6E\u7F51\u5173\u5BC6\u94A5\u3002
6759
- # rpc:
6760
- # prefix: /api/rpc
6761
- # access: gateway-only # loopback | private-network | gateway-only
6762
- # gatewayHeader: X-Gateway-Key
6763
- # gatewaySecret: \${HAI_SERV_HTTP_RPC_GATEWAYSECRET}
6764
6954
 
6765
6955
  # \u6309\u9700\u5F00\u542F\u8DE8\u57DF\u8BBF\u95EE\uFF0C\u751F\u4EA7\u73AF\u5883\u586B\u5199\u660E\u786E\u7684 Origin\u3002
6766
6956
  # cors:
@@ -6776,6 +6966,9 @@ transport: false
6776
6966
  # maxPlaintextBytes: \${HAI_SERV_TRANSPORT_MAXPLAINTEXTBYTES:1048576} # \u53CC\u5411 UTF-8 \u660E\u6587\uFF0C1 KiB\uFF5E64 MiB
6777
6967
  # keyExchangePath: /_hai/key-exchange
6778
6968
  # excludePaths: [/health, /ready]
6969
+ # \u5355\u6761\u8DEF\u5F84\u9700\u8981\u66F4\u5927\u8BF7\u6C42\u4F53\u65F6\u586B\u5199\u5B57\u8282\u6570\uFF0C* \u53EA\u5339\u914D\u4E00\u6BB5\u8DEF\u5F84\u3002
6970
+ # routePlaintextBytes: # HAI_SERV_TRANSPORT_ROUTEPLAINTEXTBYTES \u53EF\u586B JSON \u8DEF\u5F84\u6620\u5C04
6971
+ # /api/v1/uploads/*: 8388608
6779
6972
  `;
6780
6973
  }
6781
6974
  function generateDbConfig(cfg) {
@@ -6797,7 +6990,7 @@ function generateDbConfig(cfg) {
6797
6990
  # MySQL \u4E13\u7528\uFF1BPostgreSQL \u65E0\u9700\u6B64\u5757\u3002
6798
6991
  # mysql:
6799
6992
  # charset: utf8mb4
6800
- # timezone: '+08:00'`;
6993
+ # MySQL \u4E0D\u652F\u6301 timezone \u914D\u7F6E\uFF1B\u4E0D\u8981\u5728 mysql \u5757\u5185\u586B\u5199\u8BE5\u5B57\u6BB5\u3002`;
6801
6994
  return `# =============================================================================
6802
6995
  # \u6570\u636E\u5E93\u914D\u7F6E
6803
6996
  # =============================================================================
@@ -6813,7 +7006,7 @@ url: \${HAI_DB_URL:}
6813
7006
  ssl: \${HAI_DB_SSL:false}
6814
7007
  ${networkOptions}
6815
7008
 
6816
- # SQL \u65E5\u5FD7\u6309\u9700\u5F00\u542F\uFF1BmaxLength \u9650\u5236 SQL / \u53C2\u6570\u8F93\u51FA\u957F\u5EA6\u3002
7009
+ # \u64CD\u4F5C\u65E5\u5FD7\u6309\u9700\u5F00\u542F\uFF0C\u53EA\u8BB0\u5F55\u8017\u65F6\u3001\u6570\u91CF\u7B49\u5B89\u5168\u6458\u8981\uFF1BmaxLength \u9650\u5236\u6458\u8981\u957F\u5EA6\uFF0C\u4E0D\u8BB0\u5F55 SQL \u539F\u6587\u548C\u53C2\u6570\u3002
6817
7010
  # operationLog:
6818
7011
  # read: false
6819
7012
  # write: false
@@ -6903,7 +7096,7 @@ captcha:
6903
7096
  # apikey:
6904
7097
  # maxKeysPerUser: 10
6905
7098
  # defaultExpirationDays: 0 # 0 \u8868\u793A\u4E0D\u9650\u5236\u6709\u6548\u671F
6906
- # prefix: hai_
7099
+ # prefix: hai_ # \u65B0\u5EFA API Key \u7684\u5F00\u5934\uFF0C\u4F8B\u5982 hai_abc123\uFF1B\u53EA\u586B\u5E94\u7528\u6807\u8BC6\uFF0C\u4E0D\u653E\u5BC6\u7801\u3002
6907
7100
  # OTP \u9700\u542F\u7528 login.otp\uFF0C\u5E76\u9009\u62E9 Reach \u6807\u51C6\u6A21\u677F\u6216\u81EA\u5B9A\u4E49\u53D1\u9001\u56DE\u8C03\u3002
6908
7101
  ${(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:
6909
7102
  email: true
@@ -6967,7 +7160,12 @@ loginAccess:
6967
7160
  timezone: UTC
6968
7161
  allowIps: [] # \u7A7A\u5217\u8868\u4E0D\u9650\u5236\uFF1B\u652F\u6301 IPv4\u3001IPv6 \u4E0E CIDR
6969
7162
  denyIps: [] # \u62D2\u7EDD\u4F18\u5148
6970
- windows: [] # days \u4E3A\u5468\u4E001\u81F3\u5468\u65E57\uFF1Bstart/end \u4E3A HH:mm\uFF0C\u652F\u6301\u8DE8\u5348\u591C
7163
+ windows: [] # \u7559\u7A7A\u5141\u8BB8\u4EFB\u4F55\u65F6\u95F4\uFF1B\u4EE5\u4E0B\u4F8B\u5B50\u53EA\u5141\u8BB8\u5468\u4E00\u81F3\u5468\u4E94 09:00\u201318:00 \u767B\u5F55\u3002
7164
+ # windows:
7165
+ # - days: [1, 2, 3, 4, 5]
7166
+ # start: '09:00'
7167
+ # end: '18:00'
7168
+ # timezone \u8BBE\u4E3A Asia/Shanghai \u65F6\uFF0C\u4E0A\u8FF0\u65F6\u95F4\u6309\u5317\u4EAC\u65F6\u95F4\u89E3\u91CA\u3002
6971
7169
 
6972
7170
  # \u4F1A\u8BDD\u914D\u7F6E
6973
7171
  session:
@@ -6978,7 +7176,11 @@ session:
6978
7176
  singleDeviceMode: replace # replace \u9876\u65E7\u4FDD\u65B0\uFF1Breject \u62D2\u7EDD\u91CD\u590D\u767B\u5F55
6979
7177
  maxSessions: 0 # \u6BCF\u7528\u6237\u6709\u6548\u4F1A\u8BDD\u4E0A\u9650\uFF0C0 \u4E0D\u9650\u5236
6980
7178
  # \u6309\u7EC8\u7AEF\u5206\u522B\u9650\u5236\uFF1B\u975E\u7A7A\u65F6\u4EC5\u5141\u8BB8\u5217\u51FA\u7684\u7C7B\u578B\uFF0C\u4ECD\u53D7\u5168\u5C40\u6700\u5927\u4F1A\u8BDD\u6570\u7EA6\u675F\u3002
6981
- terminalLimits: {}
7179
+ terminalLimits: {} # \u7559\u7A7A\u4E0D\u6309\u7EC8\u7AEF\u9650\u5236\u3002\u4E0B\u9762\u4F8B\u5B50\u5141\u8BB8 web 2 \u4E2A\u3001app 1 \u4E2A\uFF0C\u5176\u4F59\u7EC8\u7AEF\u4E0D\u5141\u8BB8\u65B0\u767B\u5F55\u3002
7180
+ # terminalLimits:
7181
+ # web: 2
7182
+ # app: 1
7183
+ # \u524D\u7AEF\u53D1\u9001\u7684\u7EC8\u7AEF\u540D\u79F0\u5FC5\u987B\u4E0E\u952E\u540D\u76F8\u540C\uFF1B\u6B64\u9650\u5236\u540C\u65F6\u53D7 maxSessions \u7EA6\u675F\u3002
6982
7184
  terminalLimitMode: reject
6983
7185
  idleTimeout: 0 # \u95F2\u7F6E\u671F\u9650\uFF08\u79D2\uFF09\uFF0C0 \u5173\u95ED\uFF1Baccess/refresh \u5747\u6267\u884C
6984
7186
  absoluteTimeout: 0 # \u4ECE\u9996\u6B21\u767B\u5F55\u8D77\u7684\u7EDD\u5BF9\u671F\u9650\uFF08\u79D2\uFF09\uFF0C0 \u5173\u95ED
@@ -7012,8 +7214,8 @@ accessKeyId: ''
7012
7214
  secretAccessKey: ''
7013
7215
  endpoint: \${HAI_STORAGE_ENDPOINT:https://s3.amazonaws.com}
7014
7216
  forcePathStyle: false
7015
- # prefix: ''
7016
- # publicEndpoint: https://app.example.com # \u79C1\u6709\u9884\u7B7E\u540D\u8BBF\u95EE\u6E90\uFF1B\u4E0D\u542B\u6876\u540D\u6216\u7F51\u7AD9\u76EE\u5F55
7217
+ # prefix: '' # \u5BF9\u8C61\u8DEF\u5F84\u524D\u7F00\uFF0C\u4F8B\u5982 invoices/2026\uFF1B\u4FDD\u5B58 report.pdf \u540E\u952E\u540D\u4E3A invoices/2026/report.pdf\u3002
7218
+ # publicEndpoint: https://app.example.com # \u6D4F\u89C8\u5668\u4E0B\u8F7D\u5165\u53E3\uFF0C\u53EF\u5E26 /files \u7B49\u4EE3\u7406\u76EE\u5F55\uFF1B\u4E0D\u542B\u6876\u540D
7017
7219
  # publicUrl: https://cdn.example.com`;
7018
7220
  return `# \u5B58\u50A8\u914D\u7F6E\uFF1BHAI_STORAGE \u53EF\u6574\u4F53\u66FF\u6362\u8FDE\u63A5\u914D\u7F6E\u3002
7019
7221
  type: ${type}
@@ -7037,7 +7239,7 @@ function generateAiConfig(cfg) {
7037
7239
  # AI \u914D\u7F6E
7038
7240
  # =============================================================================
7039
7241
 
7040
- # LLM \u914D\u7F6E\uFF08\u5FC5\u586B\uFF09
7242
+ # \u5BF9\u8BDD\u6A21\u578B\uFF08\u4F7F\u7528\u5BF9\u8BDD\u529F\u80FD\u65F6\u914D\u7F6E\uFF09
7041
7243
  llm:
7042
7244
  # API Key\uFF08\u7EA6\u5B9A\u73AF\u5883\u53D8\u91CF HAI_AI_LLM_APIKEY \u4F18\u5148\uFF09
7043
7245
  apiKey: ''
@@ -7045,7 +7247,7 @@ llm:
7045
7247
  # baseUrl: https://api.openai.com/v1
7046
7248
  # \u9ED8\u8BA4\u6A21\u578B
7047
7249
  ${stringify({ model }).trim().split("\n").map((line) => ` ${line}`).join("\n")}
7048
- api: ${api} # chat | responses | anthropic
7250
+ protocol: ${api} # \u8BF7\u6C42\u683C\u5F0F\uFF1AOpenAI \u517C\u5BB9\u9009 chat\uFF0CResponses \u9009 responses\uFF0CClaude Messages \u9009 anthropic\u3002
7049
7251
  # \u5168\u5C40\u6700\u5927 Token \u6570\uFF08\u9ED8\u8BA4 4096\uFF09
7050
7252
  # maxTokens: 4096
7051
7253
  # \u91C7\u6837\u6E29\u5EA6\uFF080-2\uFF0C\u9ED8\u8BA4 0.7\uFF09
@@ -7054,11 +7256,11 @@ ${stringify({ model }).trim().split("\n").map((line) => ` ${line}`).join("\n")}
7054
7256
  # timeout: 60000
7055
7257
  # tempModelCacheTtl: 600000
7056
7258
 
7057
- # \u591A\u6A21\u578B\u914D\u7F6E\uFF08\u53EF\u9009\uFF0C\u7528\u4E8E\u573A\u666F\u8DEF\u7531\uFF09
7259
+ # \u591A\u6A21\u578B\u914D\u7F6E\uFF1Aid \u662F\u5E94\u7528\u4E2D\u7684\u77ED\u540D\uFF0Cmodel \u662F\u4F9B\u5E94\u5546\u7684\u771F\u5B9E\u578B\u53F7\u3002\u5404\u9879\u53EF\u5355\u72EC\u8BBE\u7F6E\u534F\u8BAE\u3001\u5730\u5740\u548C\u5BC6\u94A5\u3002
7058
7260
  # models:
7059
7261
  # - id: fast
7060
7262
  # model: gpt-4o-mini
7061
- # api: chat
7263
+ # protocol: chat
7062
7264
  # apiKey: ''
7063
7265
  # baseUrl: https://api.openai.com/v1
7064
7266
  # maxTokens: 4096
@@ -7068,7 +7270,7 @@ ${stringify({ model }).trim().split("\n").map((line) => ` ${line}`).join("\n")}
7068
7270
  # model: gpt-4o
7069
7271
  # apiKey: ''
7070
7272
 
7071
- # \u573A\u666F\u6A21\u578B\u6620\u5C04\uFF08\u53EF\u9009\uFF09
7273
+ # \u573A\u666F\u6A21\u578B\u6620\u5C04\uFF1A\u666E\u901A\u5BF9\u8BDD\u7528 fast\uFF0C\u590D\u6742\u63A8\u7406\u7528 smart\uFF1B\u503C\u5BF9\u5E94\u4E0A\u65B9 models \u7684 id\u3002
7072
7274
  # scenarios:
7073
7275
  # default: fast
7074
7276
  # chat: fast
@@ -7220,14 +7422,18 @@ function generateEnvExample(features, configs, includeDisabled = false, configCo
7220
7422
  if (!keys.has(key) && !includeDisabled)
7221
7423
  continue;
7222
7424
  const variables = configEnvironmentVariables(key, configContents[key] ?? generateConfigFile(key, configs));
7223
- const section = renderEnvironment(variables);
7425
+ const section = renderEnvironment(variables.filter((variable) => !variable.optional));
7426
+ const declaredOptional = renderEnvironment(variables.filter((variable) => variable.optional));
7224
7427
  const activeNames = new Set(variables.map((variable) => variable.name));
7225
- const optional = renderEnvironment(moduleEnvironmentVariables(key).filter((variable) => !activeNames.has(variable.name)));
7428
+ const candidates = moduleEnvironmentVariables(key);
7429
+ const primitiveArrays = candidates.filter((variable) => variable.constraint.includes("JSON \u6570\u7EC4") && candidates.some((child) => child.name === `${variable.name}_0` && !child.constraint.includes("JSON \u5BF9\u8C61")));
7430
+ const optional = renderEnvironment(candidates.filter((variable) => !activeNames.has(variable.name) && !primitiveArrays.some((parent) => variable.name.startsWith(`${parent.name}_`)) && !variables.some((child) => child.name.startsWith(`${variable.name}_`) && (variable.constraint.includes("JSON \u5BF9\u8C61") || variable.constraint.includes("JSON \u6570\u7EC4")) && !variable.constraint.includes("false")) && (!(variable.constraint.includes("JSON \u5BF9\u8C61") || variable.constraint.includes("JSON \u6570\u7EC4")) || variable.constraint.includes("false") || !candidates.some((child) => child.name.startsWith(`${variable.name}_`)) || primitiveArrays.includes(variable))));
7226
7431
  const commented = (value) => value.split("\n").map((line) => line && !line.startsWith("#") ? `# ${line}` : line).join("\n");
7227
7432
  sections.push(`# --- ${key} ---
7228
7433
  ${keys.has(key) ? section : commented(section)}
7229
7434
 
7230
- # \u53EF\u9009\u5B57\u6BB5\uFF1A\u5148\u542F\u7528 YAML \u8DEF\u5F84\uFF0C\u6216\u7528\u7236\u7EA7\u5BF9\u8C61\u6574\u4F53\u8986\u76D6\u3002
7435
+ # \u53EF\u9009\u5B57\u6BB5\uFF1A\u5148\u5728 YAML \u4E2D\u542F\u7528\u5BF9\u5E94\u914D\u7F6E\u5757\uFF1B\u4E0B\u5217\u53D8\u91CF\u540D\u4E0E\u5B57\u6BB5\u8DEF\u5F84\u4E00\u4E00\u5BF9\u5E94\u3002
7436
+ ${commented(declaredOptional)}
7231
7437
  ${commented(optional)}`);
7232
7438
  }
7233
7439
  return `${sections.join("\n\n")}
@@ -7276,6 +7482,16 @@ provider:
7276
7482
  expose:
7277
7483
  hostPort: 18080
7278
7484
  containerPort: 3000
7485
+ # HTTPS \u4E5F\u53EF\u5728 pnpm run deploy \u7684\u53EF\u9009\u8BC1\u4E66\u73AF\u8282\u4E2D\u914D\u7F6E\u3002
7486
+ # https:
7487
+ # type: files
7488
+ # domain: app.example.com
7489
+ # port: 443
7490
+ # redirectHttp: true
7491
+ # certificateFile: .hai/certificates/fullchain.pem
7492
+ # privateKeyFile: .hai/certificates/privkey.pem
7493
+ # Let's Encrypt\uFF1Atype \u6539\u4E3A letsencrypt\uFF0CHTTP hostPort \u8BBE\u4E3A 80\uFF1B
7494
+ # \u4EE5 email \u548C acceptTerms: true \u66FF\u4EE3\u4E24\u4E2A\u6587\u4EF6\u8DEF\u5F84\u3002
7279
7495
 
7280
7496
  container:
7281
7497
  s3Engine: \${HAI_DEPLOY_CONTAINER_S3ENGINE:rustfs} # rustfs | minio
@@ -7348,7 +7564,10 @@ providers:
7348
7564
  - name: console_dev
7349
7565
  type: console
7350
7566
 
7351
- # SMTP \u90AE\u4EF6\uFF08\u6309\u9700\u5F00\u542F\uFF09
7567
+ # \u751F\u4EA7\u793A\u4F8B\uFF1A\u7528\u4E0B\u9762 providers \u6574\u6BB5\u66FF\u6362\u4E0A\u65B9\u63A7\u5236\u53F0\u5217\u8868\uFF1B\u4FDD\u7559\u9700\u8981\u7684\u9879\u3002
7568
+ # \u6570\u7EC4\u7D22\u5F15\u4ECE 0 \u5F00\u59CB\uFF0C\u5220\u6389\u67D0\u9879\u540E\u540C\u6B65\u4FEE\u6539\u5176\u4F59\u73AF\u5883\u53D8\u91CF\u4E2D\u7684\u7D22\u5F15\u3002
7569
+ # providers:
7570
+ # SMTP \u90AE\u4EF6
7352
7571
  # - name: email
7353
7572
  # type: smtp
7354
7573
  # host: \${HAI_REACH_PROVIDERS_0_HOST:smtp.example.com}
@@ -7361,8 +7580,8 @@ providers:
7361
7580
  # \u963F\u91CC\u4E91\u77ED\u4FE1\uFF08\u6309\u9700\u5F00\u542F\uFF09
7362
7581
  # - name: sms
7363
7582
  # type: aliyun-sms
7364
- # accessKeyId: \${HAI_REACH_PROVIDERS_0_ACCESSKEYID}
7365
- # accessKeySecret: \${HAI_REACH_PROVIDERS_0_ACCESSKEYSECRET}
7583
+ # accessKeyId: \${HAI_REACH_PROVIDERS_1_ACCESSKEYID}
7584
+ # accessKeySecret: \${HAI_REACH_PROVIDERS_1_ACCESSKEYSECRET}
7366
7585
  # signName: MyApp
7367
7586
  # endpoint: dysmsapi.aliyuncs.com
7368
7587
 
@@ -7372,7 +7591,7 @@ providers:
7372
7591
  # url: https://notify.example.com/send
7373
7592
  # method: POST # POST | PUT
7374
7593
  # headers:
7375
- # Authorization: 'Bearer \${HAI_REACH_PROVIDERS_0_HEADERS_AUTHORIZATION}'
7594
+ # Authorization: 'Bearer \${HAI_REACH_PROVIDERS_2_HEADERS_AUTHORIZATION}'
7376
7595
  # timeout: 10000
7377
7596
  # redirect: error # \u666E\u901A\u6D88\u606F\u624D\u53EF\u663E\u5F0F follow\uFF1B\u654F\u611F\u53D1\u9001\u59CB\u7EC8\u62D2\u7EDD\u8DF3\u8F6C\u3002
7378
7597
  # requireHttps: true # \u5F3A\u5236 HTTPS\uFF1B\u7701\u7565\u65F6\u751F\u4EA7\u654F\u611F\u53D1\u9001\u4ECD\u8981\u6C42 HTTPS\u3002
@@ -7403,7 +7622,8 @@ templates: []
7403
7622
  # start: "22:00"
7404
7623
  # end: "08:00"
7405
7624
 
7406
- # \u5EF6\u8FDF\u961F\u5217\u91CD\u8BD5\u7B56\u7565\uFF08\u5165\u961F\u65F6\u6301\u4E45\u4FDD\u5B58\uFF1B\u9886\u53D6/\u5D29\u6E83\u6062\u590D\u8BA1\u6570\uFF0C\u8D85\u9650 dead\uFF1Bunknown \u7981\u6B62\u81EA\u52A8\u91CD\u53D1\uFF09
7625
+ # \u53D1\u9001\u5931\u8D25\u65F6\u6700\u591A\u5C1D\u8BD5 5 \u6B21\uFF1B\u7B49\u5F85\u65F6\u95F4\u4ECE 1 \u5206\u949F\u9010\u6B21\u52A0\u500D\uFF0C\u6700\u957F 1 \u5C0F\u65F6\u3002
7626
+ # \u65E0\u6CD5\u786E\u8BA4\u5BF9\u65B9\u662F\u5426\u6536\u5230\u65F6\u505C\u6B62\u81EA\u52A8\u91CD\u53D1\uFF0C\u5148\u6838\u5BF9\u6295\u9012\u7ED3\u679C\u3002\u4FEE\u6539\u7B56\u7565\u53EA\u5F71\u54CD\u4EE5\u540E\u8FDB\u5165\u961F\u5217\u7684\u6D88\u606F\u3002
7407
7627
  queue:
7408
7628
  maxAttempts: \${HAI_REACH_QUEUE_MAXATTEMPTS:5}
7409
7629
  retryDelayMs: \${HAI_REACH_QUEUE_RETRYDELAYMS:60000}
@@ -7436,7 +7656,7 @@ function generateAuditConfig() {
7436
7656
  # \u5BA1\u8BA1\u65E5\u5FD7\u914D\u7F6E (@h-ai/audit)
7437
7657
  # =============================================================================
7438
7658
 
7439
- # \u7528\u6237\u8868\u540D\uFF08\u7528\u4E8E JOIN \u67E5\u8BE2\uFF09
7659
+ # \u5BA1\u8BA1\u5217\u8868\u67E5\u8BE2\u64CD\u4F5C\u8005\u540D\u79F0\u65F6\u4F7F\u7528\u7684\u7528\u6237\u8868\u3002\u4F7F\u7528\u6846\u67B6 IAM \u65F6\u4FDD\u6301\u4E0B\u9762\u4E09\u4E2A\u9ED8\u8BA4\u503C\u3002
7440
7660
  userTable: hai_iam_users
7441
7661
 
7442
7662
  # \u7528\u6237\u8868\u4E3B\u952E\u5217\u540D
@@ -7445,22 +7665,27 @@ userIdColumn: id
7445
7665
  # \u7528\u6237\u540D\u5217\u540D
7446
7666
  userNameColumn: username
7447
7667
 
7448
- # \u6846\u67B6\u81EA\u52A8\u4E8B\u4EF6\u91C7\u96C6\uFF1B\u663E\u5F0F\u4E1A\u52A1 audit.log \u4E0D\u53D7\u6B64\u5F00\u5173\u5F71\u54CD
7668
+ # \u81EA\u52A8\u8BB0\u5F55\u5DF2\u63A5\u5165\u6846\u67B6\u7684\u91CD\u8981\u64CD\u4F5C\uFF1BincludeReads=true \u65F6\u4E5F\u8BB0\u5F55\u6210\u529F\u67E5\u8BE2\uFF0C\u4F1A\u589E\u52A0\u8BB0\u5F55\u91CF\u3002
7669
+ # enabled=false \u53EA\u5173\u95ED\u81EA\u52A8\u91C7\u96C6\uFF0C\u4E1A\u52A1\u4E3B\u52A8\u8C03\u7528 audit.log() \u4ECD\u53EF\u5199\u5165\u3002
7449
7670
  capture:
7450
7671
  enabled: true
7451
7672
  includeReads: false
7452
7673
 
7453
- # \u5E94\u7528\u793A\u4F8B\u4FDD\u62A4\u8FD1\u671F\u65E5\u5FD7\uFF1B\u6846\u67B6\u672A\u914D\u7F6E\u65F6\u4E0D\u5F3A\u5236\u542F\u7528\u30020\u5929\u6E05\u7406\u4E0D\u80FD\u7ED5\u8FC7\u5DF2\u542F\u7528\u4FDD\u62A4\u3002
7674
+ # enabled=true \u540E\uFF0C\u6700\u8FD1 minDays \u5929\u7684\u8BB0\u5F55\u4E0D\u80FD\u4FEE\u6539\u6216\u5220\u9664\uFF1B\u8D85\u8FC7\u4FDD\u62A4\u671F\u4E5F\u4E0D\u4F1A\u81EA\u52A8\u5220\u9664\u3002
7675
+ # \u4FDD\u62A4\u8BBE\u7F6E\u4F1A\u5B58\u5165\u6570\u636E\u5E93\uFF0C\u5220\u6389\u8FD9\u4E00\u6BB5\u4F1A\u6CBF\u7528\u5DF2\u6709\u8BBE\u7F6E\uFF1B\u660E\u786E enabled=false \u624D\u5173\u95ED\u4FDD\u62A4\u3002
7454
7676
  retention:
7455
7677
  enabled: false
7456
7678
  minDays: 90
7457
7679
 
7458
- # \u51ED\u636E\u59CB\u7EC8\u8131\u654F\uFF1B\u4EC5\u4E1A\u52A1\u9690\u79C1\u53EF\u5173\u95ED\uFF0C\u53EF\u8865\u5145\u9879\u76EE\u5B57\u6BB5\u540D
7680
+ # fields \u586B\u989D\u5916\u7684\u9690\u79C1\u5B57\u6BB5\u540D\uFF0C\u4F8B\u5982 [customerPhone, idCard]\uFF0C\u4E0D\u533A\u5206\u5927\u5C0F\u5199\u3002
7681
+ # \u5BC6\u7801\u3001\u4EE4\u724C\u7B49\u51ED\u636E\u59CB\u7EC8\u906E\u76D6\uFF1Benabled \u53EA\u63A7\u5236\u8FD9\u91CC\u8865\u5145\u7684\u4E1A\u52A1\u5B57\u6BB5\uFF0C\u4E0D\u6062\u590D\u5386\u53F2\u539F\u6587\u3002
7459
7682
  privacy:
7460
7683
  enabled: true
7461
7684
  fields: []
7462
7685
 
7463
- # \u79C1\u6709 JSONL \u5F52\u6863\uFF1B\u751F\u4EA7\u4F7F\u7528\u79C1\u6709\u5B58\u50A8\uFF0C\u5B9A\u65F6\u6267\u884C\u7531\u5E94\u7528\u73B0\u6709 Scheduler \u88C5\u914D\u3002
7686
+ # \u5C06\u5BA1\u8BA1\u53E6\u5B58\u4E3A\u79C1\u6709 JSONL \u5907\u4EFD\uFF0C\u542F\u7528\u524D\u5148\u521D\u59CB\u5316\u79C1\u6709 Storage\u3002
7687
+ # batchSize \u662F\u6BCF\u6279\u8BFB\u53D6\u6761\u6570\uFF1BmaxRecordBytes \u662F\u5355\u6761\u4E0A\u9650\uFF08\u5B57\u8282\uFF09\uFF0C\u8D85\u9650\u62A5\u9519\uFF0C\u4E0D\u622A\u65AD\u8BB0\u5F55\u3002
7688
+ # schedule.enabled=true \u6309 cron \u81EA\u52A8\u5907\u4EFD\uFF1B\u4F8B\u5982 UTC 02:00 \u5BF9\u5E94\u5317\u4EAC\u65F6\u95F4 10:00\u3002
7464
7689
  backup:
7465
7690
  enabled: false
7466
7691
  batchSize: 200
@@ -7470,18 +7695,21 @@ backup:
7470
7695
  cron: '0 2 * * *'
7471
7696
  timezone: UTC
7472
7697
 
7473
- # \u5206\u7EA7\u9608\u503C\u544A\u8B66\uFF1A\u542F\u7528\u524D\u914D\u7F6E\u89C4\u5219\u53CA Reach \u901A\u77E5\u76EE\u6807\u3002\u53EA\u7EDF\u8BA1\u5DF2\u63D0\u4EA4\u4E8B\u4EF6\u3002
7698
+ # \u6309\u4E00\u6BB5\u65F6\u95F4\u5185\u7684\u4E8B\u4EF6\u6570\u91CF\u901A\u77E5\u7BA1\u7406\u5458\uFF1B\u542F\u7528\u524D\u914D\u7F6E Reach\uFF0C\u5E76\u5C06 provider \u586B\u4E3A\u5DF2\u6CE8\u518C\u7684\u901A\u9053\u540D\u79F0\u3002
7699
+ # \u4F8B\u5B50\uFF1A5 \u5206\u949F\u5185\u767B\u5F55\u5931\u8D25/\u62D2\u7EDD\u8FBE\u5230 10 \u6B21\u65F6\u901A\u77E5\u5B89\u5168\u56E2\u961F\uFF1B\u89C4\u5219\u548C\u5B9A\u65F6\u68C0\u67E5\u9700\u8981\u5206\u522B\u542F\u7528\u3002
7474
7700
  alerts:
7475
7701
  enabled: false
7476
7702
  maxNotificationsPerCheck: 100
7477
7703
  rules: []
7478
- # - id: login-failures
7479
- # actions: [auth.login]
7480
- # outcomes: [failure, denied]
7481
- # threshold: 10
7482
- # windowSeconds: 300
7483
- # severity: warning
7484
- # targets: [{ id: security-team, provider: email, to: security@example.com }]
7704
+ # \u7528\u4E0B\u9762\u7684 rules \u5217\u8868\u66FF\u6362\u7A7A\u6570\u7EC4\u3002
7705
+ # rules:
7706
+ # - id: login-failures
7707
+ # actions: [auth.login]
7708
+ # outcomes: [failure, denied]
7709
+ # threshold: 10
7710
+ # windowSeconds: 300
7711
+ # severity: warning
7712
+ # targets: [{ id: security-team, provider: email, to: security@example.com }]
7485
7713
  schedule:
7486
7714
  enabled: false
7487
7715
  cron: '* * * * *'
@@ -7552,6 +7780,6 @@ envAllowlist:
7552
7780
  `;
7553
7781
  }
7554
7782
 
7555
- export { generateConfigFile, generateEnvExample, generateProductionEnvironment, moduleEnvironmentVariables, parameterizeConfig, renderEnvironment, runtimeEnvironmentVariables };
7556
- //# sourceMappingURL=chunk-EF7WOFWZ.js.map
7557
- //# sourceMappingURL=chunk-EF7WOFWZ.js.map
7783
+ export { documentConfig, generateConfigFile, generateEnvExample, generateProductionEnvironment, moduleEnvironmentVariables, parameterizeConfig, renderEnvironment, runtimeEnvironmentVariables };
7784
+ //# sourceMappingURL=chunk-YVNNMC4H.js.map
7785
+ //# sourceMappingURL=chunk-YVNNMC4H.js.map