@webskill/sdk 0.6.0 → 0.7.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.
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 { at as normalizeToolContent, et as mergeCatalogEntries } from "./dist-DusANsrn.js";
2
+ import { nt as mergeCatalogEntries, st as normalizeToolContent } from "./dist-D0qW6e40.js";
3
3
 
4
4
  //#region ../mcp/dist/index.js
5
5
  /**
@@ -182,6 +182,8 @@ const failure$1 = (code, message) => ({
182
182
  message
183
183
  }
184
184
  });
185
+ /** 需要重新授权不是「端点不可用」:压平成后者,模型和界面都会去查网络(0.7.0 FR-22.3) */
186
+ const endpointFailure = (e, message) => failure$1(e instanceof WebSkillError && e.code.startsWith("MCP_OAUTH_") ? e.code : "MCP_ENDPOINT_UNAVAILABLE", message);
185
187
  /**
186
188
  * endpoint:toolName 调用 + 工具清单缓存(TTL 默认 1s + registry 版本号双失效)。
187
189
  */
@@ -204,7 +206,7 @@ var McpToolResolver = class {
204
206
  try {
205
207
  names = await this.#toolNames(endpoint, client);
206
208
  } catch (e) {
207
- return failure$1("MCP_ENDPOINT_UNAVAILABLE", `Failed to list tools: ${messageOf(e)}`);
209
+ return endpointFailure(e, `Failed to list tools: ${messageOf(e)}`);
208
210
  }
209
211
  if (!names.has(toolName)) {
210
212
  this.#cache.delete(endpoint);
@@ -222,7 +224,7 @@ var McpToolResolver = class {
222
224
  });
223
225
  return this.#normalizeCallResult(raw);
224
226
  } catch (e) {
225
- return failure$1("MCP_ENDPOINT_UNAVAILABLE", `Tool "${toolName}" on endpoint "${endpoint}" failed: ${messageOf(e)}`);
227
+ return endpointFailure(e, `Tool "${toolName}" on endpoint "${endpoint}" failed: ${messageOf(e)}`);
226
228
  }
227
229
  }
228
230
  async #toolNames(endpoint, client) {
@@ -565,22 +567,182 @@ var McpRuntimePlugin = class {
565
567
  };
566
568
  }
567
569
  };
570
+ /**
571
+ * 构造授权相关错误。`message` 只含端点名与阶段,`details` 只有 `{ endpoint, stage }`——
572
+ * 不带 `cause`:SDK 的错误 message 可能回显授权 URL 或 token 端点的响应体(AC-22.6)。
573
+ */
574
+ function oauthError(code, endpoint, stage, reason) {
575
+ return new WebSkillError(code, `Remote MCP endpoint "${endpoint}" ${reason} (stage: ${stage})`, {
576
+ endpoint,
577
+ stage
578
+ });
579
+ }
580
+ /** 显式的内存存储,供 examples 与测试使用。**不是缺省行为**——是宿主主动选的(AC-22.7)。 @experimental */
581
+ function createMemoryOAuthStores() {
582
+ const tokens = /* @__PURE__ */ new Map();
583
+ const handshakes = /* @__PURE__ */ new Map();
584
+ return {
585
+ tokens: {
586
+ load: (endpoint) => Promise.resolve(tokens.get(endpoint)),
587
+ save: (endpoint, value) => {
588
+ tokens.set(endpoint, value);
589
+ return Promise.resolve();
590
+ },
591
+ clear: (endpoint) => {
592
+ tokens.delete(endpoint);
593
+ return Promise.resolve();
594
+ }
595
+ },
596
+ handshake: {
597
+ load: (endpoint) => Promise.resolve(handshakes.get(endpoint)),
598
+ save: (endpoint, value) => {
599
+ handshakes.set(endpoint, value);
600
+ return Promise.resolve();
601
+ },
602
+ clear: (endpoint) => {
603
+ handshakes.delete(endpoint);
604
+ return Promise.resolve();
605
+ }
606
+ }
607
+ };
608
+ }
609
+ const randomState = () => {
610
+ const bytes = /* @__PURE__ */ new Uint8Array(16);
611
+ crypto.getRandomValues(bytes);
612
+ return [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("");
613
+ };
614
+ /**
615
+ * `McpOAuthConfig` → SDK `OAuthClientProvider` 适配器。
616
+ *
617
+ * `state()` 与 `saveCodeVerifier()` 由 SDK 分两次调用(顺序上前者在先),
618
+ * 两者合成一条握手记录:谁先到都把当前已知部分写进去,回程时两项都在。
619
+ * @experimental
620
+ */
621
+ function createOAuthProvider(endpoint, config) {
622
+ const { client, tokens: tokenStore, handshake } = config;
623
+ let pending = {};
624
+ const persist = async (patch) => {
625
+ pending = {
626
+ ...pending,
627
+ ...patch
628
+ };
629
+ await handshake.save(endpoint, {
630
+ codeVerifier: pending.codeVerifier ?? "",
631
+ state: pending.state ?? ""
632
+ });
633
+ };
634
+ return {
635
+ get redirectUrl() {
636
+ return client.redirectUri;
637
+ },
638
+ get clientMetadata() {
639
+ return {
640
+ client_name: "WebSkill SDK",
641
+ redirect_uris: [client.redirectUri],
642
+ grant_types: ["authorization_code", "refresh_token"],
643
+ response_types: ["code"],
644
+ token_endpoint_auth_method: client.clientSecret === void 0 ? "none" : "client_secret_post",
645
+ ...client.scopes && client.scopes.length > 0 ? { scope: client.scopes.join(" ") } : {}
646
+ };
647
+ },
648
+ async state() {
649
+ const value = randomState();
650
+ await persist({ state: value });
651
+ return value;
652
+ },
653
+ clientInformation() {
654
+ return Promise.resolve({
655
+ client_id: client.clientId,
656
+ ...client.clientSecret !== void 0 ? { client_secret: client.clientSecret } : {}
657
+ });
658
+ },
659
+ async tokens() {
660
+ const saved = await tokenStore.load(endpoint);
661
+ if (!saved) return void 0;
662
+ return {
663
+ access_token: saved.accessToken,
664
+ token_type: saved.tokenType ?? "Bearer",
665
+ ...saved.expiresAt !== void 0 ? { expires_in: Math.max(0, Math.round((saved.expiresAt - Date.now()) / 1e3)) } : {},
666
+ ...saved.refreshToken !== void 0 ? { refresh_token: saved.refreshToken } : {},
667
+ ...saved.scope !== void 0 ? { scope: saved.scope } : {}
668
+ };
669
+ },
670
+ async saveTokens(next) {
671
+ await tokenStore.save(endpoint, {
672
+ accessToken: next.access_token,
673
+ ...next.expires_in !== void 0 ? { expiresAt: Date.now() + next.expires_in * 1e3 } : {},
674
+ ...next.refresh_token !== void 0 ? { refreshToken: next.refresh_token } : {},
675
+ ...next.token_type !== void 0 ? { tokenType: next.token_type } : {},
676
+ ...next.scope !== void 0 ? { scope: next.scope } : {}
677
+ });
678
+ },
679
+ async redirectToAuthorization(url) {
680
+ await config.openAuthorization(url);
681
+ },
682
+ async saveCodeVerifier(codeVerifier) {
683
+ await persist({ codeVerifier });
684
+ },
685
+ async codeVerifier() {
686
+ const saved = await handshake.load(endpoint);
687
+ if (!saved?.codeVerifier) throw oauthError("MCP_OAUTH_FAILED", endpoint, "exchange", "has no stored PKCE verifier for this handshake");
688
+ return saved.codeVerifier;
689
+ },
690
+ async invalidateCredentials(scope) {
691
+ if (scope === "all" || scope === "tokens") await tokenStore.clear(endpoint);
692
+ if (scope === "all" || scope === "verifier") await handshake.clear(endpoint);
693
+ }
694
+ };
695
+ }
568
696
  async function loadMcpSdk() {
569
697
  try {
570
- const [client, sse, streamable] = await Promise.all([
698
+ const [client, sse, streamable, auth, errors] = await Promise.all([
571
699
  import("@modelcontextprotocol/sdk/client/index.js"),
572
700
  import("@modelcontextprotocol/sdk/client/sse.js"),
573
- import("@modelcontextprotocol/sdk/client/streamableHttp.js")
701
+ import("@modelcontextprotocol/sdk/client/streamableHttp.js"),
702
+ import("@modelcontextprotocol/sdk/client/auth.js"),
703
+ import("@modelcontextprotocol/sdk/server/auth/errors.js")
574
704
  ]);
575
705
  return {
576
706
  Client: client.Client,
577
707
  SSEClientTransport: sse.SSEClientTransport,
578
- StreamableHTTPClientTransport: streamable.StreamableHTTPClientTransport
708
+ StreamableHTTPClientTransport: streamable.StreamableHTTPClientTransport,
709
+ UnauthorizedError: auth.UnauthorizedError,
710
+ OAuthError: errors.OAuthError
579
711
  };
580
712
  } catch (e) {
581
713
  throw new WebSkillError("MCP_ENDPOINT_UNAVAILABLE", "The \"@modelcontextprotocol/sdk\" package is required for remote MCP endpoints; install it first (npm i @modelcontextprotocol/sdk)", e);
582
714
  }
583
715
  }
716
+ /** 运行期的未授权(含刷新失败)必须在 endpoint 层转成 `WebSkillError`,否则 401 会以工具结果的形式进模型上下文 */
717
+ function wrapOAuthClient(client, endpoint, oauth, isUnauthorized) {
718
+ const guard = async (work) => {
719
+ try {
720
+ return await work();
721
+ } catch (e) {
722
+ if (!isUnauthorized(e)) throw e;
723
+ await oauth.tokens.clear(endpoint);
724
+ throw oauthError("MCP_OAUTH_REQUIRED", endpoint, "refresh", "needs authorization again");
725
+ }
726
+ };
727
+ return {
728
+ listTools: () => guard(() => client.listTools()),
729
+ callTool: (input) => guard(() => client.callTool(input)),
730
+ listPrompts: () => guard(() => client.listPrompts()),
731
+ getPrompt: (input) => guard(() => client.getPrompt(input)),
732
+ listResources: () => guard(() => client.listResources()),
733
+ readResource: (input) => guard(() => client.readResource(input))
734
+ };
735
+ }
736
+ /** 授权注入的完整性校验:缺一项就是宿主的配置错误,不是运行期授权问题(AC-22.7) */
737
+ function assertOAuthConfigured(endpoint, oauth) {
738
+ const missing = [];
739
+ if (!oauth.client?.clientId) missing.push("client.clientId");
740
+ if (!oauth.client?.redirectUri) missing.push("client.redirectUri");
741
+ if (!oauth.tokens) missing.push("tokens");
742
+ if (!oauth.handshake) missing.push("handshake");
743
+ if (typeof oauth.openAuthorization !== "function") missing.push("openAuthorization");
744
+ if (missing.length > 0) throw oauthError("MCP_OAUTH_NOT_CONFIGURED", endpoint, "discover", `is missing OAuth wiring: ${missing.join(", ")}`);
745
+ }
584
746
  /**
585
747
  * 远程 MCP endpoint 装配:SDK 官方 StreamableHTTPClientTransport(默认)/
586
748
  * SSEClientTransport(遗留)连接远端 server,注册进 EndpointRegistry——
@@ -588,7 +750,7 @@ async function loadMcpSdk() {
588
750
  * 返回 close 句柄:断开后 unregister(临时技能随既有生命周期自然消失)。
589
751
  */
590
752
  async function connectRemoteEndpoint(registry, config) {
591
- const { Client, SSEClientTransport, StreamableHTTPClientTransport } = await loadMcpSdk();
753
+ const { Client, SSEClientTransport, StreamableHTTPClientTransport, UnauthorizedError, OAuthError } = await loadMcpSdk();
592
754
  let url;
593
755
  try {
594
756
  url = new URL(config.url);
@@ -599,46 +761,81 @@ async function connectRemoteEndpoint(registry, config) {
599
761
  allowHttp: config.allowHttp ?? false,
600
762
  allowPrivateHosts: config.allowPrivateHosts ?? false
601
763
  });
764
+ const oauth = config.oauth;
765
+ if (oauth) assertOAuthConfigured(config.endpoint, oauth);
766
+ const authProvider = oauth ? createOAuthProvider(config.endpoint, oauth) : void 0;
602
767
  const requestInit = config.headers ? { headers: config.headers } : void 0;
603
- const transport = config.transport === "sse" ? new SSEClientTransport(url, { ...requestInit ? { requestInit } : {} }) : new StreamableHTTPClientTransport(url, { ...requestInit ? { requestInit } : {} });
768
+ const transportOptions = {
769
+ ...requestInit ? { requestInit } : {},
770
+ ...authProvider ? { authProvider } : {}
771
+ };
772
+ const makeTransport = () => config.transport === "sse" ? new SSEClientTransport(url, transportOptions) : new StreamableHTTPClientTransport(url, transportOptions);
604
773
  const client = new Client({
605
774
  name: "webskill-remote-client",
606
775
  version: "0.1.0"
607
776
  });
777
+ const isUnauthorized = (e) => e instanceof UnauthorizedError || e instanceof OAuthError;
608
778
  const unavailable = (e) => new WebSkillError("MCP_ENDPOINT_UNAVAILABLE", `Failed to connect remote MCP endpoint "${config.endpoint}" at ${config.url}: ${messageOf(e)}`, e);
609
- try {
779
+ let closed = false;
780
+ const close = async () => {
781
+ if (closed) return;
782
+ closed = true;
783
+ registry.unregister(config.endpoint);
784
+ try {
785
+ await client.close();
786
+ } catch (e) {
787
+ throw new WebSkillError("MCP_ENDPOINT_UNAVAILABLE", `Failed to close remote MCP endpoint "${config.endpoint}": ${messageOf(e)}`, e);
788
+ }
789
+ };
790
+ const register = () => {
791
+ try {
792
+ const entry = client;
793
+ registry.register(config.endpoint, oauth ? wrapOAuthClient(entry, config.endpoint, oauth, isUnauthorized) : entry);
794
+ } catch (e) {
795
+ client.close().catch(() => void 0);
796
+ throw unavailable(e);
797
+ }
798
+ };
799
+ const openConnection = async (transport) => {
610
800
  let connect = client.connect(transport);
611
801
  if (config.timeoutMs && config.timeoutMs > 0) {
612
802
  const timeoutMs = config.timeoutMs;
613
803
  connect = Promise.race([connect, new Promise((_resolve, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error(`Connection timed out after ${timeoutMs}ms`)), timeoutMs))]);
614
804
  }
615
805
  await connect;
616
- } catch (e) {
806
+ };
807
+ const finishAuthorization = async (code, state) => {
808
+ const saved = await oauth.handshake.load(config.endpoint);
809
+ if (!saved || saved.state === "" || saved.state !== state) throw oauthError("MCP_OAUTH_FAILED", config.endpoint, "authorize", "received a mismatched authorization state");
810
+ const transport = makeTransport();
617
811
  try {
618
- await client.close();
619
- } catch {}
620
- throw unavailable(e);
621
- }
812
+ await transport.finishAuth(code);
813
+ } catch (e) {
814
+ throw oauthError(isUnauthorized(e) ? "MCP_OAUTH_REQUIRED" : "MCP_OAUTH_FAILED", config.endpoint, "exchange", "could not exchange the authorization code");
815
+ }
816
+ await oauth.handshake.clear(config.endpoint);
817
+ await openConnection(transport);
818
+ register();
819
+ };
622
820
  try {
623
- registry.register(config.endpoint, client);
821
+ await openConnection(makeTransport());
624
822
  } catch (e) {
823
+ if (oauth && isUnauthorized(e)) return {
824
+ close,
825
+ finishAuthorization,
826
+ authorizationRequired: true
827
+ };
625
828
  try {
626
829
  await client.close();
627
830
  } catch {}
628
831
  throw unavailable(e);
629
832
  }
630
- let closed = false;
631
- return { close: async () => {
632
- if (closed) return;
633
- closed = true;
634
- registry.unregister(config.endpoint);
635
- try {
636
- await client.close();
637
- } catch (e) {
638
- throw new WebSkillError("MCP_ENDPOINT_UNAVAILABLE", `Failed to close remote MCP endpoint "${config.endpoint}": ${messageOf(e)}`, e);
639
- }
640
- } };
833
+ register();
834
+ return {
835
+ close,
836
+ ...oauth ? { finishAuthorization } : {}
837
+ };
641
838
  }
642
839
 
643
840
  //#endregion
644
- export { EndpointRegistry, ExperimentalWebMcpAdapter, McpRuntimePlugin, McpToolResolver, MessageChannelTransport, TemporarySkillProvider, catalogMerge, connectRemoteEndpoint, endpointToolLlmName, parseEndpointToolLlmName, parseWebMcpToolLlmName, serveSkillAsMcp, validateJsonRpcMessage, webMcpToolLlmName };
841
+ export { EndpointRegistry, ExperimentalWebMcpAdapter, McpRuntimePlugin, McpToolResolver, MessageChannelTransport, TemporarySkillProvider, catalogMerge, connectRemoteEndpoint, createMemoryOAuthStores, createOAuthProvider, endpointToolLlmName, parseEndpointToolLlmName, parseWebMcpToolLlmName, serveSkillAsMcp, validateJsonRpcMessage, webMcpToolLlmName };
package/dist/node.d.ts CHANGED
@@ -1,6 +1,6 @@
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";
1
+ import { A as ArchiveLimits, F as FileStat, G as SKILLS_LOCKFILE, I as FileSystemProvider, K as SKILL_MANIFEST_FILE, R as JsonSchema, Z as SignatureAuditSink, _t as UnsignedPolicy, c as InteractionResponse, ht as TrustedKeyStore, ot as SkillManagerPort, pt as SkillsLockfile, rt as SkillInstallSource, s as InteractionRequest, st as SkillManifest, x as UiBridge, y as RenderResultRequest, yt as VerifyResult } from "./types-CcxRLdJG-DCXyw1US.js";
2
+ import { Et as ScriptExecutor, Kt as ToolResult, M as FsMemoryStore, Tt as ScriptExecutionContext, Wt as ToolDefinition, Y as NetworkPolicy, _ as BridgeCapabilities, f as ApprovalScope, hn as createScriptContext, j as FsArtifactStore, ln as WebSkillRuntime, un as WebSkillRuntimeDeps, wt as SchemaInferer } from "./index-DkbABR43.js";
3
+ import { a as AuditLog, p as CandidateStore, r as ApprovalPolicy, u as CandidateSkill, v as SkillVersionStore } from "./skillVersionStore-Bl-ElD45-CWPvGvoq.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,6 +1,7 @@
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 { 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";
2
+ import { B as bridgeError, H as createScriptContext, L as WebSkillRuntime, c as CapabilityApproval, ct as normalizeToolError, h as FsMemoryStore, it as networkPolicyLibSource, lt as parseBridgeRequest, m as FsArtifactStore, st as normalizeToolContent } from "./dist-D0qW6e40.js";
3
3
  import { i as probeLlmCapabilities } from "./env-8cY40DXB-CGnEVZby.js";
4
+ import { t as AUDIT_EVENT_TYPES } from "./eventTypes-DjIQpt8Y-Bj3vghj4.js";
4
5
  import { createRequire } from "node:module";
5
6
  import { unzipSync, zipSync } from "fflate";
6
7
  import { existsSync, promises, realpathSync } from "node:fs";
@@ -2259,7 +2260,7 @@ var ApprovalWorkflow = class {
2259
2260
  });
2260
2261
  await this.#store.updateStatus(candidateId, "published");
2261
2262
  await this.#audit.append({
2262
- type: "skill.published",
2263
+ type: AUDIT_EVENT_TYPES.skillPublished,
2263
2264
  target: candidate.name,
2264
2265
  actor: input.actor,
2265
2266
  data: {
@@ -1,5 +1,5 @@
1
1
  import { nt as uiCatalog } from "./dist-DnYG2-eY.js";
2
- import { t as CatalogNode } from "./catalogComponents-Dr5dFMAb-Dacibl1e.js";
2
+ import { t as CatalogNode } from "./catalogComponents-Dr5dFMAb-DKH_7VPI.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";
@@ -1,5 +1,5 @@
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
- //#region ../governance/dist/skillVersionStore-BzLbzFOL.d.ts
1
+ import { H as PageQuery, I as FileSystemProvider, V as Page, et as SkillCatalogEntry, st as SkillManifest } from "./types-CcxRLdJG-DCXyw1US.js";
2
+ //#region ../governance/dist/skillVersionStore-Bl-ElD45.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) */
@@ -49,6 +49,12 @@ interface AuditQueryFilter {
49
49
  since?: string;
50
50
  /** 含端点(`ts <= until`) */
51
51
  until?: string;
52
+ /**
53
+ * true 时链校验失败不抛错,改为在结果里报告断点(`chainBrokenAt` / `chainReason`)。
54
+ * **仅用于人工查看的降级展示**:程序化消费方(合规导出等)拿到部分结果而不知情
55
+ * 比直接失败更危险。默认 false,保持既有行为。
56
+ */
57
+ tolerateBrokenChain?: boolean;
52
58
  }
53
59
  interface AuditLog {
54
60
  append(event: Omit<AuditEvent, 'id' | 'ts'> & {
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
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";
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-CcxRLdJG-DCXyw1US.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
@@ -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' | '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';
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' | 'MCP_OAUTH_REQUIRED' | 'MCP_OAUTH_FAILED' | 'MCP_OAUTH_NOT_CONFIGURED' | 'PAGE_ACTION_OUT_OF_SCOPE' | 'PAGE_ACTION_STALE_REF' | 'PAGE_ACTION_DECLINED' | '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-4pg-qp_I.d.ts
585
+ //#region ../runtime/dist/types-CcxRLdJG.d.ts
586
586
  //#region src/llm/streamTypes.d.ts
587
587
  /** 流式 LLM 事件(OpenAI SSE / Vercel fullStream 统一映射) */
588
588
  type LlmStreamEvent = {
@@ -681,6 +681,25 @@ interface ArtifactStore {
681
681
  listArtifacts(runId: string): Promise<Artifact[]>;
682
682
  }
683
683
  //#endregion
684
+ //#region src/skillGeneration/candidateMarker.d.ts
685
+ /**
686
+ * 一个已提交待审批的技能候选。字段固定为 `{ id, name }`——
687
+ * 这条通道只用来把候选交接给界面,扩字段要走 AC-G12 登记。
688
+ * @experimental
689
+ */
690
+ interface SkillCandidateMarker {
691
+ id: string;
692
+ name: string;
693
+ }
694
+ /**
695
+ * `$skillCandidate` 约定的形状校验:JSON content 的 data 含合法 `$skillCandidate` 键 → 候选载荷。
696
+ *
697
+ * 与 `$chart` / `$todo` / `$surface` 同一条既有通道,是第四个。
698
+ * 候选的生成与存储全部在 `@webskill/agent`,runtime 只认这个形状,畸形忽略不炸。
699
+ * @experimental
700
+ */
701
+ declare function extractSkillCandidate(data: unknown): SkillCandidateMarker | undefined;
702
+ //#endregion
684
703
  //#region src/interaction/types.d.ts
685
704
  /**
686
705
  * 交互的发起方标识(FR-11.6)。串行委派下父 agent 与子 agent 都能发起交互,
@@ -743,7 +762,7 @@ type InteractionRequest = {
743
762
  */
744
763
  type: 'authorize';
745
764
  id: string;
746
- capability: 'readReference' | 'writeArtifact' | 'confirm';
765
+ capability: 'readReference' | 'writeArtifact' | 'confirm' | 'pageAction';
747
766
  message: string;
748
767
  details?: unknown;
749
768
  });
@@ -801,6 +820,12 @@ interface RenderResultRequest {
801
820
  summary?: string;
802
821
  blocks: RenderBlock[];
803
822
  artifacts?: Artifact[];
823
+ /**
824
+ * 引擎注入的「最终输出」markdown block 在 `blocks` 中的下标;未注入时缺省。
825
+ * 消费方据此剔除与消息正文重复的那一块,**不得改用正文字符串比较**。
826
+ * 技能作者自己产出的 block 不在此字段的范围内。
827
+ */
828
+ outputBlockIndex?: number;
804
829
  }
805
830
  /** A user action exposed by a generative UI surface. @experimental */
806
831
  interface UiSpecActionCapability {
@@ -894,6 +919,8 @@ interface UiBridge {
894
919
  requestSurfaceAction?(input: UiSurfaceActionRequest): Promise<UiSurfaceActionResponse>;
895
920
  /** Best-effort cleanup when a surface action wait times out or is cancelled. @experimental */
896
921
  cancelSurfaceAction?(nonce: string): void | Promise<void>;
922
+ /** 已提交待审批的技能候选(`$skillCandidate` 载荷);未实现时候选只存在于工具返回值里。 @experimental */
923
+ onSkillCandidate?(runId: string, candidate: SkillCandidateMarker): void | Promise<void>;
897
924
  /** 流式文本增量(流式 LLM 路径下由 AgentLoop 转发) */
898
925
  onTextDelta?(runId: string, delta: string): Promise<void> | void;
899
926
  }
@@ -942,4 +969,4 @@ interface MemoryStore {
942
969
  transaction?<T>(scope: string, fn: (inner: MemoryStore) => Promise<T>): Promise<T>;
943
970
  }
944
971
  //#endregion
945
- export { SkillDiscovery as $, CryptoKeyLike as A, isValidSkillName as At, PageQuery as B, renderCatalogJson as Bt, UiSpecEvent as C, buildCatalog as Ct, UiSurfaceActionResponse as D, computeDigest as Dt, UiSurfaceActionRequest as E, checkSkillRules as Et, FsTrustedKeyStore as F, parseSkillMarkdown as Ft, SKILL_NAME_MAX_LENGTH as G, unzipWithLimits as Gt, SIGNATURE_SCHEMA_VERSION as H, resolveInsideRoot as Ht, JsonSchema as I, parseSkillPackManifest as It, SKILL_SIGNATURE_FILE as J, verifySkillSignature as Jt, SKILL_NAME_PATTERN as K, validateSkills as Kt, MANIFEST_EXCLUDED_FILES as L, readResponseWithLimit as Lt, DiscoveryResult as M, keyIdOf as Mt, FileStat as N, messageOf as Nt, ArchiveLimits as O, escapeXml as Ot, FileSystemProvider as P, normalizePath as Pt, SkillCatalogEntry as Q, MemoryFS as R, readSkillSignature as Rt, UiSpecDrafts as S, atomicWriteText as St, UiSpecSnapshot as T, checkDependencyCycles as Tt, SKILLS_LOCKFILE as U, signSkill as Ut, RemoteUrlPolicy as V, resolveArchiveLimits as Vt, SKILL_MANIFEST_FILE as W, signaturePayloadBytes as Wt, SignatureVerdict as X, SignatureAuditSink as Y, xmlRenderer as Yt, SkillCatalog as Z, MemoryStore as _, VerifyResult as _t, InteractionOrigin as a, SkillManifest as at, UiBridge as b, assertRemoteUrlAllowed as bt, InteractionResponse as c, SkillReader as ct, LlmContentPart as d, SkillsLockfile as dt, SkillDocument as et, LlmMessage as f, TrustedKey as ft, LlmToolSpec as g, ValidationReport as gt, LlmToolCall as h, UnsignedPolicy as ht, FormField as i, SkillManagerPort as it, DEFAULT_ARCHIVE_LIMITS as j, jsonRenderer as jt, CatalogRenderer as k, exportSkills as kt, LlmClient as l, SkillSignature as lt, LlmStreamEvent as m, UiSpecNode as mt, ArtifactStore as n, SkillIssue as nt, InteractionPolicy as o, SkillMetadata as ot, LlmResponse as p, TrustedKeyStore as pt, SKILL_PACK_FILE as q, verifyManifest as qt, ChartSpec as r, SkillLocation as rt, InteractionRequest as s, SkillPackManifest as st, Artifact as t, SkillInstallSource as tt, LlmCompleteInput as u, SkillSource as ut, RenderBlock as v, WebSkillError as vt, UiSpecPatch as w, buildManifest as wt, UiSpecActionCapability as x, assertSafePathSegment as xt, RenderResultRequest as y, WebSkillErrorCode as yt, Page as z, renderAvailableSkillsXml as zt };
972
+ export { SkillCatalog as $, ArchiveLimits as A, escapeXml as At, MemoryFS as B, readSkillSignature as Bt, UiSpecDrafts as C, assertSafePathSegment as Ct, UiSurfaceActionRequest as D, checkDependencyCycles as Dt, UiSpecSnapshot as E, buildManifest as Et, FileStat as F, messageOf as Ft, SKILLS_LOCKFILE as G, signSkill as Gt, PageQuery as H, renderCatalogJson as Ht, FileSystemProvider as I, normalizePath as It, SKILL_NAME_PATTERN as J, validateSkills as Jt, SKILL_MANIFEST_FILE as K, signaturePayloadBytes as Kt, FsTrustedKeyStore as L, parseSkillMarkdown as Lt, CryptoKeyLike as M, isValidSkillName as Mt, DEFAULT_ARCHIVE_LIMITS as N, jsonRenderer as Nt, UiSurfaceActionResponse as O, checkSkillRules as Ot, DiscoveryResult as P, keyIdOf as Pt, SignatureVerdict as Q, JsonSchema as R, parseSkillPackManifest as Rt, UiSpecActionCapability as S, assertRemoteUrlAllowed as St, UiSpecPatch as T, buildCatalog as Tt, RemoteUrlPolicy as U, resolveArchiveLimits as Ut, Page as V, renderAvailableSkillsXml as Vt, SIGNATURE_SCHEMA_VERSION as W, resolveInsideRoot as Wt, SKILL_SIGNATURE_FILE as X, verifySkillSignature as Xt, SKILL_PACK_FILE as Y, verifyManifest as Yt, SignatureAuditSink as Z, xmlRenderer as Zt, MemoryStore as _, UnsignedPolicy as _t, InteractionOrigin as a, SkillLocation as at, SkillCandidateMarker as b, WebSkillError as bt, InteractionResponse as c, SkillMetadata as ct, LlmContentPart as d, SkillSignature as dt, SkillCatalogEntry as et, LlmMessage as f, SkillSource as ft, LlmToolSpec as g, UiSpecNode as gt, LlmToolCall as h, TrustedKeyStore as ht, FormField as i, SkillIssue as it, CatalogRenderer as j, exportSkills as jt, extractSkillCandidate as k, computeDigest as kt, LlmClient as l, SkillPackManifest as lt, LlmStreamEvent as m, TrustedKey as mt, ArtifactStore as n, SkillDocument as nt, InteractionPolicy as o, SkillManagerPort as ot, LlmResponse as p, SkillsLockfile as pt, SKILL_NAME_MAX_LENGTH as q, unzipWithLimits as qt, ChartSpec as r, SkillInstallSource as rt, InteractionRequest as s, SkillManifest as st, Artifact as t, SkillDiscovery as tt, LlmCompleteInput as u, SkillReader as ut, RenderBlock as v, ValidationReport as vt, UiSpecEvent as w, atomicWriteText as wt, UiBridge as x, WebSkillErrorCode as xt, RenderResultRequest as y, VerifyResult as yt, MANIFEST_EXCLUDED_FILES as z, readResponseWithLimit as zt };
@@ -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-4pg-qp_I-Gq63X8Oa.js";
2
- import { b as InteractionSpecLabels } from "./index-BMocOEi0.js";
1
+ import { C as UiSpecDrafts, D as UiSurfaceActionRequest, E as UiSpecSnapshot, O as UiSurfaceActionResponse, S as UiSpecActionCapability, c as InteractionResponse, gt as UiSpecNode, s as InteractionRequest, w as UiSpecEvent, x as UiBridge, y as RenderResultRequest } from "./types-CcxRLdJG-DCXyw1US.js";
2
+ import { b as InteractionSpecLabels } from "./index-BwsK9lGk.js";
3
3
  import { z } from "zod";
4
4
  import { ComponentType, ReactNode } from "react";
5
5
  import "react/jsx-runtime";
@@ -410,6 +410,8 @@ interface NativeSpecSurfaceProps {
410
410
  surfaceId: string;
411
411
  value: Record<string, unknown>;
412
412
  }): void;
413
+ /** 宿主已提供卡片外壳时传 `'none'`,避免嵌套两层卡片。缺省 `'card'`。 */
414
+ shell?: 'card' | 'none';
413
415
  }
414
416
  /**
415
417
  * Native 档的 catalog registry:把声明树渲染成 ui-kit 组件。
@@ -418,7 +420,7 @@ interface NativeSpecSurfaceProps {
418
420
  * 表单行为(草稿跨刷新、必填拦截、默认值)由本组件承接——
419
421
  * 节点树取代六类 surface 后,这里是 native 档唯一的渲染实现。
420
422
  */
421
- declare function NativeSpecSurface({ surfaceId, spec, actions, registry, runId, draft, onAction, onDraftChange }: NativeSpecSurfaceProps): import("react").JSX.Element;
423
+ declare function NativeSpecSurface({ surfaceId, spec, actions, registry, runId, draft, onAction, onDraftChange, shell }: NativeSpecSurfaceProps): import("react").JSX.Element;
422
424
  //#endregion
423
425
  //#region src/catalog/JsonRenderSpecSurface.d.ts
424
426
  interface JsonRenderSpecSurfaceProps {
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 { Ct as validateUiSpecEvent, wt as validateUiSpecNode } from "./dist-DusANsrn.js";
3
+ import { Et as validateUiSpecNode, Tt as validateUiSpecEvent } from "./dist-D0qW6e40.js";
4
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";
5
+ import { C as Markdown, S as Input, _ as DataTable, a as SpecProgress, b as DropdownMenuContent, 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 DropdownMenu, w as Separator, x as DropdownMenuTrigger, y as DropdownMenuCheckboxItem } from "./catalogComponents-Dr5dFMAb-DKH_7VPI.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";
@@ -6912,7 +6912,7 @@ function StreamingText({ bridge }) {
6912
6912
  });
6913
6913
  }
6914
6914
  /**
6915
- * catalog `Table` 节点的渲染实现:排序 / 筛选 / 分页 / 列显隐 / 行选择 / 虚拟滚动。
6915
+ * catalog `Table` 节点的渲染实现:排序 / 筛选 / 分页 / 列显隐 / 虚拟滚动。
6916
6916
  * 这些是宿主侧的呈现能力,不进 catalog props——模型只声明 columns 与 rows。
6917
6917
  * 它们都带 `data-webskill-host-control`,跨渲染器语义对括据此排除宿主控件。
6918
6918
  */
@@ -6920,40 +6920,22 @@ function SpecTable({ columns, rows, label }) {
6920
6920
  const [sorting, setSorting] = useState([]);
6921
6921
  const [globalFilter, setGlobalFilter] = useState("");
6922
6922
  const [columnVisibility, setColumnVisibility] = useState({});
6923
- const [rowSelection, setRowSelection] = useState({});
6924
6923
  const scrollRef = useRef(null);
6925
6924
  const table = useReactTable({
6926
6925
  data: rows,
6927
- columns: [{
6928
- id: "selection",
6929
- header: ({ table }) => /* @__PURE__ */ jsx(Checkbox, {
6930
- "aria-label": "Select all rows",
6931
- checked: table.getIsSomePageRowsSelected() ? "indeterminate" : table.getIsAllPageRowsSelected(),
6932
- onCheckedChange: (checked) => table.toggleAllPageRowsSelected(checked === true)
6933
- }),
6934
- cell: ({ row }) => /* @__PURE__ */ jsx(Checkbox, {
6935
- "aria-label": `Select row ${row.index + 1}`,
6936
- checked: row.getIsSelected(),
6937
- onCheckedChange: (checked) => row.toggleSelected(checked === true)
6938
- }),
6939
- enableSorting: false,
6940
- enableHiding: false
6941
- }, ...columns.map((header, index) => ({
6926
+ columns: columns.map((header, index) => ({
6942
6927
  id: `column-${index}`,
6943
6928
  header,
6944
6929
  accessorFn: (row) => row[index]
6945
- }))],
6930
+ })),
6946
6931
  state: {
6947
6932
  sorting,
6948
6933
  globalFilter,
6949
- columnVisibility,
6950
- rowSelection
6934
+ columnVisibility
6951
6935
  },
6952
6936
  onSortingChange: setSorting,
6953
6937
  onGlobalFilterChange: setGlobalFilter,
6954
6938
  onColumnVisibilityChange: setColumnVisibility,
6955
- onRowSelectionChange: setRowSelection,
6956
- enableRowSelection: true,
6957
6939
  globalFilterFn: (row, _columnId, filterValue) => row.original.some((cell) => String(cell ?? "").toLocaleLowerCase().includes(String(filterValue).toLocaleLowerCase())),
6958
6940
  getCoreRowModel: getCoreRowModel(),
6959
6941
  getFilteredRowModel: getFilteredRowModel(),
@@ -7221,7 +7203,7 @@ function renderNode(node, context, key, scope) {
7221
7203
  * 表单行为(草稿跨刷新、必填拦截、默认值)由本组件承接——
7222
7204
  * 节点树取代六类 surface 后,这里是 native 档唯一的渲染实现。
7223
7205
  */
7224
- function NativeSpecSurface({ surfaceId, spec, actions, registry, runId, draft, onAction, onDraftChange }) {
7206
+ function NativeSpecSurface({ surfaceId, spec, actions, registry, runId, draft, onAction, onDraftChange, shell = "card" }) {
7225
7207
  const context = {
7226
7208
  ...useSurfaceForm({
7227
7209
  surfaceId,
@@ -7242,7 +7224,7 @@ function NativeSpecSurface({ surfaceId, spec, actions, registry, runId, draft, o
7242
7224
  children: ["Invalid UI spec: ", validation.issues.map((issue) => `${issue.path}: ${issue.message}`).join("; ")]
7243
7225
  });
7244
7226
  return /* @__PURE__ */ jsx("div", {
7245
- className: "webskill-surface webskill-surface--spec",
7227
+ className: shell === "none" ? "webskill-surface--spec" : "webskill-surface webskill-surface--spec",
7246
7228
  "data-testid": "native-spec-surface",
7247
7229
  children: renderNode(spec, context, "root")
7248
7230
  });
@@ -7536,7 +7518,7 @@ function OpenUiSpecSurface({ spec, surfaceId, actions, onAction }) {
7536
7518
  const [unavailable, setUnavailable] = useState(false);
7537
7519
  useEffect(() => {
7538
7520
  let cancelled = false;
7539
- import("./openUiLibrary-Bdrji9qK-DzAxRlTY.js").then((loaded) => {
7521
+ import("./openUiLibrary-Bdrji9qK-D2LxmM-a.js").then((loaded) => {
7540
7522
  if (!cancelled) setModule(loaded);
7541
7523
  }).catch(() => {
7542
7524
  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-4pg-qp_I-Gq63X8Oa.js";
1
+ import { c as InteractionResponse, s as InteractionRequest, x as UiBridge, y as RenderResultRequest } from "./types-CcxRLdJG-DCXyw1US.js";
2
2
  import { PropType } from "vue";
3
3
  //#region ../ui-vue/dist/index.d.ts
4
4
  //#region src/bridgeState.d.ts