@tyvm/knowhow 0.0.16 โ†’ 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/package.json +2 -1
  2. package/src/agents/base/base.ts +25 -6
  3. package/src/agents/index.ts +2 -2
  4. package/src/agents/tools/agentCall.ts +0 -1
  5. package/src/agents/tools/execCommand.ts +95 -4
  6. package/src/agents/tools/list.ts +23 -19
  7. package/src/agents/tools/writeFile.ts +1 -1
  8. package/src/chat.ts +11 -0
  9. package/src/config.ts +3 -1
  10. package/src/processors/Base64ImageDetector.ts +190 -0
  11. package/src/processors/TokenCompressor.ts +357 -0
  12. package/src/processors/ToolResponseCache.ts +235 -0
  13. package/src/services/MessageProcessor.ts +107 -0
  14. package/src/services/Tools.ts +100 -1
  15. package/src/services/types.ts +57 -0
  16. package/ts_build/src/agents/base/base.d.ts +3 -1
  17. package/ts_build/src/agents/base/base.js +20 -5
  18. package/ts_build/src/agents/base/base.js.map +1 -1
  19. package/ts_build/src/agents/index.d.ts +2 -2
  20. package/ts_build/src/agents/index.js +5 -3
  21. package/ts_build/src/agents/index.js.map +1 -1
  22. package/ts_build/src/agents/tools/agentCall.js.map +1 -1
  23. package/ts_build/src/agents/tools/execCommand.d.ts +6 -1
  24. package/ts_build/src/agents/tools/execCommand.js +70 -4
  25. package/ts_build/src/agents/tools/execCommand.js.map +1 -1
  26. package/ts_build/src/agents/tools/expandTokens.d.ts +3 -0
  27. package/ts_build/src/agents/tools/expandTokens.js +33 -0
  28. package/ts_build/src/agents/tools/expandTokens.js.map +1 -0
  29. package/ts_build/src/agents/tools/getBigString.d.ts +3 -0
  30. package/ts_build/src/agents/tools/getBigString.js +33 -0
  31. package/ts_build/src/agents/tools/getBigString.js.map +1 -0
  32. package/ts_build/src/agents/tools/list.js +19 -17
  33. package/ts_build/src/agents/tools/list.js.map +1 -1
  34. package/ts_build/src/agents/tools/writeFile.js +1 -1
  35. package/ts_build/src/agents/tools/writeFile.js.map +1 -1
  36. package/ts_build/src/chat.js +6 -0
  37. package/ts_build/src/chat.js.map +1 -1
  38. package/ts_build/src/config.js +1 -1
  39. package/ts_build/src/config.js.map +1 -1
  40. package/ts_build/src/processors/Base64ImageDetector.d.ts +14 -0
  41. package/ts_build/src/processors/Base64ImageDetector.js +153 -0
  42. package/ts_build/src/processors/Base64ImageDetector.js.map +1 -0
  43. package/ts_build/src/processors/TokenCompressor.d.ts +28 -0
  44. package/ts_build/src/processors/TokenCompressor.js +226 -0
  45. package/ts_build/src/processors/TokenCompressor.js.map +1 -0
  46. package/ts_build/src/processors/ToolResponseCache.d.ts +22 -0
  47. package/ts_build/src/processors/ToolResponseCache.js +164 -0
  48. package/ts_build/src/processors/ToolResponseCache.js.map +1 -0
  49. package/ts_build/src/processors/ToolResponseManipulator.d.ts +22 -0
  50. package/ts_build/src/processors/ToolResponseManipulator.js +162 -0
  51. package/ts_build/src/processors/ToolResponseManipulator.js.map +1 -0
  52. package/ts_build/src/services/MessageProcessor.d.ts +17 -0
  53. package/ts_build/src/services/MessageProcessor.js +63 -0
  54. package/ts_build/src/services/MessageProcessor.js.map +1 -0
  55. package/ts_build/src/services/Tools.d.ts +12 -0
  56. package/ts_build/src/services/Tools.js +71 -0
  57. package/ts_build/src/services/Tools.js.map +1 -1
  58. package/ts_build/src/services/types.d.ts +32 -0
  59. package/ts_build/src/services/types.js +38 -0
  60. package/ts_build/src/services/types.js.map +1 -0
  61. package/ts_build/src/agents/configurable/OpenAIAgent.d.ts +0 -0
  62. package/ts_build/src/agents/configurable/OpenAIAgent.js +0 -1
  63. package/ts_build/src/agents/configurable/OpenAIAgent.js.map +0 -1
  64. package/ts_build/src/agents/tools/client.d.ts +0 -5
  65. package/ts_build/src/agents/tools/client.js +0 -21
  66. package/ts_build/src/agents/tools/client.js.map +0 -1
  67. package/ts_build/src/agents/tools/googleSearchTypes.d.ts +0 -74
  68. package/ts_build/src/agents/tools/googleSearchTypes.js +0 -3
  69. package/ts_build/src/agents/tools/googleSearchTypes.js.map +0 -1
  70. package/ts_build/src/commands/chat-ui.d.ts +0 -1
  71. package/ts_build/src/commands/chat-ui.js +0 -14
  72. package/ts_build/src/commands/chat-ui.js.map +0 -1
  73. package/ts_build/src/demo/chat-ui-demo.d.ts +0 -3
  74. package/ts_build/src/demo/chat-ui-demo.js +0 -20
  75. package/ts_build/src/demo/chat-ui-demo.js.map +0 -1
  76. package/ts_build/src/plugins/EmbeddingPluginV2.d.ts +0 -7
  77. package/ts_build/src/plugins/EmbeddingPluginV2.js +0 -41
  78. package/ts_build/src/plugins/EmbeddingPluginV2.js.map +0 -1
  79. package/ts_build/src/plugins/GitHubPluginV2.d.ts +0 -10
  80. package/ts_build/src/plugins/GitHubPluginV2.js +0 -57
  81. package/ts_build/src/plugins/GitHubPluginV2.js.map +0 -1
  82. package/ts_build/src/plugins/downloader/index.d.ts +0 -3
  83. package/ts_build/src/plugins/downloader/index.js +0 -41
  84. package/ts_build/src/plugins/downloader/index.js.map +0 -1
  85. package/ts_build/src/services/MessagePreprocessor.d.ts +0 -26
  86. package/ts_build/src/services/MessagePreprocessor.js +0 -190
  87. package/ts_build/src/services/MessagePreprocessor.js.map +0 -1
  88. package/ts_build/src/services/__tests__/MessagePreprocessor.test.d.ts +0 -1
  89. package/ts_build/src/services/__tests__/MessagePreprocessor.test.js +0 -117
  90. package/ts_build/src/services/__tests__/MessagePreprocessor.test.js.map +0 -1
  91. package/ts_build/src/terminal.d.ts +0 -1
  92. package/ts_build/src/terminal.js +0 -35
  93. package/ts_build/src/terminal.js.map +0 -1
  94. package/ts_build/src/ui/InkChatUI.d.ts +0 -1
  95. package/ts_build/src/ui/InkChatUI.js +0 -792
  96. package/ts_build/src/ui/InkChatUI.js.map +0 -1
  97. package/ts_build/src/ui/components/ChatInterface.d.ts +0 -15
  98. package/ts_build/src/ui/components/ChatInterface.js +0 -39
  99. package/ts_build/src/ui/components/ChatInterface.js.map +0 -1
  100. package/ts_build/src/ui/components/ChatMessage.d.ts +0 -8
  101. package/ts_build/src/ui/components/ChatMessage.js +0 -7
  102. package/ts_build/src/ui/components/ChatMessage.js.map +0 -1
  103. package/ts_build/src/ui/components/CommandPalette.d.ts +0 -8
  104. package/ts_build/src/ui/components/CommandPalette.js +0 -23
  105. package/ts_build/src/ui/components/CommandPalette.js.map +0 -1
  106. package/ts_build/src/ui/components/InputBar.d.ts +0 -8
  107. package/ts_build/src/ui/components/InputBar.js +0 -8
  108. package/ts_build/src/ui/components/InputBar.js.map +0 -1
  109. package/ts_build/src/ui/components/Sidebar.d.ts +0 -9
  110. package/ts_build/src/ui/components/Sidebar.js +0 -7
  111. package/ts_build/src/ui/components/Sidebar.js.map +0 -1
  112. package/ts_build/src/ui/components/StatusBar.d.ts +0 -10
  113. package/ts_build/src/ui/components/StatusBar.js +0 -8
  114. package/ts_build/src/ui/components/StatusBar.js.map +0 -1
  115. package/ts_build/src/ui/demo.d.ts +0 -3
  116. package/ts_build/src/ui/demo.js +0 -26
  117. package/ts_build/src/ui/demo.js.map +0 -1
  118. package/ts_build/src/ui/index.d.ts +0 -13
  119. package/ts_build/src/ui/index.js +0 -16
  120. package/ts_build/src/ui/index.js.map +0 -1
  121. package/ts_build/tests/integration/OpenAI-MessagePreprocessor.test.d.ts +0 -1
  122. package/ts_build/tests/integration/OpenAI-MessagePreprocessor.test.js +0 -148
  123. package/ts_build/tests/integration/OpenAI-MessagePreprocessor.test.js.map +0 -1
  124. package/ts_build/tests/services/MessagePreprocessor.test.d.ts +0 -1
  125. package/ts_build/tests/services/MessagePreprocessor.test.js +0 -117
  126. package/ts_build/tests/services/MessagePreprocessor.test.js.map +0 -1
@@ -1,792 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import React, { useState, useEffect, useRef } from "react";
3
- import { Box, Text, useInput, useApp } from "ink";
4
- import Spinner from "ink-spinner";
5
- import { Agents } from "../services/AgentService";
6
- import { Clients } from "../clients";
7
- import { FlagsService } from "../services/flags";
8
- import { formatChatInput } from "../chat";
9
- import { queryEmbedding, getConfiguredEmbeddingMap } from "../embeddings";
10
- import { recordAudio, voiceToText } from "../microphone";
11
- import { Models } from "../ai";
12
- import { getConfig } from "../config";
13
- var ChatFlags;
14
- (function (ChatFlags) {
15
- ChatFlags["attach"] = "attach";
16
- ChatFlags["agent"] = "agent";
17
- ChatFlags["agents"] = "agents";
18
- ChatFlags["debug"] = "debug";
19
- ChatFlags["multi"] = "multi";
20
- ChatFlags["model"] = "model";
21
- ChatFlags["search"] = "search";
22
- ChatFlags["clear"] = "clear";
23
- ChatFlags["provider"] = "provider";
24
- ChatFlags["voice"] = "voice";
25
- ChatFlags["help"] = "help";
26
- ChatFlags["verbose"] = "verbose";
27
- })(ChatFlags || (ChatFlags = {}));
28
- var UIMode;
29
- (function (UIMode) {
30
- UIMode["CHAT"] = "chat";
31
- UIMode["AGENT_SELECT"] = "agent_select";
32
- UIMode["TASK_SELECT"] = "task_select";
33
- UIMode["VOICE_RECORD"] = "voice_record";
34
- UIMode["AGENT_THREAD"] = "agent_thread";
35
- })(UIMode || (UIMode = {}));
36
- const taskRegistry = new Map();
37
- const ChatModelDefaults = {
38
- openai: Models.openai.GPT_4o,
39
- anthropic: Models.anthropic.Sonnet4,
40
- google: Models.google.Gemini_25_Flash_Preview,
41
- xai: Models.xai.Grok3Beta,
42
- };
43
- function CostDisplay({ agent }) {
44
- const [totalCost, setTotalCost] = useState(0);
45
- useEffect(() => {
46
- if (!agent) {
47
- setTotalCost(0);
48
- return;
49
- }
50
- setTotalCost(agent.getTotalCostUsd());
51
- const costUpdateListener = (cost) => {
52
- setTotalCost(cost);
53
- };
54
- agent.agentEvents.on(agent.eventTypes.costUpdate, costUpdateListener);
55
- return () => {
56
- agent.agentEvents.off(agent.eventTypes.costUpdate, costUpdateListener);
57
- };
58
- }, [agent]);
59
- if (!agent || totalCost === 0)
60
- return null;
61
- return (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: "yellow", children: ["\uD83D\uDCB0 $", totalCost.toFixed(4), " USD"] }) }));
62
- }
63
- function CustomTextInput({ value, onChange, onSubmit, placeholder = "", suggestions = [], enabled = true, }) {
64
- const [cursor, setCursor] = useState(0);
65
- const [suggestionIndex, setSuggestionIndex] = useState(0);
66
- const [showSuggestions, setShowSuggestions] = useState(false);
67
- useEffect(() => {
68
- setCursor(value.length);
69
- }, [value]);
70
- useEffect(() => {
71
- const filteredSuggestions = suggestions.filter((s) => s.toLowerCase().startsWith(value.toLowerCase()));
72
- setShowSuggestions(value.length > 0 && filteredSuggestions.length > 0);
73
- setSuggestionIndex(0);
74
- }, [value, suggestions]);
75
- useInput((input, key) => {
76
- if (!enabled)
77
- return;
78
- if (key.return) {
79
- onSubmit(value);
80
- return;
81
- }
82
- if (key.tab && showSuggestions && suggestions.length > 0) {
83
- const filteredSuggestions = suggestions.filter((s) => s.toLowerCase().startsWith(value.toLowerCase()));
84
- if (filteredSuggestions[suggestionIndex]) {
85
- onChange(filteredSuggestions[suggestionIndex]);
86
- setShowSuggestions(false);
87
- }
88
- return;
89
- }
90
- if (key.upArrow && showSuggestions) {
91
- const filteredSuggestions = suggestions.filter((s) => s.toLowerCase().startsWith(value.toLowerCase()));
92
- setSuggestionIndex(Math.max(0, suggestionIndex - 1));
93
- return;
94
- }
95
- if (key.downArrow && showSuggestions) {
96
- const filteredSuggestions = suggestions.filter((s) => s.toLowerCase().startsWith(value.toLowerCase()));
97
- setSuggestionIndex(Math.min(filteredSuggestions.length - 1, suggestionIndex + 1));
98
- return;
99
- }
100
- if (key.backspace || key.delete) {
101
- if (value.length > 0) {
102
- onChange(value.slice(0, -1));
103
- }
104
- return;
105
- }
106
- if (key.escape) {
107
- setShowSuggestions(false);
108
- return;
109
- }
110
- if (input && !key.ctrl && !key.meta) {
111
- onChange(value + input);
112
- }
113
- });
114
- const filteredSuggestions = suggestions.filter((s) => s.toLowerCase().startsWith(value.toLowerCase()));
115
- return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { children: value || placeholder }), _jsx(Text, { color: "gray", children: "\u2502" })] }), showSuggestions && filteredSuggestions.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "yellow", bold: true, children: "Suggestions (Tab to complete):" }), filteredSuggestions.slice(0, 5).map((suggestion, index) => (_jsxs(Text, { color: index === suggestionIndex ? "cyan" : "gray", bold: index === suggestionIndex, children: [index === suggestionIndex ? "โ†’ " : " ", suggestion] })))] }))] }));
116
- }
117
- function AgentSelect({ agents, onSelect, onCancel }) {
118
- const [input, setInput] = useState("");
119
- useInput((inputChar, key) => {
120
- if (key.escape) {
121
- onCancel();
122
- return;
123
- }
124
- });
125
- const handleSubmit = (value) => {
126
- if (agents.includes(value)) {
127
- onSelect(value);
128
- }
129
- else {
130
- const match = agents.find((agent) => agent.toLowerCase().startsWith(value.toLowerCase()));
131
- if (match) {
132
- onSelect(match);
133
- }
134
- }
135
- };
136
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { borderStyle: "single", borderColor: "cyan", padding: 1, children: _jsx(Text, { color: "cyan", bold: true, children: "\uD83E\uDD16 Select Agent" }) }), _jsxs(Box, { padding: 1, children: [_jsx(Text, { color: "white", children: "Available agents:" }), agents.map((agent, index) => (_jsxs(Text, { color: "gray", children: ["\u2022 ", agent] })))] }), _jsxs(Box, { borderStyle: "single", borderColor: "green", padding: 1, children: [_jsx(Text, { color: "green", children: "Agent: " }), _jsx(CustomTextInput, { value: input, onChange: setInput, onSubmit: handleSubmit, placeholder: "Type agent name...", suggestions: agents })] }), _jsx(Text, { color: "gray", children: "Press Tab to auto-complete, Enter to select, Esc to cancel" })] }));
137
- }
138
- function TaskSelect({ tasks, onSelect, onCancel }) {
139
- const [input, setInput] = useState("");
140
- useInput((inputChar, key) => {
141
- if (key.escape) {
142
- onCancel();
143
- return;
144
- }
145
- });
146
- const handleSubmit = (value) => {
147
- if (tasks.includes(value)) {
148
- onSelect(value);
149
- }
150
- else {
151
- const match = tasks.find((task) => task.toLowerCase().includes(value.toLowerCase()));
152
- if (match) {
153
- onSelect(match);
154
- }
155
- }
156
- };
157
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { borderStyle: "single", borderColor: "yellow", padding: 1, children: _jsx(Text, { color: "yellow", bold: true, children: "\uD83D\uDD17 Reattach to Running Task" }) }), _jsxs(Box, { padding: 1, children: [_jsx(Text, { color: "white", children: "Running tasks:" }), tasks.length === 0 ? (_jsx(Text, { color: "gray", children: "No running tasks available" })) : (tasks.map((task, index) => (_jsxs(Text, { color: "gray", children: ["\u2022 ", task.substring(0, 80), "..."] }))))] }), _jsxs(Box, { borderStyle: "single", borderColor: "green", padding: 1, children: [_jsx(Text, { color: "green", children: "Task: " }), _jsx(CustomTextInput, { value: input, onChange: setInput, onSubmit: handleSubmit, placeholder: "Type task description...", suggestions: tasks })] }), _jsx(Text, { color: "gray", children: "Press Tab to auto-complete, Enter to select, Esc to cancel" })] }));
158
- }
159
- function VoiceRecord({ onComplete, onCancel }) {
160
- const [isRecording, setIsRecording] = useState(false);
161
- const [status, setStatus] = useState("Ready to record");
162
- const audioRecorderRef = useRef(null);
163
- useInput((input, key) => {
164
- if (key.escape) {
165
- if (isRecording && audioRecorderRef.current) {
166
- audioRecorderRef.current.stop();
167
- setIsRecording(false);
168
- }
169
- onCancel();
170
- return;
171
- }
172
- if (key.return) {
173
- if (!isRecording) {
174
- startRecording();
175
- }
176
- else {
177
- stopRecording();
178
- }
179
- }
180
- });
181
- const startRecording = async () => {
182
- try {
183
- setStatus("Starting recording...");
184
- const recorder = await recordAudio();
185
- if (recorder) {
186
- audioRecorderRef.current = recorder;
187
- setIsRecording(true);
188
- setStatus("๐Ÿ”ด Recording... (Press Enter to stop)");
189
- }
190
- }
191
- catch (error) {
192
- setStatus(`โŒ Failed to start recording: ${error.message}`);
193
- }
194
- };
195
- const stopRecording = async () => {
196
- if (!audioRecorderRef.current)
197
- return;
198
- try {
199
- setStatus("๐Ÿ”„ Processing recording...");
200
- audioRecorderRef.current.stop();
201
- setIsRecording(false);
202
- const transcription = await voiceToText();
203
- if (transcription) {
204
- onComplete(transcription);
205
- }
206
- else {
207
- setStatus("โŒ No transcription received");
208
- }
209
- }
210
- catch (error) {
211
- setStatus(`โŒ Transcription failed: ${error.message}`);
212
- }
213
- };
214
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { borderStyle: "single", borderColor: "magenta", padding: 1, children: _jsx(Text, { color: "magenta", bold: true, children: "\uD83C\uDFA4 Voice Input Mode" }) }), _jsx(Box, { padding: 1, children: _jsx(Text, { color: "white", children: status }) }), _jsx(Box, { padding: 1, children: _jsx(Text, { color: "gray", children: isRecording
215
- ? "Press Enter to stop recording, Esc to cancel"
216
- : "Press Enter to start recording, Esc to cancel" }) })] }));
217
- }
218
- export function InkChatUI() {
219
- const { exit } = useApp();
220
- const [messages, setMessages] = useState([]);
221
- const [inputBuffer, setInputBuffer] = useState("");
222
- const removeTaskFromRegistry = (agent) => {
223
- const taskKey = Array.from(taskRegistry.keys()).find((key) => taskRegistry.get(key) === agent);
224
- if (taskKey)
225
- taskRegistry.delete(taskKey);
226
- };
227
- const [isLoading, setIsLoading] = useState(false);
228
- const [inputHistory, setInputHistory] = useState([]);
229
- const [historyIndex, setHistoryIndex] = useState(-1);
230
- const [uiMode, setUIMode] = useState(UIMode.CHAT);
231
- const [showHelp, setShowHelp] = useState(false);
232
- const [scrollOffset, setScrollOffset] = useState(0);
233
- const [activeAgent, setActiveAgent] = useState(null);
234
- const [agentThread, setAgentThread] = useState([]);
235
- const [agentEventListeners, setAgentEventListeners] = useState([]);
236
- const [provider, setProvider] = useState("openai");
237
- const [model, setModel] = useState(ChatModelDefaults.openai);
238
- const [chatHistory, setChatHistory] = useState([]);
239
- const [plugins, setPlugins] = useState([]);
240
- const [flags, setFlags] = useState(new FlagsService([
241
- ChatFlags.agent,
242
- ChatFlags.debug,
243
- ChatFlags.multi,
244
- ChatFlags.voice,
245
- ChatFlags.verbose,
246
- ], true));
247
- const [availableAgents, setAvailableAgents] = useState([]);
248
- const [config, setConfig] = useState(null);
249
- useEffect(() => {
250
- const initializeServices = async () => {
251
- try {
252
- const appConfig = await getConfig();
253
- setConfig(appConfig);
254
- setPlugins(appConfig.plugins || ["embeddings", "files", "github"]);
255
- await Agents.loadAgentsFromConfig();
256
- const agentList = Agents.listAgents();
257
- setAvailableAgents(agentList);
258
- setMessages([
259
- {
260
- role: "system",
261
- content: "๐Ÿง  Welcome to Knowhow Chat UI! Type /help for commands.",
262
- },
263
- ]);
264
- }
265
- catch (error) {
266
- console.error("Failed to initialize services:", error);
267
- setMessages([
268
- {
269
- role: "system",
270
- content: "โš ๏ธ Warning: Failed to initialize some services.",
271
- },
272
- ]);
273
- }
274
- };
275
- initializeServices();
276
- }, []);
277
- useEffect(() => {
278
- if (activeAgent && uiMode === UIMode.AGENT_THREAD) {
279
- setupAgentEventListeners(activeAgent);
280
- }
281
- return () => {
282
- cleanupAgentEventListeners();
283
- };
284
- }, [activeAgent, uiMode]);
285
- const setupAgentEventListeners = (agent) => {
286
- cleanupAgentEventListeners();
287
- const listeners = [];
288
- const threadUpdateListener = (messages) => {
289
- const convertedMessages = messages.map((msg, index) => ({
290
- ...msg,
291
- messageId: `${Date.now()}-${index}`,
292
- timestamp: Date.now(),
293
- }));
294
- setAgentThread(convertedMessages);
295
- };
296
- const toolUsedListener = ({ toolCall, functionResponse }) => {
297
- const toolMessage = {
298
- role: "tool",
299
- content: flags.enabled(ChatFlags.verbose)
300
- ? JSON.stringify(functionResponse, null, 2)
301
- : truncateContent(String(functionResponse), 200),
302
- toolName: toolCall.function.name,
303
- toolArgs: flags.enabled(ChatFlags.verbose)
304
- ? toolCall.function.arguments
305
- : truncateContent(JSON.stringify(toolCall.function.arguments), 100),
306
- isToolCall: true,
307
- timestamp: Date.now(),
308
- messageId: `tool-${Date.now()}`,
309
- };
310
- setAgentThread((prev) => [...prev, toolMessage]);
311
- };
312
- const doneListener = (result) => {
313
- setIsLoading(false);
314
- const doneMessage = {
315
- role: "assistant",
316
- content: result || "Agent completed",
317
- agentName: agent.name,
318
- timestamp: Date.now(),
319
- messageId: `done-${Date.now()}`,
320
- };
321
- setAgentThread((prev) => [...prev, doneMessage]);
322
- };
323
- agent.agentEvents.on(agent.eventTypes.threadUpdate, threadUpdateListener);
324
- agent.agentEvents.on(agent.eventTypes.toolUsed, toolUsedListener);
325
- agent.agentEvents.on(agent.eventTypes.done, doneListener);
326
- listeners.push(() => agent.agentEvents.off(agent.eventTypes.threadUpdate, threadUpdateListener), () => agent.agentEvents.off(agent.eventTypes.toolUsed, toolUsedListener), () => agent.agentEvents.off(agent.eventTypes.done, doneListener));
327
- setAgentEventListeners(listeners);
328
- };
329
- const cleanupAgentEventListeners = () => {
330
- agentEventListeners.forEach((cleanup) => cleanup());
331
- setAgentEventListeners([]);
332
- };
333
- const truncateContent = (content, maxLength) => {
334
- if (content.length <= maxLength)
335
- return content;
336
- return content.substring(0, maxLength) + "...";
337
- };
338
- useInput((input, key) => {
339
- if (key.ctrl && input === "c") {
340
- exit();
341
- return;
342
- }
343
- if (uiMode === UIMode.CHAT) {
344
- if (key.upArrow && inputHistory.length > 0) {
345
- const newIndex = Math.min(historyIndex + 1, inputHistory.length - 1);
346
- setHistoryIndex(newIndex);
347
- setInputBuffer(inputHistory[newIndex]);
348
- return;
349
- }
350
- if (key.downArrow) {
351
- if (historyIndex > 0) {
352
- const newIndex = historyIndex - 1;
353
- setHistoryIndex(newIndex);
354
- setInputBuffer(inputHistory[newIndex]);
355
- }
356
- else if (historyIndex === 0) {
357
- setHistoryIndex(-1);
358
- setInputBuffer("");
359
- }
360
- return;
361
- }
362
- if (key.pageUp) {
363
- setScrollOffset(Math.max(0, scrollOffset - 5));
364
- return;
365
- }
366
- if (key.pageDown) {
367
- setScrollOffset(Math.min(messages.length, scrollOffset + 5));
368
- return;
369
- }
370
- }
371
- });
372
- const addToHistory = (message) => {
373
- setInputHistory((prev) => {
374
- const newHistory = [message, ...prev.slice(0, 49)];
375
- return newHistory;
376
- });
377
- setHistoryIndex(-1);
378
- };
379
- const askAI = async (prompt, _provider, _model) => {
380
- const client = Clients.clients[_provider];
381
- if (!client) {
382
- throw new Error(`Provider ${_provider} not found`);
383
- }
384
- const response = await client.createChatCompletion({
385
- model: _model,
386
- messages: [{ role: "user", content: prompt }],
387
- max_tokens: 2000,
388
- });
389
- return response.choices[0]?.message?.content || "No response received";
390
- };
391
- const handleSendMessage = async (message) => {
392
- if (!message.trim())
393
- return;
394
- addToHistory(message);
395
- const userMessage = message.trim();
396
- if (userMessage.startsWith("/")) {
397
- await handleCommand(userMessage);
398
- return;
399
- }
400
- const newMessage = {
401
- role: "user",
402
- content: userMessage,
403
- };
404
- if (uiMode === UIMode.AGENT_THREAD && activeAgent) {
405
- setAgentThread((prev) => [...prev, newMessage]);
406
- const isAgentRunning = Array.from(taskRegistry.values()).includes(activeAgent);
407
- if (!isAgentRunning) {
408
- setIsLoading(true);
409
- try {
410
- const formattedPrompt = await formatChatInput(userMessage, config.plugins, chatHistory);
411
- activeAgent.newTask();
412
- taskRegistry.set(userMessage, activeAgent);
413
- await activeAgent.call(formattedPrompt);
414
- }
415
- catch (error) {
416
- throw error;
417
- }
418
- }
419
- else {
420
- activeAgent.addPendingUserMessage(newMessage);
421
- }
422
- setInputBuffer("");
423
- return;
424
- }
425
- else {
426
- setMessages((prev) => [...prev, newMessage]);
427
- }
428
- setIsLoading(true);
429
- setInputBuffer("");
430
- try {
431
- const formattedPrompt = await formatChatInput(userMessage, plugins, chatHistory);
432
- const interaction = { input: userMessage, output: "" };
433
- let response = "";
434
- let responseMessage;
435
- console.log(flags.enabled(ChatFlags.agent), activeAgent);
436
- if (flags.enabled(ChatFlags.agent) && activeAgent) {
437
- activeAgent.newTask();
438
- taskRegistry.set(userMessage, activeAgent);
439
- response = await activeAgent.call(formattedPrompt);
440
- responseMessage = {
441
- role: "assistant",
442
- content: response || "Agent completed without output",
443
- agentName: activeAgent.name,
444
- };
445
- setMessages((prev) => [...prev, responseMessage]);
446
- }
447
- else {
448
- response = await askAI(formattedPrompt, provider, model);
449
- responseMessage = {
450
- role: "assistant",
451
- content: response,
452
- agentName: `${provider}/${model}`,
453
- };
454
- setMessages((prev) => [...prev, responseMessage]);
455
- }
456
- interaction.output = response;
457
- setChatHistory((prev) => [...prev, interaction]);
458
- }
459
- catch (error) {
460
- const errorMessage = {
461
- role: "system",
462
- content: `โŒ Error: ${error.message}`,
463
- };
464
- if (uiMode === UIMode.AGENT_THREAD) {
465
- setAgentThread((prev) => [...prev, errorMessage]);
466
- }
467
- else {
468
- setMessages((prev) => [...prev, errorMessage]);
469
- }
470
- }
471
- finally {
472
- setIsLoading(false);
473
- }
474
- };
475
- const handleCommand = async (command) => {
476
- const [cmd, ...args] = command.split(" ");
477
- const arg = args.join(" ");
478
- switch (cmd) {
479
- case "/exit":
480
- exit();
481
- break;
482
- case "/clear":
483
- if (uiMode === UIMode.AGENT_THREAD) {
484
- setAgentThread([]);
485
- }
486
- else {
487
- setMessages([]);
488
- }
489
- setChatHistory([]);
490
- break;
491
- case "/help":
492
- setShowHelp(!showHelp);
493
- break;
494
- case "/agents":
495
- if (availableAgents.length === 0) {
496
- addSystemMessage("No agents available. Check your configuration.");
497
- }
498
- else {
499
- setUIMode(UIMode.AGENT_SELECT);
500
- }
501
- break;
502
- case "/voice":
503
- setUIMode(UIMode.VOICE_RECORD);
504
- break;
505
- case "/detach":
506
- if (uiMode === UIMode.AGENT_THREAD) {
507
- setUIMode(UIMode.CHAT);
508
- addSystemMessage(`๐Ÿ”— Detached from agent thread`);
509
- }
510
- else {
511
- addSystemMessage("Not currently in an agent thread");
512
- }
513
- break;
514
- case "/attach":
515
- if (uiMode === UIMode.AGENT_THREAD) {
516
- addSystemMessage("Already in an agent thread. Use /detach first.");
517
- }
518
- else if (taskRegistry.size > 0) {
519
- setUIMode(UIMode.TASK_SELECT);
520
- }
521
- else {
522
- addSystemMessage("No running tasks available to attach to.");
523
- }
524
- break;
525
- case "/pause":
526
- if (activeAgent && uiMode === UIMode.AGENT_THREAD) {
527
- activeAgent.pause();
528
- removeTaskFromRegistry(activeAgent);
529
- addSystemMessage(`โธ๏ธ Paused agent: ${activeAgent.name}`);
530
- }
531
- else {
532
- addSystemMessage("No active agent to pause");
533
- }
534
- break;
535
- case "/kill":
536
- if (activeAgent && uiMode === UIMode.AGENT_THREAD) {
537
- await activeAgent.kill();
538
- for (const [task, agent] of taskRegistry.entries()) {
539
- if (agent === activeAgent)
540
- taskRegistry.delete(task);
541
- }
542
- addSystemMessage(`๐Ÿ’€ Killed agent: ${activeAgent.name}`);
543
- setUIMode(UIMode.CHAT);
544
- setActiveAgent(null);
545
- }
546
- else {
547
- addSystemMessage("No active agent to kill");
548
- }
549
- break;
550
- case "/agent":
551
- flags.flip(ChatFlags.agent);
552
- const agentStatus = flags.enabled(ChatFlags.agent)
553
- ? "enabled"
554
- : "disabled";
555
- addSystemMessage(`๐Ÿค– Agent mode ${agentStatus}`);
556
- break;
557
- case "/provider":
558
- if (!arg) {
559
- const providers = Object.keys(Clients.clients);
560
- addSystemMessage(`๐Ÿ”— Available providers: ${providers.join(", ")}\nCurrent: ${provider}`);
561
- }
562
- else {
563
- if (Clients.clients[arg]) {
564
- setProvider(arg);
565
- setModel(ChatModelDefaults[arg] || "");
566
- addSystemMessage(`๐Ÿ”— Provider changed to: ${arg}`);
567
- }
568
- else {
569
- addSystemMessage(`โŒ Provider '${arg}' not found`);
570
- }
571
- }
572
- break;
573
- case "/model":
574
- if (!arg) {
575
- const models = Clients.getRegisteredModels(provider);
576
- addSystemMessage(`๐ŸŽฏ Available models for ${provider}: ${models.join(", ")}\nCurrent: ${model}`);
577
- }
578
- else {
579
- const models = Clients.getRegisteredModels(provider);
580
- if (models.includes(arg)) {
581
- setModel(arg);
582
- addSystemMessage(`๐ŸŽฏ Model changed to: ${arg}`);
583
- }
584
- else {
585
- addSystemMessage(`โŒ Model '${arg}' not available for ${provider}`);
586
- }
587
- }
588
- break;
589
- case "/debug":
590
- flags.flip(ChatFlags.debug);
591
- const debugStatus = flags.enabled(ChatFlags.debug)
592
- ? "enabled"
593
- : "disabled";
594
- addSystemMessage(`๐Ÿ” Debug mode ${debugStatus}`);
595
- break;
596
- case "/multi":
597
- flags.flip(ChatFlags.multi);
598
- const multiStatus = flags.enabled(ChatFlags.multi)
599
- ? "enabled"
600
- : "disabled";
601
- addSystemMessage(`๐Ÿ“ Multi-line mode ${multiStatus}`);
602
- break;
603
- case "/verbose":
604
- flags.flip(ChatFlags.verbose);
605
- const verboseStatus = flags.enabled(ChatFlags.verbose)
606
- ? "enabled"
607
- : "disabled";
608
- addSystemMessage(`๐Ÿ” Verbose mode ${verboseStatus}`);
609
- break;
610
- case "/continue":
611
- if (activeAgent && uiMode === UIMode.AGENT_THREAD) {
612
- setIsLoading(true);
613
- try {
614
- const response = await activeAgent.call("");
615
- }
616
- catch (error) {
617
- addSystemMessage(`โŒ Error continuing agent: ${error.message}`);
618
- }
619
- finally {
620
- setIsLoading(false);
621
- }
622
- }
623
- else {
624
- addSystemMessage("No active agent thread to continue");
625
- }
626
- break;
627
- case "/search":
628
- if (!arg) {
629
- addSystemMessage("Usage: /search <query>");
630
- return;
631
- }
632
- try {
633
- const embeddingMap = await getConfiguredEmbeddingMap();
634
- const results = await queryEmbedding(arg, Object.values(embeddingMap).flat());
635
- const resultText = results.length > 0
636
- ? results
637
- .map((r) => `โ€ข ${r.text.substring(0, 100)}...`)
638
- .join("\n")
639
- : "No results found";
640
- addSystemMessage(`๐Ÿ” Search results for "${arg}":\n${resultText}`);
641
- }
642
- catch (error) {
643
- addSystemMessage(`โŒ Search failed: ${error.message}`);
644
- }
645
- break;
646
- default:
647
- addSystemMessage(`โŒ Unknown command: ${cmd}. Type /help for available commands.`);
648
- break;
649
- }
650
- };
651
- const addSystemMessage = (content) => {
652
- const message = { role: "system", content };
653
- if (uiMode === UIMode.AGENT_THREAD) {
654
- setAgentThread((prev) => [...prev, message]);
655
- }
656
- else {
657
- setMessages((prev) => [...prev, message]);
658
- }
659
- };
660
- const handleAgentSelect = (agentName) => {
661
- const selectedAgent = Agents.getAgent(agentName);
662
- if (selectedAgent) {
663
- cleanupAgentEventListeners();
664
- setActiveAgent(selectedAgent);
665
- setUIMode(UIMode.AGENT_THREAD);
666
- flags.enable(ChatFlags.agent);
667
- const initialMessage = {
668
- role: "system",
669
- content: `๐Ÿค– Started thread with agent: ${selectedAgent.name}\nUse /detach to leave thread, /pause to pause agent, /kill to terminate agent, /continue to process pending messages`,
670
- timestamp: Date.now(),
671
- messageId: `init-${Date.now()}`,
672
- };
673
- setAgentThread([initialMessage]);
674
- }
675
- };
676
- const handleTaskCancel = () => {
677
- setUIMode(UIMode.CHAT);
678
- };
679
- const handleTaskSelect = (taskDescription) => {
680
- const selectedAgent = taskRegistry.get(taskDescription);
681
- if (selectedAgent) {
682
- cleanupAgentEventListeners();
683
- setActiveAgent(selectedAgent);
684
- setUIMode(UIMode.AGENT_THREAD);
685
- setAgentThread([
686
- {
687
- role: "system",
688
- content: `๐Ÿ”— Reattached to agent: ${selectedAgent.name} working on: "${taskDescription.substring(0, 50)}..."\nUse /detach to leave thread, /pause to pause agent, /kill to terminate agent`,
689
- },
690
- ]);
691
- }
692
- };
693
- const handleVoiceComplete = (text) => {
694
- setInputBuffer(text);
695
- setUIMode(UIMode.CHAT);
696
- addSystemMessage(`๐ŸŽค Voice transcription: "${text}"`);
697
- };
698
- const handleCancel = () => {
699
- setUIMode(UIMode.CHAT);
700
- };
701
- const getDisplayRole = (msg) => {
702
- if (msg.role === "system")
703
- return "๐Ÿ”ง System";
704
- if (msg.role === "user")
705
- return "๐Ÿ‘ค You";
706
- if (msg.role === "tool") {
707
- return `๐Ÿ”ง ${msg.toolName || "Tool"}`;
708
- }
709
- if (msg.agentName)
710
- return `๐Ÿค– ${msg.agentName}`;
711
- return "๐Ÿค– AI";
712
- };
713
- const getDisplayColor = (msg) => {
714
- if (msg.role === "user")
715
- return "green";
716
- if (msg.role === "system")
717
- return "gray";
718
- if (msg.role === "tool")
719
- return "yellow";
720
- return "blue";
721
- };
722
- const formatMessageContent = (msg) => {
723
- if (msg.role === "tool") {
724
- if (msg.toolName) {
725
- const argsDisplay = flags.enabled(ChatFlags.verbose)
726
- ? `\nArgs: ${msg.toolArgs}`
727
- : msg.toolArgs
728
- ? ` (${msg.toolArgs})`
729
- : "";
730
- const resultDisplay = flags.enabled(ChatFlags.verbose)
731
- ? `\nResult: ${msg.content}`
732
- : msg.content;
733
- return `Called ${msg.toolName}${argsDisplay}${flags.enabled(ChatFlags.verbose)
734
- ? resultDisplay
735
- : "\nโ†ณ " + resultDisplay}`;
736
- }
737
- }
738
- else {
739
- return msg.content;
740
- }
741
- };
742
- const commands = [
743
- "/agent",
744
- "/agents",
745
- "/attach",
746
- "/clear",
747
- "/continue",
748
- "/verbose",
749
- "/debug",
750
- "/detach",
751
- "/exit",
752
- "/help",
753
- "/kill",
754
- "/model",
755
- "/multi",
756
- "/pause",
757
- "/provider",
758
- "/search",
759
- "/voice",
760
- ];
761
- const currentMessages = uiMode === UIMode.AGENT_THREAD ? agentThread : messages;
762
- const promptText = () => {
763
- switch (uiMode) {
764
- case UIMode.AGENT_THREAD:
765
- return `๐Ÿงต Thread with ${activeAgent?.name}: `;
766
- case UIMode.CHAT:
767
- return flags.enabled(ChatFlags.agent) && activeAgent
768
- ? `Ask ${activeAgent.name}: `
769
- : "Ask AI: ";
770
- default:
771
- return "Input: ";
772
- }
773
- };
774
- if (uiMode === UIMode.AGENT_SELECT) {
775
- return (_jsx(AgentSelect, { agents: availableAgents, onSelect: handleAgentSelect, onCancel: handleCancel }));
776
- }
777
- if (uiMode === UIMode.TASK_SELECT) {
778
- return (_jsx(TaskSelect, { tasks: Array.from(taskRegistry.keys()), onSelect: handleTaskSelect, onCancel: handleTaskCancel }));
779
- }
780
- if (uiMode === UIMode.VOICE_RECORD) {
781
- return (_jsx(VoiceRecord, { onComplete: handleVoiceComplete, onCancel: handleCancel }));
782
- }
783
- return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsx(Box, { borderStyle: "single", borderColor: "blue", padding: 1, children: _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "blue", bold: true, children: ["\uD83E\uDDE0 Knowhow Chat Interface", uiMode === UIMode.AGENT_THREAD && activeAgent && (_jsxs(Text, { color: "cyan", children: [" | \uD83E\uDDF5 Thread: ", activeAgent.name] })), uiMode === UIMode.CHAT && (_jsxs(Text, { color: "gray", children: [" ", "| Provider: ", provider, " Model: ", model] }))] }), ((uiMode === UIMode.AGENT_THREAD && activeAgent) ||
784
- (uiMode === UIMode.CHAT &&
785
- flags.enabled(ChatFlags.agent) &&
786
- activeAgent)) && _jsx(CostDisplay, { agent: activeAgent })] }) }), _jsxs(Box, { flexDirection: "column", flexGrow: 1, padding: 1, children: [currentMessages.slice(scrollOffset).map((msg, index) => (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: getDisplayColor(msg), children: [getDisplayRole(msg), ": ", formatMessageContent(msg)] }) }, `msg-${scrollOffset + index}`))), isLoading && (_jsx(Box, { children: _jsxs(Text, { color: "yellow", children: [_jsx(Spinner, { type: "dots" }), " ", uiMode === UIMode.AGENT_THREAD && activeAgent
787
- ? `${activeAgent.name} is working...`
788
- : "Processing..."] }) }))] }), _jsxs(Box, { borderStyle: "single", borderColor: "green", padding: 1, children: [_jsxs(Text, { color: "green", children: ["\uD83D\uDCAC ", promptText()] }), _jsx(CustomTextInput, { value: inputBuffer, onChange: setInputBuffer, onSubmit: handleSendMessage, placeholder: flags.enabled(ChatFlags.multi)
789
- ? "Type your message (multi-line enabled)..."
790
- : "Type your message or command...", suggestions: inputBuffer.startsWith("/") ? commands : [], enabled: uiMode === UIMode.CHAT || uiMode === UIMode.AGENT_THREAD })] }), showHelp && (_jsx(Box, { borderStyle: "single", borderColor: "magenta", padding: 1, backgroundColor: "black", children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "\uD83D\uDCDA Help & Commands:" }), _jsx(Text, { color: "white", children: "\u2022 /agents - Select and start thread with agent" }), _jsx(Text, { color: "white", children: "\u2022 /agent - Toggle agent mode" }), _jsx(Text, { color: "white", children: "\u2022 /voice - Switch to voice input mode" }), _jsx(Text, { color: "white", children: "\u2022 /detach - Leave current agent thread" }), _jsx(Text, { color: "white", children: "\u2022 /attach - Reattach to a running task" }), _jsx(Text, { color: "white", children: "\u2022 /pause - Pause current agent" }), _jsx(Text, { color: "white", children: "\u2022 /kill - Terminate current agent" }), _jsx(Text, { color: "white", children: "\u2022 /provider [name] - Change AI provider" }), _jsx(Text, { color: "white", children: "\u2022 /model [name] - Change AI model" }), _jsx(Text, { color: "white", children: "\u2022 /search [ query ] - Search embeddings" }), _jsx(Text, { color: "white", children: "\u2022 /clear - Clear chat history" }), _jsx(Text, { color: "white", children: "\u2022 /debug - Toggle debug mode" }), _jsx(Text, { color: "white", children: "\u2022 /multi - Toggle multi-line input" }), _jsx(Text, { color: "white", children: "\u2022 /verbose - Toggle verbose tool output" }), _jsx(Text, { color: "white", children: "\u2022 /continue - Continue agent execution with pending messages" }), _jsx(Text, { color: "white", children: "\u2022 /help - Show/hide this help" }), _jsx(Text, { color: "white", children: "\u2022 /exit - Exit application" }), _jsx(Text, { color: "gray", children: "\u2022 Up/Down: History | PgUp/PgDn: Scroll | Tab: Auto-complete | Ctrl+C: Exit" })] }) }))] }));
791
- }
792
- //# sourceMappingURL=InkChatUI.js.map