@pab-iprg/huohuo 1.0.0-preview.7 → 1.0.0-preview.9

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 (4) hide show
  1. package/README.md +3 -0
  2. package/cli.js +126 -10
  3. package/package.json +4 -4
  4. package/release.json +21 -21
package/README.md CHANGED
@@ -31,3 +31,6 @@ npx.cmd --yes --prefer-online @pab-iprg/huohuo@preview
31
31
  ```
32
32
 
33
33
  默认目录无需手动填写。需要独立试用目录时,CMD 使用 `--home "%USERPROFILE%\.huohuo-windows-trial-01"`,PowerShell 使用 `--home "$env:USERPROFILE\.huohuo-windows-trial-01"`。程序内部使用系统自带 PowerShell 采样,不要求用户用 PowerShell 启动。两种终端的首装、Ctrl+C、再次启动及数据保留均需分别实机验收。
34
+
35
+
36
+ 平台静态资源缺失、版本不匹配或损坏时,入口会自动补齐该固定版本并核对发行摘要,普通用户无需追加可选依赖、registry或cache参数。恢复只操作火火的受管资源缓存,不执行资源包脚本、不改变npm全局配置,继续原来固定的安装版本。
package/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // distribution/bootstrap/entry.ts
4
- import { open as open3, readFile as readFile9, realpath as realpath5 } from "node:fs/promises";
4
+ import { open as open4, readFile as readFile9, realpath as realpath5 } from "node:fs/promises";
5
5
  import { Readable } from "node:stream";
6
6
  import { homedir as homedir2 } from "node:os";
7
7
  import { dirname as dirname6, join as join9, resolve as resolve5 } from "node:path";
@@ -377,7 +377,7 @@ async function transfer(artifact2, path, source, fetcher, onBytes) {
377
377
  timer.unref();
378
378
  };
379
379
  const signal = AbortSignal.any([idle.signal, AbortSignal.timeout(30 * 6e4)]);
380
- keepAlive();
380
+ if (!artifact2.bundled) keepAlive();
381
381
  try {
382
382
  const response = await requestSource(artifact2, source, fetcher, signal, "GET", keepAlive);
383
383
  if (!response.ok || !response.body) {
@@ -420,7 +420,7 @@ function safePath(root, path) {
420
420
  if (target !== root && !target.startsWith(root + sep)) throw new Error("\u538B\u7F29\u5305\u8DEF\u5F84\u8D8A\u754C");
421
421
  return target;
422
422
  }
423
- async function extractArchive(archive, root, expandedLimit) {
423
+ async function extractArchive(archive, root, expandedLimit, allowedFiles) {
424
424
  root = resolve(root);
425
425
  await mkdir2(root, { mode: 448 });
426
426
  root = await realpath(root);
@@ -469,6 +469,11 @@ async function extractArchive(archive, root, expandedLimit) {
469
469
  } else {
470
470
  const prefix = string(header.subarray(345, 500));
471
471
  const name = pax.path ?? (prefix ? prefix + "/" : "") + string(header.subarray(0, 100));
472
+ if (allowedFiles) {
473
+ const directory = name.replace(/\/+$/, "");
474
+ const allowed = kind === "0" ? allowedFiles.has(name) : kind === "5" && [...allowedFiles].some((path) => path.startsWith(directory + "/"));
475
+ if (!allowed) throw new Error("\u5B89\u88C5\u8D44\u6E90\u538B\u7F29\u5305\u542B\u672A\u5141\u8BB8\u7684\u6587\u4EF6\u6216\u94FE\u63A5");
476
+ }
472
477
  const target = safePath(root, name);
473
478
  const linkText = pax.linkpath ?? string(header.subarray(157, 257));
474
479
  if (Object.keys(pax).some((key) => /sparse|size/i.test(key))) throw new Error("\u4E0D\u652F\u6301\u7A00\u758F\u6216\u6539\u5199\u5927\u5C0F\u7684\u538B\u7F29\u5305");
@@ -1571,7 +1576,8 @@ async function showStatus(home, watch) {
1571
1576
 
1572
1577
  // distribution/bootstrap/assets.ts
1573
1578
  import { createRequire } from "node:module";
1574
- import { readFile as readFile8 } from "node:fs/promises";
1579
+ import { readFile as readFile8, mkdir as mkdir4, mkdtemp, open as open3, rename as rename5, rm as rm5, lstat as lstat3 } from "node:fs/promises";
1580
+ import { createHash as createHash3 } from "node:crypto";
1575
1581
  import { dirname as dirname5, join as join8 } from "node:path";
1576
1582
  import { fileURLToPath } from "node:url";
1577
1583
  async function assetsDirectory(release, entryURL = import.meta.url) {
@@ -1589,18 +1595,127 @@ async function assetsDirectory(release, entryURL = import.meta.url) {
1589
1595
  }
1590
1596
  return join8(dirname5(file), "assets");
1591
1597
  }
1598
+ var recovering = /* @__PURE__ */ new Map();
1599
+ async function bundledAssetPath(release, artifact2, home, options = {}) {
1600
+ const localFile = async () => join8(await assetsDirectory(release, options.entryURL), artifact2.sha256 + ".tgz");
1601
+ if (!release.assetPackage) return localFile();
1602
+ const expected = release.assetPackage;
1603
+ if (expected.name !== `@pab-iprg/huohuo-assets-${release.platform.os}-${release.platform.arch}` || !/^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/.test(expected.version) || ![release.runtime, release.pythonDependencies].some((a) => a.bundled && a.sha256 === artifact2.sha256)) throw new Error("\u5E73\u53F0\u5B89\u88C5\u8D44\u6E90\u8EAB\u4EFD\u65E0\u6548");
1604
+ try {
1605
+ const file = await localFile();
1606
+ await verifyArtifact(file, artifact2);
1607
+ return file;
1608
+ } catch {
1609
+ }
1610
+ const key = createHash3("sha256").update(JSON.stringify([expected.name, expected.version, release.runtime.sha256, release.pythonDependencies.sha256])).digest("hex");
1611
+ const directory = join8(home, "cache", "platform-assets", key);
1612
+ let pending = recovering.get(directory);
1613
+ if (!pending) {
1614
+ pending = recoverCompanion(directory, release, options);
1615
+ recovering.set(directory, pending);
1616
+ void pending.finally(() => {
1617
+ if (recovering.get(directory) === pending) recovering.delete(directory);
1618
+ }).catch(() => {
1619
+ });
1620
+ }
1621
+ return join8(await pending, "assets", artifact2.sha256 + ".tgz");
1622
+ }
1623
+ async function validateCompanion(directory, release) {
1624
+ const meta = await lstat3(directory);
1625
+ if (!meta.isDirectory() || meta.isSymbolicLink()) throw new Error("\u5B89\u88C5\u8D44\u6E90\u7F13\u5B58\u8EAB\u4EFD\u65E0\u6548");
1626
+ const file = join8(directory, "package.json");
1627
+ if ((await lstat3(file)).size > 64 * 1024) throw new Error("\u5B89\u88C5\u8D44\u6E90\u6E05\u5355\u8FC7\u5927");
1628
+ const manifest = JSON.parse(await readFile8(file, "utf8"));
1629
+ if (manifest.name !== release.assetPackage.name || manifest.version !== release.assetPackage.version) throw new Error("\u5B89\u88C5\u8D44\u6E90\u8EAB\u4EFD\u6821\u9A8C\u672A\u901A\u8FC7");
1630
+ for (const artifact2 of [release.runtime, release.pythonDependencies]) await verifyArtifact(join8(directory, "assets", artifact2.sha256 + ".tgz"), artifact2);
1631
+ }
1632
+ async function recoverCompanion(directory, release, options) {
1633
+ try {
1634
+ await validateCompanion(directory, release);
1635
+ return directory;
1636
+ } catch {
1637
+ }
1638
+ const { name, version: version2 } = release.assetPackage;
1639
+ const basename = name.split("/")[1];
1640
+ const url = `https://registry.npmjs.org/${name}/-/${basename}-${encodeURIComponent(version2)}.tgz`;
1641
+ const limit = release.runtime.downloadBytes + release.pythonDependencies.downloadBytes + 128 * 1024;
1642
+ if (!Number.isSafeInteger(limit) || limit <= 0) throw new Error("\u5B89\u88C5\u8D44\u6E90\u5927\u5C0F\u65E0\u6548");
1643
+ const parent = dirname5(directory);
1644
+ await mkdir4(parent, { recursive: true, mode: 448 });
1645
+ const stage = await mkdtemp(join8(parent, ".recover-"));
1646
+ try {
1647
+ options.progress?.("\u6B63\u5728\u81EA\u52A8\u8865\u9F50\u5F53\u524D\u8BBE\u5907\u7684\u5B89\u88C5\u8D44\u6E90\u2026");
1648
+ const archive = join8(stage, "companion.tgz");
1649
+ await downloadCompanion(url, archive, limit, options.fetcher ?? fetch, options.signal);
1650
+ const unpacked = join8(stage, "unpacked");
1651
+ const allowed = /* @__PURE__ */ new Set([
1652
+ "package/package.json",
1653
+ "package/README.md",
1654
+ ...[release.runtime, release.pythonDependencies].map((a) => "package/assets/" + a.sha256 + ".tgz")
1655
+ ]);
1656
+ await extractArchive(archive, unpacked, limit, allowed);
1657
+ const root = join8(unpacked, "package");
1658
+ await validateCompanion(root, release);
1659
+ try {
1660
+ await rename5(directory, directory + ".invalid-" + stage.slice(-6));
1661
+ } catch (error) {
1662
+ if (error.code !== "ENOENT") throw error;
1663
+ }
1664
+ await rename5(root, directory);
1665
+ options.progress?.("\u5B89\u88C5\u8D44\u6E90\u5DF2\u8865\u9F50\u5E76\u6821\u9A8C\uFF0C\u7EE7\u7EED\u5B89\u88C5\u3002");
1666
+ return directory;
1667
+ } catch (error) {
1668
+ throw new Error("\u5B89\u88C5\u8D44\u6E90\u6682\u65F6\u672A\u80FD\u51C6\u5907\u597D\u3002\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u65B0\u8FD0\u884C\u540C\u4E00\u6761\u542F\u52A8\u547D\u4EE4\uFF0C\u5DF2\u5B8C\u6210\u7684\u6B65\u9AA4\u4F1A\u4FDD\u7559\u3002", { cause: error });
1669
+ } finally {
1670
+ await rm5(stage, { recursive: true, force: true });
1671
+ }
1672
+ }
1673
+ async function downloadCompanion(url, path, limit, fetcher, signal) {
1674
+ for (let attempt = 0; attempt < 2; attempt++) {
1675
+ const file = await open3(path, "w", 384);
1676
+ const idle = new AbortController();
1677
+ let timer;
1678
+ const touch = () => {
1679
+ clearTimeout(timer);
1680
+ timer = setTimeout(() => idle.abort(), 45e3);
1681
+ timer.unref();
1682
+ };
1683
+ touch();
1684
+ try {
1685
+ const response = await fetcher(url, { redirect: "error", signal: AbortSignal.any([idle.signal, AbortSignal.timeout(30 * 6e4), ...signal ? [signal] : []]) });
1686
+ if (!response.ok || !response.body) {
1687
+ await response.body?.cancel();
1688
+ throw new Error(`\u5B89\u88C5\u8D44\u6E90\u4E0B\u8F7D\u6682\u4E0D\u53EF\u7528\uFF08HTTP ${response.status}\uFF09`);
1689
+ }
1690
+ touch();
1691
+ let size = 0;
1692
+ for await (const chunk of response.body) {
1693
+ touch();
1694
+ size += chunk.byteLength;
1695
+ if (size > limit) throw new Error("\u5B89\u88C5\u8D44\u6E90\u8D85\u8FC7\u5927\u5C0F\u9650\u5236");
1696
+ await file.writeFile(chunk);
1697
+ }
1698
+ await file.sync();
1699
+ return;
1700
+ } catch (error) {
1701
+ if (attempt === 1 || signal?.aborted) throw error;
1702
+ } finally {
1703
+ clearTimeout(timer);
1704
+ await file.close();
1705
+ }
1706
+ }
1707
+ }
1592
1708
 
1593
1709
  // distribution/bootstrap/entry.ts
1594
- function artifactSource(source, directory) {
1710
+ function artifactSource(source, directory, home) {
1595
1711
  return async (url, options) => {
1596
1712
  const bundled = /^https:\/\/bundled\.invalid\/([a-f0-9]{64})\.tgz$/.exec(String(url));
1597
1713
  if (!directory && !bundled) return fetch(url, options);
1598
1714
  const artifact2 = source && [source.runtime, source.python, source.pythonDependencies].find((item) => item.url === String(url));
1599
1715
  const sha256 = bundled?.[1] ?? artifact2?.sha256;
1600
1716
  if (!sha256) throw new Error("\u672C\u673A\u4EA7\u7269\u76EE\u5F55\u7F3A\u5C11\u8BE5\u56FA\u5B9A\u53D1\u884C\u8D44\u6E90");
1601
- const root = directory ?? await assetsDirectory(source, import.meta.url);
1602
- const path = join9(root, sha256 + ".tgz");
1603
- const file = await open3(path).catch((error) => {
1717
+ const path = !directory && bundled && source && artifact2 && home ? await bundledAssetPath(source, artifact2, home, { entryURL: import.meta.url, signal: options?.signal ?? void 0, progress: (message) => console.log(message) }) : join9(directory ?? await assetsDirectory(source, import.meta.url), sha256 + ".tgz");
1718
+ const file = await open4(path).catch((error) => {
1604
1719
  if (error.code === "ENOENT" && bundled) throw new Error("\u7F3A\u5C11\u4E0A\u6B21\u5B89\u88C5\u4F7F\u7528\u7684\u6587\u4EF6\u3002\u8BF7\u7528\u4E0A\u6B21\u5B89\u88C5\u65F6\u7684\u7248\u672C\u7EE7\u7EED\u3002");
1605
1720
  throw error;
1606
1721
  });
@@ -1656,7 +1771,7 @@ async function main(args = process.argv.slice(2)) {
1656
1771
  const ui = installUI(assumeYes);
1657
1772
  if (command === "upgrade") {
1658
1773
  const candidate = selectRelease(JSON.parse(await readFile9(releaseFile ?? join9(dirname6(fileURLToPath2(import.meta.url)), "release.json"), "utf8")));
1659
- await upgrade(home, candidate, { fetcher: artifactSource(candidate, artifactDirectory), progress, ...ui });
1774
+ await upgrade(home, candidate, { fetcher: artifactSource(candidate, artifactDirectory, home), progress, ...ui });
1660
1775
  const current = await readInstallation(home);
1661
1776
  if (await control(home, current.releaseDigest, noOpen ? "status" : "open")) return;
1662
1777
  await run(process.execPath, [join9(installationPaths(home, current.release).runtime, "lib/distribution/managed.js"), "start", home, ...noOpen ? ["--no-open"] : []], home, process.env, () => control(home, current.releaseDigest, "stop"));
@@ -1716,7 +1831,7 @@ async function main(args = process.argv.slice(2)) {
1716
1831
  }
1717
1832
  source = selectRelease(catalog);
1718
1833
  }
1719
- const fetcher = artifactSource(source, artifactDirectory);
1834
+ const fetcher = artifactSource(source, artifactDirectory, home);
1720
1835
  record = await install(home, source, { fetcher, progress, ...ui });
1721
1836
  }
1722
1837
  const installedHome = record.home;
@@ -1729,5 +1844,6 @@ if (process.argv[1] && await realpath5(resolve5(process.argv[1])).catch(() => ""
1729
1844
  });
1730
1845
  }
1731
1846
  export {
1847
+ artifactSource,
1732
1848
  main
1733
1849
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pab-iprg/huohuo",
3
- "version": "1.0.0-preview.7",
3
+ "version": "1.0.0-preview.9",
4
4
  "type": "module",
5
5
  "description": "火火多平台安装入口(实验预览)",
6
6
  "bin": {
@@ -15,9 +15,9 @@
15
15
  "README.md"
16
16
  ],
17
17
  "optionalDependencies": {
18
- "@pab-iprg/huohuo-assets-darwin-arm64": "1.0.0-preview.7",
19
- "@pab-iprg/huohuo-assets-linux-x64": "1.0.0-preview.7",
20
- "@pab-iprg/huohuo-assets-win32-x64": "1.0.0-preview.7"
18
+ "@pab-iprg/huohuo-assets-darwin-arm64": "1.0.0-preview.9",
19
+ "@pab-iprg/huohuo-assets-linux-x64": "1.0.0-preview.9",
20
+ "@pab-iprg/huohuo-assets-win32-x64": "1.0.0-preview.9"
21
21
  },
22
22
  "publishConfig": {
23
23
  "access": "public",
package/release.json CHANGED
@@ -18,12 +18,12 @@
18
18
  "runtime": {
19
19
  "name": "@huohuo/research-agent",
20
20
  "version": "1.0.0",
21
- "url": "https://bundled.invalid/32e96855b2579f293877c67dc6c5645b2b1fb4e9300f70f3e7a783a6d67a4120.tgz",
21
+ "url": "https://bundled.invalid/0ead244c81e77cb5e63cca3b694d7e906f1fc256b4c4029fd9e40e997f9acf60.tgz",
22
22
  "bundled": true,
23
- "sha256": "32e96855b2579f293877c67dc6c5645b2b1fb4e9300f70f3e7a783a6d67a4120",
24
- "integrity": "sha512-6IAa0KnmqVFw7Z6ogyyLlaeOCHCFPJ7VxMIz7nzemffiZwBYGt8+SvNjkk4CWKzjtJppYQQl2NAPooqZ6keteg==",
25
- "downloadBytes": 2613970,
26
- "expandedBytes": 8341044
23
+ "sha256": "0ead244c81e77cb5e63cca3b694d7e906f1fc256b4c4029fd9e40e997f9acf60",
24
+ "integrity": "sha512-hUKZrQT2/Cq6eN5G6r8+eWdaVjeln/FfwEkcPrwOH5uLHr5EU6BgH7iwQq9XjVhn6PuARGZsNbx61FLcYvglag==",
25
+ "downloadBytes": 2616628,
26
+ "expandedBytes": 8352928
27
27
  },
28
28
  "python": {
29
29
  "url": "https://github.com/astral-sh/python-build-standalone/releases/download/20261026/cpython-3.13.18%2B20261026-aarch64-apple-darwin-install_only_stripped.tar.gz",
@@ -50,7 +50,7 @@
50
50
  "assemblySha256": "08cf11de70e49981b4891c0aaa2a5e7b872a95b6aa07557bb629713fa8f9e249"
51
51
  },
52
52
  "requirementsSha256": "57042fff45cee66fe33712472e2e5b88f03a084068ca20242588b2e18b3e167b",
53
- "profilesSha256": "fb3540e0d604f26280128a21f97313575848f6348733a221f7e230233fdb8e2d",
53
+ "profilesSha256": "52731340a5f899fe1440a626aab358819f2cf456c4afc59f8f772e740e10775d",
54
54
  "budget": {
55
55
  "minimumEffectiveMemoryBytes": 34359738368,
56
56
  "startupHeadroomBytes": 134217728,
@@ -99,7 +99,7 @@
99
99
  },
100
100
  "assetPackage": {
101
101
  "name": "@pab-iprg/huohuo-assets-darwin-arm64",
102
- "version": "1.0.0-preview.7"
102
+ "version": "1.0.0-preview.9"
103
103
  }
104
104
  },
105
105
  {
@@ -118,12 +118,12 @@
118
118
  "runtime": {
119
119
  "name": "@huohuo/research-agent",
120
120
  "version": "1.0.0",
121
- "url": "https://bundled.invalid/79cbf018a4363d256fee64f07dc3cd8e434ef1e89ba1dcfdcbdf4c2b0a424f65.tgz",
121
+ "url": "https://bundled.invalid/1e1096f83db29bda41a2d8e191c261022f5f468ac22ebc50208e0744a4c10f85.tgz",
122
122
  "bundled": true,
123
- "sha256": "79cbf018a4363d256fee64f07dc3cd8e434ef1e89ba1dcfdcbdf4c2b0a424f65",
124
- "integrity": "sha512-8KMx3WCkkFxvcD6XQcV7N9FNTgU/Q5SNezCkyJizOnlT4lt4bqWdbxlBfhRcTiVmaP2/3PjsyzFDB1KEaaev3g==",
125
- "downloadBytes": 2613972,
126
- "expandedBytes": 8341062
123
+ "sha256": "1e1096f83db29bda41a2d8e191c261022f5f468ac22ebc50208e0744a4c10f85",
124
+ "integrity": "sha512-DJ0sZm+4fVOrHmoPREQxFKxUfUk67UBavxCHx3o5yG94wA9woWD6cFJTqWbP7sB4MJAlGOIteQfWqwbXJA6z7w==",
125
+ "downloadBytes": 2616631,
126
+ "expandedBytes": 8352946
127
127
  },
128
128
  "python": {
129
129
  "url": "https://github.com/astral-sh/python-build-standalone/releases/download/20261026/cpython-3.13.18%2B20261026-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz",
@@ -150,7 +150,7 @@
150
150
  "assemblySha256": "08cf11de70e49981b4891c0aaa2a5e7b872a95b6aa07557bb629713fa8f9e249"
151
151
  },
152
152
  "requirementsSha256": "d4ff8161886fc286e6f8ddfcd070ac5812528971affe7b87baa03662dd242d45",
153
- "profilesSha256": "fb3540e0d604f26280128a21f97313575848f6348733a221f7e230233fdb8e2d",
153
+ "profilesSha256": "52731340a5f899fe1440a626aab358819f2cf456c4afc59f8f772e740e10775d",
154
154
  "budget": {
155
155
  "minimumEffectiveMemoryBytes": 8589934592,
156
156
  "startupHeadroomBytes": 1073741824,
@@ -198,7 +198,7 @@
198
198
  },
199
199
  "assetPackage": {
200
200
  "name": "@pab-iprg/huohuo-assets-linux-x64",
201
- "version": "1.0.0-preview.7"
201
+ "version": "1.0.0-preview.9"
202
202
  }
203
203
  },
204
204
  {
@@ -216,12 +216,12 @@
216
216
  "runtime": {
217
217
  "name": "@huohuo/research-agent",
218
218
  "version": "1.0.0",
219
- "url": "https://bundled.invalid/32f67fca6cae53021035f6b972953335a657357907620c1fa5a618290cc552eb.tgz",
219
+ "url": "https://bundled.invalid/8e28336eb95556ea35986d3e6940942f6ce1980995c5786e3b9119905c4ac5f3.tgz",
220
220
  "bundled": true,
221
- "sha256": "32f67fca6cae53021035f6b972953335a657357907620c1fa5a618290cc552eb",
222
- "integrity": "sha512-NVB0sYN/W8BWmBu6ShAl75t8jncWzSprwQ5NfS1k6M6KzJtqY+oEY/zQYZz500W6/na2yzCJC6TKmkxCugXfwA==",
223
- "downloadBytes": 2613974,
224
- "expandedBytes": 8341060
221
+ "sha256": "8e28336eb95556ea35986d3e6940942f6ce1980995c5786e3b9119905c4ac5f3",
222
+ "integrity": "sha512-PUKRGwsMTL3nJwUzNU3kpGPu+rrMB8cjKye1WTM8msqbQhlDauSOevnsGwDY6UYGtVgEP1uuGhAU5r0wsACXcA==",
223
+ "downloadBytes": 2616635,
224
+ "expandedBytes": 8352944
225
225
  },
226
226
  "python": {
227
227
  "url": "https://github.com/astral-sh/python-build-standalone/releases/download/20261026/cpython-3.13.18%2B20261026-x86_64-pc-windows-msvc-install_only_stripped.tar.gz",
@@ -248,7 +248,7 @@
248
248
  "assemblySha256": "08cf11de70e49981b4891c0aaa2a5e7b872a95b6aa07557bb629713fa8f9e249"
249
249
  },
250
250
  "requirementsSha256": "acb5dea55d39bda017e8c63c70fcfcd5dfb74eb987376d4612161257a9fd0900",
251
- "profilesSha256": "fb3540e0d604f26280128a21f97313575848f6348733a221f7e230233fdb8e2d",
251
+ "profilesSha256": "52731340a5f899fe1440a626aab358819f2cf456c4afc59f8f772e740e10775d",
252
252
  "budget": {
253
253
  "minimumEffectiveMemoryBytes": 4294967296,
254
254
  "startupHeadroomBytes": 536870912,
@@ -296,7 +296,7 @@
296
296
  },
297
297
  "assetPackage": {
298
298
  "name": "@pab-iprg/huohuo-assets-win32-x64",
299
- "version": "1.0.0-preview.7"
299
+ "version": "1.0.0-preview.9"
300
300
  }
301
301
  }
302
302
  ]