changelog
4.2.0 2026-09-21
Everything in it is on the gateway side; the extension only learns to send the open workspace's name (for routing rules) and to search the shared context index.
Plugins
Plugins are features the gateway ships with but that stay off until an admin switches them on from Plugins → Store on the admin page. Each has its own routes, files and page. They are a licence feature: without one the store lists them but none can be switched on, and plugins that were on stop when a licence lapses and start again when one is installed.
- GitHub and GitLab pull requests. Watch repositories with a token or a GitHub App and the admin page lists every open pull request across them: checks, merge state, review state, drafts. Open one to read the description and highlighted diffs. Review now sends it to one of the gateway's own chat aliases and keeps the review on the server; auto-review does it in the background for new and updated pulls while no developer request is running.
- Gitea, Forgejo, Codeberg and Bitbucket Cloud on the same pull-request core.
- Reviews posted back to the host as a comment, a change request or an approval, with a footer naming the model; auto-post per repository. A review in progress shows as a status row.
- Issue triage. Open issues are listed beside pulls; a model suggests labels, a duplicate, a priority and a first reply, kept on the server until someone posts the reply or applies the labels. Auto-triage suggests while the models are idle.
- Pull-request pages have one listing toolbar on every forge: one-click views with live counts, selects for repository, author, label, target branch and activity, a search, order by, sortable headers, all remembered per host. Each pull carries its approvals as the host reports them, and the page tags each pull with the operator's part in it ("waiting for me"). Drafts stay out of the list until a toggle brings them in.
- Reasoning models are asked not to think when reviewing (
think: falseon Ollama); reasoning deltas and inline<think>blocks are recognised, and a thinking-only answer fails with the reason. - Slack, Discord and Microsoft Teams post chosen events to webhooks (Mattermost and Rocket.Chat take the Slack shape): a review finished or asked for changes, a pull opened, checks failed, a backup made or failed, a backend down or back. A test button and a delivery log per webhook; URLs are kept secret. Plugins share one event bus.
- SSO sign-in (OIDC). Developers sign in with Okta, Entra ID, Google Workspace, Keycloak or any OpenID Connect provider: PKCE, nonce, RS256 id_token verified against the provider's keys, a domain allow-list, admin emails, and a key minted through a replacing invite that opens VS Code. Signing in again replaces the key, so it doubles as lost-key recovery.
- Shared context. Repositories are cloned shallow onto the gateway, chunked, embedded with an embeddings alias it serves, and re-indexed on a schedule while the models are idle, embedding only what changed. Connected extensions search it with their key and merge the hits into the relevant code their chat already gathers.
- Backups. A nightly copy of configuration, keys, licence, invites, plugins and usage (recordings on request) to a directory or an S3-compatible bucket, optionally encrypted, with retention and a CLI restore (
twinny-server backup restore). - Plugin logos on the store, navigation and pages; skeleton loaders while a page loads; themed scrollbars on panels and code blocks.
Gateway operations
- Audit log. Every admin change (keys, invites, sign-ins, configuration, licence, plugins on or off, plugin writes) goes to
audit/YYYY-MM.jsonl, each line carrying the hash of the line before it. Team → Audit log shows whether the chain is intact, filters by period, actor and kind, and exports. - Read-only admins.
keys create <name> --admin --read-only(or the box on People) opens the admin page and everyGETadmin route and refuses anything that changes state. - Prometheus metrics at
GET /metricsfor admin keys: requests by route, alias and outcome, a latency histogram, tokens, in-flight and queued requests, backend health, refused authentications, seats, plugin events. - Costs. Give an alias a price per million input and output tokens and a currency, and Usage and Overview show what each developer, model and period cost.
- Bounded request queue. A chat or autocomplete request that finds every slot taken waits, oldest first, for up to
limits.queue.fimWaitMsorchatWaitMsbefore it is refused; at mostlimits.queue.maxWaitingmay wait. A client that goes away while waiting is dropped asrequest.abandoned. Refusal logs say whether the gateway, the queue or the key's own limit refused;twinny_queued_requestsis exported. - Data-directory format marker.
format.jsonnames the layout; migrations run in order at start, a newer format than the build knows exits with code 6, and a directory with files but no marker is taken as format 1. Backups carry the marker along. - Routing rules in team policy keep a workspace on local backends or on named aliases, matched on the workspace name the extension now sends. Team system prompt in policy is put before every chat's system prompt on connected extensions and shown on the consent card.
- Helm chart under
deploy/helm/twinny-server: one pod, one volume, an optional Ingress with TLS, a ServiceMonitor for/metrics. - The admin shell widens to 1480px and folds the sidebar into tabs below 960px.