@webskill/sdk 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/agent.d.ts +1 -1
  2. package/dist/agent.js +1 -1
  3. package/dist/browser.d.ts +151 -4
  4. package/dist/browser.js +250 -25
  5. package/dist/{catalogComponents-Dr5dFMAb-DKH_7VPI.js → catalogComponents-DfxxfUvn-D55Gbb2l.js} +3435 -437
  6. package/dist/{dist-8oQRa8Xz.js → dist-59XlqDuv.js} +93 -6
  7. package/dist/{dist-DnYG2-eY.js → dist-CJqQsIm9.js} +498 -118
  8. package/dist/{dist-D0qW6e40.js → dist-DmI5SBBF.js} +192 -17
  9. package/dist/{eventTypes-DjIQpt8Y-Bj3vghj4.js → eventTypes-g1BXL6x5-CibcOftR.js} +7 -2
  10. package/dist/governance.d.ts +16 -3
  11. package/dist/governance.js +24 -5
  12. package/dist/{index-DkbABR43.d.ts → index-K-eewlGL.d.ts} +138 -75
  13. package/dist/{index-BwsK9lGk.d.ts → index-P9J2LTfU.d.ts} +163 -6
  14. package/dist/{index-Ba3xFtfz.d.ts → index-fLskQfAS.d.ts} +2 -2
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.js +4 -4
  17. package/dist/mcp.d.ts +8 -2
  18. package/dist/mcp.js +12 -2
  19. package/dist/{memoryArtifactStore-52Zn9npI-BMPYwvoy.js → memoryArtifactStore-52Zn9npI-upv5OWYf.js} +1 -1
  20. package/dist/node.d.ts +3 -3
  21. package/dist/node.js +3 -3
  22. package/dist/{openUiLibrary-Bdrji9qK-D2LxmM-a.js → openUiLibrary-DURlAxjk-CU6AzfSW.js} +3 -3
  23. package/dist/{skillVersionStore-Bl-ElD45-CWPvGvoq.d.ts → skillVersionStore-Bl-ElD45-gRfSaAby.d.ts} +1 -1
  24. package/dist/{testing-CYTFqkDm.js → testing-BCUO5gZR.js} +2 -2
  25. package/dist/testing.d.ts +1 -1
  26. package/dist/testing.js +2 -2
  27. package/dist/{types-CcxRLdJG-DCXyw1US.d.ts → types-B3n0cMZu-BdcqQ35O.d.ts} +46 -6
  28. package/dist/ui-react.d.ts +13 -6
  29. package/dist/ui-react.js +153 -84
  30. package/dist/ui-vue.d.ts +1 -1
  31. package/dist/ui-vue.js +2 -2
  32. package/dist/ui.d.ts +4 -4
  33. package/dist/ui.js +3 -3
  34. package/dist/{webskillLitCatalog-_mugzRHx-B_54vxum.js → webskillLitCatalog-DwTwSBFt-DiXXpNZA.js} +22 -3
  35. package/package.json +2 -2
package/dist/agent.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as TodoListener, A as PagePerceptionReader, B as SKILL_GENERATION_SYSTEM_PROMPT, C as PageActionRequest, D as PageAuditSink, E as PageActionUi, F as PerceptionAuditSink, G as SkillGenerator, H as SkillGenerationOutcome, I as PerceptionCaptureOptions, J as SubAgentRunner, K as SkillGeneratorOptions, L as PerceptionRecord, M as ParentBudget, N as PerceivedImage, O as PagePerceptionPolicy, P as PerceivedNode, Q as TodoList, R as PerceptionResult, S as PageActionRecord, T as PageActionToolSourceOptions, U as SkillGenerationPolicy, V as SkillCandidateSink, W as SkillGenerationToolSourceOptions, X as TodoEvent, Y as TODO_SYSTEM_PROMPT, Z as TodoItem, _ as PageActionExecutor, a as DelegationOrchestratorOptions, at as createPagePerceptionToolSource, b as PageActionPolicy, c as DelegationToolSourceOptions, ct as withDelegationOrigin, d as ImageCaptureBudget, et as TodoStatus, f as MANAGE_TODO_TOOL, g as PERCEPTION_SYSTEM_PROMPT, h as PERCEIVE_PAGE_TOOL, i as DelegationOrchestrator, it as createPageActionToolSource, j as PagePerceptionToolSourceOptions, k as PagePerceptionPolicyOptions, l as GENERATE_SKILL_TOOL, m as PAGE_ACTION_TOOL, n as DELEGATION_SYSTEM_PROMPT, nt as TodoToolSourceOptions, o as DelegationRequest, ot as createSkillGenerationToolSource, p as PAGE_ACTION_SYSTEM_PROMPT, q as SubAgentRunInput, r as DelegationBudget, rt as createDelegationToolSource, s as DelegationResult, st as createTodoToolSource, t as DELEGATE_TASK_TOOL, tt as TodoStore, u as GeneratedSkillDraft, v as PageActionKind, w as PageActionScope, x as PageActionPolicyOptions, y as PageActionOutcome, z as PerceptionScope } from "./index-Ba3xFtfz.js";
1
+ import { $ as TodoListener, A as PagePerceptionReader, B as SKILL_GENERATION_SYSTEM_PROMPT, C as PageActionRequest, D as PageAuditSink, E as PageActionUi, F as PerceptionAuditSink, G as SkillGenerator, H as SkillGenerationOutcome, I as PerceptionCaptureOptions, J as SubAgentRunner, K as SkillGeneratorOptions, L as PerceptionRecord, M as ParentBudget, N as PerceivedImage, O as PagePerceptionPolicy, P as PerceivedNode, Q as TodoList, R as PerceptionResult, S as PageActionRecord, T as PageActionToolSourceOptions, U as SkillGenerationPolicy, V as SkillCandidateSink, W as SkillGenerationToolSourceOptions, X as TodoEvent, Y as TODO_SYSTEM_PROMPT, Z as TodoItem, _ as PageActionExecutor, a as DelegationOrchestratorOptions, at as createPagePerceptionToolSource, b as PageActionPolicy, c as DelegationToolSourceOptions, ct as withDelegationOrigin, d as ImageCaptureBudget, et as TodoStatus, f as MANAGE_TODO_TOOL, g as PERCEPTION_SYSTEM_PROMPT, h as PERCEIVE_PAGE_TOOL, i as DelegationOrchestrator, it as createPageActionToolSource, j as PagePerceptionToolSourceOptions, k as PagePerceptionPolicyOptions, l as GENERATE_SKILL_TOOL, m as PAGE_ACTION_TOOL, n as DELEGATION_SYSTEM_PROMPT, nt as TodoToolSourceOptions, o as DelegationRequest, ot as createSkillGenerationToolSource, p as PAGE_ACTION_SYSTEM_PROMPT, q as SubAgentRunInput, r as DelegationBudget, rt as createDelegationToolSource, s as DelegationResult, st as createTodoToolSource, t as DELEGATE_TASK_TOOL, tt as TodoStore, u as GeneratedSkillDraft, v as PageActionKind, w as PageActionScope, x as PageActionPolicyOptions, y as PageActionOutcome, z as PerceptionScope } from "./index-fLskQfAS.js";
2
2
  export { DELEGATE_TASK_TOOL, DELEGATION_SYSTEM_PROMPT, type DelegationBudget, DelegationOrchestrator, type DelegationOrchestratorOptions, type DelegationRequest, type DelegationResult, type DelegationToolSourceOptions, GENERATE_SKILL_TOOL, type GeneratedSkillDraft, type ImageCaptureBudget, MANAGE_TODO_TOOL, PAGE_ACTION_SYSTEM_PROMPT, PAGE_ACTION_TOOL, PERCEIVE_PAGE_TOOL, PERCEPTION_SYSTEM_PROMPT, type PageActionExecutor, type PageActionKind, type PageActionOutcome, PageActionPolicy, type PageActionPolicyOptions, type PageActionRecord, type PageActionRequest, type PageActionScope, type PageActionToolSourceOptions, type PageActionUi, type PageAuditSink, PagePerceptionPolicy, type PagePerceptionPolicyOptions, type PagePerceptionReader, type PagePerceptionToolSourceOptions, type ParentBudget, type PerceivedImage, type PerceivedNode, type PerceptionAuditSink, type PerceptionCaptureOptions, type PerceptionRecord, type PerceptionResult, type PerceptionScope, SKILL_GENERATION_SYSTEM_PROMPT, type SkillCandidateSink, type SkillGenerationOutcome, type SkillGenerationPolicy, type SkillGenerationToolSourceOptions, SkillGenerator, type SkillGeneratorOptions, type SubAgentRunInput, type SubAgentRunner, TODO_SYSTEM_PROMPT, type TodoEvent, type TodoItem, type TodoList, type TodoListener, type TodoStatus, TodoStore, type TodoToolSourceOptions, createDelegationToolSource, createPageActionToolSource, createPagePerceptionToolSource, createSkillGenerationToolSource, createTodoToolSource, withDelegationOrigin };
package/dist/agent.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as parseSkillMarkdown, O as messageOf, T as isValidSkillName, m as WebSkillError } from "./dist-8oQRa8Xz.js";
1
+ import { A as messageOf, D as isValidSkillName, M as parseSkillMarkdown, m as WebSkillError } from "./dist-59XlqDuv.js";
2
2
 
3
3
  //#region ../agent/dist/index.js
4
4
  const STATUSES = [
package/dist/browser.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { A as ArchiveLimits, F as FileStat, I as FileSystemProvider, _ as MemoryStore, _t as UnsignedPolicy, bt as WebSkillError, c as InteractionResponse, ht as TrustedKeyStore, l as LlmClient, m as LlmStreamEvent, o as InteractionPolicy, p as LlmResponse, pt as SkillsLockfile, rt as SkillInstallSource, s as InteractionRequest, st as SkillManifest, u as LlmCompleteInput, x as UiBridge, y as RenderResultRequest, yt as VerifyResult } from "./types-CcxRLdJG-DCXyw1US.js";
2
- import { Et as ScriptExecutor, Fn as parseBridgeRequest, Kt as ToolResult, O as ExternalSkillProvider, Tt as ScriptExecutionContext, Wt as ToolDefinition, Y as NetworkPolicy, _ as BridgeCapabilities, b as BridgeResponse, cn as WebSkillApi, f as ApprovalScope, k as ExternalToolSource, pn as bridgeError, y as BridgeRequest } from "./index-DkbABR43.js";
3
- import { A as PagePerceptionReader, C as PageActionRequest, I as PerceptionCaptureOptions, P as PerceivedNode, R as PerceptionResult, _ as PageActionExecutor, w as PageActionScope, y as PageActionOutcome, z as PerceptionScope } from "./index-Ba3xFtfz.js";
1
+ import { A as ArchiveLimits, F as FileStat, I as FileSystemProvider, St as WebSkillError, _ as MemoryStore, _t as TrustedKeyStore, at as SkillInstallSource, c as InteractionResponse, ht as SkillsLockfile, l as LlmClient, lt as SkillManifest, m as LlmStreamEvent, o as InteractionPolicy, p as LlmResponse, s as InteractionRequest, u as LlmCompleteInput, x as UiBridge, xt as VerifyResult, y as RenderResultRequest, yt as UnsignedPolicy } from "./types-B3n0cMZu-BdcqQ35O.js";
2
+ import { Et as ScriptExecutor, O as ExternalSkillProvider, Tt as ScriptExecutionContext, Vn as parseBridgeRequest, Y as NetworkPolicy, Yt as ToolResult, _ as BridgeCapabilities, _n as bridgeError, b as BridgeResponse, f as ApprovalScope, fn as WebSkillApi, k as ExternalToolSource, qt as ToolDefinition, y as BridgeRequest } from "./index-K-eewlGL.js";
3
+ import { A as PagePerceptionReader, C as PageActionRequest, I as PerceptionCaptureOptions, O as PagePerceptionPolicy, P as PerceivedNode, R as PerceptionResult, _ as PageActionExecutor, w as PageActionScope, y as PageActionOutcome, z as PerceptionScope } from "./index-fLskQfAS.js";
4
4
  //#region ../browser/dist/index.d.ts
5
5
  //#region src/fs/featureDetection.d.ts
6
6
  /** 检测当前环境是否可用 OPFS(navigator.storage.getDirectory) */
@@ -86,6 +86,11 @@ declare class BrowserSkillManager {
86
86
  constructor(deps: {
87
87
  fs: FileSystemProvider;
88
88
  managedRoot: string;
89
+ /**
90
+ * 宿主的只读技能根(如 `/skills`)。Library 列的是 Catalog 全集,
91
+ * 不告诉管理器这些根,导出本地技能会报「is not installed」(FR-19.5)。
92
+ */
93
+ skillRoots?: readonly string[];
89
94
  fetchImpl?: typeof fetch;
90
95
  /** 归档体积三重上限(缺省 DEFAULT_ARCHIVE_LIMITS) */
91
96
  archiveLimits?: ArchiveLimits;
@@ -111,6 +116,8 @@ declare class BrowserSkillManager {
111
116
  });
112
117
  install(source: SkillInstallSource, options?: {
113
118
  expectedSha256?: string;
119
+ /** 缺省接受替换(升级/重装靠它);`reject` 供「新建」这类不该覆盖的调用方声明意图 */
120
+ replace?: 'allow' | 'reject';
114
121
  }): Promise<SkillManifest>;
115
122
  /**
116
123
  * 浏览器导出(单技能与包集同构:始终产出含 webskill.skill-pack.json 的 zip 字节,
@@ -120,6 +127,12 @@ declare class BrowserSkillManager {
120
127
  uninstall(name: string): Promise<void>;
121
128
  verifyIntegrity(name: string): Promise<VerifyResult>;
122
129
  listInstalled(): Promise<SkillsLockfile>;
130
+ /**
131
+ * 库里已有的技能名:managed 目录 + 宿主声明的只读根。读失败按「库为空」处理,不阻断安装。
132
+ * 与 `listInstalled()` 的区别是**含本地技能**(后者只看安装账本)。
133
+ * @experimental
134
+ */
135
+ listSkillNames(): Promise<string[]>;
123
136
  }
124
137
  //#endregion
125
138
  //#region src/skillManagement/zipExtract.d.ts
@@ -643,4 +656,138 @@ declare function openMemoryEncryptionKey(name?: string): Promise<CryptoKey>;
643
656
  /** 删除本地数据加密密钥;清除画像与记录时一并调用,避免留下解不开的旧密文 @experimental */
644
657
  declare function deleteMemoryEncryptionKey(name?: string): Promise<void>;
645
658
  //#endregion
646
- export { type BridgeCapabilities, type BridgeRequest, type BridgeResponse, BrowserSkillManager, BrowserWorkerScriptExecutor, type CaptureFailure, type CaptureLevel, type CapturedImage, type ChromeBuiltinAvailability, ChromeBuiltinLlmClient, type CompressResult, type ConfiguredLlmClient, type DictationAvailability, type DictationOptions, type DictationSession, type DomPageActionExecutor, type DomPageActionOptions, type DomPerceptionReader, type DomPerceptionReaderOptions, IframeWorkerLike, type LlmClientConfig, type LlmEntryConfig, type MainToWorkerMessage, OpfsProvider, type SandboxMode, type SerializedError, TsTranspiler, type TypeScriptSupportOptions, WORKER_BOOTSTRAP_SOURCE, type WorkerEvent, type WorkerFactory, type WorkerLike, type WorkerRequest, WorkerRuntimeClient, type WorkerRuntimeClientDeps, type WorkerRuntimeHostOverrides, type WorkerScopeLike, WorkerUiBridge, bridgeError, captureElementImage, checkDictationAvailability, compressImageToBudget, createDomPageActionExecutor, createDomPerceptionReader, createEncryptedMemoryStore, createIframeWorker, createLlmClient, deleteMemoryEncryptionKey, extractZipWeb, generateMemoryEncryptionKey, installWebSkillNavigator, isCapturableElement, isCaptureFailure, isEncryptedMemoryValue, isOpfsAvailable, openMemoryEncryptionKey, parseBridgeRequest, parseMainMessage, parseWorkerEvent, probeChromeBuiltinAvailability, sha256HexWeb, startDictation, startWorkerRuntimeHost };
659
+ //#region src/host/portMatrix.d.ts
660
+ /**
661
+ * 浏览器宿主装配(分册 17)。
662
+ *
663
+ * 本子路径**刻意不 import** `ChatbotHostAdapter` / `ConsoleBackend` / `ConnectFacade`:
664
+ * 它们分别在 `@webskill/chatbot` 与 `@webskill/console`,而 sdk 依赖不到那两个包
665
+ * (反过来让 sdk 依赖 app 包会把依赖方向倒过来,见偏差 D-18)。
666
+ * 这里只声明**结构等价**的形状,靠 TS 的结构类型系统在宿主侧自动对上。
667
+ *
668
+ * 代价是结构等价靠手工维持:上游接口加了必填字段而这里没跟,
669
+ * 只有宿主赋值时才会报错。因此配了一条测试侧的真实赋值断言(T-17-A),
670
+ * 那条判据是本方案成立的前提,不是可选项。
671
+ */
672
+ /**
673
+ * 端口矩阵覆盖的宿主面。
674
+ * `chatbot-config` 与 `chatbot-adapter` 分开:两者是不同的接口(`ChatbotConfig` / `ChatbotHostAdapter`),
675
+ * 把它们归成一面会让探测去错误的对象上找字段,永远报 missing。
676
+ */
677
+ type HostSurface = 'chatbot-adapter' | 'chatbot-config' | 'console-backend' | 'connect-facade';
678
+ /** 本版只区分浏览器与 Node:矩阵要能表达「tar 在 node 上是应有的」,否则 not-applicable 会变成无条件结论 */
679
+ type HostKind = 'browser' | 'node';
680
+ type PortApplicability = 'expected' | 'not-applicable';
681
+ interface PortSpec {
682
+ id: string;
683
+ surface: HostSurface;
684
+ /** 在该 surface 上探测的字段名 */
685
+ key: string;
686
+ applicability: Readonly<Record<HostKind, PortApplicability>>;
687
+ /** `not-applicable` 时是原因,`expected` 时是接入指引 */
688
+ note: string;
689
+ }
690
+ /**
691
+ * 端口 × 宿主类型的**唯一定义**(AC-17.4)。
692
+ * About 页与装配工厂都读这一份;护栏 `port-matrix-single-source` 盯着不许再抄。
693
+ */
694
+ declare const HOST_PORT_MATRIX: readonly PortSpec[];
695
+ /**
696
+ * 第四态 `unknown` 表示「这个 surface 没交给我看」,不是「没接」。
697
+ * About 页拿不到 `ChatbotHostAdapter` 实例(console 不依赖 chatbot),
698
+ * 只能自检两个面——把没看到的报成「未接线」是错的说法。
699
+ */
700
+ type PortStatus = 'wired' | 'missing' | 'not-applicable' | 'unknown';
701
+ interface PortReport extends PortSpec {
702
+ status: PortStatus;
703
+ }
704
+ interface InspectHostWiringInput {
705
+ kind?: HostKind;
706
+ /** 只对提供了的 surface 出结论;未提供的整面记为 `unknown` */
707
+ surfaces: Partial<Record<HostSurface, Record<string, unknown> | undefined>>;
708
+ }
709
+ declare function inspectHostWiring(input: InspectHostWiringInput): PortReport[];
710
+ /** 缺口 = 该接却没接的项;`unknown` 不算缺口,没看到不等于没接 */
711
+ declare function missingPorts(reports: readonly PortReport[]): PortReport[];
712
+ //#endregion
713
+ //#region src/host/createBrowserChatbotHost.d.ts
714
+ /**
715
+ * 浏览器宿主装配工厂(分册 17 FR-17.1 / 偏差 D-18)。
716
+ *
717
+ * 三个目标接口分属 chatbot 与 console,sdk 依赖不到它们;反过来让 sdk 依赖 app 包
718
+ * 会倒转依赖方向,让 chatbot 依赖 console 又违反 FR-20.5。所以这里只声明**结构等价**的形状,
719
+ * 宿主侧 `const a: ChatbotHostAdapter = bundle.chatbotAdapter` 靠结构类型自动成立。
720
+ *
721
+ * 结构等价是**手工维持**的——上游加必填字段这里不会红,只有宿主赋值时才报错。
722
+ * `packages/browser/test/hostAssembly.test.ts` 里做了真实赋值(T-17-A),
723
+ * 那条判据是本方案成立的前提。
724
+ */
725
+ /**
726
+ * 与 `ChatbotHostAdapter` 结构等价的最小形状。
727
+ *
728
+ * `navigation` 是**必填**:跳 console 是宿主的路由决定,工厂造不出合理缺省。
729
+ * `skillCandidates` **不在这里**——它长在 `ChatbotConfig` 上,不是 adapter 的字段。
730
+ */
731
+ interface HostChatbotAdapterShape {
732
+ storage: FileSystemProvider;
733
+ skillRoots: string[];
734
+ navigation: HostNavigationShape;
735
+ skillManager: BrowserSkillManager;
736
+ pagePerception?: PagePerceptionPolicy;
737
+ }
738
+ /** 与 `ChatbotHostAdapter['navigation']` 结构等价 */
739
+ interface HostNavigationShape {
740
+ openConsole(): void;
741
+ openConsoleTrace?(runId: string): void;
742
+ openConsoleCandidate?(candidateId: string): void;
743
+ }
744
+ /** 与 `ConsoleBackend` 结构等价的最小形状 */
745
+ interface HostConsoleBackendShape {
746
+ catalog(): Promise<unknown>;
747
+ install?: unknown;
748
+ exportSkill?: unknown;
749
+ exportSkillTar?: unknown;
750
+ verifyIntegrity?: unknown;
751
+ writeSkillFile?: unknown;
752
+ listVersions?: unknown;
753
+ runs?: unknown;
754
+ sessions?: unknown;
755
+ }
756
+ /** 与 `ConnectFacade` 结构等价的最小形状 */
757
+ interface HostConnectFacadeShape {
758
+ listEndpoints(): Promise<unknown[]>;
759
+ listTools(): Promise<unknown[]>;
760
+ temporarySkills?: unknown;
761
+ }
762
+ interface BrowserHostBundle {
763
+ readonly chatbotAdapter: HostChatbotAdapterShape;
764
+ readonly consoleBackend: HostConsoleBackendShape;
765
+ readonly connectFacade: HostConnectFacadeShape;
766
+ }
767
+ /**
768
+ * 逃生口(FR-17.1 硬要求):任一件都可替换,其余仍由工厂提供。
769
+ * 没有它,宿主会绕过工厂自建全套装配——那等于工厂没做。
770
+ */
771
+ interface BrowserHostOverrides {
772
+ chatbotAdapter?: HostChatbotAdapterShape;
773
+ consoleBackend?: HostConsoleBackendShape;
774
+ connectFacade?: HostConnectFacadeShape;
775
+ }
776
+ interface BrowserHostOptions {
777
+ /** 必填:没有合理默认值 */
778
+ fs: FileSystemProvider;
779
+ /** 受管技能目录(安装 / 回滚的作用点) */
780
+ managedRoot: string;
781
+ /** 只读技能根;本地技能从这里被发现 */
782
+ skillRoots: string[];
783
+ /** 必填:跳 console 是宿主的路由,工厂无从缺省 */
784
+ navigation: HostNavigationShape;
785
+ /** opt-in 的能力保持可选:强制必填只会逼宿主传 undefined,把类型检查变成形式 */
786
+ pagePerception?: PagePerceptionPolicy;
787
+ consoleBackend?: HostConsoleBackendShape;
788
+ connectFacade?: HostConnectFacadeShape;
789
+ overrides?: BrowserHostOverrides;
790
+ }
791
+ declare function createBrowserChatbotHost(options: BrowserHostOptions): BrowserHostBundle;
792
+ //#endregion
793
+ export { type BridgeCapabilities, type BridgeRequest, type BridgeResponse, type BrowserHostBundle, type BrowserHostOptions, type BrowserHostOverrides, BrowserSkillManager, BrowserWorkerScriptExecutor, type CaptureFailure, type CaptureLevel, type CapturedImage, type ChromeBuiltinAvailability, ChromeBuiltinLlmClient, type CompressResult, type ConfiguredLlmClient, type DictationAvailability, type DictationOptions, type DictationSession, type DomPageActionExecutor, type DomPageActionOptions, type DomPerceptionReader, type DomPerceptionReaderOptions, HOST_PORT_MATRIX, type HostChatbotAdapterShape, type HostConnectFacadeShape, type HostConsoleBackendShape, type HostKind, type HostSurface, IframeWorkerLike, type InspectHostWiringInput, type LlmClientConfig, type LlmEntryConfig, type MainToWorkerMessage, OpfsProvider, type PortApplicability, type PortReport, type PortSpec, type PortStatus, type SandboxMode, type SerializedError, TsTranspiler, type TypeScriptSupportOptions, WORKER_BOOTSTRAP_SOURCE, type WorkerEvent, type WorkerFactory, type WorkerLike, type WorkerRequest, WorkerRuntimeClient, type WorkerRuntimeClientDeps, type WorkerRuntimeHostOverrides, type WorkerScopeLike, WorkerUiBridge, bridgeError, captureElementImage, checkDictationAvailability, compressImageToBudget, createBrowserChatbotHost, createDomPageActionExecutor, createDomPerceptionReader, createEncryptedMemoryStore, createIframeWorker, createLlmClient, deleteMemoryEncryptionKey, extractZipWeb, generateMemoryEncryptionKey, inspectHostWiring, installWebSkillNavigator, isCapturableElement, isCaptureFailure, isEncryptedMemoryValue, isOpfsAvailable, missingPorts, openMemoryEncryptionKey, parseBridgeRequest, parseMainMessage, parseWorkerEvent, probeChromeBuiltinAvailability, sha256HexWeb, startDictation, startWorkerRuntimeHost };
package/dist/browser.js CHANGED
@@ -1,6 +1,6 @@
1
- import { A as parseSkillMarkdown, B as unzipWithLimits, H as verifyManifest, L as resolveInsideRoot, M as readResponseWithLimit, N as readSkillSignature, O as messageOf, T as isValidSkillName, U as verifySkillSignature, V as validateSkills, _ as atomicWriteText, f as SkillDiscovery, 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, v as buildCatalog, w as exportSkills, y as buildManifest } from "./dist-8oQRa8Xz.js";
2
- import { B as bridgeError, C as ProgressiveRouter, S as OpenAiCompatibleClient, U as createWebSkillApi, a as AgentLoop, b as GoogleGenAiClient, c as CapabilityApproval, ct as normalizeToolError, g as FsRunSnapshotStore, h as FsMemoryStore, it as networkPolicyLibSource, lt as parseBridgeRequest, m as FsArtifactStore, nt as mergeCatalogEntries, o as AnthropicClient, st as normalizeToolContent } from "./dist-D0qW6e40.js";
3
- import { n as MockLlmClient } from "./testing-CYTFqkDm.js";
1
+ import { A as messageOf, D as isValidSkillName, E as exportSkills, F as readSkillSignature, G as verifyManifest, K as verifySkillSignature, M as parseSkillMarkdown, N as parseSkillPackManifest, P as readResponseWithLimit, U as unzipWithLimits, W as validateSkills, _ as atomicWriteText, f as SkillDiscovery, h as assertRemoteUrlAllowed, m as WebSkillError, o as SKILLS_LOCKFILE, r as MANIFEST_EXCLUDED_FILES, s as SKILL_MANIFEST_FILE, u as SKILL_PACK_FILE, v as buildCatalog, w as detectSkillArchiveShapeFromFs, y as buildManifest, z as resolveInsideRoot } from "./dist-59XlqDuv.js";
2
+ import { B as bridgeError, C as ProgressiveRouter, S as OpenAiCompatibleClient, U as createWebSkillApi, a as AgentLoop, b as GoogleGenAiClient, c as CapabilityApproval, dt as parseBridgeRequest, g as FsRunSnapshotStore, h as FsMemoryStore, it as mergeCatalogEntries, lt as normalizeToolContent, m as FsArtifactStore, o as AnthropicClient, ot as networkPolicyLibSource, ut as normalizeToolError } from "./dist-DmI5SBBF.js";
3
+ import { n as MockLlmClient } from "./testing-BCUO5gZR.js";
4
4
 
5
5
  //#region ../browser/dist/index.js
6
6
  /** 检测当前环境是否可用 OPFS(navigator.storage.getDirectory) */
@@ -490,7 +490,8 @@ const PRESERVED_INSTALL_CODES = /* @__PURE__ */ new Set([
490
490
  "SIGNATURE_MALFORMED",
491
491
  "SIGNATURE_UNTRUSTED_KEY",
492
492
  "SIGNATURE_MISMATCH",
493
- "SIGNATURE_UNSUPPORTED"
493
+ "SIGNATURE_UNSUPPORTED",
494
+ "SKILL_DUPLICATE_NAME"
494
495
  ]);
495
496
  const asInstallFailed = (e) => e instanceof WebSkillError && (e.code === "INSTALL_FAILED" || e.code === "TOOL_UNSUPPORTED" || PRESERVED_INSTALL_CODES.has(e.code)) ? e : new WebSkillError("INSTALL_FAILED", `Install failed: ${messageOf(e)}`, e);
496
497
  const lockfilePath = (root) => `${root}/${SKILLS_LOCKFILE}`;
@@ -510,6 +511,8 @@ const EMPTY_TRUSTED_KEYS = {
510
511
  var BrowserSkillManager = class {
511
512
  #fs;
512
513
  #managedRoot;
514
+ /** 只读技能根(宿主自带的本地技能):参与导出与依赖存在性判定,但不可卸载 */
515
+ #skillRoots;
513
516
  #fetchImpl;
514
517
  #archiveLimits;
515
518
  #onChanged;
@@ -519,6 +522,7 @@ var BrowserSkillManager = class {
519
522
  constructor(deps) {
520
523
  this.#fs = deps.fs;
521
524
  this.#managedRoot = deps.managedRoot.replace(/\/+$/, "");
525
+ this.#skillRoots = (deps.skillRoots ?? []).map((root) => root.replace(/\/+$/, ""));
522
526
  this.#fetchImpl = deps.fetchImpl;
523
527
  this.#archiveLimits = deps.archiveLimits;
524
528
  this.#onChanged = deps.onChanged;
@@ -572,17 +576,16 @@ var BrowserSkillManager = class {
572
576
  const contentDir = `${stagingRoot}/content`;
573
577
  await fs.mkdir(contentDir);
574
578
  await extractZipWeb(fs, data, contentDir, this.#archiveLimits);
575
- const packFilePath = `${contentDir}/${SKILL_PACK_FILE}`;
576
- if (await fs.exists(packFilePath)) return (await this.#installPack({
577
- contentDir,
578
- manifest: parseSkillPackManifest(await fs.readText(packFilePath))
579
- }, source, stagingRoot))[0];
580
- let skillDir = contentDir;
581
- if (!await fs.exists(`${contentDir}/SKILL.md`)) {
582
- const dirs = (await fs.list(contentDir)).filter((e) => e.type === "directory");
583
- if (dirs.length === 1 && await fs.exists(`${dirs[0]?.path}/SKILL.md`)) skillDir = dirs[0].path;
584
- else throw new WebSkillError("INSTALL_FAILED", "Archive does not contain a SKILL.md at its root or in a single top-level directory");
579
+ const detection = await detectSkillArchiveShapeFromFs(fs, contentDir);
580
+ if (detection.shape === "invalid") throw new WebSkillError("INSTALL_FAILED", detection.reason ?? "Archive layout is not recognised");
581
+ if (detection.shape === "pack-set") {
582
+ const packRoot = detection.rootDir === void 0 ? contentDir : `${contentDir}/${detection.rootDir}`;
583
+ return (await this.#installPack({
584
+ contentDir: packRoot,
585
+ manifest: parseSkillPackManifest(await fs.readText(`${packRoot}/${SKILL_PACK_FILE}`))
586
+ }, source, stagingRoot))[0];
585
587
  }
588
+ const skillDir = detection.rootDir === void 0 ? contentDir : `${contentDir}/${detection.rootDir}`;
586
589
  let name;
587
590
  let version;
588
591
  try {
@@ -593,13 +596,18 @@ var BrowserSkillManager = class {
593
596
  throw new WebSkillError("INSTALL_FAILED", `Failed to read skill name from SKILL.md: ${messageOf(e)}`, e);
594
597
  }
595
598
  if (!isValidSkillName(name)) throw new WebSkillError("INSTALL_FAILED", `Invalid skill name in SKILL.md (path traversal rejected): ${JSON.stringify(name)}`);
599
+ if (options?.replace === "reject" && await fs.exists(`${this.#managedRoot}/${name}`)) throw new WebSkillError("SKILL_DUPLICATE_NAME", `A skill named "${name}" is already installed. Installing it again replaces the existing files; use the packages flow if that is intended.`);
596
600
  const finalRoot = `${stagingRoot}/final`;
597
601
  const finalDir = `${finalRoot}/${name}`;
598
602
  await copyDir(fs, skillDir, finalDir);
599
- const report = await validateSkills(fs, [finalRoot]);
603
+ const report = await validateSkills(fs, [finalRoot], { extraKnownSkillNames: await this.listSkillNames() });
600
604
  if (!report.ok) {
601
- const errors = report.issues.filter((i) => i.severity === "error");
602
- throw new WebSkillError("INSTALL_FAILED", `Skill "${name}" failed validation: ${errors.map((i) => i.message).join("; ")}`, errors);
605
+ const errors = report.issues.filter((i) => i.severity === "error" && i.code !== "SKILL_UNKNOWN_DEPENDENCY");
606
+ for (const issue of report.issues) if (issue.code === "SKILL_UNKNOWN_DEPENDENCY") this.#onWarning?.({
607
+ skill: name,
608
+ message: issue.message
609
+ });
610
+ if (errors.length > 0) throw new WebSkillError("INSTALL_FAILED", `Skill "${name}" failed validation: ${errors.map((i) => i.message).join("; ")}`, errors);
603
611
  }
604
612
  const manifest = await this.#createManifest(finalDir, {
605
613
  name,
@@ -714,6 +722,21 @@ var BrowserSkillManager = class {
714
722
  throw asInstallFailed(e);
715
723
  }
716
724
  }
725
+ /** 技能的真实根:先 managed,再只读根。都没有则 undefined */
726
+ async #resolveSkillRoot(name) {
727
+ const managed = `${this.#managedRoot}/${name}`;
728
+ if (await this.#fs.exists(managed)) return {
729
+ root: managed,
730
+ managed: true
731
+ };
732
+ for (const base of this.#skillRoots) {
733
+ const candidate = `${base}/${name}`;
734
+ if (await this.#fs.exists(candidate)) return {
735
+ root: candidate,
736
+ managed: false
737
+ };
738
+ }
739
+ }
717
740
  /**
718
741
  * 浏览器导出(单技能与包集同构:始终产出含 webskill.skill-pack.json 的 zip 字节,
719
742
  * 统一安装路径;保存/下载由应用层处理)。
@@ -721,11 +744,13 @@ var BrowserSkillManager = class {
721
744
  async exportArchive(names) {
722
745
  const list = Array.isArray(names) ? names : [names];
723
746
  if (list.length === 0) throw new WebSkillError("EXPORT_FAILED", "exportArchive requires at least one skill name");
724
- const roots = list.map((name) => {
747
+ const roots = [];
748
+ for (const name of list) {
725
749
  if (!isValidSkillName(name)) throw new WebSkillError("EXPORT_FAILED", `Invalid skill name (path traversal rejected): ${JSON.stringify(name)}`);
726
- return `${this.#managedRoot}/${name}`;
727
- });
728
- for (const [index, root] of roots.entries()) if (!await this.#fs.exists(root)) throw new WebSkillError("EXPORT_FAILED", `Skill "${list[index]}" is not installed`);
750
+ const resolved = await this.#resolveSkillRoot(name);
751
+ if (resolved === void 0) throw new WebSkillError("EXPORT_FAILED", `Skill "${name}" is not installed`);
752
+ roots.push(resolved.root);
753
+ }
729
754
  return exportSkills(this.#fs, {
730
755
  roots,
731
756
  manifestBuilder: (root) => this.#readManifest(root)
@@ -733,8 +758,10 @@ var BrowserSkillManager = class {
733
758
  }
734
759
  async uninstall(name) {
735
760
  if (!isValidSkillName(name)) throw new WebSkillError("UNINSTALL_FAILED", `Invalid skill name (path traversal rejected): ${JSON.stringify(name)}`);
736
- const targetDir = `${this.#managedRoot}/${name}`;
737
- if (!await this.#fs.exists(targetDir)) throw new WebSkillError("UNINSTALL_FAILED", `Skill "${name}" is not installed`);
761
+ const resolved = await this.#resolveSkillRoot(name);
762
+ if (resolved === void 0) throw new WebSkillError("UNINSTALL_FAILED", `Skill "${name}" is not installed`);
763
+ if (!resolved.managed) throw new WebSkillError("UNINSTALL_FAILED", `Skill "${name}" ships with the host application and is not managed by the skill manager; remove it from the host's skill root instead.`);
764
+ const targetDir = resolved.root;
738
765
  try {
739
766
  await this.#fs.remove(targetDir, { recursive: true });
740
767
  await this.#removeLockEntry(name);
@@ -763,6 +790,22 @@ var BrowserSkillManager = class {
763
790
  throw new WebSkillError("INTEGRITY_FAILED", `Skills lockfile at ${path} is corrupted: ${messageOf(e)}`, e);
764
791
  }
765
792
  }
793
+ /**
794
+ * 库里已有的技能名:managed 目录 + 宿主声明的只读根。读失败按「库为空」处理,不阻断安装。
795
+ * 与 `listInstalled()` 的区别是**含本地技能**(后者只看安装账本)。
796
+ * @experimental
797
+ */
798
+ async listSkillNames() {
799
+ const names = [];
800
+ for (const root of [this.#managedRoot, ...this.#skillRoots]) {
801
+ if (!await this.#fs.exists(root).catch(() => false)) continue;
802
+ for (const stat of await this.#fs.list(root).catch(() => [])) {
803
+ const name = stat.path.split("/").pop() ?? "";
804
+ if (stat.type === "directory" && isValidSkillName(name)) names.push(name);
805
+ }
806
+ }
807
+ return names;
808
+ }
766
809
  async #createManifest(skillRoot, input) {
767
810
  const files = [];
768
811
  for (const rel of (await listFiles(this.#fs, skillRoot)).sort()) {
@@ -787,7 +830,16 @@ var BrowserSkillManager = class {
787
830
  }
788
831
  async #readManifest(skillRoot) {
789
832
  const path = `${skillRoot}/${SKILL_MANIFEST_FILE}`;
790
- if (!await this.#fs.exists(path)) throw new WebSkillError("INTEGRITY_FAILED", `Skill manifest not found at ${path} (was the skill installed via BrowserSkillManager?)`);
833
+ if (!await this.#fs.exists(path)) {
834
+ const name = skillRoot.split("/").pop() ?? skillRoot;
835
+ return this.#createManifest(skillRoot, {
836
+ name,
837
+ source: {
838
+ type: "local",
839
+ path: skillRoot
840
+ }
841
+ });
842
+ }
791
843
  try {
792
844
  return JSON.parse(await this.#fs.readText(path));
793
845
  } catch (e) {
@@ -2670,6 +2722,179 @@ async function deleteMemoryEncryptionKey(name = "user-profile") {
2670
2722
  db.close();
2671
2723
  }
2672
2724
  }
2725
+ /**
2726
+ * 端口 × 宿主类型的**唯一定义**(AC-17.4)。
2727
+ * About 页与装配工厂都读这一份;护栏 `port-matrix-single-source` 盯着不许再抄。
2728
+ */
2729
+ const HOST_PORT_MATRIX = [
2730
+ {
2731
+ id: "install / uninstall",
2732
+ surface: "console-backend",
2733
+ key: "install",
2734
+ applicability: {
2735
+ browser: "expected",
2736
+ node: "expected"
2737
+ },
2738
+ note: "Wire ConsoleBackend.install to let the console install and remove skills."
2739
+ },
2740
+ {
2741
+ id: "export (zip)",
2742
+ surface: "console-backend",
2743
+ key: "exportSkill",
2744
+ applicability: {
2745
+ browser: "expected",
2746
+ node: "expected"
2747
+ },
2748
+ note: "Wire ConsoleBackend.exportSkill to enable zip export."
2749
+ },
2750
+ {
2751
+ id: "export (tar)",
2752
+ surface: "console-backend",
2753
+ key: "exportSkillTar",
2754
+ applicability: {
2755
+ browser: "not-applicable",
2756
+ node: "expected"
2757
+ },
2758
+ note: "Browsers have no tar toolchain in the platform; zip export covers the same need."
2759
+ },
2760
+ {
2761
+ id: "integrity",
2762
+ surface: "console-backend",
2763
+ key: "verifyIntegrity",
2764
+ applicability: {
2765
+ browser: "expected",
2766
+ node: "expected"
2767
+ },
2768
+ note: "Wire ConsoleBackend.verifyIntegrity to enable the integrity report."
2769
+ },
2770
+ {
2771
+ id: "editing",
2772
+ surface: "console-backend",
2773
+ key: "writeSkillFile",
2774
+ applicability: {
2775
+ browser: "expected",
2776
+ node: "expected"
2777
+ },
2778
+ note: "Wire ConsoleBackend.writeSkillFile to enable in-place skill editing."
2779
+ },
2780
+ {
2781
+ id: "versions",
2782
+ surface: "console-backend",
2783
+ key: "listVersions",
2784
+ applicability: {
2785
+ browser: "expected",
2786
+ node: "expected"
2787
+ },
2788
+ note: "Wire ConsoleBackend.listVersions to show version history and rollback."
2789
+ },
2790
+ {
2791
+ id: "runs",
2792
+ surface: "console-backend",
2793
+ key: "runs",
2794
+ applicability: {
2795
+ browser: "expected",
2796
+ node: "expected"
2797
+ },
2798
+ note: "Wire ConsoleBackend.runs to read run history; without it the runs pages have no source."
2799
+ },
2800
+ {
2801
+ id: "sessions",
2802
+ surface: "console-backend",
2803
+ key: "sessions",
2804
+ applicability: {
2805
+ browser: "expected",
2806
+ node: "expected"
2807
+ },
2808
+ note: "Wire ConsoleBackend.sessions to list chat sessions."
2809
+ },
2810
+ {
2811
+ id: "page perception",
2812
+ surface: "chatbot-adapter",
2813
+ key: "pagePerception",
2814
+ applicability: {
2815
+ browser: "expected",
2816
+ node: "not-applicable"
2817
+ },
2818
+ note: "Page perception reads the live DOM; there is no page outside a browser."
2819
+ },
2820
+ {
2821
+ id: "skill candidates",
2822
+ surface: "chatbot-config",
2823
+ key: "skillCandidates",
2824
+ applicability: {
2825
+ browser: "expected",
2826
+ node: "expected"
2827
+ },
2828
+ note: "Wire skillCandidates so skill-miss suggestions can be reviewed in the console."
2829
+ },
2830
+ {
2831
+ id: "remote endpoints",
2832
+ surface: "connect-facade",
2833
+ key: "listEndpoints",
2834
+ applicability: {
2835
+ browser: "expected",
2836
+ node: "expected"
2837
+ },
2838
+ note: "Wire ConnectFacade.listEndpoints to manage remote MCP endpoints."
2839
+ },
2840
+ {
2841
+ id: "page-declared skills",
2842
+ surface: "connect-facade",
2843
+ key: "temporarySkills",
2844
+ applicability: {
2845
+ browser: "expected",
2846
+ node: "not-applicable"
2847
+ },
2848
+ note: "Page-declared temporary skills come from the document; Node hosts have none."
2849
+ }
2850
+ ];
2851
+ function inspectHostWiring(input) {
2852
+ const kind = input.kind ?? "browser";
2853
+ return HOST_PORT_MATRIX.map((spec) => {
2854
+ if (!(spec.surface in input.surfaces)) return {
2855
+ ...spec,
2856
+ status: "unknown"
2857
+ };
2858
+ if (spec.applicability[kind] === "not-applicable") return {
2859
+ ...spec,
2860
+ status: "not-applicable"
2861
+ };
2862
+ const surface = input.surfaces[spec.surface];
2863
+ const wired = surface !== void 0 && surface[spec.key] !== void 0;
2864
+ return {
2865
+ ...spec,
2866
+ status: wired ? "wired" : "missing"
2867
+ };
2868
+ });
2869
+ }
2870
+ /** 缺口 = 该接却没接的项;`unknown` 不算缺口,没看到不等于没接 */
2871
+ function missingPorts(reports) {
2872
+ return reports.filter((report) => report.status === "missing");
2873
+ }
2874
+ function createBrowserChatbotHost(options) {
2875
+ const { fs, managedRoot, skillRoots, navigation, overrides } = options;
2876
+ const chatbotAdapter = {
2877
+ storage: fs,
2878
+ skillRoots,
2879
+ navigation,
2880
+ skillManager: new BrowserSkillManager({
2881
+ fs,
2882
+ managedRoot,
2883
+ skillRoots
2884
+ }),
2885
+ ...options.pagePerception !== void 0 ? { pagePerception: options.pagePerception } : {}
2886
+ };
2887
+ const consoleBackend = options.consoleBackend ?? { catalog: async () => ({ entries: [] }) };
2888
+ const connectFacade = options.connectFacade ?? {
2889
+ listEndpoints: async () => [],
2890
+ listTools: async () => []
2891
+ };
2892
+ return {
2893
+ chatbotAdapter: overrides?.chatbotAdapter ?? chatbotAdapter,
2894
+ consoleBackend: overrides?.consoleBackend ?? consoleBackend,
2895
+ connectFacade: overrides?.connectFacade ?? connectFacade
2896
+ };
2897
+ }
2673
2898
 
2674
2899
  //#endregion
2675
- export { BrowserSkillManager, BrowserWorkerScriptExecutor, ChromeBuiltinLlmClient, IframeWorkerLike, OpfsProvider, TsTranspiler, WORKER_BOOTSTRAP_SOURCE, WorkerRuntimeClient, WorkerUiBridge, bridgeError, captureElementImage, checkDictationAvailability, compressImageToBudget, createDomPageActionExecutor, createDomPerceptionReader, createEncryptedMemoryStore, createIframeWorker, createLlmClient, deleteMemoryEncryptionKey, extractZipWeb, generateMemoryEncryptionKey, installWebSkillNavigator, isCapturableElement, isCaptureFailure, isEncryptedMemoryValue, isOpfsAvailable, openMemoryEncryptionKey, parseBridgeRequest, parseMainMessage, parseWorkerEvent, probeChromeBuiltinAvailability, sha256HexWeb, startDictation, startWorkerRuntimeHost };
2900
+ export { BrowserSkillManager, BrowserWorkerScriptExecutor, ChromeBuiltinLlmClient, HOST_PORT_MATRIX, IframeWorkerLike, OpfsProvider, TsTranspiler, WORKER_BOOTSTRAP_SOURCE, WorkerRuntimeClient, WorkerUiBridge, bridgeError, captureElementImage, checkDictationAvailability, compressImageToBudget, createBrowserChatbotHost, createDomPageActionExecutor, createDomPerceptionReader, createEncryptedMemoryStore, createIframeWorker, createLlmClient, deleteMemoryEncryptionKey, extractZipWeb, generateMemoryEncryptionKey, inspectHostWiring, installWebSkillNavigator, isCapturableElement, isCaptureFailure, isEncryptedMemoryValue, isOpfsAvailable, missingPorts, openMemoryEncryptionKey, parseBridgeRequest, parseMainMessage, parseWorkerEvent, probeChromeBuiltinAvailability, sha256HexWeb, startDictation, startWorkerRuntimeHost };