UNPKG

@codervisor/devlog-ai

Version:

AI Chat History Extractor & Docker-based Automation - TypeScript implementation for GitHub Copilot and other AI coding assistants with automated testing capabilities

287 lines (262 loc) 8.17 kB
/** * Data models for AI Chat processing * * TypeScript interfaces and classes for representing chat histories * focused on core chat functionality. * * Note: These models are for internal AI package use. For devlog integration, * use the types from @codervisor/devlog-core/types/chat. */ import { z } from 'zod'; import type { ChatSession as CoreChatSession, ChatMessage as CoreChatMessage, AgentType, ChatRole, ChatStatus, } from '@codervisor/devlog-core'; // Specific metadata type definitions export interface MessageMetadata { type?: 'user_request' | 'assistant_response' | 'editing_session' | 'snapshot'; agent?: Record<string, unknown>; variableData?: Record<string, unknown>; modelId?: string; result?: Record<string, unknown>; followups?: unknown[]; isCanceled?: boolean; contentReferences?: unknown[]; codeCitations?: unknown[]; requestTimestamp?: string; [key: string]: unknown; // Allow additional properties } export interface ChatSessionMetadata { version?: string; requesterUsername?: string; responderUsername?: string; initialLocation?: Record<string, unknown>; creationDate?: string; lastMessageDate?: string; isImported?: boolean; customTitle?: string; type?: 'chat_session' | 'chat_editing_session' | string; // Allow any string for flexibility source_file?: string; linearHistoryIndex?: number; initialFileContents?: unknown[]; recentSnapshot?: unknown; total_requests?: number; [key: string]: unknown; // Allow additional properties } export interface WorkspaceMetadata { discovered_files_count?: number; parsing_errors?: string[]; total_sessions_discovered?: number; discovery_timestamp?: string; vscode_installations?: string[]; [key: string]: unknown; // Allow additional properties } // Zod schemas for runtime validation with more specific metadata export const MessageSchema = z.object({ id: z.string().optional(), role: z.enum(['user', 'assistant']), content: z.string(), timestamp: z.string().datetime(), metadata: z.record(z.unknown()).default({}), }); export const ChatSessionSchema = z.object({ agent: z.string(), timestamp: z.string().datetime(), messages: z.array(MessageSchema).default([]), workspace: z.string().optional(), session_id: z.string().optional(), metadata: z.record(z.unknown()).default({}), }); export const WorkspaceDataSchema = z.object({ agent: z.string(), version: z.string().optional(), workspace_path: z.string().optional(), chat_sessions: z.array(ChatSessionSchema).default([]), metadata: z.record(z.unknown()).default({}), }); // TypeScript interfaces export interface Message { /** Unique identifier for the message */ id?: string; /** Role of the message sender */ role: 'user' | 'assistant'; /** Content of the message */ content: string; /** Timestamp when the message was created */ timestamp: Date; /** Additional metadata */ metadata: MessageMetadata; } export interface ChatSession { /** Name of the AI agent (e.g., "copilot", "cursor", "windsurf") */ agent: string; /** Timestamp when the session was created */ timestamp: Date; /** List of messages in the session */ messages: Message[]; /** Workspace identifier or path */ workspace?: string; /** Unique session identifier */ session_id?: string; /** Additional metadata */ metadata: ChatSessionMetadata; } export interface WorkspaceData { /** Name of the AI agent */ agent: string; /** Version of the agent or data format */ version?: string; /** Path to the workspace */ workspace_path?: string; /** List of chat sessions */ chat_sessions: ChatSession[]; /** Additional metadata */ metadata: WorkspaceMetadata; } export interface SearchResult { session_id?: string; message_id?: string; role: string; timestamp: string; match_position: number; context: string; full_content: string; metadata: Record<string, unknown>; } export interface ChatStatistics { total_sessions: number; total_messages: number; message_types: Record<string, number>; session_types: Record<string, number>; workspace_activity: Record< string, { sessions: number; messages: number; first_seen: string; last_seen: string; } >; date_range: { earliest: string | null; latest: string | null; }; agent_activity: Record<string, number>; } // Utility classes for data manipulation export class MessageData implements Message { id?: string; role: 'user' | 'assistant'; content: string; timestamp: Date; metadata: MessageMetadata; constructor(data: Partial<Message> & Pick<Message, 'role' | 'content'>) { this.id = data.id; this.role = data.role; this.content = data.content; this.timestamp = data.timestamp || new Date(); this.metadata = data.metadata || {}; } toDict(): Record<string, unknown> { return { id: this.id, role: this.role, content: this.content, timestamp: this.timestamp.toISOString(), metadata: this.metadata, }; } static fromDict(data: Record<string, unknown>): MessageData { const validated = MessageSchema.parse(data); return new MessageData({ id: validated.id, role: validated.role, content: validated.content, timestamp: new Date(validated.timestamp), metadata: validated.metadata as MessageMetadata, }); } } export class ChatSessionData implements ChatSession { agent: string; timestamp: Date; messages: Message[]; workspace?: string; session_id?: string; metadata: ChatSessionMetadata; constructor(data: Partial<ChatSession> & Pick<ChatSession, 'agent'>) { this.agent = data.agent; this.timestamp = data.timestamp || new Date(); this.messages = data.messages || []; this.workspace = data.workspace; this.session_id = data.session_id; this.metadata = data.metadata || {}; } toDict(): Record<string, unknown> { return { agent: this.agent, timestamp: this.timestamp.toISOString(), messages: this.messages.map((msg) => msg instanceof MessageData ? msg.toDict() : new MessageData(msg).toDict(), ), workspace: this.workspace, session_id: this.session_id, metadata: this.metadata, }; } static fromDict(data: Record<string, unknown>): ChatSessionData { const validated = ChatSessionSchema.parse(data); return new ChatSessionData({ agent: validated.agent, timestamp: new Date(validated.timestamp), messages: validated.messages.map((msgData: unknown) => MessageData.fromDict(msgData as Record<string, unknown>), ), workspace: validated.workspace, session_id: validated.session_id, metadata: validated.metadata as ChatSessionMetadata, }); } } export class WorkspaceDataContainer implements WorkspaceData { agent: string; version?: string; workspace_path?: string; chat_sessions: ChatSession[]; metadata: WorkspaceMetadata; constructor(data: Partial<WorkspaceData> & Pick<WorkspaceData, 'agent'>) { this.agent = data.agent; this.version = data.version; this.workspace_path = data.workspace_path; this.chat_sessions = data.chat_sessions || []; this.metadata = data.metadata || {}; } toDict(): Record<string, unknown> { return { agent: this.agent, version: this.version, workspace_path: this.workspace_path, chat_sessions: this.chat_sessions.map((session) => session instanceof ChatSessionData ? session.toDict() : new ChatSessionData(session).toDict(), ), metadata: this.metadata, }; } static fromDict(data: Record<string, unknown>): WorkspaceDataContainer { const validated = WorkspaceDataSchema.parse(data); return new WorkspaceDataContainer({ agent: validated.agent, version: validated.version, workspace_path: validated.workspace_path, chat_sessions: validated.chat_sessions.map((sessionData: unknown) => ChatSessionData.fromDict(sessionData as Record<string, unknown>), ), metadata: validated.metadata as WorkspaceMetadata, }); } }