From 9a39ba4be0d0587c27d3e92b22abada35beea39c Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Wed, 22 Apr 2026 12:52:52 +0700 Subject: [PATCH] Default agent ls to active scope --- packages/cli/src/commands/agent/ls.test.ts | 33 +++++++++ packages/cli/src/commands/agent/ls.ts | 79 +++++++++++++--------- 2 files changed, 80 insertions(+), 32 deletions(-) create mode 100644 packages/cli/src/commands/agent/ls.test.ts diff --git a/packages/cli/src/commands/agent/ls.test.ts b/packages/cli/src/commands/agent/ls.test.ts new file mode 100644 index 000000000..479ccfeca --- /dev/null +++ b/packages/cli/src/commands/agent/ls.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, it } from "vitest"; +import { buildAgentLsFetchOptions } from "./ls.js"; + +describe("buildAgentLsFetchOptions", () => { + it("fetches active agents by default", () => { + expect(buildAgentLsFetchOptions({})).toEqual({ + scope: "active", + }); + }); + + it("keeps label and thinking filters within the active scope", () => { + expect( + buildAgentLsFetchOptions({ + label: ["surface=workspace"], + thinking: " medium ", + }), + ).toEqual({ + scope: "active", + filter: { + labels: { surface: "workspace" }, + thinkingOptionId: "medium", + }, + }); + }); + + it("uses the unscoped archived query for -a", () => { + expect(buildAgentLsFetchOptions({ all: true })).toEqual({ + filter: { + includeArchived: true, + }, + }); + }); +}); diff --git a/packages/cli/src/commands/agent/ls.ts b/packages/cli/src/commands/agent/ls.ts index 866869672..629c96842 100644 --- a/packages/cli/src/commands/agent/ls.ts +++ b/packages/cli/src/commands/agent/ls.ts @@ -5,6 +5,10 @@ import type { CommandOptions, ListResult, OutputSchema, CommandError } from "../ import { collectMultiple } from "../../utils/command-options.js"; import { isSameOrDescendantPath } from "../../utils/paths.js"; +type FetchAgentsOptions = NonNullable< + Parameters>["fetchAgents"]>[0] +>; + export function addLsOptions(cmd: Command): Command { return cmd .description("List agents. By default excludes archived agents.") @@ -115,9 +119,49 @@ export interface AgentLsOptions extends CommandOptions { thinking?: string; } +function parseLabelFilters(labels: string[] | undefined): Record { + const labelFilters: Record = {}; + for (const labelStr of labels ?? []) { + const eqIndex = labelStr.indexOf("="); + if (eqIndex !== -1) { + const key = labelStr.slice(0, eqIndex); + const value = labelStr.slice(eqIndex + 1); + labelFilters[key] = value; + } + } + return labelFilters; +} + +export function buildAgentLsFetchOptions( + options: Pick, +): FetchAgentsOptions { + const labelFilters = parseLabelFilters(options.label); + const normalizedThinkingOptionId = options.thinking?.trim(); + const daemonFilter: NonNullable = {}; + + if (options.all) { + daemonFilter.includeArchived = true; + } + if (Object.keys(labelFilters).length > 0) { + daemonFilter.labels = labelFilters; + } + if (normalizedThinkingOptionId) { + daemonFilter.thinkingOptionId = normalizedThinkingOptionId; + } + + const fetchOptions: FetchAgentsOptions = {}; + if (!options.all) { + fetchOptions.scope = "active"; + } + if (Object.keys(daemonFilter).length > 0) { + fetchOptions.filter = daemonFilter; + } + return fetchOptions; +} + /** * Agent ls command semantics: - * - `paseo agent ls` → all non-archived agents + * - `paseo agent ls` → active non-archived agents * - `paseo agent ls -a` → include archived agents */ export async function runLsCommand( @@ -149,37 +193,8 @@ export async function runLsCommand( throw error; } - // Parse --label filters (key=value). - const labelFilters: Record = {}; - if (options.label) { - for (const labelStr of options.label) { - const eqIndex = labelStr.indexOf("="); - if (eqIndex !== -1) { - const key = labelStr.slice(0, eqIndex); - const value = labelStr.slice(eqIndex + 1); - labelFilters[key] = value; - } - } - } - - const daemonFilter: { - includeArchived?: boolean; - labels?: Record; - thinkingOptionId?: string; - } = {}; - if (options.all) { - daemonFilter.includeArchived = true; - } - if (Object.keys(labelFilters).length > 0) { - daemonFilter.labels = labelFilters; - } - if (normalizedThinkingOptionId) { - daemonFilter.thinkingOptionId = normalizedThinkingOptionId; - } - - const fetchPayload = await client.fetchAgents({ - filter: Object.keys(daemonFilter).length > 0 ? daemonFilter : undefined, - }); + const labelFilters = parseLabelFilters(options.label); + const fetchPayload = await client.fetchAgents(buildAgentLsFetchOptions(options)); let agents = fetchPayload.entries.map((entry) => entry.agent); // By default, exclude archived agents. `-a` includes them.