@librechat/agents 3.1.67 → 3.1.68
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/cjs/graphs/MultiAgentGraph.cjs +36 -0
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/main.cjs +1 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/summarization/index.cjs +41 -0
- package/dist/cjs/summarization/index.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +121 -19
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +36 -0
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -1
- package/dist/esm/summarization/index.mjs +41 -1
- package/dist/esm/summarization/index.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +121 -19
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/types/graphs/MultiAgentGraph.d.ts +12 -0
- package/dist/types/summarization/index.d.ts +2 -0
- package/package.json +1 -1
- package/src/graphs/MultiAgentGraph.ts +39 -0
- package/src/graphs/__tests__/MultiAgentGraph.test.ts +91 -0
- package/src/summarization/__tests__/node.test.ts +42 -0
- package/src/summarization/__tests__/trigger.test.ts +100 -1
- package/src/summarization/index.ts +47 -0
- package/src/summarization/node.ts +149 -24
|
@@ -364,6 +364,122 @@ type LogFn = (
|
|
|
364
364
|
data?: Record<string, unknown>
|
|
365
365
|
) => void;
|
|
366
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Extracts an HTTP status code from a thrown LLM-provider error. Returns
|
|
369
|
+
* `undefined` for non-object values (including `null` or `undefined`, both
|
|
370
|
+
* valid `throw` targets in JS) so callers never dereference a nullish
|
|
371
|
+
* value.
|
|
372
|
+
*/
|
|
373
|
+
function extractHttpStatus(err: unknown): number | undefined {
|
|
374
|
+
if (err == null || typeof err !== 'object') {
|
|
375
|
+
return undefined;
|
|
376
|
+
}
|
|
377
|
+
const errRecord = err as Record<string, unknown>;
|
|
378
|
+
const direct = errRecord.status;
|
|
379
|
+
if (typeof direct === 'number') {
|
|
380
|
+
return direct;
|
|
381
|
+
}
|
|
382
|
+
const statusCode = errRecord.statusCode;
|
|
383
|
+
if (typeof statusCode === 'number') {
|
|
384
|
+
return statusCode;
|
|
385
|
+
}
|
|
386
|
+
const response = errRecord.response;
|
|
387
|
+
if (response != null && typeof response === 'object') {
|
|
388
|
+
const nested = (response as Record<string, unknown>).status;
|
|
389
|
+
if (typeof nested === 'number') {
|
|
390
|
+
return nested;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return undefined;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Formats a provider-level error for logging. Returns both a human-readable
|
|
398
|
+
* suffix (safe to include in the message string so it survives any host-side
|
|
399
|
+
* formatter) and a structured metadata bag for rich log backends.
|
|
400
|
+
*/
|
|
401
|
+
function describeProviderError(
|
|
402
|
+
err: unknown,
|
|
403
|
+
provider: string,
|
|
404
|
+
modelName?: string
|
|
405
|
+
): { suffix: string; data: Record<string, unknown> } {
|
|
406
|
+
const providerLabel = `${provider}/${modelName ?? '(no-model)'}`;
|
|
407
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
408
|
+
|
|
409
|
+
const data: Record<string, unknown> = {
|
|
410
|
+
provider,
|
|
411
|
+
model: modelName,
|
|
412
|
+
};
|
|
413
|
+
if (err instanceof Error) {
|
|
414
|
+
data.errorName = err.name;
|
|
415
|
+
data.errorStack = err.stack;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const status = extractHttpStatus(err);
|
|
419
|
+
const statusSuffix = status != null ? ` (HTTP ${status})` : '';
|
|
420
|
+
if (status != null) {
|
|
421
|
+
data.status = status;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return {
|
|
425
|
+
suffix: `[${providerLabel}]${statusSuffix}: ${errMsg}`,
|
|
426
|
+
data,
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Formats an exhausted-fallback error. `tryFallbackProviders` throws the
|
|
432
|
+
* last fallback provider's error, which may be from any of the configured
|
|
433
|
+
* fallbacks — not the primary — so we label the log with the list of
|
|
434
|
+
* fallback providers attempted rather than mis-attributing to the primary.
|
|
435
|
+
*
|
|
436
|
+
* Entries in `fallbacks` are normally strongly typed, but we defend against
|
|
437
|
+
* malformed runtime config (null/undefined entries, missing `provider`
|
|
438
|
+
* field) so a recoverable summarization failure is never promoted to an
|
|
439
|
+
* uncaught exception from inside the logging path.
|
|
440
|
+
*/
|
|
441
|
+
function describeFallbackError(
|
|
442
|
+
err: unknown,
|
|
443
|
+
fallbacks: unknown
|
|
444
|
+
): { suffix: string; data: Record<string, unknown> } {
|
|
445
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
446
|
+
const list: ReadonlyArray<unknown> = Array.isArray(fallbacks)
|
|
447
|
+
? fallbacks
|
|
448
|
+
: [];
|
|
449
|
+
const providerNames = list
|
|
450
|
+
.map((f) => {
|
|
451
|
+
if (f == null || typeof f !== 'object') {
|
|
452
|
+
return undefined;
|
|
453
|
+
}
|
|
454
|
+
const raw = (f as { provider?: unknown }).provider;
|
|
455
|
+
return raw != null ? String(raw) : undefined;
|
|
456
|
+
})
|
|
457
|
+
.filter((p): p is string => typeof p === 'string');
|
|
458
|
+
const label =
|
|
459
|
+
providerNames.length > 0
|
|
460
|
+
? `fallbacks=[${providerNames.join(',')}]`
|
|
461
|
+
: 'no-fallbacks';
|
|
462
|
+
|
|
463
|
+
const data: Record<string, unknown> = {
|
|
464
|
+
fallbackProviders: providerNames,
|
|
465
|
+
fallbackCount: list.length,
|
|
466
|
+
};
|
|
467
|
+
if (err instanceof Error) {
|
|
468
|
+
data.errorName = err.name;
|
|
469
|
+
data.errorStack = err.stack;
|
|
470
|
+
}
|
|
471
|
+
const status = extractHttpStatus(err);
|
|
472
|
+
const statusSuffix = status != null ? ` (HTTP ${status})` : '';
|
|
473
|
+
if (status != null) {
|
|
474
|
+
data.status = status;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return {
|
|
478
|
+
suffix: `[${label}]${statusSuffix}: ${errMsg}`,
|
|
479
|
+
data,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
|
|
367
483
|
/**
|
|
368
484
|
* Runs the summarization LLM call with primary + fallback providers,
|
|
369
485
|
* falling back to a metadata stub when all calls fail.
|
|
@@ -387,18 +503,23 @@ async function executeSummarizationWithFallback(params: {
|
|
|
387
503
|
log,
|
|
388
504
|
} = params;
|
|
389
505
|
|
|
390
|
-
const summarizationModel = initializeModel({
|
|
391
|
-
provider: clientConfig.provider as Providers,
|
|
392
|
-
clientOptions: clientConfig.clientOptions as t.ClientOptions,
|
|
393
|
-
tools: agentContext.getToolsForBinding(),
|
|
394
|
-
}) as t.ChatModel;
|
|
395
|
-
|
|
396
506
|
const priorSummaryText = agentContext.getSummaryText()?.trim() ?? '';
|
|
397
507
|
|
|
398
508
|
let summaryText = '';
|
|
399
509
|
let summaryUsage: Partial<UsageMetadata> | undefined;
|
|
400
510
|
|
|
401
511
|
try {
|
|
512
|
+
/**
|
|
513
|
+
* Initialize inside the try so that a misconfigured provider
|
|
514
|
+
* (e.g. an unrecognized summarization.provider) surfaces through the
|
|
515
|
+
* `log('error', ...)` path below rather than bubbling up silently.
|
|
516
|
+
*/
|
|
517
|
+
const summarizationModel = initializeModel({
|
|
518
|
+
provider: clientConfig.provider as Providers,
|
|
519
|
+
clientOptions: clientConfig.clientOptions as t.ClientOptions,
|
|
520
|
+
tools: agentContext.getToolsForBinding(),
|
|
521
|
+
}) as t.ChatModel;
|
|
522
|
+
|
|
402
523
|
const result = await summarizeWithCacheHit({
|
|
403
524
|
model: summarizationModel,
|
|
404
525
|
messages,
|
|
@@ -415,19 +536,20 @@ async function executeSummarizationWithFallback(params: {
|
|
|
415
536
|
summaryText = result.text;
|
|
416
537
|
summaryUsage = result.usage;
|
|
417
538
|
} catch (primaryError) {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
539
|
+
const primaryDescribed = describeProviderError(
|
|
540
|
+
primaryError,
|
|
541
|
+
clientConfig.provider,
|
|
542
|
+
clientConfig.modelName
|
|
543
|
+
);
|
|
544
|
+
log('error', `Summarization LLM call failed ${primaryDescribed.suffix}`, {
|
|
545
|
+
...primaryDescribed.data,
|
|
425
546
|
messagesToRefineCount: messages.length,
|
|
426
547
|
});
|
|
427
548
|
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
|
|
549
|
+
const rawFallbacks = (
|
|
550
|
+
clientConfig.clientOptions as unknown as t.LLMConfig | undefined
|
|
551
|
+
)?.fallbacks;
|
|
552
|
+
const fallbacks = Array.isArray(rawFallbacks) ? rawFallbacks : [];
|
|
431
553
|
if (fallbacks.length > 0) {
|
|
432
554
|
try {
|
|
433
555
|
const onChunk = createSummarizationChunkHandler({
|
|
@@ -460,18 +582,21 @@ async function executeSummarizationWithFallback(params: {
|
|
|
460
582
|
);
|
|
461
583
|
}
|
|
462
584
|
} catch (fbErr) {
|
|
463
|
-
|
|
464
|
-
|
|
585
|
+
const fbDescribed = describeFallbackError(fbErr, fallbacks);
|
|
586
|
+
log('warn', `Fallback providers also failed ${fbDescribed.suffix}`, {
|
|
587
|
+
...fbDescribed.data,
|
|
465
588
|
});
|
|
466
589
|
}
|
|
467
590
|
}
|
|
468
591
|
if (!summaryText) {
|
|
469
|
-
log(
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
592
|
+
log(
|
|
593
|
+
'warn',
|
|
594
|
+
`Summarization failed, falling back to metadata stub ${primaryDescribed.suffix}`,
|
|
595
|
+
{
|
|
596
|
+
...primaryDescribed.data,
|
|
597
|
+
messagesToRefineCount: messages.length,
|
|
598
|
+
}
|
|
599
|
+
);
|
|
475
600
|
summaryText = generateMetadataStub(messages);
|
|
476
601
|
}
|
|
477
602
|
}
|