(
workspaceId: string,
options: SendMessageOptions,
internal?: { allowQueuedAgentTask?: boolean; agentInitiated?: boolean }
)
| 7314 | } |
| 7315 | |
| 7316 | async resumeStream( |
| 7317 | workspaceId: string, |
| 7318 | options: SendMessageOptions, |
| 7319 | internal?: { allowQueuedAgentTask?: boolean; agentInitiated?: boolean } |
| 7320 | ): Promise<Result<{ started: boolean }, SendMessageError>> { |
| 7321 | let resumedInterruptedTask = false; |
| 7322 | try { |
| 7323 | // Block streaming while workspace is being renamed to prevent path conflicts |
| 7324 | if (this.renamingWorkspaces.has(workspaceId)) { |
| 7325 | log.debug("resumeStream blocked: workspace is being renamed", { workspaceId }); |
| 7326 | return Err({ |
| 7327 | type: "unknown", |
| 7328 | raw: "Workspace is being renamed. Please wait and try again.", |
| 7329 | }); |
| 7330 | } |
| 7331 | |
| 7332 | // Block streaming while workspace is being removed to prevent races with config/session deletion. |
| 7333 | if (this.removingWorkspaces.has(workspaceId)) { |
| 7334 | log.debug("resumeStream blocked: workspace is being removed", { workspaceId }); |
| 7335 | return Err({ |
| 7336 | type: "unknown", |
| 7337 | raw: "Workspace is being deleted. Please wait and try again.", |
| 7338 | }); |
| 7339 | } |
| 7340 | |
| 7341 | // Guard: avoid creating sessions for workspaces that don't exist anymore. |
| 7342 | if (!this.config.findWorkspace(workspaceId)) { |
| 7343 | return Err({ |
| 7344 | type: "unknown", |
| 7345 | raw: "Workspace not found. It may have been deleted.", |
| 7346 | }); |
| 7347 | } |
| 7348 | |
| 7349 | // Guard: queued agent tasks must not be resumed by generic UI/API calls. |
| 7350 | // TaskService is responsible for dequeuing and starting them. |
| 7351 | if (!internal?.allowQueuedAgentTask) { |
| 7352 | const config = this.config.loadConfigOrDefault(); |
| 7353 | for (const [_projectPath, project] of config.projects) { |
| 7354 | const ws = project.workspaces.find((w) => w.id === workspaceId); |
| 7355 | if (!ws) continue; |
| 7356 | if ( |
| 7357 | ws.parentWorkspaceId && |
| 7358 | (ws.taskStatus === "queued" || ws.taskStatus === "starting") |
| 7359 | ) { |
| 7360 | taskQueueDebug("WorkspaceService.resumeStream blocked (queued/starting task)", { |
| 7361 | workspaceId, |
| 7362 | stack: new Error("resumeStream blocked").stack, |
| 7363 | }); |
| 7364 | return Err({ |
| 7365 | type: "unknown", |
| 7366 | raw: "This agent task is queued or starting and cannot resume through generic calls yet.", |
| 7367 | }); |
| 7368 | } |
| 7369 | break; |
| 7370 | } |
| 7371 | } else { |
| 7372 | taskQueueDebug("WorkspaceService.resumeStream allowed (internal dequeue)", { |
| 7373 | workspaceId, |
nothing calls this directly
no test coverage detected