Welcome to the first chapter of the Server project tutorial! Before we write code that actually does things, we need to agree on what we are talking about.
Imagine you are running a hotel. To check a guest in, you need specific information: their name, which room they are assigned to, and whether they have paid. If one receptionist writes "Room 101" and another writes "rm #101", the system gets confused.
Session Data Models acts as the "Standard Operating Procedure" for our server. It solves a chaotic communication problem by enforcing strict rules on data.
The Use Case: We want to create a server where a client (like a coding agent) can connect, start a workspace, and resume work later. To do this, the server needs to answer questions like:
If the client expects a field named work_dir but the server sends directory, the connection fails. Our models prevent this.
When a client first connects, the server needs to send back a "Welcome Package." In our code, we use a tool called Zod to validate this package. Think of Zod as a bouncer at a clubβit checks that every piece of data matches exactly what we expect.
Here is the blueprint for the connection response:
// From types.ts
import { z } from 'zod/v4'
export const connectResponseSchema = z.object({
session_id: z.string(), // The unique ID card
ws_url: z.string(), // The address to talk to
work_dir: z.string().optional(), // Where files are saved
})
Explanation:
session_id: This is a mandatory text string. It uniquely identifies the conversation.ws_url: The WebSocket URL. This is the "phone number" the client uses to keep talking to the server.work_dir: This is optional. It tells the client which folder on the computer is being used.A session isn't just "on" or "off." It goes through a lifecycle, much like a car gear shift. We define these states specifically so the code never tries to drive while in "Park."
// From types.ts
export type SessionState =
| 'starting' // Engine turning on
| 'running' // Cruising
| 'detached' // Running in background
| 'stopping' // Brakes applied
| 'stopped' // Engine off
Explanation:
By limiting the status to only these five words, we prevent typos. You can't accidentally set the status to "crashed" or "paused" because the compiler will yell at you. This makes handling logic in Control & Permission Handling much safer later on.
We have two different ways to look at a session. This is a crucial distinction for beginners.
SessionInfo)This exists only in the computer's memory (RAM). It holds the heavy, live objects, like the actual running computer process.
// From types.ts
export type SessionInfo = {
id: string
status: SessionState
// The actual running program (cannot be saved to a text file)
process: ChildProcess | null
createdAt: number
}
SessionIndexEntry)This is the data we save to a JSON file on the hard drive. If the server restarts, the "Live Session" is wiped out, but this "Saved Record" remains.
// From types.ts
export type SessionIndexEntry = {
sessionId: string
cwd: string // Current Working Directory
lastActiveAt: number
// Notice: No 'process' here!
}
Before looking at how this is implemented, let's visualize how these models are used when a user connects.
SessionInfo) to manage the process.SessionIndexEntry) in a permanent logbook.connectResponseSchema).
Let's look at how these types connect inside the file types.ts.
The server needs to know its own settings before it can host any sessions. This is defined in ServerConfig.
// From types.ts
export type ServerConfig = {
port: number // e.g., 3000
authToken: string // Password for security
idleTimeoutMs?: number // Auto-shutdown timer
maxSessions?: number // Max capacity
}
How to use this:
When we initialize the server in the next chapter, we will pass a generic JavaScript object. Because we have this type definition, TypeScript will ensure we don't forget the port or pass a number for the authToken.
We mentioned the "Saved Record" earlier. The SessionIndex is simply a collection (a dictionary) of these records.
// From types.ts
// A dictionary where the Key is the Session ID
export type SessionIndex = Record<string, SessionIndexEntry>
Analogy:
Think of SessionIndexEntry as a single patient's medical file.
Think of SessionIndex as the entire filing cabinet containing all the folders.
When the server starts up, it reads this "filing cabinet" to remember previous sessions. This is critical for the Direct Connect Manager which we will cover in Direct Connect Manager.
In this chapter, we defined the "vocabulary" our server speaks.
connectResponseSchema: The strict contract for talking to clients.SessionState: The specific stages of a session's life (e.g., 'running', 'stopped').SessionInfo: The live data in memory (holds the process).SessionIndexEntry: The saved data on disk (holds the history).By defining these models first, we ensure that the Client, the Server, and the File System all understand each other perfectly.
Now that we have our blueprints, it's time to actually build a session.
Next Chapter: Session Initialization
Generated by Code IQ