@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.d.cts CHANGED
@@ -108,20 +108,32 @@ declare class OpenAIProvider extends BaseLLMProvider {
108
108
  text: string;
109
109
  }>;
110
110
  chatCompletion(messages: any, systemPrompt: any, tools?: any, options?: {}): Promise<{
111
+ model: any;
111
112
  parsedContent?: any;
112
113
  content: string;
113
114
  tool_calls: OpenAI.Chat.Completions.ChatCompletionMessageToolCall[];
114
115
  finishReason: string;
115
116
  _rawFinishReason: "content_filter" | "stop" | "length" | "tool_calls" | "function_call";
116
117
  _responseFormat: any;
118
+ usage: {
119
+ prompt_tokens: number;
120
+ completion_tokens: number;
121
+ total_tokens: number;
122
+ };
117
123
  }>;
118
124
  _chatCompletionWithModel(messages: any, systemPrompt: any, tools: any, modelName: any, maxTokens: any, temperature: any, options?: {}): Promise<{
125
+ model: any;
119
126
  parsedContent?: any;
120
127
  content: string;
121
128
  tool_calls: OpenAI.Chat.Completions.ChatCompletionMessageToolCall[];
122
129
  finishReason: string;
123
130
  _rawFinishReason: "content_filter" | "stop" | "length" | "tool_calls" | "function_call";
124
131
  _responseFormat: any;
132
+ usage: {
133
+ prompt_tokens: number;
134
+ completion_tokens: number;
135
+ total_tokens: number;
136
+ };
125
137
  }>;
126
138
  _buildResponseFormat(options: any): {
127
139
  type: string;
@@ -152,6 +164,7 @@ declare class GeminiProvider extends BaseLLMProvider {
152
164
  text: string;
153
165
  }>;
154
166
  chatCompletion(messages: any, systemPrompt: any, tools?: any, options?: {}): Promise<{
167
+ model: any;
155
168
  parsedContent?: any;
156
169
  content: string;
157
170
  thought_signature: any;
@@ -163,8 +176,14 @@ declare class GeminiProvider extends BaseLLMProvider {
163
176
  finishReason: string;
164
177
  _rawFinishReason: _google_genai.FinishReason;
165
178
  _responseFormat: any;
179
+ usage: {
180
+ prompt_tokens: number;
181
+ completion_tokens: number;
182
+ total_tokens: number;
183
+ };
166
184
  }>;
167
185
  _chatCompletionWithModel(messages: any, systemPrompt: any, tools: any, modelName: any, maxTokens: any, temperature: any, options?: {}): Promise<{
186
+ model: any;
168
187
  parsedContent?: any;
169
188
  content: string;
170
189
  thought_signature: any;
@@ -176,6 +195,11 @@ declare class GeminiProvider extends BaseLLMProvider {
176
195
  finishReason: string;
177
196
  _rawFinishReason: _google_genai.FinishReason;
178
197
  _responseFormat: any;
198
+ usage: {
199
+ prompt_tokens: number;
200
+ completion_tokens: number;
201
+ total_tokens: number;
202
+ };
179
203
  }>;
180
204
  _buildGenerationConfig(options: any, maxTokens: any, temperature: any): {
181
205
  temperature: any;
@@ -303,6 +327,12 @@ declare class LLMService {
303
327
  toolCalls: any;
304
328
  finishReason: any;
305
329
  _rawFinishReason: any;
330
+ usage: {
331
+ prompt_tokens: number;
332
+ completion_tokens: number;
333
+ total_tokens: number;
334
+ };
335
+ model: any;
306
336
  }>;
307
337
  /**
308
338
  * Generate a video (async wrapper with polling - backward compatibility)
package/dist/index.d.ts CHANGED
@@ -108,20 +108,32 @@ declare class OpenAIProvider extends BaseLLMProvider {
108
108
  text: string;
109
109
  }>;
110
110
  chatCompletion(messages: any, systemPrompt: any, tools?: any, options?: {}): Promise<{
111
+ model: any;
111
112
  parsedContent?: any;
112
113
  content: string;
113
114
  tool_calls: OpenAI.Chat.Completions.ChatCompletionMessageToolCall[];
114
115
  finishReason: string;
115
116
  _rawFinishReason: "content_filter" | "stop" | "length" | "tool_calls" | "function_call";
116
117
  _responseFormat: any;
118
+ usage: {
119
+ prompt_tokens: number;
120
+ completion_tokens: number;
121
+ total_tokens: number;
122
+ };
117
123
  }>;
118
124
  _chatCompletionWithModel(messages: any, systemPrompt: any, tools: any, modelName: any, maxTokens: any, temperature: any, options?: {}): Promise<{
125
+ model: any;
119
126
  parsedContent?: any;
120
127
  content: string;
121
128
  tool_calls: OpenAI.Chat.Completions.ChatCompletionMessageToolCall[];
122
129
  finishReason: string;
123
130
  _rawFinishReason: "content_filter" | "stop" | "length" | "tool_calls" | "function_call";
124
131
  _responseFormat: any;
132
+ usage: {
133
+ prompt_tokens: number;
134
+ completion_tokens: number;
135
+ total_tokens: number;
136
+ };
125
137
  }>;
126
138
  _buildResponseFormat(options: any): {
127
139
  type: string;
@@ -152,6 +164,7 @@ declare class GeminiProvider extends BaseLLMProvider {
152
164
  text: string;
153
165
  }>;
154
166
  chatCompletion(messages: any, systemPrompt: any, tools?: any, options?: {}): Promise<{
167
+ model: any;
155
168
  parsedContent?: any;
156
169
  content: string;
157
170
  thought_signature: any;
@@ -163,8 +176,14 @@ declare class GeminiProvider extends BaseLLMProvider {
163
176
  finishReason: string;
164
177
  _rawFinishReason: _google_genai.FinishReason;
165
178
  _responseFormat: any;
179
+ usage: {
180
+ prompt_tokens: number;
181
+ completion_tokens: number;
182
+ total_tokens: number;
183
+ };
166
184
  }>;
167
185
  _chatCompletionWithModel(messages: any, systemPrompt: any, tools: any, modelName: any, maxTokens: any, temperature: any, options?: {}): Promise<{
186
+ model: any;
168
187
  parsedContent?: any;
169
188
  content: string;
170
189
  thought_signature: any;
@@ -176,6 +195,11 @@ declare class GeminiProvider extends BaseLLMProvider {
176
195
  finishReason: string;
177
196
  _rawFinishReason: _google_genai.FinishReason;
178
197
  _responseFormat: any;
198
+ usage: {
199
+ prompt_tokens: number;
200
+ completion_tokens: number;
201
+ total_tokens: number;
202
+ };
179
203
  }>;
180
204
  _buildGenerationConfig(options: any, maxTokens: any, temperature: any): {
181
205
  temperature: any;
@@ -303,6 +327,12 @@ declare class LLMService {
303
327
  toolCalls: any;
304
328
  finishReason: any;
305
329
  _rawFinishReason: any;
330
+ usage: {
331
+ prompt_tokens: number;
332
+ completion_tokens: number;
333
+ total_tokens: number;
334
+ };
335
+ model: any;
306
336
  }>;
307
337
  /**
308
338
  * Generate a video (async wrapper with polling - backward compatibility)
package/dist/index.js CHANGED
@@ -394,7 +394,7 @@ var OpenAIProvider = class extends BaseLLMProvider {
394
394
  );
395
395
  }
396
396
  async _chatCompletionWithModel(messages, systemPrompt, tools, modelName, maxTokens, temperature, options = {}) {
397
- var _a, _b;
397
+ var _a, _b, _c, _d, _e;
398
398
  const requestPayload = {
399
399
  model: modelName,
400
400
  temperature: (_a = options.temperature) != null ? _a : temperature,
@@ -431,11 +431,19 @@ var OpenAIProvider = class extends BaseLLMProvider {
431
431
  _rawFinishReason: rawFinishReason,
432
432
  // Keep original for debugging
433
433
  // Add metadata about response format
434
+ // Add metadata about response format
434
435
  _responseFormat: options.responseFormat,
436
+ // Return usage stats
437
+ usage: {
438
+ prompt_tokens: ((_c = response.usage) == null ? void 0 : _c.prompt_tokens) || 0,
439
+ completion_tokens: ((_d = response.usage) == null ? void 0 : _d.completion_tokens) || 0,
440
+ total_tokens: ((_e = response.usage) == null ? void 0 : _e.total_tokens) || 0
441
+ },
435
442
  // Auto-parse JSON if requested
436
443
  ...options.responseFormat && this._shouldAutoParse(options) ? {
437
444
  parsedContent: this._safeJsonParse(message.content)
438
- } : {}
445
+ } : {},
446
+ model: modelName
439
447
  };
440
448
  }
441
449
  _buildResponseFormat(options) {
@@ -578,7 +586,7 @@ var GeminiProvider = class extends BaseLLMProvider {
578
586
  );
579
587
  }
580
588
  async _chatCompletionWithModel(messages, systemPrompt, tools, modelName, maxTokens, temperature, options = {}) {
581
- var _a, _b, _c, _d;
589
+ var _a, _b, _c, _d, _e, _f, _g;
582
590
  const generationConfig = {
583
591
  temperature: (_a = options.temperature) != null ? _a : temperature,
584
592
  maxOutputTokens: (_b = options.maxTokens) != null ? _b : maxTokens
@@ -636,7 +644,6 @@ ${msg.content}`;
636
644
  functionCall: { name: tc.function.name, args: tc.function.arguments || tc.function.args }
637
645
  };
638
646
  if (tc.thought_signature) {
639
- console.log(`[GeminiProvider] Sending thought_signature in tool_call (${tc.thought_signature.length} chars)`);
640
647
  part.thoughtSignature = tc.thought_signature;
641
648
  }
642
649
  return part;
@@ -644,7 +651,6 @@ ${msg.content}`;
644
651
  } else {
645
652
  const part = { text: msg.content || "" };
646
653
  if (isLastAssistantMessage && msg.thought_signature) {
647
- console.log(`[GeminiProvider] Sending thought_signature in text message (${msg.thought_signature.length} chars)`);
648
654
  part.thoughtSignature = msg.thought_signature;
649
655
  }
650
656
  parts2 = [part];
@@ -753,9 +759,16 @@ ${msg.content}`;
753
759
  _rawFinishReason: candidate.finishReason,
754
760
  // Keep original for debugging
755
761
  _responseFormat: options.responseFormat,
762
+ // Return usage stats
763
+ usage: {
764
+ prompt_tokens: ((_e = response.usageMetadata) == null ? void 0 : _e.promptTokenCount) || 0,
765
+ completion_tokens: ((_f = response.usageMetadata) == null ? void 0 : _f.candidatesTokenCount) || 0,
766
+ total_tokens: ((_g = response.usageMetadata) == null ? void 0 : _g.totalTokenCount) || 0
767
+ },
756
768
  ...options.responseFormat && this._shouldAutoParse(options) ? {
757
769
  parsedContent: this._safeJsonParse(textContent)
758
- } : {}
770
+ } : {},
771
+ model: modelName
759
772
  };
760
773
  }
761
774
  _buildGenerationConfig(options, maxTokens, temperature) {
@@ -842,12 +855,15 @@ ${msg.content}`;
842
855
  const tool = toolImplementations[toolName];
843
856
  const tool_call_id = `gemini-tool-call-${index}`;
844
857
  toolCall.id = tool_call_id;
858
+ console.log(`[Tool Call] > ${toolName}:`, JSON.stringify(toolCall.function.args));
845
859
  if (!tool) {
846
860
  console.error(`[Tool Error] Tool '${toolName}' not found`);
847
861
  return { tool_call_id, output: JSON.stringify({ error: `Tool '${toolName}' not found.` }) };
848
862
  }
849
863
  try {
850
864
  const output = await tool(toolCall.function.args, { env, tenantId });
865
+ const preview = typeof output === "string" ? output.length > 200 ? output.substring(0, 200) + "..." : output : JSON.stringify(output).substring(0, 200) + "...";
866
+ console.log(`[Tool Result] < ${toolName}: ${preview}`);
851
867
  return { tool_call_id, output };
852
868
  } catch (error) {
853
869
  console.error(`[Tool Error] ${toolName} failed:`, error.message);
@@ -861,8 +877,9 @@ ${msg.content}`;
861
877
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
862
878
  const modelName = options.model || this.models.image || "gemini-3-pro-image-preview";
863
879
  console.log(`[GeminiProvider] Generating image with model: ${modelName}`);
880
+ const hasReferenceImages = options.images && options.images.length > 0;
864
881
  const generationConfig = {
865
- responseModalities: ["IMAGE"]
882
+ responseModalities: hasReferenceImages ? ["TEXT", "IMAGE"] : ["IMAGE"]
866
883
  };
867
884
  if (options.aspectRatio) {
868
885
  generationConfig.imageConfig = {
@@ -870,7 +887,7 @@ ${msg.content}`;
870
887
  };
871
888
  }
872
889
  const parts = [{ text: prompt }];
873
- if (options.images && options.images.length > 0) {
890
+ if (hasReferenceImages) {
874
891
  options.images.forEach((img) => {
875
892
  parts.push({
876
893
  inlineData: {
@@ -1216,16 +1233,26 @@ var LLMService = class {
1216
1233
  let currentMessages = [...messages];
1217
1234
  const MAX_ITERATIONS = 10;
1218
1235
  let iteration = 0;
1236
+ const accumulateUsage = (responseUsage) => {
1237
+ if (responseUsage) {
1238
+ totalUsage.prompt_tokens += responseUsage.prompt_tokens || 0;
1239
+ totalUsage.completion_tokens += responseUsage.completion_tokens || 0;
1240
+ totalUsage.total_tokens += responseUsage.total_tokens || 0;
1241
+ }
1242
+ };
1219
1243
  const initialResponse = await provider.chatCompletion(
1220
1244
  currentMessages,
1221
1245
  systemPrompt,
1222
1246
  tools,
1223
1247
  options
1224
1248
  );
1249
+ const totalUsage = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };
1250
+ accumulateUsage(initialResponse.usage);
1225
1251
  let { content, tool_calls, parsedContent, finishReason, _rawFinishReason } = initialResponse;
1226
1252
  while (tool_calls && iteration < MAX_ITERATIONS) {
1227
1253
  iteration++;
1228
- console.log(`[Tool Call] Iteration ${iteration}/${MAX_ITERATIONS} with finish reason ${finishReason}: Assistant wants to use tools:`, tool_calls);
1254
+ const toolNames = tool_calls.map((tc) => tc.function.name).join(", ");
1255
+ console.log(`[Tool Call] Iteration ${iteration}/${MAX_ITERATIONS}: Using tools - [${toolNames}]`);
1229
1256
  currentMessages.push({ role: "assistant", content: content || "", tool_calls });
1230
1257
  await provider.executeTools(tool_calls, currentMessages, tenantId, this.toolImplementations, this.env);
1231
1258
  const nextResponse = await provider.chatCompletion(
@@ -1234,6 +1261,7 @@ var LLMService = class {
1234
1261
  tools,
1235
1262
  options
1236
1263
  );
1264
+ accumulateUsage(nextResponse.usage);
1237
1265
  content = nextResponse.content;
1238
1266
  tool_calls = nextResponse.tool_calls;
1239
1267
  parsedContent = nextResponse.parsedContent;
@@ -1243,7 +1271,7 @@ var LLMService = class {
1243
1271
  if (iteration >= MAX_ITERATIONS) {
1244
1272
  console.warn(`[Tool Call] Reached maximum iterations (${MAX_ITERATIONS}). Forcing completion.`);
1245
1273
  }
1246
- return { content, parsedContent, toolCalls: tool_calls, finishReason, _rawFinishReason };
1274
+ return { content, parsedContent, toolCalls: tool_calls, finishReason, _rawFinishReason, usage: totalUsage, model: initialResponse.model || "unknown-model" };
1247
1275
  }
1248
1276
  /**
1249
1277
  * Generate a video (async wrapper with polling - backward compatibility)