docs: add JSDoc comments to types.ts and MIT LICENSE

- Add comprehensive JSDoc documentation to all interfaces, types, and functions
- Add @fileoverview documentation
- Document all properties with JSDoc comments
- Add MIT LICENSE file for open source distribution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-21 03:16:55 +01:00
co-authored by Claude Opus 4.5
parent 70d87220aa
commit cdb57a1104
2 changed files with 330 additions and 15 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Claudeman Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+309 -15
View File
@@ -1,66 +1,161 @@
/**
* @fileoverview Type definitions for Claudeman
*
* This module contains all TypeScript interfaces, types, and enums used
* throughout the Claudeman application. It provides type safety for:
* - Session management
* - Task queue operations
* - Ralph Loop configuration
* - API requests/responses
* - Screen session handling
* - Inner loop tracking (Ralph Wiggum detection)
*/
// ========== Core Status Types ==========
/** Status of a Claude session */
export type SessionStatus = 'idle' | 'busy' | 'stopped' | 'error'; export type SessionStatus = 'idle' | 'busy' | 'stopped' | 'error';
/** Status of a task in the queue */
export type TaskStatus = 'pending' | 'running' | 'completed' | 'failed'; export type TaskStatus = 'pending' | 'running' | 'completed' | 'failed';
/** Status of the Ralph Loop controller */
export type RalphLoopStatus = 'stopped' | 'running' | 'paused'; export type RalphLoopStatus = 'stopped' | 'running' | 'paused';
// ========== Session Types ==========
/**
* Configuration for creating a new session
*/
export interface SessionConfig { export interface SessionConfig {
/** Unique session identifier */
id: string; id: string;
/** Working directory for the session */
workingDir: string; workingDir: string;
/** Timestamp when session was created */
createdAt: number; createdAt: number;
} }
/**
* Current state of a session
*/
export interface SessionState { export interface SessionState {
/** Unique session identifier */
id: string; id: string;
/** Process ID of the PTY process, null if not running */
pid: number | null; pid: number | null;
/** Current session status */
status: SessionStatus; status: SessionStatus;
/** Working directory path */
workingDir: string; workingDir: string;
/** ID of currently assigned task, null if none */
currentTaskId: string | null; currentTaskId: string | null;
/** Timestamp when session was created */
createdAt: number; createdAt: number;
/** Timestamp of last activity */
lastActivityAt: number; lastActivityAt: number;
} }
// ========== Task Types ==========
/**
* Definition of a task to be executed
*/
export interface TaskDefinition { export interface TaskDefinition {
/** Unique task identifier */
id: string; id: string;
/** Prompt to send to Claude */
prompt: string; prompt: string;
/** Working directory for task execution */
workingDir: string; workingDir: string;
/** Priority level (higher = processed first) */
priority: number; priority: number;
/** IDs of tasks that must complete first */
dependencies: string[]; dependencies: string[];
/** Custom phrase to detect task completion */
completionPhrase?: string; completionPhrase?: string;
/** Timeout in milliseconds */
timeoutMs?: number; timeoutMs?: number;
} }
/**
* Full state of a task including execution details
*/
export interface TaskState { export interface TaskState {
/** Unique task identifier */
id: string; id: string;
/** Prompt sent to Claude */
prompt: string; prompt: string;
/** Working directory for task execution */
workingDir: string; workingDir: string;
/** Priority level (higher = processed first) */
priority: number; priority: number;
/** IDs of tasks that must complete first */
dependencies: string[]; dependencies: string[];
/** Custom phrase to detect task completion */
completionPhrase?: string; completionPhrase?: string;
/** Timeout in milliseconds */
timeoutMs?: number; timeoutMs?: number;
/** Current task status */
status: TaskStatus; status: TaskStatus;
/** ID of session running this task, null if not assigned */
assignedSessionId: string | null; assignedSessionId: string | null;
/** Timestamp when task was created */
createdAt: number; createdAt: number;
/** Timestamp when task started executing */
startedAt: number | null; startedAt: number | null;
/** Timestamp when task completed */
completedAt: number | null; completedAt: number | null;
/** Captured output from Claude */
output: string; output: string;
/** Error message if task failed */
error: string | null; error: string | null;
} }
// ========== Ralph Loop Types ==========
/**
* State of the Ralph Loop controller
*/
export interface RalphLoopState { export interface RalphLoopState {
/** Current loop status */
status: RalphLoopStatus; status: RalphLoopStatus;
/** Timestamp when loop started */
startedAt: number | null; startedAt: number | null;
/** Minimum duration to run in milliseconds */
minDurationMs: number | null; minDurationMs: number | null;
/** Number of tasks completed in this run */
tasksCompleted: number; tasksCompleted: number;
/** Number of tasks auto-generated */
tasksGenerated: number; tasksGenerated: number;
/** Timestamp of last status check */
lastCheckAt: number | null; lastCheckAt: number | null;
} }
// ========== Application State ==========
/**
* Complete application state
*/
export interface AppState { export interface AppState {
/** Map of session ID to session state */
sessions: Record<string, SessionState>; sessions: Record<string, SessionState>;
/** Map of task ID to task state */
tasks: Record<string, TaskState>; tasks: Record<string, TaskState>;
/** Ralph Loop controller state */
ralphLoop: RalphLoopState; ralphLoop: RalphLoopState;
/** Application configuration */
config: AppConfig; config: AppConfig;
} }
// ========== Respawn Controller Types ==========
/**
* Configuration for the Respawn Controller
*
* The respawn controller keeps interactive sessions productive by
* automatically cycling through update prompts when Claude goes idle.
*/
export interface RespawnConfig { export interface RespawnConfig {
/** How long to wait after seeing prompt before considering truly idle (ms) */ /** How long to wait after seeing prompt before considering truly idle (ms) */
idleTimeoutMs: number; idleTimeoutMs: number;
@@ -78,37 +173,71 @@ export interface RespawnConfig {
kickstartPrompt?: string; kickstartPrompt?: string;
} }
/**
* Application configuration
*/
export interface AppConfig { export interface AppConfig {
/** Interval for polling session status (ms) */
pollIntervalMs: number; pollIntervalMs: number;
/** Default timeout for tasks (ms) */
defaultTimeoutMs: number; defaultTimeoutMs: number;
/** Maximum concurrent sessions allowed */
maxConcurrentSessions: number; maxConcurrentSessions: number;
/** Path to state file */
stateFilePath: string; stateFilePath: string;
/** Respawn controller configuration */
respawn: RespawnConfig; respawn: RespawnConfig;
} }
// ========== Output Types ==========
/**
* Output captured from a session
*/
export interface SessionOutput { export interface SessionOutput {
/** Standard output content */
stdout: string; stdout: string;
/** Standard error content */
stderr: string; stderr: string;
/** Exit code of the process, null if still running */
exitCode: number | null; exitCode: number | null;
} }
/**
* Task assignment record
*/
export interface TaskAssignment { export interface TaskAssignment {
/** Session ID that task is assigned to */
sessionId: string; sessionId: string;
/** Task ID being assigned */
taskId: string; taskId: string;
/** Timestamp of assignment */
assignedAt: number; assignedAt: number;
} }
// Error codes for consistent error handling // ========== API Error Handling ==========
/**
* Standard error codes for API responses
*/
export enum ApiErrorCode { export enum ApiErrorCode {
/** Resource not found */
NOT_FOUND = 'NOT_FOUND', NOT_FOUND = 'NOT_FOUND',
/** Invalid input provided */
INVALID_INPUT = 'INVALID_INPUT', INVALID_INPUT = 'INVALID_INPUT',
/** Session is currently busy */
SESSION_BUSY = 'SESSION_BUSY', SESSION_BUSY = 'SESSION_BUSY',
/** Operation failed */
OPERATION_FAILED = 'OPERATION_FAILED', OPERATION_FAILED = 'OPERATION_FAILED',
/** Resource already exists */
ALREADY_EXISTS = 'ALREADY_EXISTS', ALREADY_EXISTS = 'ALREADY_EXISTS',
/** Internal server error */
INTERNAL_ERROR = 'INTERNAL_ERROR', INTERNAL_ERROR = 'INTERNAL_ERROR',
} }
// Mapping of error codes to user-friendly messages /**
* User-friendly error messages for each error code
*/
export const ErrorMessages: Record<ApiErrorCode, string> = { export const ErrorMessages: Record<ApiErrorCode, string> = {
[ApiErrorCode.NOT_FOUND]: 'The requested resource was not found', [ApiErrorCode.NOT_FOUND]: 'The requested resource was not found',
[ApiErrorCode.INVALID_INPUT]: 'Invalid input provided', [ApiErrorCode.INVALID_INPUT]: 'Invalid input provided',
@@ -118,52 +247,105 @@ export const ErrorMessages: Record<ApiErrorCode, string> = {
[ApiErrorCode.INTERNAL_ERROR]: 'An internal error occurred', [ApiErrorCode.INTERNAL_ERROR]: 'An internal error occurred',
}; };
// API Request/Response types for type safety // ========== API Request Types ==========
/**
* Request to create a new session
*/
export interface CreateSessionRequest { export interface CreateSessionRequest {
/** Optional working directory path */
workingDir?: string; workingDir?: string;
} }
/**
* Request to run a prompt in a session
*/
export interface RunPromptRequest { export interface RunPromptRequest {
/** Prompt to send to Claude */
prompt: string; prompt: string;
} }
/**
* Request to send input to a session
*/
export interface SessionInputRequest { export interface SessionInputRequest {
/** Input string to send */
input: string; input: string;
} }
/**
* Request to resize terminal
*/
export interface ResizeRequest { export interface ResizeRequest {
/** Number of columns */
cols: number; cols: number;
/** Number of rows */
rows: number; rows: number;
} }
/**
* Request to create a new case
*/
export interface CreateCaseRequest { export interface CreateCaseRequest {
/** Case name (alphanumeric with hyphens/underscores) */
name: string; name: string;
/** Optional case description */
description?: string; description?: string;
} }
/**
* Request for quick start (create case + session)
*/
export interface QuickStartRequest { export interface QuickStartRequest {
/** Optional case name, defaults to 'testcase' */
caseName?: string; caseName?: string;
} }
/**
* Request to create a scheduled run
*/
export interface CreateScheduledRunRequest { export interface CreateScheduledRunRequest {
/** Prompt to run */
prompt: string; prompt: string;
/** Optional working directory */
workingDir?: string; workingDir?: string;
/** Duration in minutes */
durationMinutes: number; durationMinutes: number;
} }
/**
* Request for quick run (one-shot prompt execution)
*/
export interface QuickRunRequest { export interface QuickRunRequest {
/** Prompt to run */
prompt: string; prompt: string;
/** Optional working directory */
workingDir?: string; workingDir?: string;
} }
// ========== API Response Types ==========
/**
* Standard API response wrapper
* @template T Type of the data payload
*/
export interface ApiResponse<T = unknown> { export interface ApiResponse<T = unknown> {
/** Whether the request succeeded */
success: boolean; success: boolean;
/** Error message if failed */
error?: string; error?: string;
/** Error code for programmatic handling */
errorCode?: ApiErrorCode; errorCode?: ApiErrorCode;
/** Response data payload */
data?: T; data?: T;
} }
// Helper functions for creating consistent error responses /**
* Creates a standardized error response
* @param code Error code
* @param details Optional detailed error message
* @returns Formatted error response
*/
export function createErrorResponse(code: ApiErrorCode, details?: string): ApiResponse { export function createErrorResponse(code: ApiErrorCode, details?: string): ApiResponse {
return { return {
success: false, success: false,
@@ -172,6 +354,12 @@ export function createErrorResponse(code: ApiErrorCode, details?: string): ApiRe
}; };
} }
/**
* Creates a standardized success response
* @template T Type of the data payload
* @param data Optional response data
* @returns Formatted success response
*/
export function createSuccessResponse<T>(data?: T): ApiResponse<T> { export function createSuccessResponse<T>(data?: T): ApiResponse<T> {
return { return {
success: true, success: true,
@@ -179,57 +367,114 @@ export function createSuccessResponse<T>(data?: T): ApiResponse<T> {
}; };
} }
/**
* Response for session operations
*/
export interface SessionResponse { export interface SessionResponse {
/** Whether the request succeeded */
success: boolean; success: boolean;
/** Session details if successful */
session?: SessionState & { session?: SessionState & {
/** Claude session ID from CLI */
claudeSessionId: string | null; claudeSessionId: string | null;
/** Total API cost */
totalCost: number; totalCost: number;
/** Text output buffer */
textOutput: string; textOutput: string;
/** Terminal buffer */
terminalBuffer: string; terminalBuffer: string;
/** Number of messages */
messageCount: number; messageCount: number;
/** Whether Claude is working */
isWorking: boolean; isWorking: boolean;
/** Timestamp of last prompt */
lastPromptTime: number; lastPromptTime: number;
}; };
/** Error message if failed */
error?: string; error?: string;
} }
/**
* Response for quick start operation
*/
export interface QuickStartResponse { export interface QuickStartResponse {
/** Whether the request succeeded */
success: boolean; success: boolean;
/** Created session ID */
sessionId?: string; sessionId?: string;
/** Path to case folder */
casePath?: string; casePath?: string;
/** Case name */
caseName?: string; caseName?: string;
/** Error message if failed */
error?: string; error?: string;
} }
/**
* Information about a case folder
*/
export interface CaseInfo { export interface CaseInfo {
/** Case name */
name: string; name: string;
/** Full path to case folder */
path: string; path: string;
/** Whether CLAUDE.md exists */
hasClaudeMd?: boolean; hasClaudeMd?: boolean;
} }
// Screen session types for GNU screen wrapping // ========== Screen Session Types ==========
/**
* GNU screen session wrapper
*
* Claudeman uses GNU screen for session persistence across server restarts.
*/
export interface ScreenSession { export interface ScreenSession {
sessionId: string; // Claudeman session ID /** Claudeman session ID */
screenName: string; // GNU screen session name sessionId: string;
pid: number; // Screen process PID /** GNU screen session name (claudeman-<id>) */
screenName: string;
/** Screen process PID */
pid: number;
/** Timestamp when created */
createdAt: number; createdAt: number;
/** Working directory */
workingDir: string; workingDir: string;
/** Session mode: claude or shell */
mode: 'claude' | 'shell'; mode: 'claude' | 'shell';
attached: boolean; // Whether webserver is attached /** Whether webserver is attached to this screen */
name?: string; // Session display name (tab name) attached: boolean;
/** Session display name (tab name) */
name?: string;
} }
/**
* Process resource statistics
*/
export interface ProcessStats { export interface ProcessStats {
memoryMB: number; // Memory usage in MB /** Memory usage in megabytes */
cpuPercent: number; // CPU usage percentage memoryMB: number;
childCount: number; // Number of child processes /** CPU usage percentage */
cpuPercent: number;
/** Number of child processes */
childCount: number;
/** Timestamp of stats collection */
updatedAt: number; updatedAt: number;
} }
/**
* Screen session with resource statistics
*/
export interface ScreenSessionWithStats extends ScreenSession { export interface ScreenSessionWithStats extends ScreenSession {
/** Optional resource statistics */
stats?: ProcessStats; stats?: ProcessStats;
} }
// ========== Default Configuration ==========
/**
* Default application configuration values
*/
export const DEFAULT_CONFIG: AppConfig = { export const DEFAULT_CONFIG: AppConfig = {
pollIntervalMs: 1000, pollIntervalMs: 1000,
defaultTimeoutMs: 300000, // 5 minutes defaultTimeoutMs: 300000, // 5 minutes
@@ -246,39 +491,79 @@ export const DEFAULT_CONFIG: AppConfig = {
}; };
// ========== Inner Loop Tracking Types ========== // ========== Inner Loop Tracking Types ==========
// Track Ralph Wiggum loops and todo lists running inside Claude Code sessions
/**
* Types for tracking Ralph Wiggum loops and todo lists
* running inside Claude Code sessions.
*
* This allows Claudeman to detect and display when Claude Code
* is running its own autonomous loops internally.
*/
/** Status of a detected todo item */
export type InnerTodoStatus = 'pending' | 'in_progress' | 'completed'; export type InnerTodoStatus = 'pending' | 'in_progress' | 'completed';
/**
* State of an inner loop (Ralph Wiggum loop inside Claude Code)
*/
export interface InnerLoopState { export interface InnerLoopState {
enabled: boolean; // Whether the tracker is actively monitoring (disabled by default) /** Whether the tracker is actively monitoring (disabled by default) */
enabled: boolean;
/** Whether a loop is currently active */
active: boolean; active: boolean;
/** Detected completion phrase */
completionPhrase: string | null; completionPhrase: string | null;
/** Timestamp when loop started */
startedAt: number | null; startedAt: number | null;
/** Number of cycles/iterations detected */
cycleCount: number; cycleCount: number;
/** Maximum iterations if detected */
maxIterations: number | null; maxIterations: number | null;
/** Timestamp of last activity */
lastActivity: number; lastActivity: number;
/** Elapsed hours if detected */
elapsedHours: number | null; elapsedHours: number | null;
} }
/**
* A detected todo item from Claude Code output
*/
export interface InnerTodoItem { export interface InnerTodoItem {
/** Unique identifier based on content hash */
id: string; id: string;
/** Todo item text content */
content: string; content: string;
/** Current status */
status: InnerTodoStatus; status: InnerTodoStatus;
/** Timestamp when detected */
detectedAt: number; detectedAt: number;
} }
/**
* Complete inner state for a session
*/
export interface InnerSessionState { export interface InnerSessionState {
/** Session this state belongs to */
sessionId: string; sessionId: string;
/** Loop tracking state */
loop: InnerLoopState; loop: InnerLoopState;
/** Detected todo items */
todos: InnerTodoItem[]; todos: InnerTodoItem[];
/** Timestamp of last update */
lastUpdated: number; lastUpdated: number;
} }
/**
* Map of session ID to inner state
*/
export interface InnerStateRecord { export interface InnerStateRecord {
[sessionId: string]: InnerSessionState; [sessionId: string]: InnerSessionState;
} }
/**
* Creates initial inner loop state
* @returns Fresh inner loop state with defaults
*/
export function createInitialInnerLoopState(): InnerLoopState { export function createInitialInnerLoopState(): InnerLoopState {
return { return {
enabled: false, // Disabled by default, auto-enables when Ralph patterns detected enabled: false, // Disabled by default, auto-enables when Ralph patterns detected
@@ -292,6 +577,11 @@ export function createInitialInnerLoopState(): InnerLoopState {
}; };
} }
/**
* Creates initial inner session state
* @param sessionId Session ID this state belongs to
* @returns Fresh inner session state
*/
export function createInitialInnerSessionState(sessionId: string): InnerSessionState { export function createInitialInnerSessionState(sessionId: string): InnerSessionState {
return { return {
sessionId, sessionId,
@@ -301,6 +591,10 @@ export function createInitialInnerSessionState(sessionId: string): InnerSessionS
}; };
} }
/**
* Creates initial application state
* @returns Fresh application state with defaults
*/
export function createInitialState(): AppState { export function createInitialState(): AppState {
return { return {
sessions: {}, sessions: {},