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 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
- false, // includeDetails
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
- // Messages already have 'message' property from formatter
1340
- streamConfig.chatHistory = chatHistory;
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
- streamConfig.tools = tools.map((tool) => {
1388
+ const cohereTools = tools.map((tool) => {
1349
1389
  if (!tool.schema) {
1350
1390
  return {
1351
- name: tool.name,
1352
- description: tool.description,
1353
- parameter_definitions: {},
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 parameter_definitions = {};
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 || "string",
1404
+ type: prop.type || "str",
1365
1405
  description: prop.description || "",
1366
1406
  required: schema.required?.includes(key) || false,
1367
1407
  };
1368
- // Add additional properties that Cohere might expect
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
- parameter_definitions, // Use snake_case as expected by Cohere API
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
- if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
1401
- console.error(`❌ [Cohere] Stream creation failed:`, streamError);
1402
- if (streamError.response) {
1403
- console.error(`❌ [Cohere] Stream response status: ${streamError.response.status}`);
1404
- console.error(`❌ [Cohere] Stream response data:`, streamError.response.data);
1405
- }
1406
- if (streamError.status) {
1407
- console.error(`❌ [Cohere] Direct status: ${streamError.status}`);
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
- if (streamError.body) {
1410
- console.error(`❌ [Cohere] Response body:`, streamError.body);
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
- this.emitUIEvent({
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
  */
@@ -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 {
@@ -49,4 +49,12 @@ export type StreamEvent = {
49
49
  } | {
50
50
  type: "error";
51
51
  error: string;
52
+ } | {
53
+ type: "context_window";
54
+ usage: {
55
+ usedTokens: number;
56
+ maxTokens: number;
57
+ percentage: number;
58
+ remainingTokens: number;
59
+ };
52
60
  };
@@ -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: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphlit-client",
3
- "version": "1.0.20250615004",
3
+ "version": "1.0.20250615005",
4
4
  "description": "Graphlit API Client for TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/client.js",