diff --git a/packages/api/src/services/container-tasks-core.ts b/packages/api/src/services/container-tasks-core.ts index 1b9850fd..7945aee4 100644 --- a/packages/api/src/services/container-tasks-core.ts +++ b/packages/api/src/services/container-tasks-core.ts @@ -27,6 +27,13 @@ const commandSuggestsSsh = (command: string): boolean => command.startsWith("ssh const commandSuggestsAgent = (command: string): boolean => interactiveAgentPattern.test(command) || command.includes("docker-git-agent-") +// Rust browser MCP helpers (`browser-connection`, `docker-git-browser-connection`) +// run on an allocated pty, so without this they would be misclassified as visible +// `ssh` terminals and flood the task manager (issue #383). +const browserConnectionPattern = /(?:^|\/)(?:docker-git-browser-connection|browser-connection)\b/u + +const commandSuggestsBrowserHelper = (command: string): boolean => browserConnectionPattern.test(command) + const resolveAncestorManagedId = ( process: RawContainerProcess, pidToProcess: ReadonlyMap, @@ -49,6 +56,9 @@ const classifyProcess = ( process: RawContainerProcess, managedId: string | undefined ): ContainerTaskKind => { + if (commandSuggestsBrowserHelper(process.command)) { + return "system" + } if (managedId !== undefined || commandSuggestsAgent(process.command)) { return "agent" } @@ -78,7 +88,7 @@ const compareTasks = (left: ContainerTask, right: ContainerTask): number => { // FORMAT THEOREM: forall p in Processes: classify(p) in ContainerTaskKind // PURITY: CORE // EFFECT: none -// INVARIANT: includeDefault=false excludes only baseline system processes +// INVARIANT: includeDefault=false excludes system processes (baseline + browser helpers) // COMPLEXITY: O(n * h) where h is maximum process ancestry depth export const buildContainerTasks = ( processes: ReadonlyArray, diff --git a/packages/api/tests/container-tasks-core.test.ts b/packages/api/tests/container-tasks-core.test.ts index a9404ac9..fe8c1c89 100644 --- a/packages/api/tests/container-tasks-core.test.ts +++ b/packages/api/tests/container-tasks-core.test.ts @@ -31,6 +31,30 @@ describe("container task classification", () => { .toHaveLength(1) }) + it("hides browser-connection MCP helpers as internal system tasks", () => { + const browserCommand = + "browser-connection --project dg-docker-git-issue-376 --network container:dg-docker-git-issue-376" + const visible = buildContainerTasks( + [ + processOf({ command: browserCommand, pid: 11502, ppid: 5142, tty: "pts/1" }), + processOf({ command: "/usr/local/bin/docker-git-browser-connection start", pid: 11600, ppid: 5142, tty: "pts/1" }), + processOf({ command: "node server.js", pid: 20, ppid: 1, tty: "pts/2" }) + ], + [], + false + ) + + expect(visible.map((task) => task.pid)).toEqual([20]) + + const withSystem = buildContainerTasks( + [processOf({ command: browserCommand, pid: 11502, ppid: 5142, tty: "pts/1" })], + [], + true + ) + + expect(withSystem.map((task) => [task.pid, task.kind])).toEqual([[11502, "system"]]) + }) + it("marks descendants of managed agent pid as agent tasks", () => { const tasks = buildContainerTasks( [