@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.
- package/package.json +3 -3
- package/src/agents/base/base.ts +87 -43
- package/src/agents/tools/execCommand.ts +17 -14
- package/src/agents/tools/googleSearch.ts +1 -0
- package/src/agents/tools/index.ts +1 -0
- package/src/agents/tools/lazy/definitions.ts +63 -0
- package/src/agents/tools/lazy/disableTools.ts +16 -0
- package/src/agents/tools/lazy/enableTools.ts +16 -0
- package/src/agents/tools/lazy/index.ts +3 -0
- package/src/agents/tools/lazy/listAvailableTools.ts +14 -0
- package/src/agents/tools/list.ts +2 -0
- package/src/agents/tools/mcp/connectMcpServer.ts +40 -0
- package/src/agents/tools/mcp/definitions.ts +67 -0
- package/src/agents/tools/mcp/disconnectMcpServer.ts +40 -0
- package/src/agents/tools/mcp/index.ts +3 -0
- package/src/agents/tools/mcp/listAvailableMcpServers.ts +28 -0
- package/src/agents/tools/writeFile.ts +4 -1
- package/src/chat/CliChatService.ts +8 -3
- package/src/chat/modules/AgentModule.ts +74 -296
- package/src/cli.ts +33 -10
- package/src/plugins/GitPlugin.ts +30 -24
- package/src/plugins/language.ts +95 -18
- package/src/processors/ToolResponseCache.ts +98 -79
- package/src/processors/tools/grepToolResponse.ts +99 -0
- package/src/processors/tools/index.ts +21 -0
- package/src/processors/tools/jqToolResponse.ts +124 -0
- package/src/processors/tools/listStoredToolResponses.ts +83 -0
- package/src/processors/tools/tailToolResponse.ts +75 -0
- package/src/services/AgentService.ts +1 -1
- package/src/services/AgentSynchronization.ts +291 -0
- package/src/services/DockerService.ts +37 -1
- package/src/services/EventService.ts +8 -2
- package/src/services/KnowhowClient.ts +141 -1
- package/src/services/LazyToolsService.ts +146 -0
- package/src/services/Mcp.ts +171 -4
- package/src/services/SessionManager.ts +287 -0
- package/src/services/TaskRegistry.ts +108 -0
- package/src/services/Tools.ts +2 -0
- package/src/services/index.ts +7 -0
- package/src/services/script-execution/ScriptExecutor.ts +7 -5
- package/src/types.ts +1 -0
- package/src/utils/InputQueueManager.ts +91 -57
- package/src/utils/errors.ts +0 -0
- package/src/utils/index.ts +11 -0
- package/src/worker.ts +12 -0
- package/tests/compressor/bigstring.test.ts +100 -0
- package/tests/compressor/bigstring.txt +1 -0
- package/tests/plugins/language/languagePlugin-content-triggers.test.ts +13 -5
- package/tests/plugins/language/languagePlugin-integration.test.ts +22 -7
- package/tests/plugins/language/languagePlugin.test.ts +11 -4
- package/tests/processors/ToolResponseCache.test.ts +128 -0
- package/tests/unit/InputQueueManager.test.ts +174 -0
- package/ts_build/package.json +3 -3
- package/ts_build/src/agents/base/base.d.ts +10 -0
- package/ts_build/src/agents/base/base.js +66 -34
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/tools/execCommand.js +1 -9
- package/ts_build/src/agents/tools/execCommand.js.map +1 -1
- package/ts_build/src/agents/tools/github/index.d.ts +1 -1
- package/ts_build/src/agents/tools/googleSearch.d.ts +1 -0
- package/ts_build/src/agents/tools/googleSearch.js +1 -0
- package/ts_build/src/agents/tools/googleSearch.js.map +1 -1
- package/ts_build/src/agents/tools/index.d.ts +1 -0
- package/ts_build/src/agents/tools/index.js +1 -0
- package/ts_build/src/agents/tools/index.js.map +1 -1
- package/ts_build/src/agents/tools/lazy/definitions.d.ts +5 -0
- package/ts_build/src/agents/tools/lazy/definitions.js +58 -0
- package/ts_build/src/agents/tools/lazy/definitions.js.map +1 -0
- package/ts_build/src/agents/tools/lazy/disableTools.d.ts +9 -0
- package/ts_build/src/agents/tools/lazy/disableTools.js +15 -0
- package/ts_build/src/agents/tools/lazy/disableTools.js.map +1 -0
- package/ts_build/src/agents/tools/lazy/enableTools.d.ts +9 -0
- package/ts_build/src/agents/tools/lazy/enableTools.js +15 -0
- package/ts_build/src/agents/tools/lazy/enableTools.js.map +1 -0
- package/ts_build/src/agents/tools/lazy/index.d.ts +3 -0
- package/ts_build/src/agents/tools/lazy/index.js +20 -0
- package/ts_build/src/agents/tools/lazy/index.js.map +1 -0
- package/ts_build/src/agents/tools/lazy/listAvailableTools.d.ts +11 -0
- package/ts_build/src/agents/tools/lazy/listAvailableTools.js +15 -0
- package/ts_build/src/agents/tools/lazy/listAvailableTools.js.map +1 -0
- package/ts_build/src/agents/tools/list.js +2 -0
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/agents/tools/mcp/connectMcpServer.d.ts +5 -0
- package/ts_build/src/agents/tools/mcp/connectMcpServer.js +31 -0
- package/ts_build/src/agents/tools/mcp/connectMcpServer.js.map +1 -0
- package/ts_build/src/agents/tools/mcp/definitions.d.ts +2 -0
- package/ts_build/src/agents/tools/mcp/definitions.js +62 -0
- package/ts_build/src/agents/tools/mcp/definitions.js.map +1 -0
- package/ts_build/src/agents/tools/mcp/disconnectMcpServer.d.ts +5 -0
- package/ts_build/src/agents/tools/mcp/disconnectMcpServer.js +31 -0
- package/ts_build/src/agents/tools/mcp/disconnectMcpServer.js.map +1 -0
- package/ts_build/src/agents/tools/mcp/index.d.ts +3 -0
- package/ts_build/src/agents/tools/mcp/index.js +10 -0
- package/ts_build/src/agents/tools/mcp/index.js.map +1 -0
- package/ts_build/src/agents/tools/mcp/listAvailableMcpServers.d.ts +14 -0
- package/ts_build/src/agents/tools/mcp/listAvailableMcpServers.js +23 -0
- package/ts_build/src/agents/tools/mcp/listAvailableMcpServers.js.map +1 -0
- package/ts_build/src/agents/tools/writeFile.js +4 -1
- package/ts_build/src/agents/tools/writeFile.js.map +1 -1
- package/ts_build/src/chat/CliChatService.js +3 -1
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +4 -3
- package/ts_build/src/chat/modules/AgentModule.js +71 -265
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/cli.d.ts +1 -1
- package/ts_build/src/cli.js +17 -4
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/plugins/GitPlugin.d.ts +1 -0
- package/ts_build/src/plugins/GitPlugin.js +26 -19
- package/ts_build/src/plugins/GitPlugin.js.map +1 -1
- package/ts_build/src/plugins/language.d.ts +3 -0
- package/ts_build/src/plugins/language.js +55 -13
- package/ts_build/src/plugins/language.js.map +1 -1
- package/ts_build/src/processors/ToolResponseCache.d.ts +7 -4
- package/ts_build/src/processors/ToolResponseCache.js +47 -88
- package/ts_build/src/processors/ToolResponseCache.js.map +1 -1
- package/ts_build/src/processors/tools/grepToolResponse.d.ts +10 -0
- package/ts_build/src/processors/tools/grepToolResponse.js +71 -0
- package/ts_build/src/processors/tools/grepToolResponse.js.map +1 -0
- package/ts_build/src/processors/tools/index.d.ts +4 -0
- package/ts_build/src/processors/tools/index.js +16 -0
- package/ts_build/src/processors/tools/index.js.map +1 -0
- package/ts_build/src/processors/tools/jqToolResponse.d.ts +3 -0
- package/ts_build/src/processors/tools/jqToolResponse.js +115 -0
- package/ts_build/src/processors/tools/jqToolResponse.js.map +1 -0
- package/ts_build/src/processors/tools/listStoredToolResponses.d.ts +21 -0
- package/ts_build/src/processors/tools/listStoredToolResponses.js +51 -0
- package/ts_build/src/processors/tools/listStoredToolResponses.js.map +1 -0
- package/ts_build/src/processors/tools/tailToolResponse.d.ts +6 -0
- package/ts_build/src/processors/tools/tailToolResponse.js +55 -0
- package/ts_build/src/processors/tools/tailToolResponse.js.map +1 -0
- package/ts_build/src/services/AgentService.d.ts +1 -1
- package/ts_build/src/services/AgentSynchronization.d.ts +27 -0
- package/ts_build/src/services/AgentSynchronization.js +168 -0
- package/ts_build/src/services/AgentSynchronization.js.map +1 -0
- package/ts_build/src/services/DockerService.d.ts +2 -0
- package/ts_build/src/services/DockerService.js +21 -1
- package/ts_build/src/services/DockerService.js.map +1 -1
- package/ts_build/src/services/EventService.d.ts +5 -0
- package/ts_build/src/services/EventService.js +7 -2
- package/ts_build/src/services/EventService.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.d.ts +41 -1
- package/ts_build/src/services/KnowhowClient.js +42 -0
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/LazyToolsService.d.ts +29 -0
- package/ts_build/src/services/LazyToolsService.js +96 -0
- package/ts_build/src/services/LazyToolsService.js.map +1 -0
- package/ts_build/src/services/Mcp.d.ts +18 -1
- package/ts_build/src/services/Mcp.js +119 -4
- package/ts_build/src/services/Mcp.js.map +1 -1
- package/ts_build/src/services/SessionManager.d.ts +15 -0
- package/ts_build/src/services/SessionManager.js +220 -0
- package/ts_build/src/services/SessionManager.js.map +1 -0
- package/ts_build/src/services/TaskRegistry.d.ts +15 -0
- package/ts_build/src/services/TaskRegistry.js +58 -0
- package/ts_build/src/services/TaskRegistry.js.map +1 -0
- package/ts_build/src/services/Tools.d.ts +2 -0
- package/ts_build/src/services/Tools.js.map +1 -1
- package/ts_build/src/services/index.d.ts +4 -0
- package/ts_build/src/services/index.js +4 -0
- package/ts_build/src/services/index.js.map +1 -1
- package/ts_build/src/services/script-execution/ScriptExecutor.js +7 -5
- package/ts_build/src/services/script-execution/ScriptExecutor.js.map +1 -1
- package/ts_build/src/types.d.ts +1 -0
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/src/utils/InputQueueManager.d.ts +9 -2
- package/ts_build/src/utils/InputQueueManager.js +54 -40
- package/ts_build/src/utils/InputQueueManager.js.map +1 -1
- package/ts_build/src/utils/errors.d.ts +0 -0
- package/ts_build/src/utils/errors.js +1 -0
- package/ts_build/src/utils/errors.js.map +1 -0
- package/ts_build/src/utils/index.d.ts +1 -0
- package/ts_build/src/utils/index.js +5 -1
- package/ts_build/src/utils/index.js.map +1 -1
- package/ts_build/src/worker.js +8 -0
- package/ts_build/src/worker.js.map +1 -1
- package/ts_build/tests/compressor/bigstring.test.d.ts +1 -0
- package/ts_build/tests/compressor/bigstring.test.js +66 -0
- package/ts_build/tests/compressor/bigstring.test.js.map +1 -0
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +6 -5
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +1 -1
- package/ts_build/tests/plugins/language/languagePlugin-integration.test.js +9 -7
- package/ts_build/tests/plugins/language/languagePlugin-integration.test.js.map +1 -1
- package/ts_build/tests/plugins/language/languagePlugin.test.js +7 -4
- package/ts_build/tests/plugins/language/languagePlugin.test.js.map +1 -1
- package/ts_build/tests/processors/ToolResponseCache.test.js +107 -0
- package/ts_build/tests/processors/ToolResponseCache.test.js.map +1 -1
- package/ts_build/tests/unit/InputQueueManager.test.d.ts +1 -0
- package/ts_build/tests/unit/InputQueueManager.test.js +104 -0
- package/ts_build/tests/unit/InputQueueManager.test.js.map +1 -0
|
@@ -3,6 +3,7 @@ import * as path from "path";
|
|
|
3
3
|
import * as os from "os";
|
|
4
4
|
import { Config } from "../types";
|
|
5
5
|
import { updateConfig } from "../config";
|
|
6
|
+
import * as crypto from "crypto";
|
|
6
7
|
|
|
7
8
|
export interface DockerWorkerOptions {
|
|
8
9
|
workspaceDir: string;
|
|
@@ -234,15 +235,50 @@ export class DockerService {
|
|
|
234
235
|
return { valid, errors };
|
|
235
236
|
}
|
|
236
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Generate a short hash from the workspace directory path
|
|
240
|
+
* This ensures one container per workspace directory
|
|
241
|
+
*/
|
|
242
|
+
private getWorkspaceHash(workspaceDir: string): string {
|
|
243
|
+
const hash = crypto.createHash("md5").update(workspaceDir).digest("hex");
|
|
244
|
+
// Return first 8 characters for a short, readable hash
|
|
245
|
+
return hash.substring(0, 8);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Stop and remove a container by name if it exists
|
|
250
|
+
*/
|
|
251
|
+
private async removeContainerByName(containerName: string): Promise<void> {
|
|
252
|
+
try {
|
|
253
|
+
// Check if container exists
|
|
254
|
+
const { stdout } = await execAsync(
|
|
255
|
+
`docker ps -a --filter "name=^/${containerName}$" --format "{{.ID}}"`
|
|
256
|
+
);
|
|
257
|
+
const containerId = stdout.trim();
|
|
258
|
+
|
|
259
|
+
if (containerId) {
|
|
260
|
+
console.log(`🗑️ Removing existing container: ${containerName}`);
|
|
261
|
+
await execAsync(`docker stop ${containerId}`);
|
|
262
|
+
await execAsync(`docker rm ${containerId}`);
|
|
263
|
+
}
|
|
264
|
+
} catch (error) {
|
|
265
|
+
// Ignore errors if container doesn't exist
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
237
269
|
/**
|
|
238
270
|
* Run the knowhow worker in a Docker container
|
|
239
271
|
*/
|
|
240
272
|
async runWorkerContainer(options: DockerWorkerOptions): Promise<string> {
|
|
241
|
-
const
|
|
273
|
+
const workspaceHash = this.getWorkspaceHash(options.workspaceDir);
|
|
274
|
+
const containerName = `${DockerService.CONTAINER_PREFIX}-${workspaceHash}`;
|
|
242
275
|
const homedir = os.homedir();
|
|
243
276
|
const relativeWorkspace = options.workspaceDir.replace(homedir, "~");
|
|
244
277
|
const knowhowDir = path.join(homedir, ".knowhow");
|
|
245
278
|
const relativeKnowhowDir = "~/.knowhow";
|
|
279
|
+
// Remove any existing container for this workspace
|
|
280
|
+
await this.removeContainerByName(containerName);
|
|
281
|
+
|
|
246
282
|
|
|
247
283
|
let config = options.config;
|
|
248
284
|
|
|
@@ -8,6 +8,12 @@ export interface EventHandler {
|
|
|
8
8
|
export class EventService extends EventEmitter {
|
|
9
9
|
private blockingHandlers: Map<string, EventHandler[]> = new Map();
|
|
10
10
|
|
|
11
|
+
eventTypes = {
|
|
12
|
+
agentMsg: "agent:msg",
|
|
13
|
+
agentsRegister: "agents:register",
|
|
14
|
+
agentsCall: "agents:call",
|
|
15
|
+
};
|
|
16
|
+
|
|
11
17
|
constructor() {
|
|
12
18
|
super();
|
|
13
19
|
}
|
|
@@ -87,12 +93,12 @@ export class EventService extends EventEmitter {
|
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
registerAgent(agent: IAgent): void {
|
|
90
|
-
this.emit(
|
|
96
|
+
this.emit(this.eventTypes.agentsRegister, { name: agent.name, agent });
|
|
91
97
|
}
|
|
92
98
|
|
|
93
99
|
callAgent(name: string, query: string): Promise<string> {
|
|
94
100
|
return new Promise((resolve, reject) => {
|
|
95
|
-
this.emit(
|
|
101
|
+
this.emit(this.eventTypes.agentsCall, { name, query, resolve, reject });
|
|
96
102
|
});
|
|
97
103
|
}
|
|
98
104
|
}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
CompletionResponse,
|
|
8
8
|
EmbeddingOptions,
|
|
9
9
|
EmbeddingResponse,
|
|
10
|
-
} from "
|
|
10
|
+
} from "../clients";
|
|
11
11
|
import { Config } from "../types";
|
|
12
12
|
|
|
13
13
|
// Chat Task interfaces
|
|
@@ -33,6 +33,46 @@ export interface UpdateOrgTaskResponse {
|
|
|
33
33
|
inProgress: boolean;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
// Agent task synchronization interfaces
|
|
37
|
+
export interface TaskDetailsResponse {
|
|
38
|
+
taskId: string;
|
|
39
|
+
inProgress: boolean;
|
|
40
|
+
status: "running" | "paused" | "killed" | "completed";
|
|
41
|
+
totalUsdCost: number;
|
|
42
|
+
threads: any;
|
|
43
|
+
createdAt: string;
|
|
44
|
+
updatedAt: string;
|
|
45
|
+
messageId?: string;
|
|
46
|
+
hasPendingMessages: boolean;
|
|
47
|
+
pendingMessagesCount: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface PendingMessage {
|
|
51
|
+
id: string;
|
|
52
|
+
message: string;
|
|
53
|
+
role: string;
|
|
54
|
+
createdAt: Date;
|
|
55
|
+
processedAt: Date | null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface SendMessageRequest {
|
|
59
|
+
message: string;
|
|
60
|
+
role?: "user" | "system";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface SendMessageResponse {
|
|
64
|
+
id: string;
|
|
65
|
+
message: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface StatusResponse {
|
|
69
|
+
status: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface MarkProcessedResponse {
|
|
73
|
+
processedCount: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
36
76
|
export function loadKnowhowJwt(): string {
|
|
37
77
|
const jwtFile = path.join(process.cwd(), ".knowhow", ".jwt");
|
|
38
78
|
if (!fs.existsSync(jwtFile)) {
|
|
@@ -183,4 +223,104 @@ export class KnowhowSimpleClient {
|
|
|
183
223
|
}
|
|
184
224
|
);
|
|
185
225
|
}
|
|
226
|
+
|
|
227
|
+
// ============================================
|
|
228
|
+
// Agent Task Synchronization Methods
|
|
229
|
+
// ============================================
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Get task details including status, threads, and pending message info
|
|
233
|
+
*/
|
|
234
|
+
async getTaskDetails(taskId: string) {
|
|
235
|
+
await this.checkJwt();
|
|
236
|
+
return axios.get<TaskDetailsResponse>(
|
|
237
|
+
`${this.baseUrl}/api/org-agent-tasks/${taskId}`,
|
|
238
|
+
{
|
|
239
|
+
headers: this.headers,
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Get pending messages for an agent task
|
|
246
|
+
*/
|
|
247
|
+
async getPendingMessages(taskId: string) {
|
|
248
|
+
await this.checkJwt();
|
|
249
|
+
return axios.get<PendingMessage[]>(
|
|
250
|
+
`${this.baseUrl}/api/org-agent-tasks/${taskId}/pending-messages`,
|
|
251
|
+
{
|
|
252
|
+
headers: this.headers,
|
|
253
|
+
}
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Mark pending messages as processed
|
|
259
|
+
*/
|
|
260
|
+
async markMessagesAsProcessed(taskId: string, messageIds: string[]) {
|
|
261
|
+
await this.checkJwt();
|
|
262
|
+
return axios.post<MarkProcessedResponse>(
|
|
263
|
+
`${this.baseUrl}/api/org-agent-tasks/${taskId}/pending-messages/mark-processed`,
|
|
264
|
+
{ messageIds },
|
|
265
|
+
{
|
|
266
|
+
headers: this.headers,
|
|
267
|
+
}
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Send a message to a running agent task
|
|
273
|
+
*/
|
|
274
|
+
async sendMessageToAgent(taskId: string, message: string, role: "user" | "system" = "user") {
|
|
275
|
+
await this.checkJwt();
|
|
276
|
+
return axios.post<SendMessageResponse>(
|
|
277
|
+
`${this.baseUrl}/api/org-agent-tasks/${taskId}/messages`,
|
|
278
|
+
{ message, role },
|
|
279
|
+
{
|
|
280
|
+
headers: this.headers,
|
|
281
|
+
}
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Pause a running agent task
|
|
287
|
+
*/
|
|
288
|
+
async pauseAgent(taskId: string) {
|
|
289
|
+
await this.checkJwt();
|
|
290
|
+
return axios.post<StatusResponse>(
|
|
291
|
+
`${this.baseUrl}/api/org-agent-tasks/${taskId}/pause`,
|
|
292
|
+
{},
|
|
293
|
+
{
|
|
294
|
+
headers: this.headers,
|
|
295
|
+
}
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Resume a paused agent task
|
|
301
|
+
*/
|
|
302
|
+
async resumeAgent(taskId: string) {
|
|
303
|
+
await this.checkJwt();
|
|
304
|
+
return axios.post<StatusResponse>(
|
|
305
|
+
`${this.baseUrl}/api/org-agent-tasks/${taskId}/resume`,
|
|
306
|
+
{},
|
|
307
|
+
{
|
|
308
|
+
headers: this.headers,
|
|
309
|
+
}
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Kill/cancel a running or paused agent task
|
|
315
|
+
*/
|
|
316
|
+
async killAgent(taskId: string) {
|
|
317
|
+
await this.checkJwt();
|
|
318
|
+
return axios.post<StatusResponse>(
|
|
319
|
+
`${this.baseUrl}/api/org-agent-tasks/${taskId}/kill`,
|
|
320
|
+
{},
|
|
321
|
+
{
|
|
322
|
+
headers: this.headers,
|
|
323
|
+
}
|
|
324
|
+
);
|
|
325
|
+
}
|
|
186
326
|
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { minimatch } from "minimatch";
|
|
2
|
+
import { ToolsService, ToolContext } from "./Tools";
|
|
3
|
+
import { Tool } from "../clients/types";
|
|
4
|
+
import {
|
|
5
|
+
listAvailableTools,
|
|
6
|
+
enableTools,
|
|
7
|
+
disableTools,
|
|
8
|
+
} from "../agents/tools/lazy";
|
|
9
|
+
import { definitions } from "../agents/tools/lazy/definitions";
|
|
10
|
+
|
|
11
|
+
export class LazyToolsService extends ToolsService {
|
|
12
|
+
private allTools: Tool[] = [];
|
|
13
|
+
// Start with lazy tools enabled by default
|
|
14
|
+
private enabledPatterns: string[] = [
|
|
15
|
+
"listAvailableTools",
|
|
16
|
+
"enableTools",
|
|
17
|
+
"disableTools",
|
|
18
|
+
"finalAnswer",
|
|
19
|
+
];
|
|
20
|
+
private disabledPatterns: string[] = [];
|
|
21
|
+
|
|
22
|
+
constructor(context?: ToolContext) {
|
|
23
|
+
super(context);
|
|
24
|
+
this.registerLazyTools();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Registers lazy tool management tools
|
|
29
|
+
* These tools are only available when using LazyToolsService
|
|
30
|
+
*/
|
|
31
|
+
private registerLazyTools(): void {
|
|
32
|
+
// Add to allTools so they're always available
|
|
33
|
+
this.allTools.push(...definitions);
|
|
34
|
+
|
|
35
|
+
// Add to visible tools so they're immediately accessible
|
|
36
|
+
super.addTools(definitions);
|
|
37
|
+
|
|
38
|
+
// Register the function implementations
|
|
39
|
+
this.addFunctions({
|
|
40
|
+
listAvailableTools: listAvailableTools.bind(this),
|
|
41
|
+
enableTools: enableTools.bind(this),
|
|
42
|
+
disableTools: disableTools.bind(this),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Override addTools to store all tools but not expose them yet
|
|
47
|
+
addTools(tools: Tool[]) {
|
|
48
|
+
// Store tools in allTools instead of this.tools
|
|
49
|
+
const existingNames = this.allTools.map((t) => t.function.name);
|
|
50
|
+
const newTools = tools.filter(
|
|
51
|
+
(t) => !existingNames.includes(t.function.name)
|
|
52
|
+
);
|
|
53
|
+
this.allTools.push(...newTools);
|
|
54
|
+
|
|
55
|
+
// Update visible tools based on patterns
|
|
56
|
+
this.updateVisibleTools();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Override getTools to return only enabled tools
|
|
60
|
+
getTools() {
|
|
61
|
+
return this.tools; // Returns filtered subset
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Enable tools matching glob patterns
|
|
65
|
+
enableTools(patterns: string | string[]) {
|
|
66
|
+
const patternArray = Array.isArray(patterns) ? patterns : [patterns];
|
|
67
|
+
|
|
68
|
+
for (const pattern of patternArray) {
|
|
69
|
+
if (!this.enabledPatterns.includes(pattern)) {
|
|
70
|
+
this.enabledPatterns.push(pattern);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
this.updateVisibleTools();
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
enabled: this.tools.length,
|
|
78
|
+
total: this.allTools.length,
|
|
79
|
+
patterns: this.enabledPatterns,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Disable tools matching glob patterns
|
|
84
|
+
disableTools(patterns: string | string[]) {
|
|
85
|
+
const patternArray = Array.isArray(patterns) ? patterns : [patterns];
|
|
86
|
+
|
|
87
|
+
for (const pattern of patternArray) {
|
|
88
|
+
if (!this.disabledPatterns.includes(pattern)) {
|
|
89
|
+
this.disabledPatterns.push(pattern);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.updateVisibleTools();
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
enabled: this.tools.length,
|
|
97
|
+
total: this.allTools.length,
|
|
98
|
+
patterns: this.disabledPatterns,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// List all available tools (not just enabled ones)
|
|
103
|
+
listAvailableTools() {
|
|
104
|
+
return {
|
|
105
|
+
enabled: this.tools.map((t) => t.function.name),
|
|
106
|
+
disabled: this.allTools
|
|
107
|
+
.filter(
|
|
108
|
+
(t) => !this.tools.find((et) => et.function.name === t.function.name)
|
|
109
|
+
)
|
|
110
|
+
.map((t) => t.function.name),
|
|
111
|
+
total: this.allTools.length,
|
|
112
|
+
enabledCount: this.tools.length,
|
|
113
|
+
disabledCount: this.allTools.length - this.tools.length,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Internal: Update visible tools based on patterns
|
|
118
|
+
private updateVisibleTools() {
|
|
119
|
+
const enabledTools: Tool[] = [];
|
|
120
|
+
|
|
121
|
+
for (const tool of this.allTools) {
|
|
122
|
+
const name = tool.function.name;
|
|
123
|
+
|
|
124
|
+
// Check if disabled by any pattern
|
|
125
|
+
const isDisabled = this.disabledPatterns.some((pattern) =>
|
|
126
|
+
minimatch(name, pattern)
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
if (isDisabled) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Check if enabled by any pattern (requires explicit enabling)
|
|
134
|
+
const isEnabled =
|
|
135
|
+
this.enabledPatterns.length > 0 &&
|
|
136
|
+
this.enabledPatterns.some((pattern) => minimatch(name, pattern));
|
|
137
|
+
|
|
138
|
+
if (isEnabled) {
|
|
139
|
+
enabledTools.push(tool);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Update the visible tools array
|
|
144
|
+
this.tools = enabledTools;
|
|
145
|
+
}
|
|
146
|
+
}
|
package/src/services/Mcp.ts
CHANGED
|
@@ -122,13 +122,175 @@ export class McpService {
|
|
|
122
122
|
|
|
123
123
|
async connectTo(mcpServers: McpConfig[] = [], tools?: ToolsService) {
|
|
124
124
|
const clients = await this.createStdioClients(mcpServers);
|
|
125
|
-
await this.
|
|
125
|
+
await this.connectAutoServers();
|
|
126
126
|
|
|
127
127
|
if (tools) {
|
|
128
128
|
await this.addTools(tools);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
// Connect only servers with autoConnect !== false
|
|
133
|
+
async connectAutoServers() {
|
|
134
|
+
await Promise.all(
|
|
135
|
+
this.clients.map(async (client, index) => {
|
|
136
|
+
const config = this.config[index];
|
|
137
|
+
const shouldAutoConnect = config.autoConnect !== false;
|
|
138
|
+
|
|
139
|
+
if (shouldAutoConnect && !this.connected[index]) {
|
|
140
|
+
console.log(`Connecting to MCP server: ${config.name}`);
|
|
141
|
+
await client.connect(this.transports[index]);
|
|
142
|
+
this.connected[index] = true;
|
|
143
|
+
} else if (!shouldAutoConnect) {
|
|
144
|
+
console.log(
|
|
145
|
+
`Skipping auto-connect for MCP server: ${config.name} (autoConnect: false)`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Connect to a specific MCP server by name
|
|
153
|
+
async connectSingle(
|
|
154
|
+
serverName: string,
|
|
155
|
+
timeout: number = 30000
|
|
156
|
+
): Promise<{
|
|
157
|
+
success: boolean;
|
|
158
|
+
toolsAdded: string[];
|
|
159
|
+
error?: string;
|
|
160
|
+
}> {
|
|
161
|
+
const index = this.getClientIndex(serverName);
|
|
162
|
+
|
|
163
|
+
if (index < 0) {
|
|
164
|
+
return {
|
|
165
|
+
success: false,
|
|
166
|
+
toolsAdded: [],
|
|
167
|
+
error: `MCP server '${serverName}' not found in configuration`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (this.connected[index]) {
|
|
172
|
+
return {
|
|
173
|
+
success: true,
|
|
174
|
+
toolsAdded: [],
|
|
175
|
+
error: `MCP server '${serverName}' already connected`,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
const client = this.clients[index];
|
|
181
|
+
const transport = this.transports[index];
|
|
182
|
+
|
|
183
|
+
// Connect with timeout
|
|
184
|
+
await Promise.race([
|
|
185
|
+
client.connect(transport),
|
|
186
|
+
new Promise((_, reject) =>
|
|
187
|
+
setTimeout(() => reject(new Error("Connection timeout")), timeout)
|
|
188
|
+
),
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
this.connected[index] = true;
|
|
192
|
+
|
|
193
|
+
// Get tools from this server
|
|
194
|
+
const clientTools = await client.listTools();
|
|
195
|
+
const toolNames: string[] = [];
|
|
196
|
+
|
|
197
|
+
for (const tool of clientTools.tools) {
|
|
198
|
+
const transformed = this.toOpenAiTool(index, tool as any);
|
|
199
|
+
if (transformed.function.name !== tool.name) {
|
|
200
|
+
this.toolAliases[transformed.function.name] = tool.name;
|
|
201
|
+
}
|
|
202
|
+
toolNames.push(transformed.function.name);
|
|
203
|
+
|
|
204
|
+
// Add to cache if not already present
|
|
205
|
+
if (
|
|
206
|
+
!this.tools.find((t) => t.function.name === transformed.function.name)
|
|
207
|
+
) {
|
|
208
|
+
this.tools.push(transformed);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
success: true,
|
|
214
|
+
toolsAdded: toolNames,
|
|
215
|
+
};
|
|
216
|
+
} catch (error) {
|
|
217
|
+
return {
|
|
218
|
+
success: false,
|
|
219
|
+
toolsAdded: [],
|
|
220
|
+
error: error.message,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Disconnect a specific MCP server
|
|
226
|
+
async disconnectSingle(serverName: string): Promise<{
|
|
227
|
+
success: boolean;
|
|
228
|
+
toolsRemoved: string[];
|
|
229
|
+
error?: string;
|
|
230
|
+
}> {
|
|
231
|
+
const index = this.getClientIndex(serverName);
|
|
232
|
+
|
|
233
|
+
if (index < 0) {
|
|
234
|
+
return {
|
|
235
|
+
success: false,
|
|
236
|
+
toolsRemoved: [],
|
|
237
|
+
error: `MCP server '${serverName}' not found`,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (!this.connected[index]) {
|
|
242
|
+
return {
|
|
243
|
+
success: true,
|
|
244
|
+
toolsRemoved: [],
|
|
245
|
+
error: `MCP server '${serverName}' not connected`,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
const toolsToRemove = this.tools
|
|
251
|
+
.filter((t) => this.getToolClientIndex(t.function.name) === index)
|
|
252
|
+
.map((t) => t.function.name);
|
|
253
|
+
|
|
254
|
+
// Close connection
|
|
255
|
+
await this.transports[index]?.close();
|
|
256
|
+
this.connected[index] = false;
|
|
257
|
+
|
|
258
|
+
// Remove tools from cache
|
|
259
|
+
this.tools = this.tools.filter(
|
|
260
|
+
(t) => this.getToolClientIndex(t.function.name) !== index
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
success: true,
|
|
265
|
+
toolsRemoved: toolsToRemove,
|
|
266
|
+
};
|
|
267
|
+
} catch (error) {
|
|
268
|
+
return {
|
|
269
|
+
success: false,
|
|
270
|
+
toolsRemoved: [],
|
|
271
|
+
error: error.message,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Get available servers (connected and disconnected)
|
|
277
|
+
getAvailableServers() {
|
|
278
|
+
return this.config.map((config, index) => {
|
|
279
|
+
const toolCount = this.connected[index]
|
|
280
|
+
? this.tools.filter(
|
|
281
|
+
(t) => this.getToolClientIndex(t.function.name) === index
|
|
282
|
+
).length
|
|
283
|
+
: 0;
|
|
284
|
+
|
|
285
|
+
return {
|
|
286
|
+
name: config.name,
|
|
287
|
+
connected: this.connected[index] || false,
|
|
288
|
+
autoConnect: config.autoConnect !== false,
|
|
289
|
+
toolCount,
|
|
290
|
+
};
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
132
294
|
async addTools(tools: ToolsService) {
|
|
133
295
|
tools.addTools(await this.getTools());
|
|
134
296
|
tools.addFunctions(await this.getToolMap());
|
|
@@ -203,7 +365,7 @@ export class McpService {
|
|
|
203
365
|
return this.clients[index];
|
|
204
366
|
}
|
|
205
367
|
|
|
206
|
-
getFunction(toolName: string) {
|
|
368
|
+
getFunction(toolName: string, timeout?: number) {
|
|
207
369
|
const client = this.getToolClient(toolName);
|
|
208
370
|
|
|
209
371
|
// Handle unwrapped tool names if we have 1 client
|
|
@@ -227,8 +389,8 @@ export class McpService {
|
|
|
227
389
|
},
|
|
228
390
|
CallToolResultSchema,
|
|
229
391
|
{
|
|
230
|
-
timeout: 10 * 60 * 1000,
|
|
231
|
-
maxTotalTimeout: 10 * 60 * 1000,
|
|
392
|
+
timeout: timeout || 10 * 60 * 1000,
|
|
393
|
+
maxTotalTimeout: timeout || 10 * 60 * 1000,
|
|
232
394
|
}
|
|
233
395
|
);
|
|
234
396
|
return tool;
|
|
@@ -314,6 +476,11 @@ export class McpService {
|
|
|
314
476
|
for (let i = 0; i < this.config.length; i++) {
|
|
315
477
|
const config = this.config[i];
|
|
316
478
|
const client = this.clients[i];
|
|
479
|
+
|
|
480
|
+
if (!this.connected[i]) {
|
|
481
|
+
// skip adding tools for unconnected clients
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
317
484
|
const clientTools = await client.listTools();
|
|
318
485
|
|
|
319
486
|
for (const tool of clientTools.tools) {
|