@guandata/guanwf 0.1.834 → 0.1.836
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/CHANGELOG.md +9 -0
- package/README.md +10 -0
- package/bin/platforms.js +44 -0
- package/bin/run.js +99 -44
- package/package.json +16 -4
- package/skills/guanwf/SKILL.md +3 -1
- package/skills/guanwf/references/WORKFLOW_DSL.md +5 -3
- package/binaries/guanwf-darwin-arm64 +0 -0
- package/binaries/guanwf-darwin-x64 +0 -0
- package/binaries/guanwf-linux-arm64 +0 -0
- package/binaries/guanwf-linux-x64 +0 -0
- package/binaries/guanwf-win32-x64.exe +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## @guandata/guanwf 0.1.836 - 2026-09-19
|
|
4
|
+
|
|
5
|
+
- 安装包按平台拆分:主包只保留启动器、Skill 与文档,原生程序由同版本的 `@guandata/guanwf-<平台>-<架构>` 可选依赖提供,安装时只下载当前系统的一份,安装命令与 CLI 行为不变。
|
|
6
|
+
- 平台包缺失或主包与平台包版本不一致时给出可操作提示;新增 `pack:all`、`verify:platforms` 与自动选包/注册表门禁,发布前校验五个平台包。
|
|
7
|
+
|
|
8
|
+
## @guandata/guanwf 0.1.835 - 2026-09-18
|
|
9
|
+
|
|
10
|
+
- 修复 Python 镜像版本解析:优先通过 `/api/python-images/list` 读取 `pythonVersion`,旧接口不可用时降级到 `/api/system-images/list?type=PYTHON` 并解析 `runtimeEnv`;两类结构化版本字段都缺失或无法识别时才回退产品兼容契约 Python 3.8,仍然禁止从镜像描述、名称或 URL 推断版本。
|
|
11
|
+
|
|
3
12
|
## @guandata/guanwf 0.1.834 - 2026-09-17
|
|
4
13
|
|
|
5
14
|
- `schedule set --failure-strategy` 改为已废弃的兼容参数,仅接受 `CONTINUE`;显式传 `END` 会在本地校验阶段失败且不发送写请求,节点失败后的后继调度由 `FAILURE` / `ALL` 连线决定。
|
package/README.md
CHANGED
|
@@ -46,8 +46,18 @@ guanwf install-skill
|
|
|
46
46
|
|
|
47
47
|
> `npm install -g --foreground-scripts @guandata/guanwf` / `npm link --foreground-scripts` 会通过 postinstall 自动刷新 skill,并显示明确的成功、失败或跳过结果;上述 `guanwf install-skill` 仅用于失败后的手动修复或排查。CI 等无需 skill 的环境可设 `GUAN_SKIP_INSTALL_SKILL=1` 跳过。
|
|
48
48
|
|
|
49
|
+
安装包会通过 npm `optionalDependencies` 自动选择当前系统的原生二进制。不要使用 `--omit=optional` 或 `optional=false`;企业 npm 镜像也需要同步对应的 `@guandata/guanwf-<平台>-<架构>` 包。若平台包缺失,CLI 会显示对应包名和重新安装方法。
|
|
50
|
+
|
|
49
51
|
## 版本更新
|
|
50
52
|
|
|
53
|
+
### @guandata/guanwf 0.1.836
|
|
54
|
+
|
|
55
|
+
- 安装时自动选择当前系统和架构的原生程序,减少下载量与磁盘占用,原有安装命令不变;离线安装也支持自动选包。
|
|
56
|
+
|
|
57
|
+
### @guandata/guanwf 0.1.835
|
|
58
|
+
|
|
59
|
+
- 修复 Python 镜像版本解析:优先读取 `pythonVersion`,旧接口降级解析 `runtimeEnv`,两者都不可用时才回退兼容契约 Python 3.8。
|
|
60
|
+
|
|
51
61
|
### @guandata/guanwf 0.1.834
|
|
52
62
|
|
|
53
63
|
- `schedule set --failure-strategy` 仅接受 `CONTINUE`,显式传 `END` 会在本地校验阶段失败;后继调度改由 `FAILURE` / `ALL` 连线决定。
|
package/bin/platforms.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// Single source of truth for the optionalDependencies platform-package split.
|
|
4
|
+
// bin/run.js, scripts/build.js and the build/preflight tests all read this file
|
|
5
|
+
// so that the matrix, the package names and the embedded binary names can never
|
|
6
|
+
// drift apart.
|
|
7
|
+
|
|
8
|
+
const PACKAGE_PREFIX = "@guandata/guanwf";
|
|
9
|
+
const CLI_NAME = "guanwf";
|
|
10
|
+
const BINARY_NAMES = ["guanwf"];
|
|
11
|
+
|
|
12
|
+
const PLATFORM_TARGETS = [
|
|
13
|
+
{ platform: "darwin", arch: "arm64", suffix: "darwin-arm64", ext: "" },
|
|
14
|
+
{ platform: "darwin", arch: "x64", suffix: "darwin-x64", ext: "" },
|
|
15
|
+
{ platform: "linux", arch: "x64", suffix: "linux-x64", ext: "" },
|
|
16
|
+
{ platform: "linux", arch: "arm64", suffix: "linux-arm64", ext: "" },
|
|
17
|
+
{ platform: "win32", arch: "x64", suffix: "win32-x64", ext: ".exe" },
|
|
18
|
+
].map((target) => ({
|
|
19
|
+
...target,
|
|
20
|
+
key: `${target.platform}-${target.arch}`,
|
|
21
|
+
packageName: `${PACKAGE_PREFIX}-${target.suffix}`,
|
|
22
|
+
binaries: BINARY_NAMES.map((name) => `${name}${target.ext}`),
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
function targetForRuntime(platform, arch) {
|
|
26
|
+
return PLATFORM_TARGETS.find(
|
|
27
|
+
(target) => target.platform === platform && target.arch === arch
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function optionalDependencies(version) {
|
|
32
|
+
return Object.fromEntries(
|
|
33
|
+
PLATFORM_TARGETS.map((target) => [target.packageName, version])
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
CLI_NAME,
|
|
39
|
+
PACKAGE_PREFIX,
|
|
40
|
+
BINARY_NAMES,
|
|
41
|
+
PLATFORM_TARGETS,
|
|
42
|
+
optionalDependencies,
|
|
43
|
+
targetForRuntime,
|
|
44
|
+
};
|
package/bin/run.js
CHANGED
|
@@ -7,34 +7,79 @@ const path = require("path");
|
|
|
7
7
|
const fs = require("fs");
|
|
8
8
|
const os = require("os");
|
|
9
9
|
const { createInstallChildEnv, reexecInstallCommand } = require("./install-env");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
function
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
10
|
+
const {
|
|
11
|
+
BINARY_NAMES,
|
|
12
|
+
PACKAGE_PREFIX,
|
|
13
|
+
PLATFORM_TARGETS,
|
|
14
|
+
targetForRuntime,
|
|
15
|
+
} = require("./platforms");
|
|
16
|
+
|
|
17
|
+
// The native binaries are delivered by per-platform optional dependencies, so
|
|
18
|
+
// an installation only downloads and unpacks the current OS/architecture.
|
|
19
|
+
function resolvePlatformBinaries(options = {}) {
|
|
20
|
+
const platform = options.platform || process.platform;
|
|
21
|
+
const arch = options.arch || process.arch;
|
|
22
|
+
const resolvePackage = options.resolvePackage || require.resolve;
|
|
23
|
+
const exists = options.exists || fs.existsSync;
|
|
24
|
+
const readJson =
|
|
25
|
+
options.readJson || ((filename) => JSON.parse(fs.readFileSync(filename, "utf8")));
|
|
26
|
+
const key = `${platform}-${arch}`;
|
|
27
|
+
const target = targetForRuntime(platform, arch);
|
|
28
|
+
if (!target) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Unsupported platform: ${key}\nSupported: ${PLATFORM_TARGETS.map((item) => item.key).join(", ")}`
|
|
25
31
|
);
|
|
26
|
-
process.exit(1);
|
|
27
32
|
}
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
34
|
-
|
|
34
|
+
try {
|
|
35
|
+
const packageJson = resolvePackage(`${target.packageName}/package.json`);
|
|
36
|
+
const platformVersion = readJson(packageJson).version;
|
|
37
|
+
const mainVersion = readJson(path.join(__dirname, "..", "package.json")).version;
|
|
38
|
+
if (platformVersion !== mainVersion) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Platform package ${target.packageName} version ${platformVersion} does not match ` +
|
|
41
|
+
`${PACKAGE_PREFIX} ${mainVersion}. Reinstall ${PACKAGE_PREFIX}.`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
const binDir = path.join(path.dirname(packageJson), "bin");
|
|
45
|
+
const binaryPaths = {};
|
|
46
|
+
for (const binary of target.binaries) {
|
|
47
|
+
const binaryPath = path.join(binDir, binary);
|
|
48
|
+
if (!exists(binaryPath)) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Platform package ${target.packageName} is installed but its binary is missing: ${binaryPath}. ` +
|
|
51
|
+
`Reinstall ${PACKAGE_PREFIX}.`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
binaryPaths[binary.replace(/\.exe$/, "")] = binaryPath;
|
|
55
|
+
}
|
|
56
|
+
return { target, binaryPaths };
|
|
57
|
+
} catch (err) {
|
|
58
|
+
if (err.message && err.message.startsWith("Platform package ")) throw err;
|
|
59
|
+
|
|
60
|
+
// Local development fallback. The generated directory is excluded from
|
|
61
|
+
// the published main package, so installed users always use the optional
|
|
62
|
+
// platform dependency above.
|
|
63
|
+
const localBinDir = path.join(__dirname, "..", "platforms", target.suffix, "bin");
|
|
64
|
+
const binaryPaths = {};
|
|
65
|
+
for (const binary of target.binaries) {
|
|
66
|
+
const binaryPath = path.join(localBinDir, binary);
|
|
67
|
+
if (!exists(binaryPath)) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`Missing optional platform package ${target.packageName} for ${key}.\n` +
|
|
70
|
+
`Reinstall without disabling optional dependencies:\n` +
|
|
71
|
+
` npm install -g ${PACKAGE_PREFIX}\n` +
|
|
72
|
+
`If you used --omit=optional or optional=false, remove that setting first.`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
binaryPaths[binary.replace(/\.exe$/, "")] = binaryPath;
|
|
76
|
+
}
|
|
77
|
+
return { target, binaryPaths };
|
|
35
78
|
}
|
|
79
|
+
}
|
|
36
80
|
|
|
37
|
-
|
|
81
|
+
function getBinaryPath(options = {}) {
|
|
82
|
+
return resolvePlatformBinaries(options).binaryPaths[BINARY_NAMES[0]];
|
|
38
83
|
}
|
|
39
84
|
|
|
40
85
|
function copyDirectory(src, dest) {
|
|
@@ -81,7 +126,7 @@ function installBuddySkills(pkgRoot, skill) {
|
|
|
81
126
|
}
|
|
82
127
|
}
|
|
83
128
|
|
|
84
|
-
if (process.argv[2] === "version" && process.argv.length === 3) {
|
|
129
|
+
if (require.main === module && process.argv[2] === "version" && process.argv.length === 3) {
|
|
85
130
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
|
|
86
131
|
console.log(pkg.version);
|
|
87
132
|
process.exit(0);
|
|
@@ -111,7 +156,7 @@ function resolveNpxInvocation() {
|
|
|
111
156
|
return { command: "npx", argsPrefix: [] };
|
|
112
157
|
}
|
|
113
158
|
|
|
114
|
-
if (process.argv[2] === "install-skill") {
|
|
159
|
+
if (require.main === module && process.argv[2] === "install-skill") {
|
|
115
160
|
reexecInstallCommand(__filename, process.argv.slice(2));
|
|
116
161
|
const pkgRoot = path.join(__dirname, "..");
|
|
117
162
|
const extraArgs = process.argv.slice(3);
|
|
@@ -143,28 +188,38 @@ if (process.argv[2] === "install-skill") {
|
|
|
143
188
|
process.exit(status);
|
|
144
189
|
}
|
|
145
190
|
|
|
146
|
-
|
|
191
|
+
if (require.main === module) {
|
|
192
|
+
let binary;
|
|
193
|
+
try {
|
|
194
|
+
binary = getBinaryPath();
|
|
195
|
+
} catch (err) {
|
|
196
|
+
console.error(err.message);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
147
199
|
|
|
148
|
-
try {
|
|
149
|
-
|
|
150
|
-
|
|
200
|
+
try {
|
|
201
|
+
if (process.platform !== "win32") {
|
|
202
|
+
fs.chmodSync(binary, 0o755);
|
|
203
|
+
}
|
|
204
|
+
} catch (_) {
|
|
205
|
+
// chmod may fail in read-only environments
|
|
151
206
|
}
|
|
152
|
-
} catch (_) {
|
|
153
|
-
// chmod may fail in read-only environments
|
|
154
|
-
}
|
|
155
207
|
|
|
156
|
-
if (process.platform === "win32") {
|
|
157
|
-
|
|
158
|
-
}
|
|
208
|
+
if (process.platform === "win32") {
|
|
209
|
+
try { execSync("chcp 65001", { stdio: "ignore" }); } catch (_) {}
|
|
210
|
+
}
|
|
159
211
|
|
|
160
|
-
try {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
} catch (err) {
|
|
166
|
-
|
|
167
|
-
|
|
212
|
+
try {
|
|
213
|
+
execFileSync(binary, process.argv.slice(2), {
|
|
214
|
+
stdio: "inherit",
|
|
215
|
+
env: { ...process.env, GUANWF_PROG_NAME: "guanwf" },
|
|
216
|
+
});
|
|
217
|
+
} catch (err) {
|
|
218
|
+
if (err.status != null) {
|
|
219
|
+
process.exit(err.status);
|
|
220
|
+
}
|
|
221
|
+
throw err;
|
|
168
222
|
}
|
|
169
|
-
throw err;
|
|
170
223
|
}
|
|
224
|
+
|
|
225
|
+
module.exports = { getBinaryPath, resolvePlatformBinaries };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guandata/guanwf",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.836",
|
|
4
4
|
"description": "观远工作流数据流编辑工具 - 创建、编辑、导出、预览、保存数据流",
|
|
5
5
|
"bin": {
|
|
6
6
|
"guanwf": "bin/run.js"
|
|
@@ -8,13 +8,17 @@
|
|
|
8
8
|
"scripts": {
|
|
9
9
|
"postinstall": "node bin/postinstall.js",
|
|
10
10
|
"build": "node scripts/build.js && node scripts/sync-skill.js",
|
|
11
|
+
"pack:all": "node scripts/pack-all.js",
|
|
12
|
+
"test:build-script": "node scripts/platform-tests.js build && node scripts/platform-tests.js run",
|
|
13
|
+
"test:package-layout": "node scripts/platform-tests.js layout && node scripts/platform-tests.js install-smoke",
|
|
14
|
+
"test:auto-select": "node scripts/platform-tests.js auto-select",
|
|
15
|
+
"verify:platforms": "node scripts/verify-platforms.js",
|
|
11
16
|
"changelog": "node ../../scripts/generate-release-changelog.js .",
|
|
12
17
|
"check-changelog": "node ../../scripts/check-release-changelog.js .",
|
|
13
|
-
"prepublishOnly": "npm run check-changelog && npm run build && node scripts/preflight.js"
|
|
18
|
+
"prepublishOnly": "npm run test:build-script && npm run check-changelog && npm run build && node scripts/preflight.js && npm run test:package-layout && npm run test:auto-select"
|
|
14
19
|
},
|
|
15
20
|
"files": [
|
|
16
21
|
"bin/",
|
|
17
|
-
"binaries/",
|
|
18
22
|
"skills/",
|
|
19
23
|
"CHANGELOG.md",
|
|
20
24
|
"LICENSE",
|
|
@@ -37,7 +41,15 @@
|
|
|
37
41
|
"engines": {
|
|
38
42
|
"node": ">=14"
|
|
39
43
|
},
|
|
44
|
+
"optionalDependencies": {
|
|
45
|
+
"@guandata/guanwf-darwin-arm64": "0.1.836",
|
|
46
|
+
"@guandata/guanwf-darwin-x64": "0.1.836",
|
|
47
|
+
"@guandata/guanwf-linux-x64": "0.1.836",
|
|
48
|
+
"@guandata/guanwf-linux-arm64": "0.1.836",
|
|
49
|
+
"@guandata/guanwf-win32-x64": "0.1.836"
|
|
50
|
+
},
|
|
40
51
|
"publishConfig": {
|
|
41
|
-
"registry": "https://registry.npmjs.org/"
|
|
52
|
+
"registry": "https://registry.npmjs.org/",
|
|
53
|
+
"access": "public"
|
|
42
54
|
}
|
|
43
55
|
}
|
package/skills/guanwf/SKILL.md
CHANGED
|
@@ -169,7 +169,9 @@ guanwf python-runtime --dir <workdir> --format json
|
|
|
169
169
|
`pythonVersionSource`、`imageId` 及解析状态,并写入 `<workdir>/_python_runtime_context.json`。`guanwf edit` 检测到
|
|
170
170
|
Python 节点时也会自动获取并返回同一结构化上下文。生成代码时只以其中的
|
|
171
171
|
`pythonRuntime.nodes[].runtime.pythonVersion`(或 `pythonRuntime.selected`)为兼容目标;
|
|
172
|
-
|
|
172
|
+
CLI 优先通过 `/api/python-images/list` 读取 `pythonVersion`;旧接口不可用时降级到
|
|
173
|
+
`/api/system-images/list?type=PYTHON` 并解析 `runtimeEnv`。两类结构化版本字段均缺失或无法识别时,
|
|
174
|
+
使用产品兼容契约 Python 3.8,并明确标记
|
|
173
175
|
`pythonVersionSource: "compatibility_fallback"`;**禁止从镜像描述、名称或 URL 推断版本**。
|
|
174
176
|
结构化上下文中的 `imageUrl` 会移除 userinfo、fragment 和敏感 query;落盘文件使用 0600 并自动忽略。
|
|
175
177
|
固定 Runtime 输出 `runtimeMode: "FIXED_RUNTIME"`,配置镜像的动态 Pod 输出 `runtimeMode: "DYNAMIC_POD"`;
|
|
@@ -154,10 +154,12 @@ guanwf python-runtime --dir <workdir> --format json
|
|
|
154
154
|
`pythonRuntime.nodes[]` 是工作区各 Python 节点根据 `PythonConfig.ImageID` 解析出的实际选择。
|
|
155
155
|
兼容性判断以 `runtimeMode` 和嵌套 `runtime.pythonVersion` 为准,并检查 `runtime.pythonVersionSource`。CLI 不输出
|
|
156
156
|
服务端自由文本 `imageDescription`;经过凭证脱敏的 `imageUrl` 仅供排查,禁止从中推断版本。
|
|
157
|
-
CLI
|
|
157
|
+
CLI 优先调用兼容接口 `/api/python-images/list` 获取逐镜像 `pythonVersion`;该接口不可用时降级调用
|
|
158
|
+
`/api/system-images/list?type=PYTHON`,并从规范字段 `runtimeEnv`(例如 `Python 3.11`)解析版本。
|
|
158
159
|
|
|
159
|
-
|
|
160
|
-
`pythonVersionSource: "
|
|
160
|
+
兼容约定:旧接口的 `pythonVersion` 或新接口的合法 `runtimeEnv` 均标记为
|
|
161
|
+
`pythonVersionSource: "api_field"`;两者均缺失或 `runtimeEnv` 无法识别时,CLI 返回 Python 3.8,并标记
|
|
162
|
+
`pythonVersionSource: "compatibility_fallback"`。
|
|
161
163
|
|
|
162
164
|
固定 Runtime 标记 `runtimeMode: "FIXED_RUNTIME"`,配置镜像的动态 Pod 标记
|
|
163
165
|
`runtimeMode: "DYNAMIC_POD"`。目录接口不可用或版本字段缺失时,状态与 warning 会明确说明,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|