@amd-gaia/gaia 0.3.0 → 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,197 +6,425 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- - **Finished work is no longer replaced by "I can't confirm this is done".** A
10
- redaction task that loaded the `document-extract` skill had its answer swapped
11
- for a coverage warning about its own `redaction_log.csv`, and a task with two
12
- named outputs only knew about the last one. Every file the request names, and
13
- every file the turn wrote, is now an output and never a source; the skill
14
- checks coverage only when the request names a source document or asks for
15
- every item. No check replaces a non-empty answer any more: an unproven
16
- save, test result or extraction keeps the answer and adds a short "I
17
- couldn't confirm all of this" list after it; a turn that ends early keeps
18
- what it said ahead of its report; and a tool that keeps failing ends with the
19
- model's answer from what it found, then the failure. A failed image request
20
- is no longer rewritten into advice to start GAIA with an `--sd` flag that
21
- does not exist. `load_skill` no longer tells the model the extraction tools
22
- cannot run when it is about to register them, and a rejected extractor reply
23
- is now logged.
24
- - **`run_python` works in the Agent UI without a project.** It ran from the
25
- server's own folder, which is not an allowed path, so every approved snippet
26
- was refused and the agent fell back to slower shell commands. With no project
27
- and a working directory you did not allow, a snippet now runs in the agent's
28
- scratch directory, and its result says so. A project outside the allowed
29
- paths is still refused.
30
- - **An "always" answer for a shell command no longer covers code in the
31
- scratch folder.** A command run there or naming a path there — `cd` into it
32
- then `python -m explore`, or `pytest`, `make`, `pip install`, `uv run` or
33
- `go run` pointed at it — and a script handed a scratch path as an argument
34
- now ask every time, with no `always_scope`, the same as a script there.
35
- `always_scope` labels for commands that run code they do not show now say so:
36
- `pytest (runs the test code it finds)`, `make (runs the Makefile's
37
- commands)`, `python -m explore (runs that Python module)`.
38
- - **Exploring data no longer asks twice per step.** Each step wrote a helper
39
- script into the agent's own scratch folder and ran it, so a data task asked
40
- for approval about 30 times. Writes inside that folder now run unasked
41
- (writes anywhere else still ask). Running a script from it asks each time
42
- and offers no `always_scope`, since what is in that folder changes without
43
- a prompt.
44
- - **A command no loaded skill grants asks you instead of failing.** `python
45
- script.py`, `git commit` or `pip install` with no skill granting them used to
46
- come back as "needs a skill grant … declares 'shell:execute:git' in its
47
- SKILL.md", which nobody could act on. They now raise the approval prompt; a
48
- skill grant still skips it for reads. A prompt's `summary` for a write or
49
- code-running command ends with one plain line on what it can do, and the
50
- `in <folder>` line also appears when an earlier `cd` moved the session. A
51
- call you decline tells the agent not to reach the same result another way,
52
- and a run nobody can answer refuses in one plain sentence.
53
- - **Commands GAIA's checks don't cover ask once instead of failing.** `git
54
- push`, `git fetch`, `python -c`, PowerShell the checks can't read, a line with
55
- shell operators, or a path outside the allowed folders used to be refused
56
- outright. They now raise a prompt whose `summary` is the exact line the shell
57
- will run, its full folder and a risk sentence, with no `always_scope`; an
58
- approval runs that line once. Still refused with no prompt: an encoded
59
- PowerShell command or invisible characters, a line whose quoting can't be
60
- split the way the shell would, such a line that also deletes or discards work
61
- (`git push --force`, `git reset --hard`, `rm` outside the project), and
62
- folders no approval can open.
63
- - **`run_python` and `execute_python_file` work in the released binary.** The
64
- binary has no Python interpreter, so it handed every script to its own
65
- argument parser, which rejected it, and no calculation, chart or `.xlsx`
66
- could be produced. It now runs scripts itself, with openpyxl, python-docx,
67
- python-pptx, reportlab, pypdf, pandas, numpy, matplotlib and the full
68
- standard library bundled for them. The Windows binary grows from 147 MB to
69
- 168 MB.
70
- - **Long Python data jobs can finish.** `run_python` gave up after 60 s and
71
- the agent abandoned `execute_python_file` at 180 s even when it had asked
72
- for 15 minutes, while the script kept running and left a corrupt workbook
73
- behind. Python runs now get 120 s by default and up to 1800 s on request,
74
- the agent waits that long, and a run that runs out of time is killed with
75
- every process it started; the result names the files that changed while it
76
- ran so the agent checks them instead of reporting them finished.
77
- - **Document search says when it could not search.** With the embedding
78
- model or Lemonade Server down, `query_documents` and `query_specific_file`
79
- answered "no relevant information found", so the agent told the user their
80
- documents held nothing on the topic. They now return an error naming the
81
- cause (Lemonade unreachable, or the embedding model failing) and how to fix
82
- it. `index_document` and `index_directory` report the same cause, and
83
- `index_directory` stops at the first such file and reports an error when no
84
- file could be indexed. Hints for a missing optional package (RAG, PDF, Excel,
85
- HTML parsing) say in a frozen build that it isn't bundled, and from source
86
- give the install command for the running Python.
87
- - **A failed tool call is reported as a failure.** `run_shell_command` returned
88
- `status: success` for a command that exited non-zero, so the TUI and Agent UI
89
- showed a failed build or test run as a passed step. It is now `status: error`
90
- with an `error` naming the failing step, its exit code and the last stderr
91
- line; `stdout`, `stderr` and `return_code` are unchanged. grep's no-match and
92
- diff's "inputs differ" (exit 1) stay a success and say so in `expected_exit`.
93
- An MCP tool that answers `isError`, a DuckDuckGo search that was blocked, a
94
- `tasklist`/`wmctrl`/`osascript` window listing that failed, a notification
95
- whose PowerShell died, and an `open_url` with no browser to open are errors
96
- too. Install hints in a frozen build no longer name the binary as a Python to
97
- run pip with.
98
- - **Reviewing a few documents reads them in full.** `read_file` on a Word,
99
- PDF or Excel file returned `[Binary file, N bytes]`, so to compare a term
100
- sheet against a draft agreement the agent indexed them and ran a handful of
101
- searches, and missed a closing date that differed between the two because no
102
- search asked for it. `read_file` now returns the extracted text, in parts sized
103
- to the model's budget that say where the next part starts, and the prompt
104
- tells the agent to read a few documents in full for a review, comparison or
105
- reconciliation and keep indexing for large collections and single lookups.
106
- - **`fetch_page` no longer drops the middle of a long page.** Text past
107
- `max_length` was cut to its head and tail, which is where a product page keeps
108
- its menus and footer, not its price. It now returns the first part with a
109
- marker naming the offset of the next, takes `offset` to continue and `find` to
110
- jump to the passages containing a word, says so when a word is not on the
111
- page, and flags a page with almost no static text as rendered by JavaScript.
112
- `Length:` now reports the whole page rather than the excerpt.
113
- - **Long desktop tasks finish with their deliverables instead of a bare "I
114
- can't confirm this is done".** Picking a controller from nine datasheets and
115
- pricing a 40-unit BOM ran out of its 50 steps while still searching for
116
- prices, and the reply dropped the recommendation the agent had already
117
- written. The agent's default step limit is now **150** (a `/query`
118
- `max_steps` or `GAIA_AGENT_MAX_STEPS` still wins); at 20, 10 and 5 steps left
119
- it is told to write the requested files from what it has, marking unverified
120
- values, and a turn that still runs out keeps its findings and lists what is
121
- missing after them.
122
- - **The model notice is one line.** Switching or restoring a model printed a
123
- four-sentence paragraph that named the model twice and said "via Lemonade".
124
- It now reads like "Switched to **DeepSeek-V4.1-Flash** on the AMD LLM Gateway
125
- (cloud). Your messages, and anything read from files or memory, are sent
126
- there." The `/model` list drops "via Lemonade" from its headings and marks
127
- the configured default model with `(default)`.
128
- - **Single-file search results name their file.** `query_specific_file` put the
129
- path only at the top of its result, so each chunk arrived with no source and
130
- the chunk cards showed none. Every chunk now carries `source_file`, and the
131
- result lists it in `source_files`, as `query_documents` already did.
132
- - **The turn log counts the answer of a streamed turn.** With `GAIA_TURN_LOG`
133
- set, a turn whose answer streamed out recorded `answer_chars: 0`. It now
134
- records the length of the answer the user saw.
135
- - **`run_python` and `execute_python_file` work in the released binary.** The
136
- binary has no Python interpreter, so it handed every script to its own
137
- argument parser, which rejected it, and no calculation, chart or `.xlsx`
138
- could be produced. It now runs scripts itself, with pypdf, pymupdf,
139
- python-docx, python-pptx, openpyxl, xlsxwriter, reportlab, pandas, numpy,
140
- matplotlib and the full standard library bundled for them, and both tools
141
- name those libraries to the model. A script that starts `sys.executable`
142
- (`-m`, `-c`, a file) runs too; `-m pip` says packages can't be installed
143
- and lists what is bundled. The Windows binary grows from 147 MB to 168 MB.
144
- - **A Python script that fails is reported as a failure.** A non-zero exit
145
- came back as `status: success`, so the TUI showed a failed run as
146
- successful. It is now `status: error`, with an `error` naming the exit code
147
- and the last stderr line; `stdout`, `stderr` and `return_code` are unchanged.
148
- - **`GAIA_ALLOWED_PATHS` confines a run to the folders you name.** The agent
149
- could read anything under the user's home and nothing narrowed that short of
150
- embedding it, so an evaluation run could read the graders' answer keys. Set
151
- to absolute folders, it narrows every file tool, search, index and shell path
152
- check to them — it never widens, an invalid value stops startup, and code the
153
- agent runs (`run_python`, shell) is not confined.
9
+ ## [0.3.3]
154
10
 
155
- - **The sidecar's start-up warm-up now makes the first question fast.** It
156
- primed only the agent's own instructions, without the tool list or the rest
157
- of the system prompt, so the first question re-read all ~19K prompt tokens
158
- (34 s on Qwen3.6-35B-A3B). It now sends exactly what a turn sends, and the
159
- first question reads only its own ~50 tokens (5 s). A warm-up that fails is
160
- logged as a warning with its cause instead of an info line.
161
- - **`/model` names the command that connects a cloud provider.** With no
162
- Fireworks or AMD gateway connection, the list told users to "connect this
163
- provider in the TUI provider settings", a screen with no obvious way in. It
164
- now says to run `/provider`, the command that opens it.
165
- - **The TUI's provider picker works after GAIA's Lemonade restarts.** When the
166
- agent ran as the TUI's own child, its model-state ping kept naming the port
167
- Lemonade started on, so after a restart the picker said "Lemonade did not
168
- respond" while chat worked. With a local or cloud chat model the ping now
169
- reports the port the agent talks to, and it still never starts a stopped
170
- server. A Claude session still reports the port it started with.
171
- - **The Agent UI's Skills settings list this agent's skills.** With the agent
172
- installed from the Hub, the page said the agent package was not installed
173
- and to run `gaia init`, which changed nothing: the bundled skills live
174
- inside the binary, where the UI could not read them. `GET /v1/gaia/skills`
175
- (contract **2.17**) now returns them.
176
- - **A message sent right after Stop is answered instead of refused.** A stopped
177
- turn holds its session until its model call returns, so the next `/query`
178
- got `409 … is already running a turn` for as long as the stopped answer would
179
- have taken — about 40 s for a long one. It now waits for the stopped turn to
180
- finish (up to 240 s) and then runs. A turn that was not cancelled is still
181
- refused at once.
182
- - **Documents attached to a chat now reach the agent.** In the Agent UI, a
183
- Hub-installed agent answered "no documents are indexed" about a file the user
184
- had attached, because the relayed turn never carried the chat's files.
185
- `/query` now takes a `documents` field (contract **2.16**): the agent indexes
186
- them before the turn, granting each exact file and not its folder, including
187
- a file attached partway through a conversation.
188
- - **The first chat after the agent starts uses its own tools.** A session built
189
- while the start-up warm-up was still building could end up running the
190
- warm-up agent's tools, so a file it had just indexed read as access denied.
191
- Agents are now built one at a time.
192
- - **Web requests work behind a corporate TLS-inspecting proxy.** HTTPS now
193
- trusts the operating system's certificate store, as pip does, instead of only
194
- Python's bundled list, so a proxy root such as Zscaler's no longer fails every
195
- fetch with `CERTIFICATE_VERIFY_FAILED`.
196
- - **Starting the agent no longer downloads a model you skipped.** The HTTP
197
- sidecar's start-up warm-up skips the default local model when it is not
198
- downloaded, so someone using a cloud model is not handed a multi-GB download
199
- they never asked for.
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
+
47
+ ## [0.3.2]
48
+
49
+ Released with GAIA 0.25.2, and requires the `gaia`
50
+ Python CLI 0.25.2+ on `PATH`. Integrators: the sidecar contract is now
51
+ **2.24**; clients built for 2.18 keep working, and the new
52
+ `/query` fields are refused with `422` by older binaries, so probe
53
+ `/version` before sending them.
54
+
55
+ - **Memory downloads its embedding model when it is missing.** On the first
56
+ start that uses memory, the agent now fetches the required embedding model
57
+ from Lemonade instead of silently running without memory; the initial
58
+ download can be about 300 MB.
59
+ - **Unknown or misplaced switches are refused.** `gaia --forse` and
60
+ `gaia fetch --developer-mode` now exit 2 instead of silently starting the TUI;
61
+ pass terminal-UI arguments after a bare `--`.
62
+
63
+ - **The Agent UI's "Under the hood" figures cover GAIA chats.** It said every
64
+ answer was "not measured", because only the agent saw its own step timings.
65
+ `final` now carries `performance` with them: the turn's model and tool
66
+ seconds and each model call's token counts. Older binaries never send it.
67
+ - **`GET /v1/gaia/skills` says where each skill came from.** Each skill now
68
+ carries a `source` (`agent-bundled`, `user` or `claude-import`; `null` for
69
+ any other root), so the Agent UI can group the Skills list by origin. An
70
+ older agent omits it and the UI shows the list flat.
71
+ - **One very long turn no longer vanishes from the conversation.** A turn
72
+ bigger than the whole history budget, like a pasted log or a long document
73
+ read, was dropped from what the model saw next, answer included, so "now
74
+ shorten that" ran with no record of it. It is now kept: long tool results
75
+ become a short note naming the tool, and its longest messages are cut with
76
+ a note saying how much.
77
+ - **Internet off also stops the mailbox and Agent Hub tools.** With a chat's
78
+ Internet switched off, GAIA could still read Gmail or Outlook and search or
79
+ install skills from the Agent Hub, because those tools carry no URL for the
80
+ check to see. They are now refused with the same message as a web search.
81
+
82
+ ### For integrators: contract 2.24
83
+
84
+ - **Relative file paths use the chat workspace.** A new `working_directory` field
85
+ on `/query` tells the agent where bare file names resolve, separately from
86
+ `allowed_paths`. New and retained sessions use the same workspace for reads,
87
+ writes, edits and approval prompts. Send it only after `/version` reports
88
+ contract 2.24 or later.
89
+
90
+ ### For integrators: contract 2.23
91
+
92
+ - **`/query` takes `internet_off`** (contract **2.23**, #5883). The Agent UI
93
+ never told the agent when a chat's Internet switch was off, so the switch
94
+ stayed locked in every GAIA chat on a standard install. `true` refuses web
95
+ search, page fetches, the browser, connector, mailbox and Agent Hub tools and
96
+ commands that contact another host, as it does when the agent runs inside the Agent UI. `false`
97
+ allows them, and omitting it leaves the agent as it is. A retained session
98
+ keeps the last value. Older binaries `422` the field.
99
+ - **`POST /v1/gaia/sessions/{session_id}/internet`** (contract **2.23**)
100
+ reaches a turn already running. Without it, a user who turned the internet
101
+ off mid-turn watched the agent keep searching until the turn ended. Body
102
+ `{"internet_off": bool}`; the session's next tool call follows it. An
103
+ unknown session is a `404`, as for `/bypass`. Post it only once `/query`
104
+ has answered: until then the turn's own `internet_off` replaces it.
105
+
106
+ ### For integrators: contract 2.22
107
+
108
+ - **A client can show the model's reasoning.** Over `/query` the reasoning
109
+ only arrived folded into `status` lines, so the Agent UI showed none of it
110
+ for an installed GAIA. A request with `reasoning: true` now gets it as
111
+ `reasoning` events, `{ delta }`, kept apart from the answer. Without the
112
+ field nothing changes. Older binaries reject it with `422`.
113
+
114
+ ### For integrators: contract 2.21
115
+
116
+ - **`final` says how full the model's window is** (contract **2.21**,
117
+ #5738). The Agent UI's Context panel and the meter beside its message box
118
+ stayed empty for every GAIA chat, because only the agent can measure its
119
+ own prompt, tools and window. `final` now carries `context` with that
120
+ measurement for the next call, or `context_error` when measuring failed.
121
+ A stopped or failed turn carries neither. Older binaries never send it.
122
+ - **A relayed write prompt names where the file lands.** When the model asks to
123
+ write `shop2.txt`, `needs_confirmation` now carries the absolute path the
124
+ write resolves to in `prompt_context.file_path`, so a front-end can show
125
+ `/Users/you/shop2.txt` instead of a bare name. `args` still holds exactly the
126
+ model's `file_path`.
127
+ - **A web search's results reach the client.** The Agent UI listed no Sources
128
+ for a GAIA web search, because a `search_web` `tool_result` carried only a
129
+ 300-character summary. Its `data` now also carries `sources`, a list of
130
+ `{ title, url }` for each hit. Older binaries never send it.
131
+
132
+ - **An old failure in memory no longer stops a request you make now.** A note
133
+ like "this page returned 503, don't waste tool calls on it" was obeyed as a
134
+ standing ban, so the agent refused a URL you handed it. Memories now reach
135
+ the model as dated notes your request outranks, and a passing failure is
136
+ marked as one. A 429 or 502-504 "try later" failure is no longer saved as
137
+ an error memory at all.
138
+ - **Text from a file is not saved as your details.** The agent could save a
139
+ line from a document it read, or call it something you had saved. It now
140
+ saves text from a file, page or tool result only when you ask it to keep
141
+ something, and an empty memory search says that file text is not saved.
142
+
143
+ - **Pushed history that doesn't fit the model's window no longer overflows
144
+ it.** `/query` used the `context` you pushed as-is, but you size it without
145
+ seeing the agent's prompt and tools. On a 32K window the two together could
146
+ exceed the window and fail the turn. The agent now keeps the newest whole
147
+ turns that fit beside its prompt and streams a `status` event when older
148
+ ones drop out of view.
149
+
150
+ - **Homebrew tools are visible to the agent on a Mac.** An app opened from Finder
151
+ or the Dock starts with only the system folders on its search path, so the
152
+ agent could not run `gh`, `node` or anything else Homebrew installed, and its
153
+ prompt said they were "not installed". The agent now starts with the `PATH`
154
+ your login shell builds (only when opened that way: started from a terminal it
155
+ keeps the terminal's own `PATH`, so an activated virtualenv still wins), and a
156
+ tool it still cannot find is reported as not
157
+ reachable from its shell rather than missing from your machine. If your shell
158
+ startup is slow or fails, the agent logs a warning and keeps the old path.
159
+
160
+ ### For integrators: contract 2.20
161
+
162
+ - **A failed model request says which endpoint failed, worded for your
163
+ front-end** (contract **2.20**, #5295). A headless caller of `/query` whose
164
+ hosted model returned HTTP 502 was told the "cloud request through Lemonade
165
+ failed" and to check "the TUI provider settings", though no TUI was
166
+ involved. The error now names the provider and the `host:port` the request
167
+ went through. A local model on a base URL you set is reported as "the model
168
+ server at `host:port`" instead of "Lemonade on this machine", since GAIA
169
+ can't tell what serves it. The advice follows the `surface` field: a caller
170
+ that omits it is pointed at the model server the GAIA host uses; `"tui"`,
171
+ `"agent_ui"` and `"cli"` keep their own settings screens. Older binaries
172
+ refuse the field with `422`, so probe `/version` before sending it.
173
+ Version skew: a front-end older than this release never sends `surface`, so
174
+ against this agent it gets the headless advice (the model server's
175
+ `LEMONADE_BASE_URL`) instead of its own settings screen. GAIA ships the TUI,
176
+ the Agent UI and this agent together, so this only shows when one of them is
177
+ updated without the others, or when the TUI's `/version` probe times out and
178
+ it can't confirm the agent takes the field.
179
+ - **Answers stream over `/query`.** The HTTP sidecar ran its agent with
180
+ streaming off, so a relayed turn (the Agent UI, and the TUI's later sessions)
181
+ showed "Waiting on the model" until the whole answer landed at once, Stop could
182
+ not cut a model call short, and a stopped turn kept no text. Every `/query`
183
+ turn now streams its model calls and sends the answer as `token` events before
184
+ `final`, the same as the stdio transport. A run cancelled mid-answer stops
185
+ within a token and ends with an empty `final`, as stdio does; text not yet
186
+ sent when the cancel lands is dropped.
187
+ ### Fixed
188
+
189
+ - **"Save it to my Documents folder" saves to the user's Documents folder.**
190
+ The system prompt told GAIA that "my documents" meant its own documents
191
+ folder (`~/.gaia/documents`), so a new file the user asked for in Documents
192
+ went into GAIA's hidden folder, where they would never find it. Finding an
193
+ existing file still checks GAIA's folders first.
194
+ - **Secrets stay out of memory and the conversation log.** A bank PIN was saved
195
+ as a memory, because the filter knew passwords and API keys but not PINs. The
196
+ conversation log also kept the PIN, a password the agent had refused, a card
197
+ number and an SSN verbatim, where `search_past_conversations` read them back.
198
+ PINs, passcodes, card security codes, Luhn-valid card numbers and SSNs are now
199
+ refused as memories, and every credential-shaped span is replaced with
200
+ `[secret removed]` before a turn is logged.
201
+ - **"How much free disk space do I have?" gets the right number, first try.**
202
+ On a Mac, GAIA said a nearly full disk had ~233 GB free: its system-info
203
+ tool reported only the share the system volume uses, so 97.8% used read as
204
+ 5%. It now reports free space as macOS counts it, and says it answers
205
+ free-space questions, so GAIA no longer tries a shell command that is refused.
206
+ - **Full access in the Agent UI asks before a gated shell command instead of
207
+ refusing it.** With `/sessions/{id}/bypass` on, a command such as a delete or
208
+ `git add` was refused outright, so a Full access chat could not run it at
209
+ all. On a run someone can answer it now emits `needs_confirmation` and runs
210
+ only on an allow from `/tool_decision`. The shell gates still stay on over
211
+ HTTP, commands that need no approval still run unasked, and a run nobody can
212
+ answer still refuses.
213
+ - **Local models with a large window can write longer replies.** The output
214
+ cap is a quarter of the loaded window (16K at 64K, between 8K and 32K)
215
+ instead of a flat 8K, and a reply cut off at the cap is told to write the
216
+ file in smaller parts.
217
+ - **`search_file_content` searches the workspace.** A relative or default
218
+ directory resolved against the sidecar's own folder and reported "0 files";
219
+ it now resolves against the workspace, searches text files of any extension,
220
+ and says when nothing was searched.
221
+ - **Token counts are exact in the published binary, offline too.** The binary
222
+ could not load its tokenizer, so every turn trimmed history and sized
223
+ context from an estimate that overcounts, and logged `Unknown encoding
224
+ cl100k_base`. The tokenizer and its data now ship inside the binary, so it
225
+ no longer downloads anything to count tokens.
226
+
227
+ ### For integrators: contract 2.20
228
+
229
+ - **`/query` takes `surface`** (contract **2.20**): `"agent_ui"`, `"tui"` or
230
+ `"cli"`. Asked to run something on a schedule from the Agent UI, the agent
231
+ said it had no scheduler and sent the user to Windows Task Scheduler; with
232
+ `"agent_ui"` it points them at the **Scheduled tasks** page instead. Older
233
+ binaries `422` the field, so probe `/version` before sending it.
234
+ - **The agent knows which folders it can work in.** The system prompt now names
235
+ the session's folders and labels GAIA's documents folder, so "summarize X in
236
+ my documents folder" looks there first instead of trying `~/Documents` and
237
+ the home folder.
238
+
239
+ ### For integrators
240
+
241
+ - **A tool result keeps the tool's own status.** When a tool's result had no
242
+ structured payload, the `tool_result` event's `data` carried only `summary`
243
+ and `success`, so a client could not tell a skipped `remember` (a private
244
+ chat saves nothing) from a saved one, and the Agent UI listed it as saved.
245
+ `data` now also carries `status` when the tool returned one. Additive, so
246
+ the contract version is unchanged.
247
+
248
+ - **An MCP tool call says which connector it used and what came back.** A Git
249
+ connector call reached a client as a bare `mcp_git_git_log`, and its result
250
+ as "Tool 'git_log' returned data". `tool_call` gains optional `mcp_server`,
251
+ `mcp_server_label` ("Git") and `mcp_tool` ("git_log"), and the result's
252
+ `data` carries the tool's text in `mcp_output` (`{ text, truncated }`, capped
253
+ at 16,000 characters). Clients that ignore the fields see the same events.
254
+
255
+ ### For integrators: contract 2.19
256
+
257
+ - **`/query` can record a turn's file changes for undo** (contract **2.19**).
258
+ Desktop chats run in this agent and the Agent UI relays them, so a file the
259
+ agent wrote never reached the chat's Changes view or its Undo. With
260
+ `changes_turn_id` (and `session_id`), the agent copies each file before
261
+ changing it into the snapshot store the Agent UI reads, and finishes the
262
+ recording before the terminal event. Older binaries refuse the field with
263
+ `422`, so probe `/version` before sending it.
264
+ - **A confirmation's `args` are only what the model sent.** `needs_confirmation`
265
+ `args` also carried keys the agent adds to its own prompt — a risk note, a
266
+ scratch-folder marker, and the folder a shell call runs in — so a policy
267
+ client auto-approving on `args` matched fields the model never sent. `args`
268
+ is now exactly the call's arguments; the folder and risk note moved to a new
269
+ `prompt_context` object.
270
+ - **A tool result names the file it wrote.** When a tool's result carries
271
+ `file_path` or `image_path`, the `tool_result` event's `data` now keeps it, so
272
+ a client can list the files a turn produced.
273
+
274
+ ## [0.3.1]
275
+
276
+ Released with GAIA 0.25.1, and requires it. Integrators: the sidecar
277
+ contract is now **2.18**; clients built for 2.17 keep working, and the new
278
+ `/query` fields are refused with `422` by older binaries, so probe
279
+ `/version` before sending them.
280
+
281
+ ### Linux
282
+
283
+ - **The Linux agent runs on glibc 2.34 or newer.** The `linux-x64` agent is
284
+ now built against glibc 2.34 (#5545), so it starts on Ubuntu 22.04, Debian 12
285
+ and RHEL 9. Before, it needed glibc 2.38 and failed at launch on those.
286
+
287
+ ### For integrators: contract 2.18
288
+
289
+ - **`/query` takes the chat's file scope and memory mode** (contract **2.18**).
290
+ `allowed_paths` lets the Agent UI hand the agent the same scope its session
291
+ panel shows. `memory` fixes private chats saving to memory: the relayed turn
292
+ never said the chat was private or that memory was off, so the agent went on
293
+ saving the errors and lessons it records on its own. `"private"` or `"off"`
294
+ now turns off every memory write for the turn.
295
+ - **A confirmation carries the call it asks about.** `needs_confirmation` now
296
+ has `args` (each value capped at 64,000 characters, with `args_truncated`
297
+ when one was cut) and `tool_label`, so a client can show all of the code it
298
+ is approving rather than the shortened `summary`, and word a path prompt for
299
+ a file or folder that exists.
300
+ - **A turn the model gave up on ends as failed, not done.** When the model
301
+ stopped responding or refused mid-turn (a stall, a 404, every retry spent),
302
+ the turn ended on the model's opening sentence and the Agent UI listed the
303
+ chat as done. The final answer now names the step, the provider and the
304
+ cause, what already ran, and what is unfinished, and the `final` event
305
+ carries `failed: true`.
306
+ - **A turn queued for the model says so on the stream.** When another process
307
+ or request is using the model, `/query` now sends `status` events with
308
+ `phase: "model_queue"` every ~2 s, carrying a `queue` object with the turn's
309
+ place in line, who holds the model and how long it has waited, then one
310
+ `granted` update. A turn queued this way leases ahead of background work, and
311
+ `/query/{run_id}/cancel` takes it out of the queue. Before, the stream went
312
+ silent for the whole wait, so a client could not tell a queued turn from a
313
+ dead one.
314
+ - **Needs core 0.25.1.** The chat agent this one builds on imports the
315
+ reasoning-effort tool, which first ships in core 0.25.1, so its
316
+ `amd-gaia` floor and `min_gaia_version` rise to 0.25.1 with that release.
317
+
318
+ ### File access and privacy
319
+
320
+ - **Full access in the Agent UI grants the folders you name.** Turning it on
321
+ over `/sessions/{id}/bypass` refused every path outside the chat's scope with
322
+ nobody asked. On a run the caller can answer for, Full access now grants the
323
+ path without a prompt, as it does in-process; Ask mode asks. Unattended runs,
324
+ the home folder and drive roots are still refused.
325
+ - **No more approval prompts for files that aren't there.** Naming a missing
326
+ file or folder outside the allowed paths opened a 10-minute approval prompt,
327
+ and only after it did the agent learn the file didn't exist; a retry asked
328
+ again. The tool now says the file wasn't found straight away, without asking,
329
+ and names an allowed or attached file with the same name. `analyze_data_file`
330
+ given a bare file name uses the attached file of that name instead of asking
331
+ about one in the working folder. Secret and protected paths are refused
332
+ exactly as before, whether or not they exist.
333
+ - **A turn's file changes can be undone.** The agent saves a copy of every
334
+ file before a tool writes, edits, creates or deletes it, so the Agent UI
335
+ can show the turn's changes and put every file back, even after a restart.
336
+ A turn that also ran a shell command, Python or an MCP tool says undo may
337
+ be incomplete.
338
+ - **Saving a download asks about the file, not its folder.** A download into
339
+ the home folder failed without asking, because the agent asked to grant the
340
+ whole folder. It now asks about the one file it is about to create.
341
+ - **A document another program has open is re-indexed once it is free.** On
342
+ Windows, a watched file that Word, PowerPoint or another program held locked
343
+ was read once, reported as corrupted, and never re-indexed. It is now retried
344
+ a few times, and if it stays locked the log says to close the program and
345
+ save the file again.
346
+
347
+ ### Long and busy turns finish
348
+
349
+ - **A context overflow no longer throws away the evidence.** A task that read
350
+ many documents used to fill a 32K–64K window, after which the overflow retry
351
+ dropped every older result and the answer was built on whatever was left
352
+ (#2780). The retry now keeps each result whole behind a handle the model can
353
+ re-read, and retries only when the request will then fit.
354
+ - **Token counts no longer undercount when the tokenizer data can't load.** On
355
+ an offline or locked-down machine the counter fell back to characters ÷ 4.28,
356
+ which undercounts JSON and CJK text, so history that should take half the
357
+ window could fill it (#5066). It now warns and counts at least one token per
358
+ three UTF-8 bytes.
359
+ - **Opening a session or switching its model no longer freezes the other
360
+ sessions.** The sidecar built a new session's agent, and ran a `/model`
361
+ switch (which builds a new client and checks its server), on its event
362
+ loop. Every other session's stream stopped for that long, heartbeats
363
+ included, so the TUI and the daemon relay saw an idle connection. That
364
+ setup now runs on a worker thread, and a request that goes away mid-setup
365
+ still releases its session.
366
+ - **Background memory upkeep no longer wipes the chat's cached prompt.**
367
+ Memory consolidation, reconciliation and skill distillation ran on the
368
+ model slot the conversation uses, so the next message re-read the whole
369
+ ~19K-token prompt (~45 s on Gemma-4-E4B). They now run on the side slot,
370
+ as memory extraction already did.
371
+ - **A turn cut short by closing the TUI is saved as interrupted.** The session
372
+ history got a turn only once it ended, so closing the TUI mid-turn saved it
373
+ as an ordinary "stopped" answer, or, if the TUI had to kill the agent, lost
374
+ the question entirely. The question is now saved when the turn starts, and a
375
+ turn the TUI's closing cut short ends with "This answer was interrupted when
376
+ GAIA closed." A resumed session (`GAIA_HISTORY_FILE`) sees it. Questions
377
+ queued before the close are saved as they ended.
378
+ - **A busy, restarting or sleeping model server no longer fails the turn.**
379
+ The agent waits for a shared Lemonade that is loading another app's model,
380
+ waits up to 60 s for GAIA's own server to come back after a restart, and a
381
+ PC that sleeps mid-answer resumes instead of reporting a stall. A shared
382
+ KV-cache collision is no longer reported as "conversation too long".
383
+ - **Nothing a tool waits on can hang the turn for good.** A hung MCP server,
384
+ a web server sending one byte at a time (page fetches stop at 120 s,
385
+ downloads at 30 min) and a busy embedder during indexing (one 300 s wait
386
+ per batch, with a message saying why) all end with a clear error. One bad
387
+ batch of parallel tool calls no longer trips the failure breaker and ends
388
+ the task with no answer.
389
+ - **The agent's own scripts get time to run.** A script run through an
390
+ interpreter (`python analyze.py big.csv`) gets a 600 s default instead of
391
+ the 30 s kill for quick commands.
392
+ - **Web search survives DuckDuckGo rate limits.** A refused search is retried
393
+ with backoff and through DuckDuckGo's lite endpoint, or answered by Tavily
394
+ when that connector is set up, instead of failing and being saved to memory
395
+ as a known error.
396
+
397
+ ### Memory you can trust
398
+
399
+ - **Memory keeps what the user says, and keeps it current.** Facts come only
400
+ from what the user says about themselves, a forgotten fact is not re-learned
401
+ from old chats, a newer fact outranks the one it replaced, and a write that
402
+ carries tool-call markup or model reasoning is refused instead of saved
403
+ corrupted. Relevant memories now surface in the chats they are about.
404
+
405
+ ### Models and answers
406
+
407
+ - **gpt-oss 20B and 120B are supported models.** On a model that grades its
408
+ reasoning, the agent gets `set_reasoning_effort` (low, medium or high) to
409
+ choose how hard it thinks for the rest of the request; every new message
410
+ starts again at medium. It is not registered on other models, so the
411
+ agent's 95 tools on Gemma and Qwen are unchanged.
412
+ - **gpt-oss runs the agent.** Every array tool parameter now declares
413
+ `items`, without which gpt-oss's chat template rejected every request
414
+ with HTTP 500, and gpt-oss control markers inside a file or page the agent
415
+ reads are broken up so the model no longer answers with nothing.
416
+ - **Answers are checked more honestly.** A claim such as "all 55 tests pass"
417
+ is checked even when the same sentence says "but" or "not", and asking the
418
+ agent to run a shell command runs it rather than reading the shell's state.
419
+
420
+ ### Diagnostics
421
+
422
+ - **The turn log says how busy the model server was.** With `GAIA_TURN_LOG`
423
+ set, each model call records the server's own prefill, decode and cache-reuse
424
+ figures and the time spent waiting on the model-slot lease, the slot lock and
425
+ the status probe; each turn records its server compute, its non-model time,
426
+ and what filled the gaps between model calls. `GET /v1/gaia/debug/turns`
427
+ returns the last records while recording is on (off the versioned contract).
200
428
 
201
429
  ## [0.3.0]
202
430
 
@@ -543,9 +771,198 @@ Released with GAIA 0.25.0, and requires it.
543
771
  is nothing but a skill-granted CLI runs argv-only, so `>` there is refused
544
772
  with an explanation instead of reaching the binary as text. See SPEC §5.5.
545
773
 
774
+ ### Also in 0.3.0
775
+
776
+ These were still listed under Unreleased when 0.3.0 was tagged, so they
777
+ shipped in it.
778
+
779
+ - **Finished work is no longer replaced by "I can't confirm this is done".** A
780
+ redaction task that loaded the `document-extract` skill had its answer swapped
781
+ for a coverage warning about its own `redaction_log.csv`, and a task with two
782
+ named outputs only knew about the last one. Every file the request names, and
783
+ every file the turn wrote, is now an output and never a source; the skill
784
+ checks coverage only when the request names a source document or asks for
785
+ every item. No check replaces a non-empty answer any more: an unproven
786
+ save, test result or extraction keeps the answer and adds a short "I
787
+ couldn't confirm all of this" list after it; a turn that ends early keeps
788
+ what it said ahead of its report; and a tool that keeps failing ends with the
789
+ model's answer from what it found, then the failure. A failed image request
790
+ is no longer rewritten into advice to start GAIA with an `--sd` flag that
791
+ does not exist. `load_skill` no longer tells the model the extraction tools
792
+ cannot run when it is about to register them, and a rejected extractor reply
793
+ is now logged.
794
+ - **`run_python` works in the Agent UI without a project.** It ran from the
795
+ server's own folder, which is not an allowed path, so every approved snippet
796
+ was refused and the agent fell back to slower shell commands. With no project
797
+ and a working directory you did not allow, a snippet now runs in the agent's
798
+ scratch directory, and its result says so. A project outside the allowed
799
+ paths is still refused.
800
+ - **An "always" answer for a shell command no longer covers code in the
801
+ scratch folder.** A command run there or naming a path there — `cd` into it
802
+ then `python -m explore`, or `pytest`, `make`, `pip install`, `uv run` or
803
+ `go run` pointed at it — and a script handed a scratch path as an argument
804
+ now ask every time, with no `always_scope`, the same as a script there.
805
+ `always_scope` labels for commands that run code they do not show now say so:
806
+ `pytest (runs the test code it finds)`, `make (runs the Makefile's
807
+ commands)`, `python -m explore (runs that Python module)`.
808
+ - **Exploring data no longer asks twice per step.** Each step wrote a helper
809
+ script into the agent's own scratch folder and ran it, so a data task asked
810
+ for approval about 30 times. Writes inside that folder now run unasked
811
+ (writes anywhere else still ask). Running a script from it asks each time
812
+ and offers no `always_scope`, since what is in that folder changes without
813
+ a prompt.
814
+ - **A command no loaded skill grants asks you instead of failing.** `python
815
+ script.py`, `git commit` or `pip install` with no skill granting them used to
816
+ come back as "needs a skill grant … declares 'shell:execute:git' in its
817
+ SKILL.md", which nobody could act on. They now raise the approval prompt; a
818
+ skill grant still skips it for reads. A prompt's `summary` for a write or
819
+ code-running command ends with one plain line on what it can do, and the
820
+ `in <folder>` line also appears when an earlier `cd` moved the session. A
821
+ call you decline tells the agent not to reach the same result another way,
822
+ and a run nobody can answer refuses in one plain sentence.
823
+ - **Commands GAIA's checks don't cover ask once instead of failing.** `git
824
+ push`, `git fetch`, `python -c`, PowerShell the checks can't read, a line with
825
+ shell operators, or a path outside the allowed folders used to be refused
826
+ outright. They now raise a prompt whose `summary` is the exact line the shell
827
+ will run, its full folder and a risk sentence, with no `always_scope`; an
828
+ approval runs that line once. Still refused with no prompt: an encoded
829
+ PowerShell command or invisible characters, a line whose quoting can't be
830
+ split the way the shell would, such a line that also deletes or discards work
831
+ (`git push --force`, `git reset --hard`, `rm` outside the project), and
832
+ folders no approval can open.
833
+ - **Long Python data jobs can finish.** `run_python` gave up after 60 s and
834
+ the agent abandoned `execute_python_file` at 180 s even when it had asked
835
+ for 15 minutes, while the script kept running and left a corrupt workbook
836
+ behind. Python runs now get 120 s by default and up to 1800 s on request,
837
+ the agent waits that long, and a run that runs out of time is killed with
838
+ every process it started; the result names the files that changed while it
839
+ ran so the agent checks them instead of reporting them finished.
840
+ - **Document search says when it could not search.** With the embedding
841
+ model or Lemonade Server down, `query_documents` and `query_specific_file`
842
+ answered "no relevant information found", so the agent told the user their
843
+ documents held nothing on the topic. They now return an error naming the
844
+ cause (Lemonade unreachable, or the embedding model failing) and how to fix
845
+ it. `index_document` and `index_directory` report the same cause, and
846
+ `index_directory` stops at the first such file and reports an error when no
847
+ file could be indexed. Hints for a missing optional package (RAG, PDF, Excel,
848
+ HTML parsing) say in a frozen build that it isn't bundled, and from source
849
+ give the install command for the running Python.
850
+ - **A failed tool call is reported as a failure.** `run_shell_command` returned
851
+ `status: success` for a command that exited non-zero, so the TUI and Agent UI
852
+ showed a failed build or test run as a passed step. It is now `status: error`
853
+ with an `error` naming the failing step, its exit code and the last stderr
854
+ line; `stdout`, `stderr` and `return_code` are unchanged. grep's no-match and
855
+ diff's "inputs differ" (exit 1) stay a success and say so in `expected_exit`.
856
+ An MCP tool that answers `isError`, a DuckDuckGo search that was blocked, a
857
+ `tasklist`/`wmctrl`/`osascript` window listing that failed, a notification
858
+ whose PowerShell died, and an `open_url` with no browser to open are errors
859
+ too. Install hints in a frozen build no longer name the binary as a Python to
860
+ run pip with.
861
+ - **Reviewing a few documents reads them in full.** `read_file` on a Word,
862
+ PDF or Excel file returned `[Binary file, N bytes]`, so to compare a term
863
+ sheet against a draft agreement the agent indexed them and ran a handful of
864
+ searches, and missed a closing date that differed between the two because no
865
+ search asked for it. `read_file` now returns the extracted text, in parts sized
866
+ to the model's budget that say where the next part starts, and the prompt
867
+ tells the agent to read a few documents in full for a review, comparison or
868
+ reconciliation and keep indexing for large collections and single lookups.
869
+ - **`fetch_page` no longer drops the middle of a long page.** Text past
870
+ `max_length` was cut to its head and tail, which is where a product page keeps
871
+ its menus and footer, not its price. It now returns the first part with a
872
+ marker naming the offset of the next, takes `offset` to continue and `find` to
873
+ jump to the passages containing a word, says so when a word is not on the
874
+ page, and flags a page with almost no static text as rendered by JavaScript.
875
+ `Length:` now reports the whole page rather than the excerpt.
876
+ - **Long desktop tasks finish with their deliverables instead of a bare "I
877
+ can't confirm this is done".** Picking a controller from nine datasheets and
878
+ pricing a 40-unit BOM ran out of its 50 steps while still searching for
879
+ prices, and the reply dropped the recommendation the agent had already
880
+ written. The agent's default step limit is now **150** (a `/query`
881
+ `max_steps` or `GAIA_AGENT_MAX_STEPS` still wins); at 20, 10 and 5 steps left
882
+ it is told to write the requested files from what it has, marking unverified
883
+ values, and a turn that still runs out keeps its findings and lists what is
884
+ missing after them.
885
+ - **The model notice is one line.** Switching or restoring a model printed a
886
+ four-sentence paragraph that named the model twice and said "via Lemonade".
887
+ It now reads like "Switched to **DeepSeek-V4.1-Flash** on the AMD LLM Gateway
888
+ (cloud). Your messages, and anything read from files or memory, are sent
889
+ there." The `/model` list drops "via Lemonade" from its headings and marks
890
+ the configured default model with `(default)`.
891
+ - **Single-file search results name their file.** `query_specific_file` put the
892
+ path only at the top of its result, so each chunk arrived with no source and
893
+ the chunk cards showed none. Every chunk now carries `source_file`, and the
894
+ result lists it in `source_files`, as `query_documents` already did.
895
+ - **The turn log counts the answer of a streamed turn.** With `GAIA_TURN_LOG`
896
+ set, a turn whose answer streamed out recorded `answer_chars: 0`. It now
897
+ records the length of the answer the user saw.
898
+ - **`run_python` and `execute_python_file` work in the released binary.** The
899
+ binary has no Python interpreter, so it handed every script to its own
900
+ argument parser, which rejected it, and no calculation, chart or `.xlsx`
901
+ could be produced. It now runs scripts itself, with pypdf, pymupdf,
902
+ python-docx, python-pptx, openpyxl, xlsxwriter, reportlab, pandas, numpy,
903
+ matplotlib and the full standard library bundled for them, and both tools
904
+ name those libraries to the model. A script that starts `sys.executable`
905
+ (`-m`, `-c`, a file) runs too; `-m pip` says packages can't be installed
906
+ and lists what is bundled. The Windows binary grows from 147 MB to 168 MB.
907
+ - **A Python script that fails is reported as a failure.** A non-zero exit
908
+ came back as `status: success`, so the TUI showed a failed run as
909
+ successful. It is now `status: error`, with an `error` naming the exit code
910
+ and the last stderr line; `stdout`, `stderr` and `return_code` are unchanged.
911
+ - **`GAIA_ALLOWED_PATHS` confines a run to the folders you name.** The agent
912
+ could read anything under the user's home and nothing narrowed that short of
913
+ embedding it, so an evaluation run could read the graders' answer keys. Set
914
+ to absolute folders, it narrows every file tool, search, index and shell path
915
+ check to them — it never widens, an invalid value stops startup, and code the
916
+ agent runs (`run_python`, shell) is not confined.
917
+ - **The sidecar's start-up warm-up now makes the first question fast.** It
918
+ primed only the agent's own instructions, without the tool list or the rest
919
+ of the system prompt, so the first question re-read all ~19K prompt tokens
920
+ (34 s on Qwen3.6-35B-A3B). It now sends exactly what a turn sends, and the
921
+ first question reads only its own ~50 tokens (5 s). A warm-up that fails is
922
+ logged as a warning with its cause instead of an info line.
923
+ - **`/model` names the command that connects a cloud provider.** With no
924
+ Fireworks or AMD gateway connection, the list told users to "connect this
925
+ provider in the TUI provider settings", a screen with no obvious way in. It
926
+ now says to run `/provider`, the command that opens it.
927
+ - **The TUI's provider picker works after GAIA's Lemonade restarts.** When the
928
+ agent ran as the TUI's own child, its model-state ping kept naming the port
929
+ Lemonade started on, so after a restart the picker said "Lemonade did not
930
+ respond" while chat worked. With a local or cloud chat model the ping now
931
+ reports the port the agent talks to, and it still never starts a stopped
932
+ server. A Claude session still reports the port it started with.
933
+ - **The Agent UI's Skills settings list this agent's skills.** With the agent
934
+ installed from the Hub, the page said the agent package was not installed
935
+ and to run `gaia init`, which changed nothing: the bundled skills live
936
+ inside the binary, where the UI could not read them. `GET /v1/gaia/skills`
937
+ (contract **2.17**) now returns them.
938
+ - **A message sent right after Stop is answered instead of refused.** A stopped
939
+ turn holds its session until its model call returns, so the next `/query`
940
+ got `409 … is already running a turn` for as long as the stopped answer would
941
+ have taken — about 40 s for a long one. It now waits for the stopped turn to
942
+ finish (up to 240 s) and then runs. A turn that was not cancelled is still
943
+ refused at once.
944
+ - **Documents attached to a chat now reach the agent.** In the Agent UI, a
945
+ Hub-installed agent answered "no documents are indexed" about a file the user
946
+ had attached, because the relayed turn never carried the chat's files.
947
+ `/query` now takes a `documents` field (contract **2.16**): the agent indexes
948
+ them before the turn, granting each exact file and not its folder, including
949
+ a file attached partway through a conversation.
950
+ - **The first chat after the agent starts uses its own tools.** A session built
951
+ while the start-up warm-up was still building could end up running the
952
+ warm-up agent's tools, so a file it had just indexed read as access denied.
953
+ Agents are now built one at a time.
954
+ - **Web requests work behind a corporate TLS-inspecting proxy.** HTTPS now
955
+ trusts the operating system's certificate store, as pip does, instead of only
956
+ Python's bundled list, so a proxy root such as Zscaler's no longer fails every
957
+ fetch with `CERTIFICATE_VERIFY_FAILED`.
958
+ - **Starting the agent no longer downloads a model you skipped.** The HTTP
959
+ sidecar's start-up warm-up skips the default local model when it is not
960
+ downloaded, so someone using a cloud model is not handed a multi-GB download
961
+ they never asked for.
962
+
546
963
  ### Notes
547
964
 
548
- - Tracks sidecar contract `apiVersion` **2.14**; a differing major raises
965
+ - Tracks sidecar contract `apiVersion` **2.17**; a differing major raises
549
966
  `VersionMismatchError`.
550
967
  - `GET /v1/gaia/memory` (contract 2.13) answers the same read-only snapshot the
551
968
  stdio transport's `/memory` sentinel produces, so a daemon-supervised
@@ -790,9 +1207,9 @@ the terminal UI meant building it from source.
790
1207
  building its own TUI. Each terminal-hub artifact is additionally cross-checked
791
1208
  against the hub's own server-side SHA-256 before its hash enters the lock.
792
1209
  - Requires Node.js 18+ (built-in `fetch`), a running Lemonade Server for
793
- inference, and the `gaia` Python CLI 0.25.0+ on `PATH` for the daemon the TUI
794
- starts. 0.25.0 is the first core that can run this agent; on an earlier core
795
- the UI starts with nothing behind it.
1210
+ inference, and the `gaia` Python CLI 0.25.2+ on `PATH` for the daemon the TUI
1211
+ starts. 0.25.2 is the first core that can run the current release; on an
1212
+ earlier core the UI starts with nothing behind it.
796
1213
  - The sidecar has no arm64 Linux or arm64 Windows build. On those platforms the
797
1214
  run stops with an error naming the platform and the supported set rather than
798
1215
  launching a UI with no agent behind it.