147 lines
5.1 KiB
TypeScript
147 lines
5.1 KiB
TypeScript
import type { TeamModeConfig } from "../../../config/schema/team-mode"
|
|
import { sendMessage } from "../team-mailbox/send"
|
|
import { loadRuntimeState, transitionRuntimeState } from "../team-state-store/store"
|
|
import {
|
|
createSendContext,
|
|
createShutdownMessage,
|
|
findLatestShutdownRequestIndex,
|
|
getLeadMemberName,
|
|
getRuntimeMember,
|
|
} from "./shutdown-helpers"
|
|
export { deleteTeam } from "./delete-team"
|
|
|
|
export async function requestShutdownOfMember(
|
|
teamRunId: string,
|
|
targetMemberName: string,
|
|
requesterName: string,
|
|
config: TeamModeConfig,
|
|
): Promise<void> {
|
|
const runtimeState = await loadRuntimeState(teamRunId, config)
|
|
getRuntimeMember(runtimeState, targetMemberName)
|
|
getRuntimeMember(runtimeState, requesterName)
|
|
|
|
const existingRequestIndex = findLatestShutdownRequestIndex(runtimeState, targetMemberName, requesterName)
|
|
const existingRequest = existingRequestIndex >= 0
|
|
? runtimeState.shutdownRequests[existingRequestIndex]
|
|
: undefined
|
|
if (existingRequest && existingRequest.approvedAt === undefined && existingRequest.rejectedAt === undefined) {
|
|
return
|
|
}
|
|
|
|
await sendMessage(
|
|
createShutdownMessage(requesterName, targetMemberName, "shutdown_request", ""),
|
|
teamRunId,
|
|
config,
|
|
createSendContext(runtimeState, requesterName),
|
|
)
|
|
|
|
await transitionRuntimeState(teamRunId, (currentRuntimeState) => {
|
|
const duplicateRequestIndex = findLatestShutdownRequestIndex(currentRuntimeState, targetMemberName, requesterName)
|
|
const duplicateRequest = duplicateRequestIndex >= 0
|
|
? currentRuntimeState.shutdownRequests[duplicateRequestIndex]
|
|
: undefined
|
|
if (duplicateRequest && duplicateRequest.approvedAt === undefined && duplicateRequest.rejectedAt === undefined) {
|
|
return currentRuntimeState
|
|
}
|
|
|
|
return {
|
|
...currentRuntimeState,
|
|
shutdownRequests: [
|
|
...currentRuntimeState.shutdownRequests,
|
|
{ memberId: targetMemberName, requesterName, requestedAt: Date.now() },
|
|
],
|
|
}
|
|
}, config)
|
|
}
|
|
|
|
export async function approveShutdown(
|
|
teamRunId: string,
|
|
memberName: string,
|
|
approverName: string,
|
|
config: TeamModeConfig,
|
|
): Promise<void> {
|
|
const runtimeState = await loadRuntimeState(teamRunId, config)
|
|
getRuntimeMember(runtimeState, approverName)
|
|
const shutdownRequestIndex = findLatestShutdownRequestIndex(runtimeState, memberName)
|
|
if (shutdownRequestIndex < 0) {
|
|
throw new Error(`shutdown request missing for '${memberName}'`)
|
|
}
|
|
|
|
const existingRequest = runtimeState.shutdownRequests[shutdownRequestIndex]
|
|
if (existingRequest?.approvedAt !== undefined) {
|
|
return
|
|
}
|
|
|
|
const updatedRuntimeState = await transitionRuntimeState(teamRunId, (currentRuntimeState) => {
|
|
const currentRequestIndex = findLatestShutdownRequestIndex(currentRuntimeState, memberName)
|
|
if (currentRequestIndex < 0) {
|
|
throw new Error(`shutdown request missing for '${memberName}'`)
|
|
}
|
|
|
|
const currentRequest = currentRuntimeState.shutdownRequests[currentRequestIndex]
|
|
if (!currentRequest || currentRequest.approvedAt !== undefined) {
|
|
return currentRuntimeState
|
|
}
|
|
|
|
return {
|
|
...currentRuntimeState,
|
|
members: currentRuntimeState.members.map((member) => {
|
|
if (member.name !== memberName || member.status === "completed" || member.status === "errored") {
|
|
return member
|
|
}
|
|
|
|
return { ...member, status: "shutdown_approved" }
|
|
}),
|
|
shutdownRequests: currentRuntimeState.shutdownRequests.map((shutdownRequest, index) => index === currentRequestIndex
|
|
? { ...shutdownRequest, approvedAt: Date.now() }
|
|
: shutdownRequest),
|
|
}
|
|
}, config)
|
|
|
|
await sendMessage(
|
|
createShutdownMessage(approverName, getLeadMemberName(updatedRuntimeState), "shutdown_approved", memberName),
|
|
teamRunId,
|
|
config,
|
|
createSendContext(updatedRuntimeState, approverName),
|
|
)
|
|
}
|
|
|
|
export async function rejectShutdown(
|
|
teamRunId: string,
|
|
memberName: string,
|
|
reason: string,
|
|
config: TeamModeConfig,
|
|
): Promise<void> {
|
|
const runtimeState = await loadRuntimeState(teamRunId, config)
|
|
const shutdownRequestIndex = findLatestShutdownRequestIndex(runtimeState, memberName)
|
|
if (shutdownRequestIndex < 0) {
|
|
throw new Error(`shutdown request missing for '${memberName}'`)
|
|
}
|
|
|
|
const shutdownRequest = runtimeState.shutdownRequests[shutdownRequestIndex]
|
|
if (shutdownRequest.rejectedAt !== undefined && shutdownRequest.rejectedReason === reason) {
|
|
return
|
|
}
|
|
|
|
await sendMessage(
|
|
createShutdownMessage(memberName, shutdownRequest.requesterName, "shutdown_rejected", reason),
|
|
teamRunId,
|
|
config,
|
|
createSendContext(runtimeState, memberName),
|
|
)
|
|
|
|
await transitionRuntimeState(teamRunId, (currentRuntimeState) => {
|
|
const currentRequestIndex = findLatestShutdownRequestIndex(currentRuntimeState, memberName)
|
|
if (currentRequestIndex < 0) {
|
|
throw new Error(`shutdown request missing for '${memberName}'`)
|
|
}
|
|
|
|
return {
|
|
...currentRuntimeState,
|
|
shutdownRequests: currentRuntimeState.shutdownRequests.map((currentRequest, index) => index === currentRequestIndex
|
|
? { ...currentRequest, rejectedAt: Date.now(), rejectedReason: reason }
|
|
: currentRequest),
|
|
}
|
|
}, config)
|
|
}
|