graphlit-client 1.0.20250615004 → 1.0.20250615005
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 +36 -1
- package/dist/streaming/providers.js +86 -33
- package/dist/streaming/ui-event-adapter.d.ts +2 -0
- package/dist/streaming/ui-event-adapter.js +23 -2
- package/dist/types/agent.d.ts +7 -0
- package/dist/types/internal.d.ts +8 -0
- package/dist/types/ui-events.d.ts +20 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
@@ -1697,12 +1697,28 @@ class Graphlit {
|
|
1697
1697
|
}
|
1698
1698
|
// 2. Initial prompt
|
1699
1699
|
const promptResponse = await this.promptConversation(prompt, actualConversationId, specification, mimeType, data, tools, false, // requireTool
|
1700
|
-
|
1700
|
+
true, // includeDetails - needed for context window tracking
|
1701
1701
|
correlationId);
|
1702
1702
|
let currentMessage = promptResponse.promptConversation?.message;
|
1703
1703
|
if (!currentMessage) {
|
1704
1704
|
throw new Error("No message in prompt response");
|
1705
1705
|
}
|
1706
|
+
// Calculate and return context window usage in result
|
1707
|
+
const details = promptResponse.promptConversation?.details;
|
1708
|
+
let contextWindowUsage;
|
1709
|
+
if (details?.tokenLimit && details?.messages) {
|
1710
|
+
// Sum up all message tokens
|
1711
|
+
const usedTokens = details.messages.reduce((sum, msg) => sum + (msg?.tokens || 0), 0);
|
1712
|
+
contextWindowUsage = {
|
1713
|
+
usedTokens,
|
1714
|
+
maxTokens: details.tokenLimit,
|
1715
|
+
percentage: Math.round((usedTokens / details.tokenLimit) * 100),
|
1716
|
+
remainingTokens: Math.max(0, details.tokenLimit - usedTokens),
|
1717
|
+
};
|
1718
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
1719
|
+
console.log(`📊 [Context Window] Using ${usedTokens.toLocaleString()}/${details.tokenLimit.toLocaleString()} tokens (${Math.round((usedTokens / details.tokenLimit) * 100)}%)`);
|
1720
|
+
}
|
1721
|
+
}
|
1706
1722
|
// 3. Tool calling loop
|
1707
1723
|
const allToolCalls = [];
|
1708
1724
|
let rounds = 0;
|
@@ -1759,6 +1775,7 @@ class Graphlit {
|
|
1759
1775
|
toolResults: allToolCalls,
|
1760
1776
|
metrics,
|
1761
1777
|
usage,
|
1778
|
+
contextWindow: contextWindowUsage,
|
1762
1779
|
};
|
1763
1780
|
}
|
1764
1781
|
catch (error) {
|
@@ -1956,6 +1973,24 @@ class Graphlit {
|
|
1956
1973
|
});
|
1957
1974
|
}
|
1958
1975
|
}
|
1976
|
+
// Emit context window usage event
|
1977
|
+
const details = formatResponse.formatConversation?.details;
|
1978
|
+
if (details?.tokenLimit && details?.messages) {
|
1979
|
+
// Sum up all message tokens
|
1980
|
+
const usedTokens = details.messages.reduce((sum, msg) => sum + (msg?.tokens || 0), 0);
|
1981
|
+
uiAdapter.handleEvent({
|
1982
|
+
type: "context_window",
|
1983
|
+
usage: {
|
1984
|
+
usedTokens,
|
1985
|
+
maxTokens: details.tokenLimit,
|
1986
|
+
percentage: Math.round((usedTokens / details.tokenLimit) * 100),
|
1987
|
+
remainingTokens: Math.max(0, details.tokenLimit - usedTokens),
|
1988
|
+
},
|
1989
|
+
});
|
1990
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
1991
|
+
console.log(`📊 [Context Window] Using ${usedTokens.toLocaleString()}/${details.tokenLimit.toLocaleString()} tokens (${Math.round((usedTokens / details.tokenLimit) * 100)}%)`);
|
1992
|
+
}
|
1993
|
+
}
|
1959
1994
|
// Build message array with conversation history
|
1960
1995
|
const messages = [];
|
1961
1996
|
// Add system prompt if specified
|
@@ -1330,60 +1330,91 @@ onEvent, onComplete) {
|
|
1330
1330
|
if (!lastMessage || !lastMessage.message) {
|
1331
1331
|
throw new Error("Last message must have message property for Cohere streaming");
|
1332
1332
|
}
|
1333
|
+
// Build properly typed request using Cohere SDK types
|
1333
1334
|
const streamConfig = {
|
1334
1335
|
model: modelName,
|
1335
1336
|
message: lastMessage.message, // Current message (singular)
|
1336
1337
|
};
|
1337
1338
|
// Add chat history if there are previous messages
|
1338
1339
|
if (chatHistory.length > 0) {
|
1339
|
-
//
|
1340
|
-
|
1340
|
+
// Build properly typed chat history using Cohere SDK Message types
|
1341
|
+
const cohereHistory = chatHistory.map((msg) => {
|
1342
|
+
switch (msg.role) {
|
1343
|
+
case "USER":
|
1344
|
+
return {
|
1345
|
+
role: "USER",
|
1346
|
+
message: msg.message,
|
1347
|
+
};
|
1348
|
+
case "CHATBOT":
|
1349
|
+
const chatbotMsg = {
|
1350
|
+
role: "CHATBOT",
|
1351
|
+
message: msg.message,
|
1352
|
+
};
|
1353
|
+
// Add tool calls if present
|
1354
|
+
if (msg.tool_calls && msg.tool_calls.length > 0) {
|
1355
|
+
chatbotMsg.toolCalls = msg.tool_calls.map((tc) => ({
|
1356
|
+
name: tc.name,
|
1357
|
+
parameters: tc.parameters || {},
|
1358
|
+
}));
|
1359
|
+
}
|
1360
|
+
return chatbotMsg;
|
1361
|
+
case "SYSTEM":
|
1362
|
+
return {
|
1363
|
+
role: "SYSTEM",
|
1364
|
+
message: msg.message,
|
1365
|
+
};
|
1366
|
+
case "TOOL":
|
1367
|
+
return {
|
1368
|
+
role: "TOOL",
|
1369
|
+
toolResults: msg.tool_results || [],
|
1370
|
+
};
|
1371
|
+
default:
|
1372
|
+
// Fallback - treat as USER
|
1373
|
+
return {
|
1374
|
+
role: "USER",
|
1375
|
+
message: msg.message,
|
1376
|
+
};
|
1377
|
+
}
|
1378
|
+
});
|
1379
|
+
streamConfig.chatHistory = cohereHistory;
|
1341
1380
|
}
|
1342
1381
|
// Only add temperature if it's defined
|
1343
|
-
if (specification.cohere?.temperature !== undefined
|
1382
|
+
if (specification.cohere?.temperature !== undefined &&
|
1383
|
+
specification.cohere.temperature !== null) {
|
1344
1384
|
streamConfig.temperature = specification.cohere.temperature;
|
1345
1385
|
}
|
1346
1386
|
// Add tools if provided
|
1347
1387
|
if (tools && tools.length > 0) {
|
1348
|
-
|
1388
|
+
const cohereTools = tools.map((tool) => {
|
1349
1389
|
if (!tool.schema) {
|
1350
1390
|
return {
|
1351
|
-
name: tool.name,
|
1352
|
-
description: tool.description,
|
1353
|
-
|
1391
|
+
name: tool.name || "",
|
1392
|
+
description: tool.description || "",
|
1393
|
+
parameterDefinitions: {},
|
1354
1394
|
};
|
1355
1395
|
}
|
1356
1396
|
// Parse the JSON schema
|
1357
1397
|
const schema = JSON.parse(tool.schema);
|
1358
1398
|
// Convert JSON Schema to Cohere's expected format
|
1359
|
-
const
|
1399
|
+
const parameterDefinitions = {};
|
1360
1400
|
if (schema.properties) {
|
1361
1401
|
for (const [key, value] of Object.entries(schema.properties)) {
|
1362
1402
|
const prop = value;
|
1363
1403
|
const paramDef = {
|
1364
|
-
type: prop.type || "
|
1404
|
+
type: prop.type || "str",
|
1365
1405
|
description: prop.description || "",
|
1366
1406
|
required: schema.required?.includes(key) || false,
|
1367
1407
|
};
|
1368
|
-
|
1369
|
-
if (prop.enum) {
|
1370
|
-
paramDef.options = prop.enum;
|
1371
|
-
}
|
1372
|
-
if (prop.default !== undefined) {
|
1373
|
-
paramDef.default = prop.default;
|
1374
|
-
}
|
1375
|
-
if (prop.items) {
|
1376
|
-
paramDef.items = prop.items;
|
1377
|
-
}
|
1378
|
-
parameter_definitions[key] = paramDef;
|
1408
|
+
parameterDefinitions[key] = paramDef;
|
1379
1409
|
}
|
1380
1410
|
}
|
1381
1411
|
return {
|
1382
|
-
name: tool.name,
|
1383
|
-
description: tool.description,
|
1384
|
-
|
1412
|
+
name: tool.name || "",
|
1413
|
+
description: tool.description || "",
|
1414
|
+
parameterDefinitions, // Use camelCase as expected by Cohere SDK
|
1385
1415
|
};
|
1386
1416
|
});
|
1417
|
+
streamConfig.tools = cohereTools;
|
1387
1418
|
}
|
1388
1419
|
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
1389
1420
|
console.log(`🔍 [Cohere] Final stream config:`, JSON.stringify(streamConfig, null, 2));
|
@@ -1394,20 +1425,42 @@ onEvent, onComplete) {
|
|
1394
1425
|
}
|
1395
1426
|
let stream;
|
1396
1427
|
try {
|
1428
|
+
// Always log the full config when debugging Command A errors
|
1429
|
+
if (modelName.includes("command-a") ||
|
1430
|
+
process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
1431
|
+
console.log(`🔍 [Cohere] Full streamConfig for ${modelName}:`, JSON.stringify(streamConfig, null, 2));
|
1432
|
+
}
|
1397
1433
|
stream = await cohereClient.chatStream(streamConfig);
|
1398
1434
|
}
|
1399
1435
|
catch (streamError) {
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1436
|
+
// Enhanced error logging
|
1437
|
+
console.error(`❌ [Cohere] Stream creation failed for model ${modelName}`);
|
1438
|
+
console.error(`❌ [Cohere] Error type: ${streamError.constructor.name}`);
|
1439
|
+
console.error(`❌ [Cohere] Status code: ${streamError.statusCode || streamError.status || "unknown"}`);
|
1440
|
+
console.error(`❌ [Cohere] Error message: ${streamError.message}`);
|
1441
|
+
// Try to read the body if it's a ReadableStream
|
1442
|
+
if (streamError.body &&
|
1443
|
+
typeof streamError.body.getReader === "function") {
|
1444
|
+
try {
|
1445
|
+
const reader = streamError.body.getReader();
|
1446
|
+
let fullBody = "";
|
1447
|
+
while (true) {
|
1448
|
+
const { done, value } = await reader.read();
|
1449
|
+
if (done)
|
1450
|
+
break;
|
1451
|
+
fullBody += new TextDecoder().decode(value);
|
1452
|
+
}
|
1453
|
+
console.error(`❌ [Cohere] Raw error body:`, fullBody);
|
1454
|
+
try {
|
1455
|
+
const parsed = JSON.parse(fullBody);
|
1456
|
+
console.error(`❌ [Cohere] Parsed error details:`, JSON.stringify(parsed, null, 2));
|
1457
|
+
}
|
1458
|
+
catch (e) {
|
1459
|
+
console.error(`❌ [Cohere] Could not parse error body as JSON`);
|
1460
|
+
}
|
1408
1461
|
}
|
1409
|
-
|
1410
|
-
console.error(`❌ [Cohere]
|
1462
|
+
catch (e) {
|
1463
|
+
console.error(`❌ [Cohere] Could not read error body:`, e);
|
1411
1464
|
}
|
1412
1465
|
}
|
1413
1466
|
throw streamError;
|
@@ -24,6 +24,7 @@ export declare class UIEventAdapter {
|
|
24
24
|
private chunkBuffer?;
|
25
25
|
private smoothingDelay;
|
26
26
|
private chunkQueue;
|
27
|
+
private contextWindowUsage?;
|
27
28
|
constructor(onEvent: (event: AgentStreamEvent) => void, conversationId: string, options?: {
|
28
29
|
smoothingEnabled?: boolean;
|
29
30
|
chunkingStrategy?: ChunkingStrategy;
|
@@ -49,6 +50,7 @@ export declare class UIEventAdapter {
|
|
49
50
|
private emitNextChunk;
|
50
51
|
private emitMessageUpdate;
|
51
52
|
private emitUIEvent;
|
53
|
+
private handleContextWindow;
|
52
54
|
/**
|
53
55
|
* Clean up any pending timers
|
54
56
|
*/
|
@@ -23,6 +23,7 @@ export class UIEventAdapter {
|
|
23
23
|
chunkBuffer;
|
24
24
|
smoothingDelay = 30;
|
25
25
|
chunkQueue = []; // Queue of chunks waiting to be emitted
|
26
|
+
contextWindowUsage;
|
26
27
|
constructor(onEvent, conversationId, options = {}) {
|
27
28
|
this.onEvent = onEvent;
|
28
29
|
this.conversationId = conversationId;
|
@@ -66,6 +67,9 @@ export class UIEventAdapter {
|
|
66
67
|
case "error":
|
67
68
|
this.handleError(event.error);
|
68
69
|
break;
|
70
|
+
case "context_window":
|
71
|
+
this.handleContextWindow(event.usage);
|
72
|
+
break;
|
69
73
|
}
|
70
74
|
}
|
71
75
|
handleStart(conversationId) {
|
@@ -323,11 +327,16 @@ export class UIEventAdapter {
|
|
323
327
|
finalMetrics.streamingThroughput = Math.round((this.currentMessage.length / streamingTime) * 1000);
|
324
328
|
}
|
325
329
|
}
|
326
|
-
|
330
|
+
// Include context window usage if available
|
331
|
+
const event = {
|
327
332
|
type: "conversation_completed",
|
328
333
|
message: finalMessage,
|
329
334
|
metrics: finalMetrics,
|
330
|
-
}
|
335
|
+
};
|
336
|
+
if (this.contextWindowUsage) {
|
337
|
+
event.contextWindow = this.contextWindowUsage;
|
338
|
+
}
|
339
|
+
this.emitUIEvent(event);
|
331
340
|
}
|
332
341
|
handleError(error) {
|
333
342
|
this.isStreaming = false;
|
@@ -468,6 +477,18 @@ export class UIEventAdapter {
|
|
468
477
|
emitUIEvent(event) {
|
469
478
|
this.onEvent(event);
|
470
479
|
}
|
480
|
+
handleContextWindow(usage) {
|
481
|
+
// Store for later inclusion in completion event
|
482
|
+
this.contextWindowUsage = usage;
|
483
|
+
if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
|
484
|
+
console.log(`📊 [UIEventAdapter] Context window: ${usage.usedTokens}/${usage.maxTokens} (${usage.percentage}%)`);
|
485
|
+
}
|
486
|
+
this.emitUIEvent({
|
487
|
+
type: "context_window",
|
488
|
+
usage,
|
489
|
+
timestamp: new Date(),
|
490
|
+
});
|
491
|
+
}
|
471
492
|
/**
|
472
493
|
* Clean up any pending timers
|
473
494
|
*/
|
package/dist/types/agent.d.ts
CHANGED
@@ -13,6 +13,12 @@ export interface AgentMetrics {
|
|
13
13
|
toolExecutions?: number;
|
14
14
|
rounds?: number;
|
15
15
|
}
|
16
|
+
export interface ContextWindowUsage {
|
17
|
+
usedTokens: number;
|
18
|
+
maxTokens: number;
|
19
|
+
percentage: number;
|
20
|
+
remainingTokens: number;
|
21
|
+
}
|
16
22
|
export interface AgentResult {
|
17
23
|
message: string;
|
18
24
|
conversationId: string;
|
@@ -21,6 +27,7 @@ export interface AgentResult {
|
|
21
27
|
toolResults?: ToolCallResult[];
|
22
28
|
metrics?: AgentMetrics;
|
23
29
|
usage?: UsageInfo;
|
30
|
+
contextWindow?: ContextWindowUsage;
|
24
31
|
error?: AgentError;
|
25
32
|
}
|
26
33
|
export interface StreamAgentOptions {
|
package/dist/types/internal.d.ts
CHANGED
@@ -3,6 +3,19 @@ import { ConversationMessage, ConversationToolCall } from "../generated/graphql-
|
|
3
3
|
* Tool execution status for streaming
|
4
4
|
*/
|
5
5
|
export type ToolExecutionStatus = "preparing" | "executing" | "ready" | "completed" | "failed";
|
6
|
+
/**
|
7
|
+
* Context window usage event - emitted at start of agent interaction
|
8
|
+
*/
|
9
|
+
export type ContextWindowEvent = {
|
10
|
+
type: "context_window";
|
11
|
+
usage: {
|
12
|
+
usedTokens: number;
|
13
|
+
maxTokens: number;
|
14
|
+
percentage: number;
|
15
|
+
remainingTokens: number;
|
16
|
+
};
|
17
|
+
timestamp: Date;
|
18
|
+
};
|
6
19
|
/**
|
7
20
|
* Simplified UI-focused streaming events using GraphQL types
|
8
21
|
*/
|
@@ -11,7 +24,7 @@ export type AgentStreamEvent = {
|
|
11
24
|
conversationId: string;
|
12
25
|
timestamp: Date;
|
13
26
|
model?: string;
|
14
|
-
} | {
|
27
|
+
} | ContextWindowEvent | {
|
15
28
|
type: "message_update";
|
16
29
|
message: Partial<ConversationMessage> & {
|
17
30
|
message: string;
|
@@ -43,6 +56,12 @@ export type AgentStreamEvent = {
|
|
43
56
|
avgTokenDelay?: number;
|
44
57
|
streamingThroughput?: number;
|
45
58
|
};
|
59
|
+
contextWindow?: {
|
60
|
+
usedTokens: number;
|
61
|
+
maxTokens: number;
|
62
|
+
percentage: number;
|
63
|
+
remainingTokens: number;
|
64
|
+
};
|
46
65
|
} | {
|
47
66
|
type: "error";
|
48
67
|
error: {
|