Spaces:
Paused
Paused
File size: 3,622 Bytes
8523e75 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import type { IssueExecutionPolicy, IssueExecutionStageParticipant, IssueExecutionStagePrincipal } from "@paperclipai/shared";
import { parseAssigneeValue } from "./assignees";
type StageType = "review" | "approval";
function newId() {
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
return crypto.randomUUID();
}
return `stage-${Math.random().toString(36).slice(2)}`;
}
function principalKey(principal: IssueExecutionStagePrincipal | IssueExecutionStageParticipant) {
return principal.type === "agent" ? `agent:${principal.agentId}` : `user:${principal.userId}`;
}
export function principalFromSelectionValue(value: string): IssueExecutionStagePrincipal | null {
const selection = parseAssigneeValue(value);
if (selection.assigneeAgentId) {
return { type: "agent", agentId: selection.assigneeAgentId, userId: null };
}
if (selection.assigneeUserId) {
return { type: "user", userId: selection.assigneeUserId, agentId: null };
}
return null;
}
export function selectionValueFromPrincipal(principal: IssueExecutionStagePrincipal | IssueExecutionStageParticipant): string {
return principal.type === "agent" ? `agent:${principal.agentId}` : `user:${principal.userId}`;
}
export function stageParticipantValues(policy: IssueExecutionPolicy | null | undefined, stageType: StageType): string[] {
const stage = policy?.stages.find((candidate) => candidate.type === stageType);
return stage?.participants.map((participant) => selectionValueFromPrincipal(participant)) ?? [];
}
function mergeParticipants(
existing: IssueExecutionStageParticipant[] | undefined,
values: string[],
): IssueExecutionStageParticipant[] {
const existingByKey = new Map((existing ?? []).map((participant) => [principalKey(participant), participant]));
const participants: IssueExecutionStageParticipant[] = [];
for (const value of values) {
const principal = principalFromSelectionValue(value);
if (!principal) continue;
const key = principalKey(principal);
const previous = existingByKey.get(key);
participants.push({
id: previous?.id ?? newId(),
type: principal.type,
agentId: principal.type === "agent" ? principal.agentId ?? null : null,
userId: principal.type === "user" ? principal.userId ?? null : null,
});
}
return participants;
}
export function buildExecutionPolicy(input: {
existingPolicy?: IssueExecutionPolicy | null;
reviewerValues: string[];
approverValues: string[];
}): IssueExecutionPolicy | null {
const mode = input.existingPolicy?.mode ?? "normal";
const stages: IssueExecutionPolicy["stages"] = [];
const existingReviewStage = input.existingPolicy?.stages.find((stage) => stage.type === "review");
const reviewParticipants = mergeParticipants(existingReviewStage?.participants, input.reviewerValues);
if (reviewParticipants.length > 0) {
stages.push({
id: existingReviewStage?.id ?? newId(),
type: "review" as const,
approvalsNeeded: 1 as const,
participants: reviewParticipants,
});
}
const existingApprovalStage = input.existingPolicy?.stages.find((stage) => stage.type === "approval");
const approvalParticipants = mergeParticipants(existingApprovalStage?.participants, input.approverValues);
if (approvalParticipants.length > 0) {
stages.push({
id: existingApprovalStage?.id ?? newId(),
type: "approval" as const,
approvalsNeeded: 1 as const,
participants: approvalParticipants,
});
}
if (stages.length === 0) return null;
return {
mode,
commentRequired: true,
stages,
};
}
|