@webskill/sdk 0.9.0 → 0.11.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 (36) hide show
  1. package/dist/agent.d.ts +3 -2
  2. package/dist/agent.js +3 -1098
  3. package/dist/browser.d.ts +260 -11
  4. package/dist/browser.js +772 -52
  5. package/dist/{catalogComponents-DfxxfUvn-T7Ic8QFV.js → catalogComponents-BFoqpT1v-CjUBZ3bc.js} +1604 -426
  6. package/dist/{dist-CFmkV45C.js → dist-B-cOu08W.js} +874 -107
  7. package/dist/{dist-BQe1uglQ.js → dist-DTHZS2k1.js} +524 -30
  8. package/dist/dist-qnlI2Iup.js +1280 -0
  9. package/dist/{eventTypes-DbOpAECr-BjcjZVms.js → eventTypes-FllCrX-Z-DNDeHWoG.js} +9 -2
  10. package/dist/governance.d.ts +33 -6
  11. package/dist/governance.js +45 -7
  12. package/dist/{index-znZjobkr.d.ts → index-D3mONFHD.d.ts} +281 -11
  13. package/dist/{index-DXNTIa-6.d.ts → index-DACk2_XZ.d.ts} +114 -7
  14. package/dist/{index-lLcCpHE-.d.ts → index-DWbs58LF.d.ts} +234 -14
  15. package/dist/index.d.ts +4 -4
  16. package/dist/index.js +3 -3
  17. package/dist/mcp.d.ts +49 -6
  18. package/dist/mcp.js +146 -38
  19. package/dist/node.d.ts +3 -3
  20. package/dist/node.js +52 -2
  21. package/dist/{openUiLibrary-DURlAxjk-Do_yqg3u.js → openUiLibrary-D5u8oIvx-BLOAQCho.js} +3 -3
  22. package/dist/processSandboxEntry.js +6 -0
  23. package/dist/sandboxWorkerEntry.js +6 -0
  24. package/dist/{skillVersionStore-Bl-ElD45-dMJ8Ybhb.d.ts → skillVersionStore-D-qHk9ZE-BcmFLykd.d.ts} +13 -5
  25. package/dist/{testing-Csg5ljNm.js → testing-WPTyXQYt.js} +26 -3
  26. package/dist/testing.d.ts +1 -1
  27. package/dist/testing.js +1 -1
  28. package/dist/{types-B3n0cMZu-BDhheIhX.d.ts → types-C26b05fW-CdrRCRDb.d.ts} +55 -6
  29. package/dist/ui-react.d.ts +11 -2
  30. package/dist/ui-react.js +141 -42
  31. package/dist/ui-vue.d.ts +1 -1
  32. package/dist/ui-vue.js +2 -2
  33. package/dist/ui.d.ts +4 -4
  34. package/dist/ui.js +3 -3
  35. package/dist/{webskillLitCatalog-DwTwSBFt-BG7kL-Es.js → webskillLitCatalog-DME6PBkV-CmYNLlIT.js} +135 -16
  36. package/package.json +1 -1
@@ -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-C26b05fW-CdrRCRDb.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-C26b05fW-CdrRCRDb.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 };
@@ -2,7 +2,15 @@
2
2
  //#region src/errors.d.ts
3
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' | 'SKILL_MANIFEST_PROTECTED' | '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' |
4
4
  /** 历史里有未应答的工具调用,但当初为何中断已无从得知(分册 11 读取侧补齐) */
5
- 'RUN_INTERRUPTED' | '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';
5
+ 'RUN_INTERRUPTED' | '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' |
6
+ /** 0.11.0 分册 18:用户拒绝把数据交给文档投放面 */
7
+ 'DOCUMENT_SURFACE_DECLINED' |
8
+ /** 0.11.0 分册 18:viewer 未在期限内回报就绪(路由挂了 / 外壳脚本没跑起来) */
9
+ 'DOCUMENT_SURFACE_UNAVAILABLE' | '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_DOCUMENT_UNSUPPORTED' | 'MODEL_TOOLS_UNSUPPORTED' | 'ATTACHMENT_TOO_LARGE' | 'ATTACHMENT_TYPE_REJECTED' |
10
+ /** 脚本取了宿主未声明的数据源;拒绝发生在发出任何请求之前(0.11.0 分册 16) */
11
+ 'DATA_SOURCE_NOT_FOUND' |
12
+ /** 取数结果超预算。与 ATTACHMENT_TOO_LARGE 同口径:拒绝而不截断 */
13
+ 'DATA_SOURCE_TOO_LARGE';
6
14
  /**
7
15
  * 所有公开 API 抛出的结构化错误,code 供上层可编程处理
8
16
  * @stable
@@ -629,18 +637,34 @@ declare function escapeXml(text: string): string;
629
637
  declare function renderAvailableSkillsXml(catalog: SkillCatalog): string;
630
638
  declare const xmlRenderer: CatalogRenderer;
631
639
  //#endregion
632
- //#region ../runtime/dist/types-B3n0cMZu.d.ts
640
+ //#region ../runtime/dist/types-C26b05fW.d.ts
633
641
  //#region src/llm/streamTypes.d.ts
634
642
  /** 流式 LLM 事件(OpenAI SSE / Vercel fullStream 统一映射) */
635
643
  type LlmStreamEvent = {
636
644
  type: 'text-delta';
637
645
  delta: string;
646
+ } | {
647
+ /**
648
+ * 思考增量(Anthropic thinking_delta / OpenAI 兼容 reasoning_content /
649
+ * Vercel reasoning-delta 统一映射)。模型不产出思考时一个事件也没有——
650
+ * 消费方据「有没有收到」决定要不要渲染思考区,不做空壳入口。
651
+ */
652
+ type: 'thinking-delta';
653
+ delta: string;
638
654
  } | {
639
655
  type: 'tool-calls';
640
656
  toolCalls: LlmToolCall[];
641
- } | {
657
+ } |
658
+ /**
659
+ * 流收尾。`usage`(0.10.0 UI-UX5 #47):本次调用的 token 用量,
660
+ * 各家适配层在末段汇总后随 done 下发(Anthropic message_start/message_delta、
661
+ * OpenAI include_usage 末段 chunk、Vercel finish 的 totalUsage 统一映射);
662
+ * 上游不回报时缺省——消费方据「有没有」决定要不要展示,不显示假数据。
663
+ */
664
+ {
642
665
  type: 'done';
643
666
  content?: string;
667
+ usage?: LlmTokenUsage;
644
668
  };
645
669
  //#endregion
646
670
  //#region src/llm/types.d.ts
@@ -680,10 +704,35 @@ interface LlmToolCall {
680
704
  arguments: Record<string, unknown>;
681
705
  /** 流式拼接后的 arguments 不是合法 JSON 时的错误描述;设置时 arguments 不可信 */
682
706
  argumentsParseError?: string;
707
+ /**
708
+ * 供应商自己的不透明随车数据,原样回放给**同一家**供应商。
709
+ *
710
+ * Gemini 的 thinking 模型会随 `functionCall` 下发 `thoughtSignature`,
711
+ * 下一轮不带回去就直接 400——丢掉它的后果是多轮工具调用整条链跑不通(UI-UX8 D5)。
712
+ * 内容对引擎不透明,也不得跨供应商传递。
713
+ */
714
+ vendor?: Record<string, unknown>;
715
+ }
716
+ /**
717
+ * 一次模型调用的 token 用量(0.10.0 UI-UX5 #47)。
718
+ * 上游不回报 usage 时整个字段缺省——不填 0 冒充「已知为零」,
719
+ * 消费方据「有没有」决定要不要展示,不显示假数据。
720
+ * @stable
721
+ */
722
+ interface LlmTokenUsage {
723
+ inputTokens: number;
724
+ outputTokens: number;
683
725
  }
684
726
  interface LlmResponse {
685
727
  content?: LlmContentPart[];
686
728
  toolCalls?: LlmToolCall[];
729
+ /**
730
+ * 本轮模型产出的思考正文(Anthropic thinking blocks / reasoning_content 等)。
731
+ * 不进消息历史、不回喂模型;只用于运行细节展示与 trace。
732
+ */
733
+ thinking?: string;
734
+ /** 本轮 token 用量(上游回报才有;chrome-builtin 等无 usage 能力的客户端缺省) */
735
+ usage?: LlmTokenUsage;
687
736
  raw?: unknown;
688
737
  }
689
738
  interface LlmCompleteInput {
@@ -809,7 +858,7 @@ type InteractionRequest = {
809
858
  */
810
859
  type: 'authorize';
811
860
  id: string;
812
- capability: 'readReference' | 'writeArtifact' | 'confirm' | 'pageAction';
861
+ capability: 'readReference' | 'readAsset' | 'writeArtifact' | 'confirm' | 'fetchData' | 'pageAction' | 'readLinkedDocument';
813
862
  message: string;
814
863
  details?: unknown;
815
864
  });
@@ -975,7 +1024,7 @@ interface FormField {
975
1024
  name: string;
976
1025
  label: string;
977
1026
  /** `password` 的值不进 paramHistory、不进行为记录、不落会话(FR-23.7) */
978
- type: 'text' | 'number' | 'boolean' | 'select' | 'textarea' | 'file' | 'password';
1027
+ type: 'text' | 'number' | 'boolean' | 'select' | 'textarea' | 'file' | 'password' | 'date';
979
1028
  required?: boolean;
980
1029
  description?: string;
981
1030
  defaultValue?: unknown;
@@ -1017,4 +1066,4 @@ interface MemoryStore {
1017
1066
  transaction?<T>(scope: string, fn: (inner: MemoryStore) => Promise<T>): Promise<T>;
1018
1067
  }
1019
1068
  //#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 };
1069
+ 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-C26b05fW-CdrRCRDb.js";
2
+ import { W as SurfaceFormTexts, j as InteractionSpecLabels } from "./index-DACk2_XZ.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
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 { h as WebSkillError } from "./dist-Bev6i6Ip.js";
3
- import { Ot as validateUiSpecEvent, kt as validateUiSpecNode } from "./dist-CFmkV45C.js";
4
- import { F as normalizeColumnWidths, M as interactionToUiSpec, R as renderMiniChart, U as toJsonRenderSpec, W as toOpenUiSpecLang, Z as DEFAULT_SURFACE_FORM_TEXTS, ct as renderMiniMarkdown, dt as shapeInteractionValue, ft as uiCatalog, it as chartSpecFromProps, ot as interactionToFormModel, w as collectValues, y as applySuggestion } from "./dist-BQe1uglQ.js";
5
- import { C as DropdownMenuContent, D as Separator, E as Markdown, S as DropdownMenuCheckboxItem, T as Input, _ as useSurfaceFormTexts, a as SpecProgress, b as DataTable, c as SurfaceButton, d as SurfaceFormButtons, f as SurfaceFormTextsProvider, g as useSurfaceForm, h as useCatalogSurfaceForm, i as SpecGrid, l as SurfaceField, m as str, n as CatalogSurfaceProvider, o as SpecTabs, p as catalogComponentImpls, r as EChart, s as SpecTimeline, u as SurfaceFieldArray, v as Badge, w as DropdownMenuTrigger, x as DropdownMenu, y as Button } from "./catalogComponents-DfxxfUvn-T7Ic8QFV.js";
3
+ import { Bt as validateUiSpecNode, zt as validateUiSpecEvent } from "./dist-B-cOu08W.js";
4
+ import { C as applySuggestion, K as resolveColumnWidths, L as interactionToUiSpec, O as collectValues, St as uiCatalog, V as normalizeColumnWidths, W as renderMiniChart, X as toOpenUiSpecLang, Y as toJsonRenderSpec, gt as interactionToFormModel, mt as chartSpecFromProps, ot as DEFAULT_SURFACE_FORM_TEXTS, vt as renderMiniMarkdown, xt as shapeInteractionValue } from "./dist-DTHZS2k1.js";
5
+ import { A as Badge, C as catalogComponentImpls, D as useCatalogSurfaceForm, E as surfaceThemeOf, F as DropdownMenuContent, I as DropdownMenuTrigger, L as Input, M as DataTable, N as DropdownMenu, O as useSurfaceForm, P as DropdownMenuCheckboxItem, R as Markdown, S as cardLayoutProps, T as str, _ as SurfaceButton, a as SpecCallout, b as SurfaceFormButtons, c as SpecGrid, d as SpecKeyValue, f as SpecProgress, g as SpecTimeline, h as SpecTabs, i as SpecAccordion, j as Button, k as useSurfaceFormTexts, l as SpecIcon, m as SpecSplit, n as CatalogSurfaceProvider, o as SpecCarousel, p as SpecQuote, r as EChart, s as SpecGauge, u as SpecImage, v as SurfaceField, w as paletteClass, x as SurfaceFormTextsProvider, y as SurfaceFieldArray, z as Separator } from "./catalogComponents-BFoqpT1v-CjUBZ3bc.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";
@@ -6469,6 +6469,54 @@ var UiSurfaceStore = class {
6469
6469
  this.#emit();
6470
6470
  }
6471
6471
  }
6472
+ /**
6473
+ * 表单 surface 提交成功后,把提交值回写为 Field 的 `defaultValue`(UI-UX5 #15):
6474
+ * run 结束后界面用持久化快照重放,初值只认 defaultValue——不回写,
6475
+ * 只读回看就看不到用户当时选/填了什么。
6476
+ * 只写标量;字段名全树唯一才写(多表单同名字段无法判定归属,宁可不写也不写错)。
6477
+ * 0.10.0 复核注记:multi-select 的数组值不会回写,属已知限制——重放里
6478
+ * 多选项字段仍显示初值;标量优先的取舍保留。
6479
+ */
6480
+ applySubmittedValues(surfaceId, values) {
6481
+ const entry = this.#entries.get(this.#aliases.get(surfaceId) ?? surfaceId);
6482
+ if (!entry) return;
6483
+ const scalars = new Map(Object.entries(values).filter(([, value]) => [
6484
+ "string",
6485
+ "number",
6486
+ "boolean"
6487
+ ].includes(typeof value)));
6488
+ if (scalars.size === 0) return;
6489
+ const nameCount = /* @__PURE__ */ new Map();
6490
+ const count = (node) => {
6491
+ const name = node.component === "Field" ? node.props?.["name"] : void 0;
6492
+ if (typeof name === "string") nameCount.set(name, (nameCount.get(name) ?? 0) + 1);
6493
+ for (const child of node.children ?? []) count(child);
6494
+ };
6495
+ count(entry.node);
6496
+ const next = structuredClone(entry.node);
6497
+ let changed = false;
6498
+ const write = (node) => {
6499
+ if (node.component === "Field" && node.props) {
6500
+ const name = node.props["name"];
6501
+ if (typeof name === "string" && nameCount.get(name) === 1 && scalars.has(name)) {
6502
+ const value = scalars.get(name);
6503
+ if (node.props["defaultValue"] !== value) {
6504
+ node.props["defaultValue"] = value;
6505
+ changed = true;
6506
+ }
6507
+ }
6508
+ }
6509
+ for (const child of node.children ?? []) write(child);
6510
+ };
6511
+ write(next);
6512
+ if (!changed) return;
6513
+ this.#entries.set(entry.id, {
6514
+ ...entry,
6515
+ node: validateUiSpecNode(next)
6516
+ });
6517
+ this.#snapshots = [...this.#entries.values()];
6518
+ this.#emit();
6519
+ }
6472
6520
  /** 跨 run 的相同界面是合法重复(用户又问了一次),所以无 runId 时不合并 */
6473
6521
  #fingerprint(event) {
6474
6522
  if (event.runId === void 0) return void 0;
@@ -6622,6 +6670,7 @@ var ReactBridgeState = class {
6622
6670
  const { [response.surfaceId]: _discarded, ...remaining } = drafts;
6623
6671
  this.#surfaceDrafts.set(response.runId, remaining);
6624
6672
  }
6673
+ if (!response.cancelled && response.value !== void 0) this.surfaceStore.applySubmittedValues(response.surfaceId, response.value);
6625
6674
  this.#emit();
6626
6675
  resolver(response);
6627
6676
  return true;
@@ -6761,7 +6810,7 @@ function Control({ control, invalid }) {
6761
6810
  label,
6762
6811
  description,
6763
6812
  /* @__PURE__ */ jsx("input", {
6764
- type: control.control === "number" ? "number" : "text",
6813
+ type: control.control === "number" ? "number" : control.control === "date" ? "date" : "text",
6765
6814
  id: controlId,
6766
6815
  "aria-invalid": invalid || void 0,
6767
6816
  className: "webskill-form__input",
@@ -6955,6 +7004,10 @@ function SurfaceSimplifiedNote({ degradations }) {
6955
7004
  function SurfaceDegradationNote({ degradations }) {
6956
7005
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(SurfaceRejectionAlert, { degradations }), /* @__PURE__ */ jsx(SurfaceSimplifiedNote, { degradations })] });
6957
7006
  }
7007
+ /** 容器宽度未测出(jsdom / 首帧)时的最小列宽兜底:与 SPEC_TABLE_MIN_COLUMN_WIDTH.desktop(8rem @16px)一致 */
7008
+ const FALLBACK_MIN_COLUMN_PX = 128;
7009
+ /** ScrollArea 容器的左右边框合计宽度(视觉契约,测量可用宽时扣除) */
7010
+ const SCROLL_AREA_BORDER_RESERVE = 2;
6958
7011
  /**
6959
7012
  * catalog `Table` 节点的渲染实现:排序 / 筛选 / 分页 / 列显隐 / 虚拟滚动。
6960
7013
  * 这些是宿主侧的呈现能力,不进 catalog props——模型只声明 columns 与 rows。
@@ -6965,13 +7018,30 @@ function SpecTable({ columns, rows, label, columnWidths, onDegraded }) {
6965
7018
  const [globalFilter, setGlobalFilter] = useState("");
6966
7019
  const [columnVisibility, setColumnVisibility] = useState({});
6967
7020
  const scrollRef = useRef(null);
7021
+ const frameRef = useRef(null);
7022
+ /** 实测的容器宽度与最小列宽(px);未测量(jsdom / 首帧)时退回百分比 colgroup */
7023
+ const [measured, setMeasured] = useState(void 0);
6968
7024
  const normalized = normalizeColumnWidths(columnWidths, columns.length);
6969
- const weightTotal = normalized.weights.reduce((sum, weight) => sum + weight, 0);
6970
- const widthPercents = normalized.weights.map((weight) => weightTotal > 0 ? weight / weightTotal * 100 : 0);
6971
7025
  const rejected = normalized.rejected;
6972
7026
  useEffect(() => {
6973
7027
  if (rejected !== void 0) onDegraded?.(rejected);
6974
7028
  }, [rejected, onDegraded]);
7029
+ useEffect(() => {
7030
+ const frame = frameRef.current;
7031
+ if (!frame || typeof ResizeObserver === "undefined") return;
7032
+ const measure = () => {
7033
+ const th = frame.querySelector("th");
7034
+ const probe = th === null ? NaN : Number.parseFloat(getComputedStyle(th).minWidth);
7035
+ setMeasured({
7036
+ available: Math.max(0, frame.clientWidth - SCROLL_AREA_BORDER_RESERVE),
7037
+ minCol: Number.isFinite(probe) && probe > 0 ? probe : FALLBACK_MIN_COLUMN_PX
7038
+ });
7039
+ };
7040
+ measure();
7041
+ const observer = new ResizeObserver(measure);
7042
+ observer.observe(frame);
7043
+ return () => observer.disconnect();
7044
+ }, []);
6975
7045
  const table = useReactTable({
6976
7046
  data: rows,
6977
7047
  columns: columns.map((header, index) => ({
@@ -6995,6 +7065,10 @@ function SpecTable({ columns, rows, label, columnWidths, onDegraded }) {
6995
7065
  initialState: { pagination: { pageSize: 50 } }
6996
7066
  });
6997
7067
  const modelRows = table.getRowModel().rows;
7068
+ const visibleIndexes = table.getVisibleLeafColumns().map((column) => Number(column.id.replace("column-", "")));
7069
+ const visibleWeights = visibleIndexes.map((index) => normalized.weights[index] ?? 1);
7070
+ const visibleWeightTotal = visibleWeights.reduce((sum, weight) => sum + weight, 0);
7071
+ const pixelWidths = measured ? resolveColumnWidths(visibleWeights, measured.available, measured.minCol) : void 0;
6998
7072
  const virtualRows = useVirtualizer({
6999
7073
  count: modelRows.length,
7000
7074
  getScrollElement: () => scrollRef.current,
@@ -7031,37 +7105,44 @@ function SpecTable({ columns, rows, label, columnWidths, onDegraded }) {
7031
7105
  }, column.id))
7032
7106
  })] })]
7033
7107
  }),
7034
- /* @__PURE__ */ jsxs(DataTable, {
7035
- "aria-label": label,
7036
- containerClassName: "webskill-surface__table-scroll",
7037
- children: [
7038
- /* @__PURE__ */ jsx("colgroup", { children: widthPercents.map((percent, index) => /* @__PURE__ */ jsx("col", { style: { width: `${percent}%` } }, index)) }),
7039
- /* @__PURE__ */ jsx("thead", {
7040
- className: "webskill-surface__table-header",
7041
- children: /* @__PURE__ */ jsx("tr", { children: table.getFlatHeaders().map((header) => /* @__PURE__ */ jsx("th", {
7042
- scope: "col",
7043
- ...header.column.id === "selection" ? { "data-webskill-host-control": "" } : {},
7044
- "aria-sort": header.column.getIsSorted() === "asc" ? "ascending" : header.column.getIsSorted() === "desc" ? "descending" : "none",
7045
- children: header.column.getCanSort() ? /* @__PURE__ */ jsx("button", {
7046
- type: "button",
7047
- "data-webskill-host-control": "",
7048
- onClick: header.column.getToggleSortingHandler(),
7049
- children: flexRender(header.column.columnDef.header, header.getContext())
7050
- }) : flexRender(header.column.columnDef.header, header.getContext())
7051
- }, header.id)) })
7052
- }),
7053
- /* @__PURE__ */ jsx("tbody", {
7054
- ref: scrollRef,
7055
- className: "webskill-surface__table-body",
7056
- children: renderedRows.map((virtualRow) => {
7057
- const row = modelRows[virtualRow.index];
7058
- return /* @__PURE__ */ jsx("tr", { children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx("td", {
7059
- ...cell.column.id === "selection" ? { "data-webskill-host-control": "" } : {},
7060
- children: flexRender(cell.column.columnDef.cell, cell.getContext())
7061
- }, cell.id)) }, row.id);
7108
+ /* @__PURE__ */ jsx("div", {
7109
+ ref: frameRef,
7110
+ children: /* @__PURE__ */ jsxs(DataTable, {
7111
+ "aria-label": label,
7112
+ containerClassName: "webskill-surface__table-scroll",
7113
+ ...pixelWidths ? { style: {
7114
+ tableLayout: "fixed",
7115
+ width: `${pixelWidths.reduce((sum, width) => sum + width, 0)}px`
7116
+ } } : {},
7117
+ children: [
7118
+ /* @__PURE__ */ jsx("colgroup", { children: visibleIndexes.map((original, position) => /* @__PURE__ */ jsx("col", { style: { width: pixelWidths ? `${pixelWidths[position]}px` : `${visibleWeightTotal > 0 ? (visibleWeights[position] ?? 0) / visibleWeightTotal * 100 : 0}%` } }, original)) }),
7119
+ /* @__PURE__ */ jsx("thead", {
7120
+ className: "webskill-surface__table-header",
7121
+ children: /* @__PURE__ */ jsx("tr", { children: table.getFlatHeaders().map((header) => /* @__PURE__ */ jsx("th", {
7122
+ scope: "col",
7123
+ ...header.column.id === "selection" ? { "data-webskill-host-control": "" } : {},
7124
+ "aria-sort": header.column.getIsSorted() === "asc" ? "ascending" : header.column.getIsSorted() === "desc" ? "descending" : "none",
7125
+ children: header.column.getCanSort() ? /* @__PURE__ */ jsx("button", {
7126
+ type: "button",
7127
+ "data-webskill-host-control": "",
7128
+ onClick: header.column.getToggleSortingHandler(),
7129
+ children: flexRender(header.column.columnDef.header, header.getContext())
7130
+ }) : flexRender(header.column.columnDef.header, header.getContext())
7131
+ }, header.id)) })
7132
+ }),
7133
+ /* @__PURE__ */ jsx("tbody", {
7134
+ ref: scrollRef,
7135
+ className: "webskill-surface__table-body",
7136
+ children: renderedRows.map((virtualRow) => {
7137
+ const row = modelRows[virtualRow.index];
7138
+ return /* @__PURE__ */ jsx("tr", { children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx("td", {
7139
+ ...cell.column.id === "selection" ? { "data-webskill-host-control": "" } : {},
7140
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
7141
+ }, cell.id)) }, row.id);
7142
+ })
7062
7143
  })
7063
- })
7064
- ]
7144
+ ]
7145
+ })
7065
7146
  }),
7066
7147
  /* @__PURE__ */ jsxs("div", {
7067
7148
  className: "webskill-surface__table-pagination",
@@ -7106,7 +7187,7 @@ function renderNode(node, context, key, scope) {
7106
7187
  children
7107
7188
  }, key);
7108
7189
  case "Card": return /* @__PURE__ */ jsxs("section", {
7109
- className: "flex flex-col gap-2 rounded-lg border border-border bg-card p-3",
7190
+ className: `webskill-spec-card flex flex-col gap-2 rounded-lg border border-border bg-card ${cardLayoutProps(props).className} ${paletteClass(props)}`,
7110
7191
  children: [
7111
7192
  /* @__PURE__ */ jsx("h3", {
7112
7193
  className: "text-sm font-semibold text-ink",
@@ -7121,7 +7202,7 @@ function renderNode(node, context, key, scope) {
7121
7202
  }, key);
7122
7203
  case "Separator": return /* @__PURE__ */ jsx(Separator, {}, key);
7123
7204
  case "Heading": return /* @__PURE__ */ jsx(props["level"] === 2 ? "h2" : props["level"] === 4 ? "h4" : "h3", {
7124
- className: "text-sm font-semibold text-ink",
7205
+ className: `text-sm font-semibold text-ink ${paletteClass(props)}`,
7125
7206
  children: str(props, "text")
7126
7207
  }, key);
7127
7208
  case "Text": return /* @__PURE__ */ jsx("p", {
@@ -7131,7 +7212,7 @@ function renderNode(node, context, key, scope) {
7131
7212
  case "Markdown": return /* @__PURE__ */ jsx(Markdown, { children: str(props, "text") }, key);
7132
7213
  case "Badge": return /* @__PURE__ */ jsx(Badge, {
7133
7214
  tone: "neutral",
7134
- className: TONE_CLASS[str(props, "tone", "neutral")],
7215
+ className: `${TONE_CLASS[str(props, "tone", "neutral")]} ${paletteClass(props)}`,
7135
7216
  children: str(props, "text")
7136
7217
  }, key);
7137
7218
  case "Metric": return /* @__PURE__ */ jsxs("div", {
@@ -7171,7 +7252,19 @@ function renderNode(node, context, key, scope) {
7171
7252
  props,
7172
7253
  children
7173
7254
  }, key);
7255
+ case "Split": return /* @__PURE__ */ jsx(SpecSplit, {
7256
+ props,
7257
+ children
7258
+ }, key);
7174
7259
  case "Timeline": return /* @__PURE__ */ jsx(SpecTimeline, { props }, key);
7260
+ case "Icon": return /* @__PURE__ */ jsx(SpecIcon, { props }, key);
7261
+ case "Image": return /* @__PURE__ */ jsx(SpecImage, { props }, key);
7262
+ case "Quote": return /* @__PURE__ */ jsx(SpecQuote, { props }, key);
7263
+ case "Callout": return /* @__PURE__ */ jsx(SpecCallout, { props }, key);
7264
+ case "KeyValue": return /* @__PURE__ */ jsx(SpecKeyValue, { props }, key);
7265
+ case "Gauge": return /* @__PURE__ */ jsx(SpecGauge, { props }, key);
7266
+ case "Accordion": return /* @__PURE__ */ jsx(SpecAccordion, { props }, key);
7267
+ case "Carousel": return /* @__PURE__ */ jsx(SpecCarousel, { props }, key);
7175
7268
  case "Progress": return /* @__PURE__ */ jsx(SpecProgress, { props }, key);
7176
7269
  case "FileLink": return /* @__PURE__ */ jsxs("div", {
7177
7270
  className: "flex items-center gap-2 text-sm",
@@ -7198,7 +7291,10 @@ function renderNode(node, context, key, scope) {
7198
7291
  className: "text-sm font-semibold text-ink",
7199
7292
  children: str(props, "title")
7200
7293
  }) : null,
7201
- children,
7294
+ /* @__PURE__ */ jsx("div", {
7295
+ className: "webskill-spec-form__fields",
7296
+ children
7297
+ }),
7202
7298
  /* @__PURE__ */ jsx(SurfaceFormButtons, {
7203
7299
  form: context,
7204
7300
  props,
@@ -7287,9 +7383,12 @@ function NativeSpecSurface({ surfaceId, spec, actions, registry, runId, draft, o
7287
7383
  };
7288
7384
  const texts = useSurfaceFormTexts();
7289
7385
  const { node, degradations } = sanitized;
7386
+ const framed = shell !== "none" && node?.component !== "Table";
7387
+ const theme = surfaceThemeOf(node);
7290
7388
  return /* @__PURE__ */ jsxs("div", {
7291
- className: shell === "none" ? "webskill-surface--spec" : "webskill-surface webskill-surface--spec",
7389
+ className: framed ? "webskill-surface webskill-surface--spec" : "webskill-surface--spec",
7292
7390
  "data-testid": "native-spec-surface",
7391
+ ...theme ? { "data-webskill-theme": theme } : {},
7293
7392
  children: [
7294
7393
  node ? renderNode(node, context, "root") : null,
7295
7394
  form.readOnly && actions.length > 0 ? /* @__PURE__ */ jsx("p", {
@@ -7590,7 +7689,7 @@ function OpenUiSpecSurface({ spec, surfaceId, actions, onAction }) {
7590
7689
  const [unavailable, setUnavailable] = useState(false);
7591
7690
  useEffect(() => {
7592
7691
  let cancelled = false;
7593
- import("./openUiLibrary-DURlAxjk-Do_yqg3u.js").then((loaded) => {
7692
+ import("./openUiLibrary-D5u8oIvx-BLOAQCho.js").then((loaded) => {
7594
7693
  if (!cancelled) setModule(loaded);
7595
7694
  }).catch(() => {
7596
7695
  if (!cancelled) setUnavailable(true);
package/dist/ui-vue.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { c as InteractionResponse, s as InteractionRequest, x as UiBridge, y as RenderResultRequest } from "./types-B3n0cMZu-BDhheIhX.js";
1
+ import { S as UiBridge, b as RenderResultRequest, c as InteractionResponse, s as InteractionRequest } from "./types-C26b05fW-CdrRCRDb.js";
2
2
  import { PropType } from "vue";
3
3
  //#region ../ui-vue/dist/index.d.ts
4
4
  //#region src/bridgeState.d.ts
package/dist/ui-vue.js CHANGED
@@ -1,4 +1,4 @@
1
- import { R as renderMiniChart, Z as DEFAULT_SURFACE_FORM_TEXTS, ct as renderMiniMarkdown, dt as shapeInteractionValue, ot as interactionToFormModel, w as collectValues, y as applySuggestion } from "./dist-BQe1uglQ.js";
1
+ import { C as applySuggestion, O as collectValues, W as renderMiniChart, gt as interactionToFormModel, ot as DEFAULT_SURFACE_FORM_TEXTS, vt as renderMiniMarkdown, xt as shapeInteractionValue } from "./dist-DTHZS2k1.js";
2
2
  import { defineComponent, h, reactive, ref } from "vue";
3
3
 
4
4
  //#region ../ui-vue/dist/index.js
@@ -104,7 +104,7 @@ function renderControl(control, invalid) {
104
104
  });
105
105
  break;
106
106
  default: input = h("input", {
107
- type: control.control === "number" ? "number" : "text",
107
+ type: control.control === "number" ? "number" : control.control === "date" ? "date" : "text",
108
108
  id: controlId,
109
109
  "aria-invalid": invalid || void 0,
110
110
  class: "webskill-form__input",