@amd-gaia/gaia 0.3.2 → 0.3.3

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 CHANGED
@@ -6,6 +6,44 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.3.3]
10
+
11
+ Released with GAIA 0.25.3, and requires the `gaia` Python CLI 0.25.3+ on `PATH`.
12
+ Integrators: the sidecar contract is now **2.25**; clients built for 2.18
13
+ keep working, and older binaries refuse the new `turns` field with `422`,
14
+ so probe `/version` before sending it.
15
+
16
+ - **AMD LLM Gateway models run their tool calls.** The agent asks each cloud
17
+ model once whether it calls tools natively, and runs tool calls written as
18
+ text instead of dropping them, so a turn no longer ends without the work.
19
+ - **Music and sound effects can be generated locally** with Lemonade's
20
+ audio-generation models (three new tools, 98 in total).
21
+ - **The first code search on a large repo no longer hangs the turn.** The
22
+ index builds in the background and search reports its progress meanwhile.
23
+ - **A bare file name means a file in the chat's folder** for reading,
24
+ listing, browsing, finding, searching and running, as it already did for
25
+ writing.
26
+ - **`.epub` books are indexed chapter by chapter**, and a file the agent
27
+ can't read is refused instead of being indexed as binary text.
28
+ - **Two agents starting together on a new database no longer fail** with
29
+ `database is locked`.
30
+
31
+ ### For integrators: contract 2.25
32
+
33
+ - **The agent remembers its own tool calls across turns** (contract **2.25**,
34
+ #5701). A caller that pushed history as `context` could send only text, so
35
+ on the next turn the agent saw its earlier answers but not the commands it
36
+ ran or their errors, and "why did that fail?" got "I have no record of the
37
+ tool calls". Send the new `turns` field (`[]` on the first turn) and that
38
+ turn's `final` carries `model_messages`, the turn as the model saw it, tool
39
+ calls and results included. Send those back in `turns`, oldest first, and
40
+ the agent replays them, keeping the newest whole turns that fit its context
41
+ window. `turns` replaces `context` when sent (a non-empty `context` beside
42
+ it is a `422`), and `[]` clears a retained session's history. A caller that
43
+ sends no `turns` gets no `model_messages`, so a `final` stays small for
44
+ text-only clients. Pre-2.25 binaries refuse the field with `422`, so probe
45
+ `/version` first.
46
+
9
47
  ## [0.3.2]
10
48
 
11
49
  Released with GAIA 0.25.2, and requires the `gaia`
package/README.md CHANGED
@@ -42,7 +42,7 @@ however you arrive at the terminal UI, it behaves identically.
42
42
  - **On Linux x64, glibc 2.34 or newer** for the agent sidecar (Ubuntu 22.04,
43
43
  Debian 12 and RHEL 9 or later). An older distro cannot start the agent. Check
44
44
  with `ldd --version`.
45
- - The `gaia` Python CLI **0.25.2 or newer** on `PATH` for the daemon the terminal
45
+ - The `gaia` Python CLI **0.25.3 or newer** on `PATH` for the daemon the terminal
46
46
  UI starts. An earlier core cannot run this agent, so the UI comes up with
47
47
  nothing behind it. Install it with
48
48
  `curl -fsSL https://amd-gaia.ai/install.sh | sh` (Windows:
@@ -262,6 +262,14 @@ it out. It also carries `performance`, the turn's model and tool timings and
262
262
  each model call's token counts, when the binary sends it. See
263
263
  [`SPEC.md` §5.1](./SPEC.md#51-endpoints).
264
264
 
265
+ **Keeping a multi-turn conversation? Send `turns`, not `context`** (contract ≥
266
+ 2.25). Send `turns: []` on the first turn so its `final` carries
267
+ `model_messages`, store that with the reply, and send them back, oldest first,
268
+ so the agent sees the tool calls it made and what they returned.
269
+ Text-only `context` loses them, and the agent can't explain its own last turn.
270
+ An empty `turns` list clears a retained session's history. Older binaries
271
+ reject `turns` with `422`.
272
+
265
273
  Every failure throws a typed error (`IntegrityError`, `PlatformError`,
266
274
  `HealthTimeoutError`, `VersionMismatchError`, `BinaryNotFoundError`) with a message
267
275
  that names what failed and what to do about it.
package/SKILL.md CHANGED
@@ -252,7 +252,7 @@ curl http://127.0.0.1:8141/health
252
252
  ## 7. Call `POST /v1/gaia/query`
253
253
 
254
254
  This is the whole agent surface. There is **no typed query client** in this
255
- package — call it with plain `fetch`. Contract version **2.24**; the stream is
255
+ package — call it with plain `fetch`. Contract version **2.25**; the stream is
256
256
  `text/event-stream` terminated by **exactly one** `final` or `error`.
257
257
 
258
258
  Request body (`extra: "forbid"` — an unknown field is a **422**, not ignored):
@@ -270,6 +270,7 @@ Request body (`extra: "forbid"` — an unknown field is a **422**, not ignored):
270
270
  | `internet_off` | no | Contract ≥ 2.23. `true` refuses web search and page fetches, the browser, connector, mailbox and Agent Hub tools and any call or shell command that contacts another host, with a message telling the model the internet is off for this chat; `false` allows them. A retained session keeps the last value: send it every turn. Omit it to leave the agent as it is. To change it mid-turn, `POST /v1/gaia/sessions/{session_id}/internet` with `{"internet_off": true}`; the next tool call follows it, and an unknown session is a **404**. Post it only once `/query` has answered, since the turn's own value replaces an earlier one; re-read the switch then and post it if it changed. |
271
271
  | `changes_turn_id` | no | Contract ≥ 2.19. Needs `session_id`. The agent copies each file before changing it, under `<GAIA home>/snapshots/<session_id>/<changes_turn_id>/`, so the turn can be reviewed and undone; the copies are complete before the terminal event. Format: 14 digits of local time, `-`, 8 hex digits (`YYYYmmddHHMMSS-xxxxxxxx`); anything else is a **422**. Omit it to copy nothing. |
272
272
  | `surface` | no | Contract ≥ 2.20. `"agent_ui"`, `"tui"` or `"cli"` — the front-end the turn comes from. With `"agent_ui"` the agent points recurring requests at the Agent UI's **Scheduled tasks** page. It also picks where a model-provider error tells the user to fix it; omitted (a headless caller), that is the model server the GAIA host uses (`LEMONADE_BASE_URL`). Read when a session is built. |
273
+ | `turns` | no | Contract ≥ 2.25. Earlier turns as the model saw them, oldest first: each is that turn's `final.model_messages`, or a `{user, assistant}` text pair for a turn without one. Send it instead of `context` (then `[]`, or the request is a **422**) so the agent sees its own earlier tool calls and their results; send `[]` on the first turn. It keeps the newest whole turns that fit its window. Sent, even as `[]`, it makes `final` carry `model_messages`; `[]` also clears a retained session's history. |
273
274
  | `reasoning` | no | Contract ≥ 2.22. `true` streams the model's reasoning as `reasoning` events (`{ delta }`), apart from `status` lines and the answer's `token`s. Join the deltas as they come: each keeps its own spacing. Omit it and reasoning folds into `status` lines as before. |
274
275
  | `can_answer_questions` | no | Set `false` for one-shot / batch runs so the agent resolves ambiguity itself instead of parking on a question nobody can see. |
275
276
  | `model` | no | Overrides the model id. On a retained `session_id` a different model is **switched in place** (contract ≥ 2.14), keeping the conversation and any loaded skills; a switch that fails is a **409** and leaves the session on its previous model. |
@@ -336,7 +337,7 @@ The canonical event shapes, as emitted:
336
337
  | `tool_result` | `{ type, tool, data, render? }` — an MCP tool that returned text carries it in `data.mcp_output` (`{ text, truncated }`); a `search_web` result lists its hits in `data.sources` (`[{ title, url }]`) |
337
338
  | `needs_confirmation` | `{ type, run_id, action, summary, confirm_id?, always_scope?, risk?, tool_label?, args?, args_truncated?, prompt_context? }` — answer it, or it ends the run; see §8. `summary` shortens long code; `args` is the call itself, exactly the arguments the model sent, each value capped at 64,000 characters (`args_truncated: true` when one was cut — don't auto-approve a call you can't fully see). What GAIA adds to the prompt is in `prompt_context`, never `args`: `working_directory` (where a shell call runs, when the model's arguments don't say), `risk_note` (why GAIA's checks don't cover the call) and `file_path` (the absolute path a write lands at, when the model gave a relative one) |
338
339
  | `needs_input` | `{ type, run_id, request_id, question, options[], allow_free_text, sensitive, respond_url, timeout_seconds? }` |
339
- | `final` | `{ type, answer, usage?, failed?, context?, context_error?, performance? }` — terminal. `failed: true`: the model failed mid-turn and `answer` says what was and wasn't done; show it as an error, not a result. `context` / `context_error` and `performance` (the turn's step timings) are optional; see SPEC §5.1 |
340
+ | `final` | `{ type, answer, usage?, failed?, context?, context_error?, performance?, model_messages? }` — terminal. `failed: true`: the model failed mid-turn and `answer` says what was and wasn't done; show it as an error, not a result. `model_messages` (contract ≥ 2.25, only when the request sent `turns`) is the turn as the model saw it; store it with the reply and send it back in `turns`. `context` / `context_error` and `performance` (the turn's step timings) are optional; see SPEC §5.1 |
340
341
  | `error` | `{ type, detail, status }` — terminal, surface `detail` verbatim |
341
342
 
342
343
  Rules a client must respect:
@@ -580,10 +581,12 @@ Two consequences an integrator needs to plan for:
580
581
  alongside `gaia-voice`'s 790.
581
582
  - **An embedding pass on the first semantic code search.** If the repo has no
582
583
  [code index](https://amd-gaia.ai/docs/guides/code-index), the first
583
- `search_code_index` builds it, then searches. On a large monorepo that one
584
- search takes minutes of local embedding; a task that never searches pays
585
- nothing. `GAIA_PROJECT_MAP_AUTO_INDEX=1` builds it in the background at task
586
- start instead.
584
+ `search_code_index` starts building it in the background. A small repo is
585
+ searched within that call; on a large monorepo the build takes many minutes
586
+ of local embedding, and each search until then reports its progress so the
587
+ agent greps meanwhile. A task that never searches pays nothing.
588
+ `GAIA_PROJECT_MAP_AUTO_INDEX=1` builds it in the background at task start
589
+ instead.
587
590
 
588
591
  The sidecar's CLI accepts only `--host` and `--port`, so pointing the map at a
589
592
  specific project means `GAIA_PROJECT_ROOT=/path/to/repo` in its environment, or
@@ -662,7 +665,7 @@ There is no silent null.
662
665
  temp dir) is dropped, and a **shared** bin directory is moved to the end
663
666
  instead of removed, so the `python3` / `lemonade-server` / real `gaia` beside
664
667
  it stay reachable. If the Python CLI isn't installed anywhere, the daemon never
665
- comes up. It must also be **0.25.2+**: an older core's daemon starts fine but
668
+ comes up. It must also be **0.25.3+**: an older core's daemon starts fine but
666
669
  cannot run this agent, which reads as a UI with a dead agent rather than as
667
670
  a version problem.
668
671
  - **The TUI is installed as `gaia-tui`, never `gaia`** — the terminal-hub artifact
@@ -693,7 +696,7 @@ Then, in another terminal:
693
696
 
694
697
  ```bash
695
698
  curl -s http://127.0.0.1:8141/health # {"status":"ok","service":"gaia-agent-gaia"}
696
- curl -s http://127.0.0.1:8141/version # {"apiVersion":"2.24","agentVersion":"0.3.1"}
699
+ curl -s http://127.0.0.1:8141/version # {"apiVersion":"2.25","agentVersion":"0.3.1"}
697
700
  curl -s http://127.0.0.1:8141/v1/gaia/init # 200 + "ready":true, or 503 + a "hint"
698
701
  curl -N -X POST http://127.0.0.1:8141/v1/gaia/query \
699
702
  -H 'content-type: application/json' \
package/SPEC.md CHANGED
@@ -258,7 +258,7 @@ the header.
258
258
  | ------------------ | --------------------------------------- |
259
259
  | Default port | `8141` (`DEFAULT_PORT` in `server.py`) |
260
260
  | Reserved port | `4001` — refused with a `RangeError` |
261
- | Contract version | `API_VERSION = "2.24"` |
261
+ | Contract version | `API_VERSION = "2.25"` |
262
262
  | Agent id / prefix | `gaia` → `/v1/gaia/...` |
263
263
 
264
264
  ### 5.1 Endpoints
@@ -386,6 +386,19 @@ model's failure reads "the model server at `host:port`", not "Lemonade on this
386
386
  machine". Pre-2.20 binaries `422` the field and word every such error for the
387
387
  TUI.
388
388
 
389
+ `turns` (contract ≥ 2.25) is the conversation so far as the model saw it,
390
+ oldest first. Each entry is one earlier turn's `final.model_messages`, which
391
+ holds the assistant's tool calls and the tool results, or a user/assistant text
392
+ pair for a turn that recorded none. The agent replays the newest whole turns
393
+ that fit its context window and says in a `status` event when older ones drop
394
+ out. Sent, it replaces `context`, which must then be `[]` (anything else is a
395
+ `422`); `turns: []` means no earlier turns, and clears a retained session's
396
+ history. A request that sent `turns`, even `[]`, gets `model_messages` on its
397
+ `final` so the caller can store it with the reply; a request without `turns`
398
+ never does, because the record holds every tool result in full. It is also
399
+ absent when the run had not finished 15 s after its answer, and that turn then
400
+ replays as text only. Pre-2.25 binaries `422` `turns`.
401
+
389
402
  `reasoning` (contract ≥ 2.22), when `true`, streams the model's reasoning as
390
403
  `reasoning` events, `{ "type": "reasoning", "delta": "…" }`, so a client can
391
404
  show it apart from `status` lines and from the answer's `token`s. Each delta
@@ -504,7 +517,8 @@ directory shape, entry points, installed commands and platform quirks, present
504
517
  whenever the agent's working directory resolves to a code repository (a VCS
505
518
  directory or a recognised manifest at its root). `GAIA_PROJECT_ROOT=<path>`
506
519
  picks the project when the working directory is not it. If that repository has
507
- no code index, the first `search_code_index` builds one;
520
+ no code index, the first `search_code_index` starts building one in the
521
+ background and reports its progress until it lands;
508
522
  `GAIA_PROJECT_MAP_AUTO_INDEX=1` builds it in a background thread at task start
509
523
  instead. The same repository check also
510
524
  makes `run_shell_command` always-on for the session instead of semantically
@@ -1,34 +1,34 @@
1
1
  {
2
2
  "schemaVersion": "3.0",
3
- "agentVersion": "0.3.2",
3
+ "agentVersion": "0.3.3",
4
4
  "components": {
5
5
  "sidecar": {
6
- "componentVersion": "0.3.2",
7
- "baseUrl": "https://hub.amd-gaia.ai/agents/gaia/0.3.2",
6
+ "componentVersion": "0.3.3",
7
+ "baseUrl": "https://hub.amd-gaia.ai/agents/gaia/0.3.3",
8
8
  "platforms": {
9
9
  "win32-x64": {
10
10
  "filename": "gaia-agent-win32-x64.exe",
11
11
  "executable": "gaia-agent.exe",
12
- "sha256": "b107ed0740408b3ea50ab2556503549f173bcea13756e0cab0a5d0c98c867eab",
13
- "size": 172894251
12
+ "sha256": "44892b0c48b6f41d25372045b9136dc259edd644196acc59592a8fc5d16ee7a4",
13
+ "size": 173039470
14
14
  },
15
15
  "darwin-arm64": {
16
16
  "filename": "gaia-agent-darwin-arm64",
17
17
  "executable": "gaia-agent",
18
- "sha256": "2a339e225396df8f1623ff32051dd92800bf2224c76ba482cd25ae7ba30ebe30",
19
- "size": 162463472
18
+ "sha256": "66f086d888ba8d42a18a38cc2a4f532200aa03ec36e22b8ca253e21698bbd01d",
19
+ "size": 162600800
20
20
  },
21
21
  "darwin-x64": {
22
22
  "filename": "gaia-agent-darwin-x64",
23
23
  "executable": "gaia-agent",
24
- "sha256": "a796c734a72f43489062faa7d011399bcfdbd97280992e0ff8fea9734702aa28",
25
- "size": 173074704
24
+ "sha256": "864155bcee93886d22f48f04c160329baf74c7900e6cb11693a1879eb2b5f18a",
25
+ "size": 173141904
26
26
  },
27
27
  "linux-x64": {
28
28
  "filename": "gaia-agent-linux-x64",
29
29
  "executable": "gaia-agent",
30
- "sha256": "815817da63df38ae08dc96df226b758f53c54e56b59588b79a5e605c27c2ab64",
31
- "size": 211939056
30
+ "sha256": "a35a9db438e4de0abd289283eaab7ac44abf2bc529d66deb5d2eada01c423e3d",
31
+ "size": 212086912
32
32
  }
33
33
  }
34
34
  },
@@ -24,7 +24,7 @@ export declare const DEFAULT_PORT = 8141;
24
24
  /** Repo-wide reserved port. Nothing here may ever bind it. */
25
25
  export declare const RESERVED_PORT = 4001;
26
26
  /** The apiVersion this package is built against (`server.py: API_VERSION`). */
27
- export declare const API_VERSION = "2.24";
27
+ export declare const API_VERSION = "2.25";
28
28
  /** The agent id in the sidecar's route prefix (`/v1/gaia/...`). */
29
29
  export declare const AGENT_ID = "gaia";
30
30
  /** `GET /health` response. */
@@ -110,7 +110,7 @@ export interface WaitForHealthOptions {
110
110
  */
111
111
  export declare function waitForHealth(baseUrl: string, opts?: WaitForHealthOptions): Promise<void>;
112
112
  export interface VersionCheckOptions {
113
- /** apiVersion this package was built against. Default API_VERSION ("2.24"). */
113
+ /** apiVersion this package was built against. Default API_VERSION ("2.25"). */
114
114
  expectedApiVersion?: string;
115
115
  }
116
116
  /**
package/dist/lifecycle.js CHANGED
@@ -33,7 +33,7 @@ export const DEFAULT_PORT = 8141;
33
33
  /** Repo-wide reserved port. Nothing here may ever bind it. */
34
34
  export const RESERVED_PORT = 4001;
35
35
  /** The apiVersion this package is built against (`server.py: API_VERSION`). */
36
- export const API_VERSION = "2.24";
36
+ export const API_VERSION = "2.25";
37
37
  /** The agent id in the sidecar's route prefix (`/v1/gaia/...`). */
38
38
  export const AGENT_ID = "gaia";
39
39
  /** Basename the sidecar executable is written as (matches the lock). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amd-gaia/gaia",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "type": "module",
5
5
  "description": "One command to run GAIA: fetches and SHA-256 verifies the flagship agent sidecar and the terminal UI, then launches them. Runs 100% locally on AMD Ryzen AI.",
6
6
  "author": "AMD AI Group",