@zhuoyuezs/ml-platform 0.1.1 → 0.1.3
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/DEVELOPMENT.md +96 -9
- package/README.md +89 -38
- package/checksums.json +12 -12
- package/package.json +5 -1
- package/release-policy.json +10 -0
- package/release.json +13 -9
- package/runtime/business-client/README.md +13 -0
- package/runtime/business-client/package-lock.json +2 -2
- package/runtime/business-client/package.json +1 -1
- package/runtime/business-client/src/catalog.js +37 -16
- package/runtime/business-client/src/cli.js +67 -15
- package/scripts/lib.js +98 -4
- package/scripts/main.js +96 -11
- package/skills/feature-management/SKILL.md +37 -8
- package/skills/feature-management/references/commands.md +37 -4
package/scripts/main.js
CHANGED
|
@@ -17,13 +17,29 @@ const BUSINESS_ENTRY = path.resolve(__dirname, "..", "runtime", "business-client
|
|
|
17
17
|
|
|
18
18
|
function usage() {
|
|
19
19
|
return `用法:
|
|
20
|
-
ml-platform install [--
|
|
21
|
-
ml-platform upgrade [
|
|
22
|
-
ml-platform migrate [--
|
|
23
|
-
ml-platform status [--
|
|
24
|
-
ml-platform doctor [
|
|
20
|
+
ml-platform install [--scope user|project] [--json]
|
|
21
|
+
ml-platform upgrade [--scope user|project] [--json]
|
|
22
|
+
ml-platform migrate [--scope user|project] [--json]
|
|
23
|
+
ml-platform status [--scope user|project] [--json]
|
|
24
|
+
ml-platform doctor [--scope user|project] [--api-url URL] [--json]
|
|
25
25
|
ml-platform <business-command> [args]
|
|
26
26
|
|
|
27
|
+
默认安装:
|
|
28
|
+
Codex 用户级 Skill,持久 CLI,简洁输出
|
|
29
|
+
|
|
30
|
+
项目级安装:
|
|
31
|
+
ml-platform install --scope project
|
|
32
|
+
|
|
33
|
+
常用选项:
|
|
34
|
+
--scope user|project Skill 安装范围,默认 user
|
|
35
|
+
--project-dir PATH 项目根目录,project scope 默认使用当前目录
|
|
36
|
+
--json 输出供 Agent 和 CI 解析的 JSON
|
|
37
|
+
--backup-unmanaged 备份目标位置已有的非托管 Skill
|
|
38
|
+
|
|
39
|
+
高级选项:
|
|
40
|
+
--agent codex|pi|custom, --skills-dir PATH, --state-dir PATH, --bin-dir PATH,
|
|
41
|
+
--allow-downgrade, --no-prewarm, --upgrade, --summary
|
|
42
|
+
|
|
27
43
|
安装管理命令:
|
|
28
44
|
install, upgrade, migrate, status, doctor
|
|
29
45
|
|
|
@@ -31,10 +47,70 @@ function usage() {
|
|
|
31
47
|
`;
|
|
32
48
|
}
|
|
33
49
|
|
|
50
|
+
function managementUsage(command) {
|
|
51
|
+
const signatures = {
|
|
52
|
+
install: "install [--scope user|project] [--project-dir PATH] [--json]",
|
|
53
|
+
upgrade: "upgrade [--scope user|project] [--project-dir PATH] [--json]",
|
|
54
|
+
migrate: "migrate [--scope user|project] [--project-dir PATH] [--json]",
|
|
55
|
+
status: "status [--scope user|project] [--project-dir PATH] [--json]",
|
|
56
|
+
doctor: "doctor [--scope user|project] [--project-dir PATH] [--api-url URL] [--json]",
|
|
57
|
+
};
|
|
58
|
+
return `用法: ml-platform ${signatures[command]}\n`;
|
|
59
|
+
}
|
|
60
|
+
|
|
34
61
|
function printJson(payload) {
|
|
35
62
|
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
36
63
|
}
|
|
37
64
|
|
|
65
|
+
function formatSummary(command, payload) {
|
|
66
|
+
if (command === "status") {
|
|
67
|
+
const lines = [`ML Platform: ${payload.installed ? "已安装" : "未安装"}`];
|
|
68
|
+
if (payload.installed_release) lines.push(`Release: ${payload.installed_release}`);
|
|
69
|
+
if (payload.cli?.version) lines.push(`CLI: ${payload.cli.version} (${payload.cli.path})`);
|
|
70
|
+
if (payload.skill?.revision) lines.push(`Skill: ${payload.skill.name}@${payload.skill.revision} (${payload.skill.path})`);
|
|
71
|
+
if (payload.record_error) lines.push(`错误: ${payload.record_error}`);
|
|
72
|
+
return `${lines.join("\n")}\n`;
|
|
73
|
+
}
|
|
74
|
+
if (command === "doctor") {
|
|
75
|
+
if (!Array.isArray(payload.checks)) {
|
|
76
|
+
return `ML Platform 检查失败: ${payload.error || "未知错误"}\n`;
|
|
77
|
+
}
|
|
78
|
+
const failed = payload.checks.filter((check) => check.ok === false);
|
|
79
|
+
const passed = payload.checks.filter((check) => check.ok === true);
|
|
80
|
+
const skipped = payload.checks.filter((check) => check.skipped);
|
|
81
|
+
const lines = [
|
|
82
|
+
`ML Platform 检查: ${payload.ok ? "通过" : "失败"}`,
|
|
83
|
+
`Release: ${payload.release_version || "未知"} CLI: ${payload.cli_version || "未知"}`,
|
|
84
|
+
`检查项: ${passed.length} 通过, ${failed.length} 失败, ${skipped.length} 跳过`,
|
|
85
|
+
];
|
|
86
|
+
const api = payload.checks.find((check) => check.name === "platform_api");
|
|
87
|
+
if (api?.api_url) lines.push(`API: ${api.api_url} (${api.source})`);
|
|
88
|
+
else if (api?.skipped) lines.push(`API: 未配置 (${api.reason})`);
|
|
89
|
+
for (const check of failed) lines.push(`失败: ${check.name} - ${check.error || check.detail || "检查未通过"}`);
|
|
90
|
+
return `${lines.join("\n")}\n`;
|
|
91
|
+
}
|
|
92
|
+
const actionLabels = {
|
|
93
|
+
installed: "安装完成",
|
|
94
|
+
upgraded: "升级完成",
|
|
95
|
+
unchanged: "已是当前版本",
|
|
96
|
+
migrated: "迁移完成",
|
|
97
|
+
};
|
|
98
|
+
const lines = [
|
|
99
|
+
`ML Platform: ${actionLabels[payload.action] || payload.action || (payload.ok ? "完成" : "失败")}`,
|
|
100
|
+
];
|
|
101
|
+
if (payload.release_version) lines.push(`Release: ${payload.release_version} CLI: ${payload.cli_version}`);
|
|
102
|
+
if (payload.cli_shim) lines.push(`命令: ${payload.cli_shim}`);
|
|
103
|
+
if (payload.skill_root) lines.push(`Skill: ${payload.skill_root}`);
|
|
104
|
+
if (payload.path_ready === false && payload.path_setup) lines.push(`PATH: ${payload.path_setup}`);
|
|
105
|
+
if (payload.restart_agent_session) lines.push("请重启 Agent 会话以加载最新 Skill。");
|
|
106
|
+
return `${lines.join("\n")}\n`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function printResult(command, payload, summary) {
|
|
110
|
+
if (summary) process.stdout.write(formatSummary(command, payload));
|
|
111
|
+
else printJson(payload);
|
|
112
|
+
}
|
|
113
|
+
|
|
38
114
|
function loadBusinessCommands() {
|
|
39
115
|
try {
|
|
40
116
|
const { BUSINESS_COMMANDS } = require(BUSINESS_ENTRY);
|
|
@@ -66,24 +142,29 @@ function main(argv) {
|
|
|
66
142
|
}
|
|
67
143
|
if (!MANAGEMENT_COMMANDS.has(command)) return dispatchBusiness(argv);
|
|
68
144
|
|
|
145
|
+
if (rest.includes("--help") || rest.includes("-h")) {
|
|
146
|
+
process.stdout.write(managementUsage(command));
|
|
147
|
+
return 0;
|
|
148
|
+
}
|
|
149
|
+
|
|
69
150
|
const options = parseOptions(rest);
|
|
70
151
|
if (command === "install" || command === "upgrade") {
|
|
71
152
|
if (command === "upgrade") options.upgrade = true;
|
|
72
|
-
|
|
153
|
+
printResult(command, install(options), options.summary);
|
|
73
154
|
return 0;
|
|
74
155
|
}
|
|
75
156
|
if (command === "migrate") {
|
|
76
157
|
const result = migrate(options);
|
|
77
|
-
|
|
158
|
+
printResult(command, result, options.summary);
|
|
78
159
|
return result.ok ? 0 : 1;
|
|
79
160
|
}
|
|
80
161
|
if (command === "status") {
|
|
81
162
|
const result = status(options);
|
|
82
|
-
|
|
163
|
+
printResult(command, result, options.summary);
|
|
83
164
|
return result.ok ? 0 : 1;
|
|
84
165
|
}
|
|
85
166
|
const result = doctor(options);
|
|
86
|
-
|
|
167
|
+
printResult(command, result, options.summary);
|
|
87
168
|
return result.ok ? 0 : 1;
|
|
88
169
|
}
|
|
89
170
|
|
|
@@ -91,9 +172,13 @@ if (require.main === module) {
|
|
|
91
172
|
try {
|
|
92
173
|
process.exitCode = main(process.argv.slice(2));
|
|
93
174
|
} catch (error) {
|
|
94
|
-
process.
|
|
175
|
+
if (process.argv.slice(2).includes("--json")) {
|
|
176
|
+
process.stderr.write(`${JSON.stringify({ ok: false, error: error.message }, null, 2)}\n`);
|
|
177
|
+
} else {
|
|
178
|
+
process.stderr.write(`ML Platform: 失败\n错误: ${error.message}\n`);
|
|
179
|
+
}
|
|
95
180
|
process.exitCode = 2;
|
|
96
181
|
}
|
|
97
182
|
}
|
|
98
183
|
|
|
99
|
-
module.exports = { BUSINESS_ENTRY, MANAGEMENT_COMMANDS, dispatchBusiness, main, usage };
|
|
184
|
+
module.exports = { BUSINESS_ENTRY, MANAGEMENT_COMMANDS, dispatchBusiness, formatSummary, main, managementUsage, usage };
|
|
@@ -24,7 +24,10 @@ Treat `Recipe` and public `Feature.compute` as removed. Treat `computation_hash`
|
|
|
24
24
|
|
|
25
25
|
## Initialize The Client
|
|
26
26
|
|
|
27
|
-
Use the `ml-platform` executable on `PATH` for every platform command. The formal
|
|
27
|
+
Use the `ml-platform` executable on `PATH` for every platform command. The formal npm release installs
|
|
28
|
+
the CLI and this pure Skill together. The Skill does not contain a second CLI runtime, launcher, or
|
|
29
|
+
installer. During repository development, provide the current JavaScript CLI through an isolated test
|
|
30
|
+
`PATH`.
|
|
28
31
|
|
|
29
32
|
Before any platform operation, verify the executable and its version:
|
|
30
33
|
|
|
@@ -36,17 +39,19 @@ ml-platform version
|
|
|
36
39
|
If the executable is missing or cannot start, stop and report that the ML Platform release installation is incomplete. Do not download a client, search for a repository checkout, or fall back to another executable.
|
|
37
40
|
|
|
38
41
|
Before any server-profile discovery, dry-run, publication, build, or artifact
|
|
39
|
-
operation,
|
|
42
|
+
operation, inspect the effective API configuration:
|
|
40
43
|
|
|
41
44
|
```bash
|
|
42
|
-
ml-platform
|
|
45
|
+
ml-platform show-config
|
|
43
46
|
ml-platform --profile server health
|
|
44
47
|
```
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
The effective API target is resolved in this order: explicit `--api-url`,
|
|
50
|
+
`ML_PLATFORM_API_URL`, then the saved value written by `ml-platform configure`.
|
|
51
|
+
If no target is configured, ask the user for an approved API URL before making
|
|
52
|
+
server requests. Do not hardcode an environment-specific address in a Skill,
|
|
53
|
+
catalog, or prompt. Keep database, MinIO, and source credentials out of commands;
|
|
54
|
+
use the server's managed Secrets.
|
|
50
55
|
|
|
51
56
|
Install and upgrade the CLI and Skill only through the explicit commands provided by `@zhuoyuezs/ml-platform`. Restart the Agent session after a successful Skill upgrade so the definition is reloaded. Never copy files over an installed Skill directory manually.
|
|
52
57
|
|
|
@@ -76,6 +81,30 @@ Check the selected profile and list existing Parameter, Operator, Feature, Featu
|
|
|
76
81
|
|
|
77
82
|
Create a new version when source semantics, formula code, config meaning, inputs, output dtype, time behavior, quality rules, or column order change. Never overwrite an immutable version or use suffixes such as `new`, `final`, or `test2`.
|
|
78
83
|
|
|
84
|
+
### Operate An Existing Registered Dataset
|
|
85
|
+
|
|
86
|
+
For diagnosis, resolve, build, Job lookup, and artifact lookup of an already
|
|
87
|
+
registered DatasetManifest, use the API through `ml-platform`. Do not search the
|
|
88
|
+
platform source checkout or a local Catalog directory for a matching JSON file.
|
|
89
|
+
|
|
90
|
+
1. Run `show-config` and `health` to record the effective API source.
|
|
91
|
+
2. Run `list-projects`, then `list-datasets --project <project>` to discover
|
|
92
|
+
candidates from the Registry.
|
|
93
|
+
3. Ask the user to confirm the exact `project`, `dataset_id`, and
|
|
94
|
+
`dataset_version` when more than one valid candidate exists. Never infer a
|
|
95
|
+
target from a similar local filename.
|
|
96
|
+
4. Run `get-dataset <dataset_id> <dataset_version> --project <project>` and
|
|
97
|
+
inspect the returned registered contract.
|
|
98
|
+
5. Run `resolve-dataset` for a read-only dependency and manifest-hash check.
|
|
99
|
+
6. Submit exactly one `build-registered-dataset ... --wait` only after the user
|
|
100
|
+
authorizes that exact registered version.
|
|
101
|
+
7. Use the returned Job ID with `get-job`, then use the returned manifest hash
|
|
102
|
+
with `get-dataset-artifact` after success.
|
|
103
|
+
|
|
104
|
+
Local `resolve-manifest` and `build-dataset <file>` remain authoring tools for a
|
|
105
|
+
new or changed Catalog contract before it is registered. They are not required
|
|
106
|
+
for operating an existing Registry version.
|
|
107
|
+
|
|
79
108
|
## Upgrade Dependency Chains
|
|
80
109
|
|
|
81
110
|
Treat a version change as a release of its affected reverse-dependency closure, not as an isolated asset bump.
|
|
@@ -235,7 +264,7 @@ Require all of the following before reporting success:
|
|
|
235
264
|
windows tiling the fetch range, and any retries are accounted for;
|
|
236
265
|
- missing values and warnings are reported, not silently repaired.
|
|
237
266
|
|
|
238
|
-
The manifest hash returned by `resolve-manifest` is the artifact key: it stays
|
|
267
|
+
The manifest hash returned by `resolve-manifest` or `resolve-dataset` is the artifact key: it stays
|
|
239
268
|
the same after the build, so it is usable for cache reuse and polling before
|
|
240
269
|
submission. Distinguish the two lookup failures rather than treating both as "not
|
|
241
270
|
ready" — `422` with `invalid_artifact_key` means the key can never name an
|
|
@@ -31,10 +31,11 @@ ml-platform --profile server show-config
|
|
|
31
31
|
ml-platform --profile server health
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
The
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
The URL is environment-specific and must be supplied by the user, an approved
|
|
35
|
+
`ML_PLATFORM_API_URL`, or the saved value from `ml-platform configure`. Do not
|
|
36
|
+
hardcode an internal address in this Skill or in a catalog. `show-config` displays
|
|
37
|
+
the effective target before discovery, dry-run, publication, build, or artifact
|
|
38
|
+
commands.
|
|
38
39
|
|
|
39
40
|
Do not place database, MinIO, or source credentials in commands when the server profile can use managed Secrets.
|
|
40
41
|
|
|
@@ -154,6 +155,38 @@ The cross-store publication is not transactional. If an error occurs, report the
|
|
|
154
155
|
|
|
155
156
|
## Resolve And Build A Dataset
|
|
156
157
|
|
|
158
|
+
For an existing registered DatasetManifest, use the Registry identity only; no
|
|
159
|
+
local Catalog or Manifest path is needed:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
ml-platform --profile server list-projects
|
|
163
|
+
ml-platform --profile server list-datasets --project <project>
|
|
164
|
+
ml-platform --profile server \
|
|
165
|
+
get-dataset <dataset_id> <dataset_version> --project <project>
|
|
166
|
+
ml-platform --profile server \
|
|
167
|
+
resolve-dataset <dataset_id> <dataset_version> --project <project>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
After the user confirms the exact triple and authorizes one build:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
ml-platform --profile server \
|
|
174
|
+
build-registered-dataset <dataset_id> <dataset_version> \
|
|
175
|
+
--project <project> \
|
|
176
|
+
--partition-duration 1d \
|
|
177
|
+
--max-parallelism 1 \
|
|
178
|
+
--wait
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The command first fetches that immutable DatasetManifest from the API and sends
|
|
182
|
+
the validated response to the resolve/build endpoint. It never searches the
|
|
183
|
+
current repository for a similarly named file. Record the API source,
|
|
184
|
+
`project/dataset_id:dataset_version`, manifest hash, Job ID, terminal status,
|
|
185
|
+
and artifact reference.
|
|
186
|
+
|
|
187
|
+
When authoring a new or changed contract that has not been registered yet, use
|
|
188
|
+
the local-file commands below.
|
|
189
|
+
|
|
157
190
|
Resolve without fetching source data:
|
|
158
191
|
|
|
159
192
|
```bash
|