(
taskId: string,
options?: {
timeoutMs?: number;
abortSignal?: AbortSignal;
requestingWorkspaceId?: string;
backgroundOnMessageQueued?: boolean;
onExecutionStarted?: () => void | Promise<void>;
}
)
| 5187 | } |
| 5188 | |
| 5189 | async waitForAgentReport( |
| 5190 | taskId: string, |
| 5191 | options?: { |
| 5192 | timeoutMs?: number; |
| 5193 | abortSignal?: AbortSignal; |
| 5194 | requestingWorkspaceId?: string; |
| 5195 | backgroundOnMessageQueued?: boolean; |
| 5196 | onExecutionStarted?: () => void | Promise<void>; |
| 5197 | } |
| 5198 | ): Promise<{ |
| 5199 | reportMarkdown: string; |
| 5200 | title?: string; |
| 5201 | structuredOutput?: unknown; |
| 5202 | planFilePath?: string; |
| 5203 | }> { |
| 5204 | assert(taskId.length > 0, "waitForAgentReport: taskId must be non-empty"); |
| 5205 | |
| 5206 | // Report monotonicity invariant: check the in-memory cache before any status-based |
| 5207 | // interruption handling so a finalized report stays awaitable once observed. |
| 5208 | const cached = this.completedReportsByTaskId.get(taskId); |
| 5209 | if (cached) { |
| 5210 | return { |
| 5211 | reportMarkdown: cached.reportMarkdown, |
| 5212 | title: cached.title, |
| 5213 | planFilePath: cached.planFilePath, |
| 5214 | structuredOutput: cached.structuredOutput, |
| 5215 | }; |
| 5216 | } |
| 5217 | |
| 5218 | const timeoutMs = options?.timeoutMs ?? 10 * 60 * 1000; // 10 minutes |
| 5219 | assert(Number.isFinite(timeoutMs) && timeoutMs > 0, "waitForAgentReport: timeoutMs invalid"); |
| 5220 | |
| 5221 | const requestingWorkspaceId = coerceNonEmptyString(options?.requestingWorkspaceId); |
| 5222 | if (requestingWorkspaceId) { |
| 5223 | // A renewed foreground wait means this task is blocking again unless re-backgrounded later. |
| 5224 | this.markTaskForegroundRelevant(taskId); |
| 5225 | } |
| 5226 | |
| 5227 | const tryReadPersistedReport = async (): Promise<{ |
| 5228 | reportMarkdown: string; |
| 5229 | planFilePath?: string; |
| 5230 | structuredOutput?: unknown; |
| 5231 | title?: string; |
| 5232 | } | null> => { |
| 5233 | if (!requestingWorkspaceId) { |
| 5234 | return null; |
| 5235 | } |
| 5236 | |
| 5237 | const sessionDir = this.config.getSessionDir(requestingWorkspaceId); |
| 5238 | const artifact = await readSubagentReportArtifact(sessionDir, taskId); |
| 5239 | if (!artifact) { |
| 5240 | return null; |
| 5241 | } |
| 5242 | |
| 5243 | // Cache for the current process (best-effort). Disk is the source of truth. |
| 5244 | this.completedReportsByTaskId.set(taskId, { |
| 5245 | reportMarkdown: artifact.reportMarkdown, |
| 5246 | title: artifact.title, |
nothing calls this directly
no test coverage detected