@webskill/sdk 0.2.2 → 0.2.4

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.
@@ -111,6 +111,18 @@ var MemoryFS = class {
111
111
  async writeText(path, content) {
112
112
  await this.writeBinary(path, new TextEncoder().encode(content));
113
113
  }
114
+ async appendText(path, content) {
115
+ const key = this.#normalize(path);
116
+ const existing = this.#entries.get(key);
117
+ if (existing && existing.type !== "file") throw new WebSkillError("FS_PERMISSION_DENIED", `Cannot append to a directory: ${key}`);
118
+ const prior = existing ? new TextDecoder().decode(existing.content) : "";
119
+ this.#ensureParents(key);
120
+ this.#entries.set(key, {
121
+ type: "file",
122
+ content: new TextEncoder().encode(prior + content),
123
+ mtimeMs: Date.now()
124
+ });
125
+ }
114
126
  async readBinary(path) {
115
127
  return this.#getFile(this.#normalize(path)).content;
116
128
  }
@@ -203,7 +215,9 @@ function normalizePath(path) {
203
215
  * 拒绝空串、`.`、`..`、含 `/` 或 `\`、含 `:`(Windows 盘符/ADS)。
204
216
  * 违规抛 FS_PATH_OUTSIDE_ROOT(kind 用于错误消息定位,如 "runId")。
205
217
  */
218
+ const CONTROL_CHARS_RE = /[\x00-\x1f\x7f]/;
206
219
  function assertSafePathSegment(segment, kind) {
220
+ 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)}`);
207
221
  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)}`);
208
222
  }
209
223
  /**
@@ -221,6 +235,7 @@ function resolveInsideRoot(root, relativePath) {
221
235
  if (relativePath.trim() === "") fail("empty path");
222
236
  if (relativePath.startsWith("/") || relativePath.startsWith("\\") || /^[a-zA-Z]:[\\/]/.test(relativePath)) fail("absolute paths not allowed");
223
237
  const segments = relativePath.replace(/\\/g, "/").split("/");
238
+ if (CONTROL_CHARS_RE.test(relativePath)) fail("control characters including NUL are not allowed");
224
239
  if (segments.some((s) => s === "..")) fail("`..` segments not allowed");
225
240
  const clean = segments.filter((s) => s !== "" && s !== ".");
226
241
  if (clean.length === 0) fail("path resolves to empty");
@@ -392,6 +407,7 @@ async function exportSkills(fs, input) {
392
407
  for (const root of input.roots) {
393
408
  const base = root.replace(/\/+$/, "");
394
409
  const manifest = await input.manifestBuilder(base);
410
+ if (!isValidSkillName(manifest.name)) throw new WebSkillError("EXPORT_FAILED", `Skill "${manifest.name}" has an invalid name and cannot be exported to a skill pack`);
395
411
  skills.push({
396
412
  name: manifest.name,
397
413
  digest: manifest.integrity.digest
@@ -427,7 +443,7 @@ function parseSkillPackManifest(text) {
427
443
  for (const entry of record["skills"]) {
428
444
  if (typeof entry !== "object" || entry === null) invalid("skill entry is not an object");
429
445
  const { name, digest } = entry;
430
- if (typeof name !== "string" || name === "") invalid("skill entry missing a valid \"name\"");
446
+ if (typeof name !== "string" || name === "" || !isValidSkillName(name)) invalid(`skill entry has an invalid name: ${JSON.stringify(name)}`);
431
447
  if (typeof digest !== "string" || digest === "") invalid(`skill "${name}" missing a valid "digest"`);
432
448
  }
433
449
  return raw;
@@ -468,6 +484,14 @@ async function unzipWithLimits(data, limits) {
468
484
  const unzip = new Unzip();
469
485
  unzip.register(UnzipInflate);
470
486
  unzip.onfile = (file) => {
487
+ if (file.name.startsWith("/") || file.name.startsWith("\\") || /^[a-zA-Z]:[\\/]/.test(file.name)) {
488
+ failure = new WebSkillError("INSTALL_FAILED", `Archive entry escapes the destination root: ${file.name}`);
489
+ return;
490
+ }
491
+ if (file.name.replace(/\\/g, "/").split("/").some((s) => s === "..") || /[\x00-\x1f\x7f]/.test(file.name)) {
492
+ failure = new WebSkillError("INSTALL_FAILED", `Archive entry escapes the destination root: ${file.name}`);
493
+ return;
494
+ }
471
495
  if (file.name.endsWith("/")) {
472
496
  entries.push([file.name, /* @__PURE__ */ new Uint8Array(0)]);
473
497
  return;
@@ -579,7 +603,7 @@ var SkillDiscovery = class {
579
603
  const candidates = [];
580
604
  const knownSkillNames = /* @__PURE__ */ new Set();
581
605
  const adjacency = /* @__PURE__ */ new Map();
582
- for (const root of this.#roots) {
606
+ for (const [rootIndex, root] of this.#roots.entries()) {
583
607
  if (!await this.#fs.exists(root)) {
584
608
  issues.push({
585
609
  code: "FS_NOT_FOUND",
@@ -604,6 +628,7 @@ var SkillDiscovery = class {
604
628
  candidates.push({
605
629
  dirName,
606
630
  skillRoot,
631
+ rootIndex,
607
632
  hasSkillMd,
608
633
  metadata,
609
634
  parseError,
@@ -616,6 +641,7 @@ var SkillDiscovery = class {
616
641
  }
617
642
  }));
618
643
  }
644
+ candidates.sort((a, b) => a.rootIndex - b.rootIndex || a.dirName.localeCompare(b.dirName));
619
645
  const cycles = checkDependencyCycles(adjacency);
620
646
  const claimedNames = /* @__PURE__ */ new Set();
621
647
  for (const candidate of candidates) {
@@ -1,6 +1,6 @@
1
- import { F as SkillDocument, N as SkillCatalogEntry, c as LlmClient, u as LlmMessage, v as UiBridge, w as FileSystemProvider, z as SkillManifest } from "./types-CKm5G_eQ-8W8FnP4u.js";
2
- import { Q as ScriptExecutor, dt as WebSkillRuntime, ft as WebSkillRuntimeDeps, q as RuntimeRun, tt as SkillStateGuard } from "./index-gjFuBevI.js";
3
- import { d as SkillManager } from "./index-BmzysJX5.js";
1
+ import { F as SkillDocument, N as SkillCatalogEntry, c as LlmClient, u as LlmMessage, v as UiBridge, w as FileSystemProvider, z as SkillManifest } from "./types-CKm5G_eQ-BqyXnvoR.js";
2
+ import { Q as ScriptExecutor, dt as WebSkillRuntime, ft as WebSkillRuntimeDeps, q as RuntimeRun, tt as SkillStateGuard } from "./index-DZShzhon.js";
3
+ import { d as SkillManager } from "./index-DrHelz72.js";
4
4
  //#region ../governance/dist/index.d.ts
5
5
  //#region src/types.d.ts
6
6
  type CandidateStatus = 'draft' | 'pending-review' | 'approved' | 'published' | 'rejected';
@@ -209,7 +209,12 @@ interface AuditChainVerification {
209
209
  brokenAt?: number;
210
210
  reason?: string;
211
211
  }
212
- /** JSONL 追加的审计日志:<managedRoot>/.webskill/audit.jsonl;跨实例可恢复查询;prevHash 链可校验完整性 */
212
+ /**
213
+ * JSONL 追加式审计日志(<managedRoot>/.webskill/audit.jsonl):
214
+ * 真追加(fs.appendText,不整读改写)+ lastHash 内存缓存(同实例不重读)。
215
+ * 语义:**tamper-evident, not tamper-proof**——verifyChain 能检出篡改/删除/换序,
216
+ * 但不阻止有写权限者直接改写文件;更强保证需要签名信任体系(未排期)。
217
+ */
213
218
  declare class FsAuditLog implements AuditLog {
214
219
  #private;
215
220
  constructor(deps: {
@@ -360,8 +365,10 @@ declare class EvaluationRunner {
360
365
  //#region src/evaluation/evaluationRuntime.d.ts
361
366
  /**
362
367
  * 治理评估专用 runtime 装配(不可信技能试用路径):
363
- * 默认注入 ProcessSandboxExecutor(fork + --permission 真实进程隔离);
364
- * 可配置 executor 切回 SandboxedScriptExecutor(worker_threads 能力面收敛形态)。
368
+ * 默认注入 ProcessSandboxExecutor(fork + --permission 真实进程隔离;子进程
369
+ * env 默认清空防密钥泄露,需透传时经 ProcessSandboxOptions.envWhitelist 显式放行)。
370
+ * 可配置 executor 切回 SandboxedScriptExecutor(worker_threads 能力面收敛形态,
371
+ * 非安全边界;envWhitelist 同样适用于该执行器)。
365
372
  */
366
373
  declare function createEvaluationRuntime(deps: WebSkillRuntimeDeps & {
367
374
  executor?: ScriptExecutor;
@@ -1,6 +1,6 @@
1
- import { A as unzipWithLimits, b as isValidSkillName, d as assertSafePathSegment, j as validateSkills, k as resolveInsideRoot, u as WebSkillError } from "./dist-D0saNPi_.js";
2
- import { S as WebSkillRuntime } from "./dist-DrySSQ5R.js";
3
- import { i as NodeFS, s as ProcessSandboxExecutor, u as exportArchive } from "./dist-Cn9GpW6Q.js";
1
+ import { A as unzipWithLimits, b as isValidSkillName, d as assertSafePathSegment, j as validateSkills, k as resolveInsideRoot, u as WebSkillError } from "./dist-D7MsoMPx.js";
2
+ import { S as WebSkillRuntime } from "./dist-CV64gN62.js";
3
+ import { i as NodeFS, s as ProcessSandboxExecutor, u as exportArchive } from "./dist-Chgf2tcy.js";
4
4
  import path from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
  import { mkdtemp } from "node:fs/promises";
@@ -404,29 +404,42 @@ function canonical(event) {
404
404
  prevHash: event.prevHash
405
405
  });
406
406
  }
407
- /** JSONL 追加的审计日志:<managedRoot>/.webskill/audit.jsonl;跨实例可恢复查询;prevHash 链可校验完整性 */
407
+ /**
408
+ * JSONL 追加式审计日志(<managedRoot>/.webskill/audit.jsonl):
409
+ * 真追加(fs.appendText,不整读改写)+ lastHash 内存缓存(同实例不重读)。
410
+ * 语义:**tamper-evident, not tamper-proof**——verifyChain 能检出篡改/删除/换序,
411
+ * 但不阻止有写权限者直接改写文件;更强保证需要签名信任体系(未排期)。
412
+ */
408
413
  var FsAuditLog = class {
409
414
  #root;
410
415
  #fs;
411
416
  #now;
412
417
  #createId;
418
+ /** lastHash 内存缓存(同实例内追加不重读文件) */
419
+ #lastHash;
420
+ #lastHashSeeded = false;
413
421
  constructor(deps) {
414
422
  this.#root = deps.root.replace(/\/+$/, "");
415
423
  this.#fs = deps.fs;
416
424
  this.#now = deps.now;
417
425
  this.#createId = deps.createId;
418
426
  }
419
- async append(event) {
427
+ /** 首追加时播种 lastHash(读一次尾部;尾行损坏 → 抛错,不静默重开链) */
428
+ async #seedLastHash() {
429
+ this.#lastHashSeeded = true;
420
430
  const path = fileOf$1(this.#root);
421
- const existing = await this.#fs.exists(path) ? await this.#fs.readText(path) : "";
422
- const lines = existing.split("\n").filter((l) => l.trim() !== "");
423
- let prevHash = "GENESIS";
424
- if (lines.length > 0) try {
431
+ if (!await this.#fs.exists(path)) return "GENESIS";
432
+ const lines = (await this.#fs.readText(path)).split("\n").filter((l) => l.trim() !== "");
433
+ if (lines.length === 0) return "GENESIS";
434
+ try {
425
435
  const last = JSON.parse(lines.at(-1));
426
- prevHash = last.hash ?? sha256Hex(canonical(last));
427
- } catch {
428
- prevHash = "GENESIS";
436
+ return last.hash ?? sha256Hex(canonical(last));
437
+ } catch (e) {
438
+ throw new WebSkillError("GOVERNANCE_FAILED", `Audit log tail line at ${path} is corrupted; refusing to append (the chain must not silently restart)`, e);
429
439
  }
440
+ }
441
+ async append(event) {
442
+ const prevHash = this.#lastHashSeeded ? this.#lastHash : await this.#seedLastHash();
430
443
  const full = {
431
444
  id: event.id ?? this.#createId?.() ?? `audit-${Math.random().toString(36).slice(2, 10)}`,
432
445
  ts: event.ts ?? this.#now?.() ?? (/* @__PURE__ */ new Date()).toISOString(),
@@ -437,8 +450,8 @@ var FsAuditLog = class {
437
450
  prevHash
438
451
  };
439
452
  full.hash = sha256Hex(canonical(full));
440
- const prefix = existing === "" || existing.endsWith("\n") ? existing : `${existing}\n`;
441
- await this.#fs.writeText(path, `${prefix}${JSON.stringify(full)}\n`);
453
+ await this.#fs.appendText(fileOf$1(this.#root), `${JSON.stringify(full)}\n`);
454
+ this.#lastHash = full.hash;
442
455
  return full;
443
456
  }
444
457
  async query(filter) {
@@ -448,7 +461,12 @@ var FsAuditLog = class {
448
461
  const events = [];
449
462
  for (const line of raw.split("\n")) {
450
463
  if (line.trim() === "") continue;
451
- const event = JSON.parse(line);
464
+ let event;
465
+ try {
466
+ event = JSON.parse(line);
467
+ } catch {
468
+ continue;
469
+ }
452
470
  if (filter.target !== void 0 && event.target !== filter.target) continue;
453
471
  if (filter.type !== void 0 && event.type !== filter.type) continue;
454
472
  if (filter.since !== void 0 && event.ts < filter.since) continue;
@@ -843,8 +861,10 @@ var EvaluationRunner = class {
843
861
  };
844
862
  /**
845
863
  * 治理评估专用 runtime 装配(不可信技能试用路径):
846
- * 默认注入 ProcessSandboxExecutor(fork + --permission 真实进程隔离);
847
- * 可配置 executor 切回 SandboxedScriptExecutor(worker_threads 能力面收敛形态)。
864
+ * 默认注入 ProcessSandboxExecutor(fork + --permission 真实进程隔离;子进程
865
+ * env 默认清空防密钥泄露,需透传时经 ProcessSandboxOptions.envWhitelist 显式放行)。
866
+ * 可配置 executor 切回 SandboxedScriptExecutor(worker_threads 能力面收敛形态,
867
+ * 非安全边界;envWhitelist 同样适用于该执行器)。
848
868
  */
849
869
  function createEvaluationRuntime(deps) {
850
870
  return new WebSkillRuntime({
@@ -1,4 +1,4 @@
1
- import { F as SkillDocument, G as ValidationReport, I as SkillInstallSource, M as SkillCatalog, N as SkillCatalogEntry, P as SkillDiscovery, S as DiscoveryResult, T as JsonSchema, _ as RenderResultRequest, a as InteractionPolicy, c as LlmClient, d as LlmResponse, f as LlmStreamEvent, g as RenderBlock, h as MemoryStore, i as FormField, l as LlmCompleteInput, m as LlmToolSpec, n as ArtifactStore, o as InteractionRequest, r as ChartSpec, t as Artifact, u as LlmMessage, v as UiBridge, w as FileSystemProvider, z as SkillManifest } from "./types-CKm5G_eQ-8W8FnP4u.js";
1
+ import { F as SkillDocument, G as ValidationReport, I as SkillInstallSource, J as WebSkillErrorCode, M as SkillCatalog, N as SkillCatalogEntry, P as SkillDiscovery, S as DiscoveryResult, T as JsonSchema, _ as RenderResultRequest, a as InteractionPolicy, c as LlmClient, d as LlmResponse, f as LlmStreamEvent, g as RenderBlock, h as MemoryStore, i as FormField, l as LlmCompleteInput, m as LlmToolSpec, n as ArtifactStore, o as InteractionRequest, r as ChartSpec, t as Artifact, u as LlmMessage, v as UiBridge, w as FileSystemProvider, z as SkillManifest } from "./types-CKm5G_eQ-BqyXnvoR.js";
2
2
  //#region ../runtime/dist/index.d.ts
3
3
  //#region src/llm/openAiCompatibleClient.d.ts
4
4
  interface OpenAiCompatibleClientConfig {
@@ -33,6 +33,11 @@ interface AnthropicClientConfig {
33
33
  requestTimeoutMs?: number;
34
34
  /** max_tokens(Messages API 必填),默认 4096 */
35
35
  maxTokens?: number;
36
+ /**
37
+ * 浏览器直调 opt-in:true 时发送 anthropic-dangerous-direct-browser-access 头
38
+ * (默认 false 不发——仅在明确运行于浏览器且无服务端代理时开启)
39
+ */
40
+ dangerouslyAllowDirectBrowserAccess?: boolean;
36
41
  }
37
42
  /** Anthropic Messages API 客户端(零依赖 fetch;Node/浏览器通用) */
38
43
  declare class AnthropicClient implements LlmClient {
@@ -540,6 +545,18 @@ declare function isNetworkAllowed(policy: NetworkPolicy, url: string): boolean;
540
545
  /** 阻断 trace 用的脱敏 host(解析失败返回占位,不记录完整 URL) */
541
546
  declare function networkUrlHost(url: string): string;
542
547
  //#endregion
548
+ //#region src/sandbox/errorCodes.d.ts
549
+ /**
550
+ * 错误码白名单归一:沙箱/桥消息里出现的非白名单码(DOMException 数值码、
551
+ * Node 任意 ERR_* 码等)一律归为 TOOL_EXECUTION_FAILED。
552
+ */
553
+ declare function normalizeErrorCode(code: unknown): WebSkillErrorCode;
554
+ /** 归一化后的 (code, message):非白名单码保留在 message 尾部([original code: X]) */
555
+ declare function normalizeToolError(code: unknown, message: string): {
556
+ code: WebSkillErrorCode;
557
+ message: string;
558
+ };
559
+ //#endregion
543
560
  //#region src/sandbox/approval.d.ts
544
561
  /** 桥消息对应的三类能力 */
545
562
  type BridgeCapability = 'readReference' | 'writeArtifact' | 'confirm';
@@ -810,4 +827,4 @@ declare class WebSkillRuntime {
810
827
  resumeRun(runId: string): Promise<RunResult>;
811
828
  }
812
829
  //#endregion
813
- export { SerializingMemoryStore as $, LifecycleHook as A, RUN_SNAPSHOT_SCHEMA_VERSION as B, FullDisclosureRouter as C, normalizeToolContent as Ct, HookRunnerOptions as D, toLlmToolSpec as Dt, HookRunner as E, schemaToForm as Et, OpenAiCompatibleClientConfig as F, RunTerminationReason as G, RunResult as H, ProgressiveRouter as I, RuntimeSession as J, RuntimePhase as K, READ_SKILL_FILE_INPUT_SCHEMA as L, LifecycleListener as M, NetworkPolicy as N, InstalledSkillManifest as O, toVercelToolSpecs as Ot, OpenAiCompatibleClient as P, ScriptExecutor as Q, READ_SKILL_FILE_TOOL as R, FsRunSnapshotStore as S, networkUrlHost as St, GoogleGenAiClientConfig as T, resolveToolName as Tt, RunSnapshot as U, RouteResult as V, RunSnapshotStore as W, SchemaInferer as X, RuntimeSessionHandle as Y, ScriptExecutionContext as Z, EventBus as _, extractChartSpec as _t, AgentLoopConfig as a, TraceClock as at, FsArtifactStore as b, isNetworkAllowed as bt, AnthropicClientConfig as c, TraceRecorder as ct, BridgeCapabilities as d, WebSkillRuntime as dt, SkillRouter as et, BridgeCapability as f, WebSkillRuntimeDeps as ft, CapabilityMode as g, createWebSkillApi as gt, CapabilityApproval as h, createScriptContext as ht, AgentLoop as i, ToolResult as it, LifecycleHookContext as j, LifecycleEvent as k, ApprovalDecision as l, VercelToolSpec as lt, BridgeResponse as m, buildRenderResult as mt, ASK_USER_TOOL as n, ToolDefinition as nt, AgentLoopDeps as o, TraceEvent as ot, BridgeRequest as p, bridgeError as pt, RuntimeRun as q, ASK_USER_TOOL_NAME as r, ToolResolution as rt, AnthropicClient as s, TraceEventType as st, ASK_USER_INPUT_SCHEMA as t, SkillStateGuard as tt, ApprovalScope as u, WebSkillApi as ut, ExternalSkillProvider as v, fromVercelResult as vt, GoogleGenAiClient as w, parseBridgeRequest as wt, FsMemoryStore as x, mergeCatalogEntries as xt, ExternalToolSource as y, fromVercelStreamPart as yt, READ_SKILL_FILE_TOOL_NAME as z };
830
+ export { SerializingMemoryStore as $, LifecycleHook as A, toVercelToolSpecs as At, RUN_SNAPSHOT_SCHEMA_VERSION as B, FullDisclosureRouter as C, normalizeErrorCode as Ct, HookRunnerOptions as D, resolveToolName as Dt, HookRunner as E, parseBridgeRequest as Et, OpenAiCompatibleClientConfig as F, RunTerminationReason as G, RunResult as H, ProgressiveRouter as I, RuntimeSession as J, RuntimePhase as K, READ_SKILL_FILE_INPUT_SCHEMA as L, LifecycleListener as M, NetworkPolicy as N, InstalledSkillManifest as O, schemaToForm as Ot, OpenAiCompatibleClient as P, ScriptExecutor as Q, READ_SKILL_FILE_TOOL as R, FsRunSnapshotStore as S, networkUrlHost as St, GoogleGenAiClientConfig as T, normalizeToolError as Tt, RunSnapshot as U, RouteResult as V, RunSnapshotStore as W, SchemaInferer as X, RuntimeSessionHandle as Y, ScriptExecutionContext as Z, EventBus as _, extractChartSpec as _t, AgentLoopConfig as a, TraceClock as at, FsArtifactStore as b, isNetworkAllowed as bt, AnthropicClientConfig as c, TraceRecorder as ct, BridgeCapabilities as d, WebSkillRuntime as dt, SkillRouter as et, BridgeCapability as f, WebSkillRuntimeDeps as ft, CapabilityMode as g, createWebSkillApi as gt, CapabilityApproval as h, createScriptContext as ht, AgentLoop as i, ToolResult as it, LifecycleHookContext as j, LifecycleEvent as k, toLlmToolSpec as kt, ApprovalDecision as l, VercelToolSpec as lt, BridgeResponse as m, buildRenderResult as mt, ASK_USER_TOOL as n, ToolDefinition as nt, AgentLoopDeps as o, TraceEvent as ot, BridgeRequest as p, bridgeError as pt, RuntimeRun as q, ASK_USER_TOOL_NAME as r, ToolResolution as rt, AnthropicClient as s, TraceEventType as st, ASK_USER_INPUT_SCHEMA as t, SkillStateGuard as tt, ApprovalScope as u, WebSkillApi as ut, ExternalSkillProvider as v, fromVercelResult as vt, GoogleGenAiClient as w, normalizeToolContent as wt, FsMemoryStore as x, mergeCatalogEntries as xt, ExternalToolSource as y, fromVercelStreamPart as yt, READ_SKILL_FILE_TOOL_NAME as z };
@@ -1,5 +1,5 @@
1
- import { C as FileStat, I as SkillInstallSource, K as VerifyResult, T as JsonSchema, W as SkillsLockfile, _ as RenderResultRequest, o as InteractionRequest, s as InteractionResponse, v as UiBridge, w as FileSystemProvider, y as ArchiveLimits, z as SkillManifest } from "./types-CKm5G_eQ-8W8FnP4u.js";
2
- import { N as NetworkPolicy, Q as ScriptExecutor, X as SchemaInferer, Z as ScriptExecutionContext, b as FsArtifactStore, d as BridgeCapabilities, it as ToolResult, nt as ToolDefinition, u as ApprovalScope, x as FsMemoryStore } from "./index-gjFuBevI.js";
1
+ import { C as FileStat, I as SkillInstallSource, K as VerifyResult, T as JsonSchema, W as SkillsLockfile, _ as RenderResultRequest, o as InteractionRequest, s as InteractionResponse, v as UiBridge, w as FileSystemProvider, y as ArchiveLimits, z as SkillManifest } from "./types-CKm5G_eQ-BqyXnvoR.js";
2
+ import { N as NetworkPolicy, Q as ScriptExecutor, X as SchemaInferer, Z as ScriptExecutionContext, b as FsArtifactStore, d as BridgeCapabilities, it as ToolResult, nt as ToolDefinition, u as ApprovalScope, x as FsMemoryStore } from "./index-DZShzhon.js";
3
3
  import { Readable, Writable } from "node:stream";
4
4
  //#region ../node/dist/index.d.ts
5
5
  //#region src/fs/nodeFs.d.ts
@@ -14,8 +14,11 @@ declare class NodeFS implements FileSystemProvider {
14
14
  constructor(deps?: {
15
15
  root?: string;
16
16
  });
17
+ /** root 模式:全部方法(read/write/exists/stat/list/mkdir/remove/rename)目标 realpath 必须落在 root realpath 前缀内 */
18
+ withRoot(root: string): NodeFS;
17
19
  readText(p: string): Promise<string>;
18
20
  writeText(p: string, content: string): Promise<void>;
21
+ appendText(p: string, content: string): Promise<void>;
19
22
  readBinary(p: string): Promise<Uint8Array>;
20
23
  writeBinary(p: string, content: Uint8Array): Promise<void>;
21
24
  exists(p: string): Promise<boolean>;
@@ -72,8 +75,10 @@ interface SandboxOptions {
72
75
  * 能力桥协议与浏览器同一来源(runtime/sandbox/bridgeProtocol)。
73
76
  *
74
77
  * 诚实标注:本执行器做的是**能力面收敛**(网络策略、模块 allowlist、资源限额、
75
- * 超时强杀),**不是安全边界**——Worker 内脚本与宿主共享进程,仍有绕过手段;
76
- * 禁止假定其可隔离不可信脚本。
78
+ * 超时强杀),**不是安全边界**——Worker 内脚本与宿主共享进程;
79
+ * 已知主动逃逸面(process.binding/_linkedBinding/dlopen/openStdin/reallyExit/abort)
80
+ * 已在入口删除(0.2.3),常规 import 拦截之外不承诺防御其它宿主共享面;
81
+ * 禁止假定其可隔离不可信脚本(隔离级需求用 ProcessSandboxExecutor)。
77
82
  */
78
83
  declare class SandboxedScriptExecutor implements ScriptExecutor {
79
84
  #private;
@@ -92,6 +97,8 @@ declare class SandboxedScriptExecutor implements ScriptExecutor {
92
97
  interface ProcessSandboxOptions {
93
98
  /** 温池大小(并发上限;执行后 kill 并补位重生),默认 2 */
94
99
  poolSize?: number;
100
+ /** 透传给子进程的环境变量白名单(默认 []:子进程 env 为空,防密钥泄露) */
101
+ envWhitelist?: string[];
95
102
  capabilities?: BridgeCapabilities;
96
103
  /** 网络策略:默认 'deny-all'(权限模型无网络维度,补丁兜底;node:net 裸模块为已知残余面) */
97
104
  networkPolicy?: NetworkPolicy;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { $ as checkDependencyCycles, A as SKILL_NAME_PATTERN, B as SkillMetadata, C as FileStat, D as SKILLS_LOCKFILE, E as MemoryFS, F as SkillDocument, G as ValidationReport, H as SkillReader, I as SkillInstallSource, J as WebSkillErrorCode, K as VerifyResult, L as SkillIssue, M as SkillCatalog, N as SkillCatalogEntry, O as SKILL_MANIFEST_FILE, P as SkillDiscovery, Q as buildManifest, R as SkillLocation, S as DiscoveryResult, T as JsonSchema, U as SkillSource, V as SkillPackManifest, W as SkillsLockfile, X as atomicWriteText, Y as assertSafePathSegment, Z as buildCatalog, _ as RenderResultRequest, _t as xmlRenderer, a as InteractionPolicy, at as jsonRenderer, b as CatalogRenderer, c as LlmClient, ct as parseSkillPackManifest, d as LlmResponse, dt as renderCatalogJson, et as checkSkillRules, f as LlmStreamEvent, ft as resolveArchiveLimits, g as RenderBlock, gt as verifyManifest, h as MemoryStore, ht as validateSkills, i as FormField, it as isValidSkillName, j as SKILL_PACK_FILE, k as SKILL_NAME_MAX_LENGTH, l as LlmCompleteInput, lt as readResponseWithLimit, m as LlmToolSpec, mt as unzipWithLimits, n as ArtifactStore, nt as escapeXml, o as InteractionRequest, ot as normalizePath, p as LlmToolCall, pt as resolveInsideRoot, q as WebSkillError, r as ChartSpec, rt as exportSkills, s as InteractionResponse, st as parseSkillMarkdown, t as Artifact, tt as computeDigest, u as LlmMessage, ut as renderAvailableSkillsXml, v as UiBridge, w as FileSystemProvider, x as DEFAULT_ARCHIVE_LIMITS, y as ArchiveLimits, z as SkillManifest } from "./types-CKm5G_eQ-8W8FnP4u.js";
2
- import { $ as SerializingMemoryStore, A as LifecycleHook, B as RUN_SNAPSHOT_SCHEMA_VERSION, C as FullDisclosureRouter, Ct as normalizeToolContent, D as HookRunnerOptions, Dt as toLlmToolSpec, E as HookRunner, Et as schemaToForm, F as OpenAiCompatibleClientConfig, G as RunTerminationReason, H as RunResult, I as ProgressiveRouter, J as RuntimeSession, K as RuntimePhase, L as READ_SKILL_FILE_INPUT_SCHEMA, M as LifecycleListener, N as NetworkPolicy, O as InstalledSkillManifest, Ot as toVercelToolSpecs, P as OpenAiCompatibleClient, Q as ScriptExecutor, R as READ_SKILL_FILE_TOOL, S as FsRunSnapshotStore, St as networkUrlHost, T as GoogleGenAiClientConfig, Tt as resolveToolName, U as RunSnapshot, V as RouteResult, W as RunSnapshotStore, X as SchemaInferer, Y as RuntimeSessionHandle, Z as ScriptExecutionContext, _ as EventBus, _t as extractChartSpec, a as AgentLoopConfig, at as TraceClock, b as FsArtifactStore, bt as isNetworkAllowed, c as AnthropicClientConfig, ct as TraceRecorder, d as BridgeCapabilities, dt as WebSkillRuntime, et as SkillRouter, f as BridgeCapability, ft as WebSkillRuntimeDeps, g as CapabilityMode, gt as createWebSkillApi, h as CapabilityApproval, ht as createScriptContext, i as AgentLoop, it as ToolResult, j as LifecycleHookContext, k as LifecycleEvent, l as ApprovalDecision, lt as VercelToolSpec, m as BridgeResponse, mt as buildRenderResult, n as ASK_USER_TOOL, nt as ToolDefinition, o as AgentLoopDeps, ot as TraceEvent, p as BridgeRequest, pt as bridgeError, q as RuntimeRun, r as ASK_USER_TOOL_NAME, rt as ToolResolution, s as AnthropicClient, st as TraceEventType, t as ASK_USER_INPUT_SCHEMA, tt as SkillStateGuard, u as ApprovalScope, ut as WebSkillApi, v as ExternalSkillProvider, vt as fromVercelResult, w as GoogleGenAiClient, wt as parseBridgeRequest, x as FsMemoryStore, xt as mergeCatalogEntries, y as ExternalToolSource, yt as fromVercelStreamPart, z as READ_SKILL_FILE_TOOL_NAME } from "./index-gjFuBevI.js";
3
- export { ASK_USER_INPUT_SCHEMA, ASK_USER_TOOL, ASK_USER_TOOL_NAME, AgentLoop, type AgentLoopConfig, type AgentLoopDeps, AnthropicClient, type AnthropicClientConfig, type ApprovalDecision, type ApprovalScope, type ArchiveLimits, type Artifact, type ArtifactStore, type BridgeCapabilities, type BridgeCapability, type BridgeRequest, type BridgeResponse, CapabilityApproval, type CapabilityMode, type CatalogRenderer, type ChartSpec, DEFAULT_ARCHIVE_LIMITS, type DiscoveryResult, EventBus, type ExternalSkillProvider, type ExternalToolSource, type FileStat, type FileSystemProvider, type FormField, FsArtifactStore, FsMemoryStore, FsRunSnapshotStore, FullDisclosureRouter, GoogleGenAiClient, type GoogleGenAiClientConfig, HookRunner, type HookRunnerOptions, type InstalledSkillManifest, type InteractionPolicy, type InteractionRequest, type InteractionResponse, type JsonSchema, type LifecycleEvent, type LifecycleHook, type LifecycleHookContext, type LifecycleListener, type LlmClient, type LlmCompleteInput, type LlmMessage, type LlmResponse, type LlmStreamEvent, type LlmToolCall, type LlmToolSpec, MemoryFS, type MemoryStore, type NetworkPolicy, OpenAiCompatibleClient, type OpenAiCompatibleClientConfig, ProgressiveRouter, READ_SKILL_FILE_INPUT_SCHEMA, READ_SKILL_FILE_TOOL, READ_SKILL_FILE_TOOL_NAME, RUN_SNAPSHOT_SCHEMA_VERSION, type RenderBlock, type RenderResultRequest, type RouteResult, type RunResult, type RunSnapshot, type RunSnapshotStore, type RunTerminationReason, type RuntimePhase, type RuntimeRun, type RuntimeSession, type RuntimeSessionHandle, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SKILL_NAME_MAX_LENGTH, SKILL_NAME_PATTERN, SKILL_PACK_FILE, type SchemaInferer, type ScriptExecutionContext, type ScriptExecutor, SerializingMemoryStore, type SkillCatalog, type SkillCatalogEntry, SkillDiscovery, type SkillDocument, type SkillInstallSource, type SkillIssue, type SkillLocation, type SkillManifest, type SkillMetadata, type SkillPackManifest, SkillReader, type SkillRouter, type SkillSource, type SkillStateGuard, type SkillsLockfile, type ToolDefinition, type ToolResolution, type ToolResult, type TraceClock, type TraceEvent, type TraceEventType, TraceRecorder, type UiBridge, type ValidationReport, type VercelToolSpec, type VerifyResult, type WebSkillApi, WebSkillError, type WebSkillErrorCode, WebSkillRuntime, type WebSkillRuntimeDeps, assertSafePathSegment, atomicWriteText, bridgeError, buildCatalog, buildManifest, buildRenderResult, checkDependencyCycles, checkSkillRules, computeDigest, createScriptContext, createWebSkillApi, escapeXml, exportSkills, extractChartSpec, fromVercelResult, fromVercelStreamPart, isNetworkAllowed, isValidSkillName, jsonRenderer, mergeCatalogEntries, networkUrlHost, normalizePath, normalizeToolContent, parseBridgeRequest, parseSkillMarkdown, parseSkillPackManifest, readResponseWithLimit, renderAvailableSkillsXml, renderCatalogJson, resolveArchiveLimits, resolveInsideRoot, resolveToolName, schemaToForm, toLlmToolSpec, toVercelToolSpecs, unzipWithLimits, validateSkills, verifyManifest, xmlRenderer };
1
+ import { $ as checkDependencyCycles, A as SKILL_NAME_PATTERN, B as SkillMetadata, C as FileStat, D as SKILLS_LOCKFILE, E as MemoryFS, F as SkillDocument, G as ValidationReport, H as SkillReader, I as SkillInstallSource, J as WebSkillErrorCode, K as VerifyResult, L as SkillIssue, M as SkillCatalog, N as SkillCatalogEntry, O as SKILL_MANIFEST_FILE, P as SkillDiscovery, Q as buildManifest, R as SkillLocation, S as DiscoveryResult, T as JsonSchema, U as SkillSource, V as SkillPackManifest, W as SkillsLockfile, X as atomicWriteText, Y as assertSafePathSegment, Z as buildCatalog, _ as RenderResultRequest, _t as xmlRenderer, a as InteractionPolicy, at as jsonRenderer, b as CatalogRenderer, c as LlmClient, ct as parseSkillPackManifest, d as LlmResponse, dt as renderCatalogJson, et as checkSkillRules, f as LlmStreamEvent, ft as resolveArchiveLimits, g as RenderBlock, gt as verifyManifest, h as MemoryStore, ht as validateSkills, i as FormField, it as isValidSkillName, j as SKILL_PACK_FILE, k as SKILL_NAME_MAX_LENGTH, l as LlmCompleteInput, lt as readResponseWithLimit, m as LlmToolSpec, mt as unzipWithLimits, n as ArtifactStore, nt as escapeXml, o as InteractionRequest, ot as normalizePath, p as LlmToolCall, pt as resolveInsideRoot, q as WebSkillError, r as ChartSpec, rt as exportSkills, s as InteractionResponse, st as parseSkillMarkdown, t as Artifact, tt as computeDigest, u as LlmMessage, ut as renderAvailableSkillsXml, v as UiBridge, w as FileSystemProvider, x as DEFAULT_ARCHIVE_LIMITS, y as ArchiveLimits, z as SkillManifest } from "./types-CKm5G_eQ-BqyXnvoR.js";
2
+ import { $ as SerializingMemoryStore, A as LifecycleHook, At as toVercelToolSpecs, B as RUN_SNAPSHOT_SCHEMA_VERSION, C as FullDisclosureRouter, Ct as normalizeErrorCode, D as HookRunnerOptions, Dt as resolveToolName, E as HookRunner, Et as parseBridgeRequest, F as OpenAiCompatibleClientConfig, G as RunTerminationReason, H as RunResult, I as ProgressiveRouter, J as RuntimeSession, K as RuntimePhase, L as READ_SKILL_FILE_INPUT_SCHEMA, M as LifecycleListener, N as NetworkPolicy, O as InstalledSkillManifest, Ot as schemaToForm, P as OpenAiCompatibleClient, Q as ScriptExecutor, R as READ_SKILL_FILE_TOOL, S as FsRunSnapshotStore, St as networkUrlHost, T as GoogleGenAiClientConfig, Tt as normalizeToolError, U as RunSnapshot, V as RouteResult, W as RunSnapshotStore, X as SchemaInferer, Y as RuntimeSessionHandle, Z as ScriptExecutionContext, _ as EventBus, _t as extractChartSpec, a as AgentLoopConfig, at as TraceClock, b as FsArtifactStore, bt as isNetworkAllowed, c as AnthropicClientConfig, ct as TraceRecorder, d as BridgeCapabilities, dt as WebSkillRuntime, et as SkillRouter, f as BridgeCapability, ft as WebSkillRuntimeDeps, g as CapabilityMode, gt as createWebSkillApi, h as CapabilityApproval, ht as createScriptContext, i as AgentLoop, it as ToolResult, j as LifecycleHookContext, k as LifecycleEvent, kt as toLlmToolSpec, l as ApprovalDecision, lt as VercelToolSpec, m as BridgeResponse, mt as buildRenderResult, n as ASK_USER_TOOL, nt as ToolDefinition, o as AgentLoopDeps, ot as TraceEvent, p as BridgeRequest, pt as bridgeError, q as RuntimeRun, r as ASK_USER_TOOL_NAME, rt as ToolResolution, s as AnthropicClient, st as TraceEventType, t as ASK_USER_INPUT_SCHEMA, tt as SkillStateGuard, u as ApprovalScope, ut as WebSkillApi, v as ExternalSkillProvider, vt as fromVercelResult, w as GoogleGenAiClient, wt as normalizeToolContent, x as FsMemoryStore, xt as mergeCatalogEntries, y as ExternalToolSource, yt as fromVercelStreamPart, z as READ_SKILL_FILE_TOOL_NAME } from "./index-DZShzhon.js";
3
+ export { ASK_USER_INPUT_SCHEMA, ASK_USER_TOOL, ASK_USER_TOOL_NAME, AgentLoop, type AgentLoopConfig, type AgentLoopDeps, AnthropicClient, type AnthropicClientConfig, type ApprovalDecision, type ApprovalScope, type ArchiveLimits, type Artifact, type ArtifactStore, type BridgeCapabilities, type BridgeCapability, type BridgeRequest, type BridgeResponse, CapabilityApproval, type CapabilityMode, type CatalogRenderer, type ChartSpec, DEFAULT_ARCHIVE_LIMITS, type DiscoveryResult, EventBus, type ExternalSkillProvider, type ExternalToolSource, type FileStat, type FileSystemProvider, type FormField, FsArtifactStore, FsMemoryStore, FsRunSnapshotStore, FullDisclosureRouter, GoogleGenAiClient, type GoogleGenAiClientConfig, HookRunner, type HookRunnerOptions, type InstalledSkillManifest, type InteractionPolicy, type InteractionRequest, type InteractionResponse, type JsonSchema, type LifecycleEvent, type LifecycleHook, type LifecycleHookContext, type LifecycleListener, type LlmClient, type LlmCompleteInput, type LlmMessage, type LlmResponse, type LlmStreamEvent, type LlmToolCall, type LlmToolSpec, MemoryFS, type MemoryStore, type NetworkPolicy, OpenAiCompatibleClient, type OpenAiCompatibleClientConfig, ProgressiveRouter, READ_SKILL_FILE_INPUT_SCHEMA, READ_SKILL_FILE_TOOL, READ_SKILL_FILE_TOOL_NAME, RUN_SNAPSHOT_SCHEMA_VERSION, type RenderBlock, type RenderResultRequest, type RouteResult, type RunResult, type RunSnapshot, type RunSnapshotStore, type RunTerminationReason, type RuntimePhase, type RuntimeRun, type RuntimeSession, type RuntimeSessionHandle, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SKILL_NAME_MAX_LENGTH, SKILL_NAME_PATTERN, SKILL_PACK_FILE, type SchemaInferer, type ScriptExecutionContext, type ScriptExecutor, SerializingMemoryStore, type SkillCatalog, type SkillCatalogEntry, SkillDiscovery, type SkillDocument, type SkillInstallSource, type SkillIssue, type SkillLocation, type SkillManifest, type SkillMetadata, type SkillPackManifest, SkillReader, type SkillRouter, type SkillSource, type SkillStateGuard, type SkillsLockfile, type ToolDefinition, type ToolResolution, type ToolResult, type TraceClock, type TraceEvent, type TraceEventType, TraceRecorder, type UiBridge, type ValidationReport, type VercelToolSpec, type VerifyResult, type WebSkillApi, WebSkillError, type WebSkillErrorCode, WebSkillRuntime, type WebSkillRuntimeDeps, assertSafePathSegment, atomicWriteText, bridgeError, buildCatalog, buildManifest, buildRenderResult, checkDependencyCycles, checkSkillRules, computeDigest, createScriptContext, createWebSkillApi, escapeXml, exportSkills, extractChartSpec, fromVercelResult, fromVercelStreamPart, isNetworkAllowed, isValidSkillName, jsonRenderer, mergeCatalogEntries, networkUrlHost, normalizeErrorCode, normalizePath, normalizeToolContent, normalizeToolError, parseBridgeRequest, parseSkillMarkdown, parseSkillPackManifest, readResponseWithLimit, renderAvailableSkillsXml, renderCatalogJson, resolveArchiveLimits, resolveInsideRoot, resolveToolName, schemaToForm, toLlmToolSpec, toVercelToolSpecs, unzipWithLimits, validateSkills, verifyManifest, xmlRenderer };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as unzipWithLimits, C as parseSkillMarkdown, D as renderCatalogJson, E as renderAvailableSkillsXml, M as verifyManifest, N as xmlRenderer, O as resolveArchiveLimits, S as normalizePath, T as readResponseWithLimit, _ as computeDigest, a as SKILL_NAME_MAX_LENGTH, b as isValidSkillName, c as SkillDiscovery, d as assertSafePathSegment, f as atomicWriteText, g as checkSkillRules, h as checkDependencyCycles, i as SKILL_MANIFEST_FILE, j as validateSkills, k as resolveInsideRoot, l as SkillReader, m as buildManifest, n as MemoryFS, o as SKILL_NAME_PATTERN, p as buildCatalog, r as SKILLS_LOCKFILE, s as SKILL_PACK_FILE, t as DEFAULT_ARCHIVE_LIMITS, u as WebSkillError, v as escapeXml, w as parseSkillPackManifest, x as jsonRenderer, y as exportSkills } from "./dist-D0saNPi_.js";
2
- import { A as isNetworkAllowed, C as bridgeError, D as extractChartSpec, E as createWebSkillApi, F as resolveToolName, I as schemaToForm, L as toLlmToolSpec, M as networkUrlHost, N as normalizeToolContent, O as fromVercelResult, P as parseBridgeRequest, R as toVercelToolSpecs, S as WebSkillRuntime, T as createScriptContext, _ as READ_SKILL_FILE_TOOL, a as AnthropicClient, b as SerializingMemoryStore, c as FsArtifactStore, d as FullDisclosureRouter, f as GoogleGenAiClient, g as READ_SKILL_FILE_INPUT_SCHEMA, h as ProgressiveRouter, i as AgentLoop, j as mergeCatalogEntries, k as fromVercelStreamPart, l as FsMemoryStore, m as OpenAiCompatibleClient, n as ASK_USER_TOOL, o as CapabilityApproval, p as HookRunner, r as ASK_USER_TOOL_NAME, s as EventBus, t as ASK_USER_INPUT_SCHEMA, u as FsRunSnapshotStore, v as READ_SKILL_FILE_TOOL_NAME, w as buildRenderResult, x as TraceRecorder, y as RUN_SNAPSHOT_SCHEMA_VERSION } from "./dist-DrySSQ5R.js";
1
+ import { A as unzipWithLimits, C as parseSkillMarkdown, D as renderCatalogJson, E as renderAvailableSkillsXml, M as verifyManifest, N as xmlRenderer, O as resolveArchiveLimits, S as normalizePath, T as readResponseWithLimit, _ as computeDigest, a as SKILL_NAME_MAX_LENGTH, b as isValidSkillName, c as SkillDiscovery, d as assertSafePathSegment, f as atomicWriteText, g as checkSkillRules, h as checkDependencyCycles, i as SKILL_MANIFEST_FILE, j as validateSkills, k as resolveInsideRoot, l as SkillReader, m as buildManifest, n as MemoryFS, o as SKILL_NAME_PATTERN, p as buildCatalog, r as SKILLS_LOCKFILE, s as SKILL_PACK_FILE, t as DEFAULT_ARCHIVE_LIMITS, u as WebSkillError, v as escapeXml, w as parseSkillPackManifest, x as jsonRenderer, y as exportSkills } from "./dist-D7MsoMPx.js";
2
+ import { A as isNetworkAllowed, B as toVercelToolSpecs, C as bridgeError, D as extractChartSpec, E as createWebSkillApi, F as normalizeToolError, I as parseBridgeRequest, L as resolveToolName, M as networkUrlHost, N as normalizeErrorCode, O as fromVercelResult, P as normalizeToolContent, R as schemaToForm, S as WebSkillRuntime, T as createScriptContext, _ as READ_SKILL_FILE_TOOL, a as AnthropicClient, b as SerializingMemoryStore, c as FsArtifactStore, d as FullDisclosureRouter, f as GoogleGenAiClient, g as READ_SKILL_FILE_INPUT_SCHEMA, h as ProgressiveRouter, i as AgentLoop, j as mergeCatalogEntries, k as fromVercelStreamPart, l as FsMemoryStore, m as OpenAiCompatibleClient, n as ASK_USER_TOOL, o as CapabilityApproval, p as HookRunner, r as ASK_USER_TOOL_NAME, s as EventBus, t as ASK_USER_INPUT_SCHEMA, u as FsRunSnapshotStore, v as READ_SKILL_FILE_TOOL_NAME, w as buildRenderResult, x as TraceRecorder, y as RUN_SNAPSHOT_SCHEMA_VERSION, z as toLlmToolSpec } from "./dist-CV64gN62.js";
3
3
 
4
- export { ASK_USER_INPUT_SCHEMA, ASK_USER_TOOL, ASK_USER_TOOL_NAME, AgentLoop, AnthropicClient, CapabilityApproval, DEFAULT_ARCHIVE_LIMITS, EventBus, FsArtifactStore, FsMemoryStore, FsRunSnapshotStore, FullDisclosureRouter, GoogleGenAiClient, HookRunner, MemoryFS, OpenAiCompatibleClient, ProgressiveRouter, READ_SKILL_FILE_INPUT_SCHEMA, READ_SKILL_FILE_TOOL, READ_SKILL_FILE_TOOL_NAME, RUN_SNAPSHOT_SCHEMA_VERSION, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SKILL_NAME_MAX_LENGTH, SKILL_NAME_PATTERN, SKILL_PACK_FILE, SerializingMemoryStore, SkillDiscovery, SkillReader, TraceRecorder, WebSkillError, WebSkillRuntime, assertSafePathSegment, atomicWriteText, bridgeError, buildCatalog, buildManifest, buildRenderResult, checkDependencyCycles, checkSkillRules, computeDigest, createScriptContext, createWebSkillApi, escapeXml, exportSkills, extractChartSpec, fromVercelResult, fromVercelStreamPart, isNetworkAllowed, isValidSkillName, jsonRenderer, mergeCatalogEntries, networkUrlHost, normalizePath, normalizeToolContent, parseBridgeRequest, parseSkillMarkdown, parseSkillPackManifest, readResponseWithLimit, renderAvailableSkillsXml, renderCatalogJson, resolveArchiveLimits, resolveInsideRoot, resolveToolName, schemaToForm, toLlmToolSpec, toVercelToolSpecs, unzipWithLimits, validateSkills, verifyManifest, xmlRenderer };
4
+ export { ASK_USER_INPUT_SCHEMA, ASK_USER_TOOL, ASK_USER_TOOL_NAME, AgentLoop, AnthropicClient, CapabilityApproval, DEFAULT_ARCHIVE_LIMITS, EventBus, FsArtifactStore, FsMemoryStore, FsRunSnapshotStore, FullDisclosureRouter, GoogleGenAiClient, HookRunner, MemoryFS, OpenAiCompatibleClient, ProgressiveRouter, READ_SKILL_FILE_INPUT_SCHEMA, READ_SKILL_FILE_TOOL, READ_SKILL_FILE_TOOL_NAME, RUN_SNAPSHOT_SCHEMA_VERSION, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SKILL_NAME_MAX_LENGTH, SKILL_NAME_PATTERN, SKILL_PACK_FILE, SerializingMemoryStore, SkillDiscovery, SkillReader, TraceRecorder, WebSkillError, WebSkillRuntime, assertSafePathSegment, atomicWriteText, bridgeError, buildCatalog, buildManifest, buildRenderResult, checkDependencyCycles, checkSkillRules, computeDigest, createScriptContext, createWebSkillApi, escapeXml, exportSkills, extractChartSpec, fromVercelResult, fromVercelStreamPart, isNetworkAllowed, isValidSkillName, jsonRenderer, mergeCatalogEntries, networkUrlHost, normalizeErrorCode, normalizePath, normalizeToolContent, normalizeToolError, parseBridgeRequest, parseSkillMarkdown, parseSkillPackManifest, readResponseWithLimit, renderAvailableSkillsXml, renderCatalogJson, resolveArchiveLimits, resolveInsideRoot, resolveToolName, schemaToForm, toLlmToolSpec, toVercelToolSpecs, unzipWithLimits, validateSkills, verifyManifest, xmlRenderer };
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as SkillDocument, N as SkillCatalogEntry, T as JsonSchema, m as LlmToolSpec } from "./types-CKm5G_eQ-8W8FnP4u.js";
2
- import { it as ToolResult, v as ExternalSkillProvider, xt as mergeCatalogEntries, y as ExternalToolSource } from "./index-gjFuBevI.js";
1
+ import { F as SkillDocument, N as SkillCatalogEntry, T as JsonSchema, m as LlmToolSpec } from "./types-CKm5G_eQ-BqyXnvoR.js";
2
+ import { it as ToolResult, v as ExternalSkillProvider, xt as mergeCatalogEntries, y as ExternalToolSource } from "./index-DZShzhon.js";
3
3
  import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
4
4
  import { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
5
5
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -63,7 +63,7 @@ declare class MessageChannelTransport implements Transport {
63
63
  /** endpoint 名 → client 注册表;单调版本号,事件驱动等待(禁止轮询) */
64
64
  declare class EndpointRegistry<TClient> {
65
65
  #private;
66
- /** 注册新 endpoint;重名抛错 */
66
+ /** 注册新 endpoint;重名抛错;含 `__`(endpoint:tool 分隔符)或保留名 mcp 拒绝 */
67
67
  register(endpoint: string, client: TClient): void;
68
68
  /** 热替换 client,版本号 +1 */
69
69
  set(endpoint: string, client: TClient): void;
package/dist/mcp.js CHANGED
@@ -1,5 +1,5 @@
1
- import { u as WebSkillError } from "./dist-D0saNPi_.js";
2
- import { N as normalizeToolContent, j as mergeCatalogEntries } from "./dist-DrySSQ5R.js";
1
+ import { u as WebSkillError } from "./dist-D7MsoMPx.js";
2
+ import { P as normalizeToolContent, j as mergeCatalogEntries } from "./dist-CV64gN62.js";
3
3
 
4
4
  //#region ../mcp/dist/index.js
5
5
  /**
@@ -117,8 +117,9 @@ var EndpointRegistry = class {
117
117
  #clients = /* @__PURE__ */ new Map();
118
118
  #versions = /* @__PURE__ */ new Map();
119
119
  #waiters = /* @__PURE__ */ new Map();
120
- /** 注册新 endpoint;重名抛错 */
120
+ /** 注册新 endpoint;重名抛错;含 `__`(endpoint:tool 分隔符)或保留名 mcp 拒绝 */
121
121
  register(endpoint, client) {
122
+ if (endpoint.includes("__") || endpoint === "mcp") throw new Error(`Endpoint name ${JSON.stringify(endpoint)} is not allowed (no "__" segments, "mcp" is reserved)`);
122
123
  if (this.#clients.has(endpoint)) throw new Error(`Endpoint "${endpoint}" is already registered`);
123
124
  this.#clients.set(endpoint, client);
124
125
  this.#versions.set(endpoint, (this.#versions.get(endpoint) ?? 0) + 1);
@@ -172,6 +173,8 @@ var EndpointRegistry = class {
172
173
  }
173
174
  };
174
175
  const messageOf$3 = (e) => e instanceof Error ? e.message : String(e);
176
+ /** MCP 结果单项 text 上限(64KB) */
177
+ const MAX_MCP_RESULT_TEXT_BYTES = 64 * 1024;
175
178
  const failure$1 = (code, message) => ({
176
179
  ok: false,
177
180
  content: [],
@@ -235,14 +238,16 @@ var McpToolResolver = class {
235
238
  });
236
239
  return names;
237
240
  }
238
- /** CallToolResult → ToolResult;isError 转失败;content 经共享归一 */
241
+ /** CallToolResult → ToolResult;isError 转失败;形状消毒(无 content 且无 isError 不当作 ok)+ 大小上限 */
239
242
  #normalizeCallResult(raw) {
240
243
  const result = raw;
244
+ if (result?.isError !== true && result?.content === void 0) return failure$1("MCP_ENDPOINT_UNAVAILABLE", `MCP tool returned a malformed result (no "content" and no "isError"): ${messageOf$3(raw).slice(0, 200)}`);
241
245
  const content = normalizeToolContent(result?.content ?? raw);
242
246
  if (result?.isError === true) {
243
247
  const text = content.map((c) => c.text ?? "").filter(Boolean).join("\n");
244
248
  return failure$1("TOOL_EXECUTION_FAILED", text || "MCP tool returned an error");
245
249
  }
250
+ for (const item of content) if (item.text !== void 0 && item.text.length > MAX_MCP_RESULT_TEXT_BYTES) item.text = `${item.text.slice(0, MAX_MCP_RESULT_TEXT_BYTES)}…[truncated ${item.text.length - MAX_MCP_RESULT_TEXT_BYTES} chars]`;
246
251
  return {
247
252
  ok: true,
248
253
  content
@@ -414,7 +419,7 @@ var ExperimentalWebMcpAdapter = class {
414
419
  this.#enabled = options?.enabled ?? false;
415
420
  }
416
421
  isAvailable() {
417
- return typeof this.#resolveApi()?.executeTool === "function";
422
+ return this.#enabled && typeof this.#resolveApi()?.executeTool === "function";
418
423
  }
419
424
  /** 工具清单(listTools 缺失/失败时返回 undefined);描述含 inputSchema 时透传 */
420
425
  async listTools() {
@@ -549,7 +554,12 @@ const messageOf = (e) => e instanceof Error ? e.message : String(e);
549
554
  */
550
555
  async function connectRemoteEndpoint(registry, config) {
551
556
  const { Client, SSEClientTransport, StreamableHTTPClientTransport } = await loadMcpSdk();
552
- const url = new URL(config.url);
557
+ let url;
558
+ try {
559
+ url = new URL(config.url);
560
+ } catch (e) {
561
+ throw new WebSkillError("MCP_ENDPOINT_UNAVAILABLE", `Invalid remote MCP endpoint URL for "${config.endpoint}": ${JSON.stringify(config.url)}`, e);
562
+ }
553
563
  const requestInit = config.headers ? { headers: config.headers } : void 0;
554
564
  const transport = config.transport === "sse" ? new SSEClientTransport(url, { ...requestInit ? { requestInit } : {} }) : new StreamableHTTPClientTransport(url, { ...requestInit ? { requestInit } : {} });
555
565
  const client = new Client({
@@ -570,7 +580,14 @@ async function connectRemoteEndpoint(registry, config) {
570
580
  } catch {}
571
581
  throw unavailable(e);
572
582
  }
573
- registry.register(config.endpoint, client);
583
+ try {
584
+ registry.register(config.endpoint, client);
585
+ } catch (e) {
586
+ try {
587
+ await client.close();
588
+ } catch {}
589
+ throw unavailable(e);
590
+ }
574
591
  let closed = false;
575
592
  return { close: async () => {
576
593
  if (closed) return;
package/dist/node.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as SKILLS_LOCKFILE, I as SkillInstallSource, K as VerifyResult, O as SKILL_MANIFEST_FILE, W as SkillsLockfile, z as SkillManifest } from "./types-CKm5G_eQ-8W8FnP4u.js";
2
- import { ht as createScriptContext } from "./index-gjFuBevI.js";
1
+ import { D as SKILLS_LOCKFILE, I as SkillInstallSource, K as VerifyResult, O as SKILL_MANIFEST_FILE, W as SkillsLockfile, z as SkillManifest } from "./types-CKm5G_eQ-BqyXnvoR.js";
2
+ import { ht as createScriptContext } from "./index-DZShzhon.js";
3
3
  import { n as LlmEnvConfig, s as probeLlmCapabilities, t as LlmCapabilities } from "./env-BPUBZCwJ-4jat_SVG.js";
4
- import { a as NodeScriptExecutor, c as ProcessSandboxOptions, d as SkillManager, f as exportArchive, i as NodeFS, l as SandboxOptions, n as FileArtifactStore, o as OxcSchemaInferer, p as readArchiveManifest, r as FileMemoryStore, s as ProcessSandboxExecutor, t as CliUiBridge, u as SandboxedScriptExecutor } from "./index-BmzysJX5.js";
4
+ import { a as NodeScriptExecutor, c as ProcessSandboxOptions, d as SkillManager, f as exportArchive, i as NodeFS, l as SandboxOptions, n as FileArtifactStore, o as OxcSchemaInferer, p as readArchiveManifest, r as FileMemoryStore, s as ProcessSandboxExecutor, t as CliUiBridge, u as SandboxedScriptExecutor } from "./index-DrHelz72.js";
5
5
  export { CliUiBridge, FileArtifactStore, FileMemoryStore, type LlmCapabilities, type LlmEnvConfig, NodeFS, NodeScriptExecutor, OxcSchemaInferer, ProcessSandboxExecutor, type ProcessSandboxOptions, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, type SandboxOptions, SandboxedScriptExecutor, type SkillInstallSource, SkillManager, type SkillManifest, type SkillsLockfile, type VerifyResult, createScriptContext, exportArchive, probeLlmCapabilities, readArchiveManifest };
package/dist/node.js CHANGED
@@ -1,6 +1,6 @@
1
- import { i as SKILL_MANIFEST_FILE, r as SKILLS_LOCKFILE } from "./dist-D0saNPi_.js";
2
- import { T as createScriptContext } from "./dist-DrySSQ5R.js";
1
+ import { i as SKILL_MANIFEST_FILE, r as SKILLS_LOCKFILE } from "./dist-D7MsoMPx.js";
2
+ import { T as createScriptContext } from "./dist-CV64gN62.js";
3
3
  import { i as probeLlmCapabilities } from "./env--jJB-TSX-04klhTYi.js";
4
- import { a as NodeScriptExecutor, c as SandboxedScriptExecutor, d as readArchiveManifest, i as NodeFS, l as SkillManager, n as FileArtifactStore, o as OxcSchemaInferer, r as FileMemoryStore, s as ProcessSandboxExecutor, t as CliUiBridge, u as exportArchive } from "./dist-Cn9GpW6Q.js";
4
+ import { a as NodeScriptExecutor, c as SandboxedScriptExecutor, d as readArchiveManifest, i as NodeFS, l as SkillManager, n as FileArtifactStore, o as OxcSchemaInferer, r as FileMemoryStore, s as ProcessSandboxExecutor, t as CliUiBridge, u as exportArchive } from "./dist-Chgf2tcy.js";
5
5
 
6
6
  export { CliUiBridge, FileArtifactStore, FileMemoryStore, NodeFS, NodeScriptExecutor, OxcSchemaInferer, ProcessSandboxExecutor, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SandboxedScriptExecutor, SkillManager, createScriptContext, exportArchive, probeLlmCapabilities, readArchiveManifest };
@@ -16,6 +16,16 @@ import { mkdtemp, rm, writeFile } from "node:fs/promises";
16
16
  * runtime/sandbox/networkPolicy.ts);node:net 裸模块为已知残余面(文档明示)。
17
17
  * .js 走 data: URL 导入(permission 下实证可用);.ts 走中性临时目录 file URL。
18
18
  */
19
+ /** 不可序列化返回值统一报错(不静默丢数据;0.2.4 跨执行器语义统一) */
20
+ function assertSerializable(value) {
21
+ try {
22
+ structuredClone(value);
23
+ } catch (e) {
24
+ const err = /* @__PURE__ */ new Error(`Script returned a non-serializable value: ${e instanceof Error ? e.message : String(e)}`);
25
+ err.code = "TOOL_EXECUTION_FAILED";
26
+ throw err;
27
+ }
28
+ }
19
29
  const send = (message) => {
20
30
  process.send?.(message);
21
31
  };
@@ -164,6 +174,7 @@ async function main(task) {
164
174
  };
165
175
  const runFn = mod["run"];
166
176
  const value = await runFn(task.args ?? {}, context);
177
+ assertSerializable(value);
167
178
  send({
168
179
  type: "execute-result",
169
180
  ok: true,
@@ -67,6 +67,16 @@ async function loadModule(scriptPath, scriptSource) {
67
67
  }
68
68
  return await import(`${pathToFileURL(scriptPath).href}?t=${Date.now()}`);
69
69
  }
70
+ /** 不可序列化返回值统一报错(不静默丢数据;0.2.4 跨执行器语义统一) */
71
+ function assertSerializable(value) {
72
+ try {
73
+ structuredClone(value);
74
+ } catch (e) {
75
+ const err = /* @__PURE__ */ new Error(`Script returned a non-serializable value: ${e instanceof Error ? e.message : String(e)}`);
76
+ err.code = "TOOL_EXECUTION_FAILED";
77
+ throw err;
78
+ }
79
+ }
70
80
  function post(message) {
71
81
  port.postMessage(message);
72
82
  }
@@ -132,8 +142,29 @@ function setupNetworkGuards(task) {
132
142
  };
133
143
  register(`data:text/javascript,${encodeURIComponent(MODULE_HOOK_SOURCE.replace("%ALLOWED_MODULES%", JSON.stringify(task.allowedModules ?? [])))}`);
134
144
  }
145
+ /**
146
+ * 加载用户代码前删除 native 逃逸面(P0-A):binding/_linkedBinding/dlopen/
147
+ * openStdin/reallyExit/abort——这些直达宿主进程 internals,防御面与
148
+ * 能力收敛语义一致(常规 import 拦截之外的主动逃逸项由此封闭)。
149
+ * 注意:process.exit() 内部依赖 reallyExit(per_thread.js),故删前捕获引用,
150
+ * 关闭路径直接调用 internalExit(不经 process.exit)。
151
+ */
152
+ const internalExit = process.reallyExit.bind(process);
153
+ function stripProcessEscapeHatches() {
154
+ for (const key of [
155
+ "binding",
156
+ "_linkedBinding",
157
+ "dlopen",
158
+ "openStdin",
159
+ "reallyExit",
160
+ "abort"
161
+ ]) try {
162
+ Reflect.deleteProperty(process, key);
163
+ } catch {}
164
+ }
135
165
  async function main() {
136
166
  const task = workerData;
167
+ stripProcessEscapeHatches();
137
168
  setupNetworkGuards(task);
138
169
  port.on("message", (msg) => {
139
170
  if (msg?.type === "bridge-response" && msg.response?.id) {
@@ -195,6 +226,7 @@ async function main() {
195
226
  };
196
227
  const runFn = mod["run"];
197
228
  const value = await runFn(task.args ?? {}, context);
229
+ assertSerializable(value);
198
230
  post({
199
231
  type: "execute-result",
200
232
  ok: true,
@@ -222,9 +254,9 @@ async function main() {
222
254
  console.error = originals.error;
223
255
  }
224
256
  }
225
- main().then(() => process.exit(0), (e) => {
257
+ main().then(() => internalExit(0), (e) => {
226
258
  console.error(e);
227
- process.exit(1);
259
+ internalExit(1);
228
260
  });
229
261
 
230
262
  //#endregion
@@ -1,4 +1,4 @@
1
- import { u as WebSkillError } from "./dist-D0saNPi_.js";
1
+ import { u as WebSkillError } from "./dist-D7MsoMPx.js";
2
2
 
3
3
  //#region ../runtime/dist/testing.js
4
4
  /**
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { c as LlmClient, d as LlmResponse, f as LlmStreamEvent, h as MemoryStore, l as LlmCompleteInput, n as ArtifactStore, o as InteractionRequest, s as InteractionResponse, t as Artifact, v as UiBridge } from "./types-CKm5G_eQ-8W8FnP4u.js";
1
+ import { c as LlmClient, d as LlmResponse, f as LlmStreamEvent, h as MemoryStore, l as LlmCompleteInput, n as ArtifactStore, o as InteractionRequest, s as InteractionResponse, t as Artifact, v as UiBridge } from "./types-CKm5G_eQ-BqyXnvoR.js";
2
2
  import { a as loadGoogleConfigFromEnv, i as loadAnthropicConfigFromEnv, n as LlmEnvConfig, o as loadLlmConfigFromEnv, r as ProviderEnvConfig } from "./env-BPUBZCwJ-4jat_SVG.js";
3
3
  //#region ../runtime/dist/testing.d.ts
4
4
  //#region src/llm/mockLlmClient.d.ts
package/dist/testing.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as MemoryArtifactStore } from "./memoryArtifactStore-C9lFVqPF-yFz6yJj0.js";
2
2
  import { n as loadGoogleConfigFromEnv, r as loadLlmConfigFromEnv, t as loadAnthropicConfigFromEnv } from "./env--jJB-TSX-04klhTYi.js";
3
- import { n as MockLlmClient, r as MockUiBridge, t as InMemoryStore } from "./testing-B4pq6JYa.js";
3
+ import { n as MockLlmClient, r as MockUiBridge, t as InMemoryStore } from "./testing-BN18eqbD.js";
4
4
 
5
5
  export { InMemoryStore, MemoryArtifactStore, MockLlmClient, MockUiBridge, loadAnthropicConfigFromEnv, loadGoogleConfigFromEnv, loadLlmConfigFromEnv };