@webskill/sdk 0.13.0 → 0.15.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.
Files changed (60) hide show
  1. package/dist/agent.d.ts +3 -3
  2. package/dist/agent.js +2442 -3
  3. package/dist/{dist-ExSQky4C.js → approval-BnLLCOG0.js} +277 -2934
  4. package/dist/browser.d.ts +327 -8
  5. package/dist/browser.js +1017 -51
  6. package/dist/{openUiLibrary-BKXW7Iwx-CWWBVOkE.js → dist-CTsxblSD.js} +496 -28
  7. package/dist/{echarts-De78wXqV.js → echarts-BE7oV_Dl.js} +1 -1
  8. package/dist/{env-8cY40DXB-CGnEVZby.js → env-Bj1MI2Ww.js} +1 -1
  9. package/dist/errors-BDZNpC13.js +22 -0
  10. package/dist/{eventTypes-FllCrX-Z-DNDeHWoG.js → eventTypes-Y07N8IAC.js} +14 -2
  11. package/dist/external-_ZRQe-V9.js +53 -0
  12. package/dist/governance.d.ts +15 -3
  13. package/dist/governance.js +86 -4
  14. package/dist/{index-iBm9tJL_.d.ts → index-CQYo4tcT.d.ts} +469 -10
  15. package/dist/{index-C3XdItd_.d.ts → index-CU2md8R1.d.ts} +26 -18
  16. package/dist/{index-DkvBhJQy.d.ts → index-Oc3H89TJ.d.ts} +204 -4
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.js +1001 -5
  19. package/dist/kind-DxgS8LM-.js +77 -0
  20. package/dist/linkedDocument-xNXF-z8n.js +94 -0
  21. package/dist/llm-B7lLH0ZI.js +1767 -0
  22. package/dist/mcp.d.ts +56 -3
  23. package/dist/mcp.js +75 -5
  24. package/dist/memoryArtifactStore-D6dLeY55.js +48 -0
  25. package/dist/miniChart-owdCdaw-.js +533 -0
  26. package/dist/node.d.ts +3 -3
  27. package/dist/node.js +110 -13
  28. package/dist/openUiLibrary-CY_ADoe0.js +30 -0
  29. package/dist/openUiSpecLang-DuOCdw9G.js +1849 -0
  30. package/dist/pathSecurity-B1owvJAF.js +65 -0
  31. package/dist/processSandboxEntry.js +5 -1
  32. package/dist/renderResult-D9Q-Vu2x.js +143 -0
  33. package/dist/{rolldown-runtime-BOF7iYI8.js → rolldown-runtime-BHkdefai.js} +1 -2
  34. package/dist/sandboxWorkerEntry.js +5 -1
  35. package/dist/{dist-Bev6i6Ip.js → skill-CAJMsLod.js} +44 -314
  36. package/dist/{skillVersionStore-D-qHk9ZE-DheTIwAB.d.ts → skillVersionStore-B24Jjjry-C4zomhMZ.d.ts} +14 -2
  37. package/dist/surface-DVGiCmwq.js +145 -0
  38. package/dist/testing.d.ts +1 -1
  39. package/dist/testing.js +64 -3
  40. package/dist/{types-DLctJep_-B5G4uk2u.d.ts → types-C3V6lAeO-BIf7UB2e.d.ts} +79 -4
  41. package/dist/types-TUydnxaj.js +78 -0
  42. package/dist/ui-react.d.ts +12 -5
  43. package/dist/ui-react.js +128548 -4729
  44. package/dist/ui-vue.d.ts +1 -1
  45. package/dist/ui-vue.js +11 -2
  46. package/dist/ui.d.ts +3 -3
  47. package/dist/ui.js +1254 -3
  48. package/dist/urlSafety-CiSuCJvX.js +65 -0
  49. package/dist/webSkillApi-DOOyz2G5.js +106 -0
  50. package/dist/{webskillLitCatalog-D_zCqeQF-C9lrvvMr.js → webskillLitCatalog-DSqVFQjK.js} +11 -3
  51. package/package.json +1 -1
  52. package/dist/catalogComponents-BgAJN0p8-CYEXSk45.js +0 -124384
  53. package/dist/client-BCM6Z3yq-qUQNkKrK.js +0 -7787
  54. package/dist/dist-DqcL6jKO.js +0 -3509
  55. package/dist/dist-DxyxmXPU-DGC-dpXf.js +0 -5621
  56. package/dist/dist-GK6dtjRv.js +0 -1493
  57. package/dist/memoryArtifactStore-52Zn9npI-LbCQaqyx.js +0 -86
  58. package/dist/stdio-CFMoANJJ-BxrTeXh7.js +0 -31
  59. package/dist/testing-WPTyXQYt.js +0 -142
  60. package/dist/types-WovEf4ED-CZSDiiBU.js +0 -6215
@@ -0,0 +1,65 @@
1
+ import { t as WebSkillError } from "./errors-BDZNpC13.js";
2
+
3
+ //#region ../core/src/fs/atomicWrite.ts
4
+ /**
5
+ * 原子写的临时文件名后缀模式;列举/打包侧据此排除中断残留(0.9.0 分册 11)。
6
+ * 单一来源:不要在别处手写正则(AC-G10),复制正则必然漂移。
7
+ * @stable
8
+ */
9
+ const ATOMIC_TMP_SUFFIX_PATTERN = /\.tmp-\d+-[a-z0-9]+$/;
10
+ /** 该路径是否是 atomicWriteText 留下的临时文件 */
11
+ const isAtomicTempPath = (path) => ATOMIC_TMP_SUFFIX_PATTERN.test(path);
12
+ /**
13
+ * 原子写文本:先写临时文件再 rename(进程崩溃不留下半写文件;lockfile 等账本场景)。
14
+ * 原子性强弱取决于 provider 的 rename 实现:NodeFS/MemoryFS 为真 rename;
15
+ * OPFS 无原生 move,rename 是 copy+delete(非原子,崩溃可能残留双份),
16
+ * 对崩溃一致性要求极高的场景在浏览器侧需知悉此前提。
17
+ */
18
+ async function atomicWriteText(fs, path, content) {
19
+ const tmp = `${path}.tmp-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
20
+ await fs.writeText(tmp, content);
21
+ await fs.rename(tmp, path);
22
+ }
23
+
24
+ //#endregion
25
+ //#region ../core/src/fs/pathSecurity.ts
26
+ /** 统一分隔符为 `/`,去除 `.` 段与重复分隔符(不解析 `..`) */
27
+ function normalizePath(path) {
28
+ return path.replace(/\\/g, "/").split("/").filter((s) => s !== "" && s !== ".").join("/");
29
+ }
30
+ /**
31
+ * 外部标识(runId、candidateId、skillName、versionId 等)作为单一路径段使用前的统一校验:
32
+ * 拒绝空串、`.`、`..`、含 `/` 或 `\`、含 `:`(Windows 盘符/ADS)。
33
+ * 违规抛 FS_PATH_OUTSIDE_ROOT(kind 用于错误消息定位,如 "runId")。
34
+ */
35
+ const CONTROL_CHARS_RE = /[\x00-\x1f\x7f]/;
36
+ function assertSafePathSegment(segment, kind) {
37
+ if (CONTROL_CHARS_RE.test(segment)) throw new WebSkillError("FS_PATH_OUTSIDE_ROOT", `Invalid ${kind} (control characters including NUL are not allowed): ${JSON.stringify(segment)}`);
38
+ if (segment === "" || segment === "." || segment === ".." || segment.includes("/") || segment.includes("\\") || segment.includes(":")) throw new WebSkillError("FS_PATH_OUTSIDE_ROOT", `Invalid ${kind} (must be a single safe path segment): ${JSON.stringify(segment)}`);
39
+ }
40
+ /**
41
+ * 将相对路径安全地解析到 root 之内。
42
+ * 拒绝空路径、绝对路径(`/`、`\\`、`C:\` 形式)与任何 `..` 段。
43
+ *
44
+ * 注意:本函数仅做**词法**校验,不解析符号链接——root 内经符号链接指向
45
+ * 外部的目标无法被词法检查拦截(realpath 防护见 NodeFS root 模式与
46
+ * 安装管线的 lstat 符号链接扫描)。
47
+ */
48
+ function resolveInsideRoot(root, relativePath) {
49
+ const fail = (reason) => {
50
+ throw new WebSkillError("FS_PATH_OUTSIDE_ROOT", `Path outside root: ${reason} (path: ${JSON.stringify(relativePath)})`);
51
+ };
52
+ if (relativePath.trim() === "") fail("empty path");
53
+ if (relativePath.startsWith("/") || relativePath.startsWith("\\") || /^[a-zA-Z]:[\\/]/.test(relativePath)) fail("absolute paths not allowed");
54
+ const segments = relativePath.replace(/\\/g, "/").split("/");
55
+ if (CONTROL_CHARS_RE.test(relativePath)) fail("control characters including NUL are not allowed");
56
+ if (segments.some((s) => s === "..")) fail("`..` segments not allowed");
57
+ const clean = segments.filter((s) => s !== "" && s !== ".");
58
+ if (clean.length === 0) fail("path resolves to empty");
59
+ const normalizedRoot = normalizePath(root);
60
+ const joined = normalizedRoot === "" ? clean.join("/") : `${normalizedRoot}/${clean.join("/")}`;
61
+ return root.startsWith("/") || root.startsWith("\\") ? `/${joined}` : joined;
62
+ }
63
+
64
+ //#endregion
65
+ export { atomicWriteText as a, ATOMIC_TMP_SUFFIX_PATTERN as i, normalizePath as n, isAtomicTempPath as o, resolveInsideRoot as r, assertSafePathSegment as t };
@@ -177,7 +177,11 @@ async function main(task) {
177
177
  mimeType: options?.mimeType,
178
178
  metadata: options?.metadata
179
179
  }),
180
- confirm: (message) => callCapability("confirm", { message })
180
+ confirm: (message) => callCapability("confirm", { message }),
181
+ ...task.uploadFiles ? {
182
+ listUploadFiles: () => callCapability("listUploadFiles", {}),
183
+ readUploadFile: async (fileId) => new Uint8Array(await callCapability("readUploadFile", { fileId }))
184
+ } : {}
181
185
  };
182
186
  const runFn = mod["run"];
183
187
  const value = await runFn(task.args ?? {}, context);
@@ -0,0 +1,143 @@
1
+ import { t as WebSkillError } from "./errors-BDZNpC13.js";
2
+
3
+ //#region ../runtime/src/artifacts/metadataAdmission.ts
4
+ /**
5
+ * 产物 metadata 的准入与判读(分册 18)。
6
+ *
7
+ * metadata 是能力桥上第一个**开放结构**的入参,且来自沙箱内的技能脚本。
8
+ * 校验落在 `createScriptContext.writeArtifact`——它是 in-process 与三个沙箱执行器
9
+ * 唯一的汇聚点,在此抛错才能带上正确的桥请求 id 回给脚本(DV-10)。
10
+ */
11
+ /** 序列化后的字节上限;`index.json` 是整覆盖原子写,无上限等于廉价的放大面 */
12
+ const ARTIFACT_METADATA_MAX_BYTES = 4096;
13
+ /** 原型污染键;JSON 解析产生的同名键是**自有键**,可被 getOwnPropertyNames 查出 */
14
+ const FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
15
+ "__proto__",
16
+ "constructor",
17
+ "prototype"
18
+ ]);
19
+ function isPlainObject(value) {
20
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
21
+ const proto = Object.getPrototypeOf(value);
22
+ return proto === Object.prototype || proto === null;
23
+ }
24
+ /** 函数声明而非箭头函数赋值:只有前者能让 TS 的控制流分析认到 never 终止 */
25
+ function reject(message) {
26
+ throw new WebSkillError("VALIDATION_FAILED", message);
27
+ }
28
+ /**
29
+ * 递归拒绝原型污染键与不可序列化值。
30
+ * `JSON.stringify` 会**静默丢弃**函数与 symbol,而静默正是本需求明令禁止的形态,
31
+ * 所以必须在序列化之前显式查一遍。
32
+ */
33
+ function assertSerializableShape(value, path, seen) {
34
+ const kind = typeof value;
35
+ if (kind === "function" || kind === "symbol" || kind === "bigint") reject(`Artifact metadata value at "${path}" is not JSON-serializable (${kind})`);
36
+ if (kind !== "object" || value === null) return;
37
+ const container = value;
38
+ if (seen.has(container)) reject(`Artifact metadata contains a circular reference at "${path}"`);
39
+ seen.add(container);
40
+ if (Array.isArray(value)) value.forEach((item, index) => assertSerializableShape(item, `${path}[${index}]`, seen));
41
+ else {
42
+ if (!isPlainObject(value)) reject(`Artifact metadata value at "${path}" must be a plain object or array`);
43
+ for (const key of Object.getOwnPropertyNames(value)) {
44
+ if (FORBIDDEN_KEYS.has(key)) reject(`Artifact metadata must not contain the reserved key "${key}" (at "${path}")`);
45
+ assertSerializableShape(value[key], `${path}.${key}`, seen);
46
+ }
47
+ }
48
+ seen.delete(container);
49
+ }
50
+ /**
51
+ * 准入校验。通过后返回 `JSON.parse(JSON.stringify(...))` 的副本:
52
+ * in-process 路径由此获得与 JSON stdio 沙箱路径完全相同的语义,
53
+ * 而不是依赖某条传输链路碰巧做了序列化。
54
+ */
55
+ function admitArtifactMetadata(value) {
56
+ if (!isPlainObject(value)) reject("Artifact metadata must be a plain object");
57
+ assertSerializableShape(value, "metadata", /* @__PURE__ */ new Set());
58
+ let json;
59
+ try {
60
+ json = JSON.stringify(value);
61
+ } catch (error) {
62
+ reject(`Artifact metadata is not JSON-serializable: ${error.message}`);
63
+ }
64
+ const bytes = new TextEncoder().encode(json).length;
65
+ if (bytes > 4096) reject(`Artifact metadata is too large: ${bytes} bytes exceeds the ${ARTIFACT_METADATA_MAX_BYTES} byte limit`);
66
+ return JSON.parse(json);
67
+ }
68
+ /**
69
+ * 「这份产物不出自动下载卡」的判读。**严格 `=== false`**:
70
+ * 隐式真值转换会让写错的键值静默生效,而隐藏是不可见的失败。
71
+ * `buildRenderResult` 与 agentLoop 的去重集合共用本函数,两处判据不得分叉。
72
+ */
73
+ function isArtifactCardHidden(artifact) {
74
+ return artifact.metadata?.["resultCard"] === false;
75
+ }
76
+
77
+ //#endregion
78
+ //#region ../runtime/src/interaction/renderResult.ts
79
+ const isRecord = (v) => typeof v === "object" && v !== null;
80
+ /**
81
+ * $chart 约定的形状校验:JSON content 的 data 含 $chart 键且形状合法 → ChartSpec;
82
+ * 任何畸形(kind 非法 / labels 非字符串数组 / series 项缺数值 data)→ undefined(忽略不炸)。
83
+ */
84
+ function extractChartSpec(data) {
85
+ if (!isRecord(data)) return void 0;
86
+ const raw = data["$chart"];
87
+ if (!isRecord(raw)) return void 0;
88
+ const { kind, labels, series } = raw;
89
+ if (kind !== "bar" && kind !== "line" && kind !== "pie") return void 0;
90
+ if (!Array.isArray(labels) || !labels.every((l) => typeof l === "string")) return void 0;
91
+ if (!Array.isArray(series)) return void 0;
92
+ const validSeries = [];
93
+ for (const item of series) {
94
+ if (!isRecord(item) || !Array.isArray(item["data"]) || !item["data"].every((n) => typeof n === "number")) return;
95
+ const name = item["name"];
96
+ validSeries.push({
97
+ ...typeof name === "string" ? { name } : {},
98
+ data: item["data"]
99
+ });
100
+ }
101
+ const title = raw["title"];
102
+ return {
103
+ kind,
104
+ labels,
105
+ series: validSeries,
106
+ ...typeof title === "string" ? { title } : {}
107
+ };
108
+ }
109
+ /**
110
+ * 默认的结果渲染构造:run 内收集的 renderBlocks(chart 等)在前,
111
+ * LLM 最终输出 → markdown block,run.artifacts → file blocks 在后;summary 取 terminationReason。
112
+ * 注入 output block 时一并记下它的下标(S7),供消费方按来源去重。
113
+ */
114
+ function buildRenderResult(run, output, renderBlocks = []) {
115
+ const blocks = [...renderBlocks];
116
+ let outputBlockIndex;
117
+ if (output.trim() !== "") {
118
+ outputBlockIndex = blocks.length;
119
+ blocks.push({
120
+ type: "markdown",
121
+ text: output
122
+ });
123
+ }
124
+ for (const artifact of run.artifacts) {
125
+ if (isArtifactCardHidden(artifact)) continue;
126
+ blocks.push({
127
+ type: "file",
128
+ path: artifact.path,
129
+ ...artifact.mimeType ? { mimeType: artifact.mimeType } : {},
130
+ size: artifact.size
131
+ });
132
+ }
133
+ return {
134
+ runId: run.id,
135
+ summary: run.terminationReason,
136
+ blocks,
137
+ artifacts: run.artifacts,
138
+ ...outputBlockIndex === void 0 ? {} : { outputBlockIndex }
139
+ };
140
+ }
141
+
142
+ //#endregion
143
+ export { isArtifactCardHidden as i, extractChartSpec as n, admitArtifactMetadata as r, buildRenderResult as t };
@@ -43,7 +43,6 @@ var __copyProps = (to, from, except, desc) => {
43
43
  }
44
44
  return to;
45
45
  };
46
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
47
46
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
48
47
  value: mod,
49
48
  enumerable: true
@@ -52,4 +51,4 @@ var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["modu
52
51
  var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
53
52
 
54
53
  //#endregion
55
- export { __require as a, __reExport as i, __esmMin as n, __toCommonJS as o, __exportAll as r, __toESM as s, __commonJSMin as t };
54
+ export { __toCommonJS as a, __require as i, __esmMin as n, __toESM as o, __exportAll as r, __commonJSMin as t };
@@ -238,7 +238,11 @@ async function main() {
238
238
  mimeType: options?.mimeType,
239
239
  metadata: options?.metadata
240
240
  }),
241
- confirm: (message) => callCapability("confirm", { message })
241
+ confirm: (message) => callCapability("confirm", { message }),
242
+ ...task.uploadFiles ? {
243
+ listUploadFiles: () => callCapability("listUploadFiles", {}),
244
+ readUploadFile: async (fileId) => new Uint8Array(await callCapability("readUploadFile", { fileId }))
245
+ } : {}
242
246
  };
243
247
  const runFn = mod["run"];
244
248
  const value = await runFn(task.args ?? {}, context);