- A redirect followed for a custom base URL (quota on) no longer carries
the user's key or cookies to another origin, as fetch itself does, and
a private address may redirect to another private one (already counted).
- The admin Test of an Ollama or Vertex AI entry without a URL goes where
chat sends that entry's key: the environment's own URL variable, for
Ollama else the local default. The Test of an Ollama Cloud key without
a URL went to the cloud while chat went to local Ollama.
- Chat saves: each save notes the chat on screen and the order of the
reads before reading its data. A save read before switching chats no
longer writes into the chat switched to, and a copy that waited for its
thumbnail no longer replaces a newer one.
- "Continue without saving" keeps its button when a later auto-save fails,
and goes away when a new message is sent.
- A screenshot check that was waiting for its image when the user pressed
Stop stays skipped after the next message.
- MCP History: draw.io's own copy of a diagram (after get_diagram) no
longer adds an entry without a picture; a change of background is still
its own version. The tab ignores an edit's answer that arrives after a
newer AI write loaded.
- Desktop: a deleted preset is not brought back by a failed switch, and a
request naming no preset does not stop a rollback. An origin keeping
an access code counts as having settings.
- .env: a quoted value ending in a backslash ("C:\dir\") is read as dotenv
reads it.
- The tool card no longer crashes on an id that does not turn into text;
an older Test's success timer no longer ends a newer Test's spinner.
- Tests that passed without their fix now check it.
Chats:
- New Chat right after an answer saves that chat once. Saves run one at
a time and read the chat on screen when their turn comes; a save
scheduled for a chat that is no longer on screen is dropped. A chat
whose id was still on its way to the URL no longer comes back after
New Chat (the next answer went into it).
- Crossing the 768 px breakpoint keeps the chat panel: a streaming answer,
unsaved messages and attachments stay. The panel gets the sizes of each
side, and a panel collapsed on desktop opens on mobile.
- The chat's export waits for its own reply: an edit's history export
still on its way no longer answers it with the older diagram, and two
file saves at once no longer swap results.
- A second edit in one answer is previewed on the first edit's result.
- Stop also ends a running screenshot check; a chat that cannot be saved
(storage full) can be left with "Continue without saving".
- Small diagrams with shapes count as diagrams; the tool card no longer
crashes on malformed operations.
Quota and providers:
- Requests that reach the server's own endpoints count toward the quota:
EdgeOne (always its own endpoint now), a private base URL whatever key
header is sent, keyless Ollama without a URL. With the quota on, a
redirect is followed only to a public address. The output cap applies
to these requests too.
- Stop records the tokens of the steps that finished; the screenshot check
counts its tokens without counting a request.
- EdgeOne configured only by AI_PROVIDER works, also in the admin Test,
which forwards the access code. Azure set up only in the admin panel
works in chat. The Test sends a Bedrock session token.
- The admin panel's Test of an entry without a URL uses the server's URL
as the server does (no private address check for it); the admin panel
no longer writes an Ollama URL.
MCP server:
- Write tools and start_session run one at a time, so two at once never
drop each other's change; a cancelled call waiting its turn is skipped.
get_diagram and export_diagram keep the session they started with.
- Export to .drawio first gets the user's latest edits from the browser.
- History thumbnails: one that arrives after the next AI write is
dropped; a sync reply keeps the image; a version that changed only page
settings is its own entry.
- A diagram over the 10 MB limit is saved without its image, or the user
is told to download it (the server now answers 413 instead of cutting
the connection).
- Labels holding text like id='1' or parent='1' are no longer read as
attributes (a layer or a parent was deleted). A broken bare
<mxGraphModel> file is refused.
- After a sync reply the tab no longer sends its autosave copy again.
Desktop and files:
- A newer switch of the same preset is not rolled back by an older one
that failed. .env values with escaped quotes are read whole.
- MCP saved files: a file that could not be read stays protected while a
folder without permission hides it, and is saved again once deleted.
- The desktop app reports "no chats" only when the count was read and no
model settings are stored.
- Bedrock: a request's AWS region must be a region name. It becomes part
of the endpoint's host name, so a value such as
"us-east-1.attacker.example/" sent the server's bearer token or signed
request to another host.
- MCP preview server: only the preview page itself (Origin equal to the
Host) or a non-browser client may call it; a page on another localhost
port could replace the diagram with a plain text POST. History builds
its thumbnails element by element and shows only SVG data images, so a
stored value can no longer run script in the preview.
- chat, validate-model, validate-diagram, provider-models and parse-url
take JSON bodies only, so another website cannot make the user's own
server (the desktop app, a local install) run models with their keys;
the desktop app also refuses a foreign Host (DNS rebinding).
- The model list reads at most 2 MB, also through the Gateway SDK, and
answers only with its own error texts: the URL is the caller's and may
be an internal address.
- An admin panel provider with its own key and no URL no longer inherits
the global <P>_BASE_URL, which may be a proxy for another key; OpenAI
then gets the official endpoint, as its Test. Azure keeps the server's
resource.
- Bedrock: a user's AWS keys no longer go to an endpoint the server sets
in AWS_ENDPOINT_URL_BEDROCK_RUNTIME / AWS_ENDPOINT_URL (read by the
upgraded SDK), and admin panel keys win over AWS_BEARER_TOKEN_BEDROCK,
as the Test button checks them. Checked with Bedrock.
- Ollama: a server key without a base URL (admin panel, OLLAMA_API_KEY)
goes to Ollama Cloud, as env.example says, instead of 127.0.0.1.
- Quota: EdgeOne counts whatever key header comes along, keyless Ollama at
a private address counts, and their provider texts stay in the log.
- An EdgeOne server model (admin panel, ai-models.json) works: the route
checked the raw provider header, which holds the name's slug.
- parse-url ends downloads it does not read (too large, PDF, errors).
- Desktop app: the port follows where the chats are (IndexedDB per
origin) instead of a remembered port, which could hide them for good;
a same-port restart tells the page to refetch the server models; a
failed preset switch no longer undoes a newer choice; a presets file
removed after a failed read can be saved again; .env values quoted from
start to end keep their inner quotes, as dotenv reads them.
Found by the second PR review:
- With AWS_BEARER_TOKEN_BEDROCK set on the server, a request with the
user's AWS keys ran on the server's token: the Bedrock SDK prefers it.
Checked with Bedrock: invalid user keys used to get an answer.
- An OpenAI key with the official URL filled in (the settings form does
that) went to the Responses API. Back to main's rule: a configured base
URL uses Chat Completions.
- A user's Ollama key went to the server's OLLAMA_BASE_URL, for chat and
for the model list. Like every other provider, it goes to the user's
base URL or Ollama Cloud.
- The server's keyless Ollama and EdgeOne were not counted in the quota.
- AI_MODEL models on the server's keys ran on any provider with a server
key, not only on AI_PROVIDER.
- A user's Azure key without a base URL used the server's resource name.
- The admin panel's Test button failed whenever access codes were set.
- DeepSeek's errors in the stream (plain text) were shown as they were,
without a hint and also on the server's keys. Bedrock's throttling in
the stream was not recognised as a rate limit.
- The EdgeOne function accepted text/plain; x=application/json, which
other sites can send without a CORS preflight.
- Desktop app: a launch that found the old port taken for a moment (the
previous version still quitting after an update) remembered the new
port for good. The new port is kept only when Windows reserves the old
one. A failed read of the presets file moved it aside as corrupt, and a
save could then replace the presets. Switching presets on the same port
now reloads the page. The dev launcher no longer misses a preset change
made before or during a restart.
Found by the PR review, each with a test that failed first:
- Quota: any key header skipped it, even one the provider never reads
(x-aws-access-key-id with OpenAI), so a request ran on the server's
key without being counted. The check now runs after the model is
resolved and uses usesServerCredentials. On main already.
- usesServerCredentials read the raw base URL; "/" cleans up to none, so
an Ollama request ran on the server's key past the server-model check.
- SGLang's default 127.0.0.1:8000 only fills the settings form. Chat and
the model list used it as a real address, so the server called its own
machine even with private URLs blocked. Now a base URL is required.
- With a user's OpenAI key and no base URL, the SDK read the server's
OPENAI_BASE_URL. The official endpoint is now passed. On main already.
- The Test button refused nothing on the server's keys (Ollama Cloud),
and a 15 s timeout reported "connected, no tool call".
- The model list for Ollama without a base URL came from ollama.com while
chat went to the server's Ollama.
- Bedrock's "Too many tokens, please wait" counted as context too long.
- On the server's keys the provider's error text stays in the server log;
it can name the server's AWS account, role or internal hosts.
- Desktop app: the preset keys are the user's own (NEXT_AI_DRAWIO_DESKTOP),
so Max Output Tokens can be raised and keyless models in settings work
again. A launch that found the remembered port taken no longer replaces
it, which hid the user's chats and settings for good.