@tyvm/knowhow 0.0.83 → 0.0.85

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 (237) hide show
  1. package/package.json +4 -2
  2. package/src/agents/base/base.ts +72 -62
  3. package/src/agents/index.ts +30 -14
  4. package/src/agents/researcher/researcher.ts +1 -2
  5. package/src/agents/tools/aiClient.ts +48 -0
  6. package/src/agents/tools/list.ts +57 -0
  7. package/src/agents/tools/startAgentTask.ts +3 -1
  8. package/src/chat/CliChatService.ts +20 -4
  9. package/src/chat/modules/AgentModule.ts +399 -357
  10. package/src/chat/modules/CustomCommandsModule.ts +0 -1
  11. package/src/chat/modules/InternalChatModule.ts +18 -2
  12. package/src/chat/modules/RendererModule.ts +109 -0
  13. package/src/chat/modules/SessionsModule.ts +854 -0
  14. package/src/chat/modules/SetupModule.ts +6 -8
  15. package/src/chat/modules/index.ts +1 -0
  16. package/src/chat/renderer/CompactRenderer.ts +209 -0
  17. package/src/chat/renderer/ConsoleRenderer.ts +141 -0
  18. package/src/chat/renderer/FancyRenderer.ts +421 -0
  19. package/src/chat/renderer/index.ts +5 -0
  20. package/src/chat/renderer/loadRenderer.ts +314 -0
  21. package/src/chat/renderer/messagesToRenderEvents.ts +96 -0
  22. package/src/chat/renderer/types.ts +88 -0
  23. package/src/chat/types.ts +5 -0
  24. package/src/chat.ts +69 -5
  25. package/src/cli.ts +24 -5
  26. package/src/clients/index.ts +91 -0
  27. package/src/clients/pricing/google.ts +81 -2
  28. package/src/clients/pricing/openai.ts +68 -0
  29. package/src/config.ts +15 -0
  30. package/src/plugins/AgentsMdPlugin.ts +1 -1
  31. package/src/plugins/GitPlugin.ts +20 -20
  32. package/src/plugins/PluginBase.ts +11 -0
  33. package/src/plugins/SkillsPlugin.ts +150 -0
  34. package/src/plugins/asana.ts +4 -4
  35. package/src/plugins/embedding.ts +3 -5
  36. package/src/plugins/exec.ts +3 -3
  37. package/src/plugins/figma.ts +3 -7
  38. package/src/plugins/github.ts +18 -29
  39. package/src/plugins/jira.ts +2 -2
  40. package/src/plugins/language.ts +4 -4
  41. package/src/plugins/linear.ts +4 -4
  42. package/src/plugins/notion.ts +6 -8
  43. package/src/plugins/plugins.ts +29 -3
  44. package/src/plugins/url.ts +2 -2
  45. package/src/plugins/vim.ts +4 -3
  46. package/src/services/AgentService.ts +17 -0
  47. package/src/services/AgentSyncFs.ts +3 -0
  48. package/src/services/EventService.ts +168 -27
  49. package/src/services/KnowhowClient.ts +1 -0
  50. package/src/services/SessionManager.ts +51 -1
  51. package/src/services/SyncedAgentWatcher.ts +397 -0
  52. package/src/services/SyncerService.ts +147 -0
  53. package/src/services/index.ts +2 -0
  54. package/src/services/modules/index.ts +14 -3
  55. package/src/types.ts +103 -5
  56. package/src/worker.ts +80 -2
  57. package/src/workers/auth/PasskeySetup.ts +185 -0
  58. package/src/workers/auth/WorkerPasskeyAuth.ts +190 -0
  59. package/src/workers/auth/types.ts +58 -0
  60. package/src/workers/tools/getChallenge.ts +33 -0
  61. package/src/workers/tools/index.ts +8 -0
  62. package/src/workers/tools/lock.ts +31 -0
  63. package/src/workers/tools/unlock.ts +116 -0
  64. package/tests/clients/pricing.test.ts +144 -0
  65. package/tests/unit/modules/moduleLoading.test.ts +226 -0
  66. package/tests/unit/plugins/pluginLoading.test.ts +151 -0
  67. package/ts_build/package.json +4 -2
  68. package/ts_build/src/agents/base/base.d.ts +4 -3
  69. package/ts_build/src/agents/base/base.js +54 -30
  70. package/ts_build/src/agents/base/base.js.map +1 -1
  71. package/ts_build/src/agents/index.d.ts +3 -0
  72. package/ts_build/src/agents/index.js +21 -11
  73. package/ts_build/src/agents/index.js.map +1 -1
  74. package/ts_build/src/agents/researcher/researcher.js +1 -1
  75. package/ts_build/src/agents/researcher/researcher.js.map +1 -1
  76. package/ts_build/src/agents/tools/aiClient.d.ts +3 -0
  77. package/ts_build/src/agents/tools/aiClient.js +31 -1
  78. package/ts_build/src/agents/tools/aiClient.js.map +1 -1
  79. package/ts_build/src/agents/tools/list.js +48 -0
  80. package/ts_build/src/agents/tools/list.js.map +1 -1
  81. package/ts_build/src/agents/tools/startAgentTask.js +2 -1
  82. package/ts_build/src/agents/tools/startAgentTask.js.map +1 -1
  83. package/ts_build/src/chat/CliChatService.js +16 -5
  84. package/ts_build/src/chat/CliChatService.js.map +1 -1
  85. package/ts_build/src/chat/modules/AgentModule.d.ts +34 -17
  86. package/ts_build/src/chat/modules/AgentModule.js +248 -258
  87. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  88. package/ts_build/src/chat/modules/CustomCommandsModule.js.map +1 -1
  89. package/ts_build/src/chat/modules/InternalChatModule.d.ts +3 -0
  90. package/ts_build/src/chat/modules/InternalChatModule.js +16 -1
  91. package/ts_build/src/chat/modules/InternalChatModule.js.map +1 -1
  92. package/ts_build/src/chat/modules/RendererModule.d.ts +16 -0
  93. package/ts_build/src/chat/modules/RendererModule.js +76 -0
  94. package/ts_build/src/chat/modules/RendererModule.js.map +1 -0
  95. package/ts_build/src/chat/modules/SessionsModule.d.ts +33 -0
  96. package/ts_build/src/chat/modules/SessionsModule.js +582 -0
  97. package/ts_build/src/chat/modules/SessionsModule.js.map +1 -0
  98. package/ts_build/src/chat/modules/SetupModule.d.ts +3 -3
  99. package/ts_build/src/chat/modules/SetupModule.js +4 -6
  100. package/ts_build/src/chat/modules/SetupModule.js.map +1 -1
  101. package/ts_build/src/chat/modules/index.d.ts +1 -0
  102. package/ts_build/src/chat/modules/index.js +3 -1
  103. package/ts_build/src/chat/modules/index.js.map +1 -1
  104. package/ts_build/src/chat/renderer/CompactRenderer.d.ts +23 -0
  105. package/ts_build/src/chat/renderer/CompactRenderer.js +167 -0
  106. package/ts_build/src/chat/renderer/CompactRenderer.js.map +1 -0
  107. package/ts_build/src/chat/renderer/ConsoleRenderer.d.ts +22 -0
  108. package/ts_build/src/chat/renderer/ConsoleRenderer.js +110 -0
  109. package/ts_build/src/chat/renderer/ConsoleRenderer.js.map +1 -0
  110. package/ts_build/src/chat/renderer/FancyRenderer.d.ts +23 -0
  111. package/ts_build/src/chat/renderer/FancyRenderer.js +328 -0
  112. package/ts_build/src/chat/renderer/FancyRenderer.js.map +1 -0
  113. package/ts_build/src/chat/renderer/index.d.ts +5 -0
  114. package/ts_build/src/chat/renderer/index.js +29 -0
  115. package/ts_build/src/chat/renderer/index.js.map +1 -0
  116. package/ts_build/src/chat/renderer/loadRenderer.d.ts +4 -0
  117. package/ts_build/src/chat/renderer/loadRenderer.js +246 -0
  118. package/ts_build/src/chat/renderer/loadRenderer.js.map +1 -0
  119. package/ts_build/src/chat/renderer/messagesToRenderEvents.d.ts +15 -0
  120. package/ts_build/src/chat/renderer/messagesToRenderEvents.js +72 -0
  121. package/ts_build/src/chat/renderer/messagesToRenderEvents.js.map +1 -0
  122. package/ts_build/src/chat/renderer/types.d.ts +75 -0
  123. package/ts_build/src/chat/renderer/types.js +3 -0
  124. package/ts_build/src/chat/renderer/types.js.map +1 -0
  125. package/ts_build/src/chat/types.d.ts +5 -0
  126. package/ts_build/src/chat.js +46 -4
  127. package/ts_build/src/chat.js.map +1 -1
  128. package/ts_build/src/cli.js +18 -5
  129. package/ts_build/src/cli.js.map +1 -1
  130. package/ts_build/src/clients/gemini.d.ts +10 -10
  131. package/ts_build/src/clients/index.d.ts +10 -0
  132. package/ts_build/src/clients/index.js +58 -0
  133. package/ts_build/src/clients/index.js.map +1 -1
  134. package/ts_build/src/clients/pricing/google.d.ts +10 -10
  135. package/ts_build/src/clients/pricing/google.js +74 -2
  136. package/ts_build/src/clients/pricing/google.js.map +1 -1
  137. package/ts_build/src/clients/pricing/openai.js +65 -0
  138. package/ts_build/src/clients/pricing/openai.js.map +1 -1
  139. package/ts_build/src/config.d.ts +1 -0
  140. package/ts_build/src/config.js +17 -1
  141. package/ts_build/src/config.js.map +1 -1
  142. package/ts_build/src/plugins/AgentsMdPlugin.js +1 -1
  143. package/ts_build/src/plugins/AgentsMdPlugin.js.map +1 -1
  144. package/ts_build/src/plugins/GitPlugin.js +20 -20
  145. package/ts_build/src/plugins/GitPlugin.js.map +1 -1
  146. package/ts_build/src/plugins/PluginBase.d.ts +1 -0
  147. package/ts_build/src/plugins/PluginBase.js +13 -0
  148. package/ts_build/src/plugins/PluginBase.js.map +1 -1
  149. package/ts_build/src/plugins/SkillsPlugin.d.ts +13 -0
  150. package/ts_build/src/plugins/SkillsPlugin.js +149 -0
  151. package/ts_build/src/plugins/SkillsPlugin.js.map +1 -0
  152. package/ts_build/src/plugins/asana.js +4 -4
  153. package/ts_build/src/plugins/asana.js.map +1 -1
  154. package/ts_build/src/plugins/embedding.js +3 -3
  155. package/ts_build/src/plugins/embedding.js.map +1 -1
  156. package/ts_build/src/plugins/exec.js +3 -3
  157. package/ts_build/src/plugins/exec.js.map +1 -1
  158. package/ts_build/src/plugins/figma.js +3 -3
  159. package/ts_build/src/plugins/figma.js.map +1 -1
  160. package/ts_build/src/plugins/github.js +18 -18
  161. package/ts_build/src/plugins/github.js.map +1 -1
  162. package/ts_build/src/plugins/jira.js +2 -2
  163. package/ts_build/src/plugins/jira.js.map +1 -1
  164. package/ts_build/src/plugins/language.js +4 -4
  165. package/ts_build/src/plugins/language.js.map +1 -1
  166. package/ts_build/src/plugins/linear.js +4 -4
  167. package/ts_build/src/plugins/linear.js.map +1 -1
  168. package/ts_build/src/plugins/notion.js +6 -6
  169. package/ts_build/src/plugins/notion.js.map +1 -1
  170. package/ts_build/src/plugins/plugins.d.ts +3 -0
  171. package/ts_build/src/plugins/plugins.js +18 -3
  172. package/ts_build/src/plugins/plugins.js.map +1 -1
  173. package/ts_build/src/plugins/url.js +2 -2
  174. package/ts_build/src/plugins/url.js.map +1 -1
  175. package/ts_build/src/plugins/vim.js +2 -2
  176. package/ts_build/src/plugins/vim.js.map +1 -1
  177. package/ts_build/src/services/AgentService.d.ts +3 -0
  178. package/ts_build/src/services/AgentService.js +7 -0
  179. package/ts_build/src/services/AgentService.js.map +1 -1
  180. package/ts_build/src/services/AgentSyncFs.d.ts +1 -0
  181. package/ts_build/src/services/AgentSyncFs.js +2 -0
  182. package/ts_build/src/services/AgentSyncFs.js.map +1 -1
  183. package/ts_build/src/services/EventService.d.ts +25 -2
  184. package/ts_build/src/services/EventService.js +92 -14
  185. package/ts_build/src/services/EventService.js.map +1 -1
  186. package/ts_build/src/services/KnowhowClient.d.ts +1 -0
  187. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  188. package/ts_build/src/services/SessionManager.d.ts +6 -0
  189. package/ts_build/src/services/SessionManager.js +39 -1
  190. package/ts_build/src/services/SessionManager.js.map +1 -1
  191. package/ts_build/src/services/SyncedAgentWatcher.d.ts +101 -0
  192. package/ts_build/src/services/SyncedAgentWatcher.js +312 -0
  193. package/ts_build/src/services/SyncedAgentWatcher.js.map +1 -0
  194. package/ts_build/src/services/SyncerService.d.ts +30 -0
  195. package/ts_build/src/services/SyncerService.js +72 -0
  196. package/ts_build/src/services/SyncerService.js.map +1 -0
  197. package/ts_build/src/services/index.d.ts +2 -0
  198. package/ts_build/src/services/index.js +2 -0
  199. package/ts_build/src/services/index.js.map +1 -1
  200. package/ts_build/src/services/modules/index.js +10 -2
  201. package/ts_build/src/services/modules/index.js.map +1 -1
  202. package/ts_build/src/types.d.ts +51 -2
  203. package/ts_build/src/types.js +73 -5
  204. package/ts_build/src/types.js.map +1 -1
  205. package/ts_build/src/worker.d.ts +2 -0
  206. package/ts_build/src/worker.js +59 -4
  207. package/ts_build/src/worker.js.map +1 -1
  208. package/ts_build/src/workers/auth/PasskeySetup.d.ts +10 -0
  209. package/ts_build/src/workers/auth/PasskeySetup.js +131 -0
  210. package/ts_build/src/workers/auth/PasskeySetup.js.map +1 -0
  211. package/ts_build/src/workers/auth/WorkerPasskeyAuth.d.ts +35 -0
  212. package/ts_build/src/workers/auth/WorkerPasskeyAuth.js +129 -0
  213. package/ts_build/src/workers/auth/WorkerPasskeyAuth.js.map +1 -0
  214. package/ts_build/src/workers/auth/types.d.ts +36 -0
  215. package/ts_build/src/workers/auth/types.js +3 -0
  216. package/ts_build/src/workers/auth/types.js.map +1 -0
  217. package/ts_build/src/workers/tools/getChallenge.d.ts +9 -0
  218. package/ts_build/src/workers/tools/getChallenge.js +27 -0
  219. package/ts_build/src/workers/tools/getChallenge.js.map +1 -0
  220. package/ts_build/src/workers/tools/index.d.ts +6 -0
  221. package/ts_build/src/workers/tools/index.js +10 -0
  222. package/ts_build/src/workers/tools/index.js.map +1 -1
  223. package/ts_build/src/workers/tools/lock.d.ts +9 -0
  224. package/ts_build/src/workers/tools/lock.js +27 -0
  225. package/ts_build/src/workers/tools/lock.js.map +1 -0
  226. package/ts_build/src/workers/tools/unlock.d.ts +18 -0
  227. package/ts_build/src/workers/tools/unlock.js +78 -0
  228. package/ts_build/src/workers/tools/unlock.js.map +1 -0
  229. package/ts_build/tests/clients/pricing.test.d.ts +1 -0
  230. package/ts_build/tests/clients/pricing.test.js +90 -0
  231. package/ts_build/tests/clients/pricing.test.js.map +1 -0
  232. package/ts_build/tests/unit/modules/moduleLoading.test.d.ts +1 -0
  233. package/ts_build/tests/unit/modules/moduleLoading.test.js +187 -0
  234. package/ts_build/tests/unit/modules/moduleLoading.test.js.map +1 -0
  235. package/ts_build/tests/unit/plugins/pluginLoading.test.d.ts +1 -0
  236. package/ts_build/tests/unit/plugins/pluginLoading.test.js +123 -0
  237. package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -0
package/src/cli.ts CHANGED
@@ -35,6 +35,7 @@ import { BaseAgent } from "./agents/base/base";
35
35
  import { AskModule } from "./chat/modules/AskModule";
36
36
  import { SearchModule } from "./chat/modules/SearchModule";
37
37
  import { AgentModule } from "./chat/modules/AgentModule";
38
+ import { SessionsModule } from "./chat/modules/SessionsModule";
38
39
  import { readPromptFile } from "./ai";
39
40
  import { SetupModule } from "./chat/modules/SetupModule";
40
41
  import { CliChatService } from "./chat/CliChatService";
@@ -48,22 +49,32 @@ async function setupServices() {
48
49
  ...OldTools.getContext(),
49
50
  });
50
51
 
51
- const { Researcher, Developer, Patcher, Setup } = agents({
52
+ // Build the AgentContext with the fully-populated LazyToolsService so every
53
+ // agent created (including those in setupAgent) gets all tools registered.
54
+ const agentContext: import("./agents/base/base").AgentContext = {
52
55
  ...services(),
53
56
  Tools,
57
+ };
58
+
59
+ const { Researcher, Developer, Patcher, Setup } = agents({
60
+ ...agentContext,
54
61
  });
55
62
 
56
63
  Agents.registerAgent(Researcher);
57
64
  Agents.registerAgent(Patcher);
58
65
  Agents.registerAgent(Developer);
59
66
  Agents.registerAgent(Setup);
60
- Agents.loadAgentsFromConfig(services());
67
+ Agents.loadAgentsFromConfig(agentContext);
61
68
 
62
69
  Tools.defineTools(includedTools, allTools);
63
70
 
64
71
  // Add Mcp service to tool context directly so MCP management tools can access it
65
72
  Tools.addContext("Mcp", Mcp);
66
73
 
74
+ // Store the fully-wired AgentContext on AgentService so AgentModule.setupAgent
75
+ // can retrieve it when creating fresh agent instances via createAgent().
76
+ Agents.setAgentContext(agentContext);
77
+
67
78
  console.log("🔌 Connecting to MCP...");
68
79
  await Mcp.connectToConfigured(Tools);
69
80
  console.log("Connecting to clients...");
@@ -322,7 +333,9 @@ async function main() {
322
333
  .action(async (options) => {
323
334
  try {
324
335
  await setupServices();
325
- const setupModule = new SetupModule();
336
+ const agentModule = new AgentModule();
337
+ await agentModule.initialize(chatService);
338
+ const setupModule = new SetupModule(agentModule);
326
339
  await setupModule.initialize(chatService);
327
340
  await setupModule.handleSetupCommand([]);
328
341
  } catch (error) {
@@ -367,11 +380,15 @@ async function main() {
367
380
  program
368
381
  .command("sessions")
369
382
  .description("Manage agent sessions from CLI")
370
- .action(async () => {
383
+ .option("--all", "Show all historical sessions (default: current process only)")
384
+ .option("--csv", "Output sessions as CSV")
385
+ .action(async (options) => {
371
386
  try {
372
387
  const agentModule = new AgentModule();
373
388
  await agentModule.initialize(chatService);
374
- await agentModule.logSessionTable();
389
+ const sessionsModule = new SessionsModule(agentModule);
390
+ await sessionsModule.initialize(chatService);
391
+ await sessionsModule.logSessionTable(options.all || false, options.csv || false, true);
375
392
  } catch (error) {
376
393
  console.error("Error listing sessions:", error);
377
394
  process.exit(1);
@@ -394,6 +411,8 @@ async function main() {
394
411
  "--no-sandbox",
395
412
  "Run worker directly on host (disable sandbox mode)"
396
413
  )
414
+ .option("--passkey", "Set up passkey authentication for this worker")
415
+ .option("--passkey-reset", "Remove passkey authentication requirement")
397
416
  .action(async (options) => {
398
417
  await setupServices();
399
418
  await worker(options);
@@ -25,10 +25,23 @@ import { GenericGeminiClient } from "./gemini";
25
25
  import { HttpClient } from "./http";
26
26
  import { EmbeddingModels, Models } from "../types";
27
27
  import { getConfig } from "../config";
28
+ import {
29
+ GoogleImageModels,
30
+ GoogleVideoModels,
31
+ GoogleTTSModels,
32
+ OpenAiImageModels,
33
+ OpenAiVideoModels,
34
+ OpenAiTTSModels,
35
+ OpenAiTranscriptionModels,
36
+ XaiImageModels,
37
+ XaiVideoModels,
38
+ } from "../types";
28
39
  import { GenericXAIClient } from "./xai";
29
40
  import { KnowhowGenericClient } from "./knowhow";
30
41
  import { loadKnowhowJwt } from "../services/KnowhowClient";
31
42
 
43
+ export type ModelModality = "completion" | "embedding" | "image" | "audio" | "video";
44
+
32
45
  function envCheck(key: string): boolean {
33
46
  const value = process.env[key];
34
47
  if (!value) {
@@ -85,6 +98,39 @@ export class AIClient {
85
98
  ...(envCheck("XAI_API_KEY") && { xai: this.completionModels.xai }),
86
99
  };
87
100
 
101
+ imageModels: Record<string, string[]> = {
102
+ ...(envCheck("OPENAI_KEY") && {
103
+ openai: OpenAiImageModels,
104
+ }),
105
+ ...(envCheck("GEMINI_API_KEY") && {
106
+ google: GoogleImageModels,
107
+ }),
108
+ ...(envCheck("XAI_API_KEY") && {
109
+ xai: XaiImageModels,
110
+ }),
111
+ };
112
+
113
+ audioModels: Record<string, string[]> = {
114
+ ...(envCheck("OPENAI_KEY") && {
115
+ openai: [...OpenAiTTSModels, ...OpenAiTranscriptionModels],
116
+ }),
117
+ ...(envCheck("GEMINI_API_KEY") && {
118
+ google: GoogleTTSModels,
119
+ }),
120
+ };
121
+
122
+ videoModels: Record<string, string[]> = {
123
+ ...(envCheck("OPENAI_KEY") && {
124
+ openai: OpenAiVideoModels,
125
+ }),
126
+ ...(envCheck("GEMINI_API_KEY") && {
127
+ google: GoogleVideoModels,
128
+ }),
129
+ ...(envCheck("XAI_API_KEY") && {
130
+ xai: XaiVideoModels,
131
+ }),
132
+ };
133
+
88
134
  getClient(provider: string, model?: string) {
89
135
  if (provider && !model) {
90
136
  return { client: this.clients[provider], provider, model: undefined };
@@ -215,6 +261,39 @@ export class AIClient {
215
261
  );
216
262
  }
217
263
 
264
+ registerImageModels(provider: string, models: string[]) {
265
+ const currentModels = this.clientModels[provider] || [];
266
+ const currentImageModels = this.imageModels[provider] || [];
267
+ this.clientModels[provider] = Array.from<string>(
268
+ new Set(currentModels.concat(models))
269
+ );
270
+ this.imageModels[provider] = Array.from<string>(
271
+ new Set(currentImageModels.concat(models))
272
+ );
273
+ }
274
+
275
+ registerAudioModels(provider: string, models: string[]) {
276
+ const currentModels = this.clientModels[provider] || [];
277
+ const currentAudioModels = this.audioModels[provider] || [];
278
+ this.clientModels[provider] = Array.from<string>(
279
+ new Set(currentModels.concat(models))
280
+ );
281
+ this.audioModels[provider] = Array.from<string>(
282
+ new Set(currentAudioModels.concat(models))
283
+ );
284
+ }
285
+
286
+ registerVideoModels(provider: string, models: string[]) {
287
+ const currentModels = this.clientModels[provider] || [];
288
+ const currentVideoModels = this.videoModels[provider] || [];
289
+ this.clientModels[provider] = Array.from<string>(
290
+ new Set(currentModels.concat(models))
291
+ );
292
+ this.videoModels[provider] = Array.from<string>(
293
+ new Set(currentVideoModels.concat(models))
294
+ );
295
+ }
296
+
218
297
  providerHasModel(provider: string, model: string): boolean {
219
298
  const models = this.clientModels[provider];
220
299
  if (!models) return false;
@@ -517,6 +596,18 @@ export class AIClient {
517
596
  listAllProviders() {
518
597
  return Object.keys(this.clientModels);
519
598
  }
599
+
600
+ listAllImageModels() {
601
+ return this.imageModels;
602
+ }
603
+
604
+ listAllAudioModels() {
605
+ return this.audioModels;
606
+ }
607
+
608
+ listAllVideoModels() {
609
+ return this.videoModels;
610
+ }
520
611
  }
521
612
 
522
613
  export const Clients = new AIClient();
@@ -1,7 +1,8 @@
1
1
  import { Models, EmbeddingModels } from "../../types";
2
2
 
3
3
  export const GeminiTextPricing = {
4
- [Models.google.Gemini_3_Preview]: {
4
+ // Gemini 3.x
5
+ [Models.google.Gemini_31_Pro_Preview]: {
5
6
  input: 2,
6
7
  input_gt_200k: 4,
7
8
  output: 12,
@@ -9,6 +10,45 @@ export const GeminiTextPricing = {
9
10
  context_caching: 0.2,
10
11
  context_caching_gt_200k: 0.4,
11
12
  },
13
+ [Models.google.Gemini_31_Flash_Image_Preview]: {
14
+ input: 0.5,
15
+ output: 3,
16
+ image_generation: 0.045, // per 0.5K image
17
+ },
18
+ [Models.google.Gemini_31_Flash_Lite_Preview]: {
19
+ input: 0.25,
20
+ output: 1.5,
21
+ context_caching: 0.025,
22
+ },
23
+ [Models.google.Gemini_3_Flash_Preview]: {
24
+ input: 0.5,
25
+ output: 3.0,
26
+ context_caching: 0.05,
27
+ },
28
+ [Models.google.Gemini_3_Pro_Image_Preview]: {
29
+ input: 2,
30
+ output: 12,
31
+ image_generation: 0.134, // per 1K/2K image
32
+ },
33
+ // Gemini 2.5
34
+ [Models.google.Gemini_25_Pro]: {
35
+ input: 1.25,
36
+ input_gt_200k: 2.5,
37
+ output: 10.0,
38
+ output_gt_200k: 15.0,
39
+ context_caching: 0.125,
40
+ context_caching_gt_200k: 0.25,
41
+ },
42
+ [Models.google.Gemini_25_Flash]: {
43
+ input: 0.3,
44
+ output: 2.5,
45
+ context_caching: 0.03,
46
+ },
47
+ [Models.google.Gemini_25_Flash_Lite]: {
48
+ input: 0.1,
49
+ output: 0.4,
50
+ context_caching: 0.01,
51
+ },
12
52
  [Models.google.Gemini_25_Flash_Preview]: {
13
53
  input: 0.3,
14
54
  output: 2.5,
@@ -23,6 +63,19 @@ export const GeminiTextPricing = {
23
63
  context_caching: 0.125,
24
64
  context_caching_gt_200k: 0.25,
25
65
  },
66
+ [Models.google.Gemini_25_Flash_Image]: {
67
+ input: 0.3,
68
+ output: 0.039, // per image ($30/1M tokens, 1290 tokens per image)
69
+ },
70
+ [Models.google.Gemini_25_Flash_TTS]: {
71
+ input: 0.5,
72
+ output: 10.0,
73
+ },
74
+ [Models.google.Gemini_25_Pro_TTS]: {
75
+ input: 1.0,
76
+ output: 20.0,
77
+ },
78
+ // Gemini 2.0 (deprecated)
26
79
  [Models.google.Gemini_20_Flash]: {
27
80
  input: 0.1,
28
81
  output: 0.4,
@@ -37,6 +90,7 @@ export const GeminiTextPricing = {
37
90
  input: 0.075,
38
91
  output: 0.3,
39
92
  },
93
+ // Gemini 1.5 (legacy)
40
94
  [Models.google.Gemini_15_Flash]: {
41
95
  input: 0.075,
42
96
  output: 0.3,
@@ -52,14 +106,39 @@ export const GeminiTextPricing = {
52
106
  output: 5.0,
53
107
  context_caching: 0.3125,
54
108
  },
109
+ // Image generation
55
110
  [Models.google.Imagen_3]: {
56
- image_generation: 0.03,
111
+ image_generation: 0.04, // Imagen 4 Standard: $0.04/image
112
+ },
113
+ [Models.google.Imagen_4_Fast]: {
114
+ image_generation: 0.02, // $0.02/image
57
115
  },
116
+ [Models.google.Imagen_4_Ultra]: {
117
+ image_generation: 0.06, // $0.06/image
118
+ },
119
+ // Video generation
58
120
  [Models.google.Veo_2]: {
59
121
  video_generation: 0.35,
60
122
  },
123
+ [Models.google.Veo_3]: {
124
+ video_generation: 0.4, // $0.40/second
125
+ },
126
+ [Models.google.Veo_3_Fast]: {
127
+ video_generation: 0.15, // $0.15/second
128
+ },
129
+ [Models.google.Veo_3_1]: {
130
+ video_generation: 0.4, // $0.40/second (720p/1080p)
131
+ },
132
+ [Models.google.Veo_3_1_Fast]: {
133
+ video_generation: 0.15, // $0.15/second
134
+ },
135
+ // Embeddings
61
136
  [EmbeddingModels.google.Gemini_Embedding]: {
62
137
  input: 0, // Free of charge
63
138
  output: 0, // Free of charge
64
139
  },
140
+ [EmbeddingModels.google.Gemini_Embedding_001]: {
141
+ input: 0.15,
142
+ output: 0,
143
+ },
65
144
  };
@@ -1,6 +1,36 @@
1
1
  import { Models, EmbeddingModels } from "../../types";
2
2
 
3
3
  export const OpenAiTextPricing = {
4
+ [Models.openai.GPT_54]: {
5
+ input: 2.5,
6
+ cached_input: 0.25,
7
+ output: 15.0,
8
+ },
9
+ [Models.openai.GPT_54_Mini]: {
10
+ input: 0.75,
11
+ cached_input: 0.075,
12
+ output: 4.5,
13
+ },
14
+ [Models.openai.GPT_54_Nano]: {
15
+ input: 0.2,
16
+ cached_input: 0.02,
17
+ output: 1.25,
18
+ },
19
+ [Models.openai.GPT_54_Pro]: {
20
+ input: 30.0,
21
+ cached_input: 0,
22
+ output: 180.0,
23
+ },
24
+ [Models.openai.GPT_53_Chat]: {
25
+ input: 1.75,
26
+ cached_input: 0.175,
27
+ output: 14.0,
28
+ },
29
+ [Models.openai.GPT_53_Codex]: {
30
+ input: 1.75,
31
+ cached_input: 0.175,
32
+ output: 14.0,
33
+ },
4
34
  [Models.openai.GPT_4o]: {
5
35
  input: 2.5,
6
36
  cached_input: 1.25,
@@ -76,6 +106,11 @@ export const OpenAiTextPricing = {
76
106
  cached_input: 0.5,
77
107
  output: 8.0,
78
108
  },
109
+ [Models.openai.o3_Pro]: {
110
+ input: 20.0,
111
+ cached_input: 0,
112
+ output: 80.0,
113
+ },
79
114
  [Models.openai.o4_Mini]: {
80
115
  input: 1.1,
81
116
  cached_input: 0.275,
@@ -131,4 +166,37 @@ export const OpenAiTextPricing = {
131
166
  cached_input: 0,
132
167
  output: 0,
133
168
  },
169
+ // New realtime models
170
+ [Models.openai.GPT_Realtime_15]: {
171
+ input: 4.0,
172
+ cached_input: 0.4,
173
+ output: 16.0,
174
+ },
175
+ [Models.openai.GPT_Realtime_Mini]: {
176
+ input: 0.6,
177
+ cached_input: 0.06,
178
+ output: 2.4,
179
+ },
180
+ // New image models (text token pricing)
181
+ [Models.openai.GPT_Image_15]: {
182
+ input: 5.0,
183
+ cached_input: 1.25,
184
+ output: 10.0,
185
+ },
186
+ [Models.openai.GPT_Image_1_Mini]: {
187
+ input: 2.0,
188
+ cached_input: 0.2,
189
+ output: 0,
190
+ },
191
+ // New transcription models
192
+ [Models.openai.GPT_4o_Transcribe]: {
193
+ input: 2.5,
194
+ cached_input: 0,
195
+ output: 10.0,
196
+ },
197
+ [Models.openai.GPT_4o_Mini_Transcribe]: {
198
+ input: 1.25,
199
+ cached_input: 0,
200
+ output: 5.0,
201
+ },
134
202
  };
package/src/config.ts CHANGED
@@ -262,6 +262,21 @@ export async function getConfig() {
262
262
  }
263
263
  }
264
264
 
265
+ export async function getGlobalConfig(): Promise<Config> {
266
+ const globalConfigDir = getGlobalConfigDir();
267
+ const globalConfigPath = path.join(globalConfigDir, "knowhow.json");
268
+ if (!fs.existsSync(globalConfigPath)) {
269
+ return {} as Config;
270
+ }
271
+ try {
272
+ const config = await readFile(globalConfigPath, "utf8");
273
+ return JSON.parse(config) as Config;
274
+ } catch (error) {
275
+ console.warn("Failed to load global knowhow config:", error);
276
+ return {} as Config;
277
+ }
278
+ }
279
+
265
280
  export async function migrateConfig() {
266
281
  // Apply migrations, used to keep config structure up to date.
267
282
  if (!fs.existsSync(".knowhow/knowhow.json")) {
@@ -98,7 +98,7 @@ export class AgentsMdPlugin extends PluginBase implements Plugin {
98
98
 
99
99
  events.emit("agent:msg", alertMessage);
100
100
  } catch (error) {
101
- console.error("AGENTS-MD PLUGIN: Error handling file event:", error);
101
+ this.log("AGENTS-MD PLUGIN: Error handling file event: " + error, "error");
102
102
  }
103
103
  }
104
104
 
@@ -110,7 +110,7 @@ Your modifications are automatically tracked separately and won't affect the use
110
110
 
111
111
  await this.setBranch("main");
112
112
  } catch (error) {
113
- console.error("Failed to initialize .knowhow git repository:", error);
113
+ this.log(`Failed to initialize .knowhow git repository: ${error}`, "error");
114
114
  }
115
115
  }
116
116
 
@@ -144,7 +144,7 @@ Your modifications are automatically tracked separately and won't affect the use
144
144
  try {
145
145
  return this.gitCommand(command, options);
146
146
  } catch (error) {
147
- console.warn(`Safe git command failed: ${command}`, error);
147
+ this.log(`Safe git command failed: ${command} - ${error}`, "warn");
148
148
  return null;
149
149
  }
150
150
  }
@@ -235,7 +235,7 @@ Your modifications are automatically tracked separately and won't affect the use
235
235
 
236
236
  // Get the current HEAD commit hash from the actual repo (if it exists)
237
237
  const actualRepoHash = this.getRepoHash();
238
- console.log(`GitPlugin: Current branch is ${this.getCurrentBranch()}`);
238
+ this.log(`Current branch is ${this.getCurrentBranch()}`);
239
239
 
240
240
  // First, handle any uncommitted changes on the current branch
241
241
  const hasChanges = await this.hasChanges();
@@ -246,7 +246,7 @@ Your modifications are automatically tracked separately and won't affect the use
246
246
  : `sync ${new Date().toISOString()}`;
247
247
  await this.commitAll(message);
248
248
  } catch (error) {
249
- console.error("Failed to commit uncommitted changes:", error);
249
+ this.log(`Failed to commit uncommitted changes: ${error}`, "error");
250
250
  }
251
251
  }
252
252
 
@@ -259,7 +259,7 @@ Your modifications are automatically tracked separately and won't affect the use
259
259
 
260
260
  await this.setBranch("main");
261
261
  } catch (error) {
262
- console.error("Failed to ensure clean state:", error);
262
+ this.log(`Failed to ensure clean state: ${error}`, "error");
263
263
  }
264
264
  }
265
265
 
@@ -288,7 +288,7 @@ Your modifications are automatically tracked separately and won't affect the use
288
288
  this.gitCommand(`checkout -b ${branchName}`);
289
289
  }
290
290
  } catch (error) {
291
- console.error(`GitPlugin: Failed to set branch ${branchName}:`);
291
+ this.log(`Failed to set branch ${branchName}`, "error");
292
292
  }
293
293
  }
294
294
 
@@ -298,7 +298,7 @@ Your modifications are automatically tracked separately and won't affect the use
298
298
  try {
299
299
  this.gitCommand(`checkout -b ${branchName}`);
300
300
  } catch (error) {
301
- console.error(`GitPlugin: Failed to create branch ${branchName}:`);
301
+ this.log(`Failed to create branch ${branchName}`, "error");
302
302
  }
303
303
  }
304
304
 
@@ -317,7 +317,7 @@ Your modifications are automatically tracked separately and won't affect the use
317
317
  try {
318
318
  this.gitCommand(`add "${file}"`);
319
319
  } catch (error) {
320
- console.warn(`Failed to add file ${file}:`, error);
320
+ this.log(`Failed to add file ${file}: ${error}`, "warn");
321
321
  }
322
322
  }
323
323
  } else {
@@ -339,7 +339,7 @@ Your modifications are automatically tracked separately and won't affect the use
339
339
  this.gitCommand("add -A");
340
340
  await this.commitWithEvents(message);
341
341
  } catch (error) {
342
- console.error("Failed to commit all changes:", error);
342
+ this.log(`Failed to commit all changes: ${error}`, "error");
343
343
  }
344
344
  }
345
345
 
@@ -389,7 +389,7 @@ Your modifications are automatically tracked separately and won't affect the use
389
389
  `
390
390
  );
391
391
  } catch (error) {
392
- console.error("Failed to commit with events:", error);
392
+ this.log(`Failed to commit with events: ${error}`, "error");
393
393
  }
394
394
  }
395
395
 
@@ -402,7 +402,7 @@ Your modifications are automatically tracked separately and won't affect the use
402
402
  try {
403
403
  this.gitCommand('commit --allow-empty -m "Initial empty commit"');
404
404
  } catch (error) {
405
- console.warn("Could not create initial commit:", error);
405
+ this.log(`Could not create initial commit: ${error}`, "warn");
406
406
  }
407
407
  }
408
408
  }
@@ -424,7 +424,7 @@ Your modifications are automatically tracked separately and won't affect the use
424
424
 
425
425
  await this.commitAll(message);
426
426
  } catch (error) {
427
- console.error("Auto-commit failed:", error);
427
+ this.log(`Auto-commit failed: ${error}`, "error");
428
428
  }
429
429
  }
430
430
 
@@ -455,9 +455,9 @@ Your modifications are automatically tracked separately and won't affect the use
455
455
  );
456
456
  }
457
457
 
458
- console.log(`Created new task branch: ${branchName}`);
458
+ this.log(`Created new task branch: ${branchName}`);
459
459
  } catch (error) {
460
- console.error("Failed to handle new task:", error);
460
+ this.log(`Failed to handle new task: ${error}`, "error");
461
461
  }
462
462
  }
463
463
 
@@ -466,7 +466,7 @@ Your modifications are automatically tracked separately and won't affect the use
466
466
 
467
467
  try {
468
468
  if (!this.currentTask) {
469
- console.warn("No tasks in progress to complete");
469
+ this.log("No tasks in progress to complete", "warn");
470
470
  return;
471
471
  }
472
472
 
@@ -488,7 +488,7 @@ Your modifications are automatically tracked separately and won't affect the use
488
488
  // Clear current task
489
489
  this.currentTask = null;
490
490
  } catch (error) {
491
- console.error("Failed to handle task completion:", error);
491
+ this.log(`Failed to handle task completion: ${error}`, "error");
492
492
  }
493
493
  }
494
494
 
@@ -523,9 +523,9 @@ Your modifications are automatically tracked separately and won't affect the use
523
523
  try {
524
524
  const noteMessage = `[Build Stable] No linting issues found on branch: ${this.getCurrentBranch()}`;
525
525
  this.gitCommand(`notes add -f -m "${noteMessage}" ${commitHash}`);
526
- console.log(`GitPlugin: Marked commit ${commitHash} as build stable`);
526
+ this.log(`Marked commit ${commitHash} as build stable`);
527
527
  } catch (error) {
528
- console.warn(`GitPlugin: Failed to add git note for commit ${commitHash}:`, error);
528
+ this.log(`Failed to add git note for commit ${commitHash}: ${error}`, "warn");
529
529
  }
530
530
  }
531
531
 
@@ -559,7 +559,7 @@ Your modifications are automatically tracked separately and won't affect the use
559
559
  .map((line) => line.replace(/^\*?\s*/, "").trim())
560
560
  .filter((line) => line.length > 0);
561
561
  } catch (error) {
562
- console.error("Error getting branches:", error);
562
+ this.log(`Error getting branches: ${error}`, "error");
563
563
  return [];
564
564
  }
565
565
  }
@@ -592,7 +592,7 @@ Your modifications are automatically tracked separately and won't affect the use
592
592
  this.commitAll(message);
593
593
  }
594
594
  } catch (error) {
595
- console.error(`Failed to merge ${branchName}:`, error);
595
+ this.log(`Failed to merge ${branchName}: ${error}`, "error");
596
596
  }
597
597
  }
598
598
  }
@@ -43,6 +43,17 @@ export abstract class PluginBase implements Plugin {
43
43
  return true; // subclasses override if needed
44
44
  }
45
45
 
46
+ protected log(message: string, level: "info" | "warn" | "error" = "info"): void {
47
+ if (this.context.Events) {
48
+ this.context.Events.log(this.meta.name, message, level);
49
+ } else {
50
+ // Fallback to console if no Events service
51
+ if (level === "error") console.error(`[${this.meta.name}] ${message}`);
52
+ else if (level === "warn") console.warn(`[${this.meta.name}] ${message}`);
53
+ else console.log(`[${this.meta.name}] ${message}`);
54
+ }
55
+ }
56
+
46
57
  /* ------------------------------------------------------------------ */
47
58
  /** Default callMany implementation - delegates to call ------------ */
48
59
  /* ------------------------------------------------------------------ */