@amd-gaia/gaia 0.1.0 → 0.1.1

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/SPEC.md ADDED
@@ -0,0 +1,393 @@
1
+ # `@amd-gaia/gaia` — technical reference
2
+
3
+ Version **0.1.1**. Companion to [`README.md`](./README.md), which is the
4
+ user-facing doc. This file specifies the wire and file formats the package
5
+ depends on and the guarantees it makes.
6
+
7
+ ---
8
+
9
+ ## 1. Scope
10
+
11
+ `@amd-gaia/gaia` is a **binary delivery and process-lifecycle package**. It ships
12
+ no agent logic. It owns:
13
+
14
+ - resolving the host platform to a lock key,
15
+ - downloading and **SHA-256 verifying** two published binaries — one from this
16
+ package's own hub lane, one from the `terminal-hub` component's,
17
+ - caching them in stable, versioned locations,
18
+ - launching the terminal UI, or the agent sidecar directly.
19
+
20
+ It does **not** own the GAIA daemon's lifecycle, the sidecar's supervision, or
21
+ any agent behaviour. See §6 for where those boundaries sit.
22
+
23
+ ---
24
+
25
+ ## 2. `binaries.lock.json`
26
+
27
+ Ships inside the published package (`files` includes it). It is the single source
28
+ of truth for what is downloaded and what it must hash to.
29
+
30
+ ### 2.1 Schema (`schemaVersion` `3.0`)
31
+
32
+ ```jsonc
33
+ {
34
+ "schemaVersion": "3.0",
35
+ "agentVersion": "0.1.1",
36
+ "components": {
37
+ "sidecar": {
38
+ "componentVersion": "0.1.1",
39
+ "baseUrl": "https://hub.amd-gaia.ai/agents/gaia/0.1.1",
40
+ "platforms": { "<platformKey>": { /* entry */ } }
41
+ },
42
+ "tui": {
43
+ "componentVersion": "0.23.0",
44
+ "baseUrl": "https://hub.amd-gaia.ai/agents/terminal-hub/0.23.0",
45
+ "platforms": { "<platformKey>": { /* entry */ } }
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ A component lane:
52
+
53
+ | Field | Type | Meaning |
54
+ | ------------------ | -------- | ---------------------------------------------------------- |
55
+ | `componentVersion` | `string` | That component's own released version |
56
+ | `baseUrl` | `string` | Where **that component's** artifacts are served from |
57
+ | `platforms` | `object` | Platform key → entry |
58
+
59
+ An entry:
60
+
61
+ | Field | Type | Meaning |
62
+ | ------------ | -------- | ----------------------------------------------------------- |
63
+ | `filename` | `string` | Artifact name as published under **its component's** `baseUrl` |
64
+ | `executable` | `string` | Basename it is written as on disk (with the platform extension) |
65
+ | `sha256` | `string` | Lowercase hex SHA-256 the download must match |
66
+ | `size` | `number` | Informational. **Not** enforced |
67
+
68
+ **Why per-component, and why `3.0`.** `2.0` had one top-level `baseUrl` shared by
69
+ both components. That stopped being true once the TUI became the published
70
+ `terminal-hub` component (§2.2): the two live in different hub lanes at different
71
+ versions. A shared base URL cannot express that, so `2.x` is rejected at load with
72
+ an error naming the schema — never read as `3.x` with a missing field.
73
+
74
+ The email agent's lock is `schemaVersion` `1.0`, a flat `binaries` map, because it
75
+ delivers one binary from one lane. A `1.x`-shaped lock is likewise rejected.
76
+
77
+ ### 2.2 Where each component comes from
78
+
79
+ | Component | Hub lane | Published by |
80
+ | --------- | ------------------------------------- | ----------------------- |
81
+ | `sidecar` | `agents/gaia/<agentVersion>/` | this package's release |
82
+ | `tui` | `agents/terminal-hub/<componentVersion>/` | the core GAIA release |
83
+
84
+ The TUI is **consumed, not built here**. It is the same `tui/cmd/gaia` binary the
85
+ core release publishes as the `terminal-hub` component and a core install runs as
86
+ `gaia tui` — so behaviour is identical by construction rather than by convention.
87
+ Building a second copy under this package's lane would put the same bytes at a
88
+ different version under a third naming convention, and the two would drift.
89
+
90
+ The consequence is a real release dependency: this package cannot ship until
91
+ `terminal-hub` is published at the version its lock pins. The release fails loudly
92
+ naming that version; it never falls back to building its own TUI.
93
+
94
+ The `tui` lane's origin is pinned in the lock rather than derived from the release
95
+ pipeline's hub-origin variable, so the release verifies the exact URL the shipped
96
+ lock will send users to. A release pointed at a non-default origin therefore moves
97
+ the sidecar lane and **not** the TUI lane; re-point `components.tui.baseUrl` too if
98
+ you need both.
99
+
100
+ ### 2.3 Platform keys
101
+
102
+ `` `${process.platform}-${process.arch}` `` — e.g. `win32-x64`, `darwin-arm64`,
103
+ `linux-x64`. This matches `gaia.daemon.sidecars.platform.current_platform_key()`,
104
+ which normalises Python's `sys.platform` / `platform.machine()` into the same
105
+ namespace so the daemon and this package agree on a cache key.
106
+
107
+ **The `win32` ↔ `win` mapping.** The `terminal-hub` lane names its Windows
108
+ artifacts `gaia-win-x64.exe` / `gaia-win-arm64.exe` (Go's `GOOS` vocabulary), while
109
+ our keys come from `process.platform`, which says `win32`. The lock keeps the
110
+ `win32-*` key and carries the hub's spelling in `filename`:
111
+
112
+ | Platform key | `tui` `filename` |
113
+ | -------------- | ------------------------ |
114
+ | `win32-x64` | `gaia-win-x64.exe` |
115
+ | `win32-arm64` | `gaia-win-arm64.exe` |
116
+ | `darwin-x64` | `gaia-darwin-x64` |
117
+ | `darwin-arm64` | `gaia-darwin-arm64` |
118
+ | `linux-x64` | `gaia-linux-x64` |
119
+ | `linux-arm64` | `gaia-linux-arm64` |
120
+
121
+ The mapping therefore lives in **data**, not in a code path — nothing branches on
122
+ the platform to build a name. `TUI_ARTIFACT_NAMES` (in `src/platform.ts` and in
123
+ `packaging/gen_binaries_lock.py`) is the authority both the shipped lock and the
124
+ release pipeline are checked against, because a wrong name here is not a build
125
+ failure anywhere: it is a 404 on a user's first run.
126
+
127
+ ### 2.4 Platform coverage
128
+
129
+ | Platform key | `sidecar` | `tui` |
130
+ | -------------- | :-------: | :---: |
131
+ | `win32-x64` | yes | yes |
132
+ | `darwin-arm64` | yes | yes |
133
+ | `darwin-x64` | yes | yes |
134
+ | `linux-x64` | yes | yes |
135
+ | `linux-arm64` | **no** | yes |
136
+ | `win32-arm64` | **no** | yes |
137
+
138
+ `terminal-hub` publishes all six. The sidecar is a PyInstaller freeze, produced on
139
+ the platform it targets, and there is no arm64 Linux or arm64 Windows freeze.
140
+ Resolving `sidecar` on those two keys raises `PlatformError` naming the platform
141
+ and the supported set — it is not silently skipped, and the TUI is not launched
142
+ without an agent behind it.
143
+
144
+ ### 2.5 Placeholder hashes
145
+
146
+ Between releases every `sha256` is `PENDING-replace-with-real-sha256`. The release
147
+ pipeline regenerates the file with real hashes: for the sidecar, computed from the
148
+ artifacts it just published; for the TUI, computed from the `terminal-hub`
149
+ artifacts it downloaded and cross-checked against that lane's own recorded hashes
150
+ (`agents/terminal-hub/manifest.json`, which the hub computes server-side at publish
151
+ time). Both are then re-fetched from the public origin and re-hashed before the
152
+ release is allowed to ship.
153
+
154
+ `isPlaceholderSha()` treats a value as a placeholder when it is all zeros or
155
+ contains `PENDING` (case-insensitive). A placeholder **blocks the fetch before any
156
+ network call** with a `PlatformError`. There is no flag, env var, or option that
157
+ relaxes this.
158
+
159
+ ---
160
+
161
+ ## 3. Integrity
162
+
163
+ The SHA-256 check is the package's security boundary.
164
+
165
+ - Downloaded bytes are hashed in memory and compared against the lock **before
166
+ anything is written to the cache path**.
167
+ - On mismatch: `IntegrityError`, message naming expected vs actual, nothing left
168
+ on disk.
169
+ - Writes go to `<path>.download.<pid>` and are `rename`d into place, so a crash
170
+ mid-write never leaves a partial file that a later run treats as verified.
171
+ - A cache hit requires re-hashing the on-disk file and matching the lock.
172
+ A cached file whose bytes drifted is re-downloaded, not reused.
173
+ - POSIX installs `chmod 0o755` after the rename.
174
+
175
+ There is no unverified path, no "warn and continue", and no way to disable the
176
+ check.
177
+
178
+ ---
179
+
180
+ ## 4. Filesystem layout
181
+
182
+ | Component | Default directory | Executable |
183
+ | --------- | ------------------------------ | ------------------- |
184
+ | `sidecar` | `~/.gaia/agents/gaia/` | `gaia-agent[.exe]` |
185
+ | `tui` | `~/.gaia/npm-cache/gaia-<agentVersion>/` | `gaia-tui[.exe]` |
186
+
187
+ The sidecar directory is a **cross-repo contract** with
188
+ `gaia.daemon.sidecars.fetch.default_cache_dir("gaia")`. The daemon spawns and
189
+ supervises the sidecar and does its own SHA-256 check on the binary it finds
190
+ there; installing an already-verified binary at that path turns the daemon's fetch
191
+ into a cache hit instead of a second multi-hundred-megabyte download.
192
+
193
+ The TUI directory is keyed by `agentVersion` — this package's version, not the
194
+ component's — so a bump of either never reuses the previous release's executable.
195
+
196
+ The TUI executable is renamed to `gaia-tui` on install, **never** `gaia`: the
197
+ `terminal-hub` artifact is `gaia-<platform>` and npm installs a `gaia` bin shim on
198
+ `PATH`, so keeping the hub's name would shadow the shim. `filename` (what is
199
+ downloaded) and `executable` (what is written) are separate fields for exactly this
200
+ reason, and `test/lock.test.ts` asserts it for every platform.
201
+
202
+ Both defaults are overridable (`--sidecar-dir`, `--cache-dir`).
203
+
204
+ ---
205
+
206
+ ## 5. Sidecar HTTP surface
207
+
208
+ Served by `gaia_agent.server`. Bound to `127.0.0.1` only.
209
+
210
+ | Property | Value |
211
+ | ------------------ | --------------------------------------- |
212
+ | Default port | `8141` (`DEFAULT_PORT` in `server.py`) |
213
+ | Reserved port | `4001` — refused with a `RangeError` |
214
+ | Contract version | `API_VERSION = "2.12"` |
215
+ | Agent id / prefix | `gaia` → `/v1/gaia/...` |
216
+
217
+ ### 5.1 Endpoints
218
+
219
+ | Method | Path | Purpose |
220
+ | ------ | -------------------------------- | ---------------------------------------------- |
221
+ | `GET` | `/health` | Liveness. `{ "status": "ok", "service": "gaia-agent-gaia" }` |
222
+ | `GET` | `/version` | Contract probe. `{ "apiVersion", "agentVersion" }` |
223
+ | `GET` | `/v1/gaia/version` | The TUI's negotiation probe |
224
+ | `GET` | `/v1/gaia/init` | Readiness detail (Lemonade, model, connectors) |
225
+ | `POST` | `/v1/gaia/query` | The streaming surface (`text/event-stream`) |
226
+ | `POST` | `/v1/gaia/query/{run_id}/cancel` | Cancel a run by its host-minted `run_id` |
227
+ | `POST` | `/v1/gaia/query/{run_id}/respond`| Answer a mid-run question |
228
+
229
+ `/health` is liveness only. It says nothing about whether Lemonade is up or a
230
+ model is loaded — `/v1/gaia/init` answers that.
231
+
232
+ ### 5.2 `session_id` and agent retention
233
+
234
+ `POST /v1/gaia/query` accepts an optional `session_id` in the request body.
235
+ **Pass it on every call in a conversation, and reuse the same value for the
236
+ whole conversation.** Contract ≥ 2.12 resolves `session_id` to a *retained*
237
+ agent instead of a throwaway built fresh per call — indexed documents and
238
+ `load_skill` state only survive between turns when the same `session_id`
239
+ threads them together.
240
+
241
+ A retained skill stays *loaded* but its body is not necessarily in the prompt
242
+ every turn: the agent selects per turn which loaded bodies match the query and
243
+ collapses the rest to a one-line menu entry (re-activated by calling
244
+ `load_skill` again). `GAIA_DYNAMIC_SKILLS=0` disables the selection;
245
+ `GAIA_DYNAMIC_SKILLS_TAU=<float>` overrides its threshold; an embedder outage
246
+ disables it for the session and every body renders. Omitting it is a valid, explicit one-shot: nothing
247
+ persists past that single turn, and the agent is not told otherwise.
248
+
249
+ A second `/query` for a `session_id` that already has a turn in flight gets
250
+ `409 Conflict` — cancel the running turn or wait for it, then retry. A
251
+ `/query` that needs a **new** session while every retained slot is busy and
252
+ none is idle enough to evict gets `503` with the reason in `detail` — a
253
+ temporary, retryable condition, not a bug: wait for a turn to finish (or
254
+ close an idle session) and retry. A
255
+ `session_id` can also be evicted from the retention table under an idle
256
+ timeout or an LRU cap on concurrent sessions; a `/query` that lands on an
257
+ evicted id gets a fresh agent (the conversation is not blocked) but the
258
+ response stream's first event is a `{"type":"status","status":"warning",...}`
259
+ telling the caller that per-turn state — most visibly any loaded skill — did
260
+ not survive and should be reloaded.
261
+
262
+ ### 5.3 Version gate
263
+
264
+ `checkVersion()` reads `/version` and compares the **major** of `apiVersion`
265
+ against this package's `API_VERSION`. A differing major is a breaking contract
266
+ change and raises `VersionMismatchError`. A higher minor with the same major is a
267
+ backward-compatible addition and is accepted.
268
+
269
+ ### 5.4 No caller-auth token
270
+
271
+ The email sidecar authenticates callers with a per-session bearer minted into
272
+ `GAIA_EMAIL_SIDECAR_TOKEN`. `gaia_agent` has **no equivalent** at 0.1.1, so
273
+ this package mints and sends nothing. When the sidecar grows one, it lands here as
274
+ a spawn-time env var and a request header — a change to this section, not a new
275
+ subsystem.
276
+
277
+ ---
278
+
279
+ ## 6. Process ownership
280
+
281
+ Two distinct paths, deliberately:
282
+
283
+ ### 6.1 `gaia run` — the normal path
284
+
285
+ `run` fetches, verifies, installs, and **execs the TUI**. It does not spawn a
286
+ sidecar.
287
+
288
+ That is not an omission. The TUI reaches agents through the GAIA daemon's relay
289
+ (`/v1/<agent>/*`) and holds only the daemon client token, never a sidecar bearer —
290
+ `tui/internal/daemon` states this as an invariant. The TUI start-or-attaches the
291
+ daemon under an advisory lock, and the daemon spawns and supervises the sidecar
292
+ from `~/.gaia/agents/gaia/`. A sidecar spawned here would be a second process the
293
+ TUI never talks to, competing for port `8141`.
294
+
295
+ So `run`'s contribution to the sidecar is putting a **verified** binary where the
296
+ daemon looks. Daemon and sidecar lifecycle belong to the daemon.
297
+
298
+ ### 6.2 `gaia serve` — the direct path
299
+
300
+ `serve` fetches the sidecar and spawns it itself, for integrators who want the
301
+ REST surface without a daemon or a UI. This path owns the process fully: spawn →
302
+ `waitForHealth` → `checkVersion` → run until interrupted → tree-kill.
303
+
304
+ ### 6.3 Tree-kill
305
+
306
+ The sidecar is a PyInstaller one-file build: it unpacks and spawns a child uvicorn
307
+ process that `child.kill()` on the parent does **not** reap, leaving port `8141`
308
+ bound. Every teardown kills the whole tree:
309
+
310
+ - **POSIX** — spawned `detached` so the child leads its own process group;
311
+ `process.kill(-pid, SIGTERM)`, escalating to `SIGKILL` after the timeout.
312
+ - **Windows** — `taskkill /PID <pid> /T /F`.
313
+
314
+ `autoCleanup` (default `true`) also reaps on `exit`, `SIGINT`, `SIGTERM`,
315
+ `SIGHUP`, `uncaughtException`, and `unhandledRejection`. A `SIGKILL` of the parent
316
+ is the one case no in-process handler can catch.
317
+
318
+ `startSidecar()` shuts the sidecar down before rethrowing on any failure, so a
319
+ failed start never leaks a process.
320
+
321
+ ---
322
+
323
+ ## 7. Exit codes
324
+
325
+ | Code | Meaning |
326
+ | ------- | ----------------------------------------------------------------------- |
327
+ | `0` | Success |
328
+ | `1` | A typed failure: `IntegrityError`, `PlatformError`, `HealthTimeoutError`, `VersionMismatchError`, `BinaryNotFoundError`, or an unexpected error |
329
+ | `2` | Usage error: unknown command, unknown `--component`, invalid `--port` |
330
+ | *other* | From `run`: the TUI's own exit code, propagated verbatim |
331
+
332
+ A TUI killed by a signal propagates as `128 + signum` (the shell convention), so a
333
+ Ctrl+C is distinguishable from a clean `0`.
334
+
335
+ ---
336
+
337
+ ## 8. Errors
338
+
339
+ All extend `GaiaError`, so `instanceof GaiaError` catches any of ours.
340
+
341
+ | Class | Raised when |
342
+ | ---------------------- | -------------------------------------------------------------- |
343
+ | `IntegrityError` | A download's SHA-256 does not match the lock |
344
+ | `PlatformError` | Unsupported platform, missing/incomplete entry, placeholder hash, malformed lock |
345
+ | `HealthTimeoutError` | The sidecar did not report healthy within the timeout |
346
+ | `VersionMismatchError` | `apiVersion` major differs from this package's |
347
+ | `BinaryNotFoundError` | A binary is absent from disk when spawning |
348
+ | `HttpError` | A non-2xx from a sidecar probe |
349
+
350
+ Per the repo's no-silent-fallbacks rule, every message names what failed, what to
351
+ do, and where to look next.
352
+
353
+ ---
354
+
355
+ ## 9. Timeouts
356
+
357
+ | Operation | Default | Why |
358
+ | --------------------- | --------- | ------------------------------------------------ |
359
+ | Download (per binary) | `300000`ms | The frozen sidecar is a large artifact |
360
+ | Health wait | `60000`ms | A cold one-file build unpacks before it binds |
361
+ | Health poll interval | `250`ms | |
362
+ | `/health` probe | `1000`ms | |
363
+ | `/version` probe | `5000`ms | |
364
+ | Shutdown grace | `5000`ms | Then `SIGKILL` / forced |
365
+
366
+ ---
367
+
368
+ ## 10. Public API
369
+
370
+ Exported from the package root — see `src/index.ts`.
371
+
372
+ **Fetch:** `fetchAll`, `fetchBinary`, `verifySha256`, `fileSha256`,
373
+ `binaryExists`, `defaultCacheDir`, `daemonSidecarCacheDir`.
374
+
375
+ **Lifecycle:** `spawnSidecar`, `startSidecar`, `waitForHealth`, `checkVersion`,
376
+ `health`, `version`, `shutdown`, `runTui`, `resolveSidecarPath`, `resolveTuiPath`,
377
+ `sidecarExecutableName`, `tuiExecutableName`.
378
+
379
+ **Platform:** `currentPlatformKey`, `loadLock`, `resolveEntry`, `componentLock`,
380
+ `componentBaseUrl`, `platformsFor`, `defaultLockPath`, `isPlaceholderSha`,
381
+ `COMPONENTS`, `SCHEMA_MAJOR`, `TUI_ARTIFACT_NAMES`,
382
+ `SUPPORTED_SIDECAR_PLATFORMS`, `SUPPORTED_TUI_PLATFORMS`, `SUPPORTED_PLATFORMS`.
383
+
384
+ **Constants:** `AGENT_ID`, `API_VERSION`, `DEFAULT_HOST`, `DEFAULT_PORT`,
385
+ `RESERVED_PORT`.
386
+
387
+ ---
388
+
389
+ ## 11. Logging
390
+
391
+ `DEBUG=gaia` (or `DEBUG=*`) enables debug output. **Everything goes to stderr** —
392
+ stdout belongs to the TUI once it is exec'd, and to machine-readable JSON for
393
+ `fetch` / `version`.
@@ -0,0 +1,78 @@
1
+ {
2
+ "schemaVersion": "3.0",
3
+ "agentVersion": "0.1.1",
4
+ "components": {
5
+ "sidecar": {
6
+ "componentVersion": "0.1.1",
7
+ "baseUrl": "https://hub.amd-gaia.ai/agents/gaia/0.1.1",
8
+ "platforms": {
9
+ "win32-x64": {
10
+ "filename": "gaia-agent-win32-x64.exe",
11
+ "executable": "gaia-agent.exe",
12
+ "sha256": "416ed0e24cd3457ae66acd1caaf8337d0761f093b86813d8640b7cad6236856a",
13
+ "size": 90667208
14
+ },
15
+ "darwin-arm64": {
16
+ "filename": "gaia-agent-darwin-arm64",
17
+ "executable": "gaia-agent",
18
+ "sha256": "f962b8c7ce042938a940a01fcea5c94fc0ff33b4c05c02770804c89c31aaa1c2",
19
+ "size": 74152544
20
+ },
21
+ "darwin-x64": {
22
+ "filename": "gaia-agent-darwin-x64",
23
+ "executable": "gaia-agent",
24
+ "sha256": "2f001c8c8e75b286c758269d0fc22fe57ef68ef5ee59476d960531e363b73c25",
25
+ "size": 78642224
26
+ },
27
+ "linux-x64": {
28
+ "filename": "gaia-agent-linux-x64",
29
+ "executable": "gaia-agent",
30
+ "sha256": "b704f83a4beaa4654a37cf8e2fcc7429cd6da91f7431c3381e7005370e760c7a",
31
+ "size": 122029424
32
+ }
33
+ }
34
+ },
35
+ "tui": {
36
+ "componentVersion": "0.23.0",
37
+ "baseUrl": "https://hub.amd-gaia.ai/agents/terminal-hub/0.23.0",
38
+ "platforms": {
39
+ "win32-x64": {
40
+ "filename": "gaia-win-x64.exe",
41
+ "executable": "gaia-tui.exe",
42
+ "sha256": "aad0c38c5c59e8107b608981f34608ee08feb7e5965de1cfcb929a49f21258ca",
43
+ "size": 19433984
44
+ },
45
+ "win32-arm64": {
46
+ "filename": "gaia-win-arm64.exe",
47
+ "executable": "gaia-tui.exe",
48
+ "sha256": "2f78c8128a8ad6d17d51938de12ed7aa29ceadb642af8d6e929920fe17e2463c",
49
+ "size": 17975808
50
+ },
51
+ "darwin-arm64": {
52
+ "filename": "gaia-darwin-arm64",
53
+ "executable": "gaia-tui",
54
+ "sha256": "766100459d22d9886a8d7839d5eddffb2a51134be76a57360b1584755be3cef1",
55
+ "size": 17896354
56
+ },
57
+ "darwin-x64": {
58
+ "filename": "gaia-darwin-x64",
59
+ "executable": "gaia-tui",
60
+ "sha256": "494197bd2bf245df94de9361a274723536e73f275bbb92efc1c4db027cc08d9e",
61
+ "size": 19003168
62
+ },
63
+ "linux-x64": {
64
+ "filename": "gaia-linux-x64",
65
+ "executable": "gaia-tui",
66
+ "sha256": "d913c4cc4943f6a5a9be737cf397ad2a05e013e55a7880c27d4ddef973ee16f4",
67
+ "size": 18661538
68
+ },
69
+ "linux-arm64": {
70
+ "filename": "gaia-linux-arm64",
71
+ "executable": "gaia-tui",
72
+ "sha256": "c8faee8cc7281819042d9e123d5a68b6ccfe4afa3d92d5fa3b2f42770df1d894",
73
+ "size": 17432738
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `gaia` — the one command that gets you running.
4
+ *
5
+ * npx @amd-gaia/gaia fetch + verify both binaries, then launch the TUI
6
+ * npx @amd-gaia/gaia fetch fetch + verify only
7
+ * npx @amd-gaia/gaia serve run the agent sidecar alone (REST, no TUI)
8
+ * npx @amd-gaia/gaia version print the lock manifest
9
+ *
10
+ * Every download is SHA-256 verified against `binaries.lock.json` before it is
11
+ * written, and a mismatch or a placeholder hash aborts the run. There is no
12
+ * "continue anyway" path.
13
+ */
14
+ interface ParsedArgs {
15
+ _: string[];
16
+ flags: Record<string, string | boolean>;
17
+ /** Everything after a bare `--`, forwarded verbatim to the TUI. */
18
+ passthrough: string[];
19
+ }
20
+ /** Raised for a malformed command line; the caller turns it into exit 2. */
21
+ export declare class UsageError extends Error {
22
+ }
23
+ export declare function parseArgs(argv: string[]): ParsedArgs;
24
+ /**
25
+ * The child's PATH with this package's own bin directory removed.
26
+ *
27
+ * npm installs our shim as `gaia`, and the TUI starts the daemon by resolving
28
+ * `gaia` on PATH (tui/internal/daemon/client.go) expecting the *Python* CLI.
29
+ * Left alone, the TUI would re-invoke us with `daemon start` and the daemon would
30
+ * never come up. Returns undefined when PATH is unset.
31
+ */
32
+ export declare function pathWithoutOwnShim(rawPath?: string | undefined, argv1?: string | undefined): string | undefined;
33
+ /** Validate `--port`. Rejects out-of-range values and the reserved port. */
34
+ export declare function resolvePort(raw: string | boolean | undefined): {
35
+ port: number;
36
+ } | {
37
+ error: string;
38
+ };
39
+ export declare function main(argv: string[]): Promise<number>;
40
+ export {};
41
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAGA;;;;;;;;;;;GAWG;AA8BH,UAAU,UAAU;IAClB,CAAC,EAAE,MAAM,EAAE,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;IACxC,mEAAmE;IACnE,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAaD,4EAA4E;AAC5E,qBAAa,UAAW,SAAQ,KAAK;CAAG;AAExC,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAuCpD;AA0ED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,MAAM,GAAG,SAA+B,EACjD,KAAK,GAAE,MAAM,GAAG,SAA2B,GAC1C,MAAM,GAAG,SAAS,CAmBpB;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAQnG;AAqJD,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAiC1D"}