graphlit-client 1.0.20250613008 ā 1.0.20250615001
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/README.md +121 -21
- package/dist/client.d.ts +91 -1
- package/dist/client.js +501 -18
- package/dist/generated/graphql-documents.js +7 -0
- package/dist/generated/graphql-types.d.ts +7 -0
- package/dist/model-mapping.js +96 -1
- package/dist/streaming/llm-formatters.d.ts +57 -0
- package/dist/streaming/llm-formatters.js +172 -0
- package/dist/streaming/providers.d.ts +31 -1
- package/dist/streaming/providers.js +621 -1
- package/dist/types/agent.d.ts +15 -0
- package/package.json +17 -1
package/dist/client.js
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
import jwt from "jsonwebtoken";
|
2
2
|
// Apollo core (React-free) - ESM import
|
3
3
|
import { ApolloClient, InMemoryCache, createHttpLink, ApolloLink, ApolloError, } from "@apollo/client/core/index.js";
|
4
|
+
// Apollo retry link for resilient error handling
|
5
|
+
import { RetryLink } from "@apollo/client/link/retry/index.js";
|
4
6
|
import * as Types from "./generated/graphql-types.js";
|
5
7
|
import * as Documents from "./generated/graphql-documents.js";
|
6
8
|
import * as dotenv from "dotenv";
|
7
9
|
import { getServiceType, getModelName } from "./model-mapping.js";
|
8
10
|
import { UIEventAdapter } from "./streaming/ui-event-adapter.js";
|
9
|
-
import { formatMessagesForOpenAI, formatMessagesForAnthropic, formatMessagesForGoogle, } from "./streaming/llm-formatters.js";
|
10
|
-
import { streamWithOpenAI, streamWithAnthropic, streamWithGoogle, } from "./streaming/providers.js";
|
11
|
+
import { formatMessagesForOpenAI, formatMessagesForAnthropic, formatMessagesForGoogle, formatMessagesForCohere, formatMessagesForMistral, formatMessagesForBedrock, } from "./streaming/llm-formatters.js";
|
12
|
+
import { streamWithOpenAI, streamWithAnthropic, streamWithGoogle, streamWithGroq, streamWithCerebras, streamWithCohere, streamWithMistral, streamWithBedrock, streamWithDeepseek, } from "./streaming/providers.js";
|
11
13
|
// Optional imports for streaming LLM clients
|
12
14
|
// These are peer dependencies and may not be installed
|
13
15
|
// We need to use createRequire for optional dependencies to avoid build errors
|
@@ -16,6 +18,10 @@ const optionalRequire = createRequire(import.meta.url);
|
|
16
18
|
let OpenAI;
|
17
19
|
let Anthropic;
|
18
20
|
let GoogleGenerativeAI;
|
21
|
+
let Groq;
|
22
|
+
let CohereClient;
|
23
|
+
let Mistral;
|
24
|
+
let BedrockRuntimeClient;
|
19
25
|
try {
|
20
26
|
OpenAI = optionalRequire("openai").default || optionalRequire("openai");
|
21
27
|
if (process.env.DEBUG_GRAPHLIT_SDK_INITIALIZATION) {
|
@@ -54,6 +60,54 @@ catch (e) {
|
|
54
60
|
console.log("[SDK Loading] Google Generative AI SDK not found:", e.message);
|
55
61
|
}
|
56
62
|
}
|
63
|
+
try {
|
64
|
+
Groq = optionalRequire("groq-sdk").default || optionalRequire("groq-sdk");
|
65
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_INITIALIZATION) {
|
66
|
+
console.log("[SDK Loading] Groq SDK loaded successfully");
|
67
|
+
}
|
68
|
+
}
|
69
|
+
catch (e) {
|
70
|
+
// Groq SDK not installed
|
71
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_INITIALIZATION) {
|
72
|
+
console.log("[SDK Loading] Groq SDK not found:", e.message);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
try {
|
76
|
+
CohereClient = optionalRequire("cohere-ai").CohereClient;
|
77
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_INITIALIZATION) {
|
78
|
+
console.log("[SDK Loading] Cohere SDK loaded successfully");
|
79
|
+
}
|
80
|
+
}
|
81
|
+
catch (e) {
|
82
|
+
// Cohere SDK not installed
|
83
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_INITIALIZATION) {
|
84
|
+
console.log("[SDK Loading] Cohere SDK not found:", e.message);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
try {
|
88
|
+
Mistral = optionalRequire("@mistralai/mistralai").Mistral;
|
89
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_INITIALIZATION) {
|
90
|
+
console.log("[SDK Loading] Mistral SDK loaded successfully");
|
91
|
+
}
|
92
|
+
}
|
93
|
+
catch (e) {
|
94
|
+
// Mistral SDK not installed
|
95
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_INITIALIZATION) {
|
96
|
+
console.log("[SDK Loading] Mistral SDK not found:", e.message);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
try {
|
100
|
+
BedrockRuntimeClient = optionalRequire("@aws-sdk/client-bedrock-runtime").BedrockRuntimeClient;
|
101
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_INITIALIZATION) {
|
102
|
+
console.log("[SDK Loading] Bedrock SDK loaded successfully");
|
103
|
+
}
|
104
|
+
}
|
105
|
+
catch (e) {
|
106
|
+
// Bedrock SDK not installed
|
107
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_INITIALIZATION) {
|
108
|
+
console.log("[SDK Loading] Bedrock SDK not found:", e.message);
|
109
|
+
}
|
110
|
+
}
|
57
111
|
const DEFAULT_MAX_TOOL_ROUNDS = 1000;
|
58
112
|
// Define the Graphlit class
|
59
113
|
class Graphlit {
|
@@ -65,13 +119,37 @@ class Graphlit {
|
|
65
119
|
ownerId;
|
66
120
|
userId;
|
67
121
|
jwtSecret;
|
122
|
+
retryConfig;
|
68
123
|
// Streaming client instances (optional - can be provided by user)
|
69
124
|
openaiClient;
|
70
125
|
anthropicClient;
|
71
126
|
googleClient;
|
72
|
-
|
127
|
+
groqClient;
|
128
|
+
cerebrasClient;
|
129
|
+
cohereClient;
|
130
|
+
mistralClient;
|
131
|
+
bedrockClient;
|
132
|
+
deepseekClient;
|
133
|
+
constructor(organizationIdOrOptions, environmentId, jwtSecret, ownerId, userId, apiUri) {
|
134
|
+
// Handle both old constructor signature and new options object
|
135
|
+
let options;
|
136
|
+
if (typeof organizationIdOrOptions === 'object' && organizationIdOrOptions !== null) {
|
137
|
+
// New constructor with options object
|
138
|
+
options = organizationIdOrOptions;
|
139
|
+
}
|
140
|
+
else {
|
141
|
+
// Legacy constructor with individual parameters
|
142
|
+
options = {
|
143
|
+
organizationId: organizationIdOrOptions,
|
144
|
+
environmentId,
|
145
|
+
jwtSecret,
|
146
|
+
ownerId,
|
147
|
+
userId,
|
148
|
+
apiUri
|
149
|
+
};
|
150
|
+
}
|
73
151
|
this.apiUri =
|
74
|
-
apiUri ||
|
152
|
+
options.apiUri ||
|
75
153
|
(typeof process !== "undefined"
|
76
154
|
? process.env.GRAPHLIT_API_URL
|
77
155
|
: undefined) ||
|
@@ -79,21 +157,30 @@ class Graphlit {
|
|
79
157
|
if (typeof process !== "undefined") {
|
80
158
|
dotenv.config();
|
81
159
|
this.organizationId =
|
82
|
-
organizationId || process.env.GRAPHLIT_ORGANIZATION_ID;
|
83
|
-
this.environmentId = environmentId || process.env.GRAPHLIT_ENVIRONMENT_ID;
|
84
|
-
this.jwtSecret = jwtSecret || process.env.GRAPHLIT_JWT_SECRET;
|
160
|
+
options.organizationId || process.env.GRAPHLIT_ORGANIZATION_ID;
|
161
|
+
this.environmentId = options.environmentId || process.env.GRAPHLIT_ENVIRONMENT_ID;
|
162
|
+
this.jwtSecret = options.jwtSecret || process.env.GRAPHLIT_JWT_SECRET;
|
85
163
|
// optional: for multi-tenant support
|
86
|
-
this.ownerId = ownerId || process.env.GRAPHLIT_OWNER_ID;
|
87
|
-
this.userId = userId || process.env.GRAPHLIT_USER_ID;
|
164
|
+
this.ownerId = options.ownerId || process.env.GRAPHLIT_OWNER_ID;
|
165
|
+
this.userId = options.userId || process.env.GRAPHLIT_USER_ID;
|
88
166
|
}
|
89
167
|
else {
|
90
|
-
this.organizationId = organizationId;
|
91
|
-
this.environmentId = environmentId;
|
92
|
-
this.jwtSecret = jwtSecret;
|
168
|
+
this.organizationId = options.organizationId;
|
169
|
+
this.environmentId = options.environmentId;
|
170
|
+
this.jwtSecret = options.jwtSecret;
|
93
171
|
// optional: for multi-tenant support
|
94
|
-
this.ownerId = ownerId;
|
95
|
-
this.userId = userId;
|
172
|
+
this.ownerId = options.ownerId;
|
173
|
+
this.userId = options.userId;
|
96
174
|
}
|
175
|
+
// Set default retry configuration
|
176
|
+
this.retryConfig = {
|
177
|
+
maxAttempts: 5,
|
178
|
+
initialDelay: 300,
|
179
|
+
maxDelay: 30000,
|
180
|
+
retryableStatusCodes: [429, 502, 503, 504],
|
181
|
+
jitter: true,
|
182
|
+
...options.retryConfig
|
183
|
+
};
|
97
184
|
if (!this.organizationId) {
|
98
185
|
throw new Error("Graphlit organization identifier is required.");
|
99
186
|
}
|
@@ -111,6 +198,42 @@ class Graphlit {
|
|
111
198
|
const httpLink = createHttpLink({
|
112
199
|
uri: this.apiUri,
|
113
200
|
});
|
201
|
+
// Create retry link with configuration
|
202
|
+
const retryLink = new RetryLink({
|
203
|
+
delay: {
|
204
|
+
initial: this.retryConfig.initialDelay || 300,
|
205
|
+
max: this.retryConfig.maxDelay || 30000,
|
206
|
+
jitter: this.retryConfig.jitter !== false,
|
207
|
+
},
|
208
|
+
attempts: {
|
209
|
+
max: this.retryConfig.maxAttempts || 5,
|
210
|
+
retryIf: (error, _operation) => {
|
211
|
+
// Check if we should retry this error
|
212
|
+
if (!error)
|
213
|
+
return false;
|
214
|
+
// Check for network errors
|
215
|
+
const hasNetworkError = !!error.networkError;
|
216
|
+
if (!hasNetworkError)
|
217
|
+
return false;
|
218
|
+
// Get status code from different possible locations
|
219
|
+
const statusCode = error.networkError?.statusCode ||
|
220
|
+
error.networkError?.response?.status ||
|
221
|
+
error.statusCode;
|
222
|
+
// Check if status code is retryable
|
223
|
+
if (statusCode && this.retryConfig.retryableStatusCodes) {
|
224
|
+
const shouldRetry = this.retryConfig.retryableStatusCodes.includes(statusCode);
|
225
|
+
// Call onRetry callback if provided
|
226
|
+
if (shouldRetry && this.retryConfig.onRetry && _operation.getContext().retryCount !== undefined) {
|
227
|
+
const attempt = _operation.getContext().retryCount + 1;
|
228
|
+
this.retryConfig.onRetry(attempt, error, _operation);
|
229
|
+
}
|
230
|
+
return shouldRetry;
|
231
|
+
}
|
232
|
+
// Default: retry on network errors without specific status codes
|
233
|
+
return true;
|
234
|
+
},
|
235
|
+
},
|
236
|
+
});
|
114
237
|
const authLink = new ApolloLink((operation, forward) => {
|
115
238
|
operation.setContext({
|
116
239
|
headers: {
|
@@ -119,8 +242,9 @@ class Graphlit {
|
|
119
242
|
});
|
120
243
|
return forward(operation);
|
121
244
|
});
|
245
|
+
// Chain links: retry -> auth -> http
|
122
246
|
this.client = new ApolloClient({
|
123
|
-
link:
|
247
|
+
link: ApolloLink.from([retryLink, authLink, httpLink]),
|
124
248
|
cache: new InMemoryCache(),
|
125
249
|
defaultOptions: {
|
126
250
|
watchQuery: {
|
@@ -159,6 +283,60 @@ class Graphlit {
|
|
159
283
|
setGoogleClient(client) {
|
160
284
|
this.googleClient = client;
|
161
285
|
}
|
286
|
+
/**
|
287
|
+
* Set a custom Groq client instance for streaming
|
288
|
+
* @param client - Groq client instance (e.g., new Groq({ apiKey: "..." }))
|
289
|
+
*/
|
290
|
+
setGroqClient(client) {
|
291
|
+
this.groqClient = client;
|
292
|
+
}
|
293
|
+
/**
|
294
|
+
* Set a custom Cerebras client instance for streaming (OpenAI-compatible)
|
295
|
+
* @param client - OpenAI client instance configured for Cerebras (e.g., new OpenAI({ apiKey: "...", baseURL: "https://api.cerebras.ai/v1" }))
|
296
|
+
*/
|
297
|
+
setCerebrasClient(client) {
|
298
|
+
this.cerebrasClient = client;
|
299
|
+
}
|
300
|
+
/**
|
301
|
+
* Set a custom Cohere client instance for streaming
|
302
|
+
* @param client - Cohere client instance (e.g., new CohereClient({ token: "..." }))
|
303
|
+
*/
|
304
|
+
setCohereClient(client) {
|
305
|
+
this.cohereClient = client;
|
306
|
+
}
|
307
|
+
/**
|
308
|
+
* Set a custom Mistral client instance for streaming
|
309
|
+
* @param client - Mistral client instance (e.g., new Mistral({ apiKey: "..." }))
|
310
|
+
*/
|
311
|
+
setMistralClient(client) {
|
312
|
+
this.mistralClient = client;
|
313
|
+
}
|
314
|
+
/**
|
315
|
+
* Set a custom Bedrock client instance for streaming
|
316
|
+
* @param client - BedrockRuntimeClient instance (e.g., new BedrockRuntimeClient({ region: "us-east-2" }))
|
317
|
+
*/
|
318
|
+
setBedrockClient(client) {
|
319
|
+
this.bedrockClient = client;
|
320
|
+
}
|
321
|
+
/**
|
322
|
+
* Set a custom Deepseek client instance for streaming
|
323
|
+
* @param client - OpenAI client instance configured for Deepseek (e.g., new OpenAI({ baseURL: "https://api.deepseek.com", apiKey: "..." }))
|
324
|
+
*/
|
325
|
+
setDeepseekClient(client) {
|
326
|
+
this.deepseekClient = client;
|
327
|
+
}
|
328
|
+
/**
|
329
|
+
* Update retry configuration and refresh the Apollo client
|
330
|
+
* @param retryConfig - New retry configuration
|
331
|
+
*/
|
332
|
+
setRetryConfig(retryConfig) {
|
333
|
+
this.retryConfig = {
|
334
|
+
...this.retryConfig,
|
335
|
+
...retryConfig
|
336
|
+
};
|
337
|
+
// Refresh client to apply new retry configuration
|
338
|
+
this.refreshClient();
|
339
|
+
}
|
162
340
|
generateToken() {
|
163
341
|
if (!this.jwtSecret) {
|
164
342
|
throw new Error("Graphlit environment JWT secret is required.");
|
@@ -1438,6 +1616,19 @@ class Graphlit {
|
|
1438
1616
|
return Anthropic !== undefined || this.anthropicClient !== undefined;
|
1439
1617
|
case Types.ModelServiceTypes.Google:
|
1440
1618
|
return (GoogleGenerativeAI !== undefined || this.googleClient !== undefined);
|
1619
|
+
case Types.ModelServiceTypes.Groq:
|
1620
|
+
return Groq !== undefined || this.groqClient !== undefined;
|
1621
|
+
case Types.ModelServiceTypes.Cerebras:
|
1622
|
+
return OpenAI !== undefined || this.cerebrasClient !== undefined;
|
1623
|
+
case Types.ModelServiceTypes.Cohere:
|
1624
|
+
return CohereClient !== undefined || this.cohereClient !== undefined;
|
1625
|
+
case Types.ModelServiceTypes.Mistral:
|
1626
|
+
return Mistral !== undefined || this.mistralClient !== undefined;
|
1627
|
+
case Types.ModelServiceTypes.Bedrock:
|
1628
|
+
return (BedrockRuntimeClient !== undefined ||
|
1629
|
+
this.bedrockClient !== undefined);
|
1630
|
+
case Types.ModelServiceTypes.Deepseek:
|
1631
|
+
return OpenAI !== undefined || this.deepseekClient !== undefined;
|
1441
1632
|
default:
|
1442
1633
|
return false;
|
1443
1634
|
}
|
@@ -1447,7 +1638,19 @@ class Graphlit {
|
|
1447
1638
|
const hasOpenAI = OpenAI !== undefined || this.openaiClient !== undefined;
|
1448
1639
|
const hasAnthropic = Anthropic !== undefined || this.anthropicClient !== undefined;
|
1449
1640
|
const hasGoogle = GoogleGenerativeAI !== undefined || this.googleClient !== undefined;
|
1450
|
-
|
1641
|
+
const hasGroq = Groq !== undefined || this.groqClient !== undefined;
|
1642
|
+
const hasCerebras = OpenAI !== undefined || this.cerebrasClient !== undefined;
|
1643
|
+
const hasCohere = CohereClient !== undefined || this.cohereClient !== undefined;
|
1644
|
+
const hasMistral = Mistral !== undefined || this.mistralClient !== undefined;
|
1645
|
+
const hasBedrock = BedrockRuntimeClient !== undefined || this.bedrockClient !== undefined;
|
1646
|
+
return (hasOpenAI ||
|
1647
|
+
hasAnthropic ||
|
1648
|
+
hasGoogle ||
|
1649
|
+
hasGroq ||
|
1650
|
+
hasCerebras ||
|
1651
|
+
hasCohere ||
|
1652
|
+
hasMistral ||
|
1653
|
+
hasBedrock);
|
1451
1654
|
}
|
1452
1655
|
/**
|
1453
1656
|
* Execute an agent with non-streaming response
|
@@ -1499,13 +1702,17 @@ class Graphlit {
|
|
1499
1702
|
// 3. Tool calling loop
|
1500
1703
|
const allToolCalls = [];
|
1501
1704
|
let rounds = 0;
|
1502
|
-
let totalTokens = 0;
|
1705
|
+
let totalTokens = currentMessage?.tokens || 0;
|
1706
|
+
const toolStartTime = Date.now();
|
1707
|
+
let toolTime = 0;
|
1503
1708
|
while (currentMessage.toolCalls?.length &&
|
1504
1709
|
rounds < maxRounds &&
|
1505
1710
|
!abortController.signal.aborted) {
|
1506
1711
|
rounds++;
|
1507
1712
|
// Execute tools
|
1713
|
+
const toolExecStart = Date.now();
|
1508
1714
|
const toolResults = await this.executeToolsForPromptAgent(currentMessage.toolCalls.filter((tc) => tc !== null), toolHandlers || {}, allToolCalls, abortController.signal);
|
1715
|
+
toolTime += Date.now() - toolExecStart;
|
1509
1716
|
if (abortController.signal.aborted) {
|
1510
1717
|
throw new Error("Operation timed out");
|
1511
1718
|
}
|
@@ -1519,9 +1726,35 @@ class Graphlit {
|
|
1519
1726
|
totalTokens += continueResponse.continueConversation.message.tokens;
|
1520
1727
|
}
|
1521
1728
|
}
|
1729
|
+
// Calculate metrics
|
1730
|
+
const totalTime = Date.now() - startTime;
|
1731
|
+
const llmTime = totalTime - toolTime;
|
1732
|
+
const metrics = {
|
1733
|
+
totalTime,
|
1734
|
+
llmTime,
|
1735
|
+
toolTime,
|
1736
|
+
toolExecutions: allToolCalls.length,
|
1737
|
+
rounds,
|
1738
|
+
};
|
1739
|
+
// Build usage info if we have token data
|
1740
|
+
const usage = totalTokens > 0
|
1741
|
+
? {
|
1742
|
+
promptTokens: 0, // We don't have this breakdown from the API
|
1743
|
+
completionTokens: totalTokens,
|
1744
|
+
totalTokens: totalTokens,
|
1745
|
+
model: currentMessage?.model || undefined,
|
1746
|
+
}
|
1747
|
+
: undefined;
|
1522
1748
|
return {
|
1523
1749
|
message: currentMessage?.message || "",
|
1524
1750
|
conversationId: actualConversationId,
|
1751
|
+
conversationMessage: currentMessage
|
1752
|
+
? currentMessage
|
1753
|
+
: undefined,
|
1754
|
+
toolCalls: currentMessage?.toolCalls?.filter((tc) => tc !== null),
|
1755
|
+
toolResults: allToolCalls,
|
1756
|
+
metrics,
|
1757
|
+
usage,
|
1525
1758
|
};
|
1526
1759
|
}
|
1527
1760
|
catch (error) {
|
@@ -1536,6 +1769,14 @@ class Graphlit {
|
|
1536
1769
|
recoverable: isTimeout || error.code === "RATE_LIMIT",
|
1537
1770
|
details: error.response?.data,
|
1538
1771
|
},
|
1772
|
+
// Include partial metrics if available
|
1773
|
+
metrics: {
|
1774
|
+
totalTime: Date.now() - startTime,
|
1775
|
+
llmTime: 0,
|
1776
|
+
toolTime: 0,
|
1777
|
+
toolExecutions: 0,
|
1778
|
+
rounds: 0,
|
1779
|
+
},
|
1539
1780
|
};
|
1540
1781
|
}
|
1541
1782
|
finally {
|
@@ -1573,6 +1814,17 @@ class Graphlit {
|
|
1573
1814
|
? (await this.getSpecification(specification.id))
|
1574
1815
|
.specification
|
1575
1816
|
: undefined;
|
1817
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING && fullSpec) {
|
1818
|
+
console.log(`š [streamAgent] Retrieved full specification:`, {
|
1819
|
+
id: fullSpec.id,
|
1820
|
+
name: fullSpec.name,
|
1821
|
+
serviceType: fullSpec.serviceType,
|
1822
|
+
hasDeepseek: !!fullSpec.deepseek,
|
1823
|
+
deepseekModel: fullSpec.deepseek?.model,
|
1824
|
+
deepseekModelName: fullSpec.deepseek?.modelName,
|
1825
|
+
deepseekTemperature: fullSpec.deepseek?.temperature,
|
1826
|
+
});
|
1827
|
+
}
|
1576
1828
|
// Ensure conversation exists first (before streaming check)
|
1577
1829
|
let actualConversationId = conversationId;
|
1578
1830
|
if (!actualConversationId) {
|
@@ -1689,7 +1941,7 @@ class Graphlit {
|
|
1689
1941
|
if (!formattedMessage?.message) {
|
1690
1942
|
throw new Error("Failed to format conversation");
|
1691
1943
|
}
|
1692
|
-
if (process.env.
|
1944
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING_FORMAT) {
|
1693
1945
|
console.log("\nš [formatConversation] Full response:", JSON.stringify(formatResponse, null, 2));
|
1694
1946
|
console.log("\nš [formatConversation] Response - current message:", formattedMessage.message);
|
1695
1947
|
console.log(`š [formatConversation] Conversation history: ${conversationHistory?.length || 0} messages`);
|
@@ -1830,6 +2082,108 @@ class Graphlit {
|
|
1830
2082
|
console.log(`\nš [Streaming] Google native streaming completed (Round ${currentRound})`);
|
1831
2083
|
}
|
1832
2084
|
}
|
2085
|
+
else if (serviceType === Types.ModelServiceTypes.Groq &&
|
2086
|
+
(Groq || this.groqClient)) {
|
2087
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2088
|
+
console.log(`\nā
[Streaming] Using Groq native streaming (Round ${currentRound})`);
|
2089
|
+
}
|
2090
|
+
const groqMessages = formatMessagesForOpenAI(messages); // Groq uses OpenAI format
|
2091
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING_MESSAGES) {
|
2092
|
+
console.log(`š [Groq] Sending ${groqMessages.length} messages to LLM: ${JSON.stringify(groqMessages)}`);
|
2093
|
+
}
|
2094
|
+
await this.streamWithGroq(specification, groqMessages, tools, uiAdapter, (message, calls) => {
|
2095
|
+
roundMessage = message;
|
2096
|
+
toolCalls = calls;
|
2097
|
+
});
|
2098
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2099
|
+
console.log(`\nš [Streaming] Groq native streaming completed (Round ${currentRound})`);
|
2100
|
+
}
|
2101
|
+
}
|
2102
|
+
else if (serviceType === Types.ModelServiceTypes.Cerebras &&
|
2103
|
+
(OpenAI || this.cerebrasClient)) {
|
2104
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2105
|
+
console.log(`\nā
[Streaming] Using Cerebras native streaming (Round ${currentRound})`);
|
2106
|
+
}
|
2107
|
+
const cerebrasMessages = formatMessagesForOpenAI(messages); // Cerebras uses OpenAI format
|
2108
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING_MESSAGES) {
|
2109
|
+
console.log(`š [Cerebras] Sending ${cerebrasMessages.length} messages to LLM: ${JSON.stringify(cerebrasMessages)}`);
|
2110
|
+
}
|
2111
|
+
await this.streamWithCerebras(specification, cerebrasMessages, tools, uiAdapter, (message, calls) => {
|
2112
|
+
roundMessage = message;
|
2113
|
+
toolCalls = calls;
|
2114
|
+
});
|
2115
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2116
|
+
console.log(`\nš [Streaming] Cerebras native streaming completed (Round ${currentRound})`);
|
2117
|
+
}
|
2118
|
+
}
|
2119
|
+
else if (serviceType === Types.ModelServiceTypes.Cohere &&
|
2120
|
+
(CohereClient || this.cohereClient)) {
|
2121
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2122
|
+
console.log(`\nā
[Streaming] Using Cohere native streaming (Round ${currentRound})`);
|
2123
|
+
}
|
2124
|
+
const cohereMessages = formatMessagesForCohere(messages);
|
2125
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING_MESSAGES) {
|
2126
|
+
console.log(`š [Cohere] Sending ${cohereMessages.length} messages to LLM: ${JSON.stringify(cohereMessages)}`);
|
2127
|
+
}
|
2128
|
+
await this.streamWithCohere(specification, cohereMessages, tools, uiAdapter, (message, calls) => {
|
2129
|
+
roundMessage = message;
|
2130
|
+
toolCalls = calls;
|
2131
|
+
});
|
2132
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2133
|
+
console.log(`\nš [Streaming] Cohere native streaming completed (Round ${currentRound})`);
|
2134
|
+
}
|
2135
|
+
}
|
2136
|
+
else if (serviceType === Types.ModelServiceTypes.Mistral &&
|
2137
|
+
(Mistral || this.mistralClient)) {
|
2138
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2139
|
+
console.log(`\nā
[Streaming] Using Mistral native streaming (Round ${currentRound})`);
|
2140
|
+
}
|
2141
|
+
const mistralMessages = formatMessagesForMistral(messages);
|
2142
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING_MESSAGES) {
|
2143
|
+
console.log(`š [Mistral] Sending ${mistralMessages.length} messages to LLM: ${JSON.stringify(mistralMessages)}`);
|
2144
|
+
}
|
2145
|
+
await this.streamWithMistral(specification, mistralMessages, tools, uiAdapter, (message, calls) => {
|
2146
|
+
roundMessage = message;
|
2147
|
+
toolCalls = calls;
|
2148
|
+
});
|
2149
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2150
|
+
console.log(`\nš [Streaming] Mistral native streaming completed (Round ${currentRound})`);
|
2151
|
+
}
|
2152
|
+
}
|
2153
|
+
else if (serviceType === Types.ModelServiceTypes.Bedrock &&
|
2154
|
+
(BedrockRuntimeClient || this.bedrockClient)) {
|
2155
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2156
|
+
console.log(`\nā
[Streaming] Using Bedrock native streaming (Round ${currentRound})`);
|
2157
|
+
}
|
2158
|
+
const { system, messages: bedrockMessages } = formatMessagesForBedrock(messages);
|
2159
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING_MESSAGES) {
|
2160
|
+
console.log(`š [Bedrock] Sending ${bedrockMessages.length} messages to LLM (system: ${system ? "yes" : "no"}): ${JSON.stringify(bedrockMessages)}`);
|
2161
|
+
}
|
2162
|
+
await this.streamWithBedrock(specification, bedrockMessages, system, tools, uiAdapter, (message, calls) => {
|
2163
|
+
roundMessage = message;
|
2164
|
+
toolCalls = calls;
|
2165
|
+
});
|
2166
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2167
|
+
console.log(`\nš [Streaming] Bedrock native streaming completed (Round ${currentRound})`);
|
2168
|
+
}
|
2169
|
+
}
|
2170
|
+
else if (serviceType === Types.ModelServiceTypes.Deepseek &&
|
2171
|
+
(OpenAI || this.deepseekClient)) {
|
2172
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2173
|
+
console.log(`\nā
[Streaming] Using Deepseek native streaming (Round ${currentRound})`);
|
2174
|
+
}
|
2175
|
+
const deepseekMessages = formatMessagesForOpenAI(messages); // Deepseek uses OpenAI format
|
2176
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING_MESSAGES) {
|
2177
|
+
console.log(`š [Deepseek] Sending ${deepseekMessages.length} messages to LLM: ${JSON.stringify(deepseekMessages)}`);
|
2178
|
+
}
|
2179
|
+
await this.streamWithDeepseek(specification, deepseekMessages, tools, uiAdapter, (message, calls) => {
|
2180
|
+
roundMessage = message;
|
2181
|
+
toolCalls = calls;
|
2182
|
+
});
|
2183
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2184
|
+
console.log(`\nš [Streaming] Deepseek native streaming completed (Round ${currentRound})`);
|
2185
|
+
}
|
2186
|
+
}
|
1833
2187
|
else {
|
1834
2188
|
// Fallback to non-streaming
|
1835
2189
|
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
@@ -2215,6 +2569,135 @@ class Graphlit {
|
|
2215
2569
|
}
|
2216
2570
|
await streamWithGoogle(specification, messages, systemPrompt, tools, googleClient, (event) => uiAdapter.handleEvent(event), onComplete);
|
2217
2571
|
}
|
2572
|
+
/**
|
2573
|
+
* Stream with Groq client (OpenAI-compatible)
|
2574
|
+
*/
|
2575
|
+
async streamWithGroq(specification, messages, tools, uiAdapter, onComplete) {
|
2576
|
+
// Check if we have either the Groq module or a provided client
|
2577
|
+
if (!Groq && !this.groqClient) {
|
2578
|
+
throw new Error("Groq client not available");
|
2579
|
+
}
|
2580
|
+
// Use provided client or create a new one
|
2581
|
+
const groqClient = this.groqClient ||
|
2582
|
+
(Groq
|
2583
|
+
? new Groq({ apiKey: process.env.GROQ_API_KEY || "" })
|
2584
|
+
: (() => {
|
2585
|
+
throw new Error("Groq module not available");
|
2586
|
+
})());
|
2587
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2588
|
+
console.log(`š [Graphlit SDK] Routing to Groq streaming provider | Spec: ${specification.name} (${specification.id}) | Messages: ${messages.length} | Tools: ${tools?.length || 0}`);
|
2589
|
+
}
|
2590
|
+
await streamWithGroq(specification, messages, tools, groqClient, (event) => uiAdapter.handleEvent(event), onComplete);
|
2591
|
+
}
|
2592
|
+
/**
|
2593
|
+
* Stream with Cerebras client (OpenAI-compatible)
|
2594
|
+
*/
|
2595
|
+
async streamWithCerebras(specification, messages, tools, uiAdapter, onComplete) {
|
2596
|
+
// Check if we have either the OpenAI module or a provided client
|
2597
|
+
if (!OpenAI && !this.cerebrasClient) {
|
2598
|
+
throw new Error("Cerebras client not available");
|
2599
|
+
}
|
2600
|
+
// Use provided client or create a new one configured for Cerebras
|
2601
|
+
const cerebrasClient = this.cerebrasClient ||
|
2602
|
+
(OpenAI
|
2603
|
+
? new OpenAI({
|
2604
|
+
apiKey: process.env.CEREBRAS_API_KEY || "",
|
2605
|
+
baseURL: "https://api.cerebras.ai/v1",
|
2606
|
+
})
|
2607
|
+
: (() => {
|
2608
|
+
throw new Error("OpenAI module not available for Cerebras");
|
2609
|
+
})());
|
2610
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2611
|
+
console.log(`š [Graphlit SDK] Routing to Cerebras streaming provider | Spec: ${specification.name} (${specification.id}) | Messages: ${messages.length} | Tools: ${tools?.length || 0}`);
|
2612
|
+
}
|
2613
|
+
await streamWithCerebras(specification, messages, tools, cerebrasClient, (event) => uiAdapter.handleEvent(event), onComplete);
|
2614
|
+
}
|
2615
|
+
/**
|
2616
|
+
* Stream with Cohere client
|
2617
|
+
*/
|
2618
|
+
async streamWithCohere(specification, messages, tools, uiAdapter, onComplete) {
|
2619
|
+
// Check if we have either the Cohere module or a provided client
|
2620
|
+
if (!CohereClient && !this.cohereClient) {
|
2621
|
+
throw new Error("Cohere client not available");
|
2622
|
+
}
|
2623
|
+
// Use provided client or create a new one
|
2624
|
+
const cohereClient = this.cohereClient ||
|
2625
|
+
(CohereClient
|
2626
|
+
? new CohereClient({ token: process.env.COHERE_API_KEY || "" })
|
2627
|
+
: (() => {
|
2628
|
+
throw new Error("Cohere module not available");
|
2629
|
+
})());
|
2630
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2631
|
+
console.log(`š [Graphlit SDK] Routing to Cohere streaming provider | Spec: ${specification.name} (${specification.id}) | Messages: ${messages.length} | Tools: ${tools?.length || 0}`);
|
2632
|
+
}
|
2633
|
+
await streamWithCohere(specification, messages, tools, cohereClient, (event) => uiAdapter.handleEvent(event), onComplete);
|
2634
|
+
}
|
2635
|
+
/**
|
2636
|
+
* Stream with Mistral client
|
2637
|
+
*/
|
2638
|
+
async streamWithMistral(specification, messages, tools, uiAdapter, onComplete) {
|
2639
|
+
// Check if we have either the Mistral module or a provided client
|
2640
|
+
if (!Mistral && !this.mistralClient) {
|
2641
|
+
throw new Error("Mistral client not available");
|
2642
|
+
}
|
2643
|
+
// Use provided client or create a new one
|
2644
|
+
const mistralClient = this.mistralClient ||
|
2645
|
+
(Mistral
|
2646
|
+
? new Mistral({ apiKey: process.env.MISTRAL_API_KEY || "" })
|
2647
|
+
: (() => {
|
2648
|
+
throw new Error("Mistral module not available");
|
2649
|
+
})());
|
2650
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2651
|
+
console.log(`š [Graphlit SDK] Routing to Mistral streaming provider | Spec: ${specification.name} (${specification.id}) | Messages: ${messages.length} | Tools: ${tools?.length || 0}`);
|
2652
|
+
}
|
2653
|
+
await streamWithMistral(specification, messages, tools, mistralClient, (event) => uiAdapter.handleEvent(event), onComplete);
|
2654
|
+
}
|
2655
|
+
/**
|
2656
|
+
* Stream with Bedrock client
|
2657
|
+
*/
|
2658
|
+
async streamWithBedrock(specification, messages, systemPrompt, tools, uiAdapter, onComplete) {
|
2659
|
+
// Check if we have either the Bedrock module or a provided client
|
2660
|
+
if (!BedrockRuntimeClient && !this.bedrockClient) {
|
2661
|
+
throw new Error("Bedrock client not available");
|
2662
|
+
}
|
2663
|
+
// Use provided client or create a new one
|
2664
|
+
const bedrockClient = this.bedrockClient ||
|
2665
|
+
(BedrockRuntimeClient
|
2666
|
+
? new BedrockRuntimeClient({
|
2667
|
+
region: process.env.AWS_REGION || "us-east-2",
|
2668
|
+
})
|
2669
|
+
: (() => {
|
2670
|
+
throw new Error("Bedrock module not available");
|
2671
|
+
})());
|
2672
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2673
|
+
console.log(`š [Graphlit SDK] Routing to Bedrock streaming provider | Spec: ${specification.name} (${specification.id}) | Messages: ${messages.length} | Tools: ${tools?.length || 0} | SystemPrompt: ${systemPrompt ? "Yes" : "No"}`);
|
2674
|
+
}
|
2675
|
+
await streamWithBedrock(specification, messages, systemPrompt, tools, bedrockClient, (event) => uiAdapter.handleEvent(event), onComplete);
|
2676
|
+
}
|
2677
|
+
/**
|
2678
|
+
* Stream with Deepseek client
|
2679
|
+
*/
|
2680
|
+
async streamWithDeepseek(specification, messages, tools, uiAdapter, onComplete) {
|
2681
|
+
// Check if we have either the OpenAI module or a provided Deepseek client
|
2682
|
+
if (!OpenAI && !this.deepseekClient) {
|
2683
|
+
throw new Error("Deepseek client not available (requires OpenAI SDK)");
|
2684
|
+
}
|
2685
|
+
// Use provided client or create a new one with Deepseek base URL
|
2686
|
+
const deepseekClient = this.deepseekClient ||
|
2687
|
+
(OpenAI
|
2688
|
+
? new OpenAI({
|
2689
|
+
baseURL: "https://api.deepseek.com",
|
2690
|
+
apiKey: process.env.DEEPSEEK_API_KEY || "",
|
2691
|
+
})
|
2692
|
+
: null);
|
2693
|
+
if (!deepseekClient) {
|
2694
|
+
throw new Error("Failed to create Deepseek client");
|
2695
|
+
}
|
2696
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
2697
|
+
console.log(`š [Graphlit SDK] Routing to Deepseek streaming provider | Spec: ${specification.name} (${specification.id}) | Messages: ${messages.length} | Tools: ${tools?.length || 0}`);
|
2698
|
+
}
|
2699
|
+
await streamWithDeepseek(specification, messages, tools, deepseekClient, (event) => uiAdapter.handleEvent(event), onComplete);
|
2700
|
+
}
|
2218
2701
|
// Helper method to execute tools for promptAgent
|
2219
2702
|
async executeToolsForPromptAgent(toolCalls, toolHandlers, allToolCalls, signal) {
|
2220
2703
|
const responses = [];
|