graphlit-client 1.0.20250612008 → 1.0.20250612009
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/dist/client.js
CHANGED
@@ -4,7 +4,7 @@ import { ApolloClient, InMemoryCache, createHttpLink, ApolloLink, ApolloError, }
|
|
4
4
|
import * as Types from "./generated/graphql-types.js";
|
5
5
|
import * as Documents from "./generated/graphql-documents.js";
|
6
6
|
import * as dotenv from "dotenv";
|
7
|
-
import { getServiceType } from "./model-mapping.js";
|
7
|
+
import { getServiceType, getModelName } from "./model-mapping.js";
|
8
8
|
import { UIEventAdapter } from "./streaming/ui-event-adapter.js";
|
9
9
|
import { formatMessagesForOpenAI, formatMessagesForAnthropic, formatMessagesForGoogle, } from "./streaming/llm-formatters.js";
|
10
10
|
import { streamWithOpenAI, streamWithAnthropic, streamWithGoogle, } from "./streaming/providers.js";
|
@@ -1626,11 +1626,15 @@ class Graphlit {
|
|
1626
1626
|
});
|
1627
1627
|
return; // Exit early after successful fallback
|
1628
1628
|
}
|
1629
|
-
// Create UI event adapter
|
1629
|
+
// Create UI event adapter with model information
|
1630
|
+
const modelName = fullSpec ? getModelName(fullSpec) : undefined;
|
1631
|
+
const serviceType = fullSpec ? getServiceType(fullSpec) : undefined;
|
1630
1632
|
uiAdapter = new UIEventAdapter(onEvent, actualConversationId, {
|
1631
1633
|
smoothingEnabled: options?.smoothingEnabled ?? true,
|
1632
1634
|
chunkingStrategy: options?.chunkingStrategy ?? "word",
|
1633
1635
|
smoothingDelay: options?.smoothingDelay ?? 30,
|
1636
|
+
model: modelName,
|
1637
|
+
modelService: serviceType,
|
1634
1638
|
});
|
1635
1639
|
// Start the streaming conversation
|
1636
1640
|
await this.executeStreamingAgent(prompt, actualConversationId, fullSpec, tools, toolHandlers, uiAdapter, maxRounds, abortSignal, mimeType, data, correlationId);
|
@@ -9,8 +9,13 @@ export declare class UIEventAdapter {
|
|
9
9
|
private onEvent;
|
10
10
|
private conversationId;
|
11
11
|
private model?;
|
12
|
+
private modelService?;
|
13
|
+
private tokenCount;
|
12
14
|
private currentMessage;
|
13
15
|
private isStreaming;
|
16
|
+
private streamStartTime;
|
17
|
+
private firstTokenTime;
|
18
|
+
private lastTokenTime;
|
14
19
|
private activeToolCalls;
|
15
20
|
private lastUpdateTime;
|
16
21
|
private updateTimer?;
|
@@ -21,6 +26,8 @@ export declare class UIEventAdapter {
|
|
21
26
|
smoothingEnabled?: boolean;
|
22
27
|
chunkingStrategy?: ChunkingStrategy;
|
23
28
|
smoothingDelay?: number;
|
29
|
+
model?: string;
|
30
|
+
modelService?: string;
|
24
31
|
});
|
25
32
|
/**
|
26
33
|
* Process a raw streaming event and emit appropriate UI events
|
@@ -8,8 +8,13 @@ export class UIEventAdapter {
|
|
8
8
|
onEvent;
|
9
9
|
conversationId;
|
10
10
|
model;
|
11
|
+
modelService;
|
12
|
+
tokenCount = 0;
|
11
13
|
currentMessage = "";
|
12
14
|
isStreaming = false;
|
15
|
+
streamStartTime = 0;
|
16
|
+
firstTokenTime = 0;
|
17
|
+
lastTokenTime = 0;
|
13
18
|
activeToolCalls = new Map();
|
14
19
|
lastUpdateTime = 0;
|
15
20
|
updateTimer;
|
@@ -20,6 +25,8 @@ export class UIEventAdapter {
|
|
20
25
|
this.onEvent = onEvent;
|
21
26
|
this.conversationId = conversationId;
|
22
27
|
this.smoothingDelay = options.smoothingDelay ?? 30;
|
28
|
+
this.model = options.model;
|
29
|
+
this.modelService = options.modelService;
|
23
30
|
if (options.smoothingEnabled) {
|
24
31
|
this.chunkBuffer = new ChunkBuffer(options.chunkingStrategy || "word");
|
25
32
|
}
|
@@ -84,6 +91,9 @@ export class UIEventAdapter {
|
|
84
91
|
handleStart(conversationId) {
|
85
92
|
this.conversationId = conversationId;
|
86
93
|
this.isStreaming = true;
|
94
|
+
this.streamStartTime = Date.now();
|
95
|
+
this.firstTokenTime = 0;
|
96
|
+
this.lastTokenTime = 0;
|
87
97
|
this.emitUIEvent({
|
88
98
|
type: "conversation_started",
|
89
99
|
conversationId,
|
@@ -92,6 +102,12 @@ export class UIEventAdapter {
|
|
92
102
|
});
|
93
103
|
}
|
94
104
|
handleToken(token) {
|
105
|
+
// Track timing for first token
|
106
|
+
const now = Date.now();
|
107
|
+
if (this.firstTokenTime === 0) {
|
108
|
+
this.firstTokenTime = now;
|
109
|
+
}
|
110
|
+
this.lastTokenTime = now;
|
95
111
|
if (this.chunkBuffer) {
|
96
112
|
const chunks = this.chunkBuffer.addToken(token);
|
97
113
|
// Add chunks to queue for all chunking modes (character, word, sentence)
|
@@ -178,7 +194,7 @@ export class UIEventAdapter {
|
|
178
194
|
}
|
179
195
|
}
|
180
196
|
this.isStreaming = false;
|
181
|
-
// Create final message
|
197
|
+
// Create final message with metadata
|
182
198
|
const finalMessage = {
|
183
199
|
__typename: "ConversationMessage",
|
184
200
|
role: ConversationRoleTypes.Assistant,
|
@@ -186,7 +202,26 @@ export class UIEventAdapter {
|
|
186
202
|
timestamp: new Date().toISOString(),
|
187
203
|
tokens: undefined, // Will be set by caller if available
|
188
204
|
toolCalls: Array.from(this.activeToolCalls.values()).map((t) => t.toolCall),
|
205
|
+
model: this.model,
|
206
|
+
modelService: this.modelService,
|
189
207
|
};
|
208
|
+
// Add final timing metadata
|
209
|
+
if (this.streamStartTime > 0) {
|
210
|
+
const totalTime = Date.now() - this.streamStartTime;
|
211
|
+
// Final throughput (chars/second)
|
212
|
+
finalMessage.throughput = totalTime > 0
|
213
|
+
? Math.round((this.currentMessage.length / totalTime) * 1000)
|
214
|
+
: 0;
|
215
|
+
// Total completion time in seconds
|
216
|
+
finalMessage.completionTime = totalTime / 1000;
|
217
|
+
// Add time to first token if we have it (useful metric)
|
218
|
+
if (this.firstTokenTime > 0) {
|
219
|
+
const ttft = this.firstTokenTime - this.streamStartTime;
|
220
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
221
|
+
console.log(`⏱️ [UIEventAdapter] TTFT: ${ttft}ms | Total: ${totalTime}ms | Throughput: ${finalMessage.throughput} chars/s`);
|
222
|
+
}
|
223
|
+
}
|
224
|
+
}
|
190
225
|
this.emitUIEvent({
|
191
226
|
type: "conversation_completed",
|
192
227
|
message: finalMessage,
|
@@ -274,6 +309,27 @@ export class UIEventAdapter {
|
|
274
309
|
message: this.currentMessage,
|
275
310
|
timestamp: new Date().toISOString(),
|
276
311
|
};
|
312
|
+
// Add model metadata if available
|
313
|
+
if (this.model) {
|
314
|
+
message.model = this.model;
|
315
|
+
}
|
316
|
+
if (this.modelService) {
|
317
|
+
message.modelService = this.modelService;
|
318
|
+
}
|
319
|
+
// Add timing metadata if streaming has started
|
320
|
+
if (this.streamStartTime > 0) {
|
321
|
+
const now = Date.now();
|
322
|
+
const elapsedTime = now - this.streamStartTime;
|
323
|
+
// Calculate throughput (chars/second)
|
324
|
+
const throughput = elapsedTime > 0
|
325
|
+
? Math.round((this.currentMessage.length / elapsedTime) * 1000)
|
326
|
+
: 0;
|
327
|
+
message.throughput = throughput;
|
328
|
+
// Add completion time if we have it (in seconds to match API)
|
329
|
+
if (elapsedTime > 0) {
|
330
|
+
message.completionTime = elapsedTime / 1000;
|
331
|
+
}
|
332
|
+
}
|
277
333
|
this.emitUIEvent({
|
278
334
|
type: "message_update",
|
279
335
|
message,
|