@librechat/agents 3.4.2 → 3.4.4
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/Graph.cjs +27 -14
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
- package/dist/cjs/instrumentation.cjs +3 -3
- package/dist/cjs/langfuse.cjs +3 -3
- package/dist/cjs/langfuseRuntimeScope.cjs +1 -1
- package/dist/cjs/langfuseToolOutputTracing.cjs +2 -2
- package/dist/cjs/main.cjs +5 -1
- package/dist/cjs/messages/assistantPhase.cjs +59 -0
- package/dist/cjs/messages/assistantPhase.cjs.map +1 -0
- package/dist/cjs/messages/index.cjs +1 -0
- package/dist/cjs/prompts/activityLabel.cjs +76 -0
- package/dist/cjs/prompts/activityLabel.cjs.map +1 -1
- package/dist/cjs/run.cjs +200 -10
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/AgentSession.cjs +1 -1
- package/dist/cjs/stream.cjs +45 -8
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +3 -3
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +81 -6
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/utils/callbacks.cjs +8 -0
- package/dist/cjs/utils/callbacks.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +27 -14
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
- package/dist/esm/instrumentation.mjs +3 -3
- package/dist/esm/langfuse.mjs +3 -3
- package/dist/esm/langfuseRuntimeScope.mjs +1 -1
- package/dist/esm/langfuseToolOutputTracing.mjs +2 -2
- package/dist/esm/main.mjs +3 -2
- package/dist/esm/messages/assistantPhase.mjs +57 -0
- package/dist/esm/messages/assistantPhase.mjs.map +1 -0
- package/dist/esm/messages/index.mjs +1 -0
- package/dist/esm/prompts/activityLabel.mjs +74 -1
- package/dist/esm/prompts/activityLabel.mjs.map +1 -1
- package/dist/esm/run.mjs +202 -12
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/AgentSession.mjs +1 -1
- package/dist/esm/stream.mjs +45 -8
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +3 -3
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +81 -6
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/utils/callbacks.mjs +8 -1
- package/dist/esm/utils/callbacks.mjs.map +1 -1
- package/dist/types/messages/assistantPhase.d.ts +22 -0
- package/dist/types/messages/index.d.ts +1 -0
- package/dist/types/prompts/activityLabel.d.ts +21 -1
- package/dist/types/run.d.ts +15 -2
- package/dist/types/types/activityLabel.d.ts +63 -0
- package/dist/types/types/assistantPhase.d.ts +6 -0
- package/dist/types/types/graph.d.ts +8 -1
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/stream.d.ts +11 -0
- package/dist/types/utils/callbacks.d.ts +1 -0
- package/package.json +3 -3
- package/src/graphs/Graph.ts +33 -9
- package/src/graphs/__tests__/Graph.reasoning.test.ts +57 -0
- package/src/messages/assistantPhase.test.ts +75 -0
- package/src/messages/assistantPhase.ts +91 -0
- package/src/messages/index.ts +1 -0
- package/src/prompts/activityLabel.ts +177 -1
- package/src/run.ts +403 -21
- package/src/specs/activity-label-prompt.test.ts +123 -1
- package/src/specs/activity-phase-label.test.ts +306 -0
- package/src/stream.ts +69 -12
- package/src/tools/__tests__/SubagentExecutor.test.ts +436 -0
- package/src/tools/subagent/SubagentExecutor.ts +160 -8
- package/src/types/activityLabel.ts +65 -0
- package/src/types/assistantPhase.ts +6 -0
- package/src/types/graph.ts +8 -0
- package/src/types/index.ts +1 -0
- package/src/types/stream.ts +9 -0
- package/src/utils/callbacks.ts +21 -0
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ActivityLabelToolEntry,
|
|
3
|
+
ActivityPhaseEntry,
|
|
4
|
+
} from '@/types/activityLabel';
|
|
1
5
|
import type { ResolvedLangfuseToolOutputTracingConfig } from '@/langfuseRuntimeContext';
|
|
2
|
-
import type { ActivityLabelToolEntry } from '@/types/activityLabel';
|
|
3
6
|
import { shouldRedactTool } from '@/langfuseToolOutputTracing';
|
|
4
7
|
|
|
5
8
|
/**
|
|
@@ -25,6 +28,29 @@ Examples:
|
|
|
25
28
|
- Read project config and dependency manifests
|
|
26
29
|
- Attempted database migration, hit permission errors`;
|
|
27
30
|
|
|
31
|
+
/** Default system prompt for a run-wide parent activity phase. */
|
|
32
|
+
export const ACTIVITY_PHASE_LABEL_PROMPT = `Summarize what this phase of an agent run accomplished. The result appears as the header of one collapsed parent group containing several activities.
|
|
33
|
+
|
|
34
|
+
Rules:
|
|
35
|
+
- One line, 8 to 18 words, past tense
|
|
36
|
+
- Lead with the concrete outcome and name the most distinctive subject
|
|
37
|
+
- Synthesize the phase; do not enumerate, count, or restate individual activities
|
|
38
|
+
- Describe failures plainly when they are the phase's material outcome
|
|
39
|
+
- Never mention tool names, calls, arguments, reasoning, commentary, or activity counts
|
|
40
|
+
- Output only the summary — no quotes, no trailing punctuation, no preamble
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
43
|
+
- Reconciled authentication behavior and fixed the failing session refresh path
|
|
44
|
+
- Compared deployment options and documented the safest production rollout
|
|
45
|
+
- Investigated database latency but could not confirm the suspected index regression
|
|
46
|
+
|
|
47
|
+
Bad examples:
|
|
48
|
+
- Used three tools to inspect files and run tests
|
|
49
|
+
- Searched code, read configuration, and updated middleware`;
|
|
50
|
+
|
|
51
|
+
/** Hard ceiling across every activity/context section in one phase request. */
|
|
52
|
+
export const ACTIVITY_PHASE_PROMPT_MAX_LENGTH = 12_000;
|
|
53
|
+
|
|
28
54
|
/** Truncates a serialized value for the label prompt. */
|
|
29
55
|
export function truncateForLabel(value: string, maxLength: number): string {
|
|
30
56
|
if (value.length <= maxLength) {
|
|
@@ -105,6 +131,10 @@ const PREVIOUS_LABEL_LIMIT = 200;
|
|
|
105
131
|
* produce one, and the cap keeps a 200-call programmatic batch from
|
|
106
132
|
* building an enormous prompt out of per-field-bounded pieces. */
|
|
107
133
|
const MAX_PROMPT_ENTRIES = 12;
|
|
134
|
+
const MAX_PHASE_ACTIVITIES = 12;
|
|
135
|
+
const MAX_PHASE_CONTEXT = 3;
|
|
136
|
+
const MAX_PHASE_TOOL_ENTRIES = 6;
|
|
137
|
+
export const ACTIVITY_PHASE_LABEL_MAX_LENGTH = 160;
|
|
108
138
|
|
|
109
139
|
export type BuildActivityLabelPromptParams = {
|
|
110
140
|
entries: ActivityLabelToolEntry[];
|
|
@@ -240,3 +270,149 @@ export function buildActivityLabelPrompt({
|
|
|
240
270
|
sections.push('Header:');
|
|
241
271
|
return sections.join('\n\n');
|
|
242
272
|
}
|
|
273
|
+
|
|
274
|
+
export type BuildActivityPhaseLabelPromptParams = {
|
|
275
|
+
activities: ActivityPhaseEntry[];
|
|
276
|
+
totalActivityCount?: number;
|
|
277
|
+
charLimit: number;
|
|
278
|
+
assistantContext?: string[];
|
|
279
|
+
redaction?: ResolvedLangfuseToolOutputTracingConfig;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Builds bounded, redaction-aware evidence for a parent activity phase.
|
|
284
|
+
* Committed child labels are preferred; raw tool/reasoning evidence is only
|
|
285
|
+
* used when no child label exists.
|
|
286
|
+
*/
|
|
287
|
+
export function buildActivityPhaseLabelPrompt({
|
|
288
|
+
activities,
|
|
289
|
+
totalActivityCount,
|
|
290
|
+
charLimit,
|
|
291
|
+
assistantContext,
|
|
292
|
+
redaction,
|
|
293
|
+
}: BuildActivityPhaseLabelPromptParams): string {
|
|
294
|
+
const freeFormSuppressed =
|
|
295
|
+
redaction != null &&
|
|
296
|
+
(redaction.enabled === false || redaction.redactedToolNames.size > 0);
|
|
297
|
+
const sections: string[] = [];
|
|
298
|
+
if (
|
|
299
|
+
!freeFormSuppressed &&
|
|
300
|
+
assistantContext != null &&
|
|
301
|
+
assistantContext.length > 0
|
|
302
|
+
) {
|
|
303
|
+
const context = assistantContext
|
|
304
|
+
.slice(-MAX_PHASE_CONTEXT)
|
|
305
|
+
.map((text) =>
|
|
306
|
+
truncateForLabel(text.replace(/\s+/g, ' ').trim(), charLimit)
|
|
307
|
+
)
|
|
308
|
+
.filter((text) => text.length > 0);
|
|
309
|
+
if (context.length > 0) {
|
|
310
|
+
sections.push(
|
|
311
|
+
'Intermediate assistant context (do not quote or restate):\n' +
|
|
312
|
+
context.map((text) => `- ${text}`).join('\n')
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
let hasDescribableEvidence = false;
|
|
318
|
+
const activityLines = activities
|
|
319
|
+
.slice(0, MAX_PHASE_ACTIVITIES)
|
|
320
|
+
.map((activity, index) => {
|
|
321
|
+
let status = 'completed';
|
|
322
|
+
if (activity.status === 'error') {
|
|
323
|
+
status = 'failed';
|
|
324
|
+
} else if (activity.status === 'partial') {
|
|
325
|
+
status = 'partial';
|
|
326
|
+
}
|
|
327
|
+
if (
|
|
328
|
+
!freeFormSuppressed &&
|
|
329
|
+
activity.label != null &&
|
|
330
|
+
activity.label.trim() !== ''
|
|
331
|
+
) {
|
|
332
|
+
hasDescribableEvidence = true;
|
|
333
|
+
return `${index + 1}. ${status}: ${truncateForLabel(activity.label.replace(/\s+/g, ' ').trim(), charLimit)}`;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const evidence: string[] = [];
|
|
337
|
+
if (
|
|
338
|
+
!freeFormSuppressed &&
|
|
339
|
+
activity.thinkingExcerpts != null &&
|
|
340
|
+
activity.thinkingExcerpts.length > 0
|
|
341
|
+
) {
|
|
342
|
+
evidence.push(
|
|
343
|
+
...activity.thinkingExcerpts
|
|
344
|
+
.slice(0, MAX_THINKING_EXCERPTS)
|
|
345
|
+
.map((excerpt) =>
|
|
346
|
+
truncateForLabel(excerpt.replace(/\s+/g, ' ').trim(), charLimit)
|
|
347
|
+
)
|
|
348
|
+
.filter((excerpt) => excerpt.length > 0)
|
|
349
|
+
.map((excerpt) => `context=${excerpt}`)
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
if (activity.entries != null && activity.entries.length > 0) {
|
|
353
|
+
evidence.push(
|
|
354
|
+
...activity.entries.slice(0, MAX_PHASE_TOOL_ENTRIES).map((entry) => {
|
|
355
|
+
const entryRedacted =
|
|
356
|
+
redaction != null && shouldRedactTool(entry.toolName, redaction);
|
|
357
|
+
const input = truncateForLabel(
|
|
358
|
+
serializeForLabel(entry.toolInput, charLimit),
|
|
359
|
+
charLimit
|
|
360
|
+
);
|
|
361
|
+
let outcome: string;
|
|
362
|
+
if (entryRedacted) {
|
|
363
|
+
outcome = redaction.redactionText;
|
|
364
|
+
} else if (entry.status === 'error') {
|
|
365
|
+
outcome = `ERROR: ${truncateForLabel(
|
|
366
|
+
entry.error ?? 'unknown error',
|
|
367
|
+
charLimit
|
|
368
|
+
)}`;
|
|
369
|
+
} else {
|
|
370
|
+
outcome = truncateForLabel(
|
|
371
|
+
serializeForLabel(entry.toolOutput, charLimit),
|
|
372
|
+
charLimit
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
return `${entry.toolName}(${input}) → ${outcome}`;
|
|
376
|
+
})
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
if (evidence.length > 0) {
|
|
380
|
+
hasDescribableEvidence = true;
|
|
381
|
+
}
|
|
382
|
+
return `${index + 1}. ${status}${evidence.length > 0 ? `: ${evidence.join('; ')}` : ''}`;
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
if (!hasDescribableEvidence) {
|
|
386
|
+
return '';
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const activityCount = Math.max(activities.length, totalActivityCount ?? 0);
|
|
390
|
+
if (activityCount > MAX_PHASE_ACTIVITIES) {
|
|
391
|
+
activityLines.push(
|
|
392
|
+
`${MAX_PHASE_ACTIVITIES + 1}. …and ${activityCount - MAX_PHASE_ACTIVITIES} more activities`
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
sections.push(
|
|
396
|
+
'Activities in this phase (synthesize; do not restate):\n' +
|
|
397
|
+
activityLines.join('\n')
|
|
398
|
+
);
|
|
399
|
+
const terminalCue = '\n\nPhase summary:';
|
|
400
|
+
const evidence = sections.join('\n\n');
|
|
401
|
+
const prompt = evidence + terminalCue;
|
|
402
|
+
if (prompt.length <= ACTIVITY_PHASE_PROMPT_MAX_LENGTH) {
|
|
403
|
+
return prompt;
|
|
404
|
+
}
|
|
405
|
+
const evidenceLimit =
|
|
406
|
+
ACTIVITY_PHASE_PROMPT_MAX_LENGTH - terminalCue.length - 1;
|
|
407
|
+
return `${evidence.slice(0, evidenceLimit).trimEnd()}…${terminalCue}`;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/** Normalizes a model result for safe single-row persistence and display. */
|
|
411
|
+
export function normalizeActivityPhaseLabel(label: string): string {
|
|
412
|
+
const normalized = label
|
|
413
|
+
.replace(/\s+/g, ' ')
|
|
414
|
+
.trim()
|
|
415
|
+
.replace(/^["']|["']$/g, '')
|
|
416
|
+
.replace(/[.!?]+$/g, '');
|
|
417
|
+
return truncateForLabel(normalized, ACTIVITY_PHASE_LABEL_MAX_LENGTH);
|
|
418
|
+
}
|