@ibgib/web-gib 0.0.4 → 0.0.6

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 (57) hide show
  1. package/dist/api/commands/chat/tell-user.d.mts.map +1 -1
  2. package/dist/api/commands/chat/tell-user.mjs +1 -1
  3. package/dist/api/commands/chat/tell-user.mjs.map +1 -1
  4. package/dist/common/settings/settings-constants.d.mts.map +1 -1
  5. package/dist/common/settings/settings-constants.mjs.map +1 -1
  6. package/dist/helpers.d.mts +7 -0
  7. package/dist/helpers.d.mts.map +1 -1
  8. package/dist/helpers.mjs +25 -0
  9. package/dist/helpers.mjs.map +1 -1
  10. package/dist/helpers.web.d.mts +22 -0
  11. package/dist/helpers.web.d.mts.map +1 -1
  12. package/dist/helpers.web.mjs +22 -0
  13. package/dist/helpers.web.mjs.map +1 -1
  14. package/dist/witness/agent/agent-helpers.d.mts +81 -3
  15. package/dist/witness/agent/agent-helpers.d.mts.map +1 -1
  16. package/dist/witness/agent/agent-helpers.mjs +211 -2
  17. package/dist/witness/agent/agent-helpers.mjs.map +1 -1
  18. package/dist/witness/agent/agent-one-file.d.mts +1 -264
  19. package/dist/witness/agent/agent-one-file.d.mts.map +1 -1
  20. package/dist/witness/agent/agent-one-file.mjs +4 -242
  21. package/dist/witness/agent/agent-one-file.mjs.map +1 -1
  22. package/dist/witness/agent/agent-types.d.mts +189 -1
  23. package/dist/witness/agent/agent-types.d.mts.map +1 -1
  24. package/dist/witness/agent/agent-types.mjs +30 -1
  25. package/dist/witness/agent/agent-types.mjs.map +1 -1
  26. package/dist/witness/agent/agents-service-v1.d.mts +1 -1
  27. package/dist/witness/agent/agents-service-v1.d.mts.map +1 -1
  28. package/dist/witness/agent/agents-service-v1.mjs +1 -2
  29. package/dist/witness/agent/agents-service-v1.mjs.map +1 -1
  30. package/dist/witness/agent/gemini/agent-witness-gemini-v1.d.mts +4 -3
  31. package/dist/witness/agent/gemini/agent-witness-gemini-v1.d.mts.map +1 -1
  32. package/dist/witness/agent/gemini/agent-witness-gemini-v1.mjs +162 -88
  33. package/dist/witness/agent/gemini/agent-witness-gemini-v1.mjs.map +1 -1
  34. package/dist/witness/agent/gemini/gemini-agent-factory.d.mts +2 -1
  35. package/dist/witness/agent/gemini/gemini-agent-factory.d.mts.map +1 -1
  36. package/dist/witness/agent/gemini/gemini-agent-factory.mjs +1 -1
  37. package/dist/witness/agent/gemini/gemini-agent-factory.mjs.map +1 -1
  38. package/dist/witness/agent/gemini/gemini-helpers.d.mts +11 -4
  39. package/dist/witness/agent/gemini/gemini-helpers.d.mts.map +1 -1
  40. package/dist/witness/agent/gemini/gemini-helpers.mjs +7 -3
  41. package/dist/witness/agent/gemini/gemini-helpers.mjs.map +1 -1
  42. package/dist/witness/agent/gemini/gemini-types.d.mts +21 -13
  43. package/dist/witness/agent/gemini/gemini-types.d.mts.map +1 -1
  44. package/dist/witness/agent/gemini/gemini-types.mjs.map +1 -1
  45. package/package.json +2 -2
  46. package/src/api/commands/chat/tell-user.mts +1 -3
  47. package/src/common/settings/settings-constants.mts +4 -1
  48. package/src/helpers.mts +24 -0
  49. package/src/helpers.web.mts +22 -0
  50. package/src/witness/agent/agent-helpers.mts +243 -5
  51. package/src/witness/agent/agent-one-file.mts +8 -473
  52. package/src/witness/agent/agent-types.mts +228 -3
  53. package/src/witness/agent/agents-service-v1.mts +3 -2
  54. package/src/witness/agent/gemini/agent-witness-gemini-v1.mts +193 -96
  55. package/src/witness/agent/gemini/gemini-agent-factory.mts +2 -1
  56. package/src/witness/agent/gemini/gemini-helpers.mts +16 -6
  57. package/src/witness/agent/gemini/gemini-types.mts +39 -13
@@ -1,7 +1,15 @@
1
+ /**
2
+ * @module agent-witness-gemini-v1.mts
3
+ *
4
+ * ## MIGRATING TO @google/genai NOTES
5
+ *
6
+ * * Different Part types (TextPart, FunctionCallPart) are apparently "unified" in the new structure as just Part
7
+ */
8
+ import { FunctionCallPart, FunctionResponsePart, } from './gemini-types.mjs';
1
9
  import {
2
- EnhancedGenerateContentResponse, ErrorDetails, FunctionCallPart, FunctionCallingMode,
3
- FunctionResponsePart, GenerateContentResult, GoogleGenerativeAI, TextPart,
4
- } from '@google/generative-ai';
10
+ Part, GenerateContentResponse, Content, GoogleGenAI, SendMessageParameters,
11
+ CreateChatParameters, FunctionCallingConfigMode, FunctionCall,
12
+ } from '@google/genai';
5
13
 
6
14
  import { clone, delay, extractErrorMsg, getTimestampInTicks, pretty } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
7
15
  import { Ib, IbGibAddr, TransformResult } from '@ibgib/ts-gib/dist/types.mjs';
@@ -11,17 +19,19 @@ import { ROOT_ADDR } from '@ibgib/ts-gib/dist/V1/constants.mjs';
11
19
  import { getGibInfo } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';
12
20
  import { CommentIbGib_V1 } from '@ibgib/core-gib/dist/common/comment/comment-types.mjs';
13
21
  import { createCommentIbGib, parseCommentIb } from '@ibgib/core-gib/dist/common/comment/comment-helper.mjs';
14
- import { MetaspaceService } from '@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs';
15
- import { IbGibSpaceAny } from '@ibgib/core-gib/dist/witness/space/space-base-v1.mjs';
22
+ import { execInSpaceWithLocking } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';
23
+ import { appendToTimeline, Rel8nInfo } from '@ibgib/core-gib/dist/timeline/timeline-api.mjs';
16
24
 
17
25
  import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
18
26
  import { getAllFunctionInfos, getDeprecatedFunctionInfoNames } from '../../../api/api-index.mjs';
19
27
  import {
20
- AddTextsOpts, AgentWitnessData_V1, AgentWitnessIbGib_V1, AgentWitnessRel8ns_V1, AgentWitness_V1,
28
+ AddTextsOpts, AgentWitnessData_V1, AgentWitnessIbGib_V1, AgentWitnessRel8ns_V1,
21
29
  PromptOneOffOpts,
30
+ } from '../agent-types.mjs';
31
+ import {
22
32
  getAddlMetadataTextForAgentText,
23
33
  parseAddlMetadataTextForAgentText, validateAgentWitnessCommentIbGib
24
- } from '../agent-one-file.mjs';
34
+ } from '../agent-helpers.mjs';
25
35
  import {
26
36
  getFunctionCallAndResponseParts, isFunctionCallRequestComment,
27
37
  isPromptInfoGemini, systemPromptEntriesToSystemInstructionContent,
@@ -33,14 +43,13 @@ import { agentIbGibDtoToWitness } from './gemini-agent-factory.mjs';
33
43
  import { getAgentsSvc } from '../agents-service-v1.mjs';
34
44
  import { GEMINI_BACKUP_MODEL_STR, GEMINI_ERROR_DETAILS_TYPE_RETRY_INFO, GEMINI_ERROR_DETAILS_TYPE_RETRY_INFO_RETRY_DELAY_KEY, GEMINI_ERROR_STATUS_MODEL_OVERLOADED, GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED, GEMINI_MAX_TRY_COUNT } from './gemini-constants.mjs';
35
45
  import { AGENT_REL8N_NAME, TextSource } from '../agent-constants.mjs';
36
- // import { appendToTimeline, getLockScope, mut8Timeline, Rel8nInfo } from '../../../api/timeline/timeline-api.mjs';
37
- import { execInSpaceWithLocking } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';
38
- import { appendToTimeline, Rel8nInfo } from '@ibgib/core-gib/dist/timeline/timeline-api.mjs';
46
+ import { AgentWitness_V1 } from '../agent-one-file.mjs';
39
47
 
40
48
  const logalot = GLOBAL_LOG_A_LOT;
41
49
 
42
50
  export class AgentWitnessGemini_V1
43
- extends AgentWitness_V1<GoogleGenerativeAI, PromptInfoGemini, PromptAPIResult_Gemini> {
51
+ extends AgentWitness_V1<GoogleGenAI, PromptInfoGemini, PromptAPIResult_Gemini> {
52
+ // extends AgentWitness_V1<GoogleGenerativeAI, PromptInfoGemini, PromptAPIResult_Gemini> {
44
53
  // witness(arg: IbGib_V1): Promise<IbGib_V1 | undefined> {
45
54
  // throw new Error('Method not implemented.');
46
55
  // }
@@ -265,7 +274,8 @@ export class AgentWitnessGemini_V1
265
274
  text: getTextPartForCurrentContextTjpAddr({
266
275
  currentContextTjpAddr
267
276
  })
268
- } satisfies TextPart
277
+ } satisfies Part // see genai migration note at top of this file
278
+ // } satisfies TextPart
269
279
  ],
270
280
  }
271
281
  })
@@ -341,7 +351,8 @@ export class AgentWitnessGemini_V1
341
351
  text: 'no api key entered so no LLM chat happening. enter a gemini api key and donate/invest!',
342
352
  }; /* <<<< returns early */
343
353
  }
344
- this._genAI ??= new GoogleGenerativeAI(apiKey);
354
+ this._genAI ??= new GoogleGenAI({ apiKey });
355
+ // this._genAI ??= new GoogleGenerativeAI(apiKey);
345
356
 
346
357
  const functionDeclarations = Array.from(this.availableFunctions.values()).map(
347
358
  (x) => ({
@@ -388,7 +399,8 @@ export class AgentWitnessGemini_V1
388
399
  // this.transientDecompressionPromptText = undefined;
389
400
  // }
390
401
 
391
- let result: GenerateContentResult | undefined = undefined;
402
+ let result: GenerateContentResponse | undefined = undefined;
403
+ // let result: GenerateContentResult | undefined = undefined;
392
404
 
393
405
  /**
394
406
  * need to be able to call this function with retries with different
@@ -403,33 +415,75 @@ export class AgentWitnessGemini_V1
403
415
  * @param modelStr to use
404
416
  * @param isRetry if true, this indicates this is aleady a retry and should throw if fails
405
417
  */
418
+ // const fnGoModel = async (modelStr: string) => {
419
+ // if (!this._genAI) { throw new Error(`(UNEXPECTED) this._genAI falsy? (E: 503a0d9e3f729de7653ee3565b017b25)`); }
420
+ // const genModel = this._genAI.getGenerativeModel({
421
+ // model: modelStr,
422
+ // systemInstruction: systemPromptEntriesToSystemInstructionContent({ systemPromptEntries }),
423
+ // tools: [{ functionDeclarations }],
424
+ // toolConfig: {
425
+ // functionCallingConfig: {
426
+ // // mode: FunctionCallingMode.AUTO, // can be either text or function call, this is the default
427
+ // mode:
428
+ // info.overrideFunctionCallingMode ??
429
+ // FunctionCallingMode.ANY, // MANDATES a function call. If this is not used, the model gets confused, but maybe this will be fixed after we get better function response feedback in place.
430
+ // },
431
+ // },
432
+ // });
433
+ // /**
434
+ // * We start a "chat", _BUT ONLY TO USE THE HISTORY MECHANISM_.
435
+ // * Really we use this as a one-off, but we do not know how to mimic
436
+ // * the "history" so that the model understands to only respond to
437
+ // * the most recent prompt.
438
+ // */
439
+ // const chat = genModel.startChat({
440
+ // history: chatPromptHistoryParts.map(x => x.content),
441
+ // });
442
+ // result = await chat.sendMessage(chatPromptCurrent.content.parts);
443
+ // return result;
444
+ // }
445
+ // interface ChatConfigParams {
446
+ // model: string;
447
+ // history: Content[];
448
+ // config: GenerateContentConfig;
449
+ // }
450
+
406
451
  const fnGoModel = async (modelStr: string) => {
407
- if (!this._genAI) { throw new Error(`(UNEXPECTED) this._genAI falsy? (E: 503a0d9e3f729de7653ee3565b017b25)`); }
408
- const genModel = this._genAI.getGenerativeModel({
452
+ if (!this._genAI) {
453
+ throw new Error(`(UNEXPECTED) this._genAI falsy? (E: 503a0d9e3f729de7653ee3565b017b25)`);
454
+ }
455
+
456
+ const historyContents: Content[] = chatPromptHistoryParts.map(x => x.content);
457
+
458
+ const chatConfig: CreateChatParameters = {
409
459
  model: modelStr,
410
- systemInstruction: systemPromptEntriesToSystemInstructionContent({ systemPromptEntries }),
411
- tools: [{ functionDeclarations }],
412
- toolConfig: {
413
- functionCallingConfig: {
414
- // mode: FunctionCallingMode.AUTO, // can be either text or function call, this is the default
415
- mode:
416
- info.overrideFunctionCallingMode ??
417
- FunctionCallingMode.ANY, // MANDATES a function call. If this is not used, the model gets confused, but maybe this will be fixed after we get better function response feedback in place.
460
+ history: historyContents,
461
+ config: {
462
+ systemInstruction: systemPromptEntriesToSystemInstructionContent({ systemPromptEntries }),
463
+ tools: [{ functionDeclarations }],
464
+ toolConfig: {
465
+ functionCallingConfig: {
466
+ mode: info.overrideFunctionCallingMode ?? FunctionCallingConfigMode.ANY,
467
+ },
418
468
  },
419
- },
420
- });
421
- /**
422
- * We start a "chat", _BUT ONLY TO USE THE HISTORY MECHANISM_.
423
- * Really we use this as a one-off, but we do not know how to mimic
424
- * the "history" so that the model understands to only respond to
425
- * the most recent prompt.
426
- */
427
- const chat = genModel.startChat({
428
- history: chatPromptHistoryParts.map(x => x.content),
429
- });
430
- result = await chat.sendMessage(chatPromptCurrent.content.parts);
469
+ }
470
+ };
471
+
472
+ const chat = this._genAI.chats.create(chatConfig);
473
+
474
+ // The 'sendMessage' method requires a `message` property in its parameters object.
475
+ // The message content itself can be a string or Part[] (PartListUnion).
476
+
477
+ // Prepare the message parameters:
478
+ const messageParams: SendMessageParameters = {
479
+ message: chatPromptCurrent.content.parts as Part[], // Cast to Part[] to satisfy the type
480
+ };
481
+
482
+ // The result is typed as GenerateContentResponse
483
+ const result: GenerateContentResponse = await chat.sendMessage(messageParams);
484
+
431
485
  return result;
432
- }
486
+ };
433
487
 
434
488
  let tryCount = 0;
435
489
  let modelStr = model;
@@ -439,7 +493,11 @@ export class AgentWitnessGemini_V1
439
493
  result = await fnGoModel(modelStr);
440
494
  break;
441
495
  } catch (error) {
442
- if (error.status && error.status === GEMINI_ERROR_STATUS_MODEL_OVERLOADED) {
496
+ const errorMessage = error.message;
497
+ const status = (error as any).status ?? '[STATUS?]';
498
+
499
+ // if (error.status && error.status === GEMINI_ERROR_STATUS_MODEL_OVERLOADED) {
500
+ if (errorMessage.includes(`${GEMINI_ERROR_STATUS_MODEL_OVERLOADED}`)) {
443
501
  // model is overloaded, try using the backup
444
502
  console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model. will try using backup model (${GEMINI_BACKUP_MODEL_STR}) for this next call. error (${error.status}): ${extractErrorMsg(error)} (E: a5cd7d174183518058da57cc6d0d8a25)`);
445
503
  modelStr = GEMINI_BACKUP_MODEL_STR;
@@ -452,12 +510,28 @@ export class AgentWitnessGemini_V1
452
510
  if (!result) { throw new Error(`couldn't get result from model (E: ede013a53f875d99a96a2e257c7e7125)`); }
453
511
 
454
512
  // const result = await genModel.generateContent(finalChatPrompt);
455
- const enhancedResult = result.response as EnhancedGenerateContentResponse;
456
- const functionCalls = enhancedResult.functionCalls();
513
+ // const enhancedResult = result.response as EnhancedGenerateContentResponse;
514
+ // const functionCalls = enhancedResult.functionCalls();
515
+
516
+ // The 'result' IS the GenerateContentResponse object directly.
517
+ const response: GenerateContentResponse = result;
518
+
519
+ // Function calls are no longer accessed via a method, but by manually scanning the 'candidates' structure.
520
+
521
+ // We need a way to extract the function calls from the parts array manually.
522
+ const functionCalls: FunctionCall[] = [];
523
+ const parts = response.candidates?.[0]?.content?.parts || [];
524
+
525
+ for (const part of parts) {
526
+ if (part.functionCall) {
527
+ functionCalls.push(part.functionCall);
528
+ }
529
+ }
457
530
 
458
531
  if (!functionCalls || functionCalls.length === 0) {
459
532
  if (logalot) { console.warn(`${lc} no function calls in response, returning text. (W: 3a4b8c940983b9e28e3f04c01a09bb25)`); }
460
- return { text: result.response.text() };
533
+ if (!response.text) { throw new Error(`response generated no function calls and no response.text (E: 6123b8cacfb834105ad3160cfc4ef825)`); }
534
+ return { text: response.text };
461
535
  }
462
536
 
463
537
  if (logalot) {
@@ -511,13 +585,14 @@ export class AgentWitnessGemini_V1
511
585
  // part for the function response entry.
512
586
  const functionInfoIbGibs: FunctionInfoIbGib_V1[] =
513
587
  await this.getFunctionInfoIbGibs({ fcrCommentIbGib: commentIbGib });
588
+ // const functionCallParts: Part[] = [];
514
589
  const functionCallParts: FunctionCallPart[] = [];
515
590
  const functionResponseParts: FunctionResponsePart[] = [];
516
591
  for (let functionInfoIbGib of functionInfoIbGibs) {
517
592
  let { call, response } = getFunctionCallAndResponseParts({ functionInfoIbGib });
518
593
  if (!call) { throw new Error(`(UNEXPECTED) call falsy? (E: 5c8f3bd6de3b300e1c105b9603bb7b25)`); }
519
594
  if (!response) { throw new Error(`(UNEXPECTED) response falsy? (E: d0388c838975c93126c1a6d64f781d25)`); }
520
- if (call.functionCall.name !== response.functionResponse.name) {
595
+ if (call.functionCall!.name !== response.functionResponse.name) {
521
596
  throw new Error(`(UNEXPECTED) functionCall.name !== functionResponse.name? (E: e49f0d60093354db2b6ad17fdf86d425)`);
522
597
  }
523
598
  functionCallParts.push(call);
@@ -557,7 +632,12 @@ export class AgentWitnessGemini_V1
557
632
  // text: commentIbGib.data.text,
558
633
  content: {
559
634
  role: textSourceToGeminiRole(textSrc),
560
- parts: [{ text: commentIbGib.data.text } satisfies TextPart],
635
+ parts: [
636
+ {
637
+ text: commentIbGib.data.text
638
+ } satisfies Part // see genai migration note at top of this file
639
+ // } satisfies TextPart
640
+ ],
561
641
  }
562
642
  }];
563
643
  }
@@ -590,8 +670,7 @@ export class AgentWitnessGemini_V1
590
670
  console.error(`${lc} apiKey falsy. did you set this.fnGetAPIKey (E: genuuid)`);
591
671
  return undefined; /* <<<< returns early */
592
672
  }
593
- this._genAI ??= new GoogleGenerativeAI(apiKey);
594
-
673
+ this._genAI ??= new GoogleGenAI({ apiKey });
595
674
 
596
675
  /**
597
676
  * need to be able to call this function with retries with different
@@ -607,26 +686,31 @@ export class AgentWitnessGemini_V1
607
686
  * @param isRetry if true, this indicates this is aleady a retry and should throw if fails
608
687
  */
609
688
  const fnGoModel = async (modelStr: string) => {
610
- if (!this._genAI) { throw new Error(`(UNEXPECTED) this._genAI falsy? (E: genuuid)`); }
611
- const genModel = this._genAI.getGenerativeModel({
689
+ if (!this._genAI) { throw new Error(`(UNEXPECTED) this._genAI falsy? (E: fbe235713d48f0d8e87cd0b88ec54825)`); }
690
+ const chatConfig: CreateChatParameters = {
612
691
  model: modelStr,
613
- systemInstruction: systemInstructions,
614
- });
615
- /**
616
- * We start a "chat", _BUT ONLY TO USE THE HISTORY MECHANISM_.
617
- * Really we use this as a one-off, but we do not know how to mimic
618
- * the "history" so that the model understands to only respond to
619
- * the most recent prompt.
620
- */
621
- // const chat = genModel.startChat({
622
- // history: chatPromptHistoryParts.map(x => x.content),
623
- // });
624
- const result = await genModel.generateContent(text);
625
- if (result.response) {
626
- return result.response.text();
692
+ config: {
693
+ systemInstruction: systemInstructions,
694
+ }
695
+ };
696
+ const chat = this._genAI.chats.create(chatConfig);
697
+ const response = await chat.sendMessage({ message: text });
698
+ if (response.text) {
699
+ return response.text;
627
700
  } else {
628
- throw new Error(`not implemented (E: bbf05fe00da23d5b16c223bd200eaa25)`);
701
+ throw new Error(`response.text empty/falsy, potentially blocked by safety settings (E: a21a78c9471f27a42c07d1c859187825)`);
702
+
629
703
  }
704
+ // const genModel = this._genAI.getGenerativeModel({
705
+ // model: modelStr,
706
+ // systemInstruction: systemInstructions,
707
+ // });
708
+ // const result = await genModel.generateContent(text);
709
+ // if (result.response) {
710
+ // return result.response.text();
711
+ // } else {
712
+ // throw new Error(`not implemented (E: bbf05fe00da23d5b16c223bd200eaa25)`);
713
+ // }
630
714
  }
631
715
 
632
716
  let result: string | undefined = undefined;
@@ -637,47 +721,60 @@ export class AgentWitnessGemini_V1
637
721
  tryCount++;
638
722
  retryDelayInSeconds++;
639
723
  try {
640
- let x: ErrorDetails
724
+ debugger; // step through the new error mechanism and look for how to determine if the model is overloaded vs quota exceeded
725
+ // let x: ErrorDetails
641
726
  result = await fnGoModel(modelStr);
642
727
  break;
643
728
  } catch (error) {
644
- if (error.status && error.status === GEMINI_ERROR_STATUS_MODEL_OVERLOADED) {
645
- if (modelStr === GEMINI_BACKUP_MODEL_STR) {
646
- // already is the backup model, so we just fail
647
- console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model: GEMINI_ERROR_STATUS_MODEL_OVERLOADED ${GEMINI_ERROR_STATUS_MODEL_OVERLOADED}. we are already using the backup model, so SOL here. will try again... error (${error.status}): ${extractErrorMsg(error)} (E: 9bb63cb520b8bd3bb85d2ca20715c825)`);
648
- } else {
649
- // model is overloaded, try using the backup
650
- console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model: GEMINI_ERROR_STATUS_MODEL_OVERLOADED ${GEMINI_ERROR_STATUS_MODEL_OVERLOADED}. will try using backup model (${GEMINI_BACKUP_MODEL_STR}) for this next call. error (${error.status}): ${extractErrorMsg(error)} (E: b07a041bb97ea95b03cd6f9856f01525)`);
651
- modelStr = GEMINI_BACKUP_MODEL_STR;
652
- }
653
- } else if (error.status && error.status === GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED) {
654
- // quota exceeded, either try backup or wait for retry
655
- if (modelStr === GEMINI_BACKUP_MODEL_STR) {
656
- // nothing else to try, wait retry amount if possible
657
- let errorDetails: ErrorDetails[] = error.errorDetails;
658
- let retryInfo = errorDetails.find(x => x['@type'] === GEMINI_ERROR_DETAILS_TYPE_RETRY_INFO);
659
- retryDelayInSeconds = 30;
660
- if (retryInfo && retryInfo[GEMINI_ERROR_DETAILS_TYPE_RETRY_INFO_RETRY_DELAY_KEY]) {
661
- // get more accurate wait time
662
- let retryStr = retryInfo[GEMINI_ERROR_DETAILS_TYPE_RETRY_INFO_RETRY_DELAY_KEY]! as string;
663
- // retryStr from testing is in seconds, e.g., "41s". IF it's longer than a minute, I don't know/care (too long)
664
- if (retryStr.match(/^\d+s$/)) {
665
- // valid retry str in seconds
666
- retryDelayInSeconds = Number.parseInt(retryStr.substring(0, retryStr.length - 1));
667
- if (Number.isNaN(retryDelayInSeconds)) {
668
- retryDelayInSeconds = 30;
669
- }
670
- } else {
671
- retryDelayInSeconds = 30;
672
- console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model: GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED ${GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED}. Could not find valid retryInfo (errorDetails with retry info with a ${GEMINI_ERROR_DETAILS_TYPE_RETRY_INFO_RETRY_DELAY_KEY} with an "s"). So we'll just try waiting ${retryDelayInSeconds} seconds: ${extractErrorMsg(error)} (E: 986d9883fc72bf156f1691183e27ee25)`);
673
- }
729
+ if (error instanceof Error) {
730
+ const errorMessage = error.message;
731
+ const status = (error as any).status ?? '[STATUS?]';
732
+
733
+ // if (error.status && error.status === GEMINI_ERROR_STATUS_MODEL_OVERLOADED) // see migration notes at top of file
734
+ if (errorMessage.includes(`${GEMINI_ERROR_STATUS_MODEL_OVERLOADED}`)) {
735
+ if (modelStr === GEMINI_BACKUP_MODEL_STR) {
736
+ // already is the backup model, so we just fail
737
+ console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model: GEMINI_ERROR_STATUS_MODEL_OVERLOADED ${GEMINI_ERROR_STATUS_MODEL_OVERLOADED}. we are already using the backup model, so SOL here. will try again... error (${status}): ${extractErrorMsg(error)} (E: 9bb63cb520b8bd3bb85d2ca20715c825)`);
738
+ } else {
739
+ // model is overloaded, try using the backup
740
+ console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model: GEMINI_ERROR_STATUS_MODEL_OVERLOADED ${GEMINI_ERROR_STATUS_MODEL_OVERLOADED}. will try using backup model (${GEMINI_BACKUP_MODEL_STR}) for this next call. error (${status}): ${extractErrorMsg(error)} (E: b07a041bb97ea95b03cd6f9856f01525)`);
741
+ modelStr = GEMINI_BACKUP_MODEL_STR;
674
742
  }
743
+ // else if (error.status && error.status === GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED)
744
+ } else if (errorMessage.includes(`${GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED}`)) {
745
+ // quota exceeded, either try backup or wait for retry
746
+ debugger; // examine the error to see if we can manually parse out any information about retry
747
+ throw new Error('examine the error to see if we can manually parse out any information about retry (E: ea2c2e2ef1deadf968cd0558cdfd5a25)');
748
+
749
+ // if (modelStr === GEMINI_BACKUP_MODEL_STR) {
750
+ // // nothing else to try, wait retry amount if possible
751
+ // let errorDetails: ErrorDetails[] = error.errorDetails;
752
+ // let retryInfo = errorDetails.find(x => x['@type'] === GEMINI_ERROR_DETAILS_TYPE_RETRY_INFO);
753
+ // retryDelayInSeconds = 30;
754
+ // if (retryInfo && retryInfo[GEMINI_ERROR_DETAILS_TYPE_RETRY_INFO_RETRY_DELAY_KEY]) {
755
+ // // get more accurate wait time
756
+ // let retryStr = retryInfo[GEMINI_ERROR_DETAILS_TYPE_RETRY_INFO_RETRY_DELAY_KEY]! as string;
757
+ // // retryStr from testing is in seconds, e.g., "41s". IF it's longer than a minute, I don't know/care (too long)
758
+ // if (retryStr.match(/^\d+s$/)) {
759
+ // // valid retry str in seconds
760
+ // retryDelayInSeconds = Number.parseInt(retryStr.substring(0, retryStr.length - 1));
761
+ // if (Number.isNaN(retryDelayInSeconds)) {
762
+ // retryDelayInSeconds = 30;
763
+ // }
764
+ // } else {
765
+ // retryDelayInSeconds = 30;
766
+ // console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model: GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED ${GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED}. Could not find valid retryInfo (errorDetails with retry info with a ${GEMINI_ERROR_DETAILS_TYPE_RETRY_INFO_RETRY_DELAY_KEY} with an "s"). So we'll just try waiting ${retryDelayInSeconds} seconds: ${extractErrorMsg(error)} (E: 986d9883fc72bf156f1691183e27ee25)`);
767
+ // }
768
+ // }
769
+ // } else {
770
+ // console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model: GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED ${GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED}. will try using backup model (${GEMINI_BACKUP_MODEL_STR}) for this next call. error (${error.status}): ${extractErrorMsg(error)} (E: 637ed809c659f55738becab83fc01825)`);
771
+ // }
772
+ // modelStr = GEMINI_BACKUP_MODEL_STR;
675
773
  } else {
676
- console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model: GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED ${GEMINI_ERROR_STATUS_RATE_QUOTA_EXCEEDED}. will try using backup model (${GEMINI_BACKUP_MODEL_STR}) for this next call. error (${error.status}): ${extractErrorMsg(error)} (E: 637ed809c659f55738becab83fc01825)`);
774
+ console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model. error (${status}): ${extractErrorMsg(error)} (E: a67d595c8ed313d458369d4d0b3e7f25)`);
677
775
  }
678
- modelStr = GEMINI_BACKUP_MODEL_STR;
679
776
  } else {
680
- console.error(`${lc}[fnGoModel][${modelStr}] error trying to get result from model. error (${error.status}): ${extractErrorMsg(error)} (E: a67d595c8ed313d458369d4d0b3e7f25)`);
777
+ console.error(`${lc}[fnGoModel][${modelStr}] (UNEXPECTED) error is not instanceof Error? The expected error from the @google/genai lib is supposed to be an instance of Error according to Gemini migration AI. (E: 15df95701e78b35f783d250801092825)`);
681
778
  }
682
779
  }
683
780
  if (tryCount > 1) {
@@ -4,12 +4,13 @@ import {
4
4
  import { IbGibSpaceAny } from '@ibgib/core-gib/dist/witness/space/space-base-v1.mjs';
5
5
 
6
6
  import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
7
- import { AgentWitnessAny, AgentWitnessData_V1, AgentWitnessIbGib_V1, AgentWitnessRel8ns_V1, DEFAULT_AGENT_DATA_V1, DEFAULT_AGENT_REL8NS_V1, } from '../agent-one-file.mjs';
7
+ import { AgentWitnessData_V1, AgentWitnessIbGib_V1, AgentWitnessRel8ns_V1, DEFAULT_AGENT_DATA_V1, DEFAULT_AGENT_REL8NS_V1, } from '../agent-types.mjs';
8
8
  import { AgentWitnessGemini_V1 } from './agent-witness-gemini-v1.mjs';
9
9
  import { storageGet } from '../../../storage/storage-helpers.web.mjs';
10
10
  import { CreateConcreteAgentWitnessFactory, CreateNewAgentArg } from '../agent-types.mjs';
11
11
  import type { AgentsService_V1 } from '../agents-service-v1.mjs';
12
12
  import { getGlobalDbName, getGlobalIndexedDbKey_APIKey, getGlobalStoreName } from '../../../helpers.web.mjs';
13
+ import { AgentWitnessAny } from '../agent-one-file.mjs';
13
14
 
14
15
  const logalot = GLOBAL_LOG_A_LOT;
15
16
 
@@ -1,5 +1,12 @@
1
- import { Content, FunctionCall, FunctionCallPart, FunctionResponse, FunctionResponsePart, TextPart } from "@google/generative-ai";
2
- import type { GoogleGenerativeAI, ModelParams } from "@google/generative-ai";
1
+ /**
2
+ * @module gemini-helpers.mts
3
+ *
4
+ * ## MIGRATION to @google/genai
5
+ *
6
+ * See migration notes in agent-witness-gemini.mts.
7
+ */
8
+ import { FunctionCallPart, FunctionResponsePart, } from "./gemini-types.mjs";
9
+ import { Content, FunctionCall, FunctionResponse, } from "@google/genai";
3
10
 
4
11
  import { extractErrorMsg, pretty } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
5
12
  import { IbGib_V1 } from "@ibgib/ts-gib/dist/V1/types.mjs";
@@ -8,7 +15,7 @@ import { isComment, } from "@ibgib/core-gib/dist/common/comment/comment-helper.m
8
15
  import { GLOBAL_LOG_A_LOT } from '../../../constants.mjs';
9
16
  import { getAllFunctionInfos } from "../../../api/api-index.mjs";
10
17
  import { APIFunctionInfo } from "../../../api/api-types.mjs";
11
- import { PromptInfo, } from "../agent-one-file.mjs";
18
+ import { PromptInfo, } from "../agent-types.mjs";
12
19
  import { FUNCTION_CALL_REQUEST_COMMENT_TAG, TextSource, } from "../agent-constants.mjs";
13
20
  import { FunctionResponsePart_ResponseWrapper, PromptInfoEntryGemini, PromptInfoGemini } from "./gemini-types.mjs";
14
21
  import { FunctionInfoIbGib_V1 } from "../function-info/function-info-one-file.mjs";
@@ -55,6 +62,7 @@ export function geminiFunctionCallToAPIFunctionInfo({
55
62
  functionCall: FunctionCall
56
63
  }): { info: APIFunctionInfo, args: any } {
57
64
  const lc = `[${geminiFunctionCallToAPIFunctionInfo.name}]`;
65
+ if (!functionCall.name) { throw new Error(`(UNEXPECTED) functionCall.name is falsy? (E: b2c638cf22f88493d823e7e9915fd625)`); }
58
66
  const functionInfo = getAllFunctionInfos().get(functionCall.name);
59
67
  if (!functionInfo) {
60
68
  throw new Error(`${lc} no APIFunctionInfo found matching name: ${functionCall.name} (E: 7c5c7c17988a666a86e72299630c7f25)`);
@@ -68,7 +76,6 @@ export function geminiFunctionCallToAPIFunctionInfo({
68
76
  /**
69
77
  * Takes 0 or more entries and combines them into a single {@link Content}
70
78
  * object that Gemini API expects for `systemInstruction` when using the fn
71
- * {@link GoogleGenerativeAI.getGenerativeModel} (@see {@link ModelParams}).
72
79
  *
73
80
  * @param entries for system instruction, probably from {@link AgentWitnessGemini_V1.systemPromptParts}
74
81
  * @returns undefined if no entries, else single Gemini API Content object with role === "user" and combined parts from {@link systemPromptEntries}
@@ -88,7 +95,10 @@ export function systemPromptEntriesToSystemInstructionContent({
88
95
  }
89
96
  const sysInstructionContent: Content = {
90
97
  role: "user",
91
- parts: systemPromptEntries.flatMap(entry => entry.content.parts),
98
+ parts:
99
+ systemPromptEntries
100
+ .filter(entry => !!entry.content.parts)
101
+ .flatMap(entry => entry.content.parts!),
92
102
  };
93
103
  if (logalot) { console.log(`${lc} sysInstructionContent: ${pretty(sysInstructionContent)} (I: 011e5b865c23eb0b640df3f464ac2525)`); }
94
104
  return sysInstructionContent;
@@ -160,7 +170,7 @@ export function isFunctionCallRequestComment({ ibGib }: { ibGib: IbGib_V1 }): bo
160
170
  *
161
171
  * @param {object} arg - Arguments object.
162
172
  * @param {FunctionInfoIbGib_V1} arg.functionInfoIbGib - The FunctionInfoIbGib_V1 instance containing function call details.
163
- * @returns {{ call: FunctionCallPart; response: FunctionResponsePart }} - An object containing both FunctionCallPart and FunctionResponsePart objects.
173
+ * @returns {{ call: Part; response: Part }} - An object containing both FunctionCallPart and FunctionResponsePart objects.
164
174
  * @throws {Error} If there's an error during the process, such as missing function name or arguments.
165
175
  */
166
176
  export function getFunctionCallAndResponseParts({
@@ -1,8 +1,37 @@
1
- import { Content, } from "@google/generative-ai";
2
- import type { StartChatParams, ChatSession, FunctionCallingMode, } from "@google/generative-ai";
3
- import { PromptInfo, } from "../agent-one-file.mjs";
1
+ import { Content, FunctionCallingConfigMode, GoogleGenAI, } from "@google/genai";
2
+ import { PromptInfo, } from "../agent-types.mjs";
4
3
  import { TextSource } from "../agent-constants.mjs";
5
4
 
5
+ // #region @google/generative-ai to @google/genai shims
6
+ // the changes in @google/genai are a little bassackwards, in that they no
7
+ // longer expose the ability to constrain parts at compile time. these shims
8
+ // enable this.
9
+
10
+ import { type Part } from '@google/genai';
11
+
12
+ /** Utility type to make a specific key required, without using 'never' for others. */
13
+ type AssertRequired<T, K extends keyof T> = T & Required<Pick<T, K>>;
14
+
15
+ // Define your shims:
16
+
17
+ /** Represents a Part where the 'text' property is guaranteed to be a string. */
18
+ export type TextPart = AssertRequired<Part, 'text'>;
19
+
20
+ /** Represents a Part where the 'functionCall' property is guaranteed to be present. */
21
+ export type FunctionCallPart = AssertRequired<Part, 'functionCall'>;
22
+
23
+ /** Represents a Part where the 'functionResponse' property is guaranteed to be present. */
24
+ export type FunctionResponsePart = AssertRequired<Part, 'functionResponse'>;
25
+
26
+ // // If you need the other top-level types:
27
+ // export type GenerateContentResult = Parameters<NonNullable<ConstructorParameters<typeof GoogleGenAI>[0]>['generateContent']>['0'];
28
+
29
+ // The EnhancedGenerateContentResponse maps directly to the main response type now
30
+ import { type GenerateContentResponse } from '@google/genai';
31
+ export type EnhancedGenerateContentResponse = GenerateContentResponse;
32
+
33
+ // #endregion @google/generative-ai to @google/genai shims
34
+
6
35
  export interface PromptInfoEntryGemini {
7
36
  /**
8
37
  * The source of the text, in terms of our code definition.
@@ -36,23 +65,19 @@ export interface PromptInfoGemini extends PromptInfo {
36
65
  * recent.
37
66
  *
38
67
  * NOTE: We will be using this for the gemini api's "chat" function.
39
- *
40
- * @see {@link StartChatParams.history}
41
68
  */
42
69
  chatPromptHistoryParts: PromptInfoEntryGemini[];
43
70
  /**
44
71
  * The most recent chat message
45
- *
46
- * @see {@link ChatSession.sendMessage}
47
72
  */
48
73
  chatPromptCurrent: PromptInfoEntryGemini;
49
74
  /**
50
75
  * if truthy, this will override the default function calling mode when
51
76
  * prompting the LLM.
52
77
  *
53
- * if falsy, will use the default (FunctionCallingMode.ANY)
78
+ * if falsy, will use the default (FunctionCallingConfigMode.ANY)
54
79
  *
55
- * @see {@link FunctionCallingMode}
80
+ * @see {@link FunctionCallingConfigMode}
56
81
  *
57
82
  * ## notes
58
83
  *
@@ -61,7 +86,7 @@ export interface PromptInfoGemini extends PromptInfo {
61
86
  * to just ask the model a "normal" chat llm question (for translating some
62
87
  * text).
63
88
  */
64
- overrideFunctionCallingMode?: FunctionCallingMode;
89
+ overrideFunctionCallingMode?: FunctionCallingConfigMode;
65
90
  }
66
91
 
67
92
  /**
@@ -79,10 +104,11 @@ export type PromptAPIResult_Gemini =
79
104
 
80
105
  /**
81
106
  * This is a "kluge" IMO because it wraps the response part to be able to handle
82
- * all responses of functions. This is a limitation of the Gemini API which requires an
83
- * object as the response part's value. So if a function returns "undefined" or an array,
84
- * it throws an error. So this is a wrapper.
107
+ * all responses of functions. This is a limitation of the Gemini API which
108
+ * requires an object as the response part's value. So if a function returns
109
+ * "undefined" or an array, it throws an error. So this is a wrapper.
85
110
  */
86
111
  export interface FunctionResponsePart_ResponseWrapper {
87
112
  value: any | undefined;
113
+ [key: string]: any; // This satisfies the compiler for the *external* library
88
114
  }