(
taskId: string,
options: {
workflowRunId: string;
stepId: string;
inputHash: string;
finalizationToken: string;
finalInstructions?: string;
}
)
| 5008 | } |
| 5009 | |
| 5010 | async requestAgentFinalReportForTimeout( |
| 5011 | taskId: string, |
| 5012 | options: { |
| 5013 | workflowRunId: string; |
| 5014 | stepId: string; |
| 5015 | inputHash: string; |
| 5016 | finalizationToken: string; |
| 5017 | finalInstructions?: string; |
| 5018 | } |
| 5019 | ): Promise<"prompted" | "queued" | "already_reported" | "not_active"> { |
| 5020 | assert(taskId.length > 0, "requestAgentFinalReportForTimeout: taskId must be non-empty"); |
| 5021 | assert( |
| 5022 | options.finalizationToken.length > 0, |
| 5023 | "requestAgentFinalReportForTimeout: finalizationToken must be non-empty" |
| 5024 | ); |
| 5025 | |
| 5026 | const reservation = await this.workspaceEventLocks.withLock(taskId, async () => { |
| 5027 | const cfg = this.config.loadConfigOrDefault(); |
| 5028 | const entry = findWorkspaceEntry(cfg, taskId); |
| 5029 | if (!entry?.workspace.parentWorkspaceId) { |
| 5030 | return { status: "not_active" as const }; |
| 5031 | } |
| 5032 | if (hasCompletedAgentReport(entry.workspace) || this.completedReportsByTaskId.has(taskId)) { |
| 5033 | return { status: "already_reported" as const }; |
| 5034 | } |
| 5035 | if (entry.workspace.taskStatus === "interrupted" && !this.aiService.isStreaming(taskId)) { |
| 5036 | return { status: "not_active" as const }; |
| 5037 | } |
| 5038 | |
| 5039 | const tokens = entry.workspace.taskTimeoutFinalizationTokens ?? []; |
| 5040 | const alreadyPrompted = tokens.includes(options.finalizationToken); |
| 5041 | if (!alreadyPrompted) { |
| 5042 | await this.editWorkspaceEntry( |
| 5043 | taskId, |
| 5044 | (workspace) => { |
| 5045 | workspace.taskStatus = "awaiting_report"; |
| 5046 | }, |
| 5047 | { allowMissing: true } |
| 5048 | ); |
| 5049 | } |
| 5050 | return { status: "reserved" as const, alreadyPrompted }; |
| 5051 | }); |
| 5052 | |
| 5053 | if (reservation.status !== "reserved") { |
| 5054 | return reservation.status; |
| 5055 | } |
| 5056 | if (reservation.alreadyPrompted) { |
| 5057 | return "prompted"; |
| 5058 | } |
| 5059 | if (this.aiService.isStreaming(taskId)) { |
| 5060 | await this.aiService.stopStream(taskId, { |
| 5061 | soft: true, |
| 5062 | abandonPartial: false, |
| 5063 | abortReason: "system", |
| 5064 | }); |
| 5065 | } |
| 5066 | |
| 5067 | const freshConfig = this.config.loadConfigOrDefault(); |
nothing calls this directly
no test coverage detected