@ai-setting/roy-agent-core 1.5.87 → 1.5.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/env/agent/index.js +6 -6
- package/dist/env/event-source/index.js +6 -2
- package/dist/env/index.js +17 -12
- package/dist/env/prompt/index.js +2 -1
- package/dist/env/session/index.js +1 -2
- package/dist/env/task/delegate/index.js +3 -2
- package/dist/env/task/index.js +5 -4
- package/dist/env/task/plugins/index.js +7 -4
- package/dist/env/task/tools/index.js +1 -1
- package/dist/env/tool/built-in/index.js +2 -1
- package/dist/env/tool/index.js +11 -8
- package/dist/env/workflow/engine/index.js +4 -2
- package/dist/env/workflow/index.js +5 -3
- package/dist/env/workflow/tools/index.js +7 -1
- package/dist/env/workflow/utils/index.js +5 -0
- package/dist/index.js +32 -25
- package/dist/shared/@ai-setting/{roy-agent-core-6mk0m4t3.js → roy-agent-core-2q7cshpm.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-0y64qaac.js → roy-agent-core-32m0nb9j.js} +119 -30
- package/dist/shared/@ai-setting/{roy-agent-core-9y09xfav.js → roy-agent-core-3f6k060j.js} +5 -417
- package/dist/shared/@ai-setting/roy-agent-core-4yq23m5g.js +421 -0
- package/dist/shared/@ai-setting/{roy-agent-core-mmkyydw7.js → roy-agent-core-83d035pp.js} +91 -579
- package/dist/shared/@ai-setting/roy-agent-core-8wd3qwx5.js +35 -0
- package/dist/shared/@ai-setting/{roy-agent-core-29fh9mxg.js → roy-agent-core-bwjpte58.js} +1 -2
- package/dist/shared/@ai-setting/{roy-agent-core-r1adqgaa.js → roy-agent-core-ewr1nw7t.js} +7 -8
- package/dist/shared/@ai-setting/{roy-agent-core-yx0vw1aw.js → roy-agent-core-fgpnv7dt.js} +31 -4
- package/dist/shared/@ai-setting/{roy-agent-core-jymz9fzp.js → roy-agent-core-fvfc7f6v.js} +64 -33
- package/dist/shared/@ai-setting/{roy-agent-core-9vwyj29a.js → roy-agent-core-h5867smx.js} +16 -22
- package/dist/shared/@ai-setting/roy-agent-core-hvdfgvfz.js +114 -0
- package/dist/shared/@ai-setting/{roy-agent-core-3arrpf7n.js → roy-agent-core-hxsbegfc.js} +229 -9
- package/dist/shared/@ai-setting/{roy-agent-core-7fdzfsm6.js → roy-agent-core-m3dkyprg.js} +35 -211
- package/dist/shared/@ai-setting/{roy-agent-core-bgw4dq11.js → roy-agent-core-mw4ty0ba.js} +44 -5
- package/dist/shared/@ai-setting/{roy-agent-core-7z4xtrmw.js → roy-agent-core-nqzt9ne4.js} +53 -0
- package/dist/shared/@ai-setting/roy-agent-core-pt7as39r.js +0 -0
- package/dist/shared/@ai-setting/{roy-agent-core-6n7xwv4v.js → roy-agent-core-qbq3jgrn.js} +5 -3
- package/dist/shared/@ai-setting/roy-agent-core-w6bmrgap.js +581 -0
- package/dist/shared/@ai-setting/{roy-agent-core-qhjb153z.js → roy-agent-core-xnxyzaw4.js} +27 -4
- package/dist/shared/@ai-setting/roy-agent-core-yanpq5gb.js +116 -0
- package/package.json +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-x3gtyqax.js +0 -378
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
import {
|
|
2
|
+
builtInPrompts
|
|
3
|
+
} from "./roy-agent-core-83d035pp.js";
|
|
4
|
+
import {
|
|
5
|
+
getXDGPath
|
|
6
|
+
} from "./roy-agent-core-qxnbvgwe.js";
|
|
7
|
+
import {
|
|
8
|
+
envKeyToConfigKey,
|
|
9
|
+
toEnvKey
|
|
10
|
+
} from "./roy-agent-core-qxhq8ven.js";
|
|
11
|
+
import {
|
|
12
|
+
BaseComponent
|
|
13
|
+
} from "./roy-agent-core-rgckng3p.js";
|
|
14
|
+
import {
|
|
15
|
+
createHook
|
|
16
|
+
} from "./roy-agent-core-b8r4tfqq.js";
|
|
17
|
+
import {
|
|
18
|
+
globalHookManager,
|
|
19
|
+
init_global_hook_manager
|
|
20
|
+
} from "./roy-agent-core-7tp56w6n.js";
|
|
21
|
+
import {
|
|
22
|
+
createLogger,
|
|
23
|
+
init_logger
|
|
24
|
+
} from "./roy-agent-core-shme7set.js";
|
|
25
|
+
|
|
26
|
+
// src/env/prompt/types.ts
|
|
27
|
+
import { z } from "zod";
|
|
28
|
+
var PromptPathSchema = z.object({
|
|
29
|
+
type: z.enum(["file", "directory"]),
|
|
30
|
+
path: z.string(),
|
|
31
|
+
name: z.string().optional(),
|
|
32
|
+
recursive: z.boolean().default(true),
|
|
33
|
+
extension: z.string().default(".md")
|
|
34
|
+
});
|
|
35
|
+
var PromptConfigSchema = z.object({
|
|
36
|
+
promptPaths: z.array(PromptPathSchema).default([]),
|
|
37
|
+
defaultName: z.string().default("default"),
|
|
38
|
+
variablePrefix: z.string().default("{{"),
|
|
39
|
+
variableSuffix: z.string().default("}}"),
|
|
40
|
+
strictMode: z.boolean().default(false)
|
|
41
|
+
});
|
|
42
|
+
var PromptHookPoints = {
|
|
43
|
+
BEFORE_RENDER: "prompt.before-render",
|
|
44
|
+
AFTER_RENDER: "prompt.after-render"
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/env/prompt/renderer.ts
|
|
48
|
+
class PromptRenderer {
|
|
49
|
+
options;
|
|
50
|
+
constructor(options) {
|
|
51
|
+
this.options = options;
|
|
52
|
+
}
|
|
53
|
+
render(template, variables) {
|
|
54
|
+
const { prefix, suffix, strict, onMissingVariable } = this.options;
|
|
55
|
+
const regex = new RegExp(`${escapeRegex(prefix)}(.*?)${escapeRegex(suffix)}`, "g");
|
|
56
|
+
return template.replace(regex, (match, varName) => {
|
|
57
|
+
const key = varName.trim();
|
|
58
|
+
if (key in variables) {
|
|
59
|
+
return variables[key];
|
|
60
|
+
}
|
|
61
|
+
if (strict) {
|
|
62
|
+
throw new Error(`Missing required variable: ${key}`);
|
|
63
|
+
}
|
|
64
|
+
if (onMissingVariable) {
|
|
65
|
+
return onMissingVariable(key);
|
|
66
|
+
}
|
|
67
|
+
return match;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
extractVariables(template) {
|
|
71
|
+
const { prefix, suffix } = this.options;
|
|
72
|
+
const regex = new RegExp(`${escapeRegex(prefix)}(.*?)${escapeRegex(suffix)}`, "g");
|
|
73
|
+
const vars = [];
|
|
74
|
+
let match;
|
|
75
|
+
while ((match = regex.exec(template)) !== null) {
|
|
76
|
+
vars.push(match[1].trim());
|
|
77
|
+
}
|
|
78
|
+
return [...new Set(vars)];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function escapeRegex(str) {
|
|
82
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/env/prompt/prompt-store.ts
|
|
86
|
+
import { mkdir, readFile, writeFile, unlink, readdir } from "fs/promises";
|
|
87
|
+
import { existsSync } from "fs";
|
|
88
|
+
import { join, dirname } from "path";
|
|
89
|
+
init_logger();
|
|
90
|
+
var logger = createLogger("prompt:store");
|
|
91
|
+
|
|
92
|
+
class PromptStore {
|
|
93
|
+
configDir;
|
|
94
|
+
constructor(options = {}) {
|
|
95
|
+
if (options.configDir && options.configDir.length > 0) {
|
|
96
|
+
this.configDir = options.configDir;
|
|
97
|
+
} else if (options.baseDir) {
|
|
98
|
+
this.configDir = join(options.baseDir, "prompts");
|
|
99
|
+
} else {
|
|
100
|
+
this.configDir = join(getXDGPath("data"), "prompts");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
getConfigDir() {
|
|
104
|
+
return this.configDir;
|
|
105
|
+
}
|
|
106
|
+
configDirExists() {
|
|
107
|
+
return existsSync(this.configDir);
|
|
108
|
+
}
|
|
109
|
+
getPromptFilePath(name) {
|
|
110
|
+
return join(this.configDir, `${name}.md`);
|
|
111
|
+
}
|
|
112
|
+
async savePrompt(name, content) {
|
|
113
|
+
await this.ensureConfigDir();
|
|
114
|
+
const filePath = this.getPromptFilePath(name);
|
|
115
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
116
|
+
await writeFile(filePath, content, "utf-8");
|
|
117
|
+
logger.info(`[PromptStore] Saved prompt: ${name} -> ${filePath}`);
|
|
118
|
+
return filePath;
|
|
119
|
+
}
|
|
120
|
+
async deletePrompt(name) {
|
|
121
|
+
const filePath = this.getPromptFilePath(name);
|
|
122
|
+
if (!existsSync(filePath)) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
await unlink(filePath);
|
|
126
|
+
logger.info(`[PromptStore] Deleted prompt file: ${filePath}`);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
async loadAll() {
|
|
130
|
+
if (!existsSync(this.configDir)) {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
const prompts = [];
|
|
134
|
+
await this.collectPrompts(this.configDir, "", prompts);
|
|
135
|
+
return prompts;
|
|
136
|
+
}
|
|
137
|
+
async collectPrompts(directory, prefix, out) {
|
|
138
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
139
|
+
for (const entry of entries) {
|
|
140
|
+
const fullPath = join(directory, entry.name);
|
|
141
|
+
if (entry.isDirectory()) {
|
|
142
|
+
const nextPrefix = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
143
|
+
await this.collectPrompts(fullPath, nextPrefix, out);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (!entry.isFile() || !entry.name.endsWith(".md")) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const baseName = entry.name.slice(0, -3);
|
|
150
|
+
const name = prefix ? `${prefix}/${baseName}` : baseName;
|
|
151
|
+
const content = (await readFile(fullPath, "utf-8")).trim();
|
|
152
|
+
out.push({ name, content, filePath: fullPath });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async ensureConfigDir() {
|
|
156
|
+
if (!existsSync(this.configDir)) {
|
|
157
|
+
await mkdir(this.configDir, { recursive: true });
|
|
158
|
+
logger.debug(`[PromptStore] Created config directory: ${this.configDir}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/env/prompt/prompt-component.ts
|
|
164
|
+
init_logger();
|
|
165
|
+
import { readFile as readFile2, readdir as readdir2 } from "fs/promises";
|
|
166
|
+
import { join as join2, basename, extname } from "path";
|
|
167
|
+
|
|
168
|
+
// src/env/prompt/prompt-config-registration.ts
|
|
169
|
+
var PROMPT_DEFAULTS = {
|
|
170
|
+
"prompt.defaultName": "default",
|
|
171
|
+
"prompt.variablePrefix": "{{",
|
|
172
|
+
"prompt.variableSuffix": "}}",
|
|
173
|
+
"prompt.configDir": ""
|
|
174
|
+
};
|
|
175
|
+
var PROMPT_CONFIG_REGISTRATION = {
|
|
176
|
+
name: "prompt",
|
|
177
|
+
sources: [
|
|
178
|
+
{ type: "env", envPrefix: "PROMPT", priority: 20, watch: false }
|
|
179
|
+
],
|
|
180
|
+
keys: [
|
|
181
|
+
{ key: "prompt.promptPaths", sources: ["env", "file"] },
|
|
182
|
+
{ key: "prompt.configDir", sources: ["env", "file"] },
|
|
183
|
+
{ key: "prompt.defaultName", sources: ["env", "file"] },
|
|
184
|
+
{ key: "prompt.variablePrefix", sources: ["env", "file"] },
|
|
185
|
+
{ key: "prompt.variableSuffix", sources: ["env", "file"] }
|
|
186
|
+
]
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// src/env/prompt/prompt-component.ts
|
|
190
|
+
init_global_hook_manager();
|
|
191
|
+
var logger2 = createLogger("prompt");
|
|
192
|
+
|
|
193
|
+
class PromptComponent extends BaseComponent {
|
|
194
|
+
name = "prompt";
|
|
195
|
+
version = "1.0.0";
|
|
196
|
+
prompts = new Map;
|
|
197
|
+
config;
|
|
198
|
+
configComponent;
|
|
199
|
+
renderer;
|
|
200
|
+
promptStore;
|
|
201
|
+
configWatcher;
|
|
202
|
+
constructor() {
|
|
203
|
+
super();
|
|
204
|
+
}
|
|
205
|
+
async init(config) {
|
|
206
|
+
await super.init(config);
|
|
207
|
+
const options = config.options;
|
|
208
|
+
if (!options?.configComponent) {
|
|
209
|
+
throw new Error("ConfigComponent is required for PromptComponent initialization");
|
|
210
|
+
}
|
|
211
|
+
this.configComponent = options.configComponent;
|
|
212
|
+
await this.registerConfig(options);
|
|
213
|
+
this.initRenderer();
|
|
214
|
+
this.initPromptStore();
|
|
215
|
+
await this.loadPrompts();
|
|
216
|
+
this.setStatus("running");
|
|
217
|
+
logger2.info(`[PromptComponent] Initialized with ${this.prompts.size} prompts`);
|
|
218
|
+
}
|
|
219
|
+
async registerConfig(options) {
|
|
220
|
+
const configComponent = options.configComponent;
|
|
221
|
+
if (!configComponent)
|
|
222
|
+
return;
|
|
223
|
+
const { config, defaultName, promptPaths, variablePrefix, variableSuffix } = options;
|
|
224
|
+
configComponent.registerComponent(PROMPT_CONFIG_REGISTRATION);
|
|
225
|
+
await configComponent.load("prompt");
|
|
226
|
+
const prefix = "PROMPT";
|
|
227
|
+
const promptKeys = [
|
|
228
|
+
"prompt.defaultName",
|
|
229
|
+
"prompt.promptPaths",
|
|
230
|
+
"prompt.variablePrefix",
|
|
231
|
+
"prompt.variableSuffix",
|
|
232
|
+
"prompt.strictMode"
|
|
233
|
+
];
|
|
234
|
+
for (const key of promptKeys) {
|
|
235
|
+
const envKey = toEnvKey(key, prefix);
|
|
236
|
+
const value = process.env[envKey];
|
|
237
|
+
if (value !== undefined) {
|
|
238
|
+
await configComponent.set(key, value);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const loadedKeys = new Set(promptKeys);
|
|
242
|
+
for (const envKey of Object.keys(process.env)) {
|
|
243
|
+
const configKey = envKeyToConfigKey(envKey, prefix, "prompt");
|
|
244
|
+
if (!configKey)
|
|
245
|
+
continue;
|
|
246
|
+
if (loadedKeys.has(configKey))
|
|
247
|
+
continue;
|
|
248
|
+
loadedKeys.add(configKey);
|
|
249
|
+
const value = process.env[envKey];
|
|
250
|
+
if (value !== undefined) {
|
|
251
|
+
await configComponent.set(configKey, value);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
for (const [key, value] of Object.entries(PROMPT_DEFAULTS)) {
|
|
255
|
+
if (configComponent.get(key) === undefined) {
|
|
256
|
+
await configComponent.set(key, value);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (config) {
|
|
260
|
+
const flatConfig = this.flattenConfig(config);
|
|
261
|
+
for (const [key, value] of Object.entries(flatConfig)) {
|
|
262
|
+
await configComponent.set(key, value);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (defaultName !== undefined) {
|
|
266
|
+
await configComponent.set("prompt.defaultName", defaultName);
|
|
267
|
+
}
|
|
268
|
+
if (promptPaths !== undefined) {
|
|
269
|
+
await configComponent.set("prompt.promptPaths", promptPaths);
|
|
270
|
+
}
|
|
271
|
+
if (variablePrefix !== undefined) {
|
|
272
|
+
await configComponent.set("prompt.variablePrefix", variablePrefix);
|
|
273
|
+
}
|
|
274
|
+
if (variableSuffix !== undefined) {
|
|
275
|
+
await configComponent.set("prompt.variableSuffix", variableSuffix);
|
|
276
|
+
}
|
|
277
|
+
this.registerConfigWatcher(configComponent);
|
|
278
|
+
this.config = {
|
|
279
|
+
defaultName: configComponent.get("prompt.defaultName") || "default",
|
|
280
|
+
promptPaths: configComponent.get("prompt.promptPaths") || [],
|
|
281
|
+
variablePrefix: configComponent.get("prompt.variablePrefix") || "{{",
|
|
282
|
+
variableSuffix: configComponent.get("prompt.variableSuffix") || "}}",
|
|
283
|
+
strictMode: configComponent.get("prompt.strictMode") || false
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
flattenConfig(obj, prefix = "prompt") {
|
|
287
|
+
const result = {};
|
|
288
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
289
|
+
const fullKey = `${prefix}.${key}`;
|
|
290
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
291
|
+
Object.assign(result, this.flattenConfig(value, fullKey));
|
|
292
|
+
} else {
|
|
293
|
+
result[fullKey] = value;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return result;
|
|
297
|
+
}
|
|
298
|
+
registerConfigWatcher(configComponent) {
|
|
299
|
+
if (typeof configComponent.watch !== "function") {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
this.configWatcher = configComponent.watch("prompt.*", (event) => {
|
|
303
|
+
this.onConfigChange(event);
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
onConfigChange(event) {
|
|
307
|
+
const key = event.key;
|
|
308
|
+
const value = event.newValue;
|
|
309
|
+
if (value === undefined)
|
|
310
|
+
return;
|
|
311
|
+
logger2.debug(`[PromptComponent] Config updated: ${key} = ${JSON.stringify(value)}`);
|
|
312
|
+
switch (key) {
|
|
313
|
+
case "prompt.defaultName":
|
|
314
|
+
if (this.config)
|
|
315
|
+
this.config.defaultName = value;
|
|
316
|
+
break;
|
|
317
|
+
case "prompt.promptPaths":
|
|
318
|
+
if (this.config)
|
|
319
|
+
this.config.promptPaths = value;
|
|
320
|
+
break;
|
|
321
|
+
case "prompt.variablePrefix":
|
|
322
|
+
if (this.config) {
|
|
323
|
+
this.config.variablePrefix = value;
|
|
324
|
+
this.initRenderer();
|
|
325
|
+
}
|
|
326
|
+
break;
|
|
327
|
+
case "prompt.variableSuffix":
|
|
328
|
+
if (this.config) {
|
|
329
|
+
this.config.variableSuffix = value;
|
|
330
|
+
this.initRenderer();
|
|
331
|
+
}
|
|
332
|
+
break;
|
|
333
|
+
case "prompt.strictMode":
|
|
334
|
+
if (this.config)
|
|
335
|
+
this.config.strictMode = value;
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
initRenderer() {
|
|
340
|
+
const config = this.config || {
|
|
341
|
+
defaultName: "default",
|
|
342
|
+
promptPaths: [],
|
|
343
|
+
variablePrefix: "{{",
|
|
344
|
+
variableSuffix: "}}",
|
|
345
|
+
strictMode: false
|
|
346
|
+
};
|
|
347
|
+
this.renderer = new PromptRenderer({
|
|
348
|
+
prefix: config.variablePrefix,
|
|
349
|
+
suffix: config.variableSuffix,
|
|
350
|
+
strict: config.strictMode,
|
|
351
|
+
onMissingVariable: (name) => {
|
|
352
|
+
logger2.warn(`Undefined variable: ${name}`);
|
|
353
|
+
return `{{${name}}}`;
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
async onStart() {
|
|
358
|
+
logger2.info("[PromptComponent] Started");
|
|
359
|
+
}
|
|
360
|
+
async onStop() {
|
|
361
|
+
this.configWatcher?.();
|
|
362
|
+
this.configWatcher = undefined;
|
|
363
|
+
this.prompts.clear();
|
|
364
|
+
this.setStatus("stopped");
|
|
365
|
+
logger2.info("[PromptComponent] Stopped");
|
|
366
|
+
}
|
|
367
|
+
getPromptConfig(key, defaultValue) {
|
|
368
|
+
if (this.config && key in this.config) {
|
|
369
|
+
return this.config[key] ?? defaultValue;
|
|
370
|
+
}
|
|
371
|
+
return defaultValue;
|
|
372
|
+
}
|
|
373
|
+
add(name, content, source = "inline") {
|
|
374
|
+
const entry = {
|
|
375
|
+
name,
|
|
376
|
+
content,
|
|
377
|
+
source,
|
|
378
|
+
overridable: true,
|
|
379
|
+
loadedAt: Date.now()
|
|
380
|
+
};
|
|
381
|
+
const existing = this.prompts.get(name);
|
|
382
|
+
if (existing && !existing.overridable) {
|
|
383
|
+
logger2.debug(`[PromptComponent] Skip override for non-overridable prompt: ${name}`);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
this.prompts.set(name, entry);
|
|
387
|
+
logger2.debug(`[PromptComponent] Added prompt: ${name} (${source})`);
|
|
388
|
+
}
|
|
389
|
+
get(name) {
|
|
390
|
+
return this.prompts.get(name)?.content;
|
|
391
|
+
}
|
|
392
|
+
getEntry(name) {
|
|
393
|
+
return this.prompts.get(name);
|
|
394
|
+
}
|
|
395
|
+
has(name) {
|
|
396
|
+
return this.prompts.has(name);
|
|
397
|
+
}
|
|
398
|
+
delete(name) {
|
|
399
|
+
return this.prompts.delete(name);
|
|
400
|
+
}
|
|
401
|
+
list() {
|
|
402
|
+
return Array.from(this.prompts.keys());
|
|
403
|
+
}
|
|
404
|
+
listEntries() {
|
|
405
|
+
return Array.from(this.prompts.values());
|
|
406
|
+
}
|
|
407
|
+
getPromptStore() {
|
|
408
|
+
if (!this.promptStore) {
|
|
409
|
+
this.initPromptStore();
|
|
410
|
+
}
|
|
411
|
+
return this.promptStore;
|
|
412
|
+
}
|
|
413
|
+
getPromptConfigDir() {
|
|
414
|
+
return this.getPromptStore().getConfigDir();
|
|
415
|
+
}
|
|
416
|
+
async savePrompt(name, content) {
|
|
417
|
+
const filePath = await this.getPromptStore().savePrompt(name, content.trim());
|
|
418
|
+
this.add(name, content.trim(), "file");
|
|
419
|
+
const entry = this.prompts.get(name);
|
|
420
|
+
if (entry) {
|
|
421
|
+
entry.filePath = filePath;
|
|
422
|
+
}
|
|
423
|
+
return filePath;
|
|
424
|
+
}
|
|
425
|
+
async deletePromptFile(name) {
|
|
426
|
+
const deleted = await this.getPromptStore().deletePrompt(name);
|
|
427
|
+
if (deleted) {
|
|
428
|
+
this.delete(name);
|
|
429
|
+
}
|
|
430
|
+
return deleted;
|
|
431
|
+
}
|
|
432
|
+
size() {
|
|
433
|
+
return this.prompts.size;
|
|
434
|
+
}
|
|
435
|
+
async getPrompt(name, variables = {}) {
|
|
436
|
+
const defaultName = this.getPromptConfig("defaultName", "default");
|
|
437
|
+
const targetName = this.has(name) ? name : defaultName;
|
|
438
|
+
const entry = this.prompts.get(targetName);
|
|
439
|
+
if (!entry) {
|
|
440
|
+
logger2.warn(`[PromptComponent] Prompt not found: ${name}, using fallback`);
|
|
441
|
+
return "You are a helpful assistant.";
|
|
442
|
+
}
|
|
443
|
+
return this.render(entry.content, variables, { name: targetName });
|
|
444
|
+
}
|
|
445
|
+
async render(content, variables = {}, context) {
|
|
446
|
+
const hookContext = {
|
|
447
|
+
name: context?.name || "anonymous",
|
|
448
|
+
originalContent: content,
|
|
449
|
+
renderedContent: content,
|
|
450
|
+
variables
|
|
451
|
+
};
|
|
452
|
+
await globalHookManager.execute(PromptHookPoints.BEFORE_RENDER, hookContext);
|
|
453
|
+
hookContext.renderedContent = this.renderer.render(hookContext.originalContent, variables);
|
|
454
|
+
await globalHookManager.execute(PromptHookPoints.AFTER_RENDER, hookContext);
|
|
455
|
+
return hookContext.renderedContent;
|
|
456
|
+
}
|
|
457
|
+
extractVariables(content) {
|
|
458
|
+
return this.renderer.extractVariables(content);
|
|
459
|
+
}
|
|
460
|
+
initPromptStore() {
|
|
461
|
+
const customDir = this.configComponent?.get?.("prompt.configDir");
|
|
462
|
+
this.promptStore = new PromptStore({
|
|
463
|
+
configDir: typeof customDir === "string" && customDir.length > 0 ? customDir : undefined
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
async loadPrompts() {
|
|
467
|
+
await this.loadBuiltInPrompts();
|
|
468
|
+
await this.loadUserPrompts();
|
|
469
|
+
await this.loadExternalPrompts();
|
|
470
|
+
}
|
|
471
|
+
async loadUserPrompts() {
|
|
472
|
+
const store = this.getPromptStore();
|
|
473
|
+
const prompts = await store.loadAll();
|
|
474
|
+
for (const prompt of prompts) {
|
|
475
|
+
this.add(prompt.name, prompt.content, "file");
|
|
476
|
+
const entry = this.prompts.get(prompt.name);
|
|
477
|
+
if (entry) {
|
|
478
|
+
entry.filePath = prompt.filePath;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
if (prompts.length > 0) {
|
|
482
|
+
logger2.info(`[PromptComponent] Loaded ${prompts.length} prompts from ${store.getConfigDir()}`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
async loadBuiltInPrompts() {
|
|
486
|
+
for (const [name, content] of Object.entries(builtInPrompts)) {
|
|
487
|
+
if (content) {
|
|
488
|
+
this.prompts.set(name, {
|
|
489
|
+
name,
|
|
490
|
+
content,
|
|
491
|
+
source: "built-in",
|
|
492
|
+
overridable: false,
|
|
493
|
+
loadedAt: Date.now()
|
|
494
|
+
});
|
|
495
|
+
logger2.debug(`[PromptComponent] Loaded built-in prompt: ${name}`);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
logger2.info(`[PromptComponent] Loaded ${this.prompts.size} built-in prompts`);
|
|
499
|
+
}
|
|
500
|
+
async loadExternalPrompts() {
|
|
501
|
+
const promptPaths = this.getPromptConfig("promptPaths", []);
|
|
502
|
+
for (const pathConfig of promptPaths) {
|
|
503
|
+
try {
|
|
504
|
+
if (pathConfig.type === "file") {
|
|
505
|
+
await this.loadFromFile(pathConfig.path, pathConfig.name);
|
|
506
|
+
} else if (pathConfig.type === "directory") {
|
|
507
|
+
await this.loadFromDirectory(pathConfig.path, pathConfig.extension || ".md", pathConfig.recursive !== false);
|
|
508
|
+
}
|
|
509
|
+
} catch (error) {
|
|
510
|
+
logger2.error(`[PromptComponent] Failed to load from ${pathConfig.path}:`, error);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
async loadFromFile(filePath, name) {
|
|
515
|
+
try {
|
|
516
|
+
const content = await readFile2(filePath, "utf-8");
|
|
517
|
+
const promptName = name || basename(filePath, extname(filePath));
|
|
518
|
+
this.add(promptName, content.trim(), "file");
|
|
519
|
+
const entry = this.prompts.get(promptName);
|
|
520
|
+
if (entry)
|
|
521
|
+
entry.filePath = filePath;
|
|
522
|
+
logger2.debug(`[PromptComponent] Loaded prompt from file: ${filePath}`);
|
|
523
|
+
return true;
|
|
524
|
+
} catch (error) {
|
|
525
|
+
logger2.error(`[PromptComponent] Failed to load file ${filePath}:`, error);
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
async loadFromDirectory(directory, extension = ".md", recursive = true) {
|
|
530
|
+
let loaded = 0;
|
|
531
|
+
try {
|
|
532
|
+
const files = await this.findFiles(directory, extension, recursive);
|
|
533
|
+
for (const filePath of files) {
|
|
534
|
+
const relativePath = filePath.replace(directory + "/", "");
|
|
535
|
+
const promptName = relativePath.replace(/\\/g, "/").replace(new RegExp(escapeRegex2(extension) + "$"), "").replace(/\//g, "-");
|
|
536
|
+
const content = await readFile2(filePath, "utf-8");
|
|
537
|
+
this.add(promptName, content.trim(), "directory");
|
|
538
|
+
const entry = this.prompts.get(promptName);
|
|
539
|
+
if (entry)
|
|
540
|
+
entry.filePath = filePath;
|
|
541
|
+
loaded++;
|
|
542
|
+
}
|
|
543
|
+
logger2.info(`[PromptComponent] Loaded ${loaded} prompts from directory: ${directory}`);
|
|
544
|
+
} catch (error) {
|
|
545
|
+
logger2.error(`[PromptComponent] Failed to load directory ${directory}:`, error);
|
|
546
|
+
}
|
|
547
|
+
return loaded;
|
|
548
|
+
}
|
|
549
|
+
async findFiles(dir, extension, recursive) {
|
|
550
|
+
const files = [];
|
|
551
|
+
try {
|
|
552
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
553
|
+
for (const entry of entries) {
|
|
554
|
+
const fullPath = join2(dir, entry.name);
|
|
555
|
+
if (entry.isDirectory() && recursive) {
|
|
556
|
+
const subFiles = await this.findFiles(fullPath, extension, true);
|
|
557
|
+
files.push(...subFiles);
|
|
558
|
+
} else if (entry.isFile() && entry.name.endsWith(extension)) {
|
|
559
|
+
files.push(fullPath);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
} catch (error) {
|
|
563
|
+
logger2.warn(`[PromptComponent] Cannot read directory ${dir}:`, error);
|
|
564
|
+
}
|
|
565
|
+
return files;
|
|
566
|
+
}
|
|
567
|
+
registerPromptHook(hookPoint, name, fn, priority) {
|
|
568
|
+
globalHookManager.register(hookPoint, createHook({ name, priority }, fn));
|
|
569
|
+
}
|
|
570
|
+
unregisterPromptHook(hookPoint, name) {
|
|
571
|
+
return globalHookManager.unregister(hookPoint, name);
|
|
572
|
+
}
|
|
573
|
+
getHookPoints() {
|
|
574
|
+
return [PromptHookPoints.BEFORE_RENDER, PromptHookPoints.AFTER_RENDER];
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
function escapeRegex2(str) {
|
|
578
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
export { PromptPathSchema, PromptConfigSchema, PromptRenderer, PromptStore, PromptComponent };
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getCurrentProcessRegistry,
|
|
3
|
+
killProcessTree
|
|
4
|
+
} from "./roy-agent-core-hvdfgvfz.js";
|
|
1
5
|
import {
|
|
2
6
|
init_decorator,
|
|
3
7
|
wrapFunction
|
|
@@ -20,7 +24,16 @@ import { Effect as Effect2 } from "effect";
|
|
|
20
24
|
|
|
21
25
|
// src/env/tool/built-in/bash-effect.ts
|
|
22
26
|
import { Effect, Context, Layer } from "effect";
|
|
23
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
spawn as _childProcessSpawn
|
|
29
|
+
} from "child_process";
|
|
30
|
+
var spawnInjector;
|
|
31
|
+
function spawn(command, args, options) {
|
|
32
|
+
if (spawnInjector) {
|
|
33
|
+
return spawnInjector(command, args, options);
|
|
34
|
+
}
|
|
35
|
+
return _childProcessSpawn(command, args, options);
|
|
36
|
+
}
|
|
24
37
|
var BashSpawner = Context.GenericTag("BashSpawner");
|
|
25
38
|
var isWindows = process.platform === "win32";
|
|
26
39
|
var SIGKILL_TIMEOUT_MS = 200;
|
|
@@ -63,10 +76,18 @@ var makeBashSpawner = () => {
|
|
|
63
76
|
shell: true,
|
|
64
77
|
cwd,
|
|
65
78
|
env: { ...process.env, ...env },
|
|
66
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
79
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
80
|
+
detached: !isWindows
|
|
67
81
|
};
|
|
68
82
|
child = spawn(command, [], spawnOpts);
|
|
69
83
|
const checkExited = () => exited || !child || !child.pid || child.killed || child.exitCode !== null;
|
|
84
|
+
const currentRegistry = getCurrentProcessRegistry();
|
|
85
|
+
if (currentRegistry && child.pid) {
|
|
86
|
+
currentRegistry.register(child.pid);
|
|
87
|
+
child.once("exit", () => {
|
|
88
|
+
currentRegistry.unregister(child.pid);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
70
91
|
if (timeout > 0) {
|
|
71
92
|
timer = setTimeout(() => {
|
|
72
93
|
if (!checkExited()) {
|
|
@@ -83,8 +104,10 @@ var makeBashSpawner = () => {
|
|
|
83
104
|
return Effect.sync(() => {
|
|
84
105
|
if (timer)
|
|
85
106
|
clearTimeout(timer);
|
|
86
|
-
if (!checkExited() && child) {
|
|
87
|
-
|
|
107
|
+
if (!checkExited() && child && child.pid) {
|
|
108
|
+
try {
|
|
109
|
+
killProcessTree(child.pid);
|
|
110
|
+
} catch {}
|
|
88
111
|
}
|
|
89
112
|
});
|
|
90
113
|
});
|