graphlit-client 1.0.20250921001 → 1.0.20250924001

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
@@ -2486,7 +2486,7 @@ class Graphlit {
2486
2486
  // Mistral API requires that we don't pass tools when sending tool results
2487
2487
  const shouldPassTools = toolResponseCount === 0 ? tools : undefined;
2488
2488
  if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
2489
- console.log(`🔍 [Mistral] Passing tools: ${shouldPassTools ? 'YES' : 'NO'} (tool responses in messages: ${toolResponseCount})`);
2489
+ console.log(`🔍 [Mistral] Passing tools: ${shouldPassTools ? "YES" : "NO"} (tool responses in messages: ${toolResponseCount})`);
2490
2490
  }
2491
2491
  await this.streamWithMistral(specification, mistralMessages, shouldPassTools, uiAdapter, (message, calls, usage) => {
2492
2492
  roundMessage = message;
@@ -6696,6 +6696,7 @@ export const GetFeed = gql `
6696
6696
  enableMeetingRecording
6697
6697
  meetingBotName
6698
6698
  google {
6699
+ type
6699
6700
  calendarId
6700
6701
  beforeDate
6701
6702
  afterDate
@@ -6706,6 +6707,7 @@ export const GetFeed = gql `
6706
6707
  authorizationId
6707
6708
  }
6708
6709
  microsoft {
6710
+ type
6709
6711
  calendarId
6710
6712
  beforeDate
6711
6713
  afterDate
@@ -7039,6 +7041,7 @@ export const QueryFeeds = gql `
7039
7041
  enableMeetingRecording
7040
7042
  meetingBotName
7041
7043
  google {
7044
+ type
7042
7045
  calendarId
7043
7046
  beforeDate
7044
7047
  afterDate
@@ -7049,6 +7052,7 @@ export const QueryFeeds = gql `
7049
7052
  authorizationId
7050
7053
  }
7051
7054
  microsoft {
7055
+ type
7052
7056
  calendarId
7053
7057
  beforeDate
7054
7058
  afterDate
@@ -369,11 +369,11 @@ export type AnthropicModelPropertiesUpdateInput = {
369
369
  };
370
370
  /** Anthropic model type */
371
371
  export declare enum AnthropicModels {
372
- /** @deprecated Use Claude 3.x instead. */
372
+ /** @deprecated Use Claude 4.x instead. */
373
373
  Claude_2 = "CLAUDE_2",
374
- /** @deprecated Use Claude 3.x instead. */
374
+ /** @deprecated Use Claude 4.x instead. */
375
375
  Claude_2_0 = "CLAUDE_2_0",
376
- /** @deprecated Use Claude 3.x instead. */
376
+ /** @deprecated Use Claude 4.x instead. */
377
377
  Claude_2_1 = "CLAUDE_2_1",
378
378
  /** Claude 3.5 Haiku (Latest) */
379
379
  Claude_3_5Haiku = "CLAUDE_3_5_HAIKU",
@@ -381,7 +381,7 @@ export declare enum AnthropicModels {
381
381
  Claude_3_5Haiku_20241022 = "CLAUDE_3_5_HAIKU_20241022",
382
382
  /** Claude 3.5 Sonnet (Latest) */
383
383
  Claude_3_5Sonnet = "CLAUDE_3_5_SONNET",
384
- /** Claude 3.5 Sonnet (06-20-2024 version) */
384
+ /** @deprecated Use Claude 4.x instead. */
385
385
  Claude_3_5Sonnet_20240620 = "CLAUDE_3_5_SONNET_20240620",
386
386
  /** Claude 3.5 Sonnet (10-22-2024 version) */
387
387
  Claude_3_5Sonnet_20241022 = "CLAUDE_3_5_SONNET_20241022",
@@ -1278,6 +1278,13 @@ export type CalendarFeedPropertiesUpdateInput = {
1278
1278
  /** The limit of items to be read from feed, defaults to 100. */
1279
1279
  readLimit?: InputMaybe<Scalars['Int']['input']>;
1280
1280
  };
1281
+ /** Calendar list type */
1282
+ export declare enum CalendarListingTypes {
1283
+ /** Read new calendar events */
1284
+ New = "NEW",
1285
+ /** Read past calendar events */
1286
+ Past = "PAST"
1287
+ }
1281
1288
  /** Represents a calendar event recurrence. */
1282
1289
  export type CalendarRecurrence = {
1283
1290
  __typename?: 'CalendarRecurrence';
@@ -4862,6 +4869,8 @@ export type GoogleCalendarFeedProperties = {
4862
4869
  clientSecret?: Maybe<Scalars['String']['output']>;
4863
4870
  /** Google OAuth2 refresh token. */
4864
4871
  refreshToken?: Maybe<Scalars['String']['output']>;
4872
+ /** Calendar listing type, i.e. past or new events. */
4873
+ type?: Maybe<CalendarListingTypes>;
4865
4874
  };
4866
4875
  /** Represents Google Calendar properties. */
4867
4876
  export type GoogleCalendarFeedPropertiesInput = {
@@ -4881,19 +4890,29 @@ export type GoogleCalendarFeedPropertiesInput = {
4881
4890
  clientSecret?: InputMaybe<Scalars['String']['input']>;
4882
4891
  /** Google OAuth2 refresh token, requires User authentication type. */
4883
4892
  refreshToken?: InputMaybe<Scalars['String']['input']>;
4893
+ /** Calendar listing type, i.e. past or new events. */
4894
+ type?: InputMaybe<CalendarListingTypes>;
4884
4895
  };
4885
4896
  /** Represents Google Calendar properties. */
4886
4897
  export type GoogleCalendarFeedPropertiesUpdateInput = {
4898
+ /** Read calendar events after this date (inclusive), optional. */
4899
+ afterDate?: InputMaybe<Scalars['DateTime']['input']>;
4887
4900
  /** Google Calendar authentication type, defaults to User. */
4888
4901
  authenticationType?: InputMaybe<GoogleCalendarAuthenticationTypes>;
4889
4902
  /** Authentication identifier, for Connector authentication type. */
4890
4903
  authorizationId?: InputMaybe<Scalars['String']['input']>;
4904
+ /** Read calendar events before this date (inclusive), optional. */
4905
+ beforeDate?: InputMaybe<Scalars['DateTime']['input']>;
4906
+ /** Google Email calendar identifier, optional. */
4907
+ calendarId?: InputMaybe<Scalars['String']['input']>;
4891
4908
  /** Google OAuth2 client identifier, requires User authentication type. */
4892
4909
  clientId?: InputMaybe<Scalars['String']['input']>;
4893
4910
  /** Google OAuth2 client secret, requires User authentication type. */
4894
4911
  clientSecret?: InputMaybe<Scalars['String']['input']>;
4895
4912
  /** Google OAuth2 refresh token, requires User authentication type. */
4896
4913
  refreshToken?: InputMaybe<Scalars['String']['input']>;
4914
+ /** Calendar listing type, i.e. past or new events. */
4915
+ type?: InputMaybe<CalendarListingTypes>;
4897
4916
  };
4898
4917
  /** Represents Google Calendar properties. */
4899
4918
  export type GoogleCalendarsInput = {
@@ -8097,6 +8116,8 @@ export type MicrosoftCalendarFeedProperties = {
8097
8116
  clientSecret?: Maybe<Scalars['String']['output']>;
8098
8117
  /** Microsoft Entra ID refresh token. */
8099
8118
  refreshToken?: Maybe<Scalars['String']['output']>;
8119
+ /** Calendar listing type, i.e. past or new events. */
8120
+ type?: Maybe<CalendarListingTypes>;
8100
8121
  };
8101
8122
  /** Represents Microsoft Calendar properties. */
8102
8123
  export type MicrosoftCalendarFeedPropertiesInput = {
@@ -8116,19 +8137,29 @@ export type MicrosoftCalendarFeedPropertiesInput = {
8116
8137
  clientSecret?: InputMaybe<Scalars['String']['input']>;
8117
8138
  /** Microsoft Entra ID refresh token, requires User authentication type. */
8118
8139
  refreshToken?: InputMaybe<Scalars['String']['input']>;
8140
+ /** Calendar listing type, i.e. past or new events. */
8141
+ type?: InputMaybe<CalendarListingTypes>;
8119
8142
  };
8120
8143
  /** Represents Microsoft Calendar properties. */
8121
8144
  export type MicrosoftCalendarFeedPropertiesUpdateInput = {
8145
+ /** Read calendar events after this date (inclusive), optional. */
8146
+ afterDate?: InputMaybe<Scalars['DateTime']['input']>;
8122
8147
  /** Microsoft Calendar authentication type, defaults to User. */
8123
8148
  authenticationType?: InputMaybe<MicrosoftCalendarAuthenticationTypes>;
8124
8149
  /** Authentication identifier, for Connector authentication type. */
8125
8150
  authorizationId?: InputMaybe<Scalars['String']['input']>;
8151
+ /** Read calendar events before this date (inclusive), optional. */
8152
+ beforeDate?: InputMaybe<Scalars['DateTime']['input']>;
8153
+ /** Microsoft Email calendar identifier, optional. */
8154
+ calendarId?: InputMaybe<Scalars['String']['input']>;
8126
8155
  /** Microsoft Entra ID client identifier, requires User authentication type. */
8127
8156
  clientId?: InputMaybe<Scalars['String']['input']>;
8128
8157
  /** Microsoft Entra ID client secret, requires User authentication type. */
8129
8158
  clientSecret?: InputMaybe<Scalars['String']['input']>;
8130
8159
  /** Microsoft Entra ID refresh token, requires User authentication type. */
8131
8160
  refreshToken?: InputMaybe<Scalars['String']['input']>;
8161
+ /** Calendar listing type, i.e. past or new events. */
8162
+ type?: InputMaybe<CalendarListingTypes>;
8132
8163
  };
8133
8164
  /** Represents Microsoft Calendar properties. */
8134
8165
  export type MicrosoftCalendarsInput = {
@@ -22910,6 +22941,7 @@ export type GetFeedQuery = {
22910
22941
  readLimit?: number | null;
22911
22942
  google?: {
22912
22943
  __typename?: 'GoogleCalendarFeedProperties';
22944
+ type?: CalendarListingTypes | null;
22913
22945
  calendarId?: string | null;
22914
22946
  beforeDate?: any | null;
22915
22947
  afterDate?: any | null;
@@ -22921,6 +22953,7 @@ export type GetFeedQuery = {
22921
22953
  } | null;
22922
22954
  microsoft?: {
22923
22955
  __typename?: 'MicrosoftCalendarFeedProperties';
22956
+ type?: CalendarListingTypes | null;
22924
22957
  calendarId?: string | null;
22925
22958
  beforeDate?: any | null;
22926
22959
  afterDate?: any | null;
@@ -23321,6 +23354,7 @@ export type QueryFeedsQuery = {
23321
23354
  readLimit?: number | null;
23322
23355
  google?: {
23323
23356
  __typename?: 'GoogleCalendarFeedProperties';
23357
+ type?: CalendarListingTypes | null;
23324
23358
  calendarId?: string | null;
23325
23359
  beforeDate?: any | null;
23326
23360
  afterDate?: any | null;
@@ -23332,6 +23366,7 @@ export type QueryFeedsQuery = {
23332
23366
  } | null;
23333
23367
  microsoft?: {
23334
23368
  __typename?: 'MicrosoftCalendarFeedProperties';
23369
+ type?: CalendarListingTypes | null;
23335
23370
  calendarId?: string | null;
23336
23371
  beforeDate?: any | null;
23337
23372
  afterDate?: any | null;
@@ -7,11 +7,11 @@ export var AlertTypes;
7
7
  /** Anthropic model type */
8
8
  export var AnthropicModels;
9
9
  (function (AnthropicModels) {
10
- /** @deprecated Use Claude 3.x instead. */
10
+ /** @deprecated Use Claude 4.x instead. */
11
11
  AnthropicModels["Claude_2"] = "CLAUDE_2";
12
- /** @deprecated Use Claude 3.x instead. */
12
+ /** @deprecated Use Claude 4.x instead. */
13
13
  AnthropicModels["Claude_2_0"] = "CLAUDE_2_0";
14
- /** @deprecated Use Claude 3.x instead. */
14
+ /** @deprecated Use Claude 4.x instead. */
15
15
  AnthropicModels["Claude_2_1"] = "CLAUDE_2_1";
16
16
  /** Claude 3.5 Haiku (Latest) */
17
17
  AnthropicModels["Claude_3_5Haiku"] = "CLAUDE_3_5_HAIKU";
@@ -19,7 +19,7 @@ export var AnthropicModels;
19
19
  AnthropicModels["Claude_3_5Haiku_20241022"] = "CLAUDE_3_5_HAIKU_20241022";
20
20
  /** Claude 3.5 Sonnet (Latest) */
21
21
  AnthropicModels["Claude_3_5Sonnet"] = "CLAUDE_3_5_SONNET";
22
- /** Claude 3.5 Sonnet (06-20-2024 version) */
22
+ /** @deprecated Use Claude 4.x instead. */
23
23
  AnthropicModels["Claude_3_5Sonnet_20240620"] = "CLAUDE_3_5_SONNET_20240620";
24
24
  /** Claude 3.5 Sonnet (10-22-2024 version) */
25
25
  AnthropicModels["Claude_3_5Sonnet_20241022"] = "CLAUDE_3_5_SONNET_20241022";
@@ -247,6 +247,14 @@ export var CalendarEventVisibility;
247
247
  /** Public event */
248
248
  CalendarEventVisibility["Public"] = "PUBLIC";
249
249
  })(CalendarEventVisibility || (CalendarEventVisibility = {}));
250
+ /** Calendar list type */
251
+ export var CalendarListingTypes;
252
+ (function (CalendarListingTypes) {
253
+ /** Read new calendar events */
254
+ CalendarListingTypes["New"] = "NEW";
255
+ /** Read past calendar events */
256
+ CalendarListingTypes["Past"] = "PAST";
257
+ })(CalendarListingTypes || (CalendarListingTypes = {}));
250
258
  /** Calendar recurrence pattern */
251
259
  export var CalendarRecurrencePattern;
252
260
  (function (CalendarRecurrencePattern) {
@@ -108,56 +108,57 @@ export function formatMessagesForAnthropic(messages) {
108
108
  systemPrompt = trimmedMessage;
109
109
  break;
110
110
  case ConversationRoleTypes.Assistant:
111
- const content = []; // Use any[] to allow thinking blocks
112
- // Handle thinking blocks for extended thinking preservation
113
- if (trimmedMessage && trimmedMessage.includes("<thinking")) {
114
- // Extract thinking content and signature if present
115
- const thinkingMatch = trimmedMessage.match(/<thinking(?:\s+signature="([^"]*)")?>([\s\S]*?)<\/thinking>/);
116
- if (thinkingMatch) {
117
- const signature = thinkingMatch[1]; // Optional signature
118
- const thinkingContent = thinkingMatch[2].trim();
119
- // Add thinking block for conversation history preservation
120
- if (thinkingContent) {
121
- const thinkingBlock = {
122
- type: "thinking",
123
- thinking: thinkingContent,
124
- };
125
- // Add signature if present (required by Anthropic API)
126
- if (signature) {
127
- thinkingBlock.signature = signature;
128
- }
129
- else {
130
- // Provide a default signature if none captured
131
- thinkingBlock.signature = "";
132
- }
133
- content.push(thinkingBlock);
134
- }
135
- // Remove thinking tags from the main text and add remaining content
136
- const textWithoutThinking = trimmedMessage
137
- .replace(/<thinking(?:\s+[^>]*)?>[\s\S]*?<\/thinking>/g, "")
138
- .trim();
139
- if (textWithoutThinking) {
140
- content.push({
141
- type: "text",
142
- text: textWithoutThinking,
143
- });
111
+ const content = [];
112
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
113
+ console.log(`🔍 [formatMessagesForAnthropic] Processing assistant message: "${trimmedMessage.substring(0, 200)}..."`);
114
+ console.log(`🔍 [formatMessagesForAnthropic] Has tool calls: ${message.toolCalls?.length || 0}`);
115
+ }
116
+ // Check if message contains thinking content (for Anthropic compatibility)
117
+ const hasThinking = trimmedMessage.includes('<thinking');
118
+ if (hasThinking) {
119
+ // Parse thinking and text content separately for proper Anthropic format
120
+ const thinkingMatch = trimmedMessage.match(/<thinking(?:\s+signature="([^"]*)")?\s*>(.*?)<\/thinking>/s);
121
+ const thinkingSignature = thinkingMatch ? thinkingMatch[1] : '';
122
+ const thinkingContent = thinkingMatch ? thinkingMatch[2].trim() : '';
123
+ const textContent = trimmedMessage.replace(/<thinking(?:\s+signature="[^"]*")?\s*>.*?<\/thinking>/s, '').trim();
124
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
125
+ console.log(`🔍 [formatMessagesForAnthropic] Found thinking content: ${thinkingContent.length} chars`);
126
+ console.log(`🔍 [formatMessagesForAnthropic] Text content after thinking: "${textContent}"`);
127
+ console.log(`🔍 [formatMessagesForAnthropic] Signature: "${thinkingSignature}"`);
128
+ }
129
+ // CRITICAL: When thinking is enabled, thinking block must come first
130
+ if (thinkingContent) {
131
+ const thinkingBlock = {
132
+ type: "thinking",
133
+ thinking: thinkingContent,
134
+ };
135
+ // Include signature if present
136
+ if (thinkingSignature) {
137
+ thinkingBlock.signature = thinkingSignature;
144
138
  }
139
+ content.push(thinkingBlock);
145
140
  }
146
- else {
147
- // No valid thinking blocks found, add as regular text
141
+ // Add text content after thinking block
142
+ if (textContent) {
148
143
  content.push({
149
144
  type: "text",
150
- text: trimmedMessage,
145
+ text: textContent,
151
146
  });
152
147
  }
153
148
  }
154
149
  else if (trimmedMessage) {
155
- // Add regular text content
150
+ // Regular text content
151
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
152
+ console.log(`🔍 [formatMessagesForAnthropic] No thinking found, adding text content`);
153
+ }
156
154
  content.push({
157
155
  type: "text",
158
156
  text: trimmedMessage,
159
157
  });
160
158
  }
159
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
160
+ console.log(`🔍 [formatMessagesForAnthropic] Content array: ${content.map(c => c.type).join(', ')}`);
161
+ }
161
162
  // Add tool uses if present
162
163
  if (message.toolCalls && message.toolCalls.length > 0) {
163
164
  for (const toolCall of message.toolCalls) {
@@ -421,15 +421,17 @@ onEvent, onComplete, abortSignal, thinkingConfig) {
421
421
  if (!modelName) {
422
422
  throw new Error(`No model name found for Anthropic specification: ${specification.name}`);
423
423
  }
424
+ // Calculate smart default for max_tokens based on thinking mode
425
+ const defaultMaxTokens = thinkingConfig ? 32768 : 8192;
424
426
  if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
425
- console.log(`🤖 [Anthropic] Model Config: Service=Anthropic | Model=${modelName} | Temperature=${specification.anthropic?.temperature} | MaxTokens=${specification.anthropic?.completionTokenLimit || 8192} | SystemPrompt=${systemPrompt ? "Yes" : "No"} | Tools=${tools?.length || 0} | Spec="${specification.name}"`);
427
+ console.log(`🤖 [Anthropic] Model Config: Service=Anthropic | Model=${modelName} | Temperature=${specification.anthropic?.temperature} | MaxTokens=${specification.anthropic?.completionTokenLimit || defaultMaxTokens} | SystemPrompt=${systemPrompt ? "Yes" : "No"} | Tools=${tools?.length || 0} | Thinking=${!!thinkingConfig} | Spec="${specification.name}"`);
426
428
  }
427
429
  // Use proper Anthropic SDK types for the config
428
430
  const streamConfig = {
429
431
  model: modelName,
430
432
  messages,
431
433
  stream: true,
432
- max_tokens: specification.anthropic?.completionTokenLimit || 8192, // required
434
+ max_tokens: specification.anthropic?.completionTokenLimit || defaultMaxTokens,
433
435
  };
434
436
  // Handle temperature based on thinking configuration
435
437
  if (thinkingConfig) {
@@ -496,14 +498,17 @@ onEvent, onComplete, abortSignal, thinkingConfig) {
496
498
  console.log(`[Anthropic] Usage data captured from message_start.message:`, usageData);
497
499
  }
498
500
  }
499
- else if (chunk.type === "message_delta" && chunk.usage && !usageData?.input_tokens) {
501
+ else if (chunk.type === "message_delta" &&
502
+ chunk.usage &&
503
+ !usageData?.input_tokens) {
500
504
  // Only use message_delta if we don't have input_tokens yet
501
505
  usageData = chunk.usage;
502
506
  if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
503
507
  console.log(`[Anthropic] Usage data captured from ${chunk.type}:`, usageData);
504
508
  }
505
509
  }
506
- else if ((chunk.type === "message_delta" || chunk.type === "message_start") && chunk.usage) {
510
+ else if ((chunk.type === "message_delta" || chunk.type === "message_start") &&
511
+ chunk.usage) {
507
512
  // Merge usage data if we have partial data
508
513
  if (usageData) {
509
514
  usageData = { ...usageData, ...chunk.usage };
@@ -746,14 +751,24 @@ onEvent, onComplete, abortSignal, thinkingConfig) {
746
751
  }
747
752
  }
748
753
  }
749
- // Final check: filter out any remaining incomplete tool calls
750
- const validToolCalls = toolCalls.filter((tc, idx) => {
754
+ // Final check: normalize and validate tool calls
755
+ const validToolCalls = toolCalls
756
+ .map((tc, idx) => {
757
+ // For tools with no parameters, Anthropic doesn't send input_json_delta
758
+ // So we need to convert empty arguments to valid JSON
759
+ if (tc.arguments === "") {
760
+ tc.arguments = "{}";
761
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
762
+ console.log(`[Anthropic] Normalized empty arguments to "{}" for tool ${tc.name}`);
763
+ }
764
+ }
751
765
  if (!isValidJSON(tc.arguments)) {
752
766
  console.warn(`[Anthropic] Filtering out incomplete tool call ${idx} (${tc.name}) with INVALID JSON (${tc.arguments.length} chars)`);
753
- return false;
767
+ return null;
754
768
  }
755
- return true;
756
- });
769
+ return tc;
770
+ })
771
+ .filter((tc) => tc !== null);
757
772
  if (toolCalls.length !== validToolCalls.length) {
758
773
  console.log(`[Anthropic] Filtered out ${toolCalls.length - validToolCalls.length} incomplete tool calls`);
759
774
  console.log(`[Anthropic] Successfully processed ${validToolCalls.length} valid tool calls`);
@@ -825,19 +840,26 @@ onEvent, onComplete, abortSignal, thinkingConfig) {
825
840
  }
826
841
  console.log(`✅ [Anthropic] Final message (${fullMessage.length} chars): "${fullMessage}"`);
827
842
  }
828
- // Include thinking content in the final message for conversation history preservation
829
- let finalMessage = fullMessage;
830
- if (completeThinkingContent.trim()) {
831
- // Wrap thinking content with signature in special tags that formatMessagesForAnthropic can parse
832
- const thinkingBlock = completeThinkingSignature.trim()
843
+ // Include thinking content in message when there are tool calls (required by Anthropic API)
844
+ let messageWithThinking = fullMessage;
845
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
846
+ console.log(`🧠 [Anthropic] Debug - validToolCalls: ${validToolCalls.length}, thinking content: ${completeThinkingContent.length} chars, fullMessage: ${fullMessage.length} chars`);
847
+ }
848
+ if (validToolCalls.length > 0 && completeThinkingContent.trim()) {
849
+ // Include thinking content with signature for API compatibility
850
+ const thinkingXml = completeThinkingSignature
833
851
  ? `<thinking signature="${completeThinkingSignature}">${completeThinkingContent}</thinking>`
834
852
  : `<thinking>${completeThinkingContent}</thinking>`;
835
- finalMessage = `${thinkingBlock}${fullMessage}`;
853
+ messageWithThinking = `${thinkingXml}\n${fullMessage}`.trim();
836
854
  if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
837
- console.log(`🧠 [Anthropic] Including thinking content (${completeThinkingContent.length} chars) and signature (${completeThinkingSignature.length} chars) in conversation history`);
855
+ console.log(`🧠 [Anthropic] Including thinking content with message due to tool calls (${completeThinkingContent.length} chars, signature: ${completeThinkingSignature?.length || 0})`);
856
+ console.log(`🧠 [Anthropic] Final stored message: "${messageWithThinking}"`);
838
857
  }
839
858
  }
840
- onComplete(finalMessage, validToolCalls, usageData);
859
+ else if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING && completeThinkingContent.trim()) {
860
+ console.log(`🧠 [Anthropic] Thinking content captured (${completeThinkingContent.length} chars) - not including (no tool calls)`);
861
+ }
862
+ onComplete(messageWithThinking, validToolCalls, usageData);
841
863
  }
842
864
  catch (error) {
843
865
  // Handle Anthropic-specific errors
@@ -1095,7 +1117,8 @@ onEvent, onComplete, abortSignal) {
1095
1117
  continue;
1096
1118
  }
1097
1119
  // Only add if it's not already included in fullMessage
1098
- if (!fullMessage.includes(finalText) && !fullMessage.endsWith(finalText)) {
1120
+ if (!fullMessage.includes(finalText) &&
1121
+ !fullMessage.endsWith(finalText)) {
1099
1122
  fullMessage += finalText;
1100
1123
  onEvent({
1101
1124
  type: "token",
@@ -1526,7 +1549,8 @@ onEvent, onComplete, abortSignal) {
1526
1549
  }
1527
1550
  }
1528
1551
  // Check for finish reason
1529
- if (chunk.choices[0].finish_reason === "tool_calls" && toolCalls.length > 0) {
1552
+ if (chunk.choices[0].finish_reason === "tool_calls" &&
1553
+ toolCalls.length > 0) {
1530
1554
  // Emit tool_call_parsed events for completed tool calls
1531
1555
  for (const toolCall of toolCalls) {
1532
1556
  onEvent({
@@ -2227,7 +2251,7 @@ onEvent, onComplete, abortSignal) {
2227
2251
  }));
2228
2252
  }
2229
2253
  else {
2230
- console.log(`[Mistral] No tools provided - tools parameter is ${tools === undefined ? 'undefined' : 'empty array'}`);
2254
+ console.log(`[Mistral] No tools provided - tools parameter is ${tools === undefined ? "undefined" : "empty array"}`);
2231
2255
  }
2232
2256
  if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
2233
2257
  console.log(`[Mistral] Stream config:`, JSON.stringify({
@@ -2274,7 +2298,7 @@ onEvent, onComplete, abortSignal) {
2274
2298
  console.log(`[Mistral] Attempting to create stream with retry configuration`);
2275
2299
  }
2276
2300
  // Log final config being sent
2277
- console.log(`[Mistral] Sending request with tools: ${streamConfig.tools ? 'YES' : 'NO'}`);
2301
+ console.log(`[Mistral] Sending request with tools: ${streamConfig.tools ? "YES" : "NO"}`);
2278
2302
  stream = await mistralClient.chat.stream(streamConfig, {
2279
2303
  retries: {
2280
2304
  strategy: "backoff",
@@ -26,6 +26,7 @@ export declare class UIEventAdapter {
26
26
  private chunkQueue;
27
27
  private contextWindowUsage?;
28
28
  private finalMetrics?;
29
+ private roundThinkingContent?;
29
30
  private reasoningContent;
30
31
  private reasoningFormat?;
31
32
  private reasoningSignature?;
@@ -82,4 +83,8 @@ export declare class UIEventAdapter {
82
83
  * Set usage data from native provider
83
84
  */
84
85
  setUsageData(usage: any): void;
86
+ /**
87
+ * Set thinking content for this round (for conversation history formatting)
88
+ */
89
+ setRoundThinkingContent(thinkingContent: string): void;
85
90
  }
@@ -25,6 +25,7 @@ export class UIEventAdapter {
25
25
  chunkQueue = []; // Queue of chunks waiting to be emitted
26
26
  contextWindowUsage;
27
27
  finalMetrics;
28
+ roundThinkingContent; // Store thinking content for conversation history
28
29
  reasoningContent = "";
29
30
  reasoningFormat;
30
31
  reasoningSignature;
@@ -130,14 +131,16 @@ export class UIEventAdapter {
130
131
  this.lastTokenTime = now;
131
132
  this.tokenCount++;
132
133
  // Check if we're resuming after tool calls and need to add newlines
133
- if (this.hadToolCallsBeforeResume && this.hasToolCallsInProgress === false) {
134
+ if (this.hadToolCallsBeforeResume &&
135
+ this.hasToolCallsInProgress === false) {
134
136
  // We had tool calls before and now we're receiving content again
135
137
  // Add double newline to separate the content from tool results
136
- if (this.currentMessage.length > 0 && !this.currentMessage.endsWith('\n\n')) {
138
+ if (this.currentMessage.length > 0 &&
139
+ !this.currentMessage.endsWith("\n\n")) {
137
140
  if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
138
141
  console.log(`📝 [UIEventAdapter] Adding newlines after tool calls before resuming content`);
139
142
  }
140
- this.currentMessage += '\n\n';
143
+ this.currentMessage += "\n\n";
141
144
  }
142
145
  // Reset the flag now that we've added the newlines
143
146
  this.hadToolCallsBeforeResume = false;
@@ -383,6 +386,17 @@ export class UIEventAdapter {
383
386
  }
384
387
  // Store final metrics for later retrieval
385
388
  this.finalMetrics = finalMetrics;
389
+ // Check if there are tool calls that haven't been executed yet
390
+ const hasPendingToolCalls = Array.from(this.activeToolCalls.values()).some((toolData) => toolData.status === "ready" ||
391
+ toolData.status === "preparing" ||
392
+ toolData.status === "executing");
393
+ if (hasPendingToolCalls) {
394
+ // Don't emit conversation_completed yet - tool execution will continue
395
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
396
+ console.log(`🔄 [UIEventAdapter] Skipping conversation_completed - ${this.activeToolCalls.size} tool calls pending execution`);
397
+ }
398
+ return; // Exit without emitting conversation_completed
399
+ }
386
400
  // Include context window usage if available
387
401
  const event = {
388
402
  type: "conversation_completed",
@@ -395,10 +409,19 @@ export class UIEventAdapter {
395
409
  // Add native provider usage data if available
396
410
  if (this.usageData) {
397
411
  event.usage = {
398
- promptTokens: this.usageData.prompt_tokens || this.usageData.promptTokens || this.usageData.input_tokens || 0,
399
- completionTokens: this.usageData.completion_tokens || this.usageData.completionTokens || this.usageData.output_tokens || 0,
400
- totalTokens: this.usageData.total_tokens || this.usageData.totalTokens ||
401
- ((this.usageData.input_tokens || 0) + (this.usageData.output_tokens || 0)) || 0,
412
+ promptTokens: this.usageData.prompt_tokens ||
413
+ this.usageData.promptTokens ||
414
+ this.usageData.input_tokens ||
415
+ 0,
416
+ completionTokens: this.usageData.completion_tokens ||
417
+ this.usageData.completionTokens ||
418
+ this.usageData.output_tokens ||
419
+ 0,
420
+ totalTokens: this.usageData.total_tokens ||
421
+ this.usageData.totalTokens ||
422
+ (this.usageData.input_tokens || 0) +
423
+ (this.usageData.output_tokens || 0) ||
424
+ 0,
402
425
  model: this.model,
403
426
  provider: this.modelService,
404
427
  };
@@ -635,4 +658,13 @@ export class UIEventAdapter {
635
658
  console.log(`📊 [UIEventAdapter] Usage data set:`, usage);
636
659
  }
637
660
  }
661
+ /**
662
+ * Set thinking content for this round (for conversation history formatting)
663
+ */
664
+ setRoundThinkingContent(thinkingContent) {
665
+ this.roundThinkingContent = thinkingContent;
666
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
667
+ console.log(`🧠 [UIEventAdapter] Thinking content set for conversation history (${thinkingContent.length} chars)`);
668
+ }
669
+ }
638
670
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphlit-client",
3
- "version": "1.0.20250921001",
3
+ "version": "1.0.20250924001",
4
4
  "description": "Graphlit API Client for TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/client.js",