Repository navigation
Keep only setup extension classes in Microsoft's namespaces (#198) - #250
Merged
Merged
Conversation
The dashboard's 29 nested wire records and the classify, /v1/models and count_tokens bodies become internal: their contract is the JSON. Options move to the package's own namespace (RouterDashboardOptions to SemanticRouter.AspNetCore, SqliteStateOptions to SemanticRouter.Storage.Sqlite), and every SemanticRouterBuilder extension class is in Microsoft.Extensions.DependencyInjection, as the Onnx and Copilot ones already were. The breaks against 0.5.0 are suppressed. docs/architecture.md describes the convention and PublicApiNamespaceTests enforces it. Refs #198 Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
3 tasks
It had landed under 0.3.0's Changed section. Refs #198 Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Decisions for Andrew
The namespace scheme. I chose:
Microsoft.Extensions.DependencyInjection: every setup extension class, onIServiceCollectionand onSemanticRouterBuilder, in every package (SemanticRouterServiceCollectionExtensions,SqliteStateBuilderExtensions,OnnxEmbeddingsBuilderExtensions,CopilotConnectorBuilderExtensions). ASP.NET Core does the same for its own builder types (IHttpClientBuilder,IHealthChecksBuilder,IMvcBuilder), and the Web SDK's implicit using means.UseSqliteState(),.UseOnnxEmbeddings()and.AddCopilotConnector()keep working with nousing.Microsoft.AspNetCore.Builder: only the threeUse*/Map*classes (PromptRouterApplicationBuilderExtensions,RouterDashboardEndpoints,RouterForwardedHeadersExtensions).Alternative: the issue's example, with all
SemanticRouterBuilderextensions inSemanticRouter.AspNetCore. Every app would then needusing SemanticRouter.AspNetCore;to call them, and Sqlite, Onnx and Copilot would put a class in another package's namespace, which breaks the issue's own "each package's public types live in its own namespace" criterion. With my choice, only the Sqlite extension class moves; Onnx and Copilot already follow the rule.The classify,
/v1/modelsandcount_tokensDTOs becameinternalinstead of moving to a publicSemanticRouter.AspNetCore.Http. Nothing outside the package uses them (samples, Hosting, Desktop and tests checked), and their contract is the JSON the endpoints return. Making them public again later is an addition, not a break. Alternative: keep them public inSemanticRouter.AspNetCore.Http, for apps that wantPromptClassificationResponse.From(plan)in their own endpoints.There are 29 nested dashboard records, not the issue's 25. The four
PriceLookup*records were added after the audit, and they are internal now too.MapRouterDashboardgets a new binary signature, because the type of itsconfigureparameter (Action<RouterDashboardOptions>) moved namespace. The source still compiles when the caller passes a lambda. One that namesRouterDashboardOptionsneedsusing SemanticRouter.AspNetCore;.What changed
Removed from the public API, or moved (all suppressed in the
CompatibilitySuppressions.xmlthis PR adds):SemanticRouter.AspNetCore
Microsoft.AspNetCore.Builder.RouterDashboardOptionstoSemanticRouter.AspNetCore.RouterDashboardOptions, and gave it its own file,Dashboard/RouterDashboardOptions.cs.MapRouterDashboard(IEndpointRouteBuilder, string, Action<RouterDashboardOptions>)signature (CP0002), because of the move above.internalthe 29 nested records ofRouterDashboardEndpoints:SessionResponse,SignInRequest,ValidationResult,ConflictResponse,UsageResponse,HistoryResponse,ActivityResponse,ActivitySummary,MemoryMapResponse,MemoryNodeResponse,PriceLookupRequest,PriceLookupModel,PriceLookupResponse,PriceLookupResult,EmbeddingTestRequest,EmbeddingTestResponse,DiscoverResponse,LineupModel,ThemesResponse,StatusResponse,EmbeddingsStatus,IndexStatus,EmbeddingModelStatus,TierStatus,ModelStatus,ConnectorStatus,RouteStatus,GatewayStatusandConnectorLatency. (ThePriceLookup*four were not in the 0.5.0 baseline, so they have no suppression.)internaland moved toSemanticRouter.AspNetCore(Middleware/RouterEndpointModels.cs):ClassifyPromptRequest,PromptClassificationResponse(with its nestedRouteCandidateandModelChoice),RouterModelInfo,RouterModelListandTokenCountResponse.SemanticRouter.Storage.Sqlite
SemanticRouter.AspNetCore.SqliteStateOptionstoSemanticRouter.Storage.Sqlite.SqliteStateOptions.SemanticRouter.AspNetCore.SqliteStateBuilderExtensionstoMicrosoft.Extensions.DependencyInjection.SqliteStateBuilderExtensions, in its own file. The internal store classes moved toSemanticRouter.Storage.Sqliteas well.Unchanged: Core, Embeddings.Onnx and Connectors.Copilot already followed the scheme.
Also:
docs/architecture.md#namespaces, with a guideline line in CONTRIBUTING.md, anddocs/dashboard.mdnames the options' namespace.PublicApiNamespaceTestsenforces the convention by reflection over all five library assemblies:Why
#198: the Web SDK imports
Microsoft.AspNetCore.Builderin every file, so 33 DTO and options types (now 36 with the price lookup) were in scope in every app that uses the package. Every new dashboard field was also a binary breaking change of a NuGet package. Fixing this before 1.0 is the only time it is cheap.How it was verified
On Windows, on a machine busy with the other sprint lanes:
dotnet build -c Release: succeeded, 0 warnings.dotnet format --verify-no-changes: clean.dotnet pack -c Release -p:ApiCompatGenerateSuppressionFile=true: wrote the two suppression files. A seconddotnet pack -c Releaseof AspNetCore and Storage.Sqlite, with the validation semaphores deleted, passes package validation against 0.5.0.dotnet test -c Release(full suite, 1,411 tests): 1,407 passed, 4 failed. None of the four is in code this PR touches, and all four pass when run alone:MemoryMapTests.Event_stream_announces_routed_requests(10 s SSE timeout),ServiceTests.The_router_records_itself_while_it_runs_and_reports_an_address_in_useandDesktopTests.The_tray_reads_the_routers_own_status(HttpClient timeouts) timed out under the load.SecretsTests.Literal_secrets_move_to_the_store_and_resolve_backexpectsOPENAI_API_KEYto be unset, and it is set on this PC.PublicApiNamespaceTests(11 cases), rerun withOPENAI_API_KEYunset: 15/15 passed.Other OSes: nothing here depends on paths, processes or the shell. It changes only namespaces, accessibility and file layout, so Linux and macOS behave the same as Windows. System.Text.Json and minimal APIs serialise and bind internal records the same way on every OS, and the dashboard and endpoint tests exercise that.
Not done
Refs #198