@webskill/sdk 0.9.0 → 0.10.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 (33) hide show
  1. package/dist/agent.d.ts +2 -2
  2. package/dist/agent.js +5 -1
  3. package/dist/browser.d.ts +5 -3
  4. package/dist/browser.js +15 -7
  5. package/dist/{catalogComponents-DfxxfUvn-T7Ic8QFV.js → catalogComponents-DTcYfpLQ-CcoOaz-Z.js} +1354 -415
  6. package/dist/{dist-BQe1uglQ.js → dist-1OFC-zax.js} +6 -4
  7. package/dist/{dist-CFmkV45C.js → dist-BViUeszk.js} +349 -32
  8. package/dist/{eventTypes-DbOpAECr-BjcjZVms.js → eventTypes-s2uwAcLG-Go3l_dUe.js} +5 -2
  9. package/dist/governance.d.ts +29 -6
  10. package/dist/governance.js +45 -7
  11. package/dist/{index-DXNTIa-6.d.ts → index-B0QPLWPZ.d.ts} +6 -2
  12. package/dist/{index-lLcCpHE-.d.ts → index-BF4E1a9j.d.ts} +10 -3
  13. package/dist/{index-znZjobkr.d.ts → index-DtFdMKBX.d.ts} +63 -6
  14. package/dist/index.d.ts +4 -4
  15. package/dist/index.js +3 -3
  16. package/dist/mcp.d.ts +18 -3
  17. package/dist/mcp.js +62 -21
  18. package/dist/node.d.ts +3 -3
  19. package/dist/node.js +2 -2
  20. package/dist/{openUiLibrary-DURlAxjk-Do_yqg3u.js → openUiLibrary-CIrV--Ad-B8zG_91e.js} +3 -3
  21. package/dist/{skillVersionStore-Bl-ElD45-dMJ8Ybhb.d.ts → skillVersionStore-D-qHk9ZE-DBsYYCWn.d.ts} +13 -5
  22. package/dist/{testing-Csg5ljNm.js → testing-WPTyXQYt.js} +26 -3
  23. package/dist/testing.d.ts +1 -1
  24. package/dist/testing.js +1 -1
  25. package/dist/{types-B3n0cMZu-BDhheIhX.d.ts → types-CrRcT-LM-DZAp8sWv.d.ts} +36 -3
  26. package/dist/ui-react.d.ts +11 -2
  27. package/dist/ui-react.js +119 -38
  28. package/dist/ui-vue.d.ts +1 -1
  29. package/dist/ui-vue.js +1 -1
  30. package/dist/ui.d.ts +3 -3
  31. package/dist/ui.js +2 -2
  32. package/dist/{webskillLitCatalog-DwTwSBFt-BG7kL-Es.js → webskillLitCatalog-BJrphK0y-SGmRXaaO.js} +2 -2
  33. package/package.json +1 -1
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { at as SkillDocument, g as LlmToolSpec, rt as SkillCatalogEntry, z as JsonSchema } from "./types-B3n0cMZu-BDhheIhX.js";
2
- import { O as ExternalSkillProvider, Pn as mergeCatalogEntries, Yt as ToolResult, k as ExternalToolSource } from "./index-znZjobkr.js";
1
+ import { B as JsonSchema, _ as LlmToolSpec, it as SkillCatalogEntry, ot as SkillDocument } from "./types-CrRcT-LM-DZAp8sWv.js";
2
+ import { Fn as mergeCatalogEntries, O as ExternalSkillProvider, Xt as ToolResult, k as ExternalToolSource } from "./index-DtFdMKBX.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";
@@ -264,6 +264,19 @@ declare class ExperimentalWebMcpAdapter {
264
264
  }
265
265
  //#endregion
266
266
  //#region src/plugin/mcpRuntimePlugin.d.ts
267
+ /**
268
+ * 工具可见性策略(0.10.0 UI-UX5 #50.3):端点禁用 ∨ 工具禁用 ⇒ 不进 LLM tool spec,
269
+ * 调用侧同样拦截(模型找不到这些工具)。各判定缺省视为启用。
270
+ * 回调每次 listToolSpecs/call 实时求值,宿主改状态不需要重建插件。
271
+ */
272
+ interface McpToolVisibility {
273
+ /** 端点级开关;返回 false 时该端点所有工具对大模型不可见 */
274
+ isEndpointEnabled?(endpoint: string): boolean;
275
+ /** 端点工具级开关;返回 false 时该工具对大模型不可见 */
276
+ isEndpointToolEnabled?(endpoint: string, tool: string): boolean;
277
+ /** WebMCP 工具级开关;返回 false 时该工具对大模型不可见 */
278
+ isWebMcpToolEnabled?(tool: string): boolean;
279
+ }
267
280
  /**
268
281
  * runtime 扩展点实现:endpoint 注册表 + WebMCP adapter 一处装配。
269
282
  * LLM 可见名:endpoint__tool / mcp__tool;call 时反向映射。
@@ -275,6 +288,8 @@ declare class McpRuntimePlugin implements ExternalToolSource {
275
288
  registry: EndpointRegistry<McpClientLike>;
276
289
  webMcp?: ExperimentalWebMcpAdapter;
277
290
  resolver?: McpToolResolver;
291
+ /** 工具可见性策略(端点/工具级启停);缺省全部可见 */
292
+ visibility?: McpToolVisibility;
278
293
  /** 已知的 endpoint 名(注销后仍按 MCP_ENDPOINT_UNAVAILABLE 响应,而非 TOOL_NOT_FOUND) */
279
294
  endpoints?: string[];
280
295
  /** endpoint 不可用时的告警出口(默认 console.warn) */
@@ -428,4 +443,4 @@ interface RemoteEndpointHandle {
428
443
  */
429
444
  declare function connectRemoteEndpoint(registry: EndpointRegistry<McpClientLike>, config: RemoteEndpointConfig): Promise<RemoteEndpointHandle>;
430
445
  //#endregion
431
- export { type BrowserModelContextLike, EndpointRegistry, ExperimentalWebMcpAdapter, type McpClientLike, type McpOAuthClient, type McpOAuthConfig, type McpOAuthHandshake, type McpOAuthHandshakeStore, type McpOAuthProvider, type McpOAuthStage, type McpOAuthTokenStore, type McpOAuthTokens, McpRuntimePlugin, McpToolResolver, MessageChannelTransport, type MessageChannelTransportOptions, type MessagePortLike, type RemoteEndpointConfig, type RemoteEndpointHandle, type ServedSkill, TemporarySkillProvider, type TransportState, type WebMcpToolDescriptor, type WebMcpToolLike, catalogMerge, connectRemoteEndpoint, createMemoryOAuthStores, createOAuthProvider, endpointToolLlmName, parseEndpointToolLlmName, parseWebMcpToolLlmName, serveSkillAsMcp, validateJsonRpcMessage, webMcpToolLlmName };
446
+ export { type BrowserModelContextLike, EndpointRegistry, ExperimentalWebMcpAdapter, type McpClientLike, type McpOAuthClient, type McpOAuthConfig, type McpOAuthHandshake, type McpOAuthHandshakeStore, type McpOAuthProvider, type McpOAuthStage, type McpOAuthTokenStore, type McpOAuthTokens, McpRuntimePlugin, McpToolResolver, type McpToolVisibility, MessageChannelTransport, type MessageChannelTransportOptions, type MessagePortLike, type RemoteEndpointConfig, type RemoteEndpointHandle, type ServedSkill, TemporarySkillProvider, type TransportState, type WebMcpToolDescriptor, type WebMcpToolLike, catalogMerge, connectRemoteEndpoint, createMemoryOAuthStores, createOAuthProvider, endpointToolLlmName, parseEndpointToolLlmName, parseWebMcpToolLlmName, serveSkillAsMcp, validateJsonRpcMessage, webMcpToolLlmName };
package/dist/mcp.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { M as messageOf, g as assertRemoteUrlAllowed, h as WebSkillError } from "./dist-Bev6i6Ip.js";
2
- import { it as mergeCatalogEntries, lt as normalizeToolContent } from "./dist-CFmkV45C.js";
2
+ import { it as mergeCatalogEntries, lt as normalizeToolContent } from "./dist-BViUeszk.js";
3
3
 
4
4
  //#region ../mcp/dist/index.js
5
5
  /**
@@ -501,6 +501,14 @@ var ExperimentalWebMcpAdapter = class {
501
501
  }
502
502
  }
503
503
  };
504
+ const disabledResult = (llmToolName) => ({
505
+ ok: false,
506
+ content: [],
507
+ error: {
508
+ code: "MCP_TOOL_DISABLED",
509
+ message: `Tool "${llmToolName}" is disabled`
510
+ }
511
+ });
504
512
  /**
505
513
  * runtime 扩展点实现:endpoint 注册表 + WebMCP adapter 一处装配。
506
514
  * LLM 可见名:endpoint__tool / mcp__tool;call 时反向映射。
@@ -510,43 +518,71 @@ var McpRuntimePlugin = class {
510
518
  #registry;
511
519
  #resolver;
512
520
  #webMcp;
521
+ #visibility;
513
522
  #configuredEndpoints;
514
523
  #onWarning;
515
524
  constructor(deps) {
516
525
  this.#registry = deps.registry;
517
526
  this.#resolver = deps.resolver ?? new McpToolResolver(deps.registry);
518
527
  this.#webMcp = deps.webMcp;
528
+ this.#visibility = deps.visibility;
519
529
  this.#configuredEndpoints = deps.endpoints ?? [];
520
530
  this.#onWarning = deps.onWarning ?? ((message) => console.warn(message));
521
531
  }
522
532
  #endpoints() {
523
533
  return [.../* @__PURE__ */ new Set([...this.#configuredEndpoints, ...this.#registry.endpoints()])];
524
534
  }
535
+ /** 端点级可见性:未接策略或判定非 false 即启用 */
536
+ #endpointEnabled(endpoint) {
537
+ return this.#visible(() => this.#visibility?.isEndpointEnabled?.(endpoint));
538
+ }
539
+ /**
540
+ * 可见性回调统一求值:宿主注入的回调抛异常时按「放行 + 告警」处理。
541
+ * 可见性不是安全闸门(安全由审批链兜底),异常关闭会让整轮工具集消失、
542
+ * 模型转而幻觉;放行代价更小,但必须走 onWarning,否则宿主回调 bug 被静默吞掉。
543
+ */
544
+ #visible(probe) {
545
+ try {
546
+ return probe() !== false;
547
+ } catch (e) {
548
+ this.#onWarning(`[webskill] MCP visibility callback failed; treating as enabled: ${e instanceof Error ? e.message : String(e)}`);
549
+ return true;
550
+ }
551
+ }
525
552
  async listToolSpecs() {
526
553
  const specs = [];
527
- for (const endpoint of this.#endpoints()) try {
528
- const { tools } = await this.#registry.get(endpoint).listTools();
529
- for (const tool of tools) specs.push({
530
- name: endpointToolLlmName(endpoint, tool.name),
531
- ...tool.description ? { description: `[${endpoint}] ${tool.description}` } : {},
532
- inputSchema: typeof tool.inputSchema === "object" && tool.inputSchema !== null ? tool.inputSchema : {
533
- type: "object",
534
- properties: {}
554
+ for (const endpoint of this.#endpoints()) {
555
+ if (!this.#endpointEnabled(endpoint)) continue;
556
+ try {
557
+ const { tools } = await this.#registry.get(endpoint).listTools();
558
+ for (const tool of tools) {
559
+ if (!this.#visible(() => this.#visibility?.isEndpointToolEnabled?.(endpoint, tool.name))) continue;
560
+ specs.push({
561
+ name: endpointToolLlmName(endpoint, tool.name),
562
+ ...tool.description ? { description: `[${endpoint}] ${tool.description}` } : {},
563
+ inputSchema: typeof tool.inputSchema === "object" && tool.inputSchema !== null ? tool.inputSchema : {
564
+ type: "object",
565
+ properties: {}
566
+ }
567
+ });
535
568
  }
536
- });
537
- } catch (e) {
538
- this.#onWarning(`[webskill] MCP endpoint "${endpoint}" is unavailable; its tools are omitted from this turn: ${e instanceof Error ? e.message : String(e)}`);
569
+ } catch (e) {
570
+ this.#onWarning(`[webskill] MCP endpoint "${endpoint}" is unavailable; its tools are omitted from this turn: ${e instanceof Error ? e.message : String(e)}`);
571
+ }
539
572
  }
540
573
  if (this.#webMcp?.isEnabled()) {
541
574
  const tools = await this.#webMcp.listTools();
542
- for (const tool of tools ?? []) specs.push({
543
- name: webMcpToolLlmName(tool.name),
544
- description: tool.description ?? `[webmcp] ${tool.name}`,
545
- inputSchema: typeof tool.inputSchema === "object" && tool.inputSchema !== null ? tool.inputSchema : {
546
- type: "object",
547
- properties: {}
548
- }
549
- });
575
+ for (const tool of tools ?? []) {
576
+ if (!this.#visible(() => this.#visibility?.isWebMcpToolEnabled?.(tool.name))) continue;
577
+ specs.push({
578
+ name: webMcpToolLlmName(tool.name),
579
+ description: tool.description ?? `[webmcp] ${tool.name}`,
580
+ inputSchema: typeof tool.inputSchema === "object" && tool.inputSchema !== null ? tool.inputSchema : {
581
+ type: "object",
582
+ properties: {}
583
+ }
584
+ });
585
+ }
550
586
  }
551
587
  return specs;
552
588
  }
@@ -565,11 +601,16 @@ var McpRuntimePlugin = class {
565
601
  message: "WebMCP adapter is not configured"
566
602
  }
567
603
  };
604
+ if (!this.#visible(() => this.#visibility?.isWebMcpToolEnabled?.(webMcpTool))) return disabledResult(llmToolName);
568
605
  return this.#webMcp.call(webMcpTool, args);
569
606
  }
570
607
  for (const endpoint of this.#endpoints()) {
571
608
  const toolName = parseEndpointToolLlmName(endpoint, llmToolName);
572
- if (toolName !== void 0) return this.#resolver.call(endpoint, toolName, args);
609
+ if (toolName !== void 0) {
610
+ if (!this.#endpointEnabled(endpoint)) return disabledResult(llmToolName);
611
+ if (!this.#visible(() => this.#visibility?.isEndpointToolEnabled?.(endpoint, toolName))) return disabledResult(llmToolName);
612
+ return this.#resolver.call(endpoint, toolName, args);
613
+ }
573
614
  }
574
615
  return {
575
616
  ok: false,
package/dist/node.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { I as FileStat, K as SKILLS_LOCKFILE, L as FileSystemProvider, Q as SignatureAuditSink, St as VerifyResult, bt as UnsignedPolicy, c as InteractionResponse, gt as SkillsLockfile, j as ArchiveLimits, lt as SkillManagerPort, ot as SkillInstallSource, q as SKILL_MANIFEST_FILE, s as InteractionRequest, ut as SkillManifest, vt as TrustedKeyStore, x as UiBridge, y as RenderResultRequest, z as JsonSchema } from "./types-B3n0cMZu-BDhheIhX.js";
2
- import { Et as ScriptExecutor, M as FsMemoryStore, Tt as ScriptExecutionContext, Y as NetworkPolicy, Yt as ToolResult, _ as BridgeCapabilities, f as ApprovalScope, j as FsArtifactStore, mn as WebSkillRuntimeDeps, pn as WebSkillRuntime, qt as ToolDefinition, wt as SchemaInferer, yn as createScriptContext } from "./index-znZjobkr.js";
3
- import { a as AuditLog, p as CandidateStore, r as ApprovalPolicy, u as CandidateSkill, v as SkillVersionStore } from "./skillVersionStore-Bl-ElD45-dMJ8Ybhb.js";
1
+ import { $ as SignatureAuditSink, B as JsonSchema, Ct as VerifyResult, J as SKILL_MANIFEST_FILE, L as FileStat, M as ArchiveLimits, R as FileSystemProvider, S as UiBridge, _t as SkillsLockfile, b as RenderResultRequest, c as InteractionResponse, dt as SkillManifest, q as SKILLS_LOCKFILE, s as InteractionRequest, st as SkillInstallSource, ut as SkillManagerPort, xt as UnsignedPolicy, yt as TrustedKeyStore } from "./types-CrRcT-LM-DZAp8sWv.js";
2
+ import { Dt as ScriptExecutor, Et as ScriptExecutionContext, Jt as ToolDefinition, M as FsMemoryStore, Tt as SchemaInferer, Xt as ToolResult, Y as NetworkPolicy, _ as BridgeCapabilities, bn as createScriptContext, f as ApprovalScope, hn as WebSkillRuntimeDeps, j as FsArtifactStore, mn as WebSkillRuntime } from "./index-DtFdMKBX.js";
3
+ import { a as AuditLog, b as SkillVersionStore, d as CandidateSkill, m as CandidateStore, r as ApprovalPolicy } from "./skillVersionStore-D-qHk9ZE-DBsYYCWn.js";
4
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
package/dist/node.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { B as resolveArchiveLimits, D as exportSkills, F as parseSkillPackManifest, G as unzipWithLimits, I as readResponseWithLimit, J as verifySkillSignature, K as validateSkills, L as readSkillSignature, M as messageOf, O as isAtomicTempPath, P as parseSkillMarkdown, V as resolveInsideRoot, _ as assertSafePathSegment, b as buildManifest, c as SKILL_MANIFEST_FILE, d as SKILL_PACK_FILE, g as assertRemoteUrlAllowed, h as WebSkillError, i as MANIFEST_EXCLUDED_FILES, k as isValidSkillName, q as verifyManifest, s as SKILLS_LOCKFILE, v as atomicWriteText } from "./dist-Bev6i6Ip.js";
2
- import { B as bridgeError, H as createScriptContext, L as WebSkillRuntime, c as CapabilityApproval, dt as parseBridgeRequest, h as FsMemoryStore, lt as normalizeToolContent, m as FsArtifactStore, ot as networkPolicyLibSource, ut as normalizeToolError } from "./dist-CFmkV45C.js";
2
+ import { B as bridgeError, H as createScriptContext, L as WebSkillRuntime, c as CapabilityApproval, dt as parseBridgeRequest, h as FsMemoryStore, lt as normalizeToolContent, m as FsArtifactStore, ot as networkPolicyLibSource, ut as normalizeToolError } from "./dist-BViUeszk.js";
3
3
  import { i as probeLlmCapabilities } from "./env-8cY40DXB-CGnEVZby.js";
4
- import { t as AUDIT_EVENT_TYPES } from "./eventTypes-DbOpAECr-BjcjZVms.js";
4
+ import { t as AUDIT_EVENT_TYPES } from "./eventTypes-s2uwAcLG-Go3l_dUe.js";
5
5
  import { createRequire } from "node:module";
6
6
  import { unzipSync, zipSync } from "fflate";
7
7
  import { existsSync, promises, realpathSync } from "node:fs";
@@ -1,5 +1,5 @@
1
- import { ft as uiCatalog } from "./dist-BQe1uglQ.js";
2
- import { t as CatalogNode } from "./catalogComponents-DfxxfUvn-T7Ic8QFV.js";
1
+ import { ft as uiCatalog } from "./dist-1OFC-zax.js";
2
+ import { t as CatalogNode } from "./catalogComponents-DTcYfpLQ-CcoOaz-Z.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-DURlAxjk.js
3764
+ //#region ../ui-react/dist/openUiLibrary-CIrV--Ad.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,5 +1,5 @@
1
- import { H as Page, L as FileSystemProvider, U as PageQuery, rt as SkillCatalogEntry, ut as SkillManifest } from "./types-B3n0cMZu-BDhheIhX.js";
2
- //#region ../governance/dist/skillVersionStore-Bl-ElD45.d.ts
1
+ import { R as FileSystemProvider, U as Page, W as PageQuery, dt as SkillManifest, it as SkillCatalogEntry } from "./types-CrRcT-LM-DZAp8sWv.js";
2
+ //#region ../governance/dist/skillVersionStore-D-qHk9ZE.d.ts
3
3
  //#region src/types.d.ts
4
4
  type CandidateStatus = 'draft' | 'pending-review' | 'approved' | 'published' | 'rejected';
5
5
  /** `generated` 是 0.5.0 的技能自动生成来源(需求 12 号 AC-9.1) */
@@ -84,6 +84,10 @@ type SkillState = 'active' | 'quarantined' | 'deprecated' | 'disabled';
84
84
  //#region src/candidate/candidateStore.d.ts
85
85
  /** 候选列表的缺省页长。缺省属于实现,不属于调用方 */
86
86
  declare const CANDIDATE_PAGE_SIZE = 50;
87
+ /** 候选分页结果:`total` 为筛选后匹配总数(0.10.0 UI-UX5 #40.12,页码分页的总页数依据) @stable */
88
+ interface CandidatePage extends Page<CandidateSkill> {
89
+ total: number;
90
+ }
87
91
  /** 逐文件持久化的候选存储:<managedRoot>/.webskill/candidates/<id>.json */
88
92
  declare class CandidateStore {
89
93
  #private;
@@ -100,7 +104,7 @@ declare class CandidateStore {
100
104
  */
101
105
  list(options?: {
102
106
  status?: CandidateStatus;
103
- } & PageQuery): Promise<Page<CandidateSkill>>;
107
+ } & PageQuery): Promise<CandidatePage>;
104
108
  updateStatus(id: string, status: CandidateStatus, now?: string): Promise<CandidateSkill>;
105
109
  }
106
110
  /** 硬门禁:仅 published 可转换为 Catalog 条目,否则 APPROVAL_REQUIRED */
@@ -128,6 +132,10 @@ declare class CompositeApprovalPolicy implements ApprovalPolicy {
128
132
  //#region src/versioning/skillVersionStore.d.ts
129
133
  /** 版本列表的缺省页长。缺省属于实现,不属于调用方 */
130
134
  declare const SKILL_VERSION_PAGE_SIZE = 20;
135
+ /** 版本分页结果:`total` 为该技能版本总数(0.10.0 UI-UX5 #40.12,页码分页的总页数依据) @stable */
136
+ interface SkillVersionPage extends Page<SkillVersion> {
137
+ total: number;
138
+ }
131
139
  /** 版本存储:manifest 快照 + parentVersionId 链;回滚 = 追加新版本(谱系不断)。
132
140
  * 保留策略:maxArchivesPerSkill(默认 5)超出时清理最旧版本(json + zip 归档一并删除)。 */
133
141
  declare class SkillVersionStore {
@@ -153,7 +161,7 @@ declare class SkillVersionStore {
153
161
  * 版本列表分页(方向同 C1:无游标给**最新**一页)。
154
162
  * 保留策略与谱系构建走 `#readAll`:它们必须看到全量,不能被分页截断。
155
163
  */
156
- list(skillName: string, options?: PageQuery): Promise<Page<SkillVersion>>;
164
+ list(skillName: string, options?: PageQuery): Promise<SkillVersionPage>;
157
165
  get(skillName: string, versionId: string): Promise<SkillVersion>;
158
166
  /** 回滚:基于旧 manifest 追加新版本 + skill.rolled_back 审计 */
159
167
  rollback(skillName: string, targetVersionId: string, input: {
@@ -162,4 +170,4 @@ declare class SkillVersionStore {
162
170
  }): Promise<SkillVersion>;
163
171
  }
164
172
  //#endregion
165
- export { SkillVersion as _, AuditLog as a, CandidateFile as c, CandidateSource as d, CandidateStatus as f, SkillState as g, SKILL_VERSION_PAGE_SIZE as h, AuditEvent as i, CandidateRisk as l, CompositeApprovalPolicy as m, ApprovalDecision as n, AuditQueryFilter as o, CandidateStore as p, ApprovalPolicy as r, CANDIDATE_PAGE_SIZE as s, AlwaysHumanApprovalPolicy as t, CandidateSkill as u, SkillVersionStore as v, candidateToCatalogEntry as y };
173
+ export { SkillState as _, AuditLog as a, SkillVersionStore as b, CandidateFile as c, CandidateSkill as d, CandidateSource as f, SKILL_VERSION_PAGE_SIZE as g, CompositeApprovalPolicy as h, AuditEvent as i, CandidatePage as l, CandidateStore as m, ApprovalDecision as n, AuditQueryFilter as o, CandidateStatus as p, ApprovalPolicy as r, CANDIDATE_PAGE_SIZE as s, AlwaysHumanApprovalPolicy as t, CandidateRisk as u, SkillVersion as v, candidateToCatalogEntry as x, SkillVersionPage as y };
@@ -23,13 +23,21 @@ var MockLlmClient = class {
23
23
  if ("stream" in next) {
24
24
  const events = typeof next.stream === "function" ? next.stream(input) : next.stream;
25
25
  let content = "";
26
+ let thinking = "";
26
27
  let toolCalls;
28
+ let usage;
27
29
  for (const event of events) if (event.type === "text-delta") content += event.delta;
30
+ else if (event.type === "thinking-delta") thinking += event.delta;
28
31
  else if (event.type === "tool-calls") toolCalls = event.toolCalls;
29
- else if (event.type === "done" && event.content !== void 0) content = event.content;
32
+ else if (event.type === "done") {
33
+ if (event.content !== void 0) content = event.content;
34
+ if (event.usage !== void 0) usage = event.usage;
35
+ }
30
36
  return {
31
37
  content: content === "" ? void 0 : textParts(content),
32
- toolCalls
38
+ toolCalls,
39
+ ...thinking === "" ? {} : { thinking },
40
+ ...usage ? { usage } : {}
33
41
  };
34
42
  }
35
43
  return next;
@@ -44,6 +52,18 @@ var MockLlmClient = class {
44
52
  return;
45
53
  }
46
54
  const response = typeof next === "function" ? await next(input) : next;
55
+ if (response.thinking !== void 0 && response.thinking !== "") {
56
+ const half = Math.ceil(response.thinking.length / 2);
57
+ yield {
58
+ type: "thinking-delta",
59
+ delta: response.thinking.slice(0, half)
60
+ };
61
+ const rest = response.thinking.slice(half);
62
+ if (rest !== "") yield {
63
+ type: "thinking-delta",
64
+ delta: rest
65
+ };
66
+ }
47
67
  const text = partsToText(response.content);
48
68
  if (text !== "") {
49
69
  const chunkSize = Math.max(1, Math.ceil(text.length / 3));
@@ -56,7 +76,10 @@ var MockLlmClient = class {
56
76
  type: "tool-calls",
57
77
  toolCalls: response.toolCalls
58
78
  };
59
- yield { type: "done" };
79
+ yield {
80
+ type: "done",
81
+ ...response.usage ? { usage: response.usage } : {}
82
+ };
60
83
  }
61
84
  };
62
85
  /**
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as MemoryStore, c as InteractionResponse, l as LlmClient, m as LlmStreamEvent, n as ArtifactStore, p as LlmResponse, s as InteractionRequest, t as Artifact, u as LlmCompleteInput, x as UiBridge } from "./types-B3n0cMZu-BDhheIhX.js";
1
+ import { S 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, v as MemoryStore } from "./types-CrRcT-LM-DZAp8sWv.js";
2
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
package/dist/testing.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as MemoryArtifactStore } from "./memoryArtifactStore-52Zn9npI-LbCQaqyx.js";
2
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-Csg5ljNm.js";
3
+ import { n as MockLlmClient, r as MockUiBridge, t as InMemoryStore } from "./testing-WPTyXQYt.js";
4
4
 
5
5
  export { InMemoryStore, MemoryArtifactStore, MockLlmClient, MockUiBridge, loadAnthropicConfigFromEnv, loadGoogleConfigFromEnv, loadLlmConfigFromEnv };
@@ -629,18 +629,34 @@ declare function escapeXml(text: string): string;
629
629
  declare function renderAvailableSkillsXml(catalog: SkillCatalog): string;
630
630
  declare const xmlRenderer: CatalogRenderer;
631
631
  //#endregion
632
- //#region ../runtime/dist/types-B3n0cMZu.d.ts
632
+ //#region ../runtime/dist/types-CrRcT-LM.d.ts
633
633
  //#region src/llm/streamTypes.d.ts
634
634
  /** 流式 LLM 事件(OpenAI SSE / Vercel fullStream 统一映射) */
635
635
  type LlmStreamEvent = {
636
636
  type: 'text-delta';
637
637
  delta: string;
638
+ } | {
639
+ /**
640
+ * 思考增量(Anthropic thinking_delta / OpenAI 兼容 reasoning_content /
641
+ * Vercel reasoning-delta 统一映射)。模型不产出思考时一个事件也没有——
642
+ * 消费方据「有没有收到」决定要不要渲染思考区,不做空壳入口。
643
+ */
644
+ type: 'thinking-delta';
645
+ delta: string;
638
646
  } | {
639
647
  type: 'tool-calls';
640
648
  toolCalls: LlmToolCall[];
641
- } | {
649
+ } |
650
+ /**
651
+ * 流收尾。`usage`(0.10.0 UI-UX5 #47):本次调用的 token 用量,
652
+ * 各家适配层在末段汇总后随 done 下发(Anthropic message_start/message_delta、
653
+ * OpenAI include_usage 末段 chunk、Vercel finish 的 totalUsage 统一映射);
654
+ * 上游不回报时缺省——消费方据「有没有」决定要不要展示,不显示假数据。
655
+ */
656
+ {
642
657
  type: 'done';
643
658
  content?: string;
659
+ usage?: LlmTokenUsage;
644
660
  };
645
661
  //#endregion
646
662
  //#region src/llm/types.d.ts
@@ -681,9 +697,26 @@ interface LlmToolCall {
681
697
  /** 流式拼接后的 arguments 不是合法 JSON 时的错误描述;设置时 arguments 不可信 */
682
698
  argumentsParseError?: string;
683
699
  }
700
+ /**
701
+ * 一次模型调用的 token 用量(0.10.0 UI-UX5 #47)。
702
+ * 上游不回报 usage 时整个字段缺省——不填 0 冒充「已知为零」,
703
+ * 消费方据「有没有」决定要不要展示,不显示假数据。
704
+ * @stable
705
+ */
706
+ interface LlmTokenUsage {
707
+ inputTokens: number;
708
+ outputTokens: number;
709
+ }
684
710
  interface LlmResponse {
685
711
  content?: LlmContentPart[];
686
712
  toolCalls?: LlmToolCall[];
713
+ /**
714
+ * 本轮模型产出的思考正文(Anthropic thinking blocks / reasoning_content 等)。
715
+ * 不进消息历史、不回喂模型;只用于运行细节展示与 trace。
716
+ */
717
+ thinking?: string;
718
+ /** 本轮 token 用量(上游回报才有;chrome-builtin 等无 usage 能力的客户端缺省) */
719
+ usage?: LlmTokenUsage;
687
720
  raw?: unknown;
688
721
  }
689
722
  interface LlmCompleteInput {
@@ -1017,4 +1050,4 @@ interface MemoryStore {
1017
1050
  transaction?<T>(scope: string, fn: (inner: MemoryStore) => Promise<T>): Promise<T>;
1018
1051
  }
1019
1052
  //#endregion
1020
- export { SignatureVerdict as $, stripArchiveRoot as $t, ATOMIC_TMP_SUFFIX_PATTERN as A, checkDependencyCycles as At, MANIFEST_EXCLUDED_FILES as B, keyIdOf as Bt, UiSpecDrafts as C, WebSkillError as Ct, UiSurfaceActionRequest as D, atomicWriteText as Dt, UiSpecSnapshot as E, assertSafePathSegment as Et, DiscoveryResult as F, escapeXml as Ft, SIGNATURE_SCHEMA_VERSION as G, readResponseWithLimit as Gt, Page as H, normalizePath as Ht, FileStat as I, exportSkills as It, SKILL_NAME_MAX_LENGTH as J, renderCatalogJson as Jt, SKILLS_LOCKFILE as K, readSkillSignature as Kt, FileSystemProvider as L, isAtomicTempPath as Lt, CatalogRenderer as M, computeDigest as Mt, CryptoKeyLike as N, detectSkillArchiveShape as Nt, UiSurfaceActionResponse as O, buildCatalog as Ot, DEFAULT_ARCHIVE_LIMITS as P, detectSkillArchiveShapeFromFs as Pt, SignatureAuditSink as Q, signaturePayloadBytes as Qt, FsTrustedKeyStore as R, isValidSkillName as Rt, UiSpecActionCapability as S, VerifyResult as St, UiSpecPatch as T, assertRemoteUrlAllowed as Tt, PageQuery as U, parseSkillMarkdown as Ut, MemoryFS as V, messageOf as Vt, RemoteUrlPolicy as W, parseSkillPackManifest as Wt, SKILL_PACK_FILE as X, resolveInsideRoot as Xt, SKILL_NAME_PATTERN as Y, resolveArchiveLimits as Yt, SKILL_SIGNATURE_FILE as Z, signSkill as Zt, MemoryStore as _, TrustedKey as _t, InteractionOrigin as a, SkillDocument as at, SkillCandidateMarker as b, UnsignedPolicy as bt, InteractionResponse as c, SkillLocation as ct, LlmContentPart as d, SkillMetadata as dt, unzipWithLimits as en, SkillArchiveDetection as et, LlmMessage as f, SkillPackManifest as ft, LlmToolSpec as g, SkillsLockfile as gt, LlmToolCall as h, SkillSource as ht, FormField as i, xmlRenderer as in, SkillDiscovery as it, ArchiveLimits as j, checkSkillRules as jt, extractSkillCandidate as k, buildManifest as kt, LlmClient as l, SkillManagerPort as lt, LlmStreamEvent as m, SkillSignature as mt, ArtifactStore as n, verifyManifest as nn, SkillCatalog as nt, InteractionPolicy as o, SkillInstallSource as ot, LlmResponse as p, SkillReader as pt, SKILL_MANIFEST_FILE as q, renderAvailableSkillsXml as qt, ChartSpec as r, verifySkillSignature as rn, SkillCatalogEntry as rt, InteractionRequest as s, SkillIssue as st, Artifact as t, validateSkills as tn, SkillArchiveShape as tt, LlmCompleteInput as u, SkillManifest as ut, RenderBlock as v, TrustedKeyStore as vt, UiSpecEvent as w, WebSkillErrorCode as wt, UiBridge as x, ValidationReport as xt, RenderResultRequest as y, UiSpecNode as yt, JsonSchema as z, jsonRenderer as zt };
1053
+ export { SignatureAuditSink as $, signaturePayloadBytes as $t, extractSkillCandidate as A, buildManifest as At, JsonSchema as B, jsonRenderer as Bt, UiSpecActionCapability as C, VerifyResult as Ct, UiSpecSnapshot as D, assertSafePathSegment as Dt, UiSpecPatch as E, assertRemoteUrlAllowed as Et, DEFAULT_ARCHIVE_LIMITS as F, detectSkillArchiveShapeFromFs as Ft, RemoteUrlPolicy as G, parseSkillPackManifest as Gt, MemoryFS as H, messageOf as Ht, DiscoveryResult as I, escapeXml as It, SKILL_MANIFEST_FILE as J, renderAvailableSkillsXml as Jt, SIGNATURE_SCHEMA_VERSION as K, readResponseWithLimit as Kt, FileStat as L, exportSkills as Lt, ArchiveLimits as M, checkSkillRules as Mt, CatalogRenderer as N, computeDigest as Nt, UiSurfaceActionRequest as O, atomicWriteText as Ot, CryptoKeyLike as P, detectSkillArchiveShape as Pt, SKILL_SIGNATURE_FILE as Q, signSkill as Qt, FileSystemProvider as R, isAtomicTempPath as Rt, UiBridge as S, ValidationReport as St, UiSpecEvent as T, WebSkillErrorCode as Tt, Page as U, normalizePath as Ut, MANIFEST_EXCLUDED_FILES as V, keyIdOf as Vt, PageQuery as W, parseSkillMarkdown as Wt, SKILL_NAME_PATTERN as X, resolveArchiveLimits as Xt, SKILL_NAME_MAX_LENGTH as Y, renderCatalogJson as Yt, SKILL_PACK_FILE as Z, resolveInsideRoot as Zt, LlmToolSpec as _, SkillsLockfile as _t, InteractionOrigin as a, xmlRenderer as an, SkillDiscovery as at, RenderResultRequest as b, UiSpecNode as bt, InteractionResponse as c, SkillIssue as ct, LlmContentPart as d, SkillManifest as dt, stripArchiveRoot as en, SignatureVerdict as et, LlmMessage as f, SkillMetadata as ft, LlmToolCall as g, SkillSource as gt, LlmTokenUsage as h, SkillSignature as ht, FormField as i, verifySkillSignature as in, SkillCatalogEntry as it, ATOMIC_TMP_SUFFIX_PATTERN as j, checkDependencyCycles as jt, UiSurfaceActionResponse as k, buildCatalog as kt, LlmClient as l, SkillLocation as lt, LlmStreamEvent as m, SkillReader as mt, ArtifactStore as n, validateSkills as nn, SkillArchiveShape as nt, InteractionPolicy as o, SkillDocument as ot, LlmResponse as p, SkillPackManifest as pt, SKILLS_LOCKFILE as q, readSkillSignature as qt, ChartSpec as r, verifyManifest as rn, SkillCatalog as rt, InteractionRequest as s, SkillInstallSource as st, Artifact as t, unzipWithLimits as tn, SkillArchiveDetection as tt, LlmCompleteInput as u, SkillManagerPort as ut, MemoryStore as v, TrustedKey as vt, UiSpecDrafts as w, WebSkillError as wt, SkillCandidateMarker as x, UnsignedPolicy as xt, RenderBlock as y, TrustedKeyStore as yt, FsTrustedKeyStore as z, isValidSkillName as zt };
@@ -1,5 +1,5 @@
1
- import { C as UiSpecDrafts, D as UiSurfaceActionRequest, E as UiSpecSnapshot, O as UiSurfaceActionResponse, S as UiSpecActionCapability, c as InteractionResponse, s as InteractionRequest, w as UiSpecEvent, x as UiBridge, y as RenderResultRequest, yt as UiSpecNode } from "./types-B3n0cMZu-BDhheIhX.js";
2
- import { E as InteractionSpecLabels, R as SurfaceFormTexts } from "./index-DXNTIa-6.js";
1
+ import { C as UiSpecActionCapability, D as UiSpecSnapshot, O as UiSurfaceActionRequest, S as UiBridge, T as UiSpecEvent, b as RenderResultRequest, bt as UiSpecNode, c as InteractionResponse, k as UiSurfaceActionResponse, s as InteractionRequest, w as UiSpecDrafts } from "./types-CrRcT-LM-DZAp8sWv.js";
2
+ import { E as InteractionSpecLabels, R as SurfaceFormTexts } from "./index-B0QPLWPZ.js";
3
3
  import { z } from "zod";
4
4
  import React$1, { ComponentType, ReactNode } from "react";
5
5
  import "react/jsx-runtime";
@@ -253,6 +253,15 @@ declare class UiSurfaceStore {
253
253
  subscribe: (listener: () => void) => (() => void);
254
254
  get snapshots(): readonly UiSpecSnapshot[];
255
255
  apply(event: UiSpecEvent): void;
256
+ /**
257
+ * 表单 surface 提交成功后,把提交值回写为 Field 的 `defaultValue`(UI-UX5 #15):
258
+ * run 结束后界面用持久化快照重放,初值只认 defaultValue——不回写,
259
+ * 只读回看就看不到用户当时选/填了什么。
260
+ * 只写标量;字段名全树唯一才写(多表单同名字段无法判定归属,宁可不写也不写错)。
261
+ * 0.10.0 复核注记:multi-select 的数组值不会回写,属已知限制——重放里
262
+ * 多选项字段仍显示初值;标量优先的取舍保留。
263
+ */
264
+ applySubmittedValues(surfaceId: string, values: Record<string, unknown>): void;
256
265
  }
257
266
  //#endregion
258
267
  //#region src/bridgeState.d.ts