session-manager is the server side of Vibe Studio. It runs a per-builder workspace session, spawns the agent process, exposes a REST + Socket.IO API to the editor UI, and holds credentials the browser is never allowed to see — most importantly the SpinForge partner key.
The repo is /Users/imzee/projects/agent-zero/session-manager/. It's TypeScript, Express, Socket.IO, Redis (or filesystem) for persistence.
What it owns
- Workspaces on disk —
workspaces/<orgId>/<projectName>/directories with the actual files the agent edits. - Agent processes — spawned per session, isolated, with env vars containing the builder's JWT.
- The Socket.IO bridge —
bridge.service.tsproxies events between the editor UI and the agent. - The SpinForge partner key —
sfpk_…lives in env, never leaves the server. - Conversation history — every chat thread is persisted under
data/conversations/. - Planner data —
.vibe/planner.jsonper workspace. - Cohost tokens — view-only collaboration tokens.
- Deploy job state — running, finished, failed jobs with their step events.
Routes
The full route surface is in src/routes/index.ts. Highlights:
Sessions
/api/sessionsJWT/api/sessions/:userIdJWT/api/sessions/:sessionIdJWTCreate / inspect / terminate a workspace session. Body: { userId, orgId, projectName, metadata, priority }. Returns the session id, workspace path, and status.
Dev environments
/api/dev-envsJWT/api/dev-envs/:orgIdJWT/api/dev-envs/:orgId/:projectNameJWT/api/dev-envs/:orgId/:projectName/sync-ai-instructionsJWT/api/dev-envs/:orgId/:projectName/downloadJWTCRUD on workspaces. Create stamps .vibe/project.json, scaffolds files (or skips if a description is provided so the agent can pick a framework). Sync route back-fills identity files for older workspaces. Download streams a zip.
Planner
/api/planner/:orgId/:projectNameJWT/api/planner/:orgId/:projectNameJWT/api/planner/:orgId/:projectName/cards/:cardIdJWT/api/planner/:orgId/:projectName/cards/:cardId/logsJWT/api/planner/:orgId/:projectName/cards/:cardId/criteria/:acIdJWTRead / write the project planner. Whole-doc PUT, per-card PATCH, log append, acceptance-criterion flip. Every successful write emits a planner:updated socket event so frontends viewing the same project refresh in real time.
Conversations
/api/conversations/:orgId/:projectNameJWT/api/conversations/:orgId/:projectNameJWT/api/conversations/:orgId/:projectName/:conversationIdJWT/api/conversations/:orgId/:projectName/:conversationIdJWT/api/conversations/:orgId/:projectName/:conversationIdJWTPer-project chat history. Each conversation persists message turns, tool calls, and tool results.
Git
/api/git/:orgId/:projectName/statusJWT/api/git/:orgId/:projectName/initJWT/api/git/:orgId/:projectName/cloneJWT/api/git/:orgId/:projectName/commitJWT/api/git/:orgId/:projectName/remoteJWT/api/git/:orgId/:projectName/pushJWT/api/git/:orgId/:projectName/pullJWT/api/git/:orgId/:projectName/logJWTWraps real git on the workspace folder. Pushes accept an inline token so the editor doesn't need shell access to your git provider.
Cohost
/api/cohost/:orgId/:projectNameJWT/api/cohost/:tokenNo auth/api/cohost/host/:userIdJWT/api/cohost/:tokenJWTView-only collaboration tokens. The host creates a token, shares the URL, the guest joins read-only. Useful for screen-sharing-without-Zoom — the guest sees the editor and the agent stream live.
Deploy
/api/deploy/:provider/:orgId/:projectNameJWT/api/deploy/jobs/:orgId/:projectNameJWT/api/deploy/job/:jobIdJWT/api/deploy/job/:jobId/streamJWT/api/deploy/:provider/:orgId/:projectName/statusJWT/api/deploy/:provider/:orgId/:projectName/sync-aliasesJWT/api/deploy/:provider/:orgId/:projectNameJWTProvider-aware deploys. Default provider is spinforge. The deploy is async — POST returns a job id immediately and you stream events via SSE on the /stream route.
Templates
/api/templatesJWT/api/templates/applyJWTPre-built starter HTML files the studio can scaffold into a workspace.
Preview
/preview/:orgId/:projectNameNo auth/preview/:orgId/:projectName/*No authServes workspace files for the iframe preview. Path-traversal-guarded.
Session lifecycle
1. User opens a workspace in Vibe Studio
2. Studio POSTs /api/sessions → resourceManager allocates a session
3. Session manager spawns the agent (a-full) as a subprocess
4. Agent process gets env vars: APPMINT_*, SESSION_MANAGER_URL
5. Bridge wires the editor's Socket.IO to the agent's stdio
6. Editor sends prompts, agent emits tool calls, bridge ferries them
7. User closes the workspace → /api/sessions DELETE → process killed, session freed
Idle sessions get a soft termination after the configured timeout (default 30 minutes). Reconnects within the timeout window resume the same session.
Configuration
src/config/config.ts reads from environment:
| Var | Purpose | Default |
|---|---|---|
SESSION_MANAGER_PORT | HTTP port | 5600 |
MAX_CONCURRENT_SESSIONS | Cap | 50 |
WORKSPACE_BASE_PATH | Workspaces folder | ./workspaces |
REDIS_URL | Optional persistence | unset (file fallback) |
SPINFORGE_PARTNER_KEY | sfpk_… for SpinForge | required for deploy |
APPMINT_API_URL | AppMint base URL | required |
Persistence
Two backends:
- Redis (recommended for production) — fast, distributed, TTLs.
- Filesystem (fallback) — JSON under
data/, no external dependencies.
Redis is configured by setting REDIS_URL. session-manager auto-falls-back to filesystem if Redis isn't reachable on boot.
Resource management
resource-manager.service.ts allocates ports for the agent processes from a configured range, monitors memory, and queues new sessions when the cap is reached. Metrics at GET /api/metrics.
The queue can be paused / resumed administratively:
/api/resources/pauseJWT/api/resources/resumeJWT/api/resources/limitsJWTUseful for maintenance windows.
Auth
session-manager doesn't own auth — every protected endpoint expects an Authorization: Bearer <appmint JWT> header. The middleware validates the token against AppEngine. There's no local user store.
Auth endpoints (/profile/user/signin, magic-link) are explicitly NOT proxied — the route table comments call this out: "Auth endpoints removed — auth is owned entirely by the AppMint server."
Running it
cd agent-zero/session-manager
npm install
cp .env.example .env
# edit .env to set SPINFORGE_PARTNER_KEY, APPMINT_API_URL, etc.
npm run build
npm start
Production deploys typically put session-manager behind a reverse proxy (nginx, Cloudflare) with TLS termination. The Vibe Studio frontend is configured with SESSION_MANAGER_URL pointing at the public URL.
Related
- Vibe Studio overview — the front-end that talks to session-manager.
- Deploy to SpinForge — how the deploy routes are used.
- SpinForge — the deploy target session-manager calls.