import type { ExecutionEnvironmentCapabilities, ProjectId, ThreadId, ThreadPullRequestKey,} from "@t3tools/contracts"; type LinkingCapabilities = Pick< ExecutionEnvironmentCapabilities, "threadPullRequests" | "threadPullRequestLinking">; /** Capability negotiation keeps both single-link and multi-link environments usable. */export function threadPullRequestLinkMode(capabilities: LinkingCapabilities | null | undefined) { return capabilities?.threadPullRequests === true ? "multiple" : capabilities?.threadPullRequestLinking === true ? "single" : "unsupported";} export function planThreadPullRequestMutation({ capabilities, threadId, reference, legacyProjectId, legacyRepository, linked,}: { capabilities: LinkingCapabilities | null | undefined; threadId: ThreadId; reference: ThreadPullRequestKey & { readonly url: string }; /** Older servers need the exact repository checkout; same-host routing is not available. */ legacyProjectId: ProjectId | null; /** Provider selector for legacy APIs, which omit Azure organization and project paths. */ legacyRepository?: string | undefined; linked: boolean;}) { switch (threadPullRequestLinkMode(capabilities)) { case "multiple": return linked ? { type: "thread.pull-request.link" as const, input: { threadId, ...reference, source: "manual" as const }, } : { type: "thread.pull-request.unlink" as const, input: { threadId, host: reference.host, repository: reference.repository, number: reference.number, }, }; case "single": if (linked && legacyProjectId === null) return null; return { type: "thread.meta.update" as const, input: { threadId, linkedPullRequest: linked && legacyProjectId !== null ? { projectId: legacyProjectId, repository: legacyRepository ?? reference.repository, number: reference.number, url: reference.url, } : null, }, }; case "unsupported": return null; }}
import type {
ExecutionEnvironmentCapabilities,
ProjectId,
ThreadId,
ThreadPullRequestKey,
} from "@t3tools/contracts";
type LinkingCapabilities = Pick<
ExecutionEnvironmentCapabilities,
"threadPullRequests" | "threadPullRequestLinking"
>;
/** Capability negotiation keeps both single-link and multi-link environments usable. */
export function threadPullRequestLinkMode(capabilities: LinkingCapabilities | null | undefined) {
return capabilities?.threadPullRequests === true
? "multiple"
: capabilities?.threadPullRequestLinking === true
? "single"
: "unsupported";
}
export function planThreadPullRequestMutation({
capabilities,
threadId,
reference,
legacyProjectId,
legacyRepository,
linked,
}: {
capabilities: LinkingCapabilities | null | undefined;
threadId: ThreadId;
reference: ThreadPullRequestKey & { readonly url: string };
/** Older servers need the exact repository checkout; same-host routing is not available. */
legacyProjectId: ProjectId | null;
/** Provider selector for legacy APIs, which omit Azure organization and project paths. */
legacyRepository?: string | undefined;
linked: boolean;
}) {
switch (threadPullRequestLinkMode(capabilities)) {
case "multiple":
return linked
? {
type: "thread.pull-request.link" as const,
input: { threadId, ...reference, source: "manual" as const },
}
: {
type: "thread.pull-request.unlink" as const,
input: {
threadId,
host: reference.host,
repository: reference.repository,
number: reference.number,
},
};
case "single":
if (linked && legacyProjectId === null) return null;
return {
type: "thread.meta.update" as const,
input: {
threadId,
linkedPullRequest:
linked && legacyProjectId !== null
? {
projectId: legacyProjectId,
repository: legacyRepository ?? reference.repository,
number: reference.number,
url: reference.url,
}
: null,
},
};
case "unsupported":
return null;
}
}