@clickzetta/cz-cli 0.3.50 → 0.3.51
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/bin/platform.js +209 -0
- package/bin/postinstall.js +33 -26
- package/bin/run.js +13 -12
- package/package.json +6 -6
package/bin/platform.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const { execFileSync } = require("child_process");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const os = require("os");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
const zlib = require("zlib");
|
|
9
|
+
|
|
10
|
+
const SUPPORTED_PACKAGES = new Set([
|
|
11
|
+
"darwin-arm64",
|
|
12
|
+
"darwin-x64",
|
|
13
|
+
"linux-arm64",
|
|
14
|
+
"linux-x64",
|
|
15
|
+
"win32-x64",
|
|
16
|
+
]);
|
|
17
|
+
const DEFAULT_FALLBACK_ROOT = path.join(__dirname, "fallback");
|
|
18
|
+
|
|
19
|
+
function normalizeArch(arch = os.arch()) {
|
|
20
|
+
if (arch === "x64" || arch === "amd64") return "x64";
|
|
21
|
+
if (arch === "arm64" || arch === "aarch64") return "arm64";
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getPlatformSpec({
|
|
26
|
+
platform = os.platform(),
|
|
27
|
+
arch = os.arch(),
|
|
28
|
+
} = {}) {
|
|
29
|
+
const normalizedArch = normalizeArch(arch);
|
|
30
|
+
if (!normalizedArch) return null;
|
|
31
|
+
const packageTarget = `${platform}-${normalizedArch}`;
|
|
32
|
+
if (!SUPPORTED_PACKAGES.has(packageTarget)) return null;
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
platform,
|
|
36
|
+
arch: normalizedArch,
|
|
37
|
+
binaryName: platform === "win32" ? "cz-cli.exe" : "cz-cli",
|
|
38
|
+
packageName: `@clickzetta/cz-cli-${packageTarget}`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function resolvePackageDir(spec, resolve = require.resolve) {
|
|
43
|
+
try {
|
|
44
|
+
return path.dirname(resolve(`${spec.packageName}/package.json`));
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function resolveBinaryFromRoot(rootDir, spec, existsSync = fs.existsSync) {
|
|
51
|
+
if (!rootDir) return null;
|
|
52
|
+
const binPath = path.join(rootDir, spec.binaryName);
|
|
53
|
+
if (!existsSync(binPath)) return null;
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
rootDir,
|
|
57
|
+
binPath,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function resolveInstalledBinary({
|
|
62
|
+
spec = getPlatformSpec(),
|
|
63
|
+
fallbackRoot = DEFAULT_FALLBACK_ROOT,
|
|
64
|
+
resolvePackageDirFn = resolvePackageDir,
|
|
65
|
+
existsSync = fs.existsSync,
|
|
66
|
+
} = {}) {
|
|
67
|
+
if (!spec) return null;
|
|
68
|
+
|
|
69
|
+
const packageDir = resolvePackageDirFn(spec);
|
|
70
|
+
const packaged = resolveBinaryFromRoot(packageDir ? path.join(packageDir, "bin") : null, spec, existsSync);
|
|
71
|
+
if (packaged) return { ...packaged, source: "package" };
|
|
72
|
+
|
|
73
|
+
const fallback = resolveBinaryFromRoot(path.join(fallbackRoot, `${spec.platform}-${spec.arch}`), spec, existsSync);
|
|
74
|
+
if (fallback) return { ...fallback, source: "fallback" };
|
|
75
|
+
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function parseOctal(buffer, start, end) {
|
|
80
|
+
const value = buffer.toString("utf8", start, end).replace(/\0.*$/, "").trim();
|
|
81
|
+
if (!value) return 0;
|
|
82
|
+
return Number.parseInt(value, 8);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function sanitizeRelativePath(relativePath) {
|
|
86
|
+
const normalized = path.posix.normalize(relativePath).replace(/^\/+/, "");
|
|
87
|
+
if (!normalized || normalized.startsWith("../") || normalized === "..") return null;
|
|
88
|
+
return normalized;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function extractBinFromTarball(archivePath, destinationDir) {
|
|
92
|
+
const archive = zlib.gunzipSync(fs.readFileSync(archivePath));
|
|
93
|
+
const resolvedDestinationDir = path.resolve(destinationDir);
|
|
94
|
+
let offset = 0;
|
|
95
|
+
|
|
96
|
+
while (offset + 512 <= archive.length) {
|
|
97
|
+
const header = archive.subarray(offset, offset + 512);
|
|
98
|
+
if (header.every((byte) => byte === 0)) break;
|
|
99
|
+
|
|
100
|
+
const name = header.toString("utf8", 0, 100).replace(/\0.*$/, "");
|
|
101
|
+
const prefix = header.toString("utf8", 345, 500).replace(/\0.*$/, "");
|
|
102
|
+
const entryPath = sanitizeRelativePath(prefix ? `${prefix}/${name}` : name);
|
|
103
|
+
const type = String.fromCharCode(header[156] || 0);
|
|
104
|
+
const mode = parseOctal(header, 100, 108);
|
|
105
|
+
const size = parseOctal(header, 124, 136);
|
|
106
|
+
const dataStart = offset + 512;
|
|
107
|
+
const dataEnd = dataStart + size;
|
|
108
|
+
const relative = entryPath && entryPath.startsWith("package/bin/") ? sanitizeRelativePath(entryPath.slice(12)) : null;
|
|
109
|
+
|
|
110
|
+
if (relative) {
|
|
111
|
+
const targetPath = path.resolve(resolvedDestinationDir, relative);
|
|
112
|
+
if (!targetPath.startsWith(resolvedDestinationDir + path.sep) && targetPath !== resolvedDestinationDir) {
|
|
113
|
+
throw new Error(`Refusing to extract unsafe path: ${relative}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (type === "5") {
|
|
117
|
+
fs.mkdirSync(targetPath, { recursive: true });
|
|
118
|
+
} else if (type === "\0" || type === "0") {
|
|
119
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
120
|
+
fs.writeFileSync(targetPath, archive.subarray(dataStart, dataEnd));
|
|
121
|
+
if (process.platform !== "win32") fs.chmodSync(targetPath, mode || 0o755);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
offset = dataStart + Math.ceil(size / 512) * 512;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function installFromNpmRegistry({
|
|
130
|
+
packageName,
|
|
131
|
+
version,
|
|
132
|
+
destinationDir,
|
|
133
|
+
} = {}) {
|
|
134
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "cz-cli-npm-pack-"));
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
const packed = execFileSync("npm", ["pack", `${packageName}@${version}`, "--silent"], {
|
|
138
|
+
cwd: tempRoot,
|
|
139
|
+
encoding: "utf-8",
|
|
140
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
141
|
+
})
|
|
142
|
+
.trim()
|
|
143
|
+
.split(/\r?\n/)
|
|
144
|
+
.filter(Boolean)
|
|
145
|
+
.pop();
|
|
146
|
+
|
|
147
|
+
if (!packed) throw new Error(`npm pack did not return a tarball name for ${packageName}@${version}`);
|
|
148
|
+
|
|
149
|
+
extractBinFromTarball(path.join(tempRoot, packed), destinationDir);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
const detail =
|
|
152
|
+
error && typeof error === "object" && "stderr" in error && error.stderr
|
|
153
|
+
? String(error.stderr).trim()
|
|
154
|
+
: error instanceof Error
|
|
155
|
+
? error.message
|
|
156
|
+
: String(error);
|
|
157
|
+
throw new Error(`npm registry self-heal failed for ${packageName}@${version}: ${detail}`);
|
|
158
|
+
} finally {
|
|
159
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function ensureInstalledBinary({
|
|
164
|
+
spec = getPlatformSpec(),
|
|
165
|
+
version = "latest",
|
|
166
|
+
fallbackRoot = DEFAULT_FALLBACK_ROOT,
|
|
167
|
+
resolvePackageDir: resolvePackageDirOverride,
|
|
168
|
+
existsSync = fs.existsSync,
|
|
169
|
+
installFromNpmRegistry: installFromNpmRegistryOverride = installFromNpmRegistry,
|
|
170
|
+
} = {}) {
|
|
171
|
+
if (!spec) throw new Error(`Unsupported platform/arch: ${os.platform()}/${os.arch()}`);
|
|
172
|
+
|
|
173
|
+
const installed = resolveInstalledBinary({
|
|
174
|
+
spec,
|
|
175
|
+
fallbackRoot,
|
|
176
|
+
resolvePackageDirFn: resolvePackageDirOverride || resolvePackageDir,
|
|
177
|
+
existsSync,
|
|
178
|
+
});
|
|
179
|
+
if (installed) return installed;
|
|
180
|
+
|
|
181
|
+
const destinationDir = path.join(fallbackRoot, `${spec.platform}-${spec.arch}`);
|
|
182
|
+
fs.rmSync(destinationDir, { recursive: true, force: true });
|
|
183
|
+
fs.mkdirSync(destinationDir, { recursive: true });
|
|
184
|
+
await installFromNpmRegistryOverride({
|
|
185
|
+
packageName: spec.packageName,
|
|
186
|
+
version,
|
|
187
|
+
destinationDir,
|
|
188
|
+
binaryName: spec.binaryName,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const fallback = resolveInstalledBinary({
|
|
192
|
+
spec,
|
|
193
|
+
fallbackRoot,
|
|
194
|
+
resolvePackageDirFn: () => null,
|
|
195
|
+
existsSync,
|
|
196
|
+
});
|
|
197
|
+
if (fallback) return fallback;
|
|
198
|
+
|
|
199
|
+
throw new Error(
|
|
200
|
+
`Unable to install cz-cli binary for ${spec.platform}-${spec.arch} from package ${spec.packageName} or npm registry fallback.`,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
module.exports = {
|
|
205
|
+
DEFAULT_FALLBACK_ROOT,
|
|
206
|
+
ensureInstalledBinary,
|
|
207
|
+
getPlatformSpec,
|
|
208
|
+
resolveInstalledBinary,
|
|
209
|
+
};
|
package/bin/postinstall.js
CHANGED
|
@@ -3,15 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
const { execFileSync } = require("child_process");
|
|
5
5
|
const fs = require("fs");
|
|
6
|
-
const path = require("path");
|
|
7
6
|
const os = require("os");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
const { DEFAULT_FALLBACK_ROOT, ensureInstalledBinary, getPlatformSpec } = require("./platform");
|
|
8
9
|
|
|
9
10
|
const home = os.homedir();
|
|
10
|
-
const platform = os.platform();
|
|
11
|
-
const arch = os.arch() === "x64" ? "x64" : "arm64";
|
|
12
|
-
const pkgName = `@clickzetta/cz-cli-${platform}-${arch}`;
|
|
13
|
-
const binName = platform === "win32" ? "cz-cli.exe" : "cz-cli";
|
|
14
11
|
const installFile = path.join(home, ".clickzetta", "install.json");
|
|
12
|
+
const version = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf-8")).version;
|
|
15
13
|
|
|
16
14
|
function detectPackageManager() {
|
|
17
15
|
const userAgent = process.env.npm_config_user_agent || "";
|
|
@@ -22,17 +20,20 @@ function detectPackageManager() {
|
|
|
22
20
|
return "npm";
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const skillsSrc = path.join(pkgDir, "bin", "skills");
|
|
29
|
-
if (!fs.existsSync(skillsSrc)) process.exit(0);
|
|
23
|
+
async function main() {
|
|
24
|
+
const spec = getPlatformSpec();
|
|
25
|
+
if (!spec) return;
|
|
30
26
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
const installed = await ensureInstalledBinary({
|
|
28
|
+
spec,
|
|
29
|
+
version,
|
|
30
|
+
fallbackRoot: DEFAULT_FALLBACK_ROOT,
|
|
31
|
+
});
|
|
32
|
+
const skillsSrc = path.join(installed.rootDir, "skills");
|
|
33
|
+
const skills = fs.existsSync(skillsSrc)
|
|
34
|
+
? fs.readdirSync(skillsSrc).filter((name) => fs.statSync(path.join(skillsSrc, name)).isDirectory())
|
|
35
|
+
: [];
|
|
34
36
|
|
|
35
|
-
// 1. cz-cli skill → external agent directories (subagent registration)
|
|
36
37
|
const agentDirs = [
|
|
37
38
|
path.join(home, ".claude", "skills"),
|
|
38
39
|
path.join(home, ".kiro", "skills"),
|
|
@@ -50,7 +51,6 @@ try {
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
// Cleanup: fix cz-cli-v2 → cz-cli in existing skill files (bug introduced in 57a49fcdc)
|
|
54
54
|
for (const dir of agentDirs) {
|
|
55
55
|
const skillFile = path.join(dir, "cz-cli", "SKILL.md");
|
|
56
56
|
try {
|
|
@@ -75,17 +75,17 @@ try {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
// 2. All other skills → ~/.clickzetta/skills/.builtin/ (cz-cli managed, safe to overwrite)
|
|
79
78
|
const internalDest = path.join(home, ".clickzetta", "skills", ".builtin");
|
|
80
79
|
fs.mkdirSync(internalDest, { recursive: true });
|
|
81
80
|
|
|
82
|
-
// Migrate: remove legacy skills that were previously installed directly in ~/.clickzetta/skills/
|
|
83
81
|
const legacyDir = path.join(home, ".clickzetta", "skills");
|
|
84
82
|
for (const name of skills) {
|
|
85
83
|
if (name === "cz-cli") continue;
|
|
86
84
|
const legacy = path.join(legacyDir, name);
|
|
87
85
|
if (fs.existsSync(legacy) && fs.statSync(legacy).isDirectory()) {
|
|
88
|
-
try {
|
|
86
|
+
try {
|
|
87
|
+
fs.rmSync(legacy, { recursive: true, force: true });
|
|
88
|
+
} catch (e) {}
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -100,14 +100,14 @@ try {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
try {
|
|
103
|
-
execFileSync(binPath, [], {
|
|
103
|
+
execFileSync(installed.binPath, [], {
|
|
104
104
|
stdio: "ignore",
|
|
105
105
|
env: { ...process.env, CLICKZETTA_MIGRATE_PROFILES_ONLY: "1" },
|
|
106
106
|
});
|
|
107
107
|
} catch (e) {}
|
|
108
108
|
|
|
109
109
|
try {
|
|
110
|
-
const
|
|
110
|
+
const binaryVersion = execFileSync(installed.binPath, ["--version"], {
|
|
111
111
|
stdio: ["ignore", "pipe", "ignore"],
|
|
112
112
|
encoding: "utf-8",
|
|
113
113
|
env: process.env,
|
|
@@ -119,17 +119,24 @@ try {
|
|
|
119
119
|
{
|
|
120
120
|
version: 1,
|
|
121
121
|
method: detectPackageManager(),
|
|
122
|
-
installed_path: binPath,
|
|
122
|
+
installed_path: installed.binPath,
|
|
123
123
|
channel: "latest",
|
|
124
|
-
binary_version:
|
|
124
|
+
binary_version: binaryVersion,
|
|
125
125
|
updated_at: new Date().toISOString(),
|
|
126
126
|
},
|
|
127
127
|
null,
|
|
128
|
-
2
|
|
128
|
+
2,
|
|
129
129
|
) + "\n",
|
|
130
|
-
"utf-8"
|
|
130
|
+
"utf-8",
|
|
131
131
|
);
|
|
132
132
|
} catch (e) {}
|
|
133
|
-
} catch (e) {
|
|
134
|
-
// Non-fatal: don't block npm install
|
|
135
133
|
}
|
|
134
|
+
|
|
135
|
+
main().catch((error) => {
|
|
136
|
+
process.stderr.write(
|
|
137
|
+
`Failed to install cz-cli binary: ${error instanceof Error ? error.message : String(error)}\n`,
|
|
138
|
+
);
|
|
139
|
+
process.stderr.write("npm installed the launcher package, but the platform binary could not be prepared from npm.\n");
|
|
140
|
+
process.stderr.write("Check npm config for omit=optional / optional=false and ensure npm registry access works.\n");
|
|
141
|
+
process.exit(1);
|
|
142
|
+
});
|
package/bin/run.js
CHANGED
|
@@ -2,22 +2,23 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
4
|
const { execFileSync } = require("child_process");
|
|
5
|
-
const
|
|
6
|
-
const os = require("os");
|
|
5
|
+
const { DEFAULT_FALLBACK_ROOT, getPlatformSpec, resolveInstalledBinary } = require("./platform");
|
|
7
6
|
|
|
8
|
-
const
|
|
9
|
-
const arch = os.arch() === "x64" ? "x64" : "arm64";
|
|
10
|
-
const pkgName = `@clickzetta/cz-cli-${platform}-${arch}`;
|
|
11
|
-
const binName = platform === "win32" ? "cz-cli.exe" : "cz-cli";
|
|
7
|
+
const spec = getPlatformSpec();
|
|
12
8
|
|
|
13
9
|
try {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
const installed = resolveInstalledBinary({
|
|
11
|
+
spec,
|
|
12
|
+
fallbackRoot: DEFAULT_FALLBACK_ROOT,
|
|
13
|
+
});
|
|
14
|
+
if (!installed) throw new Error("missing binary");
|
|
15
|
+
|
|
16
|
+
execFileSync(installed.binPath, process.argv.slice(2), { stdio: "inherit", env: process.env });
|
|
17
17
|
} catch (e) {
|
|
18
18
|
if (e.status !== undefined) process.exit(e.status);
|
|
19
|
-
console.error(`Error: Platform binary not found (${
|
|
20
|
-
console.error(
|
|
21
|
-
console.error(
|
|
19
|
+
console.error(`Error: Platform binary not found (${spec ? spec.packageName : "unsupported-platform"}).`);
|
|
20
|
+
console.error("Fix: reinstall with npm so postinstall can repair the platform binary from npm registry");
|
|
21
|
+
console.error(" npm install -g @clickzetta/cz-cli@latest --ignore-scripts=false");
|
|
22
|
+
console.error("If this still fails, check npm config for omit=optional / optional=false and registry access.");
|
|
22
23
|
process.exit(1);
|
|
23
24
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clickzetta/cz-cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.51",
|
|
4
4
|
"description": "AI-Agent-friendly CLI for ClickZetta Lakehouse",
|
|
5
5
|
"bin": {
|
|
6
6
|
"cz-cli": "bin/run.js"
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
"bin/"
|
|
13
13
|
],
|
|
14
14
|
"optionalDependencies": {
|
|
15
|
-
"@clickzetta/cz-cli-darwin-arm64": "0.3.
|
|
16
|
-
"@clickzetta/cz-cli-darwin-x64": "0.3.
|
|
17
|
-
"@clickzetta/cz-cli-linux-arm64": "0.3.
|
|
18
|
-
"@clickzetta/cz-cli-linux-x64": "0.3.
|
|
19
|
-
"@clickzetta/cz-cli-win32-x64": "0.3.
|
|
15
|
+
"@clickzetta/cz-cli-darwin-arm64": "0.3.51",
|
|
16
|
+
"@clickzetta/cz-cli-darwin-x64": "0.3.51",
|
|
17
|
+
"@clickzetta/cz-cli-linux-arm64": "0.3.51",
|
|
18
|
+
"@clickzetta/cz-cli-linux-x64": "0.3.51",
|
|
19
|
+
"@clickzetta/cz-cli-win32-x64": "0.3.51"
|
|
20
20
|
},
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"repository": {
|