@lark-apaas/miaoda-cli 0.1.7-alpha.3b4268d → 0.1.7-alpha.785a451
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/dist/api/deploy/schemas.js +3 -0
- package/dist/cli/commands/deploy/modern.js +9 -0
- package/dist/cli/handlers/app/init.js +7 -0
- package/dist/cli/handlers/app/sync.js +45 -9
- package/dist/cli/handlers/deploy/modern.js +39 -0
- package/dist/cli/handlers/plugin/plugin-local.js +1 -1
- package/dist/services/app/init/install.js +11 -2
- package/dist/services/deploy/modern/atoms/local-release.js +7 -2
- package/dist/services/deploy/modern/pipelines/local.js +4 -1
- package/package.json +3 -2
|
@@ -19,6 +19,9 @@ function nodeStatusText(v) {
|
|
|
19
19
|
return v;
|
|
20
20
|
if (typeof v !== 'number')
|
|
21
21
|
return undefined;
|
|
22
|
+
// `number` 不在 `NodeStatus` 枚举键集时,TS Partial<Record<NodeStatus,_>> 推断
|
|
23
|
+
// 出来类型不友好(eslint 报 unsafe-return);cast 到 Record<number,string|undefined>
|
|
24
|
+
// 等价安全访问。
|
|
22
25
|
return NODE_STATUS_TEXT[v];
|
|
23
26
|
}
|
|
24
27
|
/** NodeStatus 文本(CLI flag 字符串)→ 枚举数值 */
|
|
@@ -16,6 +16,7 @@ function registerDeployCommandsModern(program) {
|
|
|
16
16
|
.description('触发 modern 应用发布:本地构建 + 本地部署(preRelease + localPublish)')
|
|
17
17
|
.option('--dir <path>', '项目目录', '.')
|
|
18
18
|
.option('--skip-build', '跳过 build 步骤(已构建好时使用)', false)
|
|
19
|
+
.option('--conf <json>', '关联元信息 JSON,仅识别 checkPointVersion / commitID 两字段')
|
|
19
20
|
.addHelpText('after', `
|
|
20
21
|
不要用异步模式或后台模式调用 deploy,否则调用可能提前结束,Agent 会误判发布已完成。
|
|
21
22
|
|
|
@@ -32,6 +33,12 @@ function registerDeployCommandsModern(program) {
|
|
|
32
33
|
6. savePluginInstances(扫描 dist/output_capabilities/*.json 批量注册)
|
|
33
34
|
7. finalizeLocalRelease(Finished|Failed)
|
|
34
35
|
|
|
36
|
+
--conf(关联元信息透传)
|
|
37
|
+
值为 JSON string,只识别两个字段,其余 key 忽略:
|
|
38
|
+
checkPointVersion 关联的 checkpoint 版本
|
|
39
|
+
commitID 关联的代码 commit ID
|
|
40
|
+
两字段均可选;非法 JSON / 非对象 / 字段值非字符串会报错。
|
|
41
|
+
|
|
35
42
|
JSON 输出(stdout)
|
|
36
43
|
{"data": {"appId": "...", "version": <n>, "url": "...", "releaseID": "...", "preReleaseID": "..."}}
|
|
37
44
|
|
|
@@ -39,12 +46,14 @@ JSON 输出(stdout)
|
|
|
39
46
|
$ miaoda deploy
|
|
40
47
|
$ miaoda deploy --dir ./my-app
|
|
41
48
|
$ miaoda deploy --skip-build
|
|
49
|
+
$ miaoda deploy --conf '{"checkPointVersion":"v3","commitID":"a1b2c3d"}'
|
|
42
50
|
`);
|
|
43
51
|
deployCmd.action((0, shared_1.withHelp)(deployCmd, async (rawOpts) => {
|
|
44
52
|
await (0, modern_1.handleDeployModern)({
|
|
45
53
|
dir: rawOpts.dir ?? '.',
|
|
46
54
|
appId: (0, shared_1.resolveAppId)({}),
|
|
47
55
|
skipBuild: rawOpts.skipBuild,
|
|
56
|
+
conf: rawOpts.conf,
|
|
48
57
|
});
|
|
49
58
|
}));
|
|
50
59
|
}
|
|
@@ -64,6 +64,12 @@ async function handleAppInit(opts) {
|
|
|
64
64
|
const upgradedPackages = (0, sync_1.upgradePlatformDeps)(targetDir, 'init');
|
|
65
65
|
// skills 同步软失败:拉不到 coding-steering 包不该阻断 writeSparkMeta /
|
|
66
66
|
// activateGitHooks(之前会让 .spark/meta.json 没写,下次 init 半渲染状态又得重跑全套)。
|
|
67
|
+
// 按 stack 分流 outputLayout:
|
|
68
|
+
// - nestjs-react-fullstack:本地主战场,用 flat 布局
|
|
69
|
+
// (.agents/skills + .claude/skills 软链),不再创建 .agent/ 老目录
|
|
70
|
+
// - 其他 stack:仍走默认 nested (.agent/skills/steering/<stack>/skills/),
|
|
71
|
+
// 跟沙箱端 update-skills.sh 老链路对齐,避免破坏
|
|
72
|
+
const outputLayout = stack === 'nestjs-react-fullstack' ? 'flat' : 'nested';
|
|
67
73
|
let steeringResult;
|
|
68
74
|
let steeringError;
|
|
69
75
|
try {
|
|
@@ -72,6 +78,7 @@ async function handleAppInit(opts) {
|
|
|
72
78
|
targetDir,
|
|
73
79
|
version: opts.conf?.steeringVersion,
|
|
74
80
|
logPrefix: 'init',
|
|
81
|
+
outputLayout,
|
|
75
82
|
});
|
|
76
83
|
}
|
|
77
84
|
catch (err) {
|
|
@@ -7,6 +7,7 @@ exports.handleAppUpgrade = void 0;
|
|
|
7
7
|
exports.handleAppSync = handleAppSync;
|
|
8
8
|
exports.runStackSync = runStackSync;
|
|
9
9
|
exports.summarizeSyncResults = summarizeSyncResults;
|
|
10
|
+
exports.listManagedDeps = listManagedDeps;
|
|
10
11
|
exports.upgradePlatformDeps = upgradePlatformDeps;
|
|
11
12
|
const node_child_process_1 = require("node:child_process");
|
|
12
13
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
@@ -15,6 +16,7 @@ const sync_configs_1 = require("../../../config/sync-configs");
|
|
|
15
16
|
const sync_rule_1 = require("../../../utils/sync-rule");
|
|
16
17
|
const platform_sync_1 = require("../../../utils/platform-sync");
|
|
17
18
|
const githooks_1 = require("../../../utils/githooks");
|
|
19
|
+
const install_1 = require("../../../services/app/init/install");
|
|
18
20
|
const spark_meta_1 = require("../../../utils/spark-meta");
|
|
19
21
|
const error_1 = require("../../../utils/error");
|
|
20
22
|
const output_1 = require("../../../utils/output");
|
|
@@ -81,16 +83,27 @@ async function handleAppSync(opts) {
|
|
|
81
83
|
const upgradedPackages = upgradePlatformDeps(targetDir, 'sync');
|
|
82
84
|
// 3. activate git hooks(template 自带 .githooks/pre-commit,core.hooksPath 一次性设置)
|
|
83
85
|
const hookActivation = (0, githooks_1.activateGitHooks)(targetDir);
|
|
84
|
-
// 4. npm install —— 跟 init
|
|
85
|
-
//
|
|
86
|
-
// resolve lockfile entry。原因:
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
86
|
+
// 4. npm install —— 跟 init 一样软失败,install 挂了不该阻断 emit / sync 总结输出。
|
|
87
|
+
// 把 user app 装着的**所有**管控包显式作为位置参数传给 npm install,强制 npm 重新
|
|
88
|
+
// resolve lockfile entry。原因:
|
|
89
|
+
// - 即便 package.json spec 已经是 "latest"(没有 from→to 变化),user app 老 lockfile
|
|
90
|
+
// 可能锁着具体老版本 (如 fullstack-vite-preset@1.0.9),纯 `npm install` 会按 lockfile
|
|
91
|
+
// 拉老版,绕过 spec "latest" 的解析意图
|
|
92
|
+
// - 显式 `npm install foo@latest bar@latest` 让 npm 重新解析,lockfile 跟着更新到当前 latest
|
|
93
|
+
// - 没装的管控包不动 (sync 的职责是对齐,不是塞依赖)
|
|
90
94
|
// --ignore-scripts 绕开 action-plugin postinstall 在缺平台 env 时的 ENOENT。
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
// --registry 跟 init 钉同一份 npmmirror,避免 user 全局 ~/.npmrc 把 sync 拉到另一个源
|
|
96
|
+
// (详见 services/app/init/install.ts 上的注释)。MIAODA_NPM_REGISTRY env 兜底。
|
|
97
|
+
const installArgs = [
|
|
98
|
+
'install',
|
|
99
|
+
'--no-audit',
|
|
100
|
+
'--no-fund',
|
|
101
|
+
'--ignore-scripts',
|
|
102
|
+
'--registry',
|
|
103
|
+
(0, install_1.resolveNpmInstallRegistry)(),
|
|
104
|
+
];
|
|
105
|
+
for (const name of listManagedDeps(targetDir)) {
|
|
106
|
+
installArgs.push(`${name}@${MANAGED_PLATFORM_PACKAGES[name]}`);
|
|
94
107
|
}
|
|
95
108
|
(0, logger_1.log)('sync', `Running npm ${installArgs.join(' ')}...`);
|
|
96
109
|
let installError;
|
|
@@ -190,6 +203,29 @@ function readPackageJson(pkgJsonPath) {
|
|
|
190
203
|
return null;
|
|
191
204
|
return JSON.parse(node_fs_1.default.readFileSync(pkgJsonPath, 'utf-8'));
|
|
192
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* 列出 user app 装着的 @lark-apaas/* 管控包 (在 MANAGED_PLATFORM_PACKAGES 白名单内的)。
|
|
208
|
+
* sync handler 用来给 `npm install` 显式列管控包名 + @latest,强制 npm 重新 resolve
|
|
209
|
+
* lockfile entry —— 即便 package.json spec 已经是 "latest" 没 from→to 变化,
|
|
210
|
+
* 老 lockfile 锁的具体老版本(如 fullstack-vite-preset@1.0.9)也会被刷掉。
|
|
211
|
+
*/
|
|
212
|
+
function listManagedDeps(targetDir) {
|
|
213
|
+
const pkg = readPackageJson(node_path_1.default.join(targetDir, 'package.json'));
|
|
214
|
+
if (!pkg)
|
|
215
|
+
return [];
|
|
216
|
+
const names = new Set();
|
|
217
|
+
for (const section of ['dependencies', 'devDependencies']) {
|
|
218
|
+
const deps = pkg[section];
|
|
219
|
+
if (!deps || typeof deps !== 'object')
|
|
220
|
+
continue;
|
|
221
|
+
for (const name of Object.keys(deps)) {
|
|
222
|
+
if (Object.prototype.hasOwnProperty.call(MANAGED_PLATFORM_PACKAGES, name)) {
|
|
223
|
+
names.add(name);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return [...names];
|
|
228
|
+
}
|
|
193
229
|
/**
|
|
194
230
|
* 把 user app package.json 里已装的 @lark-apaas/* 平台包改写成 MANAGED_PLATFORM_PACKAGES
|
|
195
231
|
* 表里的目标 spec(缺省 `"latest"`)。由 `miaoda app sync` 和 `miaoda app init`(template
|
|
@@ -3,10 +3,46 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseDeployConf = parseDeployConf;
|
|
6
7
|
exports.handleDeployModern = handleDeployModern;
|
|
7
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
9
|
const output_1 = require("../../../utils/output");
|
|
10
|
+
const error_1 = require("../../../utils/error");
|
|
9
11
|
const index_1 = require("../../../services/deploy/modern/index");
|
|
12
|
+
const CONF_EXPECTED = '期望形如 {"checkPointVersion":"...","commitID":"..."} 的 JSON 对象';
|
|
13
|
+
/**
|
|
14
|
+
* 解析 `--conf` JSON string,只取 checkPointVersion / commitID 两个白名单字段。
|
|
15
|
+
* - 未传 → 返回 {}(行为不变)。
|
|
16
|
+
* - 非法 JSON / 非 object / 字段值非 string → 抛 DEPLOY_CONF_INVALID。
|
|
17
|
+
* - 空串字段视为未提供(不进 body,保持可选语义);未知 key 忽略。
|
|
18
|
+
*/
|
|
19
|
+
function parseDeployConf(raw) {
|
|
20
|
+
if (raw === undefined || raw === '')
|
|
21
|
+
return {};
|
|
22
|
+
let parsed;
|
|
23
|
+
try {
|
|
24
|
+
parsed = JSON.parse(raw);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new error_1.AppError('DEPLOY_CONF_INVALID', `--conf 不是合法 JSON,${CONF_EXPECTED}`);
|
|
28
|
+
}
|
|
29
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
30
|
+
throw new error_1.AppError('DEPLOY_CONF_INVALID', `--conf 必须是 JSON 对象,${CONF_EXPECTED}`);
|
|
31
|
+
}
|
|
32
|
+
const source = parsed;
|
|
33
|
+
const conf = {};
|
|
34
|
+
for (const key of ['checkPointVersion', 'commitID']) {
|
|
35
|
+
const value = source[key];
|
|
36
|
+
if (value === undefined)
|
|
37
|
+
continue;
|
|
38
|
+
if (typeof value !== 'string') {
|
|
39
|
+
throw new error_1.AppError('DEPLOY_CONF_INVALID', `--conf.${key} 必须是字符串,${CONF_EXPECTED}`);
|
|
40
|
+
}
|
|
41
|
+
if (value !== '')
|
|
42
|
+
conf[key] = value;
|
|
43
|
+
}
|
|
44
|
+
return conf;
|
|
45
|
+
}
|
|
10
46
|
/**
|
|
11
47
|
* miaoda deploy(modern scene 专用,CLI 表面对齐 openclaw-cli)
|
|
12
48
|
*
|
|
@@ -14,10 +50,13 @@ const index_1 = require("../../../services/deploy/modern/index");
|
|
|
14
50
|
*/
|
|
15
51
|
async function handleDeployModern(opts) {
|
|
16
52
|
const projectDir = node_path_1.default.resolve(opts.dir);
|
|
53
|
+
const conf = parseDeployConf(opts.conf);
|
|
17
54
|
const result = await (0, index_1.runModernDeploy)({
|
|
18
55
|
projectDir,
|
|
19
56
|
appId: opts.appId,
|
|
20
57
|
skipBuild: opts.skipBuild ?? false,
|
|
58
|
+
checkPointVersion: conf.checkPointVersion,
|
|
59
|
+
commitID: conf.commitID,
|
|
21
60
|
});
|
|
22
61
|
(0, output_1.emit)({
|
|
23
62
|
data: {
|
|
@@ -76,7 +76,7 @@ function parsePluginName(input) {
|
|
|
76
76
|
if (!match) {
|
|
77
77
|
throw new error_1.AppError('INVALID_PLUGIN_NAME', `Invalid plugin name format: ${input}. Expected: @scope/name or @scope/name@version`, { next_actions: ['示例:@demo/example-plugin 或 @demo/example-plugin@1.2.3'] });
|
|
78
78
|
}
|
|
79
|
-
return { name: match[1], version: match[2]
|
|
79
|
+
return { name: match[1], version: match[2] || 'latest' };
|
|
80
80
|
}
|
|
81
81
|
// ── package.json actionPlugins CRUD ──
|
|
82
82
|
function readPackageJson() {
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.installDependencies = installDependencies;
|
|
7
|
+
exports.resolveNpmInstallRegistry = resolveNpmInstallRegistry;
|
|
7
8
|
const node_child_process_1 = require("node:child_process");
|
|
8
9
|
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
9
10
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
@@ -111,12 +112,20 @@ function extractZip(zipPath, targetDir, stdio) {
|
|
|
111
112
|
* - 字节内网 DNS 会把 npmmirror 域名透明指向公司镜像,外网就是公网阿里源;同一行配置
|
|
112
113
|
* 在两套环境都拉得到 @lark-apaas/* 私包(内网经公司镜像,外网经阿里同步过去的副本)。
|
|
113
114
|
* - 留 `MIAODA_NPM_REGISTRY` env 应急覆盖。
|
|
115
|
+
*
|
|
116
|
+
* `miaoda app sync` 也用同款规则,通过 resolveNpmInstallRegistry() 共享。
|
|
114
117
|
*/
|
|
115
118
|
const NPM_INSTALL_REGISTRY_DEFAULT = 'https://registry.npmmirror.com/';
|
|
119
|
+
/**
|
|
120
|
+
* 解析 miaoda 内部 npm install 命令使用的 registry。init / sync 共用。
|
|
121
|
+
* 优先级:`MIAODA_NPM_REGISTRY` env > `NPM_INSTALL_REGISTRY_DEFAULT`。
|
|
122
|
+
*/
|
|
123
|
+
function resolveNpmInstallRegistry() {
|
|
124
|
+
return process.env.MIAODA_NPM_REGISTRY ?? NPM_INSTALL_REGISTRY_DEFAULT;
|
|
125
|
+
}
|
|
116
126
|
function runNpmInstall(targetDir, stdio) {
|
|
117
127
|
(0, logger_1.log)('init', `npm install in ${targetDir}...`);
|
|
118
|
-
|
|
119
|
-
(0, node_child_process_1.execFileSync)('npm', ['install', '--no-audit', '--no-fund', '--registry', registry], {
|
|
128
|
+
(0, node_child_process_1.execFileSync)('npm', ['install', '--no-audit', '--no-fund', '--registry', resolveNpmInstallRegistry()], {
|
|
120
129
|
cwd: targetDir,
|
|
121
130
|
stdio,
|
|
122
131
|
});
|
|
@@ -10,8 +10,13 @@ const logger_1 = require("../../../../utils/logger");
|
|
|
10
10
|
* 创建本地发布单(加锁;不挂 pipeline)。
|
|
11
11
|
* 返回的 releaseId 必须由 finalizeLocalRelease 翻为终态,否则发布单一直挂着。
|
|
12
12
|
*/
|
|
13
|
-
async function createLocalRelease(appId, version) {
|
|
14
|
-
return (0, index_1.createLocalRelease)({
|
|
13
|
+
async function createLocalRelease(appId, version, extra) {
|
|
14
|
+
return (0, index_1.createLocalRelease)({
|
|
15
|
+
appID: appId,
|
|
16
|
+
version,
|
|
17
|
+
checkPointVersion: extra?.checkPointVersion,
|
|
18
|
+
commitID: extra?.commitID,
|
|
19
|
+
});
|
|
15
20
|
}
|
|
16
21
|
/**
|
|
17
22
|
* 把本地发布单翻为终态。Finished / Failed 由 pipeline 视上下游结果决定。
|
|
@@ -43,7 +43,10 @@ async function localBuildLocalPublishPipeline(opts) {
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
(0, logger_1.log)('deploy', 'Creating local release...');
|
|
46
|
-
const release = await (0, index_1.createLocalRelease)(ctx.appId, pre.version
|
|
46
|
+
const release = await (0, index_1.createLocalRelease)(ctx.appId, pre.version, {
|
|
47
|
+
checkPointVersion: opts.checkPointVersion,
|
|
48
|
+
commitID: opts.commitID,
|
|
49
|
+
});
|
|
47
50
|
try {
|
|
48
51
|
(0, logger_1.log)('deploy', 'Uploading artifacts...');
|
|
49
52
|
await (0, index_1.uploadArtifacts)({ projectDir: ctx.projectDir, appId: ctx.appId, data });
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lark-apaas/miaoda-cli",
|
|
3
|
-
"version": "0.1.7-alpha.
|
|
3
|
+
"version": "0.1.7-alpha.785a451",
|
|
4
4
|
"description": "Miaoda 平台命令行工具,面向 Agent 调用",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
7
7
|
"miaoda": "bin/miaoda.js"
|
|
8
8
|
},
|
|
9
9
|
"publishConfig": {
|
|
10
|
-
"access": "public"
|
|
10
|
+
"access": "public",
|
|
11
|
+
"registry": "https://registry.npmjs.org/"
|
|
11
12
|
},
|
|
12
13
|
"files": [
|
|
13
14
|
"LICENSE",
|