@tyvm/knowhow 0.0.90 → 0.0.91

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 (262) hide show
  1. package/.depcheckrc +31 -0
  2. package/bin/knowhow.js +1 -1
  3. package/package.json +4 -32
  4. package/src/agents/tools/executeScript/index.ts +5 -0
  5. package/src/agents/tools/googleSearch.ts +2 -2
  6. package/src/agents/tools/index.ts +0 -3
  7. package/src/agents/tools/list.ts +0 -147
  8. package/src/agents/tools/loadWebpage.ts +3 -113
  9. package/src/auth/browserLogin.ts +10 -13
  10. package/src/cli.ts +63 -3
  11. package/src/clients/gemini.ts +96 -25
  12. package/src/clients/http.ts +7 -11
  13. package/src/clients/pricing/google.ts +122 -26
  14. package/src/conversion.ts +24 -54
  15. package/src/index.ts +8 -1
  16. package/src/login.ts +5 -6
  17. package/src/plugins/language.ts +0 -4
  18. package/src/plugins/plugins.ts +0 -14
  19. package/src/plugins/url.ts +31 -12
  20. package/src/services/GitHub.ts +2 -2
  21. package/src/services/KnowhowClient.ts +34 -34
  22. package/src/{plugins/downloader/downloader.ts → services/MediaProcessorService.ts} +109 -267
  23. package/src/services/S3.ts +16 -16
  24. package/src/services/index.ts +4 -4
  25. package/src/services/modules/index.ts +10 -2
  26. package/src/services/modules/types.ts +5 -2
  27. package/src/services/script-execution/ScriptExecutor.ts +29 -10
  28. package/src/services/script-execution/ScriptPolicy.ts +6 -2
  29. package/src/types.ts +1 -0
  30. package/src/utils/http.ts +127 -0
  31. package/src/workers/auth/PasskeySetup.ts +7 -11
  32. package/tests/clients/AIClient.test.ts +24 -21
  33. package/tests/manual/file-edits/figma.test.ts +3 -70
  34. package/tests/plugins/language/languagePlugin-content-triggers.test.ts +2 -0
  35. package/tests/plugins/language/languagePlugin.test.ts +2 -0
  36. package/tests/processors/ToolResponseCache.test.ts +2 -2
  37. package/tests/test.spec.ts +0 -14
  38. package/tests/unit/modules/moduleLoading.test.ts +7 -4
  39. package/tests/unit/plugins/pluginLoading.test.ts +6 -6
  40. package/ts_build/package.json +4 -32
  41. package/ts_build/src/agents/tools/ast/astAppendNode.d.ts +1 -1
  42. package/ts_build/src/agents/tools/ast/astAppendNode.js +2 -90
  43. package/ts_build/src/agents/tools/ast/astAppendNode.js.map +1 -1
  44. package/ts_build/src/agents/tools/ast/astDeleteNode.d.ts +1 -1
  45. package/ts_build/src/agents/tools/ast/astDeleteNode.js +2 -88
  46. package/ts_build/src/agents/tools/ast/astDeleteNode.js.map +1 -1
  47. package/ts_build/src/agents/tools/ast/astEditNode.d.ts +1 -1
  48. package/ts_build/src/agents/tools/ast/astEditNode.js +2 -90
  49. package/ts_build/src/agents/tools/ast/astEditNode.js.map +1 -1
  50. package/ts_build/src/agents/tools/ast/astGetPathForLine.d.ts +1 -1
  51. package/ts_build/src/agents/tools/ast/astGetPathForLine.js +2 -72
  52. package/ts_build/src/agents/tools/ast/astGetPathForLine.js.map +1 -1
  53. package/ts_build/src/agents/tools/ast/astListPaths.d.ts +1 -1
  54. package/ts_build/src/agents/tools/ast/astListPaths.js +2 -72
  55. package/ts_build/src/agents/tools/ast/astListPaths.js.map +1 -1
  56. package/ts_build/src/agents/tools/executeScript/index.d.ts +3 -2
  57. package/ts_build/src/agents/tools/executeScript/index.js +4 -1
  58. package/ts_build/src/agents/tools/executeScript/index.js.map +1 -1
  59. package/ts_build/src/agents/tools/googleSearch.js +2 -2
  60. package/ts_build/src/agents/tools/googleSearch.js.map +1 -1
  61. package/ts_build/src/agents/tools/index.d.ts +0 -3
  62. package/ts_build/src/agents/tools/index.js +0 -3
  63. package/ts_build/src/agents/tools/index.js.map +1 -1
  64. package/ts_build/src/agents/tools/list.js +0 -138
  65. package/ts_build/src/agents/tools/list.js.map +1 -1
  66. package/ts_build/src/agents/tools/loadWebpage.js +1 -89
  67. package/ts_build/src/agents/tools/loadWebpage.js.map +1 -1
  68. package/ts_build/src/agents/tools/textSearch.d.ts +1 -1
  69. package/ts_build/src/auth/browserLogin.js +7 -7
  70. package/ts_build/src/auth/browserLogin.js.map +1 -1
  71. package/ts_build/src/cli.d.ts +1 -1
  72. package/ts_build/src/cli.js +47 -1
  73. package/ts_build/src/cli.js.map +1 -1
  74. package/ts_build/src/clients/gemini.d.ts +1 -73
  75. package/ts_build/src/clients/gemini.js +57 -19
  76. package/ts_build/src/clients/gemini.js.map +1 -1
  77. package/ts_build/src/clients/http.js +5 -9
  78. package/ts_build/src/clients/http.js.map +1 -1
  79. package/ts_build/src/clients/pricing/google.d.ts +17 -73
  80. package/ts_build/src/clients/pricing/google.js +47 -10
  81. package/ts_build/src/clients/pricing/google.js.map +1 -1
  82. package/ts_build/src/conversion.d.ts +1 -4
  83. package/ts_build/src/conversion.js +12 -27
  84. package/ts_build/src/conversion.js.map +1 -1
  85. package/ts_build/src/index.d.ts +4 -0
  86. package/ts_build/src/index.js +7 -1
  87. package/ts_build/src/index.js.map +1 -1
  88. package/ts_build/src/login.js +5 -4
  89. package/ts_build/src/login.js.map +1 -1
  90. package/ts_build/src/plugins/downloader/downloader.js +3 -3
  91. package/ts_build/src/plugins/downloader/downloader.js.map +1 -1
  92. package/ts_build/src/plugins/language.js.map +1 -1
  93. package/ts_build/src/plugins/plugins.js +0 -14
  94. package/ts_build/src/plugins/plugins.js.map +1 -1
  95. package/ts_build/src/plugins/tree-sitter/editor.d.ts +3 -32
  96. package/ts_build/src/plugins/tree-sitter/editor.js +6 -208
  97. package/ts_build/src/plugins/tree-sitter/editor.js.map +1 -1
  98. package/ts_build/src/plugins/tree-sitter/parser.d.ts +19 -54
  99. package/ts_build/src/plugins/tree-sitter/parser.js +19 -293
  100. package/ts_build/src/plugins/tree-sitter/parser.js.map +1 -1
  101. package/ts_build/src/plugins/tree-sitter/simple-paths.d.ts +2 -15
  102. package/ts_build/src/plugins/tree-sitter/simple-paths.js +2 -324
  103. package/ts_build/src/plugins/tree-sitter/simple-paths.js.map +1 -1
  104. package/ts_build/src/plugins/url.js +27 -8
  105. package/ts_build/src/plugins/url.js.map +1 -1
  106. package/ts_build/src/services/GitHub.js +2 -2
  107. package/ts_build/src/services/GitHub.js.map +1 -1
  108. package/ts_build/src/services/KnowhowClient.d.ts +29 -29
  109. package/ts_build/src/services/KnowhowClient.js +33 -33
  110. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  111. package/ts_build/src/services/MediaProcessorService.d.ts +22 -0
  112. package/ts_build/src/services/MediaProcessorService.js +215 -0
  113. package/ts_build/src/services/MediaProcessorService.js.map +1 -0
  114. package/ts_build/src/services/S3.js +12 -18
  115. package/ts_build/src/services/S3.js.map +1 -1
  116. package/ts_build/src/services/index.d.ts +3 -2
  117. package/ts_build/src/services/index.js +3 -3
  118. package/ts_build/src/services/index.js.map +1 -1
  119. package/ts_build/src/services/modules/index.js +10 -2
  120. package/ts_build/src/services/modules/index.js.map +1 -1
  121. package/ts_build/src/services/modules/types.d.ts +5 -2
  122. package/ts_build/src/services/script-execution/ScriptExecutor.js +22 -7
  123. package/ts_build/src/services/script-execution/ScriptExecutor.js.map +1 -1
  124. package/ts_build/src/services/script-execution/ScriptPolicy.d.ts +1 -1
  125. package/ts_build/src/services/script-execution/ScriptPolicy.js +4 -2
  126. package/ts_build/src/services/script-execution/ScriptPolicy.js.map +1 -1
  127. package/ts_build/src/types.d.ts +1 -0
  128. package/ts_build/src/types.js +1 -0
  129. package/ts_build/src/types.js.map +1 -1
  130. package/ts_build/src/utils/http.d.ts +27 -0
  131. package/ts_build/src/utils/http.js +98 -0
  132. package/ts_build/src/utils/http.js.map +1 -0
  133. package/ts_build/src/workers/auth/PasskeySetup.js +6 -7
  134. package/ts_build/src/workers/auth/PasskeySetup.js.map +1 -1
  135. package/ts_build/tests/clients/AIClient.test.js +11 -14
  136. package/ts_build/tests/clients/AIClient.test.js.map +1 -1
  137. package/ts_build/tests/manual/file-edits/figma.test.d.ts +0 -1
  138. package/ts_build/tests/manual/file-edits/figma.test.js +1 -46
  139. package/ts_build/tests/manual/file-edits/figma.test.js.map +1 -1
  140. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +2 -0
  141. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +1 -1
  142. package/ts_build/tests/plugins/language/languagePlugin.test.js +2 -0
  143. package/ts_build/tests/plugins/language/languagePlugin.test.js.map +1 -1
  144. package/ts_build/tests/processors/ToolResponseCache.test.js +2 -2
  145. package/ts_build/tests/processors/ToolResponseCache.test.js.map +1 -1
  146. package/ts_build/tests/test.spec.js +0 -14
  147. package/ts_build/tests/test.spec.js.map +1 -1
  148. package/ts_build/tests/tree-sitter/tree-sitter.test.d.ts +0 -1
  149. package/ts_build/tests/tree-sitter/tree-sitter.test.js +2 -183
  150. package/ts_build/tests/tree-sitter/tree-sitter.test.js.map +1 -1
  151. package/ts_build/tests/unit/modules/moduleLoading.test.js +6 -4
  152. package/ts_build/tests/unit/modules/moduleLoading.test.js.map +1 -1
  153. package/ts_build/tests/unit/plugins/pluginLoading.test.js +4 -4
  154. package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -1
  155. package/benchmarks/.dockerignore +0 -7
  156. package/benchmarks/README.md +0 -166
  157. package/benchmarks/docker/Dockerfile +0 -68
  158. package/benchmarks/example-config.yml +0 -27
  159. package/benchmarks/jest.config.js +0 -13
  160. package/benchmarks/package-lock.json +0 -4297
  161. package/benchmarks/package.json +0 -39
  162. package/benchmarks/results/27b0a06/2025-09-27/xai/xai-grok-code-fast-1.json +0 -2909
  163. package/benchmarks/results/4057aed/2025-08-14/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -1671
  164. package/benchmarks/results/4542435/2025-08-05/lms/lms-openai-gpt-oss-20b.json +0 -2814
  165. package/benchmarks/results/4542435/2025-08-05/lms/lms-qwen-qwen3-30b-a3b-2507.json +0 -2014
  166. package/benchmarks/results/4fb9125/2025-08-07/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -3121
  167. package/benchmarks/results/5766aee/2025-08-02/lms-qwen/qwen3-coder-30b.json +0 -98
  168. package/benchmarks/results/6d73808/2025-08-07/openai/openai-gpt-5.json +0 -3256
  169. package/benchmarks/results/77bf0a6/2025-08-02/lms-qwen/qwen3-30b-a3b-2507.json +0 -4298
  170. package/benchmarks/results/8c0d445/2025-08-03/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -3031
  171. package/benchmarks/results/8c0d445/2025-08-03/openai/openai-gpt-4.1-2025-04-14.json +0 -2990
  172. package/benchmarks/results/ac6b2ab/2025-08-03/anthropic/anthropic-claude-sonnet-4-20250514.json +0 -3256
  173. package/benchmarks/results/ac6b2ab/2025-08-03/lms/lms-qwen-qwen3-coder-30b.json +0 -3007
  174. package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-2025-04-14.json +0 -3256
  175. package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-mini-2025-04-14.json +0 -3036
  176. package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-nano-2025-04-14.json +0 -3280
  177. package/benchmarks/results/adff675/2025-08-04/lms/lms-qwen-qwen3-30b-a3b-2507.json +0 -1920
  178. package/benchmarks/results/adff675/2025-08-04/lms/lms-qwen-qwen3-coder-30b.json +0 -3281
  179. package/benchmarks/results/b502ed9/2025-08-03/lms-qwen/qwen3-coder-30b.json +0 -2896
  180. package/benchmarks/results/d1a8129/2025-08-03/lms/lms-qwen-qwen3-coder-30b.json +0 -3011
  181. package/benchmarks/results/e60471c/2025-08-03/lms/qwen3-30b-a3b-2507.json +0 -3003
  182. package/benchmarks/scripts/build-and-run.sh +0 -47
  183. package/benchmarks/scripts/clone-exercism.sh +0 -92
  184. package/benchmarks/scripts/validate.sh +0 -48
  185. package/benchmarks/src/__tests__/runner.test.ts +0 -27
  186. package/benchmarks/src/cli.ts +0 -90
  187. package/benchmarks/src/evaluators/EvaluatorRegistry.ts +0 -64
  188. package/benchmarks/src/evaluators/JavaScriptEvaluator.ts +0 -183
  189. package/benchmarks/src/evaluators/index.ts +0 -3
  190. package/benchmarks/src/evaluators/types.ts +0 -22
  191. package/benchmarks/src/index.ts +0 -3
  192. package/benchmarks/src/providers.ts +0 -13
  193. package/benchmarks/src/runner.ts +0 -824
  194. package/benchmarks/src/types.ts +0 -63
  195. package/benchmarks/tsconfig.json +0 -19
  196. package/leaderboard/README.md +0 -148
  197. package/leaderboard/app/api/benchmark-data/route.ts +0 -131
  198. package/leaderboard/app/api/benchmark-detail/route.ts +0 -172
  199. package/leaderboard/app/details/[model]/[provider]/[language]/page.tsx +0 -501
  200. package/leaderboard/app/exercise/[model]/[provider]/[language]/[exercise]/page.tsx +0 -375
  201. package/leaderboard/app/globals.css +0 -27
  202. package/leaderboard/app/layout.tsx +0 -21
  203. package/leaderboard/app/page.tsx +0 -170
  204. package/leaderboard/components/LeaderboardTable.tsx +0 -168
  205. package/leaderboard/components/PerformanceChart.tsx +0 -109
  206. package/leaderboard/next-env.d.ts +0 -5
  207. package/leaderboard/next.config.js +0 -4
  208. package/leaderboard/package-lock.json +0 -6363
  209. package/leaderboard/package.json +0 -28
  210. package/leaderboard/postcss.config.js +0 -6
  211. package/leaderboard/tailwind.config.js +0 -17
  212. package/leaderboard/tsconfig.json +0 -28
  213. package/leaderboard/types/benchmark.ts +0 -67
  214. package/leaderboard/utils/dataProcessor.ts +0 -33
  215. package/src/agents/tools/asana/definitions.ts +0 -199
  216. package/src/agents/tools/asana/index.ts +0 -108
  217. package/src/agents/tools/ast/astAppendNode.ts +0 -90
  218. package/src/agents/tools/ast/astDeleteNode.ts +0 -88
  219. package/src/agents/tools/ast/astEditNode.ts +0 -95
  220. package/src/agents/tools/ast/astGetPathForLine.ts +0 -73
  221. package/src/agents/tools/ast/astListPaths.ts +0 -66
  222. package/src/agents/tools/ast/index.ts +0 -7
  223. package/src/agents/tools/github/definitions.ts +0 -89
  224. package/src/agents/tools/github/index.ts +0 -67
  225. package/src/chat-old.ts +0 -446
  226. package/src/plugins/asana.ts +0 -146
  227. package/src/plugins/downloader/plugin.ts +0 -103
  228. package/src/plugins/downloader/types.ts +0 -92
  229. package/src/plugins/figma.ts +0 -158
  230. package/src/plugins/github.ts +0 -219
  231. package/src/plugins/jira.ts +0 -115
  232. package/src/plugins/linear.ts +0 -230
  233. package/src/plugins/notion.ts +0 -179
  234. package/src/plugins/tree-sitter/editor.ts +0 -369
  235. package/src/plugins/tree-sitter/lang-packs/index.ts +0 -23
  236. package/src/plugins/tree-sitter/lang-packs/java.ts +0 -59
  237. package/src/plugins/tree-sitter/lang-packs/javascript.ts +0 -57
  238. package/src/plugins/tree-sitter/lang-packs/python.ts +0 -45
  239. package/src/plugins/tree-sitter/lang-packs/types.ts +0 -79
  240. package/src/plugins/tree-sitter/lang-packs/typescript.ts +0 -49
  241. package/src/plugins/tree-sitter/parser.ts +0 -470
  242. package/src/plugins/tree-sitter/simple-paths.ts +0 -467
  243. package/tests/tree-sitter/editor.test.ts +0 -113
  244. package/tests/tree-sitter/invalid.test.ts +0 -299
  245. package/tests/tree-sitter/paths/common-edits.test.ts +0 -564
  246. package/tests/tree-sitter/paths/debug-exact-position.test.ts +0 -44
  247. package/tests/tree-sitter/paths/debug-line-indexing.test.ts +0 -49
  248. package/tests/tree-sitter/paths/debug-paths.test.ts +0 -90
  249. package/tests/tree-sitter/paths/paths.test.ts +0 -170
  250. package/tests/tree-sitter/paths/simple-paths.test.ts +0 -367
  251. package/tests/tree-sitter/sample-after.ts +0 -48
  252. package/tests/tree-sitter/sample-before.ts +0 -25
  253. package/tests/tree-sitter/test-files/completely-broken.ts +0 -7
  254. package/tests/tree-sitter/test-files/duplicate-braces.ts +0 -39
  255. package/tests/tree-sitter/test-files/invalid-nesting.ts +0 -39
  256. package/tests/tree-sitter/test-files/malformed-signature.ts +0 -39
  257. package/tests/tree-sitter/test-files/mismatched-parens.ts +0 -39
  258. package/tests/tree-sitter/test-files/missing-semicolon.ts +0 -39
  259. package/tests/tree-sitter/test-files/partially-broken.ts +0 -20
  260. package/tests/tree-sitter/test-files/specific-errors.ts +0 -14
  261. package/tests/tree-sitter/test-files/unclosed-string.ts +0 -39
  262. package/tests/tree-sitter/tree-sitter.test.ts +0 -251
package/src/chat-old.ts DELETED
@@ -1,446 +0,0 @@
1
- import { ChatCompletionMessageParam } from "openai/resources/chat";
2
- import Ora from "ora";
3
- import editor from "@inquirer/editor";
4
- import { cosineSimilarity } from "./utils";
5
- import {
6
- EmbeddingBase,
7
- GptQuestionEmbedding,
8
- Embeddable,
9
- ChatInteraction,
10
- } from "./types";
11
- import { Marked } from "./utils";
12
- import { ask } from "./utils";
13
- import { services } from "./services";
14
- import { queryEmbedding, getConfiguredEmbeddingMap } from "./embeddings";
15
- import { FlagsService } from "./services/flags";
16
- import { IAgent } from "./agents/interface";
17
- import { Message } from "./clients";
18
- import { recordAudio, voiceToText } from "./microphone";
19
- import { Models } from "./ai";
20
- import { BaseAgent } from "./agents";
21
- import { getConfig } from "./config";
22
- import { TokenCompressor } from "./processors/TokenCompressor";
23
- import { ToolResponseCache } from "./processors/ToolResponseCache";
24
- import { CustomVariables, XmlToolCallProcessor, HarmonyToolProcessor } from "./processors";
25
-
26
- enum ChatFlags {
27
- agent = "agent",
28
- agents = "agents",
29
- debug = "debug",
30
- multi = "multi",
31
- model = "model",
32
- search = "search",
33
- clear = "clear",
34
- provider = "provider",
35
- voice = "voice",
36
- }
37
-
38
- const Flags = new FlagsService(
39
- [ChatFlags.agent, ChatFlags.debug, ChatFlags.multi, ChatFlags.voice],
40
- true
41
- );
42
-
43
- const taskRegistry = new Map<string, BaseAgent>();
44
-
45
- export async function askEmbedding<E>(promptText: string) {
46
- const options = ["next", "exit", "embeddings", "use"];
47
- console.log(`Commands: ${options.join(", ")}`);
48
- let input = await ask(promptText + ": ", options);
49
- let answer: EmbeddingBase<any> | undefined;
50
- let results = new Array<EmbeddingBase>();
51
- let embedMap = await getConfiguredEmbeddingMap();
52
- const config = await getConfig();
53
- const files = Object.keys(embedMap);
54
-
55
- while (input !== "exit") {
56
- const embeddings = Object.values(embedMap).flat();
57
-
58
- switch (input) {
59
- case "next":
60
- answer = results.shift();
61
- break;
62
- case "embeddings":
63
- console.log(files);
64
- break;
65
- case "use":
66
- const searchOptions = ["all", ...files];
67
- console.log(searchOptions);
68
- const embeddingName = await ask("Embedding to search: ", searchOptions);
69
- if (embeddingName === "all") {
70
- embedMap = await getConfiguredEmbeddingMap();
71
- break;
72
- }
73
-
74
- embedMap = { ...{ [embeddingName]: embedMap[embeddingName] } };
75
- break;
76
- default:
77
- results = await queryEmbedding(
78
- input,
79
- embeddings,
80
- config.embeddingModel
81
- );
82
- answer = results.shift();
83
- break;
84
- }
85
- if (answer) {
86
- console.log(
87
- Marked.parse(
88
- "### TEXT \n" +
89
- answer.text +
90
- "\n### METADATA \n" +
91
- JSON.stringify(answer.metadata, null, 2)
92
- )
93
- );
94
- }
95
-
96
- input = await ask(promptText + ": ");
97
- }
98
- }
99
-
100
- const ChatModelDefaults = {
101
- openai: Models.openai.GPT_4o,
102
- anthropic: Models.anthropic.Sonnet4,
103
- google: Models.google.Gemini_25_Flash_Preview,
104
- xai: Models.xai.Grok3Beta,
105
- };
106
- export async function askAI<E extends EmbeddingBase>(
107
- query: string,
108
- provider = "openai",
109
- model = ChatModelDefaults[provider]
110
- ) {
111
- const gptPrompt = `
112
-
113
- The user has asked:
114
- ${query}
115
-
116
- Output Format in Markdown
117
- `;
118
- if (Flags.enabled("debugger")) {
119
- console.log(gptPrompt);
120
- }
121
-
122
- const thread = [
123
- {
124
- role: "system",
125
- content:
126
- "Helpful Codebase assistant. Answer users questions using the embedding data that is provided with the user's question. You have limited access to the codebase based off of how similar the codebase is to the user's question. You may reference file paths by using the IDs present in the embedding data, but be sure to remove the chunk from the end of the filepaths.",
127
- },
128
- { role: "user", content: gptPrompt },
129
- ] as Message[];
130
-
131
- const { Clients } = services();
132
- const response = await Clients.createCompletion(provider, {
133
- messages: thread,
134
- model,
135
- });
136
-
137
- return response.choices[0].message.content;
138
- }
139
-
140
- export async function getInput(
141
- question: string,
142
- options = [],
143
- chatHistory: ChatInteraction[] = []
144
- ): Promise<string> {
145
- const multiLine = Flags.enabled(ChatFlags.multi);
146
- const voice = Flags.enabled(ChatFlags.voice);
147
-
148
- let value = "";
149
- if (voice) {
150
- value = await voiceToText();
151
- } else if (multiLine) {
152
- value = await editor({ message: question });
153
- Flags.disable(ChatFlags.multi);
154
- } else {
155
- const history = chatHistory.map((c) => c.input);
156
- value = await ask(question, options, history);
157
- }
158
-
159
- return value.trim();
160
- }
161
-
162
- export async function formatChatInput(
163
- input: string,
164
- plugins: string[] = [],
165
- chatHistory: ChatInteraction[] = []
166
- ) {
167
- const { Plugins } = services();
168
- const pluginText = await Plugins.callMany(plugins, input);
169
- const historyMessage = `<PreviousChats>
170
- This information is provided as historical context and is likely not related to the current task:
171
- ${JSON.stringify(chatHistory)}
172
- </PreviousChats>`;
173
- const fullPrompt = `
174
- ${historyMessage} \n
175
- <PluginContext> ${pluginText} </PluginContext>
176
- <CurrentTask>${input}</CurrentTask>
177
- `;
178
- return fullPrompt;
179
- }
180
-
181
- export async function chatLoop<E extends GptQuestionEmbedding>(
182
- aiName: string,
183
- embeddings: Embeddable<E>[],
184
- plugins: string[] = []
185
- ) {
186
- const { Agents, Clients } = services();
187
- let activeAgent = Agents.getAgent("Developer") as BaseAgent;
188
- let provider = "openai" as keyof typeof Clients.clients;
189
- let model = ChatModelDefaults[provider];
190
- const providers = Object.keys(Clients.clients);
191
- const commands = [
192
- "agent",
193
- "agents",
194
- "clear",
195
- "debugger",
196
- "exit",
197
- "model",
198
- "multi",
199
- "provider",
200
- "search",
201
- "voice",
202
- ];
203
- console.log("Commands: ", commands.join(", "));
204
- const promptText = () =>
205
- Flags.enabled(ChatFlags.agent)
206
- ? `\nAsk ${aiName} ${activeAgent.name}: `
207
- : `\nAsk ${aiName}: `;
208
-
209
- let chatHistory = new Array<ChatInteraction>();
210
- let input = await getInput(promptText(), commands, chatHistory);
211
-
212
- let results = "";
213
- while (input !== "exit") {
214
- try {
215
- switch (input) {
216
- case ChatFlags.agents:
217
- Flags.enable(ChatFlags.agent);
218
- const agents = Agents.listAgents();
219
- console.log(agents);
220
- const selected = await ask(
221
- "Which agent would you like to use: ",
222
- agents
223
- );
224
- activeAgent = Agents.getAgent(selected) as BaseAgent;
225
- model = activeAgent.getModel();
226
- provider = activeAgent.getProvider() as keyof typeof Clients.clients;
227
- break;
228
- case ChatFlags.agent:
229
- Flags.flip(ChatFlags.agent);
230
- break;
231
- case ChatFlags.debug:
232
- Flags.flip(ChatFlags.debug);
233
- break;
234
- case ChatFlags.multi:
235
- Flags.flip(ChatFlags.multi);
236
- break;
237
- case ChatFlags.voice:
238
- Flags.flip(ChatFlags.voice);
239
- break;
240
- case ChatFlags.search:
241
- await askEmbedding("searching");
242
- break;
243
- case ChatFlags.clear:
244
- chatHistory = [];
245
- break;
246
- case ChatFlags.provider:
247
- console.log(providers);
248
- provider = await ask(
249
- `\n\nCurrent Provider: ${provider}\nCurrent Model: ${model}\n\nWhich provider would you like to use: `,
250
- providers
251
- ) as keyof typeof Clients.clients;
252
- model =
253
- ChatModelDefaults[provider] ||
254
- (await Clients.getRegisteredModels(provider))[0];
255
-
256
- if (Flags.enabled("agent")) {
257
- activeAgent.setProvider(provider);
258
- activeAgent.setModel(model);
259
- }
260
-
261
- break;
262
- case ChatFlags.model:
263
- const models = Clients.getRegisteredModels(provider);
264
- console.log(models);
265
- const selectedModel = await ask(
266
- `\n\nCurrent Provider: ${provider}\nCurrent Model: ${model}\n\nWhich model would you like to use: `,
267
- models
268
- );
269
- model = selectedModel;
270
-
271
- if (Flags.enabled("agent")) {
272
- activeAgent.setProvider(provider);
273
- activeAgent.setModel(model);
274
- }
275
- break;
276
- case "attach":
277
- if (taskRegistry.size > 0) {
278
- const options = Array.from(taskRegistry.keys());
279
- const selectedInitialMessage = await ask(
280
- "Select an agent to attach to:",
281
- options
282
- );
283
- activeAgent = taskRegistry.get(selectedInitialMessage)!;
284
- console.log(
285
- `Attached to agent with task: "${selectedInitialMessage}"`
286
- );
287
- await startAgent(activeAgent, null, true);
288
- } else {
289
- console.log("No detached agents available.");
290
- }
291
- case "":
292
- break;
293
- default:
294
- console.log("Thinking...");
295
- console.log(input);
296
- const interaction = {
297
- input,
298
- output: "",
299
- } as ChatInteraction;
300
- if (Flags.enabled("agent")) {
301
- taskRegistry.set(input, activeAgent);
302
- await startAgent(activeAgent, {
303
- initialInput: input,
304
- plugins,
305
- chatHistory,
306
- interaction,
307
- });
308
- } else {
309
- const formattedPrompt = await formatChatInput(
310
- input,
311
- plugins,
312
- chatHistory
313
- );
314
- results = await askAI(formattedPrompt, provider, model);
315
- interaction.output = results;
316
- console.log(Marked.parse(results || "No response from the AI"));
317
- }
318
- console.log("\n\n");
319
- chatHistory.push(interaction);
320
- break;
321
- }
322
- } catch (e) {
323
- console.log(e);
324
- } finally {
325
- input = await getInput(promptText(), commands, chatHistory);
326
- }
327
- }
328
- }
329
-
330
- export async function startAgent(
331
- activeAgent: BaseAgent,
332
- newTask?: {
333
- initialInput: string;
334
- plugins: string[];
335
- chatHistory: ChatInteraction[];
336
- interaction: ChatInteraction;
337
- },
338
- attach = false
339
- ) {
340
- let done = false;
341
- let output = "Done";
342
-
343
- if (newTask) {
344
- const { initialInput, plugins, chatHistory, interaction } = newTask;
345
- await activeAgent.newTask();
346
- const formattedPrompt = await formatChatInput(
347
- initialInput,
348
- plugins,
349
- chatHistory
350
- );
351
- activeAgent.call(formattedPrompt);
352
-
353
- // Compress tokens of tool responses
354
- activeAgent.messageProcessor.setProcessors("pre_call", [
355
- new ToolResponseCache(activeAgent.tools).createProcessor(),
356
-
357
- new TokenCompressor(activeAgent.tools).createProcessor((msg) =>
358
- Boolean(msg.role === "tool" && msg.tool_call_id)
359
- ),
360
- new CustomVariables(activeAgent.tools).createProcessor(),
361
- ]);
362
-
363
- // Process XML and Harmony tool calls in assistant responses
364
- activeAgent.messageProcessor.setProcessors("post_call", [
365
- new XmlToolCallProcessor().createProcessor(),
366
- new HarmonyToolProcessor().createProcessor(),
367
- ]);
368
-
369
- if (
370
- !activeAgent.agentEvents.listenerCount(activeAgent.eventTypes.toolUsed)
371
- ) {
372
- activeAgent.agentEvents.on(
373
- activeAgent.eventTypes.toolUsed,
374
- (responseMsg) => {
375
- console.log(` 🔨 Tool used: ${JSON.stringify(responseMsg, null, 2)}`);
376
- }
377
- );
378
- }
379
-
380
- activeAgent.agentEvents.once(activeAgent.eventTypes.done, (doneMsg) => {
381
- console.log("Agent has finished.");
382
- done = true;
383
- taskRegistry.delete(initialInput);
384
- output = doneMsg || "No response from the AI";
385
- interaction.output = output;
386
- console.log(Marked.parse(output));
387
- });
388
- }
389
-
390
- // Define available commands
391
- const commands = ["pause", "unpause", "kill", "detach"];
392
- const history = [];
393
-
394
- let input = await getInput(
395
- `Enter command or message for ${activeAgent.name}: `,
396
- commands,
397
- history
398
- );
399
-
400
- history.push(input);
401
-
402
- const donePromise = new Promise<string>((resolve) => {
403
- activeAgent.agentEvents.on(activeAgent.eventTypes.done, () => {
404
- done = true;
405
- resolve("done");
406
- });
407
- });
408
-
409
- while (!done) {
410
- switch (input) {
411
- case "":
412
- break;
413
- case "done":
414
- output = "Exited agent interaction.";
415
- break;
416
- case "pause":
417
- await activeAgent.pause();
418
- console.log("Agent paused.");
419
- break;
420
- case "unpause":
421
- await activeAgent.unpause();
422
- console.log("Agent unpaused.");
423
- break;
424
- case "kill":
425
- await activeAgent.kill();
426
- console.log("Agent terminated.");
427
- break;
428
- case "detach":
429
- return "Detached from agent";
430
- break;
431
- default:
432
- activeAgent.addPendingUserMessage({ role: "user", content: input });
433
- }
434
-
435
- input = await Promise.race([
436
- getInput(
437
- `Enter command or message for ${activeAgent.name}: `,
438
- commands,
439
- history
440
- ),
441
- donePromise,
442
- ]);
443
- }
444
-
445
- return output;
446
- }
@@ -1,146 +0,0 @@
1
- import { PluginBase, PluginMeta } from "./PluginBase";
2
- import { Embeddable, MinimalEmbedding } from "../types";
3
- import { PluginContext } from "./types";
4
-
5
- export class AsanaPlugin extends PluginBase {
6
- static readonly meta: PluginMeta = {
7
- key: "asana",
8
- name: "Asana Plugin",
9
- requires: ["ASANA_TOKEN"]
10
- };
11
-
12
- meta = AsanaPlugin.meta;
13
- private asanaClient = require("asana").ApiClient.instance;
14
-
15
- constructor(context: PluginContext) {
16
- super(context);
17
-
18
- if (!this.isEnabled()) return;
19
-
20
- this.asanaClient.authentications.token = process.env.ASANA_TOKEN;
21
- this.asanaClient.defaultHeaders = {
22
- "Asana-Enable": "new_user_task_lists,new_goal_memberships",
23
- };
24
- }
25
-
26
- getTaskString(task: any) {
27
- return `### Task: ${task.name}\n- Description: ${task.notes}\n- URL: ${task.permalink_url}\n Completed: ${task.completed}`;
28
- }
29
-
30
- async embed(userPrompt: string): Promise<MinimalEmbedding[]> {
31
- const urls = this.extractTaskUrls(userPrompt);
32
- const tasksData = await this.getTasksFromUrls(urls);
33
- const tasksDataFiltered = tasksData.filter((task) => task !== null);
34
-
35
- const tasksEmbeddings = tasksDataFiltered.map((task) => {
36
- return {
37
- id: task.permalink_url,
38
- text: this.getTaskString(task),
39
- metadata: {
40
- task: JSON.stringify(task),
41
- },
42
- };
43
- });
44
-
45
- const projectUrls = this.extractProjectUrls(userPrompt);
46
- const projectTasks = await this.getTasksFromProjectUrls(projectUrls);
47
- const projectTasksFiltered = projectTasks.filter((t) => t !== null);
48
-
49
- const projectTaskEmbeddings = projectTasksFiltered.map((t) => {
50
- return {
51
- id: t.permalink_url,
52
- text: this.getTaskString(t),
53
- metadata: {
54
- task: JSON.stringify(t),
55
- },
56
- };
57
- });
58
-
59
- const allTasks = tasksEmbeddings.concat(projectTaskEmbeddings);
60
- this.log(`Found ${allTasks.length} tasks`);
61
- return allTasks;
62
- }
63
-
64
- extractProjectUrls(userPrompt: string): string[] {
65
- const projectUrlRegex = /https:\/\/app\.asana\.com\/0\/(\d+)\/list/g;
66
- const matches = userPrompt.match(projectUrlRegex);
67
- return matches || [];
68
- }
69
-
70
- extractTaskUrls(userPrompt: string): string[] {
71
- const taskUrlRegex = /https:\/\/app\.asana\.com\/0\/(\d+)\/(\d+)/g;
72
- const matches = userPrompt.match(taskUrlRegex);
73
- return matches || [];
74
- }
75
-
76
- async getTasksFromUrls(urls: string[]) {
77
- const tasks = await Promise.all(
78
- urls.map(async (url) => {
79
- return this.getTaskFromUrl(url);
80
- })
81
- );
82
- return tasks;
83
- }
84
-
85
- async getTasksFromProjectUrls(urls: string[]) {
86
- const tasks = await Promise.all(
87
- urls.map((url) => this.getTasksFromProjectUrl(url))
88
- );
89
- return tasks.flat();
90
- }
91
-
92
- async getTasksFromProjectUrl(url: string) {
93
- const urlParts = url.split("/");
94
- const projectId = urlParts[4];
95
- this.log(`Project ID: ${projectId}`);
96
- if (!projectId) {
97
- return null;
98
- }
99
- let tasks = await this.asanaClient.tasks.findAll({
100
- project: projectId,
101
- opt_expand: "notes,assignee,permalink_url,custom_fields,tags,completed",
102
- });
103
- const allData = [];
104
-
105
- do {
106
- allData.push(...tasks.data);
107
- tasks = await tasks.nextPage();
108
- } while (tasks);
109
-
110
- return allData;
111
- }
112
-
113
- async getTaskFromUrl(url: string) {
114
- const taskId = url.split("/").pop();
115
- if (taskId) {
116
- this.log(`Fetching Asana task ${taskId}`);
117
- return await this.getTaskData(taskId);
118
- }
119
- return null;
120
- }
121
-
122
- async getTaskData(taskId: string) {
123
- try {
124
- const task = await this.asanaClient.tasks.findById(taskId);
125
- return task;
126
- } catch (error) {
127
- this.log(`Error fetching Asana task: ${error}`, "error");
128
- return null;
129
- }
130
- }
131
-
132
- async call(userPrompt: string): Promise<string> {
133
- const urls = this.extractTaskUrls(userPrompt);
134
- const tasksData = await this.getTasksFromUrls(urls);
135
- const tasksDataFiltered = tasksData.filter((task) => task !== null);
136
-
137
- if (tasksDataFiltered.length === 0) {
138
- return "ASANA PLUGIN: No tasks found";
139
- }
140
-
141
- const markdownTasks = tasksDataFiltered
142
- .map((task) => this.getTaskString(task))
143
- .join("\n\n");
144
- return `ASANA PLUGIN: The following tasks were loaded:\n\n${markdownTasks}`;
145
- }
146
- }
@@ -1,103 +0,0 @@
1
- import fs from "fs";
2
- import { PluginBase, PluginMeta } from "../PluginBase";
3
- import { MinimalEmbedding } from "../../types";
4
- import { PluginContext } from "../types";
5
- import { convertToText, processVideo } from "../../conversion";
6
- import { services } from "../../services";
7
-
8
- export class DownloaderPlugin extends PluginBase {
9
- static readonly meta: PluginMeta = {
10
- key: "downloader",
11
- name: "Downloader Plugin",
12
- requires: [],
13
- };
14
-
15
- meta = DownloaderPlugin.meta;
16
-
17
- constructor(context: PluginContext) {
18
- super(context);
19
- }
20
-
21
- skipExt = ["jpg", "jpeg", "png", "gif"];
22
-
23
- extractUrls(userInput: string): string[] {
24
- const urlRegex = /https:\/\/[^\s]+/gim;
25
- const matches = userInput.match(urlRegex) || [];
26
- return Array.from(new Set(matches));
27
- }
28
-
29
- async call(userInput: string): Promise<string> {
30
- const urls = this.extractUrls(userInput);
31
- if (urls.length === 0) {
32
- return "DOWNLOADER PLUGIN: No URLs found in the input";
33
- }
34
- if (urls.length > 10) {
35
- return "DOWNLOADER PLUGIN: Too many URLs found in the input. Skipping likely unintentional bulk download.";
36
- }
37
- let transcript = "";
38
- for (const url of urls) {
39
- if (this.skipExt.includes(url.split(".").pop() || "")) {
40
- console.log("DOWNLOADER PLUGIN: skipping", url);
41
- continue;
42
- }
43
- try {
44
- console.log("DOWNLOADER PLUGIN: attempting", url);
45
- const downloadDir = ".knowhow/downloads/";
46
- const { Downloader } = services();
47
- const fileInfo = await Downloader.download(url, downloadDir);
48
- const filePath = `${downloadDir}${fileInfo.id}.${fileInfo.ext}`;
49
- transcript += await convertToText(filePath);
50
- } catch (e) {
51
- console.log("DOWNLOADER PLUGIN: cannot download", url);
52
- }
53
- }
54
- return "DOWNLOADER PLUGIN: " + transcript;
55
- }
56
-
57
- async embed(userInput: string): Promise<MinimalEmbedding[]> {
58
- const urls = this.extractUrls(userInput);
59
- if (urls.length === 0) {
60
- return [];
61
- }
62
-
63
- const embeddings: MinimalEmbedding[] = [];
64
- for (const url of urls) {
65
- const downloadDir = ".knowhow/downloads/";
66
- const { Downloader } = services();
67
- const fileInfo = await Downloader.download(url, downloadDir);
68
- const filePath = `${downloadDir}${fileInfo.id}.${fileInfo.ext}`;
69
- const processed = await processVideo(filePath);
70
-
71
- let index = 0;
72
- for (const chunk of processed) {
73
- if (chunk.transcription) {
74
- embeddings.push({
75
- id: `${url}-audio-${index}`,
76
- text: chunk.transcription,
77
- metadata: {
78
- url,
79
- description: chunk.frame.description,
80
- timestamp: `${chunk.frame.timestamp}s`,
81
- image: fs.readFileSync(chunk.frame.path, "base64"),
82
- },
83
- });
84
- }
85
-
86
- if (chunk.frame.description) {
87
- embeddings.push({
88
- id: `${url}-video-${index}`,
89
- text: chunk.frame.description,
90
- metadata: {
91
- url,
92
- timestamp: `${chunk.frame.timestamp}s`,
93
- },
94
- });
95
- }
96
-
97
- index++;
98
- }
99
- }
100
-
101
- return embeddings;
102
- }
103
- }