@pab-iprg/huohuo 1.0.0-preview.4 → 1.0.0-preview.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 火火轻量入口(本地开发候选)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
此目录是 `@pab-iprg/huohuo` 的私有构建模板。入口代码只使用 Node 内置模块;npm 按 OS/CPU 选择同版本的静态资源包,资源包不含安装脚本。设备预检前只准备入口和对应平台的压缩资源,不安装 DSH 或 Python。源码具备某个平台的选择逻辑,不代表该平台已完成实机验收。
|
|
4
4
|
|
|
5
|
-
构建时需要已完成平台测量与摘要绑定的 `release.json
|
|
5
|
+
构建时需要已完成平台测量与摘要绑定的 `release.json`,可以是旧版单平台清单,也可以是包含多个同版本发行的索引。首次安装与显式升级只选择本机系统/CPU 对应的发行,再按需下载运行包、独立 Python 和固定 wheels;其他平台的大包不下载。Linux 索引条目目前只接受 glibc,未收录的平台提前提示。没有完整发行清单时明确停止。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
运行 npx 前仍需安装兼容的 Node/npm(当前入口要求 Node 24.8+,具体 Node 主版本由所选发行固定)。运行环境在用户目录中准备,不替换系统 Python;已校验的下载缓存会复用。Python 和 wheels 在构建端选定版本及 SHA;npm 预览包携带下载清单和构建好的 jsonpath wheel,其余 wheel 按固定上游 URL 下载并校验,不在用户机器编译。仍兼容旧的完整离线 wheel 包;npm 依赖按运行包锁文件安装。
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
发行清单可为同一份固定资源配置备用 HTTPS 地址。确认安装后会探测这些地址,优先从响应较快的可用地址下载,并核对同一个 SHA-256。只有一个已核验来源时,网络中断会自动重试一次。npm 和 pip 仍会按各自的依赖清单安装。
|
|
12
|
-
|
|
13
|
-
命令支持 `huohuo [start|status|doctor|stop|upgrade|uninstall] [--home 目录] [--no-open]`。在另一个终端运行 `npx --yes @pab-iprg/huohuo@next status --watch` 可打开实时状态看板,按 Ctrl+C 退出看板。
|
|
9
|
+
当前开发入口:`huohuo [start|status|doctor|stop|upgrade|uninstall] [--home 目录] [--no-open]`。`status --watch` 持续显示进度;安装前展示资源计划,`--yes` 可显式确认。默认持久目录 `~/.huohuo`;普通重开保留已安装版本,安装中断继续原目标。npx 缓存保存入口和所选平台资源;再次解析最新入口可能联网。
|
|
14
10
|
|
|
15
11
|
显式升级检查旧迁移不可变、追加迁移顺序、执行库格式与 DSH 会话兼容范围,先一致性备份再迁移和验证,成功后切换;不自动恢复旧备份覆盖新数据。默认卸载保留实例、凭据、会话和备份,不提供直接彻底删除业务数据的快捷入口。
|
|
16
12
|
|
package/cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// distribution/bootstrap/entry.ts
|
|
4
|
-
import { open as open3, readFile as
|
|
4
|
+
import { open as open3, readFile as readFile9, realpath as realpath5 } from "node:fs/promises";
|
|
5
5
|
import { Readable } from "node:stream";
|
|
6
|
-
import { homedir } from "node:os";
|
|
7
|
-
import { dirname as
|
|
8
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { homedir as homedir2 } from "node:os";
|
|
7
|
+
import { dirname as dirname6, join as join8, resolve as resolve5 } from "node:path";
|
|
8
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
9
9
|
|
|
10
10
|
// distribution/bootstrap/install.ts
|
|
11
11
|
import { readFile as readFile4, mkdir as mkdir3, access, rename as rename3, rm as rm2, realpath as realpath3, readdir } from "node:fs/promises";
|
|
@@ -149,7 +149,7 @@ function artifact(a) {
|
|
|
149
149
|
}
|
|
150
150
|
function validateRelease(input) {
|
|
151
151
|
const r = input;
|
|
152
|
-
if (!r || r.format !== 1 || r.bootstrapFormat !== 1 || !version.test(r.version) || !integer(r.nodeMajor) || r.nodeMajor < 24 || !integer(r.npmMajor) || r.npmMajor < 11 || !r.platform?.minimumOsRelease || !["darwin", "linux", "win32"].includes(r.platform.os) || !["arm64", "x64"].includes(r.platform.arch) || !artifact(r.runtime) || r.runtime.name !== "@huohuo/research-agent" || r.runtime.version !== r.version || !/^sha512-[A-Za-z0-9+/]+={0,2}$/.test(r.runtime.integrity) || !artifact(r.python) || !artifact(r.pythonDependencies) || !r.python.build || !r.python.license || r.pythonDependencies.upstreamWheelCount !== void 0 && !integer(r.pythonDependencies.upstreamWheelCount) || !r.python.executable || r.python.executable.startsWith("/") || r.python.executable.split(/[\\/]/).some((p) => p === ".." || !p) || !version.test(r.dsh?.version) || !hash.test(r.dsh?.assemblySha256) || !hash.test(r.requirementsSha256) || !hash.test(r.profilesSha256) || !r.budget || ![
|
|
152
|
+
if (!r || r.format !== 1 || r.bootstrapFormat !== 1 || !version.test(r.version) || !integer(r.nodeMajor) || r.nodeMajor < 24 || !integer(r.npmMajor) || r.npmMajor < 11 || !r.platform?.minimumOsRelease || !["darwin", "linux", "win32"].includes(r.platform.os) || !["arm64", "x64"].includes(r.platform.arch) || r.platform.libc !== void 0 && (r.platform.os !== "linux" || r.platform.libc !== "glibc") || r.assetPackage !== void 0 && (r.assetPackage.name !== `@pab-iprg/huohuo-assets-${r.platform.os}-${r.platform.arch}` || !version.test(r.assetPackage.version) || !r.runtime?.bundled || !r.pythonDependencies?.bundled) || !artifact(r.runtime) || r.runtime.name !== "@huohuo/research-agent" || r.runtime.version !== r.version || !/^sha512-[A-Za-z0-9+/]+={0,2}$/.test(r.runtime.integrity) || !artifact(r.python) || !artifact(r.pythonDependencies) || !r.python.build || !r.python.license || r.pythonDependencies.upstreamWheelCount !== void 0 && !integer(r.pythonDependencies.upstreamWheelCount) || !r.python.executable || r.python.executable.startsWith("/") || r.python.executable.split(/[\\/]/).some((p) => p === ".." || !p) || !version.test(r.dsh?.version) || !hash.test(r.dsh?.assemblySha256) || !hash.test(r.requirementsSha256) || !hash.test(r.profilesSha256) || !r.budget || ![
|
|
153
153
|
"minimumEffectiveMemoryBytes",
|
|
154
154
|
"startupHeadroomBytes",
|
|
155
155
|
"heavyJobHeadroomBytes",
|
|
@@ -364,8 +364,8 @@ async function extractArchive(archive, root, expandedLimit) {
|
|
|
364
364
|
}
|
|
365
365
|
} else if (kind === "1" || kind === "2") {
|
|
366
366
|
if (size || !linkText || linkText.startsWith("/") || linkText.includes("\\")) throw new Error("\u538B\u7F29\u5305\u94FE\u63A5\u65E0\u6548");
|
|
367
|
-
const
|
|
368
|
-
links.push({ target, source: safePath(root,
|
|
367
|
+
const relative2 = kind === "2" ? posix.normalize(posix.join(posix.dirname(name), linkText)) : linkText;
|
|
368
|
+
links.push({ target, source: safePath(root, relative2), symbolic: kind === "2", text: linkText });
|
|
369
369
|
} else throw new Error(`\u538B\u7F29\u5305\u6761\u76EE\u7C7B\u578B\u4E0D\u53D7\u652F\u6301\uFF1A${kind}`);
|
|
370
370
|
}
|
|
371
371
|
if (size % 512) await take(512 - size % 512);
|
|
@@ -418,6 +418,24 @@ async function existingParent(path) {
|
|
|
418
418
|
current = parent;
|
|
419
419
|
}
|
|
420
420
|
}
|
|
421
|
+
function linuxAvailableMemory(processAvailable, meminfo) {
|
|
422
|
+
if (processAvailable === null || !Number.isSafeInteger(processAvailable) || processAvailable <= 0) return null;
|
|
423
|
+
const match = /^MemAvailable:\s+(\d+) kB$/m.exec(meminfo);
|
|
424
|
+
if (!match) return processAvailable;
|
|
425
|
+
const hostAvailable = Number(match[1]) * 1024;
|
|
426
|
+
return Number.isSafeInteger(hostAvailable) && hostAvailable >= 0 ? Math.min(processAvailable, hostAvailable) : null;
|
|
427
|
+
}
|
|
428
|
+
function darwinAvailableMemory(processAvailable, effective, pressure, vmstat, constrained = false) {
|
|
429
|
+
if (processAvailable === null || !Number.isSafeInteger(processAvailable) || processAvailable <= 0) return null;
|
|
430
|
+
if (pressure !== "normal" || constrained || effective === null || !Number.isSafeInteger(effective) || effective <= 0) return processAvailable;
|
|
431
|
+
const pageSize = Number(/page size of (\d+) bytes/.exec(vmstat)?.[1]);
|
|
432
|
+
const counts = ["Pages free", "Pages purgeable", "Pages speculative", "File-backed pages"].map((label) => Number(new RegExp(`^${label}:\\s+(\\d+)\\.\\s*$`, "m").exec(vmstat)?.[1]));
|
|
433
|
+
if (![pageSize, ...counts].every(Number.isSafeInteger) || pageSize <= 0 || counts.some((n) => n < 0)) return processAvailable;
|
|
434
|
+
const [free, purgeable, speculative, fileBacked] = counts;
|
|
435
|
+
const estimate = pageSize * (free + Math.max(purgeable, Math.max(0, fileBacked - speculative)));
|
|
436
|
+
if (!Number.isSafeInteger(estimate) || estimate < 0 || estimate > effective) return processAvailable;
|
|
437
|
+
return Math.min(effective, Math.max(processAvailable, estimate));
|
|
438
|
+
}
|
|
421
439
|
async function sampleResources(paths) {
|
|
422
440
|
const limit = constrainedMemory();
|
|
423
441
|
let effectiveMemoryBytes = Math.min(totalmem(), limit || Infinity);
|
|
@@ -438,28 +456,14 @@ async function sampleResources(paths) {
|
|
|
438
456
|
if (pressure === "normal" && availableMemoryBytes !== null && effectiveMemoryBytes !== null) {
|
|
439
457
|
try {
|
|
440
458
|
const { stdout } = await execute2("/usr/bin/vm_stat", [], { timeout: 2e3 });
|
|
441
|
-
|
|
442
|
-
const pageCounts = ["free", "purgeable"].map((kind) => Number(new RegExp(`^Pages ${kind}:\\s+(\\d+)\\.`, "m").exec(stdout)?.[1]));
|
|
443
|
-
const reclaimable = pageBytes * pageCounts.reduce((sum, pages) => sum + pages, 0);
|
|
444
|
-
if (Number.isSafeInteger(reclaimable) && reclaimable > 0) {
|
|
445
|
-
availableMemoryBytes = Math.min(effectiveMemoryBytes, Math.max(availableMemoryBytes, reclaimable));
|
|
446
|
-
}
|
|
459
|
+
availableMemoryBytes = darwinAvailableMemory(availableMemoryBytes, effectiveMemoryBytes, pressure, stdout, limit > 0);
|
|
447
460
|
} catch {
|
|
448
461
|
}
|
|
449
462
|
}
|
|
450
463
|
} else if (process.platform === "linux") {
|
|
451
464
|
try {
|
|
452
465
|
const info = await readFile3("/proc/meminfo", "utf8");
|
|
453
|
-
|
|
454
|
-
if (available) availableMemoryBytes = Math.min(availableMemoryBytes ?? Infinity, Number(available[1]) * 1024);
|
|
455
|
-
if (limit) {
|
|
456
|
-
try {
|
|
457
|
-
const current = Number((await readFile3("/sys/fs/cgroup/memory.current", "utf8")).trim());
|
|
458
|
-
if (Number.isFinite(current)) availableMemoryBytes = Math.min(availableMemoryBytes ?? Infinity, Math.max(0, limit - current));
|
|
459
|
-
} catch {
|
|
460
|
-
availableMemoryBytes = null;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
466
|
+
availableMemoryBytes = linuxAvailableMemory(availableMemoryBytes, info);
|
|
463
467
|
const psi = await readFile3("/proc/pressure/memory", "utf8");
|
|
464
468
|
const full = /^full avg10=(\d+(?:\.\d+)?)/m.exec(psi);
|
|
465
469
|
if (full) pressure = Number(full[1]) > 0 ? "high" : "normal";
|
|
@@ -548,6 +552,50 @@ function npmCommand() {
|
|
|
548
552
|
return { command: process.env.ComSpec ?? "cmd.exe", prefix: ["/d", "/s", "/c", "npm"] };
|
|
549
553
|
}
|
|
550
554
|
|
|
555
|
+
// distribution/bootstrap/catalog.ts
|
|
556
|
+
function hostPlatform() {
|
|
557
|
+
const host = { os: process.platform, arch: process.arch };
|
|
558
|
+
if (host.os === "linux") {
|
|
559
|
+
const report = process.report?.getReport();
|
|
560
|
+
host.libc = report?.header?.glibcVersionRuntime ? "glibc" : "unknown";
|
|
561
|
+
}
|
|
562
|
+
return host;
|
|
563
|
+
}
|
|
564
|
+
function validateCatalog(input) {
|
|
565
|
+
const catalog = input;
|
|
566
|
+
if (!catalog || catalog.kind !== "huohuo-release-catalog" || catalog.format !== 1 || !Array.isArray(catalog.releases) || !catalog.releases.length || catalog.releases.length > 6) {
|
|
567
|
+
throw new Error("\u5E73\u53F0\u53D1\u884C\u7D22\u5F15\u65E0\u6548\uFF1B\u8BF7\u4F7F\u7528\u5B8C\u6574\u7684\u706B\u706B\u5B89\u88C5\u5305");
|
|
568
|
+
}
|
|
569
|
+
const platforms = /* @__PURE__ */ new Set();
|
|
570
|
+
for (const candidate of catalog.releases) {
|
|
571
|
+
const release = validateRelease(candidate);
|
|
572
|
+
const platform = `${release.platform.os}-${release.platform.arch}`;
|
|
573
|
+
if (release.version !== catalog.version || platforms.has(platform)) throw new Error("\u5E73\u53F0\u53D1\u884C\u7D22\u5F15\u542B\u6DF7\u5408\u7248\u672C\u6216\u91CD\u590D\u5E73\u53F0");
|
|
574
|
+
if (release.platform.os === "linux" && release.platform.libc !== "glibc") throw new Error("Linux \u5E73\u53F0\u53D1\u884C\u5FC5\u987B\u660E\u786E glibc \u8FD0\u884C\u73AF\u5883");
|
|
575
|
+
platforms.add(platform);
|
|
576
|
+
}
|
|
577
|
+
return catalog;
|
|
578
|
+
}
|
|
579
|
+
function validateReleaseSource(input) {
|
|
580
|
+
if (input && typeof input === "object" && ("kind" in input || "releases" in input)) return validateCatalog(input);
|
|
581
|
+
return validateRelease(input);
|
|
582
|
+
}
|
|
583
|
+
function selectRelease(input, host = hostPlatform()) {
|
|
584
|
+
const source = validateReleaseSource(input);
|
|
585
|
+
const releases = "releases" in source ? source.releases : [source];
|
|
586
|
+
const selected = releases.find((release) => release.platform.os === host.os && release.platform.arch === host.arch);
|
|
587
|
+
if (!selected) {
|
|
588
|
+
throw new Error(`\u8FD9\u4E2A\u5B89\u88C5\u5305\u5C1A\u672A\u63D0\u4F9B ${host.os}-${host.arch} \u7248\u672C\u3002\u5DF2\u6536\u5F55\uFF1A${releases.map((release) => `${release.platform.os}-${release.platform.arch}`).join("\u3001")}\u3002\u8BF7\u4F7F\u7528\u9002\u914D\u5F53\u524D\u8BBE\u5907\u7684\u53D1\u884C\u7248\u672C\uFF1B\u672A\u4E0B\u8F7D\u6216\u4FEE\u6539\u73B0\u6709\u5B89\u88C5\u3002`);
|
|
589
|
+
}
|
|
590
|
+
assertLibcCompatible(selected, host);
|
|
591
|
+
return selected;
|
|
592
|
+
}
|
|
593
|
+
function assertLibcCompatible(release, host = hostPlatform()) {
|
|
594
|
+
if (release.platform.libc && host.libc !== release.platform.libc) {
|
|
595
|
+
throw new Error("\u8FD9\u4E2A Linux \u5B89\u88C5\u5305\u9700\u8981 glibc \u73AF\u5883\uFF0C\u5F53\u524D\u7CFB\u7EDF\u65E0\u6CD5\u786E\u8BA4\u517C\u5BB9\uFF08\u4F8B\u5982 Alpine/musl\uFF09\u3002\u8BF7\u4F7F\u7528\u5DF2\u9A8C\u8BC1\u7684 glibc \u7CFB\u7EDF\uFF1B\u672A\u4E0B\u8F7D\u6216\u4FEE\u6539\u73B0\u6709\u5B89\u88C5\u3002");
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
551
599
|
// distribution/bootstrap/install.ts
|
|
552
600
|
var digest = (value) => createHash2("sha256").update(JSON.stringify(value)).digest("hex");
|
|
553
601
|
async function ownedDirectory(path, owner) {
|
|
@@ -622,13 +670,20 @@ function installationPaths(home, release) {
|
|
|
622
670
|
};
|
|
623
671
|
}
|
|
624
672
|
function versionAtLeast(actual, minimum) {
|
|
673
|
+
if (![actual, minimum].every((value) => /^\d+(?:\.\d+)*$/.test(value))) return false;
|
|
625
674
|
const a = actual.split(".").map(Number), b = minimum.split(".").map(Number);
|
|
626
|
-
if ([...a, ...b].some((n) => !Number.
|
|
675
|
+
if ([...a, ...b].some((n) => !Number.isSafeInteger(n))) return false;
|
|
627
676
|
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
628
677
|
if ((a[i] ?? 0) !== (b[i] ?? 0)) return (a[i] ?? 0) > (b[i] ?? 0);
|
|
629
678
|
}
|
|
630
679
|
return true;
|
|
631
680
|
}
|
|
681
|
+
function osReleaseAtLeast(actual, minimum, platform = process.platform) {
|
|
682
|
+
if (platform !== "linux") return versionAtLeast(actual, minimum);
|
|
683
|
+
const numericRelease = (value) => /^(\d+(?:\.\d+)*)(?:-[A-Za-z0-9][A-Za-z0-9.+_-]*)?$/.exec(value)?.[1];
|
|
684
|
+
const a = numericRelease(actual), b = numericRelease(minimum);
|
|
685
|
+
return a !== void 0 && b !== void 0 && versionAtLeast(a, b);
|
|
686
|
+
}
|
|
632
687
|
async function install(home, candidate, hooks = {}, programsOnly = false) {
|
|
633
688
|
home = resolve3(home);
|
|
634
689
|
await mkdir3(home, { recursive: true, mode: 448 });
|
|
@@ -675,7 +730,8 @@ async function install(home, candidate, hooks = {}, programsOnly = false) {
|
|
|
675
730
|
}
|
|
676
731
|
}
|
|
677
732
|
const release = record?.release ?? validateRelease(candidate);
|
|
678
|
-
|
|
733
|
+
assertLibcCompatible(release);
|
|
734
|
+
if (release.platform.os !== process.platform || release.platform.arch !== process.arch || !osReleaseAtLeast(osRelease(), release.platform.minimumOsRelease) || !versionAtLeast(process.versions.node, "24.8.0") || Number(process.versions.node.split(".")[0]) !== release.nodeMajor) {
|
|
679
735
|
throw new Error("\u6B64\u53D1\u884C\u5C1A\u672A\u9A8C\u8BC1\u5F53\u524D OS/CPU/Node \u7EC4\u5408\uFF1B\u672A\u5F00\u59CB\u91CD\u4E0B\u8F7D");
|
|
680
736
|
}
|
|
681
737
|
record ??= { format: 1, release, releaseDigest: digest(release), home, status: "installing", stage: "preflight", stages: {} };
|
|
@@ -1175,8 +1231,19 @@ async function uninstall(home, hooks = {}) {
|
|
|
1175
1231
|
|
|
1176
1232
|
// distribution/bootstrap/install-ui.ts
|
|
1177
1233
|
import { createInterface } from "node:readline";
|
|
1234
|
+
import { homedir } from "node:os";
|
|
1235
|
+
import { relative, sep as sep3 } from "node:path";
|
|
1178
1236
|
var gb = (bytes) => bytes === null ? "\u672A\u77E5" : `${(bytes / 1e9).toFixed(2)} GB`;
|
|
1179
1237
|
var mb = (bytes) => bytes < 1e5 ? `${(bytes / 1e3).toFixed(1)} KB` : `${(bytes / 1e6).toFixed(1)} MB`;
|
|
1238
|
+
var memory = (bytes) => {
|
|
1239
|
+
if (bytes === null) return "\u672A\u77E5";
|
|
1240
|
+
return bytes < 2 ** 30 ? `${Math.floor(bytes / 2 ** 20)} MiB` : `${Number((bytes / 2 ** 30).toFixed(2))} GiB`;
|
|
1241
|
+
};
|
|
1242
|
+
function displayPath(path) {
|
|
1243
|
+
const local = relative(homedir(), path);
|
|
1244
|
+
if (!local) return "~";
|
|
1245
|
+
return local === ".." || local.startsWith(`..${sep3}`) ? path : `~${sep3}${local}`;
|
|
1246
|
+
}
|
|
1180
1247
|
function installUI(assumeYes) {
|
|
1181
1248
|
const interactive = process.stdin.isTTY && process.stderr.isTTY;
|
|
1182
1249
|
const output = process.stderr;
|
|
@@ -1192,24 +1259,46 @@ function installUI(assumeYes) {
|
|
|
1192
1259
|
clear();
|
|
1193
1260
|
output.write(text + "\n");
|
|
1194
1261
|
};
|
|
1262
|
+
const heading = (text) => line(interactive && process.env.TERM !== "dumb" && process.env.NO_COLOR === void 0 ? `\x1B[1m${text}\x1B[22m` : text);
|
|
1195
1263
|
return {
|
|
1196
1264
|
async confirm(plan) {
|
|
1197
1265
|
const { sample, policy, disks } = plan.resources;
|
|
1198
|
-
|
|
1266
|
+
const narrow = interactive && output.columns > 0 && output.columns < 48;
|
|
1267
|
+
line("");
|
|
1268
|
+
heading("\u706B\u706B\u5B89\u88C5 \xB7 \u786E\u8BA4\u8BA1\u5212");
|
|
1269
|
+
line(` \u5B89\u88C5\u5230 ${displayPath(plan.home)}`);
|
|
1270
|
+
line("");
|
|
1271
|
+
heading("\u672C\u673A\u8D44\u6E90");
|
|
1199
1272
|
for (const [index, disk] of disks.entries()) {
|
|
1200
1273
|
const location = sample.disks.find((item) => item.device === disk.device)?.paths[0] ?? plan.home;
|
|
1201
|
-
line(
|
|
1274
|
+
if (disks.length > 1) line(` \u78C1\u76D8 ${index + 1} ${displayPath(location)}`);
|
|
1275
|
+
const need = `\u9700\u7559 ${gb(disk.requiredBytes)}`;
|
|
1276
|
+
const free = `\u53EF\u7528 ${gb(disk.availableBytes)}`;
|
|
1277
|
+
line(narrow ? ` \u78C1\u76D8 ${need}
|
|
1278
|
+
${free}` : ` \u78C1\u76D8 ${need} \xB7 ${free}`);
|
|
1202
1279
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
line(
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
line(
|
|
1209
|
-
|
|
1210
|
-
line(
|
|
1211
|
-
|
|
1212
|
-
|
|
1280
|
+
const available = `\u53EF\u7528 ${memory(sample.availableMemoryBytes)}`;
|
|
1281
|
+
const total = `\u603B\u91CF ${memory(sample.effectiveMemoryBytes)}`;
|
|
1282
|
+
line(narrow ? ` \u5185\u5B58 ${available}
|
|
1283
|
+
${total}` : ` \u5185\u5B58 ${available} \xB7 ${total}`);
|
|
1284
|
+
line(` \u542F\u52A8\u9700\u7559 ${memory(policy.startupHeadroomBytes)}`);
|
|
1285
|
+
line(` \u6700\u4F4E\u5BB9\u91CF ${memory(policy.minimumEffectiveMemoryBytes)}`);
|
|
1286
|
+
if (policy.observedInstallRssBytes) line(` \u5386\u53F2\u5B89\u88C5\u5CF0\u503C\u7EA6 ${memory(policy.observedInstallRssBytes)}`);
|
|
1287
|
+
for (const reason of plan.resources.reasons) line(` \u63D0\u793A ${reason}`);
|
|
1288
|
+
line("");
|
|
1289
|
+
heading("\u4E0B\u8F7D\u8BA1\u5212");
|
|
1290
|
+
const bytes = plan.downloads.reduce((total2, file) => total2 + file.size, 0);
|
|
1291
|
+
line(plan.downloads.length ? ` \u56FA\u5B9A\u8D44\u6E90\u5F85\u4E0B\u8F7D ${plan.downloads.length} \u9879 \xB7 ${mb(bytes)}` : " \u56FA\u5B9A\u8D44\u6E90\u65E0\u9700\u8054\u7F51\u4E0B\u8F7D");
|
|
1292
|
+
const local = [plan.bundled ? `\u968F\u5305 ${plan.bundled} \u9879` : "", plan.cached ? `\u590D\u7528\u7F13\u5B58 ${plan.cached} \u9879` : ""].filter(Boolean);
|
|
1293
|
+
if (local.length) line(` ${local.join(" \xB7 ")}`);
|
|
1294
|
+
for (const file of plan.downloads) {
|
|
1295
|
+
line(` ${file.name} ${mb(file.size)}`);
|
|
1296
|
+
line(` \u6765\u6E90 ${file.host}`);
|
|
1297
|
+
}
|
|
1298
|
+
if (plan.downloads.length || plan.bundled) line(` \u4FDD\u5B58\u5230 ${displayPath(plan.home)}/cache`);
|
|
1299
|
+
if (plan.upstreamWheelCount !== void 0) line(` Python \u4E0A\u6E38\u6587\u4EF6 ${plan.upstreamWheelCount} \u9879`);
|
|
1300
|
+
line(" npm \u548C Python \u4F9D\u8D56\u4ECD\u53EF\u80FD\u8054\u7F51");
|
|
1301
|
+
line("");
|
|
1213
1302
|
if (assumeYes) return true;
|
|
1214
1303
|
if (!interactive) throw new Error("\u9700\u8981\u786E\u8BA4\u5B89\u88C5\u3002\u8BF7\u5728\u7EC8\u7AEF\u8FD0\u884C\uFF0C\u6216\u5728\u706B\u706B\u547D\u4EE4\u672B\u5C3E\u52A0\u4E0A --yes\u3002");
|
|
1215
1304
|
const terminal = createInterface({ input: process.stdin, output, terminal: true });
|
|
@@ -1333,6 +1422,27 @@ async function showStatus(home, watch) {
|
|
|
1333
1422
|
}
|
|
1334
1423
|
}
|
|
1335
1424
|
|
|
1425
|
+
// distribution/bootstrap/assets.ts
|
|
1426
|
+
import { createRequire } from "node:module";
|
|
1427
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
1428
|
+
import { dirname as dirname5, join as join7 } from "node:path";
|
|
1429
|
+
import { fileURLToPath } from "node:url";
|
|
1430
|
+
async function assetsDirectory(release, entryURL = import.meta.url) {
|
|
1431
|
+
if (!release?.assetPackage) return join7(dirname5(fileURLToPath(entryURL)), "assets");
|
|
1432
|
+
const expected = release.assetPackage;
|
|
1433
|
+
let file;
|
|
1434
|
+
try {
|
|
1435
|
+
file = createRequire(entryURL).resolve(`${expected.name}/package.json`);
|
|
1436
|
+
} catch {
|
|
1437
|
+
throw new Error("\u6CA1\u6709\u627E\u5230\u5F53\u524D\u8BBE\u5907\u7684\u706B\u706B\u8D44\u6E90\u5305\u3002\u8BF7\u91CD\u65B0\u6267\u884C\u5B8C\u6574\u5B89\u88C5\u547D\u4EE4\uFF0C\u5E76\u786E\u4FDD\u6CA1\u6709\u8DF3\u8FC7 npm \u53EF\u9009\u4F9D\u8D56\u3002");
|
|
1438
|
+
}
|
|
1439
|
+
const manifest = JSON.parse(await readFile8(file, "utf8"));
|
|
1440
|
+
if (manifest.name !== expected.name || manifest.version !== expected.version) {
|
|
1441
|
+
throw new Error("\u706B\u706B\u5165\u53E3\u4E0E\u5E73\u53F0\u8D44\u6E90\u5305\u7248\u672C\u4E0D\u4E00\u81F4\u3002\u8BF7\u91CD\u65B0\u8FD0\u884C\u540C\u4E00\u7248\u672C\u7684\u5B8C\u6574\u5B89\u88C5\u547D\u4EE4\u3002");
|
|
1442
|
+
}
|
|
1443
|
+
return join7(dirname5(file), "assets");
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1336
1446
|
// distribution/bootstrap/entry.ts
|
|
1337
1447
|
function artifactSource(source, directory) {
|
|
1338
1448
|
return async (url, options) => {
|
|
@@ -1341,8 +1451,8 @@ function artifactSource(source, directory) {
|
|
|
1341
1451
|
const artifact2 = source && [source.runtime, source.python, source.pythonDependencies].find((item) => item.url === String(url));
|
|
1342
1452
|
const sha256 = bundled?.[1] ?? artifact2?.sha256;
|
|
1343
1453
|
if (!sha256) throw new Error("\u672C\u673A\u4EA7\u7269\u76EE\u5F55\u7F3A\u5C11\u8BE5\u56FA\u5B9A\u53D1\u884C\u8D44\u6E90");
|
|
1344
|
-
const root = directory ??
|
|
1345
|
-
const path =
|
|
1454
|
+
const root = directory ?? await assetsDirectory(source, import.meta.url);
|
|
1455
|
+
const path = join8(root, sha256 + ".tgz");
|
|
1346
1456
|
const file = await open3(path).catch((error) => {
|
|
1347
1457
|
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");
|
|
1348
1458
|
throw error;
|
|
@@ -1351,7 +1461,7 @@ function artifactSource(source, directory) {
|
|
|
1351
1461
|
};
|
|
1352
1462
|
}
|
|
1353
1463
|
async function main(args = process.argv.slice(2)) {
|
|
1354
|
-
let home =
|
|
1464
|
+
let home = join8(homedir2(), ".huohuo"), noOpen = false, assumeYes = false, watch = false, command = "start";
|
|
1355
1465
|
let releaseFile, artifactDirectory;
|
|
1356
1466
|
for (let i = 0; i < args.length; i++) {
|
|
1357
1467
|
if (args[i] === "--home") {
|
|
@@ -1366,8 +1476,8 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1366
1476
|
else if (args[i] === "--yes") assumeYes = true;
|
|
1367
1477
|
else if (args[i] === "--watch") watch = true;
|
|
1368
1478
|
else if (args[i] === "--version") {
|
|
1369
|
-
const packageFile =
|
|
1370
|
-
const manifest = JSON.parse(await
|
|
1479
|
+
const packageFile = join8(dirname6(fileURLToPath2(import.meta.url)), "package.json");
|
|
1480
|
+
const manifest = JSON.parse(await readFile9(packageFile, "utf8"));
|
|
1371
1481
|
console.log(`${manifest.name} ${manifest.version}${manifest.private ? "\uFF08\u672C\u5730\u5019\u9009\uFF09" : ""}`);
|
|
1372
1482
|
return;
|
|
1373
1483
|
} else if (["start", "status", "doctor", "stop", "upgrade", "uninstall"].includes(args[i])) command = args[i];
|
|
@@ -1398,11 +1508,11 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1398
1508
|
};
|
|
1399
1509
|
const ui = installUI(assumeYes);
|
|
1400
1510
|
if (command === "upgrade") {
|
|
1401
|
-
const candidate = JSON.parse(await
|
|
1511
|
+
const candidate = selectRelease(JSON.parse(await readFile9(releaseFile ?? join8(dirname6(fileURLToPath2(import.meta.url)), "release.json"), "utf8")));
|
|
1402
1512
|
await upgrade(home, candidate, { fetcher: artifactSource(candidate, artifactDirectory), progress, ...ui });
|
|
1403
1513
|
const current = await readInstallation(home);
|
|
1404
1514
|
if (await control(home, current.releaseDigest, noOpen ? "status" : "open")) return;
|
|
1405
|
-
await run(process.execPath, [
|
|
1515
|
+
await run(process.execPath, [join8(installationPaths(home, current.release).runtime, "lib/distribution/managed.js"), "start", home, ...noOpen ? ["--no-open"] : []], home);
|
|
1406
1516
|
return;
|
|
1407
1517
|
}
|
|
1408
1518
|
if (command === "uninstall") {
|
|
@@ -1420,7 +1530,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1420
1530
|
return;
|
|
1421
1531
|
}
|
|
1422
1532
|
const paths = installationPaths(home, record.release);
|
|
1423
|
-
const targets = [home, paths.directory, paths.environment,
|
|
1533
|
+
const targets = [home, paths.directory, paths.environment, join8(home, "instances/default")];
|
|
1424
1534
|
const resources = evaluateResources(await sampleResources(targets), record.release.budget, targets.map((path) => ({ path, bytes: 0 })), "start");
|
|
1425
1535
|
console.log(JSON.stringify({
|
|
1426
1536
|
home,
|
|
@@ -1441,30 +1551,31 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1441
1551
|
}
|
|
1442
1552
|
const runtime = installationPaths(home, record.release).runtime;
|
|
1443
1553
|
try {
|
|
1444
|
-
await
|
|
1554
|
+
await readFile9(join8(runtime, "lib/distribution/managed.js"));
|
|
1445
1555
|
} catch (e) {
|
|
1446
1556
|
if (e.code !== "ENOENT") throw e;
|
|
1447
1557
|
record = void 0;
|
|
1448
1558
|
}
|
|
1449
1559
|
}
|
|
1450
1560
|
if (!record || record.status !== "ready") {
|
|
1451
|
-
|
|
1452
|
-
|
|
1561
|
+
const persisted = await readInstallation(home);
|
|
1562
|
+
let source = persisted?.release;
|
|
1563
|
+
if (!source) {
|
|
1564
|
+
let catalog = null;
|
|
1453
1565
|
try {
|
|
1454
|
-
catalog = JSON.parse(await
|
|
1566
|
+
catalog = JSON.parse(await readFile9(releaseFile ?? join8(dirname6(fileURLToPath2(import.meta.url)), "release.json"), "utf8"));
|
|
1455
1567
|
} catch (e) {
|
|
1456
1568
|
if (e.code !== "ENOENT") throw e;
|
|
1457
1569
|
}
|
|
1570
|
+
source = selectRelease(catalog);
|
|
1458
1571
|
}
|
|
1459
|
-
const source = (await readInstallation(home))?.release ?? catalog;
|
|
1460
1572
|
const fetcher = artifactSource(source, artifactDirectory);
|
|
1461
|
-
|
|
1462
|
-
record = await install(home, catalog, { fetcher, progress, bundleDirectory, ...ui });
|
|
1573
|
+
record = await install(home, source, { fetcher, progress, ...ui });
|
|
1463
1574
|
}
|
|
1464
1575
|
const installedHome = record.home;
|
|
1465
|
-
await run(process.execPath, [
|
|
1576
|
+
await run(process.execPath, [join8(installationPaths(installedHome, record.release).runtime, "lib/distribution/managed.js"), "start", installedHome, ...noOpen ? ["--no-open"] : []], installedHome);
|
|
1466
1577
|
}
|
|
1467
|
-
if (process.argv[1] && await realpath5(resolve5(process.argv[1])).catch(() => "") === await realpath5(
|
|
1578
|
+
if (process.argv[1] && await realpath5(resolve5(process.argv[1])).catch(() => "") === await realpath5(fileURLToPath2(import.meta.url))) {
|
|
1468
1579
|
main().catch((error) => {
|
|
1469
1580
|
console.error(error instanceof Error ? error.message : "\u5B89\u88C5\u6216\u542F\u52A8\u5931\u8D25");
|
|
1470
1581
|
if (error?.code !== "INSTALL_CANCELLED") process.exitCode = 1;
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pab-iprg/huohuo",
|
|
3
|
-
"version": "1.0.0-preview.
|
|
3
|
+
"version": "1.0.0-preview.6",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "火火双平台安装入口(实验预览)",
|
|
6
6
|
"bin": {
|
|
7
7
|
"huohuo": "./cli.js"
|
|
8
8
|
},
|
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
"files": [
|
|
13
13
|
"cli.js",
|
|
14
14
|
"release.json",
|
|
15
|
-
"README.md"
|
|
16
|
-
"assets"
|
|
15
|
+
"README.md"
|
|
17
16
|
],
|
|
17
|
+
"optionalDependencies": {
|
|
18
|
+
"@pab-iprg/huohuo-assets-darwin-arm64": "1.0.0-preview.6",
|
|
19
|
+
"@pab-iprg/huohuo-assets-linux-x64": "1.0.0-preview.6"
|
|
20
|
+
},
|
|
18
21
|
"publishConfig": {
|
|
19
22
|
"access": "public",
|
|
20
|
-
"tag": "
|
|
23
|
+
"tag": "preview"
|
|
21
24
|
}
|
|
22
25
|
}
|
package/release.json
CHANGED
|
@@ -1,95 +1,205 @@
|
|
|
1
1
|
{
|
|
2
|
+
"kind": "huohuo-release-catalog",
|
|
2
3
|
"format": 1,
|
|
3
|
-
"bootstrapFormat": 1,
|
|
4
4
|
"version": "1.0.0",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
5
|
+
"releases": [
|
|
6
|
+
{
|
|
7
|
+
"format": 1,
|
|
8
|
+
"bootstrapFormat": 1,
|
|
9
|
+
"version": "1.0.0",
|
|
10
|
+
"nodeMajor": 24,
|
|
11
|
+
"npmMajor": 11,
|
|
12
|
+
"qualification": "controlled-acceptance-only",
|
|
13
|
+
"platform": {
|
|
14
|
+
"os": "darwin",
|
|
15
|
+
"arch": "arm64",
|
|
16
|
+
"minimumOsRelease": "25.6.0"
|
|
17
|
+
},
|
|
18
|
+
"runtime": {
|
|
19
|
+
"name": "@huohuo/research-agent",
|
|
20
|
+
"version": "1.0.0",
|
|
21
|
+
"url": "https://bundled.invalid/3d87538021deec2fa15adb57558f3abf453a405879b947adecf4253dd0ec5f28.tgz",
|
|
22
|
+
"bundled": true,
|
|
23
|
+
"sha256": "3d87538021deec2fa15adb57558f3abf453a405879b947adecf4253dd0ec5f28",
|
|
24
|
+
"integrity": "sha512-czI1E1L+ILNCh+tf/CdX1NXIBwETHnJDqXixNppcdzbdrsKXRJ6XkUKJbZK/AX1q4m6gdfETgqb8XXuVK9oKnQ==",
|
|
25
|
+
"downloadBytes": 2610631,
|
|
26
|
+
"expandedBytes": 8328828
|
|
27
|
+
},
|
|
28
|
+
"python": {
|
|
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",
|
|
30
|
+
"sha256": "8392b6ea51d94391befb2c31ebe75463f045d0b69dfcf5e1bb3234e1f5fa3405",
|
|
31
|
+
"downloadBytes": 25265774,
|
|
32
|
+
"expandedBytes": 66020864,
|
|
33
|
+
"redirectHosts": [
|
|
34
|
+
"release-assets.githubusercontent.com"
|
|
35
|
+
],
|
|
36
|
+
"executable": "python/bin/python3",
|
|
37
|
+
"build": "cpython-3.13.18+20261026-aarch64-apple-darwin-install_only_stripped.tar.gz",
|
|
38
|
+
"license": "python/lib/python3.13/LICENSE.txt"
|
|
39
|
+
},
|
|
40
|
+
"pythonDependencies": {
|
|
41
|
+
"url": "https://bundled.invalid/61bbfd92aa43f2e1ae8e339a03e88efb145ae3266f00ef8fc979c8bc1ed502a5.tgz",
|
|
42
|
+
"bundled": true,
|
|
43
|
+
"sha256": "61bbfd92aa43f2e1ae8e339a03e88efb145ae3266f00ef8fc979c8bc1ed502a5",
|
|
44
|
+
"downloadBytes": 10215,
|
|
45
|
+
"expandedBytes": 20480,
|
|
46
|
+
"upstreamWheelCount": 39
|
|
47
|
+
},
|
|
48
|
+
"dsh": {
|
|
49
|
+
"version": "0.2.1-rc.2",
|
|
50
|
+
"assemblySha256": "08cf11de70e49981b4891c0aaa2a5e7b872a95b6aa07557bb629713fa8f9e249"
|
|
51
|
+
},
|
|
52
|
+
"requirementsSha256": "57042fff45cee66fe33712472e2e5b88f03a084068ca20242588b2e18b3e167b",
|
|
53
|
+
"profilesSha256": "fb3540e0d604f26280128a21f97313575848f6348733a221f7e230233fdb8e2d",
|
|
54
|
+
"budget": {
|
|
55
|
+
"minimumEffectiveMemoryBytes": 34359738368,
|
|
56
|
+
"startupHeadroomBytes": 134217728,
|
|
57
|
+
"heavyJobHeadroomBytes": 1073741824,
|
|
58
|
+
"diskReserveBytes": 1073741824,
|
|
59
|
+
"recoverySamples": 3,
|
|
60
|
+
"processTreeBudgetBytes": 17179869184,
|
|
61
|
+
"sampleIntervalMs": 2000,
|
|
62
|
+
"sampleMaxAgeMs": 10000,
|
|
63
|
+
"installTemporaryBytes": 1073741824,
|
|
64
|
+
"dependenciesBytes": 4294967296,
|
|
65
|
+
"backupBytes": 0,
|
|
66
|
+
"observedInstallRssBytes": 1904771072
|
|
67
|
+
},
|
|
68
|
+
"schema": {
|
|
69
|
+
"minimum": 1,
|
|
70
|
+
"maximum": 1,
|
|
71
|
+
"migrationsSha256": "ba029fdbffa5320e61393b484d08accafce60e9aa8dacde5b6212fb79dd9146b",
|
|
72
|
+
"files": {
|
|
73
|
+
"001_init.sql": "b42b6192d872f0f65cfbbf9d0c7fb442d3aa49584a6cf321d3bcc641b31b70da",
|
|
74
|
+
"002_contact_decision.sql": "af82cb9975a09fa09c0f970b70d04a7b55a960d72e0853f4573d571efaa46f0a",
|
|
75
|
+
"003_schedules.sql": "2937f7be2693ce9b410ee9a73bd10c5e819c5081a10a6b3993c33f37ad42295f",
|
|
76
|
+
"004_condition_state.sql": "f081d250dd525ad57a450bd6bca59a75f8fb1428177d670ae9fa142ed79721d6",
|
|
77
|
+
"005_execution_handoff.sql": "ebf2e5c4890b7a73ae1ffb57a70bb15183f48a6c1fa2acf3a48b95ccb3d992b3",
|
|
78
|
+
"006_entity_confirmation.sql": "d25ee376e7f6dd55df2edeb68d7591ef5fbaa34eeb3eef662cd76e183526d3c0",
|
|
79
|
+
"007_research_tool_calls.sql": "df9c7d8d25b44b151f743e2d5167b34ae89c64e67423d8af554364fd792da942",
|
|
80
|
+
"008_followup_notifications.sql": "98865d811879afd679846087a5f01ee2db371dcb90381a9c400c940a5c1c4b37",
|
|
81
|
+
"008_investment.sql": "71cecf6215552c725797059efdcb501247e1225c7d9f662de606266d3a947e61",
|
|
82
|
+
"009_notification_channels.sql": "572424d739203a8514ae59920a0ad69cf83f278479b48d48becb88bddda25d9a",
|
|
83
|
+
"010_strategies.sql": "af023fab201db6bd2e15e2348125d112bc21cf3a59d8afd0a2d616fc05cee209",
|
|
84
|
+
"011_strategy_run_subjects.sql": "53a1c216ed775a06549dcc201f9494ceabe308bee6dc52a214b685cca2f2fe8d",
|
|
85
|
+
"012_strategy_schedule.sql": "ccddd81bb70d2c86356e6f1ad09132e7397837d17e926b515c8e281a362bdd58",
|
|
86
|
+
"014_industry_chain.sql": "b656efffe746d14ca350ea1c9ecfcce2d98b5753e4b2f862c75d0456a062fd4a",
|
|
87
|
+
"015_source_heads.sql": "652bf637892edbbe969ce5ed4ce45a4a0c43d03de395fce1b828fc4c0169f885",
|
|
88
|
+
"016_legacy_transfer.sql": "b6e3c214b103487d741226b0f83525e0cacbb0c440bd1935d0e963dc9b9bfd07",
|
|
89
|
+
"017_unified_strategy_work.sql": "8d055ca58f3e73482fb16c630c733ae93197244b37e4509cc90c7dec3bf88d60",
|
|
90
|
+
"018_personalization.sql": "7f62a4eb74707fb071f56d6057b6d6517ed7648af23ebe290f3be15d260a103c",
|
|
91
|
+
"019_position_risk.sql": "3c461fa435b352127fd4ee4e7ed3de2c924561a3727dce1535d7d3a47c436ca9",
|
|
92
|
+
"020_notification_tests.sql": "3eb0d72eadf04b074208dbe0ef6a72ee614ec11a15143108a2471568b7b4fb22",
|
|
93
|
+
"021_notification_priority.sql": "f742b4c4b796e918bfc6a08bac8c5ae206382075925acf7b1c430b033f5177e6",
|
|
94
|
+
"022_research_job_priority.sql": "fcb0c0af025806faab7cd403097a9d2c55e07331ab0a78b2926c1927a87f4ed4",
|
|
95
|
+
"023_adaptive_notifications.sql": "80630e2dad73844d48b265fbc33648b01d8321a6fd9a0587ef4dc01f362aadec",
|
|
96
|
+
"023_notification_attention.sql": "5dd85fb001192558211c7b69e3452984c52119f215750ed6283b296d3dccc842",
|
|
97
|
+
"024_t_trade_watch.sql": "aa38470ddab00e0cbca07ce6d5cc31399ba2b6e40c8d8d888e88ec093a9f89ef"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"assetPackage": {
|
|
101
|
+
"name": "@pab-iprg/huohuo-assets-darwin-arm64",
|
|
102
|
+
"version": "1.0.0-preview.6"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"format": 1,
|
|
107
|
+
"bootstrapFormat": 1,
|
|
108
|
+
"version": "1.0.0",
|
|
109
|
+
"nodeMajor": 24,
|
|
110
|
+
"npmMajor": 11,
|
|
111
|
+
"qualification": "controlled-acceptance-only",
|
|
112
|
+
"platform": {
|
|
113
|
+
"os": "linux",
|
|
114
|
+
"arch": "x64",
|
|
115
|
+
"minimumOsRelease": "6.8.0",
|
|
116
|
+
"libc": "glibc"
|
|
117
|
+
},
|
|
118
|
+
"runtime": {
|
|
119
|
+
"name": "@huohuo/research-agent",
|
|
120
|
+
"version": "1.0.0",
|
|
121
|
+
"url": "https://bundled.invalid/2c2e63ab7a4890ef198f2f0e3b3152788a158fabeb1828a20e9820416eb6d01a.tgz",
|
|
122
|
+
"bundled": true,
|
|
123
|
+
"sha256": "2c2e63ab7a4890ef198f2f0e3b3152788a158fabeb1828a20e9820416eb6d01a",
|
|
124
|
+
"integrity": "sha512-JkcJGHcTpa2Db/YkeUuAzzyx0B118eP5CKBEhf7oQiGBm7uY5bbndj4q1IaeNJMhJlJRYD1YAm/qxPk1tI/5aw==",
|
|
125
|
+
"downloadBytes": 2610643,
|
|
126
|
+
"expandedBytes": 8328846
|
|
127
|
+
},
|
|
128
|
+
"python": {
|
|
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",
|
|
130
|
+
"sha256": "df15fe60d3ff55bf9dcf25824b5572756bb8816ff93865a273d3301d7066a8b7",
|
|
131
|
+
"downloadBytes": 35395906,
|
|
132
|
+
"expandedBytes": 102403072,
|
|
133
|
+
"redirectHosts": [
|
|
134
|
+
"release-assets.githubusercontent.com"
|
|
135
|
+
],
|
|
136
|
+
"executable": "python/bin/python3",
|
|
137
|
+
"build": "cpython-3.13.18+20261026-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz",
|
|
138
|
+
"license": "python/lib/python3.13/LICENSE.txt"
|
|
139
|
+
},
|
|
140
|
+
"pythonDependencies": {
|
|
141
|
+
"url": "https://bundled.invalid/7e42648979228aa347ad334e4d40271a2c3dd78b76ebf6c5c557b0fd8fe36ec2.tgz",
|
|
142
|
+
"bundled": true,
|
|
143
|
+
"sha256": "7e42648979228aa347ad334e4d40271a2c3dd78b76ebf6c5c557b0fd8fe36ec2",
|
|
144
|
+
"downloadBytes": 10367,
|
|
145
|
+
"expandedBytes": 20480,
|
|
146
|
+
"upstreamWheelCount": 40
|
|
147
|
+
},
|
|
148
|
+
"dsh": {
|
|
149
|
+
"version": "0.2.1-rc.2",
|
|
150
|
+
"assemblySha256": "08cf11de70e49981b4891c0aaa2a5e7b872a95b6aa07557bb629713fa8f9e249"
|
|
151
|
+
},
|
|
152
|
+
"requirementsSha256": "d4ff8161886fc286e6f8ddfcd070ac5812528971affe7b87baa03662dd242d45",
|
|
153
|
+
"profilesSha256": "fb3540e0d604f26280128a21f97313575848f6348733a221f7e230233fdb8e2d",
|
|
154
|
+
"budget": {
|
|
155
|
+
"minimumEffectiveMemoryBytes": 8589934592,
|
|
156
|
+
"startupHeadroomBytes": 1073741824,
|
|
157
|
+
"heavyJobHeadroomBytes": 1073741824,
|
|
158
|
+
"processTreeBudgetBytes": 4294967296,
|
|
159
|
+
"diskReserveBytes": 1073741824,
|
|
160
|
+
"recoverySamples": 3,
|
|
161
|
+
"sampleIntervalMs": 2000,
|
|
162
|
+
"sampleMaxAgeMs": 10000,
|
|
163
|
+
"installTemporaryBytes": 1073741824,
|
|
164
|
+
"dependenciesBytes": 4294967296,
|
|
165
|
+
"backupBytes": 1073741824
|
|
166
|
+
},
|
|
167
|
+
"schema": {
|
|
168
|
+
"minimum": 1,
|
|
169
|
+
"maximum": 1,
|
|
170
|
+
"migrationsSha256": "ba029fdbffa5320e61393b484d08accafce60e9aa8dacde5b6212fb79dd9146b",
|
|
171
|
+
"files": {
|
|
172
|
+
"001_init.sql": "b42b6192d872f0f65cfbbf9d0c7fb442d3aa49584a6cf321d3bcc641b31b70da",
|
|
173
|
+
"002_contact_decision.sql": "af82cb9975a09fa09c0f970b70d04a7b55a960d72e0853f4573d571efaa46f0a",
|
|
174
|
+
"003_schedules.sql": "2937f7be2693ce9b410ee9a73bd10c5e819c5081a10a6b3993c33f37ad42295f",
|
|
175
|
+
"004_condition_state.sql": "f081d250dd525ad57a450bd6bca59a75f8fb1428177d670ae9fa142ed79721d6",
|
|
176
|
+
"005_execution_handoff.sql": "ebf2e5c4890b7a73ae1ffb57a70bb15183f48a6c1fa2acf3a48b95ccb3d992b3",
|
|
177
|
+
"006_entity_confirmation.sql": "d25ee376e7f6dd55df2edeb68d7591ef5fbaa34eeb3eef662cd76e183526d3c0",
|
|
178
|
+
"007_research_tool_calls.sql": "df9c7d8d25b44b151f743e2d5167b34ae89c64e67423d8af554364fd792da942",
|
|
179
|
+
"008_followup_notifications.sql": "98865d811879afd679846087a5f01ee2db371dcb90381a9c400c940a5c1c4b37",
|
|
180
|
+
"008_investment.sql": "71cecf6215552c725797059efdcb501247e1225c7d9f662de606266d3a947e61",
|
|
181
|
+
"009_notification_channels.sql": "572424d739203a8514ae59920a0ad69cf83f278479b48d48becb88bddda25d9a",
|
|
182
|
+
"010_strategies.sql": "af023fab201db6bd2e15e2348125d112bc21cf3a59d8afd0a2d616fc05cee209",
|
|
183
|
+
"011_strategy_run_subjects.sql": "53a1c216ed775a06549dcc201f9494ceabe308bee6dc52a214b685cca2f2fe8d",
|
|
184
|
+
"012_strategy_schedule.sql": "ccddd81bb70d2c86356e6f1ad09132e7397837d17e926b515c8e281a362bdd58",
|
|
185
|
+
"014_industry_chain.sql": "b656efffe746d14ca350ea1c9ecfcce2d98b5753e4b2f862c75d0456a062fd4a",
|
|
186
|
+
"015_source_heads.sql": "652bf637892edbbe969ce5ed4ce45a4a0c43d03de395fce1b828fc4c0169f885",
|
|
187
|
+
"016_legacy_transfer.sql": "b6e3c214b103487d741226b0f83525e0cacbb0c440bd1935d0e963dc9b9bfd07",
|
|
188
|
+
"017_unified_strategy_work.sql": "8d055ca58f3e73482fb16c630c733ae93197244b37e4509cc90c7dec3bf88d60",
|
|
189
|
+
"018_personalization.sql": "7f62a4eb74707fb071f56d6057b6d6517ed7648af23ebe290f3be15d260a103c",
|
|
190
|
+
"019_position_risk.sql": "3c461fa435b352127fd4ee4e7ed3de2c924561a3727dce1535d7d3a47c436ca9",
|
|
191
|
+
"020_notification_tests.sql": "3eb0d72eadf04b074208dbe0ef6a72ee614ec11a15143108a2471568b7b4fb22",
|
|
192
|
+
"021_notification_priority.sql": "f742b4c4b796e918bfc6a08bac8c5ae206382075925acf7b1c430b033f5177e6",
|
|
193
|
+
"022_research_job_priority.sql": "fcb0c0af025806faab7cd403097a9d2c55e07331ab0a78b2926c1927a87f4ed4",
|
|
194
|
+
"023_adaptive_notifications.sql": "80630e2dad73844d48b265fbc33648b01d8321a6fd9a0587ef4dc01f362aadec",
|
|
195
|
+
"023_notification_attention.sql": "5dd85fb001192558211c7b69e3452984c52119f215750ed6283b296d3dccc842",
|
|
196
|
+
"024_t_trade_watch.sql": "aa38470ddab00e0cbca07ce6d5cc31399ba2b6e40c8d8d888e88ec093a9f89ef"
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
"assetPackage": {
|
|
200
|
+
"name": "@pab-iprg/huohuo-assets-linux-x64",
|
|
201
|
+
"version": "1.0.0-preview.6"
|
|
202
|
+
}
|
|
93
203
|
}
|
|
94
|
-
|
|
204
|
+
]
|
|
95
205
|
}
|
|
Binary file
|