@tyvm/knowhow 0.0.56 → 0.0.59

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 (190) hide show
  1. package/package.json +3 -3
  2. package/src/agents/base/base.ts +87 -43
  3. package/src/agents/tools/execCommand.ts +17 -14
  4. package/src/agents/tools/googleSearch.ts +1 -0
  5. package/src/agents/tools/index.ts +1 -0
  6. package/src/agents/tools/lazy/definitions.ts +63 -0
  7. package/src/agents/tools/lazy/disableTools.ts +16 -0
  8. package/src/agents/tools/lazy/enableTools.ts +16 -0
  9. package/src/agents/tools/lazy/index.ts +3 -0
  10. package/src/agents/tools/lazy/listAvailableTools.ts +14 -0
  11. package/src/agents/tools/list.ts +2 -0
  12. package/src/agents/tools/mcp/connectMcpServer.ts +40 -0
  13. package/src/agents/tools/mcp/definitions.ts +67 -0
  14. package/src/agents/tools/mcp/disconnectMcpServer.ts +40 -0
  15. package/src/agents/tools/mcp/index.ts +3 -0
  16. package/src/agents/tools/mcp/listAvailableMcpServers.ts +28 -0
  17. package/src/agents/tools/writeFile.ts +4 -1
  18. package/src/chat/CliChatService.ts +8 -3
  19. package/src/chat/modules/AgentModule.ts +74 -296
  20. package/src/cli.ts +33 -10
  21. package/src/plugins/GitPlugin.ts +30 -24
  22. package/src/plugins/language.ts +95 -18
  23. package/src/processors/ToolResponseCache.ts +98 -79
  24. package/src/processors/tools/grepToolResponse.ts +99 -0
  25. package/src/processors/tools/index.ts +21 -0
  26. package/src/processors/tools/jqToolResponse.ts +124 -0
  27. package/src/processors/tools/listStoredToolResponses.ts +83 -0
  28. package/src/processors/tools/tailToolResponse.ts +75 -0
  29. package/src/services/AgentService.ts +1 -1
  30. package/src/services/AgentSynchronization.ts +291 -0
  31. package/src/services/DockerService.ts +37 -1
  32. package/src/services/EventService.ts +8 -2
  33. package/src/services/KnowhowClient.ts +141 -1
  34. package/src/services/LazyToolsService.ts +146 -0
  35. package/src/services/Mcp.ts +171 -4
  36. package/src/services/SessionManager.ts +287 -0
  37. package/src/services/TaskRegistry.ts +108 -0
  38. package/src/services/Tools.ts +2 -0
  39. package/src/services/index.ts +7 -0
  40. package/src/services/script-execution/ScriptExecutor.ts +7 -5
  41. package/src/types.ts +1 -0
  42. package/src/utils/InputQueueManager.ts +91 -57
  43. package/src/utils/errors.ts +0 -0
  44. package/src/utils/index.ts +11 -0
  45. package/src/worker.ts +12 -0
  46. package/tests/compressor/bigstring.test.ts +100 -0
  47. package/tests/compressor/bigstring.txt +1 -0
  48. package/tests/plugins/language/languagePlugin-content-triggers.test.ts +13 -5
  49. package/tests/plugins/language/languagePlugin-integration.test.ts +22 -7
  50. package/tests/plugins/language/languagePlugin.test.ts +11 -4
  51. package/tests/processors/ToolResponseCache.test.ts +128 -0
  52. package/tests/unit/InputQueueManager.test.ts +174 -0
  53. package/ts_build/package.json +3 -3
  54. package/ts_build/src/agents/base/base.d.ts +10 -0
  55. package/ts_build/src/agents/base/base.js +66 -34
  56. package/ts_build/src/agents/base/base.js.map +1 -1
  57. package/ts_build/src/agents/tools/execCommand.js +1 -9
  58. package/ts_build/src/agents/tools/execCommand.js.map +1 -1
  59. package/ts_build/src/agents/tools/github/index.d.ts +1 -1
  60. package/ts_build/src/agents/tools/googleSearch.d.ts +1 -0
  61. package/ts_build/src/agents/tools/googleSearch.js +1 -0
  62. package/ts_build/src/agents/tools/googleSearch.js.map +1 -1
  63. package/ts_build/src/agents/tools/index.d.ts +1 -0
  64. package/ts_build/src/agents/tools/index.js +1 -0
  65. package/ts_build/src/agents/tools/index.js.map +1 -1
  66. package/ts_build/src/agents/tools/lazy/definitions.d.ts +5 -0
  67. package/ts_build/src/agents/tools/lazy/definitions.js +58 -0
  68. package/ts_build/src/agents/tools/lazy/definitions.js.map +1 -0
  69. package/ts_build/src/agents/tools/lazy/disableTools.d.ts +9 -0
  70. package/ts_build/src/agents/tools/lazy/disableTools.js +15 -0
  71. package/ts_build/src/agents/tools/lazy/disableTools.js.map +1 -0
  72. package/ts_build/src/agents/tools/lazy/enableTools.d.ts +9 -0
  73. package/ts_build/src/agents/tools/lazy/enableTools.js +15 -0
  74. package/ts_build/src/agents/tools/lazy/enableTools.js.map +1 -0
  75. package/ts_build/src/agents/tools/lazy/index.d.ts +3 -0
  76. package/ts_build/src/agents/tools/lazy/index.js +20 -0
  77. package/ts_build/src/agents/tools/lazy/index.js.map +1 -0
  78. package/ts_build/src/agents/tools/lazy/listAvailableTools.d.ts +11 -0
  79. package/ts_build/src/agents/tools/lazy/listAvailableTools.js +15 -0
  80. package/ts_build/src/agents/tools/lazy/listAvailableTools.js.map +1 -0
  81. package/ts_build/src/agents/tools/list.js +2 -0
  82. package/ts_build/src/agents/tools/list.js.map +1 -1
  83. package/ts_build/src/agents/tools/mcp/connectMcpServer.d.ts +5 -0
  84. package/ts_build/src/agents/tools/mcp/connectMcpServer.js +31 -0
  85. package/ts_build/src/agents/tools/mcp/connectMcpServer.js.map +1 -0
  86. package/ts_build/src/agents/tools/mcp/definitions.d.ts +2 -0
  87. package/ts_build/src/agents/tools/mcp/definitions.js +62 -0
  88. package/ts_build/src/agents/tools/mcp/definitions.js.map +1 -0
  89. package/ts_build/src/agents/tools/mcp/disconnectMcpServer.d.ts +5 -0
  90. package/ts_build/src/agents/tools/mcp/disconnectMcpServer.js +31 -0
  91. package/ts_build/src/agents/tools/mcp/disconnectMcpServer.js.map +1 -0
  92. package/ts_build/src/agents/tools/mcp/index.d.ts +3 -0
  93. package/ts_build/src/agents/tools/mcp/index.js +10 -0
  94. package/ts_build/src/agents/tools/mcp/index.js.map +1 -0
  95. package/ts_build/src/agents/tools/mcp/listAvailableMcpServers.d.ts +14 -0
  96. package/ts_build/src/agents/tools/mcp/listAvailableMcpServers.js +23 -0
  97. package/ts_build/src/agents/tools/mcp/listAvailableMcpServers.js.map +1 -0
  98. package/ts_build/src/agents/tools/writeFile.js +4 -1
  99. package/ts_build/src/agents/tools/writeFile.js.map +1 -1
  100. package/ts_build/src/chat/CliChatService.js +3 -1
  101. package/ts_build/src/chat/CliChatService.js.map +1 -1
  102. package/ts_build/src/chat/modules/AgentModule.d.ts +4 -3
  103. package/ts_build/src/chat/modules/AgentModule.js +71 -265
  104. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  105. package/ts_build/src/cli.d.ts +1 -1
  106. package/ts_build/src/cli.js +17 -4
  107. package/ts_build/src/cli.js.map +1 -1
  108. package/ts_build/src/plugins/GitPlugin.d.ts +1 -0
  109. package/ts_build/src/plugins/GitPlugin.js +26 -19
  110. package/ts_build/src/plugins/GitPlugin.js.map +1 -1
  111. package/ts_build/src/plugins/language.d.ts +3 -0
  112. package/ts_build/src/plugins/language.js +55 -13
  113. package/ts_build/src/plugins/language.js.map +1 -1
  114. package/ts_build/src/processors/ToolResponseCache.d.ts +7 -4
  115. package/ts_build/src/processors/ToolResponseCache.js +47 -88
  116. package/ts_build/src/processors/ToolResponseCache.js.map +1 -1
  117. package/ts_build/src/processors/tools/grepToolResponse.d.ts +10 -0
  118. package/ts_build/src/processors/tools/grepToolResponse.js +71 -0
  119. package/ts_build/src/processors/tools/grepToolResponse.js.map +1 -0
  120. package/ts_build/src/processors/tools/index.d.ts +4 -0
  121. package/ts_build/src/processors/tools/index.js +16 -0
  122. package/ts_build/src/processors/tools/index.js.map +1 -0
  123. package/ts_build/src/processors/tools/jqToolResponse.d.ts +3 -0
  124. package/ts_build/src/processors/tools/jqToolResponse.js +115 -0
  125. package/ts_build/src/processors/tools/jqToolResponse.js.map +1 -0
  126. package/ts_build/src/processors/tools/listStoredToolResponses.d.ts +21 -0
  127. package/ts_build/src/processors/tools/listStoredToolResponses.js +51 -0
  128. package/ts_build/src/processors/tools/listStoredToolResponses.js.map +1 -0
  129. package/ts_build/src/processors/tools/tailToolResponse.d.ts +6 -0
  130. package/ts_build/src/processors/tools/tailToolResponse.js +55 -0
  131. package/ts_build/src/processors/tools/tailToolResponse.js.map +1 -0
  132. package/ts_build/src/services/AgentService.d.ts +1 -1
  133. package/ts_build/src/services/AgentSynchronization.d.ts +27 -0
  134. package/ts_build/src/services/AgentSynchronization.js +168 -0
  135. package/ts_build/src/services/AgentSynchronization.js.map +1 -0
  136. package/ts_build/src/services/DockerService.d.ts +2 -0
  137. package/ts_build/src/services/DockerService.js +21 -1
  138. package/ts_build/src/services/DockerService.js.map +1 -1
  139. package/ts_build/src/services/EventService.d.ts +5 -0
  140. package/ts_build/src/services/EventService.js +7 -2
  141. package/ts_build/src/services/EventService.js.map +1 -1
  142. package/ts_build/src/services/KnowhowClient.d.ts +41 -1
  143. package/ts_build/src/services/KnowhowClient.js +42 -0
  144. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  145. package/ts_build/src/services/LazyToolsService.d.ts +29 -0
  146. package/ts_build/src/services/LazyToolsService.js +96 -0
  147. package/ts_build/src/services/LazyToolsService.js.map +1 -0
  148. package/ts_build/src/services/Mcp.d.ts +18 -1
  149. package/ts_build/src/services/Mcp.js +119 -4
  150. package/ts_build/src/services/Mcp.js.map +1 -1
  151. package/ts_build/src/services/SessionManager.d.ts +15 -0
  152. package/ts_build/src/services/SessionManager.js +220 -0
  153. package/ts_build/src/services/SessionManager.js.map +1 -0
  154. package/ts_build/src/services/TaskRegistry.d.ts +15 -0
  155. package/ts_build/src/services/TaskRegistry.js +58 -0
  156. package/ts_build/src/services/TaskRegistry.js.map +1 -0
  157. package/ts_build/src/services/Tools.d.ts +2 -0
  158. package/ts_build/src/services/Tools.js.map +1 -1
  159. package/ts_build/src/services/index.d.ts +4 -0
  160. package/ts_build/src/services/index.js +4 -0
  161. package/ts_build/src/services/index.js.map +1 -1
  162. package/ts_build/src/services/script-execution/ScriptExecutor.js +7 -5
  163. package/ts_build/src/services/script-execution/ScriptExecutor.js.map +1 -1
  164. package/ts_build/src/types.d.ts +1 -0
  165. package/ts_build/src/types.js.map +1 -1
  166. package/ts_build/src/utils/InputQueueManager.d.ts +9 -2
  167. package/ts_build/src/utils/InputQueueManager.js +54 -40
  168. package/ts_build/src/utils/InputQueueManager.js.map +1 -1
  169. package/ts_build/src/utils/errors.d.ts +0 -0
  170. package/ts_build/src/utils/errors.js +1 -0
  171. package/ts_build/src/utils/errors.js.map +1 -0
  172. package/ts_build/src/utils/index.d.ts +1 -0
  173. package/ts_build/src/utils/index.js +5 -1
  174. package/ts_build/src/utils/index.js.map +1 -1
  175. package/ts_build/src/worker.js +8 -0
  176. package/ts_build/src/worker.js.map +1 -1
  177. package/ts_build/tests/compressor/bigstring.test.d.ts +1 -0
  178. package/ts_build/tests/compressor/bigstring.test.js +66 -0
  179. package/ts_build/tests/compressor/bigstring.test.js.map +1 -0
  180. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +6 -5
  181. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +1 -1
  182. package/ts_build/tests/plugins/language/languagePlugin-integration.test.js +9 -7
  183. package/ts_build/tests/plugins/language/languagePlugin-integration.test.js.map +1 -1
  184. package/ts_build/tests/plugins/language/languagePlugin.test.js +7 -4
  185. package/ts_build/tests/plugins/language/languagePlugin.test.js.map +1 -1
  186. package/ts_build/tests/processors/ToolResponseCache.test.js +107 -0
  187. package/ts_build/tests/processors/ToolResponseCache.test.js.map +1 -1
  188. package/ts_build/tests/unit/InputQueueManager.test.d.ts +1 -0
  189. package/ts_build/tests/unit/InputQueueManager.test.js +104 -0
  190. package/ts_build/tests/unit/InputQueueManager.test.js.map +1 -0
@@ -2,9 +2,10 @@
2
2
  * Agent Chat Module - Handles agent interactions
3
3
  */
4
4
  import {
5
- KnowhowSimpleClient,
6
- KNOWHOW_API_URL,
7
- } from "../../services/KnowhowClient";
5
+ AgentSynchronization,
6
+ SessionManager,
7
+ TaskRegistry,
8
+ } from "../../services/index";
8
9
  import * as fs from "fs";
9
10
  import * as path from "path";
10
11
 
@@ -23,24 +24,22 @@ import {
23
24
  } from "../../processors/index";
24
25
  import { TaskInfo, ChatSession } from "../types";
25
26
  import { agents } from "../../agents";
26
- import { ToolCallEvent } from "src/agents/base/base";
27
+ import { ToolCallEvent } from "../../agents/base/base";
27
28
 
28
29
  export class AgentModule extends BaseChatModule {
29
30
  name = "agent";
30
31
  description = "Agent interaction functionality";
31
32
 
32
- // Enhanced task registry for managing agents with metadata
33
- private taskRegistry = new Map<string, TaskInfo>();
34
-
35
- // Sessions directory path
36
- private sessionsDir = "./.knowhow/chats/sessions";
33
+ // Service instances for task management, session management, and synchronization
34
+ private taskRegistry: TaskRegistry;
35
+ private sessionManager: SessionManager;
36
+ private agentSync: AgentSynchronization;
37
37
 
38
38
  constructor() {
39
39
  super();
40
- // Ensure sessions directory exists
41
- if (!fs.existsSync(this.sessionsDir)) {
42
- fs.mkdirSync(this.sessionsDir, { recursive: true });
43
- }
40
+ this.taskRegistry = new TaskRegistry();
41
+ this.sessionManager = new SessionManager();
42
+ this.agentSync = new AgentSynchronization();
44
43
  }
45
44
 
46
45
  getCommands(): ChatCommand[] {
@@ -113,9 +112,14 @@ export class AgentModule extends BaseChatModule {
113
112
  if (allAgents && allAgents[agentName]) {
114
113
  // Set selected agent in context and enable agent mode
115
114
  if (context) {
116
- context.selectedAgent = allAgents[agentName];
115
+ const selectedAgent = allAgents[agentName];
116
+ context.selectedAgent = selectedAgent;
117
117
  context.agentMode = true;
118
118
  context.currentAgent = agentName;
119
+ // Update context's model/provider to reflect the agent's settings
120
+ // so /model and /provider commands show accurate information
121
+ context.currentModel = selectedAgent.getModel();
122
+ context.currentProvider = selectedAgent.getProvider();
119
123
  }
120
124
  console.log(
121
125
  `Agent mode enabled. Selected agent: ${agentName}. Type your task to get started.`
@@ -133,43 +137,15 @@ export class AgentModule extends BaseChatModule {
133
137
  async handleAttachCommand(args: string[]): Promise<void> {
134
138
  if (args.length === 0) {
135
139
  // Get both running tasks and saved sessions
136
- const runningTasks = Array.from(this.taskRegistry.values());
137
- const savedSessions = await this.listAvailableSessions();
140
+ const runningTasks = this.taskRegistry.getAll();
141
+ const savedSessions = this.sessionManager.listAvailableSessions();
138
142
 
139
143
  if (runningTasks.length === 0 && savedSessions.length === 0) {
140
144
  console.log("No active tasks or saved sessions found to attach to.");
141
145
  return;
142
146
  }
143
147
 
144
- // Show available options for selection
145
- console.log("\n📋 Available Sessions & Tasks:");
146
- console.log("─".repeat(80));
147
- console.log(
148
- "ID".padEnd(25) + "Agent".padEnd(15) + "Status".padEnd(12) + "Type"
149
- );
150
- console.log("─".repeat(80));
151
-
152
- // Show saved sessions
153
- savedSessions.forEach((session) => {
154
- console.log(
155
- session.sessionId.padEnd(25) +
156
- session.agentName.padEnd(15) +
157
- session.status.padEnd(12) +
158
- "saved"
159
- );
160
- });
161
-
162
- // Show running tasks
163
- runningTasks.forEach((task) => {
164
- console.log(
165
- task.taskId.padEnd(25) +
166
- task.agentName.padEnd(15) +
167
- task.status.padEnd(12) +
168
- "running"
169
- );
170
- });
171
-
172
- console.log("─".repeat(80));
148
+ await this.sessionManager.logRunningTasks(runningTasks, savedSessions);
173
149
 
174
150
  // Interactive selection for both types
175
151
  const allIds = [
@@ -200,24 +176,7 @@ export class AgentModule extends BaseChatModule {
200
176
  * Display single task details
201
177
  */
202
178
  private displaySingleTask(task: TaskInfo): void {
203
- console.log(`\n📋 Task Details: ${task.taskId}`);
204
- console.log("─".repeat(50));
205
- console.log(`Agent: ${task.agentName}`);
206
- console.log(`Status: ${task.status}`);
207
- console.log(`Initial Input: ${task.initialInput}`);
208
- console.log(`Start Time: ${new Date(task.startTime).toLocaleString()}`);
209
- if (task.endTime) {
210
- console.log(`End Time: ${new Date(task.endTime).toLocaleString()}`);
211
- console.log(
212
- `Duration: ${Math.round((task.endTime - task.startTime) / 1000)}s`
213
- );
214
- } else {
215
- console.log(
216
- `Running for: ${Math.round((Date.now() - task.startTime) / 1000)}s`
217
- );
218
- }
219
- console.log(`Total Cost: $${task.totalCost.toFixed(3)}`);
220
- console.log("─".repeat(50));
179
+ this.taskRegistry.displaySingleTask(task);
221
180
  }
222
181
 
223
182
  async handleAgentsCommand(args: string[]): Promise<void> {
@@ -259,63 +218,16 @@ export class AgentModule extends BaseChatModule {
259
218
  }
260
219
 
261
220
  async logSessionTable() {
262
- // Display unified table
263
- const runningTasks = Array.from(this.taskRegistry.values());
264
- const savedSessions = await this.listAvailableSessions();
265
- console.log("\n📋 Sessions & Tasks:");
266
-
267
- const data = [];
268
- // Display saved sessions first (historical)
269
- savedSessions.forEach((session) => {
270
- const lastUpdated = new Date(session.lastUpdated).toLocaleString();
271
- const inputPreview =
272
- session.initialInput && session.initialInput.length > 30
273
- ? session.initialInput.substring(0, 27) + "..."
274
- : session.initialInput || "[No input]";
275
- const cost = session.totalCost
276
- ? `$${session.totalCost.toFixed(3)}`
277
- : "$0.000";
278
-
279
- data.push({
280
- ID: session.sessionId,
281
- Agent: session.agentName,
282
- Status: session.status,
283
- Type: "saved",
284
- Time: lastUpdated,
285
- Cost: cost,
286
- "Initial Input": inputPreview,
287
- });
288
- });
289
-
290
- // Display running tasks at the bottom
291
- runningTasks.forEach((task) => {
292
- const elapsed = task.endTime
293
- ? `${Math.round((task.endTime - task.startTime) / 1000)}s`
294
- : `${Math.round((Date.now() - task.startTime) / 1000)}s`;
295
- const cost = `$${task.totalCost.toFixed(3)}`;
296
- const inputPreview =
297
- task.initialInput.length > 30
298
- ? task.initialInput.substring(0, 27) + "..."
299
- : task.initialInput;
300
- data.push({
301
- ID: task.taskId,
302
- Agent: task.agentName,
303
- Status: task.status,
304
- Type: "running",
305
- Time: elapsed,
306
- Cost: cost,
307
- "Initial Input": inputPreview,
308
- });
309
- });
310
-
311
- console.table(data);
221
+ const runningTasks = this.taskRegistry.getAll();
222
+ const savedSessions = this.sessionManager.listAvailableSessions();
223
+ this.sessionManager.logSessionTable(runningTasks, savedSessions);
312
224
  }
313
225
 
314
226
  async handleSessionsCommand(args: string[]): Promise<void> {
315
227
  try {
316
228
  // Get both running tasks and saved sessions
317
- const runningTasks = Array.from(this.taskRegistry.values());
318
- const savedSessions = await this.listAvailableSessions();
229
+ const runningTasks = this.taskRegistry.getAll();
230
+ const savedSessions = this.sessionManager.listAvailableSessions();
319
231
 
320
232
  if (runningTasks.length === 0 && savedSessions.length === 0) {
321
233
  console.log("No active tasks or saved sessions found.");
@@ -366,6 +278,10 @@ export class AgentModule extends BaseChatModule {
366
278
  context.selectedAgent = selectedAgent;
367
279
  context.agentMode = true;
368
280
  context.currentAgent = taskInfo.agentName;
281
+ // Update context's model/provider to reflect the agent's settings
282
+ // so /model and /provider commands show accurate information
283
+ context.currentModel = selectedAgent.getModel();
284
+ context.currentProvider = selectedAgent.getProvider();
369
285
  console.log(`🔄 Switched to agent mode with ${taskInfo.agentName}`);
370
286
  console.log(`📋 Attached to running task: ${id}`);
371
287
  console.log(`Task: ${taskInfo.initialInput}`);
@@ -379,12 +295,10 @@ export class AgentModule extends BaseChatModule {
379
295
 
380
296
  // Check if it's a saved session
381
297
  try {
382
- const sessionPath = path.join(this.sessionsDir, `${id}.json`);
383
- if (fs.existsSync(sessionPath)) {
298
+ const session = this.sessionManager.loadSession(id);
299
+ if (session) {
384
300
  console.log(Marked.parse(`**Resuming saved session: ${id}**`));
385
301
  // Read session to get agent information
386
- const content = fs.readFileSync(sessionPath, "utf-8");
387
- const session: ChatSession = JSON.parse(content);
388
302
 
389
303
  // Switch to agent mode and set the selected agent
390
304
  const context = this.chatService?.getContext();
@@ -394,6 +308,10 @@ export class AgentModule extends BaseChatModule {
394
308
  if (context && selectedAgent) {
395
309
  context.selectedAgent = selectedAgent;
396
310
  context.agentMode = true;
311
+ // Update context's model/provider to reflect the agent's settings
312
+ // so /model and /provider commands show accurate information
313
+ context.currentModel = selectedAgent.getModel();
314
+ context.currentProvider = selectedAgent.getProvider();
397
315
  console.log(`🔄 Switched to agent mode with ${session.agentName}`);
398
316
  console.log(`📋 Resuming saved session: ${id}`);
399
317
  console.log(`Original task: ${session.initialInput}`);
@@ -417,52 +335,7 @@ export class AgentModule extends BaseChatModule {
417
335
  * List available session files
418
336
  */
419
337
  public async listAvailableSessions(): Promise<ChatSession[]> {
420
- try {
421
- const files = fs.readdirSync(this.sessionsDir);
422
- const sessionFiles = files.filter((f) => f.endsWith(".json"));
423
-
424
- const sessions: ChatSession[] = [];
425
- const thresholdTime = 15 * 60 * 1000; // 15 minutes
426
- for (const file of sessionFiles) {
427
- const filePath = path.join(this.sessionsDir, file);
428
- try {
429
- const content = fs.readFileSync(filePath, "utf8");
430
- const session = JSON.parse(content) as ChatSession;
431
-
432
- // Cleanup check: mark stale running sessions as failed
433
- const isStale = Date.now() - session.lastUpdated > thresholdTime;
434
- const isRunningAndNotInRegistry =
435
- session.status === "running" &&
436
- !this.taskRegistry.has(session.sessionId);
437
-
438
- if (isRunningAndNotInRegistry && isStale) {
439
- console.log(
440
- `🧹 Marking stale session ${
441
- session.sessionId
442
- } as failed (last updated: ${new Date(
443
- session.lastUpdated
444
- ).toLocaleString()})`
445
- );
446
- session.status = "failed";
447
- session.lastUpdated = Date.now();
448
- // Update the session file with failed status
449
- fs.writeFileSync(filePath, JSON.stringify(session, null, 2));
450
- }
451
-
452
- sessions.push(session);
453
- } catch (error) {
454
- console.warn(
455
- `Failed to read session file ${file}:`,
456
- (error as Error).message
457
- );
458
- }
459
- }
460
-
461
- return sessions.sort((a, b) => b.lastUpdated - a.lastUpdated);
462
- } catch (error) {
463
- console.warn("Failed to list sessions:", (error as Error).message);
464
- return [];
465
- }
338
+ return this.sessionManager.listAvailableSessions();
466
339
  }
467
340
 
468
341
  /**
@@ -472,8 +345,8 @@ export class AgentModule extends BaseChatModule {
472
345
  runningTasks: TaskInfo[];
473
346
  savedSessions: ChatSession[];
474
347
  }> {
475
- const runningTasks = Array.from(this.taskRegistry.values());
476
- const savedSessions = await this.listAvailableSessions();
348
+ const runningTasks = this.taskRegistry.getAll();
349
+ const savedSessions = this.sessionManager.listAvailableSessions();
477
350
  return {
478
351
  runningTasks,
479
352
  savedSessions,
@@ -483,7 +356,7 @@ export class AgentModule extends BaseChatModule {
483
356
  /**
484
357
  * Get the task registry for CLI access
485
358
  */
486
- public getTaskRegistry(): Map<string, TaskInfo> {
359
+ public getTaskRegistry(): TaskRegistry {
487
360
  return this.taskRegistry;
488
361
  }
489
362
 
@@ -495,9 +368,11 @@ export class AgentModule extends BaseChatModule {
495
368
  resumeReason?: string
496
369
  ): Promise<void> {
497
370
  try {
498
- const sessionPath = path.join(this.sessionsDir, `${sessionId}.json`);
499
- const content = fs.readFileSync(sessionPath, "utf-8");
500
- const session: ChatSession = JSON.parse(content);
371
+ const session = this.sessionManager.loadSession(sessionId);
372
+ if (!session) {
373
+ console.error(`Session ${sessionId} not found.`);
374
+ return;
375
+ }
501
376
  const lastThread = session.threads[session.threads.length - 1];
502
377
  console.log(`\n🔄 Resuming session: ${sessionId}`);
503
378
  console.log(`Agent: ${session.agentName}`);
@@ -511,17 +386,17 @@ export class AgentModule extends BaseChatModule {
511
386
  // Create resume prompt
512
387
  const resumePrompt = `You are resuming a previously started task. Here's the context:
513
388
  ORIGINAL REQUEST:
514
- ${session.initialInput}
389
+ ${session.initialInput}
515
390
 
516
391
  LAST Progress State:
517
- ${JSON.stringify(lastThread)}
392
+ ${JSON.stringify(lastThread)}
518
393
 
519
394
  Please continue from where you left off and complete the original request.
520
- ${reason}
395
+ ${reason}
521
396
 
522
397
  `;
523
398
 
524
- console.log("🚀 Session resumption would restart the agent here...");
399
+ console.log("🚀 Session resuming...");
525
400
  const context = this.chatService?.getContext() || {};
526
401
  const allAgents = agents();
527
402
  const selectedAgent =
@@ -608,7 +483,7 @@ ${reason}
608
483
 
609
484
  let done = false;
610
485
  let output = "Done";
611
- const taskId = this.generateTaskId(input);
486
+ const taskId = this.sessionManager.generateTaskId(input);
612
487
  let knowhowTaskId: string | undefined;
613
488
 
614
489
  try {
@@ -638,32 +513,25 @@ ${reason}
638
513
  };
639
514
 
640
515
  // Add to task registry
641
- this.taskRegistry.set(taskId, taskInfo);
516
+ this.taskRegistry.register(taskId, taskInfo);
642
517
 
643
518
  // Save initial session
644
519
  this.saveSession(taskId, taskInfo, []);
645
520
 
646
521
  // Create Knowhow chat task if messageId provided
647
- const baseUrl = KNOWHOW_API_URL;
648
- console.log(
649
- `Base URL for Knowhow API: ${baseUrl}, Message ID: ${options.messageId}`
650
- );
651
- const client = new KnowhowSimpleClient(baseUrl);
652
- if (options.messageId && !options.existingKnowhowTaskId && baseUrl) {
653
- try {
654
- const response = await client.createChatTask({
655
- messageId: options.messageId,
656
- prompt: input,
657
- });
658
- knowhowTaskId = response.data.id;
659
- console.log(`✅ Created Knowhow chat task: ${knowhowTaskId}`);
522
+ if (options.messageId && !options.existingKnowhowTaskId) {
523
+ knowhowTaskId = await this.agentSync.createChatTask({
524
+ messageId: options.messageId,
525
+ prompt: input,
526
+ });
660
527
 
528
+ if (knowhowTaskId) {
661
529
  // Update TaskInfo with the created knowhowTaskId
662
530
  taskInfo.knowhowTaskId = knowhowTaskId;
663
- this.taskRegistry.set(taskId, taskInfo);
664
- } catch (error) {
665
- console.error(`❌ Failed to create Knowhow chat task:`, error);
666
- // Continue execution even if task creation fails
531
+ this.taskRegistry.register(taskId, taskInfo);
532
+
533
+ // Set up event-based synchronization with Knowhow API
534
+ await this.agentSync.setupAgentSync(agent, knowhowTaskId);
667
535
  }
668
536
  }
669
537
 
@@ -671,23 +539,8 @@ ${reason}
671
539
  agent.agentEvents.on(
672
540
  agent.eventTypes.threadUpdate,
673
541
  async (threadState) => {
674
- // Update task cost from agent's current total cost
675
- taskInfo.totalCost = agent.getTotalCostUsd();
676
542
  this.updateSession(taskId, threadState);
677
-
678
- // Update Knowhow chat task if created
679
- if (knowhowTaskId && options.messageId && baseUrl) {
680
- await client
681
- .updateChatTask(knowhowTaskId, {
682
- threads: agent.getThreads(),
683
- totalCostUsd: agent.getTotalCostUsd(),
684
- inProgress: true,
685
- })
686
- .catch((error) => {
687
- console.error(`❌ Failed to update Knowhow chat task:`, error);
688
- });
689
- console.log(`✅ Updated Knowhow chat task: ${knowhowTaskId}`);
690
- }
543
+ taskInfo.totalCost = agent.getTotalCostUsd();
691
544
  }
692
545
  );
693
546
 
@@ -742,6 +595,12 @@ ${reason}
742
595
  new HarmonyToolProcessor().createProcessor(),
743
596
  ]);
744
597
 
598
+ agent.messageProcessor.setProcessors("post_tools", [
599
+ new TokenCompressor(agent.tools).createProcessor((msg) =>
600
+ Boolean(msg.role === "tool" && msg.tool_call_id)
601
+ ),
602
+ ]);
603
+
745
604
  // Set up event listeners
746
605
  if (!agent.agentEvents.listenerCount(agent.eventTypes.toolCall)) {
747
606
  agent.agentEvents.on(
@@ -781,27 +640,6 @@ ${reason}
781
640
  // Update session with final state
782
641
  this.updateSession(taskId, agent.getThreads());
783
642
  taskInfo.endTime = Date.now();
784
-
785
- // Final update to Knowhow chat task
786
- if (knowhowTaskId && options.messageId) {
787
- console.log(
788
- `Updating Knowhow chat task on completion..., ${knowhowTaskId}, ${options.messageId}`
789
- );
790
- await client
791
- .updateChatTask(knowhowTaskId, {
792
- inProgress: false,
793
- threads: agent.getThreads(),
794
- totalCostUsd: agent.getTotalCostUsd(),
795
- result: output,
796
- })
797
- .catch((error) => {
798
- console.error(
799
- `❌ Failed to update Knowhow chat task on completion:`,
800
- error
801
- );
802
- });
803
- console.log(`✅ Completed Knowhow chat task: ${knowhowTaskId}`);
804
- }
805
643
  }
806
644
  console.log(Marked.parse(output));
807
645
  resolve(doneMsg);
@@ -845,7 +683,7 @@ ${reason}
845
683
  * Get list of active agent tasks
846
684
  */
847
685
  getActiveTasks(): { taskId: string; agent: TaskInfo }[] {
848
- return Array.from(this.taskRegistry.entries()).map(
686
+ return Array.from(this.taskRegistry.getEntries()).map(
849
687
  ([taskId, taskInfo]) => ({
850
688
  taskId,
851
689
  agent: taskInfo,
@@ -867,22 +705,6 @@ ${reason}
867
705
  return false;
868
706
  }
869
707
 
870
- /**
871
- * Generate human-readable task ID from initial input
872
- */
873
- private generateTaskId(initialInput: string): string {
874
- const words = initialInput
875
- .toLowerCase()
876
- .replace(/[^\w\s]/g, "")
877
- .split(/\s+/)
878
- .filter((word) => word.length > 2)
879
- .slice(0, 9);
880
-
881
- const wordPart = words.join("-") || "task";
882
- const epochSeconds = Math.floor(Date.now() / 1000);
883
- return `${epochSeconds}-${wordPart}`;
884
- }
885
-
886
708
  /**
887
709
  * Save session to file
888
710
  */
@@ -891,60 +713,15 @@ ${reason}
891
713
  taskInfo: TaskInfo,
892
714
  threads: any[]
893
715
  ): void {
894
- try {
895
- const sessionPath = path.join(this.sessionsDir, `${taskId}.json`);
896
- const session: ChatSession = {
897
- sessionId: taskId,
898
- knowhowMessageId: taskInfo.knowhowMessageId,
899
- knowhowTaskId: taskInfo.knowhowTaskId,
900
- taskId,
901
- agentName: taskInfo.agentName,
902
- initialInput: taskInfo.initialInput,
903
- status: taskInfo.status,
904
- startTime: taskInfo.startTime,
905
- endTime: taskInfo.endTime,
906
- totalCost: taskInfo.totalCost,
907
- threads,
908
- currentThread: 0,
909
- lastUpdated: Date.now(),
910
- };
911
-
912
- fs.writeFileSync(sessionPath, JSON.stringify(session, null, 2));
913
- } catch (error) {
914
- console.error(`Error saving session ${taskId}:`, error);
915
- }
716
+ this.sessionManager.saveSession(taskId, taskInfo, threads);
916
717
  }
917
718
 
918
719
  /**
919
720
  * Update existing session with new thread state
920
721
  */
921
722
  private updateSession(taskId: string, threads: any[]): void {
922
- try {
923
- const sessionPath = path.join(this.sessionsDir, `${taskId}.json`);
924
- if (fs.existsSync(sessionPath)) {
925
- const session: ChatSession = JSON.parse(
926
- fs.readFileSync(sessionPath, "utf8")
927
- );
928
- const taskInfo = this.taskRegistry.get(taskId);
929
-
930
- // Update session with current state
931
- session.threads = threads;
932
- session.lastUpdated = Date.now();
933
- if (taskInfo) {
934
- session.status = taskInfo.status;
935
- session.endTime = taskInfo.endTime;
936
- session.totalCost = taskInfo.totalCost;
937
-
938
- // Update Knowhow task fields if they exist in TaskInfo
939
- session.knowhowMessageId = taskInfo.knowhowMessageId;
940
- session.knowhowTaskId = taskInfo.knowhowTaskId;
941
- }
942
-
943
- fs.writeFileSync(sessionPath, JSON.stringify(session, null, 2));
944
- }
945
- } catch (error) {
946
- console.error(`Error updating session ${taskId}:`, error);
947
- }
723
+ const taskInfo = this.taskRegistry.get(taskId);
724
+ this.sessionManager.updateSession(taskId, taskInfo, threads);
948
725
  }
949
726
 
950
727
  /**
@@ -994,6 +771,7 @@ ${reason}
994
771
  agent.agentEvents.once(agent.eventTypes.done, (doneMsg) => {
995
772
  // Capture the agent's final output
996
773
  agentFinalOutput = doneMsg || "No response from the AI";
774
+ console.log("Finished", taskId, `$${agent.getTotalCostUsd()}`);
997
775
  finished = true;
998
776
  resolve("done");
999
777
  });