ak-gemini 1.1.0 → 1.1.11

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/README.md CHANGED
@@ -152,7 +152,16 @@ new AITransformer(options)
152
152
  | retryDelay | number | 1000 | Initial retry delay in ms (exponential backoff) |
153
153
  | logLevel | string | 'info' | Log level: 'trace', 'debug', 'info', 'warn', 'error', 'fatal', or 'none' |
154
154
  | chatConfig | object | ... | Gemini chat config overrides |
155
- | systemInstructions | string | ... | System prompt for Gemini |
155
+ | systemInstructions | string/null/false | (default prompt) | System prompt for Gemini. Pass `null` or `false` to disable. |
156
+ | maxOutputTokens | number | 50000 | Maximum tokens in generated response |
157
+ | thinkingConfig | object | null | Thinking features config (see below) |
158
+ | enableGrounding | boolean | false | Enable Google Search grounding (WARNING: $35/1k queries) |
159
+ | labels | object | null | Billing labels for cost attribution |
160
+ | apiKey | string | env var | Gemini API key (or use `GEMINI_API_KEY` env var) |
161
+ | vertexai | boolean | false | Use Vertex AI instead of Gemini API |
162
+ | project | string | env var | GCP project ID (for Vertex AI) |
163
+ | location | string | 'global' | GCP region (for Vertex AI) |
164
+ | googleAuthOptions | object | null | Auth options for Vertex AI (keyFilename, credentials) |
156
165
 
157
166
  ---
158
167
 
@@ -282,9 +291,85 @@ const result = await transformer.transformWithValidation(
282
291
 
283
292
  ---
284
293
 
294
+ ## Vertex AI Authentication
295
+
296
+ Use Vertex AI instead of the Gemini API for enterprise features, VPC controls, and GCP billing integration.
297
+
298
+ ### With Service Account Key File
299
+
300
+ ```js
301
+ const transformer = new AITransformer({
302
+ vertexai: true,
303
+ project: 'my-gcp-project',
304
+ location: 'us-central1', // Optional: defaults to 'global' endpoint
305
+ googleAuthOptions: {
306
+ keyFilename: './service-account.json'
307
+ }
308
+ });
309
+ ```
310
+
311
+ ### With Application Default Credentials
312
+
313
+ ```js
314
+ // Uses GOOGLE_APPLICATION_CREDENTIALS env var or `gcloud auth application-default login`
315
+ const transformer = new AITransformer({
316
+ vertexai: true,
317
+ project: 'my-gcp-project' // or GOOGLE_CLOUD_PROJECT env var
318
+ });
319
+ ```
320
+
321
+ ---
322
+
323
+ ## Advanced Configuration
324
+
325
+ ### Disabling System Instructions
326
+
327
+ By default, the transformer uses built-in system instructions optimized for JSON transformation. You can provide custom instructions or disable them entirely:
328
+
329
+ ```js
330
+ // Custom system instructions
331
+ new AITransformer({ systemInstructions: "You are a helpful assistant..." });
332
+
333
+ // Disable system instructions entirely (use Gemini's default behavior)
334
+ new AITransformer({ systemInstructions: null });
335
+ new AITransformer({ systemInstructions: false });
336
+ ```
337
+
338
+ ### Thinking Configuration
339
+
340
+ For models that support extended thinking (like `gemini-2.5-flash`):
341
+
342
+ ```js
343
+ const transformer = new AITransformer({
344
+ modelName: 'gemini-2.5-flash',
345
+ thinkingConfig: {
346
+ thinkingBudget: 1024, // Token budget for thinking
347
+ }
348
+ });
349
+ ```
350
+
351
+ ### Billing Labels
352
+
353
+ Labels flow through to GCP billing reports for cost attribution:
354
+
355
+ ```js
356
+ const transformer = new AITransformer({
357
+ labels: {
358
+ client: 'acme_corp',
359
+ app: 'data_pipeline',
360
+ environment: 'production'
361
+ }
362
+ });
363
+
364
+ // Override per-message
365
+ await transformer.message(payload, { labels: { request_type: 'batch' } });
366
+ ```
367
+
368
+ ---
369
+
285
370
  ## Token Window Management & Error Handling
286
371
 
287
- * Throws on missing `GEMINI_API_KEY`
372
+ * Throws on missing credentials (API key for Gemini API, or project ID for Vertex AI)
288
373
  * `.message()` and `.seed()` will *estimate* and prevent calls that would exceed Gemini's model window
289
374
  * All API and parsing errors surfaced as `Error` with context
290
375
  * Validator and retry failures include the number of attempts and last error
package/index.cjs CHANGED
@@ -116,7 +116,6 @@ var AITransformer = class {
116
116
  this.systemInstructionKey = "";
117
117
  this.maxRetries = 3;
118
118
  this.retryDelay = 1e3;
119
- this.systemInstructions = "";
120
119
  this.chatConfig = {};
121
120
  this.apiKey = GEMINI_API_KEY;
122
121
  this.onlyJSON = true;
@@ -152,7 +151,11 @@ var AITransformer = class {
152
151
  var index_default = AITransformer;
153
152
  function AITransformFactory(options = {}) {
154
153
  this.modelName = options.modelName || "gemini-2.5-flash";
155
- this.systemInstructions = options.systemInstructions || DEFAULT_SYSTEM_INSTRUCTIONS;
154
+ if (options.systemInstructions === void 0) {
155
+ this.systemInstructions = DEFAULT_SYSTEM_INSTRUCTIONS;
156
+ } else {
157
+ this.systemInstructions = options.systemInstructions;
158
+ }
156
159
  if (options.logLevel) {
157
160
  this.logLevel = options.logLevel;
158
161
  if (this.logLevel === "none") {
@@ -178,7 +181,7 @@ function AITransformFactory(options = {}) {
178
181
  }
179
182
  this.vertexai = options.vertexai || false;
180
183
  this.project = options.project || process.env.GOOGLE_CLOUD_PROJECT || null;
181
- this.location = options.location || process.env.GOOGLE_CLOUD_LOCATION || "us-central1";
184
+ this.location = options.location || process.env.GOOGLE_CLOUD_LOCATION || void 0;
182
185
  this.googleAuthOptions = options.googleAuthOptions || null;
183
186
  this.apiKey = options.apiKey !== void 0 && options.apiKey !== null ? options.apiKey : GEMINI_API_KEY;
184
187
  if (!this.vertexai && !this.apiKey) {
@@ -189,9 +192,13 @@ function AITransformFactory(options = {}) {
189
192
  }
190
193
  this.chatConfig = {
191
194
  ...DEFAULT_CHAT_CONFIG,
192
- ...options.chatConfig,
193
- systemInstruction: this.systemInstructions
195
+ ...options.chatConfig
194
196
  };
197
+ if (this.systemInstructions) {
198
+ this.chatConfig.systemInstruction = this.systemInstructions;
199
+ } else if (options.systemInstructions !== void 0) {
200
+ delete this.chatConfig.systemInstruction;
201
+ }
195
202
  if (options.maxOutputTokens !== void 0) {
196
203
  if (options.maxOutputTokens === null) {
197
204
  delete this.chatConfig.maxOutputTokens;
@@ -249,7 +256,11 @@ function AITransformFactory(options = {}) {
249
256
  this.groundingConfig = options.groundingConfig || {};
250
257
  this.labels = options.labels || {};
251
258
  if (Object.keys(this.labels).length > 0 && logger_default.level !== "silent") {
252
- logger_default.debug(`Billing labels configured: ${JSON.stringify(this.labels)}`);
259
+ if (!this.vertexai) {
260
+ logger_default.warn(`Billing labels are only supported with Vertex AI. Labels will be ignored.`);
261
+ } else {
262
+ logger_default.debug(`Billing labels configured: ${JSON.stringify(this.labels)}`);
263
+ }
253
264
  }
254
265
  if (this.promptKey === this.answerKey) {
255
266
  throw new Error("Source and target keys cannot be the same. Please provide distinct keys.");
@@ -259,7 +270,7 @@ function AITransformFactory(options = {}) {
259
270
  logger_default.debug(`Using keys - Source: "${this.promptKey}", Target: "${this.answerKey}", Context: "${this.contextKey}"`);
260
271
  logger_default.debug(`Max output tokens set to: ${this.chatConfig.maxOutputTokens}`);
261
272
  if (this.vertexai) {
262
- logger_default.debug(`Using Vertex AI - Project: ${this.project}, Location: ${this.location}`);
273
+ logger_default.debug(`Using Vertex AI - Project: ${this.project}, Location: ${this.location || "global (default)"}`);
263
274
  if (this.googleAuthOptions?.keyFilename) {
264
275
  logger_default.debug(`Auth: Service account key file: ${this.googleAuthOptions.keyFilename}`);
265
276
  } else if (this.googleAuthOptions?.credentials) {
@@ -275,7 +286,7 @@ function AITransformFactory(options = {}) {
275
286
  const clientOptions = this.vertexai ? {
276
287
  vertexai: true,
277
288
  project: this.project,
278
- location: this.location,
289
+ ...this.location && { location: this.location },
279
290
  ...this.googleAuthOptions && { googleAuthOptions: this.googleAuthOptions }
280
291
  } : { apiKey: this.apiKey };
281
292
  const ai = new import_genai.GoogleGenAI(clientOptions);
@@ -290,7 +301,7 @@ async function initChat(force = false) {
290
301
  // @ts-ignore
291
302
  config: {
292
303
  ...this.chatConfig,
293
- ...Object.keys(this.labels).length > 0 && { labels: this.labels }
304
+ ...this.vertexai && Object.keys(this.labels).length > 0 && { labels: this.labels }
294
305
  },
295
306
  history: []
296
307
  };
@@ -373,7 +384,7 @@ ${contextText}
373
384
  // @ts-ignore
374
385
  config: {
375
386
  ...this.chatConfig,
376
- ...Object.keys(this.labels).length > 0 && { labels: this.labels }
387
+ ...this.vertexai && Object.keys(this.labels).length > 0 && { labels: this.labels }
377
388
  },
378
389
  history: [...currentHistory, ...historyToAdd]
379
390
  });
@@ -388,7 +399,7 @@ async function rawMessage(sourcePayload, messageOptions = {}) {
388
399
  }
389
400
  const actualPayload = typeof sourcePayload === "string" ? sourcePayload : JSON.stringify(sourcePayload, null, 2);
390
401
  const mergedLabels = { ...this.labels, ...messageOptions.labels || {} };
391
- const hasLabels = Object.keys(mergedLabels).length > 0;
402
+ const hasLabels = this.vertexai && Object.keys(mergedLabels).length > 0;
392
403
  try {
393
404
  const sendParams = { message: actualPayload };
394
405
  if (hasLabels) {
@@ -603,7 +614,7 @@ async function resetChat() {
603
614
  // @ts-ignore
604
615
  config: {
605
616
  ...this.chatConfig,
606
- ...Object.keys(this.labels).length > 0 && { labels: this.labels }
617
+ ...this.vertexai && Object.keys(this.labels).length > 0 && { labels: this.labels }
607
618
  },
608
619
  history: []
609
620
  };
@@ -647,7 +658,7 @@ async function clearConversation() {
647
658
  // @ts-ignore
648
659
  config: {
649
660
  ...this.chatConfig,
650
- ...Object.keys(this.labels).length > 0 && { labels: this.labels }
661
+ ...this.vertexai && Object.keys(this.labels).length > 0 && { labels: this.labels }
651
662
  },
652
663
  history: exampleHistory
653
664
  });
@@ -701,7 +712,7 @@ async function statelessMessage(sourcePayload, options = {}, validatorFn = null)
701
712
  contents,
702
713
  config: {
703
714
  ...this.chatConfig,
704
- ...Object.keys(mergedLabels).length > 0 && { labels: mergedLabels }
715
+ ...this.vertexai && Object.keys(mergedLabels).length > 0 && { labels: mergedLabels }
705
716
  }
706
717
  });
707
718
  this.lastResponseMetadata = {
package/index.js CHANGED
@@ -106,7 +106,7 @@ class AITransformer {
106
106
  this.systemInstructionKey = "";
107
107
  this.maxRetries = 3;
108
108
  this.retryDelay = 1000;
109
- this.systemInstructions = "";
109
+ // this.systemInstructions = "";
110
110
  this.chatConfig = {};
111
111
  this.apiKey = GEMINI_API_KEY;
112
112
  this.onlyJSON = true; // always return JSON
@@ -160,7 +160,14 @@ export { attemptJSONRecovery }; // Export for testing
160
160
  function AITransformFactory(options = {}) {
161
161
  // ? https://ai.google.dev/gemini-api/docs/models
162
162
  this.modelName = options.modelName || 'gemini-2.5-flash';
163
- this.systemInstructions = options.systemInstructions || DEFAULT_SYSTEM_INSTRUCTIONS;
163
+
164
+ // Only use default if systemInstructions was not provided at all
165
+ if (options.systemInstructions === undefined) {
166
+ this.systemInstructions = DEFAULT_SYSTEM_INSTRUCTIONS;
167
+ } else {
168
+ // Use the provided value (could be null, false, or a custom string)
169
+ this.systemInstructions = options.systemInstructions;
170
+ }
164
171
 
165
172
  // Configure log level - priority: options.logLevel > LOG_LEVEL env > NODE_ENV based defaults > 'info'
166
173
  if (options.logLevel) {
@@ -194,7 +201,7 @@ function AITransformFactory(options = {}) {
194
201
  // Vertex AI configuration
195
202
  this.vertexai = options.vertexai || false;
196
203
  this.project = options.project || process.env.GOOGLE_CLOUD_PROJECT || null;
197
- this.location = options.location || process.env.GOOGLE_CLOUD_LOCATION || 'us-central1';
204
+ this.location = options.location || process.env.GOOGLE_CLOUD_LOCATION || undefined;
198
205
  this.googleAuthOptions = options.googleAuthOptions || null;
199
206
 
200
207
  // API Key (for Gemini API, not Vertex AI)
@@ -211,10 +218,18 @@ function AITransformFactory(options = {}) {
211
218
  // Build chat config, making sure systemInstruction uses the custom instructions
212
219
  this.chatConfig = {
213
220
  ...DEFAULT_CHAT_CONFIG,
214
- ...options.chatConfig,
215
- systemInstruction: this.systemInstructions
221
+ ...options.chatConfig
216
222
  };
217
223
 
224
+ // Handle systemInstructions: use custom if provided, otherwise keep default from DEFAULT_CHAT_CONFIG
225
+ // If explicitly set to null/false, remove it entirely
226
+ if (this.systemInstructions) {
227
+ this.chatConfig.systemInstruction = this.systemInstructions;
228
+ } else if (options.systemInstructions !== undefined) {
229
+ // Explicitly set to null/false/empty - remove system instruction
230
+ delete this.chatConfig.systemInstruction;
231
+ }
232
+
218
233
  // Handle maxOutputTokens with explicit null check
219
234
  // Priority: options.maxOutputTokens > options.chatConfig.maxOutputTokens > DEFAULT
220
235
  // Setting to null explicitly removes the limit
@@ -295,10 +310,14 @@ function AITransformFactory(options = {}) {
295
310
  this.enableGrounding = options.enableGrounding || false;
296
311
  this.groundingConfig = options.groundingConfig || {};
297
312
 
298
- // Billing labels for cost segmentation
313
+ // Billing labels for cost segmentation (Vertex AI only)
299
314
  this.labels = options.labels || {};
300
315
  if (Object.keys(this.labels).length > 0 && log.level !== 'silent') {
301
- log.debug(`Billing labels configured: ${JSON.stringify(this.labels)}`);
316
+ if (!this.vertexai) {
317
+ log.warn(`Billing labels are only supported with Vertex AI. Labels will be ignored.`);
318
+ } else {
319
+ log.debug(`Billing labels configured: ${JSON.stringify(this.labels)}`);
320
+ }
302
321
  }
303
322
 
304
323
  if (this.promptKey === this.answerKey) {
@@ -311,7 +330,7 @@ function AITransformFactory(options = {}) {
311
330
  log.debug(`Max output tokens set to: ${this.chatConfig.maxOutputTokens}`);
312
331
  // Log authentication method
313
332
  if (this.vertexai) {
314
- log.debug(`Using Vertex AI - Project: ${this.project}, Location: ${this.location}`);
333
+ log.debug(`Using Vertex AI - Project: ${this.project}, Location: ${this.location || 'global (default)'}`);
315
334
  if (this.googleAuthOptions?.keyFilename) {
316
335
  log.debug(`Auth: Service account key file: ${this.googleAuthOptions.keyFilename}`);
317
336
  } else if (this.googleAuthOptions?.credentials) {
@@ -330,7 +349,7 @@ function AITransformFactory(options = {}) {
330
349
  ? {
331
350
  vertexai: true,
332
351
  project: this.project,
333
- location: this.location,
352
+ ...(this.location && { location: this.location }),
334
353
  ...(this.googleAuthOptions && { googleAuthOptions: this.googleAuthOptions })
335
354
  }
336
355
  : { apiKey: this.apiKey };
@@ -357,7 +376,7 @@ async function initChat(force = false) {
357
376
  // @ts-ignore
358
377
  config: {
359
378
  ...this.chatConfig,
360
- ...(Object.keys(this.labels).length > 0 && { labels: this.labels })
379
+ ...(this.vertexai && Object.keys(this.labels).length > 0 && { labels: this.labels })
361
380
  },
362
381
  history: [],
363
382
  };
@@ -472,7 +491,7 @@ async function seedWithExamples(examples) {
472
491
  // @ts-ignore
473
492
  config: {
474
493
  ...this.chatConfig,
475
- ...(Object.keys(this.labels).length > 0 && { labels: this.labels })
494
+ ...(this.vertexai && Object.keys(this.labels).length > 0 && { labels: this.labels })
476
495
  },
477
496
  history: [...currentHistory, ...historyToAdd],
478
497
  });
@@ -509,13 +528,14 @@ async function rawMessage(sourcePayload, messageOptions = {}) {
509
528
  : JSON.stringify(sourcePayload, null, 2);
510
529
 
511
530
  // Merge instance labels with per-message labels (per-message takes precedence)
531
+ // Labels only supported with Vertex AI
512
532
  const mergedLabels = { ...this.labels, ...(messageOptions.labels || {}) };
513
- const hasLabels = Object.keys(mergedLabels).length > 0;
533
+ const hasLabels = this.vertexai && Object.keys(mergedLabels).length > 0;
514
534
 
515
535
  try {
516
536
  const sendParams = { message: actualPayload };
517
537
 
518
- // Add config with labels if we have any
538
+ // Add config with labels if we have any (Vertex AI only)
519
539
  if (hasLabels) {
520
540
  sendParams.config = { labels: mergedLabels };
521
541
  }
@@ -862,7 +882,7 @@ async function resetChat() {
862
882
  // @ts-ignore
863
883
  config: {
864
884
  ...this.chatConfig,
865
- ...(Object.keys(this.labels).length > 0 && { labels: this.labels })
885
+ ...(this.vertexai && Object.keys(this.labels).length > 0 && { labels: this.labels })
866
886
  },
867
887
  history: [],
868
888
  };
@@ -933,7 +953,7 @@ async function clearConversation() {
933
953
  // @ts-ignore
934
954
  config: {
935
955
  ...this.chatConfig,
936
- ...(Object.keys(this.labels).length > 0 && { labels: this.labels })
956
+ ...(this.vertexai && Object.keys(this.labels).length > 0 && { labels: this.labels })
937
957
  },
938
958
  history: exampleHistory,
939
959
  });
@@ -1019,7 +1039,7 @@ async function statelessMessage(sourcePayload, options = {}, validatorFn = null)
1019
1039
  // Add the user message
1020
1040
  contents.push({ role: 'user', parts: [{ text: payloadStr }] });
1021
1041
 
1022
- // Merge labels
1042
+ // Merge labels (Vertex AI only)
1023
1043
  const mergedLabels = { ...this.labels, ...(options.labels || {}) };
1024
1044
 
1025
1045
  // Use generateContent instead of chat.sendMessage
@@ -1028,7 +1048,7 @@ async function statelessMessage(sourcePayload, options = {}, validatorFn = null)
1028
1048
  contents: contents,
1029
1049
  config: {
1030
1050
  ...this.chatConfig,
1031
- ...(Object.keys(mergedLabels).length > 0 && { labels: mergedLabels })
1051
+ ...(this.vertexai && Object.keys(mergedLabels).length > 0 && { labels: mergedLabels })
1032
1052
  }
1033
1053
  });
1034
1054
 
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.1.0",
5
+ "version": "1.1.11",
6
6
  "main": "index.js",
7
7
  "files": [
8
8
  "index.js",
@@ -38,8 +38,6 @@
38
38
  "update-deps": "npx npm-check-updates -u && npm install",
39
39
  "prune": "rm -rf tmp/*",
40
40
  "test": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js",
41
- "test:unit": "npm test -- tests/module.test.js",
42
- "test:fixed": "npm test -- --testNamePattern=\"should use context in the prompt and transform accordingly|should augment the payload as instructed by system instructions|should succeed on the first try if validation passes|should handle invalid model names|should handle multiple concurrent messages|should use the constructor-provided asyncValidator|should override system instructions from the file\"",
43
41
  "build:cjs": "esbuild index.js --bundle --platform=node --format=cjs --outfile=index.cjs --external:@google/genai --external:ak-tools --external:dotenv --external:pino-pretty --external:pino",
44
42
  "coverage": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --coverage",
45
43
  "typecheck": "tsc --noEmit",
package/types.d.ts CHANGED
@@ -87,6 +87,7 @@ export interface AITransformerContext {
87
87
  enableGrounding?: boolean; // Enable Google Search grounding (default: false, WARNING: costs $35/1k queries)
88
88
  groundingConfig?: Record<string, any>; // Additional grounding configuration options
89
89
  labels?: Record<string, string>; // Custom labels for billing segmentation (keys: 1-63 chars lowercase, values: max 63 chars)
90
+ vertexai?: boolean; // Whether using Vertex AI (true) or Gemini API (false)
90
91
  estimate?: (nextPayload: Record<string, unknown> | string) => Promise<{ inputTokens: number }>;
91
92
  getLastUsage?: () => UsageData | null;
92
93
  lastResponseMetadata?: ResponseMetadata | null; // Metadata from the last API response
@@ -124,7 +125,7 @@ export interface GoogleAuthOptions {
124
125
  export interface AITransformerOptions {
125
126
  // ? https://ai.google.dev/gemini-api/docs/models
126
127
  modelName?: string; // The Gemini model to use
127
- systemInstructions?: string; // Custom system instructions for the model
128
+ systemInstructions?: string | null | false; // Custom system instructions for the model (null/false = no instructions)
128
129
  chatConfig?: ChatConfig; // Configuration object for the chat session
129
130
  thinkingConfig?: ThinkingConfig; // Thinking features configuration (defaults to thinkingBudget: 0, thinkingLevel: "MINIMAL")
130
131
  maxOutputTokens?: number; // Maximum number of tokens that can be generated in the response (defaults to 50000)
@@ -153,7 +154,7 @@ export interface AITransformerOptions {
153
154
  // Use these instead of apiKey for Vertex AI with service account authentication
154
155
  vertexai?: boolean; // Set to true to use Vertex AI instead of Gemini API
155
156
  project?: string; // Google Cloud project ID (required for Vertex AI)
156
- location?: string; // Google Cloud location/region (e.g., 'us-central1') - required for Vertex AI
157
+ location?: string; // Google Cloud location/region (e.g., 'us-central1'). If not set, defaults to 'global' endpoint
157
158
  googleAuthOptions?: GoogleAuthOptions; // Authentication options for Vertex AI (keyFilename, credentials, etc.)
158
159
  }
159
160
 
@@ -174,7 +175,7 @@ export declare class AITransformer {
174
175
  systemInstructionKey: string;
175
176
  maxRetries: number;
176
177
  retryDelay: number;
177
- systemInstructions: string;
178
+ systemInstructions: string | null | false;
178
179
  chatConfig: ChatConfig;
179
180
  apiKey: string;
180
181
  onlyJSON: boolean;
@@ -185,6 +186,7 @@ export declare class AITransformer {
185
186
  enableGrounding: boolean;
186
187
  groundingConfig: Record<string, any>;
187
188
  labels: Record<string, string>;
189
+ vertexai: boolean;
188
190
  /** Metadata from the last API response (model version, token counts, etc.) */
189
191
  lastResponseMetadata: ResponseMetadata | null;
190
192
  /** Number of history items that are seeded examples (used by clearConversation) */