@pab-iprg/huohuo 1.0.0-preview.4 → 1.0.0-preview.5
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,13 @@ 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
|
+
}
|
|
421
428
|
async function sampleResources(paths) {
|
|
422
429
|
const limit = constrainedMemory();
|
|
423
430
|
let effectiveMemoryBytes = Math.min(totalmem(), limit || Infinity);
|
|
@@ -450,16 +457,7 @@ async function sampleResources(paths) {
|
|
|
450
457
|
} else if (process.platform === "linux") {
|
|
451
458
|
try {
|
|
452
459
|
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
|
-
}
|
|
460
|
+
availableMemoryBytes = linuxAvailableMemory(availableMemoryBytes, info);
|
|
463
461
|
const psi = await readFile3("/proc/pressure/memory", "utf8");
|
|
464
462
|
const full = /^full avg10=(\d+(?:\.\d+)?)/m.exec(psi);
|
|
465
463
|
if (full) pressure = Number(full[1]) > 0 ? "high" : "normal";
|
|
@@ -548,6 +546,50 @@ function npmCommand() {
|
|
|
548
546
|
return { command: process.env.ComSpec ?? "cmd.exe", prefix: ["/d", "/s", "/c", "npm"] };
|
|
549
547
|
}
|
|
550
548
|
|
|
549
|
+
// distribution/bootstrap/catalog.ts
|
|
550
|
+
function hostPlatform() {
|
|
551
|
+
const host = { os: process.platform, arch: process.arch };
|
|
552
|
+
if (host.os === "linux") {
|
|
553
|
+
const report = process.report?.getReport();
|
|
554
|
+
host.libc = report?.header?.glibcVersionRuntime ? "glibc" : "unknown";
|
|
555
|
+
}
|
|
556
|
+
return host;
|
|
557
|
+
}
|
|
558
|
+
function validateCatalog(input) {
|
|
559
|
+
const catalog = input;
|
|
560
|
+
if (!catalog || catalog.kind !== "huohuo-release-catalog" || catalog.format !== 1 || !Array.isArray(catalog.releases) || !catalog.releases.length || catalog.releases.length > 6) {
|
|
561
|
+
throw new Error("\u5E73\u53F0\u53D1\u884C\u7D22\u5F15\u65E0\u6548\uFF1B\u8BF7\u4F7F\u7528\u5B8C\u6574\u7684\u706B\u706B\u5B89\u88C5\u5305");
|
|
562
|
+
}
|
|
563
|
+
const platforms = /* @__PURE__ */ new Set();
|
|
564
|
+
for (const candidate of catalog.releases) {
|
|
565
|
+
const release = validateRelease(candidate);
|
|
566
|
+
const platform = `${release.platform.os}-${release.platform.arch}`;
|
|
567
|
+
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");
|
|
568
|
+
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");
|
|
569
|
+
platforms.add(platform);
|
|
570
|
+
}
|
|
571
|
+
return catalog;
|
|
572
|
+
}
|
|
573
|
+
function validateReleaseSource(input) {
|
|
574
|
+
if (input && typeof input === "object" && ("kind" in input || "releases" in input)) return validateCatalog(input);
|
|
575
|
+
return validateRelease(input);
|
|
576
|
+
}
|
|
577
|
+
function selectRelease(input, host = hostPlatform()) {
|
|
578
|
+
const source = validateReleaseSource(input);
|
|
579
|
+
const releases = "releases" in source ? source.releases : [source];
|
|
580
|
+
const selected = releases.find((release) => release.platform.os === host.os && release.platform.arch === host.arch);
|
|
581
|
+
if (!selected) {
|
|
582
|
+
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`);
|
|
583
|
+
}
|
|
584
|
+
assertLibcCompatible(selected, host);
|
|
585
|
+
return selected;
|
|
586
|
+
}
|
|
587
|
+
function assertLibcCompatible(release, host = hostPlatform()) {
|
|
588
|
+
if (release.platform.libc && host.libc !== release.platform.libc) {
|
|
589
|
+
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");
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
551
593
|
// distribution/bootstrap/install.ts
|
|
552
594
|
var digest = (value) => createHash2("sha256").update(JSON.stringify(value)).digest("hex");
|
|
553
595
|
async function ownedDirectory(path, owner) {
|
|
@@ -622,13 +664,20 @@ function installationPaths(home, release) {
|
|
|
622
664
|
};
|
|
623
665
|
}
|
|
624
666
|
function versionAtLeast(actual, minimum) {
|
|
667
|
+
if (![actual, minimum].every((value) => /^\d+(?:\.\d+)*$/.test(value))) return false;
|
|
625
668
|
const a = actual.split(".").map(Number), b = minimum.split(".").map(Number);
|
|
626
|
-
if ([...a, ...b].some((n) => !Number.
|
|
669
|
+
if ([...a, ...b].some((n) => !Number.isSafeInteger(n))) return false;
|
|
627
670
|
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
628
671
|
if ((a[i] ?? 0) !== (b[i] ?? 0)) return (a[i] ?? 0) > (b[i] ?? 0);
|
|
629
672
|
}
|
|
630
673
|
return true;
|
|
631
674
|
}
|
|
675
|
+
function osReleaseAtLeast(actual, minimum, platform = process.platform) {
|
|
676
|
+
if (platform !== "linux") return versionAtLeast(actual, minimum);
|
|
677
|
+
const numericRelease = (value) => /^(\d+(?:\.\d+)*)(?:-[A-Za-z0-9][A-Za-z0-9.+_-]*)?$/.exec(value)?.[1];
|
|
678
|
+
const a = numericRelease(actual), b = numericRelease(minimum);
|
|
679
|
+
return a !== void 0 && b !== void 0 && versionAtLeast(a, b);
|
|
680
|
+
}
|
|
632
681
|
async function install(home, candidate, hooks = {}, programsOnly = false) {
|
|
633
682
|
home = resolve3(home);
|
|
634
683
|
await mkdir3(home, { recursive: true, mode: 448 });
|
|
@@ -675,7 +724,8 @@ async function install(home, candidate, hooks = {}, programsOnly = false) {
|
|
|
675
724
|
}
|
|
676
725
|
}
|
|
677
726
|
const release = record?.release ?? validateRelease(candidate);
|
|
678
|
-
|
|
727
|
+
assertLibcCompatible(release);
|
|
728
|
+
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
729
|
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
730
|
}
|
|
681
731
|
record ??= { format: 1, release, releaseDigest: digest(release), home, status: "installing", stage: "preflight", stages: {} };
|
|
@@ -1175,8 +1225,19 @@ async function uninstall(home, hooks = {}) {
|
|
|
1175
1225
|
|
|
1176
1226
|
// distribution/bootstrap/install-ui.ts
|
|
1177
1227
|
import { createInterface } from "node:readline";
|
|
1228
|
+
import { homedir } from "node:os";
|
|
1229
|
+
import { relative, sep as sep3 } from "node:path";
|
|
1178
1230
|
var gb = (bytes) => bytes === null ? "\u672A\u77E5" : `${(bytes / 1e9).toFixed(2)} GB`;
|
|
1179
1231
|
var mb = (bytes) => bytes < 1e5 ? `${(bytes / 1e3).toFixed(1)} KB` : `${(bytes / 1e6).toFixed(1)} MB`;
|
|
1232
|
+
var memory = (bytes) => {
|
|
1233
|
+
if (bytes === null) return "\u672A\u77E5";
|
|
1234
|
+
return bytes < 2 ** 30 ? `${Math.floor(bytes / 2 ** 20)} MiB` : `${Number((bytes / 2 ** 30).toFixed(2))} GiB`;
|
|
1235
|
+
};
|
|
1236
|
+
function displayPath(path) {
|
|
1237
|
+
const local = relative(homedir(), path);
|
|
1238
|
+
if (!local) return "~";
|
|
1239
|
+
return local === ".." || local.startsWith(`..${sep3}`) ? path : `~${sep3}${local}`;
|
|
1240
|
+
}
|
|
1180
1241
|
function installUI(assumeYes) {
|
|
1181
1242
|
const interactive = process.stdin.isTTY && process.stderr.isTTY;
|
|
1182
1243
|
const output = process.stderr;
|
|
@@ -1192,24 +1253,46 @@ function installUI(assumeYes) {
|
|
|
1192
1253
|
clear();
|
|
1193
1254
|
output.write(text + "\n");
|
|
1194
1255
|
};
|
|
1256
|
+
const heading = (text) => line(interactive && process.env.TERM !== "dumb" && process.env.NO_COLOR === void 0 ? `\x1B[1m${text}\x1B[22m` : text);
|
|
1195
1257
|
return {
|
|
1196
1258
|
async confirm(plan) {
|
|
1197
1259
|
const { sample, policy, disks } = plan.resources;
|
|
1198
|
-
|
|
1260
|
+
const narrow = interactive && output.columns > 0 && output.columns < 48;
|
|
1261
|
+
line("");
|
|
1262
|
+
heading("\u706B\u706B\u5B89\u88C5 \xB7 \u786E\u8BA4\u8BA1\u5212");
|
|
1263
|
+
line(` \u5B89\u88C5\u5230 ${displayPath(plan.home)}`);
|
|
1264
|
+
line("");
|
|
1265
|
+
heading("\u672C\u673A\u8D44\u6E90");
|
|
1199
1266
|
for (const [index, disk] of disks.entries()) {
|
|
1200
1267
|
const location = sample.disks.find((item) => item.device === disk.device)?.paths[0] ?? plan.home;
|
|
1201
|
-
line(
|
|
1268
|
+
if (disks.length > 1) line(` \u78C1\u76D8 ${index + 1} ${displayPath(location)}`);
|
|
1269
|
+
const need = `\u9700\u7559 ${gb(disk.requiredBytes)}`;
|
|
1270
|
+
const free = `\u53EF\u7528 ${gb(disk.availableBytes)}`;
|
|
1271
|
+
line(narrow ? ` \u78C1\u76D8 ${need}
|
|
1272
|
+
${free}` : ` \u78C1\u76D8 ${need} \xB7 ${free}`);
|
|
1273
|
+
}
|
|
1274
|
+
const available = `\u53EF\u7528 ${memory(sample.availableMemoryBytes)}`;
|
|
1275
|
+
const total = `\u603B\u91CF ${memory(sample.effectiveMemoryBytes)}`;
|
|
1276
|
+
line(narrow ? ` \u5185\u5B58 ${available}
|
|
1277
|
+
${total}` : ` \u5185\u5B58 ${available} \xB7 ${total}`);
|
|
1278
|
+
line(` \u542F\u52A8\u9700\u7559 ${memory(policy.startupHeadroomBytes)}`);
|
|
1279
|
+
line(` \u6700\u4F4E\u5BB9\u91CF ${memory(policy.minimumEffectiveMemoryBytes)}`);
|
|
1280
|
+
if (policy.observedInstallRssBytes) line(` \u5386\u53F2\u5B89\u88C5\u5CF0\u503C\u7EA6 ${memory(policy.observedInstallRssBytes)}`);
|
|
1281
|
+
for (const reason of plan.resources.reasons) line(` \u63D0\u793A ${reason}`);
|
|
1282
|
+
line("");
|
|
1283
|
+
heading("\u4E0B\u8F7D\u8BA1\u5212");
|
|
1284
|
+
const bytes = plan.downloads.reduce((total2, file) => total2 + file.size, 0);
|
|
1285
|
+
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");
|
|
1286
|
+
const local = [plan.bundled ? `\u968F\u5305 ${plan.bundled} \u9879` : "", plan.cached ? `\u590D\u7528\u7F13\u5B58 ${plan.cached} \u9879` : ""].filter(Boolean);
|
|
1287
|
+
if (local.length) line(` ${local.join(" \xB7 ")}`);
|
|
1288
|
+
for (const file of plan.downloads) {
|
|
1289
|
+
line(` ${file.name} ${mb(file.size)}`);
|
|
1290
|
+
line(` \u6765\u6E90 ${file.host}`);
|
|
1202
1291
|
}
|
|
1203
|
-
|
|
1204
|
-
line(
|
|
1205
|
-
line(
|
|
1206
|
-
|
|
1207
|
-
const bytes = plan.downloads.reduce((total, file) => total + file.size, 0);
|
|
1208
|
-
line(`\u56FA\u5B9A\u8D44\u6E90 \u8054\u7F51\u4E0B\u8F7D ${plan.downloads.length} \u9879\uFF08${mb(bytes)}\uFF09\uFF0C\u968F\u5305 ${plan.bundled} \u9879\uFF0C\u7F13\u5B58 ${plan.cached} \u9879`);
|
|
1209
|
-
for (const file of plan.downloads) line(` ${file.name} ${mb(file.size)} ${file.host}`);
|
|
1210
|
-
line(`\u56FA\u5B9A\u8D44\u6E90\u4FDD\u5B58\u81F3 ${plan.home}/cache`);
|
|
1211
|
-
if (plan.upstreamWheelCount !== void 0) line(`Python \u4F9D\u8D56\u6E05\u5355 ${plan.upstreamWheelCount} \u9879\u56FA\u5B9A\u4E0A\u6E38\u6587\u4EF6\uFF0C\u5DF2\u5B89\u88C5\u9879\u53EF\u80FD\u8DF3\u8FC7\u3002`);
|
|
1212
|
-
line("\u540E\u7EED\u8FD8\u4F1A\u5B89\u88C5 npm \u548C Python \u4F9D\u8D56\uFF0C\u5B9E\u9645\u8054\u7F51\u4E0B\u8F7D\u91CF\u53D6\u51B3\u4E8E\u672C\u673A\u7F13\u5B58\u548C\u4F9D\u8D56\u89E3\u6790\u7ED3\u679C\u3002");
|
|
1292
|
+
if (plan.downloads.length || plan.bundled) line(` \u4FDD\u5B58\u5230 ${displayPath(plan.home)}/cache`);
|
|
1293
|
+
if (plan.upstreamWheelCount !== void 0) line(` Python \u4E0A\u6E38\u6587\u4EF6 ${plan.upstreamWheelCount} \u9879`);
|
|
1294
|
+
line(" npm \u548C Python \u4F9D\u8D56\u4ECD\u53EF\u80FD\u8054\u7F51");
|
|
1295
|
+
line("");
|
|
1213
1296
|
if (assumeYes) return true;
|
|
1214
1297
|
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
1298
|
const terminal = createInterface({ input: process.stdin, output, terminal: true });
|
|
@@ -1333,6 +1416,27 @@ async function showStatus(home, watch) {
|
|
|
1333
1416
|
}
|
|
1334
1417
|
}
|
|
1335
1418
|
|
|
1419
|
+
// distribution/bootstrap/assets.ts
|
|
1420
|
+
import { createRequire } from "node:module";
|
|
1421
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
1422
|
+
import { dirname as dirname5, join as join7 } from "node:path";
|
|
1423
|
+
import { fileURLToPath } from "node:url";
|
|
1424
|
+
async function assetsDirectory(release, entryURL = import.meta.url) {
|
|
1425
|
+
if (!release?.assetPackage) return join7(dirname5(fileURLToPath(entryURL)), "assets");
|
|
1426
|
+
const expected = release.assetPackage;
|
|
1427
|
+
let file;
|
|
1428
|
+
try {
|
|
1429
|
+
file = createRequire(entryURL).resolve(`${expected.name}/package.json`);
|
|
1430
|
+
} catch {
|
|
1431
|
+
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");
|
|
1432
|
+
}
|
|
1433
|
+
const manifest = JSON.parse(await readFile8(file, "utf8"));
|
|
1434
|
+
if (manifest.name !== expected.name || manifest.version !== expected.version) {
|
|
1435
|
+
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");
|
|
1436
|
+
}
|
|
1437
|
+
return join7(dirname5(file), "assets");
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1336
1440
|
// distribution/bootstrap/entry.ts
|
|
1337
1441
|
function artifactSource(source, directory) {
|
|
1338
1442
|
return async (url, options) => {
|
|
@@ -1341,8 +1445,8 @@ function artifactSource(source, directory) {
|
|
|
1341
1445
|
const artifact2 = source && [source.runtime, source.python, source.pythonDependencies].find((item) => item.url === String(url));
|
|
1342
1446
|
const sha256 = bundled?.[1] ?? artifact2?.sha256;
|
|
1343
1447
|
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 =
|
|
1448
|
+
const root = directory ?? await assetsDirectory(source, import.meta.url);
|
|
1449
|
+
const path = join8(root, sha256 + ".tgz");
|
|
1346
1450
|
const file = await open3(path).catch((error) => {
|
|
1347
1451
|
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
1452
|
throw error;
|
|
@@ -1351,7 +1455,7 @@ function artifactSource(source, directory) {
|
|
|
1351
1455
|
};
|
|
1352
1456
|
}
|
|
1353
1457
|
async function main(args = process.argv.slice(2)) {
|
|
1354
|
-
let home =
|
|
1458
|
+
let home = join8(homedir2(), ".huohuo"), noOpen = false, assumeYes = false, watch = false, command = "start";
|
|
1355
1459
|
let releaseFile, artifactDirectory;
|
|
1356
1460
|
for (let i = 0; i < args.length; i++) {
|
|
1357
1461
|
if (args[i] === "--home") {
|
|
@@ -1366,8 +1470,8 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1366
1470
|
else if (args[i] === "--yes") assumeYes = true;
|
|
1367
1471
|
else if (args[i] === "--watch") watch = true;
|
|
1368
1472
|
else if (args[i] === "--version") {
|
|
1369
|
-
const packageFile =
|
|
1370
|
-
const manifest = JSON.parse(await
|
|
1473
|
+
const packageFile = join8(dirname6(fileURLToPath2(import.meta.url)), "package.json");
|
|
1474
|
+
const manifest = JSON.parse(await readFile9(packageFile, "utf8"));
|
|
1371
1475
|
console.log(`${manifest.name} ${manifest.version}${manifest.private ? "\uFF08\u672C\u5730\u5019\u9009\uFF09" : ""}`);
|
|
1372
1476
|
return;
|
|
1373
1477
|
} else if (["start", "status", "doctor", "stop", "upgrade", "uninstall"].includes(args[i])) command = args[i];
|
|
@@ -1398,11 +1502,11 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1398
1502
|
};
|
|
1399
1503
|
const ui = installUI(assumeYes);
|
|
1400
1504
|
if (command === "upgrade") {
|
|
1401
|
-
const candidate = JSON.parse(await
|
|
1505
|
+
const candidate = selectRelease(JSON.parse(await readFile9(releaseFile ?? join8(dirname6(fileURLToPath2(import.meta.url)), "release.json"), "utf8")));
|
|
1402
1506
|
await upgrade(home, candidate, { fetcher: artifactSource(candidate, artifactDirectory), progress, ...ui });
|
|
1403
1507
|
const current = await readInstallation(home);
|
|
1404
1508
|
if (await control(home, current.releaseDigest, noOpen ? "status" : "open")) return;
|
|
1405
|
-
await run(process.execPath, [
|
|
1509
|
+
await run(process.execPath, [join8(installationPaths(home, current.release).runtime, "lib/distribution/managed.js"), "start", home, ...noOpen ? ["--no-open"] : []], home);
|
|
1406
1510
|
return;
|
|
1407
1511
|
}
|
|
1408
1512
|
if (command === "uninstall") {
|
|
@@ -1420,7 +1524,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1420
1524
|
return;
|
|
1421
1525
|
}
|
|
1422
1526
|
const paths = installationPaths(home, record.release);
|
|
1423
|
-
const targets = [home, paths.directory, paths.environment,
|
|
1527
|
+
const targets = [home, paths.directory, paths.environment, join8(home, "instances/default")];
|
|
1424
1528
|
const resources = evaluateResources(await sampleResources(targets), record.release.budget, targets.map((path) => ({ path, bytes: 0 })), "start");
|
|
1425
1529
|
console.log(JSON.stringify({
|
|
1426
1530
|
home,
|
|
@@ -1441,30 +1545,31 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1441
1545
|
}
|
|
1442
1546
|
const runtime = installationPaths(home, record.release).runtime;
|
|
1443
1547
|
try {
|
|
1444
|
-
await
|
|
1548
|
+
await readFile9(join8(runtime, "lib/distribution/managed.js"));
|
|
1445
1549
|
} catch (e) {
|
|
1446
1550
|
if (e.code !== "ENOENT") throw e;
|
|
1447
1551
|
record = void 0;
|
|
1448
1552
|
}
|
|
1449
1553
|
}
|
|
1450
1554
|
if (!record || record.status !== "ready") {
|
|
1451
|
-
|
|
1452
|
-
|
|
1555
|
+
const persisted = await readInstallation(home);
|
|
1556
|
+
let source = persisted?.release;
|
|
1557
|
+
if (!source) {
|
|
1558
|
+
let catalog = null;
|
|
1453
1559
|
try {
|
|
1454
|
-
catalog = JSON.parse(await
|
|
1560
|
+
catalog = JSON.parse(await readFile9(releaseFile ?? join8(dirname6(fileURLToPath2(import.meta.url)), "release.json"), "utf8"));
|
|
1455
1561
|
} catch (e) {
|
|
1456
1562
|
if (e.code !== "ENOENT") throw e;
|
|
1457
1563
|
}
|
|
1564
|
+
source = selectRelease(catalog);
|
|
1458
1565
|
}
|
|
1459
|
-
const source = (await readInstallation(home))?.release ?? catalog;
|
|
1460
1566
|
const fetcher = artifactSource(source, artifactDirectory);
|
|
1461
|
-
|
|
1462
|
-
record = await install(home, catalog, { fetcher, progress, bundleDirectory, ...ui });
|
|
1567
|
+
record = await install(home, source, { fetcher, progress, ...ui });
|
|
1463
1568
|
}
|
|
1464
1569
|
const installedHome = record.home;
|
|
1465
|
-
await run(process.execPath, [
|
|
1570
|
+
await run(process.execPath, [join8(installationPaths(installedHome, record.release).runtime, "lib/distribution/managed.js"), "start", installedHome, ...noOpen ? ["--no-open"] : []], installedHome);
|
|
1466
1571
|
}
|
|
1467
|
-
if (process.argv[1] && await realpath5(resolve5(process.argv[1])).catch(() => "") === await realpath5(
|
|
1572
|
+
if (process.argv[1] && await realpath5(resolve5(process.argv[1])).catch(() => "") === await realpath5(fileURLToPath2(import.meta.url))) {
|
|
1468
1573
|
main().catch((error) => {
|
|
1469
1574
|
console.error(error instanceof Error ? error.message : "\u5B89\u88C5\u6216\u542F\u52A8\u5931\u8D25");
|
|
1470
1575
|
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.5",
|
|
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.5",
|
|
19
|
+
"@pab-iprg/huohuo-assets-linux-x64": "1.0.0-preview.5"
|
|
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/45b0bbe6c53759c5e1f50fbd506ea97ec74adf1f29b3ade98793210f3b66dfbc.tgz",
|
|
22
|
+
"bundled": true,
|
|
23
|
+
"sha256": "45b0bbe6c53759c5e1f50fbd506ea97ec74adf1f29b3ade98793210f3b66dfbc",
|
|
24
|
+
"integrity": "sha512-bFFRkVFn/4OgqU6CneroGm+qy0tP8hXaHZ4U0C6tW3DHGxvBX8c0gn0UTRYIRxrQUQ2QbcXbvcgAG7MsADw26A==",
|
|
25
|
+
"downloadBytes": 2609884,
|
|
26
|
+
"expandedBytes": 8326138
|
|
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": "aae1b5ee7f19d24d384a0f57de3e62ea9a1501e316193266d630f773dac058f1",
|
|
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.5"
|
|
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/4bab6aed6c844ab711d0a91b27c2e108ca8d4f4de1f4b30f7668b73f922d8500.tgz",
|
|
122
|
+
"bundled": true,
|
|
123
|
+
"sha256": "4bab6aed6c844ab711d0a91b27c2e108ca8d4f4de1f4b30f7668b73f922d8500",
|
|
124
|
+
"integrity": "sha512-Iu0NMfgVLZmPXcxcUfYbW48X0uvHFDUzpQWhPP6unz06v2G1f178m10ehU0pxNzJaUXkwg/p8OH5/DAeuungRg==",
|
|
125
|
+
"downloadBytes": 2609889,
|
|
126
|
+
"expandedBytes": 8326156
|
|
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": "aae1b5ee7f19d24d384a0f57de3e62ea9a1501e316193266d630f773dac058f1",
|
|
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.5"
|
|
202
|
+
}
|
|
93
203
|
}
|
|
94
|
-
|
|
204
|
+
]
|
|
95
205
|
}
|
|
Binary file
|