@tyvm/knowhow 0.0.69 → 0.0.70
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/docs/shell-commands.md +174 -0
- package/package.json +1 -1
- package/src/agents/base/base.ts +1 -3
- package/src/agents/developer/developer.ts +21 -13
- package/src/agents/tools/agentCall.ts +4 -2
- package/src/agents/tools/fileSearch.ts +5 -1
- package/src/agents/tools/startAgentTask.ts +131 -22
- package/src/chat/CliChatService.ts +57 -11
- package/src/chat/modules/AgentModule.ts +72 -12
- package/src/chat/modules/CustomCommandsModule.ts +79 -0
- package/src/chat/modules/InternalChatModule.ts +11 -1
- package/src/chat/modules/ShellCommandModule.ts +96 -0
- package/src/chat/modules/index.ts +1 -0
- package/src/chat/types.ts +14 -2
- package/src/chat.ts +16 -13
- package/src/cli.ts +16 -6
- package/src/clients/anthropic.ts +41 -90
- package/src/clients/gemini.ts +445 -87
- package/src/clients/index.ts +125 -0
- package/src/clients/knowhow.ts +81 -0
- package/src/clients/openai.ts +256 -145
- package/src/clients/pricing/anthropic.ts +90 -0
- package/src/clients/pricing/google.ts +65 -0
- package/src/clients/pricing/index.ts +4 -0
- package/src/clients/pricing/openai.ts +134 -0
- package/src/clients/pricing/xai.ts +62 -0
- package/src/clients/types.ts +170 -1
- package/src/clients/xai.ts +275 -46
- package/src/config.ts +61 -15
- package/src/embeddings.ts +9 -1
- package/src/microphone.ts +15 -16
- package/src/migrations.ts +151 -0
- package/src/plugins/AgentsMdPlugin.ts +118 -0
- package/src/plugins/PluginBase.ts +8 -0
- package/src/plugins/downloader/downloader.ts +5 -6
- package/src/plugins/embedding.ts +10 -8
- package/src/plugins/exec.ts +70 -0
- package/src/plugins/github.ts +120 -74
- package/src/plugins/language.ts +11 -13
- package/src/plugins/plugins.ts +25 -4
- package/src/plugins/tmux.ts +132 -0
- package/src/plugins/types.ts +1 -0
- package/src/plugins/vim.ts +14 -1
- package/src/services/AgentSyncFs.ts +417 -0
- package/src/services/{AgentSynchronization.ts → AgentSyncKnowhowWeb.ts} +2 -2
- package/src/services/EventService.ts +0 -1
- package/src/services/KnowhowClient.ts +106 -0
- package/src/services/index.ts +4 -2
- package/src/types.ts +57 -4
- package/src/worker.ts +11 -6
- package/tests/manual/modalities/README.md +157 -0
- package/tests/manual/modalities/google.modalities.test.ts +335 -0
- package/tests/manual/modalities/openai.modalities.test.ts +329 -0
- package/tests/manual/modalities/streaming.test.ts +260 -0
- package/tests/manual/modalities/xai.modalities.test.ts +307 -0
- package/tests/plugins/language/languagePlugin-content-triggers.test.ts +5 -5
- package/tests/plugins/language/languagePlugin-integration.test.ts +1 -1
- package/tests/plugins/language/languagePlugin.test.ts +17 -8
- package/ts_build/package.json +1 -1
- package/ts_build/src/agents/base/base.js +1 -1
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/developer/developer.js +21 -12
- package/ts_build/src/agents/developer/developer.js.map +1 -1
- package/ts_build/src/agents/tools/agentCall.js +4 -2
- package/ts_build/src/agents/tools/agentCall.js.map +1 -1
- package/ts_build/src/agents/tools/executeScript/index.d.ts +1 -1
- package/ts_build/src/agents/tools/fileSearch.js +2 -1
- package/ts_build/src/agents/tools/fileSearch.js.map +1 -1
- package/ts_build/src/agents/tools/github/index.d.ts +1 -1
- package/ts_build/src/agents/tools/startAgentTask.d.ts +2 -1
- package/ts_build/src/agents/tools/startAgentTask.js +118 -17
- package/ts_build/src/agents/tools/startAgentTask.js.map +1 -1
- package/ts_build/src/chat/CliChatService.d.ts +4 -0
- package/ts_build/src/chat/CliChatService.js +39 -5
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +4 -1
- package/ts_build/src/chat/modules/AgentModule.js +49 -11
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/CustomCommandsModule.d.ts +9 -0
- package/ts_build/src/chat/modules/CustomCommandsModule.js +58 -0
- package/ts_build/src/chat/modules/CustomCommandsModule.js.map +1 -0
- package/ts_build/src/chat/modules/InternalChatModule.d.ts +2 -0
- package/ts_build/src/chat/modules/InternalChatModule.js +10 -0
- package/ts_build/src/chat/modules/InternalChatModule.js.map +1 -1
- package/ts_build/src/chat/modules/ShellCommandModule.d.ts +8 -0
- package/ts_build/src/chat/modules/ShellCommandModule.js +83 -0
- package/ts_build/src/chat/modules/ShellCommandModule.js.map +1 -0
- package/ts_build/src/chat/modules/index.d.ts +1 -0
- package/ts_build/src/chat/modules/index.js +3 -1
- package/ts_build/src/chat/modules/index.js.map +1 -1
- package/ts_build/src/chat/types.d.ts +11 -1
- package/ts_build/src/chat.js +16 -13
- package/ts_build/src/chat.js.map +1 -1
- package/ts_build/src/cli.js +10 -3
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/anthropic.d.ts +5 -1
- package/ts_build/src/clients/anthropic.js +18 -91
- package/ts_build/src/clients/anthropic.js.map +1 -1
- package/ts_build/src/clients/gemini.d.ts +80 -2
- package/ts_build/src/clients/gemini.js +336 -74
- package/ts_build/src/clients/gemini.js.map +1 -1
- package/ts_build/src/clients/index.d.ts +9 -1
- package/ts_build/src/clients/index.js +65 -0
- package/ts_build/src/clients/index.js.map +1 -1
- package/ts_build/src/clients/knowhow.d.ts +9 -1
- package/ts_build/src/clients/knowhow.js +43 -0
- package/ts_build/src/clients/knowhow.js.map +1 -1
- package/ts_build/src/clients/openai.d.ts +9 -1
- package/ts_build/src/clients/openai.js +201 -133
- package/ts_build/src/clients/openai.js.map +1 -1
- package/ts_build/src/clients/pricing/anthropic.d.ts +17 -0
- package/ts_build/src/clients/pricing/anthropic.js +93 -0
- package/ts_build/src/clients/pricing/anthropic.js.map +1 -0
- package/ts_build/src/clients/pricing/google.d.ts +73 -0
- package/ts_build/src/clients/pricing/google.js +68 -0
- package/ts_build/src/clients/pricing/google.js.map +1 -0
- package/ts_build/src/clients/pricing/index.d.ts +4 -0
- package/ts_build/src/clients/pricing/index.js +14 -0
- package/ts_build/src/clients/pricing/index.js.map +1 -0
- package/ts_build/src/clients/pricing/openai.d.ts +7 -0
- package/ts_build/src/clients/pricing/openai.js +137 -0
- package/ts_build/src/clients/pricing/openai.js.map +1 -0
- package/ts_build/src/clients/pricing/xai.d.ts +26 -0
- package/ts_build/src/clients/pricing/xai.js +59 -0
- package/ts_build/src/clients/pricing/xai.js.map +1 -0
- package/ts_build/src/clients/types.d.ts +135 -0
- package/ts_build/src/clients/xai.d.ts +9 -1
- package/ts_build/src/clients/xai.js +178 -46
- package/ts_build/src/clients/xai.js.map +1 -1
- package/ts_build/src/config.d.ts +1 -0
- package/ts_build/src/config.js +45 -16
- package/ts_build/src/config.js.map +1 -1
- package/ts_build/src/embeddings.js +8 -1
- package/ts_build/src/embeddings.js.map +1 -1
- package/ts_build/src/microphone.js +7 -9
- package/ts_build/src/microphone.js.map +1 -1
- package/ts_build/src/migrations.d.ts +17 -0
- package/ts_build/src/migrations.js +86 -0
- package/ts_build/src/migrations.js.map +1 -0
- package/ts_build/src/plugins/AgentsMdPlugin.d.ts +13 -0
- package/ts_build/src/plugins/AgentsMdPlugin.js +118 -0
- package/ts_build/src/plugins/AgentsMdPlugin.js.map +1 -0
- package/ts_build/src/plugins/PluginBase.d.ts +1 -0
- package/ts_build/src/plugins/PluginBase.js +3 -0
- package/ts_build/src/plugins/PluginBase.js.map +1 -1
- package/ts_build/src/plugins/downloader/downloader.js +5 -5
- package/ts_build/src/plugins/downloader/downloader.js.map +1 -1
- package/ts_build/src/plugins/embedding.js +9 -8
- package/ts_build/src/plugins/embedding.js.map +1 -1
- package/ts_build/src/plugins/exec.d.ts +10 -0
- package/ts_build/src/plugins/exec.js +56 -0
- package/ts_build/src/plugins/exec.js.map +1 -0
- package/ts_build/src/plugins/github.js +93 -51
- package/ts_build/src/plugins/github.js.map +1 -1
- package/ts_build/src/plugins/language.js +14 -11
- package/ts_build/src/plugins/language.js.map +1 -1
- package/ts_build/src/plugins/plugins.d.ts +1 -0
- package/ts_build/src/plugins/plugins.js +19 -1
- package/ts_build/src/plugins/plugins.js.map +1 -1
- package/ts_build/src/plugins/tmux.d.ts +14 -0
- package/ts_build/src/plugins/tmux.js +108 -0
- package/ts_build/src/plugins/tmux.js.map +1 -0
- package/ts_build/src/plugins/types.d.ts +1 -0
- package/ts_build/src/plugins/vim.js +11 -1
- package/ts_build/src/plugins/vim.js.map +1 -1
- package/ts_build/src/services/AgentSyncFs.d.ts +34 -0
- package/ts_build/src/services/AgentSyncFs.js +325 -0
- package/ts_build/src/services/AgentSyncFs.js.map +1 -0
- package/ts_build/src/services/AgentSyncKnowhowWeb.d.ts +29 -0
- package/ts_build/src/services/AgentSyncKnowhowWeb.js +178 -0
- package/ts_build/src/services/AgentSyncKnowhowWeb.js.map +1 -0
- package/ts_build/src/services/AgentSynchronization.d.ts +1 -1
- package/ts_build/src/services/AgentSynchronization.js +3 -3
- package/ts_build/src/services/AgentSynchronization.js.map +1 -1
- package/ts_build/src/services/EventService.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.d.ts +9 -1
- package/ts_build/src/services/KnowhowClient.js +58 -0
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/index.d.ts +2 -1
- package/ts_build/src/services/index.js +2 -1
- package/ts_build/src/services/index.js.map +1 -1
- package/ts_build/src/types.d.ts +26 -1
- package/ts_build/src/types.js +45 -4
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/src/utils/PersistentInputManager.d.ts +28 -0
- package/ts_build/src/utils/PersistentInputManager.js +293 -0
- package/ts_build/src/utils/PersistentInputManager.js.map +1 -0
- package/ts_build/src/worker.js +2 -2
- package/ts_build/src/worker.js.map +1 -1
- package/ts_build/tests/manual/modalities/google.modalities.test.d.ts +1 -0
- package/ts_build/tests/manual/modalities/google.modalities.test.js +252 -0
- package/ts_build/tests/manual/modalities/google.modalities.test.js.map +1 -0
- package/ts_build/tests/manual/modalities/openai.modalities.test.d.ts +1 -0
- package/ts_build/tests/manual/modalities/openai.modalities.test.js +252 -0
- package/ts_build/tests/manual/modalities/openai.modalities.test.js.map +1 -0
- package/ts_build/tests/manual/modalities/streaming.test.d.ts +1 -0
- package/ts_build/tests/manual/modalities/streaming.test.js +206 -0
- package/ts_build/tests/manual/modalities/streaming.test.js.map +1 -0
- package/ts_build/tests/manual/modalities/xai.modalities.test.d.ts +1 -0
- package/ts_build/tests/manual/modalities/xai.modalities.test.js +226 -0
- package/ts_build/tests/manual/modalities/xai.modalities.test.js.map +1 -0
- package/ts_build/tests/manual/persistent-input-test.d.ts +1 -0
- package/ts_build/tests/manual/persistent-input-test.js +35 -0
- package/ts_build/tests/manual/persistent-input-test.js.map +1 -0
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +5 -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 +1 -1
- package/ts_build/tests/plugins/language/languagePlugin-integration.test.js.map +1 -1
- package/ts_build/tests/plugins/language/languagePlugin.test.js +17 -7
- package/ts_build/tests/plugins/language/languagePlugin.test.js.map +1 -1
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Agent Chat Module - Handles agent interactions
|
|
3
3
|
*/
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
AgentSyncKnowhowWeb,
|
|
6
|
+
AgentSyncFs,
|
|
6
7
|
SessionManager,
|
|
7
8
|
TaskRegistry,
|
|
8
9
|
} from "../../services/index";
|
|
@@ -35,13 +36,15 @@ export class AgentModule extends BaseChatModule {
|
|
|
35
36
|
// Service instances for task management, session management, and synchronization
|
|
36
37
|
private taskRegistry: TaskRegistry;
|
|
37
38
|
private sessionManager: SessionManager;
|
|
38
|
-
private
|
|
39
|
+
private webSync: AgentSyncKnowhowWeb;
|
|
40
|
+
private fsSync: AgentSyncFs;
|
|
39
41
|
|
|
40
42
|
constructor() {
|
|
41
43
|
super();
|
|
42
44
|
this.taskRegistry = new TaskRegistry();
|
|
43
45
|
this.sessionManager = new SessionManager();
|
|
44
|
-
this.
|
|
46
|
+
this.webSync = new AgentSyncKnowhowWeb();
|
|
47
|
+
this.fsSync = new AgentSyncFs();
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
getCommands(): ChatCommand[] {
|
|
@@ -95,6 +98,7 @@ export class AgentModule extends BaseChatModule {
|
|
|
95
98
|
context.agentMode = false;
|
|
96
99
|
context.selectedAgent = undefined;
|
|
97
100
|
context.currentAgent = undefined;
|
|
101
|
+
this.chatService.disableMode("agent");
|
|
98
102
|
}
|
|
99
103
|
console.log("Agent mode disabled. Switched to chat mode.");
|
|
100
104
|
return;
|
|
@@ -122,7 +126,9 @@ export class AgentModule extends BaseChatModule {
|
|
|
122
126
|
// so /model and /provider commands show accurate information
|
|
123
127
|
context.currentModel = selectedAgent.getModel();
|
|
124
128
|
context.currentProvider = selectedAgent.getProvider();
|
|
129
|
+
this.chatService.setMode("agent");
|
|
125
130
|
}
|
|
131
|
+
|
|
126
132
|
console.log(
|
|
127
133
|
`Agent mode enabled. Selected agent: ${agentName}. Type your task to get started.`
|
|
128
134
|
);
|
|
@@ -399,7 +405,7 @@ Please continue from where you left off and complete the original request.
|
|
|
399
405
|
`;
|
|
400
406
|
|
|
401
407
|
console.log("🚀 Session resuming...");
|
|
402
|
-
const context = this.chatService?.getContext()
|
|
408
|
+
const context = this.chatService?.getContext();
|
|
403
409
|
const allAgents = agents();
|
|
404
410
|
const selectedAgent =
|
|
405
411
|
allAgents[session.agentName] || allAgents[context.currentAgent];
|
|
@@ -462,6 +468,7 @@ Please continue from where you left off and complete the original request.
|
|
|
462
468
|
agentName: string;
|
|
463
469
|
input: string;
|
|
464
470
|
messageId?: string;
|
|
471
|
+
syncFs?: boolean;
|
|
465
472
|
existingKnowhowTaskId?: string;
|
|
466
473
|
provider?: string;
|
|
467
474
|
model?: string;
|
|
@@ -469,6 +476,7 @@ Please continue from where you left off and complete the original request.
|
|
|
469
476
|
maxSpendLimit?: number; // in dollars
|
|
470
477
|
chatHistory?: ChatInteraction[];
|
|
471
478
|
run?: boolean; // whether to run immediately
|
|
479
|
+
taskId?: string; // optional pre-generated taskId
|
|
472
480
|
}) {
|
|
473
481
|
const allAgents = agents();
|
|
474
482
|
|
|
@@ -485,7 +493,7 @@ Please continue from where you left off and complete the original request.
|
|
|
485
493
|
|
|
486
494
|
let done = false;
|
|
487
495
|
let output = "Done";
|
|
488
|
-
const taskId = this.sessionManager.generateTaskId(input);
|
|
496
|
+
const taskId = options.taskId || this.sessionManager.generateTaskId(input);
|
|
489
497
|
let knowhowTaskId: string | undefined;
|
|
490
498
|
|
|
491
499
|
try {
|
|
@@ -521,8 +529,12 @@ Please continue from where you left off and complete the original request.
|
|
|
521
529
|
this.saveSession(taskId, taskInfo, []);
|
|
522
530
|
|
|
523
531
|
// Create Knowhow chat task if messageId provided
|
|
524
|
-
if (
|
|
525
|
-
|
|
532
|
+
if (
|
|
533
|
+
options.messageId &&
|
|
534
|
+
!options.existingKnowhowTaskId &&
|
|
535
|
+
!options.syncFs
|
|
536
|
+
) {
|
|
537
|
+
knowhowTaskId = await this.webSync.createChatTask({
|
|
526
538
|
messageId: options.messageId,
|
|
527
539
|
prompt: input,
|
|
528
540
|
});
|
|
@@ -533,8 +545,24 @@ Please continue from where you left off and complete the original request.
|
|
|
533
545
|
this.taskRegistry.register(taskId, taskInfo);
|
|
534
546
|
|
|
535
547
|
// Set up event-based synchronization with Knowhow API
|
|
536
|
-
await this.
|
|
548
|
+
await this.webSync.setupAgentSync(agent, knowhowTaskId);
|
|
537
549
|
}
|
|
550
|
+
} else if (!options.messageId || options.syncFs) {
|
|
551
|
+
// Use filesystem sync when no messageId is provided or syncFs is explicitly enabled
|
|
552
|
+
console.log(
|
|
553
|
+
`📁 Using filesystem-based synchronization for task: ${taskId}`
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
const fsTaskId = await this.fsSync.createTask({
|
|
557
|
+
taskId,
|
|
558
|
+
prompt: input,
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
// Update TaskInfo with the fs sync info
|
|
562
|
+
taskInfo.knowhowTaskId = fsTaskId;
|
|
563
|
+
this.taskRegistry.register(taskId, taskInfo);
|
|
564
|
+
|
|
565
|
+
await this.fsSync.setupAgentSync(agent, fsTaskId);
|
|
538
566
|
}
|
|
539
567
|
|
|
540
568
|
// Set up session update listener
|
|
@@ -642,10 +670,15 @@ Please continue from where you left off and complete the original request.
|
|
|
642
670
|
|
|
643
671
|
// Wait for AgentSync to finish before resolving
|
|
644
672
|
if (knowhowTaskId) {
|
|
645
|
-
console.log(
|
|
646
|
-
|
|
647
|
-
|
|
673
|
+
console.log(
|
|
674
|
+
"🎯 [AgentModule] Waiting for web sync finalization..."
|
|
675
|
+
);
|
|
676
|
+
await this.webSync.waitForFinalization();
|
|
677
|
+
console.log("🎯 [AgentModule] Web sync finalization complete");
|
|
648
678
|
}
|
|
679
|
+
console.log("🎯 [AgentModule] Waiting for fs sync finalization...");
|
|
680
|
+
await this.fsSync.waitForFinalization();
|
|
681
|
+
console.log("🎯 [AgentModule] Fs sync finalization complete");
|
|
649
682
|
|
|
650
683
|
if (taskInfo) {
|
|
651
684
|
taskInfo.status = "completed";
|
|
@@ -778,7 +811,25 @@ Please continue from where you left off and complete the original request.
|
|
|
778
811
|
let agentFinalOutput: string | undefined;
|
|
779
812
|
|
|
780
813
|
// Define available commands
|
|
781
|
-
|
|
814
|
+
// Set mode to agent:attached so custom commands are available
|
|
815
|
+
if (this.chatService) {
|
|
816
|
+
this.chatService.setMode("agent:attached");
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// Get mode-specific commands for autocomplete
|
|
820
|
+
const modeCommands =
|
|
821
|
+
this.chatService
|
|
822
|
+
?.getCommandsForMode("agent:attached")
|
|
823
|
+
.map((cmd) => `/${cmd.name}`) || [];
|
|
824
|
+
|
|
825
|
+
const commands = [
|
|
826
|
+
...modeCommands,
|
|
827
|
+
"/pause",
|
|
828
|
+
"/unpause",
|
|
829
|
+
"/kill",
|
|
830
|
+
"/detach",
|
|
831
|
+
"/done",
|
|
832
|
+
];
|
|
782
833
|
const history: string[] = [];
|
|
783
834
|
|
|
784
835
|
// Set up the event listener BEFORE starting the agent to avoid race condition
|
|
@@ -836,6 +887,10 @@ Please continue from where you left off and complete the original request.
|
|
|
836
887
|
break;
|
|
837
888
|
case "/detach":
|
|
838
889
|
console.log("Detached from agent");
|
|
890
|
+
// Reset mode back to default when detaching
|
|
891
|
+
if (this.chatService) {
|
|
892
|
+
this.chatService.setMode("default");
|
|
893
|
+
}
|
|
839
894
|
return { result: true, finalOutput: agentFinalOutput };
|
|
840
895
|
default:
|
|
841
896
|
agent.addPendingUserMessage({
|
|
@@ -852,6 +907,11 @@ Please continue from where you left off and complete the original request.
|
|
|
852
907
|
}
|
|
853
908
|
}
|
|
854
909
|
|
|
910
|
+
// Reset mode back to default when exiting loop
|
|
911
|
+
if (this.chatService) {
|
|
912
|
+
this.chatService.setMode("default");
|
|
913
|
+
}
|
|
914
|
+
|
|
855
915
|
// Update final task status and save session
|
|
856
916
|
const finalTaskInfo = this.taskRegistry.get(taskId);
|
|
857
917
|
if (finalTaskInfo) {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { BaseChatModule } from "./BaseChatModule";
|
|
2
|
+
import { ChatCommand, ChatService, CommandResult } from "../types";
|
|
3
|
+
import { getLanguageConfig } from "../../config";
|
|
4
|
+
import { services } from "../../services";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* CustomCommandsModule - Loads `/command`-style keys from the language config
|
|
8
|
+
* and registers them as chat commands. When invoked, the resolved language
|
|
9
|
+
* sources are sent to the active agent via addPendingUserMessage.
|
|
10
|
+
*/
|
|
11
|
+
export class CustomCommandsModule extends BaseChatModule {
|
|
12
|
+
name = "custom-commands";
|
|
13
|
+
description =
|
|
14
|
+
"Dynamically registered commands from language config /command keys";
|
|
15
|
+
|
|
16
|
+
public getCommands(): ChatCommand[] {
|
|
17
|
+
// Commands are loaded asynchronously; return empty here and register dynamically in initialize
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getPlugins() {
|
|
22
|
+
return this.chatService.getTools()?.getContext()?.Plugins;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async initialize(service: ChatService): Promise<void> {
|
|
26
|
+
this.chatService = service;
|
|
27
|
+
|
|
28
|
+
// Load language config and register /command-style keys
|
|
29
|
+
try {
|
|
30
|
+
const languageConfig = await getLanguageConfig();
|
|
31
|
+
const commandKeys = Object.keys(languageConfig).filter((key) =>
|
|
32
|
+
key.trim().startsWith("/")
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
for (const commandKey of commandKeys) {
|
|
36
|
+
// Strip the leading slash to get the command name
|
|
37
|
+
const commandName = commandKey.trim().slice(1);
|
|
38
|
+
|
|
39
|
+
console.log(
|
|
40
|
+
`CUSTOM-COMMANDS: Registering command /${commandName} from language config`
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const command: ChatCommand = {
|
|
44
|
+
name: commandName,
|
|
45
|
+
description: `Custom command: ${commandKey}`,
|
|
46
|
+
modes: ["agent:attached", "agent"],
|
|
47
|
+
handler: async (args: string[]): Promise<CommandResult> => {
|
|
48
|
+
const config = languageConfig[commandKey];
|
|
49
|
+
const result = await this.getPlugins().call("language", commandKey);
|
|
50
|
+
|
|
51
|
+
// If handled is true, call the language plugin and display output but don't send to agent
|
|
52
|
+
if (config.handled === true) {
|
|
53
|
+
try {
|
|
54
|
+
console.log(result);
|
|
55
|
+
return {
|
|
56
|
+
handled: true,
|
|
57
|
+
contents: result,
|
|
58
|
+
};
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error(`Error executing command ${commandKey}:`, error);
|
|
61
|
+
return { handled: true };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// By default (handled: false or undefined), return unhandled so agent module processes it
|
|
66
|
+
return {
|
|
67
|
+
handled: false,
|
|
68
|
+
contents: commandKey + " => " + result,
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
this.chatService.registerCommand(command);
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error("CUSTOM-COMMANDS: Error loading language config:", error);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -7,6 +7,8 @@ import { SearchModule } from "./SearchModule";
|
|
|
7
7
|
import { VoiceModule } from "./VoiceModule";
|
|
8
8
|
import { SystemModule } from "./SystemModule";
|
|
9
9
|
import { SetupModule } from "./SetupModule";
|
|
10
|
+
import { CustomCommandsModule } from "./CustomCommandsModule";
|
|
11
|
+
import { ShellCommandModule } from "./ShellCommandModule";
|
|
10
12
|
|
|
11
13
|
export class InternalChatModule implements ChatModule {
|
|
12
14
|
private chatService?: CliChatService;
|
|
@@ -20,6 +22,8 @@ export class InternalChatModule implements ChatModule {
|
|
|
20
22
|
private voiceModule = new VoiceModule();
|
|
21
23
|
private systemModule = new SystemModule();
|
|
22
24
|
private setupModule = new SetupModule();
|
|
25
|
+
private customCommandsModule = new CustomCommandsModule();
|
|
26
|
+
private shellCommandModule = new ShellCommandModule();
|
|
23
27
|
|
|
24
28
|
async initialize(chatService: CliChatService): Promise<void> {
|
|
25
29
|
this.chatService = chatService;
|
|
@@ -34,7 +38,9 @@ export class InternalChatModule implements ChatModule {
|
|
|
34
38
|
await this.voiceModule.initialize(chatService);
|
|
35
39
|
await this.systemModule.initialize(chatService);
|
|
36
40
|
await this.setupModule.initialize(chatService);
|
|
37
|
-
|
|
41
|
+
await this.customCommandsModule.initialize(chatService);
|
|
42
|
+
await this.shellCommandModule.initialize(chatService);
|
|
43
|
+
|
|
38
44
|
// Register our own commands (exit and multi) - not duplicated by BaseChatModule
|
|
39
45
|
chatService.registerCommand({
|
|
40
46
|
name: "exit",
|
|
@@ -62,6 +68,8 @@ export class InternalChatModule implements ChatModule {
|
|
|
62
68
|
...this.voiceModule.getCommands(),
|
|
63
69
|
...this.systemModule.getCommands(),
|
|
64
70
|
...this.setupModule.getCommands(),
|
|
71
|
+
...this.customCommandsModule.getCommands(),
|
|
72
|
+
...this.shellCommandModule.getCommands(),
|
|
65
73
|
{
|
|
66
74
|
name: "exit",
|
|
67
75
|
description: "Exit the chat",
|
|
@@ -84,6 +92,8 @@ export class InternalChatModule implements ChatModule {
|
|
|
84
92
|
...this.voiceModule.getModes(),
|
|
85
93
|
...this.systemModule.getModes(),
|
|
86
94
|
...this.setupModule.getModes(),
|
|
95
|
+
...this.customCommandsModule.getModes(),
|
|
96
|
+
...this.shellCommandModule.getModes(),
|
|
87
97
|
];
|
|
88
98
|
}
|
|
89
99
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { BaseChatModule } from "./BaseChatModule";
|
|
2
|
+
import { ChatCommand, ChatContext, CommandResult } from "../types";
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ShellCommandModule - Handles /! and /!! commands for executing shell commands
|
|
7
|
+
* /! - Execute command and display output in console (interactive if needed)
|
|
8
|
+
* /!! - Execute command and send output to the AI agent
|
|
9
|
+
*/
|
|
10
|
+
export class ShellCommandModule extends BaseChatModule {
|
|
11
|
+
name = "shell-command";
|
|
12
|
+
description = "Execute shell commands with /! and /!!";
|
|
13
|
+
|
|
14
|
+
public getCommands(): ChatCommand[] {
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
name: "!",
|
|
18
|
+
description: "Execute a shell command (interactive)",
|
|
19
|
+
modes: ["agent", "agent:attached"],
|
|
20
|
+
handler: async (args: string[]): Promise<CommandResult> => {
|
|
21
|
+
const command = args.join(" ");
|
|
22
|
+
if (!command) {
|
|
23
|
+
console.log("Usage: /! <command>");
|
|
24
|
+
return { handled: true };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
console.log(`Executing: ${command}`);
|
|
29
|
+
// Execute the command and inherit stdio for interactivity
|
|
30
|
+
const result = execSync(command, {
|
|
31
|
+
encoding: "utf8",
|
|
32
|
+
stdio: "inherit",
|
|
33
|
+
cwd: process.cwd(),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return { handled: true };
|
|
37
|
+
} catch (error: any) {
|
|
38
|
+
console.error(`Command failed: ${error.message}`);
|
|
39
|
+
if (error.stderr) {
|
|
40
|
+
console.error(error.stderr);
|
|
41
|
+
}
|
|
42
|
+
return { handled: true };
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "!!",
|
|
48
|
+
description: "Execute a shell command and send output to AI",
|
|
49
|
+
modes: ["agent", "agent:attached"],
|
|
50
|
+
handler: async (args: string[]): Promise<CommandResult> => {
|
|
51
|
+
const command = args.join(" ");
|
|
52
|
+
if (!command) {
|
|
53
|
+
console.log("Usage: /!! <command>");
|
|
54
|
+
return { handled: true };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
console.log(`Executing: ${command}`);
|
|
59
|
+
const result = execSync(command, {
|
|
60
|
+
encoding: "utf8",
|
|
61
|
+
cwd: process.cwd(),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
console.log(result);
|
|
65
|
+
|
|
66
|
+
// Return unhandled with the command output so it gets sent to the agent
|
|
67
|
+
return {
|
|
68
|
+
handled: false,
|
|
69
|
+
contents: `Command output from \`${command}\`:\n\`\`\`\n${result}\n\`\`\``,
|
|
70
|
+
};
|
|
71
|
+
} catch (error: any) {
|
|
72
|
+
const errorMessage = error.message;
|
|
73
|
+
const stderr = error.stderr || "";
|
|
74
|
+
const stdout = error.stdout || "";
|
|
75
|
+
|
|
76
|
+
console.error(`Command failed: ${errorMessage}`);
|
|
77
|
+
if (stderr) {
|
|
78
|
+
console.error(stderr);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Send error output to agent as well
|
|
82
|
+
return {
|
|
83
|
+
handled: false,
|
|
84
|
+
contents: `Command \`${command}\` failed:\n\`\`\`\n${stdout}\n${stderr}\n${errorMessage}\n\`\`\``,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async handleInput(input: string, context: ChatContext): Promise<boolean> {
|
|
93
|
+
// This module only handles commands registered above
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
package/src/chat/types.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core Types for Modular Chat System
|
|
3
3
|
*/
|
|
4
|
-
import { ChatInteraction } from "../types";
|
|
4
|
+
import { ChatInteraction, Config } from "../types";
|
|
5
5
|
import { BaseAgent } from "../agents/base/base";
|
|
6
|
+
import { ToolsService } from "src/services";
|
|
6
7
|
|
|
7
8
|
export interface ChatContext {
|
|
8
9
|
debugMode?: boolean;
|
|
@@ -15,6 +16,8 @@ export interface ChatContext {
|
|
|
15
16
|
currentProvider?: string;
|
|
16
17
|
inputMethod?: InputMethod;
|
|
17
18
|
selectedAgent?: BaseAgent;
|
|
19
|
+
plugins: string[];
|
|
20
|
+
|
|
18
21
|
[key: string]: any;
|
|
19
22
|
}
|
|
20
23
|
|
|
@@ -24,10 +27,16 @@ export interface ChatMode {
|
|
|
24
27
|
active: boolean;
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
export interface CommandResult {
|
|
31
|
+
handled: boolean;
|
|
32
|
+
contents?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
27
35
|
export interface ChatCommand {
|
|
28
36
|
name: string;
|
|
29
37
|
description: string;
|
|
30
|
-
handler: (args: string[]) => Promise<void>;
|
|
38
|
+
handler: (args: string[]) => Promise<void | CommandResult>;
|
|
39
|
+
modes?: string[]; // Commands can specify which modes they're available in
|
|
31
40
|
}
|
|
32
41
|
|
|
33
42
|
export interface InputMethod {
|
|
@@ -38,12 +47,15 @@ export interface InputMethod {
|
|
|
38
47
|
|
|
39
48
|
export interface ChatService {
|
|
40
49
|
getContext(): ChatContext;
|
|
50
|
+
getTools(): ToolsService | undefined;
|
|
41
51
|
setContext(context: Partial<ChatContext>): void;
|
|
42
52
|
setInputMethod(method: InputMethod): void;
|
|
43
53
|
resetInputMethod(): void;
|
|
44
54
|
registerCommand(command: ChatCommand): void;
|
|
45
55
|
registerMode(mode: ChatMode): void;
|
|
46
56
|
getCommands(): ChatCommand[];
|
|
57
|
+
getCommandsForMode(mode: string): ChatCommand[];
|
|
58
|
+
setMode(mode: string): void;
|
|
47
59
|
getModes(): ChatMode[];
|
|
48
60
|
getMode(name: string): ChatMode | undefined;
|
|
49
61
|
enableMode(name: string): void;
|
package/src/chat.ts
CHANGED
|
@@ -20,23 +20,26 @@ async function main() {
|
|
|
20
20
|
configError
|
|
21
21
|
);
|
|
22
22
|
config = {
|
|
23
|
-
plugins:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
plugins: {
|
|
24
|
+
enabled: [
|
|
25
|
+
"embeddings",
|
|
26
|
+
"language",
|
|
27
|
+
"vim",
|
|
28
|
+
"github",
|
|
29
|
+
"asana",
|
|
30
|
+
"jira",
|
|
31
|
+
"linear",
|
|
32
|
+
"download",
|
|
33
|
+
"figma",
|
|
34
|
+
"url",
|
|
35
|
+
],
|
|
36
|
+
disabled: [],
|
|
37
|
+
},
|
|
35
38
|
};
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
// Create chat service with plugins
|
|
39
|
-
const chatService = new CliChatService(config.plugins);
|
|
42
|
+
const chatService = new CliChatService(config.plugins.enabled);
|
|
40
43
|
|
|
41
44
|
// Load internal chat module (includes all core functionality)
|
|
42
45
|
const internalModule = new InternalChatModule();
|
package/src/cli.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Command } from "commander";
|
|
|
7
7
|
import { execSync } from "child_process";
|
|
8
8
|
import { version } from "../package.json";
|
|
9
9
|
import { generate, embed, upload } from "./index";
|
|
10
|
-
import { init } from "./config";
|
|
10
|
+
import { init, migrateConfig } from "./config";
|
|
11
11
|
|
|
12
12
|
import { download, purge } from ".";
|
|
13
13
|
import { includedTools } from "./agents/tools/list";
|
|
@@ -26,6 +26,7 @@ import { startChat } from "./chat";
|
|
|
26
26
|
import { askAI } from "./chat-old";
|
|
27
27
|
import { getConfiguredEmbeddingMap, queryEmbedding } from "./embeddings";
|
|
28
28
|
import { getConfig } from "./config";
|
|
29
|
+
import { getEnabledPlugins } from "./types";
|
|
29
30
|
import { marked } from "marked";
|
|
30
31
|
import { BaseAgent } from "./agents/base/base";
|
|
31
32
|
import { AskModule } from "./chat/modules/AskModule";
|
|
@@ -36,9 +37,16 @@ import { SetupModule } from "./chat/modules/SetupModule";
|
|
|
36
37
|
import { CliChatService } from "./chat/CliChatService";
|
|
37
38
|
|
|
38
39
|
async function setupServices() {
|
|
39
|
-
|
|
40
|
+
await migrateConfig();
|
|
41
|
+
|
|
42
|
+
const { Agents, Mcp, Clients, Tools: OldTools } = services();
|
|
40
43
|
const Tools = new LazyToolsService();
|
|
41
44
|
|
|
45
|
+
// We need to wireup the LazyTools to be connected to the same singletons that are in services()
|
|
46
|
+
Tools.setContext({
|
|
47
|
+
...OldTools.getContext(),
|
|
48
|
+
});
|
|
49
|
+
|
|
42
50
|
const { Researcher, Developer, Patcher, Setup } = agents({
|
|
43
51
|
...services(),
|
|
44
52
|
Tools,
|
|
@@ -85,7 +93,7 @@ async function readStdin(): Promise<string> {
|
|
|
85
93
|
async function main() {
|
|
86
94
|
const program = new Command();
|
|
87
95
|
const config = await getConfig();
|
|
88
|
-
const chatService = new CliChatService(config.plugins);
|
|
96
|
+
const chatService = new CliChatService(getEnabledPlugins(config.plugins));
|
|
89
97
|
|
|
90
98
|
program
|
|
91
99
|
.name("knowhow")
|
|
@@ -114,13 +122,13 @@ async function main() {
|
|
|
114
122
|
try {
|
|
115
123
|
console.log("🔄 Checking for knowhow updates...");
|
|
116
124
|
console.log(`Current version: ${version}`);
|
|
117
|
-
|
|
125
|
+
|
|
118
126
|
console.log("📦 Installing latest version from npm...");
|
|
119
127
|
execSync("npm install -g knowhow@latest", {
|
|
120
128
|
stdio: "inherit",
|
|
121
129
|
encoding: "utf-8",
|
|
122
130
|
});
|
|
123
|
-
|
|
131
|
+
|
|
124
132
|
console.log("✓ knowhow has been updated successfully!");
|
|
125
133
|
console.log("Run 'knowhow --version' to see the new version.");
|
|
126
134
|
} catch (error) {
|
|
@@ -195,6 +203,8 @@ async function main() {
|
|
|
195
203
|
"10"
|
|
196
204
|
)
|
|
197
205
|
.option("--message-id <messageId>", "Knowhow message ID for task tracking")
|
|
206
|
+
.option("--sync-fs", "Enable filesystem-based synchronization")
|
|
207
|
+
.option("--task-id <taskId>", "Pre-generated task ID (used with --sync-fs for predictable agent directory path)")
|
|
198
208
|
.option("--prompt-file <path>", "Custom prompt template file with {text}")
|
|
199
209
|
.option("--input <text>", "Task input (fallback to stdin if not provided)")
|
|
200
210
|
.action(async (options) => {
|
|
@@ -255,7 +265,7 @@ async function main() {
|
|
|
255
265
|
const askModule = new AskModule();
|
|
256
266
|
await askModule.initialize(chatService);
|
|
257
267
|
await askModule.processAIQuery(input, {
|
|
258
|
-
plugins: config.plugins,
|
|
268
|
+
plugins: config.plugins.enabled,
|
|
259
269
|
currentModel: options.model,
|
|
260
270
|
currentProvider: options.provider,
|
|
261
271
|
});
|