Skip to content

Tags: chrstphe/GoModel

Tags

v0.1.62

Toggle v0.1.62's commit message
fix(anthropic): use adaptive thinking for Claude 5 models

claude-opus-5 and claude-sonnet-5 were missing from adaptiveThinkingPrefixes,
so reasoning requests were translated to manual thinking with budget_tokens
and Anthropic rejected them with '"thinking.type.enabled" is not supported for
this model. Use "thinking.type.adaptive" and "output_config.effort"'.

Both dialects were affected: reasoning_effort on /v1/chat/completions and
thinking on /v1/messages converge on applyReasoning. Verified against the live
API for both models, streaming and non-streaming. Haiku 4.5 predates adaptive
thinking and stays on manual budgets.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

v0.1.61

Toggle v0.1.61's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
test(e2e): cover label-scoped budgets in the release curl matrix (ENT…

…ERPILOT#597)

* test(e2e): cover label-scoped budgets in the release curl matrix

Adds S197-S204 for budgets scoped to a request label rather than a
user_path subtree: admin CRUD and validation negatives, tagging-header
enforcement with verbatim case-sensitive matching, multi-label charging,
managed-key label charging, a request matched by both a user_path and a
label budget, reset-one, PostgreSQL/MongoDB parity, and auth gating.

S200 runs on the auth-enabled gateway rather than the main SQLite one:
creating a managed key on a gateway with no GOMODEL_MASTER_KEY switches
every endpoint to require bearer auth, and managed keys have no delete
endpoint, so registering one there would lock the gateway down for every
later scenario.

Two scenarios promised more than they checked, so the assertions were
brought up to the prose: S199 now checks the block names the exhausted
label and *not* the healthy one, and S201 checks the user-path budget
that matched the same request was charged and still has room — which is
what makes it evidence that the label budget alone caused the block.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(e2e): make label budget scenarios survive a failed run

Review follow-ups.

Budget spend is a SUM over usage rows, so deleting and recreating a
budget does not forget what an earlier run charged against the same
label. A scenario that exits part-way on a failed assertion skips its own
cleanup, and the same-suffix rerun this file recommends for partial
reruns would then meet an already-exhausted tiny budget and 429 on its
first request — failing for a reason unrelated to what it tests, until
someone cleared the state by hand.

reset_release_budget resets a budget right after creation, so that first
request behaves the same on the first run and the fifth. Confirmed by
leaving an exhausted budget behind and rerunning S198 with the same
suffix: exit 1 without the reset, exit 0 with it, same leftover state
both times.

The section preamble also claimed every scenario used tagging headers.
S197 and S204 are admin-only and send no model traffic, and S200 relies
on managed-key labels precisely because no tagging rule is configured, so
it now says which scenarios do what.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

v0.1.60

Toggle v0.1.60's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(budgets): scope budgets to request labels (ENTERPILOT#590)

* feat(budgets): scope budgets to request labels

Budgets could only limit a `user_path` subtree, so an operator running
several applications through one path had no way to cap their spend
separately without minting a key per application (issue ENTERPILOT#319).

A budget now carries a scope and a subject, mirroring the shape rate limit
rules already use:

- `user_path` — a path and its descendants, unchanged
- `label` — every request carrying that label, matched verbatim

Labels come from the tagging headers and from the managed key that
authenticated the request, so a request carrying several labels is charged
against every matching label budget. Label budgets are declared under
`budgets.labels:` in config.yaml or through the dashboard and admin API;
they have no env-var form, because labels are matched verbatim and are not
env-name safe (the same rationale model rate limit rules already use).

Enforcement no longer runs one SUM query per matching budget. `Store.SumSpend`
takes every matching window and answers them in one scan — conditional
aggregation on SQL, one `$group` on MongoDB. Timed against a 50k-row usage
table: parity at one matching budget (~30ms), 96ms -> 35ms at five, 443ms ->
70ms at twenty-five.

The budgets table is rekeyed to (scope, subject, period_seconds), so both SQL
backends rebuild it in one transaction and MongoDB rewrites its documents in
place. The rebuild also absorbs the two columns older releases added with
ALTER TABLE, which removes the separate migration list.

Also folds three near-identical evaluation loops in the budget service into
one match/evaluate pair, moves the SQL-only path helpers out of the shared
store file, and corrects the admin API examples in the budgets docs, which
showed URL path parameters those endpoints never had.

Part of ENTERPILOT#319 — this covers the budgeting integration the issue asked for.
Label filtering and grouping in the audit log remain open.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(budgets): drop the legacy MongoDB index before rewriting documents

The scope migration unset `user_path` while the pre-scope unique index on
(user_path, period_seconds) was still in place. A missing field indexes as
null, so every migrated document sharing a period collapsed onto the key
{user_path: null, period_seconds: N} and the rewrite failed with a duplicate
key error — aborting startup for any MongoDB deployment holding two budgets
with the same period, which is the ordinary case rather than an edge one.

`internal/ratelimit` has carried the same ordering since rule scopes shipped,
so it is fixed alongside. Both now drop the legacy index first, and both gain
a mongotest case that seeds two pre-scope documents sharing a period and
asserts they survive the upgrade.

Also asserts at the server layer that request labels reach the budget checker
with the user path, which is what lets a label budget match at all.

Reported by Greptile and CodeRabbit on ENTERPILOT#590.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(budgets): cover the PostgreSQL label predicate in SumSpend

The label branch of SumSpend is the one part written twice — json_each on
SQLite, jsonb_exists on PostgreSQL — and only the SQLite half was tested,
because the test opened a raw SQLite database to get a usage store. A mistake
in the PostgreSQL predicate would have silently matched nothing, so label
budgets would never enforce there and no test would notice.

The case now runs on both backends. Verified it catches a broken predicate by
corrupting the bound subject and watching the PostgreSQL subtest fail.

`usage` has not moved onto sqlx, so its PostgreSQL store still takes a
*pgxpool.Pool directly; sqlxtest grows an exported NewPostgresPool so a test
spanning both can point them at one throwaway schema. Entry ids become fixed
UUIDs derived from their readable names, since PostgreSQL types usage.id as a
UUID.

Reported by CodeRabbit on ENTERPILOT#590.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refactor(dashboard): show a budget's scope on the subject itself

The budget list carried the scope twice: a "(tag) label" pill sat next to the
period, while the subject rendered in .budget-user-path regardless of what it
actually was. The pill said nothing the subject could not say itself, and the
class name was wrong for half the rows.

The tag icon now prefixes the label name inside the subject, and the shared
styling moves to .budget-scope-value with .budget-user-path and .budget-label
as hue-only modifiers. A label takes the same per-label colour the usage log,
breakdown chart, and API keys already use, so one label reads the same
everywhere. The rate limit list and inspector pick up the shared base class.

Also rounds the provider status toggle to 6px, matching .btn and
.table-action-btn rather than the full pill it was; the switch track and thumb
stay round. And the budget filter placeholder now mentions labels, which it can
now match on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

v0.1.59

Toggle v0.1.59's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(admin): restrict dashboard and admin API to selected API keys (E…

…NTERPILOT#584)

* feat(admin): restrict dashboard and admin API to selected API keys

Managed API keys now carry a dashboard_access flag (default: false).
Only the master key and flagged keys can call /admin/*; other managed
keys get 403 dashboard_access_denied. Model endpoints and GET /v1/usage
stay open to every key, and the no-master-key lockout-recovery path is
unchanged.

- authkeys: DashboardAccess on AuthKey/CreateInput/AuthenticationResult,
  store migrations (sqlite/postgres/mongo) + UpdateDashboardAccess
- admin API: dashboard_access on POST /admin/auth-keys, new
  PUT /admin/auth-keys/{id}/dashboard-access
- server: AdminAccessMiddleware gates /admin and the legacy alias
- dashboard: create-form checkbox, table column with helper text,
  grant/revoke row action, auth dialog reopens with a specific message
  when a key without access is used

Closes ENTERPILOT#583

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(admin): address review findings on dashboard access gate

- PUT /admin/auth-keys/{id}/dashboard-access rejects omitted/null
  dashboard_access with 400 instead of silently revoking
- disable all dashboard-access toggles while one update is in flight
- gate tests: table-driven allowed-credential matrix covering the
  legacy /admin/api/v1 alias
- sqlite test helper asserts List returns exactly the expected keys
- CLAUDE.md: scope the gate claim to admin REST endpoints; note the
  dashboard shell/static assets skip auth

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(authkeys): reject duplicate IDs in sqlite dashboard-access assert

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

v0.1.58

Toggle v0.1.58's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(conversations): complete OpenAI-compatible lifecycle (ENTERPILOT…

…#576)

* feat(conversations): complete OpenAI-compatible lifecycle

* fix(conversations): address persistence review findings

* fix(conversations): guard fragmented stream completion

* fix(conversations): preserve streamed output JSON

v0.1.57

Toggle v0.1.57's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
docs: Add Contributor Covenant Code of Conduct

This document outlines the Contributor Covenant Code of Conduct, detailing the pledge, standards, enforcement responsibilities, and consequences for violations.

v0.1.56

Toggle v0.1.56's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(marketing): track first-party referrals (ENTERPILOT#570)

* feat(marketing): track first-party referrals

* docs(readme): track documentation referrals

v0.1.55

Toggle v0.1.55's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(demo): add environment-controlled demo mode (ENTERPILOT#559)

* feat(demo): add environment-controlled demo mode

* fix(dashboard): prevent search engine indexing

* fix(demo): correct environment variable name

* fix(demo): update runtime config test

v0.1.54

Toggle v0.1.54's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore(demo): expand synthetic dashboard data (ENTERPILOT#557)

* chore(demo): expand synthetic dashboard data

* chore(demo): seed routing config and playable audio

v0.1.53

Toggle v0.1.53's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(mcp): publish server.json to the official MCP registry on release (

ENTERPILOT#545)

* feat(mcp): publish server.json to the official MCP registry on release

Lists GoModel in registry.modelcontextprotocol.io as
io.github.enterpilot/gomodel — an OCI package (docker.io/enterpilot/gomodel)
with streamable HTTP transport at /mcp. The Dockerfile LABEL is the
registry ownership proof and must match the server.json name. A new
release job authenticates via GitHub OIDC (no secrets) after
docker-promote, stamps the tag version into server.json, and publishes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(ci): harden the MCP registry publish job

continue-on-error so a registry outage cannot fail the release,
persist-credentials off (the job runs a third-party binary),
and mcp-publisher pinned to v1.8.0 with checksum verification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>