Switch to double quotes and reformat codebase with Biome

This commit is contained in:
Mohamed Boudra
2026-03-21 20:22:15 +07:00
parent ab40786882
commit f6579dbeb4
805 changed files with 38132 additions and 40175 deletions
+139 -126
View File
@@ -21,106 +21,111 @@
* - Clean up resources after test completes
*/
import assert from 'node:assert'
import { createE2ETestContext, type TestDaemonContext } from '../helpers/test-daemon.ts'
import assert from "node:assert";
import { createE2ETestContext, type TestDaemonContext } from "../helpers/test-daemon.ts";
interface E2EContext extends TestDaemonContext {
paseo: (args: string[], opts?: { timeout?: number; cwd?: string }) => Promise<{
exitCode: number
stdout: string
stderr: string
}>
paseo: (
args: string[],
opts?: { timeout?: number; cwd?: string },
) => Promise<{
exitCode: number;
stdout: string;
stderr: string;
}>;
}
let ctx: E2EContext
let ctx: E2EContext;
async function setup(): Promise<void> {
console.log('Setting up E2E test context...')
console.log('Starting test daemon on random port (this may take a few seconds)...')
console.log("Setting up E2E test context...");
console.log("Starting test daemon on random port (this may take a few seconds)...");
try {
ctx = await createE2ETestContext({ timeout: 45000 })
console.log(`Test daemon started on port ${ctx.port}`)
console.log(`PASEO_HOME: ${ctx.paseoHome}`)
console.log(`Work directory: ${ctx.workDir}`)
ctx = await createE2ETestContext({ timeout: 45000 });
console.log(`Test daemon started on port ${ctx.port}`);
console.log(`PASEO_HOME: ${ctx.paseoHome}`);
console.log(`Work directory: ${ctx.workDir}`);
} catch (err) {
console.error('Failed to start test daemon:', err)
throw err
console.error("Failed to start test daemon:", err);
throw err;
}
}
async function cleanup(): Promise<void> {
console.log('\nCleaning up...')
console.log("\nCleaning up...");
if (ctx) {
await ctx.stop()
console.log('Test daemon stopped and temp directories removed')
await ctx.stop();
console.log("Test daemon stopped and temp directories removed");
}
}
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms))
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function test_create_agent_with_permissions(): Promise<string> {
console.log('\n--- Test: Create agent in default mode (will request permissions) ---')
console.log("\n--- Test: Create agent in default mode (will request permissions) ---");
// Create agent WITHOUT bypassPermissions - it will need to request permissions
// Use a task that is very likely to trigger a tool use (and thus permission request)
const result = await ctx.paseo(
[
'-q',
'agent',
'run',
'-d',
'--provider',
'claude',
'--model',
'claude-3-5-haiku-20241022',
'--name',
'Permission Test Agent',
"-q",
"agent",
"run",
"-d",
"--provider",
"claude",
"--model",
"claude-3-5-haiku-20241022",
"--name",
"Permission Test Agent",
// This prompt should trigger file read or bash command, requiring permission
'List the files in the current directory using ls',
"List the files in the current directory using ls",
],
{ timeout: 60000 }
)
{ timeout: 60000 },
);
console.log('Exit code:', result.exitCode)
console.log('Stdout:', result.stdout)
if (result.stderr) console.log('Stderr:', result.stderr)
console.log("Exit code:", result.exitCode);
console.log("Stdout:", result.stdout);
if (result.stderr) console.log("Stderr:", result.stderr);
assert.strictEqual(result.exitCode, 0, 'agent run should succeed')
assert.strictEqual(result.exitCode, 0, "agent run should succeed");
const agentId = result.stdout.trim()
assert(agentId.length > 0, 'Should return agent ID')
assert(agentId.match(/^[a-z0-9-]+$/), `Agent ID should be alphanumeric: ${agentId}`)
const agentId = result.stdout.trim();
assert(agentId.length > 0, "Should return agent ID");
assert(agentId.match(/^[a-z0-9-]+$/), `Agent ID should be alphanumeric: ${agentId}`);
console.log(`PASS: agent created with ID: ${agentId}`)
return agentId
console.log(`PASS: agent created with ID: ${agentId}`);
return agentId;
}
async function test_wait_for_permission_request(agentId: string): Promise<void> {
console.log('\n--- Test: Wait for agent to request permission ---')
console.log("\n--- Test: Wait for agent to request permission ---");
// Poll for permission requests with timeout
const maxWait = 60000 // 60 seconds max
const pollInterval = 1000 // 1 second
const startTime = Date.now()
const maxWait = 60000; // 60 seconds max
const pollInterval = 1000; // 1 second
const startTime = Date.now();
while (Date.now() - startTime < maxWait) {
const result = await ctx.paseo(['permit', 'ls', '--json'])
const result = await ctx.paseo(["permit", "ls", "--json"]);
if (result.exitCode === 0) {
try {
const permissions = JSON.parse(result.stdout.trim())
const permissions = JSON.parse(result.stdout.trim());
if (Array.isArray(permissions) && permissions.length > 0) {
// Check if any permission is for our agent
const ourPermission = permissions.find(
(p: { agentId?: string }) => p.agentId?.startsWith(agentId.slice(0, 7)) || agentId.startsWith(p.agentId?.slice(0, 7) || '')
)
(p: { agentId?: string }) =>
p.agentId?.startsWith(agentId.slice(0, 7)) ||
agentId.startsWith(p.agentId?.slice(0, 7) || ""),
);
if (ourPermission) {
console.log('Permission request detected:', ourPermission)
console.log('PASS: Agent requested permission')
return
console.log("Permission request detected:", ourPermission);
console.log("PASS: Agent requested permission");
return;
}
}
} catch {
@@ -128,158 +133,166 @@ async function test_wait_for_permission_request(agentId: string): Promise<void>
}
}
await sleep(pollInterval)
await sleep(pollInterval);
}
// If we get here, check agent status - it might have already completed
const statusResult = await ctx.paseo(['inspect', agentId])
console.log('Agent status:', statusResult.stdout)
const statusResult = await ctx.paseo(["inspect", agentId]);
console.log("Agent status:", statusResult.stdout);
// It's possible the agent completed without needing permissions (e.g., haiku might not use tools)
// In that case, we should skip the permission tests
if (statusResult.stdout.includes('idle') || statusResult.stdout.includes('completed')) {
console.log('SKIP: Agent completed without requiring permissions (model chose not to use tools)')
throw new Error('SKIP_PERMISSION_TEST')
if (statusResult.stdout.includes("idle") || statusResult.stdout.includes("completed")) {
console.log(
"SKIP: Agent completed without requiring permissions (model chose not to use tools)",
);
throw new Error("SKIP_PERMISSION_TEST");
}
throw new Error('Timeout waiting for agent to request permission')
throw new Error("Timeout waiting for agent to request permission");
}
async function test_permit_ls(): Promise<{ agentShortId: string; requestId: string }> {
console.log('\n--- Test: List pending permissions with permit ls ---')
console.log("\n--- Test: List pending permissions with permit ls ---");
const result = await ctx.paseo(['permit', 'ls', '--json'])
const result = await ctx.paseo(["permit", "ls", "--json"]);
console.log('Exit code:', result.exitCode)
console.log('Stdout:', result.stdout)
if (result.stderr) console.log('Stderr:', result.stderr)
console.log("Exit code:", result.exitCode);
console.log("Stdout:", result.stdout);
if (result.stderr) console.log("Stderr:", result.stderr);
assert.strictEqual(result.exitCode, 0, 'permit ls should succeed')
assert.strictEqual(result.exitCode, 0, "permit ls should succeed");
const permissions = JSON.parse(result.stdout.trim())
assert(Array.isArray(permissions), 'Output should be JSON array')
assert(permissions.length > 0, 'Should have at least one pending permission')
const permissions = JSON.parse(result.stdout.trim());
assert(Array.isArray(permissions), "Output should be JSON array");
assert(permissions.length > 0, "Should have at least one pending permission");
const permission = permissions[0]
assert(permission.id, 'Permission should have id')
assert(permission.agentShortId, 'Permission should have agentShortId')
assert(permission.name, 'Permission should have tool name')
const permission = permissions[0];
assert(permission.id, "Permission should have id");
assert(permission.agentShortId, "Permission should have agentShortId");
assert(permission.name, "Permission should have tool name");
console.log(`PASS: Found ${permissions.length} pending permission(s)`)
console.log(` Request ID: ${permission.id}`)
console.log(` Agent: ${permission.agentShortId}`)
console.log(` Tool: ${permission.name}`)
console.log(`PASS: Found ${permissions.length} pending permission(s)`);
console.log(` Request ID: ${permission.id}`);
console.log(` Agent: ${permission.agentShortId}`);
console.log(` Tool: ${permission.name}`);
return {
agentShortId: permission.agentShortId,
requestId: permission.id,
}
};
}
async function test_permit_allow(agentShortId: string, requestId: string): Promise<void> {
console.log('\n--- Test: Allow permission with permit allow ---')
console.log("\n--- Test: Allow permission with permit allow ---");
const result = await ctx.paseo(['permit', 'allow', agentShortId, requestId])
const result = await ctx.paseo(["permit", "allow", agentShortId, requestId]);
console.log('Exit code:', result.exitCode)
console.log('Stdout:', result.stdout)
if (result.stderr) console.log('Stderr:', result.stderr)
console.log("Exit code:", result.exitCode);
console.log("Stdout:", result.stdout);
if (result.stderr) console.log("Stderr:", result.stderr);
assert.strictEqual(result.exitCode, 0, 'permit allow should succeed')
assert.strictEqual(result.exitCode, 0, "permit allow should succeed");
// Check that output shows the permission was allowed
const output = result.stdout.toLowerCase()
assert(output.includes('allowed') || output.includes(requestId.slice(0, 8).toLowerCase()), 'Should confirm permission was allowed')
const output = result.stdout.toLowerCase();
assert(
output.includes("allowed") || output.includes(requestId.slice(0, 8).toLowerCase()),
"Should confirm permission was allowed",
);
console.log('PASS: Permission allowed successfully')
console.log("PASS: Permission allowed successfully");
}
async function test_agent_continues(agentId: string): Promise<void> {
console.log('\n--- Test: Verify agent continues after permission granted ---')
console.log("\n--- Test: Verify agent continues after permission granted ---");
// Wait for agent to become idle (should continue after permission)
const result = await ctx.paseo(['wait', '--timeout', '120s', agentId], { timeout: 130000 })
const result = await ctx.paseo(["wait", "--timeout", "120s", agentId], { timeout: 130000 });
console.log('Exit code:', result.exitCode)
console.log('Stdout:', result.stdout)
if (result.stderr) console.log('Stderr:', result.stderr)
console.log("Exit code:", result.exitCode);
console.log("Stdout:", result.stdout);
if (result.stderr) console.log("Stderr:", result.stderr);
assert.strictEqual(result.exitCode, 0, 'agent wait should succeed after permission granted')
assert.strictEqual(result.exitCode, 0, "agent wait should succeed after permission granted");
// Verify agent status
const inspectResult = await ctx.paseo(['inspect', agentId])
console.log('Final agent status:', inspectResult.stdout)
const inspectResult = await ctx.paseo(["inspect", agentId]);
console.log("Final agent status:", inspectResult.stdout);
assert(inspectResult.stdout.includes('idle') || inspectResult.stdout.includes('completed'), 'Agent should be idle after completing')
assert(
inspectResult.stdout.includes("idle") || inspectResult.stdout.includes("completed"),
"Agent should be idle after completing",
);
console.log('PASS: Agent completed after permission was granted')
console.log("PASS: Agent completed after permission was granted");
}
async function test_agent_delete(agentId: string): Promise<void> {
console.log('\n--- Test: Delete agent ---')
console.log("\n--- Test: Delete agent ---");
const result = await ctx.paseo(['delete', agentId])
const result = await ctx.paseo(["delete", agentId]);
console.log('Exit code:', result.exitCode)
console.log('Stdout:', result.stdout)
if (result.stderr) console.log('Stderr:', result.stderr)
console.log("Exit code:", result.exitCode);
console.log("Stdout:", result.stdout);
if (result.stderr) console.log("Stderr:", result.stderr);
assert.strictEqual(result.exitCode, 0, 'agent delete should succeed')
assert.strictEqual(result.exitCode, 0, "agent delete should succeed");
console.log('PASS: Agent deleted successfully')
console.log("PASS: Agent deleted successfully");
}
async function main(): Promise<void> {
console.log('=== E2E Test: Permissions Workflow ===\n')
console.log('This test verifies the permission request/allow workflow.')
console.log('It creates an agent that will request tool permissions.\n')
console.log("=== E2E Test: Permissions Workflow ===\n");
console.log("This test verifies the permission request/allow workflow.");
console.log("It creates an agent that will request tool permissions.\n");
let agentId: string | undefined
let agentId: string | undefined;
try {
await setup()
await setup();
// Create agent that will need permissions
agentId = await test_create_agent_with_permissions()
agentId = await test_create_agent_with_permissions();
try {
// Wait for permission request
await test_wait_for_permission_request(agentId)
await test_wait_for_permission_request(agentId);
// List and verify permissions
const { agentShortId, requestId } = await test_permit_ls()
const { agentShortId, requestId } = await test_permit_ls();
// Allow the permission
await test_permit_allow(agentShortId, requestId)
await test_permit_allow(agentShortId, requestId);
// Verify agent continues and completes
await test_agent_continues(agentId)
await test_agent_continues(agentId);
console.log('\n=== All permissions E2E tests passed! ===')
console.log("\n=== All permissions E2E tests passed! ===");
} catch (err) {
if (err instanceof Error && err.message === 'SKIP_PERMISSION_TEST') {
console.log('\n=== Permissions test skipped (agent completed without tool use) ===')
console.log('This can happen when the model chooses not to use tools.')
if (err instanceof Error && err.message === "SKIP_PERMISSION_TEST") {
console.log("\n=== Permissions test skipped (agent completed without tool use) ===");
console.log("This can happen when the model chooses not to use tools.");
// Still considered a pass - the CLI works, just the model behavior varies
} else {
throw err
throw err;
}
}
} catch (err) {
console.error('\n=== E2E test FAILED ===')
console.error(err)
process.exitCode = 1
console.error("\n=== E2E test FAILED ===");
console.error(err);
process.exitCode = 1;
} finally {
// Always try to delete the agent if it was created
if (agentId) {
try {
await test_agent_delete(agentId)
await test_agent_delete(agentId);
} catch {
// Ignore errors during cleanup
}
}
await cleanup()
await cleanup();
}
}
main()
main();