mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-03 10:28:43 +02:00
- parse prompt tools metadata and carry structured promptInvocation payloads - store prompt invocation metadata on trigger messages for replay-safe reruns - route prompt agents through per-turn plan or Copilot agent overrides - restrict prompt-scoped tools in sidecar session configuration - auto-rescan project customization files with debounced watchers - document the new customization watcher and prompt invocation flow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
327 lines
14 KiB
TypeScript
327 lines
14 KiB
TypeScript
import electron from 'electron';
|
|
import type { BrowserWindow } from 'electron';
|
|
|
|
import { ipcChannels } from '@shared/contracts/channels';
|
|
import type {
|
|
BranchSessionInput,
|
|
CancelSessionTurnInput,
|
|
CreateSessionInput,
|
|
CreateProjectGitBranchInput,
|
|
DismissSessionMcpAuthInput,
|
|
DismissSessionPlanReviewInput,
|
|
DeleteProjectGitBranchInput,
|
|
DeleteSessionInput,
|
|
DiscardSessionRunGitChangesInput,
|
|
EditAndResendSessionMessageInput,
|
|
CommitProjectGitChangesInput,
|
|
ProjectGitDetailsInput,
|
|
ProjectGitFilePreviewInput,
|
|
ProjectGitFileSelectionInput,
|
|
ProjectGitInput,
|
|
PullProjectGitInput,
|
|
RegenerateSessionMessageInput,
|
|
StartSessionMcpAuthInput,
|
|
SuggestProjectGitCommitMessageInput,
|
|
SwitchProjectGitBranchInput,
|
|
DuplicateSessionInput,
|
|
RenameSessionInput,
|
|
RescanProjectConfigsInput,
|
|
RescanProjectCustomizationInput,
|
|
ResolveProjectDiscoveredToolingInput,
|
|
ResolveSessionApprovalInput,
|
|
ResolveSessionUserInputInput,
|
|
ResolveWorkspaceDiscoveredToolingInput,
|
|
SaveLspProfileInput,
|
|
SaveMcpServerInput,
|
|
SavePatternInput,
|
|
SendSessionMessageInput,
|
|
SetPatternFavoriteInput,
|
|
SetProjectAgentProfileEnabledInput,
|
|
SetSessionArchivedInput,
|
|
SetSessionInteractionModeInput,
|
|
SetSessionMessagePinnedInput,
|
|
SetSessionPinnedInput,
|
|
SetTerminalHeightInput,
|
|
ResizeTerminalInput,
|
|
UpdateSessionModelConfigInput,
|
|
UpdateSessionApprovalSettingsInput,
|
|
UpdateSessionToolingInput,
|
|
} from '@shared/contracts/ipc';
|
|
import type { QuerySessionsInput } from '@shared/domain/sessionLibrary';
|
|
import type { AppearanceTheme } from '@shared/domain/tooling';
|
|
|
|
import { AryxAppService } from '@main/AryxAppService';
|
|
import { AutoUpdateService } from '@main/services/autoUpdater';
|
|
import { createDesktopNotificationHandler } from '@main/services/desktopNotifications';
|
|
import { applyTitleBarTheme } from '@main/windows/titleBarTheme';
|
|
import type { UpdateStatus } from '@shared/contracts/ipc';
|
|
|
|
const { ipcMain } = electron;
|
|
|
|
export function registerIpcHandlers(
|
|
window: BrowserWindow,
|
|
service: AryxAppService,
|
|
autoUpdateService: AutoUpdateService,
|
|
): void {
|
|
window.on('focus', () => {
|
|
if (service.isGitAutoRefreshEnabled()) {
|
|
service.scheduleProjectGitRefresh();
|
|
}
|
|
});
|
|
|
|
ipcMain.handle(ipcChannels.describeSidecarCapabilities, () => service.describeSidecarCapabilities());
|
|
ipcMain.handle(ipcChannels.refreshSidecarCapabilities, () => service.refreshSidecarCapabilities());
|
|
ipcMain.handle(ipcChannels.loadWorkspace, () => service.loadWorkspace());
|
|
ipcMain.handle(ipcChannels.addProject, () => service.addProject());
|
|
ipcMain.handle(ipcChannels.removeProject, (_event, projectId: string) => service.removeProject(projectId));
|
|
ipcMain.handle(
|
|
ipcChannels.resolveWorkspaceDiscoveredTooling,
|
|
(_event, input: ResolveWorkspaceDiscoveredToolingInput) =>
|
|
service.resolveWorkspaceDiscoveredTooling(input.serverIds, input.resolution),
|
|
);
|
|
ipcMain.handle(ipcChannels.refreshProjectGitContext, (_event, projectId?: string) =>
|
|
service.refreshProjectGitContext(projectId),
|
|
);
|
|
ipcMain.handle(ipcChannels.getProjectGitDetails, (_event, input: ProjectGitDetailsInput) =>
|
|
service.getProjectGitDetails(input.projectId, input.commitLimit),
|
|
);
|
|
ipcMain.handle(ipcChannels.getProjectGitFilePreview, (_event, input: ProjectGitFilePreviewInput) =>
|
|
service.getProjectGitFilePreview(input.projectId, input.file),
|
|
);
|
|
ipcMain.handle(ipcChannels.rescanProjectConfigs, (_event, input: RescanProjectConfigsInput) =>
|
|
service.rescanProjectConfigs(input.projectId),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.rescanProjectCustomization,
|
|
(_event, input: RescanProjectCustomizationInput) =>
|
|
service.rescanProjectCustomization(input.projectId),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.resolveProjectDiscoveredTooling,
|
|
(_event, input: ResolveProjectDiscoveredToolingInput) =>
|
|
service.resolveProjectDiscoveredTooling(input.projectId, input.serverIds, input.resolution),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.setProjectAgentProfileEnabled,
|
|
(_event, input: SetProjectAgentProfileEnabledInput) =>
|
|
service.setProjectAgentProfileEnabled(input.projectId, input.agentProfileId, input.enabled),
|
|
);
|
|
ipcMain.handle(ipcChannels.savePattern, (_event, input: SavePatternInput) => service.savePattern(input.pattern));
|
|
ipcMain.handle(ipcChannels.deletePattern, (_event, patternId: string) => service.deletePattern(patternId));
|
|
ipcMain.handle(ipcChannels.setPatternFavorite, (_event, input: SetPatternFavoriteInput) =>
|
|
service.setPatternFavorite(input.patternId, input.isFavorite),
|
|
);
|
|
ipcMain.handle(ipcChannels.setTheme, async (_event, theme: AppearanceTheme) => {
|
|
const result = await service.setTheme(theme);
|
|
applyTitleBarTheme(window, theme);
|
|
return result;
|
|
});
|
|
ipcMain.handle(
|
|
ipcChannels.setTerminalHeight,
|
|
(_event, input: SetTerminalHeightInput) => service.setTerminalHeight(input.height),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.setNotificationsEnabled,
|
|
(_event, enabled: boolean) => service.setNotificationsEnabled(enabled),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.setMinimizeToTray,
|
|
(_event, enabled: boolean) => service.setMinimizeToTray(enabled),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.setGitAutoRefreshEnabled,
|
|
(_event, enabled: boolean) => service.setGitAutoRefreshEnabled(enabled),
|
|
);
|
|
ipcMain.handle(ipcChannels.checkForUpdates, () => autoUpdateService.checkForUpdates());
|
|
ipcMain.handle(ipcChannels.installUpdate, () => {
|
|
autoUpdateService.installUpdate();
|
|
});
|
|
ipcMain.handle(ipcChannels.saveMcpServer, (_event, input: SaveMcpServerInput) =>
|
|
service.saveMcpServer(input.server),
|
|
);
|
|
ipcMain.handle(ipcChannels.deleteMcpServer, (_event, serverId: string) =>
|
|
service.deleteMcpServer(serverId),
|
|
);
|
|
ipcMain.handle(ipcChannels.saveLspProfile, (_event, input: SaveLspProfileInput) =>
|
|
service.saveLspProfile(input.profile),
|
|
);
|
|
ipcMain.handle(ipcChannels.deleteLspProfile, (_event, profileId: string) =>
|
|
service.deleteLspProfile(profileId),
|
|
);
|
|
ipcMain.handle(ipcChannels.describeTerminal, () => service.describeTerminal());
|
|
ipcMain.handle(ipcChannels.createTerminal, () => service.createTerminal());
|
|
ipcMain.handle(ipcChannels.restartTerminal, () => service.restartTerminal());
|
|
ipcMain.handle(ipcChannels.killTerminal, () => service.killTerminal());
|
|
ipcMain.on(ipcChannels.writeTerminal, (_event, data: string) => {
|
|
service.writeTerminal(data);
|
|
});
|
|
ipcMain.on(ipcChannels.resizeTerminal, (_event, input: ResizeTerminalInput) => {
|
|
service.resizeTerminal(input.cols, input.rows);
|
|
});
|
|
ipcMain.handle(ipcChannels.updateSessionTooling, (_event, input: UpdateSessionToolingInput) =>
|
|
service.updateSessionTooling(
|
|
input.sessionId,
|
|
input.enabledMcpServerIds,
|
|
input.enabledLspProfileIds,
|
|
),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.updateSessionApprovalSettings,
|
|
(_event, input: UpdateSessionApprovalSettingsInput) =>
|
|
service.updateSessionApprovalSettings(input.sessionId, input.autoApprovedToolNames),
|
|
);
|
|
ipcMain.handle(ipcChannels.createSession, (_event, input: CreateSessionInput) =>
|
|
service.createSession(input.projectId, input.patternId),
|
|
);
|
|
ipcMain.handle(ipcChannels.duplicateSession, (_event, input: DuplicateSessionInput) =>
|
|
service.duplicateSession(input.sessionId),
|
|
);
|
|
ipcMain.handle(ipcChannels.branchSession, (_event, input: BranchSessionInput) =>
|
|
service.branchSession(input.sessionId, input.messageId),
|
|
);
|
|
ipcMain.handle(ipcChannels.setSessionMessagePinned, (_event, input: SetSessionMessagePinnedInput) =>
|
|
service.setSessionMessagePinned(input.sessionId, input.messageId, input.isPinned),
|
|
);
|
|
ipcMain.handle(ipcChannels.renameSession, (_event, input: RenameSessionInput) =>
|
|
service.renameSession(input.sessionId, input.title),
|
|
);
|
|
ipcMain.handle(ipcChannels.setSessionPinned, (_event, input: SetSessionPinnedInput) =>
|
|
service.setSessionPinned(input.sessionId, input.isPinned),
|
|
);
|
|
ipcMain.handle(ipcChannels.setSessionArchived, (_event, input: SetSessionArchivedInput) =>
|
|
service.setSessionArchived(input.sessionId, input.isArchived),
|
|
);
|
|
ipcMain.handle(ipcChannels.deleteSession, (_event, input: DeleteSessionInput) =>
|
|
service.deleteSession(input.sessionId),
|
|
);
|
|
ipcMain.handle(ipcChannels.regenerateSessionMessage, (_event, input: RegenerateSessionMessageInput) =>
|
|
service.regenerateSessionMessage(input.sessionId, input.messageId),
|
|
);
|
|
ipcMain.handle(ipcChannels.editAndResendSessionMessage, (_event, input: EditAndResendSessionMessageInput) =>
|
|
service.editAndResendSessionMessage(input.sessionId, input.messageId, input.content, input.attachments),
|
|
);
|
|
ipcMain.handle(ipcChannels.sendSessionMessage, (_event, input: SendSessionMessageInput) =>
|
|
service.sendSessionMessage(
|
|
input.sessionId,
|
|
input.content,
|
|
input.attachments,
|
|
input.messageMode,
|
|
input.promptInvocation,
|
|
),
|
|
);
|
|
ipcMain.handle(ipcChannels.cancelSessionTurn, (_event, input: CancelSessionTurnInput) =>
|
|
service.cancelSessionTurn(input.sessionId),
|
|
);
|
|
ipcMain.handle(ipcChannels.resolveSessionApproval, (_event, input: ResolveSessionApprovalInput) =>
|
|
service.resolveSessionApproval(input.sessionId, input.approvalId, input.decision, input.alwaysApprove),
|
|
);
|
|
ipcMain.handle(ipcChannels.resolveSessionUserInput, (_event, input: ResolveSessionUserInputInput) =>
|
|
service.resolveSessionUserInput(input.sessionId, input.userInputId, input.answer, input.wasFreeform),
|
|
);
|
|
ipcMain.handle(ipcChannels.setSessionInteractionMode, (_event, input: SetSessionInteractionModeInput) =>
|
|
service.setSessionInteractionMode(input.sessionId, input.mode),
|
|
);
|
|
ipcMain.handle(ipcChannels.dismissSessionPlanReview, (_event, input: DismissSessionPlanReviewInput) =>
|
|
service.dismissSessionPlanReview(input.sessionId),
|
|
);
|
|
ipcMain.handle(ipcChannels.dismissSessionMcpAuth, (_event, input: DismissSessionMcpAuthInput) =>
|
|
service.dismissSessionMcpAuth(input.sessionId),
|
|
);
|
|
ipcMain.handle(ipcChannels.startSessionMcpAuth, (_event, input: StartSessionMcpAuthInput) =>
|
|
service.startSessionMcpAuth(input.sessionId),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.discardSessionRunGitChanges,
|
|
(_event, input: DiscardSessionRunGitChangesInput) =>
|
|
service.discardSessionRunGitChanges(input.sessionId, input.runId, input.files),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.suggestProjectGitCommitMessage,
|
|
(_event, input: SuggestProjectGitCommitMessageInput) =>
|
|
service.suggestProjectGitCommitMessage(input.sessionId, input.runId, input.conventionalType),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.updateSessionModelConfig,
|
|
(_event, input: UpdateSessionModelConfigInput) =>
|
|
service.updateSessionModelConfig(input.sessionId, input.model, input.reasoningEffort),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.stageProjectGitFiles,
|
|
(_event, input: ProjectGitFileSelectionInput) => service.stageProjectGitFiles(input.projectId, input.files),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.unstageProjectGitFiles,
|
|
(_event, input: ProjectGitFileSelectionInput) => service.unstageProjectGitFiles(input.projectId, input.files),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.commitProjectGitChanges,
|
|
(_event, input: CommitProjectGitChangesInput) =>
|
|
service.commitProjectGitChanges(input.projectId, input.message, input.files, input.push),
|
|
);
|
|
ipcMain.handle(ipcChannels.pushProjectGit, (_event, input: ProjectGitInput) =>
|
|
service.pushProjectGit(input.projectId),
|
|
);
|
|
ipcMain.handle(ipcChannels.fetchProjectGit, (_event, input: ProjectGitInput) =>
|
|
service.fetchProjectGit(input.projectId),
|
|
);
|
|
ipcMain.handle(ipcChannels.pullProjectGit, (_event, input: PullProjectGitInput) =>
|
|
service.pullProjectGit(input.projectId, input.rebase),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.createProjectGitBranch,
|
|
(_event, input: CreateProjectGitBranchInput) =>
|
|
service.createProjectGitBranch(input.projectId, input.name, input.startPoint, input.checkout),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.switchProjectGitBranch,
|
|
(_event, input: SwitchProjectGitBranchInput) =>
|
|
service.switchProjectGitBranch(input.projectId, input.name),
|
|
);
|
|
ipcMain.handle(
|
|
ipcChannels.deleteProjectGitBranch,
|
|
(_event, input: DeleteProjectGitBranchInput) =>
|
|
service.deleteProjectGitBranch(input.projectId, input.name, input.force),
|
|
);
|
|
ipcMain.handle(ipcChannels.querySessions, (_event, input: QuerySessionsInput) => service.querySessions(input));
|
|
ipcMain.handle(ipcChannels.selectProject, (_event, projectId?: string) => service.selectProject(projectId));
|
|
ipcMain.handle(ipcChannels.selectPattern, (_event, patternId?: string) => service.selectPattern(patternId));
|
|
ipcMain.handle(ipcChannels.selectSession, (_event, sessionId?: string) => service.selectSession(sessionId));
|
|
ipcMain.handle(ipcChannels.openAppDataFolder, () => service.openAppDataFolder());
|
|
ipcMain.handle(ipcChannels.resetLocalWorkspace, () => service.resetLocalWorkspace());
|
|
ipcMain.handle(ipcChannels.getQuota, () => service.getQuota());
|
|
|
|
service.on('workspace-updated', (workspace) => {
|
|
window.webContents.send(ipcChannels.workspaceUpdated, workspace);
|
|
});
|
|
|
|
service.on('session-event', (event) => {
|
|
window.webContents.send(ipcChannels.sessionEvent, event);
|
|
});
|
|
|
|
// Desktop notifications for run completion, failure, and approval requests
|
|
const handleNotification = createDesktopNotificationHandler(
|
|
() => window,
|
|
() => service.getCachedWorkspace(),
|
|
(sessionId) => service.selectSession(sessionId),
|
|
);
|
|
service.on('session-event', handleNotification);
|
|
|
|
const sendUpdateStatus = (status: UpdateStatus) => {
|
|
if (!window.isDestroyed()) {
|
|
window.webContents.send(ipcChannels.updateStatus, status);
|
|
}
|
|
};
|
|
autoUpdateService.onStatus(sendUpdateStatus);
|
|
window.webContents.on('did-finish-load', () => {
|
|
sendUpdateStatus(autoUpdateService.getStatus());
|
|
});
|
|
|
|
service.on('terminal-data', (data) => {
|
|
window.webContents.send(ipcChannels.terminalData, data);
|
|
});
|
|
|
|
service.on('terminal-exit', (info) => {
|
|
window.webContents.send(ipcChannels.terminalExit, info);
|
|
});
|
|
}
|