mirror of
https://github.com/stablyai/orca.git
synced 2026-11-01 09:37:33 +00:00
* fix(wsl): keep background git and GitHub reads from booting a stopped distro Git history, diff and status-follower reads, GitHub issue/work-item/check polls, chat link existence checks, the composer's create-base prefetch, the worktree-root fan-out and the Settings/Automations orca.yaml previews now refuse or skip a stopped WSL distro instead of starting it (E9). * fix(wsl): explicit opens may start a stopped distro; more polls gated (E9) Folds the parallel G1-G6 work into this branch and splits background reads from user acts: - An explicit open runs as a user act for its distro and may boot it: showing a diff tab or its Retry, showing Commits or its Refresh, opening the checks panel or entering its tab, checks Refresh, a check action, and linking or creating a PR. Main takes a wakeWslDistro flag on git:diff, git:branchDiff, git:commitDiff, git:history and gh:prChecks and runs those reads under runAsWslUserAct. - Polls, timers, refreshes after Git actions, prefetches and fan-outs stay background and are refused while the distro is stopped. - Also gated: the hosted-review card poll for every provider, the GitLab checks-panel poll (background flag), and the composer's open-time orca.yaml check (Create re-checks in the foreground). - Pollers keep the data they already show on a refusal: the issue on a card, the checks list, an open diff and loaded submodule children, and stop logging it. * docs(wsl): note that a hosted-review poll's stopped-distro refusal is still logged (E9) * fix(wsl): Settings re-asks orca.yaml once a stopped distro runs; drop link-check gating (E9) - Link existence checks (shell:pathsExist / pathExists) are no longer gated here: answering "missing" cached chat and terminal links as absent and toasted "File not found" on markdown link clicks. The pathsExist refusal lives in its own PR, which throws instead. - Settings no longer sits on "checking" forever: a repo whose distro refused the background check is re-asked on window focus, on visibility, and after 10 s, until it answers. An unverifiable distro is now marked (wsl-distro-unverifiable) and treated as unread too, instead of being stored as "no orca.yaml". - The sidebar issue poll and the Tasks list and count refuse with "Open a terminal in it to start it", since their Retry is itself a background read; the checks panel keeps "Retry", whose Refresh is a user act. * fix(wsl): Tasks Refresh, interactive review refresh and manual PR lookups may start a stopped distro (E9) - Tasks: a Refresh, Retry or search, or Tasks opened on a single repo, passes wakeWslDistro through gh:listWorkItems and gh:countWorkItems (IPC only; the RPC twins and web routes drop it). A multi-repo open stays background. Their refusal says "Retry" again; only the sidebar issue poll says "Open a terminal". - hostedReview:forBranch wakes for an interactive request (the checks panel's manual Refresh), so GitLab, Bitbucket, Azure DevOps and Gitea reviews with nothing cached can load. - gh:prForBranch, the renderer's fallback when refreshPRNow is missing, is gated like the other card polls; a manual lookup wakes, matching refreshPRNow's manual-only rule. The fallback call moves into its own module, built from the refresh candidate. * fix(wsl): only an explicit Refresh starts a stopped distro for review status (E9) hostedReview:forBranch woke on admissionTier 'interactive', but the visible-review scheduler sends 'interactive' for the selected card on a timer, so that poll restarted a stopped distro every interval. The wake is now an explicit wakeWslDistro flag (desktop IPC only). The card refresh helper sets it, since every caller follows a user act (the checks panel's manual Refresh, or a review created, linked or edited), and the manual Refresh also wakes its pre-refresh git status. admissionTier is back to priority only. * fix(wsl): an explicit review Refresh never joins a refused poll (E9) fetchHostedReviewForBranch let a forced card Refresh join an in-flight forced scheduler poll, since the join only compared force. On a stopped WSL distro that poll is refused, so the click got the refusal. The in-flight entry now records the wake, and a waking request joins only a waking flight; a poll may still join an explicit Refresh.
213 lines
7.7 KiB
TypeScript
213 lines
7.7 KiB
TypeScript
import { ipcRenderer } from 'electron'
|
|
import type { GitForkSyncExpectedUpstream, GitForkSyncResult } from '../../shared/git-fork-sync'
|
|
import type { GitStagingArea, GitUpstreamStatus } from '../../shared/git-status-types'
|
|
import type { GitPushTarget } from '../../shared/worktree/types'
|
|
import type { GitStageWorktreeScope } from '../../shared/git-stage-worktree-scope'
|
|
import type { GitHistoryOptions, GitHistoryResult } from '../../shared/git-history'
|
|
import type { PreloadApi } from '../api-types'
|
|
|
|
export const gitApi = {
|
|
status: (args: {
|
|
worktreePath: string
|
|
connectionId?: string
|
|
includeIgnored?: boolean
|
|
bypassEffectiveUpstreamNegativeCache?: boolean
|
|
reuseLineStats?: boolean
|
|
branchLineTotalMergeBase?: string
|
|
requestToken?: string
|
|
wakeWslDistro?: boolean
|
|
}) => ipcRenderer.invoke('git:status', args),
|
|
cancelStatus: (args: { requestToken: string }): Promise<void> =>
|
|
ipcRenderer.invoke('git:cancelStatus', args),
|
|
setStatusUpstreamRefWatch: (args: {
|
|
worktreeId: string
|
|
worktreePath: string
|
|
executionHostId: string
|
|
connectionId?: string
|
|
branch?: string
|
|
upstreamName?: string
|
|
}): Promise<void> => ipcRenderer.invoke('git:setStatusUpstreamRefWatch', args),
|
|
submoduleStatus: (args: {
|
|
worktreePath: string
|
|
submodulePath: string
|
|
connectionId?: string
|
|
area?: GitStagingArea
|
|
}) => ipcRenderer.invoke('git:submoduleStatus', args),
|
|
checkIgnored: (args: {
|
|
worktreePath: string
|
|
paths: string[]
|
|
connectionId?: string
|
|
}): Promise<string[]> => ipcRenderer.invoke('git:checkIgnored', args),
|
|
findHugeFoldersToIgnore: (args: { worktreePath: string }): Promise<string[]> =>
|
|
ipcRenderer.invoke('git:findHugeFoldersToIgnore', args),
|
|
appendGitignore: (args: { worktreePath: string; folderName: string }): Promise<boolean> =>
|
|
ipcRenderer.invoke('git:appendGitignore', args),
|
|
history: (
|
|
args: {
|
|
worktreePath: string
|
|
connectionId?: string
|
|
wakeWslDistro?: boolean
|
|
} & GitHistoryOptions
|
|
): Promise<GitHistoryResult> => ipcRenderer.invoke('git:history', args),
|
|
conflictOperation: (args: { worktreePath: string; connectionId?: string }) =>
|
|
ipcRenderer.invoke('git:conflictOperation', args),
|
|
mutationInFlight: (args: { worktreePath: string; connectionId?: string }) =>
|
|
ipcRenderer.invoke('git:mutationInFlight', args),
|
|
abortMerge: (args: { worktreePath: string; connectionId?: string }): Promise<void> =>
|
|
ipcRenderer.invoke('git:abortMerge', args),
|
|
abortRebase: (args: { worktreePath: string; connectionId?: string }): Promise<void> =>
|
|
ipcRenderer.invoke('git:abortRebase', args),
|
|
diff: (args: {
|
|
worktreePath: string
|
|
filePath: string
|
|
staged: boolean
|
|
compareAgainstHead?: boolean
|
|
connectionId?: string
|
|
wakeWslDistro?: boolean
|
|
}) => ipcRenderer.invoke('git:diff', args),
|
|
branchCompare: (args: { worktreePath: string; baseRef: string; connectionId?: string }) =>
|
|
ipcRenderer.invoke('git:branchCompare', args),
|
|
commitCompare: (args: { worktreePath: string; commitId: string; connectionId?: string }) =>
|
|
ipcRenderer.invoke('git:commitCompare', args),
|
|
upstreamStatus: (args: {
|
|
worktreePath: string
|
|
connectionId?: string
|
|
pushTarget?: GitPushTarget
|
|
}): Promise<GitUpstreamStatus> => ipcRenderer.invoke('git:upstreamStatus', args),
|
|
fetch: (args: {
|
|
worktreePath: string
|
|
worktreeId?: string
|
|
connectionId?: string
|
|
pushTarget?: GitPushTarget
|
|
}): Promise<void> => ipcRenderer.invoke('git:fetch', args),
|
|
syncFork: (args: {
|
|
worktreePath: string
|
|
connectionId?: string
|
|
expectedUpstream: GitForkSyncExpectedUpstream
|
|
}): Promise<GitForkSyncResult> => ipcRenderer.invoke('git:syncFork', args),
|
|
push: (args: {
|
|
worktreePath: string
|
|
worktreeId?: string
|
|
publish?: boolean
|
|
forceWithLease?: boolean
|
|
connectionId?: string
|
|
pushTarget?: unknown
|
|
}): Promise<void> => ipcRenderer.invoke('git:push', args),
|
|
pull: (args: {
|
|
worktreePath: string
|
|
worktreeId?: string
|
|
connectionId?: string
|
|
pushTarget?: GitPushTarget
|
|
}): Promise<void> => ipcRenderer.invoke('git:pull', args),
|
|
fastForward: (args: {
|
|
worktreePath: string
|
|
worktreeId?: string
|
|
connectionId?: string
|
|
pushTarget?: GitPushTarget
|
|
}): Promise<void> => ipcRenderer.invoke('git:fastForward', args),
|
|
rebaseFromBase: (args: {
|
|
worktreePath: string
|
|
baseRef: string
|
|
connectionId?: string
|
|
}): Promise<void> => ipcRenderer.invoke('git:rebaseFromBase', args),
|
|
branchDiff: (args: {
|
|
worktreePath: string
|
|
compare: { baseRef: string; baseOid: string; headOid: string; mergeBase: string }
|
|
filePath: string
|
|
oldPath?: string
|
|
connectionId?: string
|
|
wakeWslDistro?: boolean
|
|
}) => ipcRenderer.invoke('git:branchDiff', args),
|
|
commitDiff: (args: {
|
|
worktreePath: string
|
|
commitOid: string
|
|
parentOid?: string | null
|
|
filePath: string
|
|
oldPath?: string
|
|
connectionId?: string
|
|
wakeWslDistro?: boolean
|
|
}) => ipcRenderer.invoke('git:commitDiff', args),
|
|
commit: (args: {
|
|
worktreePath: string
|
|
message: string
|
|
connectionId?: string
|
|
}): Promise<{ success: boolean; error?: string }> => ipcRenderer.invoke('git:commit', args),
|
|
generateCommitMessage: (args: {
|
|
worktreePath: string
|
|
worktreeId?: string
|
|
repoId?: string
|
|
connectionId?: string
|
|
sourceControlAiResolvedParams?: unknown
|
|
sourceControlAi?: unknown
|
|
agentCmdOverrides?: Record<string, string>
|
|
}) => ipcRenderer.invoke('git:generateCommitMessage', args),
|
|
discoverCommitMessageModels: (args: {
|
|
agentId: string
|
|
worktreePath?: string
|
|
connectionId?: string
|
|
}) => ipcRenderer.invoke('git:discoverCommitMessageModels', args),
|
|
cancelGenerateCommitMessage: (args: {
|
|
worktreePath: string
|
|
connectionId?: string
|
|
}): Promise<void> => ipcRenderer.invoke('git:cancelGenerateCommitMessage', args),
|
|
generatePullRequestFields: (args: {
|
|
worktreePath: string
|
|
worktreeId?: string
|
|
repoId?: string
|
|
base: string
|
|
title: string
|
|
body: string
|
|
draft: boolean
|
|
provider?: unknown
|
|
useTemplate?: boolean
|
|
connectionId?: string
|
|
sourceControlAiResolvedParams?: unknown
|
|
sourceControlAi?: unknown
|
|
agentCmdOverrides?: Record<string, string>
|
|
}) => ipcRenderer.invoke('git:generatePullRequestFields', args),
|
|
cancelGeneratePullRequestFields: (args: {
|
|
worktreePath: string
|
|
connectionId?: string
|
|
}): Promise<void> => ipcRenderer.invoke('git:cancelGeneratePullRequestFields', args),
|
|
stage: (args: { worktreePath: string; filePath: string; connectionId?: string }): Promise<void> =>
|
|
ipcRenderer.invoke('git:stage', args),
|
|
bulkStage: (args: {
|
|
worktreePath: string
|
|
filePaths: string[]
|
|
connectionId?: string
|
|
scope?: GitStageWorktreeScope
|
|
}): Promise<void> => ipcRenderer.invoke('git:bulkStage', args),
|
|
unstage: (args: {
|
|
worktreePath: string
|
|
filePath: string
|
|
connectionId?: string
|
|
}): Promise<void> => ipcRenderer.invoke('git:unstage', args),
|
|
bulkUnstage: (args: {
|
|
worktreePath: string
|
|
filePaths: string[]
|
|
connectionId?: string
|
|
}): Promise<void> => ipcRenderer.invoke('git:bulkUnstage', args),
|
|
discard: (args: {
|
|
worktreePath: string
|
|
filePath: string
|
|
connectionId?: string
|
|
}): Promise<void> => ipcRenderer.invoke('git:discard', args),
|
|
bulkDiscard: (args: {
|
|
worktreePath: string
|
|
filePaths: string[]
|
|
connectionId?: string
|
|
}): Promise<void> => ipcRenderer.invoke('git:bulkDiscard', args),
|
|
remoteFileUrl: (args: {
|
|
worktreePath: string
|
|
relativePath: string
|
|
line: number
|
|
endLine?: number
|
|
connectionId?: string
|
|
}): Promise<string | null> => ipcRenderer.invoke('git:remoteFileUrl', args),
|
|
remoteCommitUrl: (args: {
|
|
worktreePath: string
|
|
sha: string
|
|
connectionId?: string
|
|
}): Promise<string | null> => ipcRenderer.invoke('git:remoteCommitUrl', args)
|
|
} satisfies PreloadApi['git']
|