@webskill/sdk 0.0.5 → 0.1.0
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/README.md +180 -46
- package/dist/browser.d.ts +37 -2
- package/dist/browser.js +112 -3
- package/dist/{dist-D405AlPD.js → dist-CiYRkm71.js} +840 -1291
- package/dist/{dist-Ixnb-hNR.js → dist-DfKKj86A.js} +84 -2
- package/dist/{dist-BM-VcQ90.js → dist-Dv4a1Jkm.js} +226 -4
- package/dist/governance.d.ts +5 -3
- package/dist/governance.js +13 -4
- package/dist/{index-aEple804.d.ts → index-DuodMfQw.d.ts} +7 -1
- package/dist/{index-BQDc-U1x.d.ts → index-S8uza3ld.d.ts} +65 -540
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/mcp.d.ts +3 -1
- package/dist/mcp.js +3 -1
- package/dist/memoryArtifactStore-C9lFVqPF-U8nXvqL9.js +637 -0
- package/dist/node.d.ts +4 -3
- package/dist/node.js +3 -2
- package/dist/testing-pn3NhXSV.js +117 -0
- package/dist/testing.d.ts +73 -0
- package/dist/testing.js +4 -0
- package/dist/types-CgNC-oQu-DCklnS0h.d.ts +539 -0
- package/dist/ui-react.d.ts +2 -2
- package/dist/ui-react.js +12 -2
- package/dist/ui-vue.d.ts +2 -2
- package/dist/ui-vue.js +9 -2
- package/dist/ui.d.ts +30 -5
- package/dist/ui.js +3 -3
- package/package.json +5 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { D as verifyManifest, E as validateSkills, S as parseSkillPackManifest, T as resolveInsideRoot, _ as exportSkills, f as buildManifest, i as SKILL_MANIFEST_FILE, r as SKILLS_LOCKFILE, s as SKILL_PACK_FILE, u as WebSkillError, v as isValidSkillName, x as parseSkillMarkdown } from "./memoryArtifactStore-C9lFVqPF-U8nXvqL9.js";
|
|
2
|
+
import { A as normalizeToolContent, D as isNetworkAllowed, a as CapabilityApproval, b as bridgeError, c as FsMemoryStore, j as parseBridgeRequest, k as networkUrlHost, s as FsArtifactStore } from "./dist-CiYRkm71.js";
|
|
3
|
+
import { unzipSync, zipSync } from "fflate";
|
|
2
4
|
import { existsSync, promises, readFileSync } from "node:fs";
|
|
3
5
|
import path from "node:path";
|
|
4
6
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -8,7 +10,6 @@ import { parseSync } from "oxc-parser";
|
|
|
8
10
|
import { createInterface } from "node:readline/promises";
|
|
9
11
|
import { mkdtemp } from "node:fs/promises";
|
|
10
12
|
import { tmpdir } from "node:os";
|
|
11
|
-
import { unzipSync, zipSync } from "fflate";
|
|
12
13
|
import * as tar from "tar";
|
|
13
14
|
import { execFile } from "node:child_process";
|
|
14
15
|
import { createHash } from "node:crypto";
|
|
@@ -971,6 +972,15 @@ async function stageHttp(source, ctx, expectedSha256) {
|
|
|
971
972
|
await ctx.fs.writeBinary(archivePath, data);
|
|
972
973
|
await extractTarFile(toPlatform(archivePath), toPlatform(contentDir));
|
|
973
974
|
}
|
|
975
|
+
const packFilePath = `${contentDir}/${SKILL_PACK_FILE}`;
|
|
976
|
+
if (await ctx.fs.exists(packFilePath)) return {
|
|
977
|
+
skillDir: "",
|
|
978
|
+
source,
|
|
979
|
+
pack: {
|
|
980
|
+
contentDir,
|
|
981
|
+
manifest: parseSkillPackManifest(await ctx.fs.readText(packFilePath))
|
|
982
|
+
}
|
|
983
|
+
};
|
|
974
984
|
if (await ctx.fs.exists(`${contentDir}/SKILL.md`)) return {
|
|
975
985
|
skillDir: contentDir,
|
|
976
986
|
source
|
|
@@ -1117,6 +1127,7 @@ const asInstallFailed = (e) => e instanceof WebSkillError && e.code === "INSTALL
|
|
|
1117
1127
|
/**
|
|
1118
1128
|
* 技能管理门面:统一安装管线(staging → 解析 name → 校验 → 拷贝 → manifest → lockfile),
|
|
1119
1129
|
* 任何失败清理现场抛 INSTALL_FAILED。
|
|
1130
|
+
* @stable
|
|
1120
1131
|
*/
|
|
1121
1132
|
var SkillManager = class {
|
|
1122
1133
|
#managedRoot;
|
|
@@ -1157,6 +1168,7 @@ var SkillManager = class {
|
|
|
1157
1168
|
break;
|
|
1158
1169
|
case "archive": throw new WebSkillError("TOOL_UNSUPPORTED", "The \"archive\" install source is only supported by the browser skill manager");
|
|
1159
1170
|
}
|
|
1171
|
+
if (staged.pack) return (await this.#installPack(staged.pack, staged.source, stagingRoot))[0];
|
|
1160
1172
|
let name;
|
|
1161
1173
|
let version;
|
|
1162
1174
|
try {
|
|
@@ -1198,6 +1210,61 @@ var SkillManager = class {
|
|
|
1198
1210
|
}
|
|
1199
1211
|
}
|
|
1200
1212
|
/**
|
|
1213
|
+
* 包集安装:逐技能走单技能管线(归一 → 汇总校验 → 落 managed root → manifest → digest 比对)。
|
|
1214
|
+
* 任一失败整体回滚(删除本次已落目录;lockfile 在全部成功后才写入,天然零残留)。
|
|
1215
|
+
* 包是封闭产物:跳过安装期 schema 推导(sidecar 已随包携带,保证 digest 逐字节一致)。
|
|
1216
|
+
*/
|
|
1217
|
+
async #installPack(pack, source, stagingRoot) {
|
|
1218
|
+
const fs = this.#fs;
|
|
1219
|
+
const finalRoot = `${stagingRoot}/final`;
|
|
1220
|
+
const installed = [];
|
|
1221
|
+
try {
|
|
1222
|
+
const versions = /* @__PURE__ */ new Map();
|
|
1223
|
+
for (const entry of pack.manifest.skills) {
|
|
1224
|
+
const skillDir = `${pack.contentDir}/${entry.name}`;
|
|
1225
|
+
if (!await fs.exists(`${skillDir}/SKILL.md`)) throw new WebSkillError("INSTALL_FAILED", `Skill pack is missing a directory for skill "${entry.name}"`);
|
|
1226
|
+
let name;
|
|
1227
|
+
try {
|
|
1228
|
+
const { metadata } = parseSkillMarkdown(await fs.readText(`${skillDir}/SKILL.md`));
|
|
1229
|
+
name = metadata.name;
|
|
1230
|
+
versions.set(name, typeof metadata["version"] === "string" ? metadata["version"] : void 0);
|
|
1231
|
+
} catch (e) {
|
|
1232
|
+
throw new WebSkillError("INSTALL_FAILED", `Failed to read skill name from SKILL.md of pack entry "${entry.name}": ${messageOf(e)}`, e);
|
|
1233
|
+
}
|
|
1234
|
+
if (name !== entry.name) throw new WebSkillError("INSTALL_FAILED", `Skill pack entry "${entry.name}" does not match the SKILL.md name "${name}"`);
|
|
1235
|
+
await copyDir(fs, skillDir, `${finalRoot}/${name}`);
|
|
1236
|
+
}
|
|
1237
|
+
const report = await validateSkills(fs, [finalRoot]);
|
|
1238
|
+
if (!report.ok) {
|
|
1239
|
+
const errors = report.issues.filter((i) => i.severity === "error");
|
|
1240
|
+
throw new WebSkillError("INSTALL_FAILED", `Skill pack failed validation: ${errors.map((i) => i.message).join("; ")}`, errors);
|
|
1241
|
+
}
|
|
1242
|
+
const manifests = [];
|
|
1243
|
+
for (const entry of pack.manifest.skills) {
|
|
1244
|
+
const targetDir = `${this.#managedRoot}/${entry.name}`;
|
|
1245
|
+
if (await fs.exists(targetDir)) await fs.remove(targetDir, { recursive: true });
|
|
1246
|
+
await copyDir(fs, `${finalRoot}/${entry.name}`, targetDir);
|
|
1247
|
+
installed.push(targetDir);
|
|
1248
|
+
const manifest = await createManifest(fs, targetDir, {
|
|
1249
|
+
name: entry.name,
|
|
1250
|
+
...versions.get(entry.name) ? { version: versions.get(entry.name) } : {},
|
|
1251
|
+
source
|
|
1252
|
+
});
|
|
1253
|
+
if (manifest.integrity.digest !== entry.digest) throw new WebSkillError("INSTALL_FAILED", `Skill "${entry.name}" digest mismatch: expected ${entry.digest}, got ${manifest.integrity.digest}`);
|
|
1254
|
+
manifests.push(manifest);
|
|
1255
|
+
}
|
|
1256
|
+
for (const manifest of manifests) await upsertLockEntry(fs, this.#managedRoot, manifest.name, {
|
|
1257
|
+
digest: manifest.integrity.digest,
|
|
1258
|
+
installedAt: manifest.installedAt,
|
|
1259
|
+
source
|
|
1260
|
+
});
|
|
1261
|
+
return manifests;
|
|
1262
|
+
} catch (e) {
|
|
1263
|
+
for (const targetDir of installed) await removeDirQuiet(fs, targetDir);
|
|
1264
|
+
throw asInstallFailed(e);
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1201
1268
|
* D2 安装期预推导:scripts/ 下无显式 inputSchema 导出且无 sidecar 的脚本,
|
|
1202
1269
|
* 经 OXC 推导写 sidecar(计入 manifest.files;重装重新生成)
|
|
1203
1270
|
*/
|
|
@@ -1243,6 +1310,21 @@ var SkillManager = class {
|
|
|
1243
1310
|
if (!await this.#fs.exists(skillRoot)) throw new WebSkillError("EXPORT_FAILED", `Skill "${name}" is not installed`);
|
|
1244
1311
|
return exportArchive(this.#fs, skillRoot, options);
|
|
1245
1312
|
}
|
|
1313
|
+
/** 多技能包集导出(webskill.skill-pack.json + 各技能目录含 manifest),写 outPath 并返回 */
|
|
1314
|
+
async exportPack(names, options) {
|
|
1315
|
+
if (names.length === 0) throw new WebSkillError("EXPORT_FAILED", "exportPack requires at least one skill name");
|
|
1316
|
+
const roots = names.map((name) => {
|
|
1317
|
+
if (!isValidSkillName(name)) throw new WebSkillError("EXPORT_FAILED", `Invalid skill name (path traversal rejected): ${JSON.stringify(name)}`);
|
|
1318
|
+
return `${this.#managedRoot}/${name}`;
|
|
1319
|
+
});
|
|
1320
|
+
for (const [index, root] of roots.entries()) if (!await this.#fs.exists(root)) throw new WebSkillError("EXPORT_FAILED", `Skill "${names[index]}" is not installed`);
|
|
1321
|
+
const bytes = await exportSkills(this.#fs, {
|
|
1322
|
+
roots,
|
|
1323
|
+
manifestBuilder: (root) => readManifest(this.#fs, root)
|
|
1324
|
+
});
|
|
1325
|
+
await this.#fs.writeBinary(options.outPath, bytes);
|
|
1326
|
+
return options.outPath;
|
|
1327
|
+
}
|
|
1246
1328
|
};
|
|
1247
1329
|
/**
|
|
1248
1330
|
* 解析 .env(简单 KEY=VALUE 行解析,不引依赖),
|
|
@@ -190,9 +190,222 @@ function renderMiniMarkdown(text, doc) {
|
|
|
190
190
|
}
|
|
191
191
|
return root;
|
|
192
192
|
}
|
|
193
|
-
/**
|
|
193
|
+
/**
|
|
194
|
+
* 轻量 SVG 图表自绘(bar/line/pie,零依赖,三端复用单一来源)。
|
|
195
|
+
* 全部经 doc.createElementNS 构建(内容来自技能输出,不拼 innerHTML)。
|
|
196
|
+
*/
|
|
197
|
+
const SVG_NS = "http://www.w3.org/2000/svg";
|
|
198
|
+
/** 固定 8 色循环调色板 */
|
|
199
|
+
const CHART_PALETTE = [
|
|
200
|
+
"#4e79a7",
|
|
201
|
+
"#f28e2b",
|
|
202
|
+
"#e15759",
|
|
203
|
+
"#76b7b2",
|
|
204
|
+
"#59a14f",
|
|
205
|
+
"#edc948",
|
|
206
|
+
"#b07aa1",
|
|
207
|
+
"#ff9da7"
|
|
208
|
+
];
|
|
209
|
+
const WIDTH = 320;
|
|
210
|
+
const HEIGHT = 200;
|
|
211
|
+
function el(doc, name, attrs) {
|
|
212
|
+
const node = doc.createElementNS(SVG_NS, name);
|
|
213
|
+
for (const [key, value] of Object.entries(attrs)) node.setAttribute(key, value);
|
|
214
|
+
return node;
|
|
215
|
+
}
|
|
216
|
+
function text$1(doc, x, y, content, attrs = {}) {
|
|
217
|
+
const node = el(doc, "text", {
|
|
218
|
+
x: String(x),
|
|
219
|
+
y: String(y),
|
|
220
|
+
"font-size": "9",
|
|
221
|
+
fill: "#555",
|
|
222
|
+
...attrs
|
|
223
|
+
});
|
|
224
|
+
node.textContent = content;
|
|
225
|
+
return node;
|
|
226
|
+
}
|
|
227
|
+
const fmt = (n) => Number.isInteger(n) ? String(n) : n.toFixed(1);
|
|
228
|
+
function maxValue(chart) {
|
|
229
|
+
let max = 0;
|
|
230
|
+
for (const s of chart.series) for (const v of s.data) if (v > max) max = v;
|
|
231
|
+
return max;
|
|
232
|
+
}
|
|
233
|
+
function renderBar(chart, svg, doc) {
|
|
234
|
+
const plot = {
|
|
235
|
+
x0: 30,
|
|
236
|
+
y0: 24,
|
|
237
|
+
x1: 312,
|
|
238
|
+
y1: 164
|
|
239
|
+
};
|
|
240
|
+
const max = maxValue(chart);
|
|
241
|
+
svg.appendChild(el(doc, "line", {
|
|
242
|
+
x1: String(plot.x0),
|
|
243
|
+
y1: String(plot.y0),
|
|
244
|
+
x2: String(plot.x0),
|
|
245
|
+
y2: String(plot.y1),
|
|
246
|
+
stroke: "#999"
|
|
247
|
+
}));
|
|
248
|
+
svg.appendChild(el(doc, "line", {
|
|
249
|
+
x1: String(plot.x0),
|
|
250
|
+
y1: String(plot.y1),
|
|
251
|
+
x2: String(plot.x1),
|
|
252
|
+
y2: String(plot.y1),
|
|
253
|
+
stroke: "#999"
|
|
254
|
+
}));
|
|
255
|
+
if (max <= 0 || chart.labels.length === 0 || chart.series.length === 0) return;
|
|
256
|
+
const groupWidth = (plot.x1 - plot.x0) / chart.labels.length;
|
|
257
|
+
const barWidth = Math.max(1, groupWidth / chart.series.length * .7);
|
|
258
|
+
chart.series.forEach((series, si) => {
|
|
259
|
+
const color = CHART_PALETTE[si % CHART_PALETTE.length];
|
|
260
|
+
series.data.forEach((value, li) => {
|
|
261
|
+
if (li >= chart.labels.length) return;
|
|
262
|
+
const height = (plot.y1 - plot.y0) * value / max;
|
|
263
|
+
const x = plot.x0 + li * groupWidth + (groupWidth - barWidth * chart.series.length) / 2 + si * barWidth;
|
|
264
|
+
const y = plot.y1 - height;
|
|
265
|
+
svg.appendChild(el(doc, "rect", {
|
|
266
|
+
x: String(x),
|
|
267
|
+
y: String(y),
|
|
268
|
+
width: String(barWidth),
|
|
269
|
+
height: String(height),
|
|
270
|
+
fill: color,
|
|
271
|
+
"data-series": series.name ?? String(si)
|
|
272
|
+
}));
|
|
273
|
+
if (chart.series.length === 1) svg.appendChild(text$1(doc, x + barWidth / 2, y - 2, fmt(value), { "text-anchor": "middle" }));
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
chart.labels.forEach((label, li) => {
|
|
277
|
+
svg.appendChild(text$1(doc, plot.x0 + li * groupWidth + groupWidth / 2, plot.y1 + 12, label, { "text-anchor": "middle" }));
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
function renderLine(chart, svg, doc) {
|
|
281
|
+
const plot = {
|
|
282
|
+
x0: 30,
|
|
283
|
+
y0: 24,
|
|
284
|
+
x1: 312,
|
|
285
|
+
y1: 164
|
|
286
|
+
};
|
|
287
|
+
const max = maxValue(chart);
|
|
288
|
+
svg.appendChild(el(doc, "line", {
|
|
289
|
+
x1: String(plot.x0),
|
|
290
|
+
y1: String(plot.y0),
|
|
291
|
+
x2: String(plot.x0),
|
|
292
|
+
y2: String(plot.y1),
|
|
293
|
+
stroke: "#999"
|
|
294
|
+
}));
|
|
295
|
+
svg.appendChild(el(doc, "line", {
|
|
296
|
+
x1: String(plot.x0),
|
|
297
|
+
y1: String(plot.y1),
|
|
298
|
+
x2: String(plot.x1),
|
|
299
|
+
y2: String(plot.y1),
|
|
300
|
+
stroke: "#999"
|
|
301
|
+
}));
|
|
302
|
+
if (max <= 0 || chart.labels.length === 0 || chart.series.length === 0) return;
|
|
303
|
+
const step = chart.labels.length > 1 ? (plot.x1 - plot.x0) / (chart.labels.length - 1) : 0;
|
|
304
|
+
const px = (li) => chart.labels.length > 1 ? plot.x0 + li * step : (plot.x0 + plot.x1) / 2;
|
|
305
|
+
const py = (v) => plot.y1 - (plot.y1 - plot.y0) * v / max;
|
|
306
|
+
chart.series.forEach((series, si) => {
|
|
307
|
+
const color = CHART_PALETTE[si % CHART_PALETTE.length];
|
|
308
|
+
const points = series.data.slice(0, chart.labels.length).map((v, li) => `${px(li)},${py(v)}`).join(" ");
|
|
309
|
+
if (points !== "") svg.appendChild(el(doc, "polyline", {
|
|
310
|
+
points,
|
|
311
|
+
fill: "none",
|
|
312
|
+
stroke: color,
|
|
313
|
+
"stroke-width": "1.5"
|
|
314
|
+
}));
|
|
315
|
+
series.data.slice(0, chart.labels.length).forEach((v, li) => {
|
|
316
|
+
svg.appendChild(el(doc, "circle", {
|
|
317
|
+
cx: String(px(li)),
|
|
318
|
+
cy: String(py(v)),
|
|
319
|
+
r: "2",
|
|
320
|
+
fill: color
|
|
321
|
+
}));
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
chart.labels.forEach((label, li) => {
|
|
325
|
+
svg.appendChild(text$1(doc, px(li), plot.y1 + 12, label, { "text-anchor": "middle" }));
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
function renderPie(chart, svg, doc) {
|
|
329
|
+
const data = (chart.series[0]?.data ?? []).slice(0, chart.labels.length);
|
|
330
|
+
const total = data.reduce((sum, v) => sum + (v > 0 ? v : 0), 0);
|
|
331
|
+
const cx = 90;
|
|
332
|
+
const cy = 104;
|
|
333
|
+
const r = 72;
|
|
334
|
+
if (total <= 0) {
|
|
335
|
+
svg.appendChild(text$1(doc, cx, cy, "No data", { "text-anchor": "middle" }));
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
let angle = -Math.PI / 2;
|
|
339
|
+
data.forEach((value, i) => {
|
|
340
|
+
const label = chart.labels[i] ?? String(i);
|
|
341
|
+
const color = CHART_PALETTE[i % CHART_PALETTE.length];
|
|
342
|
+
const slice = Math.max(value, 0) / total * Math.PI * 2;
|
|
343
|
+
const x0 = cx + r * Math.cos(angle);
|
|
344
|
+
const y0 = cy + r * Math.sin(angle);
|
|
345
|
+
const x1 = cx + r * Math.cos(angle + slice);
|
|
346
|
+
const y1 = cy + r * Math.sin(angle + slice);
|
|
347
|
+
const path = el(doc, "path", {
|
|
348
|
+
d: `M ${cx} ${cy} L ${x0} ${y0} A ${r} ${r} 0 ${slice > Math.PI ? "1" : "0"} 1 ${x1} ${y1} Z`,
|
|
349
|
+
fill: color,
|
|
350
|
+
"data-label": label
|
|
351
|
+
});
|
|
352
|
+
svg.appendChild(path);
|
|
353
|
+
angle += slice;
|
|
354
|
+
const ly = 40 + i * 14;
|
|
355
|
+
svg.appendChild(el(doc, "rect", {
|
|
356
|
+
x: "190",
|
|
357
|
+
y: String(ly - 7),
|
|
358
|
+
width: "8",
|
|
359
|
+
height: "8",
|
|
360
|
+
fill: color
|
|
361
|
+
}));
|
|
362
|
+
svg.appendChild(text$1(doc, 202, ly, `${label} (${fmt(value)})`));
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* ChartSpec → SVG(bar 等宽柱 + 值标签;line 折线 + 点;pie 扇形 + 图例;空数据容错)
|
|
367
|
+
* @stable
|
|
368
|
+
*/
|
|
369
|
+
function renderMiniChart(chart, doc) {
|
|
370
|
+
const svg = el(doc, "svg", {
|
|
371
|
+
viewBox: `0 0 ${WIDTH} ${HEIGHT}`,
|
|
372
|
+
width: String(WIDTH),
|
|
373
|
+
height: String(HEIGHT),
|
|
374
|
+
class: `webskill-chart webskill-chart--${chart.kind}`,
|
|
375
|
+
role: "img"
|
|
376
|
+
});
|
|
377
|
+
if (chart.title) svg.appendChild(text$1(doc, WIDTH / 2, 14, chart.title, {
|
|
378
|
+
"text-anchor": "middle",
|
|
379
|
+
"font-size": "11",
|
|
380
|
+
fill: "#333"
|
|
381
|
+
}));
|
|
382
|
+
switch (chart.kind) {
|
|
383
|
+
case "bar":
|
|
384
|
+
renderBar(chart, svg, doc);
|
|
385
|
+
break;
|
|
386
|
+
case "line":
|
|
387
|
+
renderLine(chart, svg, doc);
|
|
388
|
+
break;
|
|
389
|
+
case "pie":
|
|
390
|
+
renderPie(chart, svg, doc);
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
return svg;
|
|
394
|
+
}
|
|
395
|
+
/** A2UI/OpenUI 降级:chart → table(labels 为首列,series 各为一列) */
|
|
396
|
+
function chartToTable(chart) {
|
|
397
|
+
return {
|
|
398
|
+
type: "table",
|
|
399
|
+
columns: ["label", ...chart.series.map((s, i) => s.name ?? `series ${i + 1}`)],
|
|
400
|
+
rows: chart.labels.map((label, li) => [label, ...chart.series.map((s) => s.data[li] ?? null)])
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
/** RenderBlock → DOM(markdown/json/table/image/file/chart 六种) */
|
|
194
404
|
function renderBlocks(container, blocks, doc) {
|
|
195
405
|
for (const block of blocks) switch (block.type) {
|
|
406
|
+
case "chart":
|
|
407
|
+
container.appendChild(renderMiniChart(block.chart, doc));
|
|
408
|
+
break;
|
|
196
409
|
case "markdown":
|
|
197
410
|
container.appendChild(renderMiniMarkdown(block.text, doc));
|
|
198
411
|
break;
|
|
@@ -517,6 +730,7 @@ function fieldStatements(fields) {
|
|
|
517
730
|
}
|
|
518
731
|
});
|
|
519
732
|
}
|
|
733
|
+
/** @experimental */
|
|
520
734
|
function toOpenUiLang(request) {
|
|
521
735
|
const lines = [];
|
|
522
736
|
let fields = [];
|
|
@@ -581,7 +795,10 @@ function toOpenUiLang(request) {
|
|
|
581
795
|
].join(", ")}])`);
|
|
582
796
|
return lines.join("\n");
|
|
583
797
|
}
|
|
584
|
-
/**
|
|
798
|
+
/**
|
|
799
|
+
* OpenUI ActionEvent → InteractionResponse(formState 优先,取消单独分支)
|
|
800
|
+
* @experimental
|
|
801
|
+
*/
|
|
585
802
|
function fromOpenUiAction(action) {
|
|
586
803
|
const a = action ?? {};
|
|
587
804
|
const id = String(a.params?.["id"] ?? "");
|
|
@@ -626,6 +843,7 @@ const text = (id, content, variant) => ({
|
|
|
626
843
|
text: content,
|
|
627
844
|
...variant ? { variant } : {}
|
|
628
845
|
});
|
|
846
|
+
/** @experimental */
|
|
629
847
|
function toA2uiMessages(request) {
|
|
630
848
|
const surfaceId = `webskill-${request.id}`;
|
|
631
849
|
const components = [];
|
|
@@ -751,7 +969,10 @@ function toA2uiMessages(request) {
|
|
|
751
969
|
});
|
|
752
970
|
return messages;
|
|
753
971
|
}
|
|
754
|
-
/**
|
|
972
|
+
/**
|
|
973
|
+
* A2UI client→server action 事件 → InteractionResponse
|
|
974
|
+
* @experimental
|
|
975
|
+
*/
|
|
755
976
|
function fromA2uiAction(event) {
|
|
756
977
|
const e = event ?? {};
|
|
757
978
|
const id = String(e.context?.["requestId"] ?? "");
|
|
@@ -15363,6 +15584,7 @@ const basicCatalog = new Catalog("https://a2ui.org/specification/v0_9/catalogs/b
|
|
|
15363
15584
|
*
|
|
15364
15585
|
* 版本对齐:渲染器 @a2ui/lit@0.10.x 经 v0_9 入口同时接受 v0.9 / v0.9.1 消息
|
|
15365
15586
|
* (schema 枚举 ['v0.9','v0.9.1']),与 7A v0.9.1 转换产物直接兼容。
|
|
15587
|
+
* @experimental
|
|
15366
15588
|
*/
|
|
15367
15589
|
var LitRendererBridge = class {
|
|
15368
15590
|
#mount;
|
|
@@ -15403,4 +15625,4 @@ var LitRendererBridge = class {
|
|
|
15403
15625
|
};
|
|
15404
15626
|
|
|
15405
15627
|
//#endregion
|
|
15406
|
-
export {
|
|
15628
|
+
export { renderRenderResult as C, toVercelToolInvocation as D, toOpenUiLang as E, renderMiniMarkdown as S, toA2uiMessages as T, fromOpenUiAction as _, CHART_PALETTE as a, renderBlocks as b, OPENUI_SUBMIT_ACTION as c, WEBSKILL_STYLES_CSS as d, WebFormBridge as f, fromA2uiAction as g, ensureStyles as h, A2UI_VERSION as i, VERCEL_INTERACTION_TOOL_NAME as l, collectValues as m, A2UI_CANCEL_ACTION as n, LitRendererBridge as o, chartToTable as p, A2UI_SUBMIT_ACTION as r, OPENUI_CANCEL_ACTION as s, A2UI_BASIC_CATALOG_ID as t, VercelUiBridge as u, fromVercelToolResult as v, shapeInteractionValue as w, renderMiniChart as x, interactionToFormModel as y };
|
package/dist/governance.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { L as SkillManifest, N as SkillDocument, S as FileSystemProvider, c as LlmClient, j as SkillCatalogEntry, u as LlmMessage, v as UiBridge } from "./types-CgNC-oQu-DCklnS0h.js";
|
|
2
|
+
import { U as RuntimeRun, it as WebSkillRuntime } from "./index-S8uza3ld.js";
|
|
3
|
+
import { d as SkillManager } from "./index-DuodMfQw.js";
|
|
3
4
|
//#region ../governance/dist/index.d.ts
|
|
4
5
|
//#region src/types.d.ts
|
|
5
6
|
type CandidateStatus = 'draft' | 'pending-review' | 'approved' | 'published' | 'rejected';
|
|
@@ -374,10 +375,11 @@ declare class SimilarityDetector {
|
|
|
374
375
|
}
|
|
375
376
|
//#endregion
|
|
376
377
|
//#region src/scoring/dependencyGraph.d.ts
|
|
377
|
-
/** 技能引用依赖图(references/ 中引用其他技能的声明关系) */
|
|
378
378
|
declare class DependencyGraph {
|
|
379
379
|
#private;
|
|
380
380
|
addDependency(from: string, to: string): void;
|
|
381
|
+
/** 从 frontmatter dependencies 声明建图(0.0.6 装配函数;只收录 Catalog 内技能之间的边) */
|
|
382
|
+
static buildFromCatalog(entries: SkillCatalogEntry[], documents: SkillDocument[]): DependencyGraph;
|
|
381
383
|
dependenciesOf(name: string): string[];
|
|
382
384
|
dependentsOf(name: string): string[];
|
|
383
385
|
}
|
package/dist/governance.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as NodeFS } from "./dist-
|
|
1
|
+
import { E as validateSkills, T as resolveInsideRoot, u as WebSkillError, v as isValidSkillName } from "./memoryArtifactStore-C9lFVqPF-U8nXvqL9.js";
|
|
2
|
+
import { i as NodeFS } from "./dist-DfKKj86A.js";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { mkdtemp } from "node:fs/promises";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
@@ -731,8 +731,7 @@ var SimilarityDetector = class {
|
|
|
731
731
|
for (const skill of existing) if (jaccardSimilarity(description, skill.description) >= this.#threshold) return skill.name;
|
|
732
732
|
}
|
|
733
733
|
};
|
|
734
|
-
|
|
735
|
-
var DependencyGraph = class {
|
|
734
|
+
var DependencyGraph = class DependencyGraph {
|
|
736
735
|
#edges = /* @__PURE__ */ new Map();
|
|
737
736
|
addDependency(from, to) {
|
|
738
737
|
if (from === to) return;
|
|
@@ -740,6 +739,16 @@ var DependencyGraph = class {
|
|
|
740
739
|
set.add(to);
|
|
741
740
|
this.#edges.set(from, set);
|
|
742
741
|
}
|
|
742
|
+
/** 从 frontmatter dependencies 声明建图(0.0.6 装配函数;只收录 Catalog 内技能之间的边) */
|
|
743
|
+
static buildFromCatalog(entries, documents) {
|
|
744
|
+
const names = new Set(entries.map((e) => e.name));
|
|
745
|
+
const graph = new DependencyGraph();
|
|
746
|
+
for (const doc of documents) {
|
|
747
|
+
if (!names.has(doc.metadata.name)) continue;
|
|
748
|
+
for (const dep of doc.metadata.dependencies ?? []) if (names.has(dep)) graph.addDependency(doc.metadata.name, dep);
|
|
749
|
+
}
|
|
750
|
+
return graph;
|
|
751
|
+
}
|
|
743
752
|
dependenciesOf(name) {
|
|
744
753
|
return [...this.#edges.get(name) ?? []].sort();
|
|
745
754
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as JsonSchema, H as SkillsLockfile, L as SkillManifest, P as SkillInstallSource, S as FileSystemProvider, W as VerifyResult, _ as RenderResultRequest, o as InteractionRequest, s as InteractionResponse, v as UiBridge, x as FileStat } from "./types-CgNC-oQu-DCklnS0h.js";
|
|
2
|
+
import { G as SchemaInferer, K as ScriptExecutionContext, Y as ToolDefinition, Z as ToolResult, c as ApprovalScope, k as NetworkPolicy, l as BridgeCapabilities, q as ScriptExecutor, v as FsArtifactStore, y as FsMemoryStore } from "./index-S8uza3ld.js";
|
|
2
3
|
import { Readable, Writable } from "node:stream";
|
|
3
4
|
//#region ../node/dist/index.d.ts
|
|
4
5
|
//#region src/fs/nodeFs.d.ts
|
|
@@ -134,6 +135,7 @@ declare class CliUiBridge implements UiBridge {
|
|
|
134
135
|
/**
|
|
135
136
|
* 技能管理门面:统一安装管线(staging → 解析 name → 校验 → 拷贝 → manifest → lockfile),
|
|
136
137
|
* 任何失败清理现场抛 INSTALL_FAILED。
|
|
138
|
+
* @stable
|
|
137
139
|
*/
|
|
138
140
|
declare class SkillManager {
|
|
139
141
|
#private;
|
|
@@ -154,6 +156,10 @@ declare class SkillManager {
|
|
|
154
156
|
format: 'zip' | 'tar';
|
|
155
157
|
outPath: string;
|
|
156
158
|
}): Promise<string>;
|
|
159
|
+
/** 多技能包集导出(webskill.skill-pack.json + 各技能目录含 manifest),写 outPath 并返回 */
|
|
160
|
+
exportPack(names: string[], options: {
|
|
161
|
+
outPath: string;
|
|
162
|
+
}): Promise<string>;
|
|
157
163
|
}
|
|
158
164
|
//#endregion
|
|
159
165
|
//#region src/skillManagement/export/archiveExporter.d.ts
|