@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.
- package/dist/api/commands/chat/tell-user.d.mts.map +1 -1
- package/dist/api/commands/chat/tell-user.mjs +1 -1
- package/dist/api/commands/chat/tell-user.mjs.map +1 -1
- package/dist/common/settings/settings-constants.d.mts.map +1 -1
- package/dist/common/settings/settings-constants.mjs.map +1 -1
- package/dist/helpers.d.mts +7 -0
- package/dist/helpers.d.mts.map +1 -1
- package/dist/helpers.mjs +25 -0
- package/dist/helpers.mjs.map +1 -1
- package/dist/helpers.web.d.mts +22 -0
- package/dist/helpers.web.d.mts.map +1 -1
- package/dist/helpers.web.mjs +22 -0
- package/dist/helpers.web.mjs.map +1 -1
- package/dist/witness/agent/agent-helpers.d.mts +81 -3
- package/dist/witness/agent/agent-helpers.d.mts.map +1 -1
- package/dist/witness/agent/agent-helpers.mjs +211 -2
- package/dist/witness/agent/agent-helpers.mjs.map +1 -1
- package/dist/witness/agent/agent-one-file.d.mts +1 -264
- package/dist/witness/agent/agent-one-file.d.mts.map +1 -1
- package/dist/witness/agent/agent-one-file.mjs +4 -242
- package/dist/witness/agent/agent-one-file.mjs.map +1 -1
- package/dist/witness/agent/agent-types.d.mts +189 -1
- package/dist/witness/agent/agent-types.d.mts.map +1 -1
- package/dist/witness/agent/agent-types.mjs +30 -1
- package/dist/witness/agent/agent-types.mjs.map +1 -1
- package/dist/witness/agent/agents-service-v1.d.mts +1 -1
- package/dist/witness/agent/agents-service-v1.d.mts.map +1 -1
- package/dist/witness/agent/agents-service-v1.mjs +1 -2
- package/dist/witness/agent/agents-service-v1.mjs.map +1 -1
- package/dist/witness/agent/gemini/agent-witness-gemini-v1.d.mts +4 -3
- package/dist/witness/agent/gemini/agent-witness-gemini-v1.d.mts.map +1 -1
- package/dist/witness/agent/gemini/agent-witness-gemini-v1.mjs +162 -88
- package/dist/witness/agent/gemini/agent-witness-gemini-v1.mjs.map +1 -1
- package/dist/witness/agent/gemini/gemini-agent-factory.d.mts +2 -1
- package/dist/witness/agent/gemini/gemini-agent-factory.d.mts.map +1 -1
- package/dist/witness/agent/gemini/gemini-agent-factory.mjs +1 -1
- package/dist/witness/agent/gemini/gemini-agent-factory.mjs.map +1 -1
- package/dist/witness/agent/gemini/gemini-helpers.d.mts +11 -4
- package/dist/witness/agent/gemini/gemini-helpers.d.mts.map +1 -1
- package/dist/witness/agent/gemini/gemini-helpers.mjs +7 -3
- package/dist/witness/agent/gemini/gemini-helpers.mjs.map +1 -1
- package/dist/witness/agent/gemini/gemini-types.d.mts +21 -13
- package/dist/witness/agent/gemini/gemini-types.d.mts.map +1 -1
- package/dist/witness/agent/gemini/gemini-types.mjs.map +1 -1
- package/package.json +2 -2
- package/src/api/commands/chat/tell-user.mts +1 -3
- package/src/common/settings/settings-constants.mts +4 -1
- package/src/helpers.mts +24 -0
- package/src/helpers.web.mts +22 -0
- package/src/witness/agent/agent-helpers.mts +243 -5
- package/src/witness/agent/agent-one-file.mts +8 -473
- package/src/witness/agent/agent-types.mts +228 -3
- package/src/witness/agent/agents-service-v1.mts +3 -2
- package/src/witness/agent/gemini/agent-witness-gemini-v1.mts +193 -96
- package/src/witness/agent/gemini/gemini-agent-factory.mts +2 -1
- package/src/witness/agent/gemini/gemini-helpers.mts +16 -6
- 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
|
-
|
|
3
|
-
|
|
4
|
-
} from '@google/
|
|
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 {
|
|
15
|
-
import {
|
|
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,
|
|
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-
|
|
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
|
-
|
|
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<
|
|
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
|
|
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
|
|
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:
|
|
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) {
|
|
408
|
-
|
|
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
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
info.overrideFunctionCallingMode ??
|
|
417
|
-
|
|
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
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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: [
|
|
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
|
|
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:
|
|
611
|
-
const
|
|
689
|
+
if (!this._genAI) { throw new Error(`(UNEXPECTED) this._genAI falsy? (E: fbe235713d48f0d8e87cd0b88ec54825)`); }
|
|
690
|
+
const chatConfig: CreateChatParameters = {
|
|
612
691
|
model: modelStr,
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
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(`
|
|
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
|
-
|
|
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
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
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
|
|
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
|
|
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 {
|
|
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
|
-
|
|
2
|
-
|
|
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-
|
|
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:
|
|
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:
|
|
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/
|
|
2
|
-
import
|
|
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 (
|
|
78
|
+
* if falsy, will use the default (FunctionCallingConfigMode.ANY)
|
|
54
79
|
*
|
|
55
|
-
* @see {@link
|
|
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?:
|
|
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
|
|
83
|
-
* object as the response part's value. So if a function returns
|
|
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
|
}
|