mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
feat: add configurable paseo home and port
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -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-*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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=",
|
||||
},
|
||||
|
||||
37
packages/server/src/server/config.ts
Normal file
37
packages/server/src/server/config.ts
Normal 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;
|
||||
}
|
||||
@@ -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] =
|
||||
|
||||
@@ -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);
|
||||
Reference in New Issue
Block a user