fix: Remove unused vars and improve type safety. Improve task recovery

This commit is contained in:
gsxdsm
2026-02-17 13:18:40 -08:00
parent 8bb10632b1
commit de021f96bf
68 changed files with 1028 additions and 534 deletions

View File

@@ -6,7 +6,7 @@ import type { Request, Response } from 'express';
import { AgentService } from '../../../services/agent-service.js';
import { createLogger } from '@automaker/utils';
import { getErrorMessage, logError } from '../common.js';
const logger = createLogger('Agent');
const _logger = createLogger('Agent');
export function createStartHandler(agentService: AgentService) {
return async (req: Request, res: Response): Promise<void> => {

View File

@@ -128,7 +128,7 @@ export function logAuthStatus(context: string): void {
*/
export function logError(error: unknown, context: string): void {
logger.error(`${context}:`);
logger.error('Error name:', (error as any)?.name);
logger.error('Error name:', (error as Error)?.name);
logger.error('Error message:', (error as Error)?.message);
logger.error('Error stack:', (error as Error)?.stack);
logger.error('Full error object:', JSON.stringify(error, Object.getOwnPropertyNames(error), 2));

View File

@@ -30,7 +30,7 @@ const DEFAULT_MAX_FEATURES = 50;
* Timeout for Codex models when generating features (5 minutes).
* Codex models are slower and need more time to generate 50+ features.
*/
const CODEX_FEATURE_GENERATION_TIMEOUT_MS = 300000; // 5 minutes
const _CODEX_FEATURE_GENERATION_TIMEOUT_MS = 300000; // 5 minutes
/**
* Type for extracted features JSON response

View File

@@ -29,7 +29,6 @@ import {
updateTechnologyStack,
updateRoadmapPhaseStatus,
type ImplementedFeature,
type RoadmapPhase,
} from '../../lib/xml-extractor.js';
import { getNotificationService } from '../../services/notification-service.js';

View File

@@ -6,7 +6,7 @@
*/
import type { EventEmitter } from '../../lib/events.js';
import type { Feature, BacklogPlanResult, BacklogChange, DependencyUpdate } from '@automaker/types';
import type { Feature, BacklogPlanResult } from '@automaker/types';
import {
DEFAULT_PHASE_MODELS,
isCursorModel,

View File

@@ -3,7 +3,7 @@
*/
import type { Request, Response } from 'express';
import type { BacklogPlanResult, BacklogChange, Feature } from '@automaker/types';
import type { BacklogPlanResult } from '@automaker/types';
import { FeatureLoader } from '../../../services/feature-loader.js';
import { clearBacklogPlan, getErrorMessage, logError, logger } from '../common.js';

View File

@@ -36,7 +36,7 @@ interface ExportRequest {
};
}
export function createExportHandler(featureLoader: FeatureLoader) {
export function createExportHandler(_featureLoader: FeatureLoader) {
const exportService = getFeatureExportService();
return async (req: Request, res: Response): Promise<void> => {

View File

@@ -34,7 +34,7 @@ export function createGenerateTitleHandler(
): (req: Request, res: Response) => Promise<void> {
return async (req: Request, res: Response): Promise<void> => {
try {
const { description, projectPath } = req.body as GenerateTitleRequestBody;
const { description } = req.body as GenerateTitleRequestBody;
if (!description || typeof description !== 'string') {
const response: GenerateTitleErrorResponse = {

View File

@@ -33,7 +33,7 @@ interface ConflictInfo {
hasConflict: boolean;
}
export function createImportHandler(featureLoader: FeatureLoader) {
export function createImportHandler(_featureLoader: FeatureLoader) {
const exportService = getFeatureExportService();
return async (req: Request, res: Response): Promise<void> => {

View File

@@ -35,9 +35,9 @@ export function createMkdirHandler() {
error: 'Path exists and is not a directory',
});
return;
} catch (statError: any) {
} catch (statError: unknown) {
// ENOENT means path doesn't exist - we should create it
if (statError.code !== 'ENOENT') {
if ((statError as NodeJS.ErrnoException).code !== 'ENOENT') {
// Some other error (could be ELOOP in parent path)
throw statError;
}
@@ -47,7 +47,7 @@ export function createMkdirHandler() {
await secureFs.mkdir(resolvedPath, { recursive: true });
res.json({ success: true });
} catch (error: any) {
} catch (error: unknown) {
// Path not allowed - return 403 Forbidden
if (error instanceof PathNotAllowedError) {
res.status(403).json({ success: false, error: getErrorMessage(error) });
@@ -55,7 +55,7 @@ export function createMkdirHandler() {
}
// Handle ELOOP specifically
if (error.code === 'ELOOP') {
if ((error as NodeJS.ErrnoException).code === 'ELOOP') {
logError(error, 'Create directory failed - symlink loop detected');
res.status(400).json({
success: false,

View File

@@ -10,7 +10,11 @@ import { getErrorMessage, logError } from '../common.js';
export function createResolveDirectoryHandler() {
return async (req: Request, res: Response): Promise<void> => {
try {
const { directoryName, sampleFiles, fileCount } = req.body as {
const {
directoryName,
sampleFiles,
fileCount: _fileCount,
} = req.body as {
directoryName: string;
sampleFiles?: string[];
fileCount?: number;

View File

@@ -11,10 +11,9 @@ import { getBoardDir } from '@automaker/platform';
export function createSaveBoardBackgroundHandler() {
return async (req: Request, res: Response): Promise<void> => {
try {
const { data, filename, mimeType, projectPath } = req.body as {
const { data, filename, projectPath } = req.body as {
data: string;
filename: string;
mimeType: string;
projectPath: string;
};

View File

@@ -12,10 +12,9 @@ import { sanitizeFilename } from '@automaker/utils';
export function createSaveImageHandler() {
return async (req: Request, res: Response): Promise<void> => {
try {
const { data, filename, mimeType, projectPath } = req.body as {
const { data, filename, projectPath } = req.body as {
data: string;
filename: string;
mimeType: string;
projectPath: string;
};

View File

@@ -5,7 +5,7 @@
import type { Request, Response } from 'express';
import * as secureFs from '../../../lib/secure-fs.js';
import path from 'path';
import { isPathAllowed, PathNotAllowedError, getAllowedRootDirectory } from '@automaker/platform';
import { isPathAllowed, getAllowedRootDirectory } from '@automaker/platform';
import { getErrorMessage, logError } from '../common.js';
export function createValidatePathHandler() {

View File

@@ -37,9 +37,12 @@ export function createGeminiRoutes(): Router {
const provider = new GeminiProvider();
const status = await provider.detectInstallation();
const authMethod =
(status as any).authMethod ||
(status.authenticated ? (status.hasApiKey ? 'api_key' : 'cli_login') : 'none');
// Derive authMethod from typed InstallationStatus fields
const authMethod = status.authenticated
? status.hasApiKey
? 'api_key'
: 'cli_login'
: 'none';
res.json({
success: true,
@@ -48,7 +51,7 @@ export function createGeminiRoutes(): Router {
path: status.path || null,
authenticated: status.authenticated || false,
authMethod,
hasCredentialsFile: (status as any).hasCredentialsFile || false,
hasCredentialsFile: false,
});
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';

View File

@@ -6,7 +6,6 @@ import type { Request, Response } from 'express';
import type { EventEmitter } from '../../../lib/events.js';
import type { IssueValidationEvent } from '@automaker/types';
import {
isValidationRunning,
getValidationStatus,
getRunningValidations,
abortValidation,
@@ -15,7 +14,6 @@ import {
logger,
} from './validation-common.js';
import {
readValidation,
getAllValidations,
getValidationWithFreshness,
deleteValidation,

View File

@@ -12,7 +12,7 @@ export function createProvidersHandler() {
// Get installation status from all providers
const statuses = await ProviderFactory.checkAllProviders();
const providers: Record<string, any> = {
const providers: Record<string, Record<string, unknown>> = {
anthropic: {
available: statuses.claude?.installed || false,
hasApiKey: !!process.env.ANTHROPIC_API_KEY,

View File

@@ -46,16 +46,14 @@ export function createUpdateGlobalHandler(settingsService: SettingsService) {
}
// Minimal debug logging to help diagnose accidental wipes.
const projectsLen = Array.isArray((updates as any).projects)
? (updates as any).projects.length
: undefined;
const trashedLen = Array.isArray((updates as any).trashedProjects)
? (updates as any).trashedProjects.length
const projectsLen = Array.isArray(updates.projects) ? updates.projects.length : undefined;
const trashedLen = Array.isArray(updates.trashedProjects)
? updates.trashedProjects.length
: undefined;
logger.info(
`[SERVER_SETTINGS_UPDATE] Request received: projects=${projectsLen ?? 'n/a'}, trashedProjects=${trashedLen ?? 'n/a'}, theme=${
(updates as any).theme ?? 'n/a'
}, localStorageMigrated=${(updates as any).localStorageMigrated ?? 'n/a'}`
updates.theme ?? 'n/a'
}, localStorageMigrated=${updates.localStorageMigrated ?? 'n/a'}`
);
// Get old settings to detect theme changes

View File

@@ -4,13 +4,9 @@
import type { Request, Response } from 'express';
import { getErrorMessage, logError } from '../common.js';
import { exec } from 'child_process';
import { promisify } from 'util';
import * as fs from 'fs';
import * as path from 'path';
const execAsync = promisify(exec);
export function createAuthClaudeHandler() {
return async (_req: Request, res: Response): Promise<void> => {
try {

View File

@@ -4,13 +4,9 @@
import type { Request, Response } from 'express';
import { logError, getErrorMessage } from '../common.js';
import { exec } from 'child_process';
import { promisify } from 'util';
import * as fs from 'fs';
import * as path from 'path';
const execAsync = promisify(exec);
export function createAuthOpencodeHandler() {
return async (_req: Request, res: Response): Promise<void> => {
try {

View File

@@ -10,9 +10,6 @@ import type { Request, Response } from 'express';
import { CopilotProvider } from '../../../providers/copilot-provider.js';
import { getErrorMessage, logError } from '../common.js';
import type { ModelDefinition } from '@automaker/types';
import { createLogger } from '@automaker/utils';
const logger = createLogger('CopilotModelsRoute');
// Singleton provider instance for caching
let providerInstance: CopilotProvider | null = null;

View File

@@ -14,9 +14,6 @@ import {
} from '../../../providers/opencode-provider.js';
import { getErrorMessage, logError } from '../common.js';
import type { ModelDefinition } from '@automaker/types';
import { createLogger } from '@automaker/utils';
const logger = createLogger('OpenCodeModelsRoute');
// Singleton provider instance for caching
let providerInstance: OpencodeProvider | null = null;

View File

@@ -151,7 +151,7 @@ export function createVerifyClaudeAuthHandler() {
AuthSessionManager.createSession(sessionId, authMethod || 'api_key', apiKey, 'anthropic');
// Create temporary environment override for SDK call
const cleanupEnv = createTempEnvOverride(authEnv);
const _cleanupEnv = createTempEnvOverride(authEnv);
// Run a minimal query to verify authentication
const stream = query({
@@ -194,8 +194,10 @@ export function createVerifyClaudeAuthHandler() {
}
// Check specifically for assistant messages with text content
if (msg.type === 'assistant' && (msg as any).message?.content) {
const content = (msg as any).message.content;
const msgRecord = msg as Record<string, unknown>;
const msgMessage = msgRecord.message as Record<string, unknown> | undefined;
if (msg.type === 'assistant' && msgMessage?.content) {
const content = msgMessage.content;
if (Array.isArray(content)) {
for (const block of content) {
if (block.type === 'text' && block.text) {

View File

@@ -5,7 +5,6 @@
import { randomBytes } from 'crypto';
import { createLogger } from '@automaker/utils';
import type { Request, Response, NextFunction } from 'express';
import { getTerminalService } from '../../services/terminal-service.js';
const logger = createLogger('Terminal');

View File

@@ -9,7 +9,6 @@ import {
generateToken,
addToken,
getTokenExpiryMs,
getErrorMessage,
} from '../common.js';
export function createAuthHandler() {

View File

@@ -31,8 +31,8 @@ export async function getTrackedBranches(projectPath: string): Promise<TrackedBr
const content = (await secureFs.readFile(filePath, 'utf-8')) as string;
const data: BranchTrackingData = JSON.parse(content);
return data.branches || [];
} catch (error: any) {
if (error.code === 'ENOENT') {
} catch (error: unknown) {
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
return [];
}
logger.warn('Failed to read tracked branches:', error);

View File

@@ -117,7 +117,7 @@ export function createCreatePRHandler() {
cwd: worktreePath,
env: execEnv,
});
} catch (error: unknown) {
} catch {
// If push fails, try with --set-upstream
try {
await execAsync(`git push --set-upstream origin ${branchName}`, {
@@ -195,7 +195,7 @@ export function createCreatePRHandler() {
}
}
}
} catch (error) {
} catch {
// Couldn't parse remotes - will try fallback
}
@@ -216,7 +216,7 @@ export function createCreatePRHandler() {
originOwner = owner;
repoUrl = `https://github.com/${owner}/${repo}`;
}
} catch (error) {
} catch {
// Failed to get repo URL from config
}
}

View File

@@ -51,7 +51,7 @@ export function createDeleteHandler() {
// Remove the worktree (using array arguments to prevent injection)
try {
await execGitCommand(['worktree', 'remove', worktreePath, '--force'], projectPath);
} catch (error) {
} catch {
// Try with prune if remove fails
await execGitCommand(['worktree', 'prune'], projectPath);
}

View File

@@ -64,31 +64,8 @@ export function createZaiRoutes(
router.post('/configure', async (req: Request, res: Response) => {
try {
const { apiToken, apiHost } = req.body;
if (apiToken !== undefined) {
// Set in-memory token
usageService.setApiToken(apiToken || '');
// Persist to credentials (deep merge happens in updateCredentials)
try {
await settingsService.updateCredentials({
apiKeys: { zai: apiToken || '' },
} as Parameters<typeof settingsService.updateCredentials>[0]);
logger.info('[configure] Saved z.ai API key to credentials');
} catch (persistError) {
logger.error('[configure] Failed to persist z.ai API key:', persistError);
}
}
if (apiHost) {
usageService.setApiHost(apiHost);
}
res.json({
success: true,
message: 'z.ai configuration updated',
isAvailable: usageService.isAvailable(),
});
const result = await usageService.configure({ apiToken, apiHost }, settingsService);
res.json(result);
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';
logger.error('Error configuring z.ai:', error);
@@ -100,50 +77,8 @@ export function createZaiRoutes(
router.post('/verify', async (req: Request, res: Response) => {
try {
const { apiKey } = req.body;
if (!apiKey || typeof apiKey !== 'string' || apiKey.trim().length === 0) {
res.json({
success: false,
authenticated: false,
error: 'Please provide an API key to test.',
});
return;
}
// Test the key by making a request to z.ai API
const quotaUrl =
process.env.Z_AI_QUOTA_URL ||
`${process.env.Z_AI_API_HOST ? `https://${process.env.Z_AI_API_HOST}` : 'https://api.z.ai'}/api/monitor/usage/quota/limit`;
logger.info(`[verify] Testing API key against: ${quotaUrl}`);
const response = await fetch(quotaUrl, {
method: 'GET',
headers: {
Authorization: `Bearer ${apiKey.trim()}`,
Accept: 'application/json',
},
});
if (response.ok) {
res.json({
success: true,
authenticated: true,
message: 'Connection successful! z.ai API responded.',
});
} else if (response.status === 401 || response.status === 403) {
res.json({
success: false,
authenticated: false,
error: 'Invalid API key. Please check your key and try again.',
});
} else {
res.json({
success: false,
authenticated: false,
error: `API request failed: ${response.status} ${response.statusText}`,
});
}
const result = await usageService.verifyApiKey(apiKey);
res.json(result);
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';
logger.error('Error verifying z.ai API key:', error);