graphlit-client 1.0.20250924004 → 1.0.20250924005

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.
@@ -914,6 +914,9 @@ onEvent, onComplete, abortSignal, thinkingConfig) {
914
914
  let toolArgumentTokens = 0;
915
915
  let lastEventTime = 0;
916
916
  const interTokenDelays = [];
917
+ // Thinking content detection state for Google
918
+ let hasEmittedThinkingStart = false;
919
+ let allThinkingContent = "";
917
920
  // Tool calling metrics
918
921
  const toolMetrics = {
919
922
  totalTools: 0,
@@ -984,13 +987,17 @@ onEvent, onComplete, abortSignal, thinkingConfig) {
984
987
  maxOutputTokens: streamConfig.max_tokens,
985
988
  };
986
989
  if (thinkingConfig) {
987
- // Google Gemini 2.5 Flash+ supports thinking mode
990
+ // Google Gemini 2.5 supports thinking mode
991
+ // -1 = dynamic thinking (model decides), 0 = disabled, >0 = specific budget
992
+ const budget = thinkingConfig.budget_tokens === 0 ? 0 :
993
+ thinkingConfig.budget_tokens || -1; // Default to dynamic if not specified
988
994
  generationConfig.thinkingConfig = {
989
- thinkingBudget: thinkingConfig.budget_tokens,
990
- includeThoughts: true, // Include thinking content in the response
995
+ thinkingBudget: budget,
996
+ includeThoughts: budget !== 0, // Include thoughts unless explicitly disabled
991
997
  };
992
998
  if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
993
- console.log(`🧠 [Google] Extended thinking enabled | Budget: ${thinkingConfig.budget_tokens} tokens | Include thoughts: true`);
999
+ const mode = budget === -1 ? "dynamic" : budget === 0 ? "disabled" : `${budget} tokens`;
1000
+ console.log(`🧠 [Google] Thinking mode: ${mode} | Include thoughts: ${budget !== 0}`);
994
1001
  }
995
1002
  }
996
1003
  else {
@@ -1011,6 +1018,23 @@ onEvent, onComplete, abortSignal, thinkingConfig) {
1011
1018
  const chat = model.startChat({ history });
1012
1019
  const result = await chat.sendMessageStream(prompt);
1013
1020
  for await (const chunk of result.stream) {
1021
+ // Check for thought parts in streaming chunks first (Google's thinking API)
1022
+ if (thinkingConfig && chunk.candidates?.[0]?.content?.parts) {
1023
+ for (const part of chunk.candidates[0].content.parts) {
1024
+ if (part.thought && part.text) {
1025
+ // Emit thinking content as reasoning events
1026
+ if (!hasEmittedThinkingStart) {
1027
+ onEvent({ type: "reasoning_start", format: "markdown" });
1028
+ hasEmittedThinkingStart = true;
1029
+ allThinkingContent = "";
1030
+ }
1031
+ allThinkingContent += part.text + "\n";
1032
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
1033
+ console.log(`[Google] Streaming thought part: ${part.text.length} chars`);
1034
+ }
1035
+ }
1036
+ }
1037
+ }
1014
1038
  const text = chunk.text();
1015
1039
  if (text) {
1016
1040
  fullMessage += text;
@@ -1133,7 +1157,47 @@ onEvent, onComplete, abortSignal, thinkingConfig) {
1133
1157
  console.log(`[Google] Processing final response with ${candidate.content.parts.length} parts`);
1134
1158
  }
1135
1159
  if (candidate?.content?.parts) {
1160
+ let collectedThoughts = "";
1161
+ let hasThoughts = false;
1162
+ // First pass: collect all thought parts from final response
1136
1163
  for (const part of candidate.content.parts) {
1164
+ // Check for thinking/thought parts (Google's thinking API)
1165
+ if (part.thought && thinkingConfig) {
1166
+ hasThoughts = true;
1167
+ collectedThoughts += (part.text || "") + "\n";
1168
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
1169
+ console.log(`[Google] Found thought part in final response: ${part.text?.length || 0} chars`);
1170
+ }
1171
+ }
1172
+ }
1173
+ // Emit thinking events if we found thoughts
1174
+ if (hasThoughts && collectedThoughts) {
1175
+ if (!hasEmittedThinkingStart) {
1176
+ onEvent({ type: "reasoning_start", format: "markdown" });
1177
+ }
1178
+ // Combine with any streaming thoughts
1179
+ const finalThoughts = allThinkingContent + collectedThoughts;
1180
+ onEvent({
1181
+ type: "reasoning_end",
1182
+ fullContent: finalThoughts.trim(),
1183
+ });
1184
+ if (process.env.DEBUG_GRAPHLIT_SDK_STREAMING) {
1185
+ console.log(`[Google] Emitted complete thinking: ${finalThoughts.length} chars`);
1186
+ }
1187
+ }
1188
+ else if (hasEmittedThinkingStart && allThinkingContent) {
1189
+ // Close thinking from streaming if no final thoughts
1190
+ onEvent({
1191
+ type: "reasoning_end",
1192
+ fullContent: allThinkingContent.trim(),
1193
+ });
1194
+ }
1195
+ // Second pass: handle regular text parts
1196
+ for (const part of candidate.content.parts) {
1197
+ // Skip thought parts - we already handled them
1198
+ if (part.thought) {
1199
+ continue;
1200
+ }
1137
1201
  // Check for any final text we might have missed
1138
1202
  if (part.text) {
1139
1203
  const finalText = part.text;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphlit-client",
3
- "version": "1.0.20250924004",
3
+ "version": "1.0.20250924005",
4
4
  "description": "Graphlit API Client for TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/client.js",