diff --git a/src/Internal/LoggerLib/Logger.ts b/src/Internal/LoggerLib/Logger.ts index 75769486e..c191d531d 100644 --- a/src/Internal/LoggerLib/Logger.ts +++ b/src/Internal/LoggerLib/Logger.ts @@ -707,7 +707,13 @@ export const consoleTransport: ITransport = { }, }; -export const fileTransport = (options: { filePath: string; append?: boolean; encoding?: string }): ITransport => ({ +interface FileTransportOptions { + filePath: string; + append?: boolean; + encoding?: string; +} + +export const fileTransport = (options: FileTransportOptions): ITransport => ({ log(props) { // Here you would implement file writing logic // Using appropriate React Native or Node.js APIs diff --git a/src/ask/AIChat.ts b/src/ask/AIChat.ts index 3f169af44..f63f7ef92 100644 --- a/src/ask/AIChat.ts +++ b/src/ask/AIChat.ts @@ -19,6 +19,11 @@ import { providerManager } from "@ask/providers/ProviderManager"; import type { ChatConfig } from "@ask/types"; import { getLanguageModel } from "@ask/types"; +interface EngineWithRestore { + engine: ChatEngine; + restore: () => void; +} + const DEFAULT_SESSION_DIR = resolve(homedir(), ".genesis-tools/ai-chat/sessions"); export class AIChat { @@ -241,7 +246,7 @@ export class AIChat { /** Get a ChatEngine instance with optional per-call overrides. * Returns a restore function that resets the engine to its previous state. */ - private _getEngine(override?: SendOptions["override"]): { engine: ChatEngine; restore: () => void } { + private _getEngine(override?: SendOptions["override"]): EngineWithRestore { if (!this._engine) { throw new Error("AIChat not initialized"); } diff --git a/src/ask/providers/ProviderManager.ts b/src/ask/providers/ProviderManager.ts index 23adbfe39..b6a5c20f8 100644 --- a/src/ask/providers/ProviderManager.ts +++ b/src/ask/providers/ProviderManager.ts @@ -18,6 +18,11 @@ import { getLanguageModel } from "@ask/types"; import type { AskConfig } from "@ask/types/config"; import { generateText } from "ai"; +interface ModelMetadata { + id: string; + description?: string; +} + export class ProviderManager { private detectedProviders: Map = new Map(); private initialized = false; @@ -598,7 +603,7 @@ export class ProviderManager { }; } - private parseCapabilities(model: { id: string; description?: string }): string[] { + private parseCapabilities(model: ModelMetadata): string[] { const capabilities: string[] = ["chat"]; if (model.description?.toLowerCase().includes("vision") || model.id.toLowerCase().includes("vision")) { diff --git a/src/ask/utils/cli.ts b/src/ask/utils/cli.ts index 5cd09188c..5187b823f 100644 --- a/src/ask/utils/cli.ts +++ b/src/ask/utils/cli.ts @@ -3,6 +3,16 @@ import { SafeJSON } from "@app/utils/json"; import type { Args, CLIOptions, OutputFormat } from "@ask/types"; import { Command } from "commander"; +interface ValidationResult { + valid: boolean; + errors: string[]; +} + +interface OutputFormatResult { + type: OutputFormat; + filename?: string; +} + export function parseCLIArguments(): Args { const program = new Command() .name("ask") @@ -162,7 +172,7 @@ export function showVersion(): void { console.log("Multi-provider LLM chat application for GenesisTools"); } -export function validateOptions(options: CLIOptions): { valid: boolean; errors: string[] } { +export function validateOptions(options: CLIOptions): ValidationResult { const errors: string[] = []; // Validate temperature @@ -253,7 +263,7 @@ export function shouldShowVersion(options: CLIOptions): boolean { * -f json → json to stdout * -f markdown -o out.md → markdown written to file */ -export function getOutputFormat(options: CLIOptions): { type: OutputFormat; filename?: string } | undefined { +export function getOutputFormat(options: CLIOptions): OutputFormatResult | undefined { // -o implies file output if (options.output) { return { type: "file", filename: options.output }; diff --git a/src/ask/utils/websearch.ts b/src/ask/utils/websearch.ts index 1f3669ca9..06390fa00 100644 --- a/src/ask/utils/websearch.ts +++ b/src/ask/utils/websearch.ts @@ -1,6 +1,12 @@ import logger from "@app/logger"; import type { SearchResult, WebSearchOptions } from "@ask/types"; +interface WebSearchParams { + query: string; + numResults?: number; + safeSearch?: string; +} + export class WebSearchTool { private apiKey?: string; private baseURL = "https://api.search.brave.com/res/v1"; @@ -175,7 +181,7 @@ export class WebSearchTool { optional: true, }, }, - execute: async (params: { query: string; numResults?: number; safeSearch?: string }) => { + execute: async (params: WebSearchParams) => { try { const results = await this.searchWeb(params.query, { numResults: params.numResults, diff --git a/src/automate/lib/builtins.ts b/src/automate/lib/builtins.ts index 998161975..678a9a60f 100644 --- a/src/automate/lib/builtins.ts +++ b/src/automate/lib/builtins.ts @@ -3,7 +3,7 @@ import { SafeJSON } from "@app/utils/json"; import * as p from "@clack/prompts"; import { resolveExpression, resolveParams } from "./expressions.ts"; -import type { ExecutionContext, PresetStep, StepResult } from "./types.ts"; +import type { ExecutionContext, PresetStep, StepHandlerResult, StepResult } from "./types.ts"; /** The set of built-in action names that are handled directly (not via Bun.spawn) */ export const BUILTIN_ACTIONS = new Set(["if", "log", "prompt", "shell", "set"]); @@ -20,7 +20,7 @@ export function isBuiltinAction(action: string): boolean { export async function executeBuiltin( step: PresetStep, ctx: ExecutionContext -): Promise<{ result: StepResult; jumpTo?: string }> { +): Promise { const start = Date.now(); switch (step.action) { @@ -40,7 +40,7 @@ export async function executeBuiltin( } /** if -- evaluate condition expression, return jumpTo target step ID */ -function handleIf(step: PresetStep, ctx: ExecutionContext, start: number): { result: StepResult; jumpTo?: string } { +function handleIf(step: PresetStep, ctx: ExecutionContext, start: number): StepHandlerResult { if (!step.condition) { throw new Error(`Step "${step.id}": "if" action requires a "condition" field`); } @@ -60,7 +60,7 @@ function handleIf(step: PresetStep, ctx: ExecutionContext, start: number): { res } /** log -- print a resolved message to console via @clack/prompts */ -function handleLog(step: PresetStep, ctx: ExecutionContext, start: number): { result: StepResult } { +function handleLog(step: PresetStep, ctx: ExecutionContext, start: number): StepHandlerResult { const params = step.params ? resolveParams(step.params as Record, ctx) : {}; const message = String(params.message ?? ""); @@ -76,7 +76,7 @@ function handleLog(step: PresetStep, ctx: ExecutionContext, start: number): { re } /** prompt -- ask user a question interactively, store answer as output */ -async function handlePrompt(step: PresetStep, ctx: ExecutionContext, start: number): Promise<{ result: StepResult }> { +async function handlePrompt(step: PresetStep, ctx: ExecutionContext, start: number): Promise { const params = step.params ? resolveParams(step.params as Record, ctx) : {}; const message = String(params.message ?? "Enter value:"); const defaultValue = params.default != null ? String(params.default) : undefined; @@ -108,7 +108,7 @@ async function handlePrompt(step: PresetStep, ctx: ExecutionContext, start: numb } /** shell -- run a raw shell command via bash, capture stdout/stderr */ -async function handleShell(step: PresetStep, ctx: ExecutionContext, start: number): Promise<{ result: StepResult }> { +async function handleShell(step: PresetStep, ctx: ExecutionContext, start: number): Promise { const params = step.params ? resolveParams(step.params as Record, ctx) : {}; const command = String(params.command ?? params.cmd ?? ""); @@ -162,7 +162,7 @@ async function handleShell(step: PresetStep, ctx: ExecutionContext, start: numbe } /** set -- set key-value pairs into ctx.vars */ -function handleSet(step: PresetStep, ctx: ExecutionContext, start: number): { result: StepResult } { +function handleSet(step: PresetStep, ctx: ExecutionContext, start: number): StepHandlerResult { const params = step.params ? resolveParams(step.params as Record, ctx) : {}; for (const [key, value] of Object.entries(params)) { diff --git a/src/automate/lib/step-runner.ts b/src/automate/lib/step-runner.ts index 5ea76103b..69e6fec9b 100644 --- a/src/automate/lib/step-runner.ts +++ b/src/automate/lib/step-runner.ts @@ -5,7 +5,7 @@ import { executeBuiltin, isBuiltinAction } from "./builtins.ts"; import { resolveExpression, resolveParams } from "./expressions.ts"; import type { StepContext } from "./registry.ts"; import { resolveStepHandler } from "./registry.ts"; -import type { ExecutionContext, PresetStep, StepResult } from "./types.ts"; +import type { ExecutionContext, PresetStep, StepHandlerResult, StepResult } from "./types.ts"; /** * Execute a single step. @@ -18,7 +18,7 @@ export async function executeStep( step: PresetStep, ctx: ExecutionContext, options: { dryRun?: boolean; verbose?: boolean } -): Promise<{ result: StepResult; jumpTo?: string }> { +): Promise { // Dispatch built-in actions if (isBuiltinAction(step.action)) { if (options.dryRun) { diff --git a/src/automate/lib/types.ts b/src/automate/lib/types.ts index e36cb4b43..b66fb555b 100644 --- a/src/automate/lib/types.ts +++ b/src/automate/lib/types.ts @@ -75,6 +75,12 @@ export interface StepResult { error?: string; } +/** Result from a step handler, with optional jump target for branching */ +export interface StepHandlerResult { + result: StepResult; + jumpTo?: string; +} + /** Run options from CLI flags */ export interface RunOptions { dryRun?: boolean; diff --git a/src/azure-devops/commands/timelog/prepare-import.ts b/src/azure-devops/commands/timelog/prepare-import.ts index a5cf8d900..3b17988bb 100644 --- a/src/azure-devops/commands/timelog/prepare-import.ts +++ b/src/azure-devops/commands/timelog/prepare-import.ts @@ -42,6 +42,27 @@ interface PrepareImportFile { entries: StoredEntry[]; } +interface TimelogAddOptions { + from?: string; + to?: string; + name?: string; + entry: string; +} + +interface TimelogRemoveOptions { + name: string; + id: string; +} + +interface TimelogListOptions { + name: string; + format?: string; +} + +interface TimelogClearOptions { + name: string; +} + // ============= Helpers ============= const storage = new Storage("azure-devops"); @@ -83,7 +104,7 @@ function printEntry(entry: StoredEntry): void { // ============= Subcommand Actions ============= -async function handleAdd(options: { from?: string; to?: string; name?: string; entry: string }): Promise { +async function handleAdd(options: TimelogAddOptions): Promise { const fileName = resolveFileName(options); // Parse and validate entry JSON @@ -187,7 +208,7 @@ async function handleAdd(options: { from?: string; to?: string; name?: string; e printEntry(storedEntry); } -async function handleRemove(options: { name: string; id: string }): Promise { +async function handleRemove(options: TimelogRemoveOptions): Promise { const key = cacheKey(options.name); const updated = await storage.atomicUpdate(key, (current) => { @@ -207,7 +228,7 @@ async function handleRemove(options: { name: string; id: string }): Promise { +async function handleList(options: TimelogListOptions): Promise { const key = cacheKey(options.name); const data = await storage.getCacheFile(key, "30 days"); @@ -276,7 +297,7 @@ async function handleList(options: { name: string; format?: string }): Promise { +async function handleClear(options: TimelogClearOptions): Promise { const key = cacheKey(options.name); await storage.deleteCacheFile(key); console.log(`Prepare-import file "${options.name}" cleared.`); diff --git a/src/claude-history-dashboard/src/integrations/tanstack-query/root-provider.tsx b/src/claude-history-dashboard/src/integrations/tanstack-query/root-provider.tsx index 9ac5e8530..63a93c828 100644 --- a/src/claude-history-dashboard/src/integrations/tanstack-query/root-provider.tsx +++ b/src/claude-history-dashboard/src/integrations/tanstack-query/root-provider.tsx @@ -1,5 +1,10 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +interface ProviderProps { + children: React.ReactNode; + queryClient: QueryClient; +} + export function getContext() { const queryClient = new QueryClient(); return { @@ -7,6 +12,6 @@ export function getContext() { }; } -export function Provider({ children, queryClient }: { children: React.ReactNode; queryClient: QueryClient }) { +export function Provider({ children, queryClient }: ProviderProps) { return {children}; } diff --git a/src/github-release-notes/index.ts b/src/github-release-notes/index.ts index 2b285975a..60418d06d 100644 --- a/src/github-release-notes/index.ts +++ b/src/github-release-notes/index.ts @@ -16,6 +16,11 @@ interface GitHubRelease { html_url: string; } +interface RepoIdentity { + owner: string; + repo: string; +} + interface ScriptOptions { owner: string; repo: string; @@ -124,7 +129,7 @@ function generateMarkdown(releases: GitHubRelease[], owner: string, repo: string return headerContent + releasesContent; } -function parseRepoArg(repoArg: string): { owner: string; repo: string } | null { +function parseRepoArg(repoArg: string): RepoIdentity | null { // Accepts owner/repo or full github.com URL if (!repoArg) { return null; diff --git a/src/macos-resources/index.tsx b/src/macos-resources/index.tsx index 76f887d1c..d527cd96c 100644 --- a/src/macos-resources/index.tsx +++ b/src/macos-resources/index.tsx @@ -111,6 +111,24 @@ interface CommandPerformance { timestamp: Date; } +interface MemoizedHeaderProps { + children: React.ReactNode; + sortBy: "cpu" | "pid" | "files"; +} + +interface MemoizedCellProps { + children: React.ReactNode; + column: number; +} + +interface MemoizedNotificationsPanelProps { + notifications: Notification[]; +} + +interface MemoizedCommandPanelProps { + commandHistory: CommandPerformance[]; +} + // Custom Table component using Ink's Box and Text // const Table: React.FC<{ // data: Array>; @@ -147,7 +165,7 @@ const generateTableData = (processes: ProcessInfo[], selectedIndex: number) => { // Memoized header component const MemoizedHeader = React.memo( - ({ children, sortBy }: { children: React.ReactNode; sortBy: "cpu" | "pid" | "files" }) => { + ({ children, sortBy }: MemoizedHeaderProps) => { const headerText = String(children); let sortIndicator = ""; let color = "blue"; @@ -173,7 +191,7 @@ const MemoizedHeader = React.memo( ); // Memoized cell component -const MemoizedCell = React.memo(({ children, column }: { children: React.ReactNode; column: number }) => { +const MemoizedCell = React.memo(({ children, column }: MemoizedCellProps) => { return ( {children} @@ -182,7 +200,7 @@ const MemoizedCell = React.memo(({ children, column }: { children: React.ReactNo }); // Memoized notifications panel -const MemoizedNotificationsPanel = React.memo(({ notifications }: { notifications: Notification[] }) => { +const MemoizedNotificationsPanel = React.memo(({ notifications }: MemoizedNotificationsPanelProps) => { return ( @@ -204,7 +222,7 @@ const MemoizedNotificationsPanel = React.memo(({ notifications }: { notification }); // Memoized command performance panel -const MemoizedCommandPanel = React.memo(({ commandHistory }: { commandHistory: CommandPerformance[] }) => { +const MemoizedCommandPanel = React.memo(({ commandHistory }: MemoizedCommandPanelProps) => { return ( diff --git a/src/markdown-cli/index.ts b/src/markdown-cli/index.ts index c2f0b86b2..1120aa18d 100644 --- a/src/markdown-cli/index.ts +++ b/src/markdown-cli/index.ts @@ -5,6 +5,13 @@ import { type MarkdownRenderOptions, renderMarkdownToCli } from "@app/utils/mark import chokidar from "chokidar"; import { Command, Option } from "commander"; +interface MarkdownCLIOptions { + watch?: boolean; + width?: number; + theme?: string; + color?: boolean; +} + const program = new Command(); program @@ -19,7 +26,7 @@ program .default("dark") ) .option("--no-color", "Strip ANSI color codes from output") - .action((file?: string, opts?: { watch?: boolean; width?: number; theme?: string; color?: boolean }) => { + .action((file?: string, opts?: MarkdownCLIOptions) => { const renderOpts: MarkdownRenderOptions = { width: opts?.width && !Number.isNaN(opts.width) ? opts.width : undefined, theme: (opts?.theme as MarkdownRenderOptions["theme"]) || "dark", diff --git a/src/mcp-manager/utils/command.utils.ts b/src/mcp-manager/utils/command.utils.ts index 6f0e399d3..661c7c109 100644 --- a/src/mcp-manager/utils/command.utils.ts +++ b/src/mcp-manager/utils/command.utils.ts @@ -4,6 +4,16 @@ import { ExitPromptError } from "@inquirer/core"; import { checkbox } from "@inquirer/prompts"; import type { MCPProvider, UnifiedMCPConfig } from "./providers/types.js"; +interface ParsedCommand { + command: string; + args: string[]; +} + +interface KeyValuePair { + key: string; + value: string; +} + /** * Show help message for the mcp-manager tool */ @@ -101,7 +111,7 @@ Non-Interactive Examples (for scripts and AI assistants): * Parse a command string into command and args. * Example: "npx -y @modelcontextprotocol/server-github" -> { command: "npx", args: ["-y", "@modelcontextprotocol/server-github"] } */ -export function parseCommandString(commandString: string): { command: string; args: string[] } { +export function parseCommandString(commandString: string): ParsedCommand { const parts = commandString.trim().split(/\s+/); if (parts.length === 0) { throw new Error("Command string cannot be empty"); @@ -118,7 +128,7 @@ export function parseCommandString(commandString: string): { command: string; ar * @param separator - The separator character (e.g., ":" or "=") * @returns The key-value pair, or null if invalid format */ -function parseSinglePair(input: string, separator: string): { key: string; value: string } | null { +function parseSinglePair(input: string, separator: string): KeyValuePair | null { const str = input.trim(); if (!str) { return null; diff --git a/src/mcp-tsc/LspWorker.ts b/src/mcp-tsc/LspWorker.ts index 271cfd802..0ac093fb3 100644 --- a/src/mcp-tsc/LspWorker.ts +++ b/src/mcp-tsc/LspWorker.ts @@ -64,6 +64,16 @@ interface LspDiagnostic { message: string; } +interface LspDiagnosticsNotification { + uri: string; + diagnostics: LspDiagnostic[]; +} + +interface QueueStats { + length: number; + isProcessing: boolean; +} + // Error types for classification export class LspError extends Error { constructor( @@ -275,7 +285,7 @@ export class LspWorker { // Handle diagnostics notifications this.endpoint.on( "textDocument/publishDiagnostics", - (params: { uri: string; diagnostics: LspDiagnostic[] }) => { + (params: LspDiagnosticsNotification) => { this.handleDiagnosticsNotification(params); } ); @@ -897,7 +907,7 @@ export class LspWorker { } // For testing/debugging - getQueueStats(): { length: number; isProcessing: boolean } { + getQueueStats(): QueueStats { return { length: this.requestQueue.length, isProcessing: this.requestQueue.isProcessing, diff --git a/src/mcp-web-reader/utils/tokens.ts b/src/mcp-web-reader/utils/tokens.ts index c9ac96b84..09fb8692e 100644 --- a/src/mcp-web-reader/utils/tokens.ts +++ b/src/mcp-web-reader/utils/tokens.ts @@ -1,5 +1,11 @@ import { decode, encode } from "gpt-3-encoder"; +interface TokenLimitResult { + text: string; + tokens: number; + truncated: boolean; +} + export function countTokens(text: string): number { try { return encode(text).length; @@ -9,7 +15,7 @@ export function countTokens(text: string): number { } } -export function limitToTokens(text: string, maxTokens?: number): { text: string; tokens: number; truncated: boolean } { +export function limitToTokens(text: string, maxTokens?: number): TokenLimitResult { const tokens = countTokens(text); if (!maxTokens || tokens <= maxTokens) { diff --git a/src/telegram/lib/TGClient.ts b/src/telegram/lib/TGClient.ts index 65ea0b1ba..d2c1e23d2 100644 --- a/src/telegram/lib/TGClient.ts +++ b/src/telegram/lib/TGClient.ts @@ -14,6 +14,10 @@ export interface AuthCallbacks { password: () => Promise; } +interface StopHandle { + stop: () => void; +} + export class TGClient { private client: TelegramClient; @@ -92,7 +96,7 @@ export class TGClient { ); } - startTypingLoop(userId: string, username?: string): { stop: () => void } { + startTypingLoop(userId: string, username?: string): StopHandle { let stopped = false; const tick = async () => { diff --git a/src/utils/markdown/index.ts b/src/utils/markdown/index.ts index be754cd98..6253bbfea 100644 --- a/src/utils/markdown/index.ts +++ b/src/utils/markdown/index.ts @@ -149,7 +149,12 @@ interface TableData { rows: string[][]; } -function parseTableTokens(tokens: Token[], startIdx: number): { data: TableData; endIdx: number } { +interface ParsedTableTokens { + data: TableData; + endIdx: number; +} + +function parseTableTokens(tokens: Token[], startIdx: number): ParsedTableTokens { const data: TableData = { headers: [], alignments: [], rows: [] }; let idx = startIdx;