Repository navigation
Releases
Novior.MentorAgent 1.3.0
Added
-
ACTION-RULES.md lists the rules by which a method becomes an action, how actions are named, and how roles and
confirmations add up. Each rule has a name that does not change and at least one test that fails when the rule does;
a rule that comes in, changes or is retired is named in the release notes of its version. The rules of 1.3.0:
scan.assemblies-once,scan.concrete-classes,scan.public-instance-declared,scan.marker,
scan.mentor-action-wins,scan.override-keeps-action,kind.one-per-class,kind.page-is-separate,
kind.agent-owns-methods,kind.skill-methods-level1,kind.team-needs-members,kind.member-tools-leave-level1,
kind.member-tools-same-rules,name.snake-case,name.team-tool,name.shared-warned,
name.called-method-decides,confirm.declared-decides,confirm.default-for-writes,
confirm.description-only-not-defaulted,confirm.predicate-adds,confirm.master-switch,
confirm.beats-read-only,confirm.unconfirmed-writes-warned,roles.any-of,roles.signed-in,
roles.checked-before-confirmation,roles.offered-when-allowed,surface.coordinator-only,
surface.mcp-withholds-gatedandsurface.card-ungated-only. -
An action can ship off, and the application can turn its actions on and off from outside its code.
[MentorAction(Enabled = false)]keeps an action in the catalogue (MentorActionInfo.EnabledByDefaultis false)
and nowhere else: no agent is offered it, no model reads about it, the MCP server does not list it, the A2A card
does not show it, and a call to it does not run. AnIMentorActionGovernor, registered with
AddMentorActionGovernor<T>(), answers for each action whether it is on, and can turn on one the code ships off:
registering one gives whoever implements it the power to widen what the code allows. It is asked once as a session
builds its tools, on everytools/listof the MCP server and before every call, with the session's id; a session
keeps the tools it was built with, and a call to an action turned off meanwhile is refused. There can be one: a
second registration throws. A governor that throws, or does not answer withinActionPolicyTimeout, stops the
action. The A2A card follows the code only, so an action turned on from outside is not on it. New reason codes:
disabled(Denied) andgovernor-failed(PolicyFailed). New rules:enabled.off-by-default,
enabled.external-decidesandsurface.governor-session;surface.mcp-withholds-gatedand
surface.card-ungated-onlynow also leave out an action that is off. -
The governor can also give an action its roles:
IMentorActionGovernor.GetRequiredRolesAsyncanswers in place of
[MentorAction(RequiredRoles = ...)], withnullfor the code's roles and an empty list for none. The answer
decides whom the action is offered to, the check at every call, before a confirmation and again after it, and which
MCP callers see and call it: an action the MCP server withheld only for its roles is published once the governor
requires none.MentorActionDecision.RolesFromOutsidesays when the roles came from the governor. New rule:
roles.external-replace;roles.checked-before-confirmationnow checks the governor's roles when it gives them. -
The governor can also decide whether the user confirms an action:
IMentorActionGovernor.GetConfirmationAsync
answersMentorConfirmationChoice.Codefor the code's confirmation,Requiredto ask even if the code does not,
andNonenot to ask even if the code does — declared, by default for writes, or byRequiresApproval. A
confirmation added counts from the call, one taken away from the next session, and in Native mode no auto-approval
rule lets a required one through. A policy'sConfirmstill asks, a hosted MCP server's approval still comes from
its provider, and withRequireConfirmationoff nobody is asked. An action whose confirmation is taken away still
counts as one that changes data. The MCP server publishes an action that asks for confirmation once the governor
takes it away, and withholds one it requires.MentorActionDecision.ConfirmationFromOutsidesays when the governor
changed whether a call is confirmed. New rule:confirm.external-decides;confirm.predicate-addsand
surface.mcp-withholds-gatednow say what the governor can take away. -
The governor can also rewrite the description the model reads:
IMentorActionGovernor.GetDescriptionAsyncanswers
in place of the code's, withnullor a blank text for the code's. It is asked as a session builds its tools and
on everytools/listof the MCP server, and the answer is what the coordinator, the specialists and the team
members read, what tool filtering ranks, and whattools/listshows; the action's name and argument schema never
change, and the code'sProactiveHintstill follows the description. What the user sees keeps the code's
description: the confirmation banner, the bar of the running action andMentorActionDecision.DisplayName. On a
call to the MCP server the policies are asked with the code's description. New rule:describe.external-replace. -
An
IMentorAgentSourcesays what it loaded and what it left out, and when it is asked is a promise. A source is
asked whenever a coordinator is built: at least once per session — once per Blazor circuit, MAUI app scope or hub
connection, and at every request on/mentor/chatand every task over A2A — andMentorAgentSourceContext.SessionId
names the session, asMentorActionRequest.SessionIddoes. MentorAgent now callsIMentorAgentSource.LoadAsync,
which returns aMentorAgentSourceResult: the agents, and aMentorAgentRejection(Name,ReasonCode,Detail,
Tool) for each definition left out or tool taken away. Its default body returns the agents ofGetAgentsAsync, so
an existing source works unchanged. AnIMentorAgentSourceObserver, registered with
AddMentorAgentSourceObserver<T>(), receives aMentorAgentSourceReportfor each source every time a coordinator
is built, also when the source loaded nothing; a source that throws is reported assource-failed, with the
exception's type and never its message. The reason codes, inMentorAgentRejectionReasons:invalid-definition,
not-an-agent,foreign-tools,invalid-configuration,source-failed,tool-not-foundand
hosted-tool-removed. Novior.MentorAgent.Declarative reports every definition it does not load and every tool
it takes away. New rules:declarative.functions-matchanddeclarative.no-hosted-tools. -
MentorRuntimeOptions.Changeablelists the options that can be changed while the application runs, and from when
a change applies (MentorOptionReadAt). From the next turn of every session:Language,RateLimitPerUser,
RateLimitWindowSecs,ConfirmationMessage,ConfirmationTimeout,ActionPolicyTimeout,EnableActionFeedback,
EnableGenerativeCards,EnableSafetyCheckandCheckAnnouncedActions. From the sessions that begin after the
change:MentorshipLevel,
ProactiveNextSteps,EnableRichResponses,RefuseOutOfScope,ToolFilterMaxToolsandMaxSessionMessages. To
change one, assign it on theIOptions<MentorOptions>value, replacing a collection rather than changing it in
place. Every other option is read before the application starts: set it there. Each option listed has a test that
changes it on a running application, and every option declares when it is read, so a new one cannot ship without
the decision. -
After a turn in which the coordinator called no tool, MentorAgent asks a model whether its reply announces an action
("I'm registering the note…") or reports one as done when nothing ran (MentorOptions.CheckAnnouncedActions, on by
default). If it does, the coordinator gets one more request in the same turn, with the same tools, told to call the
tool now or to say that it was not done. The question names the tools the model was sent, and the answer names the
one that does the action: the second request then says that this tool is there to call now. The instruction is that
request's last message, read after the reply it is about, and never stored. A call to an action of the application
the agent was not given (one that is off for the session) runs nothing, and the turn is checked as one in which
nothing ran. The call is never required and passes the gate as any other, the reply
already shown is not held back, and the second reply is not checked again. The question goes to
ClassifierChatClient, or toChatClientwithout one: a few hundred tokens after every reply that called no tool,
so a small deployment there is worth configuring. Its verdict is logged at Information for every reply it checks,
with the time and the tokens it took. On Path A with the history kept by MentorAgent; not with
UseServiceManagedHistorynor with a pre-builtAgent(BUG-220). -
A call the model makes to an action of the application that the coordinator was not given in the turn — one that
is off, or another agent's — reaches no gate and runs nothing.IMentorActionObservernow receives its one
decision,Deniedwith the new reason codenot-offered, and the call's span says the same, in Blocking and in
Native mode, withCheckAnnouncedActionson or off. A call the coordinator was given keeps the decisions of its
gate, and only those. -
One instance of the application can tell which tenant a request belongs to.
IMentorTenantResolver, registered with
services.AddMentorTenantResolver<T>()(one per application), names it from the caller, the surface and the
request's services;IMentorTenant.Idreads it, in an action, a policy or the governor, and
IMentorTenant.GetIdAsync()resolves it first in a scope that had n...
Novior.MentorAgent 1.2.0
Added
-
Novior.MentorAgent.Abstractions:
IMentorStateService.OnActionStartedgives the tool's technical name next to
the text shown, in aMentorActionStarted:OnActionExecutingcarries only the text shown, so whoever recorded
the actions from it could not tell for sure which tool ran. It is raised where the turn runs, not by the WebAssembly
client, and the interface implements it as an event nobody raises, so an implementation written for 1.1.0 still
compiles. The documentation ofOnActionExecutingnow says it carries the text shown, not the tool name. -
Novior.MentorAgent.Abstractions, Novior.MentorAgent:
IMentorActionObserverreceives every decision of the tool
gate, on every surface and for every agent;AddMentorActionObserver<T>()registers one. AMentorActionDecision
carries the outcome (MentorActionOutcome), a reason code that stays the same across versions
(MentorActionReasons), the tool, the agent, the surface, the session, turn and call ids, the user and who
confirmed — never the arguments. A decision never waits for an observer: each has a queue of its own and 5 seconds a
call. -
Novior.MentorAgent.Abstractions: an action that asks for confirmation knows who confirmed it and when:
MentorActionConfirmation.Current, read inside the action's method, carries the confirmation's id, the tool, the
time and who confirmed — the caller ofPOST /mentor/approve, or the session's user in a circuit and in the MAUI
app — in Blocking and in Native mode. It isnullfor an action nobody confirmed. The approval event came when
the action was already on its way, so a ledger of the writes could not say who approved one. -
Novior.MentorAgent:
MentorOptions.ConfirmationTimeoutbounds how long a confirmation waits for its answer,
counted from when the banner is shown. Once it has passed with no answer, the confirmation counts as rejected: the
action does not run, its decision isRejectedwith the new reason codeconfirmation-timeout, the span's
mentoragent.tool.confirmationistimed-out, and the model is told nobody confirmed it in time, not that the user
declined. An answer that comes later is ignored, as one after Stop is:POST /mentor/approveanswers 404. It applies
to a confirmation a policy asks for too, in Blocking and in Native mode, and for specialists and team members. Zero or
a negative value, the default, is no limit, as before. -
Novior.MentorAgent, .Abstractions, .Blazor, .Server: two tools for article 50 of the EU AI Act. A notice that
tells people they are talking to an AI assistant, under the widget's header for the whole conversation
(ShowAiDisclosure,AiDisclosureMessage, onMentorOptionsandMentorAgentBlazorOptions), with a default text
in the ten languages ofLanguage; and a machine-readable marker on every reply the model writes:
data-ai-generated="true"on the reply in the widget,"aiGenerated": trueon thechunkandcompletedframes of
/mentor/chat, the hub eventReplyStartedbefore each reply, whose argument is aMentorReplyStarted
({ "aiGenerated": true }), andaiGeneratedin the metadata of the reply to an A2A task. Turning the notice off
leaves the marker. The results of the MCP server, the spoken replies and the images and files of the provider's
hosted tools carry no marker. Which words to show, and whether the article applies, is the application's to decide. -
Novior.MentorAgent.Abstractions:
MentorTheme.Autofollows the visitor's system setting
(prefers-color-scheme): the light theme,Minimal, when it asks for light, which is also what a browser reports
when the system states no preference, andDefaultwhen it asks for dark. It follows the system, not the page: on
a page that is always light, a visitor whose system is dark sees the dark widget. No script is involved, and the
default theme staysDefault. -
Novior.MentorAgent, .Abstractions, .Blazor, .Server: a language per page.
<ChatWidget Language="…" />gives
the widget a language of its own for its texts, its voice and its onboarding tour, and every turn it sends carries
it: the assistant answers in it, and what MentorAgent writes for that turn follows it. The language travels as
MentorUserMessage.Language, in the hub's newSendUserMessage, aslanguageon/mentor/chatand onGET /mentor/tour?language=.IMentorOrchestratorandIMentorTourget default methods, so implementations written for
1.1.0 compile. A change ofMentorOptions.Languagewhile the application runs applies from the next turn. A2A and
MCP requests stay onMentorOptions.Language. -
Novior.MentorAgent:
MentorOptions.SessionContextPlacement. WithLastUserMessagethe context of each request
— the page, its data, its address, the date and time — goes at the start of the user's last message instead of the
end of the instructions, which then stay the same through the session: a model that caches the prompt by its prefix,
a local engine above all, no longer reads the whole conversation again on every new minute or page. The stored
conversation keeps the user's words. Path A with local history only; the default,Instructions, changes nothing.
Changed
-
Novior.MentorAgent, .Abstractions, .Blazor: the widget now shows, by default, under its header: "You are talking
to an AI assistant: its replies are generated automatically.", in the configuredLanguage, for the whole
conversation. SetAiDisclosureMessageto your own words, orShowAiDisclosuretofalseto show none. -
Novior.MentorAgent.Server: the hub sends
ReplyStartedbefore each reply. A client that does not register it
keeps working, and SignalR logs a warning for every reply ("Failed to find handler" in .NET, "No client method with
the name" in JavaScript): register it, even with a handler that does nothing —connection.on("ReplyStarted", () => {}), orhub.On<MentorReplyStarted>("ReplyStarted", _ => { }). The WebAssembly client of Novior.MentorAgent.Blazor
registers it. -
Every package is now checked at pack time against the public API of 1.1.0, so 1.2.0 cannot break code built
against 1.1.0 by accident. An intended break is listed in this file as Breaking. -
The family moves onto the Microsoft Agent Framework 1.26.0 line (
Microsoft.Agents.AIand
Microsoft.Agents.AI.Workflows1.26.0) andMicrosoft.Extensions.AI10.11.0. Novior.MentorAgent.Declarative:
Microsoft.Agents.AI.Declarativemoves to 1.26.0-rc1, on the same line. In Agent Framework 1.26
AgentSessionStore.DeleteSessionAsyncis abstract: a host with anAgentSessionStoreof its own implements it.
1.26 also refuses two tool approval requests with one id; MentorAgent gives each call of a response an id of its
own (BUG-225), except withUseServiceManagedHistory. -
With Agent Framework 1.25 or later, when control returns to an agent of the handoff workflow behind
route_to_specialist,
the workflow repeats the user's request to it instead of leaving it a tool result alone: whoever reads the
workflow's messages sees one more after each return. The answers do not change. -
ModelContextProtocolmoves to 2.3.0: the MCP client in Novior.MentorAgent, and
ModelContextProtocol.AspNetCore2.3.0 in Novior.MentorAgent.Server. The SDK's HTTP server is stateless by
default from 2.0; the MCP endpoint asks for the stateful transport, so a client keeps itsMcp-Session-Idand the
endpoint answers as before, aGETwithout a session with 400 included. -
An MCP server of the host that lists a tool without
inputSchemais no longer connected: ModelContextProtocol 2.0
refuses such a tool where 1.x gave it an empty schema, and the server's whole tool list is lost with it. The
warning names the server, and its exception namesinputSchema; the assistant goes on without that server. -
The A2A SDK moves to 1.0.0-preview3:
A2Ain Novior.MentorAgent andA2A.AspNetCorein
Novior.MentorAgent.Server. -
Novior.MentorAgent: a call refused for its roles is logged once, at Warning, in Blocking and in Native mode
alike. In Native mode a user who was not signed in was refused before the banner with a Debug line only, and in
Blocking mode a missing role wrote two Warnings. A confirmation cancelled by Stop or by the end of the session is
now logged at Debug in Native mode too, and a tool call's Debug line is written once instead of twice. -
The
mentor.tool.{toolName}andmentor.mcp.tool.{toolName}spans carry the outcome
(mentoragent.tool.outcome), the reason code (mentoragent.tool.reason), the confirmation
(mentoragent.tool.confirmation) and the surface (mentoragent.surface), and a failed call sets the span's
status to error. In Native mode a call refused, rejected or stopped before it runs now has its span too. -
Novior.MentorAgent.Server: the MCP server's line for each
tools/calltells apart a call refused for its roles
(denied-role), an action the server never publishes (withheld) and a name nothing defines (unknown): the
three were allunknown. A call the client cancels iscancelled. The caller is still told the same for every name
it may not use. -
Novior.MentorAgent.Abstractions, Novior.MentorAgent, .Server:
IMentorActionPolicylets the application's own
code decide whether a user may use an action and whether a call may run — a permission per company or per record, a
rule on the arguments — on every surface: the coordinator on both paths and in both modes, the specialists, team
members and agent sources, the MCP servers the application consumes, the MCP server and A2A tasks.
AddMentorActionPolicy<T>()registers one.IsAllowedAsyncdecides what is offered and is asked again before every
...
Novior.MentorAgent 1.1.0
Added
-
Novior.MentorAgent:
MentorOptions.ConfirmationMessagewrites the text of the confirmation banner, in the
application's own words or language. It gets the tool, its description, the arguments as the banner shows them,
Languageand the services of the conversation's scope. When it returnsnullthe default text is shown; when it
throws or returns only white space, the default text and a warning (BUG-186). -
Every package carries its software bill of materials: SPDX 2.2, at
_manifest/spdx_2.2/manifest.spdx.json
inside the.nupkg, with its SHA-256 beside it. It lists the package's files and the packages restored to build
it, build-time tools included. -
Novior.MentorAgent:
MentorActionAttribute.RequiresConfirmationDeclaredis public and read-only: whether the
attribute writesRequiresConfirmation, true or false. WithRequireConfirmationForWriteson, an action that
declares nothing asks for confirmation and one that declaresRequiresConfirmation = falsedoes not, while
RequiresConfirmationreads false for both; a component outside the library can now tell them apart.
Security
- Novior.MentorAgent.Blazor: BUG-173 (S2): the package depended on
Microsoft.AspNetCore.SignalR.Client
10.0.3, whoseMicrosoft.AspNetCore.SignalR.Commonis covered by advisory GHSA-334f-vvp4-7g6p
(CVE-2026-70159, high): a client using stateful reconnect can block a server's broadcasts. It now depends on
10.0.13, the patched release. With 1.0.0, add
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.13" />to the client project.
MentorAgent turns stateful reconnect on neither in its hub nor in its client. - Novior.MentorAgent.Server: the hub runs on the SignalR of the ASP.NET Core shared framework, not on a
package: a host is patched by the ASP.NET Core runtime 10.0.13 or later. - A package with a high or critical advisory (NuGet audit NU1903, NU1904), direct or transitive, now fails the
Release build of the packages.
Changed
-
Every package is now checked at pack time against the public API of 1.0.0, so a 1.x release cannot break
code built against 1.0.0 by accident. An intended break is listed in this file as Breaking. -
Novior.MentorAgent, .Server, .Blazor, .Abstractions, .Declarative: NOTICE says that "MentorAgent" and its
logo are trademarks of Antonio Macrì and Emanuele Longo, to be assigned to Novior, not licensed under the Apache
License 2.0, and points to the trademark policy, TRADEMARKS.md, in the GitHub repository.
Fixed
-
Novior.MentorAgent: the README's Migrating from the MentorAgent.* packages listed the build diagnostic
MENTOR001among what stays the same. That check, and itsMentorAgentSkipOpenAIVersionCheckswitch, were
removed in 1.0.0-rc.15: the core package has no build target, and there is no switch to keep (BUG-159, S3). -
Novior.MentorAgent.Server: three sentences of the README did not match the code.
IncludeWorkflowExceptionDetails
puts the exception message of a failing handoff or group chat agent into the reply, not a stack trace.
EnableSuggestionsand the widget options do take effect in a MAUI Blazor Hybrid app, which runs the Blazor
widget; only a MAUI app with its own native UI ignores them. And theAuthorizationheader is missing from a
WebSocket or Server-Sent Events connection because a browser cannot send one, not because the protocol forbids
it; the Blazor README said the same and is corrected too (BUG-160, S4). -
Novior.MentorAgent.Server: the README's React example for image input did not compile: a
<textarea>outside
any component and anawaitat the top level. It is now a component that keeps the attachments in its state and
sends them from anasynchandler, passingnullwhen there are none (BUG-161, S3). -
Novior.MentorAgent.Server: the README said that
POST /mentor/cancelanswers404when Stop is pressed just as
the turn ends, and that it is not an error; its React, Angular and Vue components ignored it. The endpoint answers
200whenever the connection exists, with or without a turn running, and404only when the connection is closed
or unknown, which is the case a client must not hide. The README and the three components now say so (BUG-162, S3). -
Novior.MentorAgent: the option reference tables of the README and the Server README left out options that only
their own sections described:SkillSources,SkillFilter,SkillsRefreshInterval,AutoApprovalRulesand
MaxAutoApprovalIterationsin the README;EnableRichResponses,IsReadOnlyAction,EnableOutputSafetyCheck,
RequireLookupForRecordQuestions,RequireActionForChangeRequestsandMcpCallerPrincipalin the Server README.
Every public option ofMentorOptionsis now in a reference table of both, or among the Server README's options
not listed on purpose. The[MentorAction]tables markDescriptionas required, and the Server README's lists
ReadOnly(BUG-163, S4). -
Novior.MentorAgent: with a pre-built
Agent(Path B),MemoryAutoCaptureand aClassifierChatClient, memory
had two writers: the post-turn extraction ran through the classifier, one call per message, and theremember
tool was sent too. The log and the documentation said the extraction does not run on Path B. The tool is now left
out whenever the extraction runs, and the build log names the writer: on Path B the extraction with a
ClassifierChatClient, theremembertool without one (BUG-174, S3). -
Novior.MentorAgent: a
[MentorTeam]withHandoffTowas approved when[TEAM:APPROVED]appeared anywhere
in the discussion, so a member's "yes" followed by another's "no" still told the coordinator to execute the
actions. The team is now approved only if its final message carries[TEAM:APPROVED]and no member wrote
[TEAM:REJECTED]; a discussion that ends without a verdict is not approved. Without a[TeamTerminationCondition]
the discussion now ends at the first verdict, instead of running allMaxIterationsrounds; a host's condition
still decides alone when to stop. The members' instructions keep[TEAM:REJECTED]for a definitive no and ask for
changes without a token (BUG-175, S3). -
Novior.MentorAgent, .Server, .Blazor, .Abstractions, .Declarative: the XML documentation that IntelliSense
shows no longer contradicts the code: anonymous callers share the memory key"anonymous"only with
AnonymousIdentity = Shared; an emptyAllowedToolsallows every tool, likenull(the README says so too);
MentorTheme.Customrenders likeDefault;IMentorAgentis optional and validates nothing; the hub's events list
Cards, andMapMentorAgentServerlists/mentor/session(BUG-164, S4). -
Novior.MentorAgent: the README did not say that with
UseRagthe search runs on every message, before the
model is called, so its time (an embedding call, the search, a reranker) is added to every reply; nor that the
absence of a keyword pre-gate relies onRagMinScorebeing on the source's scale. It says both now, and so does
the comment inRagContextProvider(BUG-165, S4). -
Novior.MentorAgent: the XML documentation of
RequiresApprovalsaid the predicate is evaluated once per
tool while the coordinator is built. It is asked again on every call to a tool in Blocking mode and on every turn
the tool filter matches a tool, so a predicate that reads a file or a database pays for it each time. The
documentation now says when it is asked and that it must stay a cheap, pure function of the tool name
(BUG-176, S4). -
Novior.MentorAgent: the documentation of
ConfigureChatClientPipelinesaid only that the pipeline goes
outermost. It is built once per coordinator, so once per circuit on Blazor Server and once per SignalR connection
on the hub: a limit placed there does not limit the process. And only the coordinator's own calls go through it:
the auxiliary calls — classifier, safety checks, out-of-scope refusal, memory extraction, the lookup and action
checks — useClassifierChatClient ?? ChatClient, and specialists, team members and the handoff router use
ChatClient. The READMEs and the XML documentation now say both (BUG-166, S4). -
Novior.MentorAgent: the READMEs said that
navigate_towaits forSignalReady()on aHasUIActionspage
only in a Blazor Server circuit. It waits wherever the page runs in the same process as the turn, so in a MAUI
Blazor Hybrid app too; turns over the hub, SSE or A2A still do not wait. The READMEs now say so (BUG-171, S4). -
Novior.MentorAgent: on Path B (a pre-built
Agent),EnableSafetyCheckandEnableOutputSafetyCheck
without aClassifierChatClientnow log a warning when the coordinator is built: neither check can run, so every
message and every reply goes through unchecked. Both checks run onClassifierChatClient, or onChatClientwhen
none is set, so on Path B aClassifierChatClientturns them on; the README and the XML documentation said they
required aChatClient(BUG-167, S3). -
Novior.MentorAgent: the README and the XML documentation of
HitlModesaid thatNativecosts one
model call more per approved action, and thatBlockingis cheaper. Both modes make the same model calls:
Nativeadds one agent run per round of confirmations, and its reply arrives in two segments (BUG-168, S3). -
Novior.MentorAgent.Blazor: the README said twice that the server must enable
EnableOnboardingTourtoo,
and the widget's log said so when the tour had no steps.MapMentorAgentServer()mapsGET /mentor/tour
whatever the server's flag says: the client's flag alone decides whether the tour is shown. The README and the
log now say so (BUG-169, S3). -
**No...
Novior.MentorAgent 1.0.0
Changed
- Breaking — all packages: the packages are now
Novior.MentorAgent,Novior.MentorAgent.Abstractions,
Novior.MentorAgent.Blazor,Novior.MentorAgent.DeclarativeandNovior.MentorAgent.Server; theMentorAgent.*
ids end at 1.0.0-rc.15. The namespaces follow (using Novior.MentorAgent.Extensions;), the widget's static files
are served from_content/Novior.MentorAgent.Abstractions/, and the log categories start with
Novior.MentorAgent, so a"MentorAgent"filter underLogging:LogLevelno longer matches. The five packages
depend on each other at their exact version. Unchanged: the types and extension methods (AddMentorAgent,
MentorOptions, …), the routes, the telemetry source, meter and metric names, the session snapshot format, the
MentorAgentMcpCORS policy,MentorAgent.css,MentorAgent.jsandwindow.MentorAgent. The README's
Migrating from the MentorAgent.* packages walks through the move.
Fixed
- Novior.MentorAgent: four Warnings outside the tool gate still carried a whole exception, whose text comes from the
host's code: a UI action that threw, with aChatClientor a pre-builtAgent, and anOnToolResultor a
McpCallerPrincipalthat threw on the MCP server. As in the gate, they name the exception's type; the whole
exception is logged at Debug (BUG-152, S3). - Breaking — Novior.MentorAgent.Server:
AddMentorAgentMcp()orAddMentorAgentA2A()called beforeAddMentorAgent(),
or withMcpServerEnabled/A2AServerEnabledturned on afterAddMentorAgent()read them (aConfigureor
PostConfigureofMentorOptions), registered nothing and said nothing; the map call failed later, in the
second case naming a call the host had made. The host now stops at start-up with the reason and the fix, and
one that ran without the server because of it no longer starts (BUG-153, S3). - Novior.MentorAgent: the README and the rc.15 notes said that the warning about writes that run without
confirmation comes at startup. It comes the first time the actions are read: at startup only with
WarmUpAtStartuporMapMentorAgentA2A(), otherwise with the first conversation or the first MCP or tour
request. With[Description]alone it also names the methods that only read, untilIsReadOnlyActionor
[MentorAction(ReadOnly = true)]declares them. The README now says both (BUG-154, S3). - Novior.MentorAgent.Server: the README's minimal SignalR client called Stop, the confirmations and the session
save and restore without the hub's credentials: with cookies from another origin, or a bearer token, those
calls were anonymous and did nothing. It now sends them, like the complete components. The README also no
longer says that the MCP and A2A servers are built intoMentorAgent(BUG-155, S3). - Novior.MentorAgent: the READMEs, the XML documentation of
AddMentorAgent()and the start-up warning for a
callback that throws listedAppDescriptionandAgentCardamong the options read at registration.
OnlyAppNameis, as the MCP server's name; the A2A card is built from the real options when
MapMentorAgentA2A()runs (BUG-156, S4). - Novior.MentorAgent: the README's MAUI step 3, pasted into the MAUI Blazor Hybrid template, did not compile: it
lackedusing System.Reflection;andusing Microsoft.Extensions.Configuration;, andAddUserSecretsneeds
Microsoft.Extensions.Configuration.UserSecrets, which neither the template norMentorAgentbrings. The step
now names both and the package, and says thatAddUserSecretsneeds the project'sUserSecretsIdand finds
the secrets only on the development machine (BUG-157, S3). - Novior.MentorAgent.Abstractions: its README said that the core package depends on
ModelContextProtocol.AspNetCore; since rc.15 that transport is in the Server package, and the core
referencesModelContextProtocol(BUG-158, S3).