@iqai/adk-cli
Version:
CLI tool for creating, running, and testing ADK-TS agents
159 lines • 7.55 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AgentScanner = exports.DIRECTORIES_TO_SKIP = void 0;
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const common_1 = require("@nestjs/common");
const find_project_root_1 = require("../../common/find-project-root");
exports.DIRECTORIES_TO_SKIP = [
"node_modules",
".adk-cache",
".git",
".next",
"dist",
"build",
".turbo",
"coverage",
".vscode",
".idea",
];
const AGENT_FILENAMES = ["agent.ts", "agent.js"];
let AgentScanner = class AgentScanner {
quiet;
logger;
constructor(quiet = false) {
this.quiet = quiet;
this.logger = new common_1.Logger("agent-scanner");
}
/**
* Find the project root by traversing up from the given directory
* looking for package.json, tsconfig.json, or .env files
*/
findProjectRoot(startDir) {
return (0, find_project_root_1.findProjectRoot)(startDir);
}
scanAgents(agentsDir, loadedAgents) {
const agents = new Map();
// Use current directory if agentsDir doesn't exist or is empty
const scanDir = !agentsDir || !(0, node_fs_1.existsSync)(agentsDir)
? process.cwd()
: (0, node_path_1.normalize)((0, node_path_1.resolve)(agentsDir));
// Find the actual project root (where tsconfig.json, package.json live)
const projectRoot = this.findProjectRoot(scanDir);
if (!this.quiet) {
this.logger.log(`Scan directory: ${scanDir}`);
this.logger.log(`Project root: ${projectRoot}`);
}
const shouldSkipDirectory = (dirName) => {
return exports.DIRECTORIES_TO_SKIP.includes(dirName);
};
const scanDirectory = (dir) => {
try {
const items = (0, node_fs_1.readdirSync)(dir);
for (const item of items) {
const fullPath = (0, node_path_1.normalize)((0, node_path_1.join)(dir, item));
const stat = (0, node_fs_1.statSync)(fullPath);
if (stat.isDirectory()) {
// Skip common build/dependency directories
if (!shouldSkipDirectory(item)) {
scanDirectory(fullPath);
}
}
else if (AGENT_FILENAMES.includes(item)) {
// Calculate relative path from PROJECT ROOT to agent directory
// Normalize to use forward slashes for consistency across platforms
let relativePath = (0, node_path_1.relative)(projectRoot, dir).replace(/\\/g, "/");
// Handle case where agent is directly in the project root
if (!relativePath || relativePath === ".") {
const rootDirName = projectRoot.split(/[\\/]/).pop() || "root";
relativePath = rootDirName;
}
// Remove any leading "./" from the path
relativePath = relativePath.replace(/^\.\//, "");
// Try to get the actual agent name if it's already loaded
const loadedAgent = loadedAgents.get(relativePath);
let agentName = relativePath.split(/[/\\]/).pop() || "unknown";
if (loadedAgent?.agent?.name) {
agentName = loadedAgent.agent.name;
}
else {
// Try to quickly extract name from agent file if not loaded
try {
const agentFilePath = (0, node_path_1.normalize)((0, node_path_1.join)(dir, item));
agentName =
this.extractAgentNameFromFile(agentFilePath) || agentName;
}
catch (error) {
if (!this.quiet) {
this.logger.warn(`Failed to extract agent name from ${(0, node_path_1.join)(dir, item)}: ${error instanceof Error ? error.message : String(error)}`);
}
}
}
// Store the agent with consistent keys
if (relativePath) {
agents.set(relativePath, {
relativePath,
name: agentName,
absolutePath: (0, node_path_1.normalize)((0, node_path_1.resolve)(dir)),
projectRoot,
instance: loadedAgent?.agent,
});
if (!this.quiet) {
this.logger.log(`Found agent: ${relativePath} -> ${dir}`);
}
}
else {
this.logger.warn(`Skipping agent with invalid relativePath at ${dir}`);
}
}
}
}
catch (error) {
this.logger.warn(`Error reading directory ${dir}: ${error instanceof Error ? error.message : String(error)}`);
}
};
if (!this.quiet) {
this.logger.log("Starting agent scan...");
}
scanDirectory(scanDir);
this.logger.log(`Agent scan complete. Found ${agents.size} agents.`);
if (!this.quiet && agents.size > 0) {
this.logger.log("Found agents:");
for (const [key, agent] of agents.entries()) {
this.logger.log(` ${key} -> ${agent.absolutePath}`);
}
}
return agents;
}
extractAgentNameFromFile(filePath) {
try {
const content = (0, node_fs_1.readFileSync)(filePath, "utf-8");
// Look for agent name in export statements
// Match patterns like: name: "agent_name" or name:"agent_name"
const nameMatch = content.match(/name\s*:\s*["']([^"']+)["']/);
if (nameMatch?.[1]) {
return nameMatch[1];
}
return null;
}
catch (_error) {
// Return null instead of throwing to allow fallback to directory name
return null;
}
}
};
exports.AgentScanner = AgentScanner;
exports.AgentScanner = AgentScanner = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [Object])
], AgentScanner);
//# sourceMappingURL=agent-scanner.service.js.map