@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.
- package/package.json +1 -1
- package/src/agents/base/base.ts +12 -4
- package/src/agents/patcher/patcher.ts +1 -1
- package/src/agents/tools/list.ts +1 -0
- package/src/chat/modules/AgentModule.ts +24 -22
- package/src/chat/modules/SessionsModule.ts +1 -3
- package/src/chat/modules/SystemModule.ts +23 -8
- package/src/cli.ts +17 -0
- package/src/clients/anthropic.ts +10 -4
- package/src/clients/gemini.ts +23 -5
- package/src/clients/http.ts +5 -3
- package/src/clients/index.ts +261 -139
- package/src/clients/knowhow.ts +15 -4
- package/src/clients/openai.ts +213 -10
- package/src/clients/types.ts +7 -1
- package/src/clients/xai.ts +13 -6
- package/src/cloudWorker.ts +314 -0
- package/src/config.ts +9 -1
- package/src/processors/TokenCompressor.ts +8 -1
- package/src/services/KnowhowClient.ts +56 -12
- package/src/services/LazyToolsService.ts +15 -14
- package/src/services/Tools.ts +10 -1
- package/src/types.ts +11 -2
- package/src/utils/InputQueueManager.ts +131 -20
- package/test-ai-completion.ts +39 -0
- package/test-mcp-args.ts +71 -0
- package/test-tools-service.ts +45 -0
- package/ts_build/package.json +1 -1
- package/ts_build/src/agents/base/base.js +8 -2
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/patcher/patcher.js +1 -1
- package/ts_build/src/agents/patcher/patcher.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +1 -0
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.js +17 -19
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/SessionsModule.js +1 -3
- package/ts_build/src/chat/modules/SessionsModule.js.map +1 -1
- package/ts_build/src/chat/modules/SystemModule.js +16 -8
- package/ts_build/src/chat/modules/SystemModule.js.map +1 -1
- package/ts_build/src/cli.js +17 -0
- package/ts_build/src/cli.js.map +1 -1
- package/ts_build/src/clients/anthropic.d.ts +9 -7
- package/ts_build/src/clients/anthropic.js +9 -4
- package/ts_build/src/clients/anthropic.js.map +1 -1
- package/ts_build/src/clients/gemini.d.ts +2 -1
- package/ts_build/src/clients/gemini.js +13 -4
- package/ts_build/src/clients/gemini.js.map +1 -1
- package/ts_build/src/clients/http.d.ts +1 -1
- package/ts_build/src/clients/http.js +2 -2
- package/ts_build/src/clients/http.js.map +1 -1
- package/ts_build/src/clients/index.d.ts +23 -47
- package/ts_build/src/clients/index.js +152 -99
- package/ts_build/src/clients/index.js.map +1 -1
- package/ts_build/src/clients/knowhow.d.ts +3 -2
- package/ts_build/src/clients/knowhow.js +6 -3
- package/ts_build/src/clients/knowhow.js.map +1 -1
- package/ts_build/src/clients/openai.d.ts +20 -18
- package/ts_build/src/clients/openai.js +166 -8
- package/ts_build/src/clients/openai.js.map +1 -1
- package/ts_build/src/clients/types.d.ts +3 -1
- package/ts_build/src/clients/xai.d.ts +3 -2
- package/ts_build/src/clients/xai.js +10 -4
- package/ts_build/src/clients/xai.js.map +1 -1
- package/ts_build/src/cloudWorker.d.ts +8 -0
- package/ts_build/src/cloudWorker.js +239 -0
- package/ts_build/src/cloudWorker.js.map +1 -0
- package/ts_build/src/config.js +8 -1
- package/ts_build/src/config.js.map +1 -1
- package/ts_build/src/processors/TokenCompressor.js +7 -1
- package/ts_build/src/processors/TokenCompressor.js.map +1 -1
- package/ts_build/src/services/KnowhowClient.d.ts +24 -1
- package/ts_build/src/services/KnowhowClient.js +14 -2
- package/ts_build/src/services/KnowhowClient.js.map +1 -1
- package/ts_build/src/services/LazyToolsService.js +5 -7
- package/ts_build/src/services/LazyToolsService.js.map +1 -1
- package/ts_build/src/services/Tools.js +9 -1
- package/ts_build/src/services/Tools.js.map +1 -1
- package/ts_build/src/types.d.ts +3 -1
- package/ts_build/src/types.js +8 -1
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/src/utils/InputQueueManager.d.ts +2 -0
- package/ts_build/src/utils/InputQueueManager.js +76 -10
- package/ts_build/src/utils/InputQueueManager.js.map +1 -1
package/src/clients/index.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Internal helpers
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
57
99
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
100
|
+
private async _initDefaultProviders() {
|
|
101
|
+
await this.registerModelProviders(DEFAULT_PROVIDERS);
|
|
102
|
+
}
|
|
61
103
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
openai: [...OpenAiTTSModels, ...OpenAiTranscriptionModels],
|
|
117
|
-
}),
|
|
118
|
-
...(envCheck("GEMINI_API_KEY") && {
|
|
119
|
-
google: GoogleTTSModels,
|
|
120
|
-
}),
|
|
121
|
-
};
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
122
148
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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);
|
|
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
|
|
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
|
-
*
|
|
541
|
-
*
|
|
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
|
-
*
|
|
616
|
-
*
|
|
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(
|
|
621
|
-
|
|
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 };
|
package/src/clients/knowhow.ts
CHANGED
|
@@ -18,8 +18,12 @@ import {
|
|
|
18
18
|
FileUploadResponse,
|
|
19
19
|
FileDownloadOptions,
|
|
20
20
|
FileDownloadResponse,
|
|
21
|
+
ModelModality,
|
|
21
22
|
} from "./types";
|
|
22
|
-
import {
|
|
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(
|
|
49
|
-
|
|
50
|
-
|
|
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(
|