@adminforth/completion-adapter-google-gemini 2.0.8 → 2.1.0

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.
Files changed (3) hide show
  1. package/dist/index.js +29 -2
  2. package/index.ts +58 -4
  3. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -38,6 +38,20 @@ function getGoogleLangChainAgentOptions(extraRequestBodyParameters) {
38
38
  }
39
39
  return options;
40
40
  }
41
+ function extractUsedTokens(usageMetadata) {
42
+ var _a, _b, _c, _d, _e, _f, _g, _h;
43
+ if (!usageMetadata)
44
+ return undefined;
45
+ const input = (_b = (_a = usageMetadata.promptTokenCount) !== null && _a !== void 0 ? _a : usageMetadata.prompt_token_count) !== null && _b !== void 0 ? _b : 0;
46
+ const inputCached = (_d = (_c = usageMetadata.cachedContentTokenCount) !== null && _c !== void 0 ? _c : usageMetadata.cached_content_token_count) !== null && _d !== void 0 ? _d : 0;
47
+ const output = (_f = (_e = usageMetadata.candidatesTokenCount) !== null && _e !== void 0 ? _e : usageMetadata.candidates_token_count) !== null && _f !== void 0 ? _f : 0;
48
+ const thoughts = (_h = (_g = usageMetadata.thoughtsTokenCount) !== null && _g !== void 0 ? _g : usageMetadata.thoughts_token_count) !== null && _h !== void 0 ? _h : 0;
49
+ return {
50
+ input_uncached: Math.max(input - inputCached, 0),
51
+ input_cached: inputCached,
52
+ output: output + thoughts,
53
+ };
54
+ }
41
55
  export default class CompletionAdapterGoogleGemini {
42
56
  constructor(options) {
43
57
  this.complete = (requestOrContent_1, ...args_1) => __awaiter(this, [requestOrContent_1, ...args_1], void 0, function* (requestOrContent, stopOrMaxTokens = 50, maxTokensOrOutputSchema = 50, outputSchema) {
@@ -63,17 +77,30 @@ export default class CompletionAdapterGoogleGemini {
63
77
  try {
64
78
  const response = yield ai.models.generateContent({
65
79
  model: this.options.model || "gemini-3-flash-preview",
66
- contents: content,
80
+ contents: [
81
+ {
82
+ role: "user",
83
+ parts: [{ text: content }],
84
+ },
85
+ ],
67
86
  config: Object.assign({ responseJsonSchema: requestOutputSchema ? requestOutputSchema : undefined, maxOutputTokens: requestMaxTokens }, this.options.extraRequestBodyParameters),
68
87
  });
69
88
  logger.debug(`Google Gemini SUCCESSFUL API response: ${response}`);
70
89
  return {
71
90
  content: response.text,
91
+ used_tokens: extractUsedTokens(response.usageMetadata),
72
92
  };
73
93
  }
74
94
  catch (error) {
75
95
  logger.error(`Error during Google Gemini API call: ${error}`);
76
- throw new Error(`Error during Google Gemini API call: ${JSON.parse(error.message).error.message}`);
96
+ const errorMessage = error instanceof Error ? error.message : String(error);
97
+ let googleErrorMessage = errorMessage;
98
+ try {
99
+ googleErrorMessage = JSON.parse(errorMessage).error.message;
100
+ }
101
+ catch (_a) {
102
+ }
103
+ throw new Error(`Error during Google Gemini API call: ${googleErrorMessage}`);
77
104
  }
78
105
  });
79
106
  const result = yield pRetry(tryToGenerate, {
package/index.ts CHANGED
@@ -13,6 +13,23 @@ type CompletionRequestInput = {
13
13
 
14
14
  type AgentModelPurpose = "primary" | "summary";
15
15
 
16
+ type GeminiUsageMetadata = {
17
+ promptTokenCount?: number;
18
+ cachedContentTokenCount?: number;
19
+ candidatesTokenCount?: number;
20
+ thoughtsTokenCount?: number;
21
+ prompt_token_count?: number;
22
+ cached_content_token_count?: number;
23
+ candidates_token_count?: number;
24
+ thoughts_token_count?: number;
25
+ };
26
+
27
+ type UsedTokens = {
28
+ input_uncached: number;
29
+ input_cached: number;
30
+ output: number;
31
+ };
32
+
16
33
  const GOOGLE_LANGCHAIN_AGENT_OPTION_KEYS = [
17
34
  "temperature",
18
35
  "topP",
@@ -47,6 +64,30 @@ function getGoogleLangChainAgentOptions(
47
64
  return options;
48
65
  }
49
66
 
67
+ function extractUsedTokens(usageMetadata?: GeminiUsageMetadata): UsedTokens | undefined {
68
+ if (!usageMetadata) return undefined;
69
+
70
+ const input = usageMetadata.promptTokenCount ?? usageMetadata.prompt_token_count ?? 0;
71
+ const inputCached =
72
+ usageMetadata.cachedContentTokenCount ??
73
+ usageMetadata.cached_content_token_count ??
74
+ 0;
75
+ const output =
76
+ usageMetadata.candidatesTokenCount ??
77
+ usageMetadata.candidates_token_count ??
78
+ 0;
79
+ const thoughts =
80
+ usageMetadata.thoughtsTokenCount ??
81
+ usageMetadata.thoughts_token_count ??
82
+ 0;
83
+
84
+ return {
85
+ input_uncached: Math.max(input - inputCached, 0),
86
+ input_cached: inputCached,
87
+ output: output + thoughts,
88
+ };
89
+ }
90
+
50
91
  export default class CompletionAdapterGoogleGemini
51
92
  implements CompletionAdapter
52
93
  {
@@ -61,7 +102,7 @@ export default class CompletionAdapterGoogleGemini
61
102
  throw new Error("geminiApiKey is required");
62
103
  }
63
104
  }
64
-
105
+
65
106
  async measureTokensCount(content: string): Promise<number> {
66
107
  // Implement token counting logic here
67
108
  const ai = new GoogleGenAI({
@@ -82,7 +123,7 @@ export default class CompletionAdapterGoogleGemini
82
123
  const modelOptions = getGoogleLangChainAgentOptions(
83
124
  this.options.extraRequestBodyParameters,
84
125
  );
85
-
126
+
86
127
  return {
87
128
  model: new ChatGoogleGenerativeAI({
88
129
  model: this.options.model || "gemini-3-flash-preview",
@@ -103,6 +144,7 @@ export default class CompletionAdapterGoogleGemini
103
144
  content?: string;
104
145
  finishReason?: string;
105
146
  error?: string;
147
+ used_tokens?: UsedTokens;
106
148
  }> => {
107
149
  const request =
108
150
  typeof requestOrContent === "string"
@@ -135,7 +177,12 @@ export default class CompletionAdapterGoogleGemini
135
177
  try {
136
178
  const response = await ai.models.generateContent({
137
179
  model: this.options.model || "gemini-3-flash-preview",
138
- contents: content,
180
+ contents: [
181
+ {
182
+ role: "user",
183
+ parts: [{ text: content }],
184
+ },
185
+ ],
139
186
  config: {
140
187
  responseJsonSchema: requestOutputSchema ? requestOutputSchema : undefined,
141
188
  maxOutputTokens: requestMaxTokens,
@@ -145,10 +192,17 @@ export default class CompletionAdapterGoogleGemini
145
192
  logger.debug(`Google Gemini SUCCESSFUL API response: ${response}`);
146
193
  return {
147
194
  content: response.text,
195
+ used_tokens: extractUsedTokens(response.usageMetadata),
148
196
  };
149
197
  } catch (error) {
150
198
  logger.error(`Error during Google Gemini API call: ${error}`);
151
- throw new Error(`Error during Google Gemini API call: ${JSON.parse(error.message).error.message}`);
199
+ const errorMessage = error instanceof Error ? error.message : String(error);
200
+ let googleErrorMessage = errorMessage;
201
+ try {
202
+ googleErrorMessage = JSON.parse(errorMessage).error.message;
203
+ } catch {
204
+ }
205
+ throw new Error(`Error during Google Gemini API call: ${googleErrorMessage}`);
152
206
  }
153
207
  }
154
208
  const result = await pRetry(tryToGenerate, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/completion-adapter-google-gemini",
3
- "version": "2.0.8",
3
+ "version": "2.1.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -16,7 +16,7 @@
16
16
  "description": "",
17
17
  "dependencies": {
18
18
  "@google/genai": "^1.35.0",
19
- "@langchain/google-genai": "2.1.27",
19
+ "@langchain/google-genai": "2.1.28",
20
20
  "p-retry": "^7.1.1"
21
21
  },
22
22
  "peerDependencies": {