Files
orca/src/main/runtime/runtime-github-issue-comment-commands.ts
T
NeilandKatsuma Takehisa ce07786266 Keep opened issue details and edits in the selected repository (#24729)
Keeps a fork issue’s details, metadata and edits bound to the repository the user opened, including same-number issues in fork and upstream. Repairs selected-assignee leakage and delayed failed edits repainting another issue.

Fixes #24378

Incorporates and cross-reviews contributor PR #24379, including its source-resolver correction and regression material. Covers the contributor PR’s Project-row identity and retained-dialog mutation findings. The final published head passes focused tests, hidden macOS rendering and current CI; the callback-timing bot thread has an evidence-based response.

Co-authored-by: Katsuma Takehisa <k.takehisa@nissogr.com>
2026-10-03 23:19:55 -07:00

118 lines
3.3 KiB
TypeScript

import type { GitHubCreateIssueFields, GitHubIssueUpdate } from '../../shared/issue-mutation-types'
import type { GitHubOwnerRepo } from '../../shared/github/pull-request-types'
import type { GitHubPRReviewCommentInput } from '../../shared/github/comment-types'
import type { Repo } from '../../shared/repo-types'
import type { LocalProjectGhExecOptions } from '../project-runtime-git-options'
import {
addIssueComment,
addPRReviewComment,
addPRReviewCommentReply,
createIssue,
updateIssue
} from '../github/client'
type LocalGitArgs = [] | [LocalProjectGhExecOptions]
type RuntimeGitHubIssueCommentCommandsDeps = {
resolveRepo: (selector: string) => Promise<Repo>
getLocalGitArgs: (repo: Repo) => LocalGitArgs
}
export class RuntimeGitHubIssueCommentCommands {
constructor(private readonly deps: RuntimeGitHubIssueCommentCommandsDeps) {}
async createRepoIssue(
repoSelector: string,
title: string,
body: string,
fields?: GitHubCreateIssueFields
): Promise<Awaited<ReturnType<typeof createIssue>>> {
const repo = await this.deps.resolveRepo(repoSelector)
return createIssue(
repo.path,
title,
body,
repo.issueSourcePreference,
repo.connectionId ?? null,
fields,
...this.deps.getLocalGitArgs(repo)
)
}
async updateRepoIssue(
repoSelector: string,
number: number,
updates: GitHubIssueUpdate
): Promise<Awaited<ReturnType<typeof updateIssue>>> {
const repo = await this.deps.resolveRepo(repoSelector)
return updateIssue(
repo.path,
number,
updates,
repo.connectionId ?? null,
this.deps.getLocalGitArgs(repo)[0],
repo.issueSourcePreference
)
}
async addRepoIssueComment(
repoSelector: string,
number: number,
body: string,
prRepo?: GitHubOwnerRepo | null,
type?: 'issue' | 'pr'
): Promise<Awaited<ReturnType<typeof addIssueComment>>> {
const repo = await this.deps.resolveRepo(repoSelector)
return addIssueComment(
repo.path,
number,
body,
repo.connectionId ?? null,
prRepo ?? null,
this.deps.getLocalGitArgs(repo)[0],
// Why: the issue source selector only scopes issues; PR comments keep their resolution.
type === 'pr' ? undefined : repo.issueSourcePreference
)
}
async addRepoPRReviewComment(
repoSelector: string,
args: Omit<GitHubPRReviewCommentInput, 'repoPath'>
): Promise<Awaited<ReturnType<typeof addPRReviewComment>>> {
const repo = await this.deps.resolveRepo(repoSelector)
return addPRReviewComment({
repoPath: repo.path,
connectionId: repo.connectionId ?? null,
localGitOptions: this.deps.getLocalGitArgs(repo)[0],
...args
})
}
async addRepoPRReviewCommentReply(
repoSelector: string,
args: {
prNumber: number
commentId: number
body: string
threadId?: string
path?: string
line?: number
prRepo?: GitHubOwnerRepo | null
}
): Promise<Awaited<ReturnType<typeof addPRReviewCommentReply>>> {
const repo = await this.deps.resolveRepo(repoSelector)
return addPRReviewCommentReply(
repo.path,
args.prNumber,
args.commentId,
args.body,
args.threadId,
args.path,
args.line,
repo.connectionId ?? null,
args.prRepo ?? null,
...this.deps.getLocalGitArgs(repo)
)
}
}