@amd-gaia/gaia 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +244 -0
- package/LICENSE +21 -0
- package/README.md +225 -6
- package/SKILL.md +597 -0
- package/SPEC.md +537 -0
- package/binaries.lock.json +78 -0
- package/dist/cli.d.ts +41 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +493 -0
- package/dist/cli.js.map +1 -0
- package/dist/errors.d.ts +41 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +51 -0
- package/dist/errors.js.map +1 -0
- package/dist/fetch.d.ts +111 -0
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +369 -0
- package/dist/fetch.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle.d.ts +162 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +613 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/logger.d.ts +13 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +30 -0
- package/dist/logger.js.map +1 -0
- package/dist/platform.d.ts +100 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +202 -0
- package/dist/platform.js.map +1 -0
- package/dist/url.d.ts +4 -0
- package/dist/url.d.ts.map +1 -0
- package/dist/url.js +22 -0
- package/dist/url.js.map +1 -0
- package/package.json +66 -15
package/dist/fetch.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binary fetcher for both components (`sidecar` and `tui`).
|
|
3
|
+
*
|
|
4
|
+
* Resolves the current platform → looks the component up in
|
|
5
|
+
* `binaries.lock.json` → downloads it from THAT COMPONENT's base URL
|
|
6
|
+
* (overridable) → **verifies its SHA-256 against the lock and fails loudly on
|
|
7
|
+
* any mismatch** → writes it into a cache dir → `chmod +x` on POSIX.
|
|
8
|
+
*
|
|
9
|
+
* The two components come from different hub lanes: the sidecar from
|
|
10
|
+
* `agents/gaia/<agentVersion>/`, the TUI from `agents/terminal-hub/<tuiVersion>/`
|
|
11
|
+
* (the same binary a core install runs as `gaia tui`). Each entry's base URL
|
|
12
|
+
* comes from its own component, never from a shared top-level one.
|
|
13
|
+
*
|
|
14
|
+
* The SHA verify is the security boundary: a tampered, truncated, or
|
|
15
|
+
* not-yet-published artifact is rejected before it can ever be spawned. There is
|
|
16
|
+
* NO "use it anyway" path, and a placeholder hash in the lock blocks the fetch
|
|
17
|
+
* outright rather than degrading to an unverified download.
|
|
18
|
+
*/
|
|
19
|
+
import { type BinaryLock, type ComponentName } from "./platform.js";
|
|
20
|
+
/**
|
|
21
|
+
* Where verified binaries are cached, keyed by agent version so a version bump
|
|
22
|
+
* never reuses the previous release's executables.
|
|
23
|
+
*/
|
|
24
|
+
export declare function defaultCacheDir(agentVersion: string): string;
|
|
25
|
+
/** The hub agent id this package installs the sidecar as. */
|
|
26
|
+
export declare const SIDECAR_AGENT_ID = "gaia";
|
|
27
|
+
/** Basename of the hub install record (`gaia.hub.installer.SENTINEL_NAME`). */
|
|
28
|
+
export declare const INSTALLED_SENTINEL_NAME = ".installed";
|
|
29
|
+
/**
|
|
30
|
+
* The daemon's own sidecar cache — `~/.gaia/agents/gaia/`, mirroring
|
|
31
|
+
* `gaia.daemon.sidecars.fetch.default_cache_dir("gaia")`. Staging the verified
|
|
32
|
+
* sidecar here means the daemon's own fetch is a SHA-256 cache hit instead of a
|
|
33
|
+
* second download. This path is a cross-repo contract with the daemon.
|
|
34
|
+
*/
|
|
35
|
+
export declare function daemonSidecarCacheDir(agentId?: string): string;
|
|
36
|
+
export interface FetchOptions {
|
|
37
|
+
/** Which binary to fetch. */
|
|
38
|
+
component: ComponentName;
|
|
39
|
+
/** Directory the verified binary is written into. Required. */
|
|
40
|
+
outDir: string;
|
|
41
|
+
/**
|
|
42
|
+
* Override this component's `baseUrl` (e.g. a local mirror). Trailing slash
|
|
43
|
+
* optional. Applies to whichever component is being fetched — the two lanes'
|
|
44
|
+
* filenames never collide, so one flat mirror directory can serve both.
|
|
45
|
+
*/
|
|
46
|
+
baseUrl?: string;
|
|
47
|
+
/** Override the platform key (defaults to the current host). */
|
|
48
|
+
platformKey?: string;
|
|
49
|
+
/** Path to the lock file (defaults to the packaged binaries.lock.json). */
|
|
50
|
+
lockPath?: string;
|
|
51
|
+
/** A pre-loaded lock, to avoid re-reading it per component. */
|
|
52
|
+
lock?: BinaryLock;
|
|
53
|
+
/** Fetch override (tests). Defaults to global `fetch`. */
|
|
54
|
+
fetchImpl?: typeof fetch;
|
|
55
|
+
/** Re-download even when a verified binary is already cached. Default false. */
|
|
56
|
+
force?: boolean;
|
|
57
|
+
/** Abort the download after this many ms. Default 300000 (the sidecar is ~200MB). */
|
|
58
|
+
timeoutMs?: number;
|
|
59
|
+
}
|
|
60
|
+
export interface FetchResult {
|
|
61
|
+
component: ComponentName;
|
|
62
|
+
/** Absolute path to the written, verified executable. */
|
|
63
|
+
binaryPath: string;
|
|
64
|
+
/** The platform key resolved. */
|
|
65
|
+
platformKey: string;
|
|
66
|
+
/** The verified SHA-256 (lowercase hex). */
|
|
67
|
+
sha256: string;
|
|
68
|
+
/** Source URL the artifact was downloaded from. */
|
|
69
|
+
url: string;
|
|
70
|
+
/** True when the on-disk binary was reused (hash already matched). */
|
|
71
|
+
cached: boolean;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* SHA-256 of a file on disk, or null when it is simply absent. Any other error
|
|
75
|
+
* (a permission problem, a directory in the way) is re-raised: reading it as
|
|
76
|
+
* "no cache" would trigger a re-download that then fails on write with a far
|
|
77
|
+
* less useful message.
|
|
78
|
+
*/
|
|
79
|
+
export declare function fileSha256(filePath: string): Promise<string | null>;
|
|
80
|
+
/** Verify an in-memory buffer against an expected SHA-256. */
|
|
81
|
+
export declare function verifySha256(buf: Buffer, expected: string, sourceLabel: string): string;
|
|
82
|
+
/**
|
|
83
|
+
* Fetch + verify + install one component's binary for the current platform.
|
|
84
|
+
*
|
|
85
|
+
* @throws PlatformError unsupported platform / incomplete entry / placeholder hash
|
|
86
|
+
* @throws IntegrityError SHA-256 mismatch
|
|
87
|
+
* @throws Error download/network failure (HTTP status surfaced)
|
|
88
|
+
*/
|
|
89
|
+
export declare function fetchBinary(opts: FetchOptions): Promise<FetchResult>;
|
|
90
|
+
export interface FetchAllOptions extends Omit<FetchOptions, "component" | "outDir"> {
|
|
91
|
+
/** Cache dir for the TUI. Defaults to `defaultCacheDir(lock.agentVersion)`. */
|
|
92
|
+
tuiDir?: string;
|
|
93
|
+
/** Cache dir for the sidecar. Defaults to the daemon's `~/.gaia/agents/gaia`. */
|
|
94
|
+
sidecarDir?: string;
|
|
95
|
+
}
|
|
96
|
+
export interface FetchAllResult {
|
|
97
|
+
sidecar: FetchResult;
|
|
98
|
+
tui: FetchResult;
|
|
99
|
+
lock: BinaryLock;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Fetch + verify BOTH binaries. Sequential on purpose: the sidecar is the large
|
|
103
|
+
* download and a failure there should not race a half-finished TUI download.
|
|
104
|
+
*
|
|
105
|
+
* The sidecar lands in the daemon's own cache dir so the daemon — which owns
|
|
106
|
+
* spawning it — finds it already verified instead of downloading it again.
|
|
107
|
+
*/
|
|
108
|
+
export declare function fetchAll(opts?: FetchAllOptions): Promise<FetchAllResult>;
|
|
109
|
+
/** Sync existence check, for the lifecycle layer. */
|
|
110
|
+
export declare function binaryExists(binaryPath: string): boolean;
|
|
111
|
+
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAWH,OAAO,EACL,KAAK,UAAU,EAEf,KAAK,aAAa,EAQnB,MAAM,eAAe,CAAC;AAIvB;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,SAAS,CAAC;AAEvC,+EAA+E;AAC/E,eAAO,MAAM,uBAAuB,eAAe,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,SAAmB,GAAG,MAAM,CAExE;AA+DD,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,SAAS,EAAE,aAAa,CAAC;IACzB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,aAAa,CAAC;IACzB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,MAAM,EAAE,OAAO,CAAC;CACjB;AASD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA+BzE;AA+DD,8DAA8D;AAC9D,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,MAAM,CAER;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAoJ1E;AAED,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,QAAQ,CAAC;IACjF,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAelF;AAED,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAExD"}
|
package/dist/fetch.js
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
// Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
/**
|
|
4
|
+
* Binary fetcher for both components (`sidecar` and `tui`).
|
|
5
|
+
*
|
|
6
|
+
* Resolves the current platform → looks the component up in
|
|
7
|
+
* `binaries.lock.json` → downloads it from THAT COMPONENT's base URL
|
|
8
|
+
* (overridable) → **verifies its SHA-256 against the lock and fails loudly on
|
|
9
|
+
* any mismatch** → writes it into a cache dir → `chmod +x` on POSIX.
|
|
10
|
+
*
|
|
11
|
+
* The two components come from different hub lanes: the sidecar from
|
|
12
|
+
* `agents/gaia/<agentVersion>/`, the TUI from `agents/terminal-hub/<tuiVersion>/`
|
|
13
|
+
* (the same binary a core install runs as `gaia tui`). Each entry's base URL
|
|
14
|
+
* comes from its own component, never from a shared top-level one.
|
|
15
|
+
*
|
|
16
|
+
* The SHA verify is the security boundary: a tampered, truncated, or
|
|
17
|
+
* not-yet-published artifact is rejected before it can ever be spawned. There is
|
|
18
|
+
* NO "use it anyway" path, and a placeholder hash in the lock blocks the fetch
|
|
19
|
+
* outright rather than degrading to an unverified download.
|
|
20
|
+
*/
|
|
21
|
+
import crypto from "node:crypto";
|
|
22
|
+
import fs from "node:fs";
|
|
23
|
+
import fsp from "node:fs/promises";
|
|
24
|
+
import os from "node:os";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
import { IntegrityError, PlatformError } from "./errors.js";
|
|
27
|
+
import { createLogger } from "./logger.js";
|
|
28
|
+
import { joinUrl } from "./url.js";
|
|
29
|
+
import { componentBaseUrl, componentLock, currentPlatformKey, defaultLockPath, isPlaceholderSha, loadLock, resolveEntry, } from "./platform.js";
|
|
30
|
+
const log = createLogger("fetch");
|
|
31
|
+
/**
|
|
32
|
+
* Where verified binaries are cached, keyed by agent version so a version bump
|
|
33
|
+
* never reuses the previous release's executables.
|
|
34
|
+
*/
|
|
35
|
+
export function defaultCacheDir(agentVersion) {
|
|
36
|
+
return path.join(os.homedir(), ".gaia", "npm-cache", `gaia-${agentVersion}`);
|
|
37
|
+
}
|
|
38
|
+
/** The hub agent id this package installs the sidecar as. */
|
|
39
|
+
export const SIDECAR_AGENT_ID = "gaia";
|
|
40
|
+
/** Basename of the hub install record (`gaia.hub.installer.SENTINEL_NAME`). */
|
|
41
|
+
export const INSTALLED_SENTINEL_NAME = ".installed";
|
|
42
|
+
/**
|
|
43
|
+
* The daemon's own sidecar cache — `~/.gaia/agents/gaia/`, mirroring
|
|
44
|
+
* `gaia.daemon.sidecars.fetch.default_cache_dir("gaia")`. Staging the verified
|
|
45
|
+
* sidecar here means the daemon's own fetch is a SHA-256 cache hit instead of a
|
|
46
|
+
* second download. This path is a cross-repo contract with the daemon.
|
|
47
|
+
*/
|
|
48
|
+
export function daemonSidecarCacheDir(agentId = SIDECAR_AGENT_ID) {
|
|
49
|
+
return path.join(os.homedir(), ".gaia", "agents", agentId);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Whether this fetch produced a runnable local install worth recording.
|
|
53
|
+
*
|
|
54
|
+
* `--platform` fetches a binary for a DIFFERENT host — a cross-compile staging
|
|
55
|
+
* step, not an install. Recording one would hand the daemon a wrong-arch
|
|
56
|
+
* executable that re-hashes correctly and then fails to exec.
|
|
57
|
+
*/
|
|
58
|
+
function installsForThisHost(component, platformKey) {
|
|
59
|
+
return component === "sidecar" && platformKey === currentPlatformKey();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Record a completed install the way `gaia.hub.installer` does.
|
|
63
|
+
*
|
|
64
|
+
* Staging a verified binary is only half the job the CLI claims to do. Without
|
|
65
|
+
* this file the daemon's `_hub_installed_binary` sees no install, and the TUI
|
|
66
|
+
* treats `gaia-agent` as its own stdio child — spawning our REST sidecar over
|
|
67
|
+
* stdio and filling the chat with uvicorn's startup log. With it, the TUI uses
|
|
68
|
+
* daemon transport and the daemon supervises the process and mints its token.
|
|
69
|
+
*
|
|
70
|
+
* Field names and `artifact_kind`/`executable`/`artifact_sha256` are a
|
|
71
|
+
* cross-repo contract with `InstalledAgent.to_dict()`; the daemon re-hashes the
|
|
72
|
+
* binary and raises if it does not match `artifact_sha256`, so this must carry
|
|
73
|
+
* the hash we actually verified.
|
|
74
|
+
*/
|
|
75
|
+
async function writeInstalledSentinel(opts) {
|
|
76
|
+
const sentinel = path.join(opts.outDir, INSTALLED_SENTINEL_NAME);
|
|
77
|
+
const record = {
|
|
78
|
+
id: SIDECAR_AGENT_ID,
|
|
79
|
+
version: opts.version,
|
|
80
|
+
language: "python",
|
|
81
|
+
installed_at: new Date().toISOString(),
|
|
82
|
+
artifact_sha256: opts.sha256,
|
|
83
|
+
path: opts.outDir,
|
|
84
|
+
artifact_kind: "binary",
|
|
85
|
+
executable: opts.executable,
|
|
86
|
+
};
|
|
87
|
+
// Temp-then-rename: a truncated sentinel reads as a corrupt install, which
|
|
88
|
+
// looks identical to "never installed".
|
|
89
|
+
const tmp = `${sentinel}.tmp.${process.pid}`;
|
|
90
|
+
try {
|
|
91
|
+
await fsp.writeFile(tmp, `${JSON.stringify(record, null, 2)}\n`, "utf8");
|
|
92
|
+
await fsp.rename(tmp, sentinel);
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
await fsp.rm(tmp, { force: true }).catch(() => undefined);
|
|
96
|
+
throw new Error(`verified the sidecar at ${opts.outDir} but could not write its ` +
|
|
97
|
+
`${INSTALLED_SENTINEL_NAME} record: ${e.message}. Without it the ` +
|
|
98
|
+
"daemon does not see a completed install and the TUI falls back to running " +
|
|
99
|
+
`the sidecar over stdio. Check write permissions on ${opts.outDir}.`, { cause: e });
|
|
100
|
+
}
|
|
101
|
+
log.debug(`wrote ${sentinel} (v${opts.version})`);
|
|
102
|
+
}
|
|
103
|
+
function sha256Hex(buf) {
|
|
104
|
+
return crypto.createHash("sha256").update(buf).digest("hex");
|
|
105
|
+
}
|
|
106
|
+
/** Read size for incremental hashing — bounded regardless of artifact size. */
|
|
107
|
+
const HASH_CHUNK_BYTES = 1 << 20;
|
|
108
|
+
/**
|
|
109
|
+
* SHA-256 of a file on disk, or null when it is simply absent. Any other error
|
|
110
|
+
* (a permission problem, a directory in the way) is re-raised: reading it as
|
|
111
|
+
* "no cache" would trigger a re-download that then fails on write with a far
|
|
112
|
+
* less useful message.
|
|
113
|
+
*/
|
|
114
|
+
export async function fileSha256(filePath) {
|
|
115
|
+
const unreadable = (e) => new Error(`cannot read the cached binary at ${filePath} to check its hash: ${e.message}. ` +
|
|
116
|
+
"Fix the permissions on that path, or pass a different --cache-dir / --sidecar-dir.", { cause: e });
|
|
117
|
+
let fh;
|
|
118
|
+
try {
|
|
119
|
+
fh = await fsp.open(filePath, "r");
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
if (e.code === "ENOENT")
|
|
123
|
+
return null;
|
|
124
|
+
throw unreadable(e);
|
|
125
|
+
}
|
|
126
|
+
// Chunked, not readFile: this runs on every cache hit, and the sidecar is
|
|
127
|
+
// ~200MB — buffering it whole is the peak the streaming download removed.
|
|
128
|
+
try {
|
|
129
|
+
const hash = crypto.createHash("sha256");
|
|
130
|
+
const buf = Buffer.allocUnsafe(HASH_CHUNK_BYTES);
|
|
131
|
+
for (;;) {
|
|
132
|
+
const { bytesRead } = await fh.read(buf, 0, buf.length, null);
|
|
133
|
+
if (bytesRead === 0)
|
|
134
|
+
break;
|
|
135
|
+
hash.update(buf.subarray(0, bytesRead));
|
|
136
|
+
}
|
|
137
|
+
return hash.digest("hex");
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
throw unreadable(e);
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
await fh.close();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Stream a response body to `tmp`, hashing as it goes.
|
|
148
|
+
*
|
|
149
|
+
* Incremental on purpose: the sidecar is ~200MB and `arrayBuffer()` would peak
|
|
150
|
+
* at roughly double that. Awaiting each write applies backpressure.
|
|
151
|
+
*/
|
|
152
|
+
async function streamToFile(res, tmp, url) {
|
|
153
|
+
if (!res.body) {
|
|
154
|
+
throw new Error(`download failed: ${url} returned HTTP ${res.status} with no response body. ` +
|
|
155
|
+
"Check the base URL and that the artifact is published for this platform.");
|
|
156
|
+
}
|
|
157
|
+
const hash = crypto.createHash("sha256");
|
|
158
|
+
let bytes = 0;
|
|
159
|
+
let fh;
|
|
160
|
+
try {
|
|
161
|
+
fh = await fsp.open(tmp, "w");
|
|
162
|
+
}
|
|
163
|
+
catch (e) {
|
|
164
|
+
throw new Error(`cannot open ${tmp} to stage the download: ${e.message}. ` +
|
|
165
|
+
"Check write permissions on that directory, or pass a different " +
|
|
166
|
+
"--sidecar-dir / --cache-dir.", { cause: e });
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
for await (const chunk of res.body) {
|
|
170
|
+
hash.update(chunk);
|
|
171
|
+
bytes += chunk.byteLength;
|
|
172
|
+
await fh.write(chunk);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
await fh.close();
|
|
177
|
+
}
|
|
178
|
+
return { sha256: hash.digest("hex"), bytes };
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Compare an already-computed SHA-256 with the expected one. Throws
|
|
182
|
+
* `IntegrityError` loudly on mismatch — this is the no-silent-fallback gate.
|
|
183
|
+
*/
|
|
184
|
+
function assertSha256(actual, expected, sourceLabel) {
|
|
185
|
+
if (actual.toLowerCase() !== expected.toLowerCase()) {
|
|
186
|
+
throw new IntegrityError(`SHA-256 mismatch for ${sourceLabel}:\n` +
|
|
187
|
+
` expected ${expected}\n` +
|
|
188
|
+
` actual ${actual}\n` +
|
|
189
|
+
"Refusing to use a binary that does not match binaries.lock.json. " +
|
|
190
|
+
"The download may be corrupt, truncated, or tampered with. Re-run the fetch; " +
|
|
191
|
+
"if it persists, the lock is stale relative to the published artifact — " +
|
|
192
|
+
"report it at https://github.com/amd/gaia/issues.");
|
|
193
|
+
}
|
|
194
|
+
return actual;
|
|
195
|
+
}
|
|
196
|
+
/** Verify an in-memory buffer against an expected SHA-256. */
|
|
197
|
+
export function verifySha256(buf, expected, sourceLabel) {
|
|
198
|
+
return assertSha256(sha256Hex(buf), expected, sourceLabel);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Fetch + verify + install one component's binary for the current platform.
|
|
202
|
+
*
|
|
203
|
+
* @throws PlatformError unsupported platform / incomplete entry / placeholder hash
|
|
204
|
+
* @throws IntegrityError SHA-256 mismatch
|
|
205
|
+
* @throws Error download/network failure (HTTP status surfaced)
|
|
206
|
+
*/
|
|
207
|
+
export async function fetchBinary(opts) {
|
|
208
|
+
if (!opts?.outDir) {
|
|
209
|
+
throw new TypeError("fetchBinary requires an outDir to write the binary into");
|
|
210
|
+
}
|
|
211
|
+
if (!opts?.component) {
|
|
212
|
+
throw new TypeError('fetchBinary requires a component ("sidecar" or "tui")');
|
|
213
|
+
}
|
|
214
|
+
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
215
|
+
if (typeof fetchImpl !== "function") {
|
|
216
|
+
throw new TypeError("global fetch unavailable — use Node >= 18 or pass fetchImpl");
|
|
217
|
+
}
|
|
218
|
+
const lock = opts.lock ?? loadLock(opts.lockPath ?? defaultLockPath());
|
|
219
|
+
const platformKey = opts.platformKey ?? currentPlatformKey();
|
|
220
|
+
const entry = resolveEntry(lock, opts.component, platformKey);
|
|
221
|
+
// Per-component: the sidecar and the TUI live in different hub lanes at
|
|
222
|
+
// different versions, so there is no single base URL to fall back to.
|
|
223
|
+
const baseUrl = opts.baseUrl ?? componentBaseUrl(lock, opts.component);
|
|
224
|
+
if (isPlaceholderSha(entry.sha256)) {
|
|
225
|
+
throw new PlatformError(`binaries.lock.json has a placeholder sha256 for ${opts.component}/'${platformKey}' ` +
|
|
226
|
+
`(${entry.sha256}), so no verifiable binary is published for it in this build. ` +
|
|
227
|
+
"Fetch is blocked so an unverifiable binary can never be trusted. " +
|
|
228
|
+
"Install a released @amd-gaia/gaia, or build the binary locally " +
|
|
229
|
+
"(hub/agents/gaia/python/packaging for the sidecar, `make -C tui cross-compile` " +
|
|
230
|
+
"for the TUI) and point the lifecycle helpers at it directly.");
|
|
231
|
+
}
|
|
232
|
+
const outDir = path.resolve(opts.outDir);
|
|
233
|
+
await fsp.mkdir(outDir, { recursive: true });
|
|
234
|
+
const binaryPath = path.join(outDir, entry.executable);
|
|
235
|
+
const url = joinUrl(baseUrl, entry.filename);
|
|
236
|
+
if (!opts.force) {
|
|
237
|
+
const existing = await fileSha256(binaryPath);
|
|
238
|
+
if (existing && existing.toLowerCase() === entry.sha256.toLowerCase()) {
|
|
239
|
+
log.debug(`cache hit: ${binaryPath} already matches lock sha256`);
|
|
240
|
+
// Re-apply the exec bit: an interrupted earlier run or a restrictive umask
|
|
241
|
+
// can leave correct bytes that still cannot be spawned.
|
|
242
|
+
if (process.platform !== "win32")
|
|
243
|
+
await fsp.chmod(binaryPath, 0o755);
|
|
244
|
+
// Also on a cache hit: an earlier release staged a verified binary with no
|
|
245
|
+
// sentinel, and those installs would otherwise never repair themselves.
|
|
246
|
+
if (installsForThisHost(opts.component, platformKey)) {
|
|
247
|
+
await writeInstalledSentinel({
|
|
248
|
+
outDir,
|
|
249
|
+
version: componentLock(lock, "sidecar").componentVersion,
|
|
250
|
+
sha256: existing,
|
|
251
|
+
executable: entry.executable,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
component: opts.component,
|
|
256
|
+
binaryPath,
|
|
257
|
+
platformKey,
|
|
258
|
+
sha256: existing,
|
|
259
|
+
url,
|
|
260
|
+
cached: true,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
log.info(`downloading ${opts.component} for ${platformKey} from ${url}`);
|
|
265
|
+
const timeoutMs = opts.timeoutMs ?? 300_000;
|
|
266
|
+
const controller = new AbortController();
|
|
267
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
268
|
+
// Streamed to a temp file while hashing incrementally: the sidecar is ~200MB
|
|
269
|
+
// and buffering it whole peaks at roughly double that in RSS.
|
|
270
|
+
const tmp = `${binaryPath}.download.${process.pid}`;
|
|
271
|
+
let actualSha;
|
|
272
|
+
let bytes;
|
|
273
|
+
try {
|
|
274
|
+
const res = await fetchImpl(url, {
|
|
275
|
+
headers: { accept: "application/octet-stream" },
|
|
276
|
+
signal: controller.signal,
|
|
277
|
+
});
|
|
278
|
+
if (!res.ok) {
|
|
279
|
+
throw new Error(`download failed: HTTP ${res.status} ${res.statusText} for ${url}. ` +
|
|
280
|
+
"Check the base URL and that the artifact is published for this platform.");
|
|
281
|
+
}
|
|
282
|
+
({ sha256: actualSha, bytes } = await streamToFile(res, tmp, url));
|
|
283
|
+
}
|
|
284
|
+
catch (e) {
|
|
285
|
+
await fsp.rm(tmp, { force: true }).catch(() => undefined);
|
|
286
|
+
if (e.name === "AbortError") {
|
|
287
|
+
throw new Error(`download timed out after ${timeoutMs}ms for ${url}`);
|
|
288
|
+
}
|
|
289
|
+
throw e;
|
|
290
|
+
}
|
|
291
|
+
finally {
|
|
292
|
+
clearTimeout(timer);
|
|
293
|
+
}
|
|
294
|
+
log.debug(`downloaded ${bytes} bytes`);
|
|
295
|
+
// Verify BEFORE the rename: unverified bytes must never reach the final path.
|
|
296
|
+
let sha;
|
|
297
|
+
try {
|
|
298
|
+
sha = assertSha256(actualSha, entry.sha256, `${opts.component} ${platformKey} (${url})`);
|
|
299
|
+
}
|
|
300
|
+
catch (e) {
|
|
301
|
+
await fsp.rm(tmp, { force: true }).catch(() => undefined);
|
|
302
|
+
throw e;
|
|
303
|
+
}
|
|
304
|
+
try {
|
|
305
|
+
await fsp.rename(tmp, binaryPath);
|
|
306
|
+
}
|
|
307
|
+
catch (e) {
|
|
308
|
+
await fsp.rm(tmp, { force: true }).catch(() => undefined);
|
|
309
|
+
throw new Error(`downloaded and verified the ${opts.component}, but could not move it into place ` +
|
|
310
|
+
`at ${binaryPath}: ${e.message}. ` +
|
|
311
|
+
"The usual cause is that the file is in use — stop any running gaia sidecar " +
|
|
312
|
+
"or TUI (`gaia kill`) and re-run. Otherwise check write permissions on " +
|
|
313
|
+
`${outDir}, or pass a different --sidecar-dir / --cache-dir.`, { cause: e });
|
|
314
|
+
}
|
|
315
|
+
try {
|
|
316
|
+
if (process.platform !== "win32")
|
|
317
|
+
await fsp.chmod(binaryPath, 0o755);
|
|
318
|
+
}
|
|
319
|
+
catch (e) {
|
|
320
|
+
throw new Error(`installed the ${opts.component} at ${binaryPath} but could not make it ` +
|
|
321
|
+
`executable: ${e.message}. Run \`chmod +x ${binaryPath}\`, or ` +
|
|
322
|
+
"pass a --sidecar-dir / --cache-dir you own.", { cause: e });
|
|
323
|
+
}
|
|
324
|
+
if (installsForThisHost(opts.component, platformKey)) {
|
|
325
|
+
await writeInstalledSentinel({
|
|
326
|
+
outDir,
|
|
327
|
+
version: componentLock(lock, "sidecar").componentVersion,
|
|
328
|
+
sha256: sha,
|
|
329
|
+
executable: entry.executable,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
log.info(`installed verified ${opts.component} -> ${binaryPath}`);
|
|
333
|
+
return {
|
|
334
|
+
component: opts.component,
|
|
335
|
+
binaryPath,
|
|
336
|
+
platformKey,
|
|
337
|
+
sha256: sha,
|
|
338
|
+
url,
|
|
339
|
+
cached: false,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Fetch + verify BOTH binaries. Sequential on purpose: the sidecar is the large
|
|
344
|
+
* download and a failure there should not race a half-finished TUI download.
|
|
345
|
+
*
|
|
346
|
+
* The sidecar lands in the daemon's own cache dir so the daemon — which owns
|
|
347
|
+
* spawning it — finds it already verified instead of downloading it again.
|
|
348
|
+
*/
|
|
349
|
+
export async function fetchAll(opts = {}) {
|
|
350
|
+
const lock = opts.lock ?? loadLock(opts.lockPath ?? defaultLockPath());
|
|
351
|
+
const platformKey = opts.platformKey ?? currentPlatformKey();
|
|
352
|
+
const common = { ...opts, lock, platformKey };
|
|
353
|
+
const sidecar = await fetchBinary({
|
|
354
|
+
...common,
|
|
355
|
+
component: "sidecar",
|
|
356
|
+
outDir: opts.sidecarDir ?? daemonSidecarCacheDir(),
|
|
357
|
+
});
|
|
358
|
+
const tui = await fetchBinary({
|
|
359
|
+
...common,
|
|
360
|
+
component: "tui",
|
|
361
|
+
outDir: opts.tuiDir ?? defaultCacheDir(lock.agentVersion),
|
|
362
|
+
});
|
|
363
|
+
return { sidecar, tui, lock };
|
|
364
|
+
}
|
|
365
|
+
/** Sync existence check, for the lifecycle layer. */
|
|
366
|
+
export function binaryExists(binaryPath) {
|
|
367
|
+
return fs.existsSync(binaryPath);
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @amd-gaia/gaia — binary fetcher + process lifecycle for the GAIA flagship
|
|
3
|
+
* agent sidecar and the GAIA terminal UI.
|
|
4
|
+
*
|
|
5
|
+
* The CLI (`npx @amd-gaia/gaia`) is the normal way in. These exports are for
|
|
6
|
+
* integrators who want the pieces:
|
|
7
|
+
*
|
|
8
|
+
* import { fetchAll, startSidecar, shutdown } from "@amd-gaia/gaia";
|
|
9
|
+
*
|
|
10
|
+
* const { sidecar, tui } = await fetchAll(); // both, SHA-256 verified
|
|
11
|
+
* const proc = await startSidecar({ binaryPath: sidecar.binaryPath });
|
|
12
|
+
* const res = await fetch(`${proc.baseUrl}/v1/gaia/query`, { ... });
|
|
13
|
+
* await shutdown(proc);
|
|
14
|
+
*/
|
|
15
|
+
export { INSTALLED_SENTINEL_NAME, SIDECAR_AGENT_ID, fetchAll, fetchBinary, verifySha256, fileSha256, binaryExists, defaultCacheDir, daemonSidecarCacheDir, } from "./fetch.js";
|
|
16
|
+
export type { FetchOptions, FetchResult, FetchAllOptions, FetchAllResult, } from "./fetch.js";
|
|
17
|
+
export { AGENT_ID, API_VERSION, DEFAULT_HOST, DEFAULT_PORT, RESERVED_PORT, checkVersion, health, resolveSidecarPath, resolveTuiPath, runTui, shutdown, sidecarExecutableName, spawnSidecar, startSidecar, tuiExecutableName, version, waitForHealth, } from "./lifecycle.js";
|
|
18
|
+
export type { HealthResponse, ResolveOptions, RunTuiOptions, Sidecar, SpawnOptions, StartOptions, VersionCheckOptions, VersionResponse, WaitForHealthOptions, } from "./lifecycle.js";
|
|
19
|
+
export { COMPONENTS, SCHEMA_MAJOR, SUPPORTED_PLATFORMS, SUPPORTED_SIDECAR_PLATFORMS, SUPPORTED_TUI_PLATFORMS, TUI_ARTIFACT_NAMES, componentBaseUrl, componentLock, currentPlatformKey, defaultLockPath, isPlaceholderSha, loadLock, platformsFor, resolveEntry, } from "./platform.js";
|
|
20
|
+
export type { BinaryLock, BinaryLockEntry, ComponentLock, ComponentName, } from "./platform.js";
|
|
21
|
+
export { BinaryNotFoundError, GaiaError, HealthTimeoutError, HttpError, IntegrityError, MalformedResponseError, PlatformError, PortInUseError, SidecarExitedError, VersionMismatchError, } from "./errors.js";
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,eAAe,EACf,qBAAqB,GACtB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,YAAY,EACZ,WAAW,EACX,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,MAAM,EACN,kBAAkB,EAClB,cAAc,EACd,MAAM,EACN,QAAQ,EACR,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,OAAO,EACP,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,UAAU,EACV,eAAe,EACf,aAAa,EACb,aAAa,GACd,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,sBAAsB,EACtB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
/**
|
|
4
|
+
* @amd-gaia/gaia — binary fetcher + process lifecycle for the GAIA flagship
|
|
5
|
+
* agent sidecar and the GAIA terminal UI.
|
|
6
|
+
*
|
|
7
|
+
* The CLI (`npx @amd-gaia/gaia`) is the normal way in. These exports are for
|
|
8
|
+
* integrators who want the pieces:
|
|
9
|
+
*
|
|
10
|
+
* import { fetchAll, startSidecar, shutdown } from "@amd-gaia/gaia";
|
|
11
|
+
*
|
|
12
|
+
* const { sidecar, tui } = await fetchAll(); // both, SHA-256 verified
|
|
13
|
+
* const proc = await startSidecar({ binaryPath: sidecar.binaryPath });
|
|
14
|
+
* const res = await fetch(`${proc.baseUrl}/v1/gaia/query`, { ... });
|
|
15
|
+
* await shutdown(proc);
|
|
16
|
+
*/
|
|
17
|
+
export { INSTALLED_SENTINEL_NAME, SIDECAR_AGENT_ID, fetchAll, fetchBinary, verifySha256, fileSha256, binaryExists, defaultCacheDir, daemonSidecarCacheDir, } from "./fetch.js";
|
|
18
|
+
export { AGENT_ID, API_VERSION, DEFAULT_HOST, DEFAULT_PORT, RESERVED_PORT, checkVersion, health, resolveSidecarPath, resolveTuiPath, runTui, shutdown, sidecarExecutableName, spawnSidecar, startSidecar, tuiExecutableName, version, waitForHealth, } from "./lifecycle.js";
|
|
19
|
+
export { COMPONENTS, SCHEMA_MAJOR, SUPPORTED_PLATFORMS, SUPPORTED_SIDECAR_PLATFORMS, SUPPORTED_TUI_PLATFORMS, TUI_ARTIFACT_NAMES, componentBaseUrl, componentLock, currentPlatformKey, defaultLockPath, isPlaceholderSha, loadLock, platformsFor, resolveEntry, } from "./platform.js";
|
|
20
|
+
export { BinaryNotFoundError, GaiaError, HealthTimeoutError, HttpError, IntegrityError, MalformedResponseError, PlatformError, PortInUseError, SidecarExitedError, VersionMismatchError, } from "./errors.js";
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,+BAA+B;AAC/B;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,eAAe,EACf,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAQpB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,MAAM,EACN,kBAAkB,EAClB,cAAc,EACd,MAAM,EACN,QAAQ,EACR,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,OAAO,EACP,aAAa,GACd,MAAM,gBAAgB,CAAC;AAaxB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,MAAM,eAAe,CAAC;AAQvB,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,sBAAsB,EACtB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
|