@dp-bohrium/widget-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.
Files changed (36) hide show
  1. package/AGENTS.md +6 -3
  2. package/CHANGELOG.md +21 -0
  3. package/README.md +7 -16
  4. package/assets/schemas/widget-runtime-contracts.schema.json +7 -3
  5. package/assets/toolchain.json +13 -9
  6. package/dist/cli.mjs +155 -114
  7. package/dist/contracts.d.ts +1 -1
  8. package/dist/contracts.js +2 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.js +17 -11
  11. package/dist/manifest.d.ts +1 -1
  12. package/dist/protocol/generated-host-runtime-config.d.ts +551 -0
  13. package/dist/protocol/generated-manifest.d.ts +192 -0
  14. package/dist/protocol/generated-plugin-manifest.d.ts +176 -0
  15. package/dist/protocol/generated-runtime-contracts.d.ts +1224 -0
  16. package/dist/protocol/index.d.ts +43 -0
  17. package/dist/protocol/plugin-manifest.d.ts +30 -0
  18. package/dist/protocol/widget-events.d.ts +13 -0
  19. package/dist/runtime/bootstrap.d.ts +1 -1
  20. package/dist/runtime/client.d.ts +1 -1
  21. package/dist/runtime/event-validation.d.ts +1 -1
  22. package/dist/runtime/events.d.ts +1 -1
  23. package/dist/runtime/files.d.ts +1 -1
  24. package/dist/runtime/index.d.ts +1 -1
  25. package/dist/runtime/index.js +1 -1
  26. package/dist/runtime/mock-host.d.ts +1 -1
  27. package/dist/runtime/network.d.ts +1 -1
  28. package/dist/runtime/protocol-endpoint.d.ts +1 -1
  29. package/dist/runtime/service.d.ts +2 -2
  30. package/dist/runtime/transport.d.ts +1 -1
  31. package/dist/{runtime-D7KxTtdu.js → runtime-DZA7Gqzl.js} +1 -1
  32. package/dist/widget-events-BT0QxR-H.js +65 -0
  33. package/dist/widget.d.ts +2 -2
  34. package/llms.txt +2 -3
  35. package/package.json +4 -6
  36. package/schemas/widget-runtime-contracts.schema.json +7 -3
package/dist/cli.mjs CHANGED
@@ -1,13 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { createRequire } from "node:module";
3
2
  import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
4
3
  import { constants, existsSync, lstatSync, readFileSync, readdirSync, realpathSync, statSync, watch } from "node:fs";
5
4
  import { chmod, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, rmdir, stat, writeFile } from "node:fs/promises";
6
5
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
7
6
  import { fileURLToPath } from "node:url";
8
- import { compileWidgetPluginManifest } from "@dp-bohrium/widget-sdk";
9
7
  import { spawn, spawnSync } from "node:child_process";
10
8
  import { createServer } from "node:http";
9
+ import { isDeepStrictEqual } from "node:util";
11
10
  //#region \0rolldown/runtime.js
12
11
  var __create = Object.create;
13
12
  var __defProp = Object.defineProperty;
@@ -99,7 +98,59 @@ function collectReferencedFileIds(request) {
99
98
  return referenced;
100
99
  }
101
100
  //#endregion
101
+ //#region ../widget-project/src/manifest-compiler.mjs
102
+ function compiledContribution(contribution) {
103
+ switch (contribution.type) {
104
+ case "panel": return {
105
+ type: "panel",
106
+ id: contribution.id,
107
+ ...contribution.placement === void 0 ? {} : { placement: contribution.placement }
108
+ };
109
+ case "file-preview": return {
110
+ type: "file-preview",
111
+ extensions: [...contribution.extensions]
112
+ };
113
+ }
114
+ }
115
+ /** 只编译协议数据;SDK 版本由可信调用方绑定,不读取安装或执行环境。 */
116
+ function compileWidgetPluginManifest(manifest, sdkVersion, options = {}) {
117
+ const samples = options.samples ?? manifest.samples;
118
+ if (!samples || samples.length === 0) throw new Error("Widget Plugin Manifest must provide at least one sample before packaging");
119
+ const contribution = manifest.contributes.widget;
120
+ if (contribution.type === "panel" && contribution.placement?.kind === "region" && (manifest.capabilities?.region?.mode !== contribution.placement.mode || !manifest.capabilities.region.regions.includes(contribution.placement.region))) throw new Error("A region Widget contribution must declare a matching region capability");
121
+ const activationEvents = manifest.activationEvents ? [...manifest.activationEvents] : void 0;
122
+ return {
123
+ name: manifest.name,
124
+ ...manifest.description === void 0 ? {} : { description: manifest.description },
125
+ widgetConfig: {
126
+ schemaVersion: 1,
127
+ hostApiVersion: 1,
128
+ widgetSdkVersion: sdkVersion,
129
+ entry: options.hostEntry ?? "dist/widget.js",
130
+ contribution: compiledContribution(manifest.contributes.widget),
131
+ ...activationEvents === void 0 ? {} : { activationEvents },
132
+ ...manifest.capabilities === void 0 ? {} : { requestedCapabilities: manifest.capabilities },
133
+ ...manifest.runtime === void 0 ? {} : { runtime: manifest.runtime },
134
+ samples
135
+ }
136
+ };
137
+ }
138
+ //#endregion
139
+ //#region package.json
140
+ var name = "@dp-bohrium/widget-sdk";
141
+ var version = "0.7.0";
142
+ //#endregion
143
+ //#region ../widget-project/src/sdk-metadata.mjs
144
+ /** 只读取交付包元数据,不加载 SDK 公开入口的执行代码。 */
145
+ function getSdkVersion() {
146
+ if (name !== "@dp-bohrium/widget-sdk" || typeof version !== "string" || version.length === 0) throw new Error("Widget SDK package metadata is invalid");
147
+ return version;
148
+ }
149
+ //#endregion
102
150
  //#region ../widget-project/src/manifest.mjs
151
+ function compileWithSdkMetadata(manifest, options) {
152
+ return compileWidgetPluginManifest(manifest, getSdkVersion(), options);
153
+ }
103
154
  /**
104
155
  * Convert the author-facing VS Code-style plugin manifest to the Host
105
156
  * manifest consumed by Host Runtime Config. This is deliberately a tooling
@@ -110,7 +161,7 @@ function compileAuthorManifest(manifest, options = {}) {
110
161
  if (!isAuthorManifest(manifest)) return manifest;
111
162
  const contribution = manifest.contributes?.widget;
112
163
  if (!contribution || typeof contribution !== "object" || !["panel", "file-preview"].includes(contribution.type) || contribution.type === "file-preview" && !Array.isArray(contribution.extensions)) return manifest;
113
- const compiled = (options.compiler ?? compileWidgetPluginManifest)(manifest, {
164
+ const compiled = (options.compiler ?? compileWithSdkMetadata)(manifest, {
114
165
  hostEntry: options.hostEntry,
115
166
  samples: options.samples
116
167
  });
@@ -124,7 +175,6 @@ function compileAuthorManifest(manifest, options = {}) {
124
175
  function isAuthorManifest(value) {
125
176
  return Boolean(value && typeof value === "object" && !Array.isArray(value) && "contributes" in value && "version" in value);
126
177
  }
127
- createRequire(import.meta.url);
128
178
  //#endregion
129
179
  //#region ../contract-testing/src/generated-runtime-contracts-schema.ts
130
180
  /** GENERATED FILE. Do not edit directly. */
@@ -1050,17 +1100,15 @@ const widgetRuntimeContractsSchema = {
1050
1100
  "limits": {
1051
1101
  "type": "object",
1052
1102
  "additionalProperties": false,
1053
- "required": [
1054
- "bytesPerRequest",
1055
- "bytesPerRun",
1056
- "callsPerMinute"
1057
- ],
1103
+ "required": ["bytesPerRequest", "callsPerMinute"],
1058
1104
  "properties": {
1059
1105
  "bytesPerRequest": {
1060
1106
  "type": "integer",
1061
1107
  "minimum": 1
1062
1108
  },
1063
1109
  "bytesPerRun": {
1110
+ "description": "历史读取累计额度字段,仅为兼容旧配置保留;当前 files.read 不累计或执行此额度,新宿主不再下发。",
1111
+ "deprecated": true,
1064
1112
  "type": "integer",
1065
1113
  "minimum": 1
1066
1114
  },
@@ -2376,7 +2424,6 @@ const widgetRuntimeContractsSchema = {
2376
2424
  "additionalProperties": false,
2377
2425
  "required": [
2378
2426
  "readBytesPerRequest",
2379
- "readBytesPerRun",
2380
2427
  "callsPerMinute",
2381
2428
  "listPageSize"
2382
2429
  ],
@@ -2386,6 +2433,8 @@ const widgetRuntimeContractsSchema = {
2386
2433
  "minimum": 1
2387
2434
  },
2388
2435
  "readBytesPerRun": {
2436
+ "description": "历史读取累计额度字段,仅为兼容旧配置保留;当前 files.read 不累计或执行此额度,新宿主不再下发。",
2437
+ "deprecated": true,
2389
2438
  "type": "integer",
2390
2439
  "minimum": 1
2391
2440
  },
@@ -11314,7 +11363,7 @@ function storedZip(files) {
11314
11363
  ]);
11315
11364
  }
11316
11365
  //#endregion
11317
- //#region ../widget-project/src/export.mjs
11366
+ //#region ../widget-project/src/packaging.mjs
11318
11367
  const EXCLUDED_BUILD_NAMES = /* @__PURE__ */ new Set([
11319
11368
  "node_modules",
11320
11369
  ".git",
@@ -11359,6 +11408,22 @@ function collectBuildAssets(root, entry) {
11359
11408
  visit(rootName);
11360
11409
  return files;
11361
11410
  }
11411
+ function assembleWidgetPackage(project, options) {
11412
+ const files = collectWidgetPackageFiles(project, options);
11413
+ return {
11414
+ files,
11415
+ archive: storedZip(files)
11416
+ };
11417
+ }
11418
+ /** 已完成作者工程检查后的内部交付组装;不执行构建或改变预览夹具规则。 */
11419
+ function prepareWidgetPackage(project, options = {}) {
11420
+ const prepared = assembleWidgetPackage(project, options);
11421
+ return {
11422
+ ...prepared,
11423
+ bytes: prepared.archive.byteLength,
11424
+ sha256: `sha256:${createHash("sha256").update(prepared.archive).digest("hex")}`
11425
+ };
11426
+ }
11362
11427
  /** 返回将写入 ZIP 的 `[路径, 字节]` 列表;同一路径可能重复出现,由 `storedZip` 去重。 */
11363
11428
  function collectWidgetPackageFiles(project, options = {}) {
11364
11429
  const root = resolve(project.projectRoot);
@@ -11436,7 +11501,6 @@ const RESOURCE_BUDGET = {
11436
11501
  },
11437
11502
  files: {
11438
11503
  readBytesPerRequest: 4194304,
11439
- readBytesPerRun: 16777216,
11440
11504
  callsPerMinute: 120,
11441
11505
  listPageSize: 100
11442
11506
  },
@@ -11665,7 +11729,6 @@ function requestedGrants(requested = {}) {
11665
11729
  name: "files.read",
11666
11730
  limits: {
11667
11731
  bytesPerRequest: 4194304,
11668
- bytesPerRun: 16777216,
11669
11732
  callsPerMinute: 120
11670
11733
  }
11671
11734
  });
@@ -11763,7 +11826,7 @@ function panelDevelopmentDescriptor(generation, profileUrl, statusUrl) {
11763
11826
  widgetId,
11764
11827
  widgetVersionId,
11765
11828
  snapshot: {
11766
- id,
11829
+ panelType: id,
11767
11830
  title: generation.manifest.name,
11768
11831
  state: "complete",
11769
11832
  data: {}
@@ -12760,7 +12823,7 @@ function commandTopics(context) {
12760
12823
  notes: [
12761
12824
  "不传 --project 时只发现 CLI 自带工具链,不检查当前目录是否为 Widget 工程。",
12762
12825
  "传入工程时要求工具链锁;尚未安装依赖时先核对声明,已安装时同时核对实际版本。",
12763
- "JSON 使用 interfaceVersion=2、toolchain.formatVersion=2;返回 execution、profile、requirements 和 documentation。",
12826
+ "JSON 使用 interfaceVersion=3、toolchain.formatVersion=3;返回 execution、profile、requirements 和 documentation。",
12764
12827
  "调用方应使用 execution.executable 与 execution.entry 启动同一份 CLI,避免 PATH 指向另一版本。",
12765
12828
  "宿主声明由调用方提供;unknown、snapshot、confirmed 不代表上传或发布许可。"
12766
12829
  ],
@@ -12773,7 +12836,7 @@ function commandTopics(context) {
12773
12836
  options: [HOST_OPTION, JSON_OPTION],
12774
12837
  examples: ["bohr-widget adopt ./existing-widget --json", "bohr-widget adopt . --host-compat ./host.json --json"],
12775
12838
  notes: [
12776
- "先运行 doctor,恢复当前 profile 的精确 SDK/contracts 依赖并安装。",
12839
+ "先运行 doctor,恢复当前 profile 的精确 SDK 依赖并安装。",
12777
12840
  "核对实际依赖、Manifest 和 samples 后才写锁;不要求已构建入口。",
12778
12841
  "不会自动升级依赖、迁移源码或修正协议字段;检查不通过时先修复工程。"
12779
12842
  ]
@@ -12790,7 +12853,7 @@ function commandTopics(context) {
12790
12853
  ]
12791
12854
  },
12792
12855
  version: {
12793
- description: "查看当前 CLI 及其固定的 SDK/contracts 版本。",
12856
+ description: "查看当前 SDK 执行器及内置协议摘要。",
12794
12857
  usage: ["bohr-widget version [--json]", "bohr-widget --version [--json]"],
12795
12858
  options: [JSON_OPTION],
12796
12859
  examples: ["bohr-widget version --json", "bohr-widget -v"],
@@ -12861,9 +12924,9 @@ function section(title, lines) {
12861
12924
  return lines.length ? `\n${title}:\n${lines.map((line) => ` ${line}`).join("\n")}\n` : "";
12862
12925
  }
12863
12926
  function globalHelp(context) {
12864
- const { cli, sdk, contracts, packageName = "@dp-bohrium/widget-cli", generatedProjectNode, documentation } = context;
12927
+ const { cli, sdk, packageName = "@dp-bohrium/widget-cli", generatedProjectNode, documentation } = context;
12865
12928
  return `bohr-widget ${cli} — Bohrium Widget 插件工程工具
12866
- SDK ${sdk} / contracts ${contracts}
12929
+ SDK ${sdk}(协议与执行工具链均由 SDK 内置)
12867
12930
  创建、校验、构建、开发调试与打包;上传、发布和 Agent 绑定由 Bohr CLI 或平台执行。
12868
12931
 
12869
12932
  用法:
@@ -12883,7 +12946,7 @@ SDK ${sdk} / contracts ${contracts}
12883
12946
  schema 打印作者 Manifest Schema 的本地路径
12884
12947
  migrate project plan|apply 比较 Agent 准备的候选并安全复制到新目录
12885
12948
  migrate dsh audit|scaffold 审计 DSH 来源或按已审查配方生成工程
12886
- version 查看 CLI 与固定的 SDK/contracts 版本
12949
+ version 查看 SDK 执行器与内置协议版本
12887
12950
  help [命令...] 查看全局或指定主题帮助
12888
12951
 
12889
12952
  全局选项:
@@ -13433,10 +13496,7 @@ async function scaffoldDshWidget(input, output, options) {
13433
13496
  const repeated = await auditDshPlugin(sourceRoot);
13434
13497
  const snapshotFingerprint = `sha256:${createHash("sha256").update(JSON.stringify([...snapshot.files].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0))).digest("hex")}`;
13435
13498
  if (repeated.source.fingerprint !== report.source.fingerprint || snapshotFingerprint !== report.source.fingerprint) throw failure$1("SOURCE_CHANGED", "迁移期间源快照发生变化。");
13436
- const projectFiles = applyDshRecipe(recipe, snapshot.files, {
13437
- sdkVersion: options?.sdkVersion ?? "0.1.0",
13438
- contractsVersion: options?.contractsVersion ?? "0.1.0"
13439
- });
13499
+ const projectFiles = applyDshRecipe(recipe, snapshot.files, { sdkVersion: options?.sdkVersion ?? "0.1.0" });
13440
13500
  const root = resolve(output);
13441
13501
  await mkdir(root);
13442
13502
  for (const [path, content] of Object.entries(projectFiles)) {
@@ -13457,10 +13517,7 @@ async function scaffoldDshWidget(input, output, options) {
13457
13517
  //#region ../widget-cli/src/project-executor.mjs
13458
13518
  const PROJECT_TOOLCHAIN_FILE = "widget-toolchain.json";
13459
13519
  const BUILD_RECEIPT_FILE = ".widget-build-receipt.json";
13460
- const PACKAGES = Object.freeze({
13461
- sdk: "@dp-bohrium/widget-sdk",
13462
- contracts: "@dp-bohrium/widget-contracts"
13463
- });
13520
+ const PACKAGES = Object.freeze({ sdk: "@dp-bohrium/widget-sdk" });
13464
13521
  const EXACT_VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u;
13465
13522
  function failure(code, message, context, recovery) {
13466
13523
  return Object.assign(new Error(message), {
@@ -13534,12 +13591,12 @@ async function assertHostCompatibility(hostCompatPath, toolchain, { now = Date.n
13534
13591
  }
13535
13592
  function assertMatchingLock(lock, toolchain, root) {
13536
13593
  const { profile } = toolchain;
13537
- if (!record$1(lock) || lock.formatVersion !== 1 || lock.profileId !== profile.id) throw failure("PROJECT_PROFILE_MISMATCH", "工程锁定的 profile 与当前 Widget CLI 不一致", {
13594
+ if (!record$1(lock) || lock.formatVersion !== 2 || lock.profileId !== profile.id) throw failure("PROJECT_PROFILE_MISMATCH", "工程锁定格式或 profile 与当前 SDK 不一致;旧工程需准备当前源码候选后迁移,不能复用历史执行器", {
13538
13595
  projectRoot: root,
13539
13596
  expectedProfile: profile.id,
13540
13597
  actualProfile: lock?.profileId
13541
13598
  }, ["使用当前受支持的 CLI,并在新目录显式迁移工程与验收;不要回选旧 CLI 绕过 profile 差异。"]);
13542
- if (lock.sdk !== profile.sdk || lock.contracts !== profile.contracts) throw failure("PROJECT_SDK_MISMATCH", "工程锁定的 SDK/contracts 与当前 profile 不一致", {
13599
+ if (lock.sdk !== profile.sdk || !isDeepStrictEqual(lock.protocol, toolchain.protocol)) throw failure("PROJECT_SDK_MISMATCH", "工程锁定的 SDK 或内置协议与当前 profile 不一致", {
13543
13600
  projectRoot: root,
13544
13601
  expected: profile,
13545
13602
  actual: lock
@@ -13578,39 +13635,58 @@ function assertInstalledPackage(actual, name, expected, root) {
13578
13635
  installed: actual?.version
13579
13636
  }, ["按工程锁定信息恢复依赖并重新安装,再重新构建。"]);
13580
13637
  }
13581
- /** 只接受 SDK 自身依赖或其安装目录中的提升依赖,不向工作区祖先借用。 */
13582
- async function sdkContractsMetadata(sdkPath, root) {
13638
+ /** 名称和字节同时参与摘要;禁止通过协议资产链接借用其他安装。 */
13639
+ async function schemaDigest(directory) {
13640
+ const hash = createHash("sha256");
13641
+ const paths = [];
13642
+ async function visit(path) {
13643
+ const entry = await lstat(path);
13644
+ if (entry.isSymbolicLink()) throw new Error("SDK 协议资产不允许符号链接");
13645
+ if (entry.isDirectory()) for (const name of (await readdir(path)).sort()) await visit(join(path, name));
13646
+ else if (entry.isFile()) paths.push(path);
13647
+ else throw new Error("SDK 协议资产必须是普通文件");
13648
+ }
13649
+ await visit(directory);
13650
+ if (!paths.length) throw new Error("SDK 协议资产为空");
13651
+ for (const path of paths.sort()) {
13652
+ const bytes = await readFile(path);
13653
+ hash.update(relative(directory, path).split(sep).join("/"));
13654
+ hash.update("\0");
13655
+ hash.update(String(bytes.length));
13656
+ hash.update("\0");
13657
+ hash.update(bytes);
13658
+ }
13659
+ return `sha256:${hash.digest("hex")}`;
13660
+ }
13661
+ async function assertEmbeddedProtocol(sdkPath, toolchain, root) {
13583
13662
  const sdkRoot = dirname(await realpath(sdkPath));
13584
- const resolver = createRequire(join(sdkRoot, "package.json"));
13585
- const lookupRoots = /* @__PURE__ */ new Set([join(sdkRoot, "node_modules")]);
13586
- for (let current = sdkRoot; dirname(current) !== current; current = dirname(current)) if (basename(current) === "node_modules") {
13587
- lookupRoots.add(current);
13588
- break;
13589
- }
13590
13663
  try {
13591
- const resolvedPath = await realpath(resolver.resolve(`${PACKAGES.contracts}/package.json`));
13592
- for (const lookup of resolver.resolve.paths(PACKAGES.contracts) ?? []) {
13593
- if (!lookupRoots.has(lookup)) continue;
13594
- try {
13595
- if (await realpath(join(lookup, PACKAGES.contracts, "package.json")) === resolvedPath) return await json(resolvedPath, "PROJECT_SDK_MISMATCH", ["重新安装工程 SDK 及其配套 contracts 依赖。"]);
13596
- } catch (error) {
13597
- if (error.code !== "ENOENT") throw error;
13598
- }
13599
- }
13664
+ const embedded = JSON.parse(await readFile(join(sdkRoot, "assets/toolchain.json"), "utf8"));
13665
+ if (embedded.formatVersion !== 3 || embedded.packageName !== PACKAGES.sdk || embedded.cli !== toolchain.profile.sdk || !isDeepStrictEqual(embedded.profile, toolchain.profile) || !isDeepStrictEqual(embedded.protocol, toolchain.protocol) || !isDeepStrictEqual(embedded.digests, toolchain.digests) || embedded.protocol?.schemaVersion !== 1 || embedded.protocol?.hostApiVersion !== 1 || embedded.protocol?.digest !== embedded.digests?.schemas) throw new Error("SDK 内置协议或执行工具链元数据与当前执行器不一致");
13666
+ for (const directory of ["schemas", "assets/schemas"]) if (await schemaDigest(join(sdkRoot, directory)) !== embedded.protocol.digest) throw new Error("SDK 内置协议资产已漂移");
13600
13667
  } catch (error) {
13601
- if (error.cliCode) throw error;
13668
+ throw failure("PROJECT_SDK_MISMATCH", "工程 SDK 缺少有效的自包含协议资产或摘要不一致", {
13669
+ projectRoot: root,
13670
+ package: PACKAGES.sdk,
13671
+ cause: error.message
13672
+ }, ["在当前工程安装正确的 SDK 完整包,再重新构建;不能借用祖先目录或旧 contracts 包。"]);
13602
13673
  }
13603
- throw failure("PROJECT_SDK_MISMATCH", "工程 SDK 缺少自身可解析的配套 contracts,不能借用祖先目录或 CLI 的依赖", {
13604
- projectRoot: root,
13605
- package: PACKAGES.contracts
13606
- }, ["在该 Widget 工程目录重新安装依赖,并保留 SDK 自身的传递依赖。"]);
13607
13674
  }
13608
- /** SDK 必须由工程直接安装,contracts 从该 SDK 的真实依赖核对。 */
13675
+ /** SDK 必须由工程直接安装;协议只能来自该 SDK 自己的冻结资产。 */
13609
13676
  async function validateProjectToolchain(projectRoot, toolchain, { requireInstalled = true, requireLock = true } = {}) {
13610
13677
  const root = resolve(projectRoot);
13611
13678
  const lock = await readLock(root, toolchain, requireLock);
13612
13679
  const pkg = await json(join(root, "package.json"), "PROJECT_SDK_MISMATCH", ["恢复工程 package.json 中的精确 SDK 依赖。"]);
13613
13680
  if (!record$1(pkg)) throw failure("PROJECT_SDK_MISMATCH", "工程 package.json 必须是对象", { projectRoot: root }, ["恢复工程 package.json 中的精确 SDK 依赖。"]);
13681
+ for (const section of [
13682
+ "dependencies",
13683
+ "devDependencies",
13684
+ "optionalDependencies",
13685
+ "peerDependencies"
13686
+ ]) for (const name of ["@dp-bohrium/widget-contracts", "@dp-bohrium/widget-cli"]) if (pkg[section]?.[name] !== void 0) throw failure("PROJECT_SDK_MISMATCH", "作者工程仍直接声明 contracts 或 CLI,需统一使用 SDK 入口", {
13687
+ projectRoot: root,
13688
+ package: name
13689
+ }, ["作者工程统一依赖 SDK;独立 CLI 请在工具目录或通过 npx 使用,Contracts 独立包供 Host 等消费者使用。保留作者源码,在独立候选中移除重复依赖、重新安装和构建。"]);
13614
13690
  const declared = {};
13615
13691
  const installed = {};
13616
13692
  for (const [key, name] of Object.entries(PACKAGES)) {
@@ -13633,53 +13709,22 @@ async function validateProjectToolchain(projectRoot, toolchain, { requireInstall
13633
13709
  const actual = await json(path, "PROJECT_SDK_MISMATCH", ["在该 Widget 工程目录安装依赖,再重试;父目录或 CLI 的安装不能替代工程安装。"]);
13634
13710
  assertInstalledPackage(actual, name, expected, root);
13635
13711
  installed[key] = actual.version;
13636
- if (key === "sdk") {
13637
- const dependency = actual.dependencies?.[PACKAGES.contracts];
13638
- if (dependency !== toolchain.profile.contracts && dependency !== "workspace:*" && dependency !== `workspace:${toolchain.profile.contracts}`) throw failure("PROJECT_SDK_MISMATCH", "工程 SDK 的 contracts 依赖与固定 profile 不一致", {
13639
- projectRoot: root,
13640
- package: name,
13641
- expected: toolchain.profile.contracts,
13642
- declared: dependency
13643
- }, ["安装固定 profile 对应的 SDK;发布包的 contracts 依赖必须为精确版本。"]);
13644
- const contracts = await sdkContractsMetadata(path, root);
13645
- assertInstalledPackage(contracts, PACKAGES.contracts, toolchain.profile.contracts, root);
13646
- installed.contracts = contracts.version;
13647
- }
13712
+ for (const name of ["@dp-bohrium/widget-contracts", "@dp-bohrium/widget-cli"]) if ([
13713
+ "dependencies",
13714
+ "optionalDependencies",
13715
+ "peerDependencies"
13716
+ ].some((section) => actual[section]?.[name] !== void 0)) throw failure("PROJECT_SDK_MISMATCH", "工程 SDK 仍包含独立协议或 CLI 运行依赖,不符合当前自包含发布契约", {
13717
+ projectRoot: root,
13718
+ package: name
13719
+ }, ["安装当前自包含 SDK 包,再重新构建。"]);
13720
+ await assertEmbeddedProtocol(path, toolchain, root);
13648
13721
  }
13649
13722
  return {
13650
13723
  projectRoot: root,
13651
13724
  profile: { ...toolchain.profile },
13652
13725
  declared,
13653
13726
  installed,
13654
- deprecations: declared.contracts ? [{
13655
- code: "WIDGET_CLI_DIRECT_CONTRACTS_DEPRECATED",
13656
- message: "独立消费者直接声明 contracts 的旧入口已废弃,将在统一入口切换发布 R1 前移除;协议类型与资产改从 SDK 导入。",
13657
- replacement: {
13658
- package: PACKAGES.sdk,
13659
- entryPoints: [
13660
- ".",
13661
- "./contracts",
13662
- "./schemas/*.json",
13663
- "./conformance/*"
13664
- ]
13665
- },
13666
- removal: {
13667
- release: "R1",
13668
- phase: "before-publish",
13669
- policyDocument: "docs/plans/2026-10-29-widget-sdk-forge-unified-entry.md",
13670
- prerequisites: [
13671
- "unified-sdk-entries-deliverable",
13672
- "agent-guided-project-migration-ready",
13673
- "bohr-and-hosts-upgraded"
13674
- ]
13675
- },
13676
- migration: {
13677
- status: "agent-guided",
13678
- project: "migrate project plan/apply",
13679
- candidateRequired: true
13680
- },
13681
- recovery: ["先核实目标 SDK 的统一出口已公开,再迁移类型和 Schema 导入、删除工程直接 contracts 依赖,并重新安装、构建、校验和打包。", "由 Agent 或开发者依据当前 SDK 准备候选,再用 migrate project plan --candidate 只读审阅差异,确认 canApply 后在新目录 apply;不自动改写源码或依赖,adopt 只补锁。"]
13682
- }] : [],
13727
+ deprecations: [],
13683
13728
  dependenciesVerified: requireInstalled,
13684
13729
  lock
13685
13730
  };
@@ -13689,10 +13734,10 @@ async function writeProjectToolchain(projectRoot, toolchain) {
13689
13734
  const existing = await readLock(root, toolchain, false);
13690
13735
  if (existing) return existing;
13691
13736
  const value = {
13692
- formatVersion: 1,
13737
+ formatVersion: 2,
13693
13738
  profileId: toolchain.profile.id,
13694
13739
  sdk: toolchain.profile.sdk,
13695
- contracts: toolchain.profile.contracts,
13740
+ protocol: toolchain.protocol,
13696
13741
  createdWithCli: toolchain.cli
13697
13742
  };
13698
13743
  await mkdir(root, { recursive: true });
@@ -13733,6 +13778,7 @@ function receiptToolchain(toolchain) {
13733
13778
  return {
13734
13779
  cli: toolchain.cli,
13735
13780
  profile: toolchain.profile,
13781
+ protocol: toolchain.protocol,
13736
13782
  digests: toolchain.digests
13737
13783
  };
13738
13784
  }
@@ -13777,7 +13823,7 @@ async function writeBuildReceipt(projectRoot, toolchain, { inputsBefore } = {})
13777
13823
  const outputs = await fingerprint(result.projectRoot, { outputs: true });
13778
13824
  if (outputs.files.length === 0) throw failure("BUILD_RECEIPT_MISMATCH", "构建目录 dist 没有可记录的产物", { projectRoot: result.projectRoot }, ["执行标准 build,确认 dist 产物存在后再打包。"]);
13779
13825
  const receipt = {
13780
- formatVersion: 1,
13826
+ formatVersion: 2,
13781
13827
  toolchain: receiptToolchain(toolchain),
13782
13828
  dependencies: result.installed,
13783
13829
  inputs,
@@ -13796,7 +13842,7 @@ async function assertBuildReceipt(projectRoot, toolchain) {
13796
13842
  };
13797
13843
  const receipt = await json(join(root, BUILD_RECEIPT_FILE), "BUILD_RECEIPT_MISMATCH", ["先执行 bohr-widget build,或去掉 pack 的 --no-build。"]);
13798
13844
  const project = await validateProjectToolchain(root, toolchain);
13799
- if (!record$1(receipt) || receipt.formatVersion !== 1 || JSON.stringify(receipt.toolchain) !== JSON.stringify(receiptToolchain(toolchain)) || JSON.stringify(receipt.dependencies) !== JSON.stringify(project.installed)) mismatch("receipt 工具链或实际依赖与本次执行不一致");
13845
+ if (!record$1(receipt) || receipt.formatVersion !== 2 || JSON.stringify(receipt.toolchain) !== JSON.stringify(receiptToolchain(toolchain)) || JSON.stringify(receipt.dependencies) !== JSON.stringify(project.installed)) mismatch("receipt 工具链或实际依赖与本次执行不一致");
13800
13846
  let inputs;
13801
13847
  let outputs;
13802
13848
  try {
@@ -14447,7 +14493,6 @@ export { activate };
14447
14493
  name: "files.read",
14448
14494
  limits: {
14449
14495
  bytesPerRequest: 65536,
14450
- bytesPerRun: 262144,
14451
14496
  callsPerMinute: 60
14452
14497
  }
14453
14498
  }
@@ -14570,12 +14615,11 @@ function getSchemaPath(name = "widget-manifest.schema.json") {
14570
14615
  const toolchain = getToolchain();
14571
14616
  const packageJson = { version: toolchain.cli };
14572
14617
  const sdkPackage = { version: toolchain.profile.sdk };
14573
- const contractsPackage = { version: toolchain.profile.contracts };
14574
14618
  function usage(path = []) {
14575
14619
  return renderHelp(path, {
14576
14620
  cli: packageJson.version,
14577
14621
  sdk: sdkPackage.version,
14578
- contracts: contractsPackage.version,
14622
+ protocol: toolchain.protocol,
14579
14623
  packageName: toolchain.packageName,
14580
14624
  documentation: getDocumentation(),
14581
14625
  generatedProjectNode: GENERATED_PROJECT_NODE
@@ -14726,7 +14770,7 @@ async function commandIntegration(options) {
14726
14770
  const result = {
14727
14771
  ok: true,
14728
14772
  command: "integration",
14729
- interfaceVersion: 2,
14773
+ interfaceVersion: 3,
14730
14774
  requirements: {
14731
14775
  node: ">=20",
14732
14776
  generatedProjectNode: GENERATED_PROJECT_NODE
@@ -15294,9 +15338,9 @@ async function commandPack(directory, options) {
15294
15338
  const warnings = [];
15295
15339
  if (options.includePreviewFixtures && !hasFixtures) warnings.push("使用了 --include-preview-fixtures,但 preview/fixtures.json 不存在,ZIP 未包含任何 fixtures。");
15296
15340
  else if (hasFixtures && !options.includePreviewFixtures) warnings.push("工程包含 preview/fixtures.json,未使用 --include-preview-fixtures,ZIP 未包含 fixtures。");
15297
- const files = collectWidgetPackageFiles(result, { includePreviewFixtures: fixturesIncluded });
15298
- warnings.push(...oversizedAssetWarnings(files));
15299
- const bundle = storedZip(files);
15341
+ const prepared = prepareWidgetPackage(result, { includePreviewFixtures: fixturesIncluded });
15342
+ warnings.push(...oversizedAssetWarnings(prepared.files));
15343
+ const bundle = prepared.archive;
15300
15344
  await mkdir(dirname(destination), { recursive: true });
15301
15345
  await writeFile(destination, bundle);
15302
15346
  const artifact = {
@@ -15304,12 +15348,12 @@ async function commandPack(directory, options) {
15304
15348
  command: "pack",
15305
15349
  projectRoot: result.projectRoot,
15306
15350
  path: destination,
15307
- bytes: bundle.byteLength,
15308
- sha256: `sha256:${createHash("sha256").update(bundle).digest("hex")}`,
15351
+ bytes: prepared.bytes,
15352
+ sha256: prepared.sha256,
15309
15353
  toolchain: {
15310
15354
  cli: packageJson.version,
15311
15355
  sdk: sdkPackage.version,
15312
- contracts: contractsPackage.version
15356
+ protocol: toolchain.protocol
15313
15357
  },
15314
15358
  ...compatibility,
15315
15359
  hostCompatibility: await assertHostCompatibility(options.hostCompat, toolchain),
@@ -15365,10 +15409,7 @@ async function commandMigrate(positional, options) {
15365
15409
  if (action === "scaffold") {
15366
15410
  if (!options.output) throw new Error("migrate dsh scaffold 需要 --out <widget-dir>");
15367
15411
  const hostCompatibility = await assertHostCompatibility(options.hostCompat, toolchain);
15368
- const result = await scaffoldDshWidget(input, options.output, {
15369
- sdkVersion: sdkPackage.version,
15370
- contractsVersion: contractsPackage.version
15371
- });
15412
+ const result = await scaffoldDshWidget(input, options.output, { sdkVersion: sdkPackage.version });
15372
15413
  await writeProjectToolchain(result.projectRoot, toolchain);
15373
15414
  result.profile = toolchain.profile;
15374
15415
  result.hostCompatibility = hostCompatibility;
@@ -15387,7 +15428,7 @@ async function commandDoctor(directory, options) {
15387
15428
  cli: packageJson.version,
15388
15429
  node: process.versions.node,
15389
15430
  sdk: sdkPackage.version,
15390
- contracts: contractsPackage.version,
15431
+ protocol: toolchain.protocol,
15391
15432
  project: root,
15392
15433
  packageJson: existsSync(packagePath),
15393
15434
  manifest: existsSync(manifestPath),
@@ -15462,7 +15503,7 @@ function commandVersion(options) {
15462
15503
  command: "version",
15463
15504
  cli: packageJson.version,
15464
15505
  sdk: sdkPackage.version,
15465
- contracts: contractsPackage.version
15506
+ protocol: toolchain.protocol
15466
15507
  };
15467
15508
  if (options.json) console.log(JSON.stringify(result, null, 2));
15468
15509
  else console.log(`${result.cli} (SDK ${result.sdk})`);
@@ -1,2 +1,2 @@
1
1
  /** 完整协议保持独立子入口,避免与作者接口的同名类型混用。 */
2
- export * from "@dp-bohrium/widget-contracts";
2
+ export * from "./protocol/index.js";
package/dist/contracts.js CHANGED
@@ -1 +1,2 @@
1
- export * from "@dp-bohrium/widget-contracts";
1
+ import { i as isWidgetActivationEvent, n as isWidgetEventName, r as WIDGET_ACTIVATION_EVENTS, t as WIDGET_EVENT_NAMES } from "./widget-events-BT0QxR-H.js";
2
+ export { WIDGET_ACTIVATION_EVENTS, WIDGET_EVENT_NAMES, isWidgetActivationEvent, isWidgetEventName };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export type { CapabilityRequest, CapabilityResult, FileDownloadResult, FileMutationId, FilePreviewContent, FilePreviewRenderRequest, FileReadInput, FileReadResult, FileReference, FileRevision, FileWriteInput, FileWriteResult, GrantedCapability, JsonValue, PanelContent, PanelRenderRequest, RenderRequest, RenderState, TaskObservationBatch, TaskObservationEvent, TaskObservationSnapshot, Theme, ThemeMode, WidgetActivationEvent, WidgetActivationEvents, WidgetContribution, WidgetError, WidgetErrorCode, WidgetEventName, WidgetFilePreviewContribution, WidgetLiveEvent, WidgetNetworkFetchInput, WidgetNetworkFetchOutput, WidgetPanelContribution, WidgetPluginContributions, WidgetPluginManifest, WidgetToolPhase, } from "@dp-bohrium/widget-contracts";
2
- export { isWidgetActivationEvent, isWidgetEventName, WIDGET_ACTIVATION_EVENTS, WIDGET_EVENT_NAMES, } from "@dp-bohrium/widget-contracts";
1
+ export type { CapabilityRequest, CapabilityResult, FileDownloadResult, FileMutationId, FilePreviewContent, FilePreviewRenderRequest, FileReadInput, FileReadResult, FileReference, FileRevision, FileWriteInput, FileWriteResult, GrantedCapability, JsonValue, PanelContent, PanelRenderRequest, RenderRequest, RenderState, TaskObservationBatch, TaskObservationEvent, TaskObservationSnapshot, Theme, ThemeMode, WidgetActivationEvent, WidgetActivationEvents, WidgetContribution, WidgetError, WidgetErrorCode, WidgetEventName, WidgetFilePreviewContribution, WidgetLiveEvent, WidgetNetworkFetchInput, WidgetNetworkFetchOutput, WidgetPanelContribution, WidgetPluginContributions, WidgetPluginManifest, WidgetToolPhase, } from "./protocol/index.js";
2
+ export { isWidgetActivationEvent, isWidgetEventName, WIDGET_ACTIVATION_EVENTS, WIDGET_EVENT_NAMES, } from "./protocol/index.js";
3
3
  export type { CompileWidgetPluginManifestOptions } from "./manifest.js";
4
4
  export { compileWidgetPluginManifest } from "./manifest.js";
5
5
  export type { HostUserEmail, HostUserEmailResult, HostUserProfile, HostUserProfileResult, WidgetHostUserClient, } from "./runtime/service.js";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { i as createWidgetClient, l as WIDGET_SDK_VERSION } from "./runtime-D7KxTtdu.js";
2
- import { WIDGET_ACTIVATION_EVENTS, WIDGET_EVENT_NAMES, isWidgetActivationEvent, isWidgetEventName } from "@dp-bohrium/widget-contracts";
3
- //#region src/manifest.ts
1
+ import { i as isWidgetActivationEvent, n as isWidgetEventName, r as WIDGET_ACTIVATION_EVENTS, t as WIDGET_EVENT_NAMES } from "./widget-events-BT0QxR-H.js";
2
+ import { i as createWidgetClient, l as WIDGET_SDK_VERSION } from "./runtime-DZA7Gqzl.js";
3
+ //#region ../widget-project/src/manifest-compiler.mjs
4
4
  function compiledContribution(contribution) {
5
5
  switch (contribution.type) {
6
6
  case "panel": return {
@@ -14,13 +14,8 @@ function compiledContribution(contribution) {
14
14
  };
15
15
  }
16
16
  }
17
- /**
18
- * 将开发者维护的插件清单编译为宿主可加载的宿主清单。
19
- *
20
- * 这是构建工具的边界函数,不是类型提示入口:作者直接编辑带 `$schema` 的 JSON,
21
- * SDK 版本从当前安装包读取,宿主入口默认落到 dist/widget.js,内部 contribution 标识只在这里生成。
22
- */
23
- function compileWidgetPluginManifest(manifest, options = {}) {
17
+ /** 只编译协议数据;SDK 版本由可信调用方绑定,不读取安装或执行环境。 */
18
+ function compileWidgetPluginManifest$1(manifest, sdkVersion, options = {}) {
24
19
  const samples = options.samples ?? manifest.samples;
25
20
  if (!samples || samples.length === 0) throw new Error("Widget Plugin Manifest must provide at least one sample before packaging");
26
21
  const contribution = manifest.contributes.widget;
@@ -32,7 +27,7 @@ function compileWidgetPluginManifest(manifest, options = {}) {
32
27
  widgetConfig: {
33
28
  schemaVersion: 1,
34
29
  hostApiVersion: 1,
35
- widgetSdkVersion: WIDGET_SDK_VERSION,
30
+ widgetSdkVersion: sdkVersion,
36
31
  entry: options.hostEntry ?? "dist/widget.js",
37
32
  contribution: compiledContribution(manifest.contributes.widget),
38
33
  ...activationEvents === void 0 ? {} : { activationEvents },
@@ -43,6 +38,17 @@ function compileWidgetPluginManifest(manifest, options = {}) {
43
38
  };
44
39
  }
45
40
  //#endregion
41
+ //#region src/manifest.ts
42
+ /**
43
+ * 将开发者维护的插件清单编译为宿主可加载的宿主清单。
44
+ *
45
+ * 这是构建工具的边界函数,不是类型提示入口:作者直接编辑带 `$schema` 的 JSON,
46
+ * SDK 版本从当前安装包读取,宿主入口默认落到 dist/widget.js,内部 contribution 标识只在这里生成。
47
+ */
48
+ function compileWidgetPluginManifest(manifest, options = {}) {
49
+ return compileWidgetPluginManifest$1(manifest, WIDGET_SDK_VERSION, options);
50
+ }
51
+ //#endregion
46
52
  //#region src/lifetime.ts
47
53
  function createWidgetLifetime(onError) {
48
54
  const controller = new AbortController();
@@ -1,4 +1,4 @@
1
- import type { WidgetManifest, WidgetPluginManifest } from "@dp-bohrium/widget-contracts";
1
+ import type { WidgetManifest, WidgetPluginManifest } from "./protocol/index.js";
2
2
  export interface CompileWidgetPluginManifestOptions {
3
3
  readonly samples?: NonNullable<WidgetPluginManifest["samples"]>;
4
4
  /** Host bundle entry. CLI supplies this after the project is built. */