Repository navigation
ThinkWatch v2.1.0
Images
ghcr.io/thinkwatchproject/think-watch-server:2.1.0ghcr.io/thinkwatchproject/think-watch-web:2.1.0
Helm
helm install think-watch ./think-watch-2.1.0.tgz \
--namespace thinkwatch --create-namespaceAmazon Bedrock becomes a provider you can run from the console. It
authenticates with a Bedrock API key as well as access keys or the
instance role, lists its models for import and for the route editor,
and has a working Test Connection. Requests converted for Bedrock now
keep their prompt-cache breakpoints and Claude's thinking settings. The
route editor takes any upstream model name, and a route the provider
refused can be created anyway. ThinkWatch-Core moves to v0.55.0, whose
Bedrock layer this edition now shares with the desktop gateway. No
database, setting, environment variable or Helm value changes.
Read before upgrading
- Test Connection with a saved provider's secrets needs
providers:update. A test that names a saved provider
(provider_id, which is what the Edit dialog sends) used to take only
providers:create. A custom role that hasproviders:createwithout
providers:updatecan no longer test existing providers; the built-in
admin role has both. A test with values typed into the request still
takesproviders:create. See Security below. - Refusing a route the provider does not serve answers
model_not_served.POST /api/admin/models/{model_id}/routesstill
answers400when the import probe found no API the provider serves
the model on, buterror.typeis nowmodel_not_served, where it was
bad_request. Scripts that matched onbad_requestfor this case need
the new value. The request takes a new optional"force": trueto
create the route anyway. error_typeingateway_logsfor failed requests is always the
error's tag. An upstream HTTP error used to log its debug text, such
asProviderHttpError { status: 502, message: "…" }, and an upstream
rate limit a cut-offUpstreamRateLimited { retry_after_secs: Some.
They now logProviderHttpErrorandUpstreamRateLimited, as the
metric labels and streamed requests already did. Dashboards or log
forwarder queries that grouped by those strings see them merge into
one value each.- The server log now carries the upstream's reply to a 401 or 403,
as it already did for other upstream errors. For Bedrock that reply
names the AWS account and the IAM principal. Callers still see only
"Authentication failed with upstream", and failover, breakers and
gateway_logstreat these errors as before. - Prompt caching now works on Bedrock routes, and is billed at cache
prices. Requests converted for Bedrock used to lose their
cache_controlbreakpoints, so Claude on Bedrock re-read the whole
prompt at full price every turn. Breakpoints now go out as Converse
cachePointblocks, to Claude and Nova models only (others reject
them), and the cache reads and writes Bedrock reports come back into
usage, one-hour writes included. Traffic with repeated prompts, such as
Claude Code, costs much less on Bedrock routes than it did; writes cost
a little more, atcache_write_weight/cache_write_1h_weight. - Claude's thinking reaches Bedrock. A request converted for Claude
on Bedrock now carries its thinking and effort settings, in the form
Anthropic's API uses, along with the sampling limits thinking imposes
(temperature1, notop_k,top_pat least 0.95). Thinking used to
be dropped on the way to Bedrock. Other Bedrock models still get no
thinking.
Added
- Bedrock providers can authenticate with a Bedrock API key. Pick
Bedrock API Key as the authentication mode and paste the key AWS
generated. It is kept like any other provider's API key, as an
encryptedAuthorization: Bearerheader, and replaced in the
provider's Edit dialog. A Bedrock provider that sends an
Authorizationheader is not SigV4-signed; one without it is signed
as before, with access keys or the instance role. Use a long-term key:
a short-term one expires within 12 hours. - Bedrock models can be imported, and are suggested in the route
editor. A Bedrock provider now lists what it can be routed to: the
region's foundation models that can be invoked on demand and answer in
text, and the inference profiles AWS defines, such as
us.anthropic.claude-sonnet-4-5-20250929-v1:0. A model that is only
served through an inference profile, as most current models are, is
listed under its profiles' ids and not its own. Whether the account
may call a model is still checked one model at a time when it is
imported. The provider's credential needs
bedrock:ListFoundationModelsandbedrock:ListInferenceProfiles;
theAmazonBedrockLimitedAccesspolicy a long-term API key is created
with allows both. - Test Connection for Bedrock providers, however they authenticate:
with an API key, access keys or the instance role. It lists the models
above, so a wrong credential or a missing permission shows up before
any traffic does. - Create anyway, for a route the provider refused. When the route
editor's save is refused because the provider does not serve the
model, the error now offers Create anyway: the refusal can be
stale, or be about the probe's request rather than the model. The
route is created, and itsmodel_route.createdaudit row records the
refusal it overrode in a newrefusal_overriddenkey.
Changed
- The route editor's upstream model field takes any model name. For
a provider that lists its models, the field used to turn into a list
to pick from, so a model the listing leaves out could not be routed to
from the console. It now suggests the provider's models as you type,
and takes whatever is typed. - Bedrock instance-role credentials are cached. They took three
IMDSv2 round trips per request; they are now kept until five minutes
before they expire, and a burst of requests at expiry makes one trip. - Chat Completions requests can switch reasoning with
thinking.
When a request is converted for another format,thinking.type
(enabled/disabled, as DeepSeek, GLM and Kimi write it) now turns
reasoning on or off;disabledwins overreasoning_effort. - Core crates at ThinkWatch-Core v0.55.0.
tw-dialect,tw-guard
andtw-breakermove from v0.43.0, andtw-bedrockjoins them:
SigV4 signing, eventstream unframing, Bedrock's addresses, region
checks and model catalog now come from core. Where credentials come
from (provider keys, the instance role) stays in this repository.
tw-breakeris unchanged.
Fixed
- Bedrock providers could not be created or edited in the console.
The region was checked as a URL, so saving failed with
400 Invalid URL. A Bedrock provider'sbase_urlis now checked as an
AWS region such asus-east-1, and anything else is refused, since the
host is built from it. A provider saved with a URL there never reached
Bedrock; set its region in the Edit dialog. - Bedrock models the account may not call were imported anyway.
Bedrock refuses such a model (model access not granted, or an IAM or
organization policy that denies it) with a 403, and the import probe
read every 403 as a credential problem that says nothing about the
model. The route was created and failed on first use. Now, when the
region's control plane accepts the same credential, the refusal is
recorded as the model's, with AWS's reason, and the model is skipped
on import like any other refused one. Once access is granted,
re-check the provider's models. - A Bedrock provider whose stored secret key would not decrypt signed
with an empty secret, and every request failed with AWS's
SignatureDoesNotMatch. It now refuses its requests with the reason
until the keys are saved again, rather than falling back to the
instance role, which would call AWS as a different identity. An
access key ID saved without a secret is refused the same way. - A Bedrock model id that is an ARN could not be routed. Its
/
went into the request path unescaped, adding a path segment AWS could
not route. It is now escaped. - A base URL ending in its version segment doubled it. A provider
written ashttps://api.openai.com/v1sent requests, and the model
listing, to/v1/v1/…and got 404s. A trailing version segment
(v1,v1beta, …) that the request path starts with is now written
once. Base URLs without one are unchanged. - Typing into a provider's API key field and clearing it again wiped
the saved key on save. The field sentBearerwith nothing after
it. A cleared field now keeps the saved key, as a blank one always did.
Security
- Testing a connection with a saved provider's secrets takes
providers:update. The test fills each header left blank with the
saved provider's secret and sends it to the URL in the request, and
providers:createwas enough to ask for it. So a user allowed only to
create providers could send any saved API key to a server of their
own. A test that names a saved provider (provider_id) now takes
providers:update, which lets a user point that provider elsewhere
anyway; a test without one still takesproviders:create. A user with
providers:updatealone can now use Test Connection in the Edit
dialog, which used to answer403.