diff --git a/packages/cli/__tests__/commands/session.test.ts b/packages/cli/__tests__/commands/session.test.ts index 1e4a45cdd..ee65e5dfb 100644 --- a/packages/cli/__tests__/commands/session.test.ts +++ b/packages/cli/__tests__/commands/session.test.ts @@ -365,6 +365,34 @@ describe("session ls", () => { ]); }); + it("marks metadata-based orchestrators correctly in JSON output", async () => { + writeFileSync( + join(sessionsDir, "app-control"), + "branch=control\nstatus=working\nrole=orchestrator\n", + ); + + mockTmux.mockResolvedValue(null); + mockGit.mockResolvedValue(null); + + await program.parseAsync(["node", "test", "session", "ls", "--json"]); + + expect(consoleSpy).toHaveBeenCalledTimes(1); + expect(JSON.parse(String(consoleSpy.mock.calls[0][0]))).toEqual([ + { + id: "app-control", + projectId: "my-app", + projectName: "My App", + role: "orchestrator", + branch: "control", + status: "working", + issueId: null, + pr: null, + workspacePath: null, + lastActivityAt: null, + }, + ]); + }); + it("returns an empty JSON array when there are no active sessions", async () => { mockTmux.mockResolvedValue(null); diff --git a/packages/cli/src/commands/session.ts b/packages/cli/src/commands/session.ts index 80ea17c7f..36a76780b 100644 --- a/packages/cli/src/commands/session.ts +++ b/packages/cli/src/commands/session.ts @@ -1,7 +1,12 @@ import { spawn } from "node:child_process"; import chalk from "chalk"; import type { Command } from "commander"; -import { loadConfig, SessionNotRestorableError, WorkspaceMissingError } from "@composio/ao-core"; +import { + isOrchestratorSession, + loadConfig, + SessionNotRestorableError, + WorkspaceMissingError, +} from "@composio/ao-core"; import { git, getTmuxActivity, tmux } from "../lib/shell.js"; import { formatAge } from "../lib/format.js"; import { getSessionManager } from "../lib/create-session-manager.js"; @@ -50,6 +55,9 @@ export function registerSession(program: Command): void { // Iterate over all configured projects (not just ones with sessions) const projectIds = opts.project ? [opts.project] : Object.keys(config.projects); + const allSessionPrefixes = Object.entries(config.projects).map( + ([id, project]) => project.sessionPrefix ?? id, + ); const jsonOutput: SessionListEntry[] = []; for (const projectId of projectIds) { @@ -97,7 +105,11 @@ export function registerSession(program: Command): void { const prUrl = s.metadata["pr"] ?? null; if (opts.json) { - const role = isOrchestratorSessionName(config, s.id, projectId) + const role = isOrchestratorSession( + s, + project.sessionPrefix ?? projectId, + allSessionPrefixes, + ) ? "orchestrator" : "worker";