@webskill/sdk 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/agent.d.ts +2 -2
  2. package/dist/agent.js +57 -15
  3. package/dist/browser.d.ts +101 -5
  4. package/dist/browser.js +421 -11
  5. package/dist/{catalogComponents-DV7cPpUm-C77AEEx9.js → catalogComponents-Dr5dFMAb-Dacibl1e.js} +126 -44
  6. package/dist/{dist-bewtXYlO.js → dist-DnYG2-eY.js} +53 -14
  7. package/dist/{dist-6C03DShK.js → dist-DusANsrn.js} +981 -185
  8. package/dist/{env--jJB-TSX-04klhTYi.js → env-8cY40DXB-CGnEVZby.js} +7 -6
  9. package/dist/{env-BPUBZCwJ-4jat_SVG.d.ts → env-AK3cSMEA-Dli6QU5E.d.ts} +4 -3
  10. package/dist/governance.d.ts +3 -3
  11. package/dist/governance.js +1 -1
  12. package/dist/{index-Bsqg4ftU.d.ts → index-BMocOEi0.d.ts} +13 -7
  13. package/dist/{index-D_7ZZjkl.d.ts → index-BuTpBMzr.d.ts} +69 -6
  14. package/dist/{index-vBz_FC9w.d.ts → index-C-KFAZoF.d.ts} +298 -52
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.js +3 -3
  17. package/dist/mcp.d.ts +39 -8
  18. package/dist/mcp.js +53 -19
  19. package/dist/{memoryArtifactStore-BtOeB_hm-tj3fC5ip.js → memoryArtifactStore-52Zn9npI-BMPYwvoy.js} +10 -2
  20. package/dist/node.d.ts +4 -4
  21. package/dist/node.js +9 -2
  22. package/dist/{openUiLibrary-W3Ce896k-ClFTRZFs.js → openUiLibrary-Bdrji9qK-DzAxRlTY.js} +3 -3
  23. package/dist/{skillVersionStore-BzLbzFOL-CxwIewHJ.d.ts → skillVersionStore-BzLbzFOL-CxdAFWO2.d.ts} +1 -1
  24. package/dist/{testing-DDCJWvgA.js → testing-CYTFqkDm.js} +1 -1
  25. package/dist/testing.d.ts +2 -2
  26. package/dist/testing.js +3 -3
  27. package/dist/{types-D_hoCri8-BnNPiZCi.d.ts → types-4pg-qp_I-Gq63X8Oa.d.ts} +33 -8
  28. package/dist/ui-react.d.ts +2 -2
  29. package/dist/ui-react.js +66 -23
  30. package/dist/ui-vue.d.ts +1 -1
  31. package/dist/ui-vue.js +13 -8
  32. package/dist/ui.d.ts +3 -3
  33. package/dist/ui.js +2 -2
  34. package/dist/{webskillLitCatalog-_mugzRHx-DiuJpCuf.js → webskillLitCatalog-_mugzRHx-B_54vxum.js} +1 -1
  35. package/package.json +1 -1
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as JsonSchema, Q as SkillCatalogEntry, et as SkillDocument, g as LlmToolSpec } from "./types-D_hoCri8-BnNPiZCi.js";
2
- import { Nt as ToolResult, b as ExternalSkillProvider, rn as mergeCatalogEntries, x as ExternalToolSource } from "./index-vBz_FC9w.js";
1
+ import { I as JsonSchema, Q as SkillCatalogEntry, et as SkillDocument, g as LlmToolSpec } from "./types-4pg-qp_I-Gq63X8Oa.js";
2
+ import { D as ExternalSkillProvider, O as ExternalToolSource, Tn as mergeCatalogEntries, Ut as ToolResult } from "./index-C-KFAZoF.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";
@@ -192,15 +192,46 @@ declare function serveSkillAsMcp(server: McpServer, skill: ServedSkill): Promise
192
192
  declare const catalogMerge: typeof mergeCatalogEntries;
193
193
  //#endregion
194
194
  //#region src/webmcp/experimentalWebMcpAdapter.d.ts
195
- /** navigator.modelContext 鸭子类型(对齐浏览器 WebMCP API 草案) */
195
+ /**
196
+ * WebMCP 命令式 API 的工具形状(Chrome 150+)。
197
+ * `getTools()` 返回的工具含 `inputSchema`(JSON 字符串)、`origin`、`window`、`annotations`。
198
+ * 参考 https://developer.chrome.com/docs/ai/webmcp/imperative-api
199
+ */
200
+ interface WebMcpToolLike {
201
+ name: string;
202
+ description?: string;
203
+ /** getTools() 返回的 inputSchema 是 JSON 字符串(非对象) */
204
+ inputSchema?: string;
205
+ origin?: string;
206
+ window?: unknown;
207
+ annotations?: {
208
+ readOnlyHint?: boolean;
209
+ untrustedContentHint?: boolean;
210
+ };
211
+ }
212
+ /**
213
+ * document.modelContext 鸭子类型(对齐 Chrome 150+ 的 WebMCP 命令式 API)。
214
+ * - 旧版(Chrome <150):navigator.modelContext.listTools() / executeTool(name, argsJson)
215
+ * - 新版(Chrome 150+):document.modelContext.getTools() / executeTool(tool, argsJson, { signal? })
216
+ * executeTool 的第一参在两种版本都能接受:新版传 tool 对象,旧版传 name 字符串。
217
+ */
196
218
  interface BrowserModelContextLike {
197
- listTools?: () => Promise<unknown>;
198
- executeTool?: (name: string, argsJson: string) => Promise<unknown>;
219
+ getTools?: () => Promise<unknown>;
220
+ executeTool?: (tool: WebMcpToolLike | string, argsJson: string, options?: {
221
+ signal?: AbortSignal;
222
+ }) => Promise<unknown>;
199
223
  }
200
224
  interface WebMcpToolDescriptor {
201
225
  name: string;
202
226
  description?: string;
203
227
  inputSchema?: unknown;
228
+ origin?: string;
229
+ annotations?: {
230
+ readOnlyHint?: boolean;
231
+ untrustedContentHint?: boolean;
232
+ };
233
+ /** getTools() 返回的原始 tool 对象:executeTool 第一参须透传原对象(含 inputSchema JSON 字符串、window 等) */
234
+ raw?: unknown;
204
235
  }
205
236
  /**
206
237
  * Experimental WebMCP Adapter(mcp# 分支):默认关闭显式启用;
@@ -214,9 +245,9 @@ declare class ExperimentalWebMcpAdapter {
214
245
  enabled?: boolean;
215
246
  });
216
247
  isAvailable(): boolean;
217
- /** 工具清单(listTools 缺失时返回 undefined;调用失败时告警后返回 undefined) */
248
+ /** 工具清单(getTools 缺失时返回 undefined;调用失败时告警后返回 undefined) */
218
249
  listTools(): Promise<WebMcpToolDescriptor[] | undefined>;
219
- /** 工具名清单(listTools 缺失/失败时返回 undefined) */
250
+ /** 工具名清单(getTools 缺失/失败时返回 undefined) */
220
251
  listToolNames(): Promise<string[] | undefined>;
221
252
  call(toolName: string, args: Record<string, unknown>): Promise<ToolResult>;
222
253
  }
@@ -269,4 +300,4 @@ declare function connectRemoteEndpoint(registry: EndpointRegistry<McpClientLike>
269
300
  close(): Promise<void>;
270
301
  }>;
271
302
  //#endregion
272
- export { type BrowserModelContextLike, EndpointRegistry, ExperimentalWebMcpAdapter, type McpClientLike, McpRuntimePlugin, McpToolResolver, MessageChannelTransport, type MessageChannelTransportOptions, type MessagePortLike, type RemoteEndpointConfig, type ServedSkill, TemporarySkillProvider, type TransportState, type WebMcpToolDescriptor, catalogMerge, connectRemoteEndpoint, endpointToolLlmName, parseEndpointToolLlmName, parseWebMcpToolLlmName, serveSkillAsMcp, validateJsonRpcMessage, webMcpToolLlmName };
303
+ export { type BrowserModelContextLike, EndpointRegistry, ExperimentalWebMcpAdapter, type McpClientLike, McpRuntimePlugin, McpToolResolver, MessageChannelTransport, type MessageChannelTransportOptions, type MessagePortLike, type RemoteEndpointConfig, type ServedSkill, TemporarySkillProvider, type TransportState, type WebMcpToolDescriptor, type WebMcpToolLike, catalogMerge, connectRemoteEndpoint, endpointToolLlmName, parseEndpointToolLlmName, parseWebMcpToolLlmName, serveSkillAsMcp, validateJsonRpcMessage, webMcpToolLlmName };
package/dist/mcp.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { O as messageOf, h as assertRemoteUrlAllowed, m as WebSkillError } from "./dist-8oQRa8Xz.js";
2
- import { U as mergeCatalogEntries, q as normalizeToolContent } from "./dist-6C03DShK.js";
2
+ import { at as normalizeToolContent, et as mergeCatalogEntries } from "./dist-DusANsrn.js";
3
3
 
4
4
  //#region ../mcp/dist/index.js
5
5
  /**
@@ -392,15 +392,39 @@ const failure = (code, message) => ({
392
392
  message
393
393
  }
394
394
  });
395
- /** listTools 返回值提取工具描述(容忍数组或 {tools:[]} 两种形状) */
395
+ /** getTools() 返回的工具 描述符:inputSchema JSON 字符串时解析为对象,并保留原始对象 */
396
+ function toDescriptor(raw) {
397
+ if (typeof raw !== "object" || raw === null) return void 0;
398
+ const t = raw;
399
+ const name = String(t["name"] ?? "");
400
+ if (name === "") return void 0;
401
+ const descriptor = {
402
+ name,
403
+ raw
404
+ };
405
+ if (typeof t["description"] === "string") descriptor.description = t["description"];
406
+ if (typeof t["origin"] === "string") descriptor.origin = t["origin"];
407
+ if (typeof t["annotations"] === "object" && t["annotations"] !== null) {
408
+ const annotations = t["annotations"];
409
+ descriptor.annotations = {
410
+ ...typeof annotations["readOnlyHint"] === "boolean" ? { readOnlyHint: annotations["readOnlyHint"] } : {},
411
+ ...typeof annotations["untrustedContentHint"] === "boolean" ? { untrustedContentHint: annotations["untrustedContentHint"] } : {}
412
+ };
413
+ }
414
+ const schema = t["inputSchema"];
415
+ if (typeof schema === "string" && schema.trim() !== "") try {
416
+ descriptor.inputSchema = JSON.parse(schema);
417
+ } catch {
418
+ descriptor.inputSchema = schema;
419
+ }
420
+ else if (typeof schema === "object" && schema !== null) descriptor.inputSchema = schema;
421
+ return descriptor;
422
+ }
423
+ /** 从 getTools 返回值提取工具描述(容忍数组或 {tools:[]} 两种形状) */
396
424
  function extractToolDescriptors(raw) {
397
425
  const list = Array.isArray(raw) ? raw : typeof raw === "object" && raw !== null && Array.isArray(raw.tools) ? raw.tools : void 0;
398
426
  if (!list) return void 0;
399
- return list.filter((t) => typeof t === "object" && t !== null).map((t) => ({
400
- name: String(t["name"] ?? ""),
401
- ...typeof t["description"] === "string" ? { description: t["description"] } : {},
402
- ...typeof t["inputSchema"] === "object" && t["inputSchema"] !== null ? { inputSchema: t["inputSchema"] } : {}
403
- })).filter((t) => t.name !== "");
427
+ return list.map(toDescriptor).filter((d) => d !== void 0);
404
428
  }
405
429
  /**
406
430
  * Experimental WebMCP Adapter(mcp# 分支):默认关闭显式启用;
@@ -416,35 +440,45 @@ var ExperimentalWebMcpAdapter = class {
416
440
  this.#enabled = options?.enabled ?? false;
417
441
  }
418
442
  isAvailable() {
419
- return this.#enabled && typeof this.#resolveApi()?.executeTool === "function";
443
+ const api = this.#resolveApi();
444
+ return this.#enabled && typeof api?.executeTool === "function";
420
445
  }
421
- /** 工具清单(listTools 缺失时返回 undefined;调用失败时告警后返回 undefined) */
446
+ /** 工具清单(getTools 缺失时返回 undefined;调用失败时告警后返回 undefined) */
422
447
  async listTools() {
423
448
  const api = this.#resolveApi();
424
- if (typeof api?.listTools !== "function") return void 0;
449
+ if (typeof api?.getTools !== "function") return void 0;
425
450
  try {
426
- return extractToolDescriptors(await api.listTools());
451
+ return extractToolDescriptors(await api.getTools());
427
452
  } catch (e) {
428
- console.warn(`[webskill] navigator.modelContext.listTools() failed: ${e instanceof Error ? e.message : String(e)}`);
453
+ console.warn(`[webskill] document.modelContext.getTools() failed: ${e instanceof Error ? e.message : String(e)}`);
429
454
  return;
430
455
  }
431
456
  }
432
- /** 工具名清单(listTools 缺失/失败时返回 undefined) */
457
+ /** 工具名清单(getTools 缺失/失败时返回 undefined) */
433
458
  async listToolNames() {
434
459
  return (await this.listTools())?.map((t) => t.name);
435
460
  }
436
461
  async call(toolName, args) {
437
462
  if (!this.#enabled) return failure("TOOL_UNSUPPORTED", "WebMCP adapter is disabled (enable it explicitly to use mcp# tools)");
438
463
  const api = this.#resolveApi();
439
- if (typeof api?.executeTool !== "function") return failure("TOOL_UNSUPPORTED", "navigator.modelContext is not available");
440
- if (typeof api.listTools === "function") try {
441
- const names = extractToolDescriptors(await api.listTools())?.map((t) => t.name);
442
- if (names && !names.includes(toolName)) return failure("MCP_TOOL_NOT_FOUND", `WebMCP tool "${toolName}" not found`);
443
- } catch {}
464
+ if (typeof api?.executeTool !== "function") return failure("TOOL_UNSUPPORTED", "document.modelContext is not available");
465
+ const argsJson = JSON.stringify(args);
466
+ if (typeof api.getTools === "function") try {
467
+ const descriptors = extractToolDescriptors(await api.getTools());
468
+ const match = descriptors?.find((t) => t.name === toolName);
469
+ if (descriptors !== void 0 && match === void 0) return failure("MCP_TOOL_NOT_FOUND", `WebMCP tool "${toolName}" not found`);
470
+ const tool = match?.raw ?? { name: toolName };
471
+ return {
472
+ ok: true,
473
+ content: normalizeToolContent(await api.executeTool(tool, argsJson))
474
+ };
475
+ } catch (e) {
476
+ return failure("TOOL_EXECUTION_FAILED", `WebMCP tool "${toolName}" failed: ${messageOf(e)}`);
477
+ }
444
478
  try {
445
479
  return {
446
480
  ok: true,
447
- content: normalizeToolContent(await api.executeTool(toolName, JSON.stringify(args)))
481
+ content: normalizeToolContent(await api.executeTool(toolName, argsJson))
448
482
  };
449
483
  } catch (e) {
450
484
  return failure("TOOL_EXECUTION_FAILED", `WebMCP tool "${toolName}" failed: ${messageOf(e)}`);
@@ -1,6 +1,6 @@
1
1
  import { m as WebSkillError } from "./dist-8oQRa8Xz.js";
2
2
 
3
- //#region ../runtime/dist/memoryArtifactStore-BtOeB_hm.js
3
+ //#region ../runtime/dist/memoryArtifactStore-52Zn9npI.js
4
4
  /** 纯文本消息内容的构造快捷方式(引擎内部绝大多数消息仍是纯文本) */
5
5
  const textParts = (text) => [{
6
6
  type: "text",
@@ -8,6 +8,14 @@ const textParts = (text) => [{
8
8
  }];
9
9
  /** 取出 parts 中的文本(非文本分片在纯文本语境下无法表达,此处按丢弃处理——调用方须先校验) */
10
10
  const partsToText = (parts) => (parts ?? []).reduce((acc, part) => part.type === "text" ? acc + part.text : acc, "");
11
+ /**
12
+ * run 的提示词文本投影:`RuntimeRun.userPrompt` 与快照都是字符串字段,
13
+ * 而多模态提示词里的图片/文件分片没有文本形态,用占位符标注,避免记录成空串。
14
+ */
15
+ const promptText = (prompt) => {
16
+ if (typeof prompt === "string") return prompt;
17
+ return prompt.map((part) => part.type === "text" ? part.text : `[${part.type}: ${part.mimeType}]`).join("\n");
18
+ };
11
19
  const isContentPart = (value) => {
12
20
  if (typeof value !== "object" || value === null) return false;
13
21
  const part = value;
@@ -75,4 +83,4 @@ var MemoryArtifactStore = class {
75
83
  };
76
84
 
77
85
  //#endregion
78
- export { validateLlmMessages as a, textParts as i, partsToText as n, rejectUnsupportedPart as r, MemoryArtifactStore as t };
86
+ export { textParts as a, rejectUnsupportedPart as i, partsToText as n, validateLlmMessages as o, promptText as r, MemoryArtifactStore as t };
package/dist/node.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { I as JsonSchema, N as FileStat, O as ArchiveLimits, P as FileSystemProvider, U as SKILLS_LOCKFILE, W as SKILL_MANIFEST_FILE, Y as SignatureAuditSink, _t as VerifyResult, at as SkillManifest, b as UiBridge, c as InteractionResponse, dt as SkillsLockfile, ht as UnsignedPolicy, it as SkillManagerPort, pt as TrustedKeyStore, s as InteractionRequest, tt as SkillInstallSource, y as RenderResultRequest } from "./types-D_hoCri8-BnNPiZCi.js";
2
- import { D as FsMemoryStore, E as FsArtifactStore, Ht as WebSkillRuntimeDeps, Nt as ToolResult, Vt as WebSkillRuntime, W as NetworkPolicy, _t as SchemaInferer, d as ApprovalScope, f as BridgeCapabilities, jt as ToolDefinition, qt as createScriptContext, vt as ScriptExecutionContext, yt as ScriptExecutor } from "./index-vBz_FC9w.js";
3
- import { a as AuditLog, p as CandidateStore, r as ApprovalPolicy, u as CandidateSkill, v as SkillVersionStore } from "./skillVersionStore-BzLbzFOL-CxwIewHJ.js";
4
- import { n as LlmEnvConfig, s as probeLlmCapabilities, t as LlmCapabilities } from "./env-BPUBZCwJ-4jat_SVG.js";
1
+ import { I as JsonSchema, N as FileStat, O as ArchiveLimits, P as FileSystemProvider, U as SKILLS_LOCKFILE, W as SKILL_MANIFEST_FILE, Y as SignatureAuditSink, _t as VerifyResult, at as SkillManifest, b as UiBridge, c as InteractionResponse, dt as SkillsLockfile, ht as UnsignedPolicy, it as SkillManagerPort, pt as TrustedKeyStore, s as InteractionRequest, tt as SkillInstallSource, y as RenderResultRequest } from "./types-4pg-qp_I-Gq63X8Oa.js";
2
+ import { A as FsArtifactStore, Ct as ScriptExecutionContext, J as NetworkPolicy, St as SchemaInferer, Ut as ToolResult, Vt as ToolDefinition, _ as BridgeCapabilities, f as ApprovalScope, fn as createScriptContext, j as FsMemoryStore, on as WebSkillRuntime, sn as WebSkillRuntimeDeps, wt as ScriptExecutor } from "./index-C-KFAZoF.js";
3
+ import { a as AuditLog, p as CandidateStore, r as ApprovalPolicy, u as CandidateSkill, v as SkillVersionStore } from "./skillVersionStore-BzLbzFOL-CxdAFWO2.js";
4
+ import { n as LlmEnvConfig, s as probeLlmCapabilities, t as LlmCapabilities } from "./env-AK3cSMEA-Dli6QU5E.js";
5
5
  import { Readable, Writable } from "node:stream";
6
6
  //#region ../node/dist/index.d.ts
7
7
  //#region src/fs/nodeFs.d.ts
package/dist/node.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { A as parseSkillMarkdown, B as unzipWithLimits, H as verifyManifest, I as resolveArchiveLimits, L as resolveInsideRoot, M as readResponseWithLimit, N as readSkillSignature, O as messageOf, T as isValidSkillName, U as verifySkillSignature, V as validateSkills, _ as atomicWriteText, g as assertSafePathSegment, h as assertRemoteUrlAllowed, j as parseSkillPackManifest, m as WebSkillError, o as SKILLS_LOCKFILE, r as MANIFEST_EXCLUDED_FILES, s as SKILL_MANIFEST_FILE, u as SKILL_PACK_FILE, w as exportSkills, y as buildManifest } from "./dist-8oQRa8Xz.js";
2
- import { J as normalizeToolError, N as createScriptContext, O as WebSkillRuntime, W as networkPolicyLibSource, Y as parseBridgeRequest, d as FsMemoryStore, k as bridgeError, o as CapabilityApproval, q as normalizeToolContent, u as FsArtifactStore } from "./dist-6C03DShK.js";
3
- import { i as probeLlmCapabilities } from "./env--jJB-TSX-04klhTYi.js";
2
+ import { I as WebSkillRuntime, V as createScriptContext, at as normalizeToolContent, c as CapabilityApproval, m as FsMemoryStore, nt as networkPolicyLibSource, ot as normalizeToolError, p as FsArtifactStore, st as parseBridgeRequest, z as bridgeError } from "./dist-DusANsrn.js";
3
+ import { i as probeLlmCapabilities } from "./env-8cY40DXB-CGnEVZby.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { unzipSync, zipSync } from "fflate";
6
6
  import { existsSync, promises, realpathSync } from "node:fs";
@@ -1148,6 +1148,13 @@ var CliUiBridge = class {
1148
1148
  value: answer === "y" || answer === "yes"
1149
1149
  };
1150
1150
  }
1151
+ case "file-pick": {
1152
+ const answer = (await this.#question(`${input.message}\nLocal file path (empty to decline): `)).trim();
1153
+ return answer === "" ? { id: input.id } : {
1154
+ id: input.id,
1155
+ value: { path: answer }
1156
+ };
1157
+ }
1151
1158
  }
1152
1159
  }
1153
1160
  async progress(input) {
@@ -1,5 +1,5 @@
1
- import { nt as uiCatalog } from "./dist-bewtXYlO.js";
2
- import { t as CatalogNode } from "./catalogComponents-DV7cPpUm-C77AEEx9.js";
1
+ import { nt as uiCatalog } from "./dist-DnYG2-eY.js";
2
+ import { t as CatalogNode } from "./catalogComponents-Dr5dFMAb-Dacibl1e.js";
3
3
  import { z } from "zod";
4
4
  import { Component, Fragment, createContext, useCallback, useContext, useEffect, useInsertionEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -3761,7 +3761,7 @@ function Renderer({ response, library, isStreaming = false, onAction, onStateUpd
3761
3761
  const FormValidationContext = createContext(null);
3762
3762
 
3763
3763
  //#endregion
3764
- //#region ../ui-react/dist/openUiLibrary-W3Ce896k.js
3764
+ //#region ../ui-react/dist/openUiLibrary-Bdrji9qK.js
3765
3765
  const propsFor = (props, container) => container ? props.extend({ children: z.array(z.any()).optional() }) : props;
3766
3766
  /**
3767
3767
  * catalog 的 OpenUI 投影:`defineComponent` 复用同一份 zod schema 与描述,
@@ -1,4 +1,4 @@
1
- import { B as PageQuery, P as FileSystemProvider, Q as SkillCatalogEntry, at as SkillManifest, z as Page } from "./types-D_hoCri8-BnNPiZCi.js";
1
+ import { B as PageQuery, P as FileSystemProvider, Q as SkillCatalogEntry, at as SkillManifest, z as Page } from "./types-4pg-qp_I-Gq63X8Oa.js";
2
2
  //#region ../governance/dist/skillVersionStore-BzLbzFOL.d.ts
3
3
  //#region src/types.d.ts
4
4
  type CandidateStatus = 'draft' | 'pending-review' | 'approved' | 'published' | 'rejected';
@@ -1,5 +1,5 @@
1
1
  import { m as WebSkillError } from "./dist-8oQRa8Xz.js";
2
- import { i as textParts, n as partsToText } from "./memoryArtifactStore-BtOeB_hm-tj3fC5ip.js";
2
+ import { a as textParts, n as partsToText } from "./memoryArtifactStore-52Zn9npI-BMPYwvoy.js";
3
3
 
4
4
  //#region ../runtime/dist/testing.js
5
5
  /**
package/dist/testing.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { _ as MemoryStore, b as UiBridge, c as InteractionResponse, l as LlmClient, m as LlmStreamEvent, n as ArtifactStore, p as LlmResponse, s as InteractionRequest, t as Artifact, u as LlmCompleteInput } from "./types-D_hoCri8-BnNPiZCi.js";
2
- import { a as loadGoogleConfigFromEnv, i as loadAnthropicConfigFromEnv, n as LlmEnvConfig, o as loadLlmConfigFromEnv, r as ProviderEnvConfig } from "./env-BPUBZCwJ-4jat_SVG.js";
1
+ import { _ as MemoryStore, b as UiBridge, c as InteractionResponse, l as LlmClient, m as LlmStreamEvent, n as ArtifactStore, p as LlmResponse, s as InteractionRequest, t as Artifact, u as LlmCompleteInput } from "./types-4pg-qp_I-Gq63X8Oa.js";
2
+ import { a as loadGoogleConfigFromEnv, i as loadAnthropicConfigFromEnv, n as LlmEnvConfig, o as loadLlmConfigFromEnv, r as ProviderEnvConfig } from "./env-AK3cSMEA-Dli6QU5E.js";
3
3
  //#region ../runtime/dist/testing.d.ts
4
4
  //#region src/llm/mockLlmClient.d.ts
5
5
  type MockLlmHandler = (input: LlmCompleteInput) => LlmResponse | Promise<LlmResponse>;
package/dist/testing.js CHANGED
@@ -1,5 +1,5 @@
1
- import { t as MemoryArtifactStore } from "./memoryArtifactStore-BtOeB_hm-tj3fC5ip.js";
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-DDCJWvgA.js";
1
+ import { t as MemoryArtifactStore } from "./memoryArtifactStore-52Zn9npI-BMPYwvoy.js";
2
+ import { n as loadGoogleConfigFromEnv, r as loadLlmConfigFromEnv, t as loadAnthropicConfigFromEnv } from "./env-8cY40DXB-CGnEVZby.js";
3
+ import { n as MockLlmClient, r as MockUiBridge, t as InMemoryStore } from "./testing-CYTFqkDm.js";
4
4
 
5
5
  export { InMemoryStore, MemoryArtifactStore, MockLlmClient, MockUiBridge, loadAnthropicConfigFromEnv, loadGoogleConfigFromEnv, loadLlmConfigFromEnv };
@@ -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' | 'NETWORK_BLOCKED' | 'TOOL_UNSUPPORTED' | 'TOOL_NOT_ALLOWED' | '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' | 'SKILL_UNKNOWN_ALLOWED_TOOL' | 'SKILL_UNKNOWN_DEPENDENCY' | 'SKILL_CIRCULAR_DEPENDENCY' | 'GOVERNANCE_FAILED' | 'RUN_SNAPSHOT_NOT_FOUND' | 'RUN_SNAPSHOT_EXPIRED' | 'RUN_SNAPSHOT_INCOMPATIBLE' | 'RUN_SNAPSHOT_SCHEMA_UNSUPPORTED' | 'RUN_TRACE_INCOMPATIBLE' | 'SESSION_INCOMPATIBLE' | 'SIGNATURE_MISSING' | 'SIGNATURE_MALFORMED' | 'SIGNATURE_UNTRUSTED_KEY' | 'SIGNATURE_MISMATCH' | 'SIGNATURE_UNSUPPORTED' | 'MCP_STDIO_SPAWN_FAILED' | 'MCP_STDIO_EXITED' | 'MCP_STDIO_TIMEOUT' | 'TS_RESOURCE_URL_REJECTED' | 'TS_TRANSPILER_UNAVAILABLE' | 'TS_TRANSPILE_FAILED' | 'TODO_LIST_INVALID' | 'TODO_ITEM_NOT_FOUND' | 'SKILL_GENERATION_DISABLED' | 'SKILL_GENERATION_LIMIT_EXCEEDED' | 'SKILL_GENERATION_VALIDATION_FAILED' | 'DELEGATION_UNAVAILABLE' | 'DELEGATION_IN_PROGRESS' | 'DELEGATION_BUDGET_EXCEEDED' | 'PREFERENCE_IMPORT_INVALID' | 'PREFERENCE_IMPORT_VERSION_UNSUPPORTED' | 'PREFERENCE_IMPORT_CREDENTIAL_REJECTED' | 'DICTATION_UNAVAILABLE' | 'DICTATION_PERMISSION_DENIED' | 'DICTATION_FAILED' | 'PERCEPTION_NOT_ENABLED' | 'PERCEPTION_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' | 'NETWORK_BLOCKED' | 'TOOL_UNSUPPORTED' | 'TOOL_NOT_ALLOWED' | 'TOOL_SCHEMA_UNAVAILABLE' | 'TOOL_RESOLUTION_EXHAUSTED' | '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' | 'SKILL_UNKNOWN_ALLOWED_TOOL' | 'SKILL_UNKNOWN_DEPENDENCY' | 'SKILL_CIRCULAR_DEPENDENCY' | 'GOVERNANCE_FAILED' | 'RUN_SNAPSHOT_NOT_FOUND' | 'RUN_SNAPSHOT_EXPIRED' | 'RUN_SNAPSHOT_INCOMPATIBLE' | 'RUN_SNAPSHOT_SCHEMA_UNSUPPORTED' | 'RUN_TRACE_INCOMPATIBLE' | 'SESSION_INCOMPATIBLE' | 'SIGNATURE_MISSING' | 'SIGNATURE_MALFORMED' | 'SIGNATURE_UNTRUSTED_KEY' | 'SIGNATURE_MISMATCH' | 'SIGNATURE_UNSUPPORTED' | 'MCP_STDIO_SPAWN_FAILED' | 'MCP_STDIO_EXITED' | 'MCP_STDIO_TIMEOUT' | 'TS_RESOURCE_URL_REJECTED' | 'TS_TRANSPILER_UNAVAILABLE' | 'TS_TRANSPILE_FAILED' | 'TODO_LIST_INVALID' | 'TODO_ITEM_NOT_FOUND' | 'SKILL_GENERATION_DISABLED' | 'SKILL_GENERATION_LIMIT_EXCEEDED' | 'SKILL_GENERATION_VALIDATION_FAILED' | 'DELEGATION_UNAVAILABLE' | 'DELEGATION_IN_PROGRESS' | 'DELEGATION_BUDGET_EXCEEDED' | 'PROFILE_IMPORT_INVALID' | 'PROFILE_IMPORT_VERSION_UNSUPPORTED' | 'PROFILE_IMPORT_CREDENTIAL_REJECTED' | 'PROFILE_KEY_UNAVAILABLE' | 'DICTATION_UNAVAILABLE' | 'DICTATION_PERMISSION_DENIED' | 'DICTATION_FAILED' | 'PERCEPTION_NOT_ENABLED' | 'PERCEPTION_FAILED' | 'MODEL_IMAGE_UNSUPPORTED' | 'MODEL_TOOLS_UNSUPPORTED' | 'ATTACHMENT_TOO_LARGE' | 'ATTACHMENT_TYPE_REJECTED';
4
4
  /**
5
5
  * 所有公开 API 抛出的结构化错误,code 供上层可编程处理
6
6
  * @stable
@@ -582,7 +582,7 @@ declare function escapeXml(text: string): string;
582
582
  declare function renderAvailableSkillsXml(catalog: SkillCatalog): string;
583
583
  declare const xmlRenderer: CatalogRenderer;
584
584
  //#endregion
585
- //#region ../runtime/dist/types-D_hoCri8.d.ts
585
+ //#region ../runtime/dist/types-4pg-qp_I.d.ts
586
586
  //#region src/llm/streamTypes.d.ts
587
587
  /** 流式 LLM 事件(OpenAI SSE / Vercel fullStream 统一映射) */
588
588
  type LlmStreamEvent = {
@@ -701,6 +701,7 @@ type InteractionRequest = {
701
701
  id: string;
702
702
  message: string;
703
703
  schema?: JsonSchema;
704
+ suggestion?: InteractionSuggestion;
704
705
  } | {
705
706
  type: 'confirm';
706
707
  id: string;
@@ -719,6 +720,22 @@ type InteractionRequest = {
719
720
  label: string;
720
721
  value: unknown;
721
722
  }>;
723
+ suggestion?: InteractionSuggestion;
724
+ } | {
725
+ /**
726
+ * 打开本地文件选择(FR-11.1)。与 `confirm` 分开:浏览器要求
727
+ * `input[type=file].click()` 处于用户手势的调用栈内,渲染层必须能识别
728
+ * 出“这个确认按钮点下去要同步打开选择器”,光看文案分辨不出。
729
+ * @experimental
730
+ */
731
+ type: 'file-pick';
732
+ id: string;
733
+ message: string;
734
+ /** 传给 `input.accept` 的 MIME / 扩展名列表 */
735
+ accept?: readonly string[];
736
+ multiple?: boolean;
737
+ /** 该文件要填的表单字段名 */
738
+ field?: string;
722
739
  } | {
723
740
  /**
724
741
  * 能力强制授权(require-approval):与脚本自发 confirm 区分,UI 渲染为授权样式
@@ -735,6 +752,16 @@ interface InteractionResponse {
735
752
  value?: unknown;
736
753
  cancelled?: boolean;
737
754
  }
755
+ /**
756
+ * 依据用户画像给出的建议值(FR-19.4)。**不会预填进控件**:
757
+ * 渲染器只能展示它并提供「采纳」入口,用户确认后才算填写。
758
+ * @experimental
759
+ */
760
+ interface InteractionSuggestion {
761
+ value: unknown;
762
+ /** 建议依据,展示给用户判断是否采纳 */
763
+ reason?: string;
764
+ }
738
765
  /** 图表规格($chart 约定的校验后形态;渲染单一来源在 ui/chart/miniChart) */
739
766
  interface ChartSpec {
740
767
  kind: 'bar' | 'line' | 'pie';
@@ -873,7 +900,7 @@ interface UiBridge {
873
900
  interface FormField {
874
901
  name: string;
875
902
  label: string;
876
- type: 'text' | 'number' | 'boolean' | 'select' | 'textarea';
903
+ type: 'text' | 'number' | 'boolean' | 'select' | 'textarea' | 'file';
877
904
  required?: boolean;
878
905
  description?: string;
879
906
  defaultValue?: unknown;
@@ -881,16 +908,14 @@ interface FormField {
881
908
  label: string;
882
909
  value: unknown;
883
910
  }>;
884
- /** 跨会话稳定的字段标识 `<skillName>#<fieldName>`(FR-5.6);缺省表示该字段不参与召回 */
885
- fieldKey?: string;
886
911
  /**
887
- * 上次填写值(FR-5.9)。**刻意不叫 defaultValue**:渲染器会把 defaultValue 直接填进控件,
888
- * 而历史值可能是手机号、地址甚至凭据,必须由用户看到后主动采纳。
912
+ * 建议值(FR-19.4)。**刻意不叫 defaultValue**:渲染器会把 defaultValue 直接填进控件,
913
+ * 而建议值来自对用户过往行为的推断,可能过时或不适用,必须由用户看到后主动采纳。
889
914
  * @experimental
890
915
  */
891
916
  suggestion?: {
892
917
  value: unknown;
893
- ts: number;
918
+ reason?: string;
894
919
  };
895
920
  }
896
921
  interface InteractionPolicy {
@@ -1,5 +1,5 @@
1
- import { C as UiSpecEvent, D as UiSurfaceActionResponse, E as UiSurfaceActionRequest, S as UiSpecDrafts, T as UiSpecSnapshot, b as UiBridge, c as InteractionResponse, mt as UiSpecNode, s as InteractionRequest, x as UiSpecActionCapability, y as RenderResultRequest } from "./types-D_hoCri8-BnNPiZCi.js";
2
- import { b as InteractionSpecLabels } from "./index-Bsqg4ftU.js";
1
+ import { C as UiSpecEvent, D as UiSurfaceActionResponse, E as UiSurfaceActionRequest, S as UiSpecDrafts, T as UiSpecSnapshot, b as UiBridge, c as InteractionResponse, mt as UiSpecNode, s as InteractionRequest, x as UiSpecActionCapability, y as RenderResultRequest } from "./types-4pg-qp_I-Gq63X8Oa.js";
2
+ import { b as InteractionSpecLabels } from "./index-BMocOEi0.js";
3
3
  import { z } from "zod";
4
4
  import { ComponentType, ReactNode } from "react";
5
5
  import "react/jsx-runtime";
package/dist/ui-react.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { r as __exportAll$1 } from "./rolldown-runtime-BOF7iYI8.js";
2
2
  import { m as WebSkillError } from "./dist-8oQRa8Xz.js";
3
- import { it as validateUiSpecNode, rt as validateUiSpecEvent } from "./dist-6C03DShK.js";
4
- import { B as toOpenUiSpecLang, I as shapeInteractionValue, O as interactionToFormModel, P as renderMiniChart, Q as chartSpecFromProps, g as applySuggestion, k as interactionToUiSpec, nt as uiCatalog, tt as renderMiniMarkdown, x as collectValues, z as toJsonRenderSpec } from "./dist-bewtXYlO.js";
5
- import { C as Input, S as DropdownMenuTrigger, T as Separator, _ as Checkbox, a as SpecProgress, b as DropdownMenuCheckboxItem, c as SurfaceButton, d as catalogComponentImpls, f as str, g as Button, h as Badge, i as SpecGrid, l as SurfaceField, m as useSurfaceForm, n as CatalogSurfaceProvider, o as SpecTabs, p as useCatalogSurfaceForm, r as EChart, s as SpecTimeline, u as SurfaceFormButtons, v as DataTable, w as Markdown, x as DropdownMenuContent, y as DropdownMenu } from "./catalogComponents-DV7cPpUm-C77AEEx9.js";
3
+ import { Ct as validateUiSpecEvent, wt as validateUiSpecNode } from "./dist-DusANsrn.js";
4
+ import { B as toOpenUiSpecLang, I as shapeInteractionValue, O as interactionToFormModel, P as renderMiniChart, Q as chartSpecFromProps, g as applySuggestion, k as interactionToUiSpec, nt as uiCatalog, tt as renderMiniMarkdown, x as collectValues, z as toJsonRenderSpec } from "./dist-DnYG2-eY.js";
5
+ import { C as Input, S as DropdownMenuTrigger, T as Separator, _ as Checkbox, a as SpecProgress, b as DropdownMenuCheckboxItem, c as SurfaceButton, d as catalogComponentImpls, f as str, g as Button, h as Badge, i as SpecGrid, l as SurfaceField, m as useSurfaceForm, n as CatalogSurfaceProvider, o as SpecTabs, p as useCatalogSurfaceForm, r as EChart, s as SpecTimeline, u as SurfaceFormButtons, v as DataTable, w as Markdown, x as DropdownMenuContent, y as DropdownMenu } from "./catalogComponents-Dr5dFMAb-Dacibl1e.js";
6
6
  import { z } from "zod";
7
7
  import * as React$1 from "react";
8
8
  import React, { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
@@ -6367,9 +6367,19 @@ function applyPatch(node, patch) {
6367
6367
  }
6368
6368
  return copy;
6369
6369
  }
6370
+ /** 键序无关的序列化:同一份内容不能因写入顺序不同而算两个 surface(FR-21.5) */
6371
+ function stableStringify(value) {
6372
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
6373
+ if (isRecord(value)) return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`).join(",")}}`;
6374
+ return JSON.stringify(value) ?? "null";
6375
+ }
6370
6376
  /** Observable, revision-checked snapshot store for framework-neutral UI surfaces. @experimental */
6371
6377
  var UiSurfaceStore = class {
6372
6378
  #entries = /* @__PURE__ */ new Map();
6379
+ /** 内容指纹 → 首次开的 surface id;仅在同一 runId 内合并 */
6380
+ #fingerprints = /* @__PURE__ */ new Map();
6381
+ /** 后到的重复 id → 已存在的 surface id,让后续 patch/complete 仍然寻址得到 */
6382
+ #aliases = /* @__PURE__ */ new Map();
6373
6383
  #listeners = /* @__PURE__ */ new Set();
6374
6384
  #snapshots = [];
6375
6385
  #patchEmitTimer;
@@ -6383,23 +6393,36 @@ var UiSurfaceStore = class {
6383
6393
  apply(event) {
6384
6394
  event = validateUiSpecEvent(event);
6385
6395
  switch (event.type) {
6386
- case "open":
6387
- this.#entries.set(event.id, {
6396
+ case "open": {
6397
+ const snapshot = {
6388
6398
  id: event.id,
6389
6399
  node: structuredClone(event.node),
6390
6400
  ...event.actions ? { actions: structuredClone(event.actions) } : {},
6391
6401
  revision: 0,
6392
6402
  status: "active",
6393
6403
  ...event.runId ? { runId: event.runId } : {}
6394
- });
6404
+ };
6405
+ const fingerprint = this.#fingerprint(event);
6406
+ const merged = fingerprint === void 0 ? void 0 : this.#fingerprints.get(fingerprint);
6407
+ if (merged !== void 0 && this.#entries.has(merged)) {
6408
+ this.#aliases.set(event.id, merged);
6409
+ this.#entries.set(merged, {
6410
+ ...snapshot,
6411
+ id: merged
6412
+ });
6413
+ } else {
6414
+ if (fingerprint !== void 0) this.#fingerprints.set(fingerprint, event.id);
6415
+ this.#entries.set(event.id, snapshot);
6416
+ }
6395
6417
  break;
6418
+ }
6396
6419
  case "patch": {
6397
6420
  const current = this.#entry(event.id);
6398
6421
  this.#assertRunId(current, event.runId);
6399
6422
  if (current.status !== "active" || event.revision !== current.revision + 1) throw new WebSkillError("VALIDATION_FAILED", `Surface patch revision is invalid for "${event.id}"`);
6400
6423
  let node = current.node;
6401
6424
  for (const operation of event.operations) node = applyPatch(node, operation);
6402
- this.#entries.set(event.id, {
6425
+ this.#entries.set(current.id, {
6403
6426
  ...current,
6404
6427
  node: validateUiSpecNode(node),
6405
6428
  revision: event.revision
@@ -6410,7 +6433,7 @@ var UiSurfaceStore = class {
6410
6433
  const current = this.#entry(event.id);
6411
6434
  this.#assertRunId(current, event.runId);
6412
6435
  if (event.revision !== current.revision) throw new WebSkillError("VALIDATION_FAILED", `Surface completion revision is invalid for "${event.id}"`);
6413
- this.#entries.set(event.id, {
6436
+ this.#entries.set(current.id, {
6414
6437
  ...current,
6415
6438
  status: "complete"
6416
6439
  });
@@ -6419,7 +6442,7 @@ var UiSurfaceStore = class {
6419
6442
  case "error": {
6420
6443
  const current = this.#entry(event.id);
6421
6444
  this.#assertRunId(current, event.runId);
6422
- this.#entries.set(event.id, {
6445
+ this.#entries.set(current.id, {
6423
6446
  ...current,
6424
6447
  status: "error",
6425
6448
  error: {
@@ -6432,7 +6455,7 @@ var UiSurfaceStore = class {
6432
6455
  case "cancel": {
6433
6456
  const current = this.#entry(event.id);
6434
6457
  this.#assertRunId(current, event.runId);
6435
- this.#entries.set(event.id, {
6458
+ this.#entries.set(current.id, {
6436
6459
  ...current,
6437
6460
  status: "cancelled"
6438
6461
  });
@@ -6446,8 +6469,16 @@ var UiSurfaceStore = class {
6446
6469
  this.#emit();
6447
6470
  }
6448
6471
  }
6472
+ /** 跨 run 的相同界面是合法重复(用户又问了一次),所以无 runId 时不合并 */
6473
+ #fingerprint(event) {
6474
+ if (event.runId === void 0) return void 0;
6475
+ return `${event.runId}\u0000${stableStringify({
6476
+ node: event.node,
6477
+ actions: event.actions ?? null
6478
+ })}`;
6479
+ }
6449
6480
  #entry(id) {
6450
- const entry = this.#entries.get(id);
6481
+ const entry = this.#entries.get(this.#aliases.get(id) ?? id);
6451
6482
  if (!entry) throw new WebSkillError("VALIDATION_FAILED", `Unknown UI surface "${id}"`);
6452
6483
  return entry;
6453
6484
  }
@@ -6625,25 +6656,37 @@ var ReactBridgeState = class {
6625
6656
  }
6626
6657
  };
6627
6658
  /**
6628
- * 历史值以**建议**形态出现(FR-5.9):控件初始值仍为空,
6659
+ * 建议值以**建议**形态出现(FR-19.4):控件初始值仍为空,
6629
6660
  * 用户点「使用」才写入。切勿改成 defaultValue。
6630
6661
  */
6631
6662
  function Suggestion({ control, onUse }) {
6632
6663
  if (control.suggestion === void 0) return null;
6633
6664
  const preview = String(control.suggestion.value);
6665
+ const reason = control.suggestion.reason;
6634
6666
  return /* @__PURE__ */ jsxs("div", {
6635
6667
  className: "webskill-form__suggestion",
6636
6668
  "data-webskill-suggestion": control.name,
6637
- children: [/* @__PURE__ */ jsxs("span", {
6638
- className: "webskill-form__suggestion-value",
6639
- children: ["Last entered: ", preview]
6640
- }), /* @__PURE__ */ jsx("button", {
6641
- type: "button",
6642
- className: "webskill-form__suggestion-use",
6643
- "data-webskill-suggestion-use": control.name,
6644
- onClick: onUse,
6645
- children: "Use"
6646
- })]
6669
+ children: [
6670
+ /* @__PURE__ */ jsxs("span", {
6671
+ className: "webskill-form__suggestion-value",
6672
+ children: ["Suggested: ", preview]
6673
+ }),
6674
+ reason ? /* @__PURE__ */ jsxs("span", {
6675
+ className: "webskill-form__suggestion-reason",
6676
+ children: [
6677
+ "(",
6678
+ reason,
6679
+ ")"
6680
+ ]
6681
+ }) : null,
6682
+ /* @__PURE__ */ jsx("button", {
6683
+ type: "button",
6684
+ className: "webskill-form__suggestion-use",
6685
+ "data-webskill-suggestion-use": control.name,
6686
+ onClick: onUse,
6687
+ children: "Use"
6688
+ })
6689
+ ]
6647
6690
  });
6648
6691
  }
6649
6692
  function Control({ control, invalid }) {
@@ -7493,7 +7536,7 @@ function OpenUiSpecSurface({ spec, surfaceId, actions, onAction }) {
7493
7536
  const [unavailable, setUnavailable] = useState(false);
7494
7537
  useEffect(() => {
7495
7538
  let cancelled = false;
7496
- import("./openUiLibrary-W3Ce896k-ClFTRZFs.js").then((loaded) => {
7539
+ import("./openUiLibrary-Bdrji9qK-DzAxRlTY.js").then((loaded) => {
7497
7540
  if (!cancelled) setModule(loaded);
7498
7541
  }).catch(() => {
7499
7542
  if (!cancelled) setUnavailable(true);
package/dist/ui-vue.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { b as UiBridge, c as InteractionResponse, s as InteractionRequest, y as RenderResultRequest } from "./types-D_hoCri8-BnNPiZCi.js";
1
+ import { b as UiBridge, c as InteractionResponse, s as InteractionRequest, y as RenderResultRequest } from "./types-4pg-qp_I-Gq63X8Oa.js";
2
2
  import { PropType } from "vue";
3
3
  //#region ../ui-vue/dist/index.d.ts
4
4
  //#region src/bridgeState.d.ts