feat: add multi-agent proxy support to dashboard backend#4
Conversation
- server/db.ts: adds tenant_memberships table (user_id, tenant_id, role) - server/index.ts: adds foxmemoryUrl() helper for agent-scoped upstream routing; all /api/foxmemory/* routes accept optional ?agentId= query param and proxy to /v2/agents/:agentId/... when provided; adds GET /api/tenants and GET /api/tenants/:tenantId/agents proxy routes Legacy behavior preserved — when agentId is omitted, routes proxy to /v2/... as before. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 755483cce8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| // ── Helper: build upstream foxmemory URL (agent-scoped when agentId provided) ─ | ||
| const foxmemoryUrl = (urlPath: string, agentId?: string) => { | ||
| const base = agentId ? `/v2/agents/${agentId}` : '/v2'; |
There was a problem hiding this comment.
Encode agentId before interpolating upstream path
The agentId query param is inserted into the URL path without encodeURIComponent, so agent IDs containing reserved characters (for example /, ?, or #) will alter the upstream route and can target the wrong endpoint (or fail with 404s) instead of /v2/agents/:agentId/... for that exact ID. Since this value is user-controlled via query string, it should be encoded (or validated to a safe character set) before building the path.
Useful? React with 👍 / 👎.
| try { | ||
| const overview = await probeFoxmemory(); | ||
| const agentId = req.query.agentId as string | undefined; | ||
| const overview = await probeFoxmemory(agentId); |
There was a problem hiding this comment.
Keep overview memoryCount scoped to selected agent
This now enables agent-scoped overview requests, but probeFoxmemory(agentId) still overwrites memoryCount from a global Qdrant count (/collections/foxmemory/points/count) with no agent filter; when ?agentId= is used, the cards/charts become internally inconsistent because most metrics are agent-scoped while memoryCount is global. In multi-agent deployments this produces inaccurate dashboard totals for the selected agent.
Useful? React with 👍 / 👎.
Summary
tenant_membershipstable to SQLite schema (user_id, tenant_id, role)foxmemoryUrl()helper that builds agent-scoped upstream URLs (/v2/agents/:agentId/...) whenagentIdquery param is provided/api/foxmemory/*proxy routes accept optional?agentId=and forward to agent-scoped endpointsGET /api/tenantsandGET /api/tenants/:tenantId/agentsproxy routesLegacy behavior preserved — when agentId is omitted, routes proxy to
/v2/...as before.Test plan
yarn typecheck:serverpassesGET /api/foxmemory/overviewstill works without agentIdGET /api/foxmemory/overview?agentId=Xproxies to/v2/agents/X/...GET /api/tenantsreturns tenant list from foxmemory-storeGET /api/tenants/:id/agentsreturns agent list🤖 Generated with Claude Code