@webskill/sdk 0.0.3 → 0.0.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.
package/dist/browser.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $t as VerifyResult, C as InteractionRequest, M as LlmResponse, Mt as FileStat, N as LlmStreamEvent, Nt as FileSystemProvider, S as InteractionPolicy, Tt as parseBridgeRequest, Wt as SkillInstallSource, X as RenderResultRequest, Zt as SkillsLockfile, at as ScriptExecutor, d as BridgeResponse, it as ScriptExecutionContext, k as LlmClient, l as BridgeCapabilities, lt as ToolResult, m as ExternalToolSource, mt as UiBridge, p as ExternalSkillProvider, qt as SkillManifest, st as ToolDefinition, u as BridgeRequest, vt as bridgeError, w as InteractionResponse } from "./index-DnI0BTEp.js";
1
+ import { A as LlmClient, C as InteractionPolicy, It as FileStat, Jt as SkillInstallSource, Lt as FileSystemProvider, N as LlmResponse, P as LlmStreamEvent, Q as RenderResultRequest, St as bridgeError, T as InteractionResponse, Zt as SkillManifest, ct as ScriptExecutionContext, d as BridgeResponse, dt as ToolDefinition, kt as parseBridgeRequest, l as BridgeCapabilities, lt as ScriptExecutor, m as ExternalToolSource, p as ExternalSkillProvider, pt as ToolResult, rn as VerifyResult, tn as SkillsLockfile, u as BridgeRequest, vt as UiBridge, w as InteractionRequest } from "./index-CqDIreSE.js";
2
2
  //#region ../browser/dist/index.d.ts
3
3
  //#region src/fs/featureDetection.d.ts
4
4
  /** 检测当前环境是否可用 OPFS(navigator.storage.getDirectory) */
@@ -165,6 +165,13 @@ type WorkerRequest = {
165
165
  type: 'cancel';
166
166
  id: string;
167
167
  runId: string;
168
+ } | {
169
+ type: 'list-interrupted';
170
+ id: string;
171
+ } | {
172
+ type: 'resume';
173
+ id: string;
174
+ runId: string;
168
175
  } | {
169
176
  type: 'status';
170
177
  id: string;
@@ -260,6 +267,10 @@ declare class WorkerRuntimeClient {
260
267
  run(prompt: string, runId?: string): Promise<WorkerEvent>;
261
268
  status(runId: string): Promise<WorkerEvent>;
262
269
  cancel(runId: string): Promise<WorkerEvent>;
270
+ /** D3:列出可恢复的 interrupted run */
271
+ listInterrupted(): Promise<WorkerEvent>;
272
+ /** D3:恢复 interrupted run(新 Worker 重建后重新发起等待中的交互) */
273
+ resume(runId: string): Promise<WorkerEvent>;
263
274
  dispose(): void;
264
275
  }
265
276
  //#endregion
package/dist/browser.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as validateSkills, B as WebSkillError, D as normalizeToolContent, E as mergeCatalogEntries, F as SKILL_MANIFEST_FILE, H as buildManifest, K as isValidSkillName, O as parseBridgeRequest, P as SKILLS_LOCKFILE, Q as resolveInsideRoot, R as SkillDiscovery, V as buildCatalog, Y as parseSkillMarkdown, et as verifyManifest, f as MockLlmClient, h as ProgressiveRouter, i as AgentLoop, m as OpenAiCompatibleClient, o as FsArtifactStore, s as FsMemoryStore, x as bridgeError } from "./dist-hMMxARXK.js";
1
+ import { A as parseBridgeRequest, B as SkillDiscovery, C as bridgeError, H as WebSkillError, I as SKILLS_LOCKFILE, J as isValidSkillName, L as SKILL_MANIFEST_FILE, O as mergeCatalogEntries, U as buildCatalog, W as buildManifest, Z as parseSkillMarkdown, b as RUN_SNAPSHOT_SCHEMA_VERSION, c as FsRunSnapshotStore, et as resolveInsideRoot, g as ProgressiveRouter, h as OpenAiCompatibleClient, i as AgentLoop, k as normalizeToolContent, nt as verifyManifest, o as FsArtifactStore, p as MockLlmClient, s as FsMemoryStore, tt as validateSkills } from "./dist-COsE72Ct.js";
2
2
  import { unzipSync } from "fflate";
3
3
 
4
4
  //#region ../browser/dist/index.js
@@ -744,11 +744,16 @@ function parseMainMessage(data) {
744
744
  ...isNonEmptyString(data["runId"]) ? { runId: data["runId"] } : {}
745
745
  } : void 0;
746
746
  case "cancel":
747
- case "status": return isNonEmptyString(data["id"]) && isNonEmptyString(data["runId"]) ? {
747
+ case "status":
748
+ case "resume": return isNonEmptyString(data["id"]) && isNonEmptyString(data["runId"]) ? {
748
749
  type: data["type"],
749
750
  id: data["id"],
750
751
  runId: data["runId"]
751
752
  } : void 0;
753
+ case "list-interrupted": return isNonEmptyString(data["id"]) ? {
754
+ type: "list-interrupted",
755
+ id: data["id"]
756
+ } : void 0;
752
757
  case "interaction-response": {
753
758
  const response = data["response"];
754
759
  return isNonEmptyString(data["workerMessageId"]) && isRecord(response) && isNonEmptyString(response["id"]) ? {
@@ -890,7 +895,11 @@ function startWorkerRuntimeHost(scope, overrides = {}) {
890
895
  ...config.typescript ? { typescript: config.typescript } : {}
891
896
  }),
892
897
  ...config.interaction ? { interaction: config.interaction } : {},
893
- roots: config.roots ?? ["/skills"]
898
+ roots: config.roots ?? ["/skills"],
899
+ snapshotStore: new FsRunSnapshotStore({
900
+ root: "snapshots",
901
+ fs
902
+ })
894
903
  };
895
904
  post({
896
905
  type: "ready",
@@ -936,7 +945,8 @@ function startWorkerRuntimeHost(scope, overrides = {}) {
936
945
  uiBridge,
937
946
  ...state.interaction ? { interaction: state.interaction } : {},
938
947
  ...overrides.externalTools ? { externalTools: overrides.externalTools } : {},
939
- ...overrides.skillProviders ? { skillProviders: overrides.skillProviders } : {}
948
+ ...overrides.skillProviders ? { skillProviders: overrides.skillProviders } : {},
949
+ snapshotStore: state.snapshotStore
940
950
  }).run({
941
951
  sessionId: `session-${runId}`,
942
952
  userPrompt: prompt,
@@ -977,6 +987,91 @@ function startWorkerRuntimeHost(scope, overrides = {}) {
977
987
  } } });
978
988
  return;
979
989
  }
990
+ case "list-interrupted":
991
+ if (!state) {
992
+ result(message.id, { error: {
993
+ code: "RUN_FAILED",
994
+ message: "Host is not initialized"
995
+ } });
996
+ return;
997
+ }
998
+ state.snapshotStore.list().then((snapshots) => result(message.id, { result: { snapshots } }), (e) => result(message.id, { error: serializeError(e) }));
999
+ return;
1000
+ case "resume":
1001
+ if (!state) {
1002
+ result(message.id, { error: {
1003
+ code: "RUN_FAILED",
1004
+ message: "Host is not initialized"
1005
+ } });
1006
+ return;
1007
+ }
1008
+ (async () => {
1009
+ const snapshot = await state.snapshotStore.load(message.runId);
1010
+ if (!snapshot) throw new WebSkillError("RUN_SNAPSHOT_NOT_FOUND", `No snapshot found for run "${message.runId}"`);
1011
+ if (snapshot.schemaVersion !== 1) {
1012
+ await state.snapshotStore.delete(message.runId);
1013
+ throw new WebSkillError("RUN_SNAPSHOT_INCOMPATIBLE", `Snapshot for run "${message.runId}" has incompatible schemaVersion ${String(snapshot.schemaVersion)}`);
1014
+ }
1015
+ if (Date.now() > Date.parse(snapshot.interactionExpiresAt)) {
1016
+ await state.snapshotStore.delete(message.runId);
1017
+ const endedAt = (/* @__PURE__ */ new Date()).toISOString();
1018
+ return {
1019
+ output: "Interaction timed out before the run was resumed",
1020
+ run: {
1021
+ id: message.runId,
1022
+ sessionId: snapshot.sessionId,
1023
+ status: "failed",
1024
+ phase: "fail",
1025
+ userPrompt: snapshot.userPrompt,
1026
+ startedAt: snapshot.startedAt,
1027
+ endedAt,
1028
+ terminationReason: "interaction-timeout",
1029
+ activeSkillNames: snapshot.activeSkillNames,
1030
+ artifacts: [],
1031
+ trace: [{
1032
+ id: `evt-expired-${message.runId}`,
1033
+ runId: message.runId,
1034
+ ts: endedAt,
1035
+ type: "run.failed",
1036
+ message: `Interaction timed out before the run was resumed (expired at ${snapshot.interactionExpiresAt})`,
1037
+ data: {
1038
+ reason: "interaction-timeout",
1039
+ code: "RUN_INTERACTION_TIMEOUT"
1040
+ }
1041
+ }]
1042
+ }
1043
+ };
1044
+ }
1045
+ const resumeUiBridge = new WorkerUiBridge(scope);
1046
+ activeUiBridge = resumeUiBridge;
1047
+ try {
1048
+ return await new AgentLoop({
1049
+ llm: state.llm,
1050
+ executor: state.executor,
1051
+ artifactStore: new FsArtifactStore({
1052
+ root: "artifacts",
1053
+ fs: state.fs
1054
+ }),
1055
+ memory: new FsMemoryStore({
1056
+ root: "memory",
1057
+ fs: state.fs
1058
+ }),
1059
+ fs: state.fs,
1060
+ skillIndex: /* @__PURE__ */ new Map(),
1061
+ uiBridge: resumeUiBridge,
1062
+ ...state.interaction ? { interaction: state.interaction } : {},
1063
+ ...overrides.externalTools ? { externalTools: overrides.externalTools } : {},
1064
+ ...overrides.skillProviders ? { skillProviders: overrides.skillProviders } : {},
1065
+ snapshotStore: state.snapshotStore
1066
+ }).resume(snapshot);
1067
+ } finally {
1068
+ activeUiBridge = void 0;
1069
+ }
1070
+ })().then((runResult) => {
1071
+ runs.set(message.runId, { status: runResult.run.status });
1072
+ result(message.id, { result: runResult });
1073
+ }, (e) => result(message.id, { error: serializeError(e) }));
1074
+ return;
980
1075
  case "cancel":
981
1076
  if (!runs.get(message.runId)) {
982
1077
  result(message.id, { error: {
@@ -1042,6 +1137,21 @@ var WorkerRuntimeClient = class {
1042
1137
  runId
1043
1138
  });
1044
1139
  }
1140
+ /** D3:列出可恢复的 interrupted run */
1141
+ listInterrupted() {
1142
+ return this.#call({
1143
+ type: "list-interrupted",
1144
+ id: this.#nextId()
1145
+ });
1146
+ }
1147
+ /** D3:恢复 interrupted run(新 Worker 重建后重新发起等待中的交互) */
1148
+ resume(runId) {
1149
+ return this.#call({
1150
+ type: "resume",
1151
+ id: this.#nextId(),
1152
+ runId
1153
+ });
1154
+ }
1045
1155
  dispose() {
1046
1156
  for (const [id, pending] of this.#pending) {
1047
1157
  clearTimeout(pending.timer);
@@ -1,4 +1,4 @@
1
- import { $ as validateSkills, B as WebSkillError, D as normalizeToolContent, F as SKILL_MANIFEST_FILE, H as buildManifest, K as isValidSkillName, O as parseBridgeRequest, P as SKILLS_LOCKFILE, Q as resolveInsideRoot, Y as parseSkillMarkdown, et as verifyManifest, o as FsArtifactStore, s as FsMemoryStore, x as bridgeError } from "./dist-hMMxARXK.js";
1
+ import { A as parseBridgeRequest, C as bridgeError, H as WebSkillError, I as SKILLS_LOCKFILE, J as isValidSkillName, L as SKILL_MANIFEST_FILE, W as buildManifest, Z as parseSkillMarkdown, et as resolveInsideRoot, k as normalizeToolContent, nt as verifyManifest, o as FsArtifactStore, s as FsMemoryStore, tt as validateSkills } from "./dist-COsE72Ct.js";
2
2
  import { existsSync, promises, readFileSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
@@ -1384,34 +1384,35 @@ var AgentLoop = class {
1384
1384
  };
1385
1385
  }
1386
1386
  async run(input) {
1387
- const llm = this.#deps.llm;
1388
- const artifactStore = this.#deps.artifactStore;
1387
+ this.#deps.llm;
1388
+ this.#deps.artifactStore;
1389
1389
  const now = this.#deps.clock?.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
1390
1390
  const runId = input.runId ?? `run-${Math.random().toString(36).slice(2, 10)}`;
1391
1391
  const trace = new TraceRecorder(runId, this.#deps.clock);
1392
1392
  const startedAt = now();
1393
1393
  const startMs = Date.parse(startedAt);
1394
- const run = {
1395
- id: runId,
1396
- sessionId: input.sessionId,
1397
- status: "running",
1398
- phase: "route",
1399
- userPrompt: input.userPrompt,
1400
- startedAt,
1401
- activeSkillNames: [],
1402
- artifacts: [],
1403
- trace: []
1404
- };
1405
1394
  const state = {
1406
1395
  runId,
1407
- run,
1396
+ run: {
1397
+ id: runId,
1398
+ sessionId: input.sessionId,
1399
+ status: "running",
1400
+ phase: "route",
1401
+ userPrompt: input.userPrompt,
1402
+ startedAt,
1403
+ activeSkillNames: [],
1404
+ artifacts: [],
1405
+ trace: []
1406
+ },
1408
1407
  trace,
1409
1408
  reader: new SkillReader(this.#deps.fs, this.#deps.skillIndex),
1410
1409
  activated: /* @__PURE__ */ new Set(),
1411
1410
  activatedTools: /* @__PURE__ */ new Map(),
1412
1411
  toolTimeoutMs: this.#config.toolTimeoutMs,
1413
1412
  now,
1414
- interactionSeq: 0
1413
+ interactionSeq: 0,
1414
+ messages: [],
1415
+ turn: 0
1415
1416
  };
1416
1417
  if (this.#deps.hooks && !this.#deps.hooks.onWarning) this.#deps.hooks.onWarning = (message) => trace.record("run.warning", { message });
1417
1418
  const route = this.#deps.catalogFilter ? {
@@ -1431,113 +1432,272 @@ var AgentLoop = class {
1431
1432
  return [];
1432
1433
  }
1433
1434
  }))).flat();
1434
- const messages = [{
1435
+ state.messages = [{
1435
1436
  role: "system",
1436
1437
  content: route.systemPrompt
1437
1438
  }, {
1438
1439
  role: "user",
1439
1440
  content: input.userPrompt
1440
1441
  }];
1441
- const finish = async (status, reason, output, errorCode) => {
1442
- run.status = status;
1443
- run.terminationReason = reason;
1444
- run.endedAt = now();
1445
- run.activeSkillNames = [...state.activated].sort();
1446
- run.artifacts = await artifactStore.listArtifacts(runId);
1447
- if (status === "completed") trace.record("run.completed", { data: { reason } });
1448
- else if (status === "cancelled") trace.record("run.cancelled", {
1449
- message: output,
1450
- data: { reason }
1451
- });
1452
- else trace.record("run.failed", {
1453
- message: output,
1454
- data: {
1455
- reason,
1456
- ...errorCode ? { code: errorCode } : {}
1457
- }
1458
- });
1459
- const bridge = this.#deps.uiBridge;
1460
- if (status === "completed" && bridge?.renderResult && this.#config.renderResult !== "off") try {
1461
- const request = buildRenderResult(run, output);
1462
- await bridge.renderResult(request);
1463
- trace.record("ui.rendered", { data: { blockCount: request.blocks.length } });
1464
- } catch (e) {
1465
- trace.record("run.warning", { message: `renderResult failed: ${messageOf(e)}` });
1466
- }
1442
+ try {
1443
+ return await this.#turnLoop(state, startMs, 1, externalSpecs);
1444
+ } catch (e) {
1445
+ if (e instanceof WebSkillError && e.code === "RUN_FAILED") return this.#finish(state, "failed", "hook-error", messageOf(e), "RUN_FAILED");
1446
+ throw e;
1447
+ }
1448
+ }
1449
+ /** 主循环(run 从第 1 轮、resume 从快照轮次续跑;totalTimeout 以 startedAt 续算) */
1450
+ async #turnLoop(state, startMs, startTurn, externalSpecs) {
1451
+ const finish = (status, reason, output, errorCode) => this.#finish(state, status, reason, output, errorCode);
1452
+ const { llm } = this.#deps;
1453
+ const { trace, messages } = state;
1454
+ for (let turn = startTurn;; turn++) {
1455
+ state.turn = turn;
1456
+ if (turn > this.#config.maxTurns) return finish("failed", "max-turns", `Agent loop exceeded the maximum of ${this.#config.maxTurns} turns`, "RUN_MAX_TURNS_EXCEEDED");
1457
+ if (Date.parse(state.now()) - startMs > this.#config.totalTimeoutMs) return finish("failed", "timeout", `Agent loop exceeded the total timeout of ${this.#config.totalTimeoutMs}ms`, "RUN_TIMEOUT");
1458
+ const toolSpecs = [
1459
+ toLlmToolSpec(READ_SKILL_FILE_TOOL),
1460
+ ...this.#deps.uiBridge ? [toLlmToolSpec(ASK_USER_TOOL)] : [],
1461
+ ...[...state.activatedTools.values()].map(toLlmToolSpec),
1462
+ ...externalSpecs
1463
+ ];
1464
+ trace.record("llm.request", { data: {
1465
+ turn,
1466
+ messageCount: messages.length,
1467
+ toolCount: toolSpecs.length
1468
+ } });
1469
+ let response;
1467
1470
  try {
1468
- await this.#lifecycle(status === "completed" ? "complete" : "fail", state, { reason });
1471
+ response = llm.stream ? await this.#completeStreaming(llm, state, {
1472
+ model: this.#deps.model,
1473
+ messages,
1474
+ tools: toolSpecs,
1475
+ temperature: this.#config.temperature
1476
+ }) : await llm.complete({
1477
+ model: this.#deps.model,
1478
+ messages,
1479
+ tools: toolSpecs,
1480
+ temperature: this.#config.temperature
1481
+ });
1469
1482
  } catch (e) {
1470
- trace.record("run.warning", { message: `Terminal lifecycle hook failed: ${messageOf(e)}` });
1483
+ const code = e instanceof WebSkillError && (e.code === "LLM_UNAVAILABLE" || e.code === "LLM_REQUEST_FAILED") ? e.code : "LLM_REQUEST_FAILED";
1484
+ return finish("failed", "llm-error", messageOf(e), code);
1471
1485
  }
1472
- run.trace = trace.list();
1473
- return {
1474
- output,
1475
- run
1476
- };
1477
- };
1478
- try {
1479
- for (let turn = 1;; turn++) {
1480
- if (turn > this.#config.maxTurns) return await finish("failed", "max-turns", `Agent loop exceeded the maximum of ${this.#config.maxTurns} turns`, "RUN_MAX_TURNS_EXCEEDED");
1481
- if (Date.parse(now()) - startMs > this.#config.totalTimeoutMs) return await finish("failed", "timeout", `Agent loop exceeded the total timeout of ${this.#config.totalTimeoutMs}ms`, "RUN_TIMEOUT");
1482
- const toolSpecs = [
1483
- toLlmToolSpec(READ_SKILL_FILE_TOOL),
1484
- ...this.#deps.uiBridge ? [toLlmToolSpec(ASK_USER_TOOL)] : [],
1485
- ...[...state.activatedTools.values()].map(toLlmToolSpec),
1486
- ...externalSpecs
1487
- ];
1488
- trace.record("llm.request", { data: {
1489
- turn,
1490
- messageCount: messages.length,
1491
- toolCount: toolSpecs.length
1492
- } });
1493
- let response;
1486
+ trace.record("llm.response", { data: {
1487
+ turn,
1488
+ hasToolCalls: Boolean(response.toolCalls?.length),
1489
+ contentLength: response.content?.length ?? 0
1490
+ } });
1491
+ if (!response.toolCalls?.length) return finish("completed", "final-answer", response.content ?? "");
1492
+ await this.#lifecycle("execute", state, { turn });
1493
+ messages.push({
1494
+ role: "assistant",
1495
+ content: response.content ?? "",
1496
+ toolCalls: response.toolCalls
1497
+ });
1498
+ for (const call of response.toolCalls) {
1499
+ let result;
1494
1500
  try {
1495
- response = llm.stream ? await this.#completeStreaming(llm, state, {
1496
- model: this.#deps.model,
1497
- messages,
1498
- tools: toolSpecs,
1499
- temperature: this.#config.temperature
1500
- }) : await llm.complete({
1501
- model: this.#deps.model,
1502
- messages,
1503
- tools: toolSpecs,
1504
- temperature: this.#config.temperature
1505
- });
1501
+ result = await this.#executeCall(call, state);
1506
1502
  } catch (e) {
1507
- const code = e instanceof WebSkillError && (e.code === "LLM_UNAVAILABLE" || e.code === "LLM_REQUEST_FAILED") ? e.code : "LLM_REQUEST_FAILED";
1508
- return await finish("failed", "llm-error", messageOf(e), code);
1503
+ if (e instanceof RunTerminated) return finish(e.outcome.status, e.outcome.reason, e.outcome.message, e.outcome.code);
1504
+ throw e;
1509
1505
  }
1510
- trace.record("llm.response", { data: {
1511
- turn,
1512
- hasToolCalls: Boolean(response.toolCalls?.length),
1513
- contentLength: response.content?.length ?? 0
1514
- } });
1515
- if (!response.toolCalls?.length) return await finish("completed", "final-answer", response.content ?? "");
1516
- await this.#lifecycle("execute", state, { turn });
1517
1506
  messages.push({
1518
- role: "assistant",
1519
- content: response.content ?? "",
1520
- toolCalls: response.toolCalls
1507
+ role: "tool",
1508
+ toolCallId: call.id,
1509
+ content: JSON.stringify(result)
1521
1510
  });
1522
- for (const call of response.toolCalls) {
1523
- let result;
1524
- try {
1525
- result = await this.#executeCall(call, state);
1526
- } catch (e) {
1527
- if (e instanceof RunTerminated) return await finish(e.outcome.status, e.outcome.reason, e.outcome.message, e.outcome.code);
1528
- throw e;
1529
- }
1530
- messages.push({
1531
- role: "tool",
1532
- toolCallId: call.id,
1533
- content: JSON.stringify(result)
1534
- });
1535
- }
1536
1511
  }
1512
+ }
1513
+ }
1514
+ /** 统一终态处理:completed/failed/cancelled;终态即删快照(快照是续命机制,审计归治理) */
1515
+ async #finish(state, status, reason, output, errorCode) {
1516
+ const { run, trace } = state;
1517
+ run.status = status;
1518
+ run.terminationReason = reason;
1519
+ run.endedAt = state.now();
1520
+ run.activeSkillNames = [...state.activated].sort();
1521
+ run.artifacts = await this.#deps.artifactStore.listArtifacts(state.runId);
1522
+ if (status === "completed") trace.record("run.completed", { data: { reason } });
1523
+ else if (status === "cancelled") trace.record("run.cancelled", {
1524
+ message: output,
1525
+ data: { reason }
1526
+ });
1527
+ else trace.record("run.failed", {
1528
+ message: output,
1529
+ data: {
1530
+ reason,
1531
+ ...errorCode ? { code: errorCode } : {}
1532
+ }
1533
+ });
1534
+ const bridge = this.#deps.uiBridge;
1535
+ if (status === "completed" && bridge?.renderResult && this.#config.renderResult !== "off") try {
1536
+ const request = buildRenderResult(run, output);
1537
+ await bridge.renderResult(request);
1538
+ trace.record("ui.rendered", { data: { blockCount: request.blocks.length } });
1539
+ } catch (e) {
1540
+ trace.record("run.warning", { message: `renderResult failed: ${messageOf(e)}` });
1541
+ }
1542
+ if (this.#deps.snapshotStore) try {
1543
+ await this.#deps.snapshotStore.delete(state.runId);
1544
+ } catch (e) {
1545
+ trace.record("run.warning", { message: `Failed to delete run snapshot: ${messageOf(e)}` });
1546
+ }
1547
+ try {
1548
+ await this.#lifecycle(status === "completed" ? "complete" : "fail", state, { reason });
1537
1549
  } catch (e) {
1538
- if (e instanceof WebSkillError && e.code === "RUN_FAILED") return await finish("failed", "hook-error", messageOf(e), "RUN_FAILED");
1550
+ trace.record("run.warning", { message: `Terminal lifecycle hook failed: ${messageOf(e)}` });
1551
+ }
1552
+ run.trace = trace.list();
1553
+ return {
1554
+ output,
1555
+ run
1556
+ };
1557
+ }
1558
+ /** D3 快照写入(含 pendingInteraction 与过期时间;写失败降级 run.warning) */
1559
+ async #saveSnapshot(state, request) {
1560
+ const store = this.#deps.snapshotStore;
1561
+ if (!store) return;
1562
+ const snapshot = {
1563
+ schemaVersion: 1,
1564
+ runId: state.runId,
1565
+ sessionId: state.run.sessionId,
1566
+ userPrompt: state.run.userPrompt,
1567
+ startedAt: state.run.startedAt,
1568
+ messages: state.messages.map((m) => ({ ...m })),
1569
+ turn: state.turn,
1570
+ activeSkillNames: [...state.activated].sort(),
1571
+ activatedTools: [...state.activatedTools.values()],
1572
+ pendingInteraction: request,
1573
+ interactionExpiresAt: state.run.interruptExpiresAt,
1574
+ config: {
1575
+ maxTurns: this.#config.maxTurns,
1576
+ totalTimeoutMs: this.#config.totalTimeoutMs,
1577
+ toolTimeoutMs: this.#config.toolTimeoutMs,
1578
+ ...this.#config.temperature !== void 0 ? { temperature: this.#config.temperature } : {}
1579
+ },
1580
+ snapshotAt: state.now()
1581
+ };
1582
+ try {
1583
+ await store.save(snapshot);
1584
+ } catch (e) {
1585
+ state.trace.record("run.warning", { message: `Failed to save run snapshot: ${messageOf(e)}` });
1586
+ }
1587
+ }
1588
+ /**
1589
+ * D3 恢复:以快照重建 LoopState,重新发起等待中的交互(表单重新渲染),
1590
+ * 应答后从快照轮次续跑主循环;totalTimeout 以快照 startedAt 续算。
1591
+ */
1592
+ async resume(snapshot) {
1593
+ const now = this.#deps.clock?.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
1594
+ const runId = snapshot.runId;
1595
+ const trace = new TraceRecorder(runId, this.#deps.clock);
1596
+ const startMs = Date.parse(snapshot.startedAt);
1597
+ const state = {
1598
+ runId,
1599
+ run: {
1600
+ id: runId,
1601
+ sessionId: snapshot.sessionId,
1602
+ status: "running",
1603
+ phase: "execute",
1604
+ userPrompt: snapshot.userPrompt,
1605
+ startedAt: snapshot.startedAt,
1606
+ activeSkillNames: snapshot.activeSkillNames,
1607
+ artifacts: [],
1608
+ trace: []
1609
+ },
1610
+ trace,
1611
+ reader: new SkillReader(this.#deps.fs, this.#deps.skillIndex),
1612
+ activated: new Set(snapshot.activeSkillNames),
1613
+ activatedTools: new Map(snapshot.activatedTools.map((d) => [d.name, d])),
1614
+ toolTimeoutMs: snapshot.config.toolTimeoutMs,
1615
+ now,
1616
+ interactionSeq: 0,
1617
+ messages: snapshot.messages.map((m) => ({ ...m })),
1618
+ turn: snapshot.turn
1619
+ };
1620
+ if (this.#deps.hooks && !this.#deps.hooks.onWarning) this.#deps.hooks.onWarning = (message) => trace.record("run.warning", { message });
1621
+ trace.record("run.resumed", { data: {
1622
+ snapshotAt: snapshot.snapshotAt,
1623
+ turn: snapshot.turn,
1624
+ interactionType: snapshot.pendingInteraction.type
1625
+ } });
1626
+ const pending = snapshot.pendingInteraction;
1627
+ const pendingCall = this.#findPendingToolCall(state.messages);
1628
+ try {
1629
+ if ((pending.type === "form" || pending.type === "select") && pendingCall) {
1630
+ const value = await this.#interact(state, pending, {
1631
+ tool: pendingCall.name,
1632
+ resumed: true
1633
+ });
1634
+ const args = {
1635
+ ...pendingCall.arguments,
1636
+ ...typeof value === "object" && value !== null ? value : {}
1637
+ };
1638
+ const result = await this.#executeCall({
1639
+ ...pendingCall,
1640
+ arguments: args
1641
+ }, state);
1642
+ state.messages.push({
1643
+ role: "tool",
1644
+ toolCallId: pendingCall.id,
1645
+ content: JSON.stringify(result)
1646
+ });
1647
+ } else if (pending.type === "ask" && pendingCall) {
1648
+ const value = await this.#interact(state, pending, {
1649
+ tool: pendingCall.name,
1650
+ resumed: true
1651
+ });
1652
+ const result = {
1653
+ ok: true,
1654
+ content: [{
1655
+ type: "text",
1656
+ text: typeof value === "string" ? value : JSON.stringify(value ?? "")
1657
+ }]
1658
+ };
1659
+ state.trace.record("tool.completed", { data: {
1660
+ name: pendingCall.name,
1661
+ callId: pendingCall.id
1662
+ } });
1663
+ state.messages.push({
1664
+ role: "tool",
1665
+ toolCallId: pendingCall.id,
1666
+ content: JSON.stringify(result)
1667
+ });
1668
+ } else if (pendingCall) {
1669
+ const result = await this.#executeCall(pendingCall, state);
1670
+ state.messages.push({
1671
+ role: "tool",
1672
+ toolCallId: pendingCall.id,
1673
+ content: JSON.stringify(result)
1674
+ });
1675
+ }
1676
+ } catch (e) {
1677
+ if (e instanceof RunTerminated) return this.#finish(state, e.outcome.status, e.outcome.reason, e.outcome.message, e.outcome.code);
1539
1678
  throw e;
1540
1679
  }
1680
+ const externalSpecs = (await Promise.all((this.#deps.externalTools ?? []).map(async (source) => {
1681
+ try {
1682
+ return await source.listToolSpecs();
1683
+ } catch (e) {
1684
+ trace.record("run.warning", { message: `External tool source "${source.kind}" failed to list specs: ${messageOf(e)}` });
1685
+ return [];
1686
+ }
1687
+ }))).flat();
1688
+ try {
1689
+ return await this.#turnLoop(state, startMs, snapshot.turn + 1, externalSpecs);
1690
+ } catch (e) {
1691
+ if (e instanceof WebSkillError && e.code === "RUN_FAILED") return this.#finish(state, "failed", "hook-error", messageOf(e), "RUN_FAILED");
1692
+ throw e;
1693
+ }
1694
+ }
1695
+ /** 最后一条 assistant 消息里第一个尚无 tool 响应的工具调用(即中断时正在处理的那个) */
1696
+ #findPendingToolCall(messages) {
1697
+ const lastAssistant = [...messages].reverse().find((m) => m.role === "assistant" && m.toolCalls?.length);
1698
+ if (!lastAssistant?.toolCalls) return void 0;
1699
+ const answered = new Set(messages.filter((m) => m.role === "tool").map((m) => m.toolCallId));
1700
+ return lastAssistant.toolCalls.find((call) => !answered.has(call.id));
1541
1701
  }
1542
1702
  /**
1543
1703
  * 流式 LLM 调用:text-delta 仅在 EventBus 有订阅者时发射 llm.delta 事件,
@@ -1598,6 +1758,7 @@ var AgentLoop = class {
1598
1758
  const { run } = state;
1599
1759
  run.status = "interrupted";
1600
1760
  run.interruptExpiresAt = new Date(Date.parse(state.now()) + this.#policy.interactionTimeoutMs).toISOString();
1761
+ await this.#saveSnapshot(state, request);
1601
1762
  await this.#lifecycle("interact", state, {
1602
1763
  interactionId: request.id,
1603
1764
  type: request.type
@@ -1954,6 +2115,58 @@ function mergeCatalogEntries(localEntries, providerEntries) {
1954
2115
  for (const entry of providerEntries) if (!byName.has(entry.name)) byName.set(entry.name, entry);
1955
2116
  return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
1956
2117
  }
2118
+ const RUN_SNAPSHOT_SCHEMA_VERSION = 1;
2119
+ const SNAPSHOT_SUFFIX = ".snapshot.json";
2120
+ /**
2121
+ * FileSystemProvider 后端的快照存储:<root>/<runId>.snapshot.json。
2122
+ * 坏 JSON → RUN_SNAPSHOT_INCOMPATIBLE 并自动清理坏文件;runId 过路径安全校验。
2123
+ */
2124
+ var FsRunSnapshotStore = class {
2125
+ #root;
2126
+ #fs;
2127
+ constructor(deps) {
2128
+ this.#root = deps.root.replace(/\/+$/, "");
2129
+ this.#fs = deps.fs;
2130
+ }
2131
+ #path(runId) {
2132
+ return resolveInsideRoot(this.#root, `${runId}${SNAPSHOT_SUFFIX}`);
2133
+ }
2134
+ async save(snapshot) {
2135
+ await this.#fs.writeText(this.#path(snapshot.runId), JSON.stringify(snapshot, null, 2));
2136
+ }
2137
+ async load(runId) {
2138
+ const path = this.#path(runId);
2139
+ if (!await this.#fs.exists(path)) return void 0;
2140
+ let parsed;
2141
+ try {
2142
+ parsed = JSON.parse(await this.#fs.readText(path));
2143
+ } catch (e) {
2144
+ await this.#fs.remove(path).catch(() => void 0);
2145
+ throw new WebSkillError("RUN_SNAPSHOT_INCOMPATIBLE", `Snapshot for run "${runId}" is corrupted and was deleted: ${e instanceof Error ? e.message : String(e)}`, e);
2146
+ }
2147
+ const snapshot = parsed;
2148
+ if (typeof snapshot !== "object" || snapshot === null || snapshot.runId !== runId) {
2149
+ await this.#fs.remove(path).catch(() => void 0);
2150
+ throw new WebSkillError("RUN_SNAPSHOT_INCOMPATIBLE", `Snapshot for run "${runId}" has an unexpected shape and was deleted`);
2151
+ }
2152
+ return snapshot;
2153
+ }
2154
+ async delete(runId) {
2155
+ const path = this.#path(runId);
2156
+ if (await this.#fs.exists(path)) await this.#fs.remove(path);
2157
+ }
2158
+ async list() {
2159
+ if (!await this.#fs.exists(this.#root)) return [];
2160
+ const out = [];
2161
+ for (const entry of await this.#fs.list(this.#root)) {
2162
+ if (entry.type !== "file" || !entry.path.endsWith(SNAPSHOT_SUFFIX)) continue;
2163
+ try {
2164
+ out.push(JSON.parse(await this.#fs.readText(entry.path)));
2165
+ } catch {}
2166
+ }
2167
+ return out.sort((a, b) => a.snapshotAt.localeCompare(b.snapshotAt));
2168
+ }
2169
+ };
1957
2170
  /** runtime 门面:组合 discovery / router / agent loop / lifecycle */
1958
2171
  var WebSkillRuntime = class {
1959
2172
  #deps;
@@ -2017,7 +2230,8 @@ var WebSkillRuntime = class {
2017
2230
  longTerm: this.#deps.longTerm,
2018
2231
  externalTools: this.#deps.externalTools,
2019
2232
  skillProviders: this.#deps.skillProviders,
2020
- catalogFilter: this.#deps.catalogFilter
2233
+ catalogFilter: this.#deps.catalogFilter,
2234
+ snapshotStore: this.#deps.snapshotStore
2021
2235
  }, this.#deps.config).run({
2022
2236
  sessionId: this.#session.id,
2023
2237
  userPrompt,
@@ -2037,7 +2251,78 @@ var WebSkillRuntime = class {
2037
2251
  });
2038
2252
  return result;
2039
2253
  }
2254
+ /** D3:列出可恢复的 interrupted run(供 UI 展示"未完成任务") */
2255
+ async listInterruptedRuns() {
2256
+ if (!this.#deps.snapshotStore) return [];
2257
+ return this.#deps.snapshotStore.list();
2258
+ }
2259
+ /**
2260
+ * D3 恢复 interrupted run:
2261
+ * 不存在 → RUN_SNAPSHOT_NOT_FOUND;schemaVersion 不匹配 → 删除 + RUN_SNAPSHOT_INCOMPATIBLE;
2262
+ * 已过期 → interaction-timeout 终态并删快照;否则重建 LoopState 重新发起交互续跑。
2263
+ */
2264
+ async resumeRun(runId) {
2265
+ const store = this.#deps.snapshotStore;
2266
+ const snapshot = store ? await store.load(runId) : void 0;
2267
+ if (!snapshot) throw new WebSkillError("RUN_SNAPSHOT_NOT_FOUND", `No snapshot found for run "${runId}"`);
2268
+ if (snapshot.schemaVersion !== 1) {
2269
+ await store.delete(runId);
2270
+ throw new WebSkillError("RUN_SNAPSHOT_INCOMPATIBLE", `Snapshot for run "${runId}" has incompatible schemaVersion ${String(snapshot.schemaVersion)}`);
2271
+ }
2272
+ if (Date.now() > Date.parse(snapshot.interactionExpiresAt)) {
2273
+ await store.delete(runId);
2274
+ const endedAt = (/* @__PURE__ */ new Date()).toISOString();
2275
+ return {
2276
+ output: "Interaction timed out before the run was resumed",
2277
+ run: {
2278
+ id: runId,
2279
+ sessionId: snapshot.sessionId,
2280
+ status: "failed",
2281
+ phase: "fail",
2282
+ userPrompt: snapshot.userPrompt,
2283
+ startedAt: snapshot.startedAt,
2284
+ endedAt,
2285
+ terminationReason: "interaction-timeout",
2286
+ activeSkillNames: snapshot.activeSkillNames,
2287
+ artifacts: [],
2288
+ trace: [{
2289
+ id: `evt-expired-${runId}`,
2290
+ runId,
2291
+ ts: endedAt,
2292
+ type: "run.failed",
2293
+ message: `Interaction timed out before the run was resumed (expired at ${snapshot.interactionExpiresAt})`,
2294
+ data: {
2295
+ reason: "interaction-timeout",
2296
+ code: "RUN_INTERACTION_TIMEOUT"
2297
+ }
2298
+ }]
2299
+ }
2300
+ };
2301
+ }
2302
+ if (!this.#catalogCache) await this.discover();
2303
+ const cache = this.#catalogCache;
2304
+ if (!cache) throw new WebSkillError("RUN_FAILED", "discover() did not populate the catalog cache");
2305
+ return new AgentLoop({
2306
+ llm: this.#deps.llm,
2307
+ executor: this.#deps.executor,
2308
+ schemaInferer: this.#deps.schemaInferer,
2309
+ artifactStore: this.#deps.artifactStore,
2310
+ fs: this.#deps.fs,
2311
+ skillIndex: cache.index,
2312
+ model: this.#deps.model,
2313
+ uiBridge: this.#deps.uiBridge,
2314
+ interaction: this.#deps.interaction,
2315
+ memory: this.#deps.memory,
2316
+ hooks: this.#deps.hooks,
2317
+ eventBus: this.#events,
2318
+ longTerm: this.#deps.longTerm,
2319
+ externalTools: this.#deps.externalTools,
2320
+ skillProviders: this.#deps.skillProviders,
2321
+ catalogFilter: this.#deps.catalogFilter,
2322
+ snapshotStore: store
2323
+ }, this.#deps.config).resume(snapshot);
2324
+ }
2040
2325
  };
2041
2326
 
2042
2327
  //#endregion
2043
- export { validateSkills as $, schemaToForm as A, WebSkillError as B, createScriptContext as C, normalizeToolContent as D, mergeCatalogEntries as E, SKILL_MANIFEST_FILE as F, escapeXml as G, buildManifest as H, SKILL_NAME_MAX_LENGTH as I, normalizePath as J, isValidSkillName as K, SKILL_NAME_PATTERN as L, toVercelToolSpecs as M, MemoryFS as N, parseBridgeRequest as O, SKILLS_LOCKFILE as P, resolveInsideRoot as Q, SkillDiscovery as R, buildRenderResult as S, fromVercelStreamPart as T, checkSkillRules as U, buildCatalog as V, computeDigest as W, renderAvailableSkillsXml as X, parseSkillMarkdown as Y, renderCatalogJson as Z, READ_SKILL_FILE_TOOL as _, EventBus as a, WebSkillRuntime as b, FullDisclosureRouter as c, MemoryArtifactStore as d, verifyManifest as et, MockLlmClient as f, READ_SKILL_FILE_INPUT_SCHEMA as g, ProgressiveRouter as h, AgentLoop as i, toLlmToolSpec as j, resolveToolName as k, HookRunner as l, OpenAiCompatibleClient as m, ASK_USER_TOOL as n, FsArtifactStore as o, MockUiBridge as p, jsonRenderer as q, ASK_USER_TOOL_NAME as r, FsMemoryStore as s, ASK_USER_INPUT_SCHEMA as t, xmlRenderer as tt, InMemoryStore as u, READ_SKILL_FILE_TOOL_NAME as v, fromVercelResult as w, bridgeError as x, TraceRecorder as y, SkillReader as z };
2328
+ export { renderCatalogJson as $, parseBridgeRequest as A, SkillDiscovery as B, bridgeError as C, fromVercelStreamPart as D, fromVercelResult as E, MemoryFS as F, checkSkillRules as G, WebSkillError as H, SKILLS_LOCKFILE as I, isValidSkillName as J, computeDigest as K, SKILL_MANIFEST_FILE as L, schemaToForm as M, toLlmToolSpec as N, mergeCatalogEntries as O, toVercelToolSpecs as P, renderAvailableSkillsXml as Q, SKILL_NAME_MAX_LENGTH as R, WebSkillRuntime as S, createScriptContext as T, buildCatalog as U, SkillReader as V, buildManifest as W, normalizePath as X, jsonRenderer as Y, parseSkillMarkdown as Z, READ_SKILL_FILE_INPUT_SCHEMA as _, EventBus as a, RUN_SNAPSHOT_SCHEMA_VERSION as b, FsRunSnapshotStore as c, InMemoryStore as d, resolveInsideRoot as et, MemoryArtifactStore as f, ProgressiveRouter as g, OpenAiCompatibleClient as h, AgentLoop as i, resolveToolName as j, normalizeToolContent as k, FullDisclosureRouter as l, MockUiBridge as m, ASK_USER_TOOL as n, verifyManifest as nt, FsArtifactStore as o, MockLlmClient as p, escapeXml as q, ASK_USER_TOOL_NAME as r, xmlRenderer as rt, FsMemoryStore as s, ASK_USER_INPUT_SCHEMA as t, validateSkills as tt, HookRunner as u, READ_SKILL_FILE_TOOL as v, buildRenderResult as w, TraceRecorder as x, READ_SKILL_FILE_TOOL_NAME as y, SKILL_NAME_PATTERN as z };
@@ -1,5 +1,5 @@
1
- import { Nt as FileSystemProvider, Vt as SkillCatalogEntry, gt as WebSkillRuntime, j as LlmMessage, k as LlmClient, mt as UiBridge, qt as SkillManifest, tt as RuntimeRun } from "./index-DnI0BTEp.js";
2
- import { d as SkillManager } from "./index-D65Jk0ju.js";
1
+ import { A as LlmClient, Gt as SkillCatalogEntry, Lt as FileSystemProvider, M as LlmMessage, Zt as SkillManifest, at as RuntimeRun, bt as WebSkillRuntime, vt as UiBridge } from "./index-CqDIreSE.js";
2
+ import { d as SkillManager } from "./index-BsbfEiaC.js";
3
3
  //#region ../governance/dist/index.d.ts
4
4
  //#region src/types.d.ts
5
5
  type CandidateStatus = 'draft' | 'pending-review' | 'approved' | 'published' | 'rejected';
@@ -1,5 +1,5 @@
1
- import { $ as validateSkills, B as WebSkillError, K as isValidSkillName, Q as resolveInsideRoot } from "./dist-hMMxARXK.js";
2
- import { i as NodeFS } from "./dist-C1p26Ap9.js";
1
+ import { H as WebSkillError, J as isValidSkillName, et as resolveInsideRoot, tt as validateSkills } from "./dist-COsE72Ct.js";
2
+ import { i as NodeFS } from "./dist-Bvhbxrrt.js";
3
3
  import path from "node:path";
4
4
  import { mkdtemp } from "node:fs/promises";
5
5
  import { tmpdir } from "node:os";
@@ -1,4 +1,4 @@
1
- import { $t as VerifyResult, C as InteractionRequest, Mt as FileStat, Nt as FileSystemProvider, Pt as JsonSchema, Wt as SkillInstallSource, X as RenderResultRequest, Zt as SkillsLockfile, _ as FsMemoryStore, at as ScriptExecutor, g as FsArtifactStore, it as ScriptExecutionContext, l as BridgeCapabilities, lt as ToolResult, mt as UiBridge, qt as SkillManifest, rt as SchemaInferer, st as ToolDefinition, w as InteractionResponse } from "./index-DnI0BTEp.js";
1
+ import { It as FileStat, Jt as SkillInstallSource, Lt as FileSystemProvider, Q as RenderResultRequest, Rt as JsonSchema, T as InteractionResponse, Zt as SkillManifest, _ as FsMemoryStore, ct as ScriptExecutionContext, dt as ToolDefinition, g as FsArtifactStore, l as BridgeCapabilities, lt as ScriptExecutor, pt as ToolResult, rn as VerifyResult, st as SchemaInferer, tn as SkillsLockfile, vt as UiBridge, w as InteractionRequest } from "./index-CqDIreSE.js";
2
2
  import { Readable, Writable } from "node:stream";
3
3
  //#region ../node/dist/index.d.ts
4
4
  //#region src/fs/nodeFs.d.ts
@@ -1,6 +1,6 @@
1
1
  //#region ../core/dist/index.d.ts
2
2
  //#region src/errors.d.ts
3
- type WebSkillErrorCode = 'FS_NOT_FOUND' | 'FS_PATH_OUTSIDE_ROOT' | 'SKILL_NOT_FOUND' | 'SKILL_INVALID_METADATA' | 'SKILL_INVALID_NAME' | 'SKILL_DUPLICATE_NAME' | 'SKILL_UNSUPPORTED_SCRIPT' | 'VALIDATION_FAILED' | 'TOOL_NOT_FOUND' | 'TOOL_EXECUTION_FAILED' | 'TOOL_UNSUPPORTED' | 'TOOL_SCHEMA_UNAVAILABLE' | 'RUN_TIMEOUT' | 'RUN_MAX_TURNS_EXCEEDED' | 'RUN_FAILED' | 'RUN_CANCELLED' | 'RUN_INTERACTION_TIMEOUT' | 'UI_UNAVAILABLE' | 'LLM_UNAVAILABLE' | 'LLM_REQUEST_FAILED' | 'INSTALL_FAILED' | 'UNINSTALL_FAILED' | 'EXPORT_FAILED' | 'INTEGRITY_FAILED' | 'FS_PERMISSION_DENIED' | 'MCP_ENDPOINT_UNAVAILABLE' | 'MCP_TOOL_NOT_FOUND' | 'CANDIDATE_INVALID' | 'APPROVAL_REQUIRED' | 'SKILL_QUARANTINED' | 'SKILL_DISABLED' | 'GOVERNANCE_FAILED';
3
+ type WebSkillErrorCode = 'FS_NOT_FOUND' | 'FS_PATH_OUTSIDE_ROOT' | 'SKILL_NOT_FOUND' | 'SKILL_INVALID_METADATA' | 'SKILL_INVALID_NAME' | 'SKILL_DUPLICATE_NAME' | 'SKILL_UNSUPPORTED_SCRIPT' | 'VALIDATION_FAILED' | 'TOOL_NOT_FOUND' | 'TOOL_EXECUTION_FAILED' | 'TOOL_UNSUPPORTED' | 'TOOL_SCHEMA_UNAVAILABLE' | 'RUN_TIMEOUT' | 'RUN_MAX_TURNS_EXCEEDED' | 'RUN_FAILED' | 'RUN_CANCELLED' | 'RUN_INTERACTION_TIMEOUT' | 'UI_UNAVAILABLE' | 'LLM_UNAVAILABLE' | 'LLM_REQUEST_FAILED' | 'INSTALL_FAILED' | 'UNINSTALL_FAILED' | 'EXPORT_FAILED' | 'INTEGRITY_FAILED' | 'FS_PERMISSION_DENIED' | 'MCP_ENDPOINT_UNAVAILABLE' | 'MCP_TOOL_NOT_FOUND' | 'CANDIDATE_INVALID' | 'APPROVAL_REQUIRED' | 'SKILL_QUARANTINED' | 'SKILL_DISABLED' | 'GOVERNANCE_FAILED' | 'RUN_SNAPSHOT_NOT_FOUND' | 'RUN_SNAPSHOT_EXPIRED' | 'RUN_SNAPSHOT_INCOMPATIBLE';
4
4
  /** 所有公开 API 抛出的结构化错误,code 供上层可编程处理 */
5
5
  declare class WebSkillError extends Error {
6
6
  readonly code: WebSkillErrorCode;
@@ -657,7 +657,7 @@ type LifecycleHook = (ctx: LifecycleHookContext) => Promise<void | {
657
657
  }>;
658
658
  //#endregion
659
659
  //#region src/trace/types.d.ts
660
- type TraceEventType = 'skill.routed' | 'skill.activated' | 'llm.request' | 'llm.response' | 'tool.started' | 'tool.completed' | 'tool.failed' | 'artifact.created' | 'ui.requested' | 'ui.resumed' | 'ui.rendered' | 'run.warning' | 'run.completed' | 'run.cancelled' | 'run.failed';
660
+ type TraceEventType = 'skill.routed' | 'skill.activated' | 'llm.request' | 'llm.response' | 'tool.started' | 'tool.completed' | 'tool.failed' | 'artifact.created' | 'ui.requested' | 'ui.resumed' | 'ui.rendered' | 'run.warning' | 'run.completed' | 'run.cancelled' | 'run.failed' | 'run.resumed';
661
661
  interface TraceEvent {
662
662
  id: string;
663
663
  runId: string;
@@ -940,6 +940,56 @@ interface ExternalSkillProvider {
940
940
  */
941
941
  declare function mergeCatalogEntries(localEntries: SkillCatalogEntry[], providerEntries: SkillCatalogEntry[]): SkillCatalogEntry[];
942
942
  //#endregion
943
+ //#region src/engine/snapshot.d.ts
944
+ declare const RUN_SNAPSHOT_SCHEMA_VERSION = 1;
945
+ /** interrupted(等待用户)状态点的可恢复快照(D3 收窄版) */
946
+ interface RunSnapshot {
947
+ schemaVersion: 1;
948
+ runId: string;
949
+ sessionId: string;
950
+ userPrompt: string;
951
+ startedAt: string;
952
+ /** 完整消息历史(含 system/user/assistant/tool) */
953
+ messages: LlmMessage[];
954
+ /** 当前轮次(护栏续算) */
955
+ turn: number;
956
+ activeSkillNames: string[];
957
+ /** 已注册脚本工具定义(恢复后免重新激活) */
958
+ activatedTools: ToolDefinition[];
959
+ /** 等待中的交互(恢复时重新发起,表单重新渲染) */
960
+ pendingInteraction: InteractionRequest;
961
+ /** 进入 interrupted 时计算的过期时间 */
962
+ interactionExpiresAt: string;
963
+ config: {
964
+ maxTurns: number;
965
+ totalTimeoutMs: number;
966
+ toolTimeoutMs: number;
967
+ temperature?: number;
968
+ };
969
+ snapshotAt: string;
970
+ }
971
+ interface RunSnapshotStore {
972
+ save(snapshot: RunSnapshot): Promise<void>;
973
+ load(runId: string): Promise<RunSnapshot | undefined>;
974
+ delete(runId: string): Promise<void>;
975
+ list(): Promise<RunSnapshot[]>;
976
+ }
977
+ /**
978
+ * FileSystemProvider 后端的快照存储:<root>/<runId>.snapshot.json。
979
+ * 坏 JSON → RUN_SNAPSHOT_INCOMPATIBLE 并自动清理坏文件;runId 过路径安全校验。
980
+ */
981
+ declare class FsRunSnapshotStore implements RunSnapshotStore {
982
+ #private;
983
+ constructor(deps: {
984
+ root: string;
985
+ fs: FileSystemProvider;
986
+ });
987
+ save(snapshot: RunSnapshot): Promise<void>;
988
+ load(runId: string): Promise<RunSnapshot | undefined>;
989
+ delete(runId: string): Promise<void>;
990
+ list(): Promise<RunSnapshot[]>;
991
+ }
992
+ //#endregion
943
993
  //#region src/engine/agentLoop.d.ts
944
994
  interface AgentLoopDeps {
945
995
  llm: LlmClient;
@@ -971,6 +1021,8 @@ interface AgentLoopDeps {
971
1021
  skillProviders?: ExternalSkillProvider[];
972
1022
  /** Catalog 过滤钩子(治理状态拦截路由,如 quarantined/deprecated 过滤) */
973
1023
  catalogFilter?: (entries: SkillCatalogEntry[]) => SkillCatalogEntry[] | Promise<SkillCatalogEntry[]>;
1024
+ /** D3:interrupt 点快照存储(无配置则行为与现状完全一致) */
1025
+ snapshotStore?: RunSnapshotStore;
974
1026
  }
975
1027
  /**
976
1028
  * 多轮 Agent 循环。
@@ -986,6 +1038,11 @@ declare class AgentLoop {
986
1038
  route: RouteResult;
987
1039
  runId?: string;
988
1040
  }): Promise<RunResult>;
1041
+ /**
1042
+ * D3 恢复:以快照重建 LoopState,重新发起等待中的交互(表单重新渲染),
1043
+ * 应答后从快照轮次续跑主循环;totalTimeout 以快照 startedAt 续算。
1044
+ */
1045
+ resume(snapshot: RunSnapshot): Promise<RunResult>;
989
1046
  }
990
1047
  //#endregion
991
1048
  //#region src/engine/runtime.d.ts
@@ -1022,8 +1079,10 @@ interface WebSkillRuntimeDeps {
1022
1079
  /** opt-in:run 完成且未激活任何技能时回调(默认关闭,fire-and-forget) */
1023
1080
  onSkillMiss?: (input: {
1024
1081
  prompt: string;
1025
- run: RunResult['run'];
1082
+ run: RuntimeRun;
1026
1083
  }) => Promise<void>;
1084
+ /** D3:interrupt 点快照存储(配置后 interrupted run 可 resumeRun 恢复) */
1085
+ snapshotStore?: RunSnapshotStore;
1027
1086
  }
1028
1087
  /** runtime 门面:组合 discovery / router / agent loop / lifecycle */
1029
1088
  declare class WebSkillRuntime {
@@ -1034,6 +1093,14 @@ declare class WebSkillRuntime {
1034
1093
  get events(): EventBus;
1035
1094
  discover(): Promise<DiscoveryResult>;
1036
1095
  run(userPrompt: string): Promise<RunResult>;
1096
+ /** D3:列出可恢复的 interrupted run(供 UI 展示"未完成任务") */
1097
+ listInterruptedRuns(): Promise<RunSnapshot[]>;
1098
+ /**
1099
+ * D3 恢复 interrupted run:
1100
+ * 不存在 → RUN_SNAPSHOT_NOT_FOUND;schemaVersion 不匹配 → 删除 + RUN_SNAPSHOT_INCOMPATIBLE;
1101
+ * 已过期 → interaction-timeout 终态并删快照;否则重建 LoopState 重新发起交互续跑。
1102
+ */
1103
+ resumeRun(runId: string): Promise<RunResult>;
1037
1104
  }
1038
1105
  //#endregion
1039
- export { RunTerminationReason as $, VerifyResult as $t, LlmCompleteInput as A, CatalogRenderer as At, MockLlmQueueItem as B, SkillCatalog as Bt, InteractionRequest as C, mergeCatalogEntries as Ct, LifecycleHookContext as D, schemaToForm as Dt, LifecycleHook as E, resolveToolName as Et, LlmToolSpec as F, MemoryFS as Ft, ProgressiveRouter as G, SkillIssue as Gt, MockUiBridge as H, SkillDiscovery as Ht, MemoryArtifactStore as I, SKILLS_LOCKFILE as It, READ_SKILL_FILE_TOOL_NAME as J, SkillMetadata as Jt, READ_SKILL_FILE_INPUT_SCHEMA as K, SkillLocation as Kt, MemoryStore as L, SKILL_MANIFEST_FILE as Lt, LlmResponse as M, FileStat as Mt, LlmStreamEvent as N, FileSystemProvider as Nt, LifecycleListener as O, toLlmToolSpec as Ot, LlmToolCall as P, JsonSchema as Pt, RunResult as Q, ValidationReport as Qt, MockLlmClient as R, SKILL_NAME_MAX_LENGTH as Rt, InteractionPolicy as S, fromVercelStreamPart as St, LifecycleEvent as T, parseBridgeRequest as Tt, OpenAiCompatibleClient as U, SkillDocument as Ut, MockUiAnswer as V, SkillCatalogEntry as Vt, OpenAiCompatibleClientConfig as W, SkillInstallSource as Wt, RenderResultRequest as X, SkillSource as Xt, RenderBlock as Y, SkillReader as Yt, RouteResult as Z, SkillsLockfile as Zt, FsMemoryStore as _, WebSkillRuntimeDeps as _t, AgentLoopConfig as a, computeDigest as an, ScriptExecutor as at, HookRunnerOptions as b, createScriptContext as bt, ArtifactStore as c, jsonRenderer as cn, ToolResolution as ct, BridgeResponse as d, renderAvailableSkillsXml as dn, TraceEvent as dt, WebSkillError as en, RuntimePhase as et, EventBus as f, renderCatalogJson as fn, TraceEventType as ft, FsArtifactStore as g, xmlRenderer as gn, WebSkillRuntime as gt, FormField as h, verifyManifest as hn, VercelToolSpec as ht, AgentLoop as i, checkSkillRules as in, ScriptExecutionContext as it, LlmMessage as j, DiscoveryResult as jt, LlmClient as k, toVercelToolSpecs as kt, BridgeCapabilities as l, normalizePath as ln, ToolResult as lt, ExternalToolSource as m, validateSkills as mn, UiBridge as mt, ASK_USER_TOOL as n, buildCatalog as nn, RuntimeSession as nt, AgentLoopDeps as o, escapeXml as on, SkillRouter as ot, ExternalSkillProvider as p, resolveInsideRoot as pn, TraceRecorder as pt, READ_SKILL_FILE_TOOL as q, SkillManifest as qt, ASK_USER_TOOL_NAME as r, buildManifest as rn, SchemaInferer as rt, Artifact as s, isValidSkillName as sn, ToolDefinition as st, ASK_USER_INPUT_SCHEMA as t, WebSkillErrorCode as tn, RuntimeRun as tt, BridgeRequest as u, parseSkillMarkdown as un, TraceClock as ut, FullDisclosureRouter as v, bridgeError as vt, InteractionResponse as w, normalizeToolContent as wt, InMemoryStore as x, fromVercelResult as xt, HookRunner as y, buildRenderResult as yt, MockLlmHandler as z, SKILL_NAME_PATTERN as zt };
1106
+ export { RouteResult as $, SkillReader as $t, LlmClient as A, resolveToolName as At, MockLlmHandler as B, SKILLS_LOCKFILE as Bt, InteractionPolicy as C, buildRenderResult as Ct, LifecycleHook as D, mergeCatalogEntries as Dt, LifecycleEvent as E, fromVercelStreamPart as Et, LlmToolCall as F, DiscoveryResult as Ft, OpenAiCompatibleClientConfig as G, SkillCatalogEntry as Gt, MockUiAnswer as H, SKILL_NAME_MAX_LENGTH as Ht, LlmToolSpec as I, FileStat as It, READ_SKILL_FILE_TOOL as J, SkillInstallSource as Jt, ProgressiveRouter as K, SkillDiscovery as Kt, MemoryArtifactStore as L, FileSystemProvider as Lt, LlmMessage as M, toLlmToolSpec as Mt, LlmResponse as N, toVercelToolSpecs as Nt, LifecycleHookContext as O, normalizeToolContent as Ot, LlmStreamEvent as P, CatalogRenderer as Pt, RenderResultRequest as Q, SkillMetadata as Qt, MemoryStore as R, JsonSchema as Rt, InMemoryStore as S, bridgeError as St, InteractionResponse as T, fromVercelResult as Tt, MockUiBridge as U, SKILL_NAME_PATTERN as Ut, MockLlmQueueItem as V, SKILL_MANIFEST_FILE as Vt, OpenAiCompatibleClient as W, SkillCatalog as Wt, RUN_SNAPSHOT_SCHEMA_VERSION as X, SkillLocation as Xt, READ_SKILL_FILE_TOOL_NAME as Y, SkillIssue as Yt, RenderBlock as Z, SkillManifest as Zt, FsMemoryStore as _, resolveInsideRoot as _n, TraceRecorder as _t, AgentLoopConfig as a, WebSkillErrorCode as an, RuntimeRun as at, HookRunner as b, xmlRenderer as bn, WebSkillRuntime as bt, ArtifactStore as c, checkSkillRules as cn, ScriptExecutionContext as ct, BridgeResponse as d, isValidSkillName as dn, ToolDefinition as dt, SkillSource as en, RunResult as et, EventBus as f, jsonRenderer as fn, ToolResolution as ft, FsArtifactStore as g, renderCatalogJson as gn, TraceEventType as gt, FormField as h, renderAvailableSkillsXml as hn, TraceEvent as ht, AgentLoop as i, WebSkillError as in, RuntimePhase as it, LlmCompleteInput as j, schemaToForm as jt, LifecycleListener as k, parseBridgeRequest as kt, BridgeCapabilities as l, computeDigest as ln, ScriptExecutor as lt, ExternalToolSource as m, parseSkillMarkdown as mn, TraceClock as mt, ASK_USER_TOOL as n, ValidationReport as nn, RunSnapshotStore as nt, AgentLoopDeps as o, buildCatalog as on, RuntimeSession as ot, ExternalSkillProvider as p, normalizePath as pn, ToolResult as pt, READ_SKILL_FILE_INPUT_SCHEMA as q, SkillDocument as qt, ASK_USER_TOOL_NAME as r, VerifyResult as rn, RunTerminationReason as rt, Artifact as s, buildManifest as sn, SchemaInferer as st, ASK_USER_INPUT_SCHEMA as t, SkillsLockfile as tn, RunSnapshot as tt, BridgeRequest as u, escapeXml as un, SkillRouter as ut, FsRunSnapshotStore as v, validateSkills as vn, UiBridge as vt, InteractionRequest as w, createScriptContext as wt, HookRunnerOptions as x, WebSkillRuntimeDeps as xt, FullDisclosureRouter as y, verifyManifest as yn, VercelToolSpec as yt, MockLlmClient as z, MemoryFS as zt };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as RunTerminationReason, $t as VerifyResult, A as LlmCompleteInput, At as CatalogRenderer, B as MockLlmQueueItem, Bt as SkillCatalog, C as InteractionRequest, Ct as mergeCatalogEntries, D as LifecycleHookContext, Dt as schemaToForm, E as LifecycleHook, Et as resolveToolName, F as LlmToolSpec, Ft as MemoryFS, G as ProgressiveRouter, Gt as SkillIssue, H as MockUiBridge, Ht as SkillDiscovery, I as MemoryArtifactStore, It as SKILLS_LOCKFILE, J as READ_SKILL_FILE_TOOL_NAME, Jt as SkillMetadata, K as READ_SKILL_FILE_INPUT_SCHEMA, Kt as SkillLocation, L as MemoryStore, Lt as SKILL_MANIFEST_FILE, M as LlmResponse, Mt as FileStat, N as LlmStreamEvent, Nt as FileSystemProvider, O as LifecycleListener, Ot as toLlmToolSpec, P as LlmToolCall, Pt as JsonSchema, Q as RunResult, Qt as ValidationReport, R as MockLlmClient, Rt as SKILL_NAME_MAX_LENGTH, S as InteractionPolicy, St as fromVercelStreamPart, T as LifecycleEvent, Tt as parseBridgeRequest, U as OpenAiCompatibleClient, Ut as SkillDocument, V as MockUiAnswer, Vt as SkillCatalogEntry, W as OpenAiCompatibleClientConfig, Wt as SkillInstallSource, X as RenderResultRequest, Xt as SkillSource, Y as RenderBlock, Yt as SkillReader, Z as RouteResult, Zt as SkillsLockfile, _ as FsMemoryStore, _t as WebSkillRuntimeDeps, a as AgentLoopConfig, an as computeDigest, at as ScriptExecutor, b as HookRunnerOptions, bt as createScriptContext, c as ArtifactStore, cn as jsonRenderer, ct as ToolResolution, d as BridgeResponse, dn as renderAvailableSkillsXml, dt as TraceEvent, en as WebSkillError, et as RuntimePhase, f as EventBus, fn as renderCatalogJson, ft as TraceEventType, g as FsArtifactStore, gn as xmlRenderer, gt as WebSkillRuntime, h as FormField, hn as verifyManifest, ht as VercelToolSpec, i as AgentLoop, in as checkSkillRules, it as ScriptExecutionContext, j as LlmMessage, jt as DiscoveryResult, k as LlmClient, kt as toVercelToolSpecs, l as BridgeCapabilities, ln as normalizePath, lt as ToolResult, m as ExternalToolSource, mn as validateSkills, mt as UiBridge, n as ASK_USER_TOOL, nn as buildCatalog, nt as RuntimeSession, o as AgentLoopDeps, on as escapeXml, ot as SkillRouter, p as ExternalSkillProvider, pn as resolveInsideRoot, pt as TraceRecorder, q as READ_SKILL_FILE_TOOL, qt as SkillManifest, r as ASK_USER_TOOL_NAME, rn as buildManifest, rt as SchemaInferer, s as Artifact, sn as isValidSkillName, st as ToolDefinition, t as ASK_USER_INPUT_SCHEMA, tn as WebSkillErrorCode, tt as RuntimeRun, u as BridgeRequest, un as parseSkillMarkdown, ut as TraceClock, v as FullDisclosureRouter, vt as bridgeError, w as InteractionResponse, wt as normalizeToolContent, x as InMemoryStore, xt as fromVercelResult, y as HookRunner, yt as buildRenderResult, z as MockLlmHandler, zt as SKILL_NAME_PATTERN } from "./index-DnI0BTEp.js";
2
- export { ASK_USER_INPUT_SCHEMA, ASK_USER_TOOL, ASK_USER_TOOL_NAME, AgentLoop, type AgentLoopConfig, type AgentLoopDeps, type Artifact, type ArtifactStore, type BridgeCapabilities, type BridgeRequest, type BridgeResponse, type CatalogRenderer, type DiscoveryResult, EventBus, type ExternalSkillProvider, type ExternalToolSource, type FileStat, type FileSystemProvider, type FormField, FsArtifactStore, FsMemoryStore, FullDisclosureRouter, HookRunner, type HookRunnerOptions, InMemoryStore, 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, MemoryArtifactStore, MemoryFS, type MemoryStore, MockLlmClient, type MockLlmHandler, type MockLlmQueueItem, type MockUiAnswer, MockUiBridge, OpenAiCompatibleClient, type OpenAiCompatibleClientConfig, ProgressiveRouter, READ_SKILL_FILE_INPUT_SCHEMA, READ_SKILL_FILE_TOOL, READ_SKILL_FILE_TOOL_NAME, type RenderBlock, type RenderResultRequest, type RouteResult, type RunResult, type RunTerminationReason, type RuntimePhase, type RuntimeRun, type RuntimeSession, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SKILL_NAME_MAX_LENGTH, SKILL_NAME_PATTERN, type SchemaInferer, type ScriptExecutionContext, type ScriptExecutor, type SkillCatalog, type SkillCatalogEntry, SkillDiscovery, type SkillDocument, type SkillInstallSource, type SkillIssue, type SkillLocation, type SkillManifest, type SkillMetadata, SkillReader, type SkillRouter, type SkillSource, type SkillsLockfile, type ToolDefinition, type ToolResolution, type ToolResult, type TraceClock, type TraceEvent, type TraceEventType, TraceRecorder, type UiBridge, type ValidationReport, type VercelToolSpec, type VerifyResult, WebSkillError, type WebSkillErrorCode, WebSkillRuntime, type WebSkillRuntimeDeps, bridgeError, buildCatalog, buildManifest, buildRenderResult, checkSkillRules, computeDigest, createScriptContext, escapeXml, fromVercelResult, fromVercelStreamPart, isValidSkillName, jsonRenderer, mergeCatalogEntries, normalizePath, normalizeToolContent, parseBridgeRequest, parseSkillMarkdown, renderAvailableSkillsXml, renderCatalogJson, resolveInsideRoot, resolveToolName, schemaToForm, toLlmToolSpec, toVercelToolSpecs, validateSkills, verifyManifest, xmlRenderer };
1
+ import { $ as RouteResult, $t as SkillReader, A as LlmClient, At as resolveToolName, B as MockLlmHandler, Bt as SKILLS_LOCKFILE, C as InteractionPolicy, Ct as buildRenderResult, D as LifecycleHook, Dt as mergeCatalogEntries, E as LifecycleEvent, Et as fromVercelStreamPart, F as LlmToolCall, Ft as DiscoveryResult, G as OpenAiCompatibleClientConfig, Gt as SkillCatalogEntry, H as MockUiAnswer, Ht as SKILL_NAME_MAX_LENGTH, I as LlmToolSpec, It as FileStat, J as READ_SKILL_FILE_TOOL, Jt as SkillInstallSource, K as ProgressiveRouter, Kt as SkillDiscovery, L as MemoryArtifactStore, Lt as FileSystemProvider, M as LlmMessage, Mt as toLlmToolSpec, N as LlmResponse, Nt as toVercelToolSpecs, O as LifecycleHookContext, Ot as normalizeToolContent, P as LlmStreamEvent, Pt as CatalogRenderer, Q as RenderResultRequest, Qt as SkillMetadata, R as MemoryStore, Rt as JsonSchema, S as InMemoryStore, St as bridgeError, T as InteractionResponse, Tt as fromVercelResult, U as MockUiBridge, Ut as SKILL_NAME_PATTERN, V as MockLlmQueueItem, Vt as SKILL_MANIFEST_FILE, W as OpenAiCompatibleClient, Wt as SkillCatalog, X as RUN_SNAPSHOT_SCHEMA_VERSION, Xt as SkillLocation, Y as READ_SKILL_FILE_TOOL_NAME, Yt as SkillIssue, Z as RenderBlock, Zt as SkillManifest, _ as FsMemoryStore, _n as resolveInsideRoot, _t as TraceRecorder, a as AgentLoopConfig, an as WebSkillErrorCode, at as RuntimeRun, b as HookRunner, bn as xmlRenderer, bt as WebSkillRuntime, c as ArtifactStore, cn as checkSkillRules, ct as ScriptExecutionContext, d as BridgeResponse, dn as isValidSkillName, dt as ToolDefinition, en as SkillSource, et as RunResult, f as EventBus, fn as jsonRenderer, ft as ToolResolution, g as FsArtifactStore, gn as renderCatalogJson, gt as TraceEventType, h as FormField, hn as renderAvailableSkillsXml, ht as TraceEvent, i as AgentLoop, in as WebSkillError, it as RuntimePhase, j as LlmCompleteInput, jt as schemaToForm, k as LifecycleListener, kt as parseBridgeRequest, l as BridgeCapabilities, ln as computeDigest, lt as ScriptExecutor, m as ExternalToolSource, mn as parseSkillMarkdown, mt as TraceClock, n as ASK_USER_TOOL, nn as ValidationReport, nt as RunSnapshotStore, o as AgentLoopDeps, on as buildCatalog, ot as RuntimeSession, p as ExternalSkillProvider, pn as normalizePath, pt as ToolResult, q as READ_SKILL_FILE_INPUT_SCHEMA, qt as SkillDocument, r as ASK_USER_TOOL_NAME, rn as VerifyResult, rt as RunTerminationReason, s as Artifact, sn as buildManifest, st as SchemaInferer, t as ASK_USER_INPUT_SCHEMA, tn as SkillsLockfile, tt as RunSnapshot, u as BridgeRequest, un as escapeXml, ut as SkillRouter, v as FsRunSnapshotStore, vn as validateSkills, vt as UiBridge, w as InteractionRequest, wt as createScriptContext, x as HookRunnerOptions, xt as WebSkillRuntimeDeps, y as FullDisclosureRouter, yn as verifyManifest, yt as VercelToolSpec, z as MockLlmClient, zt as MemoryFS } from "./index-CqDIreSE.js";
2
+ export { ASK_USER_INPUT_SCHEMA, ASK_USER_TOOL, ASK_USER_TOOL_NAME, AgentLoop, type AgentLoopConfig, type AgentLoopDeps, type Artifact, type ArtifactStore, type BridgeCapabilities, type BridgeRequest, type BridgeResponse, type CatalogRenderer, type DiscoveryResult, EventBus, type ExternalSkillProvider, type ExternalToolSource, type FileStat, type FileSystemProvider, type FormField, FsArtifactStore, FsMemoryStore, FsRunSnapshotStore, FullDisclosureRouter, HookRunner, type HookRunnerOptions, InMemoryStore, 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, MemoryArtifactStore, MemoryFS, type MemoryStore, MockLlmClient, type MockLlmHandler, type MockLlmQueueItem, type MockUiAnswer, MockUiBridge, 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, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SKILL_NAME_MAX_LENGTH, SKILL_NAME_PATTERN, type SchemaInferer, type ScriptExecutionContext, type ScriptExecutor, type SkillCatalog, type SkillCatalogEntry, SkillDiscovery, type SkillDocument, type SkillInstallSource, type SkillIssue, type SkillLocation, type SkillManifest, type SkillMetadata, SkillReader, type SkillRouter, type SkillSource, type SkillsLockfile, type ToolDefinition, type ToolResolution, type ToolResult, type TraceClock, type TraceEvent, type TraceEventType, TraceRecorder, type UiBridge, type ValidationReport, type VercelToolSpec, type VerifyResult, WebSkillError, type WebSkillErrorCode, WebSkillRuntime, type WebSkillRuntimeDeps, bridgeError, buildCatalog, buildManifest, buildRenderResult, checkSkillRules, computeDigest, createScriptContext, escapeXml, fromVercelResult, fromVercelStreamPart, isValidSkillName, jsonRenderer, mergeCatalogEntries, normalizePath, normalizeToolContent, parseBridgeRequest, parseSkillMarkdown, renderAvailableSkillsXml, renderCatalogJson, resolveInsideRoot, resolveToolName, schemaToForm, toLlmToolSpec, toVercelToolSpecs, validateSkills, verifyManifest, xmlRenderer };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { $ as validateSkills, A as schemaToForm, B as WebSkillError, C as createScriptContext, D as normalizeToolContent, E as mergeCatalogEntries, F as SKILL_MANIFEST_FILE, G as escapeXml, H as buildManifest, I as SKILL_NAME_MAX_LENGTH, J as normalizePath, K as isValidSkillName, L as SKILL_NAME_PATTERN, M as toVercelToolSpecs, N as MemoryFS, O as parseBridgeRequest, P as SKILLS_LOCKFILE, Q as resolveInsideRoot, R as SkillDiscovery, S as buildRenderResult, T as fromVercelStreamPart, U as checkSkillRules, V as buildCatalog, W as computeDigest, X as renderAvailableSkillsXml, Y as parseSkillMarkdown, Z as renderCatalogJson, _ as READ_SKILL_FILE_TOOL, a as EventBus, b as WebSkillRuntime, c as FullDisclosureRouter, d as MemoryArtifactStore, et as verifyManifest, f as MockLlmClient, g as READ_SKILL_FILE_INPUT_SCHEMA, h as ProgressiveRouter, i as AgentLoop, j as toLlmToolSpec, k as resolveToolName, l as HookRunner, m as OpenAiCompatibleClient, n as ASK_USER_TOOL, o as FsArtifactStore, p as MockUiBridge, q as jsonRenderer, r as ASK_USER_TOOL_NAME, s as FsMemoryStore, t as ASK_USER_INPUT_SCHEMA, tt as xmlRenderer, u as InMemoryStore, v as READ_SKILL_FILE_TOOL_NAME, w as fromVercelResult, x as bridgeError, y as TraceRecorder, z as SkillReader } from "./dist-hMMxARXK.js";
1
+ import { $ as renderCatalogJson, A as parseBridgeRequest, B as SkillDiscovery, C as bridgeError, D as fromVercelStreamPart, E as fromVercelResult, F as MemoryFS, G as checkSkillRules, H as WebSkillError, I as SKILLS_LOCKFILE, J as isValidSkillName, K as computeDigest, L as SKILL_MANIFEST_FILE, M as schemaToForm, N as toLlmToolSpec, O as mergeCatalogEntries, P as toVercelToolSpecs, Q as renderAvailableSkillsXml, R as SKILL_NAME_MAX_LENGTH, S as WebSkillRuntime, T as createScriptContext, U as buildCatalog, V as SkillReader, W as buildManifest, X as normalizePath, Y as jsonRenderer, Z as parseSkillMarkdown, _ as READ_SKILL_FILE_INPUT_SCHEMA, a as EventBus, b as RUN_SNAPSHOT_SCHEMA_VERSION, c as FsRunSnapshotStore, d as InMemoryStore, et as resolveInsideRoot, f as MemoryArtifactStore, g as ProgressiveRouter, h as OpenAiCompatibleClient, i as AgentLoop, j as resolveToolName, k as normalizeToolContent, l as FullDisclosureRouter, m as MockUiBridge, n as ASK_USER_TOOL, nt as verifyManifest, o as FsArtifactStore, p as MockLlmClient, q as escapeXml, r as ASK_USER_TOOL_NAME, rt as xmlRenderer, s as FsMemoryStore, t as ASK_USER_INPUT_SCHEMA, tt as validateSkills, u as HookRunner, v as READ_SKILL_FILE_TOOL, w as buildRenderResult, x as TraceRecorder, y as READ_SKILL_FILE_TOOL_NAME, z as SKILL_NAME_PATTERN } from "./dist-COsE72Ct.js";
2
2
 
3
- export { ASK_USER_INPUT_SCHEMA, ASK_USER_TOOL, ASK_USER_TOOL_NAME, AgentLoop, EventBus, FsArtifactStore, FsMemoryStore, FullDisclosureRouter, HookRunner, InMemoryStore, MemoryArtifactStore, MemoryFS, MockLlmClient, MockUiBridge, OpenAiCompatibleClient, ProgressiveRouter, READ_SKILL_FILE_INPUT_SCHEMA, READ_SKILL_FILE_TOOL, READ_SKILL_FILE_TOOL_NAME, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SKILL_NAME_MAX_LENGTH, SKILL_NAME_PATTERN, SkillDiscovery, SkillReader, TraceRecorder, WebSkillError, WebSkillRuntime, bridgeError, buildCatalog, buildManifest, buildRenderResult, checkSkillRules, computeDigest, createScriptContext, escapeXml, fromVercelResult, fromVercelStreamPart, isValidSkillName, jsonRenderer, mergeCatalogEntries, normalizePath, normalizeToolContent, parseBridgeRequest, parseSkillMarkdown, renderAvailableSkillsXml, renderCatalogJson, resolveInsideRoot, resolveToolName, schemaToForm, toLlmToolSpec, toVercelToolSpecs, validateSkills, verifyManifest, xmlRenderer };
3
+ export { ASK_USER_INPUT_SCHEMA, ASK_USER_TOOL, ASK_USER_TOOL_NAME, AgentLoop, EventBus, FsArtifactStore, FsMemoryStore, FsRunSnapshotStore, FullDisclosureRouter, HookRunner, InMemoryStore, MemoryArtifactStore, MemoryFS, MockLlmClient, MockUiBridge, 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, SkillDiscovery, SkillReader, TraceRecorder, WebSkillError, WebSkillRuntime, bridgeError, buildCatalog, buildManifest, buildRenderResult, checkSkillRules, computeDigest, createScriptContext, escapeXml, fromVercelResult, fromVercelStreamPart, isValidSkillName, jsonRenderer, mergeCatalogEntries, normalizePath, normalizeToolContent, parseBridgeRequest, parseSkillMarkdown, renderAvailableSkillsXml, renderCatalogJson, resolveInsideRoot, resolveToolName, schemaToForm, toLlmToolSpec, toVercelToolSpecs, validateSkills, verifyManifest, xmlRenderer };
package/dist/mcp.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Ct as mergeCatalogEntries, F as LlmToolSpec, Pt as JsonSchema, Ut as SkillDocument, Vt as SkillCatalogEntry, lt as ToolResult, m as ExternalToolSource, p as ExternalSkillProvider } from "./index-DnI0BTEp.js";
1
+ import { Dt as mergeCatalogEntries, Gt as SkillCatalogEntry, I as LlmToolSpec, Rt as JsonSchema, m as ExternalToolSource, p as ExternalSkillProvider, pt as ToolResult, qt as SkillDocument } from "./index-CqDIreSE.js";
2
2
  import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
3
3
  import { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
package/dist/mcp.js CHANGED
@@ -1,4 +1,4 @@
1
- import { B as WebSkillError, D as normalizeToolContent, E as mergeCatalogEntries } from "./dist-hMMxARXK.js";
1
+ import { H as WebSkillError, O as mergeCatalogEntries, k as normalizeToolContent } from "./dist-COsE72Ct.js";
2
2
  import { fromJSONSchema } from "zod";
3
3
 
4
4
  //#region ../mcp/dist/index.js
package/dist/node.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { $t as VerifyResult, It as SKILLS_LOCKFILE, Lt as SKILL_MANIFEST_FILE, Wt as SkillInstallSource, Zt as SkillsLockfile, bt as createScriptContext, qt as SkillManifest } from "./index-DnI0BTEp.js";
2
- import { a as LlmEnvConfig, c as OxcSchemaInferer, d as SkillManager, f as loadLlmConfigFromEnv, i as LlmCapabilities, l as SandboxOptions, m as readArchiveManifest, n as FileArtifactStore, o as NodeFS, p as probeLlmCapabilities, r as FileMemoryStore, s as NodeScriptExecutor, t as CliUiBridge, u as SandboxedScriptExecutor } from "./index-D65Jk0ju.js";
1
+ import { Bt as SKILLS_LOCKFILE, Jt as SkillInstallSource, Vt as SKILL_MANIFEST_FILE, Zt as SkillManifest, rn as VerifyResult, tn as SkillsLockfile, wt as createScriptContext } from "./index-CqDIreSE.js";
2
+ import { a as LlmEnvConfig, c as OxcSchemaInferer, d as SkillManager, f as loadLlmConfigFromEnv, i as LlmCapabilities, l as SandboxOptions, m as readArchiveManifest, n as FileArtifactStore, o as NodeFS, p as probeLlmCapabilities, r as FileMemoryStore, s as NodeScriptExecutor, t as CliUiBridge, u as SandboxedScriptExecutor } from "./index-BsbfEiaC.js";
3
3
  export { CliUiBridge, FileArtifactStore, FileMemoryStore, type LlmCapabilities, type LlmEnvConfig, NodeFS, NodeScriptExecutor, OxcSchemaInferer, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, type SandboxOptions, SandboxedScriptExecutor, SkillManager, type SkillManifest, type SkillInstallSource as SkillSource, type SkillsLockfile, type VerifyResult, createScriptContext, loadLlmConfigFromEnv, probeLlmCapabilities, readArchiveManifest };
package/dist/node.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as createScriptContext, F as SKILL_MANIFEST_FILE, P as SKILLS_LOCKFILE } from "./dist-hMMxARXK.js";
2
- import { a as NodeScriptExecutor, c as SkillManager, d as readArchiveManifest, i as NodeFS, l as loadLlmConfigFromEnv, n as FileArtifactStore, o as OxcSchemaInferer, r as FileMemoryStore, s as SandboxedScriptExecutor, t as CliUiBridge, u as probeLlmCapabilities } from "./dist-C1p26Ap9.js";
1
+ import { I as SKILLS_LOCKFILE, L as SKILL_MANIFEST_FILE, T as createScriptContext } from "./dist-COsE72Ct.js";
2
+ import { a as NodeScriptExecutor, c as SkillManager, d as readArchiveManifest, i as NodeFS, l as loadLlmConfigFromEnv, n as FileArtifactStore, o as OxcSchemaInferer, r as FileMemoryStore, s as SandboxedScriptExecutor, t as CliUiBridge, u as probeLlmCapabilities } from "./dist-Bvhbxrrt.js";
3
3
 
4
4
  export { CliUiBridge, FileArtifactStore, FileMemoryStore, NodeFS, NodeScriptExecutor, OxcSchemaInferer, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SandboxedScriptExecutor, SkillManager, createScriptContext, loadLlmConfigFromEnv, probeLlmCapabilities, readArchiveManifest };
@@ -1,4 +1,4 @@
1
- import { C as InteractionRequest, X as RenderResultRequest, mt as UiBridge, w as InteractionResponse } from "./index-DnI0BTEp.js";
1
+ import { Q as RenderResultRequest, T as InteractionResponse, vt as UiBridge, w as InteractionRequest } from "./index-CqDIreSE.js";
2
2
  //#region ../ui-react/dist/index.d.ts
3
3
  //#region src/bridgeState.d.ts
4
4
  /**
package/dist/ui-vue.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as InteractionRequest, X as RenderResultRequest, mt as UiBridge, w as InteractionResponse } from "./index-DnI0BTEp.js";
1
+ import { Q as RenderResultRequest, T as InteractionResponse, vt as UiBridge, w as InteractionRequest } from "./index-CqDIreSE.js";
2
2
  import { PropType } from "vue";
3
3
  //#region ../ui-vue/dist/index.d.ts
4
4
  //#region src/bridgeState.d.ts
package/dist/ui.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as InteractionRequest, X as RenderResultRequest, Y as RenderBlock, mt as UiBridge, w as InteractionResponse, yt as buildRenderResult } from "./index-DnI0BTEp.js";
1
+ import { Ct as buildRenderResult, Q as RenderResultRequest, T as InteractionResponse, Z as RenderBlock, vt as UiBridge, w as InteractionRequest } from "./index-CqDIreSE.js";
2
2
  //#region ../ui/dist/index.d.ts
3
3
  //#region src/model/formModel.d.ts
4
4
  interface FormModel {
package/dist/ui.js CHANGED
@@ -1,4 +1,4 @@
1
- import { S as buildRenderResult } from "./dist-hMMxARXK.js";
1
+ import { w as buildRenderResult } from "./dist-COsE72Ct.js";
2
2
  import { C as toOpenUiLang, S as toA2uiMessages, _ as interactionToFormModel, a as LitRendererBridge, b as renderRenderResult, c as VERCEL_INTERACTION_TOOL_NAME, d as WebFormBridge, f as collectValues, g as fromVercelToolResult, h as fromOpenUiAction, i as A2UI_VERSION, l as VercelUiBridge, m as fromA2uiAction, n as A2UI_CANCEL_ACTION, o as OPENUI_CANCEL_ACTION, p as ensureStyles, r as A2UI_SUBMIT_ACTION, s as OPENUI_SUBMIT_ACTION, t as A2UI_BASIC_CATALOG_ID, u as WEBSKILL_STYLES_CSS, v as renderBlocks, w as toVercelToolInvocation, x as shapeInteractionValue, y as renderMiniMarkdown } from "./dist-RcqvzAGF.js";
3
3
 
4
4
  export { A2UI_BASIC_CATALOG_ID, A2UI_CANCEL_ACTION, A2UI_SUBMIT_ACTION, A2UI_VERSION, LitRendererBridge, OPENUI_CANCEL_ACTION, OPENUI_SUBMIT_ACTION, VERCEL_INTERACTION_TOOL_NAME, VercelUiBridge, WEBSKILL_STYLES_CSS, WebFormBridge, buildRenderResult, collectValues, ensureStyles, fromA2uiAction, fromOpenUiAction, fromVercelToolResult, interactionToFormModel, renderBlocks, renderMiniMarkdown, renderRenderResult, shapeInteractionValue, toA2uiMessages, toOpenUiLang, toVercelToolInvocation };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webskill/sdk",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "WebSkill — browser/Node agent skill runtime (skills, tools, MCP, governance, UI)",
5
5
  "license": "MIT",
6
6
  "type": "module",