-
Notifications
You must be signed in to change notification settings - Fork 42
/
Copy pathpromptLoader.ts
128 lines (108 loc) · 3.61 KB
/
promptLoader.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { PromptProtocol } from "../prompts/BasePrompt.js";
import { join, dirname } from "path";
import { promises as fs } from "fs";
import { logger } from "./Logger.js";
export class PromptLoader {
private readonly PROMPTS_DIR: string;
private readonly EXCLUDED_FILES = ["BasePrompt.js", "*.test.js", "*.spec.js"];
constructor(basePath?: string) {
const mainModulePath = basePath || process.argv[1];
this.PROMPTS_DIR = join(dirname(mainModulePath), "prompts");
logger.debug(
`Initialized PromptLoader with directory: ${this.PROMPTS_DIR}`
);
}
async hasPrompts(): Promise<boolean> {
try {
const stats = await fs.stat(this.PROMPTS_DIR);
if (!stats.isDirectory()) {
logger.debug("Prompts path exists but is not a directory");
return false;
}
const files = await fs.readdir(this.PROMPTS_DIR);
const hasValidFiles = files.some((file) => this.isPromptFile(file));
logger.debug(`Prompts directory has valid files: ${hasValidFiles}`);
return hasValidFiles;
} catch (error) {
logger.debug("No prompts directory found");
return false;
}
}
private isPromptFile(file: string): boolean {
if (!file.endsWith(".js")) return false;
const isExcluded = this.EXCLUDED_FILES.some((pattern) => {
if (pattern.includes("*")) {
const regex = new RegExp(pattern.replace("*", ".*"));
return regex.test(file);
}
return file === pattern;
});
logger.debug(
`Checking file ${file}: ${isExcluded ? "excluded" : "included"}`
);
return !isExcluded;
}
private validatePrompt(prompt: any): prompt is PromptProtocol {
const isValid = Boolean(
prompt &&
typeof prompt.name === "string" &&
prompt.promptDefinition &&
typeof prompt.getMessages === "function"
);
if (isValid) {
logger.debug(`Validated prompt: ${prompt.name}`);
} else {
logger.warn(`Invalid prompt found: missing required properties`);
}
return isValid;
}
async loadPrompts(): Promise<PromptProtocol[]> {
try {
logger.debug(`Attempting to load prompts from: ${this.PROMPTS_DIR}`);
let stats;
try {
stats = await fs.stat(this.PROMPTS_DIR);
} catch (error) {
logger.debug("No prompts directory found");
return [];
}
if (!stats.isDirectory()) {
logger.error(`Path is not a directory: ${this.PROMPTS_DIR}`);
return [];
}
const files = await fs.readdir(this.PROMPTS_DIR);
logger.debug(`Found files in directory: ${files.join(", ")}`);
const prompts: PromptProtocol[] = [];
for (const file of files) {
if (!this.isPromptFile(file)) {
continue;
}
try {
const fullPath = join(this.PROMPTS_DIR, file);
logger.debug(`Attempting to load prompt from: ${fullPath}`);
const importPath = `file://${fullPath}`;
const { default: PromptClass } = await import(importPath);
if (!PromptClass) {
logger.warn(`No default export found in ${file}`);
continue;
}
const prompt = new PromptClass();
if (this.validatePrompt(prompt)) {
prompts.push(prompt);
}
} catch (error) {
logger.error(`Error loading prompt ${file}: ${error}`);
}
}
logger.debug(
`Successfully loaded ${prompts.length} prompts: ${prompts
.map((p) => p.name)
.join(", ")}`
);
return prompts;
} catch (error) {
logger.error(`Failed to load prompts: ${error}`);
return [];
}
}
}