@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
@@ -18,119 +18,271 @@ import {
18
18
  FileUploadResponse,
19
19
  FileDownloadOptions,
20
20
  FileDownloadResponse,
21
+ ModelModality,
21
22
  } from "./types";
22
23
  import { GenericOpenAiClient } from "./openai";
23
24
  import { GenericAnthropicClient } from "./anthropic";
24
25
  import { GenericGeminiClient } from "./gemini";
25
- import { HttpClient } from "./http";
26
- import { EmbeddingModels, Models } from "../types";
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";
39
26
  import { GenericXAIClient } from "./xai";
40
27
  import { KnowhowGenericClient } from "./knowhow";
41
- import { loadKnowhowJwt } from "../services/KnowhowClient";
28
+ import { HttpClient } from "./http";
29
+ import { ModelProvider } from "../types";
30
+ import { getConfig } from "../config";
31
+ import { loadKnowhowJwt, KNOWHOW_API_URL } from "../services/KnowhowClient";
42
32
  import { ContextLimits } from "./contextLimits";
43
33
 
44
- export type ModelModality = "completion" | "embedding" | "image" | "audio" | "video";
34
+ // ---------------------------------------------------------------------------
35
+ // Built-in provider registry
36
+ // Maps provider name → { clientClass } so AIClient knows how to instantiate
37
+ // known providers without needing a url.
38
+ // ---------------------------------------------------------------------------
39
+
40
+ type ProviderRegistryEntry = {
41
+ /** Constructor that accepts up to two optional string args (e.g. apiKey or url, jwt) */
42
+ clientClass?: new (arg1?: string, arg2?: string) => GenericClient;
43
+ /** Custom factory — takes precedence over clientClass */
44
+ createClient?: (entry: ModelProvider) => GenericClient | null;
45
+ };
46
+
47
+ const BUILT_IN_PROVIDER_REGISTRY: Record<string, ProviderRegistryEntry> = {
48
+ openai: { clientClass: GenericOpenAiClient },
49
+ anthropic: { clientClass: GenericAnthropicClient },
50
+ google: { clientClass: GenericGeminiClient },
51
+ xai: { clientClass: GenericXAIClient },
52
+ knowhow: {
53
+ createClient: (entry: ModelProvider) => {
54
+ const jwt = loadKnowhowJwt();
55
+ if (!jwt) return null;
56
+ return new KnowhowGenericClient(KNOWHOW_API_URL, jwt);
57
+ },
58
+ },
59
+ };
60
+
61
+ // ---------------------------------------------------------------------------
62
+ // Default providers — pure data, no createClient logic here.
63
+ // envKey: if set, the env var must be non-empty before this provider is init'd.
64
+ // No envKey means the provider uses its own check (e.g. knowhow uses JWT file).
65
+ // ---------------------------------------------------------------------------
66
+ const DEFAULT_PROVIDERS: ModelProvider[] = [
67
+ { provider: "openai", envKey: "OPENAI_API_KEY" },
68
+ { provider: "anthropic", envKey: "ANTHROPIC_API_KEY" },
69
+ { provider: "google", envKey: "GEMINI_API_KEY" },
70
+ { provider: "xai", envKey: "XAI_API_KEY" },
71
+ { provider: "knowhow" },
72
+ ];
45
73
 
46
- function envCheck(key: string): boolean {
47
- const value = process.env[key];
48
- if (!value) {
49
- return false;
74
+ export class AIClient {
75
+ clients: Record<string, GenericClient> = {};
76
+
77
+ completionModels: Record<string, string[]> = {};
78
+ embeddingModels: Record<string, string[]> = {};
79
+ clientModels: Record<string, string[]> = {};
80
+ imageModels: Record<string, string[]> = {};
81
+ audioModels: Record<string, string[]> = {};
82
+ videoModels: Record<string, string[]> = {};
83
+
84
+ /** Internal registry: provider name → how to create + what models it has */
85
+ private providerRegistry: Record<string, ProviderRegistryEntry> = {
86
+ ...BUILT_IN_PROVIDER_REGISTRY,
87
+ };
88
+
89
+ constructor() {
90
+ // _initDefaultProviders is async but we fire-and-forget here.
91
+ // Call registerModelProviders() or registerConfiguredModels() after construction
92
+ // if you need to await full registration.
93
+ this._initDefaultProviders();
50
94
  }
51
- return true;
52
- }
53
95
 
54
- export class AIClient {
55
- clients = {
56
- ...(envCheck("OPENAI_KEY") && { openai: new GenericOpenAiClient() }),
96
+ // ---------------------------------------------------------------------------
97
+ // Internal helpers
98
+ // ---------------------------------------------------------------------------
57
99
 
58
- ...(envCheck("ANTHROPIC_API_KEY") && {
59
- anthropic: new GenericAnthropicClient(),
60
- }),
100
+ private async _initDefaultProviders() {
101
+ await this.registerModelProviders(DEFAULT_PROVIDERS);
102
+ }
61
103
 
62
- ...(envCheck("GEMINI_API_KEY") && { google: new GenericGeminiClient() }),
63
- ...(envCheck("XAI_API_KEY") && { xai: new GenericXAIClient() }),
64
- ...(loadKnowhowJwt() && { knowhow: new KnowhowGenericClient() }),
65
- };
104
+ /**
105
+ * Resolve a GenericClient from a ModelProvider entry.
106
+ * Priority:
107
+ * 1. registry.createClient(entry)
108
+ * 2. registry.clientClass(envValue)
109
+ * 3. HttpClient(url, headers) + optional JWT
110
+ */
111
+ public resolveClient(entry: ModelProvider): GenericClient | null {
112
+ const reg = this.providerRegistry[entry.provider];
66
113
 
67
- completionModels = {
68
- ...(envCheck("OPENAI_KEY") && {
69
- openai: Object.values(Models.openai),
70
- }),
71
- ...(envCheck("ANTHROPIC_API_KEY") && {
72
- anthropic: Object.values(Models.anthropic),
73
- }),
74
- ...(envCheck("GEMINI_API_KEY") && {
75
- google: Object.values(Models.google),
76
- }),
77
- ...(envCheck("XAI_API_KEY") && { xai: Object.values(Models.xai) }),
78
- };
114
+ // 1. Custom factory in registry
115
+ if (reg?.createClient) {
116
+ return reg.createClient(entry);
117
+ }
79
118
 
80
- embeddingModels = {
81
- ...(envCheck("OPENAI_KEY") && {
82
- openai: Object.values(EmbeddingModels.openai),
83
- }),
84
- ...(envCheck("GEMINI_API_KEY") && {
85
- google: Object.values(EmbeddingModels.google),
86
- }),
87
- };
119
+ // 2. Known clientClass
120
+ if (reg?.clientClass) {
121
+ // Use the entry's envKey, or fall back to the DEFAULT_PROVIDERS envKey for this provider
122
+ const effectiveEnvKey =
123
+ entry.envKey ??
124
+ DEFAULT_PROVIDERS.find((p) => p.provider === entry.provider)?.envKey;
125
+
126
+ if (effectiveEnvKey) {
127
+ // envKey-based auth: env var must be present
128
+ const envValue = process.env[effectiveEnvKey];
129
+ if (!envValue) return null;
130
+ return new reg.clientClass(envValue);
131
+ }
88
132
 
89
- clientModels = {
90
- ...(envCheck("OPENAI_KEY") && {
91
- openai: [...this.completionModels.openai, ...this.embeddingModels.openai],
92
- }),
93
- ...(envCheck("ANTHROPIC_API_KEY") && {
94
- anthropic: [...this.completionModels.anthropic],
95
- }),
96
- ...(envCheck("GEMINI_API_KEY") && {
97
- google: [...this.completionModels.google, ...this.embeddingModels.google],
98
- }),
99
- ...(envCheck("XAI_API_KEY") && { xai: this.completionModels.xai }),
100
- };
133
+ // No envKey, no url — instantiate with no arg (client uses its own defaults)
134
+ return new reg.clientClass();
135
+ }
101
136
 
102
- imageModels: Record<string, string[]> = {
103
- ...(envCheck("OPENAI_KEY") && {
104
- openai: OpenAiImageModels,
105
- }),
106
- ...(envCheck("GEMINI_API_KEY") && {
107
- google: GoogleImageModels,
108
- }),
109
- ...(envCheck("XAI_API_KEY") && {
110
- xai: XaiImageModels,
111
- }),
112
- };
137
+ // 3. HTTP provider — requires url, no clientClass in registry
138
+ if (entry.url) {
139
+ const client = new HttpClient(entry.url, entry.headers);
140
+ if (entry.jwtFile) {
141
+ client.loadJwtFile(entry.jwtFile);
142
+ }
143
+ return client;
144
+ }
113
145
 
114
- audioModels: Record<string, string[]> = {
115
- ...(envCheck("OPENAI_KEY") && {
116
- openai: [...OpenAiTTSModels, ...OpenAiTranscriptionModels],
117
- }),
118
- ...(envCheck("GEMINI_API_KEY") && {
119
- google: GoogleTTSModels,
120
- }),
121
- };
146
+ return null;
147
+ }
122
148
 
123
- videoModels: Record<string, string[]> = {
124
- ...(envCheck("OPENAI_KEY") && {
125
- openai: OpenAiVideoModels,
126
- }),
127
- ...(envCheck("GEMINI_API_KEY") && {
128
- google: GoogleVideoModels,
129
- }),
130
- ...(envCheck("XAI_API_KEY") && {
131
- xai: XaiVideoModels,
132
- }),
133
- };
149
+ /**
150
+ * Register a client's models into all relevant modality buckets by calling
151
+ * client.getModels(modality) for each modality.
152
+ */
153
+ private async _registerClientModalities(
154
+ provider: string,
155
+ client: GenericClient
156
+ ) {
157
+ this.clients[provider] = client;
158
+
159
+ const modalities: ModelModality[] = [
160
+ "completion",
161
+ "embedding",
162
+ "image",
163
+ "audio",
164
+ "video",
165
+ ];
166
+ for (const modality of modalities) {
167
+ try {
168
+ const result = await client.getModels(modality);
169
+ const models = result.map((m) => m.id);
170
+
171
+ if (!models.length) continue;
172
+
173
+ switch (modality) {
174
+ case "completion":
175
+ this._mergeModels(this.completionModels, provider, models);
176
+ break;
177
+ case "embedding":
178
+ this._mergeModels(this.embeddingModels, provider, models);
179
+ break;
180
+ case "image":
181
+ this._mergeModels(this.imageModels, provider, models);
182
+ break;
183
+ case "audio":
184
+ this._mergeModels(this.audioModels, provider, models);
185
+ break;
186
+ case "video":
187
+ this._mergeModels(this.videoModels, provider, models);
188
+ break;
189
+ }
190
+ this._mergeModels(this.clientModels, provider, models);
191
+ } catch {
192
+ // modality not supported by this client — skip silently
193
+ }
194
+ }
195
+ }
196
+
197
+ private _mergeModels(
198
+ map: Record<string, string[]>,
199
+ provider: string,
200
+ models: string[]
201
+ ) {
202
+ const current = map[provider] || [];
203
+ map[provider] = Array.from(new Set([...current, ...models]));
204
+ }
205
+
206
+ // ---------------------------------------------------------------------------
207
+ // Public API
208
+ // ---------------------------------------------------------------------------
209
+
210
+ /**
211
+ * Register model providers from a list of ModelProvider entries.
212
+ * This is the central registration method — registerConfiguredModels() calls this.
213
+ * For registry-known providers, uses getModels() for modality registration.
214
+ * For HTTP-only providers, falls back to loadProviderModels() (live /models call).
215
+ */
216
+ async registerModelProviders(providers: ModelProvider[]) {
217
+ for (const entry of providers) {
218
+ const client = this.resolveClient(entry);
219
+
220
+ if (!client) continue;
221
+
222
+ const reg = this.providerRegistry[entry.provider];
223
+
224
+ if (reg) {
225
+ // Registry-known provider: use client.getModels(modality) for registration
226
+ await this._registerClientModalities(entry.provider, client);
227
+ } else {
228
+ // HTTP provider (no registry entry): register client and fetch /models live
229
+ this.clients[entry.provider] = client;
230
+ try {
231
+ await this.loadProviderModels(entry.provider);
232
+ } catch (error) {
233
+ console.error(
234
+ `Failed to register models for provider ${entry.provider}:`,
235
+ error.message
236
+ );
237
+ }
238
+ }
239
+ }
240
+ }
241
+
242
+ async registerConfiguredModels() {
243
+ const config = await getConfig();
244
+ const modelProviders = config.modelProviders || [];
245
+
246
+ // If the config explicitly defines modelProviders, unregister only the
247
+ // default providers that are NOT present in the config — so omitting a
248
+ // provider from the config effectively disables it, but providers that
249
+ // appear in both defaults and config are not double-processed.
250
+ if (config.modelProviders !== undefined) {
251
+ const configProviderNames = new Set(
252
+ modelProviders.map((p) => p.provider)
253
+ );
254
+ for (const defaultEntry of DEFAULT_PROVIDERS) {
255
+ if (!configProviderNames.has(defaultEntry.provider)) {
256
+ this.unregisterProvider(defaultEntry.provider);
257
+ }
258
+ }
259
+ }
260
+
261
+ if (modelProviders.length > 0) {
262
+ await this.registerModelProviders(modelProviders);
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Remove a provider and all its registered models from the client.
268
+ */
269
+ unregisterProvider(provider: string) {
270
+ delete this.clients[provider];
271
+ delete this.clientModels[provider];
272
+ delete this.completionModels[provider];
273
+ delete this.embeddingModels[provider];
274
+ delete this.imageModels[provider];
275
+ delete this.audioModels[provider];
276
+ delete this.videoModels[provider];
277
+ }
278
+
279
+ /**
280
+ * Register a custom client class or factory for a provider name.
281
+ * This allows external code (plugins, modules) to add first-party clients.
282
+ */
283
+ registerClientClass(provider: string, entry: ProviderRegistryEntry) {
284
+ this.providerRegistry[provider] = entry;
285
+ }
134
286
 
135
287
  getClient(provider: string, model?: string) {
136
288
  if (provider && !model) {
@@ -166,35 +318,11 @@ export class AIClient {
166
318
  }
167
319
 
168
320
  setKey(provider: string, apiKey: string) {
169
- const { client } = this.getClient(provider); // Ensure provider is registered
321
+ const { client } = this.getClient(provider);
170
322
  client.setKey(apiKey);
171
323
  this.clients[provider].setKey(apiKey);
172
324
  }
173
325
 
174
- async registerConfiguredModels() {
175
- const config = await getConfig();
176
- const modelProviders = config.modelProviders || [];
177
-
178
- for (const modelProvider of modelProviders) {
179
- const client = new HttpClient(modelProvider.url, modelProvider.headers);
180
-
181
- if (modelProvider.jwtFile) {
182
- client.loadJwtFile(modelProvider.jwtFile);
183
- }
184
-
185
- this.registerClient(modelProvider.provider, client);
186
-
187
- try {
188
- await this.loadProviderModels(modelProvider.provider);
189
- } catch (error) {
190
- console.error(
191
- `Failed to register models for provider ${modelProvider.provider}:`,
192
- error.message
193
- );
194
- }
195
- }
196
- }
197
-
198
326
  async loadProviderModels(provider: string) {
199
327
  if (!this.clients[provider]) {
200
328
  throw new Error(`Provider ${provider} not registered.`);
@@ -236,8 +364,7 @@ export class AIClient {
236
364
 
237
365
  /*
238
366
  * Some clients support multiple providers, most clients are single provider
239
- * For the mult-provider clients, we register them with this method
240
- * TODO: currently registering overwrites any existing providers, but a fallback list could be useful
367
+ * For the multi-provider clients, we register them with this method
241
368
  */
242
369
  registerClientProviderModels(
243
370
  client: GenericClient,
@@ -251,8 +378,6 @@ export class AIClient {
251
378
 
252
379
  registerEmbeddingModels(provider: string, models: string[]) {
253
380
  const currentModels = this.clientModels[provider] || [];
254
- const currentEmbeddingModels = this.embeddingModels[provider] || [];
255
-
256
381
  this.clientModels[provider] = Array.from<string>(
257
382
  new Set(currentModels.concat(models))
258
383
  );
@@ -334,13 +459,12 @@ export class AIClient {
334
459
  return undefined;
335
460
  }
336
461
 
337
- // detects these formats
462
+ // detects these formats:
338
463
  // "openai", "gpt-5"
339
464
  // "knowhow", "openai/gpt-5"
340
465
  // "", "openai/gpt-5"
341
466
  // "", openai/gpt-5
342
467
  // "", "knowhow/openai/gpt-5"
343
- //
344
468
  detectProviderModel(provider: string, model?: string) {
345
469
  if (this.providerHasModel(provider, model)) {
346
470
  return { provider, model };
@@ -536,14 +660,13 @@ export class AIClient {
536
660
  }
537
661
 
538
662
  /*
663
+ * Some clients return models in the format "provider/model_name".
664
+ * This function parses those models into our {provider, model} format
665
+ * then creates a provider -> [models] map.
666
+ * The models will not have the provider prefix.
539
667
  *
540
- * some clients return models in the format "provider/model_name"
541
- * this function parses those models into our {provider, model} format
542
- * then creates a provider -> [models] map
543
- * the models will not have the provider prefix
544
- *
545
- * if the client doesn't return models in that format, use knownProvider
546
- * to set the provider
668
+ * If the client doesn't return models in that format, use knownProvider
669
+ * to set the provider.
547
670
  */
548
671
  async parseProviderPrefixedModels(
549
672
  client: GenericClient,
@@ -612,18 +735,17 @@ export class AIClient {
612
735
 
613
736
  /**
614
737
  * Returns the context window limit (in tokens) for a given model.
615
- * Optionally accepts a provider for future provider-specific overrides.
616
- * Delegates to the registered client's getContextLimit() if available,
617
- * so custom clients can provide their own context limits.
618
- * Returns undefined if neither the client nor the global ContextLimits table knows the model.
738
+ * Delegates to the registered client's getContextLimit() if available.
739
+ * Falls back to the global ContextLimits table.
619
740
  */
620
- getContextLimit(provider: string, model: string): { contextLimit: number; threshold: number } | undefined {
621
- // Try the registered client first
741
+ getContextLimit(
742
+ provider: string,
743
+ model: string
744
+ ): { contextLimit: number; threshold: number } | undefined {
622
745
  const client = this.clients[provider];
623
746
  if (client?.getContextLimit) {
624
747
  return client.getContextLimit(model);
625
748
  }
626
- // Fall back to the global ContextLimits table
627
749
  const contextLimit = ContextLimits[model];
628
750
  if (contextLimit === undefined) return undefined;
629
751
  return { contextLimit, threshold: contextLimit };
@@ -18,8 +18,12 @@ import {
18
18
  FileUploadResponse,
19
19
  FileDownloadOptions,
20
20
  FileDownloadResponse,
21
+ ModelModality,
21
22
  } from "./types";
22
- import { KnowhowSimpleClient, KNOWHOW_API_URL } from "../services/KnowhowClient";
23
+ import {
24
+ KnowhowSimpleClient,
25
+ KNOWHOW_API_URL,
26
+ } from "../services/KnowhowClient";
23
27
 
24
28
  const envUrl = KNOWHOW_API_URL;
25
29
  export class KnowhowGenericClient implements GenericClient {
@@ -45,9 +49,16 @@ export class KnowhowGenericClient implements GenericClient {
45
49
  return response.data;
46
50
  }
47
51
 
48
- async getModels(): Promise<{ id: string }[]> {
49
- const response = await this.client.getModels();
50
- return response.data;
52
+ async getModels(
53
+ type = "all"
54
+ ): Promise<{ id: string; modality: ModelModality[] }[]> {
55
+ const response = await this.client.getModels(type);
56
+ return (
57
+ response.data?.data?.map((model) => ({
58
+ id: model.id,
59
+ modality: [model.type],
60
+ })) || []
61
+ );
51
62
  }
52
63
 
53
64
  async createAudioTranscription(