443 lines · 13.8 KB · TypeScript
RawDownload
/** * IPC API type definitions for Electron preload bridge. * * These types define the interface exposed to the renderer process * via contextBridge. The actual implementation lives in src/preload/index.ts. * * Shared between preload and renderer processes. */ import type {  AppConfig,  DetectedError,  NotificationTrigger,  TriggerTestResult,} from './notifications';import type { WaterfallData } from './visualization';import type {  ConversationGroup,  FileChangeEvent,  PaginatedSessionsResult,  Project,  RepositoryGroup,  SearchSessionsResult,  Session,  SessionDetail,  SessionMetrics,  SessionsByIdsOptions,  SessionsPaginationOptions,  SubagentDetail,} from '@main/types'; // =============================================================================// Agent Config// ============================================================================= export interface AgentConfig {  name: string;  color?: string;} // =============================================================================// Notifications API// ============================================================================= /** * Result of notifications:get with pagination. */interface NotificationsResult {  notifications: DetectedError[];  total: number;  totalCount: number;  unreadCount: number;  hasMore: boolean;} /** * Notifications API exposed via preload. * Note: Event callbacks use `unknown` types because IPC data cannot be typed at the preload layer. * Consumers should cast to DetectedError or NotificationClickData as appropriate. */export interface NotificationsAPI {  get: (options?: { limit?: number; offset?: number }) => Promise<NotificationsResult>;  markRead: (id: string) => Promise<boolean>;  markAllRead: () => Promise<boolean>;  delete: (id: string) => Promise<boolean>;  clear: () => Promise<boolean>;  getUnreadCount: () => Promise<number>;  onNew: (callback: (event: unknown, error: unknown) => void) => () => void;  onUpdated: (    callback: (event: unknown, payload: { total: number; unreadCount: number }) => void  ) => () => void;  onClicked: (callback: (event: unknown, data: unknown) => void) => () => void;} // =============================================================================// Config API// ============================================================================= /** * Config API exposed via preload. */export interface ConfigAPI {  get: () => Promise<AppConfig>;  update: (section: string, data: object) => Promise<AppConfig>;  addIgnoreRegex: (pattern: string) => Promise<AppConfig>;  removeIgnoreRegex: (pattern: string) => Promise<AppConfig>;  addIgnoreRepository: (repositoryId: string) => Promise<AppConfig>;  removeIgnoreRepository: (repositoryId: string) => Promise<AppConfig>;  snooze: (minutes: number) => Promise<AppConfig>;  clearSnooze: () => Promise<AppConfig>;  // Trigger management methods  addTrigger: (trigger: Omit<NotificationTrigger, 'isBuiltin'>) => Promise<AppConfig>;  updateTrigger: (triggerId: string, updates: Partial<NotificationTrigger>) => Promise<AppConfig>;  removeTrigger: (triggerId: string) => Promise<AppConfig>;  getTriggers: () => Promise<NotificationTrigger[]>;  testTrigger: (trigger: NotificationTrigger) => Promise<TriggerTestResult>;  /** Opens native folder selection dialog and returns selected paths */  selectFolders: () => Promise<string[]>;  /** Open native dialog to select local Claude root folder */  selectClaudeRootFolder: () => Promise<ClaudeRootFolderSelection | null>;  /** Get resolved Claude root path info for local mode */  getClaudeRootInfo: () => Promise<ClaudeRootInfo>;  /** Find Windows WSL Claude root candidates (UNC paths) */  findWslClaudeRoots: () => Promise<WslClaudeRootCandidate[]>;  /** Opens the config JSON file in an external editor */  openInEditor: () => Promise<void>;  /** Pin a session for a project */  pinSession: (projectId: string, sessionId: string) => Promise<void>;  /** Unpin a session for a project */  unpinSession: (projectId: string, sessionId: string) => Promise<void>;  /** Hide a session for a project */  hideSession: (projectId: string, sessionId: string) => Promise<void>;  /** Unhide a session for a project */  unhideSession: (projectId: string, sessionId: string) => Promise<void>;  /** Bulk hide sessions for a project */  hideSessions: (projectId: string, sessionIds: string[]) => Promise<void>;  /** Bulk unhide sessions for a project */  unhideSessions: (projectId: string, sessionIds: string[]) => Promise<void>;} export interface ClaudeRootInfo {  /** Auto-detected default Claude root path for this machine */  defaultPath: string;  /** Effective path currently used by local context */  resolvedPath: string;  /** Custom override path from settings (null means auto-detect) */  customPath: string | null;} export interface ClaudeRootFolderSelection {  /** Selected directory absolute path */  path: string;  /** Whether the selected folder name is exactly ".claude" */  isClaudeDirName: boolean;  /** Whether selected folder contains a "projects" directory */  hasProjectsDir: boolean;} export interface WslClaudeRootCandidate {  /** WSL distribution name (e.g. Ubuntu) */  distro: string;  /** Candidate Claude root path in UNC format */  path: string;  /** True if this root contains "projects" directory */  hasProjectsDir: boolean;} // =============================================================================// Session API// ============================================================================= /** * Session navigation API exposed via preload. */export interface SessionAPI {  scrollToLine: (sessionId: string, lineNumber: number) => Promise<void>;} // =============================================================================// CLAUDE.md File Info// ============================================================================= /** * CLAUDE.md file information returned from reading operations. */export interface ClaudeMdFileInfo {  path: string;  exists: boolean;  charCount: number;  estimatedTokens: number;} // =============================================================================// Updater API// ============================================================================= /** * Status payload sent from the main process updater to the renderer. */export interface UpdaterStatus {  type: 'checking' | 'available' | 'not-available' | 'downloading' | 'downloaded' | 'error';  version?: string;  releaseNotes?: string;  progress?: { percent: number; transferred: number; total: number };  error?: string;} /** * Updater API exposed via preload. */export interface UpdaterAPI {  check: () => Promise<void>;  download: () => Promise<void>;  install: () => Promise<void>;  onStatus: (callback: (event: unknown, status: unknown) => void) => () => void;} // =============================================================================// Context API// ============================================================================= /** * Context information for listing available contexts. */export interface ContextInfo {  id: string;  type: 'local' | 'ssh';} // =============================================================================// SSH API// ============================================================================= /** * SSH connection state. */export type SshConnectionState = 'disconnected' | 'connecting' | 'connected' | 'error'; /** * SSH authentication method. */export type SshAuthMethod = 'password' | 'privateKey' | 'agent' | 'auto'; /** * SSH config host entry resolved from ~/.ssh/config. */export interface SshConfigHostEntry {  alias: string;  hostName?: string;  user?: string;  port?: number;  hasIdentityFile: boolean;} /** * SSH connection configuration sent from renderer. */export interface SshConnectionConfig {  host: string;  port: number;  username: string;  authMethod: SshAuthMethod;  password?: string;  privateKeyPath?: string;} /** * Saved SSH connection profile (no password stored). */export interface SshConnectionProfile {  id: string;  name: string;  host: string;  port: number;  username: string;  authMethod: SshAuthMethod;  privateKeyPath?: string;} /** * SSH connection status returned from main process. */export interface SshConnectionStatus {  state: SshConnectionState;  host: string | null;  error: string | null;  remoteProjectsPath: string | null;} /** * SSH API exposed via preload. *//** * Saved SSH connection config (no password). */export interface SshLastConnection {  host: string;  port: number;  username: string;  authMethod: SshAuthMethod;  privateKeyPath?: string;} export interface SshAPI {  connect: (config: SshConnectionConfig) => Promise<SshConnectionStatus>;  disconnect: () => Promise<SshConnectionStatus>;  getState: () => Promise<SshConnectionStatus>;  test: (config: SshConnectionConfig) => Promise<{ success: boolean; error?: string }>;  getConfigHosts: () => Promise<SshConfigHostEntry[]>;  resolveHost: (alias: string) => Promise<SshConfigHostEntry | null>;  saveLastConnection: (config: SshLastConnection) => Promise<void>;  getLastConnection: () => Promise<SshLastConnection | null>;  onStatus: (callback: (event: unknown, status: SshConnectionStatus) => void) => () => void;} // =============================================================================// HTTP Server API// ============================================================================= /** * HTTP server status returned from main process. */export interface HttpServerStatus {  running: boolean;  port: number;} /** * HTTP Server API for controlling the sidecar server. */export interface HttpServerAPI {  start: () => Promise<HttpServerStatus>;  stop: () => Promise<HttpServerStatus>;  getStatus: () => Promise<HttpServerStatus>;} // =============================================================================// Main Electron API// ============================================================================= /** * Complete Electron API exposed to the renderer process via preload script. */export interface ElectronAPI {  getAppVersion: () => Promise<string>;  getProjects: () => Promise<Project[]>;  getSessions: (projectId: string) => Promise<Session[]>;  getSessionsPaginated: (    projectId: string,    cursor: string | null,    limit?: number,    options?: SessionsPaginationOptions  ) => Promise<PaginatedSessionsResult>;  searchSessions: (    projectId: string,    query: string,    maxResults?: number  ) => Promise<SearchSessionsResult>;  searchAllProjects: (query: string, maxResults?: number) => Promise<SearchSessionsResult>;  getSessionDetail: (projectId: string, sessionId: string) => Promise<SessionDetail | null>;  getSessionMetrics: (projectId: string, sessionId: string) => Promise<SessionMetrics | null>;  getWaterfallData: (projectId: string, sessionId: string) => Promise<WaterfallData | null>;  getSubagentDetail: (    projectId: string,    sessionId: string,    subagentId: string  ) => Promise<SubagentDetail | null>;  getSessionGroups: (projectId: string, sessionId: string) => Promise<ConversationGroup[]>;  getSessionsByIds: (    projectId: string,    sessionIds: string[],    options?: SessionsByIdsOptions  ) => Promise<Session[]>;   // Repository grouping (worktree support)  getRepositoryGroups: () => Promise<RepositoryGroup[]>;  getWorktreeSessions: (worktreeId: string) => Promise<Session[]>;   // Validation methods  validatePath: (    relativePath: string,    projectPath: string  ) => Promise<{ exists: boolean; isDirectory?: boolean }>;  validateMentions: (    mentions: { type: 'path'; value: string }[],    projectPath: string  ) => Promise<Record<string, boolean>>;   // CLAUDE.md reading methods  readClaudeMdFiles: (projectRoot: string) => Promise<Record<string, ClaudeMdFileInfo>>;  readDirectoryClaudeMd: (dirPath: string) => Promise<ClaudeMdFileInfo>;  readMentionedFile: (    absolutePath: string,    projectRoot: string,    maxTokens?: number  ) => Promise<ClaudeMdFileInfo | null>;   // Agent config reading  readAgentConfigs: (projectRoot: string) => Promise<Record<string, AgentConfig>>;   // Notifications API  notifications: NotificationsAPI;   // Config API  config: ConfigAPI;   // Deep link navigation  session: SessionAPI;   // Window zoom sync (for traffic-light-safe layout)  getZoomFactor: () => Promise<number>;  onZoomFactorChanged: (callback: (zoomFactor: number) => void) => () => void;   // File change events (real-time updates)  onFileChange: (callback: (event: FileChangeEvent) => void) => () => void;  onTodoChange: (callback: (event: FileChangeEvent) => void) => () => void;   // Session refresh (Ctrl+R / Cmd+R intercepted by main process)  onSessionRefresh: (callback: () => void) => () => void;   // Shell operations  openPath: (    targetPath: string,    projectRoot?: string  ) => Promise<{ success: boolean; error?: string }>;  openExternal: (url: string) => Promise<{ success: boolean; error?: string }>;   // Window controls (when title bar is hidden, e.g. Windows / Linux)  windowControls: {    minimize: () => Promise<void>;    maximize: () => Promise<void>;    close: () => Promise<void>;    isMaximized: () => Promise<boolean>;    relaunch: () => Promise<void>;  };   // Updater API  updater: UpdaterAPI;   // SSH API  ssh: SshAPI;   // Context API  context: {    list: () => Promise<ContextInfo[]>;    getActive: () => Promise<string>;    switch: (contextId: string) => Promise<{ contextId: string }>;    onChanged: (callback: (event: unknown, data: ContextInfo) => void) => () => void;  };   // HTTP Server API  httpServer: HttpServerAPI;} // =============================================================================// Window Type Extension// ============================================================================= declare global {  interface Window {    electronAPI: ElectronAPI;  }}