Repository navigation
feat: scope OmniRoute session per project and allow opting out of Memory - #50
Open
ahmet-cetinkaya wants to merge 1 commit into
Open
ahmet-cetinkaya wants to merge 1 commit into
ahmet-cetinkaya wants to merge 1 commit into
Conversation
OmniRoute scopes per-project server-side state (notably Memory) by the x-omniroute-session-id header. The plugin never sent one, so OmniRoute fell back to a fresh per-request id and state extracted while working on one project could surface in an unrelated project sharing the same API key. Send a stable id derived from the current working directory by default, hashing the path so it never leaves the machine. An explicit caller-supplied header still wins, and sessionScope: 'off' restores the previous behavior. Also add a disableMemory option that sends x-omniroute-no-memory: true, so a client can opt out of Memory without changing the server-side setting shared by every client of that instance. Refs Alph4d0g#49
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.
🚀 Context
OmniRoute scopes per-project server-side state — most visibly its Memory feature — by the
x-omniroute-session-idrequest header.createFetchInterceptoronly ever setAuthorizationandContent-Type, so OmniRoute fell back to a fresh per-request id (pipelineSessionId = explicitSessionIdHeader || skillRequestId).For anyone running OpenCode against a single OmniRoute API key across several repositories, memory extracted while working on Project A can be injected into an unrelated Project B session. There was also no way to opt out client-side, since OmniRoute's Memory toggle is server-side and shared by every client of that instance.
Important
Sending a stable session id does not by itself fully close the leak. OmniRoute's retrieval path currently hardcodes
scope: 'apiKey'intoMemoryRetrievalConfig()and ignores session scope — that half needs an upstream fix in OmniRoute itself. This PR is the client-side prerequisite: without a stable per-project id sent by the client, no server-side session scoping can ever work for OpenCode users.🔗 Related
⚙️ Implementation Details
Project-scoped session id (default on). The interceptor now sends
x-omniroute-session-id: opencode-<sha256(cwd) first 16 hex>.x-omniroute-session-idalways wins; the plugin only fills in a default.sessionScope: 'off'restores the previous behavior.disableMemoryoption (default off). Whentrue, sendsx-omniroute-no-memory: trueon every intercepted request, which disables memory and skill injection server-side for that request. This lets one client opt out without touching the shared server setting.Both options are additive and default to behavior that is either unchanged (
disableMemory) or strictly safer (sessionScope).flowchart LR A[OpenCode request] --> B{OmniRoute URL?} B -- no --> C[pass through untouched] B -- yes --> D[set Authorization + Content-Type] D --> E{sessionScope = off?} E -- yes --> G E -- no --> F{caller already<br/>sent session id?} F -- yes --> G[keep caller value] F -- no --> H["set opencode-sha256(cwd)"] G --> I{disableMemory?} H --> I I -- yes --> J[set x-omniroute-no-memory: true] I -- no --> K[forward request] J --> Ksrc/plugin.tsresolveProjectSessionId(),getSessionScope(), header wiring increateFetchInterceptorsrc/types.tsOmniRouteSessionScopetype;sessionScope+disableMemoryonOmniRouteConfigsrc/constants.tsindex.tsOmniRouteSessionScopealongside the other public typestest/plugin.test.mjsREADME.mdOmniRouteConfig📋 Checklist for Reviewer
npm test71/71 (66 existing + 5 new),npm run check:exportsclean.any, follows the repo'sHeaders/ URL-handling conventions fromAGENTS.md.Verification detail
New tests cover: header present and correctly shaped by default, stability across repeated loader calls in one project,
sessionScope: 'off'omits it, caller-supplied header preserved,disableMemory: truesends the no-memory header, and non-OmniRoute URLs get neither header.Beyond the suite, verified against a real OmniRoute v3.8.50 instance: a
/v1/chat/completionsrequest carrying both headers returns200. Also confirmed independently that the emitted id equals a separately computedsha256(cwd)prefix, contains no raw path, and differs across project directories.