@volcengine/ark-cli 0.1.17-beta.ed7c4f9 → 0.1.17-beta.ff33f49
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/manifest.json +16 -16
- package/package.json +1 -1
- package/scripts/postinstall.js +26 -149
package/manifest.json
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.17-beta.
|
|
2
|
+
"version": "0.1.17-beta.ff33f49",
|
|
3
3
|
"platforms": {
|
|
4
4
|
"darwin-amd64": {
|
|
5
|
-
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.
|
|
6
|
-
"sha256": "
|
|
5
|
+
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.ff33f49/arkcli-0.1.17-beta.ff33f49-darwin-amd64",
|
|
6
|
+
"sha256": "30b720390e282b55dae2a79865f88ea4458bda2bf642765d1e3ae73e8d9131c0"
|
|
7
7
|
},
|
|
8
8
|
"darwin-arm64": {
|
|
9
|
-
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.
|
|
10
|
-
"sha256": "
|
|
9
|
+
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.ff33f49/arkcli-0.1.17-beta.ff33f49-darwin-arm64",
|
|
10
|
+
"sha256": "174c750203b81620e1c6f94f0c909eb5e2de0f4315b3442cedcb3d0380ca406b"
|
|
11
11
|
},
|
|
12
12
|
"linux-amd64": {
|
|
13
|
-
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.
|
|
14
|
-
"sha256": "
|
|
13
|
+
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.ff33f49/arkcli-0.1.17-beta.ff33f49-linux-amd64",
|
|
14
|
+
"sha256": "367343620a80f245eee54c13debf56dd9950c652db570aa4041bc2ae1704d351"
|
|
15
15
|
},
|
|
16
16
|
"linux-arm64": {
|
|
17
|
-
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.
|
|
18
|
-
"sha256": "
|
|
17
|
+
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.ff33f49/arkcli-0.1.17-beta.ff33f49-linux-arm64",
|
|
18
|
+
"sha256": "54f4de3039c2f1a0018c77d9ac720e029afc4fd86394b1e457dce043b907f46b"
|
|
19
19
|
},
|
|
20
20
|
"windows-amd64": {
|
|
21
|
-
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.
|
|
22
|
-
"sha256": "
|
|
21
|
+
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.ff33f49/arkcli-0.1.17-beta.ff33f49-windows-amd64.exe",
|
|
22
|
+
"sha256": "8fb5ee829685566031acdbaeb72f195dc2a0a7b38efb339e6098df8712098cf6"
|
|
23
23
|
},
|
|
24
24
|
"windows-arm64": {
|
|
25
|
-
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.
|
|
26
|
-
"sha256": "
|
|
25
|
+
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.ff33f49/arkcli-0.1.17-beta.ff33f49-windows-arm64.exe",
|
|
26
|
+
"sha256": "1b623830d7ee01c362414b4056b1ef63a68889abd427aec06f4dcb06e02fee4d"
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"skills": {
|
|
30
30
|
"primary": {
|
|
31
|
-
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.
|
|
32
|
-
"sha256": "
|
|
31
|
+
"url": "https://lf3-static.bytednsdoc.com/obj/eden-cn/psjryh/ljhwZthlaukjlkulzlp/dev/0.1.17-beta.ff33f49/skills.tar.gz",
|
|
32
|
+
"sha256": "26422ce55dac421a0ce4cd4d9905d5038f5aca8705802c1328935bfc5bebcbf7",
|
|
33
33
|
"kind": "cdn"
|
|
34
34
|
},
|
|
35
|
-
"tag": "v0.1.17-beta.
|
|
35
|
+
"tag": "v0.1.17-beta.ff33f49"
|
|
36
36
|
}
|
|
37
37
|
}
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @volcengine/ark-cli postinstall。
|
|
3
3
|
// 由 npm 的 postinstall lifecycle 触发:读 manifest.json,按当前平台从 CDN 下载
|
|
4
|
-
// 对应二进制,校验 sha256,落到 <pkg>/bin/,然后(
|
|
4
|
+
// 对应二进制,校验 sha256,落到 <pkg>/bin/,然后(非 CI 时)调 `arkcli +connect
|
|
5
|
+
// --refresh` —— 由二进制【收口的 Go 实现】下载最新 skill 到 <pkg>/skills/ 再装进
|
|
6
|
+
// 各 agent。skill 的下载/解压/校验逻辑不再在本脚本维护(避免 node / Go 两份),
|
|
7
|
+
// 与用户手动 `arkcli +connect --refresh` 重装/刷新【共用同一份实现】。
|
|
5
8
|
//
|
|
6
9
|
// 与内场 postinstall 的区别(对外洁净契约):
|
|
7
10
|
// - 无 TEA 埋点
|
|
@@ -10,7 +13,7 @@
|
|
|
10
13
|
//
|
|
11
14
|
// 失败策略:
|
|
12
15
|
// - 下载/校验二进制 = 核心,失败则 exit 1(没有二进制这个包不可用,fail loud)
|
|
13
|
-
// - +connect 装
|
|
16
|
+
// - +connect --refresh(下 skill + 装 agent) = 增强,失败仅告警,不影响安装结果(exit 0)
|
|
14
17
|
|
|
15
18
|
const fs = require("fs");
|
|
16
19
|
const path = require("path");
|
|
@@ -18,7 +21,6 @@ const http = require("http");
|
|
|
18
21
|
const https = require("https");
|
|
19
22
|
const crypto = require("crypto");
|
|
20
23
|
const { execFileSync } = require("child_process");
|
|
21
|
-
const os = require("os");
|
|
22
24
|
|
|
23
25
|
// —— 逃生阀 ——
|
|
24
26
|
if (process.env.ARKCLI_SKIP_POSTINSTALL === "1") {
|
|
@@ -99,134 +101,6 @@ function sha256(file) {
|
|
|
99
101
|
return crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex");
|
|
100
102
|
}
|
|
101
103
|
|
|
102
|
-
// —— skill 安装(Phase 2:对外 skill 不内嵌,运行时下载到 <pkg>/skills/)——
|
|
103
|
-
// 候选源顺序:ARKCLI_SKILLS_URL(逃生阀) > manifest.skills.primary(CDN,强 sha)
|
|
104
|
-
// > manifest.skills.fallback(GitHub archive,结构校验)。任一成功即停。
|
|
105
|
-
// 全失败仅告警不阻断(skill 是 agent 增强,二进制才是核心;且 GitHub 国内不稳是已知风险)。
|
|
106
|
-
|
|
107
|
-
// skills 目录有效性:含至少一个 <name>/SKILL.md。
|
|
108
|
-
function isSkillsDir(p) {
|
|
109
|
-
try {
|
|
110
|
-
for (const e of fs.readdirSync(p, { withFileTypes: true })) {
|
|
111
|
-
if (e.isDirectory() && fs.existsSync(path.join(p, e.name, "SKILL.md"))) return true;
|
|
112
|
-
}
|
|
113
|
-
} catch (_) {}
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// 在解压根下定位 skills/ 目录:CDN tar 顶层就是 skills/;
|
|
118
|
-
// GitHub archive tarball 是 <repo>-<tag>/skills/(多一层前缀)。
|
|
119
|
-
function findSkillsDir(root) {
|
|
120
|
-
const direct = path.join(root, "skills");
|
|
121
|
-
if (isSkillsDir(direct)) return direct;
|
|
122
|
-
let entries = [];
|
|
123
|
-
try { entries = fs.readdirSync(root, { withFileTypes: true }); } catch (_) {}
|
|
124
|
-
for (const e of entries) {
|
|
125
|
-
if (e.isDirectory()) {
|
|
126
|
-
const nested = path.join(root, e.name, "skills");
|
|
127
|
-
if (isSkillsDir(nested)) return nested;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// 解压前安全校验:不受信任归档(尤其 GitHub fallback 无 sha 强校验)可能塞越界/软链条目,
|
|
134
|
-
// 直接 tar -x 会写出到目标目录之外(路径穿越 / 软链攻击)。这里先 tar -t 列条目,
|
|
135
|
-
// 拒绝【绝对路径 / 含 .. 的路径 / 非「普通文件·目录」的条目(软链/硬链/设备等)】,通过才解压。
|
|
136
|
-
function assertSafeTar(tarPath) {
|
|
137
|
-
const names = execFileSync("tar", ["-tzf", tarPath], { encoding: "utf-8" });
|
|
138
|
-
for (const raw of names.split("\n")) {
|
|
139
|
-
const name = raw.trim();
|
|
140
|
-
if (!name) continue;
|
|
141
|
-
if (name.startsWith("/") || name.split("/").includes("..")) {
|
|
142
|
-
throw new Error(`unsafe path in skills archive: ${name}`);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
// tar -tvzf 行首是文件类型:- 普通文件 / d 目录 / l 软链 / h 硬链 / b,c,p,s 设备等。
|
|
146
|
-
const verbose = execFileSync("tar", ["-tvzf", tarPath], { encoding: "utf-8" });
|
|
147
|
-
for (const raw of verbose.split("\n")) {
|
|
148
|
-
const line = raw.trim();
|
|
149
|
-
if (!line) continue;
|
|
150
|
-
const type = line[0];
|
|
151
|
-
if (type !== "-" && type !== "d") {
|
|
152
|
-
throw new Error(`unsafe entry type '${type}' in skills archive: ${line}`);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function extractSkillsTo(tarPath, destSkillsDir) {
|
|
158
|
-
assertSafeTar(tarPath); // 不受信任归档:解压前校验路径与类型,防越界写 / 软链攻击
|
|
159
|
-
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "arkcli-skills-"));
|
|
160
|
-
try {
|
|
161
|
-
execFileSync("tar", ["-xzf", tarPath, "-C", tmp], { stdio: "ignore" });
|
|
162
|
-
const src = findSkillsDir(tmp);
|
|
163
|
-
if (!src) throw new Error("archive 内找不到有效 skills/(无 */SKILL.md)");
|
|
164
|
-
fs.rmSync(destSkillsDir, { recursive: true, force: true });
|
|
165
|
-
try {
|
|
166
|
-
fs.renameSync(src, destSkillsDir);
|
|
167
|
-
} catch (_) {
|
|
168
|
-
fs.cpSync(src, destSkillsDir, { recursive: true }); // 跨设备 rename 失败兜底
|
|
169
|
-
}
|
|
170
|
-
} finally {
|
|
171
|
-
fs.rmSync(tmp, { recursive: true, force: true });
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async function installSkillsFromSource(src, destSkillsDir) {
|
|
176
|
-
const tmpTar = path.join(os.tmpdir(), `arkcli-skills-${process.pid}.tar.gz`);
|
|
177
|
-
try {
|
|
178
|
-
await download(src.url, tmpTar);
|
|
179
|
-
if (src.sha256) {
|
|
180
|
-
const actual = sha256(tmpTar);
|
|
181
|
-
if (actual !== src.sha256) {
|
|
182
|
-
throw new Error(`sha256 mismatch (expected ${src.sha256}, got ${actual})`);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
extractSkillsTo(tmpTar, destSkillsDir);
|
|
186
|
-
if (!isSkillsDir(destSkillsDir)) {
|
|
187
|
-
throw new Error("解压后 skills/ 无 */SKILL.md(结构校验失败)");
|
|
188
|
-
}
|
|
189
|
-
} finally {
|
|
190
|
-
fs.rmSync(tmpTar, { force: true });
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
async function installSkills() {
|
|
195
|
-
const pkgDir = path.join(__dirname, "..");
|
|
196
|
-
const destSkillsDir = path.join(pkgDir, "skills");
|
|
197
|
-
const skills = manifest.skills;
|
|
198
|
-
const override = (process.env.ARKCLI_SKILLS_URL || "").trim();
|
|
199
|
-
|
|
200
|
-
// 候选源:override(逃生阀,无 sha) > primary(强 sha) > fallback(结构校验)。
|
|
201
|
-
const sources = [];
|
|
202
|
-
if (override) sources.push({ url: override, sha256: null, kind: "override" });
|
|
203
|
-
if (skills && skills.primary && skills.primary.url) {
|
|
204
|
-
sources.push({ url: skills.primary.url, sha256: skills.primary.sha256 || null, kind: skills.primary.kind || "primary" });
|
|
205
|
-
}
|
|
206
|
-
if (skills && skills.fallback && skills.fallback.url) {
|
|
207
|
-
sources.push({ url: skills.fallback.url, sha256: null, kind: skills.fallback.kind || "fallback" });
|
|
208
|
-
}
|
|
209
|
-
if (sources.length === 0) {
|
|
210
|
-
console.warn("@volcengine/ark-cli: manifest 无 skills 源,跳过 skill 下载(可稍后 arkcli +connect 手动补)");
|
|
211
|
-
return false;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
for (const src of sources) {
|
|
215
|
-
try {
|
|
216
|
-
console.log(`@volcengine/ark-cli: downloading skills from ${src.kind}...`);
|
|
217
|
-
await installSkillsFromSource(src, destSkillsDir);
|
|
218
|
-
console.log(`@volcengine/ark-cli: skills ready (${src.kind})`);
|
|
219
|
-
return true;
|
|
220
|
-
} catch (e) {
|
|
221
|
-
console.warn(`@volcengine/ark-cli: skill source ${src.kind} failed: ${e.message || e}`);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
console.warn(
|
|
225
|
-
"@volcengine/ark-cli: 所有 skill 源下载失败;稍后可跑 `arkcli +connect`,或设 ARKCLI_SKILLS_URL 指定镜像后重装",
|
|
226
|
-
);
|
|
227
|
-
return false;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
104
|
(async () => {
|
|
231
105
|
fs.mkdirSync(binDir, { recursive: true });
|
|
232
106
|
const tmp = `${binPath}.download`;
|
|
@@ -265,33 +139,36 @@ async function installSkills() {
|
|
|
265
139
|
process.exit(0);
|
|
266
140
|
}
|
|
267
141
|
|
|
268
|
-
// ——
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// —— +connect 把 skill 装到各 agent:增强项,失败不影响安装结果 ——
|
|
276
|
-
// 无 controlling tty 时静默跳过(管道 / Windows 无 /dev/tty 等)。
|
|
142
|
+
// —— +connect --refresh:下载最新 skill 到 <pkg>/skills/ 再装进各 agent ——
|
|
143
|
+
// skill 的下载/解压/校验【收口在 Go 二进制】(internal/skillfs.Refresh),postinstall
|
|
144
|
+
// 不再自己下 skill。+connect 非交互(自动检测 agent + 全装),有/无 tty 都能跑:有
|
|
145
|
+
// tty 时把日志接到 /dev/tty(体验更好),无 tty 时走默认 stdio(connect 不读 stdin、
|
|
146
|
+
// 不会卡)。整体是【增强项】:下载或安装失败仅告警,不影响包安装结果(exit 0)。
|
|
277
147
|
let ttyFd = null;
|
|
278
148
|
try {
|
|
279
149
|
ttyFd = fs.openSync("/dev/tty", "r+");
|
|
280
150
|
} catch (_) {
|
|
281
|
-
//
|
|
282
|
-
}
|
|
283
|
-
if (ttyFd === null) {
|
|
284
|
-
process.exit(0);
|
|
151
|
+
// 无 controlling tty(管道 / Windows 无 /dev/tty 等)— 仍执行,只是输出走默认 stdio
|
|
285
152
|
}
|
|
153
|
+
const stdio = ttyFd !== null ? ["ignore", ttyFd, ttyFd] : "inherit";
|
|
286
154
|
try {
|
|
287
|
-
execFileSync(binPath, ["+connect"
|
|
155
|
+
execFileSync(binPath, ["+connect", "--refresh"], { stdio });
|
|
288
156
|
} catch (err) {
|
|
157
|
+
const msg =
|
|
158
|
+
`arkcli: skill 下载/安装跳过 (${err.message || err});` +
|
|
159
|
+
"稍后可手动跑 `arkcli +connect --refresh` 重新下载并安装";
|
|
160
|
+
if (ttyFd !== null) {
|
|
161
|
+
try {
|
|
162
|
+
fs.writeSync(ttyFd, msg + "\n");
|
|
163
|
+
} catch (_) {}
|
|
164
|
+
} else {
|
|
165
|
+
console.warn(msg);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (ttyFd !== null) {
|
|
289
169
|
try {
|
|
290
|
-
fs.
|
|
170
|
+
fs.closeSync(ttyFd);
|
|
291
171
|
} catch (_) {}
|
|
292
172
|
}
|
|
293
|
-
try {
|
|
294
|
-
fs.closeSync(ttyFd);
|
|
295
|
-
} catch (_) {}
|
|
296
173
|
process.exit(0);
|
|
297
174
|
})();
|