@lark-apaas/miaoda-cli 0.1.3 → 0.1.4-alpha.8b6506a
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/app/api.js +3 -3
- package/dist/api/app/schemas.js +43 -43
- package/dist/api/db/api.js +398 -55
- package/dist/api/db/client.js +155 -28
- package/dist/api/db/index.js +12 -1
- package/dist/api/db/parsers.js +20 -20
- package/dist/api/db/sql-keywords.js +87 -87
- package/dist/api/deploy/api.js +5 -5
- package/dist/api/deploy/index.js +12 -1
- package/dist/api/deploy/modern-types.js +23 -0
- package/dist/api/deploy/modern.js +70 -0
- package/dist/api/deploy/plugin-instances-types.js +6 -0
- package/dist/api/deploy/plugin-instances.js +30 -0
- package/dist/api/deploy/schemas.js +32 -32
- package/dist/api/file/api.js +89 -87
- package/dist/api/file/client.js +62 -22
- package/dist/api/file/detect.js +3 -3
- package/dist/api/file/index.js +2 -1
- package/dist/api/file/parsers.js +18 -7
- package/dist/api/observability/api.js +6 -6
- package/dist/api/observability/schemas.js +14 -14
- package/dist/api/plugin/api.js +31 -31
- package/dist/cli/commands/app/index.js +94 -13
- package/dist/cli/commands/db/index.js +602 -54
- package/dist/cli/commands/deploy/index.js +28 -28
- package/dist/cli/commands/deploy/modern.js +48 -0
- package/dist/cli/commands/file/index.js +85 -58
- package/dist/cli/commands/index.js +33 -5
- package/dist/cli/commands/observability/index.js +69 -69
- package/dist/cli/commands/plugin/index.js +27 -27
- package/dist/cli/commands/shared.js +10 -10
- package/dist/cli/commands/skills/index.js +63 -0
- package/dist/cli/handlers/app/index.js +6 -1
- package/dist/cli/handlers/app/init.js +84 -0
- package/dist/cli/handlers/app/update.js +2 -2
- package/dist/cli/handlers/db/_destructive.js +67 -0
- package/dist/cli/handlers/db/_env.js +26 -0
- package/dist/cli/handlers/db/_operator.js +35 -0
- package/dist/cli/handlers/db/audit.js +383 -0
- package/dist/cli/handlers/db/changelog.js +160 -0
- package/dist/cli/handlers/db/data.js +32 -31
- package/dist/cli/handlers/db/index.js +17 -1
- package/dist/cli/handlers/db/migration.js +234 -0
- package/dist/cli/handlers/db/quota.js +68 -0
- package/dist/cli/handlers/db/recovery.js +413 -0
- package/dist/cli/handlers/db/schema.js +33 -33
- package/dist/cli/handlers/db/sql.js +69 -69
- package/dist/cli/handlers/deploy/deploy.js +4 -4
- package/dist/cli/handlers/deploy/error-log.js +1 -1
- package/dist/cli/handlers/deploy/get.js +3 -3
- package/dist/cli/handlers/deploy/modern.js +32 -0
- package/dist/cli/handlers/deploy/polling.js +11 -11
- package/dist/cli/handlers/file/cp.js +30 -30
- package/dist/cli/handlers/file/index.js +3 -1
- package/dist/cli/handlers/file/ls.js +5 -5
- package/dist/cli/handlers/file/quota.js +66 -0
- package/dist/cli/handlers/file/rm.js +32 -30
- package/dist/cli/handlers/file/sign.js +3 -3
- package/dist/cli/handlers/file/stat.js +10 -9
- package/dist/cli/handlers/observability/analytics.js +47 -47
- package/dist/cli/handlers/observability/helpers.js +2 -2
- package/dist/cli/handlers/observability/log.js +9 -9
- package/dist/cli/handlers/observability/metric.js +26 -26
- package/dist/cli/handlers/observability/trace.js +5 -5
- package/dist/cli/handlers/plugin/plugin-local.js +53 -53
- package/dist/cli/handlers/plugin/plugin.js +15 -15
- 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/cli/help.js +16 -16
- package/dist/main.js +12 -12
- package/dist/services/app/init/index.js +12 -0
- package/dist/services/app/init/install.js +101 -0
- package/dist/services/app/init/template.js +85 -0
- package/dist/services/deploy/modern/atoms/build.js +54 -0
- package/dist/services/deploy/modern/atoms/context.js +30 -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 +205 -0
- package/dist/services/deploy/modern/check.js +58 -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 +43 -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 +29 -0
- package/dist/services/skills/index.js +5 -0
- package/dist/services/skills/status.js +37 -0
- package/dist/utils/args.js +1 -1
- package/dist/utils/coding-steering.js +84 -0
- package/dist/utils/colors.js +2 -2
- package/dist/utils/config.js +2 -2
- package/dist/utils/devops-error.js +9 -9
- package/dist/utils/error.js +2 -2
- package/dist/utils/git.js +4 -4
- package/dist/utils/http.js +28 -26
- package/dist/utils/index.js +3 -1
- package/dist/utils/npm-pack.js +55 -0
- package/dist/utils/output.js +67 -45
- package/dist/utils/poll.js +35 -0
- package/dist/utils/render.js +27 -27
- package/dist/utils/spark-meta.js +42 -0
- package/dist/utils/spinner.js +46 -0
- package/dist/utils/time.js +47 -42
- package/package.json +1 -1
|
@@ -16,12 +16,12 @@ const COMMON_TIME_HELP = `
|
|
|
16
16
|
`;
|
|
17
17
|
function registerObservabilityCommands(program) {
|
|
18
18
|
const obCmd = program
|
|
19
|
-
.command(
|
|
20
|
-
.description(
|
|
19
|
+
.command('observability')
|
|
20
|
+
.description('可观测性:查询线上日志、链路、监控指标、运营指标');
|
|
21
21
|
obCmd.action(() => {
|
|
22
22
|
obCmd.outputHelp();
|
|
23
23
|
});
|
|
24
|
-
obCmd.addHelpText(
|
|
24
|
+
obCmd.addHelpText('after', `
|
|
25
25
|
作用范围
|
|
26
26
|
仅供 Agent 在妙搭沙箱内调用,查询当前应用的线上观测数据。所有命令为只读。
|
|
27
27
|
应用上下文:--app-id <id> 或环境变量 MIAODA_APP_ID。
|
|
@@ -37,26 +37,26 @@ function registerObservabilityCommands(program) {
|
|
|
37
37
|
// ── log ──
|
|
38
38
|
function registerLog(parent) {
|
|
39
39
|
const cmd = parent
|
|
40
|
-
.command(
|
|
41
|
-
.description(
|
|
40
|
+
.command('log')
|
|
41
|
+
.description('查询线上运行日志(按时间倒序,分页)')
|
|
42
42
|
.addOption((0, shared_1.appIdOption)().hideHelp())
|
|
43
|
-
.addOption(new commander_1.Option(
|
|
44
|
-
.choices([
|
|
45
|
-
.argParser((0, shared_1.caseInsensitiveChoice)([
|
|
46
|
-
.option(
|
|
47
|
-
.option(
|
|
48
|
-
.option(
|
|
49
|
-
.option(
|
|
50
|
-
.option(
|
|
51
|
-
.option(
|
|
52
|
-
.option(
|
|
53
|
-
.option(
|
|
54
|
-
.option(
|
|
55
|
-
.option(
|
|
56
|
-
.option(
|
|
57
|
-
.option(
|
|
58
|
-
.option(
|
|
59
|
-
.addHelpText(
|
|
43
|
+
.addOption(new commander_1.Option('--level <level>', '日志级别(大小写不敏感)')
|
|
44
|
+
.choices(['DEBUG', 'INFO', 'WARN', 'ERROR'])
|
|
45
|
+
.argParser((0, shared_1.caseInsensitiveChoice)(['DEBUG', 'INFO', 'WARN', 'ERROR'])))
|
|
46
|
+
.option('--since <time>', '开始时间')
|
|
47
|
+
.option('--until <time>', '截止时间')
|
|
48
|
+
.option('--log-id <id>', '按请求 logid 过滤(attributes.ob_data_id)')
|
|
49
|
+
.option('--trace-id <id>', '按 trace ID 过滤')
|
|
50
|
+
.option('--grep <pattern>', '按关键字模糊搜索 body')
|
|
51
|
+
.option('--module <name>', '按模块名过滤')
|
|
52
|
+
.option('--user-id <user-id>', '按触发用户 ID 过滤')
|
|
53
|
+
.option('--page <path>', '按页面路径过滤')
|
|
54
|
+
.option('--api <path>', '按接口路径过滤')
|
|
55
|
+
.option('--min-duration <ms>', '最小耗时过滤(毫秒)')
|
|
56
|
+
.option('--max-duration <ms>', '最大耗时过滤(毫秒)')
|
|
57
|
+
.option('--limit <n>', '返回条数上限(1~100)', parseLimit, 50)
|
|
58
|
+
.option('--cursor <token>', '下一页游标,从上一次返回的 next_cursor 取值')
|
|
59
|
+
.addHelpText('after', `${COMMON_TIME_HELP}
|
|
60
60
|
JSON 输出
|
|
61
61
|
{"data": [...], "next_cursor": "...", "has_more": true|false}
|
|
62
62
|
|
|
@@ -67,8 +67,8 @@ JSON 输出
|
|
|
67
67
|
$ miaoda observability log --api /api/orders --min-duration 200 --json
|
|
68
68
|
`);
|
|
69
69
|
cmd.action((0, shared_1.withHelp)(cmd, async (rawOpts) => {
|
|
70
|
-
(0, shared_1.validateTimeOptions)(rawOpts,
|
|
71
|
-
(0, shared_1.rejectCliOverride)(cmd,
|
|
70
|
+
(0, shared_1.validateTimeOptions)(rawOpts, 'since', 'until');
|
|
71
|
+
(0, shared_1.rejectCliOverride)(cmd, 'appId');
|
|
72
72
|
await (0, index_1.handleObservabilityLog)({
|
|
73
73
|
appId: (0, shared_1.resolveAppId)({ appId: rawOpts.appId }),
|
|
74
74
|
level: rawOpts.level,
|
|
@@ -90,22 +90,22 @@ JSON 输出
|
|
|
90
90
|
}
|
|
91
91
|
// ── trace ──
|
|
92
92
|
function registerTrace(parent) {
|
|
93
|
-
const traceCmd = parent.command(
|
|
93
|
+
const traceCmd = parent.command('trace').description('链路追踪:列表 / 详情');
|
|
94
94
|
traceCmd.action(() => {
|
|
95
95
|
traceCmd.outputHelp();
|
|
96
96
|
});
|
|
97
97
|
const listCmd = traceCmd
|
|
98
|
-
.command(
|
|
99
|
-
.description(
|
|
98
|
+
.command('list')
|
|
99
|
+
.description('查询线上链路列表(按链路时间倒序,分页)')
|
|
100
100
|
.addOption((0, shared_1.appIdOption)().hideHelp())
|
|
101
|
-
.option(
|
|
102
|
-
.option(
|
|
103
|
-
.option(
|
|
104
|
-
.option(
|
|
105
|
-
.option(
|
|
106
|
-
.option(
|
|
107
|
-
.option(
|
|
108
|
-
.addHelpText(
|
|
101
|
+
.option('--since <time>', '开始时间')
|
|
102
|
+
.option('--until <time>', '截止时间')
|
|
103
|
+
.option('--trace-id <id>', '按 trace ID 过滤')
|
|
104
|
+
.option('--root-span <span-name>', '按入口节点关键词过滤')
|
|
105
|
+
.option('--user-id <user-id>', '按触发用户 ID 过滤')
|
|
106
|
+
.option('--limit <n>', '返回条数上限(1~100)', parseLimit, 50)
|
|
107
|
+
.option('--cursor <token>', '下一页游标')
|
|
108
|
+
.addHelpText('after', `${COMMON_TIME_HELP}
|
|
109
109
|
JSON 输出
|
|
110
110
|
{"data": [...], "next_cursor": "...", "has_more": true|false}
|
|
111
111
|
|
|
@@ -114,8 +114,8 @@ JSON 输出
|
|
|
114
114
|
$ miaoda observability trace list --root-span api-gateway --limit 20 --json
|
|
115
115
|
`);
|
|
116
116
|
listCmd.action((0, shared_1.withHelp)(listCmd, async (rawOpts) => {
|
|
117
|
-
(0, shared_1.validateTimeOptions)(rawOpts,
|
|
118
|
-
(0, shared_1.rejectCliOverride)(listCmd,
|
|
117
|
+
(0, shared_1.validateTimeOptions)(rawOpts, 'since', 'until');
|
|
118
|
+
(0, shared_1.rejectCliOverride)(listCmd, 'appId');
|
|
119
119
|
await (0, index_1.handleObservabilityTraceList)({
|
|
120
120
|
appId: (0, shared_1.resolveAppId)({ appId: rawOpts.appId }),
|
|
121
121
|
since: rawOpts.since,
|
|
@@ -128,12 +128,12 @@ JSON 输出
|
|
|
128
128
|
});
|
|
129
129
|
}));
|
|
130
130
|
const getCmd = traceCmd
|
|
131
|
-
.command(
|
|
132
|
-
.description(
|
|
133
|
-
.argument(
|
|
131
|
+
.command('get')
|
|
132
|
+
.description('查询指定链路的完整详情')
|
|
133
|
+
.argument('<trace-id>', '链路 ID')
|
|
134
134
|
.addOption((0, shared_1.appIdOption)().hideHelp())
|
|
135
|
-
.option(
|
|
136
|
-
.addHelpText(
|
|
135
|
+
.option('--with-log-severity-count', '返回每个 Span 各日志级别的数量', false)
|
|
136
|
+
.addHelpText('after', `
|
|
137
137
|
JSON 输出
|
|
138
138
|
{"data": {"spans": [...], "isBreak": false}}
|
|
139
139
|
|
|
@@ -146,7 +146,7 @@ JSON 输出
|
|
|
146
146
|
hint: 检查 trace-id 是否正确,或链路已超出保留时长
|
|
147
147
|
`);
|
|
148
148
|
getCmd.action((0, shared_1.withHelp)(getCmd, async (traceId, rawOpts) => {
|
|
149
|
-
(0, shared_1.rejectCliOverride)(getCmd,
|
|
149
|
+
(0, shared_1.rejectCliOverride)(getCmd, 'appId');
|
|
150
150
|
await (0, index_1.handleObservabilityTraceGet)({
|
|
151
151
|
traceId,
|
|
152
152
|
appId: (0, shared_1.resolveAppId)({ appId: rawOpts.appId }),
|
|
@@ -157,20 +157,20 @@ JSON 输出
|
|
|
157
157
|
// ── metric ──
|
|
158
158
|
function registerMetric(parent) {
|
|
159
159
|
const cmd = parent
|
|
160
|
-
.command(
|
|
161
|
-
.description(
|
|
162
|
-
.argument(
|
|
160
|
+
.command('metric')
|
|
161
|
+
.description('查询监控指标:requests / latency / cpu / memory')
|
|
162
|
+
.argument('<metric-name>', '指标名:requests | latency | cpu | memory')
|
|
163
163
|
.addOption((0, shared_1.appIdOption)().hideHelp())
|
|
164
|
-
.option(
|
|
165
|
-
.option(
|
|
166
|
-
.option(
|
|
167
|
-
.option(
|
|
168
|
-
.option(
|
|
169
|
-
.addOption(new commander_1.Option(
|
|
170
|
-
.choices([
|
|
171
|
-
.argParser((0, shared_1.caseInsensitiveChoice)([
|
|
172
|
-
.default(
|
|
173
|
-
.addHelpText(
|
|
164
|
+
.option('--page <path>', '按页面路径过滤(仅对 requests/latency 生效)')
|
|
165
|
+
.option('--api <path>', '按接口路径过滤(仅对 requests/latency 生效)')
|
|
166
|
+
.option('--series <name>', '过滤图表中的某条线:latency 取 p50/p99;requests 取 total/error;缺省返回所有相关线')
|
|
167
|
+
.option('--since <time>', '开始时间')
|
|
168
|
+
.option('--until <time>', '截止时间')
|
|
169
|
+
.addOption(new commander_1.Option('--down-sample <duration>', '降采样粒度(1m=1分钟 / 1h=1小时 / 1d=1天,大小写不敏感)')
|
|
170
|
+
.choices(['1m', '1h', '1d'])
|
|
171
|
+
.argParser((0, shared_1.caseInsensitiveChoice)(['1m', '1h', '1d']))
|
|
172
|
+
.default('1m'))
|
|
173
|
+
.addHelpText('after', `${COMMON_TIME_HELP}
|
|
174
174
|
JSON 输出
|
|
175
175
|
{"data": [{"metricName": "...", "dimensions": {...}, "dataPoints": [...]}], "next_cursor": null, "has_more": false}
|
|
176
176
|
|
|
@@ -181,8 +181,8 @@ JSON 输出
|
|
|
181
181
|
$ miaoda observability metric cpu --since 1d --down-sample 1d --json
|
|
182
182
|
`);
|
|
183
183
|
cmd.action((0, shared_1.withHelp)(cmd, async (metricName, rawOpts) => {
|
|
184
|
-
(0, shared_1.validateTimeOptions)(rawOpts,
|
|
185
|
-
(0, shared_1.rejectCliOverride)(cmd,
|
|
184
|
+
(0, shared_1.validateTimeOptions)(rawOpts, 'since', 'until');
|
|
185
|
+
(0, shared_1.rejectCliOverride)(cmd, 'appId');
|
|
186
186
|
await (0, index_1.handleObservabilityMetric)({
|
|
187
187
|
metricName,
|
|
188
188
|
appId: (0, shared_1.resolveAppId)({ appId: rawOpts.appId }),
|
|
@@ -198,16 +198,16 @@ JSON 输出
|
|
|
198
198
|
// ── analytics ──
|
|
199
199
|
function registerAnalytics(parent) {
|
|
200
200
|
const cmd = parent
|
|
201
|
-
.command(
|
|
202
|
-
.description(
|
|
203
|
-
.argument(
|
|
201
|
+
.command('analytics')
|
|
202
|
+
.description('查询运营指标:users(用户数)/ page-view(页面访问)')
|
|
203
|
+
.argument('<analytics-name>', '指标名:users | page-view')
|
|
204
204
|
.addOption((0, shared_1.appIdOption)().hideHelp())
|
|
205
|
-
.option(
|
|
206
|
-
.option(
|
|
207
|
-
.option(
|
|
208
|
-
.option(
|
|
209
|
-
.option(
|
|
210
|
-
.addHelpText(
|
|
205
|
+
.option('--page <path>', '按页面路径过滤(仅对 page-view 生效)')
|
|
206
|
+
.option('--series <name>', '过滤图表中的某条线:users 取 active/new/total(兼容 active-users/new-users/total-users);page-view 取 all/desktop/mobile(兼容 all-view/desktop-view/mobile-view)')
|
|
207
|
+
.option('--since <time>', '开始时间')
|
|
208
|
+
.option('--until <time>', '截止时间')
|
|
209
|
+
.option('--granularity <duration>', '时间粒度:day | week | month', 'day')
|
|
210
|
+
.addHelpText('after', `${COMMON_TIME_HELP}
|
|
211
211
|
JSON 输出
|
|
212
212
|
{"data": [{"metricType": "...", "points": [{"timestampNs": "...", "value": ..., "dimensions": {...}}]}], "next_cursor": null, "has_more": false}
|
|
213
213
|
|
|
@@ -217,8 +217,8 @@ JSON 输出
|
|
|
217
217
|
$ miaoda observability analytics page-view --granularity week --json
|
|
218
218
|
`);
|
|
219
219
|
cmd.action((0, shared_1.withHelp)(cmd, async (analyticsName, rawOpts) => {
|
|
220
|
-
(0, shared_1.validateTimeOptions)(rawOpts,
|
|
221
|
-
(0, shared_1.rejectCliOverride)(cmd,
|
|
220
|
+
(0, shared_1.validateTimeOptions)(rawOpts, 'since', 'until');
|
|
221
|
+
(0, shared_1.rejectCliOverride)(cmd, 'appId');
|
|
222
222
|
await (0, index_1.handleObservabilityAnalytics)({
|
|
223
223
|
analyticsName,
|
|
224
224
|
appId: (0, shared_1.resolveAppId)({ appId: rawOpts.appId }),
|
|
@@ -4,13 +4,13 @@ exports.registerPluginCommands = registerPluginCommands;
|
|
|
4
4
|
const index_1 = require("../../../cli/handlers/plugin/index");
|
|
5
5
|
function registerPluginCommands(program) {
|
|
6
6
|
const pluginCmd = program
|
|
7
|
-
.command(
|
|
8
|
-
.description(
|
|
9
|
-
.usage(
|
|
7
|
+
.command('plugin')
|
|
8
|
+
.description('插件管理:安装/更新/移除插件包,查询 capability 实例')
|
|
9
|
+
.usage('<command> [flags]');
|
|
10
10
|
pluginCmd.action(() => {
|
|
11
11
|
pluginCmd.outputHelp();
|
|
12
12
|
});
|
|
13
|
-
pluginCmd.addHelpText(
|
|
13
|
+
pluginCmd.addHelpText('after', `
|
|
14
14
|
概念
|
|
15
15
|
- 插件包 (plugin package):.tgz 包,释放到 ./node_modules/<name>
|
|
16
16
|
- actionPlugins:./package.json 里的字段,记录 { "@scope/name": "version" },作为
|
|
@@ -26,10 +26,10 @@ function registerPluginCommands(program) {
|
|
|
26
26
|
- remove / list / list-packages:纯本地 FS,不走网络
|
|
27
27
|
`);
|
|
28
28
|
pluginCmd
|
|
29
|
-
.command(
|
|
30
|
-
.description(
|
|
31
|
-
.argument(
|
|
32
|
-
.addHelpText(
|
|
29
|
+
.command('install')
|
|
30
|
+
.description('拉取插件包并安装到当前应用项目')
|
|
31
|
+
.argument('<names...>', '插件名,格式 @scope/name 或 @scope/name@version;未带版本默认 latest')
|
|
32
|
+
.addHelpText('after', `
|
|
33
33
|
行为
|
|
34
34
|
- 拉取 .tgz 到本地缓存,解压到 ./node_modules/<name>
|
|
35
35
|
- 在 ./package.json 的 actionPlugins 字段记录 <name>: <version>
|
|
@@ -62,10 +62,10 @@ JSON 输出
|
|
|
62
62
|
await (0, index_1.handlePluginInstall)({ names });
|
|
63
63
|
});
|
|
64
64
|
pluginCmd
|
|
65
|
-
.command(
|
|
66
|
-
.description(
|
|
67
|
-
.argument(
|
|
68
|
-
.addHelpText(
|
|
65
|
+
.command('update')
|
|
66
|
+
.description('把已安装插件升级到 latest 版本')
|
|
67
|
+
.argument('<names...>', '插件名,格式 @scope/name;带 @version 也只取 name 部分')
|
|
68
|
+
.addHelpText('after', `
|
|
69
69
|
行为
|
|
70
70
|
- 仅对已在 actionPlugins 里的插件生效;未安装的插件返回 notInstalled
|
|
71
71
|
- 拉取 latest 版本 .tgz,覆盖安装到 ./node_modules/<name>
|
|
@@ -97,10 +97,10 @@ JSON 输出
|
|
|
97
97
|
await (0, index_1.handlePluginUpdate)({ names });
|
|
98
98
|
});
|
|
99
99
|
pluginCmd
|
|
100
|
-
.command(
|
|
101
|
-
.description(
|
|
102
|
-
.argument(
|
|
103
|
-
.addHelpText(
|
|
100
|
+
.command('remove')
|
|
101
|
+
.description('从当前项目移除一个已安装的插件')
|
|
102
|
+
.argument('<name>', '插件名,格式 @scope/name')
|
|
103
|
+
.addHelpText('after', `
|
|
104
104
|
行为
|
|
105
105
|
- 删除 ./node_modules/<name> 目录
|
|
106
106
|
- 从 ./package.json 的 actionPlugins 字段移除对应条目
|
|
@@ -123,9 +123,9 @@ JSON 输出
|
|
|
123
123
|
(0, index_1.handlePluginRemove)({ name });
|
|
124
124
|
});
|
|
125
125
|
pluginCmd
|
|
126
|
-
.command(
|
|
127
|
-
.description(
|
|
128
|
-
.addHelpText(
|
|
126
|
+
.command('init')
|
|
127
|
+
.description('按 package.json 的 actionPlugins 批量安装所有插件')
|
|
128
|
+
.addHelpText('after', `
|
|
129
129
|
行为
|
|
130
130
|
- 读取 ./package.json 的 actionPlugins,对每个条目按固定版本安装
|
|
131
131
|
- 已经是目标版本的跳过(幂等),用于 clone 项目后首次同步 / CI
|
|
@@ -156,11 +156,11 @@ JSON 输出
|
|
|
156
156
|
await (0, index_1.handlePluginInit)();
|
|
157
157
|
});
|
|
158
158
|
pluginCmd
|
|
159
|
-
.command(
|
|
160
|
-
.description(
|
|
161
|
-
.option(
|
|
162
|
-
.option(
|
|
163
|
-
.addHelpText(
|
|
159
|
+
.command('list')
|
|
160
|
+
.description('列出当前项目的 capability 实例(./server/capabilities/*.json)')
|
|
161
|
+
.option('--summary', '不 hydrate(不充血),直接返回 capability 文件的原始 JSON')
|
|
162
|
+
.option('--id <id>', '只查询指定 id 的单个 capability')
|
|
163
|
+
.addHelpText('after', `
|
|
164
164
|
行为
|
|
165
165
|
- 扫描 ./server/capabilities/*.json(排除 capabilities.json)
|
|
166
166
|
- 默认对每条 capability 做 hydrate:读取 ./node_modules/<pluginKey>/manifest.json,
|
|
@@ -190,9 +190,9 @@ JSON 输出
|
|
|
190
190
|
await (0, index_1.handlePluginList)(opts);
|
|
191
191
|
});
|
|
192
192
|
pluginCmd
|
|
193
|
-
.command(
|
|
194
|
-
.description(
|
|
195
|
-
.addHelpText(
|
|
193
|
+
.command('list-packages')
|
|
194
|
+
.description('列出 package.json actionPlugins 里已声明的插件包')
|
|
195
|
+
.addHelpText('after', `
|
|
196
196
|
行为
|
|
197
197
|
- 读取 ./package.json 的 actionPlugins 字段
|
|
198
198
|
- 只看声明,不校验 ./node_modules 下是否实际存在
|
|
@@ -16,10 +16,10 @@ const args_1 = require("../../utils/args");
|
|
|
16
16
|
Object.defineProperty(exports, "failArgs", { enumerable: true, get: function () { return args_1.failArgs; } });
|
|
17
17
|
/** --app-id option,需要应用上下文的命令自行 .addOption(appIdOption()) */
|
|
18
18
|
function appIdOption() {
|
|
19
|
-
return new commander_1.Option(
|
|
19
|
+
return new commander_1.Option('--app-id <id>', '指定目标应用').env('MIAODA_APP_ID');
|
|
20
20
|
}
|
|
21
21
|
function branchOption() {
|
|
22
|
-
return new commander_1.Option(
|
|
22
|
+
return new commander_1.Option('--branch <branch>', '分支(优先级:--branch > 当前仓库 HEAD 分支;非 git 目录回退应用默认分支)').env('LOCAL_MOCK_MIAODA_DEPLOY_BRANCH');
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* soft-required: Commander 类型上 optional,runtime 校验必填。
|
|
@@ -36,8 +36,8 @@ function softRequiredOption(name, desc) {
|
|
|
36
36
|
function resolveAppId(opts) {
|
|
37
37
|
const id = opts.appId ?? process.env.MIAODA_APP_ID ?? process.env.app_id;
|
|
38
38
|
if (!id) {
|
|
39
|
-
throw new error_1.AppError(
|
|
40
|
-
next_actions: [
|
|
39
|
+
throw new error_1.AppError('APP_ID_MISSING', '未指定应用', {
|
|
40
|
+
next_actions: ['设置 export MIAODA_APP_ID=<id>'],
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
return id;
|
|
@@ -53,7 +53,7 @@ function withHelp(cmd, handler) {
|
|
|
53
53
|
await handler(...args);
|
|
54
54
|
}
|
|
55
55
|
catch (err) {
|
|
56
|
-
if (err instanceof error_1.AppError && err.code ===
|
|
56
|
+
if (err instanceof error_1.AppError && err.code === 'ARGS_INVALID') {
|
|
57
57
|
process.stderr.write(`Error: ${err.message}\n`);
|
|
58
58
|
cmd.outputHelp();
|
|
59
59
|
process.exitCode = 2;
|
|
@@ -81,7 +81,7 @@ function caseInsensitiveChoice(canonical) {
|
|
|
81
81
|
return (raw) => {
|
|
82
82
|
const hit = map.get(raw.toLowerCase());
|
|
83
83
|
if (hit === undefined) {
|
|
84
|
-
throw new commander_1.InvalidArgumentError(`Allowed choices are ${canonical.join(
|
|
84
|
+
throw new commander_1.InvalidArgumentError(`Allowed choices are ${canonical.join(', ')} (case-insensitive).`);
|
|
85
85
|
}
|
|
86
86
|
return hit;
|
|
87
87
|
};
|
|
@@ -98,8 +98,8 @@ function validateTimeOptions(opts, ...names) {
|
|
|
98
98
|
const value = opts[name];
|
|
99
99
|
if (value === undefined)
|
|
100
100
|
continue;
|
|
101
|
-
if (typeof value !==
|
|
102
|
-
(0, args_1.failArgs)(`--${name.replace(/([A-Z])/g,
|
|
101
|
+
if (typeof value !== 'string') {
|
|
102
|
+
(0, args_1.failArgs)(`--${name.replace(/([A-Z])/g, '-$1').toLowerCase()} 必须是时间字符串`);
|
|
103
103
|
}
|
|
104
104
|
(0, time_1.parseTimeToMs)(value);
|
|
105
105
|
}
|
|
@@ -118,8 +118,8 @@ function validateTimeOptions(opts, ...names) {
|
|
|
118
118
|
*/
|
|
119
119
|
function rejectCliOverride(cmd, ...optNames) {
|
|
120
120
|
for (const name of optNames) {
|
|
121
|
-
if (cmd.getOptionValueSource(name) ===
|
|
122
|
-
const flag =
|
|
121
|
+
if (cmd.getOptionValueSource(name) === 'cli') {
|
|
122
|
+
const flag = '--' + name.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
123
123
|
(0, args_1.failArgs)(`${flag} 由沙箱/本地配置注入,不允许显式传递`);
|
|
124
124
|
}
|
|
125
125
|
}
|
|
@@ -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,7 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleAppUpdate = exports.handleAppGet = void 0;
|
|
3
|
+
exports.SUPPORTED_STACKS = 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
|
+
// commands 层渲染 help 时需要这份枚举;从 handler barrel 转发,避免 commands → services 越界
|
|
11
|
+
var index_1 = require("../../../services/app/init/index");
|
|
12
|
+
Object.defineProperty(exports, "SUPPORTED_STACKS", { enumerable: true, get: function () { return index_1.SUPPORTED_STACKS; } });
|
|
@@ -0,0 +1,84 @@
|
|
|
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.handleAppInit = handleAppInit;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const index_1 = require("../../../services/app/init/index");
|
|
10
|
+
const coding_steering_1 = require("../../../utils/coding-steering");
|
|
11
|
+
const error_1 = require("../../../utils/error");
|
|
12
|
+
const output_1 = require("../../../utils/output");
|
|
13
|
+
/** miaoda app init [--template <stack>] [--conf <json>] */
|
|
14
|
+
async function handleAppInit(opts) {
|
|
15
|
+
await Promise.resolve();
|
|
16
|
+
const targetDir = opts.targetDir ?? process.cwd();
|
|
17
|
+
const metaPath = node_path_1.default.join(targetDir, '.spark', 'meta.json');
|
|
18
|
+
// 幂等:.spark/meta.json 是 init 流程最后才写的,存在即代表"已完整成功一次"。
|
|
19
|
+
// 用 package.json 判幂等会让 install 失败、CWD 留下半渲染状态的应用永远 init 不了。
|
|
20
|
+
if (node_fs_1.default.existsSync(metaPath)) {
|
|
21
|
+
if (!(0, output_1.isJsonMode)()) {
|
|
22
|
+
process.stdout.write(`Already initialized: ${metaPath}\n`);
|
|
23
|
+
}
|
|
24
|
+
(0, output_1.emit)({
|
|
25
|
+
data: {
|
|
26
|
+
initialized: false,
|
|
27
|
+
reason: 'already_initialized',
|
|
28
|
+
targetDir,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const stack = opts.template;
|
|
34
|
+
if (!stack) {
|
|
35
|
+
throw new error_1.AppError('ARGS_INVALID', '缺少 --template <stack>', {
|
|
36
|
+
next_actions: [`可用 stack:${index_1.SUPPORTED_STACKS.join(', ')}`],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (!index_1.SUPPORTED_STACKS.includes(stack)) {
|
|
40
|
+
throw new error_1.AppError('ARGS_INVALID', `不支持的 template: ${stack}`, {
|
|
41
|
+
next_actions: [`可用 stack:${index_1.SUPPORTED_STACKS.join(', ')}`],
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const version = opts.conf?.version;
|
|
45
|
+
const projectName = node_path_1.default.basename(targetDir);
|
|
46
|
+
const tplResult = (0, index_1.renderTemplate)({ stack, version, targetDir, projectName });
|
|
47
|
+
const steeringResult = (0, coding_steering_1.syncCodingSteering)({
|
|
48
|
+
stack,
|
|
49
|
+
targetDir,
|
|
50
|
+
version: opts.conf?.steeringVersion,
|
|
51
|
+
logPrefix: 'init',
|
|
52
|
+
});
|
|
53
|
+
const installResult = (0, index_1.installDependencies)({
|
|
54
|
+
targetDir,
|
|
55
|
+
skip: opts.skipInstall,
|
|
56
|
+
quietStdout: (0, output_1.isJsonMode)(),
|
|
57
|
+
});
|
|
58
|
+
(0, index_1.writeSparkMeta)(targetDir, {
|
|
59
|
+
appId: opts.appId,
|
|
60
|
+
stack,
|
|
61
|
+
version: tplResult.version,
|
|
62
|
+
archType: tplResult.archType,
|
|
63
|
+
});
|
|
64
|
+
if (!(0, output_1.isJsonMode)()) {
|
|
65
|
+
process.stdout.write(`✓ Initialized ${stack} (template ${tplResult.version}, steering ${steeringResult.version}, install ${installResult.source}) in ${targetDir}\n`);
|
|
66
|
+
}
|
|
67
|
+
(0, output_1.emit)({
|
|
68
|
+
data: {
|
|
69
|
+
initialized: true,
|
|
70
|
+
appId: opts.appId,
|
|
71
|
+
template: stack,
|
|
72
|
+
templatePackage: tplResult.packageName,
|
|
73
|
+
templateVersion: tplResult.version,
|
|
74
|
+
steeringVersion: steeringResult.version,
|
|
75
|
+
archType: tplResult.archType,
|
|
76
|
+
syncedSkills: steeringResult.syncedSkills,
|
|
77
|
+
techSynced: steeringResult.techSynced,
|
|
78
|
+
installed: installResult.installed,
|
|
79
|
+
installSource: installResult.source,
|
|
80
|
+
installHash: installResult.hash,
|
|
81
|
+
cacheZip: installResult.cacheZip,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
@@ -41,7 +41,7 @@ const index_1 = require("../../../api/app/index");
|
|
|
41
41
|
/** miaoda app update [--app-id <id>] [--name <n>] [--description <d>] */
|
|
42
42
|
async function handleAppUpdate(opts) {
|
|
43
43
|
if (opts.name === undefined && opts.description === undefined) {
|
|
44
|
-
(0, args_1.failArgs)(
|
|
44
|
+
(0, args_1.failArgs)('至少需要 --name 或 --description 中的一个');
|
|
45
45
|
}
|
|
46
46
|
const appID = opts.appId;
|
|
47
47
|
await api.app.updateAppMeta({
|
|
@@ -53,7 +53,7 @@ async function handleAppUpdate(opts) {
|
|
|
53
53
|
const resp = await api.app.getAppInfo(appID);
|
|
54
54
|
const meta = resp.appInfo?.appMeta ?? {};
|
|
55
55
|
if (!(0, output_1.isJsonMode)()) {
|
|
56
|
-
process.stdout.write(
|
|
56
|
+
process.stdout.write('✓ App updated successfully\n');
|
|
57
57
|
}
|
|
58
58
|
(0, output_1.emit)({ data: meta }, index_1.appMetaSchema);
|
|
59
59
|
}
|