mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-28 12:12:47 +00:00
fix(cli): emit full permission request ids from permit ls, allow, and deny (#5305)
The permit result items stored the request id already shortened to eight characters for the table, so JSON, YAML, and quiet output serialized that display value. Every request id starts with "permission-", so every row came out as "permissi" and could not be passed back to permit allow. The items now keep the full id and only the table column shortens it. Closes #4732 Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -16,7 +16,7 @@ export interface PermissionResponseItem {
|
||||
export const permitResponseSchema: OutputSchema<PermissionResponseItem> = {
|
||||
idField: "requestId",
|
||||
columns: [
|
||||
{ header: "REQUEST ID", field: "requestId", width: 12 },
|
||||
{ header: "REQUEST ID", field: (item) => item.requestId.slice(0, 8), width: 12 },
|
||||
{ header: "AGENT", field: "agentShortId", width: 10 },
|
||||
{ header: "TOOL", field: "name", width: 20 },
|
||||
{
|
||||
@@ -32,6 +32,21 @@ export const permitResponseSchema: OutputSchema<PermissionResponseItem> = {
|
||||
],
|
||||
};
|
||||
|
||||
/** Transform a permission the agent answered to a response item */
|
||||
export function toPermissionResponseItem(
|
||||
agentId: string,
|
||||
permission: AgentPermissionRequest,
|
||||
result: "allowed" | "denied",
|
||||
): PermissionResponseItem {
|
||||
return {
|
||||
requestId: permission.id,
|
||||
agentId,
|
||||
agentShortId: agentId.slice(0, 7),
|
||||
name: permission.name,
|
||||
result,
|
||||
};
|
||||
}
|
||||
|
||||
export type PermitAllowResult = ListResult<PermissionResponseItem>;
|
||||
|
||||
export interface PermitAllowOptions extends CommandOptions {
|
||||
@@ -118,13 +133,7 @@ export async function runAllowCommand(
|
||||
behavior: "allow",
|
||||
...(updatedInput ? { updatedInput } : {}),
|
||||
});
|
||||
return {
|
||||
requestId: permission.id.slice(0, 8),
|
||||
agentId: resolvedAgentId,
|
||||
agentShortId: resolvedAgentId.slice(0, 7),
|
||||
name: permission.name,
|
||||
result: "allowed",
|
||||
};
|
||||
return toPermissionResponseItem(resolvedAgentId, permission, "allowed");
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@ import type { Command } from "commander";
|
||||
import type { AgentPermissionRequest } from "@getpaseo/protocol/agent-types";
|
||||
import { connectToDaemon } from "../../utils/client.js";
|
||||
import type { CommandOptions, ListResult, CommandError } from "../../output/index.js";
|
||||
import { permitResponseSchema, type PermissionResponseItem } from "./allow.js";
|
||||
import {
|
||||
permitResponseSchema,
|
||||
toPermissionResponseItem,
|
||||
type PermissionResponseItem,
|
||||
} from "./allow.js";
|
||||
|
||||
export type PermitDenyResult = ListResult<PermissionResponseItem>;
|
||||
|
||||
@@ -83,13 +87,7 @@ export async function runDenyCommand(
|
||||
...(options.message ? { message: options.message } : {}),
|
||||
...(options.interrupt ? { interrupt: true } : {}),
|
||||
});
|
||||
return {
|
||||
requestId: permission.id.slice(0, 8),
|
||||
agentId: resolvedAgentId,
|
||||
agentShortId: resolvedAgentId.slice(0, 7),
|
||||
name: permission.name,
|
||||
result: "denied",
|
||||
};
|
||||
return toPermissionResponseItem(resolvedAgentId, permission, "denied");
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export const permitLsSchema: OutputSchema<PermissionListItem> = {
|
||||
idField: "id",
|
||||
columns: [
|
||||
{ header: "AGENT", field: "agentShortId", width: 12 },
|
||||
{ header: "REQ_ID", field: "id", width: 12 },
|
||||
{ header: "REQ_ID", field: (item) => item.id.slice(0, 8), width: 12 },
|
||||
{ header: "TOOL", field: "name", width: 20 },
|
||||
{ header: "DESCRIPTION", field: "description", width: 50 },
|
||||
],
|
||||
@@ -30,7 +30,7 @@ function toListItem(
|
||||
permission: AgentPermissionRequest,
|
||||
): PermissionListItem {
|
||||
return {
|
||||
id: permission.id.slice(0, 8),
|
||||
id: permission.id,
|
||||
agentId: agent.id,
|
||||
agentShortId: agent.id.slice(0, 7),
|
||||
name: permission.name,
|
||||
@@ -40,6 +40,22 @@ function toListItem(
|
||||
|
||||
export type PermitLsResult = ListResult<PermissionListItem>;
|
||||
|
||||
/** Collect the pending permissions of every agent */
|
||||
export function listPendingPermissions(agents: AgentSnapshotPayload[]): PermitLsResult {
|
||||
const items: PermissionListItem[] = [];
|
||||
for (const agent of agents) {
|
||||
for (const permission of agent.pendingPermissions ?? []) {
|
||||
items.push(toListItem(agent, permission));
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: "list",
|
||||
data: items,
|
||||
schema: permitLsSchema,
|
||||
};
|
||||
}
|
||||
|
||||
export interface PermitLsOptions extends CommandOptions {
|
||||
host?: string;
|
||||
}
|
||||
@@ -55,21 +71,7 @@ export async function runLsCommand(
|
||||
const agents = agentsPayload.entries.map((entry) => entry.agent);
|
||||
await client.close();
|
||||
|
||||
// Collect all pending permissions from all agents
|
||||
const items: PermissionListItem[] = [];
|
||||
for (const agent of agents) {
|
||||
if (agent.pendingPermissions && agent.pendingPermissions.length > 0) {
|
||||
for (const permission of agent.pendingPermissions) {
|
||||
items.push(toListItem(agent, permission));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: "list",
|
||||
data: items,
|
||||
schema: permitLsSchema,
|
||||
};
|
||||
return listPendingPermissions(agents);
|
||||
} catch (err) {
|
||||
await client.close().catch(() => {});
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import type { AgentPermissionRequest } from "@getpaseo/protocol/agent-types";
|
||||
import type { AgentSnapshotPayload } from "@getpaseo/protocol/messages";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { render } from "../../output/index.js";
|
||||
import { permitResponseSchema, toPermissionResponseItem } from "./allow.js";
|
||||
import { listPendingPermissions } from "./ls.js";
|
||||
|
||||
const agentId = "2d85f428-fdaf-4d98-906f-c583de2b805f";
|
||||
|
||||
function permissionRequest(id: string): AgentPermissionRequest {
|
||||
return { id, provider: "claude", name: "Write", kind: "tool" };
|
||||
}
|
||||
|
||||
const writeRequest = permissionRequest("permission-cc93510e-a45d-4c4e-a0bf-fc2821f82783");
|
||||
const editRequest = permissionRequest("permission-654ff862-b312-4f6e-8aac-427421ff65eb");
|
||||
|
||||
const agent = {
|
||||
id: agentId,
|
||||
pendingPermissions: [writeRequest, editRequest],
|
||||
} as AgentSnapshotPayload;
|
||||
|
||||
describe("permit ls output", () => {
|
||||
it("emits full request ids that permit allow accepts", () => {
|
||||
const result = listPendingPermissions([agent]);
|
||||
|
||||
const listed = JSON.parse(render(result, { format: "json" })) as Array<{ id: string }>;
|
||||
expect(listed.map((item) => item.id)).toEqual([writeRequest.id, editRequest.id]);
|
||||
expect(render(result, { quiet: true }).split("\n")).toEqual([writeRequest.id, editRequest.id]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("permit allow and deny output", () => {
|
||||
it("emits the full id of the request that was answered", () => {
|
||||
const result = {
|
||||
type: "list" as const,
|
||||
data: [toPermissionResponseItem(agentId, writeRequest, "allowed")],
|
||||
schema: permitResponseSchema,
|
||||
};
|
||||
|
||||
const answered = JSON.parse(render(result, { format: "json" })) as Array<{
|
||||
requestId: string;
|
||||
}>;
|
||||
expect(answered.map((item) => item.requestId)).toEqual([writeRequest.id]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user