@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
package/src/cli.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node --no-node-snapshot
|
|
2
2
|
import "source-map-support/register";
|
|
3
3
|
import * as fs from "fs";
|
|
4
4
|
import * as path from "path";
|
|
@@ -11,7 +11,7 @@ import { init } from "./config";
|
|
|
11
11
|
import { download, purge } from ".";
|
|
12
12
|
import { includedTools } from "./agents/tools/list";
|
|
13
13
|
import * as allTools from "./agents/tools";
|
|
14
|
-
import { services } from "./services";
|
|
14
|
+
import { LazyToolsService, services } from "./services";
|
|
15
15
|
import { login } from "./login";
|
|
16
16
|
import { worker } from "./worker";
|
|
17
17
|
import {
|
|
@@ -35,8 +35,14 @@ import { SetupModule } from "./chat/modules/SetupModule";
|
|
|
35
35
|
import { CliChatService } from "./chat/CliChatService";
|
|
36
36
|
|
|
37
37
|
async function setupServices() {
|
|
38
|
-
const {
|
|
39
|
-
const
|
|
38
|
+
const { Agents, Mcp, Clients } = services();
|
|
39
|
+
const Tools = new LazyToolsService();
|
|
40
|
+
|
|
41
|
+
const { Researcher, Developer, Patcher, Setup } = agents({
|
|
42
|
+
...services(),
|
|
43
|
+
Tools,
|
|
44
|
+
});
|
|
45
|
+
|
|
40
46
|
Agents.registerAgent(Researcher);
|
|
41
47
|
Agents.registerAgent(Patcher);
|
|
42
48
|
Agents.registerAgent(Developer);
|
|
@@ -45,6 +51,9 @@ async function setupServices() {
|
|
|
45
51
|
|
|
46
52
|
Tools.defineTools(includedTools, allTools);
|
|
47
53
|
|
|
54
|
+
// Add Mcp service to tool context directly so MCP management tools can access it
|
|
55
|
+
Tools.addContext("Mcp", Mcp);
|
|
56
|
+
|
|
48
57
|
await Promise.all([
|
|
49
58
|
Mcp.connectToConfigured(Tools),
|
|
50
59
|
Clients.registerConfiguredModels(),
|
|
@@ -81,9 +90,6 @@ async function main() {
|
|
|
81
90
|
.description("AI CLI with plugins and agents")
|
|
82
91
|
.version(version);
|
|
83
92
|
|
|
84
|
-
// Initialize services for all commands
|
|
85
|
-
await setupServices();
|
|
86
|
-
|
|
87
93
|
program
|
|
88
94
|
.command("init")
|
|
89
95
|
.description("Initialize knowhow configuration")
|
|
@@ -103,6 +109,7 @@ async function main() {
|
|
|
103
109
|
.command("generate")
|
|
104
110
|
.description("Generate documentation")
|
|
105
111
|
.action(async () => {
|
|
112
|
+
await setupServices();
|
|
106
113
|
await generate();
|
|
107
114
|
});
|
|
108
115
|
|
|
@@ -110,6 +117,7 @@ async function main() {
|
|
|
110
117
|
.command("embed")
|
|
111
118
|
.description("Create embeddings")
|
|
112
119
|
.action(async () => {
|
|
120
|
+
await setupServices();
|
|
113
121
|
await embed();
|
|
114
122
|
});
|
|
115
123
|
|
|
@@ -139,6 +147,7 @@ async function main() {
|
|
|
139
147
|
.command("chat")
|
|
140
148
|
.description("Start new chat interface")
|
|
141
149
|
.action(async () => {
|
|
150
|
+
await setupServices();
|
|
142
151
|
await startChat();
|
|
143
152
|
});
|
|
144
153
|
|
|
@@ -166,6 +175,7 @@ async function main() {
|
|
|
166
175
|
.option("--input <text>", "Task input (fallback to stdin if not provided)")
|
|
167
176
|
.action(async (options) => {
|
|
168
177
|
try {
|
|
178
|
+
await setupServices();
|
|
169
179
|
let input = options.input;
|
|
170
180
|
if (!input) {
|
|
171
181
|
input = await readStdin();
|
|
@@ -204,6 +214,7 @@ async function main() {
|
|
|
204
214
|
.option("--prompt-file <path>", "Custom prompt template file")
|
|
205
215
|
.action(async (options) => {
|
|
206
216
|
try {
|
|
217
|
+
await setupServices();
|
|
207
218
|
let input = options.input;
|
|
208
219
|
if (!input) {
|
|
209
220
|
input = await readStdin();
|
|
@@ -235,6 +246,7 @@ async function main() {
|
|
|
235
246
|
.description("Ask the agent to configure knowhow")
|
|
236
247
|
.action(async (options) => {
|
|
237
248
|
try {
|
|
249
|
+
await setupServices();
|
|
238
250
|
const setupModule = new SetupModule();
|
|
239
251
|
await setupModule.initialize(chatService);
|
|
240
252
|
await setupModule.handleSetupCommand([]);
|
|
@@ -258,6 +270,7 @@ async function main() {
|
|
|
258
270
|
)
|
|
259
271
|
.action(async (options) => {
|
|
260
272
|
try {
|
|
273
|
+
await setupServices();
|
|
261
274
|
let input = options.input;
|
|
262
275
|
if (!input) {
|
|
263
276
|
input = await readStdin();
|
|
@@ -292,13 +305,22 @@ async function main() {
|
|
|
292
305
|
|
|
293
306
|
program
|
|
294
307
|
.command("worker")
|
|
295
|
-
.description(
|
|
308
|
+
.description(
|
|
309
|
+
"Start worker process and optionally register current directory"
|
|
310
|
+
)
|
|
296
311
|
.option("--register", "Register current directory as a worker path")
|
|
297
|
-
.option(
|
|
312
|
+
.option(
|
|
313
|
+
"--share",
|
|
314
|
+
"Share this worker with your organization (allows other users to use it)"
|
|
315
|
+
)
|
|
298
316
|
.option("--unshare", "Make this worker private (only you can use it)")
|
|
299
317
|
.option("--sandbox", "Run worker in a Docker container for isolation")
|
|
300
|
-
.option(
|
|
318
|
+
.option(
|
|
319
|
+
"--no-sandbox",
|
|
320
|
+
"Run worker directly on host (disable sandbox mode)"
|
|
321
|
+
)
|
|
301
322
|
.action(async (options) => {
|
|
323
|
+
await setupServices();
|
|
302
324
|
await worker(options);
|
|
303
325
|
});
|
|
304
326
|
|
|
@@ -337,6 +359,7 @@ async function main() {
|
|
|
337
359
|
}
|
|
338
360
|
|
|
339
361
|
// Default action: start all workers
|
|
362
|
+
await setupServices();
|
|
340
363
|
await startAllWorkers();
|
|
341
364
|
} catch (error) {
|
|
342
365
|
console.error("Error managing workers:", error);
|
package/src/plugins/GitPlugin.ts
CHANGED
|
@@ -19,6 +19,7 @@ export class GitPlugin extends PluginBase {
|
|
|
19
19
|
private projectHasGit: boolean = false;
|
|
20
20
|
private eventService: EventService;
|
|
21
21
|
private currentTask: string | null = null;
|
|
22
|
+
static isListening = false;
|
|
22
23
|
|
|
23
24
|
constructor(context: PluginContext = {}) {
|
|
24
25
|
super(context);
|
|
@@ -96,9 +97,7 @@ Your modifications are automatically tracked separately and won't affect the use
|
|
|
96
97
|
// since HEAD doesn't exist yet
|
|
97
98
|
try {
|
|
98
99
|
this.gitCommand("add -A");
|
|
99
|
-
this.gitCommand(
|
|
100
|
-
'commit -m "Initial commit for agent tracking"'
|
|
101
|
-
);
|
|
100
|
+
this.gitCommand('commit -m "Initial commit for agent tracking"');
|
|
102
101
|
} catch (error) {
|
|
103
102
|
// If there's nothing to commit, create an empty commit
|
|
104
103
|
this.gitCommand(
|
|
@@ -150,26 +149,30 @@ Your modifications are automatically tracked separately and won't affect the use
|
|
|
150
149
|
|
|
151
150
|
private setupEventListeners(): void {
|
|
152
151
|
// Listen for file:post-edit events to auto-commit
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
152
|
+
if (!GitPlugin.isListening) {
|
|
153
|
+
this.eventService.on("file:post-edit", async (data: any) => {
|
|
154
|
+
if (this.isEnabled()) {
|
|
155
|
+
await this.autoCommit(data);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
159
|
+
// Listen for agent newTask events to create new branches
|
|
160
|
+
this.eventService.on("agent:newTask", async (data: any) => {
|
|
161
|
+
if (this.isEnabled()) {
|
|
162
|
+
await this.ensureCleanState(data);
|
|
163
|
+
await this.handleNewTask(data);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
167
|
+
// Listen for task completion events to squash merge
|
|
168
|
+
this.eventService.on("agent:taskComplete", async (data: any) => {
|
|
169
|
+
if (this.isEnabled()) {
|
|
170
|
+
await this.handleTaskComplete(data);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
GitPlugin.isListening = true;
|
|
175
|
+
}
|
|
173
176
|
}
|
|
174
177
|
|
|
175
178
|
/**
|
|
@@ -306,8 +309,8 @@ Your modifications are automatically tracked separately and won't affect the use
|
|
|
306
309
|
this.ensureValidHead();
|
|
307
310
|
|
|
308
311
|
// Commit the changes
|
|
309
|
-
const escapedMessage = message.replace(/\n/g,
|
|
310
|
-
this.gitCommand(`commit -m "${escapedMessage}"`);
|
|
312
|
+
const escapedMessage = message.replace(/\n/g, "\\n");
|
|
313
|
+
this.gitCommand(`commit --allow-empty -m "${escapedMessage}"`);
|
|
311
314
|
}
|
|
312
315
|
|
|
313
316
|
async commitAll(message: string): Promise<void> {
|
|
@@ -356,11 +359,14 @@ Your modifications are automatically tracked separately and won't affect the use
|
|
|
356
359
|
|
|
357
360
|
this.eventService.emit(
|
|
358
361
|
"agent:msg",
|
|
359
|
-
`
|
|
362
|
+
`
|
|
363
|
+
<Workflow>
|
|
364
|
+
GitPlugin::Commit: ${enhancedMessage} on branch: ${this.getCurrentBranch()}
|
|
360
365
|
You can access your change history via git --git-dir ${
|
|
361
366
|
this.knowhowGitPath
|
|
362
367
|
} log or other commands
|
|
363
368
|
This can be used to revert changes, or compare against previous states during a task.
|
|
369
|
+
</Workflow>
|
|
364
370
|
`
|
|
365
371
|
);
|
|
366
372
|
} catch (error) {
|
package/src/plugins/language.ts
CHANGED
|
@@ -46,11 +46,25 @@ export class LanguagePlugin extends PluginBase implements Plugin {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
// Register handlers for each event
|
|
49
|
-
allEvents.
|
|
49
|
+
const fileEvents = Array.from(allEvents).filter((e: string) =>
|
|
50
|
+
e.startsWith("file")
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const otherEvents = Array.from(allEvents).filter(
|
|
54
|
+
(e: string) => !e.startsWith("file")
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
fileEvents.forEach((eventType) => {
|
|
50
58
|
this.eventService.on(eventType, async (eventData) => {
|
|
51
59
|
await this.handleFileEvent(eventType, eventData);
|
|
52
60
|
});
|
|
53
61
|
});
|
|
62
|
+
|
|
63
|
+
otherEvents.forEach((eventType) => {
|
|
64
|
+
this.eventService.on(eventType, async (eventData) => {
|
|
65
|
+
await this.handleGenericEvent(eventType, eventData);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
54
68
|
} catch (error) {
|
|
55
69
|
console.error("LANGUAGE PLUGIN: Error setting up event handlers:", error);
|
|
56
70
|
}
|
|
@@ -143,7 +157,10 @@ export class LanguagePlugin extends PluginBase implements Plugin {
|
|
|
143
157
|
const matches = patterns.some(
|
|
144
158
|
(pattern) =>
|
|
145
159
|
minimatch(filePath, pattern) ||
|
|
146
|
-
fileContent
|
|
160
|
+
fileContent
|
|
161
|
+
.toString()
|
|
162
|
+
.toLowerCase()
|
|
163
|
+
.includes(pattern.toLowerCase())
|
|
147
164
|
);
|
|
148
165
|
return matches;
|
|
149
166
|
})
|
|
@@ -153,21 +170,12 @@ export class LanguagePlugin extends PluginBase implements Plugin {
|
|
|
153
170
|
// Resolve sources for matching terms
|
|
154
171
|
const resolvedSources = await this.resolveSources(matchingFileTerms);
|
|
155
172
|
|
|
156
|
-
|
|
157
|
-
this.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
matchingTerms: matchingFileTerms,
|
|
163
|
-
eventType,
|
|
164
|
-
resolvedSources,
|
|
165
|
-
contextMessage: `LANGUAGE PLUGIN: File event ${eventType} on ${filePath} triggered contextual expansions for terms: ${matchingFileTerms.join(
|
|
166
|
-
", "
|
|
167
|
-
)}.
|
|
168
|
-
Expanded context: ${JSON.stringify(resolvedSources)}
|
|
169
|
-
These terms are directly related to the file operation so be sure to contextualize your response to this information.`,
|
|
170
|
-
})
|
|
173
|
+
const message = `These terms are directly related to the file operation so be sure to contextualize your response to this information.`;
|
|
174
|
+
this.emitAgentMessage(
|
|
175
|
+
eventType,
|
|
176
|
+
matchingFileTerms,
|
|
177
|
+
resolvedSources,
|
|
178
|
+
message
|
|
171
179
|
);
|
|
172
180
|
}
|
|
173
181
|
} catch (error) {
|
|
@@ -175,11 +183,72 @@ export class LanguagePlugin extends PluginBase implements Plugin {
|
|
|
175
183
|
}
|
|
176
184
|
}
|
|
177
185
|
|
|
186
|
+
private emitAgentMessage(
|
|
187
|
+
eventType: string,
|
|
188
|
+
matchingTerms: string[],
|
|
189
|
+
resolvedSources: any[],
|
|
190
|
+
context: string
|
|
191
|
+
) {
|
|
192
|
+
this.eventService.emit(
|
|
193
|
+
"agent:msg",
|
|
194
|
+
|
|
195
|
+
`<Workflow>
|
|
196
|
+
${JSON.stringify({
|
|
197
|
+
type: "language_context_trigger",
|
|
198
|
+
eventType,
|
|
199
|
+
matchingTerms,
|
|
200
|
+
resolvedSources,
|
|
201
|
+
contextMessage: `LANGUAGE PLUGIN: Agent event ${eventType} triggered contextual expansions for terms: ${matchingTerms.join(
|
|
202
|
+
", "
|
|
203
|
+
)}.
|
|
204
|
+
Expanded context: ${JSON.stringify(resolvedSources)}
|
|
205
|
+
These terms are directly related to what the agent is discussing so be sure to contextualize your response to this information.
|
|
206
|
+
${context}
|
|
207
|
+
`,
|
|
208
|
+
})}
|
|
209
|
+
</Workflow>
|
|
210
|
+
`
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Handle agent message and say events and emit agent messages when patterns match
|
|
216
|
+
*/
|
|
217
|
+
private async handleGenericEvent(eventType: string, eventData: any) {
|
|
218
|
+
try {
|
|
219
|
+
const languageConfig = await getLanguageConfig();
|
|
220
|
+
const userPrompt = JSON.stringify(eventData);
|
|
221
|
+
const isJsonObj = userPrompt.startsWith("{") && userPrompt.endsWith("}");
|
|
222
|
+
|
|
223
|
+
// Skip if this is probably a language_context_trigger to avoid loops
|
|
224
|
+
if (userPrompt.includes("language_context_trigger")) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const matchingTerms = await this.getMatchingTerms(userPrompt);
|
|
229
|
+
|
|
230
|
+
if (matchingTerms.length > 0) {
|
|
231
|
+
// Resolve sources for matching terms
|
|
232
|
+
const resolvedSources = await this.resolveSources(matchingTerms);
|
|
233
|
+
|
|
234
|
+
const message = `These terms are directly related to the agent's message so be sure to contextualize your response to this information.`;
|
|
235
|
+
this.emitAgentMessage(
|
|
236
|
+
eventType,
|
|
237
|
+
matchingTerms,
|
|
238
|
+
resolvedSources,
|
|
239
|
+
message
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
} catch (error) {
|
|
243
|
+
console.error("LANGUAGE PLUGIN: Error handling agent event:", error);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
178
247
|
async embed(userPrompt: string) {
|
|
179
248
|
return [];
|
|
180
249
|
}
|
|
181
250
|
|
|
182
|
-
async
|
|
251
|
+
async getMatchingTerms(userPrompt: string) {
|
|
183
252
|
// Get language configuration
|
|
184
253
|
const languageConfig = await getLanguageConfig();
|
|
185
254
|
const terms = Object.keys(languageConfig);
|
|
@@ -194,6 +263,12 @@ export class LanguagePlugin extends PluginBase implements Plugin {
|
|
|
194
263
|
: userPrompt.toLowerCase().includes(trimmedPattern.toLowerCase());
|
|
195
264
|
})
|
|
196
265
|
);
|
|
266
|
+
return matchingTerms;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async call(userPrompt: string) {
|
|
270
|
+
// Get language configuration
|
|
271
|
+
const matchingTerms = await this.getMatchingTerms(userPrompt);
|
|
197
272
|
|
|
198
273
|
if (matchingTerms.length === 0) {
|
|
199
274
|
return "LANGUAGE PLUGIN: No matching terms found";
|
|
@@ -206,6 +281,8 @@ export class LanguagePlugin extends PluginBase implements Plugin {
|
|
|
206
281
|
return "LANGUAGE PLUGIN: No matching terms found";
|
|
207
282
|
}
|
|
208
283
|
|
|
284
|
+
console.log("LANGUAGE PLUGIN: Matching terms found:", matchingTerms);
|
|
285
|
+
|
|
209
286
|
// Return the file contents in a format that can be added to the prompt context
|
|
210
287
|
return `LANGUAGE PLUGIN: The user mentioned these terms triggering contextual expansions ${matchingTerms} expanded to: ${JSON.stringify(
|
|
211
288
|
contexts
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { Message } from "../clients/types";
|
|
2
2
|
import { MessageProcessorFunction } from "../services/MessageProcessor";
|
|
3
3
|
import { ToolsService } from "../services";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
jqToolResponseDefinition,
|
|
6
|
+
executeJqQuery,
|
|
7
|
+
grepToolResponseDefinition,
|
|
8
|
+
executeGrep,
|
|
9
|
+
GrepOptions,
|
|
10
|
+
tailToolResponseDefinition,
|
|
11
|
+
executeTail,
|
|
12
|
+
TailOptions,
|
|
13
|
+
listStoredToolResponsesDefinition,
|
|
14
|
+
executeListStoredToolResponses,
|
|
15
|
+
} from "./tools";
|
|
6
16
|
|
|
7
17
|
interface ToolResponseStorage {
|
|
8
18
|
[toolCallId: string]: string;
|
|
@@ -21,7 +31,7 @@ interface ToolResponseMetadataStorage {
|
|
|
21
31
|
export class ToolResponseCache {
|
|
22
32
|
private storage: ToolResponseStorage = {};
|
|
23
33
|
private metadataStorage: ToolResponseMetadataStorage = {};
|
|
24
|
-
private
|
|
34
|
+
private toolNameMap: { [toolCallId: string]: string } = {};
|
|
25
35
|
|
|
26
36
|
constructor(toolsService: ToolsService) {
|
|
27
37
|
this.registerTool(toolsService);
|
|
@@ -68,8 +78,19 @@ export class ToolResponseCache {
|
|
|
68
78
|
/**
|
|
69
79
|
* Stores a tool response for later manipulation
|
|
70
80
|
*/
|
|
71
|
-
public storeToolResponse(
|
|
72
|
-
|
|
81
|
+
public storeToolResponse(
|
|
82
|
+
content: string,
|
|
83
|
+
toolCallId: string,
|
|
84
|
+
toolName?: string
|
|
85
|
+
): void {
|
|
86
|
+
// Only store if not already stored - prevents overwriting with compressed data
|
|
87
|
+
// The first time we see a tool response, it contains the original uncompressed content
|
|
88
|
+
// On subsequent passes (after compression), we don't want to overwrite with compressed data
|
|
89
|
+
if (this.storage[toolCallId]) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Store the original content for later JQ/grep manipulation
|
|
73
94
|
this.storage[toolCallId] = content;
|
|
74
95
|
|
|
75
96
|
// Store metadata for reference
|
|
@@ -78,6 +99,10 @@ export class ToolResponseCache {
|
|
|
78
99
|
originalLength: content.length,
|
|
79
100
|
storedAt: Date.now(),
|
|
80
101
|
};
|
|
102
|
+
|
|
103
|
+
if (toolName) {
|
|
104
|
+
this.toolNameMap[toolCallId] = toolName;
|
|
105
|
+
}
|
|
81
106
|
}
|
|
82
107
|
|
|
83
108
|
/**
|
|
@@ -94,7 +119,7 @@ export class ToolResponseCache {
|
|
|
94
119
|
}
|
|
95
120
|
|
|
96
121
|
// Store the tool response silently without modifying the message
|
|
97
|
-
this.storeToolResponse(message.content, message.tool_call_id);
|
|
122
|
+
this.storeToolResponse(message.content, message.tool_call_id, message.name);
|
|
98
123
|
}
|
|
99
124
|
|
|
100
125
|
/**
|
|
@@ -104,7 +129,7 @@ export class ToolResponseCache {
|
|
|
104
129
|
filterFn?: (msg: Message) => boolean
|
|
105
130
|
): MessageProcessorFunction {
|
|
106
131
|
return async (originalMessages: Message[], modifiedMessages: Message[]) => {
|
|
107
|
-
for (const message of
|
|
132
|
+
for (const message of originalMessages) {
|
|
108
133
|
if (filterFn && !filterFn(message)) {
|
|
109
134
|
continue;
|
|
110
135
|
}
|
|
@@ -121,56 +146,44 @@ export class ToolResponseCache {
|
|
|
121
146
|
jqQuery: string
|
|
122
147
|
): Promise<string> {
|
|
123
148
|
const data = this.storage[toolCallId];
|
|
149
|
+
const availableIds = Object.keys(this.storage);
|
|
150
|
+
return executeJqQuery(data, toolCallId, jqQuery, availableIds);
|
|
151
|
+
}
|
|
124
152
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Grep through tool response data to find matching lines
|
|
155
|
+
*/
|
|
156
|
+
async grepToolResponse(
|
|
157
|
+
toolCallId: string,
|
|
158
|
+
pattern: string,
|
|
159
|
+
options?: GrepOptions
|
|
160
|
+
): Promise<string> {
|
|
161
|
+
const data = this.storage[toolCallId];
|
|
162
|
+
const availableIds = Object.keys(this.storage);
|
|
163
|
+
return executeGrep(data, toolCallId, pattern, availableIds, options);
|
|
164
|
+
}
|
|
131
165
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
// Handle the result based on its type
|
|
144
|
-
if (typeof result === "string") {
|
|
145
|
-
return result;
|
|
146
|
-
} else if (typeof result === "number" || typeof result === "boolean") {
|
|
147
|
-
return String(result);
|
|
148
|
-
} else if (result === null) {
|
|
149
|
-
return "null";
|
|
150
|
-
} else {
|
|
151
|
-
return JSON.stringify(result);
|
|
152
|
-
}
|
|
153
|
-
} catch (error: any) {
|
|
154
|
-
// If JQ fails, try to provide helpful error message
|
|
155
|
-
let errorMessage = `JQ Query Error: ${error.message}`;
|
|
156
|
-
|
|
157
|
-
// Try to parse as JSON to see if it's valid
|
|
158
|
-
const jsonObj = this.tryParseJson(data);
|
|
159
|
-
if (!jsonObj) {
|
|
160
|
-
errorMessage += `\nNote: The tool response data is not valid JSON. Raw data preview:\n${data.substring(
|
|
161
|
-
0,
|
|
162
|
-
300
|
|
163
|
-
)}...`;
|
|
164
|
-
} else {
|
|
165
|
-
errorMessage += `\nData structure preview:\n${JSON.stringify(
|
|
166
|
-
jsonObj,
|
|
167
|
-
null,
|
|
168
|
-
2
|
|
169
|
-
).substring(0, 500)}...`;
|
|
170
|
-
}
|
|
166
|
+
/**
|
|
167
|
+
* Get the last n lines from a tool response
|
|
168
|
+
*/
|
|
169
|
+
async tailToolResponse(
|
|
170
|
+
toolCallId: string,
|
|
171
|
+
options?: TailOptions
|
|
172
|
+
): Promise<string> {
|
|
173
|
+
const data = this.storage[toolCallId];
|
|
174
|
+
const availableIds = Object.keys(this.storage);
|
|
175
|
+
return executeTail(data, toolCallId, availableIds, options);
|
|
176
|
+
}
|
|
171
177
|
|
|
172
|
-
|
|
173
|
-
|
|
178
|
+
/**
|
|
179
|
+
* List all stored tool responses with metadata
|
|
180
|
+
*/
|
|
181
|
+
async listStoredToolResponses(): Promise<string> {
|
|
182
|
+
return executeListStoredToolResponses(
|
|
183
|
+
this.storage,
|
|
184
|
+
this.metadataStorage,
|
|
185
|
+
this.toolNameMap
|
|
186
|
+
);
|
|
174
187
|
}
|
|
175
188
|
|
|
176
189
|
/**
|
|
@@ -206,36 +219,42 @@ export class ToolResponseCache {
|
|
|
206
219
|
* Registers the jqToolResponse tool with the ToolsService
|
|
207
220
|
*/
|
|
208
221
|
registerTool(toolsService: ToolsService): void {
|
|
209
|
-
toolsService.addTools([
|
|
222
|
+
toolsService.addTools([
|
|
223
|
+
jqToolResponseDefinition,
|
|
224
|
+
grepToolResponseDefinition,
|
|
225
|
+
tailToolResponseDefinition,
|
|
226
|
+
listStoredToolResponsesDefinition,
|
|
227
|
+
]);
|
|
210
228
|
toolsService.addFunctions({
|
|
211
|
-
[
|
|
229
|
+
[jqToolResponseDefinition.function.name]: async (
|
|
230
|
+
toolCallId: string,
|
|
231
|
+
jqQuery: string
|
|
232
|
+
) => {
|
|
212
233
|
return await this.queryToolResponse(toolCallId, jqQuery);
|
|
213
234
|
},
|
|
235
|
+
[grepToolResponseDefinition.function.name]: async (
|
|
236
|
+
toolCallId: string,
|
|
237
|
+
pattern: string,
|
|
238
|
+
options?: any
|
|
239
|
+
) => {
|
|
240
|
+
return await this.grepToolResponse(toolCallId, pattern, options);
|
|
241
|
+
},
|
|
242
|
+
[tailToolResponseDefinition.function.name]: async (
|
|
243
|
+
toolCallId: string,
|
|
244
|
+
options?: any
|
|
245
|
+
) => {
|
|
246
|
+
return await this.tailToolResponse(toolCallId, options);
|
|
247
|
+
},
|
|
248
|
+
[listStoredToolResponsesDefinition.function.name]: async () => {
|
|
249
|
+
return await this.listStoredToolResponses();
|
|
250
|
+
},
|
|
214
251
|
});
|
|
215
252
|
}
|
|
216
253
|
}
|
|
217
254
|
|
|
218
|
-
export
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
"Execute a JQ query on a stored tool response to extract specific data. Use this when you need to extract specific information from any tool response that has been stored. Many MCP tool responses store data in nested structures like .content[0].text where the actual data array is located.",
|
|
224
|
-
parameters: {
|
|
225
|
-
type: "object",
|
|
226
|
-
positional: true,
|
|
227
|
-
properties: {
|
|
228
|
-
toolCallId: {
|
|
229
|
-
type: "string",
|
|
230
|
-
description: "The toolCallId of the stored tool response",
|
|
231
|
-
},
|
|
232
|
-
jqQuery: {
|
|
233
|
-
type: "string",
|
|
234
|
-
description:
|
|
235
|
-
"The JQ query to execute on the tool response data. Examples: '.content[0].text | map(.title)' (extract titles from MCP array), '.content[0].text | map(select(.createdAt > \"2025-01-01\"))' (filter MCP items by date) ",
|
|
236
|
-
},
|
|
237
|
-
},
|
|
238
|
-
required: ["toolCallId", "jqQuery"],
|
|
239
|
-
},
|
|
240
|
-
},
|
|
255
|
+
export {
|
|
256
|
+
jqToolResponseDefinition,
|
|
257
|
+
grepToolResponseDefinition,
|
|
258
|
+
tailToolResponseDefinition,
|
|
259
|
+
listStoredToolResponsesDefinition,
|
|
241
260
|
};
|