ak-gemini 1.0.8 → 1.0.9

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/index.cjs CHANGED
@@ -29,6 +29,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // index.js
30
30
  var index_exports = {};
31
31
  __export(index_exports, {
32
+ HarmBlockThreshold: () => import_genai.HarmBlockThreshold,
33
+ HarmCategory: () => import_genai.HarmCategory,
32
34
  ThinkingLevel: () => import_genai.ThinkingLevel,
33
35
  attemptJSONRecovery: () => attemptJSONRecovery,
34
36
  default: () => index_default,
@@ -221,6 +223,8 @@ function AITransformFactory(options = {}) {
221
223
  this.retryDelay = options.retryDelay || 1e3;
222
224
  this.asyncValidator = options.asyncValidator || null;
223
225
  this.onlyJSON = options.onlyJSON !== void 0 ? options.onlyJSON : true;
226
+ this.enableGrounding = options.enableGrounding || false;
227
+ this.groundingConfig = options.groundingConfig || {};
224
228
  if (this.promptKey === this.answerKey) {
225
229
  throw new Error("Source and target keys cannot be the same. Please provide distinct keys.");
226
230
  }
@@ -228,6 +232,8 @@ function AITransformFactory(options = {}) {
228
232
  logger_default.debug(`Creating AI Transformer with model: ${this.modelName}`);
229
233
  logger_default.debug(`Using keys - Source: "${this.promptKey}", Target: "${this.answerKey}", Context: "${this.contextKey}"`);
230
234
  logger_default.debug(`Max output tokens set to: ${this.chatConfig.maxOutputTokens}`);
235
+ logger_default.debug(`Using API key: ${this.apiKey.substring(0, 10)}...`);
236
+ logger_default.debug(`Grounding ${this.enableGrounding ? "ENABLED" : "DISABLED"} (costs $35/1k queries)`);
231
237
  }
232
238
  const ai = new import_genai.GoogleGenAI({ apiKey: this.apiKey });
233
239
  this.genAIClient = ai;
@@ -236,12 +242,19 @@ function AITransformFactory(options = {}) {
236
242
  async function initChat(force = false) {
237
243
  if (this.chat && !force) return;
238
244
  logger_default.debug(`Initializing Gemini chat session with model: ${this.modelName}...`);
239
- this.chat = await this.genAIClient.chats.create({
245
+ const chatOptions = {
240
246
  model: this.modelName,
241
247
  // @ts-ignore
242
248
  config: this.chatConfig,
243
249
  history: []
244
- });
250
+ };
251
+ if (this.enableGrounding) {
252
+ chatOptions.config.tools = [{
253
+ googleSearch: this.groundingConfig
254
+ }];
255
+ logger_default.debug(`Search grounding ENABLED for this session (WARNING: costs $35/1k queries)`);
256
+ }
257
+ this.chat = await this.genAIClient.chats.create(chatOptions);
245
258
  try {
246
259
  await this.genAIClient.models.list();
247
260
  logger_default.debug("Gemini API connection successful.");
@@ -345,6 +358,32 @@ async function prepareAndValidateMessage(sourcePayload, options = {}, validatorF
345
358
  }
346
359
  const maxRetries = options.maxRetries ?? this.maxRetries;
347
360
  const retryDelay = options.retryDelay ?? this.retryDelay;
361
+ const enableGroundingForMessage = options.enableGrounding ?? this.enableGrounding;
362
+ const groundingConfigForMessage = options.groundingConfig ?? this.groundingConfig;
363
+ if (enableGroundingForMessage !== this.enableGrounding) {
364
+ const originalGrounding = this.enableGrounding;
365
+ const originalConfig = this.groundingConfig;
366
+ try {
367
+ this.enableGrounding = enableGroundingForMessage;
368
+ this.groundingConfig = groundingConfigForMessage;
369
+ await this.init(true);
370
+ if (enableGroundingForMessage) {
371
+ logger_default.warn(`Search grounding ENABLED for this message (WARNING: costs $35/1k queries)`);
372
+ } else {
373
+ logger_default.debug(`Search grounding DISABLED for this message`);
374
+ }
375
+ } catch (error) {
376
+ this.enableGrounding = originalGrounding;
377
+ this.groundingConfig = originalConfig;
378
+ throw error;
379
+ }
380
+ const restoreGrounding = async () => {
381
+ this.enableGrounding = originalGrounding;
382
+ this.groundingConfig = originalConfig;
383
+ await this.init(true);
384
+ };
385
+ options._restoreGrounding = restoreGrounding;
386
+ }
348
387
  let lastError = null;
349
388
  let lastPayload = null;
350
389
  if (sourcePayload && isJSON(sourcePayload)) {
@@ -366,12 +405,18 @@ async function prepareAndValidateMessage(sourcePayload, options = {}, validatorF
366
405
  await validatorFn(transformedPayload);
367
406
  }
368
407
  logger_default.debug(`Transformation succeeded on attempt ${attempt + 1}`);
408
+ if (options._restoreGrounding) {
409
+ await options._restoreGrounding();
410
+ }
369
411
  return transformedPayload;
370
412
  } catch (error) {
371
413
  lastError = error;
372
414
  logger_default.warn(`Attempt ${attempt + 1} failed: ${error.message}`);
373
415
  if (attempt >= maxRetries) {
374
416
  logger_default.error(`All ${maxRetries + 1} attempts failed.`);
417
+ if (options._restoreGrounding) {
418
+ await options._restoreGrounding();
419
+ }
375
420
  throw new Error(`Transformation failed after ${maxRetries + 1} attempts. Last error: ${error.message}`);
376
421
  }
377
422
  const delay = retryDelay * Math.pow(2, attempt);
@@ -430,12 +475,19 @@ async function estimateTokenUsage(nextPayload) {
430
475
  async function resetChat() {
431
476
  if (this.chat) {
432
477
  logger_default.debug("Resetting Gemini chat session...");
433
- this.chat = await this.genAIClient.chats.create({
478
+ const chatOptions = {
434
479
  model: this.modelName,
435
480
  // @ts-ignore
436
481
  config: this.chatConfig,
437
482
  history: []
438
- });
483
+ };
484
+ if (this.enableGrounding) {
485
+ chatOptions.config.tools = [{
486
+ googleSearch: this.groundingConfig
487
+ }];
488
+ logger_default.debug(`Search grounding preserved during reset (WARNING: costs $35/1k queries)`);
489
+ }
490
+ this.chat = await this.genAIClient.chats.create(chatOptions);
439
491
  logger_default.debug("Chat session reset.");
440
492
  } else {
441
493
  logger_default.warn("Cannot reset chat session: chat not yet initialized.");
@@ -748,6 +800,8 @@ if (import_meta.url === new URL(`file://${process.argv[1]}`).href) {
748
800
  }
749
801
  // Annotate the CommonJS export names for ESM import in node:
750
802
  0 && (module.exports = {
803
+ HarmBlockThreshold,
804
+ HarmCategory,
751
805
  ThinkingLevel,
752
806
  attemptJSONRecovery,
753
807
  log
package/index.js CHANGED
@@ -28,7 +28,7 @@ import u from 'ak-tools';
28
28
  import path from 'path';
29
29
  import log from './logger.js';
30
30
  export { log };
31
- export { ThinkingLevel };
31
+ export { ThinkingLevel, HarmCategory, HarmBlockThreshold };
32
32
 
33
33
 
34
34
 
@@ -265,6 +265,10 @@ function AITransformFactory(options = {}) {
265
265
  //are we forcing json responses only?
266
266
  this.onlyJSON = options.onlyJSON !== undefined ? options.onlyJSON : true; // If true, only return JSON responses
267
267
 
268
+ // Grounding configuration (disabled by default to avoid costs)
269
+ this.enableGrounding = options.enableGrounding || false;
270
+ this.groundingConfig = options.groundingConfig || {};
271
+
268
272
  if (this.promptKey === this.answerKey) {
269
273
  throw new Error("Source and target keys cannot be the same. Please provide distinct keys.");
270
274
  }
@@ -273,6 +277,9 @@ function AITransformFactory(options = {}) {
273
277
  log.debug(`Creating AI Transformer with model: ${this.modelName}`);
274
278
  log.debug(`Using keys - Source: "${this.promptKey}", Target: "${this.answerKey}", Context: "${this.contextKey}"`);
275
279
  log.debug(`Max output tokens set to: ${this.chatConfig.maxOutputTokens}`);
280
+ // Log API key prefix for tracking (first 10 chars only for security)
281
+ log.debug(`Using API key: ${this.apiKey.substring(0, 10)}...`);
282
+ log.debug(`Grounding ${this.enableGrounding ? 'ENABLED' : 'DISABLED'} (costs $35/1k queries)`);
276
283
  }
277
284
 
278
285
  const ai = new GoogleGenAI({ apiKey: this.apiKey });
@@ -291,12 +298,23 @@ async function initChat(force = false) {
291
298
 
292
299
  log.debug(`Initializing Gemini chat session with model: ${this.modelName}...`);
293
300
 
294
- this.chat = await this.genAIClient.chats.create({
301
+ // Add grounding tools if enabled
302
+ const chatOptions = {
295
303
  model: this.modelName,
296
304
  // @ts-ignore
297
305
  config: this.chatConfig,
298
306
  history: [],
299
- });
307
+ };
308
+
309
+ // Only add tools if grounding is explicitly enabled
310
+ if (this.enableGrounding) {
311
+ chatOptions.config.tools = [{
312
+ googleSearch: this.groundingConfig
313
+ }];
314
+ log.debug(`Search grounding ENABLED for this session (WARNING: costs $35/1k queries)`);
315
+ }
316
+
317
+ this.chat = await this.genAIClient.chats.create(chatOptions);
300
318
 
301
319
  try {
302
320
  await this.genAIClient.models.list();
@@ -463,6 +481,47 @@ async function prepareAndValidateMessage(sourcePayload, options = {}, validatorF
463
481
  const maxRetries = options.maxRetries ?? this.maxRetries;
464
482
  const retryDelay = options.retryDelay ?? this.retryDelay;
465
483
 
484
+ // Check if grounding should be enabled for this specific message
485
+ const enableGroundingForMessage = options.enableGrounding ?? this.enableGrounding;
486
+ const groundingConfigForMessage = options.groundingConfig ?? this.groundingConfig;
487
+
488
+ // Reinitialize chat if grounding settings changed for this message
489
+ if (enableGroundingForMessage !== this.enableGrounding) {
490
+ const originalGrounding = this.enableGrounding;
491
+ const originalConfig = this.groundingConfig;
492
+
493
+ try {
494
+ // Temporarily change grounding settings
495
+ this.enableGrounding = enableGroundingForMessage;
496
+ this.groundingConfig = groundingConfigForMessage;
497
+
498
+ // Force reinit with new settings
499
+ await this.init(true);
500
+
501
+ // Log the change
502
+ if (enableGroundingForMessage) {
503
+ log.warn(`Search grounding ENABLED for this message (WARNING: costs $35/1k queries)`);
504
+ } else {
505
+ log.debug(`Search grounding DISABLED for this message`);
506
+ }
507
+ } catch (error) {
508
+ // Restore original settings on error
509
+ this.enableGrounding = originalGrounding;
510
+ this.groundingConfig = originalConfig;
511
+ throw error;
512
+ }
513
+
514
+ // Schedule restoration after message completes
515
+ const restoreGrounding = async () => {
516
+ this.enableGrounding = originalGrounding;
517
+ this.groundingConfig = originalConfig;
518
+ await this.init(true);
519
+ };
520
+
521
+ // Store restoration function to call after message completes
522
+ options._restoreGrounding = restoreGrounding;
523
+ }
524
+
466
525
  let lastError = null;
467
526
  let lastPayload = null; // Store the payload that caused the validation error
468
527
 
@@ -498,6 +557,12 @@ async function prepareAndValidateMessage(sourcePayload, options = {}, validatorF
498
557
 
499
558
  // Step 3: Success!
500
559
  log.debug(`Transformation succeeded on attempt ${attempt + 1}`);
560
+
561
+ // Restore original grounding settings if they were changed
562
+ if (options._restoreGrounding) {
563
+ await options._restoreGrounding();
564
+ }
565
+
501
566
  return transformedPayload;
502
567
 
503
568
  } catch (error) {
@@ -506,6 +571,12 @@ async function prepareAndValidateMessage(sourcePayload, options = {}, validatorF
506
571
 
507
572
  if (attempt >= maxRetries) {
508
573
  log.error(`All ${maxRetries + 1} attempts failed.`);
574
+
575
+ // Restore original grounding settings even on failure
576
+ if (options._restoreGrounding) {
577
+ await options._restoreGrounding();
578
+ }
579
+
509
580
  throw new Error(`Transformation failed after ${maxRetries + 1} attempts. Last error: ${error.message}`);
510
581
  }
511
582
 
@@ -607,12 +678,24 @@ async function estimateTokenUsage(nextPayload) {
607
678
  async function resetChat() {
608
679
  if (this.chat) {
609
680
  log.debug("Resetting Gemini chat session...");
610
- this.chat = await this.genAIClient.chats.create({
681
+
682
+ // Prepare chat options with grounding if enabled
683
+ const chatOptions = {
611
684
  model: this.modelName,
612
685
  // @ts-ignore
613
686
  config: this.chatConfig,
614
687
  history: [],
615
- });
688
+ };
689
+
690
+ // Only add tools if grounding is explicitly enabled
691
+ if (this.enableGrounding) {
692
+ chatOptions.config.tools = [{
693
+ googleSearch: this.groundingConfig
694
+ }];
695
+ log.debug(`Search grounding preserved during reset (WARNING: costs $35/1k queries)`);
696
+ }
697
+
698
+ this.chat = await this.genAIClient.chats.create(chatOptions);
616
699
  log.debug("Chat session reset.");
617
700
  } else {
618
701
  log.warn("Cannot reset chat session: chat not yet initialized.");
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "ak-gemini",
3
3
  "author": "ak@mixpanel.com",
4
4
  "description": "AK's Generative AI Helper for doing... transforms",
5
- "version": "1.0.8",
5
+ "version": "1.0.9",
6
6
  "main": "index.js",
7
7
  "files": [
8
8
  "index.js",
package/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { GoogleGenAI, ThinkingLevel } from '@google/genai';
1
+ import type { GoogleGenAI, ThinkingLevel, HarmCategory, HarmBlockThreshold } from '@google/genai';
2
2
 
3
- export { ThinkingLevel };
3
+ export { ThinkingLevel, HarmCategory, HarmBlockThreshold };
4
4
 
5
5
  export interface ThinkingConfig {
6
6
  /** Indicates whether to include thoughts in the response. If true, thoughts are returned only if the model supports thought and thoughts are available. */
@@ -12,8 +12,8 @@ export interface ThinkingConfig {
12
12
  }
13
13
 
14
14
  export interface SafetySetting {
15
- category: string; // The harm category
16
- threshold: string; // The blocking threshold
15
+ category: HarmCategory; // The harm category
16
+ threshold: HarmBlockThreshold; // The blocking threshold
17
17
  }
18
18
 
19
19
  export interface ChatConfig {
@@ -51,7 +51,9 @@ export interface AITransformerContext {
51
51
  rawMessage?: (payload: Record<string, unknown> | string) => Promise<Record<string, unknown>>; // Function to send raw messages to the model
52
52
  genAIClient?: GoogleGenAI; // Google GenAI client instance
53
53
  onlyJSON?: boolean; // If true, only JSON responses are allowed
54
-
54
+ enableGrounding?: boolean; // Enable Google Search grounding (default: false, WARNING: costs $35/1k queries)
55
+ groundingConfig?: Record<string, any>; // Additional grounding configuration options
56
+
55
57
  }
56
58
 
57
59
  export interface TransformationExample {
@@ -93,6 +95,8 @@ export interface AITransformerOptions {
93
95
  onlyJSON?: boolean; // If true, only JSON responses are allowed
94
96
  asyncValidator?: AsyncValidatorFunction; // Optional async validator function for response validation
95
97
  logLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'none'; // Log level for the logger (defaults to 'info', 'none' disables logging)
98
+ enableGrounding?: boolean; // Enable Google Search grounding (default: false, WARNING: costs $35/1k queries)
99
+ groundingConfig?: Record<string, any>; // Additional grounding configuration options
96
100
  }
97
101
 
98
102
  // Async validator function type
@@ -120,6 +124,8 @@ export declare class AITransformer {
120
124
  genAIClient: any;
121
125
  chat: any;
122
126
  logLevel: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'none';
127
+ enableGrounding: boolean;
128
+ groundingConfig: Record<string, any>;
123
129
 
124
130
  // Methods
125
131
  init(force?: boolean): Promise<void>;