@contentgrowth/llm-service 1.0.9 → 1.1.1

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/index.cjs CHANGED
@@ -442,7 +442,7 @@ var OpenAIProvider = class extends BaseLLMProvider {
442
442
  );
443
443
  }
444
444
  async _chatCompletionWithModel(messages, systemPrompt, tools, modelName, maxTokens, temperature, options = {}) {
445
- var _a, _b;
445
+ var _a, _b, _c, _d, _e;
446
446
  const requestPayload = {
447
447
  model: modelName,
448
448
  temperature: (_a = options.temperature) != null ? _a : temperature,
@@ -479,11 +479,19 @@ var OpenAIProvider = class extends BaseLLMProvider {
479
479
  _rawFinishReason: rawFinishReason,
480
480
  // Keep original for debugging
481
481
  // Add metadata about response format
482
+ // Add metadata about response format
482
483
  _responseFormat: options.responseFormat,
484
+ // Return usage stats
485
+ usage: {
486
+ prompt_tokens: ((_c = response.usage) == null ? void 0 : _c.prompt_tokens) || 0,
487
+ completion_tokens: ((_d = response.usage) == null ? void 0 : _d.completion_tokens) || 0,
488
+ total_tokens: ((_e = response.usage) == null ? void 0 : _e.total_tokens) || 0
489
+ },
483
490
  // Auto-parse JSON if requested
484
491
  ...options.responseFormat && this._shouldAutoParse(options) ? {
485
492
  parsedContent: this._safeJsonParse(message.content)
486
- } : {}
493
+ } : {},
494
+ model: modelName
487
495
  };
488
496
  }
489
497
  _buildResponseFormat(options) {
@@ -626,7 +634,7 @@ var GeminiProvider = class extends BaseLLMProvider {
626
634
  );
627
635
  }
628
636
  async _chatCompletionWithModel(messages, systemPrompt, tools, modelName, maxTokens, temperature, options = {}) {
629
- var _a, _b, _c, _d;
637
+ var _a, _b, _c, _d, _e, _f, _g;
630
638
  const generationConfig = {
631
639
  temperature: (_a = options.temperature) != null ? _a : temperature,
632
640
  maxOutputTokens: (_b = options.maxTokens) != null ? _b : maxTokens
@@ -684,7 +692,6 @@ ${msg.content}`;
684
692
  functionCall: { name: tc.function.name, args: tc.function.arguments || tc.function.args }
685
693
  };
686
694
  if (tc.thought_signature) {
687
- console.log(`[GeminiProvider] Sending thought_signature in tool_call (${tc.thought_signature.length} chars)`);
688
695
  part.thoughtSignature = tc.thought_signature;
689
696
  }
690
697
  return part;
@@ -692,7 +699,6 @@ ${msg.content}`;
692
699
  } else {
693
700
  const part = { text: msg.content || "" };
694
701
  if (isLastAssistantMessage && msg.thought_signature) {
695
- console.log(`[GeminiProvider] Sending thought_signature in text message (${msg.thought_signature.length} chars)`);
696
702
  part.thoughtSignature = msg.thought_signature;
697
703
  }
698
704
  parts2 = [part];
@@ -801,9 +807,16 @@ ${msg.content}`;
801
807
  _rawFinishReason: candidate.finishReason,
802
808
  // Keep original for debugging
803
809
  _responseFormat: options.responseFormat,
810
+ // Return usage stats
811
+ usage: {
812
+ prompt_tokens: ((_e = response.usageMetadata) == null ? void 0 : _e.promptTokenCount) || 0,
813
+ completion_tokens: ((_f = response.usageMetadata) == null ? void 0 : _f.candidatesTokenCount) || 0,
814
+ total_tokens: ((_g = response.usageMetadata) == null ? void 0 : _g.totalTokenCount) || 0
815
+ },
804
816
  ...options.responseFormat && this._shouldAutoParse(options) ? {
805
817
  parsedContent: this._safeJsonParse(textContent)
806
- } : {}
818
+ } : {},
819
+ model: modelName
807
820
  };
808
821
  }
809
822
  _buildGenerationConfig(options, maxTokens, temperature) {
@@ -890,12 +903,15 @@ ${msg.content}`;
890
903
  const tool = toolImplementations[toolName];
891
904
  const tool_call_id = `gemini-tool-call-${index}`;
892
905
  toolCall.id = tool_call_id;
906
+ console.log(`[Tool Call] > ${toolName}:`, JSON.stringify(toolCall.function.args));
893
907
  if (!tool) {
894
908
  console.error(`[Tool Error] Tool '${toolName}' not found`);
895
909
  return { tool_call_id, output: JSON.stringify({ error: `Tool '${toolName}' not found.` }) };
896
910
  }
897
911
  try {
898
912
  const output = await tool(toolCall.function.args, { env, tenantId });
913
+ const preview = typeof output === "string" ? output.length > 200 ? output.substring(0, 200) + "..." : output : JSON.stringify(output).substring(0, 200) + "...";
914
+ console.log(`[Tool Result] < ${toolName}: ${preview}`);
899
915
  return { tool_call_id, output };
900
916
  } catch (error) {
901
917
  console.error(`[Tool Error] ${toolName} failed:`, error.message);
@@ -909,8 +925,9 @@ ${msg.content}`;
909
925
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
910
926
  const modelName = options.model || this.models.image || "gemini-3-pro-image-preview";
911
927
  console.log(`[GeminiProvider] Generating image with model: ${modelName}`);
928
+ const hasReferenceImages = options.images && options.images.length > 0;
912
929
  const generationConfig = {
913
- responseModalities: ["IMAGE"]
930
+ responseModalities: hasReferenceImages ? ["TEXT", "IMAGE"] : ["IMAGE"]
914
931
  };
915
932
  if (options.aspectRatio) {
916
933
  generationConfig.imageConfig = {
@@ -918,7 +935,7 @@ ${msg.content}`;
918
935
  };
919
936
  }
920
937
  const parts = [{ text: prompt }];
921
- if (options.images && options.images.length > 0) {
938
+ if (hasReferenceImages) {
922
939
  options.images.forEach((img) => {
923
940
  parts.push({
924
941
  inlineData: {
@@ -1264,16 +1281,26 @@ var LLMService = class {
1264
1281
  let currentMessages = [...messages];
1265
1282
  const MAX_ITERATIONS = 10;
1266
1283
  let iteration = 0;
1284
+ const accumulateUsage = (responseUsage) => {
1285
+ if (responseUsage) {
1286
+ totalUsage.prompt_tokens += responseUsage.prompt_tokens || 0;
1287
+ totalUsage.completion_tokens += responseUsage.completion_tokens || 0;
1288
+ totalUsage.total_tokens += responseUsage.total_tokens || 0;
1289
+ }
1290
+ };
1267
1291
  const initialResponse = await provider.chatCompletion(
1268
1292
  currentMessages,
1269
1293
  systemPrompt,
1270
1294
  tools,
1271
1295
  options
1272
1296
  );
1297
+ const totalUsage = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };
1298
+ accumulateUsage(initialResponse.usage);
1273
1299
  let { content, tool_calls, parsedContent, finishReason, _rawFinishReason } = initialResponse;
1274
1300
  while (tool_calls && iteration < MAX_ITERATIONS) {
1275
1301
  iteration++;
1276
- console.log(`[Tool Call] Iteration ${iteration}/${MAX_ITERATIONS} with finish reason ${finishReason}: Assistant wants to use tools:`, tool_calls);
1302
+ const toolNames = tool_calls.map((tc) => tc.function.name).join(", ");
1303
+ console.log(`[Tool Call] Iteration ${iteration}/${MAX_ITERATIONS}: Using tools - [${toolNames}]`);
1277
1304
  currentMessages.push({ role: "assistant", content: content || "", tool_calls });
1278
1305
  await provider.executeTools(tool_calls, currentMessages, tenantId, this.toolImplementations, this.env);
1279
1306
  const nextResponse = await provider.chatCompletion(
@@ -1282,6 +1309,7 @@ var LLMService = class {
1282
1309
  tools,
1283
1310
  options
1284
1311
  );
1312
+ accumulateUsage(nextResponse.usage);
1285
1313
  content = nextResponse.content;
1286
1314
  tool_calls = nextResponse.tool_calls;
1287
1315
  parsedContent = nextResponse.parsedContent;
@@ -1291,7 +1319,7 @@ var LLMService = class {
1291
1319
  if (iteration >= MAX_ITERATIONS) {
1292
1320
  console.warn(`[Tool Call] Reached maximum iterations (${MAX_ITERATIONS}). Forcing completion.`);
1293
1321
  }
1294
- return { content, parsedContent, toolCalls: tool_calls, finishReason, _rawFinishReason };
1322
+ return { content, parsedContent, toolCalls: tool_calls, finishReason, _rawFinishReason, usage: totalUsage, model: initialResponse.model || "unknown-model" };
1295
1323
  }
1296
1324
  /**
1297
1325
  * Generate a video (async wrapper with polling - backward compatibility)