feat: add profile-based routing foundation#161
Conversation
|
I'll review this in the morning! Thank you for. the submission and ideas! |
rynfar
left a comment
There was a problem hiding this comment.
Review
Good work on this — the scope is right, the session isolation approach is clean, and the per-profile auth caching is well done. I want to merge this once two things are adjusted:
1. Move getProfileId out of AgentAdapter
x-meridian-profile is Meridian proxy infrastructure, not an agent-specific concern. Every adapter would implement it identically — it's just c.req.header("x-meridian-profile"). The AgentAdapter interface should stay focused on abstracting agent differences (OpenCode vs. future agents).
Read the header directly in server.ts instead:
const requestedProfileId = c.req.header("x-meridian-profile")
const requestedProfile = resolveProfile(finalConfig, requestedProfileId)And drop getProfileId from adapter.ts and adapters/opencode.ts.
2. Handle unknown profile as a 400, not a 500
Right now if a client sends x-meridian-profile: nonexistent, resolveProfile() throws, which hits the generic catch in server.ts and returns a 500 with a stack trace. This should be a clean 400.
Easiest fix — catch it at the call site in server.ts:
let requestedProfile: ResolvedProfile
try {
requestedProfile = resolveProfile(finalConfig, requestedProfileId)
} catch (e) {
return c.json({
type: "error",
error: { type: "invalid_request_error", message: e instanceof Error ? e.message : "Invalid profile" },
}, 400)
}Everything else looks good. The buildScopedKey approach, the per-profile auth status cache, and the test coverage are all solid. Happy to merge once these two are in.
|
Thanks for the feedback. Whenever I get some free time I'll get the suggestions added in, and continue testing. |
Summary
x-meridian-profileUse Case
I have both a personal and a company Claude account/plan, and I want to use OpenCode from several systems without having to install and auth Meridian separately on each machine.
The goal is to run a single Meridian instance that I can reach over my local network or a private Tailscale tunnel, then route requests to the right Claude profile from each client. That gives me better control over which systems use which account, while still feeling similar to how each machine might otherwise have its own
claude authsetup.This PR only adds the profile-routing foundation. It does not add request authentication or admin-route protection yet.
Testing
bun test src/__tests__/proxy-profiles.test.tsbun test src/__tests__/proxy-stale-uuid-retry.test.tsnpm run buildNotes
Follow-up PRs will keep the maintainer review small:
/healthand/telemetry*