claude-flow 2.0.0-alpha.65 → 2.0.0-alpha.67
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/.claude/cache/agent-pool.json +33 -0
- package/.claude/cache/memory-optimization.json +19 -0
- package/.claude/cache/neural-optimization.json +25 -0
- package/.claude/cache/optimized-hooks.json +19 -0
- package/.claude/cache/parallel-processing.json +26 -0
- package/.claude/optimized-settings.json +270 -0
- package/.claude/settings-enhanced.json +278 -0
- package/.claude/settings.json +105 -8
- package/CHANGELOG.md +40 -0
- package/bin/claude-flow +1 -1
- package/dist/cli/simple-commands/hive-mind.js +1 -1
- package/dist/cli/simple-commands/hive-mind.js.map +1 -1
- package/dist/cli/simple-commands/hooks.js +6 -4
- package/dist/cli/simple-commands/hooks.js.map +1 -1
- package/dist/providers/anthropic-provider.d.ts +27 -0
- package/dist/providers/anthropic-provider.d.ts.map +1 -0
- package/dist/providers/anthropic-provider.js +247 -0
- package/dist/providers/anthropic-provider.js.map +1 -0
- package/dist/providers/base-provider.d.ts +134 -0
- package/dist/providers/base-provider.d.ts.map +1 -0
- package/dist/providers/base-provider.js +407 -0
- package/dist/providers/base-provider.js.map +1 -0
- package/dist/providers/cohere-provider.d.ts +28 -0
- package/dist/providers/cohere-provider.d.ts.map +1 -0
- package/dist/providers/cohere-provider.js +407 -0
- package/dist/providers/cohere-provider.js.map +1 -0
- package/dist/providers/google-provider.d.ts +23 -0
- package/dist/providers/google-provider.d.ts.map +1 -0
- package/dist/providers/google-provider.js +362 -0
- package/dist/providers/google-provider.js.map +1 -0
- package/dist/providers/index.d.ts +14 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +18 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama-provider.d.ts +23 -0
- package/dist/providers/ollama-provider.d.ts.map +1 -0
- package/dist/providers/ollama-provider.js +374 -0
- package/dist/providers/ollama-provider.js.map +1 -0
- package/dist/providers/openai-provider.d.ts +23 -0
- package/dist/providers/openai-provider.d.ts.map +1 -0
- package/dist/providers/openai-provider.js +349 -0
- package/dist/providers/openai-provider.js.map +1 -0
- package/dist/providers/provider-manager.d.ts +139 -0
- package/dist/providers/provider-manager.d.ts.map +1 -0
- package/dist/providers/provider-manager.js +513 -0
- package/dist/providers/provider-manager.js.map +1 -0
- package/dist/providers/types.d.ts +356 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +61 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/providers/utils.d.ts +37 -0
- package/dist/providers/utils.d.ts.map +1 -0
- package/dist/providers/utils.js +322 -0
- package/dist/providers/utils.js.map +1 -0
- package/dist/services/agentic-flow-hooks/hook-manager.d.ts +70 -0
- package/dist/services/agentic-flow-hooks/hook-manager.d.ts.map +1 -0
- package/dist/services/agentic-flow-hooks/hook-manager.js +512 -0
- package/dist/services/agentic-flow-hooks/hook-manager.js.map +1 -0
- package/dist/services/agentic-flow-hooks/index.d.ts +36 -0
- package/dist/services/agentic-flow-hooks/index.d.ts.map +1 -0
- package/dist/services/agentic-flow-hooks/index.js +325 -0
- package/dist/services/agentic-flow-hooks/index.js.map +1 -0
- package/dist/services/agentic-flow-hooks/llm-hooks.d.ts +33 -0
- package/dist/services/agentic-flow-hooks/llm-hooks.d.ts.map +1 -0
- package/dist/services/agentic-flow-hooks/llm-hooks.js +415 -0
- package/dist/services/agentic-flow-hooks/llm-hooks.js.map +1 -0
- package/dist/services/agentic-flow-hooks/memory-hooks.d.ts +45 -0
- package/dist/services/agentic-flow-hooks/memory-hooks.d.ts.map +1 -0
- package/dist/services/agentic-flow-hooks/memory-hooks.js +532 -0
- package/dist/services/agentic-flow-hooks/memory-hooks.js.map +1 -0
- package/dist/services/agentic-flow-hooks/neural-hooks.d.ts +39 -0
- package/dist/services/agentic-flow-hooks/neural-hooks.d.ts.map +1 -0
- package/dist/services/agentic-flow-hooks/neural-hooks.js +561 -0
- package/dist/services/agentic-flow-hooks/neural-hooks.js.map +1 -0
- package/dist/services/agentic-flow-hooks/performance-hooks.d.ts +33 -0
- package/dist/services/agentic-flow-hooks/performance-hooks.d.ts.map +1 -0
- package/dist/services/agentic-flow-hooks/performance-hooks.js +621 -0
- package/dist/services/agentic-flow-hooks/performance-hooks.js.map +1 -0
- package/dist/services/agentic-flow-hooks/types.d.ts +379 -0
- package/dist/services/agentic-flow-hooks/types.d.ts.map +1 -0
- package/dist/services/agentic-flow-hooks/types.js +8 -0
- package/dist/services/agentic-flow-hooks/types.js.map +1 -0
- package/dist/services/agentic-flow-hooks/workflow-hooks.d.ts +39 -0
- package/dist/services/agentic-flow-hooks/workflow-hooks.d.ts.map +1 -0
- package/dist/services/agentic-flow-hooks/workflow-hooks.js +742 -0
- package/dist/services/agentic-flow-hooks/workflow-hooks.js.map +1 -0
- package/package.json +2 -2
- package/scripts/install-arm64.js +78 -0
- package/scripts/optimize-performance.js +400 -0
- package/scripts/performance-monitor.js +263 -0
- package/src/cli/help-text.js +1 -1
- package/src/cli/simple-cli.js +1 -1
- package/src/cli/simple-commands/hive-mind.js +1 -1
- package/src/cli/simple-commands/hooks.js +8 -6
- package/src/providers/anthropic-provider.ts +282 -0
- package/src/providers/base-provider.ts +560 -0
- package/src/providers/cohere-provider.ts +521 -0
- package/src/providers/google-provider.ts +477 -0
- package/src/providers/index.ts +21 -0
- package/src/providers/ollama-provider.ts +489 -0
- package/src/providers/openai-provider.ts +476 -0
- package/src/providers/provider-manager.ts +654 -0
- package/src/providers/types.ts +531 -0
- package/src/providers/utils.ts +376 -0
- package/src/services/agentic-flow-hooks/hook-manager.ts +701 -0
- package/src/services/agentic-flow-hooks/index.ts +386 -0
- package/src/services/agentic-flow-hooks/llm-hooks.ts +557 -0
- package/src/services/agentic-flow-hooks/memory-hooks.ts +710 -0
- package/src/services/agentic-flow-hooks/neural-hooks.ts +758 -0
- package/src/services/agentic-flow-hooks/performance-hooks.ts +827 -0
- package/src/services/agentic-flow-hooks/types.ts +503 -0
- package/src/services/agentic-flow-hooks/workflow-hooks.ts +1026 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohere Provider Implementation
|
|
3
|
+
* Supports Command, Generate, and other Cohere models
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { BaseProvider } from './base-provider.js';
|
|
7
|
+
import {
|
|
8
|
+
LLMProvider,
|
|
9
|
+
LLMModel,
|
|
10
|
+
LLMRequest,
|
|
11
|
+
LLMResponse,
|
|
12
|
+
LLMStreamEvent,
|
|
13
|
+
ModelInfo,
|
|
14
|
+
ProviderCapabilities,
|
|
15
|
+
HealthCheckResult,
|
|
16
|
+
LLMProviderError,
|
|
17
|
+
RateLimitError,
|
|
18
|
+
AuthenticationError,
|
|
19
|
+
} from './types.js';
|
|
20
|
+
|
|
21
|
+
interface CohereGenerateRequest {
|
|
22
|
+
model: string;
|
|
23
|
+
prompt?: string;
|
|
24
|
+
messages?: Array<{
|
|
25
|
+
role: 'USER' | 'CHATBOT' | 'SYSTEM';
|
|
26
|
+
message: string;
|
|
27
|
+
}>;
|
|
28
|
+
preamble?: string;
|
|
29
|
+
temperature?: number;
|
|
30
|
+
max_tokens?: number;
|
|
31
|
+
k?: number;
|
|
32
|
+
p?: number;
|
|
33
|
+
frequency_penalty?: number;
|
|
34
|
+
presence_penalty?: number;
|
|
35
|
+
stop_sequences?: string[];
|
|
36
|
+
stream?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface CohereGenerateResponse {
|
|
40
|
+
id: string;
|
|
41
|
+
generations: Array<{
|
|
42
|
+
id: string;
|
|
43
|
+
text: string;
|
|
44
|
+
finish_reason: string;
|
|
45
|
+
}>;
|
|
46
|
+
prompt: string;
|
|
47
|
+
meta: {
|
|
48
|
+
api_version: {
|
|
49
|
+
version: string;
|
|
50
|
+
};
|
|
51
|
+
billed_units: {
|
|
52
|
+
input_tokens: number;
|
|
53
|
+
output_tokens: number;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface CohereChatResponse {
|
|
59
|
+
text: string;
|
|
60
|
+
generation_id: string;
|
|
61
|
+
finish_reason: string;
|
|
62
|
+
meta: {
|
|
63
|
+
api_version: {
|
|
64
|
+
version: string;
|
|
65
|
+
};
|
|
66
|
+
billed_units: {
|
|
67
|
+
input_tokens: number;
|
|
68
|
+
output_tokens: number;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class CohereProvider extends BaseProvider {
|
|
74
|
+
readonly name: LLMProvider = 'cohere';
|
|
75
|
+
readonly capabilities: ProviderCapabilities = {
|
|
76
|
+
supportedModels: [
|
|
77
|
+
'command',
|
|
78
|
+
'command-light',
|
|
79
|
+
'command-nightly',
|
|
80
|
+
'generate-xlarge',
|
|
81
|
+
'generate-medium',
|
|
82
|
+
],
|
|
83
|
+
maxContextLength: {
|
|
84
|
+
'command': 4096,
|
|
85
|
+
'command-light': 4096,
|
|
86
|
+
'command-nightly': 8192,
|
|
87
|
+
'generate-xlarge': 2048,
|
|
88
|
+
'generate-medium': 2048,
|
|
89
|
+
} as Record<LLMModel, number>,
|
|
90
|
+
maxOutputTokens: {
|
|
91
|
+
'command': 4096,
|
|
92
|
+
'command-light': 4096,
|
|
93
|
+
'command-nightly': 4096,
|
|
94
|
+
'generate-xlarge': 2048,
|
|
95
|
+
'generate-medium': 2048,
|
|
96
|
+
} as Record<LLMModel, number>,
|
|
97
|
+
supportsStreaming: true,
|
|
98
|
+
supportsFunctionCalling: false,
|
|
99
|
+
supportsSystemMessages: true,
|
|
100
|
+
supportsVision: false,
|
|
101
|
+
supportsAudio: false,
|
|
102
|
+
supportsTools: true,
|
|
103
|
+
supportsFineTuning: true,
|
|
104
|
+
supportsEmbeddings: true,
|
|
105
|
+
supportsLogprobs: true,
|
|
106
|
+
supportsBatching: false,
|
|
107
|
+
rateLimit: {
|
|
108
|
+
requestsPerMinute: 100,
|
|
109
|
+
tokensPerMinute: 100000,
|
|
110
|
+
concurrentRequests: 20,
|
|
111
|
+
},
|
|
112
|
+
pricing: {
|
|
113
|
+
'command': {
|
|
114
|
+
promptCostPer1k: 0.0015,
|
|
115
|
+
completionCostPer1k: 0.0015,
|
|
116
|
+
currency: 'USD',
|
|
117
|
+
},
|
|
118
|
+
'command-light': {
|
|
119
|
+
promptCostPer1k: 0.00015,
|
|
120
|
+
completionCostPer1k: 0.00015,
|
|
121
|
+
currency: 'USD',
|
|
122
|
+
},
|
|
123
|
+
'command-nightly': {
|
|
124
|
+
promptCostPer1k: 0.0015,
|
|
125
|
+
completionCostPer1k: 0.0015,
|
|
126
|
+
currency: 'USD',
|
|
127
|
+
},
|
|
128
|
+
'generate-xlarge': {
|
|
129
|
+
promptCostPer1k: 0.005,
|
|
130
|
+
completionCostPer1k: 0.015,
|
|
131
|
+
currency: 'USD',
|
|
132
|
+
},
|
|
133
|
+
'generate-medium': {
|
|
134
|
+
promptCostPer1k: 0.001,
|
|
135
|
+
completionCostPer1k: 0.005,
|
|
136
|
+
currency: 'USD',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
private baseUrl = 'https://api.cohere.ai/v1';
|
|
142
|
+
private headers: Record<string, string> = {};
|
|
143
|
+
|
|
144
|
+
protected async doInitialize(): Promise<void> {
|
|
145
|
+
if (!this.config.apiKey) {
|
|
146
|
+
throw new AuthenticationError('Cohere API key is required', 'cohere');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this.headers = {
|
|
150
|
+
'Authorization': `Bearer ${this.config.apiKey}`,
|
|
151
|
+
'Content-Type': 'application/json',
|
|
152
|
+
'Accept': 'application/json',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
protected async doComplete(request: LLMRequest): Promise<LLMResponse> {
|
|
157
|
+
const isChat = request.messages.length > 1 || request.messages[0].role !== 'user';
|
|
158
|
+
const model = request.model || this.config.model;
|
|
159
|
+
|
|
160
|
+
if (isChat && model.startsWith('command')) {
|
|
161
|
+
return this.doChatComplete(request);
|
|
162
|
+
} else {
|
|
163
|
+
return this.doGenerateComplete(request);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private async doChatComplete(request: LLMRequest): Promise<LLMResponse> {
|
|
168
|
+
const messages = this.convertMessages(request.messages);
|
|
169
|
+
const systemMessage = request.messages.find(m => m.role === 'system');
|
|
170
|
+
|
|
171
|
+
const cohereRequest = {
|
|
172
|
+
model: this.mapToCohereModel(request.model || this.config.model),
|
|
173
|
+
messages,
|
|
174
|
+
preamble: systemMessage?.content,
|
|
175
|
+
temperature: request.temperature ?? this.config.temperature,
|
|
176
|
+
max_tokens: request.maxTokens ?? this.config.maxTokens,
|
|
177
|
+
k: request.topK ?? this.config.topK,
|
|
178
|
+
p: request.topP ?? this.config.topP,
|
|
179
|
+
frequency_penalty: request.frequencyPenalty ?? this.config.frequencyPenalty,
|
|
180
|
+
presence_penalty: request.presencePenalty ?? this.config.presencePenalty,
|
|
181
|
+
stop_sequences: request.stopSequences ?? this.config.stopSequences,
|
|
182
|
+
stream: false,
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const controller = new AbortController();
|
|
186
|
+
const timeout = setTimeout(() => controller.abort(), this.config.timeout || 60000);
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
const response = await fetch(`${this.baseUrl}/chat`, {
|
|
190
|
+
method: 'POST',
|
|
191
|
+
headers: this.headers,
|
|
192
|
+
body: JSON.stringify(cohereRequest),
|
|
193
|
+
signal: controller.signal,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
clearTimeout(timeout);
|
|
197
|
+
|
|
198
|
+
if (!response.ok) {
|
|
199
|
+
await this.handleErrorResponse(response);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const data: CohereChatResponse = await response.json();
|
|
203
|
+
|
|
204
|
+
// Calculate cost
|
|
205
|
+
const pricing = this.capabilities.pricing![request.model || this.config.model];
|
|
206
|
+
const promptCost = (data.meta.billed_units.input_tokens / 1000) * pricing.promptCostPer1k;
|
|
207
|
+
const completionCost = (data.meta.billed_units.output_tokens / 1000) * pricing.completionCostPer1k;
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
id: data.generation_id,
|
|
211
|
+
model: request.model || this.config.model,
|
|
212
|
+
provider: 'cohere',
|
|
213
|
+
content: data.text,
|
|
214
|
+
usage: {
|
|
215
|
+
promptTokens: data.meta.billed_units.input_tokens,
|
|
216
|
+
completionTokens: data.meta.billed_units.output_tokens,
|
|
217
|
+
totalTokens: data.meta.billed_units.input_tokens + data.meta.billed_units.output_tokens,
|
|
218
|
+
},
|
|
219
|
+
cost: {
|
|
220
|
+
promptCost,
|
|
221
|
+
completionCost,
|
|
222
|
+
totalCost: promptCost + completionCost,
|
|
223
|
+
currency: 'USD',
|
|
224
|
+
},
|
|
225
|
+
finishReason: this.mapFinishReason(data.finish_reason),
|
|
226
|
+
};
|
|
227
|
+
} catch (error) {
|
|
228
|
+
clearTimeout(timeout);
|
|
229
|
+
throw this.transformError(error);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
private async doGenerateComplete(request: LLMRequest): Promise<LLMResponse> {
|
|
234
|
+
// For generate endpoint, concatenate messages into a prompt
|
|
235
|
+
const prompt = request.messages.map(m => m.content).join('\n\n');
|
|
236
|
+
|
|
237
|
+
const cohereRequest: CohereGenerateRequest = {
|
|
238
|
+
model: this.mapToCohereModel(request.model || this.config.model),
|
|
239
|
+
prompt,
|
|
240
|
+
temperature: request.temperature ?? this.config.temperature,
|
|
241
|
+
max_tokens: request.maxTokens ?? this.config.maxTokens,
|
|
242
|
+
k: request.topK ?? this.config.topK,
|
|
243
|
+
p: request.topP ?? this.config.topP,
|
|
244
|
+
frequency_penalty: request.frequencyPenalty ?? this.config.frequencyPenalty,
|
|
245
|
+
presence_penalty: request.presencePenalty ?? this.config.presencePenalty,
|
|
246
|
+
stop_sequences: request.stopSequences ?? this.config.stopSequences,
|
|
247
|
+
stream: false,
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const controller = new AbortController();
|
|
251
|
+
const timeout = setTimeout(() => controller.abort(), this.config.timeout || 60000);
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
const response = await fetch(`${this.baseUrl}/generate`, {
|
|
255
|
+
method: 'POST',
|
|
256
|
+
headers: this.headers,
|
|
257
|
+
body: JSON.stringify(cohereRequest),
|
|
258
|
+
signal: controller.signal,
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
clearTimeout(timeout);
|
|
262
|
+
|
|
263
|
+
if (!response.ok) {
|
|
264
|
+
await this.handleErrorResponse(response);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const data: CohereGenerateResponse = await response.json();
|
|
268
|
+
const generation = data.generations[0];
|
|
269
|
+
|
|
270
|
+
// Calculate cost
|
|
271
|
+
const pricing = this.capabilities.pricing![request.model || this.config.model];
|
|
272
|
+
const promptCost = (data.meta.billed_units.input_tokens / 1000) * pricing.promptCostPer1k;
|
|
273
|
+
const completionCost = (data.meta.billed_units.output_tokens / 1000) * pricing.completionCostPer1k;
|
|
274
|
+
|
|
275
|
+
return {
|
|
276
|
+
id: generation.id,
|
|
277
|
+
model: request.model || this.config.model,
|
|
278
|
+
provider: 'cohere',
|
|
279
|
+
content: generation.text,
|
|
280
|
+
usage: {
|
|
281
|
+
promptTokens: data.meta.billed_units.input_tokens,
|
|
282
|
+
completionTokens: data.meta.billed_units.output_tokens,
|
|
283
|
+
totalTokens: data.meta.billed_units.input_tokens + data.meta.billed_units.output_tokens,
|
|
284
|
+
},
|
|
285
|
+
cost: {
|
|
286
|
+
promptCost,
|
|
287
|
+
completionCost,
|
|
288
|
+
totalCost: promptCost + completionCost,
|
|
289
|
+
currency: 'USD',
|
|
290
|
+
},
|
|
291
|
+
finishReason: this.mapFinishReason(generation.finish_reason),
|
|
292
|
+
};
|
|
293
|
+
} catch (error) {
|
|
294
|
+
clearTimeout(timeout);
|
|
295
|
+
throw this.transformError(error);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
protected async *doStreamComplete(request: LLMRequest): AsyncIterable<LLMStreamEvent> {
|
|
300
|
+
const isChat = request.messages.length > 1 || request.messages[0].role !== 'user';
|
|
301
|
+
const model = request.model || this.config.model;
|
|
302
|
+
|
|
303
|
+
if (isChat && model.startsWith('command')) {
|
|
304
|
+
yield* this.streamChatComplete(request);
|
|
305
|
+
} else {
|
|
306
|
+
yield* this.streamGenerateComplete(request);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private async *streamChatComplete(request: LLMRequest): AsyncIterable<LLMStreamEvent> {
|
|
311
|
+
const messages = this.convertMessages(request.messages);
|
|
312
|
+
const systemMessage = request.messages.find(m => m.role === 'system');
|
|
313
|
+
|
|
314
|
+
const cohereRequest = {
|
|
315
|
+
model: this.mapToCohereModel(request.model || this.config.model),
|
|
316
|
+
messages,
|
|
317
|
+
preamble: systemMessage?.content,
|
|
318
|
+
temperature: request.temperature ?? this.config.temperature,
|
|
319
|
+
max_tokens: request.maxTokens ?? this.config.maxTokens,
|
|
320
|
+
k: request.topK ?? this.config.topK,
|
|
321
|
+
p: request.topP ?? this.config.topP,
|
|
322
|
+
frequency_penalty: request.frequencyPenalty ?? this.config.frequencyPenalty,
|
|
323
|
+
presence_penalty: request.presencePenalty ?? this.config.presencePenalty,
|
|
324
|
+
stop_sequences: request.stopSequences ?? this.config.stopSequences,
|
|
325
|
+
stream: true,
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
const controller = new AbortController();
|
|
329
|
+
const timeout = setTimeout(() => controller.abort(), (this.config.timeout || 60000) * 2);
|
|
330
|
+
|
|
331
|
+
try {
|
|
332
|
+
const response = await fetch(`${this.baseUrl}/chat`, {
|
|
333
|
+
method: 'POST',
|
|
334
|
+
headers: this.headers,
|
|
335
|
+
body: JSON.stringify(cohereRequest),
|
|
336
|
+
signal: controller.signal,
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
if (!response.ok) {
|
|
340
|
+
await this.handleErrorResponse(response);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const reader = response.body!.getReader();
|
|
344
|
+
const decoder = new TextDecoder();
|
|
345
|
+
let buffer = '';
|
|
346
|
+
let totalContent = '';
|
|
347
|
+
|
|
348
|
+
while (true) {
|
|
349
|
+
const { done, value } = await reader.read();
|
|
350
|
+
if (done) break;
|
|
351
|
+
|
|
352
|
+
buffer += decoder.decode(value, { stream: true });
|
|
353
|
+
const lines = buffer.split('\n');
|
|
354
|
+
buffer = lines.pop() || '';
|
|
355
|
+
|
|
356
|
+
for (const line of lines) {
|
|
357
|
+
if (line.trim() === '') continue;
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
const data = JSON.parse(line);
|
|
361
|
+
|
|
362
|
+
if (data.text) {
|
|
363
|
+
totalContent += data.text;
|
|
364
|
+
yield {
|
|
365
|
+
type: 'content',
|
|
366
|
+
delta: { content: data.text },
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (data.is_finished) {
|
|
371
|
+
// Estimate tokens for streaming
|
|
372
|
+
const promptTokens = this.estimateTokens(JSON.stringify(request.messages));
|
|
373
|
+
const completionTokens = this.estimateTokens(totalContent);
|
|
374
|
+
|
|
375
|
+
const pricing = this.capabilities.pricing![request.model || this.config.model];
|
|
376
|
+
const promptCost = (promptTokens / 1000) * pricing.promptCostPer1k;
|
|
377
|
+
const completionCost = (completionTokens / 1000) * pricing.completionCostPer1k;
|
|
378
|
+
|
|
379
|
+
yield {
|
|
380
|
+
type: 'done',
|
|
381
|
+
usage: {
|
|
382
|
+
promptTokens,
|
|
383
|
+
completionTokens,
|
|
384
|
+
totalTokens: promptTokens + completionTokens,
|
|
385
|
+
},
|
|
386
|
+
cost: {
|
|
387
|
+
promptCost,
|
|
388
|
+
completionCost,
|
|
389
|
+
totalCost: promptCost + completionCost,
|
|
390
|
+
currency: 'USD',
|
|
391
|
+
},
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
} catch (e) {
|
|
395
|
+
this.logger.warn('Failed to parse Cohere stream chunk', { line, error: e });
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
} catch (error) {
|
|
400
|
+
clearTimeout(timeout);
|
|
401
|
+
throw this.transformError(error);
|
|
402
|
+
} finally {
|
|
403
|
+
clearTimeout(timeout);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
private async *streamGenerateComplete(request: LLMRequest): AsyncIterable<LLMStreamEvent> {
|
|
408
|
+
// Similar implementation for generate endpoint
|
|
409
|
+
// Omitted for brevity - follows same pattern as streamChatComplete
|
|
410
|
+
yield* this.streamChatComplete(request); // Fallback to chat for now
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
async listModels(): Promise<LLMModel[]> {
|
|
414
|
+
return this.capabilities.supportedModels;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
async getModelInfo(model: LLMModel): Promise<ModelInfo> {
|
|
418
|
+
return {
|
|
419
|
+
model,
|
|
420
|
+
name: model,
|
|
421
|
+
description: this.getModelDescription(model),
|
|
422
|
+
contextLength: this.capabilities.maxContextLength[model] || 4096,
|
|
423
|
+
maxOutputTokens: this.capabilities.maxOutputTokens[model] || 4096,
|
|
424
|
+
supportedFeatures: [
|
|
425
|
+
'chat',
|
|
426
|
+
'completion',
|
|
427
|
+
'embeddings',
|
|
428
|
+
...(model.startsWith('command') ? ['tools'] : []),
|
|
429
|
+
],
|
|
430
|
+
pricing: this.capabilities.pricing![model],
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
protected async doHealthCheck(): Promise<HealthCheckResult> {
|
|
435
|
+
try {
|
|
436
|
+
const response = await fetch(`${this.baseUrl}/check-api-key`, {
|
|
437
|
+
method: 'POST',
|
|
438
|
+
headers: this.headers,
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
if (!response.ok) {
|
|
442
|
+
throw new Error(`Health check failed: ${response.status}`);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return {
|
|
446
|
+
healthy: true,
|
|
447
|
+
timestamp: new Date(),
|
|
448
|
+
};
|
|
449
|
+
} catch (error) {
|
|
450
|
+
return {
|
|
451
|
+
healthy: false,
|
|
452
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
453
|
+
timestamp: new Date(),
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
private convertMessages(messages: LLMRequest['messages']) {
|
|
459
|
+
return messages
|
|
460
|
+
.filter(m => m.role !== 'system')
|
|
461
|
+
.map(m => ({
|
|
462
|
+
role: m.role === 'assistant' ? 'CHATBOT' as const : 'USER' as const,
|
|
463
|
+
message: m.content,
|
|
464
|
+
}));
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
private mapToCohereModel(model: LLMModel): string {
|
|
468
|
+
const modelMap: Record<string, string> = {
|
|
469
|
+
'command': 'command',
|
|
470
|
+
'command-light': 'command-light',
|
|
471
|
+
'command-nightly': 'command-nightly',
|
|
472
|
+
'generate-xlarge': 'xlarge',
|
|
473
|
+
'generate-medium': 'medium',
|
|
474
|
+
};
|
|
475
|
+
return modelMap[model] || model;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
private mapFinishReason(reason: string): 'stop' | 'length' {
|
|
479
|
+
return reason === 'COMPLETE' ? 'stop' : 'length';
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
private getModelDescription(model: LLMModel): string {
|
|
483
|
+
const descriptions: Record<string, string> = {
|
|
484
|
+
'command': 'Powerful model for complex tasks',
|
|
485
|
+
'command-light': 'Faster, lightweight version of Command',
|
|
486
|
+
'command-nightly': 'Latest experimental Command model',
|
|
487
|
+
'generate-xlarge': 'Large generation model',
|
|
488
|
+
'generate-medium': 'Medium generation model',
|
|
489
|
+
};
|
|
490
|
+
return descriptions[model] || 'Cohere language model';
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
private async handleErrorResponse(response: Response): Promise<void> {
|
|
494
|
+
const errorText = await response.text();
|
|
495
|
+
let errorData: any;
|
|
496
|
+
|
|
497
|
+
try {
|
|
498
|
+
errorData = JSON.parse(errorText);
|
|
499
|
+
} catch {
|
|
500
|
+
errorData = { message: errorText };
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const message = errorData.message || 'Unknown error';
|
|
504
|
+
|
|
505
|
+
switch (response.status) {
|
|
506
|
+
case 401:
|
|
507
|
+
throw new AuthenticationError(message, 'cohere', errorData);
|
|
508
|
+
case 429:
|
|
509
|
+
throw new RateLimitError(message, 'cohere', undefined, errorData);
|
|
510
|
+
default:
|
|
511
|
+
throw new LLMProviderError(
|
|
512
|
+
message,
|
|
513
|
+
`COHERE_${response.status}`,
|
|
514
|
+
'cohere',
|
|
515
|
+
response.status,
|
|
516
|
+
response.status >= 500,
|
|
517
|
+
errorData
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|