@librechat/agents 3.4.3 → 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.
Files changed (75) hide show
  1. package/dist/cjs/graphs/Graph.cjs +27 -14
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
  4. package/dist/cjs/instrumentation.cjs +3 -3
  5. package/dist/cjs/langfuse.cjs +3 -3
  6. package/dist/cjs/langfuseRuntimeScope.cjs +1 -1
  7. package/dist/cjs/langfuseToolOutputTracing.cjs +2 -2
  8. package/dist/cjs/main.cjs +5 -1
  9. package/dist/cjs/messages/assistantPhase.cjs +59 -0
  10. package/dist/cjs/messages/assistantPhase.cjs.map +1 -0
  11. package/dist/cjs/messages/index.cjs +1 -0
  12. package/dist/cjs/prompts/activityLabel.cjs +76 -0
  13. package/dist/cjs/prompts/activityLabel.cjs.map +1 -1
  14. package/dist/cjs/run.cjs +200 -10
  15. package/dist/cjs/run.cjs.map +1 -1
  16. package/dist/cjs/session/AgentSession.cjs +1 -1
  17. package/dist/cjs/stream.cjs +45 -8
  18. package/dist/cjs/stream.cjs.map +1 -1
  19. package/dist/cjs/tools/ToolNode.cjs +3 -3
  20. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +81 -6
  21. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  22. package/dist/cjs/utils/callbacks.cjs +8 -0
  23. package/dist/cjs/utils/callbacks.cjs.map +1 -1
  24. package/dist/esm/graphs/Graph.mjs +27 -14
  25. package/dist/esm/graphs/Graph.mjs.map +1 -1
  26. package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
  27. package/dist/esm/instrumentation.mjs +3 -3
  28. package/dist/esm/langfuse.mjs +3 -3
  29. package/dist/esm/langfuseRuntimeScope.mjs +1 -1
  30. package/dist/esm/langfuseToolOutputTracing.mjs +2 -2
  31. package/dist/esm/main.mjs +3 -2
  32. package/dist/esm/messages/assistantPhase.mjs +57 -0
  33. package/dist/esm/messages/assistantPhase.mjs.map +1 -0
  34. package/dist/esm/messages/index.mjs +1 -0
  35. package/dist/esm/prompts/activityLabel.mjs +74 -1
  36. package/dist/esm/prompts/activityLabel.mjs.map +1 -1
  37. package/dist/esm/run.mjs +202 -12
  38. package/dist/esm/run.mjs.map +1 -1
  39. package/dist/esm/session/AgentSession.mjs +1 -1
  40. package/dist/esm/stream.mjs +45 -8
  41. package/dist/esm/stream.mjs.map +1 -1
  42. package/dist/esm/tools/ToolNode.mjs +3 -3
  43. package/dist/esm/tools/subagent/SubagentExecutor.mjs +81 -6
  44. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  45. package/dist/esm/utils/callbacks.mjs +8 -1
  46. package/dist/esm/utils/callbacks.mjs.map +1 -1
  47. package/dist/types/messages/assistantPhase.d.ts +22 -0
  48. package/dist/types/messages/index.d.ts +1 -0
  49. package/dist/types/prompts/activityLabel.d.ts +21 -1
  50. package/dist/types/run.d.ts +15 -2
  51. package/dist/types/types/activityLabel.d.ts +63 -0
  52. package/dist/types/types/assistantPhase.d.ts +6 -0
  53. package/dist/types/types/graph.d.ts +8 -1
  54. package/dist/types/types/index.d.ts +1 -0
  55. package/dist/types/types/stream.d.ts +11 -0
  56. package/dist/types/utils/callbacks.d.ts +1 -0
  57. package/package.json +1 -1
  58. package/src/graphs/Graph.ts +33 -9
  59. package/src/graphs/__tests__/Graph.reasoning.test.ts +57 -0
  60. package/src/messages/assistantPhase.test.ts +75 -0
  61. package/src/messages/assistantPhase.ts +91 -0
  62. package/src/messages/index.ts +1 -0
  63. package/src/prompts/activityLabel.ts +177 -1
  64. package/src/run.ts +403 -21
  65. package/src/specs/activity-label-prompt.test.ts +123 -1
  66. package/src/specs/activity-phase-label.test.ts +306 -0
  67. package/src/stream.ts +69 -12
  68. package/src/tools/__tests__/SubagentExecutor.test.ts +436 -0
  69. package/src/tools/subagent/SubagentExecutor.ts +160 -8
  70. package/src/types/activityLabel.ts +65 -0
  71. package/src/types/assistantPhase.ts +6 -0
  72. package/src/types/graph.ts +8 -0
  73. package/src/types/index.ts +1 -0
  74. package/src/types/stream.ts +9 -0
  75. package/src/utils/callbacks.ts +21 -0
package/dist/esm/run.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  import { SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY, SUBAGENT_RESUME_MANIFEST_CONFIG_KEY, requireValidSubagentResumeManifest, stripSubagentResumeManifest } from "./tools/subagent/SubagentReplay.mjs";
2
- import { getTraceIdSeed } from "./langfuseRuntimeContext.mjs";
3
2
  import { hasToolOutputTracingConfig, resolveLangfuseConfig, resolveToolOutputTracingConfig } from "./langfuseConfig.mjs";
4
- import { resolveLangfuseRuntimeScope, withLangfuseRuntimeScope } from "./langfuseRuntimeScope.mjs";
5
- import { createLangfuseHandler, createLangfuseTraceMetadata, disposeLangfuseHandler, getLangfuseTraceName, isLangfuseCallbackHandler, withLangfuseAttributes } from "./langfuse.mjs";
6
3
  import "./common/constants.mjs";
7
4
  import "./common/enum.mjs";
8
5
  import "./common/index.mjs";
9
- import { ACTIVITY_LABEL_PROMPT, buildActivityLabelPrompt } from "./prompts/activityLabel.mjs";
10
- import { appendCallbacks, findCallback } from "./utils/callbacks.mjs";
6
+ import { getTraceIdSeed } from "./langfuseRuntimeContext.mjs";
7
+ import { resolveLangfuseRuntimeScope, withLangfuseRuntimeScope } from "./langfuseRuntimeScope.mjs";
8
+ import { ACTIVITY_LABEL_PROMPT, ACTIVITY_PHASE_LABEL_PROMPT, buildActivityLabelPrompt, buildActivityPhaseLabelPrompt, normalizeActivityPhaseLabel } from "./prompts/activityLabel.mjs";
9
+ import { createLangfuseHandler, createLangfuseTraceMetadata, disposeLangfuseHandler, getLangfuseTraceName, isLangfuseCallbackHandler, withLangfuseAttributes } from "./langfuse.mjs";
10
+ import { appendCallbacks, filterCallbacks, findCallback } from "./utils/callbacks.mjs";
11
11
  import { createCompletionTitleRunnable, createTitleRunnable } from "./utils/title.mjs";
12
12
  import { applyGraphRuntimeConfig } from "./graphs/applyGraphRuntimeConfig.mjs";
13
13
  import { createTokenCounter, encodingForModel } from "./utils/tokens.mjs";
@@ -24,8 +24,8 @@ import { PromptTemplate } from "@langchain/core/prompts";
24
24
  import { RunnableLambda } from "@langchain/core/runnables";
25
25
  import { AzureChatOpenAI, ChatOpenAI } from "@langchain/openai";
26
26
  import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
27
- import { BaseMessage, HumanMessage, SystemMessage } from "@langchain/core/messages";
28
27
  import { Command, INTERRUPT, MemorySaver, isInterrupted } from "@langchain/langgraph";
28
+ import { AIMessage, BaseMessage, HumanMessage, SystemMessage } from "@langchain/core/messages";
29
29
  //#region src/run.ts
30
30
  const defaultOmitOptions = new Set([
31
31
  "stream",
@@ -133,6 +133,10 @@ var Run = class Run {
133
133
  _interrupt;
134
134
  /** Per-run sequence for batch-unique activity-label trace-seed fallbacks. */
135
135
  activityLabelSeq = 0;
136
+ /** Per-run sequence for parent activity-phase trace and invocation ids. */
137
+ activityPhaseLabelSeq = 0;
138
+ /** Latest user turn used to keep detached phase roots conversation-shaped. */
139
+ activityPhaseTraceInput;
136
140
  /** Distinguishes sibling forks started from the same explicit checkpoint. */
137
141
  checkpointForkSeq = 0;
138
142
  _haltedReason;
@@ -519,6 +523,7 @@ var Run = class Run {
519
523
  */
520
524
  const isResume = inputs instanceof Command;
521
525
  const stateInputs = isResume ? void 0 : inputs;
526
+ if (stateInputs != null) this.activityPhaseTraceInput = findActivityPhaseTraceInput(stateInputs.messages);
522
527
  /**
523
528
  * Every honored seal costs one extra superstep, so a preemption-enabled
524
529
  * run reserves headroom for its whole seal budget. Without it, a
@@ -1036,7 +1041,11 @@ var Run = class Run {
1036
1041
  const persistedInterrupt = getFirstPersistedInterrupt(snapshot);
1037
1042
  if (persistedInterrupt == null) return;
1038
1043
  const persistedMessages = getPersistedMessages(snapshot);
1039
- if (persistedMessages != null) this.Graph?.restoreCheckpointMessages(persistedMessages, getResumeUpdateMessages(resumeUpdate));
1044
+ if (persistedMessages != null) {
1045
+ const resumeMessages = getResumeUpdateMessages(resumeUpdate);
1046
+ this.Graph?.restoreCheckpointMessages(persistedMessages, resumeMessages);
1047
+ this.activityPhaseTraceInput = findActivityPhaseTraceInput(resumeMessages == null ? persistedMessages : [...persistedMessages, ...resumeMessages]);
1048
+ }
1040
1049
  const checkpointConfigurable = snapshot.config?.configurable;
1041
1050
  const checkpointId = checkpointConfigurable?.checkpoint_id;
1042
1051
  const checkpointNs = checkpointConfigurable?.checkpoint_ns;
@@ -1169,7 +1178,7 @@ var Run = class Run {
1169
1178
  * comes from `lastAssistantText`, content from reasoning excerpts and
1170
1179
  * tool entries.
1171
1180
  */
1172
- async generateActivityLabel({ provider, clientOptions, entries, thinkingExcerpts, lastAssistantText, previousLabels, prompt, charLimit = 600, chainOptions, traceSeed, agentId }) {
1181
+ async generateActivityLabel({ provider, clientOptions, entries, thinkingExcerpts, lastAssistantText, lastAssistantPhase, previousLabels, prompt, charLimit = 600, chainOptions, traceSeed, agentId }) {
1173
1182
  if (entries.length === 0 && !(thinkingExcerpts && thinkingExcerpts.length > 0)) return {};
1174
1183
  const labelSeq = ++this.activityLabelSeq;
1175
1184
  /** Resolve the LABELED agent's context: its Langfuse overlay carries the
@@ -1266,7 +1275,7 @@ var Run = class Run {
1266
1275
  entries,
1267
1276
  charLimit,
1268
1277
  thinkingExcerpts,
1269
- lastAssistantText,
1278
+ lastAssistantText: lastAssistantPhase === "final_answer" ? void 0 : lastAssistantText,
1270
1279
  previousLabels,
1271
1280
  redaction
1272
1281
  });
@@ -1318,8 +1327,8 @@ var Run = class Run {
1318
1327
  const callbackFailure = /callback|tracer|event.?stream/i.test(String(error?.stack ?? error?.message ?? ""));
1319
1328
  if (aborted || !callbackFailure) throw error;
1320
1329
  const langfuseHandler = findCallback(invokeConfig.callbacks, isLangfuseCallbackHandler);
1321
- const { callbacks: _cb, ...rest } = invokeConfig;
1322
- const safeConfig = Object.assign({}, rest, { callbacks: langfuseHandler ? [langfuseHandler] : [] });
1330
+ const { callbacks, ...rest } = invokeConfig;
1331
+ const safeConfig = Object.assign({}, rest, { callbacks: filterCallbacks(callbacks, (callback) => callback === langfuseHandler) });
1323
1332
  response = await withLangfuseRuntimeScope(labelRuntimeScope, () => invokeLabel(safeConfig));
1324
1333
  }
1325
1334
  const label = extractLabel(response);
@@ -1328,16 +1337,197 @@ var Run = class Run {
1328
1337
  await disposeLangfuseHandler(labelLangfuseHandler);
1329
1338
  }
1330
1339
  }
1340
+ /**
1341
+ * Generates one parent summary for two or more logical activities. The
1342
+ * summary model is traced as a dedicated activity-phase agent root in the
1343
+ * conversation session, with the model callback recorded as its generation
1344
+ * child. No session id means no phase trace, avoiding orphan observations.
1345
+ */
1346
+ async generateActivityPhaseLabel({ provider, clientOptions, activities, totalActivityCount, assistantContext, closingTextPhase, prompt, charLimit = 600, chainOptions, traceSeed, sourceRunId, sourceTraceId, responseId, phaseIndex, status = "completed", agentIds }) {
1347
+ if (activities.length < 2) return {};
1348
+ const phaseSeq = ++this.activityPhaseLabelSeq;
1349
+ const hasUnattributedActivity = activities.some((activity) => activity.agentId == null);
1350
+ const hasOmittedActivitiesWithoutAgentIds = agentIds == null && (totalActivityCount ?? activities.length) > activities.length;
1351
+ const contributingAgentIds = [...new Set([...agentIds ?? [], ...activities.flatMap((activity) => activity.agentId == null ? [] : [activity.agentId])])];
1352
+ const agentContexts = this.Graph?.agentContexts;
1353
+ if (contributingAgentIds.some((agentId) => agentContexts?.get(agentId) == null)) return {};
1354
+ const phaseContext = this.Graph == null ? void 0 : this.Graph.agentContexts.get(this.Graph.defaultAgentId);
1355
+ const phaseLangfuseConfig = resolveLangfuseConfig(this.langfuse, phaseContext?.langfuse);
1356
+ let redaction = hasToolOutputTracingConfig(this.langfuse, phaseContext?.langfuse) ? resolveToolOutputTracingConfig(this.langfuse, phaseContext?.langfuse) : void 0;
1357
+ const redactionContexts = contributingAgentIds.length > 0 && !hasUnattributedActivity && !hasOmittedActivitiesWithoutAgentIds ? contributingAgentIds.flatMap((agentId) => {
1358
+ const context = agentContexts?.get(agentId);
1359
+ return context == null ? [] : [context];
1360
+ }) : Array.from(agentContexts?.values() ?? []);
1361
+ for (const context of redactionContexts) {
1362
+ if (!hasToolOutputTracingConfig(this.langfuse, context.langfuse)) continue;
1363
+ const candidate = resolveToolOutputTracingConfig(this.langfuse, context.langfuse);
1364
+ if (redaction == null) {
1365
+ redaction = candidate;
1366
+ continue;
1367
+ }
1368
+ redaction = {
1369
+ enabled: redaction.enabled === false ? false : candidate.enabled,
1370
+ redactedToolNames: new Set([...redaction.redactedToolNames, ...candidate.redactedToolNames]),
1371
+ redactedToolNameMatchMode: redaction.redactedToolNameMatchMode === "partial" || candidate.redactedToolNameMatchMode === "partial" ? "partial" : "exact",
1372
+ redactionText: redaction.redactionText
1373
+ };
1374
+ }
1375
+ const userPrompt = buildActivityPhaseLabelPrompt({
1376
+ activities,
1377
+ totalActivityCount,
1378
+ charLimit,
1379
+ assistantContext,
1380
+ redaction
1381
+ });
1382
+ if (userPrompt === "") return {};
1383
+ const phaseChainOptions = { ...chainOptions ?? {} };
1384
+ const phaseUserId = typeof phaseChainOptions.configurable?.user_id === "string" ? phaseChainOptions.configurable.user_id : void 0;
1385
+ const phaseSessionId = typeof phaseChainOptions.configurable?.thread_id === "string" ? phaseChainOptions.configurable.thread_id : void 0;
1386
+ const resolvedPhaseIndex = phaseIndex ?? phaseSeq - 1;
1387
+ const phaseMessageId = responseId ?? `activity-phase-${this.id}-${resolvedPhaseIndex}`;
1388
+ const phaseAgentId = this.Graph?.defaultAgentId;
1389
+ const phaseAgentName = phaseContext?.name;
1390
+ const phaseParentMessageId = phaseChainOptions.configurable?.requestBody?.parentMessageId;
1391
+ const phaseMetadata = {
1392
+ sourceRunId: sourceRunId ?? this.id,
1393
+ ...sourceTraceId == null ? {} : { sourceTraceId },
1394
+ responseId: phaseMessageId,
1395
+ phaseIndex: resolvedPhaseIndex,
1396
+ activityCount: Math.max(activities.length, totalActivityCount ?? 0),
1397
+ status,
1398
+ contributingAgentIds,
1399
+ ...typeof phaseParentMessageId === "string" ? { parentMessageId: phaseParentMessageId } : {},
1400
+ ...phaseAgentId == null ? {} : { agentId: phaseAgentId },
1401
+ ...phaseAgentName == null ? {} : { agentName: phaseAgentName },
1402
+ ...closingTextPhase == null ? {} : { closingTextPhase }
1403
+ };
1404
+ const traceMetadata = {
1405
+ ...createLangfuseTraceMetadata({
1406
+ messageId: phaseMessageId,
1407
+ parentMessageId: phaseParentMessageId,
1408
+ agentId: phaseAgentId,
1409
+ agentName: phaseAgentName
1410
+ }),
1411
+ sourceRunId: String(phaseMetadata.sourceRunId),
1412
+ ...sourceTraceId == null ? {} : { sourceTraceId },
1413
+ responseId: phaseMessageId,
1414
+ phaseIndex: String(resolvedPhaseIndex),
1415
+ activityCount: String(phaseMetadata.activityCount),
1416
+ status,
1417
+ ...contributingAgentIds.length === 0 ? {} : { contributingAgentIds: contributingAgentIds.join(",") },
1418
+ ...closingTextPhase == null ? {} : { closingTextPhase }
1419
+ };
1420
+ const phaseRunName = getLangfuseTraceName(traceMetadata, "LibreChat Activity Phase");
1421
+ const phaseTraceName = phaseChainOptions.runName ?? phaseRunName;
1422
+ const phaseTags = [
1423
+ "librechat",
1424
+ "activity-phase",
1425
+ "agent-run-summary",
1426
+ "agent"
1427
+ ];
1428
+ initializeLangfuseTracing(phaseLangfuseConfig);
1429
+ const inheritedTraceSeed = getTraceIdSeed();
1430
+ const phaseTraceSeed = phaseLangfuseConfig?.deterministicTraceId === true || inheritedTraceSeed != null ? traceSeed ?? `activity-phase-${this.id}-${resolvedPhaseIndex}` : void 0;
1431
+ const phaseScopeRunId = `activity-phase:${this.id}:${phaseSeq}:${nanoid()}`;
1432
+ const phaseRuntimeScope = resolveLangfuseRuntimeScope({
1433
+ runLangfuse: this.langfuse,
1434
+ langfuseOverlay: phaseContext?.langfuse,
1435
+ traceIdSeed: phaseTraceSeed,
1436
+ runId: phaseScopeRunId
1437
+ });
1438
+ let phaseLangfuseHandler;
1439
+ const sourceUserText = this.activityPhaseTraceInput ?? findActivityPhaseTraceInput(this.Graph?.getRunMessages() ?? []);
1440
+ if (phaseSessionId != null && sourceUserText != null) phaseLangfuseHandler = createLangfuseHandler({
1441
+ langfuse: phaseLangfuseConfig,
1442
+ userId: phaseUserId,
1443
+ sessionId: phaseSessionId,
1444
+ traceMetadata,
1445
+ tags: phaseTags,
1446
+ traceIdSeed: phaseLangfuseConfig?.deterministicTraceId === true ? phaseTraceSeed : void 0,
1447
+ runId: phaseScopeRunId,
1448
+ toolOutputTracing: phaseRuntimeScope.toolOutputTracing,
1449
+ traceName: phaseTraceName
1450
+ });
1451
+ if (phaseLangfuseHandler != null) phaseChainOptions.callbacks = appendCallbacks(phaseChainOptions.callbacks, [phaseLangfuseHandler]);
1452
+ const model = initializeModel({
1453
+ provider,
1454
+ clientOptions: {
1455
+ ...clientOptions ?? {},
1456
+ streaming: false
1457
+ }
1458
+ });
1459
+ const phaseRunId = `${this.id}-activity-phase-${phaseSeq}`;
1460
+ const invokeConfig = Object.assign({}, phaseChainOptions, {
1461
+ run_id: phaseRunId,
1462
+ runId: phaseRunId,
1463
+ runName: "summarize-activity-phase",
1464
+ tags: [...new Set([...phaseChainOptions.tags ?? [], ...phaseTags])],
1465
+ metadata: {
1466
+ ...phaseChainOptions.metadata ?? {},
1467
+ ...phaseMetadata
1468
+ }
1469
+ });
1470
+ const invokeModel = (runtimeConfig) => model.invoke([new SystemMessage(prompt ?? ACTIVITY_PHASE_LABEL_PROMPT), new HumanMessage(userPrompt)], runtimeConfig);
1471
+ const invokeWithCallbackFallback = async (runtimeConfig) => {
1472
+ try {
1473
+ return await invokeModel(runtimeConfig);
1474
+ } catch (error) {
1475
+ const aborted = runtimeConfig.signal?.aborted === true || error?.name === "AbortError";
1476
+ const callbackFailure = /callback|tracer|event.?stream/i.test(String(error?.stack ?? error?.message ?? ""));
1477
+ if (aborted || !callbackFailure) throw error;
1478
+ const langfuseHandler = findCallback(runtimeConfig.callbacks, isLangfuseCallbackHandler);
1479
+ const { callbacks, ...rest } = runtimeConfig;
1480
+ return invokeModel(Object.assign({}, rest, { callbacks: filterCallbacks(callbacks, (callback) => callback === langfuseHandler) }));
1481
+ }
1482
+ };
1483
+ const extractPhaseLabel = (response) => {
1484
+ const content = response?.content;
1485
+ if (typeof content === "string") return normalizeActivityPhaseLabel(content);
1486
+ if (!Array.isArray(content)) return "";
1487
+ return normalizeActivityPhaseLabel(content.map((block) => typeof block === "string" ? block : block.text ?? "").join(""));
1488
+ };
1489
+ const phaseRunnable = new RunnableLambda({ func: async (_input, runtimeConfig) => {
1490
+ const label = extractPhaseLabel(await invokeWithCallbackFallback(runtimeConfig ?? {}));
1491
+ return label.length > 0 ? {
1492
+ label,
1493
+ messages: [new AIMessage(label)]
1494
+ } : { messages: [] };
1495
+ } }).withConfig({ runName: "summarize-activity-phase" });
1496
+ try {
1497
+ const result = await withLangfuseRuntimeScope(phaseRuntimeScope, () => withLangfuseAttributes({
1498
+ langfuse: phaseLangfuseConfig,
1499
+ userId: phaseUserId,
1500
+ sessionId: phaseSessionId,
1501
+ traceName: phaseTraceName,
1502
+ traceMetadata,
1503
+ tags: phaseTags
1504
+ }, () => phaseRunnable.invoke({ messages: sourceUserText == null ? [] : [new HumanMessage(sourceUserText)] }, invokeConfig)));
1505
+ return result.label == null ? {} : { label: result.label };
1506
+ } finally {
1507
+ await disposeLangfuseHandler(phaseLangfuseHandler);
1508
+ }
1509
+ }
1331
1510
  };
1332
1511
  function findLastMessageOfType(messages, type) {
1333
1512
  for (let i = messages.length - 1; i >= 0; i--) if (messages[i].getType() === type) return messages[i];
1334
1513
  }
1514
+ function findActivityPhaseTraceInput(messages) {
1515
+ for (let i = messages.length - 1; i >= 0; i--) {
1516
+ const message = messages[i];
1517
+ if (message.getType() !== "human" || message.additional_kwargs?.role === "system" || message.additional_kwargs?.isMeta === true) continue;
1518
+ const input = extractPromptText(message).trim();
1519
+ if (input !== "") return input;
1520
+ }
1521
+ }
1335
1522
  function extractPromptText(message) {
1336
1523
  const content = message.content;
1337
1524
  if (typeof content === "string") return content;
1338
1525
  if (!Array.isArray(content)) return String(content);
1339
1526
  const parts = [];
1340
- for (const block of content) if (typeof block === "object" && "type" in block && block.type === "text" && "text" in block && typeof block.text === "string") parts.push(block.text);
1527
+ for (const block of content) {
1528
+ const textBlock = block;
1529
+ if (textBlock != null && (textBlock.type === "text" || textBlock.type === "input_text") && typeof textBlock.text === "string") parts.push(textBlock.text);
1530
+ }
1341
1531
  return parts.join("\n");
1342
1532
  }
1343
1533
  //#endregion