Commit Graph
245 Commits
Author SHA1 Message Date
Timothy Jaeryang Baek 789a0f402a refac 2026-11-02 11:37:00 +09:00
Timothy Jaeryang Baek 91241306e2 refac 2026-11-01 09:52:12 +09:00
Timothy Jaeryang Baek 9d1b4ef362 refac 2026-10-30 16:01:47 +09:00
Timothy Jaeryang Baek 0e0ba872a4 refac 2026-10-30 07:50:55 +09:00
Timothy Jaeryang Baek f2cdbbebe3 refac 2026-10-29 16:39:42 +09:00
Classic298andGitHub 2c64ab5487 fix: chat stops with no answer when an MCP server request fails mid-chat (#33272)
When an MCP tool server could not be reached for a tool call (server restarted, connection reset by a proxy or load balancer, a request timing out), the whole chat was cancelled as if the user had pressed stop, and the log only said "Task was cancelled!". Now only that tool call fails, the model gets the connection error as the tool result and the reply finishes, and the underlying connection error is logged. The MCP SDK cancels whatever task opened the session when a single request fails, so each MCP session now runs in its own task instead of the chat's.

Fixes #33268
2026-10-28 10:19:33 +09:00
Classic298andGitHub ee7c9ff5c1 fix: tool server tools change their schema on every restart and break prompt caching (#33000)
The required parameters of OpenAPI tool server tools, Open Terminal included, were sent to the model in a random order that could change every time Open WebUI restarted. The tool list sits at the start of every prompt, so a different order made every prefix cache on the model side miss, and long chats were processed again from scratch after a restart. The required parameters now keep the order the tool server declares, so the tool list stays identical across restarts.
2026-10-25 04:46:48 +09:00
G30andGitHub ab6976b5bf fix: when two tools have a function with the same name, the model can call both (#32670) 2026-10-21 02:25:31 +09:00
G30andGitHub fd1e59b25f fix: an array query parameter reaches an OpenAPI tool server as repeated values (#32677) 2026-10-21 02:18:13 +09:00
Classic298andGitHub 51a4d58270 feat: tools come back on their own after all OpenAPI tool servers were unreachable (#32533)
With Redis, if every tool server was unreachable when Open WebUI loaded the tool server list, it cached an empty list and served it forever. The tools stayed missing from chats and the tool list after the servers came back, until a restart, a save in the tool server settings or a manual delete of the cached Redis key. An empty cached list is now only trusted while no OpenAPI tool server is enabled, so the next request that loads tools fetches the servers again, the same way terminal servers already behave. While an enabled server stays unreachable, each such request tries it again and can wait for its timeout.

Fixes #29573
2026-10-16 14:10:33 +04:00
Timothy Jaeryang Baek 97333a4697 refac 2026-10-13 20:04:28 +04:00
Timothy Jaeryang Baek 7840194631 refac 2026-10-13 19:51:58 +04:00
Timothy Jaeryang Baek d34f73066d refac 2026-10-13 19:10:21 +04:00
Timothy Jaeryang Baek 78613d86f7 refac 2026-10-11 15:55:57 +04:00
Timothy Jaeryang Baek c7b5edc726 refac 2026-10-10 23:50:29 +04:00
Timothy Jaeryang Baek d3acc2706d refac 2026-10-10 01:28:36 +04:00
Timothy Jaeryang Baek e6476928ee refac 2026-10-09 18:37:55 +04:00
Timothy Jaeryang Baek 9bbb95048b refac 2026-10-09 15:07:43 +04:00
Timothy Jaeryang Baek a20b622ba8 refac 2026-10-09 00:43:01 +04:00
Timothy Jaeryang Baek 93fc3fcb72 refac 2026-10-08 20:33:47 +04:00
Timothy Jaeryang Baek 55e1c44c94 refac 2026-10-07 17:18:05 +04:00
Timothy Jaeryang Baek d4c561d9f2 refac 2026-10-05 14:01:02 +04:00
Timothy Jaeryang Baek fb741ebcd2 refac 2026-10-05 10:56:06 +04:00
Timothy Jaeryang Baek f50f9e6252 refac 2026-10-01 03:31:20 +04:00
Classic298andGitHub c488f60e8b fix: temporary chats save sub-agent conversations on the server (#31573)
In a temporary chat, when the model handed a task to a sub-agent, the sub-agent's conversation with the task and its answer was saved on the server, although a temporary chat should leave nothing behind. The model is no longer offered sub-agents in temporary chats.

Fixes #31567
2026-09-30 19:05:21 +04:00
G30andGitHub 702da1e471 fix: stop injecting memories and memory tools when memory is switched off (#30228) 2026-09-21 01:00:08 -04:00
Timothy Jaeryang Baek 3cda47cdb4 refac 2026-09-07 12:16:09 -04:00
Classic298andGitHub 1932ca649e fix: stop sending OpenAPI tool server path and query parameters in the request body (#29717)
Tool calls to an OpenAPI tool server put every argument the model returned into the JSON request body, including the parameters that were already substituted into the URL. Servers that validate their input strictly (additionalProperties: false) answered 422 "unexpected property", so reads worked and every write through an endpoint with a path or query parameter failed.

The body is now built from the model's arguments minus the operation's declared parameters, keeping any name the requestBody schema declares as a property of its own, so an endpoint that wants the resource id in the body as well as in the path still gets it.

The filter only runs when the resolved body schema lists its properties. A free-form, composed or non-JSON body offers nothing to check a name against, so those requests go out exactly as before.

src/lib/apis/index.ts carries the same request builder for direct tool server connections and had the same bug, so it gets the same fix.

Fixes #29716
2026-09-06 17:01:26 -04:00
Timothy Jaeryang Baek 2140c189e1 refac 2026-08-31 00:05:34 -04:00
Timothy Jaeryang Baek 81b9afb731 refac 2026-08-31 00:03:51 -04:00
Timothy Jaeryang Baek 26f37426b7 refac 2026-08-30 12:09:34 -04:00
Timothy Jaeryang Baek 5c62cc0517 chore: format 2026-08-25 16:53:53 -04:00
Classic298andGitHub b1bfc18762 perf: cache the serialized builtin tool spec instead of deep-copying it per request (#28860)
Every chat request hands each builtin tool a fresh copy of its cached spec, because callers mutate what they get. That copy was a full deepcopy of a nested dict, repeated per tool per message.

The builder now caches the spec already serialized, so a request only parses it back. Parsing is what produces the independent tree callers mutate, and the cached value becomes an immutable string, so a request can no longer reach the cached object at all.

Measured on CPython 3.12 with a 1.1 KB spec and 20 builtin tools per request:

| | before | after |
|---|---|---|
| stdlib json, the default | 276.2 us | 66.4 us |
| orjson | 279.5 us | 37.5 us |

Builtin specs are plain JSON by construction: pydantic normalizes every default before it reaches the schema, so a tuple, set, enum or datetime cannot appear in one, and an unserializable default is dropped rather than embedded.
2026-08-25 16:00:34 -04:00
Timothy Jaeryang Baek 97466deea1 refac 2026-08-24 18:38:29 -04:00
Timothy Jaeryang Baek 6cb2449ab7 refac 2026-08-24 18:10:08 -04:00
Timothy Jaeryang Baek cf4ac9c8db refac 2026-08-24 18:07:03 -04:00
Timothy Jaeryang Baek fd8cc2ba4a refac 2026-08-24 18:06:59 -04:00
G30andGitHub fd7024f198 fix: log tool server connectivity failures without a traceback (#27757) 2026-08-24 07:35:57 -04:00
Timothy Jaeryang Baek f64c0c87e8 refac 2026-08-23 15:14:43 -04:00
Timothy Jaeryang Baek 78f48a21ee refac 2026-08-23 14:40:48 -04:00
Classic298andGitHub 284da2ae49 perf: reuse the already loaded chat when assembling builtin tools (#28809)
Assembling the builtin tools for a chat message fetched the chat row a second time to answer one question: whether this is a note chat. The caller had loaded that same row a few lines earlier, from the same id in the same metadata dict, and had already evaluated the same predicate for its own note handling. So every message with builtin tools enabled read the whole conversation blob twice.

The caller now works the flag out once and passes it down. Tool assembly no longer touches a chat model at all, so the two files cannot drift apart when the shape of that metadata changes.

Measured with a stub request across five chat shapes, a note chat, a plain chat, an internal chat that is not a note, a chat id with no row behind it, and an unsaved chat id: the returned tool set is identical in every case and the query count drops from six to five. The note tools are still enabled for a note chat with the notes feature switched off, which is the only thing that predicate decides.
2026-08-19 11:06:49 -07:00
Timothy Jaeryang Baek f1a64ccfc2 refac 2026-08-17 00:35:12 -07:00
Classic298andGitHub cd9db21c52 refac: bind tool server cookies per connection (#28630)
The tool callable now takes its connection's cookie jar as a parameter, matching how its headers are already passed and how the terminal tool factory in the same module builds its callables.
2026-08-17 00:25:07 -06:00
Timothy Jaeryang Baek 083e351441 refac 2026-08-13 21:02:17 -06:00
Timothy Jaeryang Baek 4465f52a3e refac 2026-08-13 18:13:43 -06:00
Timothy Jaeryang Baek b606e13da3 refac 2026-08-10 19:44:56 -06:00
Timothy Jaeryang Baek 009999f363 refac 2026-08-08 15:47:10 -06:00
Classic298andGitHub 52cfb02c72 perf: build debug log messages lazily so disabled debug logs cost nothing (#27834)
GLOBAL_LOG_LEVEL defaults to INFO, so every log.debug(...) in the backend is discarded, but the message is built first: 187 call sites interpolate their payload into an f-string before the logging call runs, so the work happens on every request and the result is thrown away. The worst one sits in process_chat_payload and stringifies the whole request body, full conversation history included, once per chat completion.

That one line with DEBUG disabled, CPython 3.12:

| conversation | payload | before   | after   |
| ------------ | ------- | -------- | ------- |
| 4 messages   | 1.2 kB  | 3.4 us   | 0.07 us |
| 20 messages  | 17 kB   | 24.8 us  | 0.07 us |
| 60 messages  | 123 kB  | 216.6 us | 0.07 us |

The lazy form log.debug('form_data: %s', form_data) hands the payload to record.getMessage(), which the InterceptHandler only reaches once a record has passed the level check. With DEBUG enabled the emitted lines are byte-identical, f'{x=}' sites included: those map to %r. MistralLoader._debug_log callers get the same treatment, since that wrapper already forwards *args.
2026-07-31 19:09:01 -05:00
Timothy Jaeryang Baek bb0f898b43 refac 2026-07-31 17:41:14 -04:00
Timothy Jaeryang Baek 7537989235 refac 2026-07-27 03:41:08 -04:00