From 51f8f3545c39d892b425d6016ff20df95e451c46 Mon Sep 17 00:00:00 2001 From: iliya Date: Mon, 16 Mar 2026 20:48:42 +0200 Subject: [PATCH] style: auto-fix import/export sorting and formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ran pnpm lint:fix to resolve 220 auto-fixable lint issues. All changes are import/export reordering — no logic changes. --- src/main/index.ts | 48 +++--- src/main/ipc/crossTeam.ts | 4 +- src/main/ipc/extensions.ts | 47 +++--- src/main/ipc/handlers.ts | 12 +- src/main/ipc/skills.ts | 29 ++-- src/main/ipc/teams.ts | 16 +- .../extensions/ExtensionFacadeService.ts | 11 +- .../extensions/apikeys/ApiKeyService.ts | 8 +- .../extensions/catalog/GitHubStarsService.ts | 10 +- .../catalog/GlamaMcpEnrichmentService.ts | 3 +- .../catalog/McpCatalogAggregator.ts | 9 +- .../catalog/OfficialMcpRegistryService.ts | 3 +- .../catalog/PluginCatalogService.ts | 11 +- src/main/services/extensions/index.ts | 32 ++-- .../extensions/install/McpInstallService.ts | 2 +- .../install/PluginInstallService.ts | 2 +- .../extensions/skills/SkillImportService.ts | 8 +- .../extensions/skills/SkillMetadataParser.ts | 8 +- .../extensions/skills/SkillPlanService.ts | 13 +- .../extensions/skills/SkillReviewService.ts | 2 +- .../extensions/skills/SkillRootsResolver.ts | 3 +- .../extensions/skills/SkillScaffoldService.ts | 3 +- .../extensions/skills/SkillScanner.ts | 4 +- .../extensions/skills/SkillsCatalogService.ts | 5 +- .../skills/SkillsMutationService.ts | 18 +-- .../extensions/skills/SkillsWatcherService.ts | 4 +- .../state/McpInstallationStateService.ts | 5 +- .../state/PluginInstallationStateService.ts | 11 +- src/main/services/index.ts | 4 +- .../schedule/JsonScheduleRepository.ts | 2 +- .../schedule/ScheduledTaskExecutor.ts | 2 +- .../services/schedule/SchedulerService.ts | 8 +- src/main/services/schedule/index.ts | 6 +- .../services/team/ChangeExtractorService.ts | 2 +- src/main/services/team/CrossTeamService.ts | 2 +- src/main/services/team/TeamBackupService.ts | 26 +-- .../services/team/TeamMcpConfigBuilder.ts | 5 +- .../services/team/TeamProvisioningService.ts | 34 ++-- .../JsonTaskChangeSummaryCacheRepository.ts | 2 +- .../cache/taskChangeSummaryCacheSchema.ts | 2 +- src/main/workers/team-fs-worker.ts | 4 +- src/preload/index.ts | 128 +++++++-------- .../chat/viewers/MarkdownViewer.tsx | 152 +++++++++++++++--- .../components/common/ErrorBoundary.tsx | 7 +- .../extensions/ExtensionStoreView.tsx | 8 +- .../extensions/ExtensionsSubTabTrigger.tsx | 7 +- .../extensions/apikeys/ApiKeyCard.tsx | 2 +- .../extensions/common/InstallButton.tsx | 15 +- .../extensions/common/InstallCountBadge.tsx | 3 +- .../extensions/mcp/CustomMcpServerDialog.tsx | 2 +- .../extensions/mcp/McpServerCard.tsx | 10 +- .../extensions/mcp/McpServerDetailDialog.tsx | 10 +- .../extensions/mcp/McpServersPanel.tsx | 2 +- .../extensions/plugins/PluginCard.tsx | 4 +- .../extensions/plugins/PluginDetailDialog.tsx | 9 +- .../extensions/skills/SkillCodeEditor.tsx | 2 +- .../extensions/skills/SkillEditorDialog.tsx | 4 +- .../extensions/skills/SkillImportDialog.tsx | 2 +- .../extensions/skills/SkillsPanel.tsx | 8 +- .../extensions/skills/skillDraftUtils.ts | 4 +- .../components/layout/TabBarActions.tsx | 2 +- .../components/schedules/SchedulesView.tsx | 4 +- .../settings/sections/ConfigEditorDialog.tsx | 2 +- .../sections/NotificationsSection.tsx | 10 +- .../components/sidebar/GlobalTaskList.tsx | 1 - .../components/sidebar/SidebarTaskItem.tsx | 2 +- src/renderer/components/team/TaskTooltip.tsx | 2 +- .../components/team/TeamDetailView.tsx | 7 +- .../team/TeamProvisioningBanner.tsx | 2 +- .../components/team/ToolApprovalSheet.tsx | 4 +- .../team/activity/ActiveTasksBlock.tsx | 2 +- .../components/team/activity/ActivityItem.tsx | 6 +- .../team/activity/ActivityTimeline.tsx | 3 +- .../team/activity/LeadThoughtsGroup.tsx | 3 +- .../team/activity/MessageExpandDialog.tsx | 5 +- .../team/activity/PendingRepliesBlock.tsx | 4 +- .../team/activity/ThoughtBodyContent.tsx | 2 +- .../team/attachments/ImageLightbox.tsx | 2 +- .../attachments/SourceMessageAttachments.tsx | 7 +- .../team/dialogs/AddMemberDialog.tsx | 2 +- .../team/dialogs/CreateTeamDialog.tsx | 6 +- .../team/dialogs/LaunchTeamDialog.tsx | 21 ++- .../team/dialogs/LimitContextCheckbox.tsx | 3 +- .../team/dialogs/OptionalSettingsSection.tsx | 2 +- .../team/dialogs/StatusHistoryTimeline.tsx | 2 +- .../team/dialogs/TaskCommentInput.tsx | 9 +- .../team/dialogs/TaskDetailDialog.tsx | 23 +-- .../team/kanban/KanbanFilterPopover.tsx | 3 +- .../team/kanban/KanbanSearchInput.tsx | 2 +- .../components/team/kanban/KanbanTaskCard.tsx | 2 +- .../team/members/MemberDraftRow.tsx | 2 +- .../components/team/members/MemberLogsTab.tsx | 18 ++- .../team/members/membersEditorUtils.ts | 4 +- .../team/messages/ActionModeSelector.tsx | 3 +- .../team/messages/MessageComposer.tsx | 7 +- .../team/messages/MessagesPanel.tsx | 11 +- .../team/review/ChangesLoadingAnimation.tsx | 6 +- .../team/review/FullDiffLoadingBanner.tsx | 2 +- .../team/schedule/ScheduleRunLogDialog.tsx | 1 + .../team/schedule/ScheduleSection.tsx | 3 +- .../team/schedule/ScheduleStatusBadge.tsx | 2 +- .../components/ui/MentionSuggestionList.tsx | 2 +- .../components/ui/MentionableTextarea.tsx | 38 ++--- .../components/ui/tiptap/TiptapBubbleMenu.tsx | 7 +- .../components/ui/tiptap/TiptapEditor.tsx | 13 +- .../components/ui/tiptap/TiptapToolbar.tsx | 20 ++- src/renderer/components/ui/tiptap/index.ts | 2 +- .../components/ui/tiptap/useTiptapEditor.ts | 3 +- src/renderer/hooks/useComposerDraft.ts | 2 +- src/renderer/hooks/useMentionDetection.ts | 2 +- src/renderer/services/commentReadStorage.ts | 2 +- src/renderer/services/composerDraftStorage.ts | 2 +- src/renderer/store/index.ts | 2 +- src/renderer/store/slices/extensionsSlice.ts | 2 +- src/renderer/store/slices/scheduleSlice.ts | 2 +- src/renderer/store/slices/teamSlice.ts | 13 +- src/renderer/utils/chipUtils.ts | 5 +- src/renderer/utils/taskChangeRequest.ts | 5 +- src/shared/constants/crossTeam.ts | 2 +- src/shared/types/api.ts | 16 +- src/shared/types/extensions/api.ts | 4 +- src/shared/types/extensions/index.ts | 61 ++++--- src/shared/types/team.ts | 2 +- src/shared/utils/taskChangeState.ts | 4 +- 124 files changed, 672 insertions(+), 552 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 9624b6ec..7884e7b7 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -16,17 +16,17 @@ // On Windows this saturates all threads, blocking the event loop. process.env.UV_THREADPOOL_SIZE ??= '16'; -import { CrossTeamService } from '@main/services/team/CrossTeamService'; -import { TeamConfigReader } from '@main/services/team/TeamConfigReader'; -import { TeamInboxWriter } from '@main/services/team/TeamInboxWriter'; +import { JsonScheduleRepository } from '@main/services/schedule/JsonScheduleRepository'; +import { ScheduledTaskExecutor } from '@main/services/schedule/ScheduledTaskExecutor'; +import { SchedulerService } from '@main/services/schedule/SchedulerService'; import { ChangeExtractorService } from '@main/services/team/ChangeExtractorService'; +import { CrossTeamService } from '@main/services/team/CrossTeamService'; import { FileContentResolver } from '@main/services/team/FileContentResolver'; import { GitDiffFallback } from '@main/services/team/GitDiffFallback'; import { ReviewApplierService } from '@main/services/team/ReviewApplierService'; import { TeamBackupService } from '@main/services/team/TeamBackupService'; -import { JsonScheduleRepository } from '@main/services/schedule/JsonScheduleRepository'; -import { ScheduledTaskExecutor } from '@main/services/schedule/ScheduledTaskExecutor'; -import { SchedulerService } from '@main/services/schedule/SchedulerService'; +import { TeamConfigReader } from '@main/services/team/TeamConfigReader'; +import { TeamInboxWriter } from '@main/services/team/TeamInboxWriter'; import { CONTEXT_CHANGED, SCHEDULE_CHANGE, @@ -51,16 +51,32 @@ import { existsSync } from 'fs'; import { join } from 'path'; import { cleanupEditorState, setEditorMainWindow } from './ipc/editor'; -import { setReviewMainWindow } from './ipc/review'; import { initializeIpcHandlers, removeIpcHandlers } from './ipc/handlers'; +import { setReviewMainWindow } from './ipc/review'; +import { + ApiKeyService, + ExtensionFacadeService, + GlamaMcpEnrichmentService, + McpCatalogAggregator, + McpHealthDiagnosticsService, + McpInstallationStateService, + McpInstallService, + OfficialMcpRegistryService, + PluginCatalogService, + PluginInstallationStateService, + PluginInstallService, + SkillsCatalogService, + SkillsMutationService, + SkillsWatcherService, +} from './services/extensions'; import { startEventLoopLagMonitor } from './services/infrastructure/EventLoopLagMonitor'; import { HttpServer } from './services/infrastructure/HttpServer'; -import { TeamInboxReader } from './services/team/TeamInboxReader'; import { buildTeamControlApiBaseUrl, clearTeamControlApiState, writeTeamControlApiState, } from './services/team/TeamControlApiState'; +import { TeamInboxReader } from './services/team/TeamInboxReader'; import { TeamSentMessagesStore } from './services/team/TeamSentMessagesStore'; import { getAppIconPath } from './utils/appIcon'; import { getProjectsBasePath, getTeamsBasePath, getTodosBasePath } from './utils/pathDecoder'; @@ -80,22 +96,6 @@ import { TeamProvisioningService, UpdaterService, } from './services'; -import { - ApiKeyService, - ExtensionFacadeService, - GlamaMcpEnrichmentService, - McpCatalogAggregator, - McpHealthDiagnosticsService, - McpInstallationStateService, - McpInstallService, - OfficialMcpRegistryService, - PluginCatalogService, - PluginInstallationStateService, - PluginInstallService, - SkillsCatalogService, - SkillsMutationService, - SkillsWatcherService, -} from './services/extensions'; import type { FileChangeEvent } from '@main/types'; import type { TeamChangeEvent } from '@shared/types'; diff --git a/src/main/ipc/crossTeam.ts b/src/main/ipc/crossTeam.ts index 11b0fff8..84efe4c0 100644 --- a/src/main/ipc/crossTeam.ts +++ b/src/main/ipc/crossTeam.ts @@ -7,10 +7,12 @@ import { import { createLogger } from '@shared/utils/logger'; import { isAgentActionMode } from '../services/team/actionModeInstructions'; + import { validateTaskId, validateTeamName } from './guards'; + import type { CrossTeamService } from '../services/team/CrossTeamService'; -import type { IpcMain, IpcMainInvokeEvent } from 'electron'; import type { IpcResult, TaskRef } from '@shared/types'; +import type { IpcMain, IpcMainInvokeEvent } from 'electron'; const logger = createLogger('IPC:crossTeam'); diff --git a/src/main/ipc/extensions.ts b/src/main/ipc/extensions.ts index d2948f79..0efa4db2 100644 --- a/src/main/ipc/extensions.ts +++ b/src/main/ipc/extensions.ts @@ -6,30 +6,6 @@ * Phase 5: install/uninstall mutations. */ -import { createLogger } from '@shared/utils/logger'; -import type { - ApiKeyEntry, - ApiKeyLookupResult, - ApiKeySaveRequest, - ApiKeyStorageStatus, - EnrichedPlugin, - InstalledMcpEntry, - McpCatalogItem, - McpCustomInstallRequest, - McpInstallRequest, - McpServerDiagnostic, - McpSearchResult, - OperationResult, - PluginInstallRequest, -} from '@shared/types/extensions'; -import type { IpcMain, IpcMainInvokeEvent } from 'electron'; - -import type { ExtensionFacadeService } from '../services/extensions/ExtensionFacadeService'; -import type { PluginInstallService } from '../services/extensions/install/PluginInstallService'; -import type { McpInstallService } from '../services/extensions/install/McpInstallService'; -import type { ApiKeyService } from '../services/extensions/apikeys/ApiKeyService'; -import type { McpHealthDiagnosticsService } from '../services/extensions/state/McpHealthDiagnosticsService'; - import { API_KEYS_DELETE, API_KEYS_LIST, @@ -50,9 +26,32 @@ import { PLUGIN_INSTALL, PLUGIN_UNINSTALL, } from '@preload/constants/ipcChannels'; +import { createLogger } from '@shared/utils/logger'; import { GitHubStarsService } from '../services/extensions/catalog/GitHubStarsService'; +import type { ApiKeyService } from '../services/extensions/apikeys/ApiKeyService'; +import type { ExtensionFacadeService } from '../services/extensions/ExtensionFacadeService'; +import type { McpInstallService } from '../services/extensions/install/McpInstallService'; +import type { PluginInstallService } from '../services/extensions/install/PluginInstallService'; +import type { McpHealthDiagnosticsService } from '../services/extensions/state/McpHealthDiagnosticsService'; +import type { + ApiKeyEntry, + ApiKeyLookupResult, + ApiKeySaveRequest, + ApiKeyStorageStatus, + EnrichedPlugin, + InstalledMcpEntry, + McpCatalogItem, + McpCustomInstallRequest, + McpInstallRequest, + McpSearchResult, + McpServerDiagnostic, + OperationResult, + PluginInstallRequest, +} from '@shared/types/extensions'; +import type { IpcMain, IpcMainInvokeEvent } from 'electron'; + const logger = createLogger('IPC:extensions'); /** Allowed scope values */ diff --git a/src/main/ipc/handlers.ts b/src/main/ipc/handlers.ts index d1f44da1..9f57c9dc 100644 --- a/src/main/ipc/handlers.ts +++ b/src/main/ipc/handlers.ts @@ -65,8 +65,8 @@ import { registerSessionHandlers, removeSessionHandlers, } from './sessions'; -import { initializeSshHandlers, registerSshHandlers, removeSshHandlers } from './ssh'; import { initializeSkillsHandlers, registerSkillsHandlers, removeSkillsHandlers } from './skills'; +import { initializeSshHandlers, registerSshHandlers, removeSshHandlers } from './ssh'; import { initializeSubagentHandlers, registerSubagentHandlers, @@ -103,18 +103,18 @@ import type { TeamProvisioningService, UpdaterService, } from '../services'; -import type { HttpServer } from '../services/infrastructure/HttpServer'; -import type { CrossTeamService } from '../services/team/CrossTeamService'; -import type { TeamBackupService } from '../services/team/TeamBackupService'; +import type { ApiKeyService } from '../services/extensions/apikeys/ApiKeyService'; import type { ExtensionFacadeService } from '../services/extensions/ExtensionFacadeService'; import type { McpInstallService } from '../services/extensions/install/McpInstallService'; import type { PluginInstallService } from '../services/extensions/install/PluginInstallService'; -import type { ApiKeyService } from '../services/extensions/apikeys/ApiKeyService'; -import type { McpHealthDiagnosticsService } from '../services/extensions/state/McpHealthDiagnosticsService'; import type { SkillsCatalogService } from '../services/extensions/skills/SkillsCatalogService'; import type { SkillsMutationService } from '../services/extensions/skills/SkillsMutationService'; import type { SkillsWatcherService } from '../services/extensions/skills/SkillsWatcherService'; +import type { McpHealthDiagnosticsService } from '../services/extensions/state/McpHealthDiagnosticsService'; +import type { HttpServer } from '../services/infrastructure/HttpServer'; import type { SchedulerService } from '../services/schedule/SchedulerService'; +import type { CrossTeamService } from '../services/team/CrossTeamService'; +import type { TeamBackupService } from '../services/team/TeamBackupService'; /** * Initializes IPC handlers with service registry. diff --git a/src/main/ipc/skills.ts b/src/main/ipc/skills.ts index 701dc673..57bf35a7 100644 --- a/src/main/ipc/skills.ts +++ b/src/main/ipc/skills.ts @@ -1,18 +1,3 @@ -import { createLogger } from '@shared/utils/logger'; -import type { - SkillCatalogItem, - SkillDeleteRequest, - SkillDetail, - SkillImportRequest, - SkillReviewPreview, - SkillUpsertRequest, -} from '@shared/types/extensions'; -import type { IpcMain, IpcMainInvokeEvent } from 'electron'; - -import type { SkillsCatalogService } from '../services/extensions/skills/SkillsCatalogService'; -import type { SkillsMutationService } from '../services/extensions/skills/SkillsMutationService'; -import type { SkillsWatcherService } from '../services/extensions/skills/SkillsWatcherService'; - import { SKILLS_APPLY_IMPORT, SKILLS_APPLY_UPSERT, @@ -24,6 +9,20 @@ import { SKILLS_START_WATCHING, SKILLS_STOP_WATCHING, } from '@preload/constants/ipcChannels'; +import { createLogger } from '@shared/utils/logger'; + +import type { SkillsCatalogService } from '../services/extensions/skills/SkillsCatalogService'; +import type { SkillsMutationService } from '../services/extensions/skills/SkillsMutationService'; +import type { SkillsWatcherService } from '../services/extensions/skills/SkillsWatcherService'; +import type { + SkillCatalogItem, + SkillDeleteRequest, + SkillDetail, + SkillImportRequest, + SkillReviewPreview, + SkillUpsertRequest, +} from '@shared/types/extensions'; +import type { IpcMain, IpcMainInvokeEvent } from 'electron'; const logger = createLogger('IPC:skills'); diff --git a/src/main/ipc/teams.ts b/src/main/ipc/teams.ts index 05abaf4c..a2693474 100644 --- a/src/main/ipc/teams.ts +++ b/src/main/ipc/teams.ts @@ -1,5 +1,3 @@ -import crypto from 'crypto'; - import { setCurrentMainOp } from '@main/services/infrastructure/EventLoopLagMonitor'; import { getAppIconPath } from '@main/utils/appIcon'; import { getAppDataPath } from '@main/utils/pathDecoder'; @@ -29,8 +27,8 @@ import { TEAM_LAUNCH, TEAM_LEAD_ACTIVITY, TEAM_LEAD_CONTEXT, - TEAM_MEMBER_SPAWN_STATUSES, TEAM_LIST, + TEAM_MEMBER_SPAWN_STATUSES, TEAM_PERMANENTLY_DELETE, TEAM_PREPARE_PROVISIONING, TEAM_PROCESS_ALIVE, @@ -72,17 +70,18 @@ import { } from '@shared/utils/cliArgsParser'; import { createLogger } from '@shared/utils/logger'; import { isRateLimitMessage } from '@shared/utils/rateLimitDetector'; +import crypto from 'crypto'; import { BrowserWindow, type IpcMain, type IpcMainInvokeEvent, Notification } from 'electron'; import * as fs from 'fs'; import * as path from 'path'; import { ConfigManager } from '../services/infrastructure/ConfigManager'; import { NotificationManager } from '../services/infrastructure/NotificationManager'; +import { gitIdentityResolver } from '../services/parsing/GitIdentityResolver'; import { buildActionModeAgentBlock, isAgentActionMode, } from '../services/team/actionModeInstructions'; -import { gitIdentityResolver } from '../services/parsing/GitIdentityResolver'; import { TeamAttachmentStore } from '../services/team/TeamAttachmentStore'; import { buildAddMemberSpawnMessage } from '../services/team/TeamProvisioningService'; import { TeamTaskAttachmentStore } from '../services/team/TeamTaskAttachmentStore'; @@ -113,13 +112,13 @@ import type { GlobalTask, IpcResult, KanbanColumnId, - LeadContextUsage, LeadActivitySnapshot, + LeadContextUsage, LeadContextUsageSnapshot, MemberFullStats, - MemberSpawnStatusesSnapshot, MemberLogSummary, MemberSpawnStatusEntry, + MemberSpawnStatusesSnapshot, SendMessageRequest, SendMessageResult, TaskAttachmentMeta, @@ -548,7 +547,10 @@ async function handlePermanentlyDeleteTeam( .rm(path.join(appData, 'attachments', validated.value!), { recursive: true, force: true }) .catch(() => undefined); await fs.promises - .rm(path.join(appData, 'task-attachments', validated.value!), { recursive: true, force: true }) + .rm(path.join(appData, 'task-attachments', validated.value!), { + recursive: true, + force: true, + }) .catch(() => undefined); // Mark in backup registry AFTER successful deletion if (teamBackupService) { diff --git a/src/main/services/extensions/ExtensionFacadeService.ts b/src/main/services/extensions/ExtensionFacadeService.ts index 7a5df4f9..9bdf2632 100644 --- a/src/main/services/extensions/ExtensionFacadeService.ts +++ b/src/main/services/extensions/ExtensionFacadeService.ts @@ -7,6 +7,12 @@ */ import { createLogger } from '@shared/utils/logger'; + +import { type McpCatalogAggregator } from './catalog/McpCatalogAggregator'; +import { type PluginCatalogService } from './catalog/PluginCatalogService'; +import { type McpInstallationStateService } from './state/McpInstallationStateService'; +import { type PluginInstallationStateService } from './state/PluginInstallationStateService'; + import type { EnrichedPlugin, InstalledMcpEntry, @@ -15,11 +21,6 @@ import type { PluginCatalogItem, } from '@shared/types/extensions'; -import { PluginCatalogService } from './catalog/PluginCatalogService'; -import { McpCatalogAggregator } from './catalog/McpCatalogAggregator'; -import { PluginInstallationStateService } from './state/PluginInstallationStateService'; -import { McpInstallationStateService } from './state/McpInstallationStateService'; - const logger = createLogger('Extensions:Facade'); export class ExtensionFacadeService { diff --git a/src/main/services/extensions/apikeys/ApiKeyService.ts b/src/main/services/extensions/apikeys/ApiKeyService.ts index be754ad3..790eaa45 100644 --- a/src/main/services/extensions/apikeys/ApiKeyService.ts +++ b/src/main/services/extensions/apikeys/ApiKeyService.ts @@ -9,12 +9,14 @@ * Storage file: ~/.claude/api-keys.json */ -import { safeStorage } from 'electron'; -import fs from 'node:fs/promises'; -import path from 'node:path'; import crypto from 'node:crypto'; +import fs from 'node:fs/promises'; import os from 'node:os'; +import path from 'node:path'; + import { createLogger } from '@shared/utils/logger'; +import { safeStorage } from 'electron'; + import type { ApiKeyEntry, ApiKeyLookupResult, diff --git a/src/main/services/extensions/catalog/GitHubStarsService.ts b/src/main/services/extensions/catalog/GitHubStarsService.ts index 99ebfa6c..7458a76e 100644 --- a/src/main/services/extensions/catalog/GitHubStarsService.ts +++ b/src/main/services/extensions/catalog/GitHubStarsService.ts @@ -9,8 +9,8 @@ import https from 'node:https'; -import { createLogger } from '@shared/utils/logger'; import { parseGitHubOwnerRepo } from '@shared/utils/extensionNormalizers'; +import { createLogger } from '@shared/utils/logger'; const logger = createLogger('Extensions:GitHubStars'); @@ -39,7 +39,7 @@ export class GitHubStarsService { */ async fetchStars(repositoryUrls: string[]): Promise> { const result: Record = {}; - const tasks: Array<{ url: string; owner: string; repo: string }> = []; + const tasks: { url: string; owner: string; repo: string }[] = []; for (const url of repositoryUrls) { const parsed = parseGitHubOwnerRepo(url); @@ -107,10 +107,10 @@ export class GitHubStarsService { * Run async tasks with a concurrency limit. */ private async withConcurrencyLimit( - tasks: Array<() => Promise>, + tasks: (() => Promise)[], limit: number - ): Promise> { - const results: Array<'ok' | 'error'> = []; + ): Promise<('ok' | 'error')[]> { + const results: ('ok' | 'error')[] = []; let index = 0; const run = async (): Promise => { diff --git a/src/main/services/extensions/catalog/GlamaMcpEnrichmentService.ts b/src/main/services/extensions/catalog/GlamaMcpEnrichmentService.ts index 01ec4230..3ee0e0df 100644 --- a/src/main/services/extensions/catalog/GlamaMcpEnrichmentService.ts +++ b/src/main/services/extensions/catalog/GlamaMcpEnrichmentService.ts @@ -9,10 +9,11 @@ * Cursor-based pagination (after), no auth required. */ -import https from 'node:https'; import http from 'node:http'; +import https from 'node:https'; import { createLogger } from '@shared/utils/logger'; + import type { McpCatalogItem, McpHostingType, McpToolDef } from '@shared/types/extensions'; const logger = createLogger('Extensions:GlamaMcp'); diff --git a/src/main/services/extensions/catalog/McpCatalogAggregator.ts b/src/main/services/extensions/catalog/McpCatalogAggregator.ts index 11de57e4..df817642 100644 --- a/src/main/services/extensions/catalog/McpCatalogAggregator.ts +++ b/src/main/services/extensions/catalog/McpCatalogAggregator.ts @@ -7,12 +7,13 @@ * - Provides getById() for secure install flow */ -import { createLogger } from '@shared/utils/logger'; -import type { McpCatalogItem, McpSearchResult } from '@shared/types/extensions'; import { normalizeRepoUrl } from '@shared/utils/extensionNormalizers'; +import { createLogger } from '@shared/utils/logger'; -import { OfficialMcpRegistryService } from './OfficialMcpRegistryService'; -import { GlamaMcpEnrichmentService } from './GlamaMcpEnrichmentService'; +import { type GlamaMcpEnrichmentService } from './GlamaMcpEnrichmentService'; +import { type OfficialMcpRegistryService } from './OfficialMcpRegistryService'; + +import type { McpCatalogItem, McpSearchResult } from '@shared/types/extensions'; const logger = createLogger('Extensions:McpAggregator'); diff --git a/src/main/services/extensions/catalog/OfficialMcpRegistryService.ts b/src/main/services/extensions/catalog/OfficialMcpRegistryService.ts index d6279afd..612192a1 100644 --- a/src/main/services/extensions/catalog/OfficialMcpRegistryService.ts +++ b/src/main/services/extensions/catalog/OfficialMcpRegistryService.ts @@ -6,10 +6,11 @@ * Filters for _meta.isLatest to pick only latest versions. */ -import https from 'node:https'; import http from 'node:http'; +import https from 'node:https'; import { createLogger } from '@shared/utils/logger'; + import type { McpAuthHeaderDef, McpCatalogItem, diff --git a/src/main/services/extensions/catalog/PluginCatalogService.ts b/src/main/services/extensions/catalog/PluginCatalogService.ts index 27f73c4f..74eea7ed 100644 --- a/src/main/services/extensions/catalog/PluginCatalogService.ts +++ b/src/main/services/extensions/catalog/PluginCatalogService.ts @@ -8,12 +8,13 @@ * - Deduplicates concurrent requests */ -import https from 'node:https'; import http from 'node:http'; +import https from 'node:https'; -import { createLogger } from '@shared/utils/logger'; -import type { PluginCatalogItem } from '@shared/types/extensions'; import { buildPluginId } from '@shared/utils/extensionNormalizers'; +import { createLogger } from '@shared/utils/logger'; + +import type { PluginCatalogItem } from '@shared/types/extensions'; const logger = createLogger('Extensions:PluginCatalog'); @@ -260,7 +261,7 @@ export class PluginCatalogService { const json = JSON.parse(response.body) as MarketplaceJson; const items = this.parseMarketplace(json); - const etag = (response.headers['etag'] as string) ?? null; + const etag = (response.headers.etag as string) ?? null; this.cache = { items, etag, fetchedAt: Date.now() }; logger.info(`Fetched ${items.length} plugins from marketplace "${json.name}"`); @@ -311,7 +312,7 @@ export class PluginCatalogService { * e.g. https://github.com/org/repo → https://raw.githubusercontent.com/org/repo/main/README.md */ private buildReadmeUrl(repoUrl: string): string | null { - const match = repoUrl.match(/github\.com\/([^/]+)\/([^/]+)/); + const match = /github\.com\/([^/]+)\/([^/]+)/.exec(repoUrl); if (!match) return null; const [, owner, repo] = match; return `https://raw.githubusercontent.com/${owner}/${repo}/main/README.md`; diff --git a/src/main/services/extensions/index.ts b/src/main/services/extensions/index.ts index 1a8d5d7b..957965c1 100644 --- a/src/main/services/extensions/index.ts +++ b/src/main/services/extensions/index.ts @@ -2,26 +2,26 @@ * Extension services barrel export. */ -export { PluginCatalogService } from './catalog/PluginCatalogService'; -export { OfficialMcpRegistryService } from './catalog/OfficialMcpRegistryService'; -export { GlamaMcpEnrichmentService } from './catalog/GlamaMcpEnrichmentService'; -export { McpCatalogAggregator } from './catalog/McpCatalogAggregator'; -export { PluginInstallationStateService } from './state/PluginInstallationStateService'; -export { McpInstallationStateService } from './state/McpInstallationStateService'; -export { McpHealthDiagnosticsService } from './state/McpHealthDiagnosticsService'; -export { ExtensionFacadeService } from './ExtensionFacadeService'; -export { PluginInstallService } from './install/PluginInstallService'; -export { McpInstallService } from './install/McpInstallService'; export { ApiKeyService } from './apikeys/ApiKeyService'; export { GitHubStarsService } from './catalog/GitHubStarsService'; -export { SkillRootsResolver } from './skills/SkillRootsResolver'; -export { SkillScanner } from './skills/SkillScanner'; -export { SkillMetadataParser } from './skills/SkillMetadataParser'; -export { SkillValidator } from './skills/SkillValidator'; -export { SkillsCatalogService } from './skills/SkillsCatalogService'; -export { SkillScaffoldService } from './skills/SkillScaffoldService'; +export { GlamaMcpEnrichmentService } from './catalog/GlamaMcpEnrichmentService'; +export { McpCatalogAggregator } from './catalog/McpCatalogAggregator'; +export { OfficialMcpRegistryService } from './catalog/OfficialMcpRegistryService'; +export { PluginCatalogService } from './catalog/PluginCatalogService'; +export { ExtensionFacadeService } from './ExtensionFacadeService'; +export { McpInstallService } from './install/McpInstallService'; +export { PluginInstallService } from './install/PluginInstallService'; export { SkillImportService } from './skills/SkillImportService'; +export { SkillMetadataParser } from './skills/SkillMetadataParser'; export { SkillPlanService } from './skills/SkillPlanService'; export { SkillReviewService } from './skills/SkillReviewService'; +export { SkillRootsResolver } from './skills/SkillRootsResolver'; +export { SkillScaffoldService } from './skills/SkillScaffoldService'; +export { SkillScanner } from './skills/SkillScanner'; +export { SkillsCatalogService } from './skills/SkillsCatalogService'; export { SkillsMutationService } from './skills/SkillsMutationService'; export { SkillsWatcherService } from './skills/SkillsWatcherService'; +export { SkillValidator } from './skills/SkillValidator'; +export { McpHealthDiagnosticsService } from './state/McpHealthDiagnosticsService'; +export { McpInstallationStateService } from './state/McpInstallationStateService'; +export { PluginInstallationStateService } from './state/PluginInstallationStateService'; diff --git a/src/main/services/extensions/install/McpInstallService.ts b/src/main/services/extensions/install/McpInstallService.ts index 0cb8cf46..ec42a3aa 100644 --- a/src/main/services/extensions/install/McpInstallService.ts +++ b/src/main/services/extensions/install/McpInstallService.ts @@ -10,12 +10,12 @@ import { execCli } from '@main/utils/childProcess'; import { createLogger } from '@shared/utils/logger'; +import type { McpCatalogAggregator } from '../catalog/McpCatalogAggregator'; import type { McpCustomInstallRequest, McpInstallRequest, OperationResult, } from '@shared/types/extensions'; -import type { McpCatalogAggregator } from '../catalog/McpCatalogAggregator'; const logger = createLogger('Extensions:McpInstall'); diff --git a/src/main/services/extensions/install/PluginInstallService.ts b/src/main/services/extensions/install/PluginInstallService.ts index ac4a76b5..d81f24b4 100644 --- a/src/main/services/extensions/install/PluginInstallService.ts +++ b/src/main/services/extensions/install/PluginInstallService.ts @@ -8,8 +8,8 @@ import { execCli } from '@main/utils/childProcess'; import { createLogger } from '@shared/utils/logger'; -import type { OperationResult, PluginInstallRequest } from '@shared/types/extensions'; import type { PluginCatalogService } from '../catalog/PluginCatalogService'; +import type { OperationResult, PluginInstallRequest } from '@shared/types/extensions'; const logger = createLogger('Extensions:PluginInstall'); diff --git a/src/main/services/extensions/skills/SkillImportService.ts b/src/main/services/extensions/skills/SkillImportService.ts index b67c0b01..c44298ba 100644 --- a/src/main/services/extensions/skills/SkillImportService.ts +++ b/src/main/services/extensions/skills/SkillImportService.ts @@ -101,13 +101,11 @@ export class SkillImportService { } } - private async walkDirectory( - rootDir: string - ): Promise<{ - files: Array<{ absolutePath: string; relativePath: string }>; + private async walkDirectory(rootDir: string): Promise<{ + files: { absolutePath: string; relativePath: string }[]; hiddenEntriesSkipped: number; }> { - const allFiles: Array<{ absolutePath: string; relativePath: string }> = []; + const allFiles: { absolutePath: string; relativePath: string }[] = []; let hiddenEntriesSkipped = 0; let totalBytes = 0; diff --git a/src/main/services/extensions/skills/SkillMetadataParser.ts b/src/main/services/extensions/skills/SkillMetadataParser.ts index 5aa82ab4..82971cf2 100644 --- a/src/main/services/extensions/skills/SkillMetadataParser.ts +++ b/src/main/services/extensions/skills/SkillMetadataParser.ts @@ -1,6 +1,9 @@ import * as path from 'node:path'; import { createLogger } from '@shared/utils/logger'; +import YAML from 'yaml'; + +import type { ResolvedSkillRoot } from './SkillRootsResolver'; import type { SkillCatalogItem, SkillDetail, @@ -8,9 +11,6 @@ import type { SkillInvocationMode, SkillValidationIssue, } from '@shared/types/extensions'; -import YAML from 'yaml'; - -import type { ResolvedSkillRoot } from './SkillRootsResolver'; const logger = createLogger('Extensions:SkillParser'); @@ -203,7 +203,7 @@ export class SkillMetadataParser { }; } - const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/u); + const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/u.exec(content); if (!match) { return { rawFrontmatter: null, diff --git a/src/main/services/extensions/skills/SkillPlanService.ts b/src/main/services/extensions/skills/SkillPlanService.ts index 7b357ddf..a855d907 100644 --- a/src/main/services/extensions/skills/SkillPlanService.ts +++ b/src/main/services/extensions/skills/SkillPlanService.ts @@ -1,8 +1,11 @@ +import { createHash } from 'node:crypto'; import * as fs from 'node:fs/promises'; import * as os from 'node:os'; import * as path from 'node:path'; -import { createHash } from 'node:crypto'; +import { SkillScanner } from './SkillScanner'; + +import type { ImportedSkillSourceFile } from './SkillImportService'; import type { SkillDraftFile, SkillReviewFileChange, @@ -10,10 +13,6 @@ import type { SkillReviewSummary, } from '@shared/types/extensions'; -import type { ImportedSkillSourceFile } from './SkillImportService'; - -import { SkillScanner } from './SkillScanner'; - type SkillPlanInputFile = | { relativePath: string; isBinary: false; content: string } | { relativePath: string; isBinary: true; sourceAbsolutePath: string }; @@ -73,7 +72,7 @@ export class SkillPlanService { async applyPlan(plan: SkillExecutionPlan): Promise { const backupRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'skill-plan-backup-')); const createdPaths: string[] = []; - const backups: Array<{ absolutePath: string; backupPath: string }> = []; + const backups: { absolutePath: string; backupPath: string }[] = []; try { for (const [index, change] of plan.changes.entries()) { @@ -200,7 +199,7 @@ export class SkillPlanService { const summary = changes.reduce( (acc, change) => { - acc[`${change.action}d` as 'created' | 'updated' | 'deleted'] += 1; + acc[`${change.action}d`] += 1; if (change.isBinary) { acc.binary += 1; } diff --git a/src/main/services/extensions/skills/SkillReviewService.ts b/src/main/services/extensions/skills/SkillReviewService.ts index 046456eb..d6e52c85 100644 --- a/src/main/services/extensions/skills/SkillReviewService.ts +++ b/src/main/services/extensions/skills/SkillReviewService.ts @@ -2,9 +2,9 @@ import * as fs from 'node:fs/promises'; import * as path from 'node:path'; import { createLogger } from '@shared/utils/logger'; -import type { SkillDraftFile, SkillReviewFileChange } from '@shared/types/extensions'; import type { ImportedSkillSourceFile } from './SkillImportService'; +import type { SkillDraftFile, SkillReviewFileChange } from '@shared/types/extensions'; const logger = createLogger('Extensions:SkillReview'); diff --git a/src/main/services/extensions/skills/SkillRootsResolver.ts b/src/main/services/extensions/skills/SkillRootsResolver.ts index 2f14c61f..288b54e5 100644 --- a/src/main/services/extensions/skills/SkillRootsResolver.ts +++ b/src/main/services/extensions/skills/SkillRootsResolver.ts @@ -1,6 +1,7 @@ import * as path from 'node:path'; import { getHomeDir } from '@main/utils/pathDecoder'; + import type { SkillRootKind, SkillScope } from '@shared/types/extensions'; export interface ResolvedSkillRoot { @@ -10,7 +11,7 @@ export interface ResolvedSkillRoot { rootPath: string; } -const USER_ROOTS: Array<{ rootKind: SkillRootKind; segments: string[] }> = [ +const USER_ROOTS: { rootKind: SkillRootKind; segments: string[] }[] = [ { rootKind: 'claude', segments: ['.claude', 'skills'] }, { rootKind: 'cursor', segments: ['.cursor', 'skills'] }, { rootKind: 'agents', segments: ['.agents', 'skills'] }, diff --git a/src/main/services/extensions/skills/SkillScaffoldService.ts b/src/main/services/extensions/skills/SkillScaffoldService.ts index 4dd051f8..851aec94 100644 --- a/src/main/services/extensions/skills/SkillScaffoldService.ts +++ b/src/main/services/extensions/skills/SkillScaffoldService.ts @@ -2,10 +2,11 @@ import * as fs from 'node:fs/promises'; import * as path from 'node:path'; import { isPathWithinRoot, validateFileName } from '@main/utils/pathValidation'; -import type { SkillDraftFile, SkillRootKind, SkillScope } from '@shared/types/extensions'; import { SkillRootsResolver } from './SkillRootsResolver'; +import type { SkillDraftFile, SkillRootKind, SkillScope } from '@shared/types/extensions'; + export class SkillScaffoldService { constructor(private readonly rootsResolver = new SkillRootsResolver()) {} diff --git a/src/main/services/extensions/skills/SkillScanner.ts b/src/main/services/extensions/skills/SkillScanner.ts index bbb1c5bd..86d281a7 100644 --- a/src/main/services/extensions/skills/SkillScanner.ts +++ b/src/main/services/extensions/skills/SkillScanner.ts @@ -1,10 +1,10 @@ import * as fs from 'node:fs/promises'; import * as path from 'node:path'; -import type { SkillCatalogItem, SkillDirectoryFlags } from '@shared/types/extensions'; - import { SkillMetadataParser, type SkillRelatedFiles } from './SkillMetadataParser'; + import type { ResolvedSkillRoot } from './SkillRootsResolver'; +import type { SkillCatalogItem, SkillDirectoryFlags } from '@shared/types/extensions'; const SKILL_FILE_CANDIDATES = ['SKILL.md', 'Skill.md', 'skill.md'] as const; diff --git a/src/main/services/extensions/skills/SkillsCatalogService.ts b/src/main/services/extensions/skills/SkillsCatalogService.ts index 7e46a233..f207ffd8 100644 --- a/src/main/services/extensions/skills/SkillsCatalogService.ts +++ b/src/main/services/extensions/skills/SkillsCatalogService.ts @@ -2,13 +2,14 @@ import * as fs from 'node:fs/promises'; import * as path from 'node:path'; import { createLogger } from '@shared/utils/logger'; -import type { SkillCatalogItem, SkillDetail } from '@shared/types/extensions'; import { SkillMetadataParser } from './SkillMetadataParser'; -import { SkillRootsResolver, type ResolvedSkillRoot } from './SkillRootsResolver'; +import { type ResolvedSkillRoot, SkillRootsResolver } from './SkillRootsResolver'; import { SkillScanner } from './SkillScanner'; import { SkillValidator } from './SkillValidator'; +import type { SkillCatalogItem, SkillDetail } from '@shared/types/extensions'; + const logger = createLogger('Extensions:SkillsCatalog'); export class SkillsCatalogService { diff --git a/src/main/services/extensions/skills/SkillsMutationService.ts b/src/main/services/extensions/skills/SkillsMutationService.ts index 6cf02a96..0f90ea50 100644 --- a/src/main/services/extensions/skills/SkillsMutationService.ts +++ b/src/main/services/extensions/skills/SkillsMutationService.ts @@ -1,6 +1,15 @@ import * as fs from 'node:fs/promises'; import * as path from 'node:path'; +import { isPathWithinRoot, validateFileName } from '@main/utils/pathValidation'; +import { shell } from 'electron'; + +import { SkillImportService } from './SkillImportService'; +import { SkillPlanService } from './SkillPlanService'; +import { SkillRootsResolver } from './SkillRootsResolver'; +import { SkillScaffoldService } from './SkillScaffoldService'; +import { SkillsCatalogService } from './SkillsCatalogService'; + import type { SkillDeleteRequest, SkillDetail, @@ -8,15 +17,6 @@ import type { SkillReviewPreview, SkillUpsertRequest, } from '@shared/types/extensions'; -import { shell } from 'electron'; - -import { isPathWithinRoot, validateFileName } from '@main/utils/pathValidation'; - -import { SkillImportService } from './SkillImportService'; -import { SkillPlanService } from './SkillPlanService'; -import { SkillScaffoldService } from './SkillScaffoldService'; -import { SkillRootsResolver } from './SkillRootsResolver'; -import { SkillsCatalogService } from './SkillsCatalogService'; export class SkillsMutationService { constructor( diff --git a/src/main/services/extensions/skills/SkillsWatcherService.ts b/src/main/services/extensions/skills/SkillsWatcherService.ts index 08c20dc9..5188656f 100644 --- a/src/main/services/extensions/skills/SkillsWatcherService.ts +++ b/src/main/services/extensions/skills/SkillsWatcherService.ts @@ -1,10 +1,10 @@ -import { createLogger } from '@shared/utils/logger'; -import type { SkillWatcherEvent } from '@shared/types/extensions'; import { isPathWithinRoot } from '@main/utils/pathValidation'; +import { createLogger } from '@shared/utils/logger'; import { watch } from 'chokidar'; import { SkillRootsResolver } from './SkillRootsResolver'; +import type { SkillWatcherEvent } from '@shared/types/extensions'; import type { FSWatcher } from 'chokidar'; const logger = createLogger('Extensions:SkillsWatcher'); diff --git a/src/main/services/extensions/state/McpInstallationStateService.ts b/src/main/services/extensions/state/McpInstallationStateService.ts index 4b75daaf..f947f190 100644 --- a/src/main/services/extensions/state/McpInstallationStateService.ts +++ b/src/main/services/extensions/state/McpInstallationStateService.ts @@ -12,9 +12,10 @@ import * as fs from 'node:fs/promises'; import * as path from 'node:path'; -import { createLogger } from '@shared/utils/logger'; -import type { InstalledMcpEntry } from '@shared/types/extensions'; import { getHomeDir } from '@main/utils/pathDecoder'; +import { createLogger } from '@shared/utils/logger'; + +import type { InstalledMcpEntry } from '@shared/types/extensions'; const logger = createLogger('Extensions:McpState'); diff --git a/src/main/services/extensions/state/PluginInstallationStateService.ts b/src/main/services/extensions/state/PluginInstallationStateService.ts index 08954eb0..382b07f8 100644 --- a/src/main/services/extensions/state/PluginInstallationStateService.ts +++ b/src/main/services/extensions/state/PluginInstallationStateService.ts @@ -11,10 +11,11 @@ import * as fs from 'node:fs/promises'; import * as path from 'node:path'; +import { getClaudeBasePath } from '@main/utils/pathDecoder'; import { createLogger } from '@shared/utils/logger'; + import type { InstalledPluginEntry } from '@shared/types/extensions'; import type { InstallScope } from '@shared/types/extensions'; -import { getClaudeBasePath } from '@main/utils/pathDecoder'; const logger = createLogger('Extensions:PluginState'); @@ -29,24 +30,24 @@ interface InstalledPluginsJson { version: number; plugins: Record< string, // qualifiedName - Array<{ + { scope: string; installPath?: string; version?: string; installedAt?: string; lastUpdated?: string; gitCommitSha?: string; - }> + }[] >; } interface InstallCountsJson { version: number; fetchedAt: string; - counts: Array<{ + counts: { plugin: string; // qualifiedName format unique_installs: number; - }>; + }[]; } // ── Cache ────────────────────────────────────────────────────────────────── diff --git a/src/main/services/index.ts b/src/main/services/index.ts index 23d40919..55abfc31 100644 --- a/src/main/services/index.ts +++ b/src/main/services/index.ts @@ -12,8 +12,8 @@ export * from './analysis'; export * from './discovery'; export * from './error'; +export * from './extensions'; export * from './infrastructure'; export * from './parsing'; -export * from './team'; export * from './schedule'; -export * from './extensions'; +export * from './team'; diff --git a/src/main/services/schedule/JsonScheduleRepository.ts b/src/main/services/schedule/JsonScheduleRepository.ts index bbb8461c..0de15c33 100644 --- a/src/main/services/schedule/JsonScheduleRepository.ts +++ b/src/main/services/schedule/JsonScheduleRepository.ts @@ -15,8 +15,8 @@ import { createLogger } from '@shared/utils/logger'; import * as fs from 'fs'; import * as path from 'path'; -import type { Schedule, ScheduleRun } from '@shared/types'; import type { ScheduleRepository } from './ScheduleRepository'; +import type { Schedule, ScheduleRun } from '@shared/types'; const logger = createLogger('Service:JsonScheduleRepo'); diff --git a/src/main/services/schedule/ScheduledTaskExecutor.ts b/src/main/services/schedule/ScheduledTaskExecutor.ts index 6dab6fd8..4bd19749 100644 --- a/src/main/services/schedule/ScheduledTaskExecutor.ts +++ b/src/main/services/schedule/ScheduledTaskExecutor.ts @@ -41,7 +41,7 @@ function extractSummaryFromStreamJson(stdout: string): string { const content = (parsed.content ?? (parsed.message as Record | undefined)?.content) as - | Array<{ type?: string; text?: string }> + | { type?: string; text?: string }[] | undefined; if (!Array.isArray(content)) continue; diff --git a/src/main/services/schedule/SchedulerService.ts b/src/main/services/schedule/SchedulerService.ts index 94bcb803..43039ce1 100644 --- a/src/main/services/schedule/SchedulerService.ts +++ b/src/main/services/schedule/SchedulerService.ts @@ -10,6 +10,8 @@ import { createLogger } from '@shared/utils/logger'; import { Cron } from 'croner'; import { randomUUID } from 'crypto'; +import type { ScheduledTaskExecutor } from './ScheduledTaskExecutor'; +import type { ScheduleRepository } from './ScheduleRepository'; import type { CreateScheduleInput, Schedule, @@ -18,8 +20,6 @@ import type { ScheduleRunStatus, UpdateSchedulePatch, } from '@shared/types'; -import type { ScheduleRepository } from './ScheduleRepository'; -import type { ScheduledTaskExecutor } from './ScheduledTaskExecutor'; const logger = createLogger('Service:Scheduler'); @@ -511,7 +511,7 @@ export class SchedulerService { private async onCronTick(scheduleId: string): Promise { const schedule = await this.repository.getSchedule(scheduleId); - if (!schedule || schedule.status !== 'active') { + if (schedule?.status !== 'active') { logger.debug(`Cron tick for ${scheduleId} skipped (not active)`); return; } @@ -659,7 +659,7 @@ export class SchedulerService { } const freshSchedule = await this.repository.getSchedule(schedule.id); - if (!freshSchedule || freshSchedule.status !== 'active') { + if (freshSchedule?.status !== 'active') { await this.completeRun(retryRun, 'failed', exitCode, undefined, error); return false; } diff --git a/src/main/services/schedule/index.ts b/src/main/services/schedule/index.ts index c5ae7f0c..ceed50c1 100644 --- a/src/main/services/schedule/index.ts +++ b/src/main/services/schedule/index.ts @@ -3,12 +3,12 @@ */ export { JsonScheduleRepository } from './JsonScheduleRepository'; -export type { ScheduleRepository } from './ScheduleRepository'; -export { ScheduledTaskExecutor } from './ScheduledTaskExecutor'; export type { ExecutionRequest, InternalScheduleRun, ScheduledTaskResult, } from './ScheduledTaskExecutor'; -export { SchedulerService } from './SchedulerService'; +export { ScheduledTaskExecutor } from './ScheduledTaskExecutor'; +export type { ScheduleRepository } from './ScheduleRepository'; export type { WarmUpFn } from './SchedulerService'; +export { SchedulerService } from './SchedulerService'; diff --git a/src/main/services/team/ChangeExtractorService.ts b/src/main/services/team/ChangeExtractorService.ts index 94e1eae8..fe63d20d 100644 --- a/src/main/services/team/ChangeExtractorService.ts +++ b/src/main/services/team/ChangeExtractorService.ts @@ -577,7 +577,7 @@ export class ChangeExtractorService { private async parseJSONLFilesWithConcurrency( paths: string[] - ): Promise> { + ): Promise<{ snippets: SnippetDiff[]; mtime: number }[]> { if (paths.length === 0) return []; const results = new Array<{ snippets: SnippetDiff[]; mtime: number }>(paths.length); diff --git a/src/main/services/team/CrossTeamService.ts b/src/main/services/team/CrossTeamService.ts index 10c44f6e..63c01676 100644 --- a/src/main/services/team/CrossTeamService.ts +++ b/src/main/services/team/CrossTeamService.ts @@ -1,5 +1,5 @@ -import { CROSS_TEAM_SENT_SOURCE, CROSS_TEAM_SOURCE, formatCrossTeamText } from '@shared/constants'; import { getClaudeBasePath, getTeamsBasePath } from '@main/utils/pathDecoder'; +import { CROSS_TEAM_SENT_SOURCE, CROSS_TEAM_SOURCE, formatCrossTeamText } from '@shared/constants'; import { isLeadMember } from '@shared/utils/leadDetection'; import { createLogger } from '@shared/utils/logger'; import * as agentTeamsControllerModule from 'agent-teams-controller'; diff --git a/src/main/services/team/TeamBackupService.ts b/src/main/services/team/TeamBackupService.ts index d9d8379b..cb9fb394 100644 --- a/src/main/services/team/TeamBackupService.ts +++ b/src/main/services/team/TeamBackupService.ts @@ -300,7 +300,8 @@ export class TeamBackupService { if (raw && isValidConfig(raw)) { const parsed = JSON.parse(raw) as Record; manifest.displayName = typeof parsed.name === 'string' ? parsed.name : undefined; - manifest.projectPath = typeof parsed.projectPath === 'string' ? parsed.projectPath : undefined; + manifest.projectPath = + typeof parsed.projectPath === 'string' ? parsed.projectPath : undefined; } } catch { // best-effort @@ -392,7 +393,7 @@ export class TeamBackupService { } const cached = manifest.fileStats[descriptor.relPath]; - if (cached && cached.mtime === stat.mtimeMs && cached.size === stat.size) { + if (cached?.mtime === stat.mtimeMs && cached.size === stat.size) { return false; // not dirty } @@ -431,7 +432,7 @@ export class TeamBackupService { if (stat.size > MAX_FILE_SIZE_BYTES) return; // skip oversized silently during shutdown const cached = manifest.fileStats[descriptor.relPath]; - if (cached && cached.mtime === stat.mtimeMs && cached.size === stat.size) return; + if (cached?.mtime === stat.mtimeMs && cached.size === stat.size) return; const destPath = path.join(backupDir, descriptor.relPath); @@ -572,10 +573,7 @@ export class TeamBackupService { return count > 0; } - private async restoreGenericPartial( - teamName: string, - manifest: BackupManifest - ): Promise { + private async restoreGenericPartial(teamName: string, manifest: BackupManifest): Promise { const backupDir = this.getBackupDir(teamName); const backupFiles = await this.enumerateBackupFiles(teamName); let count = 0; @@ -892,10 +890,20 @@ export class TeamBackupService { return path.join(getTasksBasePath(), teamName, relPath.slice('tasks/'.length)); } if (relPath.startsWith('attachments/')) { - return path.join(getAppDataPath(), 'attachments', teamName, relPath.slice('attachments/'.length)); + return path.join( + getAppDataPath(), + 'attachments', + teamName, + relPath.slice('attachments/'.length) + ); } if (relPath.startsWith('task-attachments/')) { - return path.join(getAppDataPath(), 'task-attachments', teamName, relPath.slice('task-attachments/'.length)); + return path.join( + getAppDataPath(), + 'task-attachments', + teamName, + relPath.slice('task-attachments/'.length) + ); } return path.join(getTeamsBasePath(), teamName, relPath); } diff --git a/src/main/services/team/TeamMcpConfigBuilder.ts b/src/main/services/team/TeamMcpConfigBuilder.ts index 038cbdde..39dacf77 100644 --- a/src/main/services/team/TeamMcpConfigBuilder.ts +++ b/src/main/services/team/TeamMcpConfigBuilder.ts @@ -1,12 +1,11 @@ +import { getHomeDir } from '@main/utils/pathDecoder'; +import { createLogger } from '@shared/utils/logger'; import { execFile } from 'child_process'; import { randomUUID } from 'crypto'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { getHomeDir } from '@main/utils/pathDecoder'; -import { createLogger } from '@shared/utils/logger'; - import { atomicWriteAsync } from './atomicWrite'; interface McpLaunchSpec { diff --git a/src/main/services/team/TeamProvisioningService.ts b/src/main/services/team/TeamProvisioningService.ts index 5bd0466e..7330f878 100644 --- a/src/main/services/team/TeamProvisioningService.ts +++ b/src/main/services/team/TeamProvisioningService.ts @@ -1,9 +1,7 @@ /* eslint-disable no-param-reassign -- ProvisioningRun object is intentionally mutated as a state tracker throughout the provisioning lifecycle */ import { ConfigManager } from '@main/services/infrastructure/ConfigManager'; import { killProcessTree, spawnCli } from '@main/utils/childProcess'; -import { shouldAutoAllow } from '@main/utils/toolApprovalRules'; import { FileReadTimeoutError, readFileUtf8WithTimeout } from '@main/utils/fsRead'; -import { resolveInteractiveShellEnv } from '@main/utils/shellEnv'; import { encodePath, extractBaseDir, @@ -14,6 +12,8 @@ import { getTasksBasePath, getTeamsBasePath, } from '@main/utils/pathDecoder'; +import { resolveInteractiveShellEnv } from '@main/utils/shellEnv'; +import { shouldAutoAllow } from '@main/utils/toolApprovalRules'; import { AGENT_BLOCK_CLOSE, AGENT_BLOCK_OPEN, @@ -21,8 +21,8 @@ import { } from '@shared/constants/agentBlocks'; import { CROSS_TEAM_PREFIX_TAG, - CROSS_TEAM_SOURCE, CROSS_TEAM_SENT_SOURCE, + CROSS_TEAM_SOURCE, parseCrossTeamPrefix, stripCrossTeamPrefix, } from '@shared/constants/crossTeam'; @@ -41,14 +41,14 @@ import { import { createCliAutoSuffixNameGuard, parseNumericSuffixName } from '@shared/utils/teamMemberName'; import { extractToolPreview, formatToolSummaryFromCalls } from '@shared/utils/toolSummary'; import * as agentTeamsControllerModule from 'agent-teams-controller'; -import { spawn, type ChildProcess } from 'child_process'; +import { type ChildProcess, type spawn } from 'child_process'; import { randomUUID } from 'crypto'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { atomicWriteAsync } from './atomicWrite'; import { buildActionModeProtocol } from './actionModeInstructions'; +import { atomicWriteAsync } from './atomicWrite'; import { ClaudeBinaryResolver } from './ClaudeBinaryResolver'; import { withFileLock } from './fileLock'; import { withInboxLock } from './inboxLock'; @@ -231,10 +231,10 @@ interface ProvisioningRun { rejectOnce: (error: string) => void; timeoutHandle: NodeJS.Timeout; } | null; - activeCrossTeamReplyHints: Array<{ + activeCrossTeamReplyHints: { toTeam: string; conversationId: string; - }>; + }[]; /** Monotonic counter for individual lead assistant messages. */ leadMsgSeq: number; /** Accumulated tool_use details between text messages. */ @@ -1122,11 +1122,11 @@ interface CachedProbeResult { cachedAtMs: number; } -type ProbeResult = { +interface ProbeResult { claudePath: string; authSource: ProvisioningAuthSource; warning?: string; -}; +} type AuthWarningSource = 'probe' | 'stdout' | 'stderr' | 'assistant' | 'pre-complete'; @@ -1607,21 +1607,21 @@ export class TeamProvisioningService { private async matchCrossTeamLeadInboxMessages( teamName: string, leadName: string, - deliveredBlocks: Array<{ + deliveredBlocks: { teammateId: string; content: string; toTeam: string; conversationId: string; - }> + }[] ): Promise< - Array<{ + { teammateId: string; content: string; toTeam: string; conversationId: string; messageId: string; wasRead: boolean; - }> + }[] > { if (deliveredBlocks.length === 0) return []; @@ -1633,14 +1633,14 @@ export class TeamProvisioningService { } const usedMessageIds = new Set(); - const matches: Array<{ + const matches: { teammateId: string; content: string; toTeam: string; conversationId: string; messageId: string; wasRead: boolean; - }> = []; + }[] = []; for (const block of deliveredBlocks) { const matchesBlock = (message: InboxMessage, requireExactText: boolean): boolean => { if (message.source !== CROSS_TEAM_SOURCE) return false; @@ -1816,7 +1816,7 @@ export class TeamProvisioningService { private rememberPendingInboxRelayCandidates( run: ProvisioningRun, recipient: string, - messages: Array> + messages: Pick[] ): string[] { const candidates = this.prunePendingInboxRelayCandidates(run); const queuedAtMs = Date.now(); @@ -4167,7 +4167,7 @@ export class TeamProvisioningService { (mistakenToolHint ? { teamName: mistakenToolHint.toTeam, memberName: 'team-lead' } : null); if (crossTeamRecipient && this.crossTeamSender) { const inferredReplyMeta = - mistakenToolHint && mistakenToolHint.toTeam === crossTeamRecipient.teamName + mistakenToolHint?.toTeam === crossTeamRecipient.teamName ? { conversationId: mistakenToolHint.conversationId, replyToConversationId: mistakenToolHint.conversationId, diff --git a/src/main/services/team/cache/JsonTaskChangeSummaryCacheRepository.ts b/src/main/services/team/cache/JsonTaskChangeSummaryCacheRepository.ts index 921ee0b9..e312c8b8 100644 --- a/src/main/services/team/cache/JsonTaskChangeSummaryCacheRepository.ts +++ b/src/main/services/team/cache/JsonTaskChangeSummaryCacheRepository.ts @@ -1,5 +1,5 @@ -import { getTaskChangeSummariesBasePath } from '@main/utils/pathDecoder'; import { atomicWriteAsync } from '@main/utils/atomicWrite'; +import { getTaskChangeSummariesBasePath } from '@main/utils/pathDecoder'; import { createLogger } from '@shared/utils/logger'; import * as fs from 'fs'; import * as path from 'path'; diff --git a/src/main/services/team/cache/taskChangeSummaryCacheSchema.ts b/src/main/services/team/cache/taskChangeSummaryCacheSchema.ts index 579ad738..3165d21e 100644 --- a/src/main/services/team/cache/taskChangeSummaryCacheSchema.ts +++ b/src/main/services/team/cache/taskChangeSummaryCacheSchema.ts @@ -1,7 +1,7 @@ import { TASK_CHANGE_SUMMARY_CACHE_SCHEMA_VERSION } from './taskChangeSummaryCacheTypes'; -import type { FileChangeSummary, TaskChangeSetV2 } from '@shared/types'; import type { PersistedTaskChangeSummaryEntry } from './taskChangeSummaryCacheTypes'; +import type { FileChangeSummary, TaskChangeSetV2 } from '@shared/types'; function normalizeIsoString(value: unknown): string | null { if (typeof value !== 'string' || value.trim() === '') return null; diff --git a/src/main/workers/team-fs-worker.ts b/src/main/workers/team-fs-worker.ts index d4f8b7ab..d02fe020 100644 --- a/src/main/workers/team-fs-worker.ts +++ b/src/main/workers/team-fs-worker.ts @@ -707,8 +707,8 @@ async function readTasksDirForTeam( ? (parsed.attachments as unknown[]) : undefined, sourceMessageId: - typeof parsed.sourceMessageId === 'string' && (parsed.sourceMessageId as string).trim() - ? (parsed.sourceMessageId as string).trim() + typeof parsed.sourceMessageId === 'string' && parsed.sourceMessageId.trim() + ? parsed.sourceMessageId.trim() : undefined, sourceMessage: parsed.sourceMessage && diff --git a/src/preload/index.ts b/src/preload/index.ts index 79fef7a3..108e5537 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -2,6 +2,11 @@ import { WINDOW_ZOOM_FACTOR_CHANGED_CHANNEL } from '@shared/constants'; import { contextBridge, ipcRenderer } from 'electron'; import { + API_KEYS_DELETE, + API_KEYS_LIST, + API_KEYS_LOOKUP, + API_KEYS_SAVE, + API_KEYS_STORAGE_STATUS, APP_RELAUNCH, CLI_INSTALLER_GET_STATUS, CLI_INSTALLER_INSTALL, @@ -34,28 +39,30 @@ import { HTTP_SERVER_GET_STATUS, HTTP_SERVER_START, HTTP_SERVER_STOP, + MCP_GITHUB_STARS, + MCP_REGISTRY_BROWSE, + MCP_REGISTRY_DIAGNOSE, + MCP_REGISTRY_GET_BY_ID, + MCP_REGISTRY_GET_INSTALLED, + MCP_REGISTRY_INSTALL, + MCP_REGISTRY_INSTALL_CUSTOM, + MCP_REGISTRY_SEARCH, + MCP_REGISTRY_UNINSTALL, + PLUGIN_GET_ALL, + PLUGIN_GET_README, + PLUGIN_INSTALL, + PLUGIN_UNINSTALL, PROJECT_LIST_FILES, RENDERER_BOOT, RENDERER_HEARTBEAT, RENDERER_LOG, - SCHEDULE_CHANGE, - SCHEDULE_CREATE, - SCHEDULE_DELETE, - SCHEDULE_GET, - SCHEDULE_GET_RUN_LOGS, - SCHEDULE_GET_RUNS, - SCHEDULE_LIST, - SCHEDULE_PAUSE, - SCHEDULE_RESUME, - SCHEDULE_TRIGGER_NOW, - SCHEDULE_UPDATE, REVIEW_APPLY_DECISIONS, REVIEW_CHECK_CONFLICT, REVIEW_CLEAR_DECISIONS, + REVIEW_FILE_CHANGE, REVIEW_GET_AGENT_CHANGES, REVIEW_GET_CHANGE_STATS, REVIEW_GET_FILE_CONTENT, - REVIEW_FILE_CHANGE, REVIEW_GET_GIT_FILE_LOG, REVIEW_GET_TASK_CHANGES, REVIEW_INVALIDATE_TASK_CHANGE_SUMMARIES, @@ -67,6 +74,27 @@ import { REVIEW_SAVE_EDITED_FILE, REVIEW_UNWATCH_FILES, REVIEW_WATCH_FILES, + SCHEDULE_CHANGE, + SCHEDULE_CREATE, + SCHEDULE_DELETE, + SCHEDULE_GET, + SCHEDULE_GET_RUN_LOGS, + SCHEDULE_GET_RUNS, + SCHEDULE_LIST, + SCHEDULE_PAUSE, + SCHEDULE_RESUME, + SCHEDULE_TRIGGER_NOW, + SCHEDULE_UPDATE, + SKILLS_APPLY_IMPORT, + SKILLS_APPLY_UPSERT, + SKILLS_CHANGED, + SKILLS_DELETE, + SKILLS_GET_DETAIL, + SKILLS_LIST, + SKILLS_PREVIEW_IMPORT, + SKILLS_PREVIEW_UPSERT, + SKILLS_START_WATCHING, + SKILLS_STOP_WATCHING, SSH_CONNECT, SSH_DISCONNECT, SSH_GET_CONFIG_HOSTS, @@ -101,8 +129,8 @@ import { TEAM_LAUNCH, TEAM_LEAD_ACTIVITY, TEAM_LEAD_CONTEXT, - TEAM_MEMBER_SPAWN_STATUSES, TEAM_LIST, + TEAM_MEMBER_SPAWN_STATUSES, TEAM_PERMANENTLY_DELETE, TEAM_PREPARE_PROVISIONING, TEAM_PROCESS_ALIVE, @@ -149,34 +177,6 @@ import { WINDOW_IS_MAXIMIZED, WINDOW_MAXIMIZE, WINDOW_MINIMIZE, - PLUGIN_GET_ALL, - PLUGIN_GET_README, - PLUGIN_INSTALL, - PLUGIN_UNINSTALL, - MCP_REGISTRY_SEARCH, - MCP_REGISTRY_BROWSE, - MCP_REGISTRY_DIAGNOSE, - MCP_REGISTRY_GET_BY_ID, - MCP_REGISTRY_GET_INSTALLED, - MCP_REGISTRY_INSTALL, - MCP_REGISTRY_INSTALL_CUSTOM, - MCP_REGISTRY_UNINSTALL, - MCP_GITHUB_STARS, - SKILLS_APPLY_IMPORT, - SKILLS_APPLY_UPSERT, - SKILLS_CHANGED, - SKILLS_DELETE, - SKILLS_GET_DETAIL, - SKILLS_LIST, - SKILLS_PREVIEW_IMPORT, - SKILLS_PREVIEW_UPSERT, - SKILLS_START_WATCHING, - SKILLS_STOP_WATCHING, - API_KEYS_LIST, - API_KEYS_SAVE, - API_KEYS_DELETE, - API_KEYS_LOOKUP, - API_KEYS_STORAGE_STATUS, } from './constants/ipcChannels'; import { CONFIG_ADD_CUSTOM_PROJECT_PATH, @@ -236,9 +236,9 @@ import type { KanbanColumnId, LeadActivitySnapshot, LeadContextUsageSnapshot, - MemberSpawnStatusesSnapshot, MemberFullStats, MemberLogSummary, + MemberSpawnStatusesSnapshot, NotificationTrigger, RejectResult, ReplaceMembersRequest, @@ -281,28 +281,6 @@ import type { UpdateSchedulePatch, WslClaudeRootCandidate, } from '@shared/types'; -import type { - ApiKeyEntry, - ApiKeyLookupResult, - ApiKeySaveRequest, - ApiKeyStorageStatus, - EnrichedPlugin, - InstalledMcpEntry, - McpCatalogItem, - McpCustomInstallRequest, - McpInstallRequest, - McpServerDiagnostic, - McpSearchResult, - OperationResult, - PluginInstallRequest, - SkillCatalogItem, - SkillDeleteRequest, - SkillDetail, - SkillImportRequest, - SkillReviewPreview, - SkillUpsertRequest, - SkillWatcherEvent, -} from '@shared/types/extensions'; import type { BinaryPreviewResult, CreateDirResponse, @@ -318,6 +296,28 @@ import type { SearchInFilesResult, WriteFileResponse, } from '@shared/types/editor'; +import type { + ApiKeyEntry, + ApiKeyLookupResult, + ApiKeySaveRequest, + ApiKeyStorageStatus, + EnrichedPlugin, + InstalledMcpEntry, + McpCatalogItem, + McpCustomInstallRequest, + McpInstallRequest, + McpSearchResult, + McpServerDiagnostic, + OperationResult, + PluginInstallRequest, + SkillCatalogItem, + SkillDeleteRequest, + SkillDetail, + SkillImportRequest, + SkillReviewPreview, + SkillUpsertRequest, + SkillWatcherEvent, +} from '@shared/types/extensions'; import type { PtySpawnOptions } from '@shared/types/terminal'; import type { CliArgsValidationResult } from '@shared/utils/cliArgsParser'; diff --git a/src/renderer/components/chat/viewers/MarkdownViewer.tsx b/src/renderer/components/chat/viewers/MarkdownViewer.tsx index 0618f3fa..703c07d9 100644 --- a/src/renderer/components/chat/viewers/MarkdownViewer.tsx +++ b/src/renderer/components/chat/viewers/MarkdownViewer.tsx @@ -27,7 +27,6 @@ import { import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors'; import { useTheme } from '@renderer/hooks/useTheme'; import { useStore } from '@renderer/store'; -import type { SearchMatch } from '@renderer/store/types'; import { REHYPE_PLUGINS, REHYPE_PLUGINS_NO_HIGHLIGHT } from '@renderer/utils/markdownPlugins'; import { nameColorSet } from '@renderer/utils/projectColor'; import { parseTaskLinkHref } from '@renderer/utils/taskReferenceUtils'; @@ -44,6 +43,8 @@ import { import { FileLink, isRelativeUrl } from './FileLink'; import { MermaidDiagram } from './MermaidDiagram'; +import type { SearchMatch } from '@renderer/store/types'; + // ============================================================================= // Types // ============================================================================= @@ -69,7 +70,7 @@ interface MarkdownViewerProps { onTeamClick?: (teamName: string) => void; } -const EMPTY_TEAMS: Array<{ teamName?: string; displayName?: string; color?: string }> = []; +const EMPTY_TEAMS: { teamName?: string; displayName?: string; color?: string }[] = []; const EMPTY_TEAM_COLOR_MAP = new Map(); const EMPTY_SEARCH_MATCHES: SearchMatch[] = []; const NOOP_TEAM_CLICK = (): void => undefined; @@ -94,31 +95,136 @@ function allowCustomProtocols(url: string): string { * that appear in agent messages and cause React "unrecognized tag" warnings. */ const STANDARD_HTML_TAGS = new Set([ - 'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', - 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', - 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', - 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', - 'em', 'embed', - 'fieldset', 'figcaption', 'figure', 'footer', 'form', - 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', - 'i', 'iframe', 'img', 'input', 'ins', + 'a', + 'abbr', + 'address', + 'area', + 'article', + 'aside', + 'audio', + 'b', + 'base', + 'bdi', + 'bdo', + 'blockquote', + 'body', + 'br', + 'button', + 'canvas', + 'caption', + 'cite', + 'code', + 'col', + 'colgroup', + 'data', + 'datalist', + 'dd', + 'del', + 'details', + 'dfn', + 'dialog', + 'div', + 'dl', + 'dt', + 'em', + 'embed', + 'fieldset', + 'figcaption', + 'figure', + 'footer', + 'form', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'head', + 'header', + 'hgroup', + 'hr', + 'html', + 'i', + 'iframe', + 'img', + 'input', + 'ins', 'kbd', - 'label', 'legend', 'li', 'link', - 'main', 'map', 'mark', 'menu', 'meta', 'meter', - 'nav', 'noscript', - 'object', 'ol', 'optgroup', 'option', 'output', - 'p', 'picture', 'pre', 'progress', + 'label', + 'legend', + 'li', + 'link', + 'main', + 'map', + 'mark', + 'menu', + 'meta', + 'meter', + 'nav', + 'noscript', + 'object', + 'ol', + 'optgroup', + 'option', + 'output', + 'p', + 'picture', + 'pre', + 'progress', 'q', - 'rp', 'rt', 'ruby', - 's', 'samp', 'script', 'search', 'section', 'select', 'slot', 'small', 'source', 'span', - 'strong', 'style', 'sub', 'summary', 'sup', - 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', - 'u', 'ul', - 'var', 'video', + 'rp', + 'rt', + 'ruby', + 's', + 'samp', + 'script', + 'search', + 'section', + 'select', + 'slot', + 'small', + 'source', + 'span', + 'strong', + 'style', + 'sub', + 'summary', + 'sup', + 'table', + 'tbody', + 'td', + 'template', + 'textarea', + 'tfoot', + 'th', + 'thead', + 'time', + 'title', + 'tr', + 'track', + 'u', + 'ul', + 'var', + 'video', 'wbr', // SVG elements commonly used inline - 'svg', 'path', 'circle', 'rect', 'line', 'polyline', 'polygon', 'g', 'defs', 'use', - 'text', 'tspan', 'clippath', 'mask', 'pattern', 'image', 'foreignobject', + 'svg', + 'path', + 'circle', + 'rect', + 'line', + 'polyline', + 'polygon', + 'g', + 'defs', + 'use', + 'text', + 'tspan', + 'clippath', + 'mask', + 'pattern', + 'image', + 'foreignobject', ]); /** diff --git a/src/renderer/components/common/ErrorBoundary.tsx b/src/renderer/components/common/ErrorBoundary.tsx index a8904129..5e975989 100644 --- a/src/renderer/components/common/ErrorBoundary.tsx +++ b/src/renderer/components/common/ErrorBoundary.tsx @@ -1,14 +1,13 @@ import React, { Component, type ErrorInfo, type ReactNode } from 'react'; import { useStore } from '@renderer/store'; -import { createLogger } from '@shared/utils/logger'; -import { AlertTriangle, Bug, Check, Copy, RefreshCw } from 'lucide-react'; - import { + type BugReportContext, buildBugReportText, buildGitHubBugReportUrl, - type BugReportContext, } from '@renderer/utils/bugReportUtils'; +import { createLogger } from '@shared/utils/logger'; +import { AlertTriangle, Bug, Check, Copy, RefreshCw } from 'lucide-react'; const logger = createLogger('Component:ErrorBoundary'); diff --git a/src/renderer/components/extensions/ExtensionStoreView.tsx b/src/renderer/components/extensions/ExtensionStoreView.tsx index d1ad148e..8f0c7130 100644 --- a/src/renderer/components/extensions/ExtensionStoreView.tsx +++ b/src/renderer/components/extensions/ExtensionStoreView.tsx @@ -8,9 +8,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { api } from '@renderer/api'; import { Button } from '@renderer/components/ui/button'; -import { useTabIdOptional } from '@renderer/contexts/useTabUIContext'; -import { useExtensionsTabState } from '@renderer/hooks/useExtensionsTabState'; -import { useStore } from '@renderer/store'; import { Tabs, TabsContent, TabsList } from '@renderer/components/ui/tabs'; import { Tooltip, @@ -18,14 +15,17 @@ import { TooltipProvider, TooltipTrigger, } from '@renderer/components/ui/tooltip'; +import { useTabIdOptional } from '@renderer/contexts/useTabUIContext'; +import { useExtensionsTabState } from '@renderer/hooks/useExtensionsTabState'; +import { useStore } from '@renderer/store'; import { AlertTriangle, BookOpen, Info, Key, Plus, Puzzle, RefreshCw, Server } from 'lucide-react'; import { ApiKeysPanel } from './apikeys/ApiKeysPanel'; -import { ExtensionsSubTabTrigger } from './ExtensionsSubTabTrigger'; import { CustomMcpServerDialog } from './mcp/CustomMcpServerDialog'; import { McpServersPanel } from './mcp/McpServersPanel'; import { PluginsPanel } from './plugins/PluginsPanel'; import { SkillsPanel } from './skills/SkillsPanel'; +import { ExtensionsSubTabTrigger } from './ExtensionsSubTabTrigger'; export const ExtensionStoreView = (): React.JSX.Element => { const tabId = useTabIdOptional(); diff --git a/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx b/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx index 6df3b7da..387a90a2 100644 --- a/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +++ b/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx @@ -1,10 +1,9 @@ -import type { LucideIcon } from 'lucide-react'; - import { TabsTrigger } from '@renderer/components/ui/tabs'; import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip'; - import { Info } from 'lucide-react'; +import type { LucideIcon } from 'lucide-react'; + interface ExtensionsSubTabTriggerProps { value: 'plugins' | 'mcp-servers' | 'skills' | 'api-keys'; label: string; @@ -21,7 +20,7 @@ export const ExtensionsSubTabTrigger = ({ return ( {label} diff --git a/src/renderer/components/extensions/apikeys/ApiKeyCard.tsx b/src/renderer/components/extensions/apikeys/ApiKeyCard.tsx index 30db3d68..3e704724 100644 --- a/src/renderer/components/extensions/apikeys/ApiKeyCard.tsx +++ b/src/renderer/components/extensions/apikeys/ApiKeyCard.tsx @@ -13,7 +13,7 @@ import { TooltipTrigger, } from '@renderer/components/ui/tooltip'; import { useStore } from '@renderer/store'; -import { Copy, Check, Pencil, Trash2 } from 'lucide-react'; +import { Check, Copy, Pencil, Trash2 } from 'lucide-react'; import type { ApiKeyEntry } from '@shared/types/extensions'; diff --git a/src/renderer/components/extensions/common/InstallButton.tsx b/src/renderer/components/extensions/common/InstallButton.tsx index cab9ae13..5d45a257 100644 --- a/src/renderer/components/extensions/common/InstallButton.tsx +++ b/src/renderer/components/extensions/common/InstallButton.tsx @@ -5,8 +5,6 @@ import { useEffect, useState } from 'react'; -import { Check, Loader2, Trash2 } from 'lucide-react'; - import { Button } from '@renderer/components/ui/button'; import { Tooltip, @@ -15,6 +13,7 @@ import { TooltipTrigger, } from '@renderer/components/ui/tooltip'; import { useStore } from '@renderer/store'; +import { Check, Loader2, Trash2 } from 'lucide-react'; import type { ExtensionOperationState } from '@shared/types/extensions'; @@ -28,7 +27,7 @@ interface InstallButtonProps { errorMessage?: string; } -export function InstallButton({ +export const InstallButton = ({ state, isInstalled, onInstall, @@ -36,7 +35,7 @@ export function InstallButton({ disabled, size = 'sm', errorMessage, -}: InstallButtonProps) { +}: InstallButtonProps) => { const cliStatus = useStore((s) => s.cliStatus); const cliMissing = cliStatus !== null && !cliStatus.installed; const isDisabled = disabled || cliMissing; @@ -52,7 +51,7 @@ export function InstallButton({ if (state === 'pending') { return ( ); @@ -121,7 +120,7 @@ export function InstallButton({ }} disabled={isDisabled} > - + Uninstall ) : ( @@ -153,4 +152,4 @@ export function InstallButton({ } return button; -} +}; diff --git a/src/renderer/components/extensions/common/InstallCountBadge.tsx b/src/renderer/components/extensions/common/InstallCountBadge.tsx index 9e04f667..10590a17 100644 --- a/src/renderer/components/extensions/common/InstallCountBadge.tsx +++ b/src/renderer/components/extensions/common/InstallCountBadge.tsx @@ -2,9 +2,8 @@ * InstallCountBadge — formatted download count with icon. */ -import { Download } from 'lucide-react'; - import { formatInstallCount } from '@shared/utils/extensionNormalizers'; +import { Download } from 'lucide-react'; interface InstallCountBadgeProps { count: number; diff --git a/src/renderer/components/extensions/mcp/CustomMcpServerDialog.tsx b/src/renderer/components/extensions/mcp/CustomMcpServerDialog.tsx index 53e1dc42..35624aad 100644 --- a/src/renderer/components/extensions/mcp/CustomMcpServerDialog.tsx +++ b/src/renderer/components/extensions/mcp/CustomMcpServerDialog.tsx @@ -5,6 +5,7 @@ import { useEffect, useState } from 'react'; +import { api } from '@renderer/api'; import { Button } from '@renderer/components/ui/button'; import { Dialog, @@ -23,7 +24,6 @@ import { SelectValue, } from '@renderer/components/ui/select'; import { useStore } from '@renderer/store'; -import { api } from '@renderer/api'; import { Plus, Server, Trash2 } from 'lucide-react'; import type { diff --git a/src/renderer/components/extensions/mcp/McpServerCard.tsx b/src/renderer/components/extensions/mcp/McpServerCard.tsx index 0b9d023d..e2f04f87 100644 --- a/src/renderer/components/extensions/mcp/McpServerCard.tsx +++ b/src/renderer/components/extensions/mcp/McpServerCard.tsx @@ -5,20 +5,18 @@ import { useState } from 'react'; +import { api } from '@renderer/api'; import { Badge } from '@renderer/components/ui/badge'; import { Button } from '@renderer/components/ui/button'; import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip'; import { useStore } from '@renderer/store'; -import { api } from '@renderer/api'; import { formatCompactNumber, formatRelativeTime } from '@renderer/utils/formatters'; -import { Cloud, Clock, Globe, KeyRound, Lock, Monitor, Star, Tag, Wrench } from 'lucide-react'; - -// eslint-disable-next-line @typescript-eslint/no-deprecated -- lucide naming migration, alias is stable +import { sanitizeMcpServerName } from '@shared/utils/extensionNormalizers'; +import { Clock, Cloud, Globe, KeyRound, Lock, Monitor, Star, Tag, Wrench } from 'lucide-react'; import { Github as GithubIcon } from 'lucide-react'; import { InstallButton } from '../common/InstallButton'; import { SourceBadge } from '../common/SourceBadge'; -import { sanitizeMcpServerName } from '@shared/utils/extensionNormalizers'; import type { McpCatalogItem, McpServerDiagnostic } from '@shared/types/extensions'; @@ -82,7 +80,7 @@ export const McpServerCard = ({ {hasIcon && (
setImgError(true)} diff --git a/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx b/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx index 54c79281..e108af70 100644 --- a/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx +++ b/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx @@ -5,6 +5,9 @@ import { useEffect, useState } from 'react'; +import { api } from '@renderer/api'; +import { Badge } from '@renderer/components/ui/badge'; +import { Button } from '@renderer/components/ui/button'; import { Dialog, DialogContent, @@ -12,8 +15,6 @@ import { DialogHeader, DialogTitle, } from '@renderer/components/ui/dialog'; -import { Badge } from '@renderer/components/ui/badge'; -import { Button } from '@renderer/components/ui/button'; import { Input } from '@renderer/components/ui/input'; import { Label } from '@renderer/components/ui/label'; import { @@ -24,12 +25,11 @@ import { SelectValue, } from '@renderer/components/ui/select'; import { useStore } from '@renderer/store'; -import { api } from '@renderer/api'; +import { sanitizeMcpServerName } from '@shared/utils/extensionNormalizers'; import { ExternalLink, Lock, Plus, Star, Trash2, Wrench } from 'lucide-react'; import { InstallButton } from '../common/InstallButton'; import { SourceBadge } from '../common/SourceBadge'; -import { sanitizeMcpServerName } from '@shared/utils/extensionNormalizers'; import type { McpCatalogItem, McpHeaderDef, McpServerDiagnostic } from '@shared/types/extensions'; @@ -214,7 +214,7 @@ export const McpServerDetailDialog = ({ {hasIcon && (
setImgError(true)} diff --git a/src/renderer/components/extensions/mcp/McpServersPanel.tsx b/src/renderer/components/extensions/mcp/McpServersPanel.tsx index e2131fc5..e17e8335 100644 --- a/src/renderer/components/extensions/mcp/McpServersPanel.tsx +++ b/src/renderer/components/extensions/mcp/McpServersPanel.tsx @@ -15,6 +15,7 @@ import { } from '@renderer/components/ui/select'; import { useStore } from '@renderer/store'; import { formatRelativeTime } from '@renderer/utils/formatters'; +import { sanitizeMcpServerName } from '@shared/utils/extensionNormalizers'; import { AlertTriangle, RefreshCw, Search, Server } from 'lucide-react'; import { SearchInput } from '../common/SearchInput'; @@ -27,7 +28,6 @@ import type { McpCatalogItem, McpServerDiagnostic, } from '@shared/types/extensions'; -import { sanitizeMcpServerName } from '@shared/utils/extensionNormalizers'; type McpSortValue = 'name-asc' | 'name-desc' | 'tools-desc'; diff --git a/src/renderer/components/extensions/plugins/PluginCard.tsx b/src/renderer/components/extensions/plugins/PluginCard.tsx index b1649255..be2a7379 100644 --- a/src/renderer/components/extensions/plugins/PluginCard.tsx +++ b/src/renderer/components/extensions/plugins/PluginCard.tsx @@ -53,8 +53,8 @@ export const PluginCard = ({ plugin, index, onClick }: PluginCardProps): React.J }`} > {plugin.source === 'official' && ( -
-
+
+
Official
diff --git a/src/renderer/components/extensions/plugins/PluginDetailDialog.tsx b/src/renderer/components/extensions/plugins/PluginDetailDialog.tsx index 83cf3d00..d963e3f6 100644 --- a/src/renderer/components/extensions/plugins/PluginDetailDialog.tsx +++ b/src/renderer/components/extensions/plugins/PluginDetailDialog.tsx @@ -4,6 +4,10 @@ import { useEffect, useState } from 'react'; +import { api } from '@renderer/api'; +import { MarkdownViewer } from '@renderer/components/chat/viewers/MarkdownViewer'; +import { Badge } from '@renderer/components/ui/badge'; +import { Button } from '@renderer/components/ui/button'; import { Dialog, DialogContent, @@ -11,8 +15,6 @@ import { DialogHeader, DialogTitle, } from '@renderer/components/ui/dialog'; -import { Badge } from '@renderer/components/ui/badge'; -import { Button } from '@renderer/components/ui/button'; import { Label } from '@renderer/components/ui/label'; import { Select, @@ -22,7 +24,6 @@ import { SelectValue, } from '@renderer/components/ui/select'; import { useStore } from '@renderer/store'; -import { api } from '@renderer/api'; import { getCapabilityLabel, inferCapabilities, @@ -34,8 +35,6 @@ import { InstallButton } from '../common/InstallButton'; import { InstallCountBadge } from '../common/InstallCountBadge'; import { SourceBadge } from '../common/SourceBadge'; -import { MarkdownViewer } from '@renderer/components/chat/viewers/MarkdownViewer'; - import type { EnrichedPlugin, InstallScope } from '@shared/types/extensions'; interface PluginDetailDialogProps { diff --git a/src/renderer/components/extensions/skills/SkillCodeEditor.tsx b/src/renderer/components/extensions/skills/SkillCodeEditor.tsx index 875cf1a3..3cff0cfb 100644 --- a/src/renderer/components/extensions/skills/SkillCodeEditor.tsx +++ b/src/renderer/components/extensions/skills/SkillCodeEditor.tsx @@ -18,8 +18,8 @@ import { keymap, lineNumbers, } from '@codemirror/view'; -import { baseEditorTheme } from '@renderer/utils/codemirrorTheme'; import { getSyncLanguageExtension } from '@renderer/utils/codemirrorLanguages'; +import { baseEditorTheme } from '@renderer/utils/codemirrorTheme'; const skillEditorTheme = EditorView.theme({ '&': { diff --git a/src/renderer/components/extensions/skills/SkillEditorDialog.tsx b/src/renderer/components/extensions/skills/SkillEditorDialog.tsx index 8e66ac6c..3131a8c4 100644 --- a/src/renderer/components/extensions/skills/SkillEditorDialog.tsx +++ b/src/renderer/components/extensions/skills/SkillEditorDialog.tsx @@ -26,13 +26,13 @@ import { useStore } from '@renderer/store'; import { FileSearch, RotateCcw, X } from 'lucide-react'; import { SkillCodeEditor } from './SkillCodeEditor'; -import { SkillReviewDialog } from './SkillReviewDialog'; import { buildSkillDraftFiles, buildSkillTemplate, readSkillTemplateContent, updateSkillTemplateFrontmatter, } from './skillDraftUtils'; +import { SkillReviewDialog } from './SkillReviewDialog'; import type { SkillDetail, @@ -792,7 +792,7 @@ export const SkillEditorDialog = ({ Cancel -
+

Review the file changes first, then confirm save in the next step.

diff --git a/src/renderer/components/extensions/skills/SkillImportDialog.tsx b/src/renderer/components/extensions/skills/SkillImportDialog.tsx index f9a4b3a9..507b4f8c 100644 --- a/src/renderer/components/extensions/skills/SkillImportDialog.tsx +++ b/src/renderer/components/extensions/skills/SkillImportDialog.tsx @@ -255,7 +255,7 @@ export const SkillImportDialog = ({ Cancel -

+

Review the copied files first, then confirm the import in the next step.

); -} +}; diff --git a/src/renderer/components/ui/tiptap/TiptapEditor.tsx b/src/renderer/components/ui/tiptap/TiptapEditor.tsx index aa45561f..f72d5d91 100644 --- a/src/renderer/components/ui/tiptap/TiptapEditor.tsx +++ b/src/renderer/components/ui/tiptap/TiptapEditor.tsx @@ -1,16 +1,17 @@ -import { EditorContent, EditorContext } from '@tiptap/react'; +import './tiptapStyles.css'; + import { useMemo } from 'react'; import { cn } from '@renderer/lib/utils'; +import { EditorContent, EditorContext } from '@tiptap/react'; import { TiptapBubbleMenu } from './TiptapBubbleMenu'; import { TiptapToolbar } from './TiptapToolbar'; -import type { TiptapEditorProps } from './types'; import { useTiptapEditor } from './useTiptapEditor'; -import './tiptapStyles.css'; +import type { TiptapEditorProps } from './types'; -export function TiptapEditor({ +export const TiptapEditor = ({ content, onChange, placeholder, @@ -23,7 +24,7 @@ export function TiptapEditor({ extensions, className, disabled = false, -}: TiptapEditorProps) { +}: TiptapEditorProps) => { const isEditable = editable && !disabled; const { editor } = useTiptapEditor({ content, @@ -69,4 +70,4 @@ export function TiptapEditor({
); -} +}; diff --git a/src/renderer/components/ui/tiptap/TiptapToolbar.tsx b/src/renderer/components/ui/tiptap/TiptapToolbar.tsx index 2d470938..ad7060af 100644 --- a/src/renderer/components/ui/tiptap/TiptapToolbar.tsx +++ b/src/renderer/components/ui/tiptap/TiptapToolbar.tsx @@ -1,3 +1,4 @@ +import { cn } from '@renderer/lib/utils'; import { useCurrentEditor, useEditorState } from '@tiptap/react'; import { Bold, @@ -16,8 +17,6 @@ import { Undo2, } from 'lucide-react'; -import { cn } from '@renderer/lib/utils'; - import { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip'; import type { ToolbarConfig } from './types'; @@ -26,7 +25,7 @@ interface TiptapToolbarProps { config?: ToolbarConfig; } -function ToolbarButton({ +const ToolbarButton = ({ icon, active, disabled, @@ -38,7 +37,7 @@ function ToolbarButton({ disabled?: boolean; onClick: () => void; label: string; -}) { +}) => { return ( @@ -65,13 +64,13 @@ function ToolbarButton({ ); -} +}; -function Divider() { +const Divider = () => { return
; -} +}; -export function TiptapToolbar({ config }: TiptapToolbarProps) { +export const TiptapToolbar = ({ config }: TiptapToolbarProps) => { const { editor } = useCurrentEditor(); // useEditorState — КРИТИЧНО для v3! @@ -89,8 +88,7 @@ export function TiptapToolbar({ config }: TiptapToolbarProps) { isBulletList: e.isActive('bulletList'), isOrderedList: e.isActive('orderedList'), isBlockquote: e.isActive('blockquote'), - headingLevel: - ([1, 2, 3] as const).find((l) => e.isActive('heading', { level: l })) ?? 0, + headingLevel: ([1, 2, 3] as const).find((l) => e.isActive('heading', { level: l })) ?? 0, canUndo: e.can().undo(), canRedo: e.can().redo(), }; @@ -268,4 +266,4 @@ export function TiptapToolbar({ config }: TiptapToolbarProps) { ))}
); -} +}; diff --git a/src/renderer/components/ui/tiptap/index.ts b/src/renderer/components/ui/tiptap/index.ts index 9d770de8..74ea9e2b 100644 --- a/src/renderer/components/ui/tiptap/index.ts +++ b/src/renderer/components/ui/tiptap/index.ts @@ -1,3 +1,3 @@ +export { EDITOR_PRESETS } from './presets'; export { TiptapEditor } from './TiptapEditor'; export type { EditorPreset, TiptapEditorProps, ToolbarConfig } from './types'; -export { EDITOR_PRESETS } from './presets'; diff --git a/src/renderer/components/ui/tiptap/useTiptapEditor.ts b/src/renderer/components/ui/tiptap/useTiptapEditor.ts index cd34abc0..32ea7888 100644 --- a/src/renderer/components/ui/tiptap/useTiptapEditor.ts +++ b/src/renderer/components/ui/tiptap/useTiptapEditor.ts @@ -1,8 +1,9 @@ +import { useEffect, useRef } from 'react'; + import Placeholder from '@tiptap/extension-placeholder'; import { Markdown } from '@tiptap/markdown'; import { type Extension, useEditor } from '@tiptap/react'; import StarterKit from '@tiptap/starter-kit'; -import { useEffect, useRef } from 'react'; interface UseTiptapEditorOptions { content: string; diff --git a/src/renderer/hooks/useComposerDraft.ts b/src/renderer/hooks/useComposerDraft.ts index 6bb7c17c..019a21f0 100644 --- a/src/renderer/hooks/useComposerDraft.ts +++ b/src/renderer/hooks/useComposerDraft.ts @@ -25,7 +25,7 @@ import { } from '@renderer/utils/attachmentUtils'; import type { InlineChip } from '@renderer/types/inlineChip'; -import type { AttachmentPayload, AgentActionMode } from '@shared/types'; +import type { AgentActionMode, AttachmentPayload } from '@shared/types'; // --------------------------------------------------------------------------- // Types diff --git a/src/renderer/hooks/useMentionDetection.ts b/src/renderer/hooks/useMentionDetection.ts index b80a6775..a273bc69 100644 --- a/src/renderer/hooks/useMentionDetection.ts +++ b/src/renderer/hooks/useMentionDetection.ts @@ -1,4 +1,4 @@ -import { useCallback, useRef, useState, type Dispatch, type SetStateAction } from 'react'; +import { type Dispatch, type SetStateAction, useCallback, useRef, useState } from 'react'; import { getSuggestionInsertionText, diff --git a/src/renderer/services/commentReadStorage.ts b/src/renderer/services/commentReadStorage.ts index 459932b4..295321da 100644 --- a/src/renderer/services/commentReadStorage.ts +++ b/src/renderer/services/commentReadStorage.ts @@ -262,7 +262,7 @@ async function load(): Promise { const merged = { ...cache }; for (const [k, v] of Object.entries(stored)) { if (!v || typeof v !== 'object') continue; - const entry = v as TaskReadEntry; + const entry = v; const prev = merged[k]; if (!prev) { merged[k] = entry; diff --git a/src/renderer/services/composerDraftStorage.ts b/src/renderer/services/composerDraftStorage.ts index ceb73836..5a59e7cc 100644 --- a/src/renderer/services/composerDraftStorage.ts +++ b/src/renderer/services/composerDraftStorage.ts @@ -9,7 +9,7 @@ import { del, get, set } from 'idb-keyval'; import type { InlineChip } from '@renderer/types/inlineChip'; -import type { AttachmentPayload, AgentActionMode } from '@shared/types'; +import type { AgentActionMode, AttachmentPayload } from '@shared/types'; // --------------------------------------------------------------------------- // Types diff --git a/src/renderer/store/index.ts b/src/renderer/store/index.ts index c6d3370a..c63757e4 100644 --- a/src/renderer/store/index.ts +++ b/src/renderer/store/index.ts @@ -15,10 +15,10 @@ import { createConversationSlice } from './slices/conversationSlice'; import { createEditorSlice } from './slices/editorSlice'; import { createExtensionsSlice } from './slices/extensionsSlice'; import { createNotificationSlice } from './slices/notificationSlice'; -import { createScheduleSlice } from './slices/scheduleSlice'; import { createPaneSlice } from './slices/paneSlice'; import { createProjectSlice } from './slices/projectSlice'; import { createRepositorySlice } from './slices/repositorySlice'; +import { createScheduleSlice } from './slices/scheduleSlice'; import { createSessionDetailSlice } from './slices/sessionDetailSlice'; import { createSessionSlice } from './slices/sessionSlice'; import { createSubagentSlice } from './slices/subagentSlice'; diff --git a/src/renderer/store/slices/extensionsSlice.ts b/src/renderer/store/slices/extensionsSlice.ts index 0275b4d0..067a1eba 100644 --- a/src/renderer/store/slices/extensionsSlice.ts +++ b/src/renderer/store/slices/extensionsSlice.ts @@ -12,8 +12,8 @@ import type { ApiKeyStorageStatus, EnrichedPlugin, ExtensionOperationState, - InstallScope, InstalledMcpEntry, + InstallScope, McpCatalogItem, McpCustomInstallRequest, McpInstallRequest, diff --git a/src/renderer/store/slices/scheduleSlice.ts b/src/renderer/store/slices/scheduleSlice.ts index 0d9d4248..a3c99e7e 100644 --- a/src/renderer/store/slices/scheduleSlice.ts +++ b/src/renderer/store/slices/scheduleSlice.ts @@ -2,13 +2,13 @@ import { api } from '@renderer/api'; import { createLogger } from '@shared/utils/logger'; import type { AppState } from '../types'; -import type { StateCreator } from 'zustand'; import type { CreateScheduleInput, Schedule, ScheduleRun, UpdateSchedulePatch, } from '@shared/types'; +import type { StateCreator } from 'zustand'; const logger = createLogger('scheduleSlice'); diff --git a/src/renderer/store/slices/teamSlice.ts b/src/renderer/store/slices/teamSlice.ts index 552ba129..91ef7aaf 100644 --- a/src/renderer/store/slices/teamSlice.ts +++ b/src/renderer/store/slices/teamSlice.ts @@ -1,11 +1,11 @@ import { api } from '@renderer/api'; +import { normalizePath } from '@renderer/utils/pathNormalize'; import { buildTaskChangePresenceKey, buildTaskChangeRequestOptions, isTaskSummaryCacheableForOptions, type TaskChangeRequestOptions, } from '@renderer/utils/taskChangeRequest'; -import { normalizePath } from '@renderer/utils/pathNormalize'; import { IpcError, unwrapIpc } from '@renderer/utils/unwrapIpc'; import { createLogger } from '@shared/utils/logger'; import { getTaskKanbanColumn } from '@shared/utils/reviewState'; @@ -79,6 +79,8 @@ async function pollProvisioningStatus( } } +import { DEFAULT_TOOL_APPROVAL_SETTINGS } from '@shared/types/team'; + import type { AppState } from '../types'; import type { AppConfig } from '@renderer/types/data'; import type { @@ -106,7 +108,6 @@ import type { ToolApprovalSettings, UpdateKanbanPatch, } from '@shared/types'; -import { DEFAULT_TOOL_APPROVAL_SETTINGS } from '@shared/types/team'; import type { StateCreator } from 'zustand'; // --- Clarification notification tracking --- @@ -212,7 +213,13 @@ function detectStatusChangeNotifications( fireStatusChangeNotification( task, fromLabel, - becameApproved ? 'approved' : becameReview ? 'review' : becameNeedsFix ? 'needsFix' : undefined, + becameApproved + ? 'approved' + : becameReview + ? 'review' + : becameNeedsFix + ? 'needsFix' + : undefined, !statusChangeEnabled ); } diff --git a/src/renderer/utils/chipUtils.ts b/src/renderer/utils/chipUtils.ts index 3247f51f..94d2cecc 100644 --- a/src/renderer/utils/chipUtils.ts +++ b/src/renderer/utils/chipUtils.ts @@ -3,13 +3,12 @@ */ import { chipToken } from '@renderer/types/inlineChip'; -import { getSuggestionInsertionText } from '@renderer/utils/mentionSuggestions'; - -import type { MentionSuggestion } from '@renderer/types/mention'; import { getCodeFenceLanguage } from '@renderer/utils/buildSelectionAction'; +import { getSuggestionInsertionText } from '@renderer/utils/mentionSuggestions'; import { getBasename } from '@shared/utils/platformPath'; import type { InlineChip } from '@renderer/types/inlineChip'; +import type { MentionSuggestion } from '@renderer/types/mention'; import type { EditorSelectionAction } from '@shared/types/editor'; // ============================================================================= diff --git a/src/renderer/utils/taskChangeRequest.ts b/src/renderer/utils/taskChangeRequest.ts index 520818a0..2a8a398c 100644 --- a/src/renderer/utils/taskChangeRequest.ts +++ b/src/renderer/utils/taskChangeRequest.ts @@ -1,11 +1,12 @@ -import type { ReviewAPI } from '@shared/types/api'; -import type { TeamTaskWithKanban } from '@shared/types/team'; import { getTaskChangeStateBucket, isTaskChangeSummaryCacheable, type TaskChangeStateBucket, } from '@shared/utils/taskChangeState'; +import type { ReviewAPI } from '@shared/types/api'; +import type { TeamTaskWithKanban } from '@shared/types/team'; + const TASK_SINCE_GRACE_MS = 2 * 60 * 1000; export type TaskChangeRequestOptions = NonNullable[2]>; diff --git a/src/shared/constants/crossTeam.ts b/src/shared/constants/crossTeam.ts index 4cd4c1b3..f4a949ce 100644 --- a/src/shared/constants/crossTeam.ts +++ b/src/shared/constants/crossTeam.ts @@ -93,7 +93,7 @@ export const CROSS_TEAM_PREFIX_RE = new RegExp( /** Parse metadata from a cross-team prefix line. */ export function parseCrossTeamPrefix(text: string): ParsedCrossTeamPrefix | null { - const match = text.match(CROSS_TEAM_PREFIX_RE); + const match = CROSS_TEAM_PREFIX_RE.exec(text); if (!match?.groups) return null; const attrs = parseCrossTeamAttributes(match.groups.attrs ?? ''); diff --git a/src/shared/types/api.ts b/src/shared/types/api.ts index dbc0e18a..9b5bb57f 100644 --- a/src/shared/types/api.ts +++ b/src/shared/types/api.ts @@ -10,20 +10,13 @@ import type { CliArgsValidationResult } from '../utils/cliArgsParser'; import type { CliInstallerAPI } from './cliInstaller'; import type { EditorAPI, EditorFileChangeEvent, ProjectAPI } from './editor'; -import type { McpCatalogAPI, PluginCatalogAPI, ApiKeysAPI, SkillsCatalogAPI } from './extensions'; +import type { ApiKeysAPI, McpCatalogAPI, PluginCatalogAPI, SkillsCatalogAPI } from './extensions'; import type { AppConfig, DetectedError, NotificationTrigger, TriggerTestResult, } from './notifications'; -import type { - CreateScheduleInput, - Schedule, - ScheduleChangeEvent, - ScheduleRun, - UpdateSchedulePatch, -} from './schedule'; import type { AgentChangeSet, ApplyReviewRequest, @@ -36,6 +29,13 @@ import type { SnippetDiff, TaskChangeSetV2, } from './review'; +import type { + CreateScheduleInput, + Schedule, + ScheduleChangeEvent, + ScheduleRun, + UpdateSchedulePatch, +} from './schedule'; import type { AddMemberRequest, AddTaskCommentRequest, diff --git a/src/shared/types/extensions/api.ts b/src/shared/types/extensions/api.ts index 61e7e9c1..f6d7927a 100644 --- a/src/shared/types/extensions/api.ts +++ b/src/shared/types/extensions/api.ts @@ -10,15 +10,15 @@ import type { ApiKeyStorageStatus, } from './apikey'; import type { InstallScope, OperationResult } from './common'; -import type { EnrichedPlugin, PluginInstallRequest } from './plugin'; import type { InstalledMcpEntry, McpCatalogItem, McpCustomInstallRequest, McpInstallRequest, - McpServerDiagnostic, McpSearchResult, + McpServerDiagnostic, } from './mcp'; +import type { EnrichedPlugin, PluginInstallRequest } from './plugin'; import type { SkillCatalogItem, SkillDeleteRequest, diff --git a/src/shared/types/extensions/index.ts b/src/shared/types/extensions/index.ts index 20831b8d..424722a6 100644 --- a/src/shared/types/extensions/index.ts +++ b/src/shared/types/extensions/index.ts @@ -2,8 +2,31 @@ * Extension Store types — barrel export. */ +export type { ApiKeysAPI, McpCatalogAPI, PluginCatalogAPI, SkillsCatalogAPI } from './api'; +export type { + ApiKeyEntry, + ApiKeyLookupResult, + ApiKeySaveRequest, + ApiKeyStorageStatus, +} from './apikey'; export type { ExtensionOperationState, InstallScope, OperationResult } from './common'; - +export type { + InstalledMcpEntry, + McpAuthHeaderDef, + McpCatalogItem, + McpCustomInstallRequest, + McpEnvVarDef, + McpHeaderDef, + McpHostingType, + McpHttpInstallSpec, + McpInstallRequest, + McpInstallSpec, + McpSearchResult, + McpServerDiagnostic, + McpServerHealthStatus, + McpStdioInstallSpec, + McpToolDef, +} from './mcp'; export type { EnrichedPlugin, InstalledPluginEntry, @@ -14,57 +37,29 @@ export type { PluginSortField, } from './plugin'; export { inferCapabilities } from './plugin'; - -export type { - InstalledMcpEntry, - McpAuthHeaderDef, - McpCatalogItem, - McpCustomInstallRequest, - McpServerDiagnostic, - McpServerHealthStatus, - McpEnvVarDef, - McpHeaderDef, - McpHostingType, - McpHttpInstallSpec, - McpInstallRequest, - McpInstallSpec, - McpSearchResult, - McpStdioInstallSpec, - McpToolDef, -} from './mcp'; - export type { CreateSkillRequest, DeleteSkillRequest, SkillCatalogItem, SkillDeleteRequest, + SkillDetail, + SkillDirectoryFlags, SkillDraft, SkillDraftFile, SkillDraftTemplateInput, - SkillDetail, - SkillDirectoryFlags, SkillImportRequest, SkillInvocationMode, SkillIssueSeverity, - SkillRootKind, SkillReviewAction, SkillReviewFileChange, SkillReviewPreview, SkillReviewSummary, + SkillRootKind, SkillSaveResult, SkillScope, SkillSourceType, - UpdateSkillRequest, SkillUpsertRequest, SkillValidationIssue, SkillWatcherEvent, + UpdateSkillRequest, } from './skill'; - -export type { - ApiKeyEntry, - ApiKeyLookupResult, - ApiKeySaveRequest, - ApiKeyStorageStatus, -} from './apikey'; - -export type { ApiKeysAPI, McpCatalogAPI, PluginCatalogAPI, SkillsCatalogAPI } from './api'; diff --git a/src/shared/types/team.ts b/src/shared/types/team.ts index 5a3090ad..c13d9d24 100644 --- a/src/shared/types/team.ts +++ b/src/shared/types/team.ts @@ -155,7 +155,7 @@ export interface SourceMessageSnapshot { /** Message source type (e.g. "user_sent", "inbox"). */ source?: string; /** Attachment metadata references (IDs only, no blobs). */ - attachments?: Array<{ id: string; filename: string; mimeType: string; size: number }>; + attachments?: { id: string; filename: string; mimeType: string; size: number }[]; } // Fields are validated in TeamTaskReader.getTasks() using `satisfies Record`. diff --git a/src/shared/utils/taskChangeState.ts b/src/shared/utils/taskChangeState.ts index 0c8f7cf2..cb55e0c5 100644 --- a/src/shared/utils/taskChangeState.ts +++ b/src/shared/utils/taskChangeState.ts @@ -1,7 +1,7 @@ -import type { TaskHistoryEvent, TeamReviewState } from '@shared/types'; - import { getDerivedReviewState } from './taskHistory'; +import type { TaskHistoryEvent, TeamReviewState } from '@shared/types'; + export type TaskChangeStateBucket = 'approved' | 'review' | 'completed' | 'active'; interface TaskChangeStateLike {