fix(cli): fail agent open for an agent the daemon does not have (#5727)

paseo agent open launched Desktop with whatever string it was given,
printed "opened" and exited 0, so a bad ID moved the user to a broken
"Agent not found" tab and the calling script saw success. Look the agent
up on the daemon first, the way inspect and mode do, and open Desktop on
the ID the daemon resolved.

Closes #5721

Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
This commit is contained in:
paseo-bot[bot]
2026-09-30 02:55:44 +02:00
committed by GitHub
parent 4e9a4582b7
commit 5599f9e567
2 changed files with 82 additions and 6 deletions
+30 -6
View File
@@ -1,5 +1,6 @@
import type { Command } from "commander";
import { connectToDaemon } from "../../utils/client.js";
import type { AgentDeepLinkTarget } from "@getpaseo/protocol/agent-deep-link";
import { openDesktopWithAgent } from "../open.js";
import type {
CommandError,
@@ -30,10 +31,21 @@ export function addOpenOptions(command: Command): Command {
.option("--server <server-id>", "Server ID (defaults to the local daemon)");
}
async function resolveServerId(options: CommandOptions): Promise<string> {
function toOpenError(err: unknown): CommandError {
if (err && typeof err === "object" && "code" in err) {
return err as CommandError;
}
const message = err instanceof Error ? err.message : String(err);
return { code: "OPEN_FAILED", message: `Failed to open agent: ${message}` };
}
async function resolveAgentTarget(
agentId: string,
options: CommandOptions,
): Promise<AgentDeepLinkTarget> {
const explicitServerId = typeof options.server === "string" ? options.server.trim() : "";
if (explicitServerId) {
return explicitServerId;
return { serverId: explicitServerId, agentId };
}
const client = await connectToDaemon({ target: options.daemonTarget });
@@ -46,7 +58,19 @@ async function resolveServerId(options: CommandOptions): Promise<string> {
};
throw error;
}
return serverId;
const fetchResult = await client.fetchAgent({ agentId });
if (!fetchResult) {
const error: CommandError = {
code: "AGENT_NOT_FOUND",
message: `Agent not found: ${agentId}`,
details: 'Use "paseo ls" to list available agents',
};
throw error;
}
return { serverId, agentId: fetchResult.agent.id };
} catch (err) {
throw toOpenError(err);
} finally {
await client.close().catch(() => {});
}
@@ -66,12 +90,12 @@ export async function runOpenCommand(
throw error;
}
const serverId = await resolveServerId(options);
await openDesktopWithAgent({ serverId, agentId });
const target = await resolveAgentTarget(agentId, options);
await openDesktopWithAgent(target);
return {
type: "single",
data: { agentId, serverId, status: "opened" },
data: { ...target, status: "opened" },
schema: openAgentSchema,
};
}
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env npx tsx
import assert from "node:assert";
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
import { existsSync } from "node:fs";
import { join } from "node:path";
import { runPaseoCli, startTestDaemon } from "./helpers/test-daemon.ts";
console.log("=== Agent Open Command Tests ===\n");
if (process.platform !== "linux") {
console.log("Skipped: the fake Desktop app is a Linux AppImage path.");
process.exit(0);
}
const daemon = await startTestDaemon();
// runPaseoCli sets HOME to the daemon's home, where the CLI looks for
// ~/Applications/Paseo.AppImage on Linux. The fake app records its launch.
const launchRecord = join(daemon.paseoHome, "desktop-launches.txt");
const fakeDesktop = join(daemon.paseoHome, "Applications", "Paseo.AppImage");
await mkdir(join(daemon.paseoHome, "Applications"), { recursive: true });
await writeFile(fakeDesktop, `#!/bin/sh\necho "$@" >> "${launchRecord}"\n`);
await chmod(fakeDesktop, 0o755);
try {
{
console.log("Test 1: an unknown agent ID fails without opening Desktop");
const result = await runPaseoCli(daemon, [
"agent",
"open",
"does-not-exist",
"--host",
`127.0.0.1:${daemon.port}`,
"--json",
]);
assert.notStrictEqual(result.exitCode, 0, "open should fail for an unknown agent");
assert.match(JSON.parse(result.stderr).error.message, /Agent not found: does-not-exist/);
// Give a wrongly spawned detached app time to write its record.
await new Promise((resolve) => setTimeout(resolve, 500));
assert.ok(
!existsSync(launchRecord),
`Desktop should not open, but was launched with: ${existsSync(launchRecord) ? await readFile(launchRecord, "utf8") : ""}`,
);
console.log("✓ unknown agent ID fails without opening Desktop\n");
}
} finally {
await daemon.stop();
}
console.log("=== All agent open tests passed ===");