@lark-apaas/miaoda-cli 0.1.5 → 0.1.6-alpha.388541c
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 +13 -1
- package/dist/api/deploy/modern-types.js +23 -0
- package/dist/api/deploy/modern.js +78 -0
- package/dist/api/deploy/plugin-instances-types.js +6 -0
- package/dist/api/deploy/plugin-instances.js +22 -0
- package/dist/cli/commands/app/index.js +144 -2
- package/dist/cli/commands/deploy/modern.js +50 -0
- package/dist/cli/commands/index.js +68 -5
- package/dist/cli/commands/skills/index.js +79 -0
- package/dist/cli/handlers/app/index.js +9 -1
- package/dist/cli/handlers/app/init.js +132 -0
- package/dist/cli/handlers/app/sync.js +219 -0
- package/dist/cli/handlers/deploy/modern.js +33 -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 +49 -0
- package/dist/config/fullstack-cli-pin.js +17 -0
- package/dist/config/sync-configs/design-stack.js +98 -0
- package/dist/config/sync-configs/index.js +62 -0
- package/dist/config/sync-configs/nestjs-react-fullstack.js +177 -0
- package/dist/config/sync.js +14 -0
- package/dist/services/app/init/index.js +12 -0
- package/dist/services/app/init/install.js +123 -0
- package/dist/services/app/init/template.js +109 -0
- package/dist/services/deploy/modern/atoms/build.js +59 -0
- package/dist/services/deploy/modern/atoms/context.js +27 -0
- package/dist/services/deploy/modern/atoms/index.js +17 -0
- package/dist/services/deploy/modern/atoms/local-release.js +27 -0
- package/dist/services/deploy/modern/atoms/pre-release.js +13 -0
- package/dist/services/deploy/modern/atoms/save-plugin-instances.js +72 -0
- package/dist/services/deploy/modern/atoms/upload.js +246 -0
- package/dist/services/deploy/modern/check.js +53 -0
- package/dist/services/deploy/modern/constants.js +13 -0
- package/dist/services/deploy/modern/index.js +16 -0
- package/dist/services/deploy/modern/pipelines/index.js +5 -0
- package/dist/services/deploy/modern/pipelines/local.js +75 -0
- package/dist/services/deploy/modern/protocol.js +122 -0
- package/dist/services/deploy/modern/run-types.js +4 -0
- package/dist/services/deploy/modern/run.js +13 -0
- package/dist/services/deploy/modern/template-key-map.js +22 -0
- package/dist/services/skills/index.js +5 -0
- package/dist/services/skills/status.js +37 -0
- package/dist/utils/coding-steering.js +169 -0
- package/dist/utils/file-ops.js +45 -0
- package/dist/utils/githooks.js +55 -0
- package/dist/utils/http.js +21 -11
- package/dist/utils/merge-json.js +63 -0
- package/dist/utils/npm-pack.js +55 -0
- package/dist/utils/platform-sync.js +160 -0
- package/dist/utils/spark-meta.js +42 -0
- package/dist/utils/sync-rule.js +295 -0
- package/package.json +5 -3
- package/upgrade/templates/README.md +34 -0
- package/upgrade/templates/design-stack/templates/.githooks/pre-commit +4 -0
- package/upgrade/templates/design-stack/templates/scripts/dev-local.sh +53 -0
- package/upgrade/templates/design-stack/templates/scripts/dev.sh +25 -0
- package/upgrade/templates/design-stack/templates/scripts/hooks/run-precommit.js +37 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/.githooks/pre-commit +4 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/.gitignore.append +8 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/.spark_project +16 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/drizzle.config.ts +55 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/helper/gen-openapi.ts +34 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/nest-cli.json +25 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/build.sh +207 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/dev-local.sh +61 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/dev.js +295 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/dev.sh +25 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/hooks/run-precommit.js +37 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/lint.js +150 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/prune-smart.js +330 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/run.sh +8 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/server/global.d.ts +19 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/tsconfig.node.json +5 -0
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ miaoda file ls --output json
|
|
|
55
55
|
## 环境变量
|
|
56
56
|
|
|
57
57
|
- `MIAODA_APP_ID`:默认应用 ID,等价于 `--app-id`。
|
|
58
|
-
- `MIAODA_CANARY_HEADER
|
|
58
|
+
- `MIAODA_CANARY_HEADER`:HTTP 请求的 `x-tt-env` 小流量头取值。未设置时默认 `boe_miaoda_doubao`;设为空字符串则不带该头(例:`export MIAODA_CANARY_HEADER=boe_xxx`)。值形如 `ppe_xxx` 时额外带上 `x-use-ppe: 1`。
|
|
59
59
|
|
|
60
60
|
## 输出契约
|
|
61
61
|
|
package/dist/api/deploy/index.js
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
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.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; } });
|
|
7
7
|
Object.defineProperty(exports, "getErrorLog", { enumerable: true, get: function () { return api_1.getErrorLog; } });
|
|
8
8
|
Object.defineProperty(exports, "queryPipelineInstance", { enumerable: true, get: function () { return api_1.queryPipelineInstance; } });
|
|
9
|
+
var modern_1 = require("./modern");
|
|
10
|
+
Object.defineProperty(exports, "preRelease", { enumerable: true, get: function () { return modern_1.preRelease; } });
|
|
11
|
+
Object.defineProperty(exports, "createLocalRelease", { enumerable: true, get: function () { return modern_1.createLocalRelease; } });
|
|
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; } });
|
|
14
|
+
Object.defineProperty(exports, "createModernRelease", { enumerable: true, get: function () { return modern_1.createRelease; } });
|
|
15
|
+
Object.defineProperty(exports, "getModernReleaseStatus", { enumerable: true, get: function () { return modern_1.getReleaseStatus; } });
|
|
16
|
+
Object.defineProperty(exports, "getModernLastPublishedVersion", { enumerable: true, get: function () { return modern_1.getLastPublishedVersion; } });
|
|
17
|
+
var modern_types_1 = require("./modern-types");
|
|
18
|
+
Object.defineProperty(exports, "LocalReleaseStatus", { enumerable: true, get: function () { return modern_types_1.LocalReleaseStatus; } });
|
|
19
|
+
var plugin_instances_1 = require("./plugin-instances");
|
|
20
|
+
Object.defineProperty(exports, "batchSavePluginInstances", { enumerable: true, get: function () { return plugin_instances_1.batchSavePluginInstances; } });
|
|
9
21
|
var schemas_1 = require("./schemas");
|
|
10
22
|
Object.defineProperty(exports, "deployHistorySchema", { enumerable: true, get: function () { return schemas_1.deployHistorySchema; } });
|
|
11
23
|
Object.defineProperty(exports, "deployGetSchema", { enumerable: true, get: function () { return schemas_1.deployGetSchema; } });
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// modern deploy 接口的请求 / 响应类型(与服务端发布编排接口对齐)。
|
|
3
|
+
// 第一期落地的链路:本地构建 + 本地部署。
|
|
4
|
+
//
|
|
5
|
+
// 接口分两类:
|
|
6
|
+
// - preRelease:所有"本地构建"链路共用,签发动态配置(含 pre-signed TOS upload URL)
|
|
7
|
+
// - localPublish:本地构建 + 本地部署专用(createReleaseLocalPublish + updateReleaseLocalPublish)
|
|
8
|
+
//
|
|
9
|
+
// 远端部署链路(B/C)所需的 release 接口先预留类型骨架,待 B/C 落地时启用。
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.LocalReleaseStatus = void 0;
|
|
12
|
+
/**
|
|
13
|
+
* localPublish 状态枚举(数值,与服务端 IDL 对齐)。
|
|
14
|
+
* CLI updateLocalRelease 只翻 Finished / Failed 两个终态;其它由后端流转。
|
|
15
|
+
*/
|
|
16
|
+
exports.LocalReleaseStatus = {
|
|
17
|
+
Unspecified: 0,
|
|
18
|
+
Publishing: 1,
|
|
19
|
+
Finished: 2,
|
|
20
|
+
Failed: 3,
|
|
21
|
+
Canceled: 4,
|
|
22
|
+
Rollback: 5,
|
|
23
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// modern deploy 接口客户端。统一走管理端 innerapi(postInnerApi 信封解析)。
|
|
3
|
+
//
|
|
4
|
+
// 第一期落地(本地构建 + 本地部署):
|
|
5
|
+
// - preRelease:拿 pre_release_id + version + 动态配置 data
|
|
6
|
+
// - createLocalRelease / updateLocalRelease:完整本地部署生命周期
|
|
7
|
+
//
|
|
8
|
+
// 远端部署(本地构建+远端部署、远端构建+远端部署)需要 createRelease + getReleaseStatus,
|
|
9
|
+
// 后续 commit 接入;本文件已预留 endpoint 骨架但暂不导出。
|
|
10
|
+
//
|
|
11
|
+
// 约定:所有接口的 appID 走 URL :appID 路径参数,body 不再冗余携带 appID。
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.preRelease = preRelease;
|
|
14
|
+
exports.createLocalRelease = createLocalRelease;
|
|
15
|
+
exports.updateLocalRelease = updateLocalRelease;
|
|
16
|
+
exports.callbackStatic = callbackStatic;
|
|
17
|
+
exports.createRelease = createRelease;
|
|
18
|
+
exports.getReleaseStatus = getReleaseStatus;
|
|
19
|
+
exports.getLastPublishedVersion = getLastPublishedVersion;
|
|
20
|
+
const http_1 = require("../../utils/http");
|
|
21
|
+
const devops_error_1 = require("../../utils/devops-error");
|
|
22
|
+
const DEFAULT_ERR_CODE = 'INTERNAL_DEVOPS_ERROR';
|
|
23
|
+
function envelopeOpts(errPrefix) {
|
|
24
|
+
// modern deploy 接口与 default deploy / app 走同一个 lark.apaas.devops PSM,
|
|
25
|
+
// 业务错误码命名空间共享,直接复用 mapDevopsError 把 BAM 码翻为 AppError。
|
|
26
|
+
return {
|
|
27
|
+
errPrefix,
|
|
28
|
+
defaultErrCode: DEFAULT_ERR_CODE,
|
|
29
|
+
mapErr: devops_error_1.mapDevopsError,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// ── preRelease ──
|
|
33
|
+
/** POST /v1/devops/app/:appID/pre_release */
|
|
34
|
+
async function preRelease(req) {
|
|
35
|
+
const { appID, ...body } = req;
|
|
36
|
+
const url = `/v1/devops/app/${encodeURIComponent(appID)}/pre_release`;
|
|
37
|
+
return (0, http_1.postInnerApi)(url, body, envelopeOpts('Failed to pre-release'));
|
|
38
|
+
}
|
|
39
|
+
// ── localPublish ──
|
|
40
|
+
/** POST /v1/devops/app/:appID/local_publish/release */
|
|
41
|
+
async function createLocalRelease(req) {
|
|
42
|
+
const { appID, ...body } = req;
|
|
43
|
+
const url = `/v1/devops/app/${encodeURIComponent(appID)}/local_publish/release`;
|
|
44
|
+
return (0, http_1.postInnerApi)(url, body, envelopeOpts('Failed to create local release'));
|
|
45
|
+
}
|
|
46
|
+
/** POST /v1/devops/app/:appID/local_publish/update_release */
|
|
47
|
+
async function updateLocalRelease(req) {
|
|
48
|
+
const { appID, ...body } = req;
|
|
49
|
+
const url = `/v1/devops/app/${encodeURIComponent(appID)}/local_publish/update_release`;
|
|
50
|
+
await (0, http_1.postInnerApi)(url, body, envelopeOpts('Failed to update local release'));
|
|
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
|
+
}
|
|
59
|
+
// ── release(远端部署,B / C 链路;本期不导出,类型骨架已就绪) ──
|
|
60
|
+
/** POST /v1/devops/app/:appID/remote_publish/release */
|
|
61
|
+
async function createRelease(req) {
|
|
62
|
+
const { appID, ...body } = req;
|
|
63
|
+
const url = `/v1/devops/app/${encodeURIComponent(appID)}/remote_publish/release`;
|
|
64
|
+
return (0, http_1.postInnerApi)(url, body, envelopeOpts('Failed to create release'));
|
|
65
|
+
}
|
|
66
|
+
/** POST /v1/devops/app/:appID/release/status */
|
|
67
|
+
async function getReleaseStatus(req) {
|
|
68
|
+
const { appID, ...body } = req;
|
|
69
|
+
const url = `/v1/devops/app/${encodeURIComponent(appID)}/release/status`;
|
|
70
|
+
return (0, http_1.postInnerApi)(url, body, envelopeOpts('Failed to query release status'));
|
|
71
|
+
}
|
|
72
|
+
// ── getLastPublishedVersion(URL path 待文档补充) ──
|
|
73
|
+
/** POST /v1/devops/app/:appID/last_published_version(path 待后端确认) */
|
|
74
|
+
async function getLastPublishedVersion(req) {
|
|
75
|
+
const { appID } = req;
|
|
76
|
+
const url = `/v1/devops/app/${encodeURIComponent(appID)}/last_published_version`;
|
|
77
|
+
return (0, http_1.postInnerApi)(url, {}, envelopeOpts('Failed to get last published version'));
|
|
78
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// studio_server 的 plugin_instances 批量保存接口。
|
|
3
|
+
//
|
|
4
|
+
// 后端已统一到 InnerEnvelope(`{data, status_code, message}`)信封;不再手撸
|
|
5
|
+
// 旧 BaseResp 解析,直接复用 utils/http.ts 的 postInnerApi,verbose 下也能拿到
|
|
6
|
+
// `→ POST` / `body:` / `resp:` 的完整日志。
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.batchSavePluginInstances = batchSavePluginInstances;
|
|
9
|
+
const http_1 = require("../../utils/http");
|
|
10
|
+
const URL_PATH = '/api/v1/studio/innerapi/plugin_instances/batch_save';
|
|
11
|
+
/**
|
|
12
|
+
* POST /api/v1/studio/innerapi/plugin_instances/batch_save
|
|
13
|
+
*
|
|
14
|
+
* 把发布版本的 capability 集合注册到 studio_server。
|
|
15
|
+
* 失败时抛 AppError("DEPLOY_PLUGIN_BATCH_SAVE_FAILED"),错误信息来自 envelope.message。
|
|
16
|
+
*/
|
|
17
|
+
async function batchSavePluginInstances(req) {
|
|
18
|
+
await (0, http_1.postInnerApi)(URL_PATH, req, {
|
|
19
|
+
errPrefix: 'Failed to save plugin instances',
|
|
20
|
+
defaultErrCode: 'DEPLOY_PLUGIN_BATCH_SAVE_FAILED',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
@@ -3,8 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.registerAppCommands = registerAppCommands;
|
|
4
4
|
const shared_1 = require("../../../cli/commands/shared");
|
|
5
5
|
const index_1 = require("../../../cli/handlers/app/index");
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const error_1 = require("../../../utils/error");
|
|
7
|
+
function registerAppCommands(program, opts = {}) {
|
|
8
|
+
const description = opts.includeInit
|
|
9
|
+
? '应用元数据管理:查看 / 修改 / 初始化 / 升级平台资产'
|
|
10
|
+
: '应用元数据管理:查看 / 修改';
|
|
11
|
+
const appCmd = program.command('app').description(description);
|
|
8
12
|
appCmd.action(() => {
|
|
9
13
|
appCmd.outputHelp();
|
|
10
14
|
});
|
|
@@ -15,6 +19,58 @@ function registerAppCommands(program) {
|
|
|
15
19
|
`);
|
|
16
20
|
registerAppGet(appCmd);
|
|
17
21
|
registerAppUpdate(appCmd);
|
|
22
|
+
if (opts.includeInit) {
|
|
23
|
+
registerAppInit(appCmd);
|
|
24
|
+
registerAppSync(appCmd);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function registerAppSync(parent) {
|
|
28
|
+
const cmd = parent
|
|
29
|
+
.command('sync')
|
|
30
|
+
.alias('upgrade')
|
|
31
|
+
.description('一站式同步:按 stack 的 SyncRule 全套 apply + 按钉死版本表升 @lark-apaas/* deps + npm install')
|
|
32
|
+
.option('--dir <path>', '项目目录,默认 cwd(需含 .spark/meta.json)')
|
|
33
|
+
.addHelpText('after', `
|
|
34
|
+
别名
|
|
35
|
+
miaoda app sync 与 miaoda app upgrade 等价(upgrade 是历史别名,新调用方请用 sync)。
|
|
36
|
+
|
|
37
|
+
流程
|
|
38
|
+
1. 按 stack 的 SyncRule[] 全套 apply(src/config/sync-configs/<stack>.ts 定义):
|
|
39
|
+
directory → 整个目录拷贝(.sh 自动 +x)
|
|
40
|
+
file → 单文件覆盖(可选 onlyIfExists / overwrite)
|
|
41
|
+
merge-json → JSON deep merge(可选 arrayMerge by key 去重)
|
|
42
|
+
add-script → npm script 不存在时添加(overwrite=false 默认不覆盖)
|
|
43
|
+
patch-script → npm script 以指定前缀开头时改写(守护用户自定义)
|
|
44
|
+
add-line → 行不存在时追加到文件
|
|
45
|
+
remove-line → 行存在时移除
|
|
46
|
+
delete-file/delete-directory → 删除
|
|
47
|
+
沙箱里跑的 fullstack-cli sync 走同一套 rule 类型,行为对齐;miaoda app sync 在此之上
|
|
48
|
+
补 dev:local 等本地开发独有规则。
|
|
49
|
+
2. 平台 deps 钉版本:按 handlers/app/sync.ts 里 PINNED_PLATFORM_VERSIONS 升 user app 已装的
|
|
50
|
+
@lark-apaas/* 包;表外 / 未装的不动。
|
|
51
|
+
3. activateGitHooks:core.hooksPath 一次性指向 .githooks/。
|
|
52
|
+
4. npm install --no-audit --no-fund --ignore-scripts。--ignore-scripts 是为绕开
|
|
53
|
+
action-plugin postinstall 在 npm install 时缺平台 env 的卡点(需要时再
|
|
54
|
+
FORCE_AUTHN_INNERAPI_DOMAIN=... npm install 手动跑一次)。
|
|
55
|
+
|
|
56
|
+
JSON 输出
|
|
57
|
+
{"data": {"stack": "...",
|
|
58
|
+
"appliedRules": [{"type": "...", "action": "...", "path": "...", "detail": "..."}],
|
|
59
|
+
"syncedFiles": [...],
|
|
60
|
+
"mergedJsonFiles": [{"path": "...", "keys": [...]}],
|
|
61
|
+
"patchedScripts": [...],
|
|
62
|
+
"upgradedPackages": [{"name": "...", "from": "...", "to": "...", "section": "..."}]}}
|
|
63
|
+
|
|
64
|
+
示例
|
|
65
|
+
$ miaoda app sync
|
|
66
|
+
$ miaoda app sync --dir /path/to/app
|
|
67
|
+
$ miaoda app upgrade # 等价于 miaoda app sync
|
|
68
|
+
`);
|
|
69
|
+
cmd.action((0, shared_1.withHelp)(cmd, async (rawOpts) => {
|
|
70
|
+
await (0, index_1.handleAppSync)({
|
|
71
|
+
dir: rawOpts.dir,
|
|
72
|
+
});
|
|
73
|
+
}));
|
|
18
74
|
}
|
|
19
75
|
function registerAppGet(parent) {
|
|
20
76
|
const cmd = parent
|
|
@@ -60,3 +116,89 @@ JSON 输出
|
|
|
60
116
|
});
|
|
61
117
|
}));
|
|
62
118
|
}
|
|
119
|
+
function registerAppInit(parent) {
|
|
120
|
+
const cmd = parent
|
|
121
|
+
.command('init')
|
|
122
|
+
.description('初始化应用代码:抓 template 渲染、同步 upgrade/templates、装 .agent/steering/ skills、写 .spark/meta.json。.spark/meta.json 已存在则直接退出')
|
|
123
|
+
.option('--template <stack>', `技术栈短名(${index_1.SUPPORTED_STACKS.join(' / ')})`)
|
|
124
|
+
.option('--conf <json>', 'init 配置 JSON。支持 {"version": "<template 版本>"} / {"steeringVersion": "<steering 版本>"},均默认 latest')
|
|
125
|
+
.option('--skip-install', '跳过依赖安装', false)
|
|
126
|
+
.addOption((0, shared_1.appIdOption)())
|
|
127
|
+
.addHelpText('after', `
|
|
128
|
+
幂等
|
|
129
|
+
.spark/meta.json 已存在时直接退出(initialized=false, reason=already_initialized),
|
|
130
|
+
不再触发 template 渲染、不重新跑 upgrade/templates 同步、不重新拉 skills、不安装依赖。
|
|
131
|
+
meta.json 在 init 流程最后才写,写了 = 已完整成功一次;
|
|
132
|
+
上一次失败留下半渲染状态时(package.json 在但 meta.json 没在)允许重跑。
|
|
133
|
+
|
|
134
|
+
应用身份(app_id)
|
|
135
|
+
--app-id <id>(或 MIAODA_APP_ID env)提供时写入 .spark/meta.json 的 app_id 字段;
|
|
136
|
+
未提供则不写。运行端命令(deploy / file / plugin 等)仍优先读 MIAODA_APP_ID env,
|
|
137
|
+
env 未设置时回退到 meta.json.app_id。
|
|
138
|
+
|
|
139
|
+
平台同步(upgrade/templates)
|
|
140
|
+
init 内嵌一次 upgrade/templates 同步(跟 app upgrade 共用同一份 util):
|
|
141
|
+
从 miaoda-cli 自带的 upgrade/templates/<stack>/ 同步 files/(覆盖)+ patches/
|
|
142
|
+
(JSON deep merge,含 scripts.dev:local 等)。目标 stack 未纳入 upgrade/templates/
|
|
143
|
+
时跳过(不报错)。后续要升 @lark-apaas/* 平台包到最新 alpha,跑 'miaoda app upgrade'。
|
|
144
|
+
|
|
145
|
+
依赖安装
|
|
146
|
+
默认:npm install --no-audit --no-fund
|
|
147
|
+
--skip-install: 跳过
|
|
148
|
+
MIAODA_DEP_CACHE_DIR 环境变量:
|
|
149
|
+
若设了且 CWD 含 package.json,先算 md5(package.json),
|
|
150
|
+
命中 \${MIAODA_DEP_CACHE_DIR}/\${hash}.zip 则 unzip 复用缓存;未命中或解压后 node_modules
|
|
151
|
+
为空都会 fallback npm install。
|
|
152
|
+
JSON 模式下子进程 stdout 重定向到 stderr,避免污染最终 emit 的 JSON。
|
|
153
|
+
|
|
154
|
+
JSON 输出
|
|
155
|
+
已初始化:{"data": {"initialized": false, "reason": "already_initialized", "targetDir": "..."}}
|
|
156
|
+
新初始化:{"data": {"initialized": true, "template": "...", "templateVersion": "...", "steeringVersion": "...",
|
|
157
|
+
"appId": "...", "platformStackFound": true, "platformSyncedFiles": [...],
|
|
158
|
+
"installed": true, "installSource": "cache|npm|skipped", "installHash": "...", ...}}
|
|
159
|
+
|
|
160
|
+
示例
|
|
161
|
+
$ miaoda app init --template vite-react
|
|
162
|
+
$ miaoda app init --template nestjs-react-fullstack --app-id app_xxx
|
|
163
|
+
$ miaoda app init --template vite-react --conf '{"version": "0.1.0-alpha.1"}'
|
|
164
|
+
$ miaoda app init --template vite-react --conf '{"steeringVersion": "0.1.0"}'
|
|
165
|
+
$ miaoda app init --template vite-react --skip-install
|
|
166
|
+
$ MIAODA_DEP_CACHE_DIR=/tmp/dep-cache miaoda app init --template vite-react
|
|
167
|
+
`);
|
|
168
|
+
cmd.action((0, shared_1.withHelp)(cmd, async (rawOpts) => {
|
|
169
|
+
const conf = parseInitConf(rawOpts.conf);
|
|
170
|
+
await (0, index_1.handleAppInit)({
|
|
171
|
+
template: rawOpts.template,
|
|
172
|
+
conf,
|
|
173
|
+
skipInstall: rawOpts.skipInstall,
|
|
174
|
+
appId: rawOpts.appId,
|
|
175
|
+
});
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
function parseInitConf(raw) {
|
|
179
|
+
if (raw === undefined)
|
|
180
|
+
return undefined;
|
|
181
|
+
let parsed;
|
|
182
|
+
try {
|
|
183
|
+
parsed = JSON.parse(raw);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
187
|
+
throw new error_1.AppError('ARGS_INVALID', `--conf 必须是合法 JSON:${msg}`);
|
|
188
|
+
}
|
|
189
|
+
if (!isPlainObject(parsed)) {
|
|
190
|
+
throw new error_1.AppError('ARGS_INVALID', '--conf 必须是 JSON 对象');
|
|
191
|
+
}
|
|
192
|
+
const version = parsed.version;
|
|
193
|
+
if (version !== undefined && typeof version !== 'string') {
|
|
194
|
+
throw new error_1.AppError('ARGS_INVALID', '--conf.version 必须是字符串');
|
|
195
|
+
}
|
|
196
|
+
const steeringVersion = parsed.steeringVersion;
|
|
197
|
+
if (steeringVersion !== undefined && typeof steeringVersion !== 'string') {
|
|
198
|
+
throw new error_1.AppError('ARGS_INVALID', '--conf.steeringVersion 必须是字符串');
|
|
199
|
+
}
|
|
200
|
+
return { version, steeringVersion };
|
|
201
|
+
}
|
|
202
|
+
function isPlainObject(v) {
|
|
203
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
204
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerDeployCommandsModern = registerDeployCommandsModern;
|
|
4
|
+
const shared_1 = require("../../../cli/commands/shared");
|
|
5
|
+
const modern_1 = require("../../../cli/handlers/deploy/modern");
|
|
6
|
+
/**
|
|
7
|
+
* modern scene (MIAODA_APP_TYPE=7) 专用 deploy 注册。
|
|
8
|
+
* 仅披露顶层 `miaoda deploy`,CLI 表面对齐 openclaw-cli:`--dir / --skip-build`。
|
|
9
|
+
*
|
|
10
|
+
* 与 default 的 registerDeployCommands 完全平行:两套实现 100% 隔离,
|
|
11
|
+
* 不共享分支、不互相依赖。后端调用与编排在 src/services/deploy/modern/。
|
|
12
|
+
*/
|
|
13
|
+
function registerDeployCommandsModern(program) {
|
|
14
|
+
const deployCmd = program
|
|
15
|
+
.command('deploy')
|
|
16
|
+
.description('触发 modern 应用发布:本地构建 + 本地部署(preRelease + localPublish)')
|
|
17
|
+
.option('--dir <path>', '项目目录', '.')
|
|
18
|
+
.option('--skip-build', '跳过 build 步骤(已构建好时使用)', false)
|
|
19
|
+
.addHelpText('after', `
|
|
20
|
+
不要用异步模式或后台模式调用 deploy,否则调用可能提前结束,Agent 会误判发布已完成。
|
|
21
|
+
|
|
22
|
+
前置要求
|
|
23
|
+
- 项目已 init(.spark/meta.json 含 stack)
|
|
24
|
+
- MIAODA_APP_ID 已设置(应用身份从 env 读,不再从 meta.json 读)
|
|
25
|
+
- node_modules 已安装
|
|
26
|
+
- package.json 含 build script
|
|
27
|
+
- 沙箱内预装 tosutil(用于把构建产物上传到 TOS)
|
|
28
|
+
|
|
29
|
+
流程概览(stderr 进度提示)
|
|
30
|
+
1. prepareContext 2. preRelease 3. build
|
|
31
|
+
4. createLocalRelease 5. uploadArtifacts
|
|
32
|
+
6. savePluginInstances(扫描 dist/output_capabilities/*.json 批量注册)
|
|
33
|
+
7. finalizeLocalRelease(Finished|Failed)
|
|
34
|
+
|
|
35
|
+
JSON 输出(stdout)
|
|
36
|
+
{"data": {"appId": "...", "version": <n>, "url": "...", "releaseID": "...", "preReleaseID": "..."}}
|
|
37
|
+
|
|
38
|
+
示例
|
|
39
|
+
$ miaoda deploy
|
|
40
|
+
$ miaoda deploy --dir ./my-app
|
|
41
|
+
$ miaoda deploy --skip-build
|
|
42
|
+
`);
|
|
43
|
+
deployCmd.action((0, shared_1.withHelp)(deployCmd, async (rawOpts) => {
|
|
44
|
+
await (0, modern_1.handleDeployModern)({
|
|
45
|
+
dir: rawOpts.dir ?? '.',
|
|
46
|
+
appId: (0, shared_1.resolveAppId)({}),
|
|
47
|
+
skipBuild: rawOpts.skipBuild,
|
|
48
|
+
});
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
@@ -1,15 +1,78 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveScene = resolveScene;
|
|
3
4
|
exports.registerCommands = registerCommands;
|
|
4
5
|
const index_1 = require("../../cli/commands/file/index");
|
|
5
6
|
const index_2 = require("../../cli/commands/db/index");
|
|
6
7
|
const index_3 = require("../../cli/commands/observability/index");
|
|
7
8
|
const index_4 = require("../../cli/commands/app/index");
|
|
8
9
|
const index_5 = require("../../cli/commands/deploy/index");
|
|
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>/ 子目录。
|
|
20
|
+
function resolveScene(appType, _archType) {
|
|
21
|
+
if (appType === '7')
|
|
22
|
+
return 'modern';
|
|
23
|
+
if (appType === '3')
|
|
24
|
+
return 'application';
|
|
25
|
+
if (appType === '4')
|
|
26
|
+
return 'design';
|
|
27
|
+
return 'default';
|
|
28
|
+
}
|
|
29
|
+
const SCENE_REGISTRARS = {
|
|
30
|
+
default: (p) => {
|
|
31
|
+
// init / upgrade / skills 都挂出来:本地用户不需要 export MIAODA_APP_TYPE=3
|
|
32
|
+
// 就能跑 `miaoda app init` / `miaoda app upgrade` / `miaoda skills sync`。
|
|
33
|
+
// 其它 scene 的差异(design 裁 db/file,modern 拆 deploy)仍按 MIAODA_APP_TYPE 路由
|
|
34
|
+
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
35
|
+
(0, index_5.registerDeployCommands)(p);
|
|
36
|
+
(0, index_2.registerDbCommands)(p);
|
|
37
|
+
(0, index_1.registerFileCommands)(p);
|
|
38
|
+
(0, index_3.registerObservabilityCommands)(p);
|
|
39
|
+
(0, index_6.registerSkillsCommands)(p);
|
|
40
|
+
},
|
|
41
|
+
modern: (p) => {
|
|
42
|
+
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
43
|
+
(0, modern_1.registerDeployCommandsModern)(p);
|
|
44
|
+
(0, index_6.registerSkillsCommands)(p);
|
|
45
|
+
},
|
|
46
|
+
// application scene(AppType_APPLICATION=3):
|
|
47
|
+
// 在 default 命令集基础上加 skills(按 meta.json.stack 拉对应 stack 技能)
|
|
48
|
+
// + app init(新一代应用走 init 写 .spark/meta.json)
|
|
49
|
+
application: (p) => {
|
|
50
|
+
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
51
|
+
(0, index_5.registerDeployCommands)(p);
|
|
52
|
+
(0, index_2.registerDbCommands)(p);
|
|
53
|
+
(0, index_1.registerFileCommands)(p);
|
|
54
|
+
(0, index_3.registerObservabilityCommands)(p);
|
|
55
|
+
(0, index_6.registerSkillsCommands)(p);
|
|
56
|
+
},
|
|
57
|
+
// design scene(AppType_DESIGN=4):design-stack 仅 SSR 渲染、无后端业务逻辑、
|
|
58
|
+
// 无数据库、无 UGC 文件。命令集裁掉 db / file,保留 deploy / observability / app(init) / skills。
|
|
59
|
+
design: (p) => {
|
|
60
|
+
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
61
|
+
(0, index_5.registerDeployCommands)(p);
|
|
62
|
+
(0, index_3.registerObservabilityCommands)(p);
|
|
63
|
+
(0, index_6.registerSkillsCommands)(p);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
function readEnv(name) {
|
|
67
|
+
const v = process.env[name]?.trim();
|
|
68
|
+
return v !== undefined && v !== '' ? v : undefined;
|
|
69
|
+
}
|
|
9
70
|
function registerCommands(program) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
(
|
|
13
|
-
(
|
|
14
|
-
(
|
|
71
|
+
const appType = readEnv('MIAODA_APP_TYPE');
|
|
72
|
+
const archType = readEnv('MIAODA_APP_ARCH_TYPE');
|
|
73
|
+
const scene = resolveScene(appType, archType);
|
|
74
|
+
SCENE_REGISTRARS[scene](program);
|
|
75
|
+
if (process.env.MIAODA_VERBOSE === '1' || process.argv.includes('--verbose')) {
|
|
76
|
+
process.stderr.write(`[miaoda] scene=${scene} app_type=${appType ?? '-'} arch_type=${archType ?? '-'}\n`);
|
|
77
|
+
}
|
|
15
78
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
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 或指定版本)到 user app')
|
|
25
|
+
.argument('[version]', 'coding-steering 包版本或 dist-tag,缺省 latest')
|
|
26
|
+
.option('--dir <path>', '项目目录,默认当前目录', '.')
|
|
27
|
+
.option('--local', '走本地 dev / agent 输出形态:拷到 .agents/skills 平铺 + 创建 .claude/skills 软链。' +
|
|
28
|
+
'不传时退回老形态:拷到 .agent/skills/steering/<stack>/skills/(跟沙箱端 update-skills.sh 对齐)', false)
|
|
29
|
+
.addHelpText('after', `
|
|
30
|
+
前置要求
|
|
31
|
+
当前目录(或 --dir)已走过 'miaoda app init'(.spark/meta.json 含 stack)
|
|
32
|
+
|
|
33
|
+
输出形态(--local 切换)
|
|
34
|
+
默认(不传 --local):
|
|
35
|
+
.agent/skills/steering/<stack>/skills/<skill>/...
|
|
36
|
+
.agent/skills/steering/<stack>/tech.md
|
|
37
|
+
(老链路,沙箱端 update-skills.sh 也输出这套结构)
|
|
38
|
+
|
|
39
|
+
传 --local:
|
|
40
|
+
.agents/skills/<skill>/... ← 平铺,无 stack 命名空间
|
|
41
|
+
.agents/tech.md
|
|
42
|
+
.claude/skills → ../.agents/skills(软链,让 Claude Code 识别同一份)
|
|
43
|
+
|
|
44
|
+
JSON 输出
|
|
45
|
+
{"data": {"stack": "...", "version": "...", "syncedSkills": [...], "techSynced": true|false,
|
|
46
|
+
"claudeSkillsLink": "created|updated|noop|conflict" // 仅 --local 时}}
|
|
47
|
+
|
|
48
|
+
示例
|
|
49
|
+
$ miaoda skills sync
|
|
50
|
+
$ miaoda skills sync --local # 本地 dev / agent 用
|
|
51
|
+
$ miaoda skills sync 0.2.0
|
|
52
|
+
$ miaoda skills sync --dir ./my-app
|
|
53
|
+
`);
|
|
54
|
+
cmd.action((0, shared_1.withHelp)(cmd, async (version, rawOpts) => {
|
|
55
|
+
await (0, index_1.handleSkillsSync)({
|
|
56
|
+
dir: rawOpts.dir,
|
|
57
|
+
version,
|
|
58
|
+
local: rawOpts.local,
|
|
59
|
+
});
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
function registerSkillsStatus(parent) {
|
|
63
|
+
const cmd = parent
|
|
64
|
+
.command('status')
|
|
65
|
+
.description('查看本地 .agent/steering/ 的当前状态(不联网)')
|
|
66
|
+
.option('--dir <path>', '项目目录,默认当前目录', '.')
|
|
67
|
+
.addHelpText('after', `
|
|
68
|
+
JSON 输出
|
|
69
|
+
{"data": {"present": true|false, "skills": [...], "techSynced": true|false}}
|
|
70
|
+
|
|
71
|
+
示例
|
|
72
|
+
$ miaoda skills status
|
|
73
|
+
`);
|
|
74
|
+
cmd.action((0, shared_1.withHelp)(cmd, async (rawOpts) => {
|
|
75
|
+
await (0, index_1.handleSkillsStatus)({
|
|
76
|
+
dir: rawOpts.dir,
|
|
77
|
+
});
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleAppUpdate = exports.handleAppGet = void 0;
|
|
3
|
+
exports.SUPPORTED_STACKS = exports.handleAppUpgrade = 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
|
+
var init_1 = require("./init");
|
|
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; } });
|
|
12
|
+
Object.defineProperty(exports, "handleAppUpgrade", { enumerable: true, get: function () { return sync_1.handleAppUpgrade; } });
|
|
13
|
+
// commands 层渲染 help 时需要这份枚举;从 handler barrel 转发,避免 commands → services 越界
|
|
14
|
+
var index_1 = require("../../../services/app/init/index");
|
|
15
|
+
Object.defineProperty(exports, "SUPPORTED_STACKS", { enumerable: true, get: function () { return index_1.SUPPORTED_STACKS; } });
|