feat: add configurable paseo home and port

This commit is contained in:
Mohamed Boudra
2025-11-30 02:46:44 +00:00
parent cc34ea722a
commit b8d942cb6b
7 changed files with 50 additions and 114 deletions

5
.gitignore vendored
View File

@@ -43,8 +43,3 @@ coverage/
# Misc
*.pem
.vercel
# Runtime agent data
packages/server/agents.json
packages/server/agents.json.temporary
packages/server/.agents.json.tmp-*

View File

@@ -8,5 +8,12 @@ TTS_MODEL=tts-1
# Available models: tts-1 (faster), tts-1-hd (higher quality)
# Server Configuration
# Location for runtime state (agents.json, etc.). Defaults to ~/.paseo
PASEO_HOME=~/.paseo
# Voice server port (overrides PORT). Defaults to 6767
PASEO_PORT=6767
# Legacy web server port used by the legacy Express app
PORT=3000
NODE_ENV=development

View File

@@ -1,11 +1,10 @@
import { randomUUID } from "node:crypto";
import { existsSync } from "node:fs";
import { promises as fs } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { z } from "zod";
import { AgentStatusSchema } from "../messages.js";
import { resolvePaseoHome } from "../config.js";
import { toStoredAgentRecord } from "./agent-projections.js";
import type { ManagedAgent } from "./agent-manager.js";
import type { AgentSessionConfig } from "./agent-sdk-types.js";
@@ -57,8 +56,7 @@ export class AgentRegistry {
private filePath: string;
constructor(filePath?: string) {
this.filePath =
filePath ?? path.join(resolveServerPackageRoot(), "agents.json");
this.filePath = filePath ?? path.join(resolvePaseoHome(), "agents.json");
}
async load(): Promise<StoredAgentRecord[]> {
@@ -188,22 +186,6 @@ export class AgentRegistry {
}
}
function resolveServerPackageRoot(): string {
let currentDir = path.dirname(fileURLToPath(import.meta.url));
while (true) {
if (existsSync(path.join(currentDir, "package.json"))) {
return currentDir;
}
const parentDir = path.dirname(currentDir);
if (parentDir === currentDir) {
throw new Error(
"[AgentRegistry] Failed to locate server package root for agents.json"
);
}
currentDir = parentDir;
}
}
async function writeFileAtomically(targetPath: string, payload: string) {
const directory = path.dirname(targetPath);
const tempPath = path.join(

View File

@@ -38,6 +38,7 @@ import type {
ListPersistedAgentsOptions,
PersistedAgentDescriptor,
} from "../agent-sdk-types.js";
import { resolvePaseoPort } from "../../config.js";
const CLAUDE_CAPABILITIES: AgentCapabilityFlags = {
supportsStreaming: true,
@@ -92,7 +93,7 @@ type ClaudeAgentSessionOptions = {
};
const DEFAULT_AGENT_CONTROL_MCP: AgentControlMcpConfig = {
url: "http://127.0.0.1:6767/mcp/agents",
url: `http://127.0.0.1:${resolvePaseoPort()}/mcp/agents`,
headers: {
Authorization: "Basic bW86Ym8=",
},

View File

@@ -0,0 +1,37 @@
import os from "node:os";
import path from "node:path";
import { mkdirSync } from "node:fs";
let cachedHomeDir: string | null = null;
let cachedPort: number | null = null;
function expandHomeDir(input: string): string {
if (input.startsWith("~/")) {
return path.join(os.homedir(), input.slice(2));
}
if (input === "~") {
return os.homedir();
}
return input;
}
export function resolvePaseoHome(): string {
if (cachedHomeDir) {
return cachedHomeDir;
}
const raw = process.env.PASEO_HOME ?? process.env.PASEO_HOME_DIR ?? "~/.paseo";
const expanded = path.resolve(expandHomeDir(raw));
mkdirSync(expanded, { recursive: true });
cachedHomeDir = expanded;
return cachedHomeDir;
}
export function resolvePaseoPort(): number {
if (cachedPort !== null) {
return cachedPort;
}
const raw = process.env.PASEO_PORT ?? process.env.PORT ?? "6767";
const parsed = Number.parseInt(raw, 10);
cachedPort = Number.isFinite(parsed) ? parsed : 6767;
return cachedPort;
}

View File

@@ -11,6 +11,7 @@ import { AgentManager } from "./agent/agent-manager.js";
import { AgentRegistry } from "./agent/agent-registry.js";
import { ClaudeAgentClient } from "./agent/providers/claude-agent.js";
import { CodexAgentClient } from "./agent/providers/codex-agent.js";
import { resolvePaseoPort } from "./config.js";
import { initializeTitleGenerator } from "../services/agent-title-generator.js";
import { attachAgentRegistryPersistence } from "./persistence-hooks.js";
import { createAgentMcpServer } from "./agent/mcp-server.js";
@@ -73,7 +74,7 @@ function createServer() {
}
async function main() {
const port = parseInt(process.env.PORT || "6767", 10);
const port = resolvePaseoPort();
const agentMcpRoute = "/mcp/agents";
const agentMcpUrl = `http://127.0.0.1:${port}${agentMcpRoute}`;
const [agentMcpUser, agentMcpPassword] =

View File

@@ -1,87 +0,0 @@
#!/usr/bin/env node
const CLAUDE_AGENT_ID = 'f7644b18-7fb9-4491-80f3-788d0d27a119';
const CODEX_AGENT_ID = 'd7c360ea-1579-4091-b224-ee8442400823';
const url = 'http://127.0.0.1:6767/mcp/agents';
const auth = Buffer.from('mo:bo').toString('base64');
async function makeRequest(method, params) {
console.log(`\n[TEST] Calling ${method} with params:`, JSON.stringify(params, null, 2));
const startTime = Date.now();
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${auth}`
},
body: JSON.stringify({
jsonrpc: '2.0',
id: Date.now(),
method: 'tools/call',
params: {
name: method,
arguments: params
}
})
});
const elapsed = Date.now() - startTime;
console.log(`[TEST] Response received in ${elapsed}ms`);
const data = await response.json();
console.log(`[TEST] Response:`, JSON.stringify(data, null, 2));
return data;
} catch (error) {
const elapsed = Date.now() - startTime;
console.error(`[TEST] Request failed after ${elapsed}ms:`, error.message);
throw error;
}
}
async function initialize() {
console.log('[TEST] Initializing MCP session...');
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${auth}`
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
capabilities: {},
clientInfo: {
name: 'test-client',
version: '1.0.0'
}
}
})
});
const data = await response.json();
console.log('[TEST] Initialized:', JSON.stringify(data, null, 2));
}
async function main() {
console.log('=== Testing MCP Agent Control Tools ===\n');
// Initialize session
await initialize();
// Test 1: Get status of Codex agent (should work)
console.log('\n--- Test 1: get_agent_status on Codex agent ---');
await makeRequest('get_agent_status', { agentId: CODEX_AGENT_ID });
// Test 2: Get status of Claude agent (might hang)
console.log('\n--- Test 2: get_agent_status on Claude agent ---');
await makeRequest('get_agent_status', { agentId: CLAUDE_AGENT_ID });
console.log('\n=== All tests complete ===');
}
main().catch(console.error);