@redigg/redigg 0.1.0

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 (322) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +145 -0
  3. package/dist/agent/ResearchAgent.d.ts +35 -0
  4. package/dist/agent/ResearchAgent.js +818 -0
  5. package/dist/agent/ResearchAgent.js.map +1 -0
  6. package/dist/agent/subagent/SubAgent.d.ts +23 -0
  7. package/dist/agent/subagent/SubAgent.js +87 -0
  8. package/dist/agent/subagent/SubAgent.js.map +1 -0
  9. package/dist/agent/subagent/SubAgentManager.d.ts +19 -0
  10. package/dist/agent/subagent/SubAgentManager.js +40 -0
  11. package/dist/agent/subagent/SubAgentManager.js.map +1 -0
  12. package/dist/bin.d.ts +2 -0
  13. package/dist/bin.js +34 -0
  14. package/dist/bin.js.map +1 -0
  15. package/dist/cli.d.ts +1 -0
  16. package/dist/cli.js +179 -0
  17. package/dist/cli.js.map +1 -0
  18. package/dist/events/EventManager.d.ts +39 -0
  19. package/dist/events/EventManager.js +20 -0
  20. package/dist/events/EventManager.js.map +1 -0
  21. package/dist/gateway/index.d.ts +9 -0
  22. package/dist/gateway/index.js +474 -0
  23. package/dist/gateway/index.js.map +1 -0
  24. package/dist/index.d.ts +3 -0
  25. package/dist/index.js +97 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/llm/LLMClient.d.ts +30 -0
  28. package/dist/llm/LLMClient.js +21 -0
  29. package/dist/llm/LLMClient.js.map +1 -0
  30. package/dist/llm/OpenAIClient.d.ts +16 -0
  31. package/dist/llm/OpenAIClient.js +58 -0
  32. package/dist/llm/OpenAIClient.js.map +1 -0
  33. package/dist/memory/MemoryManager.d.ts +41 -0
  34. package/dist/memory/MemoryManager.js +221 -0
  35. package/dist/memory/MemoryManager.js.map +1 -0
  36. package/dist/memory/evolution/MemoryEvolutionSystem.d.ts +17 -0
  37. package/dist/memory/evolution/MemoryEvolutionSystem.js +71 -0
  38. package/dist/memory/evolution/MemoryEvolutionSystem.js.map +1 -0
  39. package/dist/memory/search/BM25Search.d.ts +22 -0
  40. package/dist/memory/search/BM25Search.js +61 -0
  41. package/dist/memory/search/BM25Search.js.map +1 -0
  42. package/dist/memory/structure/PageIndex.d.ts +26 -0
  43. package/dist/memory/structure/PageIndex.js +156 -0
  44. package/dist/memory/structure/PageIndex.js.map +1 -0
  45. package/dist/quality/QualityManager.d.ts +12 -0
  46. package/dist/quality/QualityManager.js +61 -0
  47. package/dist/quality/QualityManager.js.map +1 -0
  48. package/dist/scheduling/CronManager.d.ts +21 -0
  49. package/dist/scheduling/CronManager.js +66 -0
  50. package/dist/scheduling/CronManager.js.map +1 -0
  51. package/dist/session/SessionManager.d.ts +37 -0
  52. package/dist/session/SessionManager.js +238 -0
  53. package/dist/session/SessionManager.js.map +1 -0
  54. package/dist/skills/SkillManager.d.ts +31 -0
  55. package/dist/skills/SkillManager.js +254 -0
  56. package/dist/skills/SkillManager.js.map +1 -0
  57. package/dist/skills/agent/PACK.md +13 -0
  58. package/dist/skills/agent/agent-orchestration/SKILL.md +37 -0
  59. package/dist/skills/agent/agent-orchestration/index.d.ts +9 -0
  60. package/dist/skills/agent/agent-orchestration/index.js +70 -0
  61. package/dist/skills/agent/agent-orchestration/index.js.map +1 -0
  62. package/dist/skills/agent/evolution/SKILL.md +25 -0
  63. package/dist/skills/agent/evolution/index.d.ts +9 -0
  64. package/dist/skills/agent/evolution/index.js +57 -0
  65. package/dist/skills/agent/evolution/index.js.map +1 -0
  66. package/dist/skills/agent/heartbeat/index.d.ts +8 -0
  67. package/dist/skills/agent/heartbeat/index.js +44 -0
  68. package/dist/skills/agent/heartbeat/index.js.map +1 -0
  69. package/dist/skills/agent/memory-management/SKILL.md +40 -0
  70. package/dist/skills/agent/memory-management/index.d.ts +8 -0
  71. package/dist/skills/agent/memory-management/index.js +44 -0
  72. package/dist/skills/agent/memory-management/index.js.map +1 -0
  73. package/dist/skills/agent/scheduling/SKILL.md +33 -0
  74. package/dist/skills/agent/scheduling/index.d.ts +13 -0
  75. package/dist/skills/agent/scheduling/index.js +80 -0
  76. package/dist/skills/agent/scheduling/index.js.map +1 -0
  77. package/dist/skills/agent/session-management/SKILL.md +35 -0
  78. package/dist/skills/agent/session-management/index.d.ts +11 -0
  79. package/dist/skills/agent/session-management/index.js +54 -0
  80. package/dist/skills/agent/session-management/index.js.map +1 -0
  81. package/dist/skills/agent/skill-management/SKILL.md +31 -0
  82. package/dist/skills/agent/skill-management/index.d.ts +8 -0
  83. package/dist/skills/agent/skill-management/index.js +25 -0
  84. package/dist/skills/agent/skill-management/index.js.map +1 -0
  85. package/dist/skills/evolution/SkillEvolutionSystem.d.ts +12 -0
  86. package/dist/skills/evolution/SkillEvolutionSystem.js +157 -0
  87. package/dist/skills/evolution/SkillEvolutionSystem.js.map +1 -0
  88. package/dist/skills/lib/ScholarTool.d.ts +14 -0
  89. package/dist/skills/lib/ScholarTool.js +71 -0
  90. package/dist/skills/lib/ScholarTool.js.map +1 -0
  91. package/dist/skills/research/PACK.md +7 -0
  92. package/dist/skills/research/academic-survey-self-improve/SKILL.md +17 -0
  93. package/dist/skills/research/academic-survey-self-improve/index.d.ts +10 -0
  94. package/dist/skills/research/academic-survey-self-improve/index.js +75 -0
  95. package/dist/skills/research/academic-survey-self-improve/index.js.map +1 -0
  96. package/dist/skills/research/concept-explainer/SKILL.md +3 -0
  97. package/dist/skills/research/concept-explainer/index.d.ts +8 -0
  98. package/dist/skills/research/concept-explainer/index.js +37 -0
  99. package/dist/skills/research/concept-explainer/index.js.map +1 -0
  100. package/dist/skills/research/literature-review/SKILL.md +25 -0
  101. package/dist/skills/research/literature-review/index.d.ts +9 -0
  102. package/dist/skills/research/literature-review/index.js +132 -0
  103. package/dist/skills/research/literature-review/index.js.map +1 -0
  104. package/dist/skills/research/paper-analysis/SKILL.md +3 -0
  105. package/dist/skills/research/paper-analysis/index.d.ts +9 -0
  106. package/dist/skills/research/paper-analysis/index.js +64 -0
  107. package/dist/skills/research/paper-analysis/index.js.map +1 -0
  108. package/dist/skills/research/pdf-generator/SKILL.md +16 -0
  109. package/dist/skills/research/pdf-generator/index.d.ts +10 -0
  110. package/dist/skills/research/pdf-generator/index.js +88 -0
  111. package/dist/skills/research/pdf-generator/index.js.map +1 -0
  112. package/dist/skills/system/PACK.md +8 -0
  113. package/dist/skills/system/code-analysis/SKILL.md +43 -0
  114. package/dist/skills/system/code-analysis/index.d.ts +12 -0
  115. package/dist/skills/system/code-analysis/index.js +172 -0
  116. package/dist/skills/system/code-analysis/index.js.map +1 -0
  117. package/dist/skills/system/local-file-ops/SKILL.md +55 -0
  118. package/dist/skills/system/local-file-ops/index.d.ts +9 -0
  119. package/dist/skills/system/local-file-ops/index.js +111 -0
  120. package/dist/skills/system/local-file-ops/index.js.map +1 -0
  121. package/dist/skills/types.d.ts +41 -0
  122. package/dist/skills/types.js +2 -0
  123. package/dist/skills/types.js.map +1 -0
  124. package/dist/skills/vendor/PACK.md +11 -0
  125. package/dist/skills/vendor/agent-browser/CONTRIBUTING.md +63 -0
  126. package/dist/skills/vendor/agent-browser/SKILL.md +328 -0
  127. package/dist/skills/vendor/find-skills/SKILL.md +133 -0
  128. package/dist/skills/vendor/proactive-agent/SKILL-v2.3-backup.md +554 -0
  129. package/dist/skills/vendor/proactive-agent/SKILL-v3-draft.md +499 -0
  130. package/dist/skills/vendor/proactive-agent/SKILL.md +632 -0
  131. package/dist/skills/vendor/proactive-agent/assets/AGENTS.md +155 -0
  132. package/dist/skills/vendor/proactive-agent/assets/HEARTBEAT.md +128 -0
  133. package/dist/skills/vendor/proactive-agent/assets/MEMORY.md +47 -0
  134. package/dist/skills/vendor/proactive-agent/assets/ONBOARDING.md +103 -0
  135. package/dist/skills/vendor/proactive-agent/assets/SOUL.md +40 -0
  136. package/dist/skills/vendor/proactive-agent/assets/TOOLS.md +55 -0
  137. package/dist/skills/vendor/proactive-agent/assets/USER.md +36 -0
  138. package/dist/skills/vendor/proactive-agent/references/onboarding-flow.md +158 -0
  139. package/dist/skills/vendor/proactive-agent/references/security-patterns.md +109 -0
  140. package/dist/skills/vendor/searxng/CHANGELOG.md +38 -0
  141. package/dist/skills/vendor/searxng/PUBLISH.md +147 -0
  142. package/dist/skills/vendor/searxng/PUBLISHING_CHECKLIST.md +111 -0
  143. package/dist/skills/vendor/searxng/README.md +168 -0
  144. package/dist/skills/vendor/searxng/SKILL.md +69 -0
  145. package/dist/skills/vendor/self-improving-agent/.learnings/ERRORS.md +5 -0
  146. package/dist/skills/vendor/self-improving-agent/.learnings/FEATURE_REQUESTS.md +5 -0
  147. package/dist/skills/vendor/self-improving-agent/.learnings/LEARNINGS.md +5 -0
  148. package/dist/skills/vendor/self-improving-agent/SKILL.md +647 -0
  149. package/dist/skills/vendor/self-improving-agent/assets/LEARNINGS.md +45 -0
  150. package/dist/skills/vendor/self-improving-agent/assets/SKILL-TEMPLATE.md +177 -0
  151. package/dist/skills/vendor/self-improving-agent/hooks/openclaw/HOOK.md +23 -0
  152. package/dist/skills/vendor/self-improving-agent/hooks/openclaw/handler.d.ts +9 -0
  153. package/dist/skills/vendor/self-improving-agent/hooks/openclaw/handler.js +54 -0
  154. package/dist/skills/vendor/self-improving-agent/hooks/openclaw/handler.js.map +1 -0
  155. package/dist/skills/vendor/self-improving-agent/references/examples.md +374 -0
  156. package/dist/skills/vendor/self-improving-agent/references/hooks-setup.md +223 -0
  157. package/dist/skills/vendor/self-improving-agent/references/openclaw-integration.md +248 -0
  158. package/dist/skills/vendor/skill-vetter/SKILL.md +138 -0
  159. package/dist/src/agent/ResearchAgent.d.ts +35 -0
  160. package/dist/src/agent/ResearchAgent.js +818 -0
  161. package/dist/src/agent/ResearchAgent.js.map +1 -0
  162. package/dist/src/agent/subagent/SubAgent.d.ts +23 -0
  163. package/dist/src/agent/subagent/SubAgent.js +87 -0
  164. package/dist/src/agent/subagent/SubAgent.js.map +1 -0
  165. package/dist/src/agent/subagent/SubAgentManager.d.ts +19 -0
  166. package/dist/src/agent/subagent/SubAgentManager.js +40 -0
  167. package/dist/src/agent/subagent/SubAgentManager.js.map +1 -0
  168. package/dist/src/bin.d.ts +2 -0
  169. package/dist/src/bin.js +34 -0
  170. package/dist/src/bin.js.map +1 -0
  171. package/dist/src/cli.d.ts +1 -0
  172. package/dist/src/cli.js +179 -0
  173. package/dist/src/cli.js.map +1 -0
  174. package/dist/src/events/EventManager.d.ts +39 -0
  175. package/dist/src/events/EventManager.js +20 -0
  176. package/dist/src/events/EventManager.js.map +1 -0
  177. package/dist/src/gateway/index.d.ts +9 -0
  178. package/dist/src/gateway/index.js +474 -0
  179. package/dist/src/gateway/index.js.map +1 -0
  180. package/dist/src/index.d.ts +3 -0
  181. package/dist/src/index.js +105 -0
  182. package/dist/src/index.js.map +1 -0
  183. package/dist/src/llm/LLMClient.d.ts +30 -0
  184. package/dist/src/llm/LLMClient.js +21 -0
  185. package/dist/src/llm/LLMClient.js.map +1 -0
  186. package/dist/src/llm/OpenAIClient.d.ts +16 -0
  187. package/dist/src/llm/OpenAIClient.js +58 -0
  188. package/dist/src/llm/OpenAIClient.js.map +1 -0
  189. package/dist/src/memory/MemoryManager.d.ts +41 -0
  190. package/dist/src/memory/MemoryManager.js +221 -0
  191. package/dist/src/memory/MemoryManager.js.map +1 -0
  192. package/dist/src/memory/evolution/MemoryEvolutionSystem.d.ts +17 -0
  193. package/dist/src/memory/evolution/MemoryEvolutionSystem.js +71 -0
  194. package/dist/src/memory/evolution/MemoryEvolutionSystem.js.map +1 -0
  195. package/dist/src/memory/search/BM25Search.d.ts +22 -0
  196. package/dist/src/memory/search/BM25Search.js +61 -0
  197. package/dist/src/memory/search/BM25Search.js.map +1 -0
  198. package/dist/src/memory/structure/PageIndex.d.ts +26 -0
  199. package/dist/src/memory/structure/PageIndex.js +156 -0
  200. package/dist/src/memory/structure/PageIndex.js.map +1 -0
  201. package/dist/src/quality/QualityManager.d.ts +12 -0
  202. package/dist/src/quality/QualityManager.js +61 -0
  203. package/dist/src/quality/QualityManager.js.map +1 -0
  204. package/dist/src/scheduling/CronManager.d.ts +21 -0
  205. package/dist/src/scheduling/CronManager.js +66 -0
  206. package/dist/src/scheduling/CronManager.js.map +1 -0
  207. package/dist/src/session/SessionManager.d.ts +37 -0
  208. package/dist/src/session/SessionManager.js +238 -0
  209. package/dist/src/session/SessionManager.js.map +1 -0
  210. package/dist/src/skills/SkillManager.d.ts +33 -0
  211. package/dist/src/skills/SkillManager.js +260 -0
  212. package/dist/src/skills/SkillManager.js.map +1 -0
  213. package/dist/src/skills/evolution/SkillEvolutionSystem.d.ts +12 -0
  214. package/dist/src/skills/evolution/SkillEvolutionSystem.js +157 -0
  215. package/dist/src/skills/evolution/SkillEvolutionSystem.js.map +1 -0
  216. package/dist/src/skills/lib/ScholarTool.d.ts +14 -0
  217. package/dist/src/skills/lib/ScholarTool.js +71 -0
  218. package/dist/src/skills/lib/ScholarTool.js.map +1 -0
  219. package/dist/src/skills/types.d.ts +41 -0
  220. package/dist/src/skills/types.js +2 -0
  221. package/dist/src/skills/types.js.map +1 -0
  222. package/dist/src/storage/sqlite.d.ts +8 -0
  223. package/dist/src/storage/sqlite.js +73 -0
  224. package/dist/src/storage/sqlite.js.map +1 -0
  225. package/dist/src/utils/logger.d.ts +12 -0
  226. package/dist/src/utils/logger.js +53 -0
  227. package/dist/src/utils/logger.js.map +1 -0
  228. package/dist/storage/sqlite.d.ts +8 -0
  229. package/dist/storage/sqlite.js +73 -0
  230. package/dist/storage/sqlite.js.map +1 -0
  231. package/dist/utils/logger.d.ts +12 -0
  232. package/dist/utils/logger.js +53 -0
  233. package/dist/utils/logger.js.map +1 -0
  234. package/package.json +71 -0
  235. package/skills/agent/PACK.md +13 -0
  236. package/skills/agent/agent-orchestration/SKILL.md +37 -0
  237. package/skills/agent/agent-orchestration/index.ts +84 -0
  238. package/skills/agent/evolution/SKILL.md +25 -0
  239. package/skills/agent/evolution/index.ts +67 -0
  240. package/skills/agent/heartbeat/index.ts +48 -0
  241. package/skills/agent/memory-management/SKILL.md +40 -0
  242. package/skills/agent/memory-management/index.ts +48 -0
  243. package/skills/agent/scheduling/SKILL.md +33 -0
  244. package/skills/agent/scheduling/index.ts +97 -0
  245. package/skills/agent/session-management/SKILL.md +35 -0
  246. package/skills/agent/session-management/index.ts +65 -0
  247. package/skills/agent/skill-management/SKILL.md +31 -0
  248. package/skills/agent/skill-management/index.ts +32 -0
  249. package/skills/research/PACK.md +7 -0
  250. package/skills/research/academic-survey-self-improve/SKILL.md +17 -0
  251. package/skills/research/academic-survey-self-improve/index.ts +87 -0
  252. package/skills/research/concept-explainer/SKILL.md +3 -0
  253. package/skills/research/concept-explainer/index.ts +42 -0
  254. package/skills/research/literature-review/SKILL.md +25 -0
  255. package/skills/research/literature-review/index.ts +168 -0
  256. package/skills/research/paper-analysis/SKILL.md +3 -0
  257. package/skills/research/paper-analysis/index.ts +73 -0
  258. package/skills/research/pdf-generator/SKILL.md +16 -0
  259. package/skills/research/pdf-generator/index.d.ts +10 -0
  260. package/skills/research/pdf-generator/index.js +114 -0
  261. package/skills/research/pdf-generator/index.js.map +1 -0
  262. package/skills/research/pdf-generator/index.ts +97 -0
  263. package/skills/system/PACK.md +8 -0
  264. package/skills/system/code-analysis/SKILL.md +43 -0
  265. package/skills/system/code-analysis/index.ts +180 -0
  266. package/skills/system/local-file-ops/SKILL.md +55 -0
  267. package/skills/system/local-file-ops/index.ts +123 -0
  268. package/skills/vendor/PACK.md +11 -0
  269. package/skills/vendor/agent-browser/.clawhub/origin.json +7 -0
  270. package/skills/vendor/agent-browser/CONTRIBUTING.md +63 -0
  271. package/skills/vendor/agent-browser/SKILL.md +328 -0
  272. package/skills/vendor/agent-browser/_meta.json +6 -0
  273. package/skills/vendor/find-skills/.clawhub/origin.json +7 -0
  274. package/skills/vendor/find-skills/SKILL.md +133 -0
  275. package/skills/vendor/find-skills/_meta.json +6 -0
  276. package/skills/vendor/proactive-agent/.clawhub/origin.json +7 -0
  277. package/skills/vendor/proactive-agent/SKILL-v2.3-backup.md +554 -0
  278. package/skills/vendor/proactive-agent/SKILL-v3-draft.md +499 -0
  279. package/skills/vendor/proactive-agent/SKILL.md +632 -0
  280. package/skills/vendor/proactive-agent/_meta.json +6 -0
  281. package/skills/vendor/proactive-agent/assets/AGENTS.md +155 -0
  282. package/skills/vendor/proactive-agent/assets/HEARTBEAT.md +128 -0
  283. package/skills/vendor/proactive-agent/assets/MEMORY.md +47 -0
  284. package/skills/vendor/proactive-agent/assets/ONBOARDING.md +103 -0
  285. package/skills/vendor/proactive-agent/assets/SOUL.md +40 -0
  286. package/skills/vendor/proactive-agent/assets/TOOLS.md +55 -0
  287. package/skills/vendor/proactive-agent/assets/USER.md +36 -0
  288. package/skills/vendor/proactive-agent/references/onboarding-flow.md +158 -0
  289. package/skills/vendor/proactive-agent/references/security-patterns.md +109 -0
  290. package/skills/vendor/proactive-agent/scripts/security-audit.sh +149 -0
  291. package/skills/vendor/searxng/.clawdhub/origin.json +7 -0
  292. package/skills/vendor/searxng/CHANGELOG.md +38 -0
  293. package/skills/vendor/searxng/PUBLISH.md +147 -0
  294. package/skills/vendor/searxng/PUBLISHING_CHECKLIST.md +111 -0
  295. package/skills/vendor/searxng/README.md +168 -0
  296. package/skills/vendor/searxng/SKILL.md +69 -0
  297. package/skills/vendor/searxng/_meta.json +6 -0
  298. package/skills/vendor/searxng/config/settings.yml +36 -0
  299. package/skills/vendor/searxng/run-searxng.sh +48 -0
  300. package/skills/vendor/searxng/scripts/searxng.py +211 -0
  301. package/skills/vendor/self-improving-agent/.clawhub/origin.json +7 -0
  302. package/skills/vendor/self-improving-agent/.learnings/ERRORS.md +5 -0
  303. package/skills/vendor/self-improving-agent/.learnings/FEATURE_REQUESTS.md +5 -0
  304. package/skills/vendor/self-improving-agent/.learnings/LEARNINGS.md +5 -0
  305. package/skills/vendor/self-improving-agent/SKILL.md +647 -0
  306. package/skills/vendor/self-improving-agent/_meta.json +6 -0
  307. package/skills/vendor/self-improving-agent/assets/LEARNINGS.md +45 -0
  308. package/skills/vendor/self-improving-agent/assets/SKILL-TEMPLATE.md +177 -0
  309. package/skills/vendor/self-improving-agent/hooks/openclaw/HOOK.md +23 -0
  310. package/skills/vendor/self-improving-agent/hooks/openclaw/handler.js +56 -0
  311. package/skills/vendor/self-improving-agent/hooks/openclaw/handler.ts +62 -0
  312. package/skills/vendor/self-improving-agent/references/examples.md +374 -0
  313. package/skills/vendor/self-improving-agent/references/hooks-setup.md +223 -0
  314. package/skills/vendor/self-improving-agent/references/openclaw-integration.md +248 -0
  315. package/skills/vendor/self-improving-agent/scripts/activator.sh +20 -0
  316. package/skills/vendor/self-improving-agent/scripts/error-detector.sh +55 -0
  317. package/skills/vendor/self-improving-agent/scripts/extract-skill.sh +221 -0
  318. package/skills/vendor/skill-vetter/.clawhub/origin.json +7 -0
  319. package/skills/vendor/skill-vetter/SKILL.md +138 -0
  320. package/skills/vendor/skill-vetter/_meta.json +6 -0
  321. package/web/README.md +73 -0
  322. package/web/package.json +65 -0
@@ -0,0 +1,818 @@
1
+ import { SkillEvolutionSystem } from '../skills/evolution/SkillEvolutionSystem.js';
2
+ import { SkillManager } from '../skills/SkillManager.js';
3
+ import { SessionManager } from '../session/SessionManager.js';
4
+ import { CronManager } from '../scheduling/CronManager.js';
5
+ import { EventManager } from '../events/EventManager.js';
6
+ import { QualityManager } from '../quality/QualityManager.js';
7
+ import { createLogger } from '../utils/logger.js';
8
+ const logger = createLogger('Agent');
9
+ export class ResearchAgent {
10
+ memoryManager;
11
+ memoryEvo;
12
+ skillEvo;
13
+ llm;
14
+ skillManager;
15
+ sessionManager;
16
+ cronManager;
17
+ eventManager;
18
+ qualityManager;
19
+ heartbeatInterval = null;
20
+ constructor(memoryManager, memoryEvo, llm, skillManager) {
21
+ this.memoryManager = memoryManager;
22
+ this.memoryEvo = memoryEvo;
23
+ this.llm = llm;
24
+ this.sessionManager = new SessionManager(memoryManager.storage); // Reuse storage
25
+ this.cronManager = new CronManager();
26
+ this.eventManager = new EventManager();
27
+ this.qualityManager = new QualityManager(llm);
28
+ // Pass managers to SkillManager for injection into SkillContext
29
+ this.skillManager = skillManager || new SkillManager(llm, memoryManager, process.cwd());
30
+ // Inject managers now that they are created
31
+ this.skillManager.setManagers({
32
+ cron: this.cronManager,
33
+ session: this.sessionManager,
34
+ skill: this.skillManager, // Self-reference for skills that need to execute other skills
35
+ event: this.eventManager,
36
+ });
37
+ this.skillEvo = new SkillEvolutionSystem(this.skillManager, llm);
38
+ // Trigger loading from disk (async)
39
+ this.skillManager.loadSkillsFromDisk().catch(err => {
40
+ logger.error('Failed to load skills from disk:', err);
41
+ });
42
+ // Wire up events
43
+ this.setupEventListeners();
44
+ }
45
+ setupEventListeners() {
46
+ // Example: Log all commands
47
+ this.eventManager.on('command:executed', (payload) => {
48
+ logger.info(`[Event] Command Executed: ${payload.command}`);
49
+ });
50
+ // Example: Log memory additions
51
+ this.eventManager.on('memory:added', (payload) => {
52
+ logger.info(`[Event] Memory Added: ${payload.id} (${payload.type})`);
53
+ });
54
+ }
55
+ async start() {
56
+ logger.info('Starting heartbeat...');
57
+ this.heartbeatInterval = setInterval(() => this.heartbeat(), 60000); // Every minute
58
+ // Initial check on start
59
+ this.heartbeat().catch(e => logger.error('Initial heartbeat failed:', e));
60
+ }
61
+ stop() {
62
+ if (this.heartbeatInterval) {
63
+ clearInterval(this.heartbeatInterval);
64
+ this.heartbeatInterval = null;
65
+ logger.info('Stopped heartbeat.');
66
+ }
67
+ }
68
+ async heartbeat() {
69
+ logger.debug('[Agent] Heartbeat...');
70
+ // Execute Heartbeat Skill
71
+ try {
72
+ // SkillManager loads skills asynchronously, so "heartbeat" might not be ready on first call
73
+ // We should check if it's available or wait/retry, but for now we just catch error
74
+ if (this.skillManager.getSkill('heartbeat')) {
75
+ const result = await this.skillManager.executeSkill('heartbeat', 'system', {});
76
+ // Check for significant updates and notify active session if possible
77
+ const memoryStats = result.memory;
78
+ if (memoryStats && (memoryStats.moved > 0 || memoryStats.promoted > 0 || memoryStats.pruned > 0)) {
79
+ const msg = `[System Heartbeat] Memory Optimization: Moved ${memoryStats.moved} to short-term, Promoted ${memoryStats.promoted} to long-term.`;
80
+ const session = this.sessionManager.getOrCreateActiveSession('web-user');
81
+ if (session) {
82
+ this.sessionManager.addMessage(session.id, 'assistant', msg);
83
+ }
84
+ }
85
+ const skillStats = result.skills;
86
+ if (skillStats) {
87
+ // Log stats
88
+ }
89
+ }
90
+ else {
91
+ logger.warn('Heartbeat skill not found (yet). Skipping this beat.');
92
+ }
93
+ }
94
+ catch (e) {
95
+ logger.error('Heartbeat skill failed:', e);
96
+ }
97
+ // 3. Cron jobs are handled by CronManager independently
98
+ }
99
+ async chat(userId, message, onProgress, sessionId, options) {
100
+ // Helper to log and emit progress
101
+ const log = (content, stats) => {
102
+ const payload = stats ? `${content}__STATS__${JSON.stringify(stats)}` : content;
103
+ onProgress?.('log', payload);
104
+ // Persist log to session history
105
+ this.sessionManager.addMessage(session.id, 'log', payload);
106
+ };
107
+ // Send plan update (UI list)
108
+ const sendPlan = (plan) => {
109
+ onProgress?.('plan', plan);
110
+ };
111
+ // Send todo update (Dynamic List)
112
+ const sendTodo = (todo) => {
113
+ onProgress?.('todo', todo);
114
+ };
115
+ // Get or create session
116
+ let session;
117
+ if (sessionId) {
118
+ const existing = this.sessionManager.getSession(sessionId);
119
+ if (existing && existing.userId === userId) {
120
+ session = existing;
121
+ }
122
+ else {
123
+ session = this.sessionManager.createSession(userId);
124
+ }
125
+ }
126
+ else {
127
+ session = this.sessionManager.getOrCreateActiveSession(userId);
128
+ }
129
+ // Ensure session is active
130
+ this.sessionManager.activateSession(session.id);
131
+ // Update session title if it's the first user message
132
+ if (session.messages.length === 0) {
133
+ session.title = message.slice(0, 30) + (message.length > 30 ? '...' : '');
134
+ }
135
+ this.sessionManager.addMessage(session.id, 'user', message);
136
+ // 1. Plan
137
+ logger.info(`Creating plan for user ${userId}...`);
138
+ log(`[Agent] Planning response...`);
139
+ // Check if message is simple conversational
140
+ const isConversational = /^(hello|hi|hey|thanks|thank you|bye|goodbye|ok|okay|yes|no|cool|great|wow|who are you|what are you)\b/i.test(message.trim().replace(/[!.?]+$/, ''));
141
+ let plan = { intent: 'single', steps: [] };
142
+ let planningMessage = message;
143
+ // Removed string-based auto mode check in favor of explicit option
144
+ if (!isConversational || options?.autoMode) {
145
+ try {
146
+ // Check for explicit auto-research request
147
+ const forceAuto = options?.autoMode || false;
148
+ plan = await this.createPlan(planningMessage, log, forceAuto);
149
+ if (plan.steps.length > 0) {
150
+ sendPlan({ steps: plan.steps });
151
+ }
152
+ }
153
+ catch (e) {
154
+ logger.error('Planning failed, falling back to legacy logic', e);
155
+ }
156
+ }
157
+ let reply = '';
158
+ let accumulatedArtifacts = [];
159
+ // 2. Execute Plan or Fallback
160
+ if (plan.intent === 'multi_step' || (plan.intent === 'single' && plan.steps.length > 0)) {
161
+ for (const step of plan.steps) {
162
+ if (this.sessionManager.isSessionStopped(session.id)) {
163
+ log('[Agent] Session stopped by user.');
164
+ return 'Session stopped by user.';
165
+ }
166
+ step.status = 'in_progress';
167
+ sendPlan({ steps: plan.steps });
168
+ let retryCount = 0;
169
+ const maxRetries = 2;
170
+ let success = false;
171
+ const stepStartTime = Date.now();
172
+ while (retryCount <= maxRetries && !success) {
173
+ try {
174
+ if (retryCount > 0) {
175
+ log(`[Agent] Retry ${retryCount}/${maxRetries} for step: ${step.description}`);
176
+ }
177
+ else {
178
+ log(`[${step.tool}] ${step.description}`);
179
+ }
180
+ const result = await this.executeStep(step, userId, session, log, onProgress, accumulatedArtifacts);
181
+ // Accumulate artifacts
182
+ if (result.artifacts && result.artifacts.length > 0) {
183
+ accumulatedArtifacts.push(...result.artifacts);
184
+ }
185
+ const duration = Date.now() - stepStartTime;
186
+ // Estimate tokens based on result length if string, or use actual usage
187
+ const tokens = result.usage
188
+ ? (result.usage.completionTokens + (result.usage.promptTokens || 0))
189
+ : (typeof result.output === 'string' ? Math.ceil(result.output.length / 4) : 0);
190
+ log(`[${step.tool}] Step completed`, { duration, tokens });
191
+ step.status = 'completed';
192
+ step.result = result.output;
193
+ success = true;
194
+ if (step.tool === 'Chat') {
195
+ reply = result.output;
196
+ }
197
+ }
198
+ catch (e) {
199
+ retryCount++;
200
+ const errorMsg = String(e);
201
+ const duration = Date.now() - stepStartTime;
202
+ logger.error(`Step failed (Attempt ${retryCount}): ${step.description}`, e);
203
+ if (retryCount > maxRetries) {
204
+ step.status = 'failed';
205
+ step.error = errorMsg;
206
+ log(`[Error] Step failed permanently: ${step.description}`, { duration });
207
+ }
208
+ else {
209
+ log(`[Warning] Step failed, retrying... (${errorMsg})`, { duration });
210
+ // Wait a bit before retry
211
+ await new Promise(resolve => setTimeout(resolve, 1000));
212
+ }
213
+ }
214
+ }
215
+ sendPlan({ steps: plan.steps });
216
+ }
217
+ if (!reply) {
218
+ // If no chat step, summarize results
219
+ const completedSteps = plan.steps.filter(s => s.status === 'completed');
220
+ const failedSteps = plan.steps.filter(s => s.status === 'failed');
221
+ let summary = "I have completed the requested tasks.\n\n";
222
+ if (completedSteps.length > 0) {
223
+ summary += "**Completed:**\n" + completedSteps.map(s => `- ${s.description}`).join('\n') + "\n";
224
+ }
225
+ if (failedSteps.length > 0) {
226
+ summary += "\n**Failed:**\n" + failedSteps.map(s => `- ${s.description}: ${s.error}`).join('\n');
227
+ }
228
+ reply = summary;
229
+ const metadata = accumulatedArtifacts.length > 0 ? { attachments: accumulatedArtifacts } : undefined;
230
+ this.sessionManager.addMessage(session.id, 'assistant', reply, metadata);
231
+ }
232
+ }
233
+ else {
234
+ // Legacy logic fallback
235
+ reply = await this.executeLegacyLogic(session, userId, message, log, onProgress) || '';
236
+ }
237
+ // If we have a reply from Plan or Legacy, we are done.
238
+ if (reply) {
239
+ // Trigger evolution if needed (Post-processing)
240
+ await this.handlePostProcessing(session, userId, message, reply, log, onProgress);
241
+ }
242
+ return reply || 'I was unable to generate a response.';
243
+ }
244
+ async createPlan(message, log, forceAuto = false) {
245
+ const startTime = Date.now();
246
+ const prompt = `
247
+ You are a planning engine for a research agent.
248
+ User Request: "${message}"
249
+ Force Auto Mode: ${forceAuto}
250
+
251
+ Available Tools:
252
+ - LiteratureReview(topic): Search for papers/web.
253
+ - PaperAnalysis(title): Analyze a specific paper in depth.
254
+ - ConceptExplainer(concept): Explain a scientific concept.
255
+ - PdfGenerator(title, content): Generate a PDF report.
256
+ - CodeAnalysis(path): Analyze project structure/code.
257
+ - MemorySearch(query): Search past memories.
258
+ - FileOps(operation): Organize files.
259
+ - AgentOrchestration(operation): Create/manage sub-agents.
260
+ - Evolution(intent): Create new skills.
261
+ - AutoResearch(topic, iterations): Continuously optimize and improve a research report in a loop.
262
+ - Chat(message): Reply to user (final step).
263
+
264
+ Return a JSON plan:
265
+ {
266
+ "intent": "single" | "multi_step",
267
+ "steps": [
268
+ {
269
+ "id": "1",
270
+ "description": "Concise action description",
271
+ "tool": "ToolName",
272
+ "params": { ... }
273
+ }
274
+ ]
275
+ }
276
+
277
+ Rules:
278
+ 1. If 'Force Auto Mode' is true, you MUST use the 'AutoResearch' tool as the primary step.
279
+ 2. If the user asks for a PDF, ALWAYS include a 'PdfGenerator' step followed by a 'Chat' step.
280
+ 3. The 'Chat' step message MUST explicitly mention the generated file and include a placeholder link like '[Title](...)' to indicate where it can be downloaded.
281
+ 4. If the user wants to test PDF generation directly or asks for a PDF without confirmation, just generate it.
282
+ `;
283
+ try {
284
+ const response = await this.llm.chat([{ role: 'user', content: prompt }]);
285
+ // Log stats
286
+ const duration = Date.now() - startTime;
287
+ const tokens = response.usage?.completionTokens || Math.ceil(response.content.length / 4);
288
+ if (log) {
289
+ log(`[Agent] Created plan`, { duration, tokens, operation: 'planning' });
290
+ }
291
+ let text = response.content.trim();
292
+ if (text.startsWith('```')) {
293
+ text = text.replace(/^```(json)?/, '').replace(/```$/, '');
294
+ }
295
+ const plan = JSON.parse(text);
296
+ return plan;
297
+ }
298
+ catch (e) {
299
+ logger.error('Planning failed:', e);
300
+ return { intent: 'single', steps: [] };
301
+ }
302
+ }
303
+ async executeStep(step, userId, session, log, onProgress, accumulatedArtifacts = []) {
304
+ let output = '';
305
+ let artifacts = [];
306
+ let usage;
307
+ switch (step.tool) {
308
+ case 'LiteratureReview':
309
+ output = await this.executeLiteratureReview(session, userId, step.params.topic, log, onProgress);
310
+ break;
311
+ case 'ConceptExplainer':
312
+ const ceResult = await this.skillManager.executeSkill('concept_explainer', userId, { concept: step.params.concept });
313
+ output = ceResult.formatted_output;
314
+ break;
315
+ case 'PdfGenerator':
316
+ const pdfResult = await this.skillManager.executeSkill('pdf_generator', userId, { title: step.params.title, content: step.params.content }, (type, content) => log(`[Skill] ${content}`));
317
+ output = pdfResult.formatted_output;
318
+ if (pdfResult.url && pdfResult.file_path) {
319
+ // Ensure URL is valid (gateway url + relative path)
320
+ const url = pdfResult.url.startsWith('/') ? pdfResult.url : `/${pdfResult.url}`;
321
+ // Use absolute URL if needed, but relative is fine for same origin
322
+ artifacts.push({
323
+ id: `file-${Date.now()}`,
324
+ name: `${step.params.title || 'document'}.pdf`,
325
+ type: 'file',
326
+ url: `http://localhost:4000${url}`,
327
+ path: pdfResult.file_path,
328
+ mimeType: 'application/pdf'
329
+ });
330
+ }
331
+ break;
332
+ case 'CodeAnalysis':
333
+ const caResult = await this.skillManager.executeSkill('code_analysis', userId, { path: step.params.path || '.', operation: 'structure' });
334
+ output = `Project Structure:\n${caResult.structure}`;
335
+ break;
336
+ case 'MemorySearch':
337
+ const msResult = await this.skillManager.executeSkill('memory_management', userId, { operation: 'search', query: step.params.query });
338
+ output = JSON.stringify(msResult.results);
339
+ break;
340
+ case 'FileOps':
341
+ const foResult = await this.skillManager.executeSkill('local_file_ops', userId, { operation: step.params.operation });
342
+ output = `Moved ${foResult.moved} files.`;
343
+ break;
344
+ case 'AgentOrchestration':
345
+ output = "Agent orchestration not fully implemented in plan yet.";
346
+ break;
347
+ case 'Evolution':
348
+ output = "Evolution not fully implemented in plan yet.";
349
+ break;
350
+ case 'AutoResearch':
351
+ const topic = step.params.topic || 'General Research';
352
+ const iterations = Math.min(step.params.iterations || 3, 5); // Limit to 5
353
+ log(`[AutoResearch] Starting continuous optimization loop for "${topic}" (${iterations} rounds)...`);
354
+ // Notify session that auto mode is active
355
+ // We can use a special log or message that the frontend parses?
356
+ // Or better, we just send logs. Ideally, we'd have a session status.
357
+ // For now, let's just log it clearly.
358
+ let currentContent = `Initial draft for ${topic}.`;
359
+ for (let i = 1; i <= iterations; i++) {
360
+ if (this.sessionManager.isSessionStopped(session.id)) {
361
+ log('[AutoResearch] Session stopped by user.');
362
+ output = `Auto-research stopped by user after ${i - 1} iterations.`;
363
+ break;
364
+ }
365
+ // Check if session is still active/not stopped?
366
+ // Currently we don't have a cancellation token passed down here.
367
+ // But we can check session state if we had it.
368
+ log(`[AutoResearch] Round ${i}/${iterations}: Analyzing and improving...`);
369
+ // 1. Plan Improvement
370
+ const improvePrompt = `
371
+ You are optimizing a research report on "${topic}".
372
+ Current Round: ${i}/${iterations}
373
+ Current Content Length: ${currentContent.length} chars.
374
+
375
+ Goal: Identify ONE specific area to improve (e.g., "Add recent statistics", "Explain concept X better", "Find a case study").
376
+ Return ONLY the improvement task description.
377
+ `;
378
+ const planRes = await this.llm.chat([{ role: 'user', content: improvePrompt }]);
379
+ const improvementTask = planRes.content.trim();
380
+ log(`[AutoResearch] Improvement Task: ${improvementTask}`);
381
+ // 2. Execute Improvement (Simulated via LLM or Skill)
382
+ // For now, we use LLM to expand/refine based on the task
383
+ const refinePrompt = `
384
+ You are an expert researcher.
385
+ Topic: ${topic}
386
+ Current Content:
387
+ ${currentContent}
388
+
389
+ Task: ${improvementTask}
390
+
391
+ Action: Perform the task and rewrite the FULL content to include the new information. Make it better, more detailed, and academic.
392
+ `;
393
+ const refineRes = await this.llm.chat([{ role: 'user', content: refinePrompt }]);
394
+ currentContent = refineRes.content;
395
+ // 3. Generate Intermediate PDF
396
+ const title = `${topic} - v${i}`;
397
+ log(`[AutoResearch] Generating PDF version ${i}...`);
398
+ const pdfRes = await this.skillManager.executeSkill('pdf_generator', userId, { title, content: currentContent }, (type, content) => log(`[Skill] ${content}`));
399
+ if (pdfRes.url && pdfRes.file_path) {
400
+ const url = pdfRes.url.startsWith('/') ? pdfRes.url : `/${pdfRes.url}`;
401
+ const artifact = {
402
+ id: `file-${Date.now()}`,
403
+ name: `${title}.pdf`,
404
+ type: 'file',
405
+ url: `http://localhost:4000${url}`,
406
+ path: pdfRes.file_path,
407
+ mimeType: 'application/pdf'
408
+ };
409
+ artifacts.push(artifact);
410
+ accumulatedArtifacts.push(artifact); // Add to global list
411
+ // Send intermediate update to chat
412
+ this.sessionManager.addMessage(session.id, 'assistant', `Round ${i} Complete: I have improved the document based on "${improvementTask}".\n\n[Download ${title}.pdf](${artifact.url})`, { attachments: [artifact] });
413
+ }
414
+ }
415
+ output = `Auto-research completed after ${iterations} iterations. Final content length: ${currentContent.length}`;
416
+ break;
417
+ case 'Chat': {
418
+ // Use direct LLM call to avoid recursion loop
419
+ // But we need context.
420
+ const context = await this.memoryManager.getFormattedMemories(userId, step.params.message);
421
+ // Include session history
422
+ const history = this.sessionManager.getHistory(session.id, 10);
423
+ const historyText = history.map(m => `${m.role.toUpperCase()}: ${m.content}`).join('\n');
424
+ // Inject artifact info into system prompt so LLM knows what was generated
425
+ let artifactContext = '';
426
+ if (accumulatedArtifacts.length > 0) {
427
+ artifactContext = `
428
+ [SYSTEM NOTICE]
429
+ The following files have been generated and are attached to this response:
430
+ ${accumulatedArtifacts.map(a => `- ${a.name} (${a.url})`).join('\n')}
431
+
432
+ IMPORTANT INSTRUCTIONS FOR YOUR REPLY:
433
+ 1. You MUST explicitly mention that you have generated these files.
434
+ 2. You MUST include a markdown link to the file in your response using the format: [Filename.pdf](URL)
435
+ 3. Do not just say "I have attached the file", but provide the clickable link in the text.
436
+ `;
437
+ }
438
+ const response = await this.llm.chat([
439
+ { role: 'system', content: `You are Redigg. Context: ${context}\n\nSession History:\n${historyText}${artifactContext}` },
440
+ { role: 'user', content: step.params.message }
441
+ ]);
442
+ const reply = response.content;
443
+ usage = response.usage;
444
+ // Attach accumulated artifacts to the final chat message
445
+ // Make sure to attach artifacts to metadata so they are persisted
446
+ const metadata = accumulatedArtifacts.length > 0 ? { attachments: accumulatedArtifacts } : undefined;
447
+ this.sessionManager.addMessage(session.id, 'assistant', reply, metadata);
448
+ output = reply;
449
+ break;
450
+ }
451
+ default:
452
+ throw new Error(`Unknown tool: ${step.tool}`);
453
+ }
454
+ return { output, artifacts, usage };
455
+ }
456
+ async handlePostProcessing(session, userId, message, reply, log, onProgress) {
457
+ // Evolve Memory (Async)
458
+ try {
459
+ const result = await this.memoryEvo.evolve(userId, message, reply, (msg) => log(msg));
460
+ if (result && result.added && result.added.length > 0) {
461
+ // log(`[Evolution] Extracted ${result.added.length} new memories.`); // Redundant as memoryEvo logs it now
462
+ }
463
+ await this.memoryManager.consolidateMemories(userId).catch(e => logger.error('Consolidation failed', e));
464
+ }
465
+ catch (err) {
466
+ logger.error('Memory evolution failed:', err);
467
+ }
468
+ }
469
+ async executeLegacyLogic(session, userId, message, log, onProgress) {
470
+ const lowerMsg = message.toLowerCase();
471
+ // 1. Research Skills / Web Search
472
+ if (lowerMsg.includes('analyze paper') || lowerMsg.includes('summary of paper') || lowerMsg.includes('critique paper')) {
473
+ const title = message.replace(/\b(analyze paper|summary of paper|critique paper|about|on)\b/gi, '').trim();
474
+ if (title.length > 3) {
475
+ log(`[Agent] Analyzing paper: "${title}"`);
476
+ const result = await this.skillManager.executeSkill('paper_analysis', userId, { paper_title: title });
477
+ this.sessionManager.addMessage(session.id, 'assistant', result.formatted_output);
478
+ return result.formatted_output;
479
+ }
480
+ }
481
+ if (lowerMsg.startsWith('explain') || lowerMsg.includes('what is') || lowerMsg.includes('concept of')) {
482
+ // Simple heuristic: if it looks like a concept question
483
+ // But "what is your name" is conversational.
484
+ if (!lowerMsg.includes('your name') && !lowerMsg.includes('the time')) {
485
+ const concept = message.replace(/\b(explain|what is|concept of|tell me about)\b/gi, '').trim();
486
+ // Let's rely on LLM decision engine usually, but here we can force it if explicitly asked "explain X"
487
+ if (lowerMsg.startsWith('explain')) {
488
+ log(`[Agent] Explaining concept: "${concept}"`);
489
+ const result = await this.skillManager.executeSkill('concept_explainer', userId, { concept });
490
+ this.sessionManager.addMessage(session.id, 'assistant', result.formatted_output);
491
+ return result.formatted_output;
492
+ }
493
+ }
494
+ }
495
+ if (lowerMsg.includes('literature review') || lowerMsg.includes('search papers') || message.includes('[WEB SEARCH REQUEST]')) {
496
+ let topic = message.replace(/\b(do a|perform a|literature review|search papers|about|on)\b/gi, '').trim().replace(/\s+/g, ' ');
497
+ if (message.includes('[WEB SEARCH REQUEST]')) {
498
+ topic = message.replace('[WEB SEARCH REQUEST]', '').split('\n')[0].trim(); // Extract first line as topic usually
499
+ // Clean up the prompt suffix if present
500
+ topic = topic.replace('Please perform a literature review or web search to answer this question.', '').trim();
501
+ }
502
+ if (topic.length > 3) {
503
+ return this.executeLiteratureReview(session, userId, topic, log, onProgress);
504
+ }
505
+ }
506
+ // 2. Infra Skills
507
+ if (lowerMsg.includes('analyze code') || lowerMsg.includes('project structure')) {
508
+ try {
509
+ const targetPath = '.';
510
+ logger.info(`Analyzing code in ${targetPath}...`);
511
+ const startTime = Date.now();
512
+ log(`[Agent] Analyzing code in ${targetPath}...`);
513
+ const result = await this.skillManager.executeSkill('code_analysis', userId, { path: targetPath, operation: 'structure' });
514
+ const duration = Date.now() - startTime;
515
+ const tokens = Math.ceil(result.structure.length / 4);
516
+ log(`[Agent] Completed Code Analysis`, { duration, tokens, operation: 'code_analysis' });
517
+ const response = `Here is the project structure:\n\`\`\`\n${result.structure}\n\`\`\``;
518
+ this.sessionManager.addMessage(session.id, 'assistant', response);
519
+ return response;
520
+ }
521
+ catch (e) {
522
+ logger.error('Skill execution failed:', e);
523
+ }
524
+ }
525
+ if (lowerMsg.includes('organize files') || lowerMsg.includes('move pdfs')) {
526
+ try {
527
+ logger.info('Organizing files...');
528
+ const startTime = Date.now();
529
+ log('[Agent] Organizing files...');
530
+ const result = await this.skillManager.executeSkill('local_file_ops', userId, { operation: 'organize' });
531
+ const duration = Date.now() - startTime;
532
+ log(`[Agent] Completed File Organization`, { duration, tokens: 0, operation: 'file_ops' });
533
+ const response = `I have organized your PDF files into a 'papers' folder. Moved ${result.moved} files.`;
534
+ this.sessionManager.addMessage(session.id, 'assistant', response);
535
+ return response;
536
+ }
537
+ catch (e) {
538
+ logger.error('Skill execution failed:', e);
539
+ }
540
+ }
541
+ // 3. Core Skills (Memory, Agents, Evolution)
542
+ if (lowerMsg.includes('search memories') || lowerMsg.includes('recall')) {
543
+ try {
544
+ const query = message.replace(/\b(search memories|recall|find memory about)\b/gi, '').trim();
545
+ logger.info(`Searching memories for "${query}"...`);
546
+ const startTime = Date.now();
547
+ log(`[Agent] Searching memories for "${query}"...`);
548
+ const result = await this.skillManager.executeSkill('memory_management', userId, {
549
+ operation: 'search',
550
+ query
551
+ });
552
+ const duration = Date.now() - startTime;
553
+ const memories = result.results;
554
+ const tokens = Math.ceil(JSON.stringify(memories).length / 4);
555
+ log(`[Agent] Completed Memory Search`, { duration, tokens, operation: 'memory_search' });
556
+ let response = '';
557
+ if (memories.length === 0) {
558
+ response = `I couldn't find any memories matching "${query}".`;
559
+ }
560
+ else {
561
+ response = `Here are the memories I found:\n\n${memories.map(m => `- [${m.tier}] ${m.content} (${new Date(m.created_at).toLocaleDateString()})`).join('\n')}`;
562
+ }
563
+ this.sessionManager.addMessage(session.id, 'assistant', response);
564
+ return response;
565
+ }
566
+ catch (e) {
567
+ logger.error('Memory search failed:', e);
568
+ }
569
+ }
570
+ if (lowerMsg.includes('create agent') || lowerMsg.includes('sub-agent') || lowerMsg.includes('delegate') || lowerMsg.includes('list agents')) {
571
+ try {
572
+ if (lowerMsg.includes('create agent')) {
573
+ const nameMatch = message.match(/named\s+["']?(\w+)["']?/i);
574
+ const roleMatch = message.match(/role\s+of\s+["']?([\w\s]+)["']?/i);
575
+ const name = nameMatch ? nameMatch[1] : 'Assistant';
576
+ const role = roleMatch ? roleMatch[1] : 'Generalist';
577
+ const result = await this.skillManager.executeSkill('agent_orchestration', userId, {
578
+ operation: 'create_agent',
579
+ name,
580
+ role
581
+ });
582
+ const response = `Created sub-agent ${result.name} (ID: ${result.agentId})`;
583
+ this.sessionManager.addMessage(session.id, 'assistant', response);
584
+ return response;
585
+ }
586
+ else if (lowerMsg.includes('list agents')) {
587
+ const result = await this.skillManager.executeSkill('agent_orchestration', userId, {
588
+ operation: 'list_agents'
589
+ });
590
+ const agents = result.agents;
591
+ const response = `Active Agents:\n${agents.map(a => `- ${a.name} (${a.role})`).join('\n')}`;
592
+ this.sessionManager.addMessage(session.id, 'assistant', response);
593
+ return response;
594
+ }
595
+ }
596
+ catch (e) {
597
+ logger.error('Orchestration failed:', e);
598
+ }
599
+ }
600
+ if (lowerMsg.includes('can you') || lowerMsg.includes('how do i') || lowerMsg.includes('evolve')) {
601
+ logger.info('Checking if I need to learn a new skill or evolve...');
602
+ log('[Agent] Checking if I need to learn a new skill or evolve...');
603
+ try {
604
+ const intent = message.replace(/\b(can you|how do i|evolve|create a skill to)\b/gi, '').trim();
605
+ if (intent.length > 5) {
606
+ const result = await this.skillManager.executeSkill('evolution', userId, {
607
+ operation: 'create_skill',
608
+ intent
609
+ });
610
+ if (result.success) {
611
+ const response = `I've evolved! ${result.message} (Skill ID: ${result.skillId})`;
612
+ this.sessionManager.addMessage(session.id, 'assistant', response);
613
+ return response;
614
+ }
615
+ }
616
+ }
617
+ catch (e) {
618
+ // Fallback
619
+ }
620
+ }
621
+ // 4. Intelligent Default: Web Search for Unknown Topics
622
+ // Check if we have relevant memories. Strict search (no fallback to recent).
623
+ // This implements the "Default to Search" behavior for new topics.
624
+ const strictMemories = await this.memoryManager.searchMemories(userId, message, { limit: 1 });
625
+ const hasContext = strictMemories.length > 0;
626
+ const isConversational = /^(hello|hi|hey|thanks|thank you|bye|goodbye|ok|okay|yes|no|cool|great|wow|who are you|what are you)\b/i.test(message.trim().replace(/[!.?]+$/, ''));
627
+ if (!hasContext && !isConversational) {
628
+ log('[Agent] No local knowledge found. Checking if web search is needed...');
629
+ const decision = await this.shouldSearch(message, log);
630
+ if (decision.shouldSearch) {
631
+ logger.info(`Implicit intent: Web Search on "${decision.topic}"`);
632
+ log(`[Agent] Decided to search web for: "${decision.topic}"`);
633
+ return this.executeLiteratureReview(session, userId, decision.topic, log, onProgress);
634
+ }
635
+ else {
636
+ log('[Agent] Decided not to search web. Generating response...');
637
+ }
638
+ }
639
+ // 5. Fallback: LLM Chat
640
+ logger.info(`Retrieving context for user ${userId}...`);
641
+ log(`[Agent] Retrieving context for user ${userId}...`);
642
+ const context = await this.memoryManager.getFormattedMemories(userId, message);
643
+ // Retrieve Session History
644
+ const history = this.sessionManager.getHistory(session.id, 5); // Last 5 messages
645
+ const historyText = history.map(m => `${m.role.toUpperCase()}: ${m.content}`).join('\n');
646
+ // Build Prompt
647
+ const systemPrompt = `
648
+ You are Redigg, an autonomous research agent.
649
+ Your goal is to assist researchers by providing accurate, insightful, and personalized responses.
650
+
651
+ User Context & Preferences:
652
+ ${context || 'No prior context available.'}
653
+
654
+ Session History:
655
+ ${historyText}
656
+
657
+ Instructions:
658
+ - Use the provided context to tailor your response.
659
+ - Be concise and scientific.
660
+ - If you don't know something, admit it.
661
+ `.trim();
662
+ // Generate Response
663
+ logger.info(`Generating response...`);
664
+ log(`[Agent] Generating response...`);
665
+ let reply = '';
666
+ if (this.llm.chatStream && onProgress) {
667
+ await this.llm.chatStream([
668
+ { role: 'system', content: systemPrompt },
669
+ { role: 'user', content: message }
670
+ ], {
671
+ onToken: (token) => {
672
+ reply += token;
673
+ onProgress('token', token);
674
+ },
675
+ onError: (err) => logger.error(String(err))
676
+ });
677
+ }
678
+ else {
679
+ const response = await this.llm.chat([
680
+ { role: 'system', content: systemPrompt },
681
+ { role: 'user', content: message }
682
+ ]);
683
+ reply = response.content;
684
+ }
685
+ // Save response to session
686
+ this.sessionManager.addMessage(session.id, 'assistant', reply);
687
+ // Evolve Memory (Async - now awaited to ensure logs are streamed)
688
+ try {
689
+ const result = await this.memoryEvo.evolve(userId, message, reply, (msg) => log(msg));
690
+ if (result && result.added && result.added.length > 0) {
691
+ log(`[Evolution] Extracted ${result.added.length} new memories.`);
692
+ result.added.forEach((m) => {
693
+ log(`[Evolution] New Memory: "${m.content}" (${m.type}/${m.tier})`);
694
+ });
695
+ // Silent execution: no chat message for memory updates
696
+ }
697
+ if (result && result.updated && result.updated.length > 0) {
698
+ log(`[Evolution] Updated ${result.updated.length} memories.`);
699
+ result.updated.forEach((m) => {
700
+ log(`[Evolution] Updated Memory: "${m.content}" (${m.type}/${m.tier})`);
701
+ });
702
+ }
703
+ // Trigger memory consolidation immediately after new interaction
704
+ await this.memoryManager.consolidateMemories(userId).then(() => {
705
+ // logger.debug('Post-chat consolidation complete');
706
+ }).catch(e => {
707
+ logger.error('Post-chat consolidation failed', e);
708
+ });
709
+ // After response and memory evolution, generate a title for the session if it's still generic
710
+ if (session.messages.length <= 4 && (session.title || '').length > 20) { // Early in convo or long default title
711
+ const title = await this.generateSessionTitle(session, message, reply);
712
+ if (title) {
713
+ session.title = title;
714
+ onProgress?.('token', `[TITLE_GENERATED]${title}`);
715
+ }
716
+ }
717
+ }
718
+ catch (err) {
719
+ logger.error('Memory evolution failed:', err);
720
+ }
721
+ return reply;
722
+ }
723
+ async generateSessionTitle(session, userMsg, agentMsg) {
724
+ try {
725
+ const prompt = `Summarize the following conversation into a short, 3-5 word title. Do not use quotes.
726
+ User: ${userMsg}
727
+ Agent: ${agentMsg}
728
+ Title:`;
729
+ const response = await this.llm.chat([{ role: 'user', content: prompt }]);
730
+ return response.content.trim();
731
+ }
732
+ catch (e) {
733
+ return null;
734
+ }
735
+ }
736
+ async executeLiteratureReview(session, userId, topic, log, onProgress) {
737
+ logger.info(`Detected intent: Literature Review on "${topic}"`);
738
+ const startTime = Date.now();
739
+ log(`[Agent] Detected intent: Literature Review (Web Search) on "${topic}"`);
740
+ try {
741
+ const result = await this.skillManager.executeSkill('academic_survey_self_improve', userId, { topic }, {
742
+ onLog: (type, content) => log(`[Skill] ${content}`),
743
+ onProgress: async (progress, description, metadata) => {
744
+ log(`[Skill Progress] ${progress}% - ${description}`, metadata);
745
+ if (metadata && metadata.papers) {
746
+ // Emit todo/progress update for UI
747
+ onProgress?.('todo', {
748
+ id: 'research-progress',
749
+ type: 'research',
750
+ status: 'in_progress',
751
+ content: `Found ${metadata.papers.length} papers`,
752
+ metadata: metadata
753
+ });
754
+ }
755
+ },
756
+ onTodo: async (content, priority, step) => {
757
+ onProgress?.('todo', {
758
+ id: `skill-todo-${Date.now()}`,
759
+ status: 'pending',
760
+ content,
761
+ priority
762
+ });
763
+ }
764
+ });
765
+ const duration = Date.now() - startTime;
766
+ const tokens = Math.ceil(result.summary.length / 4); // Estimate
767
+ log(`[Agent] Completed Literature Review`, { duration, tokens, operation: 'literature_review' });
768
+ const response = `Here is a literature review on "${topic}":\n\n${result.summary}\n\n**Sources:**\n${result.papers.map((p) => `- [${p.title}](${p.url || '#'}) (${p.year})`).join('\n')}`;
769
+ // Perform Quality Check
770
+ const quality = await this.qualityManager.evaluateTask(`Literature Review on "${topic}"`, result.summary, { papersCount: result.papers.length });
771
+ if (!quality.passed) {
772
+ log(`[Quality] Warning: Score ${quality.score}/100. ${quality.reasoning}`);
773
+ const warning = `\n\n> ⚠️ **Quality Check**: This review scored ${quality.score}/100. ${quality.suggestions[0] || ''}`;
774
+ this.sessionManager.addMessage(session.id, 'assistant', response + warning);
775
+ return response + warning;
776
+ }
777
+ this.sessionManager.addMessage(session.id, 'assistant', response);
778
+ return response;
779
+ }
780
+ catch (e) {
781
+ logger.error('Skill execution failed:', e);
782
+ const errorMsg = "I encountered an error while searching for papers.";
783
+ this.sessionManager.addMessage(session.id, 'assistant', errorMsg);
784
+ return errorMsg;
785
+ }
786
+ }
787
+ async shouldSearch(message, log) {
788
+ const prompt = `
789
+ You are a decision engine for a research agent.
790
+ The user sent: "${message}"
791
+ We have NO local memory/context about this topic.
792
+
793
+ Should we perform a web search to answer this?
794
+ - YES if it asks for facts, news, definitions, explanations of concepts, or research.
795
+ - NO if it is conversational (greeting, thanks), personal ("who are you"), or asks about "this project" or "code" (which should have been caught by other skills).
796
+
797
+ Reply strictly in this format:
798
+ SEARCH: <topic>
799
+ or
800
+ NO_SEARCH
801
+ `;
802
+ try {
803
+ if (log)
804
+ log('[Agent] Thinking about whether to search the web...');
805
+ const res = await this.llm.chat([{ role: 'user', content: prompt }]);
806
+ console.log('[DEBUG] shouldSearch response:', res);
807
+ const text = res.content.trim();
808
+ if (text.startsWith('SEARCH:')) {
809
+ return { shouldSearch: true, topic: text.replace('SEARCH:', '').trim() };
810
+ }
811
+ }
812
+ catch (e) {
813
+ logger.error('Decision engine failed:', e);
814
+ }
815
+ return { shouldSearch: false, topic: '' };
816
+ }
817
+ }
818
+ //# sourceMappingURL=ResearchAgent.js.map