@tyvm/knowhow 0.0.97 → 0.0.99

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 (84) hide show
  1. package/package.json +1 -1
  2. package/src/agents/base/base.ts +12 -4
  3. package/src/agents/patcher/patcher.ts +1 -1
  4. package/src/agents/tools/list.ts +1 -0
  5. package/src/chat/modules/AgentModule.ts +24 -22
  6. package/src/chat/modules/SessionsModule.ts +1 -3
  7. package/src/chat/modules/SystemModule.ts +23 -8
  8. package/src/cli.ts +17 -0
  9. package/src/clients/anthropic.ts +10 -4
  10. package/src/clients/gemini.ts +23 -5
  11. package/src/clients/http.ts +5 -3
  12. package/src/clients/index.ts +261 -139
  13. package/src/clients/knowhow.ts +15 -4
  14. package/src/clients/openai.ts +213 -10
  15. package/src/clients/types.ts +7 -1
  16. package/src/clients/xai.ts +13 -6
  17. package/src/cloudWorker.ts +314 -0
  18. package/src/config.ts +9 -1
  19. package/src/processors/TokenCompressor.ts +8 -1
  20. package/src/services/KnowhowClient.ts +56 -12
  21. package/src/services/LazyToolsService.ts +15 -14
  22. package/src/services/Tools.ts +10 -1
  23. package/src/types.ts +11 -2
  24. package/src/utils/InputQueueManager.ts +131 -20
  25. package/test-ai-completion.ts +39 -0
  26. package/test-mcp-args.ts +71 -0
  27. package/test-tools-service.ts +45 -0
  28. package/ts_build/package.json +1 -1
  29. package/ts_build/src/agents/base/base.js +8 -2
  30. package/ts_build/src/agents/base/base.js.map +1 -1
  31. package/ts_build/src/agents/patcher/patcher.js +1 -1
  32. package/ts_build/src/agents/patcher/patcher.js.map +1 -1
  33. package/ts_build/src/agents/tools/list.js +1 -0
  34. package/ts_build/src/agents/tools/list.js.map +1 -1
  35. package/ts_build/src/chat/modules/AgentModule.js +17 -19
  36. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  37. package/ts_build/src/chat/modules/SessionsModule.js +1 -3
  38. package/ts_build/src/chat/modules/SessionsModule.js.map +1 -1
  39. package/ts_build/src/chat/modules/SystemModule.js +16 -8
  40. package/ts_build/src/chat/modules/SystemModule.js.map +1 -1
  41. package/ts_build/src/cli.js +17 -0
  42. package/ts_build/src/cli.js.map +1 -1
  43. package/ts_build/src/clients/anthropic.d.ts +9 -7
  44. package/ts_build/src/clients/anthropic.js +9 -4
  45. package/ts_build/src/clients/anthropic.js.map +1 -1
  46. package/ts_build/src/clients/gemini.d.ts +2 -1
  47. package/ts_build/src/clients/gemini.js +13 -4
  48. package/ts_build/src/clients/gemini.js.map +1 -1
  49. package/ts_build/src/clients/http.d.ts +1 -1
  50. package/ts_build/src/clients/http.js +2 -2
  51. package/ts_build/src/clients/http.js.map +1 -1
  52. package/ts_build/src/clients/index.d.ts +23 -47
  53. package/ts_build/src/clients/index.js +152 -99
  54. package/ts_build/src/clients/index.js.map +1 -1
  55. package/ts_build/src/clients/knowhow.d.ts +3 -2
  56. package/ts_build/src/clients/knowhow.js +6 -3
  57. package/ts_build/src/clients/knowhow.js.map +1 -1
  58. package/ts_build/src/clients/openai.d.ts +20 -18
  59. package/ts_build/src/clients/openai.js +166 -8
  60. package/ts_build/src/clients/openai.js.map +1 -1
  61. package/ts_build/src/clients/types.d.ts +3 -1
  62. package/ts_build/src/clients/xai.d.ts +3 -2
  63. package/ts_build/src/clients/xai.js +10 -4
  64. package/ts_build/src/clients/xai.js.map +1 -1
  65. package/ts_build/src/cloudWorker.d.ts +8 -0
  66. package/ts_build/src/cloudWorker.js +239 -0
  67. package/ts_build/src/cloudWorker.js.map +1 -0
  68. package/ts_build/src/config.js +8 -1
  69. package/ts_build/src/config.js.map +1 -1
  70. package/ts_build/src/processors/TokenCompressor.js +7 -1
  71. package/ts_build/src/processors/TokenCompressor.js.map +1 -1
  72. package/ts_build/src/services/KnowhowClient.d.ts +24 -1
  73. package/ts_build/src/services/KnowhowClient.js +14 -2
  74. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  75. package/ts_build/src/services/LazyToolsService.js +5 -7
  76. package/ts_build/src/services/LazyToolsService.js.map +1 -1
  77. package/ts_build/src/services/Tools.js +9 -1
  78. package/ts_build/src/services/Tools.js.map +1 -1
  79. package/ts_build/src/types.d.ts +3 -1
  80. package/ts_build/src/types.js +8 -1
  81. package/ts_build/src/types.js.map +1 -1
  82. package/ts_build/src/utils/InputQueueManager.d.ts +2 -0
  83. package/ts_build/src/utils/InputQueueManager.js +76 -10
  84. package/ts_build/src/utils/InputQueueManager.js.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tyvm/knowhow",
3
- "version": "0.0.97",
3
+ "version": "0.0.99",
4
4
  "description": "ai cli with plugins and agents",
5
5
  "main": "ts_build/src/index.js",
6
6
  "bin": {
@@ -247,15 +247,23 @@ export abstract class BaseAgent implements IAgent {
247
247
  if (!this.client) {
248
248
  if (this.provider) {
249
249
  this.log(`Getting client for provider ${this.provider}`);
250
- this.client = this.clientService.getClient(this.provider)?.client;
250
+ const clientInfo = this.clientService.getClient(this.getProvider());
251
+ if (clientInfo) {
252
+ this.client = clientInfo.client;
253
+ // don't set provider or model yet
254
+ }
251
255
  }
252
256
 
253
257
  if (!this.client) {
254
258
  this.log(`Getting client for model ${this.modelName}`);
255
- this.client = this.clientService.getClient(
259
+ const clientInfo = this.clientService.getClient(
256
260
  undefined,
257
- this.modelName
258
- )?.client;
261
+ this.getModel()
262
+ );
263
+
264
+ if (clientInfo) {
265
+ this.client = clientInfo.client;
266
+ }
259
267
  }
260
268
  }
261
269
  return this.client;
@@ -80,8 +80,8 @@ export class PatchingAgent extends BaseAgent {
80
80
 
81
81
  this.setModelPreferences([
82
82
  { model: Models.anthropic.Sonnet4_6, provider: "anthropic" },
83
+ { model: Models.openai.GPT_53_Codex, provider: "openai" },
83
84
  { model: Models.xai.GrokCodeFast, provider: "xai" },
84
- { model: Models.openai.GPT_5, provider: "openai" },
85
85
  ]);
86
86
  }
87
87
 
@@ -459,6 +459,7 @@ export const includedTools = [
459
459
  },
460
460
  },
461
461
  required: ["provider"],
462
+ positional: true,
462
463
  },
463
464
  returns: {
464
465
  type: "object",
@@ -34,7 +34,6 @@ import {
34
34
  createAgent,
35
35
  agentConstructors,
36
36
  AgentName,
37
- agents,
38
37
  } from "../../agents";
39
38
  import { ToolCallEvent } from "../../agents/base/base";
40
39
  import { KnowhowSimpleClient } from "../../services/KnowhowClient";
@@ -244,20 +243,28 @@ export class AgentModule extends BaseChatModule {
244
243
  }
245
244
 
246
245
  const agentName = args[0];
247
- const allAgents = agents();
248
246
 
249
247
  try {
250
- if (allAgents && allAgents[agentName]) {
248
+ if (agentConstructors[agentName as AgentName]) {
251
249
  // Set selected agent in context and enable agent mode
252
250
  if (context) {
253
- const selectedAgent = allAgents[agentName];
254
- context.selectedAgent = selectedAgent;
251
+ // Create a temporary agent instance to read its default model/provider
252
+ const agentContext = services().Agents.getAgentContext();
253
+ const tempAgent = createAgent(agentName as AgentName, agentContext) as BaseAgent;
254
+ context.selectedAgent = tempAgent;
255
255
  context.agentMode = true;
256
256
  context.currentAgent = agentName;
257
257
  // Update context's model/provider to reflect the agent's settings
258
258
  // so /model and /provider commands show accurate information
259
- context.currentModel = selectedAgent.getModel();
260
- context.currentProvider = selectedAgent.getProvider();
259
+
260
+ const clientInfo = await tempAgent.clientService.getClient(
261
+ undefined,
262
+ tempAgent.getModel()
263
+ );
264
+
265
+ context.currentModel = clientInfo.model;
266
+ context.currentProvider = clientInfo.provider;
267
+
261
268
  this.chatService.setMode("agent");
262
269
  }
263
270
 
@@ -435,16 +442,13 @@ export class AgentModule extends BaseChatModule {
435
442
  */
436
443
  async handleAgentsCommand(args: string[]): Promise<void> {
437
444
  try {
438
- const allAgents = agents();
445
+ const agentNames = Object.keys(agentConstructors);
439
446
 
440
- if (allAgents && Object.keys(allAgents).length > 0) {
441
- const agentNames = Object.keys(allAgents);
447
+ if (agentNames.length > 0) {
442
448
 
443
449
  console.log("\nAvailable agents:");
444
- Object.entries(allAgents).forEach(([name, agent]: [string, any]) => {
445
- console.log(
446
- ` - ${name}: ${(agent as any).description || "No description"}`
447
- );
450
+ agentNames.forEach((name) => {
451
+ console.log(` - ${name}`);
448
452
  });
449
453
  console.log("─".repeat(80), "\n");
450
454
 
@@ -462,8 +466,6 @@ export class AgentModule extends BaseChatModule {
462
466
  } else if (selectedAgent && selectedAgent.trim()) {
463
467
  console.log(`Agent "${selectedAgent.trim()}" not found.`);
464
468
  }
465
- } else {
466
- console.log("No agents available.");
467
469
  }
468
470
  } catch (error) {
469
471
  console.error("Error listing agents:", error);
@@ -516,18 +518,16 @@ Please continue from where you left off and complete the original request.
516
518
 
517
519
  console.log("🚀 Session resuming...");
518
520
  const context = this.chatService?.getContext();
519
- const allAgents = agents();
520
- const selectedAgent =
521
- allAgents[session.agentName] || allAgents[context.currentAgent];
521
+ const agentName = session.agentName || context.currentAgent;
522
522
 
523
- if (!selectedAgent) {
524
- console.error(`Agent ${session.agentName} not found.`);
523
+ if (!agentName || !agentConstructors[agentName as AgentName]) {
524
+ console.error(`Agent ${agentName} not found.`);
525
525
  return;
526
526
  }
527
527
 
528
528
  // Start agent with Knowhow task context if available
529
529
  const { agent, taskId } = await this.setupAgent({
530
- agentName: selectedAgent.name,
530
+ agentName,
531
531
  input: resumePrompt,
532
532
  messageId: session.knowhowMessageId,
533
533
  existingKnowhowTaskId: session.knowhowTaskId,
@@ -1003,6 +1003,8 @@ Please continue from where you left off and complete the original request.
1003
1003
  agentName: selectedAgent.name,
1004
1004
  input: initialInput,
1005
1005
  chatHistory,
1006
+ model: selectedAgent.getModel(),
1007
+ provider: selectedAgent.getProvider() as any,
1006
1008
  run: false, // Don't run yet, we need to set up event listeners first
1007
1009
  });
1008
1010
 
@@ -18,7 +18,6 @@ import {
18
18
  WatcherBackedAgent,
19
19
  } from "../../services/index";
20
20
  import { TaskInfo, ChatSession } from "../types";
21
- import { agents } from "../../agents";
22
21
  import { KnowhowSimpleClient } from "../../services/KnowhowClient";
23
22
  import { messagesToRenderEvents } from "../renderer/messagesToRenderEvents";
24
23
  import { Marked } from "../../utils/index";
@@ -217,8 +216,7 @@ export class SessionsModule extends BaseChatModule {
217
216
  const taskInfo = taskRegistry.get(id)!;
218
217
  const renderer = this.agentModule.getRenderer();
219
218
  const context = this.chatService?.getContext();
220
- const allAgents = agents();
221
- const selectedAgent = allAgents[taskInfo.agentName];
219
+ const selectedAgent = taskInfo.agent;
222
220
 
223
221
  if (context && selectedAgent) {
224
222
  context.selectedAgent = selectedAgent;
@@ -28,7 +28,8 @@ export class SystemModule extends BaseChatModule {
28
28
  },
29
29
  {
30
30
  name: "clear",
31
- description: "Clear chat history - AI will not remember previous messages",
31
+ description:
32
+ "Clear chat history - AI will not remember previous messages",
32
33
  handler: this.handleClearCommand.bind(this),
33
34
  },
34
35
  ];
@@ -40,8 +41,9 @@ export class SystemModule extends BaseChatModule {
40
41
 
41
42
  async handleModelCommand(args: string[]): Promise<void> {
42
43
  const context = this.chatService?.getContext();
43
- const { Clients } = services();
44
44
 
45
+ const agent = context?.selectedAgent;
46
+ const Clients = agent.clientService;
45
47
  const currentProvider = context?.currentProvider || "openai";
46
48
  const currentModel = context?.currentModel || "gpt-4o";
47
49
 
@@ -53,11 +55,17 @@ export class SystemModule extends BaseChatModule {
53
55
  models
54
56
  );
55
57
 
58
+ if (!selectedModel) {
59
+ return;
60
+ }
61
+
56
62
  this.chatService?.setContext({
57
63
  currentModel: selectedModel,
58
64
  currentProvider,
59
65
  });
60
- console.log(`Model set to: ${selectedModel}`);
66
+ console.log(
67
+ `Model set to: ${selectedModel} for provider: ${currentProvider}`
68
+ );
61
69
 
62
70
  // Update currently active agent if any
63
71
  if (context?.selectedAgent) {
@@ -73,7 +81,9 @@ export class SystemModule extends BaseChatModule {
73
81
 
74
82
  async handleProviderCommand(args: string[]): Promise<void> {
75
83
  const context = this.chatService?.getContext();
76
- const { Clients } = services();
84
+
85
+ const agent = context?.selectedAgent;
86
+ const Clients = agent.clientService;
77
87
 
78
88
  const currentProvider = context?.currentProvider || "openai";
79
89
  const currentModel = context?.currentModel || "gpt-4o";
@@ -86,12 +96,17 @@ export class SystemModule extends BaseChatModule {
86
96
  providers
87
97
  );
88
98
 
99
+ if (!selectedProvider) {
100
+ return;
101
+ }
102
+
89
103
  // Get default model for new provider
90
104
  const ChatModelDefaults = {
91
- openai: Models.openai.GPT_5,
92
- anthropic: Models.anthropic.Sonnet4,
93
- google: Models.google.Gemini_25_Flash_Preview,
94
- xai: Models.xai.GrokCodeFast,
105
+ openai: Models.openai.GPT_53_Codex,
106
+ anthropic: Models.anthropic.Sonnet4_6,
107
+ google: Models.google.Gemini_3_Flash_Preview,
108
+ xai: Models.xai.Grok4_1_Fast_NonReasoning,
109
+ knowhow: "anthropic/" + Models.anthropic.Sonnet4_6,
95
110
  };
96
111
 
97
112
  const newModel =
package/src/cli.ts CHANGED
@@ -489,6 +489,23 @@ async function main() {
489
489
  }
490
490
  });
491
491
 
492
+ program
493
+ .command("cloudworker")
494
+ .description("Create or sync a cloud worker with your local knowhow config")
495
+ .option("--create", "Create a new cloud worker with synced config and files")
496
+ .option("--push <uid>", "Push/sync local config and files to an existing cloud worker")
497
+ .option("--name <name>", "Name for the cloud worker (used with --create)")
498
+ .option("--dry-run", "Print what would be synced without doing it")
499
+ .action(async (options) => {
500
+ try {
501
+ const { cloudWorker } = await import("./cloudWorker");
502
+ await cloudWorker(options);
503
+ } catch (error) {
504
+ console.error("Error running cloudworker:", error);
505
+ process.exit(1);
506
+ }
507
+ });
508
+
492
509
  program
493
510
  .command("script")
494
511
  .description("Run a local tool script file using the executeScript sandbox")
@@ -2,6 +2,7 @@ import Anthropic from "@anthropic-ai/sdk";
2
2
  import { wait } from "../utils";
3
3
  import { AnthropicTextPricing } from "./pricing";
4
4
  import { ContextLimits } from "./contextLimits";
5
+ import { ModelModality } from "./types";
5
6
  import { Models } from "../types";
6
7
  import {
7
8
  GenericClient,
@@ -467,11 +468,16 @@ export class GenericAnthropicClient implements GenericClient {
467
468
  return nonCachedInputCost + cacheWriteCost + cacheReadCost + outputCost;
468
469
  }
469
470
 
470
- async getModels() {
471
+ async getModels(modality?: ModelModality): Promise<{ id: string }[]> {
472
+ if (modality) {
473
+ if (modality === "completion") {
474
+ return Object.values(Models.anthropic).map((id) => ({ id }));
475
+ }
476
+ return [];
477
+ }
478
+ // No modality — live API call (backward compat)
471
479
  const models = await this.client.models.list();
472
- return models.data.map((m) => ({
473
- id: m.id,
474
- }));
480
+ return models.data.map((m) => ({ id: m.id }));
475
481
  }
476
482
 
477
483
  async createEmbedding(options: EmbeddingOptions): Promise<EmbeddingResponse> {
@@ -13,9 +13,18 @@ import * as os from "os";
13
13
  import * as fsSync from "fs";
14
14
  import * as pathSync from "path";
15
15
  import { wait } from "../utils";
16
- import { EmbeddingModels, Models } from "../types";
16
+ import {
17
+ EmbeddingModels,
18
+ Models,
19
+ GoogleImageModels,
20
+ GoogleVideoModels,
21
+ GoogleTTSModels,
22
+ GoogleEmbeddingModels,
23
+ GoogleReasoningModels,
24
+ } from "../types";
17
25
  import { GeminiTextPricing } from "./pricing";
18
26
  import { ContextLimits } from "./contextLimits";
27
+ import { ModelModality } from "./types";
19
28
 
20
29
  import {
21
30
  GenericClient,
@@ -587,12 +596,21 @@ export class GenericGeminiClient implements GenericClient {
587
596
  return cost;
588
597
  }
589
598
 
590
- async getModels() {
599
+ async getModels(modality?: ModelModality): Promise<{ id: string }[]> {
600
+ if (modality) {
601
+ const map: Partial<Record<ModelModality, string[]>> = {
602
+ completion: GoogleReasoningModels,
603
+ embedding: GoogleEmbeddingModels,
604
+ image: GoogleImageModels,
605
+ audio: GoogleTTSModels,
606
+ video: GoogleVideoModels,
607
+ };
608
+ return (map[modality] ?? []).map((id) => ({ id }));
609
+ }
610
+ // No modality — live API call (backward compat)
591
611
  try {
592
612
  const models = await this.client.models.list();
593
- return models.page.map((m) => ({
594
- id: m.name!,
595
- }));
613
+ return models.page.map((m) => ({ id: m.name! }));
596
614
  } catch (error) {
597
615
  console.error("Error fetching Google GenAI models:", error);
598
616
  throw error;
@@ -38,7 +38,9 @@ export class HttpClient implements GenericClient {
38
38
  }
39
39
  const delay = 1000 * Math.pow(2, attempt);
40
40
  console.warn(
41
- `HTTP request failed (attempt ${attempt + 1}/${retries}), retrying in ${delay}ms...`,
41
+ `HTTP request failed (attempt ${
42
+ attempt + 1
43
+ }/${retries}), retrying in ${delay}ms...`,
42
44
  e.message
43
45
  );
44
46
  await new Promise((resolve) => setTimeout(resolve, delay));
@@ -146,9 +148,9 @@ export class HttpClient implements GenericClient {
146
148
  });
147
149
  }
148
150
 
149
- async getModels() {
151
+ async getModels(type = "all") {
150
152
  return this.withRetry(async () => {
151
- const response = await http.get(`${this.baseUrl}/v1/models`, {
153
+ const response = await http.get(`${this.baseUrl}/v1/models?type=${type}`, {
152
154
  headers: this.headers as Record<string, string>,
153
155
  });
154
156