Skip to content

Releases: siebe41/SemanticRouter.NET

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 18:09
18f2ff5

Added

  • GET api/setup for the dashboard's first-run setup: whether a model is still needed, what semantic-router init would find on this machine (LM Studio, Ollama, and the claude, codex and copilot CLIs with whether they are signed in) and one-click provider presets (LM Studio, Ollama, OpenAI, Anthropic, OpenRouter, Google Gemini, Claude Code, Codex, GitHub Copilot). It only describes; nothing is enabled until the dashboard applies it. The machine policy, offline mode and the allowed endpoints leave out what they turn off (offline, no CLI is started to ask). Like a change, it is refused from other sites, so a page elsewhere cannot set off the CLI checks; ?refresh=true reuses a look younger than 10 seconds, and a detection that fails still answers with the presets and the problem in detectionProblem.
  • POST api/connectors/discover discovers the models of a connector that is only in the dashboard's draft, held to the same checks as applying it (policy, what a CLI may run, where a stored secret may go). The audit log records where it asked (scheme://host:port, or a CLI's program).
  • POST api/config/save and POST api/config/revert, and unsaved in GET api/status: a configuration applied without saving can be kept or undone, and the dashboard can say it is not saved.
  • PUT api/config?baseVersion=N&instance=X refuses a change made against a version that is no longer running (409 with who changed it, when and how), so two editors cannot silently undo each other. instance, a random id for this run of the router, is in every configuration envelope and GET api/status: version numbers start again at 1 on every start.
  • Validation errors from PUT api/config and POST api/config/validate come with issues that name the field (Routes.1.Name, Connectors.local.Timeout), and a value that does not fit its field says the format it needs ("5m" is not a duration; use hh:mm:ss, e.g. 00:05:00) instead of "Expected a configuration document".
  • The semantic-router tool and the desktop app redirect / to the dashboard (MapRouterDashboardRedirect; an application's own / endpoint wins).
  • The start-up banner has a Try it block: a request to send (curl, or Invoke-RestMethod on Windows), where to watch it on the dashboard (#/live), and the Claude Code command as one line with its variables inline, as in the client guide. While no model is enabled it says so instead, with the link to the setup on the dashboard's Overview.
  • The container seeds a connector for OPENAI_API_KEY and ANTHROPIC_API_KEY on the start that creates the configuration file (deleting one sticks); the connector refers to the key as ${env:…}, so the key never lands in the file (SEMANTIC_ROUTER_SEED_API_KEYS, on in the image).
  • doctor checks the Codex CLI's sign-in with codex login status.
  • Desktop app: on the first start the dashboard opens on its Overview, where the setup is, and the welcome window says so. While the router has no enabled model, the tray menu says so and offers the setup, with one notification.
  • README: a Quick start right under the introduction (who it is for, what to install, the commands, the desktop app, where to go next).
  • Dashboard: Running configuration not saved in the top bar when the router runs a configuration that was applied without saving, with Save and Revert to saved for the admin (the More panel shows the source as "not saved").
  • Dashboard: the save bar counts the draft's changes, and Review shows them next to the running configuration.
  • Dashboard: Apply names the version the draft started from; when someone else applied a configuration meanwhile, a notice says who and when and offers Reload, Compare or Apply mine anyway. The refresh notices such a change too (a router restart included): it reloads a draft without changes quietly, and moves unapplied edits onto the new configuration when they touch other settings. Moving them is strict: a new order of model aliases, routes or models, or a list such as CLI arguments changed on both sides, is a conflict; only lists that are sets (utterances, capabilities and similar) combine.
  • Dashboard: removing a route, model, connector, profile, tier, budget or memory source offers Undo; removing a connector that models use, or a profile that rules, virtual models, client mappings or budgets name, asks whether to remove those too.
  • Dashboard: problems from Validate and Apply are shown next to their fields (the item opens, the first gets the focus), and the problem list links each one to its field on its page.
  • Dashboard: model aliases can be reordered (the first matching glob wins).
  • Dashboard: new Activity entries that arrive while the table holds still (auto-refresh off, a label being written, text selected) are counted, with Show.
  • Dashboard: Set up SemanticRouter on the Overview while no model is enabled: add a connector (tools found on this machine first, then presets for LM Studio, Ollama, OpenAI, Anthropic, OpenRouter, Gemini and the CLIs), add models (Discover models, Apply & save), send a test prompt. Read-only users see that an admin needs to add a model.
  • Dashboard: Add connector is a menu of presets and a blank connector, also shown on an empty Connectors page.
  • Dashboard: Activity has a search box, and a click (or Enter) on a row opens the whole decision.
  • Dashboard: Router learned has a small Settings form for the common Tuning options.
  • Dashboard: Routes can be set to follow the conversation (FollowsConversation).

Changed

  • Dashboard: the 19-link sidebar, which no longer fit a laptop screen or the desktop app's default window, is a narrow rail of five sections (Monitor, Routing, Providers, Gateway, Admin) with each section's pages as tabs under the top bar. Routing rules is the Rules tab and the gateway page the Settings tab. Report an issue (the Feedback page) sits at the foot of the rail, and the version, theme picker and Sign out moved under More. Every page keeps its address, so existing links and bookmarks still work.
  • A request no model can serve because of the configuration (no model enabled, or none with the tier, capabilities, locality or profile it needs) gets 400 invalid_request_error in the client's protocol instead of 503, so the SDKs and Claude Code stop retrying, with what to do and where: "SemanticRouter has no model that can answer this (no model is enabled). Add one on the dashboard: http://localhost:5080/router#/overview". Failed or cooling-down models still give a retryable 503, as do a prompt that could not be classified (the embeddings did not answer) and a request only models outside their active hours would fit ("no model is in its active hours right now").
  • The "no model is enabled" warning and service note point to the dashboard's setup on Overview instead of the Models page or semantic-router init.
  • init replaces a configuration that still holds the built-in template (as the router writes it on its first start) without --force; a file whose embeddings someone chose is not the template.
  • init output: a one-line tier legend, no similarity-threshold note, the Claude Code command on one line (no export) and only when a model is enabled; with none, the dashboard's setup. When a subscription CLI is all it found, the question says that without it the router has no model to use.
  • doctor: no enabled model is a [FAIL] (exit code 1), whose fix is a step that helps (the dashboard's setup, or init while the configuration is still the template). Fix lines name the dashboard field beside the setting, e.g. Providers → Connectors → openai → API key.
  • An unreachable LM Studio or Ollama says how to start it (Developer → Start server, ollama serve); other servers name the address setting and where it is on the dashboard.
  • A failed ONNX model download names huggingface.co, HTTPS_PROXY and Network:CaBundle, and where to copy the file instead, and is logged without a stack trace.
  • A quieter console: ASP.NET Core's lines per request and the hosting start-up notes from Warning, data protection from Error (the router's own key-ring line covers it); the router keeps its one line per request. Logging:LogLevel turns any of it back up.
  • The key-ring warning (unencrypted keys, macOS and Linux) appears only once the secrets file holds a key.
  • An address that is in use is explained without a stack trace; when this configuration's own router holds that address, the message says so with its dashboard address.
  • Links in the tool's output, the help text and the desktop app point to the documentation site instead of files in the repository.
  • deploy/compose.yaml runs the published image ghcr.io/siebe41/semantic-router:<version>; building from the checkout is a commented-out alternative.
  • The site's Get started (home page and top bar) goes to the README's Quick start; its Try it names the .NET 10 SDK and the Claude Code line.
  • Dashboard: Apply & save is the primary action; Apply is now Apply only ("a restart undoes it").
  • Dashboard: Discard, Use defaults (tiers, complexity rules), revert, reset, rollback and the other confirmations ask in the page instead of the browser's dialog; Discard says how many changes go and offers Undo.
  • Dashboard: the top bar's health dot shows the router's overall state (red when failing or no model is enabled, amber when degraded or warming up), with a label, and a short word next to it on a phone.
  • Dashboard: messages stack instead of replacing one another, are spoken once (errors as alerts, prefixed so), and "Not applied" stays until it is closed; the top bar and banner are rewritten only when they change.
  • Dashboard: a button is marked busy while its action runs and cannot be sent twice.
  • Dashboard: the read-only role sees forms as read-only (no add or remove buttons, no Send in the prompt tester), and is not asked before leaving.
    -...
Read more

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 14:05
3916ea2

Added

  • Desktop app: an Updates section in About SemanticRouter, and Check for updates now… in the tray menu. It shows whether the app is up to date and when it last checked, an update that is downloading, ready or available, and why a check failed or updates are off. It has Check now, Restart to update and the two update switches.

What's Changed

  • Release signing check: accept ALLOW_UNSIGNED_RELEASE with stray spaces or capitals by @siebe41 in #167
  • Documentation site on GitHub Pages, with a home for the demo videos by @siebe41 in #168
  • Changelog: the Unreleased changes shipped as 0.3.0 by @siebe41 in #169
  • Bump mermaid from 11.17.2 to 12.1.0 in /site in the site group by @dependabot[bot] in #170
  • Add a kit that records a marketing demo video of the router by @siebe41 in #166
  • Desktop app: an Updates section in the About window by @siebe41 in #171

Full Changelog: v0.3.0...v0.4.0

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 01:39
d237a64

Security

  • Machine-wide policy that the user's configuration cannot override, read from HKLM\Software\Policies\SemanticRouter, macOS managed preferences or /etc/semantic-router/policy.json: turn off connector types and CLI presets, limit endpoints and the hosts that count as local, require local-only, cap prompt storage and retention, make the dashboard read-only or turn it off, control desktop updates and turn features off. A policy that cannot be read stops the router. See docs/enterprise.md. (#142)
  • init does not add, or ask about, CLIs that the machine policy turns off. (#146)
  • Offline mode (Network:Offline with Network:AllowedHosts, or Offline in the machine policy): connectors, embeddings and webhooks reach only this machine and the allowed hosts, CLI and Copilot connectors are off, and the ONNX model is never downloaded. (#147)
  • Remote gateway clients need a key: with no Middleware:GatewayKeys they get 401 (AllowUnauthenticatedRemoteClients restores the old behaviour), and a key reference that does not resolve no longer opens the gateway. The container image reads ROUTER_GATEWAY_KEY. (#129)
  • Default limits for remote clients (Middleware:RemoteRequestsPerMinute, 120) and CLI queues (MaxQueue, 16), and ForwardedHeaders:KnownProxies/KnownNetworks to trust X-Forwarded-For only from named proxies. (#129)
  • Web pages cannot use the gateway through DNS rebinding or a foreign Origin; /v1/models, count_tokens and /semantic-router/classify follow the same gateway-key rule as the chat endpoints. (#114)
  • Dashboard responses forbid framing (frame-ancestors 'none', X-Frame-Options: DENY) and send nosniff and no-referrer; the dashboard bundles its fonts and sends a strict Content-Security-Policy. (#114, #129)
  • The admin API cannot change what a CLI runs (program, arguments, environment, home directory) or which paths memory sources read, unless Dashboard:AllowProcessSettings is on. (#114, #144)
  • The read-only dashboard role can no longer trigger calls that cost money or scan the disk (evaluate, classify, embeddings test, discover, check, memory refresh); dashboard sessions expire after Dashboard:SessionLifetime (12 hours), and wrong tokens are throttled per address. (#144)
  • Dashboard identity from an authenticating reverse proxy (Dashboard:TrustedIdentityHeader, believed only from KnownProxies), the real actor on every configuration change, and an append-only audit log (GET /router/api/audit, an Audit log page, State:Retention:AuditDays). (#150)
  • A Metrics dashboard role (Dashboard:MetricsToken, or Metrics in TrustedIdentityRoles) that sees figures only, never prompt or reply text. Signing out ends the session on the server, and an admin can sign out every session (POST /router/api/session/revoke-all); sessions from before the upgrade sign in once more. (#161)
  • With State:StorePrompts: Off, a failed CLI run's output and the judge's reason for a grade are not stored or logged either; Redacted masks credentials in them. (#162)
  • Local-only routing holds in more cases: a failed classification stays local while any route is local-only, a conversation kept local stays local (including named cloud models), local-only prompts stay off remote embedding endpoints (Embeddings:IsLocal), and the judge respects routing profiles. (#114)
  • Secrets: CLI environment variables and more header names (auth, cookie, password, credential, session, signature) are masked; masked or stored keys are never sent to a connector that now points somewhere else; the configuration history keeps no secrets; keyed requests do not follow redirects; webhook URLs are not logged. (#114, #116)
  • Keys written into addresses (user:key@, key-named query values) are masked in the admin API, the configuration history and every address the dashboard and doctor show. (#117, #129)
  • CLIs run in a working directory only the user can write to and start by full path; a Custom CLI's {prompt} cannot become an option; the router's files are readable by their owner only. (#114)
  • The data-protection key ring is encrypted at rest: to a certificate (DataProtection:Certificate) on any OS, with DPAPI for SEMANTIC_ROUTER_KEYS_DIR on Windows; otherwise owner-only permissions and a start-up warning. doctor says how the keys are protected. (#149)
  • Stored prompts: State:StorePrompts (Redacted by default, masking credentials in previews; On; Off), State:Retention, and a purge (DELETE /router/api/activity, "Delete all activity") that leaves nothing readable in the database files. (#129)
  • Webhooks carry no prompt or reply text unless Notifications:IncludeDetails is on, and the stored project label is a hash of the client's user_id, never the id. (#144)
  • Prompted tool calls are harder to forge: a random fence label per run that never reaches the client, defused tool results, PromptedToolParsing: Strict (opt-in), calls copied from a tool result kept as text in both modes, and a prompted-call count in the activity log. (#129, #152)
  • No outbound traffic you did not configure: no web fonts from other hosts, Claude Code started without its auto-updater and non-essential traffic, Codex with update checks and analytics off. doctor lists every host the router will contact. (#129, #143)
  • Desktop updates: Updates:Publisher requires an update to be code-signed by a given publisher before it is applied, and the updater refuses feeds over plain HTTP other than loopback. (#142, #151)
  • Verifiable releases: build provenance attestations for every asset, SHA256SUMS, CycloneDX SBOMs, a keyless cosign signature and attestations on the container image, and THIRD-PARTY-NOTICES.txt. See docs/releases.md. (#145)
  • Release pipeline: a tag must be on main, tests pass before anything publishes, the desktop app is built in jobs without secrets, and the image is built and scanned (Trivy) before the registry login. CodeQL and OpenSSF Scorecard run on the repository. (#129)
  • The container runs on a chiseled ASP.NET Core image with no shell, with both base images pinned by digest. (#129)
  • NuGet restores are locked to committed packages.lock.json files in CI, the release and the container build. (#148)

Added

  • A "Cut a release" workflow (Actions > Cut a release): the repository owner enters a version, it checks CI, code signing and NuGet publishing, tags main, and the release workflow publishes everything with the CHANGELOG section as the release notes. Only the owner can release, by this workflow or a pushed tag. See docs/releases.md.
  • Cache-aware stickiness: a conversation stays on the model with the warm prompt cache when that is cheaper than moving, and returns to it after a failover (Middleware:Conversation:CacheLifetime). (#137)
  • Prompt-cache markers on Anthropic requests translated from OpenAI or Responses clients (Connectors:{name}:PromptCaching, CacheTtl). (#139)
  • Cache reads and writes per activity entry, and a cache hit rate on the Usage page. (#113)
  • Endpoints card on the Overview (host, state, health and latency per connector, with a Check button) and a Service card (where the router runs, the URLs for clients, its health). (#117, #121)
  • Network:CaBundle, a PEM file trusted in addition to the system store, for TLS-inspecting proxies. (#143)
  • Desktop app: notify-only updates (Updates:Apply: Notify in the machine policy, or "Install updates when quitting" in the tray), and managed deployment docs. (#151)
  • PromptRouterMiddlewareOptions.InjectedTags; the Copilot app's injected context blocks are ignored when classifying. (#118)
  • Model names semantic-router, claude-semantic-router, -cheapest and -best; /v1/models entries have a display_name. (#156)
  • tool-calls benchmark for prompted tool calling. (#152)
  • A quick-answers route (tier 2) in the starting routes, for short factual and explain questions, and small-refactor utterances in simple-code; the sample evaluation set has 116 prompts. (#160)
  • Dashboard Feedback page and a Report button on each Activity entry: they open a GitHub issue (misroute, bug or idea) with the decision line, the model that answered, the embedding settings and the router version filled in. The prompt is left out unless you add it, and a local-only prompt answered by a cloud model points to private security reporting instead. The misroute and bug forms ask for the router version and the decision line. (#164)

Changed

  • Targets .NET 10 (LTS) instead of .NET 9, whose support ends on 10 November 2026: the packages and the tool need the .NET 10 runtime, and the container runs on ASP.NET Core 10. Building needs a 10.0.4xx SDK. (#115, #148)
  • init asks before enabling a subscription CLI connector (Claude Code, Codex); declined or non-interactive runs add it disabled. --yes restores the old behaviour and --no-cli leaves CLIs out. (#141)
  • Prompts go to Claude Code and Copilot CLIs on standard input; PromptInput: "Argument" restores the old behaviour. (#114)
  • Model comparisons count each model's prompt-cache prices, from the share of input it reads from cache (Selection:CacheShareWindow, CacheShareSamples). (#138)
  • Only the prose of a prompt is embedded, without pasted code or data (EmbedProseOnly, on by default); local-only routes are still checked against the whole prompt. (#157)
  • The init template routes Claude Code's *opus* as auto; opus-pinned pins Opus, and an exact alias wins over a wildcard. (#156)
  • Routing profile Projects globs match the hashed user:… project label, and dashboard sessions sign in once more after the upgrade. (#144)
  • Dependency updates, among them GitHub.Copilot.SDK 1.0.22. (#134, #135, #136)

Fixed

  • Cached-token counts on streamed and translated replies, from the CLIs and in "saved by routing". (#113)
  • After a failover, the serving model is timed from ...
Read more

Site Media

Site Media Pre-release
Pre-release

Choose a tag to compare

@siebe41 siebe41 released this 16 Oct 03:41
3f6f229
Merge pull request #166 from siebe41/siebes/pensive-mayer-921bpq

Add a kit that records a marketing demo video of the router

v0.2.1

Choose a tag to compare

@github-actions github-actions released this 14 Oct 15:03
c49145a

What's Changed

  • Use NuGet Trusted Publishing instead of API key by @siebe41 in #112

Full Changelog: v0.2.0...v0.2.1

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 14:01
a9168cc

What's Changed

  • Latency as a model selection factor (#70) by @siebe41 in #91
  • Roadmap: where we are after round 7, and round 8 (prompt caching) by @siebe41 in #97

Full Changelog: v0.1.0...v0.2.0

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 12 Oct 14:46
eda81c0

What's Changed

  • Add SemanticRouter: semantic prompt routing for .NET 9 by @siebe41 in #1
  • Pin NuGet restore to nuget.org with a repo nuget.config by @siebe41 in #2
  • Anthropic front door for Claude Code, a hot-reload dashboard, named tiers and a roadmap by @siebe41 in #20
  • Secrets out of the config file, dashboard tokens and gateway keys, LM Studio authentication by @siebe41 in #21
  • Add the semantic-router tool and container; run CI on Windows and macOS by @siebe41 in #22
  • Durable state: cooldowns, tool-call affinity, activity and configuration history by @siebe41 in #23
  • Usage, cost and budgets; limit reset times; OpenTelemetry traces and metrics by @siebe41 in #24
  • Responses API front door for Codex; thinking, structured output and dropped features across protocols by @siebe41 in #25
  • Land the host, durable state, usage and protocol work on main by @siebe41 in #26
  • Routing quality loop: evaluation sets, threshold calibration, route health, labelling activity by @siebe41 in #27
  • In-process ONNX embeddings, a classification cache and warm-up statistics by @siebe41 in #29
  • Add memory map: track notes sent to models in requests by @siebe41 in #28
  • Routing profiles: policy per client, project and content by @siebe41 in #31
  • Land the routing-quality work (#27) on main by @siebe41 in #30
  • Faster prompted CLI turns, and a Copilot connector on GitHub's official SDK by @siebe41 in #32
  • Dashboard: end-to-end tests in CI, accessibility, phone layout and drop-in themes by @siebe41 in #33
  • Add model lineup discovery and suggestions for connectors by @siebe41 in #34
  • Add desktop app and background service support by @siebe41 in #35
  • Desktop: fit the window to the screen, About window; fix Windows CI by @siebe41 in #36
  • Windows update script; SQLite state no longer drops bursts of writes by @siebe41 in #37
  • Improve CLI queue test reliability with synchronization by @siebe41 in #38
  • Fix Windows CI (SQLite handle leak); safer update-windows.ps1 by @siebe41 in #39
  • Desktop app owns the background service; route by the conversation (#41); explicit callouts (#42) by @siebe41 in #51
  • Record implicit outcome feedback per routing decision (#43) by @siebe41 in #52
  • Tune thresholds and utterances automatically, within guardrails (#45) by @siebe41 in #53
  • Track model reliability per kind of work (#44) by @siebe41 in #54
  • Model-family priors: tiers and capabilities from a curated table (#46) by @siebe41 in #55
  • Default routes and evaluation prompts for agentic clients (#47) by @siebe41 in #56
  • Optional judge that grades a sample of cheap answers (#48) by @siebe41 in #57
  • Weekly digest; notify only when a decision is needed (#49) by @siebe41 in #58
  • Installers for the desktop app: Setup.exe, .pkg, AppImage (#50) by @siebe41 in #59
  • Add CODEOWNERS and a ruleset that protects main by @siebe41 in #60
  • Ready the first release: install CI on every OS, signing, durable counts (#63–#66) by @siebe41 in #75
  • Harden the repo for public use: CI gates, least-privilege release, security and contributor docs by @siebe41 in #61
  • Fix the formatting gate on main; installer jobs follow the release hardening by @siebe41 in #77
  • Bump the actions group across 1 directory with 6 updates by @dependabot[bot] in #76
  • Bump the nuget-minor-and-patch group with 10 updates by @dependabot[bot] in #78
  • Bump Microsoft.Data.Sqlite from 9.0.20 to 10.0.12 by @dependabot[bot] in #81
  • Bump coverlet.collector from 6.0.4 to 10.1.0 by @dependabot[bot] in #79
  • Send notices and the weekly digest to webhooks by @siebe41 in #84
  • Bump FluentAssertions from 7.2.2 to 8.11.0 by @dependabot[bot] in #80
  • Bump Microsoft.NET.Test.Sdk from 17.12.0 to 18.10.1 by @dependabot[bot] in #82
  • Bump xunit.runner.visualstudio from 3.0.2 to 4.0.1 by @dependabot[bot] in #83
  • Ship the client side-request wording as an updatable data file by @siebe41 in #85
  • Per-client rate limits for gateway keys by @siebe41 in #86
  • Fuzz tests for protocol translation, and the crashes they found by @siebe41 in #87
  • Recognise corrections in other languages and other words by @siebe41 in #88
  • Measure how often the judge agrees with hand labels by @siebe41 in #89
  • Learn the cheapest good-enough model per route by @siebe41 in #90

New Contributors

Full Changelog: https://github.com/siebe41/SemanticRouter.NET/commits/v0.1.0