refactor: plumb SessionId end-to-end + paste + event-context fixes #96
No reviewers
Labels
No labels
bug
commercial
documentation
duplicate
enhancement
feature
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
jasoncouture/llama-shears!96
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "undoing-claudes-dumbass-bullshit"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
(string agentId, Guid? sessionId)withSessionIdacrossIContextStore,ArchiveId, persistence, data-context scope/factory,AgentInfo,IAgentContextProvider,IAgentDirectory, slash-command context, andChannelMessage.JsonLineContextStoreresolves folder/file fromSessionId.IsDefault: default →<agentId>/current.json; non-default →<agentId>/<name>/<sessionId:n>.json.preserveSubscriberExecutionContextonIEventBus.Subscribeso their handler runs with the agent's ambient data scope.NameIdentifier; middleware parses it back and joins the matching scope.AgentWorkspaceLocatorparses the same claim so MCP tools resolve the agent's workspace instead of process cwd.SelectedSession; slash commands consumecontext.Session;AgentInstanceRepositorygainsTryGetDefaultSessionfor UI/auth lookup.MaximumReceiveMessageSizebumped to 32 MB so a pasted image survives the round-trip.Test plan
dotnet builddotnet test/clear,/archive,/compact,/interrupt.Pull request overview
This PR refactors the codebase to use
SessionIdas the canonical identifier end-to-end (persistence, data scopes, auth claims, event routing, slash commands, and UI state), and includes web UI fixes for image paste and larger SignalR payloads.Changes:
SessionIdacross persistence (IContextStore,ArchiveId), data context (IDataContextScope/Factory), and agent snapshot APIs (IAgentContextProvider,AgentInfo).preserveSubscriberExecutionContexttoIEventBus.Subscribe.Reviewed changes
Copilot reviewed 79 out of 79 changed files in this pull request and generated 6 comments.
Show a summary per file
SessionId.NameIdentifier.SessionIdfrom claims.SessionId.SessionId.SessionIdin store calls.ChannelMessageshape.AgentInfowith aSessionId.preserveSubscriberExecutionContextparameter toSubscribe.ChannelMessagepayload shape to remove agent targeting and includeChannelId.SessionId.SessionId.SessionId.SessionId.SessionIdand updates storage remarks.ArchiveIdto(SessionId, UnixMillis).TryGetDefaultSessionfor UI/auth lookup of root sessions.AgentIdconvenience accessor.SessionIdin agent context implementation while keeping compat accessors.SessionId.SessionId.SessionId.SessionIdwhen creating agent scopes.preserveSubscriberExecutionContext.MaximumReceiveMessageSizeto 32MB.NameIdentifierclaim carrying session canonical.SelectedSession.ChannelMessagepayload.TryGetDefaultSession.ChannelMessagedocs to match new payload.CreateAgentContextAsync(SessionId, ...).SessionId-keyed API.(SessionId, UnixMillis)archive identity.AgentInfo.AgentInfodocs for session-based identity.💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When the bearer token contains a valid SessionId but the corresponding data scope can’t be joined, the middleware returns 500. This scenario can occur with a stale token for an agent/session that isn’t running, which is more appropriately treated as an auth failure (401/403) rather than an internal error. Consider returning 403 (or 401) and optionally logging the condition instead of 500.
AgentTurnContextPersister currently relies on IDataContextFactory.Current to discover the session to persist, but this handler is registered as an activated singleton (via AddEventHandler) and will typically run with no ambient data scope. As a result, turns will be dropped on the floor (session == null => return) and persisted context won’t update. Consider deriving the target SessionId from the event envelope (e.g., parse envelope.Type.Id as a SessionId) rather than relying on ambient scope, and then OpenAsync/AppendAsync against that session.
Non-default session persistence uses Path.Combine(session.AgentId, session.Name) as the folder, but does not include session.Id. This means multiple sessions with the same (AgentId, Name) will share the same archive namespace: ClearAsync archives to ".json" and ListArchivesAsync will return archives created by other sessions with the same Name. Consider scoping the folder (or archive filenames) by session.Id so archives/current data cannot collide or bleed across sessions.
ResolveFolder uses session.Name as a directory name. SessionId.Name explicitly allows ':' (and other characters) for canonical round-tripping, which will produce invalid paths on Windows (':' is not permitted in directory names). Consider encoding/sanitizing Name for filesystem use, or avoiding Name in the directory path and using only session.Id (or another filesystem-safe representation).
@ -65,12 +65,11 @@ public sealed partial class ModelContextProtocolToolCallDispatcher : IToolCallDiToolResponseClamp was removed, so tool results are now returned/published unbounded. A single large MCP tool response can inflate event payloads, UI memory usage, and model prompt size, potentially causing failures (e.g., exceeding context window or transport limits). Consider reinstating output clamping (or adding an alternative size/line limit) before returning/publishing the result content.
The XML doc says ChannelMessage is published with the channel id in the event type Id segment, but the updated routing publishes/subscribes Channel.Message by session id and carries the channel as ChannelId in the payload. This comment (and the generated docs) should be updated to match the new routing semantics. Also, the using for Agent.Sessions appears unused in this file after the signature change.