@h-ai/cli 1.0.0-beta.6 → 1.0.0-beta.8
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.
- package/README.en.md +9 -9
- package/README.ja.md +9 -9
- package/README.md +9 -9
- package/dist/{chunk-4XVCGFBA.js → chunk-MEEFB4BI.js} +552 -11
- package/dist/chunk-MEEFB4BI.js.map +1 -0
- package/dist/{chunk-STWZQ3IP.js → chunk-SGWSVWZ5.js} +588 -11
- package/dist/chunk-SGWSVWZ5.js.map +1 -0
- package/dist/cli-config-templates-SVV3633D.js +5 -0
- package/dist/{cli-config-templates-YGPVNRX5.js.map → cli-config-templates-SVV3633D.js.map} +1 -1
- package/dist/index.js +97 -78
- package/dist/index.js.map +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/{src-NXCCU6GO.js → src-IW4CY2IN.js} +3 -3
- package/dist/src-IW4CY2IN.js.map +1 -0
- package/package.json +16 -12
- package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +1 -1
- package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +6 -2
- package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +29 -3
- package/templates/apps/fullstack/.gitignore.hbs +7 -2
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +2 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +2 -2
- package/templates/apps/mobile-app/messages/en-US.json +1 -1
- package/templates/apps/mobile-app/messages/ja-JP.json +1 -1
- package/templates/apps/mobile-app/messages/zh-CN.json +1 -1
- package/templates/apps/mobile-app/src/lib/api.ts.hbs +8 -5
- package/templates/base/.gitignore.hbs +7 -2
- package/templates/base/e2e/app.spec.ts.hbs +9 -4
- package/templates/base/package.json.hbs +7 -2
- package/templates/skills/hai-ai/SKILL.md +6 -2
- package/templates/skills/hai-ai/acp.md +145 -0
- package/templates/skills/hai-ai/guide.md +1 -1
- package/templates/skills/hai-ai/reference.md +1 -1
- package/templates/skills/hai-ai/resources.md +69 -0
- package/templates/skills/hai-api-client/reference.md +2 -0
- package/templates/skills/hai-app-create/development.md +1 -1
- package/templates/skills/hai-app-create/reference.md +1 -1
- package/templates/skills/hai-build/SKILL.md +1 -1
- package/templates/skills/hai-build/reference.md +1 -1
- package/templates/skills/hai-cache/reference.md +6 -2
- package/templates/skills/hai-ci/SKILL.md +2 -0
- package/templates/skills/hai-core/SKILL.md +1 -1
- package/templates/skills/hai-crypto/reference.md +2 -0
- package/templates/skills/hai-payment/reference.md +39 -17
- package/templates/skills/hai-reach/reference.md +15 -7
- package/templates/skills/hai-reldb/reference.md +5 -2
- package/templates/skills/hai-scheduler/reference.md +1 -1
- package/templates/skills/hai-storage/reference.md +8 -2
- package/templates/skills/hai-vecdb/reference.md +7 -2
- package/dist/chunk-4XVCGFBA.js.map +0 -1
- package/dist/chunk-STWZQ3IP.js.map +0 -1
- package/dist/cli-config-templates-YGPVNRX5.js +0 -5
- package/dist/src-NXCCU6GO.js.map +0 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export { generateConfigFile, generateEnvExample, generateProductionEnvironment } from './chunk-SGWSVWZ5.js';
|
|
3
|
+
import './chunk-ZSDEVXZ7.js';
|
|
4
|
+
//# sourceMappingURL=cli-config-templates-SVV3633D.js.map
|
|
5
|
+
//# sourceMappingURL=cli-config-templates-SVV3633D.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"cli-config-templates-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"cli-config-templates-SVV3633D.js"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { generateConfigFile, runtimeEnvironmentVariables, renderEnvironment, generateProductionEnvironment, moduleEnvironmentVariables, documentConfig, parameterizeConfig } from './chunk-
|
|
2
|
+
import { generateConfigFile, runtimeEnvironmentVariables, renderEnvironment, generateProductionEnvironment, moduleEnvironmentVariables, documentConfig, parameterizeConfig } from './chunk-SGWSVWZ5.js';
|
|
3
3
|
import { cliM } from './chunk-7DNIMG2H.js';
|
|
4
|
-
import { normalizeProjectName, resolveImageReference, resolveDownloadProxy } from './chunk-
|
|
4
|
+
import { normalizeProjectName, resolveImageReference, resolveDownloadProxy } from './chunk-MEEFB4BI.js';
|
|
5
5
|
import './chunk-ZSDEVXZ7.js';
|
|
6
6
|
import process5 from 'process';
|
|
7
7
|
import { cac } from 'cac';
|
|
@@ -14,7 +14,7 @@ import Handlebars2 from 'handlebars';
|
|
|
14
14
|
import { parseEnv } from 'util';
|
|
15
15
|
import ora from 'ora';
|
|
16
16
|
import prompts from 'prompts';
|
|
17
|
-
import { parse, stringify, parseAllDocuments } from 'yaml';
|
|
17
|
+
import { parse, stringify, parseDocument, parseAllDocuments } from 'yaml';
|
|
18
18
|
import { Buffer } from 'buffer';
|
|
19
19
|
import { execSync, execFileSync, spawn } from 'child_process';
|
|
20
20
|
import { randomBytes, createECDH, randomUUID, createHash } from 'crypto';
|
|
@@ -133,11 +133,10 @@ Handlebars2.registerHelper("html", (value) => Handlebars2.escapeExpression(value
|
|
|
133
133
|
Handlebars2.registerHelper("yaml", (key, value) => stringify({ [key]: value }).trim());
|
|
134
134
|
Handlebars2.registerHelper("jsString", (value) => `'${JSON.stringify(value).slice(1, -1).replace(/\\"/g, '"').replace(/'/g, "\\'")}'`);
|
|
135
135
|
Handlebars2.registerHelper("moduleConfig", function(moduleKey, enabled) {
|
|
136
|
-
const generated = generateConfigFile(moduleKey, this.moduleConfigs).trimEnd();
|
|
136
|
+
const generated = generateConfigFile(moduleKey, this.moduleConfigs, Boolean(enabled)).trimEnd();
|
|
137
137
|
const content = moduleKey === "feedback" ? generated.replace("HAI_FEEDBACK_APPID:my-app", `HAI_FEEDBACK_APPID:${this.projectName}`) : generated;
|
|
138
138
|
const configured = this.appType === "fullstack" && moduleKey === "iam" ? content.replace("HAI_IAM_SEEDDEFAULTDATA:true", "HAI_IAM_SEEDDEFAULTDATA:false").replace("variant: card", "variant: split") : content;
|
|
139
|
-
return
|
|
140
|
-
${configured.split("\n").map((line) => line ? `# ${line}` : "").join("\n")}`;
|
|
139
|
+
return configured;
|
|
141
140
|
});
|
|
142
141
|
var TEMPLATE_SKIP_IF_EMPTY_MARKER = "@skipIfEmpty";
|
|
143
142
|
var NORMALIZED_RENDER_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".js", ".svelte", ".json", ".css"]);
|
|
@@ -460,7 +459,11 @@ function buildApiWorkspaceCatalogPackages(featureMap) {
|
|
|
460
459
|
function buildAppHaiCatalogPackages(options) {
|
|
461
460
|
const packageNames = ["@h-ai/cli"];
|
|
462
461
|
if (options.isSvelteOnlyApp) {
|
|
463
|
-
packageNames.push("@h-ai/api-client", "@h-ai/
|
|
462
|
+
packageNames.push("@h-ai/api-client", "@h-ai/capacitor", "@h-ai/core", "@h-ai/ui");
|
|
463
|
+
if (options.featureMap.iam)
|
|
464
|
+
packageNames.push("@h-ai/api-contract");
|
|
465
|
+
if (options.featureMap.deploy)
|
|
466
|
+
packageNames.push("@h-ai/deploy");
|
|
464
467
|
if (options.featureMap.crypto)
|
|
465
468
|
packageNames.push("@h-ai/crypto");
|
|
466
469
|
return pickCatalogPackages(packageNames, HAI_CATALOG_PACKAGES);
|
|
@@ -1228,7 +1231,14 @@ var FEATURES = {
|
|
|
1228
1231
|
packages: ["@h-ai/capacitor"]
|
|
1229
1232
|
}
|
|
1230
1233
|
};
|
|
1231
|
-
var
|
|
1234
|
+
var TEMPLATE_FEATURES = {
|
|
1235
|
+
"admin": ["iam", "reach"],
|
|
1236
|
+
"website": [],
|
|
1237
|
+
"h5": ["iam", "reach"],
|
|
1238
|
+
"api": ["iam", "reach", "storage", "feedback"],
|
|
1239
|
+
"mobile-app": ["iam", "crypto", "api-client", "capacitor"],
|
|
1240
|
+
"fullstack": ["iam", "storage", "audit", "reach", "scheduler", "feedback"]
|
|
1241
|
+
};
|
|
1232
1242
|
var PROJECT_NAME_REGEX = /^[a-z0-9-]+$/;
|
|
1233
1243
|
async function createProject(options) {
|
|
1234
1244
|
const spinner = ora();
|
|
@@ -1271,30 +1281,23 @@ async function createProject(options) {
|
|
|
1271
1281
|
});
|
|
1272
1282
|
await generateFromTemplates(projectPath, context);
|
|
1273
1283
|
{
|
|
1274
|
-
const { generateConfigFile: generateConfigFile2, generateEnvExample, generateProductionEnvironment: generateProductionEnvironment2 } = await import('./cli-config-templates-
|
|
1284
|
+
const { generateConfigFile: generateConfigFile2, generateEnvExample, generateProductionEnvironment: generateProductionEnvironment2 } = await import('./cli-config-templates-SVV3633D.js');
|
|
1275
1285
|
const configs = resolvedOptions.moduleConfigs;
|
|
1276
1286
|
const isApiWorkspace = resolvedOptions.appType === "api";
|
|
1277
1287
|
const isFullstack = resolvedOptions.appType === "fullstack";
|
|
1278
1288
|
const configDir = isApiWorkspace ? path2.join(projectPath, "apps", `${resolvedOptions.name}-serv`, "config") : isFullstack ? path2.join(projectPath, "packages", `${resolvedOptions.name}-serv`, "config") : path2.join(projectPath, "config");
|
|
1279
1289
|
const envExamplePath = isApiWorkspace ? path2.join(projectPath, "apps", `${resolvedOptions.name}-serv`, ".env.example") : path2.join(projectPath, ".env.example");
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
if (!isApiWorkspace && !isFullstack) {
|
|
1292
|
-
await writeFile(
|
|
1293
|
-
path2.join(configDir, "_core.yml"),
|
|
1294
|
-
generateConfigFile2("core", configs)
|
|
1295
|
-
);
|
|
1296
|
-
if (!context.isSvelteOnlyApp)
|
|
1297
|
-
await writeFile(path2.join(configDir, "_kit.yml"), generateConfigFile2("kit", configs));
|
|
1290
|
+
const enabledConfigs = /* @__PURE__ */ new Set(["core", ...context.isSvelteOnlyApp ? [] : resolvedOptions.features.map(getFeatureConfigKey).filter(Boolean)]);
|
|
1291
|
+
if (isApiWorkspace || isFullstack)
|
|
1292
|
+
enabledConfigs.add("serv");
|
|
1293
|
+
else if (!context.isSvelteOnlyApp)
|
|
1294
|
+
enabledConfigs.add("kit");
|
|
1295
|
+
for (const configKey of ["core", "serv", "kit", "db", "cache", "iam", "storage", "audit", "reach", "ai", "vecdb", "payment", "scheduler", "feedback"]) {
|
|
1296
|
+
const configPath = path2.join(configDir, `_${configKey}.yml`);
|
|
1297
|
+
if ((isApiWorkspace || isFullstack) && await fse.pathExists(configPath))
|
|
1298
|
+
continue;
|
|
1299
|
+
const content = generateConfigFile2(configKey, configs, enabledConfigs.has(configKey));
|
|
1300
|
+
await writeFile(configPath, configKey === "feedback" ? content.replace("HAI_FEEDBACK_APPID:my-app", `HAI_FEEDBACK_APPID:${resolvedOptions.name}`) : content);
|
|
1298
1301
|
}
|
|
1299
1302
|
const configContents = {};
|
|
1300
1303
|
for (const file of await fse.readdir(configDir)) {
|
|
@@ -1302,7 +1305,7 @@ async function createProject(options) {
|
|
|
1302
1305
|
configContents[file.slice(1, -4)] = await fse.readFile(path2.join(configDir, file), "utf8");
|
|
1303
1306
|
}
|
|
1304
1307
|
const envFeatures = context.isSvelteOnlyApp ? [] : isFullstack ? [.../* @__PURE__ */ new Set([...resolvedOptions.features, "reach"])] : resolvedOptions.features;
|
|
1305
|
-
const envContents = generateEnvExample(envFeatures, configs,
|
|
1308
|
+
const envContents = generateEnvExample(envFeatures, configs, true, configContents);
|
|
1306
1309
|
let envExample = isApiWorkspace ? envContents : isFullstack ? `${envContents}
|
|
1307
1310
|
# First-start administrator password; must satisfy the IAM password policy.
|
|
1308
1311
|
HAI_ADMIN_DEFAULT_PASSWORD=
|
|
@@ -1452,7 +1455,7 @@ ${formatPromptDescription(cliM("cli_selectHint"))}`,
|
|
|
1452
1455
|
}
|
|
1453
1456
|
const selectedAppType = resolvedAppType || "admin";
|
|
1454
1457
|
const selectedFrontends = selectedAppType === "fullstack" ? await resolveFrontendTargets(options.frontends, useDefaults, onCancel) : [];
|
|
1455
|
-
let selectedFeatures = selectedAppType === "mobile-app" ? [
|
|
1458
|
+
let selectedFeatures = selectedAppType === "mobile-app" ? [...TEMPLATE_FEATURES[selectedAppType]] : resolveFeatureDependencies(TEMPLATE_FEATURES[selectedAppType]);
|
|
1456
1459
|
selectedFeatures = selectedFeatures.filter((feature) => feature !== "deploy");
|
|
1457
1460
|
if (options.deploy !== false)
|
|
1458
1461
|
selectedFeatures.push("deploy");
|
|
@@ -1857,7 +1860,9 @@ function generateEnvironmentReadme() {
|
|
|
1857
1860
|
|
|
1858
1861
|
\u8FD0\u884C\u53C2\u6570\u5728 \`.env.example\` \u4E2D\u9010\u9879\u8BF4\u660E\u7528\u9014\u3001\u679A\u4E3E\u548C\u8303\u56F4\u3002\`.env\` \u4E3A\u516C\u5171\u57FA\u7840\uFF0C\`.env.dev\` / \`.env.test\` / \`.env.prod\` \u4E3A\u73AF\u5883\u8986\u76D6\uFF0C\u5747\u63D0\u4EA4 Git\uFF1B\`.env.local\` \u4E3A\u672C\u673A\u79C1\u6709\u8986\u76D6\uFF0C\u4E0D\u63D0\u4EA4 Git\u3002\u4F18\u5148\u7EA7\u4E3A\u8FDB\u7A0B > \`.env.<mode>.local\` > \`.env.local\` > \`.env.<mode>\` > \`.env\` > YAML\u3002\u540C\u6765\u6E90\u5148\u7236 JSON \u540E\u7EC6\u9879\uFF0C\u9AD8\u6765\u6E90\u6574\u6BB5\u66FF\u6362\u5148\u6E05\u9664\u4F4E\u6765\u6E90\u7EC6\u9879\u3002YAML \u663E\u5F0F\u5F15\u7528 \`HAI_<\u914D\u7F6E\u540D>_<\u8DEF\u5F84>\` \u5E76\u4FDD\u7559\u672C\u5730\u56DE\u9000\uFF0CcamelCase \u4E0D\u62C6\u8BCD\u3002\u5B8C\u6574\u547D\u4EE4\u3001\u52A0\u8F7D\u4F18\u5148\u7EA7\u548C Provider \u5207\u6362\u89C1 [\u73AF\u5883\u914D\u7F6E](.agents/skills/hai-app-create/development.md#\u73AF\u5883\u914D\u7F6E)\u3002
|
|
1859
1862
|
|
|
1860
|
-
\
|
|
1863
|
+
\u4F9D\u8D56\u53EA\u5305\u542B\u6A21\u677F\u5B9E\u9645\u4F7F\u7528\u7684\u6A21\u5757\uFF1Bconfig \u4E0E \`.env.example\` \u4FDD\u7559\u6240\u6709\u6A21\u5757\u7684\u5B8C\u6574\u53C2\u8003\uFF0C\u672A\u542F\u7528\u9879\u4EE5\u6CE8\u91CA\u63D0\u4F9B\uFF0C\u4E0D\u8FDB\u5165\u516C\u5171\u73AF\u5883\u9ED8\u8BA4\u503C\u3002\u65B0\u589E\u529F\u80FD\u65F6\u6DFB\u52A0\u4F9D\u8D56\u3001\u542F\u7528\u6240\u9700\u914D\u7F6E\uFF0C\u518D\u63A5\u5165\u521D\u59CB\u5316\u3001\u53CD\u5E8F\u5173\u95ED\u548C\u4E1A\u52A1\u4EE3\u7801\uFF1B\u5B89\u88C5\u4F9D\u8D56\u4E0D\u4F1A\u81EA\u52A8\u63A5\u5165\u6A21\u5757\u3002\u7EAF\u5BA2\u6237\u7AEF\u7684\u670D\u52A1\u7AEF\u914D\u7F6E\u4EC5\u4F9B\u540E\u7EED\u540E\u7AEF\u96C6\u6210\u53C2\u8003\uFF0C\u79D8\u5BC6\u4E0D\u5F97\u6CE8\u5165\u6D4F\u89C8\u5668\u3002
|
|
1864
|
+
|
|
1865
|
+
\u751F\u4EA7 .env.prod \u6309\u5DF2\u542F\u7528\u6A21\u5757\u9009\u62E9\u5171\u4EAB PostgreSQL\uFF08\u660E\u786E\u9009\u62E9 MySQL \u65F6\u4FDD\u7559\uFF09\u3001Redis\u3001S3\u3001Qdrant\uFF0C\u9ED8\u8BA4\u4F7F\u7528 Compose \u5185\u90E8\u670D\u52A1\u540D db/cache/storage/vecdb\u3002\u5BC6\u7801\u3001S3 \u51ED\u636E\u3001\u6A21\u578B Key \u4E0E\u53D7\u4FDD\u62A4 Qdrant \u7684 Key \u53EA\u7531\u79C1\u6709\u73AF\u5883\u6CE8\u5165\uFF1B\u5BB9\u5668\u5916\u8FD0\u884C\u8986\u76D6\u5185\u90E8\u8FDE\u63A5\u5730\u5740\u3002\u751F\u4EA7 Reach \u5FC5\u987B\u6CE8\u5165\u771F\u5B9E HAI_REACH_PROVIDERS JSON\uFF0C\u516C\u5171\u7A7A\u6570\u7EC4\u4F1A\u62D2\u7EDD\u542F\u52A8\u3002\u540E\u7EED\u901A\u8FC7 hai add ai \u8865\u9F50 db+vecdb \u4F9D\u8D56\u65F6\uFF0C\u8FD8\u987B\u5728\u5E94\u7528\u5165\u53E3\u63A5\u5165\u521D\u59CB\u5316\u548C\u53CD\u5E8F\u5173\u95ED\uFF0C\u4E0D\u80FD\u4EC5\u5B89\u88C5\u4F9D\u8D56\u3002
|
|
1861
1866
|
|
|
1862
1867
|
| \u7528\u9014 | \u547D\u4EE4 |
|
|
1863
1868
|
| --- | --- |
|
|
@@ -1913,7 +1918,7 @@ function generateReadme(name, appTypeLabel, pm, appType) {
|
|
|
1913
1918
|
const install = getInstallCommand(pm);
|
|
1914
1919
|
const staticWebsite = appType === "website" ? `### \u9759\u6001\u7F51\u7AD9\u4E0E GitHub Pages
|
|
1915
1920
|
|
|
1916
|
-
\u9ED8\u8BA4\u4F7F\u7528Node SSR\uFF0C\
|
|
1921
|
+
\u9ED8\u8BA4\u4F7F\u7528Node SSR\uFF0C\u53EA\u5B89\u88C5\u5C55\u793A\u529F\u80FD\u6240\u9700\u7684Core/Kit/UI\uFF0C\u53EF\u76F4\u63A5\u5207\u6362\u9759\u6001\u53D1\u5E03\uFF1B\u5B8C\u6574\u6CE8\u91CA\u914D\u7F6E\u4E0D\u542F\u7528\u6A21\u5757\u3002\u540E\u7EED\u65B0\u589E\u7684\u670D\u52A1\u7AEF\u4E1A\u52A1\u4F9D\u8D56\u3001\u521D\u59CB\u5316\u53CAAPI/actions\u987B\u5148\u79FB\u9664\uFF0C\u5DF2\u6709\u52A8\u6001\u6A21\u5757\u4E0D\u80FD\u4EC5\u6253\u5F00\u5F00\u5173\u9759\u6001\u53D1\u5E03\u3002
|
|
1917
1922
|
|
|
1918
1923
|
\`HAI_BUILD_STATIC=1\`\u663E\u5F0F\u9884\u6E32\u67D3\uFF0C\`PUBLIC_BASE_PATH=/${name}\`\u6307\u5B9A\u9879\u76EE\u7AD9\u76EE\u5F55\uFF08\u65E0\u672B\u5C3E/\uFF0C\u6839\u7AD9\u7559\u7A7A\uFF09\uFF1B\u5728PowerShell\u8BBE\u7F6E\u672C\u6B21\u6784\u5EFA\u73AF\u5883\uFF1A
|
|
1919
1924
|
|
|
@@ -2103,7 +2108,7 @@ CLI \u5728\u6839\u76EE\u5F55 .env.dev.local\u3001.env.test.local\u3001.env.prod.
|
|
|
2103
2108
|
|
|
2104
2109
|
### \u914D\u7F6E\u6269\u5C55
|
|
2105
2110
|
|
|
2106
|
-
\u670D\u52A1\u7AEF \`packages/${name}-serv/config/\` \u59CB\u7EC8\u4FDD\u7559 core\u3001serv\u3001db\u3001cache\u3001iam\u3001storage\u3001audit\u3001reach\u3001ai\u3001vecdb\u3001payment\u3001scheduler\u3001feedback \u5171
|
|
2111
|
+
\u670D\u52A1\u7AEF \`packages/${name}-serv/config/\` \u59CB\u7EC8\u4FDD\u7559 core\u3001serv\u3001kit\u3001db\u3001cache\u3001iam\u3001storage\u3001audit\u3001reach\u3001ai\u3001vecdb\u3001payment\u3001scheduler\u3001feedback \u5171 14 \u4EFD YAML\uFF1B\u6784\u5EFA\u90E8\u7F72\u914D\u7F6E\u7EDF\u4E00\u4F4D\u4E8E\u9879\u76EE\u6839 hai.json\u3002\u53EA\u5B89\u88C5\u7BA1\u7406\u540E\u53F0\u5B9E\u9645\u4F7F\u7528\u7684\u6A21\u5757\uFF1B\u5DF2\u7528\u6A21\u5757\u4FDD\u7559\u5DE5\u4F5C\u9ED8\u8BA4\u503C\uFF0C\u672A\u542F\u7528\u6A21\u5757\u6574\u4EFD\u6CE8\u91CA\uFF0C\u53EF\u9009\u5B57\u6BB5\u548C\u66FF\u4EE3 Provider \u6309\u5757\u6CE8\u91CA\uFF1B\u6839 \`.env.example\` \u4E5F\u4FDD\u7559\u672A\u542F\u7528\u6A21\u5757\u7684\u51ED\u636E\u793A\u4F8B\u3002\u65B0\u589E\u529F\u80FD\u65F6\u5B89\u88C5\u4F9D\u8D56\u5E76\u63A5\u5165\u521D\u59CB\u5316\u3001\u5173\u95ED\u53CA\u4E1A\u52A1\u4EE3\u7801\u3002Reach \u9ED8\u8BA4\u4E3A\u5F00\u53D1\u63A7\u5236\u53F0\u901A\u77E5\uFF0Cfeedback \u4F7F\u7528 email \u522B\u540D\uFF1B\u751F\u4EA7\u6309 \`_reach.yml\` \u6CE8\u91CA\u66FF\u6362\u4E3A SMTP\u3001\u77ED\u4FE1\u6216 API Provider\uFF0C\u5E76\u4FDD\u6301\u540D\u79F0\u552F\u4E00\u3002
|
|
2107
2112
|
|
|
2108
2113
|
\u81EA\u52A8\u751F\u6210\u7684 \`.env\` \u5305\u542B\u5DF2\u542F\u7528\u6A21\u5757\u7684\u73AF\u5883\u53C2\u6570\uFF1BYAML \u663E\u5F0F\u5F15\u7528\u76F8\u540C\u53D8\u91CF\u5E76\u4FDD\u7559\u672C\u5730\u56DE\u9000\u3002\u7F16\u8F91\u73AF\u5883\u53C2\u6570\u4F18\u5148\u4FEE\u6539\u5BF9\u5E94 \`.env\`\uFF1B\u672A\u542F\u7528\u6A21\u5757\u4ECD\u4FDD\u7559\u6CE8\u91CA\u3002
|
|
2109
2114
|
|
|
@@ -2244,7 +2249,7 @@ async function ensureDeployConfig(cwd) {
|
|
|
2244
2249
|
}
|
|
2245
2250
|
var MODULE_MAP = {
|
|
2246
2251
|
// iam 依赖 crypto(password hash)/ db(user 存储)/ cache(session 缓存)
|
|
2247
|
-
"iam": { packages: ["@h-ai/iam"],
|
|
2252
|
+
"iam": { packages: ["@h-ai/iam"], configKey: "iam", get description() {
|
|
2248
2253
|
return cliM("cli_featureIamName");
|
|
2249
2254
|
} },
|
|
2250
2255
|
// 'db' 和 'reldb' 都映射到 @h-ai/reldb,兼容用户习惯(hai add db 和 hai add reldb 均可)
|
|
@@ -2257,13 +2262,13 @@ var MODULE_MAP = {
|
|
|
2257
2262
|
"cache": { packages: ["@h-ai/cache"], configKey: "cache", get description() {
|
|
2258
2263
|
return cliM("cli_featureCacheName");
|
|
2259
2264
|
} },
|
|
2260
|
-
"ai": { packages: ["@h-ai/ai"],
|
|
2265
|
+
"ai": { packages: ["@h-ai/ai"], configKey: "ai", get description() {
|
|
2261
2266
|
return cliM("cli_featureAiName");
|
|
2262
2267
|
} },
|
|
2263
2268
|
"storage": { packages: ["@h-ai/storage"], configKey: "storage", get description() {
|
|
2264
2269
|
return cliM("cli_featureStorageName");
|
|
2265
2270
|
} },
|
|
2266
|
-
"crypto": { packages: ["@h-ai/crypto"],
|
|
2271
|
+
"crypto": { packages: ["@h-ai/crypto"], get description() {
|
|
2267
2272
|
return cliM("cli_featureCryptoName");
|
|
2268
2273
|
} },
|
|
2269
2274
|
"kit": { packages: ["@h-ai/kit"], get description() {
|
|
@@ -2284,13 +2289,13 @@ var MODULE_MAP = {
|
|
|
2284
2289
|
"reach": { packages: ["@h-ai/reach"], configKey: "reach", get description() {
|
|
2285
2290
|
return cliM("cli_featureReachName");
|
|
2286
2291
|
} },
|
|
2287
|
-
"feedback": { packages: ["@h-ai/feedback"],
|
|
2292
|
+
"feedback": { packages: ["@h-ai/feedback"], configKey: "feedback", get description() {
|
|
2288
2293
|
return cliM("cli_featureFeedbackName");
|
|
2289
2294
|
} },
|
|
2290
|
-
"scheduler": { packages: ["@h-ai/scheduler"],
|
|
2295
|
+
"scheduler": { packages: ["@h-ai/scheduler"], configKey: "scheduler", get description() {
|
|
2291
2296
|
return cliM("cli_featureSchedulerName");
|
|
2292
2297
|
} },
|
|
2293
|
-
"audit": { packages: ["@h-ai/audit"],
|
|
2298
|
+
"audit": { packages: ["@h-ai/audit"], configKey: "audit", get description() {
|
|
2294
2299
|
return cliM("cli_featureAuditName");
|
|
2295
2300
|
} },
|
|
2296
2301
|
"payment": { packages: ["@h-ai/payment"], configKey: "payment", get description() {
|
|
@@ -2323,25 +2328,62 @@ async function addModule(options) {
|
|
|
2323
2328
|
writeCliMessage(chalk.green(cliM("cli_addAllInstalled")));
|
|
2324
2329
|
return;
|
|
2325
2330
|
}
|
|
2326
|
-
const { selected } = await prompts({
|
|
2331
|
+
const { selected: selected2 } = await prompts({
|
|
2327
2332
|
type: "select",
|
|
2328
2333
|
hint: cliM("cli_selectHint"),
|
|
2329
2334
|
name: "selected",
|
|
2330
2335
|
message: cliM("cli_addModulePrompt"),
|
|
2331
2336
|
choices
|
|
2332
2337
|
});
|
|
2333
|
-
if (!
|
|
2338
|
+
if (!selected2)
|
|
2334
2339
|
return;
|
|
2335
|
-
moduleName =
|
|
2340
|
+
moduleName = selected2;
|
|
2336
2341
|
}
|
|
2337
|
-
const
|
|
2338
|
-
if (!
|
|
2342
|
+
const baseDefinition = MODULE_MAP[moduleName];
|
|
2343
|
+
if (!baseDefinition) {
|
|
2339
2344
|
writeCliError(chalk.red(cliM("cli_addUnknownModule", { params: { module: moduleName } })));
|
|
2340
2345
|
writeCliMessage(cliM("cli_addAvailableModules", { params: { modules: Object.keys(MODULE_MAP).join(", ") } }));
|
|
2341
2346
|
return;
|
|
2342
2347
|
}
|
|
2348
|
+
const selected = baseDefinition.configKey === "db" ? "db" : moduleName;
|
|
2349
|
+
const moduleDef = { ...baseDefinition, deps: resolveFeatureDependencies([selected]).filter((feature) => feature !== selected) };
|
|
2343
2350
|
const { generateProjectAiSupport, resolveSkillNamesForPackages } = await import('./cli-skill-templates-S2YH642Z.js');
|
|
2344
|
-
|
|
2351
|
+
const allPackages = new Set(moduleDef.packages);
|
|
2352
|
+
for (const dep of moduleDef.deps) {
|
|
2353
|
+
for (const name of MODULE_MAP[dep]?.packages ?? [])
|
|
2354
|
+
allPackages.add(name);
|
|
2355
|
+
}
|
|
2356
|
+
const pkgPath = path2.join(cwd, "package.json");
|
|
2357
|
+
const pkg = await fse.readJson(pkgPath);
|
|
2358
|
+
if (!pkg.dependencies)
|
|
2359
|
+
pkg.dependencies = {};
|
|
2360
|
+
const existingHaiSpecifier = Object.entries(pkg.dependencies).find(([pkgName]) => pkgName.startsWith("@h-ai/"))?.[1];
|
|
2361
|
+
const depVersion = existingHaiSpecifier === "catalog:" ? "catalog:" : getCliVersion();
|
|
2362
|
+
let catalogUpdated = false;
|
|
2363
|
+
if (depVersion === "catalog:") {
|
|
2364
|
+
let workspaceRoot = path2.resolve(cwd);
|
|
2365
|
+
while (!await fileExists(path2.join(workspaceRoot, "pnpm-workspace.yaml"))) {
|
|
2366
|
+
const parent = path2.dirname(workspaceRoot);
|
|
2367
|
+
if (parent === workspaceRoot) {
|
|
2368
|
+
workspaceRoot = path2.resolve(cwd);
|
|
2369
|
+
break;
|
|
2370
|
+
}
|
|
2371
|
+
workspaceRoot = parent;
|
|
2372
|
+
}
|
|
2373
|
+
const workspacePath = path2.join(workspaceRoot, "pnpm-workspace.yaml");
|
|
2374
|
+
const document = parseDocument(await fileExists(workspacePath) ? await fse.readFile(workspacePath, "utf8") : "packages: []\n");
|
|
2375
|
+
const currentVersion = document.getIn(["catalog", "@h-ai/core"]);
|
|
2376
|
+
const version = typeof currentVersion === "string" && /^[~^]?\d+\.\d+\.\d+/.test(currentVersion) ? currentVersion : getCliVersion();
|
|
2377
|
+
const dependencies = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
2378
|
+
const names = [.../* @__PURE__ */ new Set([...allPackages, ...Object.keys(dependencies).filter((name) => name.startsWith("@h-ai/") && dependencies[name] === "catalog:")])].filter((name) => !document.hasIn(["catalog", name]));
|
|
2379
|
+
for (const name of names)
|
|
2380
|
+
document.setIn(["catalog", name], version);
|
|
2381
|
+
if (names.length > 0) {
|
|
2382
|
+
await writeFile(workspacePath, document.toString());
|
|
2383
|
+
catalogUpdated = true;
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
if (!catalogUpdated && [...allPackages].every((p) => project.haiPackages.includes(p))) {
|
|
2345
2387
|
if (moduleName === "deploy")
|
|
2346
2388
|
await ensureDeployConfig(cwd);
|
|
2347
2389
|
const generatedFiles2 = await generateProjectAiSupport(
|
|
@@ -2362,24 +2404,7 @@ async function addModule(options) {
|
|
|
2362
2404
|
}
|
|
2363
2405
|
return;
|
|
2364
2406
|
}
|
|
2365
|
-
const allPackages = new Set(moduleDef.packages);
|
|
2366
|
-
if (moduleDef.deps) {
|
|
2367
|
-
for (const dep of moduleDef.deps) {
|
|
2368
|
-
const depDef = MODULE_MAP[dep];
|
|
2369
|
-
if (depDef) {
|
|
2370
|
-
for (const pkg2 of depDef.packages) {
|
|
2371
|
-
allPackages.add(pkg2);
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
2407
|
spinner.start(cliM("cli_addUpdateManifest"));
|
|
2377
|
-
const pkgPath = path2.join(cwd, "package.json");
|
|
2378
|
-
const pkg = await fse.readJson(pkgPath);
|
|
2379
|
-
if (!pkg.dependencies)
|
|
2380
|
-
pkg.dependencies = {};
|
|
2381
|
-
const existingHaiSpecifier = Object.entries(pkg.dependencies).find(([pkgName]) => pkgName.startsWith("@h-ai/"))?.[1];
|
|
2382
|
-
const depVersion = existingHaiSpecifier === "catalog:" ? "catalog:" : getCliVersion();
|
|
2383
2408
|
for (const pkgName of allPackages) {
|
|
2384
2409
|
if (pkgName === "@h-ai/deploy") {
|
|
2385
2410
|
pkg.devDependencies ??= {};
|
|
@@ -2404,16 +2429,14 @@ async function addModule(options) {
|
|
|
2404
2429
|
writeCliMessage(chalk.gray(cliM("cli_addConfigExists", { params: { config: moduleDef.configKey } })));
|
|
2405
2430
|
}
|
|
2406
2431
|
}
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
writeCliMessage(chalk.gray(cliM("cli_addDependencyConfig", { params: { config: depDef.configKey } })));
|
|
2416
|
-
}
|
|
2432
|
+
for (const dep of moduleDef.deps) {
|
|
2433
|
+
const depDef = MODULE_MAP[dep];
|
|
2434
|
+
if (depDef?.configKey) {
|
|
2435
|
+
const depConfigPath = path2.join(cwd, "config", `_${depDef.configKey}.yml`);
|
|
2436
|
+
if (!await fileExists(depConfigPath)) {
|
|
2437
|
+
const content = generateConfigFile(depDef.configKey);
|
|
2438
|
+
await writeFile(depConfigPath, content);
|
|
2439
|
+
writeCliMessage(chalk.gray(cliM("cli_addDependencyConfig", { params: { config: depDef.configKey } })));
|
|
2417
2440
|
}
|
|
2418
2441
|
}
|
|
2419
2442
|
}
|
|
@@ -2435,7 +2458,7 @@ async function addModule(options) {
|
|
|
2435
2458
|
const previousProduction = await fileExists(productionPath) ? await fse.readFile(productionPath, "utf8") : "";
|
|
2436
2459
|
const configured = new Set([...previousProduction.matchAll(/^([A-Z][A-Z0-9_]*)=/gm)].map((match) => match[1]));
|
|
2437
2460
|
const previousValues = parseEnv(previousProduction);
|
|
2438
|
-
const production = generateProductionEnvironment([
|
|
2461
|
+
const production = generateProductionEnvironment([selected, ...moduleDef.deps], previousValues.HAI_DB_TYPE === "mysql" ? { db: { type: "mysql", database: previousValues.HAI_DB_DATABASE } } : void 0).split("\n").filter((line) => !/^[A-Z][A-Z0-9_]*=/.test(line) || !configured.has(line.split("=")[0]));
|
|
2439
2462
|
await writeFile(productionPath, `${previousProduction.trimEnd()}
|
|
2440
2463
|
|
|
2441
2464
|
${production.join("\n")}`);
|
|
@@ -2765,11 +2788,7 @@ function staticCompileEnvironment(target) {
|
|
|
2765
2788
|
function sourceCommit(cwd) {
|
|
2766
2789
|
try {
|
|
2767
2790
|
const options = { cwd, encoding: "utf8", stdio: "pipe", windowsHide: true };
|
|
2768
|
-
|
|
2769
|
-
const manifest = relative(root, join(cwd, "package.json")).replaceAll("\\", "/");
|
|
2770
|
-
if (manifest.startsWith("../"))
|
|
2771
|
-
return "unknown";
|
|
2772
|
-
execFileSync("git", ["ls-files", "--error-unmatch", "--", manifest], { ...options, cwd: root });
|
|
2791
|
+
execFileSync("git", ["--literal-pathspecs", "ls-files", "--error-unmatch", "--", "package.json"], options);
|
|
2773
2792
|
const commit = execFileSync("git", ["rev-parse", "HEAD"], options).trim();
|
|
2774
2793
|
return /^(?:[a-f\d]{40}|[a-f\d]{64})$/i.test(commit) ? commit : "unknown";
|
|
2775
2794
|
} catch {
|
|
@@ -3317,7 +3336,7 @@ async function deployCommand(options) {
|
|
|
3317
3336
|
localModule = localRequire.resolve("@h-ai/deploy");
|
|
3318
3337
|
} catch {
|
|
3319
3338
|
}
|
|
3320
|
-
deployModule = localModule ? await import(pathToFileURL(localModule).href) : await import('./src-
|
|
3339
|
+
deployModule = localModule ? await import(pathToFileURL(localModule).href) : await import('./src-IW4CY2IN.js');
|
|
3321
3340
|
} catch {
|
|
3322
3341
|
writeCliError(chalk.red(cliM("cli_deploy_module_missing")));
|
|
3323
3342
|
writeCliMessage(chalk.cyan(" pnpm add -D @h-ai/deploy"));
|