TypeScript Types
Complete TypeScript interfaces for the STELLA Session Management API.
Installation
Copy these types directly into your project:
// src/types/session-management.ts
Enums
export enum SessionStatus {
ACTIVE = 'ACTIVE',
CLOSED = 'CLOSED'
}
export enum AgentStatus {
STARTING = 'STARTING',
RUNNING = 'RUNNING',
STOPPING = 'STOPPING',
STOPPED = 'STOPPED',
FAILED = 'FAILED'
}
export type MessageType = 'text' | 'transcript' | 'system';
Entity Types
Project
export interface Project {
id: string;
name: string;
createdAt: string;
updatedAt: string;
}
export interface ProjectWithCounts extends Project {
activeSessions: number;
activeAgents: number;
totalSessions: number;
}
export interface ProjectWithSessions extends Project {
sessions: Session[];
}
export interface ProjectStats {
totalSessions: number;
activeSessions: number;
totalAgents: number;
activeAgents: number;
totalMessages: number;
totalParticipants: number;
}
Session
export interface Session {
id: string;
projectId: string;
status: SessionStatus;
createdAt: string;
closedAt: string | null;
}
export interface SessionWithRoom extends Session {
room: Room;
}
export interface SessionDetail extends SessionWithRoom {
agents: AgentInstance[];
participants: Participant[];
_count: {
messages: number;
events: number;
};
}
export interface SessionListItem extends SessionWithRoom {
_count: {
agents: number;
participants: number;
messages: number;
};
}
Room
export interface Room {
id: string;
sessionId: string;
livekitRoomName: string;
serverUrl: string;
}
Agent Instance
export interface AgentInstance {
id: string;
sessionId: string;
role: string;
status: AgentStatus;
podName: string | null;
secretName: string | null;
configMapName: string | null;
planId: string | null;
createdAt: string;
stoppedAt: string | null;
}
export interface AgentWithSession extends AgentInstance {
session: {
id: string;
room: {
livekitRoomName: string;
serverUrl: string;
};
};
}
export interface AgentWithPodStatus extends AgentWithSession {
podStatus: {
phase: 'Pending' | 'Running' | 'Succeeded' | 'Failed' | 'Unknown';
conditions: any[];
containerStatuses: any[];
} | null;
}
Participant
export interface Participant {
id: string;
sessionId: string;
identity: string;
joinedAt: string;
leftAt: string | null;
}
Message
export interface Message {
id: string;
sessionId: string;
participantId: string | null;
content: string;
messageType: MessageType;
timestamp: string;
}
export interface MessageWithParticipant extends Message {
participant: Participant | null;
}
Room Event
export interface RoomEvent {
id: string;
sessionId: string;
eventType: string;
data: Record<string, any>;
timestamp: string;
}
Timeline
export type TimelineItem =
| { type: 'message'; data: MessageWithParticipant }
| { type: 'event'; data: RoomEvent };
export interface Timeline {
timeline: TimelineItem[];
total: number;
}
Request DTOs
Project Requests
export interface CreateProjectDto {
name: string; // 1-255 characters
}
Session Requests
export interface CreateSessionDto {
planId?: string; // max 255 characters
}
export interface QuerySessionsDto {
status?: SessionStatus;
search?: string;
skip?: number; // default: 0
take?: number; // default: 20, max: 100
}
export interface CreateTokenDto {
identity: string; // max 255 characters
name?: string; // max 255 characters
}
Agent Requests
export interface CreateAgentDto {
role: string; // max 255 characters
planId?: string; // max 255 characters
}
Response Types
Paginated Response
export interface PaginatedResponse<T> {
data: T[];
total: number;
skip: number;
take: number;
}
export type SessionsResponse = PaginatedResponse<SessionListItem>;
Join Token Response
export interface JoinTokenResponse {
token: string;
serverUrl: string;
roomName: string;
}
Delete Response
export interface DeleteResponse {
message: string;
}
Error Response
export interface ApiError {
statusCode: number;
timestamp: string;
path: string;
message: string | string[];
}
API Client Interface
export interface ApiClient {
// Projects
createProject(data: CreateProjectDto): Promise<Project>;
listProjects(): Promise<ProjectWithCounts[]>;
getProject(projectId: string): Promise<ProjectWithSessions>;
getProjectStats(projectId: string): Promise<ProjectStats>;
deleteProject(projectId: string): Promise<DeleteResponse>;
// Sessions
createSession(
projectId: string,
data: CreateSessionDto
): Promise<SessionWithRoom>;
listSessions(
projectId: string,
query: QuerySessionsDto
): Promise<SessionsResponse>;
getSession(sessionId: string): Promise<SessionDetail>;
createJoinToken(
sessionId: string,
data: CreateTokenDto
): Promise<JoinTokenResponse>;
getTimeline(
sessionId: string,
skip?: number,
take?: number
): Promise<Timeline>;
closeSession(sessionId: string): Promise<DeleteResponse>;
// Agents
createAgent(
sessionId: string,
data: CreateAgentDto
): Promise<AgentInstance>;
getAgent(agentId: string): Promise<AgentWithPodStatus>;
getAgentLogs(agentId: string): Promise<string>;
stopAgent(agentId: string): Promise<DeleteResponse>;
}
Usage Example
import {
ApiClient,
CreateProjectDto,
SessionDetail,
} from './types/session-management';
class SessionManagementClient implements ApiClient {
constructor(private baseUrl: string) {}
async createProject(data: CreateProjectDto) {
const response = await fetch(`${this.baseUrl}/projects`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
return response.json();
}
// ... implement other methods
}
// Use with type safety
const client = new SessionManagementClient('http://localhost:3000');
const project = await client.createProject({ name: 'My Project' });
// project is typed as Project
const session = await client.createSession(project.id, {
planId: 'cognitive_stimulation_demo_sm',
});
// session is typed as SessionWithRoom
React Hooks
import { useState, useEffect } from 'react';
import {
Project,
SessionDetail,
AgentWithPodStatus,
} from './types/session-management';
// useProject hook
export function useProject(projectId: string) {
const [project, setProject] = useState<Project | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
async function fetchProject() {
try {
const response = await fetch(`/api/projects/${projectId}`);
const data: Project = await response.json();
setProject(data);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
}
fetchProject();
}, [projectId]);
return { project, loading, error };
}
// useSession hook
export function useSession(sessionId: string) {
const [session, setSession] = useState<SessionDetail | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchSession() {
const response = await fetch(`/api/sessions/${sessionId}`);
const data: SessionDetail = await response.json();
setSession(data);
setLoading(false);
}
fetchSession();
}, [sessionId]);
return { session, loading };
}
// useAgent hook with polling
export function useAgent(agentId: string, pollInterval = 2000) {
const [agent, setAgent] = useState<AgentWithPodStatus | null>(null);
useEffect(() => {
async function fetchAgent() {
const response = await fetch(`/api/agents/${agentId}`);
const data: AgentWithPodStatus = await response.json();
setAgent(data);
}
fetchAgent();
const interval = setInterval(fetchAgent, pollInterval);
return () => clearInterval(interval);
}, [agentId, pollInterval]);
return { agent };
}
Validation Helpers
export const validators = {
projectName: (name: string): boolean => {
return name.length >= 1 && name.length <= 255;
},
identity: (identity: string): boolean => {
return identity.length >= 1 && identity.length <= 255;
},
pagination: (skip: number, take: number): boolean => {
return skip >= 0 && take >= 1 && take <= 100;
},
};
Type Guards
export function isApiError(error: any): error is ApiError {
return (
error &&
typeof error.statusCode === 'number' &&
typeof error.timestamp === 'string' &&
typeof error.path === 'string' &&
(typeof error.message === 'string' || Array.isArray(error.message))
);
}
export function isSessionActive(session: Session): boolean {
return session.status === SessionStatus.ACTIVE;
}
export function isAgentRunning(agent: AgentInstance): boolean {
return agent.status === AgentStatus.RUNNING;
}
Constants
export const DEFAULT_PAGINATION = {
skip: 0,
take: 20,
} as const;
export const MAX_PAGINATION = {
take: 100,
} as const;
export const POLL_INTERVALS = {
SESSIONS: 5000, // 5 seconds
AGENTS: 2000, // 2 seconds
TIMELINE: 3000, // 3 seconds
} as const;