| 1540 | |
| 1541 | // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging |
| 1542 | export class WorkspaceService extends EventEmitter { |
| 1543 | private readonly sessions = new Map<string, AgentSession>(); |
| 1544 | // Startup recovery may need a short-lived session even before the workspace is opened. |
| 1545 | // Promote only sessions that keep retry/stream activity alive after the initial check. |
| 1546 | private readonly transientStartupRecoverySessions = new Map<string, AgentSession>(); |
| 1547 | private readonly sessionSubscriptions = new Map< |
| 1548 | string, |
| 1549 | { chat: () => void; metadata: () => void } |
| 1550 | >(); |
| 1551 | |
| 1552 | private readonly bashMonitorWakeStore: BashMonitorWakeStore; |
| 1553 | private readonly pendingBashMonitorWakeDrainsByOwner = new Map<string, Promise<void>>(); |
| 1554 | private readonly pendingBashMonitorWakeIdleWaitsByOwner = new Map<string, Promise<void>>(); |
| 1555 | private readonly cancelingBashMonitorWakeKeys = new Set<string>(); |
| 1556 | private readonly pendingBashMonitorWakeDrains = new Set<Promise<void>>(); |
| 1557 | private readonly bashMonitorMatchListener = ( |
| 1558 | _workspaceId: string, |
| 1559 | payload: MonitorMatchPayload |
| 1560 | ) => { |
| 1561 | void this.handleBashMonitorMatch(payload); |
| 1562 | }; |
| 1563 | |
| 1564 | // Lazily bootstrapped workflow activity cache so sidebar refreshes don't rescan run history. |
| 1565 | private readonly activeWorkflowRunIdBootstrapsByWorkspace = new Map< |
| 1566 | string, |
| 1567 | Promise<Set<string>> |
| 1568 | >(); |
| 1569 | private readonly activeWorkflowRunIdsByWorkspace = new Map<string, Set<string>>(); |
| 1570 | |
| 1571 | // Debounce post-compaction metadata refreshes (file_edit_* can fire rapidly) |
| 1572 | private readonly postCompactionRefreshTimers = new Map<string, ReturnType<typeof setTimeout>>(); |
| 1573 | // Tracks workspaces currently being renamed to prevent streaming during rename |
| 1574 | private readonly renamingWorkspaces = new Set<string>(); |
| 1575 | |
| 1576 | // Cache for @file mention autocomplete (git ls-files output). |
| 1577 | private readonly fileCompletionsCache = new Map<string, FileCompletionsCacheEntry>(); |
| 1578 | // Tracks workspaces currently being removed to prevent new sessions/streams during deletion. |
| 1579 | private readonly removingWorkspaces = new Set<string>(); |
| 1580 | |
| 1581 | // Tracks workspaces currently being archived to prevent runtime-affecting operations (e.g. SSH) |
| 1582 | // from waking a dedicated workspace during archive(). |
| 1583 | private readonly archivingWorkspaces = new Set<string>(); |
| 1584 | |
| 1585 | // Tracks stream generations that are compaction turns so background stop snapshots |
| 1586 | // can carry authoritative notification policy instead of forcing the frontend to |
| 1587 | // infer compaction from best-effort chat replay state. |
| 1588 | private readonly compactionStreamGenerations = new Map<string, number>(); |
| 1589 | |
| 1590 | // Tracks workspaces undergoing idle (background) compaction so the activity snapshot |
| 1591 | // can tag the stream, letting the frontend suppress notifications for maintenance work. |
| 1592 | private readonly idleCompactingWorkspaces = new Set<string>(); |
| 1593 | |
| 1594 | // Reports the terminal outcome of an idle compaction (success or failure, including |
| 1595 | // mid-stream failures like model_not_found) back to IdleCompactionService so it can |
| 1596 | // stop re-attempting a persistently failing workspace. Wired in ServiceContainer. |
| 1597 | private idleCompactionOutcomeListener: |
| 1598 | | ((workspaceId: string, outcome: IdleCompactionOutcome) => void) |
| 1599 | | undefined; |
nothing calls this directly
no test coverage detected