Something went wrong. Try again.
fork of prime agent with changes i want but are not upstreamable probqbly (and some fixes)
Something went wrong. Try again.
3.3 kB · 126 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127/** * Agent discovery and configuration */
import * as fs from "node:fs";import * as path from "node:path";import { getAgentDir, parseFrontmatter } from "@earendil-works/pi-coding-agent";
export type AgentScope = "user" | "project" | "both";
export interface AgentConfig { name: string; description: string; tools?: string[]; model?: string; systemPrompt: string; source: "user" | "project"; filePath: string;}
export interface AgentDiscoveryResult { agents: AgentConfig[]; projectAgentsDir: string | null;}
function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig[] { const agents: AgentConfig[] = [];
if (!fs.existsSync(dir)) { return agents; }
let entries: fs.Dirent[]; try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return agents; }
for (const entry of entries) { if (!entry.name.endsWith(".md")) continue; if (!entry.isFile() && !entry.isSymbolicLink()) continue;
const filePath = path.join(dir, entry.name); let content: string; try { content = fs.readFileSync(filePath, "utf-8"); } catch { continue; }
const { frontmatter, body } = parseFrontmatter<Record<string, string>>(content);
if (!frontmatter.name || !frontmatter.description) { continue; }
const tools = frontmatter.tools ?.split(",") .map((t: string) => t.trim()) .filter(Boolean);
agents.push({ name: frontmatter.name, description: frontmatter.description, tools: tools && tools.length > 0 ? tools : undefined, model: frontmatter.model, systemPrompt: body, source, filePath, }); }
return agents;}
function isDirectory(p: string): boolean { try { return fs.statSync(p).isDirectory(); } catch { return false; }}
function findNearestProjectAgentsDir(cwd: string): string | null { let currentDir = cwd; while (true) { const candidate = path.join(currentDir, ".prime", "agent", "agents"); if (isDirectory(candidate)) return candidate;
const parentDir = path.dirname(currentDir); if (parentDir === currentDir) return null; currentDir = parentDir; }}
export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult { const userDir = path.join(getAgentDir(), "agents"); const projectAgentsDir = findNearestProjectAgentsDir(cwd);
const userAgents = scope === "project" ? [] : loadAgentsFromDir(userDir, "user"); const projectAgents = scope === "user" || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, "project");
const agentMap = new Map<string, AgentConfig>();
if (scope === "both") { for (const agent of userAgents) agentMap.set(agent.name, agent); for (const agent of projectAgents) agentMap.set(agent.name, agent); } else if (scope === "user") { for (const agent of userAgents) agentMap.set(agent.name, agent); } else { for (const agent of projectAgents) agentMap.set(agent.name, agent); }
return { agents: Array.from(agentMap.values()), projectAgentsDir };}
export function formatAgentList(agents: AgentConfig[], maxItems: number): { text: string; remaining: number } { if (agents.length === 0) return { text: "none", remaining: 0 }; const listed = agents.slice(0, maxItems); const remaining = agents.length - listed.length; return { text: listed.map((a) => `${a.name} (${a.source}): ${a.description}`).join("; "), remaining, };}