refactor: replace agent-control MCP with labels system and Paseo MCP

This commit is contained in:
Mohamed Boudra
2026-01-29 11:31:15 +07:00
parent dfda6daeed
commit c015fdbef1
40 changed files with 171 additions and 797 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ Notes:
### `packages/cli/src/commands/agent/inspect.ts`
Inline types:
- `AgentSnapshotLike` (snapshot fields + `lastUsage`, `capabilities`, `availableModes`, `pendingPermissions`, `parentAgentId`)
- `AgentSnapshotLike` (snapshot fields + `lastUsage`, `capabilities`, `availableModes`, `pendingPermissions`)
Recommended server types:
- `AgentSnapshotPayload` (overall snapshot shape). **Not exported**.
+5 -1
View File
@@ -37,9 +37,11 @@ export function createCli(): Command {
// Primary agent commands (top-level)
program
.command('ls')
.description('List agents. By default shows running agents in current directory.')
.description('List agents. By default shows background agents (without ui=true) in current directory.')
.option('-a, --all', 'Include all statuses (not just running)')
.option('-g, --global', 'Show agents from all directories (not just current)')
.option('--label <key=value>', 'Filter by label (can be used multiple times)', collectMultiple, [])
.option('--ui', 'Show only UI agents (equivalent to --label ui=true)')
.option('--json', 'Output in JSON format')
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
.action((options, command) => {
@@ -62,6 +64,8 @@ export function createCli(): Command {
.option('--base <branch>', 'Base branch for worktree (default: current branch)')
.option('--image <path>', 'Attach image(s) to the initial prompt (can be used multiple times)', collectMultiple, [])
.option('--cwd <path>', 'Working directory (default: current)')
.option('--label <key=value>', 'Add label(s) to the agent (can be used multiple times)', collectMultiple, [])
.option('--ui', 'Mark as UI agent (equivalent to --label ui=true)')
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
.action(withOutput(runRunCommand))
+10 -1
View File
@@ -14,12 +14,19 @@ import { withOutput } from '../../output/index.js'
export function createAgentCommand(): Command {
const agent = new Command('agent').description('Manage agents (advanced operations)')
// Helper function to collect multiple option values into an array
const collectMultiple = (value: string, previous: string[]): string[] => {
return previous.concat([value])
}
// Primary agent commands (same as top-level)
agent
.command('ls')
.description('List agents. By default shows running agents in current directory.')
.description('List agents. By default shows background agents (without ui=true) in current directory.')
.option('-a, --all', 'Include all statuses (not just running)')
.option('-g, --global', 'Show agents from all directories (not just current)')
.option('--label <key=value>', 'Filter by label (can be used multiple times)', collectMultiple, [])
.option('--ui', 'Show only UI agents (equivalent to --label ui=true)')
.option('--json', 'Output in JSON format')
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
.action((options, command) => {
@@ -39,6 +46,8 @@ export function createAgentCommand(): Command {
.option('--model <model>', 'Model to use (e.g., claude-sonnet-4-20250514, claude-3-5-haiku-20241022)')
.option('--mode <mode>', 'Provider-specific mode (e.g., plan, default, bypass)')
.option('--cwd <path>', 'Working directory (default: current)')
.option('--label <key=value>', 'Add label(s) to the agent (can be used multiple times)', collectMultiple, [])
.option('--ui', 'Mark as UI agent (equivalent to --label ui=true)')
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
.action(withOutput(runRunCommand))
@@ -34,7 +34,6 @@ interface AgentInspect {
id: string
tool: string
}>
parentAgentId: string | null
}
/** Key-value row for table display */
@@ -122,7 +121,6 @@ function toInspectData(snapshot: AgentSnapshotPayload): AgentInspect {
id: p.id,
tool: p.name ?? 'unknown',
})),
parentAgentId: snapshot.parentAgentId ?? null,
}
}
@@ -177,11 +175,6 @@ function toInspectRows(agent: AgentInspect): InspectRow[] {
rows.push({ key: 'PendingPermissions', value: '[]' })
}
rows.push({
key: 'ParentAgentId',
value: agent.parentAgentId ?? 'null',
})
return rows
}
+44
View File
@@ -82,6 +82,10 @@ export interface AgentLsOptions extends CommandOptions {
status?: string
/** Filter by specific cwd (overrides default cwd filtering) */
cwd?: string
/** Filter by labels (key=value format) */
label?: string[]
/** Filter to UI agents only (equivalent to --label ui=true) */
ui?: boolean
}
/**
@@ -145,6 +149,46 @@ export async function runLsCommand(
})
}
// Label filtering:
// Parse --label flags and --ui flag
// --ui is equivalent to --label ui=true
// By default (no --ui flag), show background agents (those WITHOUT ui=true)
const labelFilters: Record<string, string> = {}
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
}
}
}
// Add ui=true filter if --ui flag is set
if (options.ui) {
labelFilters['ui'] = 'true'
}
// Apply label filtering
if (Object.keys(labelFilters).length > 0) {
// Filter to agents that have ALL specified labels (AND semantics)
agents = agents.filter((a) => {
const agentLabels = (a as any).labels as Record<string, string> | undefined
for (const [key, value] of Object.entries(labelFilters)) {
if (!agentLabels || agentLabels[key] !== value) {
return false
}
}
return true
})
} else {
// Default: show background agents only (those without ui=true)
agents = agents.filter((a) => {
const agentLabels = (a as any).labels as Record<string, string> | undefined
return !agentLabels || agentLabels['ui'] !== 'true'
})
}
await client.close()
// Sort agents: running first, then idle, then others; within each group, most recent first
+28
View File
@@ -37,6 +37,8 @@ export interface AgentRunOptions extends CommandOptions {
base?: string
image?: string[]
cwd?: string
label?: string[]
ui?: boolean
}
function toRunResult(agent: AgentSnapshotPayload): AgentRunResult {
@@ -127,6 +129,31 @@ export async function runRunCommand(
}
: undefined
// Build labels from --label and --ui flags
// --ui is syntactic sugar for --label ui=true
// If explicit --label ui=... is provided, it takes precedence over --ui
const labels: Record<string, string> = {}
if (options.label) {
for (const labelStr of options.label) {
const eqIndex = labelStr.indexOf('=')
if (eqIndex === -1) {
const error: CommandError = {
code: 'INVALID_LABEL',
message: `Invalid label format: ${labelStr}`,
details: 'Labels must be in key=value format',
}
throw error
}
const key = labelStr.slice(0, eqIndex)
const value = labelStr.slice(eqIndex + 1)
labels[key] = value
}
}
// Add ui=true if --ui flag is set and ui label not already set
if (options.ui && !('ui' in labels)) {
labels['ui'] = 'true'
}
// Create the agent
const agent = await client.createAgent({
provider: (options.provider as 'claude' | 'codex' | 'opencode') ?? 'claude',
@@ -138,6 +165,7 @@ export async function runRunCommand(
images,
git,
worktreeName: options.worktree,
labels: Object.keys(labels).length > 0 ? labels : undefined,
})
await client.close()