@lark-apaas/miaoda-cli 0.1.4-alpha.abaa17f → 0.1.4-alpha.dbe45ea
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.md +1 -1
- package/dist/api/deploy/index.js +2 -1
- package/dist/api/deploy/modern.js +8 -0
- package/dist/api/deploy/plugin-instances-types.js +2 -2
- package/dist/api/deploy/plugin-instances.js +9 -17
- package/dist/cli/commands/app/index.js +32 -4
- package/dist/cli/commands/deploy/modern.js +3 -1
- package/dist/cli/commands/index.js +33 -0
- package/dist/cli/commands/skills/index.js +63 -0
- package/dist/cli/handlers/app/index.js +3 -1
- package/dist/cli/handlers/app/init.js +14 -12
- package/dist/cli/handlers/app/sync.js +45 -0
- package/dist/cli/handlers/deploy/modern.js +1 -0
- package/dist/cli/handlers/skills/index.js +7 -0
- package/dist/cli/handlers/skills/status.js +31 -0
- package/dist/cli/handlers/skills/sync.js +38 -0
- package/dist/services/app/init/index.js +1 -3
- package/dist/services/app/init/template.js +8 -6
- package/dist/services/deploy/modern/atoms/build.js +8 -3
- package/dist/services/deploy/modern/atoms/context.js +8 -11
- package/dist/services/deploy/modern/atoms/upload.js +103 -49
- package/dist/services/deploy/modern/check.js +2 -7
- package/dist/services/deploy/modern/pipelines/local.js +5 -5
- package/dist/services/deploy/modern/protocol.js +83 -4
- package/dist/services/deploy/modern/template-key-map.js +8 -15
- package/dist/services/skills/index.js +5 -0
- package/dist/services/skills/status.js +37 -0
- package/dist/{services/app/init/steering.js → utils/coding-steering.js} +24 -9
- package/dist/utils/http.js +14 -10
- package/dist/utils/platform-sync.js +114 -0
- package/dist/utils/spark-meta.js +2 -8
- package/package.json +4 -3
- package/platform-controlled/README.md +33 -0
- package/platform-controlled/design-stack/files/scripts/dev-local.sh +38 -0
- package/platform-controlled/design-stack/patches/package.json +5 -0
- package/platform-controlled/nestjs-react-fullstack/files/scripts/dev-local.sh +40 -0
- package/platform-controlled/nestjs-react-fullstack/patches/package.json +5 -0
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ miaoda file ls --output json
|
|
|
54
54
|
## 环境变量
|
|
55
55
|
|
|
56
56
|
- `MIAODA_APP_ID`:默认应用 ID,等价于 `--app-id`。
|
|
57
|
-
- `MIAODA_CANARY_HEADER
|
|
57
|
+
- `MIAODA_CANARY_HEADER`:HTTP 请求的 `x-tt-env` 小流量头取值。未设置时默认 `boe_miaoda_doubao`;设为空字符串则不带该头(例:`export MIAODA_CANARY_HEADER=boe_xxx`)。值形如 `ppe_xxx` 时额外带上 `x-use-ppe: 1`。
|
|
58
58
|
|
|
59
59
|
## 输出契约
|
|
60
60
|
|
package/dist/api/deploy/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NodeStatus = exports.nodeStatusFromText = exports.nodeStatusText = exports.errorJobSchema = exports.deployGetSchema = exports.deployHistorySchema = exports.batchSavePluginInstances = exports.LocalReleaseStatus = exports.getModernLastPublishedVersion = exports.getModernReleaseStatus = exports.createModernRelease = exports.updateLocalRelease = exports.createLocalRelease = exports.preRelease = exports.queryPipelineInstance = exports.getErrorLog = exports.listPipelineInstances = exports.createRelease = void 0;
|
|
3
|
+
exports.NodeStatus = exports.nodeStatusFromText = exports.nodeStatusText = exports.errorJobSchema = exports.deployGetSchema = exports.deployHistorySchema = exports.batchSavePluginInstances = exports.LocalReleaseStatus = exports.getModernLastPublishedVersion = exports.getModernReleaseStatus = exports.createModernRelease = exports.callbackStatic = exports.updateLocalRelease = exports.createLocalRelease = exports.preRelease = exports.queryPipelineInstance = exports.getErrorLog = exports.listPipelineInstances = exports.createRelease = void 0;
|
|
4
4
|
var api_1 = require("./api");
|
|
5
5
|
Object.defineProperty(exports, "createRelease", { enumerable: true, get: function () { return api_1.createRelease; } });
|
|
6
6
|
Object.defineProperty(exports, "listPipelineInstances", { enumerable: true, get: function () { return api_1.listPipelineInstances; } });
|
|
@@ -10,6 +10,7 @@ var modern_1 = require("./modern");
|
|
|
10
10
|
Object.defineProperty(exports, "preRelease", { enumerable: true, get: function () { return modern_1.preRelease; } });
|
|
11
11
|
Object.defineProperty(exports, "createLocalRelease", { enumerable: true, get: function () { return modern_1.createLocalRelease; } });
|
|
12
12
|
Object.defineProperty(exports, "updateLocalRelease", { enumerable: true, get: function () { return modern_1.updateLocalRelease; } });
|
|
13
|
+
Object.defineProperty(exports, "callbackStatic", { enumerable: true, get: function () { return modern_1.callbackStatic; } });
|
|
13
14
|
Object.defineProperty(exports, "createModernRelease", { enumerable: true, get: function () { return modern_1.createRelease; } });
|
|
14
15
|
Object.defineProperty(exports, "getModernReleaseStatus", { enumerable: true, get: function () { return modern_1.getReleaseStatus; } });
|
|
15
16
|
Object.defineProperty(exports, "getModernLastPublishedVersion", { enumerable: true, get: function () { return modern_1.getLastPublishedVersion; } });
|
|
@@ -13,6 +13,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
13
13
|
exports.preRelease = preRelease;
|
|
14
14
|
exports.createLocalRelease = createLocalRelease;
|
|
15
15
|
exports.updateLocalRelease = updateLocalRelease;
|
|
16
|
+
exports.callbackStatic = callbackStatic;
|
|
16
17
|
exports.createRelease = createRelease;
|
|
17
18
|
exports.getReleaseStatus = getReleaseStatus;
|
|
18
19
|
exports.getLastPublishedVersion = getLastPublishedVersion;
|
|
@@ -48,6 +49,13 @@ async function updateLocalRelease(req) {
|
|
|
48
49
|
const url = `/v1/devops/app/${encodeURIComponent(appID)}/local_publish/update_release`;
|
|
49
50
|
await (0, http_1.postInnerApi)(url, body, envelopeOpts('Failed to update local release'));
|
|
50
51
|
}
|
|
52
|
+
// ── callbackStatic(PaaS Storage 静态资源上传完成回调) ──
|
|
53
|
+
/** POST /v1/storage/app/:appID/bucket/:bucketID/object/callbackStatic */
|
|
54
|
+
async function callbackStatic(req) {
|
|
55
|
+
const { appID, bucketID, uploadID } = req;
|
|
56
|
+
const url = `/v1/storage/app/${encodeURIComponent(appID)}/bucket/${encodeURIComponent(bucketID)}/object/callbackStatic`;
|
|
57
|
+
return (0, http_1.postInnerApi)(url, { uploadID }, envelopeOpts('Failed to callback static upload'));
|
|
58
|
+
}
|
|
51
59
|
// ── release(远端部署,B / C 链路;本期不导出,类型骨架已就绪) ──
|
|
52
60
|
/** POST /v1/devops/app/:appID/remote_publish/release */
|
|
53
61
|
async function createRelease(req) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// plugin_instances batch_save 接口的请求 / 响应类型。
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
4
|
+
// 后端已统一到 InnerEnvelope(`{data, status_code, message}`),与 modern deploy
|
|
5
|
+
// 其它接口一致;旧的 BaseResp 形态已下线,类型也不再保留。
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -1,30 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// studio_server 的 plugin_instances 批量保存接口。
|
|
3
|
-
//
|
|
4
|
-
//
|
|
3
|
+
//
|
|
4
|
+
// 后端已统一到 InnerEnvelope(`{data, status_code, message}`)信封;不再手撸
|
|
5
|
+
// 旧 BaseResp 解析,直接复用 utils/http.ts 的 postInnerApi,verbose 下也能拿到
|
|
6
|
+
// `→ POST` / `body:` / `resp:` 的完整日志。
|
|
5
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
8
|
exports.batchSavePluginInstances = batchSavePluginInstances;
|
|
7
9
|
const http_1 = require("../../utils/http");
|
|
8
|
-
const error_1 = require("../../utils/error");
|
|
9
10
|
const URL_PATH = '/api/v1/studio/innerapi/plugin_instances/batch_save';
|
|
10
11
|
/**
|
|
11
12
|
* POST /api/v1/studio/innerapi/plugin_instances/batch_save
|
|
12
13
|
*
|
|
13
14
|
* 把发布版本的 capability 集合注册到 studio_server。
|
|
14
|
-
* 失败时抛 AppError("DEPLOY_PLUGIN_BATCH_SAVE_FAILED")
|
|
15
|
+
* 失败时抛 AppError("DEPLOY_PLUGIN_BATCH_SAVE_FAILED"),错误信息来自 envelope.message。
|
|
15
16
|
*/
|
|
16
17
|
async function batchSavePluginInstances(req) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
const body = (await response.json());
|
|
22
|
-
const baseResp = body.BaseResp;
|
|
23
|
-
if (baseResp?.StatusCode !== 0) {
|
|
24
|
-
const msg = baseResp?.StatusMessage ?? baseResp?.KStatusMessage ?? 'unknown error';
|
|
25
|
-
const code = baseResp?.KStatusCode !== undefined && baseResp.KStatusCode !== ''
|
|
26
|
-
? baseResp.KStatusCode
|
|
27
|
-
: String(baseResp?.StatusCode ?? 'unknown');
|
|
28
|
-
throw new error_1.AppError('DEPLOY_PLUGIN_BATCH_SAVE_FAILED', `Failed to save plugin instances: status_code=${code} message=${msg}`);
|
|
29
|
-
}
|
|
18
|
+
await (0, http_1.postInnerApi)(URL_PATH, req, {
|
|
19
|
+
errPrefix: 'Failed to save plugin instances',
|
|
20
|
+
defaultErrCode: 'DEPLOY_PLUGIN_BATCH_SAVE_FAILED',
|
|
21
|
+
});
|
|
30
22
|
}
|
|
@@ -6,7 +6,7 @@ const index_1 = require("../../../cli/handlers/app/index");
|
|
|
6
6
|
const error_1 = require("../../../utils/error");
|
|
7
7
|
function registerAppCommands(program, opts = {}) {
|
|
8
8
|
const description = opts.includeInit
|
|
9
|
-
? '应用元数据管理:查看 / 修改 / 初始化'
|
|
9
|
+
? '应用元数据管理:查看 / 修改 / 初始化 / 同步平台脚本'
|
|
10
10
|
: '应用元数据管理:查看 / 修改';
|
|
11
11
|
const appCmd = program.command('app').description(description);
|
|
12
12
|
appCmd.action(() => {
|
|
@@ -21,8 +21,35 @@ function registerAppCommands(program, opts = {}) {
|
|
|
21
21
|
registerAppUpdate(appCmd);
|
|
22
22
|
if (opts.includeInit) {
|
|
23
23
|
registerAppInit(appCmd);
|
|
24
|
+
registerAppSync(appCmd);
|
|
24
25
|
}
|
|
25
26
|
}
|
|
27
|
+
function registerAppSync(parent) {
|
|
28
|
+
const cmd = parent
|
|
29
|
+
.command('sync')
|
|
30
|
+
.description('按 stack 同步 platform-controlled/ 下的平台管控内容(scripts / package.json 字段等)到项目')
|
|
31
|
+
.option('--dir <path>', '项目目录,默认 cwd(需含 .spark/meta.json)')
|
|
32
|
+
.addHelpText('after', `
|
|
33
|
+
流程
|
|
34
|
+
1. 读 .spark/meta.json.stack 决定从 platform-controlled/<stack>/ 拉取
|
|
35
|
+
2. files/ → 按相对路径覆盖到 <dir>(.sh 自动 +x)
|
|
36
|
+
3. patches/ → 每个 .json 文件按相对路径 deep merge 到 <dir>/<rel-path>
|
|
37
|
+
(支持任意 JSON:package.json / tsconfig.json / nest-cli.json / ...)
|
|
38
|
+
|
|
39
|
+
JSON 输出
|
|
40
|
+
{"data": {"stack": "...", "syncedFiles": [...],
|
|
41
|
+
"mergedJsonFiles": [{"path": "...", "keys": [...]}]}}
|
|
42
|
+
|
|
43
|
+
示例
|
|
44
|
+
$ miaoda app sync
|
|
45
|
+
$ miaoda app sync --dir /path/to/app --json
|
|
46
|
+
`);
|
|
47
|
+
cmd.action((0, shared_1.withHelp)(cmd, async (rawOpts) => {
|
|
48
|
+
await (0, index_1.handleAppSync)({
|
|
49
|
+
dir: rawOpts.dir,
|
|
50
|
+
});
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
26
53
|
function registerAppGet(parent) {
|
|
27
54
|
const cmd = parent
|
|
28
55
|
.command('get')
|
|
@@ -71,7 +98,6 @@ function registerAppInit(parent) {
|
|
|
71
98
|
const cmd = parent
|
|
72
99
|
.command('init')
|
|
73
100
|
.description('初始化应用代码:抓 template 渲染、装 .agent/steering/ skills、写 .spark/meta.json。.spark/meta.json 已存在则直接退出')
|
|
74
|
-
.addOption((0, shared_1.appIdOption)().hideHelp())
|
|
75
101
|
.option('--template <stack>', `技术栈短名(${index_1.SUPPORTED_STACKS.join(' / ')})`)
|
|
76
102
|
.option('--conf <json>', 'init 配置 JSON。支持 {"version": "<template 版本>"} / {"steeringVersion": "<steering 版本>"},均默认 latest')
|
|
77
103
|
.option('--skip-install', '跳过依赖安装', false)
|
|
@@ -82,6 +108,10 @@ function registerAppInit(parent) {
|
|
|
82
108
|
meta.json 在 init 流程最后才写,写了 = 已完整成功一次;
|
|
83
109
|
上一次失败留下半渲染状态时(package.json 在但 meta.json 没在)允许重跑。
|
|
84
110
|
|
|
111
|
+
应用身份(appId)
|
|
112
|
+
init 不再持久化 appId。运行端命令(deploy / file / plugin 等)始终从 MIAODA_APP_ID env 读,
|
|
113
|
+
init 阶段也无需感知 appId。
|
|
114
|
+
|
|
85
115
|
依赖安装
|
|
86
116
|
默认:npm install --no-audit --no-fund
|
|
87
117
|
--skip-install: 跳过
|
|
@@ -104,10 +134,8 @@ JSON 输出
|
|
|
104
134
|
$ MIAODA_DEP_CACHE_DIR=/tmp/dep-cache miaoda app init --template vite-react
|
|
105
135
|
`);
|
|
106
136
|
cmd.action((0, shared_1.withHelp)(cmd, async (rawOpts) => {
|
|
107
|
-
(0, shared_1.rejectCliOverride)(cmd, 'appId');
|
|
108
137
|
const conf = parseInitConf(rawOpts.conf);
|
|
109
138
|
await (0, index_1.handleAppInit)({
|
|
110
|
-
appId: (0, shared_1.resolveAppId)({ appId: rawOpts.appId }),
|
|
111
139
|
template: rawOpts.template,
|
|
112
140
|
conf,
|
|
113
141
|
skipInstall: rawOpts.skipInstall,
|
|
@@ -20,7 +20,8 @@ function registerDeployCommandsModern(program) {
|
|
|
20
20
|
不要用异步模式或后台模式调用 deploy,否则调用可能提前结束,Agent 会误判发布已完成。
|
|
21
21
|
|
|
22
22
|
前置要求
|
|
23
|
-
- 项目已 init(.spark/meta.json 含
|
|
23
|
+
- 项目已 init(.spark/meta.json 含 stack)
|
|
24
|
+
- MIAODA_APP_ID 已设置(应用身份从 env 读,不再从 meta.json 读)
|
|
24
25
|
- node_modules 已安装
|
|
25
26
|
- package.json 含 build script
|
|
26
27
|
- 沙箱内预装 tosutil(用于把构建产物上传到 TOS)
|
|
@@ -42,6 +43,7 @@ JSON 输出(stdout)
|
|
|
42
43
|
deployCmd.action((0, shared_1.withHelp)(deployCmd, async (rawOpts) => {
|
|
43
44
|
await (0, modern_1.handleDeployModern)({
|
|
44
45
|
dir: rawOpts.dir ?? '.',
|
|
46
|
+
appId: (0, shared_1.resolveAppId)({}),
|
|
45
47
|
skipBuild: rawOpts.skipBuild,
|
|
46
48
|
});
|
|
47
49
|
}));
|
|
@@ -8,9 +8,22 @@ const index_3 = require("../../cli/commands/observability/index");
|
|
|
8
8
|
const index_4 = require("../../cli/commands/app/index");
|
|
9
9
|
const index_5 = require("../../cli/commands/deploy/index");
|
|
10
10
|
const modern_1 = require("../../cli/commands/deploy/modern");
|
|
11
|
+
const index_6 = require("../../cli/commands/skills/index");
|
|
12
|
+
// scene 跟 dispatcher(MIAODA_APP_TYPE)同语义层级 —— app 业务类型维度,
|
|
13
|
+
// 对齐后端 devops app_common.AppType 枚举:
|
|
14
|
+
// 3 = AppType_APPLICATION(全栈应用,当前仅 nestjs-react-fullstack 一个 stack)
|
|
15
|
+
// 4 = AppType_DESIGN(design-stack,SSR 渲染、无业务逻辑、无数据库)
|
|
16
|
+
// 7 = miaoda-cli 自定义 modern 占位(后端枚举无 7,沙箱目前不传)
|
|
17
|
+
// 其它(0/1/2/5/6 / 未设)→ default(命令全开,本地 dev / CI / 兼容回退)
|
|
18
|
+
// stack 维度(nestjs-react-fullstack / vite-react / ...)是正交的,
|
|
19
|
+
// skills sync 内部按 .spark/meta.json.stack 拉对应 coding-steering/steering/<stack>/ 子目录。
|
|
11
20
|
function resolveScene(appType, _archType) {
|
|
12
21
|
if (appType === '7')
|
|
13
22
|
return 'modern';
|
|
23
|
+
if (appType === '3')
|
|
24
|
+
return 'application';
|
|
25
|
+
if (appType === '4')
|
|
26
|
+
return 'design';
|
|
14
27
|
return 'default';
|
|
15
28
|
}
|
|
16
29
|
const SCENE_REGISTRARS = {
|
|
@@ -24,6 +37,26 @@ const SCENE_REGISTRARS = {
|
|
|
24
37
|
modern: (p) => {
|
|
25
38
|
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
26
39
|
(0, modern_1.registerDeployCommandsModern)(p);
|
|
40
|
+
(0, index_6.registerSkillsCommands)(p);
|
|
41
|
+
},
|
|
42
|
+
// application scene(AppType_APPLICATION=3):
|
|
43
|
+
// 在 default 命令集基础上加 skills(按 meta.json.stack 拉对应 stack 技能)
|
|
44
|
+
// + app init(新一代应用走 init 写 .spark/meta.json)
|
|
45
|
+
application: (p) => {
|
|
46
|
+
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
47
|
+
(0, index_5.registerDeployCommands)(p);
|
|
48
|
+
(0, index_2.registerDbCommands)(p);
|
|
49
|
+
(0, index_1.registerFileCommands)(p);
|
|
50
|
+
(0, index_3.registerObservabilityCommands)(p);
|
|
51
|
+
(0, index_6.registerSkillsCommands)(p);
|
|
52
|
+
},
|
|
53
|
+
// design scene(AppType_DESIGN=4):design-stack 仅 SSR 渲染、无后端业务逻辑、
|
|
54
|
+
// 无数据库、无 UGC 文件。命令集裁掉 db / file,保留 deploy / observability / app(init) / skills。
|
|
55
|
+
design: (p) => {
|
|
56
|
+
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
57
|
+
(0, index_5.registerDeployCommands)(p);
|
|
58
|
+
(0, index_3.registerObservabilityCommands)(p);
|
|
59
|
+
(0, index_6.registerSkillsCommands)(p);
|
|
27
60
|
},
|
|
28
61
|
};
|
|
29
62
|
function readEnv(name) {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerSkillsCommands = registerSkillsCommands;
|
|
4
|
+
const shared_1 = require("../../../cli/commands/shared");
|
|
5
|
+
const index_1 = require("../../../cli/handlers/skills/index");
|
|
6
|
+
/**
|
|
7
|
+
* miaoda skills:本地 agent skills 维护。
|
|
8
|
+
*
|
|
9
|
+
* 当前仅 steering 一类子集(coding-steering 包内的 _common/skills + <stack>/skills + tech.md);
|
|
10
|
+
* 后续如有更多 skill 类型再加 --type。`app init` 会一次性同步装上,独立 `skills sync` 用于
|
|
11
|
+
* 后续单独升级 / pin 版本,不必走完整 init。
|
|
12
|
+
*/
|
|
13
|
+
function registerSkillsCommands(program) {
|
|
14
|
+
const skillsCmd = program.command('skills').description('本地 agent skills(含 steering)维护');
|
|
15
|
+
skillsCmd.action(() => {
|
|
16
|
+
skillsCmd.outputHelp();
|
|
17
|
+
});
|
|
18
|
+
registerSkillsSync(skillsCmd);
|
|
19
|
+
registerSkillsStatus(skillsCmd);
|
|
20
|
+
}
|
|
21
|
+
function registerSkillsSync(parent) {
|
|
22
|
+
const cmd = parent
|
|
23
|
+
.command('sync')
|
|
24
|
+
.description('同步 coding-steering(latest 或指定版本)到 .agent/steering/')
|
|
25
|
+
.argument('[version]', 'coding-steering 包版本或 dist-tag,缺省 latest')
|
|
26
|
+
.option('--dir <path>', '项目目录,默认当前目录', '.')
|
|
27
|
+
.addHelpText('after', `
|
|
28
|
+
前置要求
|
|
29
|
+
当前目录(或 --dir)已走过 'miaoda app init'(.spark/meta.json 含 stack)
|
|
30
|
+
|
|
31
|
+
JSON 输出
|
|
32
|
+
{"data": {"stack": "...", "version": "...", "syncedSkills": [...], "techSynced": true|false}}
|
|
33
|
+
|
|
34
|
+
示例
|
|
35
|
+
$ miaoda skills sync
|
|
36
|
+
$ miaoda skills sync 0.2.0
|
|
37
|
+
$ miaoda skills sync --dir ./my-app
|
|
38
|
+
`);
|
|
39
|
+
cmd.action((0, shared_1.withHelp)(cmd, async (version, rawOpts) => {
|
|
40
|
+
await (0, index_1.handleSkillsSync)({
|
|
41
|
+
dir: rawOpts.dir,
|
|
42
|
+
version,
|
|
43
|
+
});
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
function registerSkillsStatus(parent) {
|
|
47
|
+
const cmd = parent
|
|
48
|
+
.command('status')
|
|
49
|
+
.description('查看本地 .agent/steering/ 的当前状态(不联网)')
|
|
50
|
+
.option('--dir <path>', '项目目录,默认当前目录', '.')
|
|
51
|
+
.addHelpText('after', `
|
|
52
|
+
JSON 输出
|
|
53
|
+
{"data": {"present": true|false, "skills": [...], "techSynced": true|false}}
|
|
54
|
+
|
|
55
|
+
示例
|
|
56
|
+
$ miaoda skills status
|
|
57
|
+
`);
|
|
58
|
+
cmd.action((0, shared_1.withHelp)(cmd, async (rawOpts) => {
|
|
59
|
+
await (0, index_1.handleSkillsStatus)({
|
|
60
|
+
dir: rawOpts.dir,
|
|
61
|
+
});
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SUPPORTED_STACKS = exports.handleAppInit = exports.handleAppUpdate = exports.handleAppGet = void 0;
|
|
3
|
+
exports.SUPPORTED_STACKS = exports.handleAppSync = exports.handleAppInit = exports.handleAppUpdate = exports.handleAppGet = void 0;
|
|
4
4
|
var get_1 = require("./get");
|
|
5
5
|
Object.defineProperty(exports, "handleAppGet", { enumerable: true, get: function () { return get_1.handleAppGet; } });
|
|
6
6
|
var update_1 = require("./update");
|
|
7
7
|
Object.defineProperty(exports, "handleAppUpdate", { enumerable: true, get: function () { return update_1.handleAppUpdate; } });
|
|
8
8
|
var init_1 = require("./init");
|
|
9
9
|
Object.defineProperty(exports, "handleAppInit", { enumerable: true, get: function () { return init_1.handleAppInit; } });
|
|
10
|
+
var sync_1 = require("./sync");
|
|
11
|
+
Object.defineProperty(exports, "handleAppSync", { enumerable: true, get: function () { return sync_1.handleAppSync; } });
|
|
10
12
|
// commands 层渲染 help 时需要这份枚举;从 handler barrel 转发,避免 commands → services 越界
|
|
11
13
|
var index_1 = require("../../../services/app/init/index");
|
|
12
14
|
Object.defineProperty(exports, "SUPPORTED_STACKS", { enumerable: true, get: function () { return index_1.SUPPORTED_STACKS; } });
|
|
@@ -7,15 +7,22 @@ exports.handleAppInit = handleAppInit;
|
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const index_1 = require("../../../services/app/init/index");
|
|
10
|
+
const coding_steering_1 = require("../../../utils/coding-steering");
|
|
10
11
|
const error_1 = require("../../../utils/error");
|
|
11
12
|
const output_1 = require("../../../utils/output");
|
|
12
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* miaoda app init
|
|
15
|
+
*
|
|
16
|
+
* 只负责本地脚手架:render template、sync skills、install deps,把 {stack, version, archType}
|
|
17
|
+
* 写入 .spark/meta.json。appId 不在此处持久化——deploy 等运行端通过 MIAODA_APP_ID env 拿。
|
|
18
|
+
*
|
|
19
|
+
* 幂等:.spark/meta.json 存在即表示已完整成功一次,直接退出,不重跑任何子步骤。
|
|
20
|
+
* 半渲染状态(package.json 在但 meta.json 不在)会重新跑完整流程。
|
|
21
|
+
*/
|
|
13
22
|
async function handleAppInit(opts) {
|
|
14
23
|
await Promise.resolve();
|
|
15
24
|
const targetDir = opts.targetDir ?? process.cwd();
|
|
16
25
|
const metaPath = node_path_1.default.join(targetDir, '.spark', 'meta.json');
|
|
17
|
-
// 幂等:.spark/meta.json 是 init 流程最后才写的,存在即代表"已完整成功一次"。
|
|
18
|
-
// 用 package.json 判幂等会让 install 失败、CWD 留下半渲染状态的应用永远 init 不了。
|
|
19
26
|
if (node_fs_1.default.existsSync(metaPath)) {
|
|
20
27
|
if (!(0, output_1.isJsonMode)()) {
|
|
21
28
|
process.stdout.write(`Already initialized: ${metaPath}\n`);
|
|
@@ -43,10 +50,11 @@ async function handleAppInit(opts) {
|
|
|
43
50
|
const version = opts.conf?.version;
|
|
44
51
|
const projectName = node_path_1.default.basename(targetDir);
|
|
45
52
|
const tplResult = (0, index_1.renderTemplate)({ stack, version, targetDir, projectName });
|
|
46
|
-
const steeringResult = (0,
|
|
53
|
+
const steeringResult = (0, coding_steering_1.syncCodingSteering)({
|
|
47
54
|
stack,
|
|
48
55
|
targetDir,
|
|
49
56
|
version: opts.conf?.steeringVersion,
|
|
57
|
+
logPrefix: 'init',
|
|
50
58
|
});
|
|
51
59
|
const installResult = (0, index_1.installDependencies)({
|
|
52
60
|
targetDir,
|
|
@@ -54,14 +62,9 @@ async function handleAppInit(opts) {
|
|
|
54
62
|
quietStdout: (0, output_1.isJsonMode)(),
|
|
55
63
|
});
|
|
56
64
|
(0, index_1.writeSparkMeta)(targetDir, {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
templatePackage: tplResult.packageName,
|
|
60
|
-
templateVersion: tplResult.version,
|
|
61
|
-
steeringVersion: steeringResult.version,
|
|
65
|
+
stack,
|
|
66
|
+
version: tplResult.version,
|
|
62
67
|
archType: tplResult.archType,
|
|
63
|
-
installSource: installResult.source,
|
|
64
|
-
installHash: installResult.hash,
|
|
65
68
|
});
|
|
66
69
|
if (!(0, output_1.isJsonMode)()) {
|
|
67
70
|
process.stdout.write(`✓ Initialized ${stack} (template ${tplResult.version}, steering ${steeringResult.version}, install ${installResult.source}) in ${targetDir}\n`);
|
|
@@ -69,7 +72,6 @@ async function handleAppInit(opts) {
|
|
|
69
72
|
(0, output_1.emit)({
|
|
70
73
|
data: {
|
|
71
74
|
initialized: true,
|
|
72
|
-
appId: opts.appId,
|
|
73
75
|
template: stack,
|
|
74
76
|
templatePackage: tplResult.packageName,
|
|
75
77
|
templateVersion: tplResult.version,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.handleAppSync = handleAppSync;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const platform_sync_1 = require("../../../utils/platform-sync");
|
|
9
|
+
const spark_meta_1 = require("../../../utils/spark-meta");
|
|
10
|
+
const error_1 = require("../../../utils/error");
|
|
11
|
+
const output_1 = require("../../../utils/output");
|
|
12
|
+
/**
|
|
13
|
+
* miaoda app sync [--dir <path>]
|
|
14
|
+
*
|
|
15
|
+
* 从 platform-controlled/<stack>/ 同步平台管控内容到项目:
|
|
16
|
+
* - files/ → 按相对路径覆盖
|
|
17
|
+
* - package.json → deep merge patch
|
|
18
|
+
*
|
|
19
|
+
* 需要 .spark/meta.json 已含 stack(走过 `miaoda app init`)。
|
|
20
|
+
* 不动 .agent/skills/(那是 `miaoda skills sync` 的事)。
|
|
21
|
+
*/
|
|
22
|
+
async function handleAppSync(opts) {
|
|
23
|
+
await Promise.resolve();
|
|
24
|
+
const targetDir = node_path_1.default.resolve(opts.dir ?? process.cwd());
|
|
25
|
+
const meta = (0, spark_meta_1.readSparkMeta)(targetDir);
|
|
26
|
+
if (meta.stack === undefined || meta.stack === '') {
|
|
27
|
+
throw new error_1.AppError('SYNC_META_INCOMPLETE', '.spark/meta.json missing stack — run `miaoda app init` first');
|
|
28
|
+
}
|
|
29
|
+
const result = (0, platform_sync_1.syncPlatformControlled)({
|
|
30
|
+
stack: meta.stack,
|
|
31
|
+
targetDir,
|
|
32
|
+
});
|
|
33
|
+
if (!result.stackFound) {
|
|
34
|
+
throw new error_1.AppError('SYNC_STACK_NOT_SUPPORTED', `platform-controlled/${meta.stack}/ not found — 该 stack 暂未纳入 app sync 范围`, {
|
|
35
|
+
next_actions: ['在 miaoda-cli 仓 platform-controlled/ 下添加该 stack 目录,然后重新发版'],
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
(0, output_1.emit)({
|
|
39
|
+
data: {
|
|
40
|
+
stack: meta.stack,
|
|
41
|
+
syncedFiles: result.syncedFiles,
|
|
42
|
+
mergedJsonFiles: result.mergedJsonFiles,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -16,6 +16,7 @@ async function handleDeployModern(opts) {
|
|
|
16
16
|
const projectDir = node_path_1.default.resolve(opts.dir);
|
|
17
17
|
const result = await (0, index_1.runModernDeploy)({
|
|
18
18
|
projectDir,
|
|
19
|
+
appId: opts.appId,
|
|
19
20
|
skipBuild: opts.skipBuild ?? false,
|
|
20
21
|
});
|
|
21
22
|
(0, output_1.emit)({
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleSkillsStatus = exports.handleSkillsSync = void 0;
|
|
4
|
+
var sync_1 = require("./sync");
|
|
5
|
+
Object.defineProperty(exports, "handleSkillsSync", { enumerable: true, get: function () { return sync_1.handleSkillsSync; } });
|
|
6
|
+
var status_1 = require("./status");
|
|
7
|
+
Object.defineProperty(exports, "handleSkillsStatus", { enumerable: true, get: function () { return status_1.handleSkillsStatus; } });
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.handleSkillsStatus = handleSkillsStatus;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const index_1 = require("../../../services/skills/index");
|
|
9
|
+
const spark_meta_1 = require("../../../utils/spark-meta");
|
|
10
|
+
const output_1 = require("../../../utils/output");
|
|
11
|
+
/**
|
|
12
|
+
* miaoda skills status [--dir <path>]
|
|
13
|
+
*
|
|
14
|
+
* 从 .spark/meta.json 读 stack,扫描 <dir>/.agent/steering/<stack>/,
|
|
15
|
+
* 给出当前装了哪些 skills、tech.md 是否在。纯本地操作,不联网。
|
|
16
|
+
* meta 缺 stack 时返回 present=false(不抛错,方便和 init 的引导分开)。
|
|
17
|
+
*/
|
|
18
|
+
async function handleSkillsStatus(opts) {
|
|
19
|
+
await Promise.resolve();
|
|
20
|
+
const targetDir = node_path_1.default.resolve(opts.dir ?? process.cwd());
|
|
21
|
+
const meta = (0, spark_meta_1.readSparkMeta)(targetDir);
|
|
22
|
+
const status = (0, index_1.readSkillsStatus)({ targetDir, stack: meta.stack });
|
|
23
|
+
(0, output_1.emit)({
|
|
24
|
+
data: {
|
|
25
|
+
stack: meta.stack ?? null,
|
|
26
|
+
present: status.present,
|
|
27
|
+
skills: status.skills,
|
|
28
|
+
techSynced: status.techSynced,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.handleSkillsSync = handleSkillsSync;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const coding_steering_1 = require("../../../utils/coding-steering");
|
|
9
|
+
const spark_meta_1 = require("../../../utils/spark-meta");
|
|
10
|
+
const error_1 = require("../../../utils/error");
|
|
11
|
+
const output_1 = require("../../../utils/output");
|
|
12
|
+
/**
|
|
13
|
+
* miaoda skills sync [--dir <path>] [--version <ver>]
|
|
14
|
+
*
|
|
15
|
+
* 从 .spark/meta.json 读 stack,把 coding-steering 包内对应 stack 的 skills + tech.md
|
|
16
|
+
* 同步到 <dir>/.agent/steering/。需要先跑过 `miaoda app init`。
|
|
17
|
+
*/
|
|
18
|
+
async function handleSkillsSync(opts) {
|
|
19
|
+
await Promise.resolve();
|
|
20
|
+
const targetDir = node_path_1.default.resolve(opts.dir ?? process.cwd());
|
|
21
|
+
const meta = (0, spark_meta_1.readSparkMeta)(targetDir);
|
|
22
|
+
if (meta.stack === undefined || meta.stack === '') {
|
|
23
|
+
throw new error_1.AppError('SKILLS_META_INCOMPLETE', '.spark/meta.json missing stack — run `miaoda app init` first');
|
|
24
|
+
}
|
|
25
|
+
const result = (0, coding_steering_1.syncCodingSteering)({
|
|
26
|
+
stack: meta.stack,
|
|
27
|
+
targetDir,
|
|
28
|
+
version: opts.version,
|
|
29
|
+
});
|
|
30
|
+
(0, output_1.emit)({
|
|
31
|
+
data: {
|
|
32
|
+
stack: meta.stack,
|
|
33
|
+
version: result.version,
|
|
34
|
+
syncedSkills: result.syncedSkills,
|
|
35
|
+
techSynced: result.techSynced,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.installDependencies = exports.writeSparkMeta = exports.readSparkMeta = exports.
|
|
3
|
+
exports.installDependencies = exports.writeSparkMeta = exports.readSparkMeta = exports.TEMPLATE_PACKAGE_BY_STACK = exports.SUPPORTED_STACKS = exports.renderTemplate = void 0;
|
|
4
4
|
var template_1 = require("./template");
|
|
5
5
|
Object.defineProperty(exports, "renderTemplate", { enumerable: true, get: function () { return template_1.renderTemplate; } });
|
|
6
6
|
Object.defineProperty(exports, "SUPPORTED_STACKS", { enumerable: true, get: function () { return template_1.SUPPORTED_STACKS; } });
|
|
7
7
|
Object.defineProperty(exports, "TEMPLATE_PACKAGE_BY_STACK", { enumerable: true, get: function () { return template_1.TEMPLATE_PACKAGE_BY_STACK; } });
|
|
8
|
-
var steering_1 = require("./steering");
|
|
9
|
-
Object.defineProperty(exports, "syncSteering", { enumerable: true, get: function () { return steering_1.syncSteering; } });
|
|
10
8
|
var spark_meta_1 = require("../../../utils/spark-meta");
|
|
11
9
|
Object.defineProperty(exports, "readSparkMeta", { enumerable: true, get: function () { return spark_meta_1.readSparkMeta; } });
|
|
12
10
|
Object.defineProperty(exports, "writeSparkMeta", { enumerable: true, get: function () { return spark_meta_1.writeSparkMeta; } });
|
|
@@ -10,17 +10,18 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
10
10
|
const npm_pack_1 = require("../../../utils/npm-pack");
|
|
11
11
|
const error_1 = require("../../../utils/error");
|
|
12
12
|
const logger_1 = require("../../../utils/logger");
|
|
13
|
-
/** 短名 → 包名映射。新增 stack 时改这里。 */
|
|
13
|
+
/** 短名 → 包名映射。新增 stack 时改这里。archType 由 template 包自报,CLI 不维护。 */
|
|
14
14
|
exports.TEMPLATE_PACKAGE_BY_STACK = {
|
|
15
15
|
'vite-react': '@lark-apaas/coding-template-vite-react',
|
|
16
16
|
html: '@lark-apaas/coding-template-html',
|
|
17
17
|
};
|
|
18
18
|
exports.SUPPORTED_STACKS = Object.keys(exports.TEMPLATE_PACKAGE_BY_STACK);
|
|
19
|
-
// template/ 内以下划线开头的占位文件名在渲染时改名(npm publish 会把 .gitignore 吞掉,
|
|
20
|
-
// 模板里用 _gitignore 提交,渲染时再改回)。
|
|
19
|
+
// template/ 内以下划线开头的占位文件名在渲染时改名(npm publish 会把 .gitignore / .npmrc 吞掉,
|
|
20
|
+
// 模板里用 _gitignore / _npmrc 提交,渲染时再改回)。
|
|
21
21
|
const RENAME_FILES = {
|
|
22
22
|
_gitignore: '.gitignore',
|
|
23
23
|
'_env.local': '.env.local',
|
|
24
|
+
_npmrc: '.npmrc',
|
|
24
25
|
};
|
|
25
26
|
function renderTemplate(opts) {
|
|
26
27
|
const packageName = exports.TEMPLATE_PACKAGE_BY_STACK[opts.stack];
|
|
@@ -37,12 +38,13 @@ function renderTemplate(opts) {
|
|
|
37
38
|
throw new error_1.AppError('TEMPLATE_INVALID', `包 ${packageName}@${fetched.version} 缺少 template/ 目录`);
|
|
38
39
|
}
|
|
39
40
|
const pkgJsonPath = node_path_1.default.join(fetched.extractDir, 'package.json');
|
|
40
|
-
let archType
|
|
41
|
+
let archType;
|
|
41
42
|
if (node_fs_1.default.existsSync(pkgJsonPath)) {
|
|
42
43
|
const pkgJson = JSON.parse(node_fs_1.default.readFileSync(pkgJsonPath, 'utf-8'));
|
|
43
|
-
archType = pkgJson.miaodaTemplate?.archType
|
|
44
|
+
archType = pkgJson.miaodaTemplate?.archType;
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
+
// 用显式 null/undefined/'' 判,避免把合法值 0 / false 当成"缺失"误抛
|
|
47
|
+
if (archType === undefined || archType === null || archType === '') {
|
|
46
48
|
throw new error_1.AppError('TEMPLATE_INVALID', `包 ${packageName}@${fetched.version} 缺少 package.json.miaodaTemplate.archType`);
|
|
47
49
|
}
|
|
48
50
|
(0, logger_1.log)('init', `Rendering template to ${opts.targetDir}...`);
|
|
@@ -6,13 +6,14 @@ const error_1 = require("../../../../utils/error");
|
|
|
6
6
|
const logger_1 = require("../../../../utils/logger");
|
|
7
7
|
const protocol_1 = require("../protocol");
|
|
8
8
|
/**
|
|
9
|
-
* 给
|
|
9
|
+
* 给 RESOURCE_CDN_PREFIX 补 https:// 协议头:
|
|
10
10
|
* - 已带 http:// 或 https:// → 原样返回
|
|
11
11
|
* - 以 / 开头(绝对路径)→ 原样返回
|
|
12
12
|
* - 不含 dot(看起来不像域名,比如纯路径 app_xxx/2)→ 原样返回
|
|
13
13
|
* - 其它(典型:lf-xxx.bytetos.com/...)→ 前缀 https://
|
|
14
14
|
*
|
|
15
15
|
* template 的 build script 直接拿来当 vite base / asset URL 用,必须是合法 URL。
|
|
16
|
+
* STATIC_CDN_PREFIX 由 runtime 同域提供(相对路径),不走这里。
|
|
16
17
|
*/
|
|
17
18
|
function ensureHttpsScheme(v) {
|
|
18
19
|
if (/^https?:\/\//i.test(v))
|
|
@@ -28,17 +29,21 @@ function ensureHttpsScheme(v) {
|
|
|
28
29
|
* MIAODA_APP_ID / MIAODA_VERSION / MIAODA_STACK
|
|
29
30
|
* MIAODA_RESOURCE_CDN_PREFIX / MIAODA_STATIC_CDN_PREFIX
|
|
30
31
|
*
|
|
31
|
-
*
|
|
32
|
+
* MIAODA_STATIC_CDN_PREFIX 取自 output_static_paas_storage_credential.downloadURLPrefix,
|
|
33
|
+
* 是 runtime 同域相对路径(例如 /app/<appId>/runtime/api/v1/storage/object/<bucket>/),
|
|
34
|
+
* 不补 https scheme,原样注入。顶层 static_cdn_prefix 不再下发。
|
|
35
|
+
*
|
|
32
36
|
* build 失败抛 AppError(execSync 自身会 throw,捕获后包一层加错误码)。
|
|
33
37
|
*/
|
|
34
38
|
function runBuild(opts) {
|
|
39
|
+
const staticCred = (0, protocol_1.parsePaasStorageCredential)((0, protocol_1.requireDataKey)(opts.data, protocol_1.DataKey.OUTPUT_STATIC_PAAS_STORAGE_CREDENTIAL), protocol_1.DataKey.OUTPUT_STATIC_PAAS_STORAGE_CREDENTIAL);
|
|
35
40
|
const buildEnv = {
|
|
36
41
|
...process.env,
|
|
37
42
|
MIAODA_APP_ID: opts.appId,
|
|
38
43
|
MIAODA_VERSION: opts.version,
|
|
39
44
|
MIAODA_STACK: opts.templateKey,
|
|
40
45
|
MIAODA_RESOURCE_CDN_PREFIX: ensureHttpsScheme((0, protocol_1.requireDataKey)(opts.data, protocol_1.DataKey.RESOURCE_CDN_PREFIX)),
|
|
41
|
-
MIAODA_STATIC_CDN_PREFIX:
|
|
46
|
+
MIAODA_STATIC_CDN_PREFIX: staticCred.downloadURLPrefix,
|
|
42
47
|
};
|
|
43
48
|
(0, logger_1.log)('deploy', 'Building...');
|
|
44
49
|
try {
|