@ai-setting/roy-agent-core 1.5.88 → 1.5.90

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.
Files changed (48) hide show
  1. package/dist/env/agent/index.js +8 -8
  2. package/dist/env/event-source/index.js +12 -4
  3. package/dist/env/index.js +20 -15
  4. package/dist/env/llm/index.js +4 -2
  5. package/dist/env/prompt/index.js +2 -1
  6. package/dist/env/session/index.js +3 -4
  7. package/dist/env/session/storage/index.js +2 -2
  8. package/dist/env/task/delegate/index.js +3 -2
  9. package/dist/env/task/index.js +4 -3
  10. package/dist/env/task/plugins/index.js +7 -4
  11. package/dist/env/tool/built-in/index.js +2 -1
  12. package/dist/env/tool/index.js +11 -8
  13. package/dist/env/workflow/engine/index.js +5 -3
  14. package/dist/env/workflow/index.js +6 -4
  15. package/dist/env/workflow/nodes/index.js +1 -1
  16. package/dist/env/workflow/tools/index.js +7 -1
  17. package/dist/env/workflow/utils/index.js +5 -0
  18. package/dist/index.js +144 -32
  19. package/dist/shared/@ai-setting/{roy-agent-core-r0m0at3x.js → roy-agent-core-0r4ndyn9.js} +119 -7
  20. package/dist/shared/@ai-setting/{roy-agent-core-jymz9fzp.js → roy-agent-core-2c8eraxq.js} +126 -41
  21. package/dist/shared/@ai-setting/{roy-agent-core-0y64qaac.js → roy-agent-core-32m0nb9j.js} +119 -30
  22. package/dist/shared/@ai-setting/roy-agent-core-4yq23m5g.js +421 -0
  23. package/dist/shared/@ai-setting/{roy-agent-core-h2d1s8yd.js → roy-agent-core-5ykms33a.js} +1 -1
  24. package/dist/shared/@ai-setting/{roy-agent-core-mmkyydw7.js → roy-agent-core-83d035pp.js} +91 -579
  25. package/dist/shared/@ai-setting/roy-agent-core-8wd3qwx5.js +35 -0
  26. package/dist/shared/@ai-setting/{roy-agent-core-yx0vw1aw.js → roy-agent-core-8zjntsbb.js} +102 -32
  27. package/dist/shared/@ai-setting/{roy-agent-core-29fh9mxg.js → roy-agent-core-bwjpte58.js} +1 -2
  28. package/dist/shared/@ai-setting/{roy-agent-core-vneyghpg.js → roy-agent-core-ddq5hcp5.js} +1 -1
  29. package/dist/shared/@ai-setting/{roy-agent-core-qhhxx2x2.js → roy-agent-core-ds5f75pg.js} +2 -1
  30. package/dist/shared/@ai-setting/{roy-agent-core-4cdtdxqx.js → roy-agent-core-ewr1nw7t.js} +1 -1
  31. package/dist/shared/@ai-setting/roy-agent-core-hvdfgvfz.js +114 -0
  32. package/dist/shared/@ai-setting/{roy-agent-core-3arrpf7n.js → roy-agent-core-hxsbegfc.js} +229 -9
  33. package/dist/shared/@ai-setting/{roy-agent-core-9y09xfav.js → roy-agent-core-j0107ww1.js} +6 -418
  34. package/dist/shared/@ai-setting/{roy-agent-core-6mk0m4t3.js → roy-agent-core-m683wd1n.js} +283 -15
  35. package/dist/shared/@ai-setting/{roy-agent-core-bgw4dq11.js → roy-agent-core-mw4ty0ba.js} +44 -5
  36. package/dist/shared/@ai-setting/{roy-agent-core-7z4xtrmw.js → roy-agent-core-nqzt9ne4.js} +53 -0
  37. package/dist/shared/@ai-setting/roy-agent-core-pt7as39r.js +0 -0
  38. package/dist/shared/@ai-setting/{roy-agent-core-6n7xwv4v.js → roy-agent-core-rkz8r2sx.js} +5 -3
  39. package/dist/shared/@ai-setting/{roy-agent-core-c1j7ev4e.js → roy-agent-core-txwf64pd.js} +70 -0
  40. package/dist/shared/@ai-setting/{roy-agent-core-7fdzfsm6.js → roy-agent-core-w0kb72ve.js} +42 -213
  41. package/dist/shared/@ai-setting/roy-agent-core-w6bmrgap.js +581 -0
  42. package/dist/shared/@ai-setting/{roy-agent-core-qhjb153z.js → roy-agent-core-xnxyzaw4.js} +27 -4
  43. package/dist/shared/@ai-setting/roy-agent-core-yanpq5gb.js +116 -0
  44. package/dist/shared/@ai-setting/{roy-agent-core-hc20420t.js → roy-agent-core-z240ts1r.js} +27 -3
  45. package/dist/shared/@ai-setting/{roy-agent-core-q7sqeax6.js → roy-agent-core-zky9jse4.js} +163 -3
  46. package/package.json +1 -1
  47. package/dist/shared/@ai-setting/roy-agent-core-x3gtyqax.js +0 -378
  48. /package/dist/shared/@ai-setting/{roy-agent-core-4f3976cd.js → roy-agent-core-k5hxvaf0.js} +0 -0
@@ -1,84 +1,3 @@
1
- import {
2
- getXDGPath
3
- } from "./roy-agent-core-qxnbvgwe.js";
4
- import {
5
- envKeyToConfigKey,
6
- toEnvKey
7
- } from "./roy-agent-core-qxhq8ven.js";
8
- import {
9
- BaseComponent
10
- } from "./roy-agent-core-rgckng3p.js";
11
- import {
12
- createHook
13
- } from "./roy-agent-core-b8r4tfqq.js";
14
- import {
15
- globalHookManager,
16
- init_global_hook_manager
17
- } from "./roy-agent-core-7tp56w6n.js";
18
- import {
19
- createLogger,
20
- init_logger
21
- } from "./roy-agent-core-shme7set.js";
22
-
23
- // src/env/prompt/types.ts
24
- import { z } from "zod";
25
- var PromptPathSchema = z.object({
26
- type: z.enum(["file", "directory"]),
27
- path: z.string(),
28
- name: z.string().optional(),
29
- recursive: z.boolean().default(true),
30
- extension: z.string().default(".md")
31
- });
32
- var PromptConfigSchema = z.object({
33
- promptPaths: z.array(PromptPathSchema).default([]),
34
- defaultName: z.string().default("default"),
35
- variablePrefix: z.string().default("{{"),
36
- variableSuffix: z.string().default("}}"),
37
- strictMode: z.boolean().default(false)
38
- });
39
- var PromptHookPoints = {
40
- BEFORE_RENDER: "prompt.before-render",
41
- AFTER_RENDER: "prompt.after-render"
42
- };
43
-
44
- // src/env/prompt/renderer.ts
45
- class PromptRenderer {
46
- options;
47
- constructor(options) {
48
- this.options = options;
49
- }
50
- render(template, variables) {
51
- const { prefix, suffix, strict, onMissingVariable } = this.options;
52
- const regex = new RegExp(`${escapeRegex(prefix)}(.*?)${escapeRegex(suffix)}`, "g");
53
- return template.replace(regex, (match, varName) => {
54
- const key = varName.trim();
55
- if (key in variables) {
56
- return variables[key];
57
- }
58
- if (strict) {
59
- throw new Error(`Missing required variable: ${key}`);
60
- }
61
- if (onMissingVariable) {
62
- return onMissingVariable(key);
63
- }
64
- return match;
65
- });
66
- }
67
- extractVariables(template) {
68
- const { prefix, suffix } = this.options;
69
- const regex = new RegExp(`${escapeRegex(prefix)}(.*?)${escapeRegex(suffix)}`, "g");
70
- const vars = [];
71
- let match;
72
- while ((match = regex.exec(template)) !== null) {
73
- vars.push(match[1].trim());
74
- }
75
- return [...new Set(vars)];
76
- }
77
- }
78
- function escapeRegex(str) {
79
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
80
- }
81
-
82
1
  // src/env/prompt/prompts-index.ts
83
2
  var builtInPrompts = {
84
3
  default: `你是 Roy 接待智能体(Receptionist Agent)—— Roy 系统的智能入口。
@@ -1099,8 +1018,97 @@ workflow_run(workflow_name="strict-task-agent", input={"task_description": "修
1099
1018
  - ❌ 不要输出普通文本或解释
1100
1019
  - ❌ 不要输出 \`\`\`json 代码块
1101
1020
  - ❌ 不要调用其他工具
1102
- - ❌ 不要问澄清问题`
1021
+ - ❌ 不要问澄清问题`,
1022
+ "workflow-extract": `# Workflow Extract Agent
1023
+
1024
+ 你是 Workflow 提取专家。**唯一职责**:从 task 的对话历史中分析需求,生成可复用的 Workflow YAML,并通过工作流工具迭代式构建并验证。
1025
+
1026
+ ## 工具
1027
+
1028
+ 你有 4 个工具可用:
1029
+
1030
+ | 工具 | 用途 |
1031
+ |------|------|
1032
+ | \`workflow_list\` | 浏览已有 workflow(学习节点结构、命名约定) |
1033
+ | \`workflow_get\` | 获取指定 workflow 详情(查看完整 YAML) |
1034
+ | \`workflow_validate\` | 验证 YAML 结构(依赖、节点 ID、循环检测) |
1035
+ | \`workflow_add\` | 添加新 workflow(需要 1-3 个 tags) |
1036
+
1037
+ ## 迭代式构建流程
1038
+
1039
+ **重要**:必须按以下流程调用工具,**不能跳过 validate**。
1040
+
1041
+ 1. **学习** —— 调用 \`workflow_list\` 和 \`workflow_get <name>\` 查看已有 workflow
1042
+ 2. **设计** —— 根据需求生成 YAML 草稿(内存中)
1043
+ 3. **验证** —— 调用 \`workflow_validate\` 验证结构
1044
+ 4. **修正** —— 验证失败 → 修正 YAML → 重新验证(直到通过)
1045
+ 5. **添加** —— 验证通过后调用 \`workflow_add\` 提交
1046
+
1047
+ ## 构建原则
1048
+
1049
+ 1. **优先具象节点**:优先使用特定工具节点(如 tool/skill/agent)
1050
+ 2. **避免条件分支**:不提取循环和条件判断,保持线性流程
1051
+ 3. **至少 2 个节点**:单节点 workflow 无意义
1052
+ 4. **必须设置 tags**:tags 是 workflow 分类的依据(1-3 个)
1053
+ 5. **节点 ID 唯一**:每个节点必须有唯一 id
1054
+
1055
+ ## 验证失败的处理
1056
+
1057
+ 如果 \`workflow_validate\` 返回 invalid:
1058
+
1059
+ 1. 仔细阅读 errors 列表
1060
+ 2. 修正 YAML(节点 ID 重复、依赖缺失、循环等问题)
1061
+ 3. 重新调用 \`workflow_validate\` 验证
1062
+ 4. 最多迭代 8 次,超过则停止并报告失败原因
1063
+
1064
+ ## YAML 结构参考
1065
+
1066
+ \`\`\`yaml
1067
+ name: <workflow-name> # 必填,kebab-case
1068
+ version: "1.0" # 选填,默认 1.0
1069
+ description: <一句话描述>
1070
+ tags: [<至少1个,最多3个>] # 必填
1071
+ nodes:
1072
+ - id: node-1 # 必填,唯一
1073
+ type: tool|skill|agent # 必填
1074
+ name: <节点名称>
1075
+ config: {} # 根据类型配置
1076
+ depends_on: [] # 依赖列表
1077
+ outputs: [] # 输出定义(可空)
1078
+ \`\`\`
1079
+
1080
+ ## 禁止
1081
+
1082
+ - ❌ 不要跳过 \`workflow_validate\` 直接 \`workflow_add\`
1083
+ - ❌ 不要生成少于 2 个节点的 workflow
1084
+ - ❌ 不要生成条件节点(if/else/switch)或循环节点(while/for)
1085
+ - ❌ 不要使用 bash 或其他工具(严格使用 4 个 workflow 工具)`,
1086
+ compact: `# Session Checkpoint Generator
1087
+
1088
+ 你是专业的会话 checkpoint 生成器。阅读对话历史,提取结构化 checkpoint 信息。
1089
+
1090
+ 使用 \`workflow_submit_output\` 工具提交结果,包含以下字段:
1091
+ - **title**: 简洁的 checkpoint 标题(不超过 30 字符)
1092
+ - **processKeyPoints**: 关键发现或决策列表
1093
+ - **currentState**: 当前进度和状态描述
1094
+ - **nextSteps**: 后续行动项列表
1095
+ - **userIntents**: 用户核心意图列表(2-5 个)
1096
+
1097
+ ## 提取指南
1098
+
1099
+ - **processKeyPoints**:聚焦对后续推进有意义的里程碑
1100
+ - **currentState**:让后续接手者能快速了解当前局面
1101
+ - **nextSteps**:明确的后续行动项
1102
+ - **userIntents**:从整个对话中提取,优先最重要最紧急的
1103
+ - 使用 \`workflow_submit_output\` 工具提交结果
1104
+ - 用户输入中的场景提示(scenario hint)指明了重点关注方向,请严格遵守。`,
1105
+ "compact-hint": `# Compact Hint Generator
1106
+
1107
+ 你是会话压缩指导提示生成器。分析对话历史,生成"压缩指导提示"告诉 checkpoint 生成器在压缩时重点提取什么。
1108
+
1109
+ 使用 \`workflow_submit_output\` 工具提交结果,包含 guidance_prompt 字段。`
1103
1110
  };
1111
+ var WORKFLOW_EXTRACT_PROMPT = builtInPrompts["workflow-extract"];
1104
1112
  function getBuiltInPromptNames() {
1105
1113
  return Object.keys(builtInPrompts);
1106
1114
  }
@@ -1108,500 +1116,4 @@ function getBuiltInPrompt(name) {
1108
1116
  return builtInPrompts[name];
1109
1117
  }
1110
1118
 
1111
- // src/env/prompt/prompt-store.ts
1112
- import { mkdir, readFile, writeFile, unlink, readdir } from "fs/promises";
1113
- import { existsSync } from "fs";
1114
- import { join, dirname } from "path";
1115
- init_logger();
1116
- var logger = createLogger("prompt:store");
1117
-
1118
- class PromptStore {
1119
- configDir;
1120
- constructor(options = {}) {
1121
- if (options.configDir && options.configDir.length > 0) {
1122
- this.configDir = options.configDir;
1123
- } else if (options.baseDir) {
1124
- this.configDir = join(options.baseDir, "prompts");
1125
- } else {
1126
- this.configDir = join(getXDGPath("data"), "prompts");
1127
- }
1128
- }
1129
- getConfigDir() {
1130
- return this.configDir;
1131
- }
1132
- configDirExists() {
1133
- return existsSync(this.configDir);
1134
- }
1135
- getPromptFilePath(name) {
1136
- return join(this.configDir, `${name}.md`);
1137
- }
1138
- async savePrompt(name, content) {
1139
- await this.ensureConfigDir();
1140
- const filePath = this.getPromptFilePath(name);
1141
- await mkdir(dirname(filePath), { recursive: true });
1142
- await writeFile(filePath, content, "utf-8");
1143
- logger.info(`[PromptStore] Saved prompt: ${name} -> ${filePath}`);
1144
- return filePath;
1145
- }
1146
- async deletePrompt(name) {
1147
- const filePath = this.getPromptFilePath(name);
1148
- if (!existsSync(filePath)) {
1149
- return false;
1150
- }
1151
- await unlink(filePath);
1152
- logger.info(`[PromptStore] Deleted prompt file: ${filePath}`);
1153
- return true;
1154
- }
1155
- async loadAll() {
1156
- if (!existsSync(this.configDir)) {
1157
- return [];
1158
- }
1159
- const prompts = [];
1160
- await this.collectPrompts(this.configDir, "", prompts);
1161
- return prompts;
1162
- }
1163
- async collectPrompts(directory, prefix, out) {
1164
- const entries = await readdir(directory, { withFileTypes: true });
1165
- for (const entry of entries) {
1166
- const fullPath = join(directory, entry.name);
1167
- if (entry.isDirectory()) {
1168
- const nextPrefix = prefix ? `${prefix}/${entry.name}` : entry.name;
1169
- await this.collectPrompts(fullPath, nextPrefix, out);
1170
- continue;
1171
- }
1172
- if (!entry.isFile() || !entry.name.endsWith(".md")) {
1173
- continue;
1174
- }
1175
- const baseName = entry.name.slice(0, -3);
1176
- const name = prefix ? `${prefix}/${baseName}` : baseName;
1177
- const content = (await readFile(fullPath, "utf-8")).trim();
1178
- out.push({ name, content, filePath: fullPath });
1179
- }
1180
- }
1181
- async ensureConfigDir() {
1182
- if (!existsSync(this.configDir)) {
1183
- await mkdir(this.configDir, { recursive: true });
1184
- logger.debug(`[PromptStore] Created config directory: ${this.configDir}`);
1185
- }
1186
- }
1187
- }
1188
-
1189
- // src/env/prompt/prompt-component.ts
1190
- init_logger();
1191
- import { readFile as readFile2, readdir as readdir2 } from "fs/promises";
1192
- import { join as join2, basename, extname } from "path";
1193
-
1194
- // src/env/prompt/prompt-config-registration.ts
1195
- var PROMPT_DEFAULTS = {
1196
- "prompt.defaultName": "default",
1197
- "prompt.variablePrefix": "{{",
1198
- "prompt.variableSuffix": "}}",
1199
- "prompt.configDir": ""
1200
- };
1201
- var PROMPT_CONFIG_REGISTRATION = {
1202
- name: "prompt",
1203
- sources: [
1204
- { type: "env", envPrefix: "PROMPT", priority: 20, watch: false }
1205
- ],
1206
- keys: [
1207
- { key: "prompt.promptPaths", sources: ["env", "file"] },
1208
- { key: "prompt.configDir", sources: ["env", "file"] },
1209
- { key: "prompt.defaultName", sources: ["env", "file"] },
1210
- { key: "prompt.variablePrefix", sources: ["env", "file"] },
1211
- { key: "prompt.variableSuffix", sources: ["env", "file"] }
1212
- ]
1213
- };
1214
-
1215
- // src/env/prompt/prompt-component.ts
1216
- init_global_hook_manager();
1217
- var logger2 = createLogger("prompt");
1218
-
1219
- class PromptComponent extends BaseComponent {
1220
- name = "prompt";
1221
- version = "1.0.0";
1222
- prompts = new Map;
1223
- config;
1224
- configComponent;
1225
- renderer;
1226
- promptStore;
1227
- configWatcher;
1228
- constructor() {
1229
- super();
1230
- }
1231
- async init(config) {
1232
- await super.init(config);
1233
- const options = config.options;
1234
- if (!options?.configComponent) {
1235
- throw new Error("ConfigComponent is required for PromptComponent initialization");
1236
- }
1237
- this.configComponent = options.configComponent;
1238
- await this.registerConfig(options);
1239
- this.initRenderer();
1240
- this.initPromptStore();
1241
- await this.loadPrompts();
1242
- this.setStatus("running");
1243
- logger2.info(`[PromptComponent] Initialized with ${this.prompts.size} prompts`);
1244
- }
1245
- async registerConfig(options) {
1246
- const configComponent = options.configComponent;
1247
- if (!configComponent)
1248
- return;
1249
- const { config, defaultName, promptPaths, variablePrefix, variableSuffix } = options;
1250
- configComponent.registerComponent(PROMPT_CONFIG_REGISTRATION);
1251
- await configComponent.load("prompt");
1252
- const prefix = "PROMPT";
1253
- const promptKeys = [
1254
- "prompt.defaultName",
1255
- "prompt.promptPaths",
1256
- "prompt.variablePrefix",
1257
- "prompt.variableSuffix",
1258
- "prompt.strictMode"
1259
- ];
1260
- for (const key of promptKeys) {
1261
- const envKey = toEnvKey(key, prefix);
1262
- const value = process.env[envKey];
1263
- if (value !== undefined) {
1264
- await configComponent.set(key, value);
1265
- }
1266
- }
1267
- const loadedKeys = new Set(promptKeys);
1268
- for (const envKey of Object.keys(process.env)) {
1269
- const configKey = envKeyToConfigKey(envKey, prefix, "prompt");
1270
- if (!configKey)
1271
- continue;
1272
- if (loadedKeys.has(configKey))
1273
- continue;
1274
- loadedKeys.add(configKey);
1275
- const value = process.env[envKey];
1276
- if (value !== undefined) {
1277
- await configComponent.set(configKey, value);
1278
- }
1279
- }
1280
- for (const [key, value] of Object.entries(PROMPT_DEFAULTS)) {
1281
- if (configComponent.get(key) === undefined) {
1282
- await configComponent.set(key, value);
1283
- }
1284
- }
1285
- if (config) {
1286
- const flatConfig = this.flattenConfig(config);
1287
- for (const [key, value] of Object.entries(flatConfig)) {
1288
- await configComponent.set(key, value);
1289
- }
1290
- }
1291
- if (defaultName !== undefined) {
1292
- await configComponent.set("prompt.defaultName", defaultName);
1293
- }
1294
- if (promptPaths !== undefined) {
1295
- await configComponent.set("prompt.promptPaths", promptPaths);
1296
- }
1297
- if (variablePrefix !== undefined) {
1298
- await configComponent.set("prompt.variablePrefix", variablePrefix);
1299
- }
1300
- if (variableSuffix !== undefined) {
1301
- await configComponent.set("prompt.variableSuffix", variableSuffix);
1302
- }
1303
- this.registerConfigWatcher(configComponent);
1304
- this.config = {
1305
- defaultName: configComponent.get("prompt.defaultName") || "default",
1306
- promptPaths: configComponent.get("prompt.promptPaths") || [],
1307
- variablePrefix: configComponent.get("prompt.variablePrefix") || "{{",
1308
- variableSuffix: configComponent.get("prompt.variableSuffix") || "}}",
1309
- strictMode: configComponent.get("prompt.strictMode") || false
1310
- };
1311
- }
1312
- flattenConfig(obj, prefix = "prompt") {
1313
- const result = {};
1314
- for (const [key, value] of Object.entries(obj)) {
1315
- const fullKey = `${prefix}.${key}`;
1316
- if (value && typeof value === "object" && !Array.isArray(value)) {
1317
- Object.assign(result, this.flattenConfig(value, fullKey));
1318
- } else {
1319
- result[fullKey] = value;
1320
- }
1321
- }
1322
- return result;
1323
- }
1324
- registerConfigWatcher(configComponent) {
1325
- if (typeof configComponent.watch !== "function") {
1326
- return;
1327
- }
1328
- this.configWatcher = configComponent.watch("prompt.*", (event) => {
1329
- this.onConfigChange(event);
1330
- });
1331
- }
1332
- onConfigChange(event) {
1333
- const key = event.key;
1334
- const value = event.newValue;
1335
- if (value === undefined)
1336
- return;
1337
- logger2.debug(`[PromptComponent] Config updated: ${key} = ${JSON.stringify(value)}`);
1338
- switch (key) {
1339
- case "prompt.defaultName":
1340
- if (this.config)
1341
- this.config.defaultName = value;
1342
- break;
1343
- case "prompt.promptPaths":
1344
- if (this.config)
1345
- this.config.promptPaths = value;
1346
- break;
1347
- case "prompt.variablePrefix":
1348
- if (this.config) {
1349
- this.config.variablePrefix = value;
1350
- this.initRenderer();
1351
- }
1352
- break;
1353
- case "prompt.variableSuffix":
1354
- if (this.config) {
1355
- this.config.variableSuffix = value;
1356
- this.initRenderer();
1357
- }
1358
- break;
1359
- case "prompt.strictMode":
1360
- if (this.config)
1361
- this.config.strictMode = value;
1362
- break;
1363
- }
1364
- }
1365
- initRenderer() {
1366
- const config = this.config || {
1367
- defaultName: "default",
1368
- promptPaths: [],
1369
- variablePrefix: "{{",
1370
- variableSuffix: "}}",
1371
- strictMode: false
1372
- };
1373
- this.renderer = new PromptRenderer({
1374
- prefix: config.variablePrefix,
1375
- suffix: config.variableSuffix,
1376
- strict: config.strictMode,
1377
- onMissingVariable: (name) => {
1378
- logger2.warn(`Undefined variable: ${name}`);
1379
- return `{{${name}}}`;
1380
- }
1381
- });
1382
- }
1383
- async onStart() {
1384
- logger2.info("[PromptComponent] Started");
1385
- }
1386
- async onStop() {
1387
- this.configWatcher?.();
1388
- this.configWatcher = undefined;
1389
- this.prompts.clear();
1390
- this.setStatus("stopped");
1391
- logger2.info("[PromptComponent] Stopped");
1392
- }
1393
- getPromptConfig(key, defaultValue) {
1394
- if (this.config && key in this.config) {
1395
- return this.config[key] ?? defaultValue;
1396
- }
1397
- return defaultValue;
1398
- }
1399
- add(name, content, source = "inline") {
1400
- const entry = {
1401
- name,
1402
- content,
1403
- source,
1404
- overridable: true,
1405
- loadedAt: Date.now()
1406
- };
1407
- const existing = this.prompts.get(name);
1408
- if (existing && !existing.overridable) {
1409
- logger2.debug(`[PromptComponent] Skip override for non-overridable prompt: ${name}`);
1410
- return;
1411
- }
1412
- this.prompts.set(name, entry);
1413
- logger2.debug(`[PromptComponent] Added prompt: ${name} (${source})`);
1414
- }
1415
- get(name) {
1416
- return this.prompts.get(name)?.content;
1417
- }
1418
- getEntry(name) {
1419
- return this.prompts.get(name);
1420
- }
1421
- has(name) {
1422
- return this.prompts.has(name);
1423
- }
1424
- delete(name) {
1425
- return this.prompts.delete(name);
1426
- }
1427
- list() {
1428
- return Array.from(this.prompts.keys());
1429
- }
1430
- listEntries() {
1431
- return Array.from(this.prompts.values());
1432
- }
1433
- getPromptStore() {
1434
- if (!this.promptStore) {
1435
- this.initPromptStore();
1436
- }
1437
- return this.promptStore;
1438
- }
1439
- getPromptConfigDir() {
1440
- return this.getPromptStore().getConfigDir();
1441
- }
1442
- async savePrompt(name, content) {
1443
- const filePath = await this.getPromptStore().savePrompt(name, content.trim());
1444
- this.add(name, content.trim(), "file");
1445
- const entry = this.prompts.get(name);
1446
- if (entry) {
1447
- entry.filePath = filePath;
1448
- }
1449
- return filePath;
1450
- }
1451
- async deletePromptFile(name) {
1452
- const deleted = await this.getPromptStore().deletePrompt(name);
1453
- if (deleted) {
1454
- this.delete(name);
1455
- }
1456
- return deleted;
1457
- }
1458
- size() {
1459
- return this.prompts.size;
1460
- }
1461
- async getPrompt(name, variables = {}) {
1462
- const defaultName = this.getPromptConfig("defaultName", "default");
1463
- const targetName = this.has(name) ? name : defaultName;
1464
- const entry = this.prompts.get(targetName);
1465
- if (!entry) {
1466
- logger2.warn(`[PromptComponent] Prompt not found: ${name}, using fallback`);
1467
- return "You are a helpful assistant.";
1468
- }
1469
- return this.render(entry.content, variables, { name: targetName });
1470
- }
1471
- async render(content, variables = {}, context) {
1472
- const hookContext = {
1473
- name: context?.name || "anonymous",
1474
- originalContent: content,
1475
- renderedContent: content,
1476
- variables
1477
- };
1478
- await globalHookManager.execute(PromptHookPoints.BEFORE_RENDER, hookContext);
1479
- hookContext.renderedContent = this.renderer.render(hookContext.originalContent, variables);
1480
- await globalHookManager.execute(PromptHookPoints.AFTER_RENDER, hookContext);
1481
- return hookContext.renderedContent;
1482
- }
1483
- extractVariables(content) {
1484
- return this.renderer.extractVariables(content);
1485
- }
1486
- initPromptStore() {
1487
- const customDir = this.configComponent?.get?.("prompt.configDir");
1488
- this.promptStore = new PromptStore({
1489
- configDir: typeof customDir === "string" && customDir.length > 0 ? customDir : undefined
1490
- });
1491
- }
1492
- async loadPrompts() {
1493
- await this.loadBuiltInPrompts();
1494
- await this.loadUserPrompts();
1495
- await this.loadExternalPrompts();
1496
- }
1497
- async loadUserPrompts() {
1498
- const store = this.getPromptStore();
1499
- const prompts = await store.loadAll();
1500
- for (const prompt of prompts) {
1501
- this.add(prompt.name, prompt.content, "file");
1502
- const entry = this.prompts.get(prompt.name);
1503
- if (entry) {
1504
- entry.filePath = prompt.filePath;
1505
- }
1506
- }
1507
- if (prompts.length > 0) {
1508
- logger2.info(`[PromptComponent] Loaded ${prompts.length} prompts from ${store.getConfigDir()}`);
1509
- }
1510
- }
1511
- async loadBuiltInPrompts() {
1512
- for (const [name, content] of Object.entries(builtInPrompts)) {
1513
- if (content) {
1514
- this.prompts.set(name, {
1515
- name,
1516
- content,
1517
- source: "built-in",
1518
- overridable: false,
1519
- loadedAt: Date.now()
1520
- });
1521
- logger2.debug(`[PromptComponent] Loaded built-in prompt: ${name}`);
1522
- }
1523
- }
1524
- logger2.info(`[PromptComponent] Loaded ${this.prompts.size} built-in prompts`);
1525
- }
1526
- async loadExternalPrompts() {
1527
- const promptPaths = this.getPromptConfig("promptPaths", []);
1528
- for (const pathConfig of promptPaths) {
1529
- try {
1530
- if (pathConfig.type === "file") {
1531
- await this.loadFromFile(pathConfig.path, pathConfig.name);
1532
- } else if (pathConfig.type === "directory") {
1533
- await this.loadFromDirectory(pathConfig.path, pathConfig.extension || ".md", pathConfig.recursive !== false);
1534
- }
1535
- } catch (error) {
1536
- logger2.error(`[PromptComponent] Failed to load from ${pathConfig.path}:`, error);
1537
- }
1538
- }
1539
- }
1540
- async loadFromFile(filePath, name) {
1541
- try {
1542
- const content = await readFile2(filePath, "utf-8");
1543
- const promptName = name || basename(filePath, extname(filePath));
1544
- this.add(promptName, content.trim(), "file");
1545
- const entry = this.prompts.get(promptName);
1546
- if (entry)
1547
- entry.filePath = filePath;
1548
- logger2.debug(`[PromptComponent] Loaded prompt from file: ${filePath}`);
1549
- return true;
1550
- } catch (error) {
1551
- logger2.error(`[PromptComponent] Failed to load file ${filePath}:`, error);
1552
- return false;
1553
- }
1554
- }
1555
- async loadFromDirectory(directory, extension = ".md", recursive = true) {
1556
- let loaded = 0;
1557
- try {
1558
- const files = await this.findFiles(directory, extension, recursive);
1559
- for (const filePath of files) {
1560
- const relativePath = filePath.replace(directory + "/", "");
1561
- const promptName = relativePath.replace(/\\/g, "/").replace(new RegExp(escapeRegex2(extension) + "$"), "").replace(/\//g, "-");
1562
- const content = await readFile2(filePath, "utf-8");
1563
- this.add(promptName, content.trim(), "directory");
1564
- const entry = this.prompts.get(promptName);
1565
- if (entry)
1566
- entry.filePath = filePath;
1567
- loaded++;
1568
- }
1569
- logger2.info(`[PromptComponent] Loaded ${loaded} prompts from directory: ${directory}`);
1570
- } catch (error) {
1571
- logger2.error(`[PromptComponent] Failed to load directory ${directory}:`, error);
1572
- }
1573
- return loaded;
1574
- }
1575
- async findFiles(dir, extension, recursive) {
1576
- const files = [];
1577
- try {
1578
- const entries = await readdir2(dir, { withFileTypes: true });
1579
- for (const entry of entries) {
1580
- const fullPath = join2(dir, entry.name);
1581
- if (entry.isDirectory() && recursive) {
1582
- const subFiles = await this.findFiles(fullPath, extension, true);
1583
- files.push(...subFiles);
1584
- } else if (entry.isFile() && entry.name.endsWith(extension)) {
1585
- files.push(fullPath);
1586
- }
1587
- }
1588
- } catch (error) {
1589
- logger2.warn(`[PromptComponent] Cannot read directory ${dir}:`, error);
1590
- }
1591
- return files;
1592
- }
1593
- registerPromptHook(hookPoint, name, fn, priority) {
1594
- globalHookManager.register(hookPoint, createHook({ name, priority }, fn));
1595
- }
1596
- unregisterPromptHook(hookPoint, name) {
1597
- return globalHookManager.unregister(hookPoint, name);
1598
- }
1599
- getHookPoints() {
1600
- return [PromptHookPoints.BEFORE_RENDER, PromptHookPoints.AFTER_RENDER];
1601
- }
1602
- }
1603
- function escapeRegex2(str) {
1604
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1605
- }
1606
-
1607
- export { PromptPathSchema, PromptConfigSchema, PromptRenderer, getBuiltInPromptNames, getBuiltInPrompt, PromptStore, PromptComponent };
1119
+ export { builtInPrompts, WORKFLOW_EXTRACT_PROMPT, getBuiltInPromptNames, getBuiltInPrompt };