@ai-setting/roy-agent-core 1.5.41 → 1.5.42

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.
@@ -10,7 +10,7 @@ import {
10
10
  parseJSONCWithProtocols,
11
11
  substituteEnvVars,
12
12
  substituteProtocolRefs
13
- } from "../shared/@ai-setting/roy-agent-core-frx4p6d1.js";
13
+ } from "../shared/@ai-setting/roy-agent-core-nj8yerg9.js";
14
14
  import"../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
15
15
  import"../shared/@ai-setting/roy-agent-core-qxhq8ven.js";
16
16
  import"../shared/@ai-setting/roy-agent-core-4jqq077c.js";
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  AgentComponent,
3
3
  AgentComponentConfigSchema
4
- } from "../../shared/@ai-setting/roy-agent-core-c8f2hync.js";
4
+ } from "../../shared/@ai-setting/roy-agent-core-ek6gk3wk.js";
5
5
  import"../../shared/@ai-setting/roy-agent-core-e25xkv53.js";
6
+ import"../../shared/@ai-setting/roy-agent-core-7t05apnp.js";
7
+ import"../../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
6
8
  import"../../shared/@ai-setting/roy-agent-core-ctdhjv68.js";
7
9
  import {
8
10
  SummaryAgent
package/dist/env/index.js CHANGED
@@ -1,11 +1,6 @@
1
1
  import {
2
2
  BaseEnvironment
3
3
  } from "../shared/@ai-setting/roy-agent-core-ee6nnnqw.js";
4
- import {
5
- XDG_PATHS,
6
- getXDGPath,
7
- getXDGPaths
8
- } from "../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
9
4
  import {
10
5
  EventSourceComponent,
11
6
  builtInHandlers,
@@ -26,7 +21,7 @@ import"../shared/@ai-setting/roy-agent-core-e9fdm13a.js";
26
21
  import"../shared/@ai-setting/roy-agent-core-az13yzmc.js";
27
22
  import {
28
23
  WorkflowComponent
29
- } from "../shared/@ai-setting/roy-agent-core-yc543gnq.js";
24
+ } from "../shared/@ai-setting/roy-agent-core-bmr6bdfb.js";
30
25
  import"../shared/@ai-setting/roy-agent-core-0rtxwr28.js";
31
26
  import"../shared/@ai-setting/roy-agent-core-2jnzv9at.js";
32
27
  import"../shared/@ai-setting/roy-agent-core-69jskqjg.js";
@@ -39,20 +34,26 @@ import"../shared/@ai-setting/roy-agent-core-1ce3fqrk.js";
39
34
  import {
40
35
  AgentComponent,
41
36
  AgentComponentConfigSchema
42
- } from "../shared/@ai-setting/roy-agent-core-c8f2hync.js";
37
+ } from "../shared/@ai-setting/roy-agent-core-ek6gk3wk.js";
43
38
  import"../shared/@ai-setting/roy-agent-core-e25xkv53.js";
44
39
  import {
45
40
  TaskComponent
46
- } from "../shared/@ai-setting/roy-agent-core-15x8fe5h.js";
47
- import"../shared/@ai-setting/roy-agent-core-v53rfk99.js";
41
+ } from "../shared/@ai-setting/roy-agent-core-9q6sa7m3.js";
42
+ import"../shared/@ai-setting/roy-agent-core-xz22rmak.js";
48
43
  import"../shared/@ai-setting/roy-agent-core-hsxn8m1j.js";
44
+ import"../shared/@ai-setting/roy-agent-core-7t05apnp.js";
45
+ import {
46
+ XDG_PATHS,
47
+ getXDGPath,
48
+ getXDGPaths
49
+ } from "../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
49
50
  import"../shared/@ai-setting/roy-agent-core-wa1kzqky.js";
50
51
  import"../shared/@ai-setting/roy-agent-core-t94ktchq.js";
51
52
  import"../shared/@ai-setting/roy-agent-core-92z6t4he.js";
52
53
  import"../shared/@ai-setting/roy-agent-core-8gxth0eh.js";
53
54
  import {
54
55
  McpComponent
55
- } from "../shared/@ai-setting/roy-agent-core-ycg9rk6z.js";
56
+ } from "../shared/@ai-setting/roy-agent-core-xkb264a8.js";
56
57
  import"../shared/@ai-setting/roy-agent-core-ctdhjv68.js";
57
58
  import"../shared/@ai-setting/roy-agent-core-1bfmxx89.js";
58
59
  import"../shared/@ai-setting/roy-agent-core-kwhv9dcd.js";
@@ -8,7 +8,7 @@ import {
8
8
  McpServerLocalConfigSchema,
9
9
  McpServerRemoteConfigSchema,
10
10
  getMcpPathPriority
11
- } from "../../shared/@ai-setting/roy-agent-core-ycg9rk6z.js";
11
+ } from "../../shared/@ai-setting/roy-agent-core-xkb264a8.js";
12
12
  import"../../shared/@ai-setting/roy-agent-core-ctdhjv68.js";
13
13
  import {
14
14
  adaptMcpTool,
@@ -3,7 +3,8 @@ import {
3
3
  PromptConfigSchema,
4
4
  PromptPathSchema,
5
5
  PromptRenderer
6
- } from "../../shared/@ai-setting/roy-agent-core-wb43x8hd.js";
6
+ } from "../../shared/@ai-setting/roy-agent-core-z1xf2fdk.js";
7
+ import"../../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
7
8
  import"../../shared/@ai-setting/roy-agent-core-qxhq8ven.js";
8
9
  import"../../shared/@ai-setting/roy-agent-core-4jqq077c.js";
9
10
  import"../../shared/@ai-setting/roy-agent-core-2dhd60aw.js";
@@ -3,7 +3,9 @@ import {
3
3
  BackgroundTaskManager,
4
4
  createDelegateTool,
5
5
  createStopTool
6
- } from "../../../shared/@ai-setting/roy-agent-core-v53rfk99.js";
6
+ } from "../../../shared/@ai-setting/roy-agent-core-xz22rmak.js";
7
+ import"../../../shared/@ai-setting/roy-agent-core-7t05apnp.js";
8
+ import"../../../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
7
9
  import"../../../shared/@ai-setting/roy-agent-core-92z6t4he.js";
8
10
  import"../../../shared/@ai-setting/roy-agent-core-jqy2mdyq.js";
9
11
  import"../../../shared/@ai-setting/roy-agent-core-z33en0cz.js";
@@ -4,11 +4,13 @@ import {
4
4
  TaskConfigSchema,
5
5
  TaskPriorityEnum,
6
6
  TaskStatusEnum
7
- } from "../../shared/@ai-setting/roy-agent-core-15x8fe5h.js";
8
- import"../../shared/@ai-setting/roy-agent-core-v53rfk99.js";
7
+ } from "../../shared/@ai-setting/roy-agent-core-9q6sa7m3.js";
8
+ import"../../shared/@ai-setting/roy-agent-core-xz22rmak.js";
9
9
  import {
10
10
  SQLiteTaskStore
11
11
  } from "../../shared/@ai-setting/roy-agent-core-hsxn8m1j.js";
12
+ import"../../shared/@ai-setting/roy-agent-core-7t05apnp.js";
13
+ import"../../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
12
14
  import"../../shared/@ai-setting/roy-agent-core-wa1kzqky.js";
13
15
  import"../../shared/@ai-setting/roy-agent-core-t94ktchq.js";
14
16
  import"../../shared/@ai-setting/roy-agent-core-92z6t4he.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  WorkflowComponent
3
- } from "../../shared/@ai-setting/roy-agent-core-yc543gnq.js";
3
+ } from "../../shared/@ai-setting/roy-agent-core-bmr6bdfb.js";
4
4
  import"../../shared/@ai-setting/roy-agent-core-0rtxwr28.js";
5
5
  import"../../shared/@ai-setting/roy-agent-core-2jnzv9at.js";
6
6
  import"../../shared/@ai-setting/roy-agent-core-69jskqjg.js";
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  } from "./shared/@ai-setting/roy-agent-core-kajktp3d.js";
13
13
  import {
14
14
  ConfigComponent
15
- } from "./shared/@ai-setting/roy-agent-core-frx4p6d1.js";
15
+ } from "./shared/@ai-setting/roy-agent-core-nj8yerg9.js";
16
16
  import {
17
17
  CommandsComponent
18
18
  } from "./shared/@ai-setting/roy-agent-core-b4wd9tn6.js";
@@ -33,9 +33,13 @@ import {
33
33
  } from "./shared/@ai-setting/roy-agent-core-rsybkb38.js";
34
34
  import {
35
35
  PromptComponent,
36
+ PromptStore,
36
37
  getBuiltInPrompt,
37
38
  getBuiltInPromptNames
38
- } from "./shared/@ai-setting/roy-agent-core-wb43x8hd.js";
39
+ } from "./shared/@ai-setting/roy-agent-core-z1xf2fdk.js";
40
+ import {
41
+ closeDatabase
42
+ } from "./shared/@ai-setting/roy-agent-core-9ffsvvcf.js";
39
43
  import"./shared/@ai-setting/roy-agent-core-2grcjaad.js";
40
44
  import {
41
45
  MemoryComponent
@@ -58,11 +62,6 @@ import {
58
62
  generateDescendingId,
59
63
  generateId
60
64
  } from "./shared/@ai-setting/roy-agent-core-ee6nnnqw.js";
61
- import {
62
- XDG_PATHS,
63
- getXDGPath,
64
- getXDGPaths
65
- } from "./shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
66
65
  import {
67
66
  EventSourceComponent,
68
67
  builtInHandlers,
@@ -93,7 +92,7 @@ import {
93
92
  } from "./shared/@ai-setting/roy-agent-core-az13yzmc.js";
94
93
  import {
95
94
  WorkflowComponent
96
- } from "./shared/@ai-setting/roy-agent-core-yc543gnq.js";
95
+ } from "./shared/@ai-setting/roy-agent-core-bmr6bdfb.js";
97
96
  import {
98
97
  init_node_registry_helper,
99
98
  registerDecoratorNodeType
@@ -115,16 +114,24 @@ import"./shared/@ai-setting/roy-agent-core-1ce3fqrk.js";
115
114
  import {
116
115
  AgentComponent,
117
116
  AgentComponentConfigSchema
118
- } from "./shared/@ai-setting/roy-agent-core-c8f2hync.js";
117
+ } from "./shared/@ai-setting/roy-agent-core-ek6gk3wk.js";
119
118
  import {
120
119
  AskUserError,
121
120
  init_workflow_hil
122
121
  } from "./shared/@ai-setting/roy-agent-core-e25xkv53.js";
123
122
  import {
124
123
  TaskComponent
125
- } from "./shared/@ai-setting/roy-agent-core-15x8fe5h.js";
126
- import"./shared/@ai-setting/roy-agent-core-v53rfk99.js";
124
+ } from "./shared/@ai-setting/roy-agent-core-9q6sa7m3.js";
125
+ import"./shared/@ai-setting/roy-agent-core-xz22rmak.js";
127
126
  import"./shared/@ai-setting/roy-agent-core-hsxn8m1j.js";
127
+ import {
128
+ AgentRegistry
129
+ } from "./shared/@ai-setting/roy-agent-core-7t05apnp.js";
130
+ import {
131
+ XDG_PATHS,
132
+ getXDGPath,
133
+ getXDGPaths
134
+ } from "./shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
128
135
  import"./shared/@ai-setting/roy-agent-core-wa1kzqky.js";
129
136
  import"./shared/@ai-setting/roy-agent-core-t94ktchq.js";
130
137
  import {
@@ -137,7 +144,7 @@ import {
137
144
  import"./shared/@ai-setting/roy-agent-core-psvxt4c9.js";
138
145
  import {
139
146
  McpComponent
140
- } from "./shared/@ai-setting/roy-agent-core-ycg9rk6z.js";
147
+ } from "./shared/@ai-setting/roy-agent-core-xkb264a8.js";
141
148
  import {
142
149
  AgentError,
143
150
  ComponentError,
@@ -365,6 +372,7 @@ export {
365
372
  createLogger,
366
373
  createInvokeConfig,
367
374
  createHook,
375
+ closeDatabase,
368
376
  builtInHandlers,
369
377
  bashTool,
370
378
  XDG_PATHS,
@@ -392,6 +400,7 @@ export {
392
400
  ReplFormatter,
393
401
  ProviderConfigSchema,
394
402
  ProviderCapabilitiesSchema,
403
+ PromptStore,
395
404
  PromptComponent,
396
405
  PluginComponent,
397
406
  OTelTracerProvider,
@@ -423,6 +432,7 @@ export {
423
432
  BUILT_IN_EVENT_SOURCE_TYPE_LIST,
424
433
  BUILT_IN_EVENT_SOURCE_TYPES,
425
434
  AskUserError,
435
+ AgentRegistry,
426
436
  AgentError,
427
437
  AgentComponentConfigSchema,
428
438
  AgentComponent
@@ -0,0 +1,287 @@
1
+ import {
2
+ getXDGPath
3
+ } from "./roy-agent-core-qxnbvgwe.js";
4
+ import {
5
+ createLogger,
6
+ init_logger
7
+ } from "./roy-agent-core-10n2jh7p.js";
8
+
9
+ // src/env/agent/agent-registry.ts
10
+ import { readdir, readFile, writeFile, mkdir, unlink } from "fs/promises";
11
+ import { existsSync } from "fs";
12
+ import { join } from "path";
13
+ import { z } from "zod";
14
+ import yaml from "yaml";
15
+ init_logger();
16
+ var logger = createLogger("agent:registry");
17
+ var AgentConfigSchema = z.object({
18
+ name: z.string(),
19
+ type: z.enum(["primary", "sub"]),
20
+ description: z.string().optional(),
21
+ systemPromptRef: z.string().optional(),
22
+ systemPrompt: z.string().optional(),
23
+ model: z.string().optional(),
24
+ maxIterations: z.number().optional(),
25
+ maxErrorRetries: z.number().optional(),
26
+ allowedTools: z.array(z.string()).optional(),
27
+ deniedTools: z.array(z.string()).optional(),
28
+ toolTimeout: z.number().optional(),
29
+ toolRetries: z.number().optional(),
30
+ doomLoopThreshold: z.number().optional(),
31
+ filterHistory: z.boolean().optional()
32
+ });
33
+
34
+ class AgentRegistry {
35
+ agents = new Map;
36
+ configDir;
37
+ configComponent;
38
+ promptComponent;
39
+ resolvePromptComponent;
40
+ constructor(options) {
41
+ this.configComponent = options.configComponent;
42
+ this.promptComponent = options.promptComponent ?? null;
43
+ this.resolvePromptComponent = options.resolvePromptComponent;
44
+ const customDir = this.configComponent?.get?.("agent.configDir");
45
+ if (customDir && typeof customDir === "string" && customDir.length > 0) {
46
+ this.configDir = customDir;
47
+ } else if (options.baseDir) {
48
+ this.configDir = join(options.baseDir, "agents");
49
+ } else {
50
+ this.configDir = join(getXDGPath("data"), "agents");
51
+ }
52
+ logger.debug(`[AgentRegistry] Config dir: ${this.configDir}`);
53
+ }
54
+ getConfigDir() {
55
+ return this.configDir;
56
+ }
57
+ hasAgent(name) {
58
+ return this.agents.has(name);
59
+ }
60
+ get(name) {
61
+ return this.agents.get(name);
62
+ }
63
+ list() {
64
+ return Array.from(this.agents.values());
65
+ }
66
+ listAgentsByType(type) {
67
+ return this.list().filter((agent) => agent.type === type);
68
+ }
69
+ register(agent) {
70
+ if (!agent.name) {
71
+ throw new Error("Agent name is required");
72
+ }
73
+ this.agents.set(agent.name, { ...agent });
74
+ logger.info(`[AgentRegistry] Registered agent: ${agent.name}`, { type: agent.type });
75
+ }
76
+ unregister(name) {
77
+ const deleted = this.agents.delete(name);
78
+ if (deleted) {
79
+ logger.info(`[AgentRegistry] Unregistered agent: ${name}`);
80
+ }
81
+ return deleted;
82
+ }
83
+ clear() {
84
+ this.agents.clear();
85
+ logger.info("[AgentRegistry] Cleared all agents");
86
+ }
87
+ async getSystemPrompt(name) {
88
+ const agent = this.agents.get(name);
89
+ if (!agent) {
90
+ return;
91
+ }
92
+ const promptComponent = this.getActivePromptComponent();
93
+ if (agent.systemPromptRef) {
94
+ try {
95
+ const prompt = promptComponent?.get?.(agent.systemPromptRef);
96
+ if (prompt) {
97
+ logger.debug(`[AgentRegistry] Resolved systemPromptRef: ${agent.systemPromptRef}`);
98
+ return prompt;
99
+ }
100
+ if (promptComponent?.getPrompt) {
101
+ const rendered = await promptComponent.getPrompt(agent.systemPromptRef);
102
+ if (rendered) {
103
+ return rendered;
104
+ }
105
+ }
106
+ if (agent.systemPrompt) {
107
+ logger.debug(`[AgentRegistry] systemPromptRef not found, falling back to inline`);
108
+ return agent.systemPrompt;
109
+ }
110
+ return;
111
+ } catch (error) {
112
+ logger.warn(`[AgentRegistry] Failed to resolve systemPromptRef: ${agent.systemPromptRef}`, { error });
113
+ return agent.systemPrompt;
114
+ }
115
+ }
116
+ return agent.systemPrompt;
117
+ }
118
+ getActivePromptComponent() {
119
+ return this.resolvePromptComponent?.() ?? this.promptComponent;
120
+ }
121
+ getInlineSystemPrompt(name) {
122
+ const agent = this.agents.get(name);
123
+ if (!agent) {
124
+ return;
125
+ }
126
+ return agent.systemPrompt;
127
+ }
128
+ async load() {
129
+ try {
130
+ return await this.loadFromDirectory(this.configDir);
131
+ } catch (error) {
132
+ logger.warn(`[AgentRegistry] Failed to load agents: ${error}`);
133
+ return 0;
134
+ }
135
+ }
136
+ async loadFromDirectory(directory) {
137
+ let loaded = 0;
138
+ try {
139
+ if (!existsSync(directory)) {
140
+ logger.debug(`[AgentRegistry] Config directory does not exist: ${directory}`);
141
+ return 0;
142
+ }
143
+ const files = await readdir(directory, { withFileTypes: true });
144
+ for (const file of files) {
145
+ const fullPath = join(directory, file.name);
146
+ if (file.isDirectory()) {
147
+ continue;
148
+ }
149
+ if (!isAgentConfigFile(file.name)) {
150
+ continue;
151
+ }
152
+ try {
153
+ const content = await readFile(fullPath, "utf-8");
154
+ const agent = this.parseAgentConfig(content, fullPath);
155
+ if (agent) {
156
+ this.agents.set(agent.name, agent);
157
+ logger.info(`[AgentRegistry] Loaded agent: ${agent.name} from ${file.name}`);
158
+ loaded++;
159
+ }
160
+ } catch (error) {
161
+ logger.warn(`[AgentRegistry] Failed to load agent from ${file.name}: ${error}`);
162
+ }
163
+ }
164
+ logger.info(`[AgentRegistry] Loaded ${loaded} agents from ${directory}`);
165
+ } catch (error) {
166
+ logger.warn(`[AgentRegistry] Error reading config directory: ${error}`);
167
+ }
168
+ return loaded;
169
+ }
170
+ parseAgentConfig(content, source) {
171
+ try {
172
+ const parsed = yaml.parse(content);
173
+ const result = AgentConfigSchema.safeParse(parsed);
174
+ if (!result.success) {
175
+ logger.warn(`[AgentRegistry] Invalid agent config: ${source}`, {
176
+ errors: result.error.errors
177
+ });
178
+ return null;
179
+ }
180
+ return result.data;
181
+ } catch (error) {
182
+ logger.error(`[AgentRegistry] Failed to parse agent config: ${source}`, { error });
183
+ return null;
184
+ }
185
+ }
186
+ async saveAgent(agent) {
187
+ try {
188
+ await this.ensureConfigDir();
189
+ const yamlContent = this.agentToYaml(agent);
190
+ const filePath = join(this.configDir, `${agent.name}.yaml`);
191
+ await writeFile(filePath, yamlContent, "utf-8");
192
+ this.agents.set(agent.name, agent);
193
+ logger.info(`[AgentRegistry] Saved agent: ${agent.name} to ${filePath}`);
194
+ return true;
195
+ } catch (error) {
196
+ logger.error(`[AgentRegistry] Failed to save agent: ${agent.name}`, { error });
197
+ return false;
198
+ }
199
+ }
200
+ async ensureConfigDir() {
201
+ if (!existsSync(this.configDir)) {
202
+ await mkdir(this.configDir, { recursive: true });
203
+ logger.debug(`[AgentRegistry] Created config directory: ${this.configDir}`);
204
+ }
205
+ }
206
+ agentToYaml(agent) {
207
+ const config = {
208
+ name: agent.name,
209
+ type: agent.type,
210
+ ...agent.description !== undefined ? { description: agent.description } : {},
211
+ ...agent.systemPromptRef !== undefined ? { systemPromptRef: agent.systemPromptRef } : {},
212
+ ...agent.systemPrompt !== undefined ? { systemPrompt: agent.systemPrompt } : {},
213
+ ...agent.model !== undefined ? { model: agent.model } : {},
214
+ ...agent.maxIterations !== undefined ? { maxIterations: agent.maxIterations } : {},
215
+ ...agent.maxErrorRetries !== undefined ? { maxErrorRetries: agent.maxErrorRetries } : {},
216
+ ...agent.allowedTools !== undefined ? { allowedTools: agent.allowedTools } : {},
217
+ ...agent.deniedTools !== undefined ? { deniedTools: agent.deniedTools } : {},
218
+ ...agent.toolTimeout !== undefined ? { toolTimeout: agent.toolTimeout } : {},
219
+ ...agent.toolRetries !== undefined ? { toolRetries: agent.toolRetries } : {},
220
+ ...agent.doomLoopThreshold !== undefined ? { doomLoopThreshold: agent.doomLoopThreshold } : {},
221
+ ...agent.filterHistory !== undefined ? { filterHistory: agent.filterHistory } : {}
222
+ };
223
+ return yaml.stringify(config).trimEnd() + `
224
+ `;
225
+ }
226
+ async deleteAgent(name) {
227
+ const agent = this.agents.get(name);
228
+ if (!agent) {
229
+ logger.warn(`[AgentRegistry] Agent not found: ${name}`);
230
+ return false;
231
+ }
232
+ try {
233
+ const filePath = join(this.configDir, `${name}.yaml`);
234
+ if (existsSync(filePath)) {
235
+ await unlink(filePath);
236
+ logger.info(`[AgentRegistry] Deleted agent file: ${filePath}`);
237
+ }
238
+ this.agents.delete(name);
239
+ return true;
240
+ } catch (error) {
241
+ logger.error(`[AgentRegistry] Failed to delete agent: ${name}`, { error });
242
+ return false;
243
+ }
244
+ }
245
+ exportAgents(options = {}) {
246
+ const agents = this.list();
247
+ if (options.format === "json") {
248
+ return agents;
249
+ }
250
+ return agents;
251
+ }
252
+ exportAgentsAsJson() {
253
+ return JSON.stringify(this.list(), null, 2);
254
+ }
255
+ size() {
256
+ return this.agents.size;
257
+ }
258
+ configDirExists() {
259
+ return existsSync(this.configDir);
260
+ }
261
+ getAgentFilePath(name) {
262
+ return join(this.configDir, `${name}.yaml`);
263
+ }
264
+ }
265
+ function isAgentConfigFile(fileName) {
266
+ return fileName.endsWith(".yaml") || fileName.endsWith(".yml");
267
+ }
268
+ var DEFAULT_SUBAGENT_PROMPT = `You are a subagent created by the main agent to handle a specific task.
269
+
270
+ ## Your Role
271
+ - You were created to handle: {task_description}
272
+ - Complete this task. That's your entire purpose.
273
+ - You are NOT the main agent. Don't try to be.
274
+
275
+ ## Rules
276
+ 1. **Stay focused** - Do your assigned task, nothing else
277
+ 2. **Complete the task** - Your final message will be automatically reported to the main agent
278
+ 3. **Don't initiate** - No heartbeats, no proactive actions, no side quests
279
+ 4. **Be ephemeral** - You may be terminated after task completion. That's fine.
280
+ 5. **No nested delegation** - Do NOT use delegate_task or stop_task tools. Complete the task yourself.
281
+
282
+ ## Execution
283
+ - Use the available tools to complete the task
284
+ - If you need more information, ask the main agent through the result
285
+ - Return a clear summary of what you did and the results`;
286
+
287
+ export { AgentRegistry, DEFAULT_SUBAGENT_PROMPT };
@@ -2,7 +2,7 @@ import {
2
2
  BackgroundTaskManager,
3
3
  createDelegateTool,
4
4
  createStopTool
5
- } from "./roy-agent-core-v53rfk99.js";
5
+ } from "./roy-agent-core-xz22rmak.js";
6
6
  import {
7
7
  SQLiteTaskStore,
8
8
  getDefaultTaskDbPath
@@ -259,6 +259,10 @@ class WorkflowComponent extends BaseComponent {
259
259
  this._status = "stopping";
260
260
  this.workflowService = null;
261
261
  this.nodeRegistry = null;
262
+ try {
263
+ const { closeDatabase } = await import("./roy-agent-core-zwp3jp02.js");
264
+ closeDatabase();
265
+ } catch {}
262
266
  this._status = "stopped";
263
267
  componentLogger.info("WorkflowComponent stopped");
264
268
  }
@@ -2,6 +2,9 @@ import {
2
2
  AskUserError,
3
3
  init_workflow_hil
4
4
  } from "./roy-agent-core-e25xkv53.js";
5
+ import {
6
+ AgentRegistry
7
+ } from "./roy-agent-core-7t05apnp.js";
5
8
  import {
6
9
  ContextError
7
10
  } from "./roy-agent-core-ctdhjv68.js";
@@ -166,6 +169,7 @@ class AgentComponent extends BaseComponent {
166
169
  configWatcher;
167
170
  messageConverter = new SessionMessageConverter;
168
171
  _constructorConfig;
172
+ registry;
169
173
  runCounter = 0;
170
174
  constructor(options = {}) {
171
175
  super();
@@ -185,6 +189,7 @@ class AgentComponent extends BaseComponent {
185
189
  }
186
190
  this.configComponent = options.configComponent;
187
191
  await this.registerConfig(options);
192
+ await this.initRegistry(options.configComponent);
188
193
  this.setStatus("running");
189
194
  }
190
195
  async registerConfig(options) {
@@ -271,6 +276,63 @@ class AgentComponent extends BaseComponent {
271
276
  newValue: event.newValue
272
277
  });
273
278
  }
279
+ async initRegistry(configComponent) {
280
+ try {
281
+ this.registry = new AgentRegistry({
282
+ configComponent,
283
+ resolvePromptComponent: () => this.env?.getComponent?.("prompt") ?? null
284
+ });
285
+ const loadedCount = await this.registry.load();
286
+ logger.info(`[AgentComponent] Loaded ${loadedCount} agents from config directory`);
287
+ for (const agentDef of this.registry.list()) {
288
+ if (!this.agents.has(agentDef.name)) {
289
+ const systemPrompt = await this.registry.getSystemPrompt(agentDef.name);
290
+ this.registerAgent(agentDef.name, {
291
+ type: agentDef.type,
292
+ systemPrompt,
293
+ allowedTools: agentDef.allowedTools,
294
+ deniedTools: agentDef.deniedTools,
295
+ model: agentDef.model,
296
+ maxIterations: agentDef.maxIterations
297
+ });
298
+ logger.debug(`[AgentComponent] Registered agent from config: ${agentDef.name}`);
299
+ }
300
+ }
301
+ } catch (error) {
302
+ logger.warn(`[AgentComponent] Failed to initialize AgentRegistry: ${error}`);
303
+ }
304
+ }
305
+ async syncRegistryAgentsFromConfig() {
306
+ if (!this.registry) {
307
+ return;
308
+ }
309
+ for (const agentDef of this.registry.list()) {
310
+ const systemPrompt = await this.registry.getSystemPrompt(agentDef.name);
311
+ const existing = this.agents.get(agentDef.name);
312
+ if (existing) {
313
+ existing.config.systemPrompt = systemPrompt;
314
+ } else {
315
+ this.registerAgent(agentDef.name, {
316
+ type: agentDef.type,
317
+ systemPrompt,
318
+ allowedTools: agentDef.allowedTools,
319
+ deniedTools: agentDef.deniedTools,
320
+ model: agentDef.model,
321
+ maxIterations: agentDef.maxIterations
322
+ });
323
+ }
324
+ logger.debug(`[AgentComponent] Synced registry agent: ${agentDef.name}`);
325
+ }
326
+ }
327
+ getRegistry() {
328
+ return this.registry;
329
+ }
330
+ getAgentFromRegistry(name) {
331
+ return this.registry?.get(name);
332
+ }
333
+ listAgentsFromRegistry() {
334
+ return this.registry?.list() ?? [];
335
+ }
274
336
  async onStop() {
275
337
  logger.info("[AgentComponent] Stopping and cleaning up resources...");
276
338
  for (const [name, agent] of this.agents) {
@@ -1048,6 +1048,14 @@ class ConfigComponent extends BaseComponent {
1048
1048
  }
1049
1049
  this.sourceUnwatchFns.clear();
1050
1050
  }
1051
+ shutdown() {
1052
+ this.unwatchAll();
1053
+ this.persistQueue.clear();
1054
+ }
1055
+ async onStop() {
1056
+ this.shutdown();
1057
+ await super.onStop();
1058
+ }
1051
1059
  getSources() {
1052
1060
  return [...this.sources];
1053
1061
  }
@@ -318,10 +318,25 @@ class McpLoader {
318
318
  return;
319
319
  try {
320
320
  await entry.client.close();
321
- this.clients.delete(name);
322
- logger2.info(`[McpLoader] Disconnected from ${name}`);
323
321
  } catch (error) {
324
- logger2.warn(`[McpLoader] Error disconnecting from ${name}`, { error });
322
+ logger2.warn(`[McpLoader] Error closing client for ${name}`, { error });
323
+ }
324
+ await this.closeTransport(entry.transport, name);
325
+ this.clients.delete(name);
326
+ logger2.info(`[McpLoader] Disconnected from ${name}`);
327
+ }
328
+ async closeTransport(transport, name) {
329
+ try {
330
+ const transportAny = transport;
331
+ if (typeof transportAny.close === "function") {
332
+ await transportAny.close();
333
+ }
334
+ const child = transportAny._process ?? transportAny.process;
335
+ if (child?.pid && !child.killed) {
336
+ child.kill?.("SIGTERM");
337
+ }
338
+ } catch (error) {
339
+ logger2.warn(`[McpLoader] Error closing transport for ${name}`, { error });
325
340
  }
326
341
  }
327
342
  async disconnectAll() {
@@ -1,3 +1,6 @@
1
+ import {
2
+ DEFAULT_SUBAGENT_PROMPT
3
+ } from "./roy-agent-core-7t05apnp.js";
1
4
  import {
2
5
  TaskHookPoints
3
6
  } from "./roy-agent-core-92z6t4he.js";
@@ -12,6 +15,54 @@ import {
12
15
  // src/env/task/delegate/delegate-tool.ts
13
16
  init_logger();
14
17
  import { z } from "zod";
18
+
19
+ // src/env/task/delegate/subagent-resolver.ts
20
+ function isKnownSubagentType(subagentType, registry) {
21
+ if (getSubAgentSpec(subagentType)) {
22
+ return true;
23
+ }
24
+ return registry?.hasAgent(subagentType) ?? false;
25
+ }
26
+ async function resolveSubAgentConfig(subagentType, options = {}) {
27
+ const getBuiltIn = options.getBuiltIn ?? getSubAgentSpec;
28
+ const builtIn = getBuiltIn(subagentType);
29
+ const agentDef = options.registry?.get(subagentType);
30
+ if (!builtIn && !agentDef) {
31
+ return;
32
+ }
33
+ if (agentDef) {
34
+ return resolveFromRegistry(subagentType, agentDef, builtIn, options.registry);
35
+ }
36
+ return {
37
+ subagentType,
38
+ description: builtIn.description,
39
+ basePrompt: builtIn.promptOverride || DEFAULT_SUBAGENT_PROMPT,
40
+ allowedTools: builtIn.allowedTools,
41
+ deniedTools: builtIn.deniedTools ?? ["delegate_task", "stop_task"],
42
+ fromRegistry: false
43
+ };
44
+ }
45
+ async function resolveFromRegistry(subagentType, agentDef, builtIn, registry) {
46
+ const resolvedPrompt = registry ? await registry.getSystemPrompt(subagentType) : agentDef.systemPrompt;
47
+ return {
48
+ subagentType,
49
+ description: agentDef.description || builtIn?.description || "Custom agent",
50
+ basePrompt: resolvedPrompt || builtIn?.promptOverride || DEFAULT_SUBAGENT_PROMPT,
51
+ allowedTools: agentDef.allowedTools ?? builtIn?.allowedTools,
52
+ deniedTools: agentDef.deniedTools ?? builtIn?.deniedTools ?? ["delegate_task", "stop_task"],
53
+ fromRegistry: true
54
+ };
55
+ }
56
+ function listKnownSubagentDescriptions(registry) {
57
+ const builtInLines = builtInSubAgents.map((agent) => `- ${agent.id}: ${agent.description}`);
58
+ const registryAgents = registry?.listAgentsByType("sub") ?? [];
59
+ const customLines = registryAgents.filter((agent) => !builtInSubAgents.some((builtIn) => builtIn.id === agent.name)).map((agent) => `- ${agent.name}: ${agent.description || "Custom agent"}`);
60
+ const lines = [...builtInLines, ...customLines];
61
+ return lines.join(`
62
+ `);
63
+ }
64
+
65
+ // src/env/task/delegate/delegate-tool.ts
15
66
  var logger = createLogger("task:delegate");
16
67
  var BackgroundTaskEventTypes = {
17
68
  STARTED: "task.background.started",
@@ -99,10 +150,6 @@ var builtInSubAgents = [
99
150
  function getSubAgentSpec(id) {
100
151
  return builtInSubAgents.find((agent) => agent.id === id);
101
152
  }
102
- function getSubAgentToolDescription() {
103
- return builtInSubAgents.map((agent) => `- ${agent.id}: ${agent.description}`).join(`
104
- `);
105
- }
106
153
  function ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools) {
107
154
  let agentInstance = agentComponent.getAgent(subagentType);
108
155
  if (!agentInstance) {
@@ -341,24 +388,20 @@ class BackgroundTaskManager {
341
388
  }
342
389
  }
343
390
  async executeWithAbort(subSession, prompt, timeoutMs, signal) {
344
- return new Promise((resolve, reject) => {
345
- const timer = setTimeout(() => {
346
- reject(new Error(`Task execution timeout after ${timeoutMs}ms`));
347
- }, timeoutMs);
348
- signal?.addEventListener("abort", () => {
349
- clearTimeout(timer);
350
- reject(new Error("Task execution stopped"));
351
- });
352
- const metadata = subSession.info?.metadata || {};
353
- const taskId = metadata.task_id;
354
- const taskDescription = metadata.task_description || "";
355
- const sessionId = subSession.id;
356
- const subagentType = metadata.subagent_type || "general";
357
- const subAgent = getSubAgentSpec(subagentType);
358
- let basePrompt = subAgent?.promptOverride || `You are a subagent. Complete this task: {task_description}`;
359
- const deniedTools = subAgent?.deniedTools || [];
360
- let fullPrompt = basePrompt.replace(/{task_description}/g, taskDescription || "N/A");
361
- fullPrompt += `
391
+ const metadata = subSession.info?.metadata || {};
392
+ const taskId = metadata.task_id;
393
+ const taskDescription = metadata.task_description || "";
394
+ const sessionId = subSession.id;
395
+ const subagentType = metadata.subagent_type || "general";
396
+ const agentComponent = this.env?.getComponent?.("agent");
397
+ const registry = agentComponent?.getRegistry?.();
398
+ const resolved = await resolveSubAgentConfig(subagentType, { registry });
399
+ const subAgent = getSubAgentSpec(subagentType);
400
+ const basePrompt = resolved?.basePrompt || subAgent?.promptOverride || `You are a subagent. Complete this task: {task_description}`;
401
+ const deniedTools = resolved?.deniedTools || subAgent?.deniedTools || [];
402
+ const allowedTools = resolved?.allowedTools || subAgent?.allowedTools;
403
+ let fullPrompt = basePrompt.replace(/{task_description}/g, taskDescription || "N/A");
404
+ fullPrompt += `
362
405
 
363
406
  ---
364
407
 
@@ -377,18 +420,31 @@ ${prompt}
377
420
  - 使用可用工具完成任务
378
421
  - 返回清晰的任务执行结果摘要
379
422
  - 适时调用 task_operation_create 记录进展`;
380
- const agentComponent = this.env?.getComponent?.("agent");
381
- if (!agentComponent) {
423
+ if (!agentComponent) {
424
+ throw new Error("AgentComponent not found");
425
+ }
426
+ const subAgentForRegister = subAgent ? { ...subAgent, allowedTools } : allowedTools ? {
427
+ id: subagentType,
428
+ name: subagentType,
429
+ mode: "subagent",
430
+ description: resolved?.description || "Custom agent",
431
+ allowedTools,
432
+ deniedTools
433
+ } : undefined;
434
+ ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgentForRegister, deniedTools);
435
+ return new Promise((resolve, reject) => {
436
+ const timer = setTimeout(() => {
437
+ reject(new Error(`Task execution timeout after ${timeoutMs}ms`));
438
+ }, timeoutMs);
439
+ signal?.addEventListener("abort", () => {
382
440
  clearTimeout(timer);
383
- reject(new Error("AgentComponent not found"));
384
- return;
385
- }
386
- ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools);
441
+ reject(new Error("Task execution stopped"));
442
+ });
387
443
  this.env.handle_query?.(fullPrompt, {
388
444
  sessionId,
389
445
  deniedTools: deniedTools.length > 0 ? deniedTools : undefined,
390
446
  agentType: subagentType
391
- }).then((result) => {
447
+ })?.then((result) => {
392
448
  clearTimeout(timer);
393
449
  resolve(result);
394
450
  }).catch((error) => {
@@ -450,7 +506,7 @@ function createDelegateTool(taskComponent) {
450
506
  description: `Launch a new sub-agent to handle complex, multistep tasks autonomously.
451
507
 
452
508
  Available agent types:
453
- ${getSubAgentToolDescription()}
509
+ ${listKnownSubagentDescriptions()}
454
510
 
455
511
  When using the delegate_task tool, you must specify a subagent_type parameter to select which agent type to use.
456
512
 
@@ -477,8 +533,9 @@ When using the delegate_task tool, you must specify a subagent_type parameter to
477
533
  const { description, prompt, subagent_type = "general", background = false, timeout, cleanup, task_id, reason } = params;
478
534
  const parentSessionId = ctx.session_id || "default";
479
535
  logger.info(`[delegate_task] Called: description=${description}, subagent_type=${subagent_type}, background=${background}, task_id=${task_id}`);
480
- const subAgent = getSubAgentSpec(subagent_type);
481
- if (!subAgent) {
536
+ const agentComponent = taskComponent.env?.getComponent?.("agent");
537
+ const registry = agentComponent?.getRegistry?.();
538
+ if (!isKnownSubagentType(subagent_type, registry)) {
482
539
  return {
483
540
  success: false,
484
541
  output: "",
@@ -558,9 +615,13 @@ async function handleSyncTask(taskComponent, parentSessionId, description, promp
558
615
  metadata: { execution_time_ms: Date.now() - startTime }
559
616
  };
560
617
  }
618
+ const agentComponent = taskComponent.env?.getComponent?.("agent");
619
+ const registry = agentComponent?.getRegistry?.();
620
+ const resolved = await resolveSubAgentConfig(subagentType, { registry });
561
621
  const subAgent = getSubAgentSpec(subagentType);
562
- let basePrompt = subAgent?.promptOverride || `You are a subagent. Complete this task: {task_description}`;
563
- const deniedTools = subAgent?.deniedTools || [];
622
+ let basePrompt = resolved?.basePrompt || subAgent?.promptOverride || `You are a subagent. Complete this task: {task_description}`;
623
+ const deniedTools = resolved?.deniedTools || subAgent?.deniedTools || [];
624
+ const allowedTools = resolved?.allowedTools || subAgent?.allowedTools;
564
625
  let fullPrompt = basePrompt.replace(/{task_description}/g, description || "N/A");
565
626
  fullPrompt += `
566
627
 
@@ -581,7 +642,6 @@ ${prompt}
581
642
  - 使用可用工具完成任务
582
643
  - 返回清晰的任务执行结果摘要
583
644
  - 适时调用 task_operation_create 记录进展`;
584
- const agentComponent = taskComponent.env?.getComponent?.("agent");
585
645
  if (!agentComponent) {
586
646
  return {
587
647
  success: false,
@@ -590,7 +650,15 @@ ${prompt}
590
650
  metadata: { execution_time_ms: Date.now() - startTime }
591
651
  };
592
652
  }
593
- ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools);
653
+ const subAgentForRegister = subAgent ? { ...subAgent, allowedTools } : allowedTools ? {
654
+ id: subagentType,
655
+ name: subagentType,
656
+ mode: "subagent",
657
+ description: resolved?.description || "Custom agent",
658
+ allowedTools,
659
+ deniedTools
660
+ } : undefined;
661
+ ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgentForRegister, deniedTools);
594
662
  const timeoutMs = timeout || DEFAULT_TIMEOUT;
595
663
  let result;
596
664
  try {
@@ -1,3 +1,6 @@
1
+ import {
2
+ getXDGPath
3
+ } from "./roy-agent-core-qxnbvgwe.js";
1
4
  import {
2
5
  envKeyToConfigKey,
3
6
  toEnvKey
@@ -236,6 +239,33 @@ roy-agent mcp list|tools|reload
236
239
  roy-agent config|cfg list|export|import
237
240
  \`\`\`
238
241
 
242
+ - \`roy-agent config list [component]\` - 查看组件配置 (tool/session/agent/prompt/all)
243
+ - \`roy-agent config export <component>\` - 导出组件配置
244
+ - \`roy-agent config import <component>\` - 导入组件配置
245
+
246
+ #### Agents Command
247
+
248
+ \`\`\`bash
249
+ roy-agent agents list|get|add|delete|config-dir
250
+ \`\`\`
251
+
252
+ - \`roy-agent agents list\` - 列出所有可用 agents
253
+ - \`roy-agent agents get <name>\` - 获取指定 agent 的详细信息和 resolved system prompt
254
+ - \`roy-agent agents add <name>\` - 添加 agent 配置(写入 YAML 文件)
255
+ - \`roy-agent agents delete <name>\` - 删除 agent 配置文件
256
+ - \`roy-agent agents config-dir\` - 显示 agent 配置目录路径
257
+
258
+ #### Prompt Command
259
+
260
+ \`\`\`bash
261
+ roy-agent prompt list|get|add|config-dir
262
+ \`\`\`
263
+
264
+ - \`roy-agent prompt list\` - 列出所有可用 prompts (built-in/directory/file/all)
265
+ - \`roy-agent prompt get <name>\` - 获取指定 prompt 的内容
266
+ - \`roy-agent prompt add <name>\` - 添加 prompt 并持久化到 ~/.local/share/roy-agent/prompts/
267
+ - \`roy-agent prompt config-dir\` - 显示 prompt 持久化目录路径
268
+
239
269
  #### Debug Command
240
270
 
241
271
  \`\`\`bash
@@ -557,16 +587,95 @@ function getBuiltInPrompt(name) {
557
587
  return builtInPrompts[name];
558
588
  }
559
589
 
590
+ // src/env/prompt/prompt-store.ts
591
+ import { mkdir, readFile, writeFile, unlink, readdir } from "fs/promises";
592
+ import { existsSync } from "fs";
593
+ import { join, dirname } from "path";
594
+ init_logger();
595
+ var logger = createLogger("prompt:store");
596
+
597
+ class PromptStore {
598
+ configDir;
599
+ constructor(options = {}) {
600
+ if (options.configDir && options.configDir.length > 0) {
601
+ this.configDir = options.configDir;
602
+ } else if (options.baseDir) {
603
+ this.configDir = join(options.baseDir, "prompts");
604
+ } else {
605
+ this.configDir = join(getXDGPath("data"), "prompts");
606
+ }
607
+ }
608
+ getConfigDir() {
609
+ return this.configDir;
610
+ }
611
+ configDirExists() {
612
+ return existsSync(this.configDir);
613
+ }
614
+ getPromptFilePath(name) {
615
+ return join(this.configDir, `${name}.md`);
616
+ }
617
+ async savePrompt(name, content) {
618
+ await this.ensureConfigDir();
619
+ const filePath = this.getPromptFilePath(name);
620
+ await mkdir(dirname(filePath), { recursive: true });
621
+ await writeFile(filePath, content, "utf-8");
622
+ logger.info(`[PromptStore] Saved prompt: ${name} -> ${filePath}`);
623
+ return filePath;
624
+ }
625
+ async deletePrompt(name) {
626
+ const filePath = this.getPromptFilePath(name);
627
+ if (!existsSync(filePath)) {
628
+ return false;
629
+ }
630
+ await unlink(filePath);
631
+ logger.info(`[PromptStore] Deleted prompt file: ${filePath}`);
632
+ return true;
633
+ }
634
+ async loadAll() {
635
+ if (!existsSync(this.configDir)) {
636
+ return [];
637
+ }
638
+ const prompts = [];
639
+ await this.collectPrompts(this.configDir, "", prompts);
640
+ return prompts;
641
+ }
642
+ async collectPrompts(directory, prefix, out) {
643
+ const entries = await readdir(directory, { withFileTypes: true });
644
+ for (const entry of entries) {
645
+ const fullPath = join(directory, entry.name);
646
+ if (entry.isDirectory()) {
647
+ const nextPrefix = prefix ? `${prefix}/${entry.name}` : entry.name;
648
+ await this.collectPrompts(fullPath, nextPrefix, out);
649
+ continue;
650
+ }
651
+ if (!entry.isFile() || !entry.name.endsWith(".md")) {
652
+ continue;
653
+ }
654
+ const baseName = entry.name.slice(0, -3);
655
+ const name = prefix ? `${prefix}/${baseName}` : baseName;
656
+ const content = (await readFile(fullPath, "utf-8")).trim();
657
+ out.push({ name, content, filePath: fullPath });
658
+ }
659
+ }
660
+ async ensureConfigDir() {
661
+ if (!existsSync(this.configDir)) {
662
+ await mkdir(this.configDir, { recursive: true });
663
+ logger.debug(`[PromptStore] Created config directory: ${this.configDir}`);
664
+ }
665
+ }
666
+ }
667
+
560
668
  // src/env/prompt/prompt-component.ts
561
669
  init_logger();
562
- import { readFile, readdir } from "fs/promises";
563
- import { join, basename, extname } from "path";
670
+ import { readFile as readFile2, readdir as readdir2 } from "fs/promises";
671
+ import { join as join2, basename, extname } from "path";
564
672
 
565
673
  // src/env/prompt/prompt-config-registration.ts
566
674
  var PROMPT_DEFAULTS = {
567
675
  "prompt.defaultName": "default",
568
676
  "prompt.variablePrefix": "{{",
569
- "prompt.variableSuffix": "}}"
677
+ "prompt.variableSuffix": "}}",
678
+ "prompt.configDir": ""
570
679
  };
571
680
  var PROMPT_CONFIG_REGISTRATION = {
572
681
  name: "prompt",
@@ -575,6 +684,7 @@ var PROMPT_CONFIG_REGISTRATION = {
575
684
  ],
576
685
  keys: [
577
686
  { key: "prompt.promptPaths", sources: ["env", "file"] },
687
+ { key: "prompt.configDir", sources: ["env", "file"] },
578
688
  { key: "prompt.defaultName", sources: ["env", "file"] },
579
689
  { key: "prompt.variablePrefix", sources: ["env", "file"] },
580
690
  { key: "prompt.variableSuffix", sources: ["env", "file"] }
@@ -582,7 +692,7 @@ var PROMPT_CONFIG_REGISTRATION = {
582
692
  };
583
693
 
584
694
  // src/env/prompt/prompt-component.ts
585
- var logger = createLogger("prompt");
695
+ var logger2 = createLogger("prompt");
586
696
 
587
697
  class PromptComponent extends BaseComponent {
588
698
  name = "prompt";
@@ -591,6 +701,7 @@ class PromptComponent extends BaseComponent {
591
701
  config;
592
702
  configComponent;
593
703
  renderer;
704
+ promptStore;
594
705
  configWatcher;
595
706
  constructor() {
596
707
  super();
@@ -604,9 +715,10 @@ class PromptComponent extends BaseComponent {
604
715
  this.configComponent = options.configComponent;
605
716
  await this.registerConfig(options);
606
717
  this.initRenderer();
718
+ this.initPromptStore();
607
719
  await this.loadPrompts();
608
720
  this.setStatus("running");
609
- logger.info(`[PromptComponent] Initialized with ${this.prompts.size} prompts`);
721
+ logger2.info(`[PromptComponent] Initialized with ${this.prompts.size} prompts`);
610
722
  }
611
723
  async registerConfig(options) {
612
724
  const configComponent = options.configComponent;
@@ -700,7 +812,7 @@ class PromptComponent extends BaseComponent {
700
812
  const value = event.newValue;
701
813
  if (value === undefined)
702
814
  return;
703
- logger.debug(`[PromptComponent] Config updated: ${key} = ${JSON.stringify(value)}`);
815
+ logger2.debug(`[PromptComponent] Config updated: ${key} = ${JSON.stringify(value)}`);
704
816
  switch (key) {
705
817
  case "prompt.defaultName":
706
818
  if (this.config)
@@ -741,18 +853,20 @@ class PromptComponent extends BaseComponent {
741
853
  suffix: config.variableSuffix,
742
854
  strict: config.strictMode,
743
855
  onMissingVariable: (name) => {
744
- logger.warn(`Undefined variable: ${name}`);
856
+ logger2.warn(`Undefined variable: ${name}`);
745
857
  return `{{${name}}}`;
746
858
  }
747
859
  });
748
860
  }
749
861
  async onStart() {
750
- logger.info("[PromptComponent] Started");
862
+ logger2.info("[PromptComponent] Started");
751
863
  }
752
864
  async onStop() {
865
+ this.configWatcher?.();
866
+ this.configWatcher = undefined;
753
867
  this.prompts.clear();
754
868
  this.setStatus("stopped");
755
- logger.info("[PromptComponent] Stopped");
869
+ logger2.info("[PromptComponent] Stopped");
756
870
  }
757
871
  getPromptConfig(key, defaultValue) {
758
872
  if (this.config && key in this.config) {
@@ -770,11 +884,11 @@ class PromptComponent extends BaseComponent {
770
884
  };
771
885
  const existing = this.prompts.get(name);
772
886
  if (existing && !existing.overridable) {
773
- logger.debug(`[PromptComponent] Skip override for non-overridable prompt: ${name}`);
887
+ logger2.debug(`[PromptComponent] Skip override for non-overridable prompt: ${name}`);
774
888
  return;
775
889
  }
776
890
  this.prompts.set(name, entry);
777
- logger.debug(`[PromptComponent] Added prompt: ${name} (${source})`);
891
+ logger2.debug(`[PromptComponent] Added prompt: ${name} (${source})`);
778
892
  }
779
893
  get(name) {
780
894
  return this.prompts.get(name)?.content;
@@ -791,6 +905,34 @@ class PromptComponent extends BaseComponent {
791
905
  list() {
792
906
  return Array.from(this.prompts.keys());
793
907
  }
908
+ listEntries() {
909
+ return Array.from(this.prompts.values());
910
+ }
911
+ getPromptStore() {
912
+ if (!this.promptStore) {
913
+ this.initPromptStore();
914
+ }
915
+ return this.promptStore;
916
+ }
917
+ getPromptConfigDir() {
918
+ return this.getPromptStore().getConfigDir();
919
+ }
920
+ async savePrompt(name, content) {
921
+ const filePath = await this.getPromptStore().savePrompt(name, content.trim());
922
+ this.add(name, content.trim(), "file");
923
+ const entry = this.prompts.get(name);
924
+ if (entry) {
925
+ entry.filePath = filePath;
926
+ }
927
+ return filePath;
928
+ }
929
+ async deletePromptFile(name) {
930
+ const deleted = await this.getPromptStore().deletePrompt(name);
931
+ if (deleted) {
932
+ this.delete(name);
933
+ }
934
+ return deleted;
935
+ }
794
936
  size() {
795
937
  return this.prompts.size;
796
938
  }
@@ -799,7 +941,7 @@ class PromptComponent extends BaseComponent {
799
941
  const targetName = this.has(name) ? name : defaultName;
800
942
  const entry = this.prompts.get(targetName);
801
943
  if (!entry) {
802
- logger.warn(`[PromptComponent] Prompt not found: ${name}, using fallback`);
944
+ logger2.warn(`[PromptComponent] Prompt not found: ${name}, using fallback`);
803
945
  return "You are a helpful assistant.";
804
946
  }
805
947
  return this.render(entry.content, variables, { name: targetName });
@@ -819,10 +961,31 @@ class PromptComponent extends BaseComponent {
819
961
  extractVariables(content) {
820
962
  return this.renderer.extractVariables(content);
821
963
  }
964
+ initPromptStore() {
965
+ const customDir = this.configComponent?.get?.("prompt.configDir");
966
+ this.promptStore = new PromptStore({
967
+ configDir: typeof customDir === "string" && customDir.length > 0 ? customDir : undefined
968
+ });
969
+ }
822
970
  async loadPrompts() {
823
971
  await this.loadBuiltInPrompts();
972
+ await this.loadUserPrompts();
824
973
  await this.loadExternalPrompts();
825
974
  }
975
+ async loadUserPrompts() {
976
+ const store = this.getPromptStore();
977
+ const prompts = await store.loadAll();
978
+ for (const prompt of prompts) {
979
+ this.add(prompt.name, prompt.content, "file");
980
+ const entry = this.prompts.get(prompt.name);
981
+ if (entry) {
982
+ entry.filePath = prompt.filePath;
983
+ }
984
+ }
985
+ if (prompts.length > 0) {
986
+ logger2.info(`[PromptComponent] Loaded ${prompts.length} prompts from ${store.getConfigDir()}`);
987
+ }
988
+ }
826
989
  async loadBuiltInPrompts() {
827
990
  for (const [name, content] of Object.entries(builtInPrompts)) {
828
991
  if (content) {
@@ -833,10 +996,10 @@ class PromptComponent extends BaseComponent {
833
996
  overridable: false,
834
997
  loadedAt: Date.now()
835
998
  });
836
- logger.debug(`[PromptComponent] Loaded built-in prompt: ${name}`);
999
+ logger2.debug(`[PromptComponent] Loaded built-in prompt: ${name}`);
837
1000
  }
838
1001
  }
839
- logger.info(`[PromptComponent] Loaded ${this.prompts.size} built-in prompts`);
1002
+ logger2.info(`[PromptComponent] Loaded ${this.prompts.size} built-in prompts`);
840
1003
  }
841
1004
  async loadExternalPrompts() {
842
1005
  const promptPaths = this.getPromptConfig("promptPaths", []);
@@ -848,22 +1011,22 @@ class PromptComponent extends BaseComponent {
848
1011
  await this.loadFromDirectory(pathConfig.path, pathConfig.extension || ".md", pathConfig.recursive !== false);
849
1012
  }
850
1013
  } catch (error) {
851
- logger.error(`[PromptComponent] Failed to load from ${pathConfig.path}:`, error);
1014
+ logger2.error(`[PromptComponent] Failed to load from ${pathConfig.path}:`, error);
852
1015
  }
853
1016
  }
854
1017
  }
855
1018
  async loadFromFile(filePath, name) {
856
1019
  try {
857
- const content = await readFile(filePath, "utf-8");
1020
+ const content = await readFile2(filePath, "utf-8");
858
1021
  const promptName = name || basename(filePath, extname(filePath));
859
1022
  this.add(promptName, content.trim(), "file");
860
1023
  const entry = this.prompts.get(promptName);
861
1024
  if (entry)
862
1025
  entry.filePath = filePath;
863
- logger.debug(`[PromptComponent] Loaded prompt from file: ${filePath}`);
1026
+ logger2.debug(`[PromptComponent] Loaded prompt from file: ${filePath}`);
864
1027
  return true;
865
1028
  } catch (error) {
866
- logger.error(`[PromptComponent] Failed to load file ${filePath}:`, error);
1029
+ logger2.error(`[PromptComponent] Failed to load file ${filePath}:`, error);
867
1030
  return false;
868
1031
  }
869
1032
  }
@@ -874,25 +1037,25 @@ class PromptComponent extends BaseComponent {
874
1037
  for (const filePath of files) {
875
1038
  const relativePath = filePath.replace(directory + "/", "");
876
1039
  const promptName = relativePath.replace(/\\/g, "/").replace(new RegExp(escapeRegex2(extension) + "$"), "").replace(/\//g, "-");
877
- const content = await readFile(filePath, "utf-8");
1040
+ const content = await readFile2(filePath, "utf-8");
878
1041
  this.add(promptName, content.trim(), "directory");
879
1042
  const entry = this.prompts.get(promptName);
880
1043
  if (entry)
881
1044
  entry.filePath = filePath;
882
1045
  loaded++;
883
1046
  }
884
- logger.info(`[PromptComponent] Loaded ${loaded} prompts from directory: ${directory}`);
1047
+ logger2.info(`[PromptComponent] Loaded ${loaded} prompts from directory: ${directory}`);
885
1048
  } catch (error) {
886
- logger.error(`[PromptComponent] Failed to load directory ${directory}:`, error);
1049
+ logger2.error(`[PromptComponent] Failed to load directory ${directory}:`, error);
887
1050
  }
888
1051
  return loaded;
889
1052
  }
890
1053
  async findFiles(dir, extension, recursive) {
891
1054
  const files = [];
892
1055
  try {
893
- const entries = await readdir(dir, { withFileTypes: true });
1056
+ const entries = await readdir2(dir, { withFileTypes: true });
894
1057
  for (const entry of entries) {
895
- const fullPath = join(dir, entry.name);
1058
+ const fullPath = join2(dir, entry.name);
896
1059
  if (entry.isDirectory() && recursive) {
897
1060
  const subFiles = await this.findFiles(fullPath, extension, true);
898
1061
  files.push(...subFiles);
@@ -901,7 +1064,7 @@ class PromptComponent extends BaseComponent {
901
1064
  }
902
1065
  }
903
1066
  } catch (error) {
904
- logger.warn(`[PromptComponent] Cannot read directory ${dir}:`, error);
1067
+ logger2.warn(`[PromptComponent] Cannot read directory ${dir}:`, error);
905
1068
  }
906
1069
  return files;
907
1070
  }
@@ -919,4 +1082,4 @@ function escapeRegex2(str) {
919
1082
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
920
1083
  }
921
1084
 
922
- export { PromptPathSchema, PromptConfigSchema, PromptRenderer, getBuiltInPromptNames, getBuiltInPrompt, PromptComponent };
1085
+ export { PromptPathSchema, PromptConfigSchema, PromptRenderer, getBuiltInPromptNames, getBuiltInPrompt, PromptStore, PromptComponent };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-core",
3
- "version": "1.5.41",
3
+ "version": "1.5.42",
4
4
  "type": "module",
5
5
  "description": "Core SDK for roy-agent - Environment, Components, Tools, Sessions, Tasks",
6
6
  "main": "./dist/index.js",