@librechat/agents 3.4.4 → 3.4.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 (107) hide show
  1. package/dist/cjs/common/enum.cjs +2 -0
  2. package/dist/cjs/common/enum.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +268 -14
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/hitl/askUserQuestions.cjs +66 -0
  6. package/dist/cjs/hitl/askUserQuestions.cjs.map +1 -0
  7. package/dist/cjs/hitl/askUserQuestionsInterrupt.cjs +46 -0
  8. package/dist/cjs/hitl/askUserQuestionsInterrupt.cjs.map +1 -0
  9. package/dist/cjs/hitl/index.cjs +2 -0
  10. package/dist/cjs/langfuseTraceShaping.cjs +9 -6
  11. package/dist/cjs/langfuseTraceShaping.cjs.map +1 -1
  12. package/dist/cjs/main.cjs +6 -0
  13. package/dist/cjs/run.cjs +147 -14
  14. package/dist/cjs/run.cjs.map +1 -1
  15. package/dist/cjs/session/AgentSession.cjs +93 -31
  16. package/dist/cjs/session/AgentSession.cjs.map +1 -1
  17. package/dist/cjs/session/handlers.cjs +10 -0
  18. package/dist/cjs/session/handlers.cjs.map +1 -1
  19. package/dist/cjs/stream.cjs +17 -3
  20. package/dist/cjs/stream.cjs.map +1 -1
  21. package/dist/cjs/summarization/node.cjs +1 -0
  22. package/dist/cjs/summarization/node.cjs.map +1 -1
  23. package/dist/cjs/tools/ToolNode.cjs +4 -2
  24. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  25. package/dist/cjs/tools/handlers.cjs +1 -0
  26. package/dist/cjs/tools/handlers.cjs.map +1 -1
  27. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +28 -0
  28. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  29. package/dist/cjs/types/hitl.cjs +13 -0
  30. package/dist/cjs/types/hitl.cjs.map +1 -0
  31. package/dist/cjs/utils/handlers.cjs +3 -0
  32. package/dist/cjs/utils/handlers.cjs.map +1 -1
  33. package/dist/esm/common/enum.mjs +2 -0
  34. package/dist/esm/common/enum.mjs.map +1 -1
  35. package/dist/esm/graphs/Graph.mjs +268 -14
  36. package/dist/esm/graphs/Graph.mjs.map +1 -1
  37. package/dist/esm/hitl/askUserQuestions.mjs +66 -0
  38. package/dist/esm/hitl/askUserQuestions.mjs.map +1 -0
  39. package/dist/esm/hitl/askUserQuestionsInterrupt.mjs +43 -0
  40. package/dist/esm/hitl/askUserQuestionsInterrupt.mjs.map +1 -0
  41. package/dist/esm/hitl/index.mjs +2 -0
  42. package/dist/esm/langfuseTraceShaping.mjs +9 -6
  43. package/dist/esm/langfuseTraceShaping.mjs.map +1 -1
  44. package/dist/esm/main.mjs +3 -1
  45. package/dist/esm/run.mjs +147 -14
  46. package/dist/esm/run.mjs.map +1 -1
  47. package/dist/esm/session/AgentSession.mjs +93 -31
  48. package/dist/esm/session/AgentSession.mjs.map +1 -1
  49. package/dist/esm/session/handlers.mjs +10 -0
  50. package/dist/esm/session/handlers.mjs.map +1 -1
  51. package/dist/esm/stream.mjs +17 -3
  52. package/dist/esm/stream.mjs.map +1 -1
  53. package/dist/esm/summarization/node.mjs +1 -0
  54. package/dist/esm/summarization/node.mjs.map +1 -1
  55. package/dist/esm/tools/ToolNode.mjs +4 -2
  56. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  57. package/dist/esm/tools/handlers.mjs +1 -0
  58. package/dist/esm/tools/handlers.mjs.map +1 -1
  59. package/dist/esm/tools/subagent/SubagentExecutor.mjs +28 -0
  60. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  61. package/dist/esm/types/hitl.mjs +13 -0
  62. package/dist/esm/types/hitl.mjs.map +1 -0
  63. package/dist/esm/utils/handlers.mjs +3 -0
  64. package/dist/esm/utils/handlers.mjs.map +1 -1
  65. package/dist/types/common/enum.d.ts +2 -0
  66. package/dist/types/graphs/Graph.d.ts +87 -0
  67. package/dist/types/hitl/askUserQuestions.d.ts +24 -0
  68. package/dist/types/hitl/askUserQuestionsInterrupt.d.ts +11 -0
  69. package/dist/types/hitl/index.d.ts +2 -0
  70. package/dist/types/langfuseTraceShaping.d.ts +4 -3
  71. package/dist/types/run.d.ts +9 -1
  72. package/dist/types/session/types.d.ts +1 -1
  73. package/dist/types/summarization/node.d.ts +6 -0
  74. package/dist/types/types/graph.d.ts +3 -3
  75. package/dist/types/types/hitl.d.ts +31 -2
  76. package/dist/types/types/stream.d.ts +57 -0
  77. package/dist/types/utils/handlers.d.ts +1 -0
  78. package/package.json +2 -1
  79. package/src/aggregator.test.ts +127 -0
  80. package/src/common/enum.ts +2 -0
  81. package/src/graphs/Graph.ts +365 -7
  82. package/src/graphs/__tests__/Graph.closeRunStep.test.ts +385 -0
  83. package/src/hitl/askUserQuestions.ts +126 -0
  84. package/src/hitl/askUserQuestionsInterrupt.ts +115 -0
  85. package/src/hitl/index.ts +6 -0
  86. package/src/langfuseTraceShaping.ts +14 -7
  87. package/src/run.ts +219 -41
  88. package/src/session/AgentSession.ts +105 -13
  89. package/src/session/handlers.ts +14 -2
  90. package/src/session/types.ts +1 -0
  91. package/src/specs/activity-label-observability.live.test.ts +262 -0
  92. package/src/specs/activity-label-observability.test.ts +167 -0
  93. package/src/specs/ask-user-questions.live.test.ts +185 -0
  94. package/src/specs/ask-user-questions.test.ts +293 -0
  95. package/src/specs/langfuse-trace-shaping.test.ts +32 -0
  96. package/src/specs/run-step-timestamps.test.ts +414 -0
  97. package/src/stream.ts +29 -6
  98. package/src/summarization/node.ts +11 -0
  99. package/src/tools/ToolNode.ts +2 -0
  100. package/src/tools/__tests__/SubagentExecutor.test.ts +52 -10
  101. package/src/tools/__tests__/handlers.test.ts +2 -0
  102. package/src/tools/handlers.ts +1 -0
  103. package/src/tools/subagent/SubagentExecutor.ts +46 -4
  104. package/src/types/graph.ts +9 -6
  105. package/src/types/hitl.ts +36 -2
  106. package/src/types/stream.ts +65 -12
  107. package/src/utils/handlers.ts +13 -0
@@ -0,0 +1,66 @@
1
+ import { ASK_USER_QUESTION_ID_PATTERN, isAskUserQuestionRequest } from "./askUserQuestionsInterrupt.mjs";
2
+ import { interrupt } from "@langchain/langgraph";
3
+ //#region src/hitl/askUserQuestions.ts
4
+ function validateQuestions(questions) {
5
+ if (questions.length === 0) throw new RangeError("askUserQuestions requires at least one question.");
6
+ if (questions.length > 4) throw new RangeError(`askUserQuestions accepts at most 4 questions.`);
7
+ const ids = /* @__PURE__ */ new Set();
8
+ for (const question of questions) {
9
+ if (!isAskUserQuestionRequest(question)) throw new TypeError("askUserQuestions requires each question and option to have valid string fields.");
10
+ if (!ASK_USER_QUESTION_ID_PATTERN.test(question.id)) throw new Error("askUserQuestions requires each question id to match [A-Za-z][A-Za-z0-9_-]{0,63}.");
11
+ if (ids.has(question.id)) throw new Error(`askUserQuestions requires unique question ids; received "${question.id}" more than once.`);
12
+ ids.add(question.id);
13
+ }
14
+ return questions[0];
15
+ }
16
+ function validateResolution(value, questions) {
17
+ if (typeof value !== "object" || value === null) throw new TypeError("askUserQuestions requires an answers object.");
18
+ const answers = value.answers;
19
+ if (typeof answers !== "object" || answers === null || Array.isArray(answers)) throw new TypeError("askUserQuestions requires an answers object.");
20
+ const validated = {};
21
+ for (const question of questions) {
22
+ const descriptor = Object.getOwnPropertyDescriptor(answers, question.id);
23
+ const answer = descriptor?.value;
24
+ if (descriptor == null || typeof answer !== "string") throw new TypeError(`askUserQuestions requires a string answer for question id "${question.id}".`);
25
+ validated[question.id] = answer;
26
+ }
27
+ return { answers: validated };
28
+ }
29
+ /**
30
+ * Suspend once to collect answers to several related questions. The first
31
+ * question is also included in the legacy `question` field so existing hosts
32
+ * can render a useful fallback during a staged rollout.
33
+ *
34
+ * Question ids must be non-empty and unique within the batch. The helper
35
+ * accepts at most four questions so hosts can render the interaction as one
36
+ * focused decision surface rather than an unbounded form.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * const { answers } = askUserQuestions({
41
+ * questions: [
42
+ * { id: 'environment', question: 'Which environment?' },
43
+ * { id: 'region', question: 'Which region?' },
44
+ * ],
45
+ * });
46
+ * return `Deploy to ${answers.environment} in ${answers.region}`;
47
+ * ```
48
+ */
49
+ function askUserQuestions(request, options) {
50
+ const first = validateQuestions(request.questions);
51
+ return validateResolution(interrupt({
52
+ type: "ask_user_question",
53
+ question: {
54
+ question: first.question,
55
+ ...first.description != null && { description: first.description },
56
+ ...first.options != null && { options: first.options },
57
+ ...first.multiSelect != null && { multiSelect: first.multiSelect }
58
+ },
59
+ questions: request.questions,
60
+ ...options?.toolCallId != null && options.toolCallId !== "" && { tool_call_id: options.toolCallId }
61
+ }), request.questions);
62
+ }
63
+ //#endregion
64
+ export { askUserQuestions };
65
+
66
+ //# sourceMappingURL=askUserQuestions.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"askUserQuestions.mjs","names":[],"sources":["../../../src/hitl/askUserQuestions.ts"],"sourcesContent":["import { interrupt } from '@langchain/langgraph';\nimport type {\n AskUserQuestionBatchItem,\n AskUserQuestionRequest,\n AskUserQuestionsInterruptPayload,\n AskUserQuestionsRequest,\n AskUserQuestionsResolution,\n} from '@/types/hitl';\nimport {\n ASK_USER_QUESTION_ID_PATTERN,\n isAskUserQuestionRequest,\n MAX_ASK_USER_QUESTIONS,\n} from './askUserQuestionsInterrupt';\n\nfunction validateQuestions(\n questions: readonly AskUserQuestionBatchItem[]\n): AskUserQuestionBatchItem {\n if (questions.length === 0) {\n throw new RangeError('askUserQuestions requires at least one question.');\n }\n if (questions.length > MAX_ASK_USER_QUESTIONS) {\n throw new RangeError(\n `askUserQuestions accepts at most ${MAX_ASK_USER_QUESTIONS} questions.`\n );\n }\n\n const ids = new Set<string>();\n for (const question of questions) {\n if (!isAskUserQuestionRequest(question)) {\n throw new TypeError(\n 'askUserQuestions requires each question and option to have valid string fields.'\n );\n }\n if (!ASK_USER_QUESTION_ID_PATTERN.test(question.id)) {\n throw new Error(\n 'askUserQuestions requires each question id to match [A-Za-z][A-Za-z0-9_-]{0,63}.'\n );\n }\n if (ids.has(question.id)) {\n throw new Error(\n `askUserQuestions requires unique question ids; received \"${question.id}\" more than once.`\n );\n }\n ids.add(question.id);\n }\n return questions[0];\n}\n\ninterface AskUserQuestionsResolutionCandidate {\n answers?: unknown;\n}\n\nfunction validateResolution(\n value: unknown,\n questions: readonly AskUserQuestionBatchItem[]\n): AskUserQuestionsResolution {\n if (typeof value !== 'object' || value === null) {\n throw new TypeError('askUserQuestions requires an answers object.');\n }\n const answers = (value as AskUserQuestionsResolutionCandidate).answers;\n if (\n typeof answers !== 'object' ||\n answers === null ||\n Array.isArray(answers)\n ) {\n throw new TypeError('askUserQuestions requires an answers object.');\n }\n\n const validated: Record<string, string> = {};\n for (const question of questions) {\n const descriptor = Object.getOwnPropertyDescriptor(answers, question.id);\n const answer: unknown = descriptor?.value;\n if (descriptor == null || typeof answer !== 'string') {\n throw new TypeError(\n `askUserQuestions requires a string answer for question id \"${question.id}\".`\n );\n }\n validated[question.id] = answer;\n }\n return { answers: validated };\n}\n\n/**\n * Suspend once to collect answers to several related questions. The first\n * question is also included in the legacy `question` field so existing hosts\n * can render a useful fallback during a staged rollout.\n *\n * Question ids must be non-empty and unique within the batch. The helper\n * accepts at most four questions so hosts can render the interaction as one\n * focused decision surface rather than an unbounded form.\n *\n * @example\n * ```ts\n * const { answers } = askUserQuestions({\n * questions: [\n * { id: 'environment', question: 'Which environment?' },\n * { id: 'region', question: 'Which region?' },\n * ],\n * });\n * return `Deploy to ${answers.environment} in ${answers.region}`;\n * ```\n */\nexport function askUserQuestions(\n request: AskUserQuestionsRequest,\n options?: { toolCallId?: string }\n): AskUserQuestionsResolution {\n const first = validateQuestions(request.questions);\n const fallback: AskUserQuestionRequest = {\n question: first.question,\n ...(first.description != null && { description: first.description }),\n ...(first.options != null && { options: first.options }),\n ...(first.multiSelect != null && { multiSelect: first.multiSelect }),\n };\n const payload: AskUserQuestionsInterruptPayload = {\n type: 'ask_user_question',\n question: fallback,\n questions: request.questions,\n ...(options?.toolCallId != null &&\n options.toolCallId !== '' && { tool_call_id: options.toolCallId }),\n };\n\n const resolution = interrupt<AskUserQuestionsInterruptPayload, unknown>(\n payload\n );\n return validateResolution(resolution, request.questions);\n}\n"],"mappings":";;;AAcA,SAAS,kBACP,WAC0B;CAC1B,IAAI,UAAU,WAAW,GACvB,MAAM,IAAI,WAAW,kDAAkD;CAEzE,IAAI,UAAU,SAAA,GACZ,MAAM,IAAI,WACR,+CACF;CAGF,MAAM,sBAAM,IAAI,IAAY;CAC5B,KAAK,MAAM,YAAY,WAAW;EAChC,IAAI,CAAC,yBAAyB,QAAQ,GACpC,MAAM,IAAI,UACR,iFACF;EAEF,IAAI,CAAC,6BAA6B,KAAK,SAAS,EAAE,GAChD,MAAM,IAAI,MACR,kFACF;EAEF,IAAI,IAAI,IAAI,SAAS,EAAE,GACrB,MAAM,IAAI,MACR,4DAA4D,SAAS,GAAG,kBAC1E;EAEF,IAAI,IAAI,SAAS,EAAE;CACrB;CACA,OAAO,UAAU;AACnB;AAMA,SAAS,mBACP,OACA,WAC4B;CAC5B,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,MAAM,IAAI,UAAU,8CAA8C;CAEpE,MAAM,UAAW,MAA8C;CAC/D,IACE,OAAO,YAAY,YACnB,YAAY,QACZ,MAAM,QAAQ,OAAO,GAErB,MAAM,IAAI,UAAU,8CAA8C;CAGpE,MAAM,YAAoC,CAAC;CAC3C,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,aAAa,OAAO,yBAAyB,SAAS,SAAS,EAAE;EACvE,MAAM,SAAkB,YAAY;EACpC,IAAI,cAAc,QAAQ,OAAO,WAAW,UAC1C,MAAM,IAAI,UACR,8DAA8D,SAAS,GAAG,GAC5E;EAEF,UAAU,SAAS,MAAM;CAC3B;CACA,OAAO,EAAE,SAAS,UAAU;AAC9B;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,iBACd,SACA,SAC4B;CAC5B,MAAM,QAAQ,kBAAkB,QAAQ,SAAS;CAkBjD,OAAO,mBAHY,UACjB;EARA,MAAM;EACN,UAAU;GAPV,UAAU,MAAM;GAChB,GAAI,MAAM,eAAe,QAAQ,EAAE,aAAa,MAAM,YAAY;GAClE,GAAI,MAAM,WAAW,QAAQ,EAAE,SAAS,MAAM,QAAQ;GACtD,GAAI,MAAM,eAAe,QAAQ,EAAE,aAAa,MAAM,YAAY;EAIjD;EACjB,WAAW,QAAQ;EACnB,GAAI,SAAS,cAAc,QACzB,QAAQ,eAAe,MAAM,EAAE,cAAc,QAAQ,WAAW;CAI5D,CAE2B,GAAG,QAAQ,SAAS;AACzD"}
@@ -0,0 +1,43 @@
1
+ import { isAskUserQuestionInterrupt } from "../types/hitl.mjs";
2
+ //#region src/hitl/askUserQuestionsInterrupt.ts
3
+ /** Maximum questions supported by one batched clarification interaction. */
4
+ const MAX_ASK_USER_QUESTIONS = 4;
5
+ /** Safe identifier format for answer-map keys in a batched question. */
6
+ const ASK_USER_QUESTION_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
7
+ function isAskUserQuestionOption(value) {
8
+ if (typeof value !== "object" || value === null) return false;
9
+ const option = value;
10
+ return typeof option.label === "string" && typeof option.value === "string";
11
+ }
12
+ function isAskUserQuestionOptions(value) {
13
+ if (!Array.isArray(value)) return false;
14
+ for (let index = 0; index < value.length; index++) if (!Object.hasOwn(value, index) || !isAskUserQuestionOption(value[index])) return false;
15
+ return true;
16
+ }
17
+ function isAskUserQuestionRequest(value) {
18
+ if (typeof value !== "object" || value === null) return false;
19
+ const question = value;
20
+ return typeof question.question === "string" && (question.description === void 0 || typeof question.description === "string") && (question.options === void 0 || isAskUserQuestionOptions(question.options)) && (question.multiSelect === void 0 || typeof question.multiSelect === "boolean");
21
+ }
22
+ function isAskUserQuestionBatchItem(value) {
23
+ if (!isAskUserQuestionRequest(value)) return false;
24
+ const question = value;
25
+ return typeof question.id === "string" && ASK_USER_QUESTION_ID_PATTERN.test(question.id) && (question.header === void 0 || typeof question.header === "string");
26
+ }
27
+ /**
28
+ * Type guard for the batched form of an `ask_user_question` interrupt. Hosts
29
+ * use this to select the multi-question UI and `AskUserQuestionsResolution`.
30
+ */
31
+ function isAskUserQuestionsInterrupt(payload) {
32
+ if (!isAskUserQuestionInterrupt(payload) || !isAskUserQuestionRequest(payload.question) || payload.tool_call_id !== void 0 && typeof payload.tool_call_id !== "string" || !Array.isArray(payload.questions) || payload.questions.length === 0 || payload.questions.length > 4) return false;
33
+ const ids = /* @__PURE__ */ new Set();
34
+ for (const question of payload.questions) {
35
+ if (!isAskUserQuestionBatchItem(question) || ids.has(question.id)) return false;
36
+ ids.add(question.id);
37
+ }
38
+ return true;
39
+ }
40
+ //#endregion
41
+ export { ASK_USER_QUESTION_ID_PATTERN, MAX_ASK_USER_QUESTIONS, isAskUserQuestionRequest, isAskUserQuestionsInterrupt };
42
+
43
+ //# sourceMappingURL=askUserQuestionsInterrupt.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"askUserQuestionsInterrupt.mjs","names":[],"sources":["../../../src/hitl/askUserQuestionsInterrupt.ts"],"sourcesContent":["import type {\n AskUserQuestionBatchItem,\n AskUserQuestionOption,\n AskUserQuestionRequest,\n AskUserQuestionsInterruptPayload,\n} from '@/types/hitl';\nimport { isAskUserQuestionInterrupt } from '@/types/hitl';\n\n/** Maximum questions supported by one batched clarification interaction. */\nexport const MAX_ASK_USER_QUESTIONS = 4;\n\n/** Safe identifier format for answer-map keys in a batched question. */\nexport const ASK_USER_QUESTION_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;\n\ninterface AskUserQuestionOptionCandidate {\n label?: unknown;\n value?: unknown;\n}\n\ninterface AskUserQuestionCandidate {\n question?: unknown;\n description?: unknown;\n options?: unknown;\n multiSelect?: unknown;\n}\n\ninterface AskUserQuestionBatchItemCandidate extends AskUserQuestionCandidate {\n id?: unknown;\n header?: unknown;\n}\n\nfunction isAskUserQuestionOption(\n value: unknown\n): value is AskUserQuestionOption {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const option = value as AskUserQuestionOptionCandidate;\n return typeof option.label === 'string' && typeof option.value === 'string';\n}\n\nfunction isAskUserQuestionOptions(\n value: unknown\n): value is AskUserQuestionOption[] {\n if (!Array.isArray(value)) {\n return false;\n }\n for (let index = 0; index < value.length; index++) {\n if (!Object.hasOwn(value, index) || !isAskUserQuestionOption(value[index])) {\n return false;\n }\n }\n return true;\n}\n\nexport function isAskUserQuestionRequest(\n value: unknown\n): value is AskUserQuestionRequest {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const question = value as AskUserQuestionCandidate;\n return (\n typeof question.question === 'string' &&\n (question.description === undefined ||\n typeof question.description === 'string') &&\n (question.options === undefined ||\n isAskUserQuestionOptions(question.options)) &&\n (question.multiSelect === undefined ||\n typeof question.multiSelect === 'boolean')\n );\n}\n\nfunction isAskUserQuestionBatchItem(\n value: unknown\n): value is AskUserQuestionBatchItem {\n if (!isAskUserQuestionRequest(value)) {\n return false;\n }\n const question = value as AskUserQuestionBatchItemCandidate;\n return (\n typeof question.id === 'string' &&\n ASK_USER_QUESTION_ID_PATTERN.test(question.id) &&\n (question.header === undefined || typeof question.header === 'string')\n );\n}\n\n/**\n * Type guard for the batched form of an `ask_user_question` interrupt. Hosts\n * use this to select the multi-question UI and `AskUserQuestionsResolution`.\n */\nexport function isAskUserQuestionsInterrupt(\n payload: unknown\n): payload is AskUserQuestionsInterruptPayload {\n if (\n !isAskUserQuestionInterrupt(payload) ||\n !isAskUserQuestionRequest(payload.question) ||\n (payload.tool_call_id !== undefined &&\n typeof payload.tool_call_id !== 'string') ||\n !Array.isArray(payload.questions) ||\n payload.questions.length === 0 ||\n payload.questions.length > MAX_ASK_USER_QUESTIONS\n ) {\n return false;\n }\n\n const ids = new Set<string>();\n for (const question of payload.questions) {\n if (!isAskUserQuestionBatchItem(question) || ids.has(question.id)) {\n return false;\n }\n ids.add(question.id);\n }\n return true;\n}\n"],"mappings":";;;AASA,MAAa,yBAAyB;;AAGtC,MAAa,+BAA+B;AAmB5C,SAAS,wBACP,OACgC;CAChC,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAET,MAAM,SAAS;CACf,OAAO,OAAO,OAAO,UAAU,YAAY,OAAO,OAAO,UAAU;AACrE;AAEA,SAAS,yBACP,OACkC;CAClC,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,OAAO;CAET,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SACxC,IAAI,CAAC,OAAO,OAAO,OAAO,KAAK,KAAK,CAAC,wBAAwB,MAAM,MAAM,GACvE,OAAO;CAGX,OAAO;AACT;AAEA,SAAgB,yBACd,OACiC;CACjC,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAET,MAAM,WAAW;CACjB,OACE,OAAO,SAAS,aAAa,aAC5B,SAAS,gBAAgB,KAAA,KACxB,OAAO,SAAS,gBAAgB,cACjC,SAAS,YAAY,KAAA,KACpB,yBAAyB,SAAS,OAAO,OAC1C,SAAS,gBAAgB,KAAA,KACxB,OAAO,SAAS,gBAAgB;AAEtC;AAEA,SAAS,2BACP,OACmC;CACnC,IAAI,CAAC,yBAAyB,KAAK,GACjC,OAAO;CAET,MAAM,WAAW;CACjB,OACE,OAAO,SAAS,OAAO,YACvB,6BAA6B,KAAK,SAAS,EAAE,MAC5C,SAAS,WAAW,KAAA,KAAa,OAAO,SAAS,WAAW;AAEjE;;;;;AAMA,SAAgB,4BACd,SAC6C;CAC7C,IACE,CAAC,2BAA2B,OAAO,KACnC,CAAC,yBAAyB,QAAQ,QAAQ,KACzC,QAAQ,iBAAiB,KAAA,KACxB,OAAO,QAAQ,iBAAiB,YAClC,CAAC,MAAM,QAAQ,QAAQ,SAAS,KAChC,QAAQ,UAAU,WAAW,KAC7B,QAAQ,UAAU,SAAA,GAElB,OAAO;CAGT,MAAM,sBAAM,IAAI,IAAY;CAC5B,KAAK,MAAM,YAAY,QAAQ,WAAW;EACxC,IAAI,CAAC,2BAA2B,QAAQ,KAAK,IAAI,IAAI,SAAS,EAAE,GAC9D,OAAO;EAET,IAAI,IAAI,SAAS,EAAE;CACrB;CACA,OAAO;AACT"}
@@ -1,2 +1,4 @@
1
1
  import "./askUserQuestion.mjs";
2
+ import "./askUserQuestionsInterrupt.mjs";
3
+ import "./askUserQuestions.mjs";
2
4
  export {};
@@ -14,6 +14,8 @@ const CHAIN_OBSERVATION_TYPE = "chain";
14
14
  const TOOL_OBSERVATION_TYPE = "tool";
15
15
  const AGENT_TRACE_TAG = "agent";
16
16
  const TITLE_TRACE_TAG = "title";
17
+ const ACTIVITY_PHASE_TRACE_TAG = "activity-phase";
18
+ const ACTIVITY_PHASE_ROOT_NAME = "summarize-activity-phase";
17
19
  const EPHEMERAL_AGENT_SENDER_SEPARATOR = "___";
18
20
  const EPHEMERAL_AGENT_INDEX_SEPARATOR = "____";
19
21
  const OBSERVATION_METADATA_LANGGRAPH_NODE = `${LangfuseOtelSpanAttributes.OBSERVATION_METADATA}.langgraph_node`;
@@ -276,11 +278,11 @@ function hasTraceTag(span, expectedTag) {
276
278
  }
277
279
  function shapeRootObservationType(span) {
278
280
  if (isGenerationSpan(span)) return;
279
- if (hasTraceTag(span, AGENT_TRACE_TAG)) {
280
- span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] = ROOT_OBSERVATION_TYPE;
281
+ if (hasTraceTag(span, TITLE_TRACE_TAG) || span.name === ACTIVITY_PHASE_ROOT_NAME && hasTraceTag(span, ACTIVITY_PHASE_TRACE_TAG)) {
282
+ span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] = CHAIN_OBSERVATION_TYPE;
281
283
  return;
282
284
  }
283
- if (hasTraceTag(span, TITLE_TRACE_TAG)) span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] = CHAIN_OBSERVATION_TYPE;
285
+ if (hasTraceTag(span, AGENT_TRACE_TAG)) span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] = ROOT_OBSERVATION_TYPE;
284
286
  }
285
287
  /**
286
288
  * Reshapes spans per Langfuse-team feedback before export:
@@ -295,9 +297,10 @@ function shapeRootObservationType(span) {
295
297
  * - Agent nodes become `agent` observations, while tool-dispatch nodes become
296
298
  * stable `chain` observations whose input is scoped to the pending calls.
297
299
  * Individual child calls remain `tool` observations (items 3 & 4).
298
- * - Agent trace roots become `agent` observations and title trace roots become
299
- * `chain` observations. Root and trace input/output are reduced to the user
300
- * question and assistant response when chat messages are available (item 2).
300
+ * - Agent trace roots become `agent` observations, while title and activity
301
+ * summary roots become `chain` observations. Root and trace input/output are
302
+ * reduced to the user question and assistant response when chat messages are
303
+ * available (item 2).
301
304
  */
302
305
  function shapeLangfuseSpan(span) {
303
306
  const mutable = span;
@@ -1 +1 @@
1
- {"version":3,"file":"langfuseTraceShaping.mjs","names":[],"sources":["../../src/langfuseTraceShaping.ts"],"sourcesContent":["import { LangfuseOtelSpanAttributes } from '@langfuse/tracing';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport { Constants } from '@/common';\n\nconst LANGGRAPH_START_NODE = '__start__';\nconst ANONYMOUS_LAMBDA_NAME = 'RunnableLambda';\nconst LANGGRAPH_AGENT_NODE_PREFIX = 'agent=';\nconst LANGGRAPH_TOOL_NODE_PREFIX = 'tools=';\nconst AGENT_NODE_SPAN_NAME = 'agent';\nconst TOOL_DISPATCH_SPAN_NAME = 'tool-dispatch';\nconst GENERATION_SPAN_NAME = 'llm';\nconst ROOT_OBSERVATION_TYPE = 'agent';\nconst CHAIN_OBSERVATION_TYPE = 'chain';\nconst TOOL_OBSERVATION_TYPE = 'tool';\nconst AGENT_TRACE_TAG = 'agent';\nconst TITLE_TRACE_TAG = 'title';\nconst EPHEMERAL_AGENT_SENDER_SEPARATOR = '___';\nconst EPHEMERAL_AGENT_INDEX_SEPARATOR = '____';\nconst OBSERVATION_METADATA_LANGGRAPH_NODE = `${LangfuseOtelSpanAttributes.OBSERVATION_METADATA}.langgraph_node`;\n\ntype MutableSpan = ReadableSpan & {\n name: string;\n attributes: Record<string, unknown>;\n};\n\ntype SerializedToolCall = {\n name: string;\n args: unknown;\n id?: string;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction parseAttributeValue(value: unknown): unknown {\n if (typeof value !== 'string') {\n return value;\n }\n const trimmed = value.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return value;\n }\n try {\n return JSON.parse(value) as unknown;\n } catch {\n return value;\n }\n}\n\nfunction getMessageArray(\n value: unknown\n): Record<string, unknown>[] | undefined {\n if (Array.isArray(value)) {\n const records = value.filter(isRecord);\n return records.length > 0 ? records : undefined;\n }\n if (!isRecord(value)) {\n return undefined;\n }\n return (\n getMessageArray(value.messages) ??\n getMessageArray(value.input) ??\n getMessageArray(value.output)\n );\n}\n\nfunction getMessageRole(message: Record<string, unknown>): string | undefined {\n const id = message.id;\n if (Array.isArray(id)) {\n const className = id[id.length - 1];\n if (typeof className === 'string') {\n if (className.includes('Human')) {\n return 'user';\n }\n if (className.includes('AI')) {\n return 'assistant';\n }\n if (className.includes('System')) {\n return 'system';\n }\n if (className.includes('Tool')) {\n return 'tool';\n }\n }\n }\n const rawRole =\n message.type ?? message._type ?? message.role ?? message.sender;\n if (typeof rawRole !== 'string') {\n const kwargs = message.kwargs;\n return isRecord(kwargs) ? getMessageRole(kwargs) : undefined;\n }\n const normalized = rawRole.toLowerCase();\n if (normalized === 'human') {\n return 'user';\n }\n if (normalized === 'ai') {\n return 'assistant';\n }\n return normalized;\n}\n\nfunction getMessageText(message: Record<string, unknown>): string | undefined {\n const content =\n message.content ??\n (isRecord(message.kwargs) ? message.kwargs.content : undefined) ??\n (isRecord(message.data) ? message.data.content : undefined);\n if (typeof content === 'string') {\n return content;\n }\n if (!Array.isArray(content)) {\n return undefined;\n }\n const text = content\n .filter(isRecord)\n .map((part) => (typeof part.text === 'string' ? part.text : ''))\n .join('');\n return text === '' ? undefined : text;\n}\n\nfunction findLastMessageText(value: unknown, role: string): string | undefined {\n const messages = getMessageArray(value);\n if (messages == null) {\n return undefined;\n }\n for (let i = messages.length - 1; i >= 0; i--) {\n if (getMessageRole(messages[i]) !== role) {\n continue;\n }\n const text = getMessageText(messages[i]);\n if (text != null && text.trim() !== '') {\n return text;\n }\n }\n return undefined;\n}\n\nfunction normalizeToolCall(value: unknown): SerializedToolCall | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n const fn = value.function;\n if (isRecord(fn) && typeof fn.name === 'string') {\n return {\n name: fn.name,\n args: parseAttributeValue(fn.arguments),\n ...(typeof value.id === 'string' ? { id: value.id } : {}),\n };\n }\n if (typeof value.name !== 'string') {\n return undefined;\n }\n return {\n name: value.name,\n args: value.args ?? {},\n ...(typeof value.id === 'string' ? { id: value.id } : {}),\n };\n}\n\nfunction getMessageToolCalls(\n message: Record<string, unknown>\n): SerializedToolCall[] {\n const rawCalls =\n message.tool_calls ??\n (isRecord(message.kwargs) ? message.kwargs.tool_calls : undefined) ??\n (isRecord(message.additional_kwargs)\n ? message.additional_kwargs.tool_calls\n : undefined) ??\n (isRecord(message.data) ? message.data.tool_calls : undefined);\n if (!Array.isArray(rawCalls)) {\n return [];\n }\n const calls: SerializedToolCall[] = [];\n for (const rawCall of rawCalls) {\n const call = normalizeToolCall(rawCall);\n if (call != null) {\n calls.push(call);\n }\n }\n return calls;\n}\n\n/**\n * Id-bearing `invalid_tool_calls` on the assistant turn. ToolNode pairs these\n * with synthesized error results (and an invalid-only turn is routed on them\n * alone), so the tool-dispatch span must count them as part of the executing\n * batch — otherwise an invalid-only dispatch finds zero calls and the span\n * keeps the full serialized graph state as its input, and a mixed dispatch\n * silently omits the malformed call. `args` stays the raw unparsed string.\n */\n/** Tool-result ids present in the serialized state — ToolNode's\n * `!toolMessageIds.has(id)` execution filter, mirrored for the span. */\nfunction getToolResultIds(\n messages: Record<string, unknown>[]\n): Set<string> {\n const ids = new Set<string>();\n for (const message of messages) {\n if (getMessageRole(message) !== 'tool') {\n continue;\n }\n const rawId =\n message.tool_call_id ??\n (isRecord(message.kwargs) ? message.kwargs.tool_call_id : undefined) ??\n (isRecord(message.data) ? message.data.tool_call_id : undefined);\n if (typeof rawId === 'string' && rawId !== '') {\n ids.add(rawId);\n }\n }\n return ids;\n}\n\nfunction getMessageInvalidToolCalls(\n message: Record<string, unknown>,\n answeredIds: ReadonlySet<string>\n): SerializedToolCall[] {\n const rawCalls =\n message.invalid_tool_calls ??\n (isRecord(message.kwargs) ? message.kwargs.invalid_tool_calls : undefined) ??\n (isRecord(message.data) ? message.data.invalid_tool_calls : undefined);\n if (!Array.isArray(rawCalls)) {\n return [];\n }\n const calls: SerializedToolCall[] = [];\n for (const rawCall of rawCalls) {\n // Same attribution predicate ToolNode executes with (id-bearing,\n // non-server) so the span never claims calls the node deliberately skips.\n if (\n !isRecord(rawCall) ||\n typeof rawCall.id !== 'string' ||\n rawCall.id === '' ||\n answeredIds.has(rawCall.id) ||\n rawCall.id.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX)\n ) {\n continue;\n }\n // Same name fallback ToolNode synthesizes with — a nameless attributable\n // call still gets a result, so it must still count in the span input.\n const call = normalizeToolCall(\n typeof rawCall.name === 'string' && rawCall.name !== ''\n ? rawCall\n : { ...rawCall, name: 'unknown' }\n );\n if (call != null) {\n calls.push(call);\n }\n }\n return calls;\n}\n\n/** The serialized message's own id (uuid), NOT the LC-serialization type id\n * array that `message.id` carries in constructor dumps. */\nfunction getSerializedMessageId(\n message: Record<string, unknown>\n): string | undefined {\n const kwargsId = isRecord(message.kwargs) ? message.kwargs.id : undefined;\n const dataId = isRecord(message.data) ? message.data.id : undefined;\n const rawId = message.id;\n const id = kwargsId ?? dataId ?? rawId;\n return typeof id === 'string' && id !== '' ? id : undefined;\n}\n\n/** Latest assistant turn's tool calls — the calls this tool node is executing. */\nfunction findPendingToolCalls(value: unknown): SerializedToolCall[] {\n const messages = getMessageArray(value);\n if (messages == null) {\n return [];\n }\n /**\n * Invalid calls count only where ToolNode's own gate lets them execute:\n * the messages-state form (a bare-array state means the node returns a\n * plain output list and skips invalid handling) with an id-bearing\n * assistant message (no id, no reducer upsert). Mirrors\n * `canPromoteInvalidCalls` so the span never reports skipped calls.\n */\n const invalidCallsApply = !Array.isArray(value);\n const answeredIds = invalidCallsApply\n ? getToolResultIds(messages)\n : undefined;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (getMessageRole(messages[i]) !== 'assistant') {\n continue;\n }\n const calls = [\n ...getMessageToolCalls(messages[i]),\n ...(invalidCallsApply && getSerializedMessageId(messages[i]) != null\n ? getMessageInvalidToolCalls(messages[i], answeredIds!)\n : []),\n ];\n if (calls.length > 0) {\n return calls;\n }\n }\n return [];\n}\n\nfunction getRootSpanParentId(span: ReadableSpan): string | undefined {\n const legacyParent = (span as { parentSpanId?: string }).parentSpanId;\n if (typeof legacyParent === 'string' && legacyParent !== '') {\n return legacyParent;\n }\n const parentContext = (span as { parentSpanContext?: { spanId?: string } })\n .parentSpanContext;\n const spanId = parentContext?.spanId;\n return typeof spanId === 'string' && spanId !== '' ? spanId : undefined;\n}\n\nfunction isRootSpan(span: ReadableSpan): boolean {\n return getRootSpanParentId(span) == null;\n}\n\n/**\n * LangGraph plumbing observations that add noise without information:\n * the duplicated `__start__` channel-seed nodes and anonymous\n * `RunnableLambda` pass-throughs (Langfuse team feedback items 4 & 5).\n * Internal ToolNode batch spans are disabled at their source so traced child\n * tools retain an exported parent. Explicitly traced ToolNodes are preserved.\n */\nexport function shouldDropLangfuseSpan(spanName: string): boolean {\n return (\n spanName === LANGGRAPH_START_NODE || spanName === ANONYMOUS_LAMBDA_NAME\n );\n}\n\nfunction shapeToolNodeSpan(span: MutableSpan): void {\n const inputKey = LangfuseOtelSpanAttributes.OBSERVATION_INPUT;\n span.name = TOOL_DISPATCH_SPAN_NAME;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n CHAIN_OBSERVATION_TYPE;\n const calls = findPendingToolCalls(\n parseAttributeValue(span.attributes[inputKey])\n );\n if (calls.length === 0) {\n return;\n }\n span.attributes[inputKey] = JSON.stringify(\n calls.map(({ name, args }) => ({ name, args }))\n );\n}\n\nfunction shapeAgentNodeSpan(span: MutableSpan): void {\n span.name = AGENT_NODE_SPAN_NAME;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n}\n\nfunction shapeRootSpan(span: MutableSpan): void {\n const inputKey = LangfuseOtelSpanAttributes.OBSERVATION_INPUT;\n const outputKey = LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT;\n const question = findLastMessageText(\n parseAttributeValue(span.attributes[inputKey]),\n 'user'\n );\n const answer = findLastMessageText(\n parseAttributeValue(span.attributes[outputKey]),\n 'assistant'\n );\n /** A generation that IS the trace root — a bare `model.invoke` with no\n * wrapping chain, i.e. the activity-label path — is also the only\n * observation carrying its own prompt: reducing its observation input\n * would discard the SystemMessage from the one place it is traced.\n * Chain/agent roots keep the full reduction; their child generations\n * still record the complete prompt. Trace-level input/output reduce\n * either way, so the trace list keeps showing question and answer. */\n if (!isGenerationSpan(span)) {\n if (question != null) {\n span.attributes[inputKey] = question;\n }\n if (answer != null) {\n span.attributes[outputKey] = answer;\n }\n }\n const traceInput = question ?? span.attributes[inputKey];\n const traceOutput = answer ?? span.attributes[outputKey];\n if (traceInput != null) {\n span.attributes[LangfuseOtelSpanAttributes.TRACE_INPUT] = traceInput;\n }\n if (traceOutput != null) {\n span.attributes[LangfuseOtelSpanAttributes.TRACE_OUTPUT] = traceOutput;\n }\n}\n\nfunction isGenerationSpan(span: MutableSpan): boolean {\n const type = span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n return typeof type === 'string' && type.toLowerCase() === 'generation';\n}\n\nfunction isToolSpan(span: MutableSpan): boolean {\n const type = span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n return (\n typeof type === 'string' && type.toLowerCase() === TOOL_OBSERVATION_TYPE\n );\n}\n\n/**\n * Whether the span is a LangGraph node execution whose node id is the span\n * name — the shape of the outer workflow-agent node. `@langfuse/tracing`\n * flattens object metadata to per-key attributes with string values stored\n * raw, so LangGraph's `langgraph_node` arrives directly comparable.\n */\nfunction isWorkflowNodeSpan(span: MutableSpan): boolean {\n return span.attributes[OBSERVATION_METADATA_LANGGRAPH_NODE] === span.name;\n}\n\n/**\n * LibreChat ephemeral agents are identified as\n * `endpoint__model___sender[____index]` (`__` encodes `:`; see LibreChat's\n * `encodeEphemeralAgentId`), and the outer workflow node carries that id as\n * its span name — so switching models renames the span (item 1). Returns the\n * stable human `sender` segment only when the name matches that encoding:\n * the `endpoint__model` prefix must contain both segments and — unlike\n * display names such as `LibreChat Agent: Ops___EU` — never contains\n * whitespace, so legitimate names that merely embed `___` are left alone.\n */\nfunction extractEphemeralAgentSender(name: string): string | undefined {\n let workingId = name;\n const indexSeparator = workingId.lastIndexOf(EPHEMERAL_AGENT_INDEX_SEPARATOR);\n if (\n indexSeparator !== -1 &&\n /^\\d+$/.test(\n workingId.slice(indexSeparator + EPHEMERAL_AGENT_INDEX_SEPARATOR.length)\n )\n ) {\n workingId = workingId.slice(0, indexSeparator);\n }\n const senderSeparator = workingId.indexOf(EPHEMERAL_AGENT_SENDER_SEPARATOR);\n if (senderSeparator <= 0) {\n return undefined;\n }\n const encodedPrefix = workingId.slice(0, senderSeparator);\n if (/\\s/.test(encodedPrefix)) {\n return undefined;\n }\n const prefixParts = encodedPrefix.split('__');\n if (prefixParts.length < 2 || prefixParts.some((part) => part === '')) {\n return undefined;\n }\n const sender = workingId\n .slice(senderSeparator + EPHEMERAL_AGENT_SENDER_SEPARATOR.length)\n .replace(/__/g, ':');\n return sender === '' ? undefined : sender;\n}\n\n/** Workflow-agent node spans are always children of the run's root chain and\n * always carry `langgraph_node` metadata equal to their name, so host-named\n * run roots (`LibreChat Agent: <name>`) and ordinary chains that merely look\n * like encoded ids (`pipeline__stage___EU`) are never rename candidates.\n * Successful decodes become `agent` observations, matching the inner\n * `agent=<id>` node shaping. */\nfunction shapeEphemeralAgentNodeSpan(span: MutableSpan): void {\n if (isToolSpan(span) || isRootSpan(span) || !isWorkflowNodeSpan(span)) {\n return;\n }\n const sender = extractEphemeralAgentSender(span.name);\n if (sender == null) {\n return;\n }\n span.name = sender;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n}\n\nfunction hasTraceTag(span: MutableSpan, expectedTag: string): boolean {\n const tags = parseAttributeValue(\n span.attributes[LangfuseOtelSpanAttributes.TRACE_TAGS]\n );\n return (\n Array.isArray(tags) &&\n tags.some((tag) => typeof tag === 'string' && tag === expectedTag)\n );\n}\n\nfunction shapeRootObservationType(span: MutableSpan): void {\n if (isGenerationSpan(span)) {\n return;\n }\n if (hasTraceTag(span, AGENT_TRACE_TAG)) {\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n return;\n }\n if (hasTraceTag(span, TITLE_TRACE_TAG)) {\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n CHAIN_OBSERVATION_TYPE;\n }\n}\n\n/**\n * Reshapes spans per Langfuse-team feedback before export:\n * - `agent=<id>` / `tools=<id>` node names carry the ephemeral agent id\n * (`provider__model`) — strip it so switching models doesn't break\n * name-based logic (item 1). The outer workflow node is named with the\n * bare agent id; ephemeral ids reduce to their stable sender name.\n * - LLM generation spans keep the provider client class name (`ChatOpenAI`,\n * `AzureChatOpenAI`, …); rename them to a provider-agnostic `llm` so the\n * name reflects the operation, not the model (the model stays on the\n * generation's model attribute).\n * - Agent nodes become `agent` observations, while tool-dispatch nodes become\n * stable `chain` observations whose input is scoped to the pending calls.\n * Individual child calls remain `tool` observations (items 3 & 4).\n * - Agent trace roots become `agent` observations and title trace roots become\n * `chain` observations. Root and trace input/output are reduced to the user\n * question and assistant response when chat messages are available (item 2).\n */\nexport function shapeLangfuseSpan(span: ReadableSpan): void {\n const mutable = span as MutableSpan;\n if (mutable.name.startsWith(LANGGRAPH_AGENT_NODE_PREFIX)) {\n shapeAgentNodeSpan(mutable);\n } else if (mutable.name.startsWith(LANGGRAPH_TOOL_NODE_PREFIX)) {\n shapeToolNodeSpan(mutable);\n } else if (isGenerationSpan(mutable)) {\n mutable.name = GENERATION_SPAN_NAME;\n } else {\n shapeEphemeralAgentNodeSpan(mutable);\n }\n if (!isRootSpan(span)) {\n return;\n }\n shapeRootObservationType(mutable);\n shapeRootSpan(mutable);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"langfuseTraceShaping.mjs","names":[],"sources":["../../src/langfuseTraceShaping.ts"],"sourcesContent":["import { LangfuseOtelSpanAttributes } from '@langfuse/tracing';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport { Constants } from '@/common';\n\nconst LANGGRAPH_START_NODE = '__start__';\nconst ANONYMOUS_LAMBDA_NAME = 'RunnableLambda';\nconst LANGGRAPH_AGENT_NODE_PREFIX = 'agent=';\nconst LANGGRAPH_TOOL_NODE_PREFIX = 'tools=';\nconst AGENT_NODE_SPAN_NAME = 'agent';\nconst TOOL_DISPATCH_SPAN_NAME = 'tool-dispatch';\nconst GENERATION_SPAN_NAME = 'llm';\nconst ROOT_OBSERVATION_TYPE = 'agent';\nconst CHAIN_OBSERVATION_TYPE = 'chain';\nconst TOOL_OBSERVATION_TYPE = 'tool';\nconst AGENT_TRACE_TAG = 'agent';\nconst TITLE_TRACE_TAG = 'title';\nconst ACTIVITY_PHASE_TRACE_TAG = 'activity-phase';\nconst ACTIVITY_PHASE_ROOT_NAME = 'summarize-activity-phase';\nconst EPHEMERAL_AGENT_SENDER_SEPARATOR = '___';\nconst EPHEMERAL_AGENT_INDEX_SEPARATOR = '____';\nconst OBSERVATION_METADATA_LANGGRAPH_NODE = `${LangfuseOtelSpanAttributes.OBSERVATION_METADATA}.langgraph_node`;\n\ntype MutableSpan = ReadableSpan & {\n name: string;\n attributes: Record<string, unknown>;\n};\n\ntype SerializedToolCall = {\n name: string;\n args: unknown;\n id?: string;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction parseAttributeValue(value: unknown): unknown {\n if (typeof value !== 'string') {\n return value;\n }\n const trimmed = value.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return value;\n }\n try {\n return JSON.parse(value) as unknown;\n } catch {\n return value;\n }\n}\n\nfunction getMessageArray(\n value: unknown\n): Record<string, unknown>[] | undefined {\n if (Array.isArray(value)) {\n const records = value.filter(isRecord);\n return records.length > 0 ? records : undefined;\n }\n if (!isRecord(value)) {\n return undefined;\n }\n return (\n getMessageArray(value.messages) ??\n getMessageArray(value.input) ??\n getMessageArray(value.output)\n );\n}\n\nfunction getMessageRole(message: Record<string, unknown>): string | undefined {\n const id = message.id;\n if (Array.isArray(id)) {\n const className = id[id.length - 1];\n if (typeof className === 'string') {\n if (className.includes('Human')) {\n return 'user';\n }\n if (className.includes('AI')) {\n return 'assistant';\n }\n if (className.includes('System')) {\n return 'system';\n }\n if (className.includes('Tool')) {\n return 'tool';\n }\n }\n }\n const rawRole =\n message.type ?? message._type ?? message.role ?? message.sender;\n if (typeof rawRole !== 'string') {\n const kwargs = message.kwargs;\n return isRecord(kwargs) ? getMessageRole(kwargs) : undefined;\n }\n const normalized = rawRole.toLowerCase();\n if (normalized === 'human') {\n return 'user';\n }\n if (normalized === 'ai') {\n return 'assistant';\n }\n return normalized;\n}\n\nfunction getMessageText(message: Record<string, unknown>): string | undefined {\n const content =\n message.content ??\n (isRecord(message.kwargs) ? message.kwargs.content : undefined) ??\n (isRecord(message.data) ? message.data.content : undefined);\n if (typeof content === 'string') {\n return content;\n }\n if (!Array.isArray(content)) {\n return undefined;\n }\n const text = content\n .filter(isRecord)\n .map((part) => (typeof part.text === 'string' ? part.text : ''))\n .join('');\n return text === '' ? undefined : text;\n}\n\nfunction findLastMessageText(value: unknown, role: string): string | undefined {\n const messages = getMessageArray(value);\n if (messages == null) {\n return undefined;\n }\n for (let i = messages.length - 1; i >= 0; i--) {\n if (getMessageRole(messages[i]) !== role) {\n continue;\n }\n const text = getMessageText(messages[i]);\n if (text != null && text.trim() !== '') {\n return text;\n }\n }\n return undefined;\n}\n\nfunction normalizeToolCall(value: unknown): SerializedToolCall | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n const fn = value.function;\n if (isRecord(fn) && typeof fn.name === 'string') {\n return {\n name: fn.name,\n args: parseAttributeValue(fn.arguments),\n ...(typeof value.id === 'string' ? { id: value.id } : {}),\n };\n }\n if (typeof value.name !== 'string') {\n return undefined;\n }\n return {\n name: value.name,\n args: value.args ?? {},\n ...(typeof value.id === 'string' ? { id: value.id } : {}),\n };\n}\n\nfunction getMessageToolCalls(\n message: Record<string, unknown>\n): SerializedToolCall[] {\n const rawCalls =\n message.tool_calls ??\n (isRecord(message.kwargs) ? message.kwargs.tool_calls : undefined) ??\n (isRecord(message.additional_kwargs)\n ? message.additional_kwargs.tool_calls\n : undefined) ??\n (isRecord(message.data) ? message.data.tool_calls : undefined);\n if (!Array.isArray(rawCalls)) {\n return [];\n }\n const calls: SerializedToolCall[] = [];\n for (const rawCall of rawCalls) {\n const call = normalizeToolCall(rawCall);\n if (call != null) {\n calls.push(call);\n }\n }\n return calls;\n}\n\n/**\n * Id-bearing `invalid_tool_calls` on the assistant turn. ToolNode pairs these\n * with synthesized error results (and an invalid-only turn is routed on them\n * alone), so the tool-dispatch span must count them as part of the executing\n * batch — otherwise an invalid-only dispatch finds zero calls and the span\n * keeps the full serialized graph state as its input, and a mixed dispatch\n * silently omits the malformed call. `args` stays the raw unparsed string.\n */\n/** Tool-result ids present in the serialized state — ToolNode's\n * `!toolMessageIds.has(id)` execution filter, mirrored for the span. */\nfunction getToolResultIds(\n messages: Record<string, unknown>[]\n): Set<string> {\n const ids = new Set<string>();\n for (const message of messages) {\n if (getMessageRole(message) !== 'tool') {\n continue;\n }\n const rawId =\n message.tool_call_id ??\n (isRecord(message.kwargs) ? message.kwargs.tool_call_id : undefined) ??\n (isRecord(message.data) ? message.data.tool_call_id : undefined);\n if (typeof rawId === 'string' && rawId !== '') {\n ids.add(rawId);\n }\n }\n return ids;\n}\n\nfunction getMessageInvalidToolCalls(\n message: Record<string, unknown>,\n answeredIds: ReadonlySet<string>\n): SerializedToolCall[] {\n const rawCalls =\n message.invalid_tool_calls ??\n (isRecord(message.kwargs) ? message.kwargs.invalid_tool_calls : undefined) ??\n (isRecord(message.data) ? message.data.invalid_tool_calls : undefined);\n if (!Array.isArray(rawCalls)) {\n return [];\n }\n const calls: SerializedToolCall[] = [];\n for (const rawCall of rawCalls) {\n // Same attribution predicate ToolNode executes with (id-bearing,\n // non-server) so the span never claims calls the node deliberately skips.\n if (\n !isRecord(rawCall) ||\n typeof rawCall.id !== 'string' ||\n rawCall.id === '' ||\n answeredIds.has(rawCall.id) ||\n rawCall.id.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX)\n ) {\n continue;\n }\n // Same name fallback ToolNode synthesizes with — a nameless attributable\n // call still gets a result, so it must still count in the span input.\n const call = normalizeToolCall(\n typeof rawCall.name === 'string' && rawCall.name !== ''\n ? rawCall\n : { ...rawCall, name: 'unknown' }\n );\n if (call != null) {\n calls.push(call);\n }\n }\n return calls;\n}\n\n/** The serialized message's own id (uuid), NOT the LC-serialization type id\n * array that `message.id` carries in constructor dumps. */\nfunction getSerializedMessageId(\n message: Record<string, unknown>\n): string | undefined {\n const kwargsId = isRecord(message.kwargs) ? message.kwargs.id : undefined;\n const dataId = isRecord(message.data) ? message.data.id : undefined;\n const rawId = message.id;\n const id = kwargsId ?? dataId ?? rawId;\n return typeof id === 'string' && id !== '' ? id : undefined;\n}\n\n/** Latest assistant turn's tool calls — the calls this tool node is executing. */\nfunction findPendingToolCalls(value: unknown): SerializedToolCall[] {\n const messages = getMessageArray(value);\n if (messages == null) {\n return [];\n }\n /**\n * Invalid calls count only where ToolNode's own gate lets them execute:\n * the messages-state form (a bare-array state means the node returns a\n * plain output list and skips invalid handling) with an id-bearing\n * assistant message (no id, no reducer upsert). Mirrors\n * `canPromoteInvalidCalls` so the span never reports skipped calls.\n */\n const invalidCallsApply = !Array.isArray(value);\n const answeredIds = invalidCallsApply\n ? getToolResultIds(messages)\n : undefined;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (getMessageRole(messages[i]) !== 'assistant') {\n continue;\n }\n const calls = [\n ...getMessageToolCalls(messages[i]),\n ...(invalidCallsApply && getSerializedMessageId(messages[i]) != null\n ? getMessageInvalidToolCalls(messages[i], answeredIds!)\n : []),\n ];\n if (calls.length > 0) {\n return calls;\n }\n }\n return [];\n}\n\nfunction getRootSpanParentId(span: ReadableSpan): string | undefined {\n const legacyParent = (span as { parentSpanId?: string }).parentSpanId;\n if (typeof legacyParent === 'string' && legacyParent !== '') {\n return legacyParent;\n }\n const parentContext = (span as { parentSpanContext?: { spanId?: string } })\n .parentSpanContext;\n const spanId = parentContext?.spanId;\n return typeof spanId === 'string' && spanId !== '' ? spanId : undefined;\n}\n\nfunction isRootSpan(span: ReadableSpan): boolean {\n return getRootSpanParentId(span) == null;\n}\n\n/**\n * LangGraph plumbing observations that add noise without information:\n * the duplicated `__start__` channel-seed nodes and anonymous\n * `RunnableLambda` pass-throughs (Langfuse team feedback items 4 & 5).\n * Internal ToolNode batch spans are disabled at their source so traced child\n * tools retain an exported parent. Explicitly traced ToolNodes are preserved.\n */\nexport function shouldDropLangfuseSpan(spanName: string): boolean {\n return (\n spanName === LANGGRAPH_START_NODE || spanName === ANONYMOUS_LAMBDA_NAME\n );\n}\n\nfunction shapeToolNodeSpan(span: MutableSpan): void {\n const inputKey = LangfuseOtelSpanAttributes.OBSERVATION_INPUT;\n span.name = TOOL_DISPATCH_SPAN_NAME;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n CHAIN_OBSERVATION_TYPE;\n const calls = findPendingToolCalls(\n parseAttributeValue(span.attributes[inputKey])\n );\n if (calls.length === 0) {\n return;\n }\n span.attributes[inputKey] = JSON.stringify(\n calls.map(({ name, args }) => ({ name, args }))\n );\n}\n\nfunction shapeAgentNodeSpan(span: MutableSpan): void {\n span.name = AGENT_NODE_SPAN_NAME;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n}\n\nfunction shapeRootSpan(span: MutableSpan): void {\n const inputKey = LangfuseOtelSpanAttributes.OBSERVATION_INPUT;\n const outputKey = LangfuseOtelSpanAttributes.OBSERVATION_OUTPUT;\n const question = findLastMessageText(\n parseAttributeValue(span.attributes[inputKey]),\n 'user'\n );\n const answer = findLastMessageText(\n parseAttributeValue(span.attributes[outputKey]),\n 'assistant'\n );\n /** A generation that IS the trace root — a bare `model.invoke` with no\n * wrapping chain, i.e. the activity-label path — is also the only\n * observation carrying its own prompt: reducing its observation input\n * would discard the SystemMessage from the one place it is traced.\n * Chain/agent roots keep the full reduction; their child generations\n * still record the complete prompt. Trace-level input/output reduce\n * either way, so the trace list keeps showing question and answer. */\n if (!isGenerationSpan(span)) {\n if (question != null) {\n span.attributes[inputKey] = question;\n }\n if (answer != null) {\n span.attributes[outputKey] = answer;\n }\n }\n const traceInput = question ?? span.attributes[inputKey];\n const traceOutput = answer ?? span.attributes[outputKey];\n if (traceInput != null) {\n span.attributes[LangfuseOtelSpanAttributes.TRACE_INPUT] = traceInput;\n }\n if (traceOutput != null) {\n span.attributes[LangfuseOtelSpanAttributes.TRACE_OUTPUT] = traceOutput;\n }\n}\n\nfunction isGenerationSpan(span: MutableSpan): boolean {\n const type = span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n return typeof type === 'string' && type.toLowerCase() === 'generation';\n}\n\nfunction isToolSpan(span: MutableSpan): boolean {\n const type = span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE];\n return (\n typeof type === 'string' && type.toLowerCase() === TOOL_OBSERVATION_TYPE\n );\n}\n\n/**\n * Whether the span is a LangGraph node execution whose node id is the span\n * name — the shape of the outer workflow-agent node. `@langfuse/tracing`\n * flattens object metadata to per-key attributes with string values stored\n * raw, so LangGraph's `langgraph_node` arrives directly comparable.\n */\nfunction isWorkflowNodeSpan(span: MutableSpan): boolean {\n return span.attributes[OBSERVATION_METADATA_LANGGRAPH_NODE] === span.name;\n}\n\n/**\n * LibreChat ephemeral agents are identified as\n * `endpoint__model___sender[____index]` (`__` encodes `:`; see LibreChat's\n * `encodeEphemeralAgentId`), and the outer workflow node carries that id as\n * its span name — so switching models renames the span (item 1). Returns the\n * stable human `sender` segment only when the name matches that encoding:\n * the `endpoint__model` prefix must contain both segments and — unlike\n * display names such as `LibreChat Agent: Ops___EU` — never contains\n * whitespace, so legitimate names that merely embed `___` are left alone.\n */\nfunction extractEphemeralAgentSender(name: string): string | undefined {\n let workingId = name;\n const indexSeparator = workingId.lastIndexOf(EPHEMERAL_AGENT_INDEX_SEPARATOR);\n if (\n indexSeparator !== -1 &&\n /^\\d+$/.test(\n workingId.slice(indexSeparator + EPHEMERAL_AGENT_INDEX_SEPARATOR.length)\n )\n ) {\n workingId = workingId.slice(0, indexSeparator);\n }\n const senderSeparator = workingId.indexOf(EPHEMERAL_AGENT_SENDER_SEPARATOR);\n if (senderSeparator <= 0) {\n return undefined;\n }\n const encodedPrefix = workingId.slice(0, senderSeparator);\n if (/\\s/.test(encodedPrefix)) {\n return undefined;\n }\n const prefixParts = encodedPrefix.split('__');\n if (prefixParts.length < 2 || prefixParts.some((part) => part === '')) {\n return undefined;\n }\n const sender = workingId\n .slice(senderSeparator + EPHEMERAL_AGENT_SENDER_SEPARATOR.length)\n .replace(/__/g, ':');\n return sender === '' ? undefined : sender;\n}\n\n/** Workflow-agent node spans are always children of the run's root chain and\n * always carry `langgraph_node` metadata equal to their name, so host-named\n * run roots (`LibreChat Agent: <name>`) and ordinary chains that merely look\n * like encoded ids (`pipeline__stage___EU`) are never rename candidates.\n * Successful decodes become `agent` observations, matching the inner\n * `agent=<id>` node shaping. */\nfunction shapeEphemeralAgentNodeSpan(span: MutableSpan): void {\n if (isToolSpan(span) || isRootSpan(span) || !isWorkflowNodeSpan(span)) {\n return;\n }\n const sender = extractEphemeralAgentSender(span.name);\n if (sender == null) {\n return;\n }\n span.name = sender;\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n}\n\nfunction hasTraceTag(span: MutableSpan, expectedTag: string): boolean {\n const tags = parseAttributeValue(\n span.attributes[LangfuseOtelSpanAttributes.TRACE_TAGS]\n );\n return (\n Array.isArray(tags) &&\n tags.some((tag) => typeof tag === 'string' && tag === expectedTag)\n );\n}\n\nfunction shapeRootObservationType(span: MutableSpan): void {\n if (isGenerationSpan(span)) {\n return;\n }\n if (\n hasTraceTag(span, TITLE_TRACE_TAG) ||\n (span.name === ACTIVITY_PHASE_ROOT_NAME &&\n hasTraceTag(span, ACTIVITY_PHASE_TRACE_TAG))\n ) {\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n CHAIN_OBSERVATION_TYPE;\n return;\n }\n if (hasTraceTag(span, AGENT_TRACE_TAG)) {\n span.attributes[LangfuseOtelSpanAttributes.OBSERVATION_TYPE] =\n ROOT_OBSERVATION_TYPE;\n }\n}\n\n/**\n * Reshapes spans per Langfuse-team feedback before export:\n * - `agent=<id>` / `tools=<id>` node names carry the ephemeral agent id\n * (`provider__model`) — strip it so switching models doesn't break\n * name-based logic (item 1). The outer workflow node is named with the\n * bare agent id; ephemeral ids reduce to their stable sender name.\n * - LLM generation spans keep the provider client class name (`ChatOpenAI`,\n * `AzureChatOpenAI`, …); rename them to a provider-agnostic `llm` so the\n * name reflects the operation, not the model (the model stays on the\n * generation's model attribute).\n * - Agent nodes become `agent` observations, while tool-dispatch nodes become\n * stable `chain` observations whose input is scoped to the pending calls.\n * Individual child calls remain `tool` observations (items 3 & 4).\n * - Agent trace roots become `agent` observations, while title and activity\n * summary roots become `chain` observations. Root and trace input/output are\n * reduced to the user question and assistant response when chat messages are\n * available (item 2).\n */\nexport function shapeLangfuseSpan(span: ReadableSpan): void {\n const mutable = span as MutableSpan;\n if (mutable.name.startsWith(LANGGRAPH_AGENT_NODE_PREFIX)) {\n shapeAgentNodeSpan(mutable);\n } else if (mutable.name.startsWith(LANGGRAPH_TOOL_NODE_PREFIX)) {\n shapeToolNodeSpan(mutable);\n } else if (isGenerationSpan(mutable)) {\n mutable.name = GENERATION_SPAN_NAME;\n } else {\n shapeEphemeralAgentNodeSpan(mutable);\n }\n if (!isRootSpan(span)) {\n return;\n }\n shapeRootObservationType(mutable);\n shapeRootSpan(mutable);\n}\n"],"mappings":";;;;AAIA,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAC9B,MAAM,8BAA8B;AACpC,MAAM,6BAA6B;AACnC,MAAM,uBAAuB;AAC7B,MAAM,0BAA0B;AAChC,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAC9B,MAAM,yBAAyB;AAC/B,MAAM,wBAAwB;AAC9B,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AACxB,MAAM,2BAA2B;AACjC,MAAM,2BAA2B;AACjC,MAAM,mCAAmC;AACzC,MAAM,kCAAkC;AACxC,MAAM,sCAAsC,GAAG,2BAA2B,qBAAqB;AAa/F,SAAS,SAAS,OAAkD;CAClE,OAAO,SAAS,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC3E;AAEA,SAAS,oBAAoB,OAAyB;CACpD,IAAI,OAAO,UAAU,UACnB,OAAO;CAET,MAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,CAAC,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,WAAW,GAAG,GACrD,OAAO;CAET,IAAI;EACF,OAAO,KAAK,MAAM,KAAK;CACzB,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,gBACP,OACuC;CACvC,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,MAAM,UAAU,MAAM,OAAO,QAAQ;EACrC,OAAO,QAAQ,SAAS,IAAI,UAAU,KAAA;CACxC;CACA,IAAI,CAAC,SAAS,KAAK,GACjB;CAEF,OACE,gBAAgB,MAAM,QAAQ,KAC9B,gBAAgB,MAAM,KAAK,KAC3B,gBAAgB,MAAM,MAAM;AAEhC;AAEA,SAAS,eAAe,SAAsD;CAC5E,MAAM,KAAK,QAAQ;CACnB,IAAI,MAAM,QAAQ,EAAE,GAAG;EACrB,MAAM,YAAY,GAAG,GAAG,SAAS;EACjC,IAAI,OAAO,cAAc,UAAU;GACjC,IAAI,UAAU,SAAS,OAAO,GAC5B,OAAO;GAET,IAAI,UAAU,SAAS,IAAI,GACzB,OAAO;GAET,IAAI,UAAU,SAAS,QAAQ,GAC7B,OAAO;GAET,IAAI,UAAU,SAAS,MAAM,GAC3B,OAAO;EAEX;CACF;CACA,MAAM,UACJ,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,QAAQ,QAAQ;CAC3D,IAAI,OAAO,YAAY,UAAU;EAC/B,MAAM,SAAS,QAAQ;EACvB,OAAO,SAAS,MAAM,IAAI,eAAe,MAAM,IAAI,KAAA;CACrD;CACA,MAAM,aAAa,QAAQ,YAAY;CACvC,IAAI,eAAe,SACjB,OAAO;CAET,IAAI,eAAe,MACjB,OAAO;CAET,OAAO;AACT;AAEA,SAAS,eAAe,SAAsD;CAC5E,MAAM,UACJ,QAAQ,YACP,SAAS,QAAQ,MAAM,IAAI,QAAQ,OAAO,UAAU,KAAA,OACpD,SAAS,QAAQ,IAAI,IAAI,QAAQ,KAAK,UAAU,KAAA;CACnD,IAAI,OAAO,YAAY,UACrB,OAAO;CAET,IAAI,CAAC,MAAM,QAAQ,OAAO,GACxB;CAEF,MAAM,OAAO,QACV,OAAO,QAAQ,CAAC,CAChB,KAAK,SAAU,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,EAAG,CAAC,CAC/D,KAAK,EAAE;CACV,OAAO,SAAS,KAAK,KAAA,IAAY;AACnC;AAEA,SAAS,oBAAoB,OAAgB,MAAkC;CAC7E,MAAM,WAAW,gBAAgB,KAAK;CACtC,IAAI,YAAY,MACd;CAEF,KAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;EAC7C,IAAI,eAAe,SAAS,EAAE,MAAM,MAClC;EAEF,MAAM,OAAO,eAAe,SAAS,EAAE;EACvC,IAAI,QAAQ,QAAQ,KAAK,KAAK,MAAM,IAClC,OAAO;CAEX;AAEF;AAEA,SAAS,kBAAkB,OAAgD;CACzE,IAAI,CAAC,SAAS,KAAK,GACjB;CAEF,MAAM,KAAK,MAAM;CACjB,IAAI,SAAS,EAAE,KAAK,OAAO,GAAG,SAAS,UACrC,OAAO;EACL,MAAM,GAAG;EACT,MAAM,oBAAoB,GAAG,SAAS;EACtC,GAAI,OAAO,MAAM,OAAO,WAAW,EAAE,IAAI,MAAM,GAAG,IAAI,CAAC;CACzD;CAEF,IAAI,OAAO,MAAM,SAAS,UACxB;CAEF,OAAO;EACL,MAAM,MAAM;EACZ,MAAM,MAAM,QAAQ,CAAC;EACrB,GAAI,OAAO,MAAM,OAAO,WAAW,EAAE,IAAI,MAAM,GAAG,IAAI,CAAC;CACzD;AACF;AAEA,SAAS,oBACP,SACsB;CACtB,MAAM,WACJ,QAAQ,eACP,SAAS,QAAQ,MAAM,IAAI,QAAQ,OAAO,aAAa,KAAA,OACvD,SAAS,QAAQ,iBAAiB,IAC/B,QAAQ,kBAAkB,aAC1B,KAAA,OACH,SAAS,QAAQ,IAAI,IAAI,QAAQ,KAAK,aAAa,KAAA;CACtD,IAAI,CAAC,MAAM,QAAQ,QAAQ,GACzB,OAAO,CAAC;CAEV,MAAM,QAA8B,CAAC;CACrC,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,OAAO,kBAAkB,OAAO;EACtC,IAAI,QAAQ,MACV,MAAM,KAAK,IAAI;CAEnB;CACA,OAAO;AACT;;;;;;;;;;;AAYA,SAAS,iBACP,UACa;CACb,MAAM,sBAAM,IAAI,IAAY;CAC5B,KAAK,MAAM,WAAW,UAAU;EAC9B,IAAI,eAAe,OAAO,MAAM,QAC9B;EAEF,MAAM,QACJ,QAAQ,iBACP,SAAS,QAAQ,MAAM,IAAI,QAAQ,OAAO,eAAe,KAAA,OACzD,SAAS,QAAQ,IAAI,IAAI,QAAQ,KAAK,eAAe,KAAA;EACxD,IAAI,OAAO,UAAU,YAAY,UAAU,IACzC,IAAI,IAAI,KAAK;CAEjB;CACA,OAAO;AACT;AAEA,SAAS,2BACP,SACA,aACsB;CACtB,MAAM,WACJ,QAAQ,uBACP,SAAS,QAAQ,MAAM,IAAI,QAAQ,OAAO,qBAAqB,KAAA,OAC/D,SAAS,QAAQ,IAAI,IAAI,QAAQ,KAAK,qBAAqB,KAAA;CAC9D,IAAI,CAAC,MAAM,QAAQ,QAAQ,GACzB,OAAO,CAAC;CAEV,MAAM,QAA8B,CAAC;CACrC,KAAK,MAAM,WAAW,UAAU;EAG9B,IACE,CAAC,SAAS,OAAO,KACjB,OAAO,QAAQ,OAAO,YACtB,QAAQ,OAAO,MACf,YAAY,IAAI,QAAQ,EAAE,KAC1B,QAAQ,GAAG,WAAA,WAAiD,GAE5D;EAIF,MAAM,OAAO,kBACX,OAAO,QAAQ,SAAS,YAAY,QAAQ,SAAS,KACjD,UACA;GAAE,GAAG;GAAS,MAAM;EAAU,CACpC;EACA,IAAI,QAAQ,MACV,MAAM,KAAK,IAAI;CAEnB;CACA,OAAO;AACT;;;AAIA,SAAS,uBACP,SACoB;CACpB,MAAM,WAAW,SAAS,QAAQ,MAAM,IAAI,QAAQ,OAAO,KAAK,KAAA;CAChE,MAAM,SAAS,SAAS,QAAQ,IAAI,IAAI,QAAQ,KAAK,KAAK,KAAA;CAC1D,MAAM,QAAQ,QAAQ;CACtB,MAAM,KAAK,YAAY,UAAU;CACjC,OAAO,OAAO,OAAO,YAAY,OAAO,KAAK,KAAK,KAAA;AACpD;;AAGA,SAAS,qBAAqB,OAAsC;CAClE,MAAM,WAAW,gBAAgB,KAAK;CACtC,IAAI,YAAY,MACd,OAAO,CAAC;;;;;;;;CASV,MAAM,oBAAoB,CAAC,MAAM,QAAQ,KAAK;CAC9C,MAAM,cAAc,oBAChB,iBAAiB,QAAQ,IACzB,KAAA;CACJ,KAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;EAC7C,IAAI,eAAe,SAAS,EAAE,MAAM,aAClC;EAEF,MAAM,QAAQ,CACZ,GAAG,oBAAoB,SAAS,EAAE,GAClC,GAAI,qBAAqB,uBAAuB,SAAS,EAAE,KAAK,OAC5D,2BAA2B,SAAS,IAAI,WAAY,IACpD,CAAC,CACP;EACA,IAAI,MAAM,SAAS,GACjB,OAAO;CAEX;CACA,OAAO,CAAC;AACV;AAEA,SAAS,oBAAoB,MAAwC;CACnE,MAAM,eAAgB,KAAmC;CACzD,IAAI,OAAO,iBAAiB,YAAY,iBAAiB,IACvD,OAAO;CAIT,MAAM,SAFiB,KACpB,mBAC2B;CAC9B,OAAO,OAAO,WAAW,YAAY,WAAW,KAAK,SAAS,KAAA;AAChE;AAEA,SAAS,WAAW,MAA6B;CAC/C,OAAO,oBAAoB,IAAI,KAAK;AACtC;;;;;;;;AASA,SAAgB,uBAAuB,UAA2B;CAChE,OACE,aAAa,wBAAwB,aAAa;AAEtD;AAEA,SAAS,kBAAkB,MAAyB;CAClD,MAAM,WAAW,2BAA2B;CAC5C,KAAK,OAAO;CACZ,KAAK,WAAW,2BAA2B,oBACzC;CACF,MAAM,QAAQ,qBACZ,oBAAoB,KAAK,WAAW,SAAS,CAC/C;CACA,IAAI,MAAM,WAAW,GACnB;CAEF,KAAK,WAAW,YAAY,KAAK,UAC/B,MAAM,KAAK,EAAE,MAAM,YAAY;EAAE;EAAM;CAAK,EAAE,CAChD;AACF;AAEA,SAAS,mBAAmB,MAAyB;CACnD,KAAK,OAAO;CACZ,KAAK,WAAW,2BAA2B,oBACzC;AACJ;AAEA,SAAS,cAAc,MAAyB;CAC9C,MAAM,WAAW,2BAA2B;CAC5C,MAAM,YAAY,2BAA2B;CAC7C,MAAM,WAAW,oBACf,oBAAoB,KAAK,WAAW,SAAS,GAC7C,MACF;CACA,MAAM,SAAS,oBACb,oBAAoB,KAAK,WAAW,UAAU,GAC9C,WACF;;;;;;;;CAQA,IAAI,CAAC,iBAAiB,IAAI,GAAG;EAC3B,IAAI,YAAY,MACd,KAAK,WAAW,YAAY;EAE9B,IAAI,UAAU,MACZ,KAAK,WAAW,aAAa;CAEjC;CACA,MAAM,aAAa,YAAY,KAAK,WAAW;CAC/C,MAAM,cAAc,UAAU,KAAK,WAAW;CAC9C,IAAI,cAAc,MAChB,KAAK,WAAW,2BAA2B,eAAe;CAE5D,IAAI,eAAe,MACjB,KAAK,WAAW,2BAA2B,gBAAgB;AAE/D;AAEA,SAAS,iBAAiB,MAA4B;CACpD,MAAM,OAAO,KAAK,WAAW,2BAA2B;CACxD,OAAO,OAAO,SAAS,YAAY,KAAK,YAAY,MAAM;AAC5D;AAEA,SAAS,WAAW,MAA4B;CAC9C,MAAM,OAAO,KAAK,WAAW,2BAA2B;CACxD,OACE,OAAO,SAAS,YAAY,KAAK,YAAY,MAAM;AAEvD;;;;;;;AAQA,SAAS,mBAAmB,MAA4B;CACtD,OAAO,KAAK,WAAW,yCAAyC,KAAK;AACvE;;;;;;;;;;;AAYA,SAAS,4BAA4B,MAAkC;CACrE,IAAI,YAAY;CAChB,MAAM,iBAAiB,UAAU,YAAY,+BAA+B;CAC5E,IACE,mBAAmB,MACnB,QAAQ,KACN,UAAU,MAAM,iBAAiB,CAAsC,CACzE,GAEA,YAAY,UAAU,MAAM,GAAG,cAAc;CAE/C,MAAM,kBAAkB,UAAU,QAAQ,gCAAgC;CAC1E,IAAI,mBAAmB,GACrB;CAEF,MAAM,gBAAgB,UAAU,MAAM,GAAG,eAAe;CACxD,IAAI,KAAK,KAAK,aAAa,GACzB;CAEF,MAAM,cAAc,cAAc,MAAM,IAAI;CAC5C,IAAI,YAAY,SAAS,KAAK,YAAY,MAAM,SAAS,SAAS,EAAE,GAClE;CAEF,MAAM,SAAS,UACZ,MAAM,kBAAkB,CAAuC,CAAC,CAChE,QAAQ,OAAO,GAAG;CACrB,OAAO,WAAW,KAAK,KAAA,IAAY;AACrC;;;;;;;AAQA,SAAS,4BAA4B,MAAyB;CAC5D,IAAI,WAAW,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,mBAAmB,IAAI,GAClE;CAEF,MAAM,SAAS,4BAA4B,KAAK,IAAI;CACpD,IAAI,UAAU,MACZ;CAEF,KAAK,OAAO;CACZ,KAAK,WAAW,2BAA2B,oBACzC;AACJ;AAEA,SAAS,YAAY,MAAmB,aAA8B;CACpE,MAAM,OAAO,oBACX,KAAK,WAAW,2BAA2B,WAC7C;CACA,OACE,MAAM,QAAQ,IAAI,KAClB,KAAK,MAAM,QAAQ,OAAO,QAAQ,YAAY,QAAQ,WAAW;AAErE;AAEA,SAAS,yBAAyB,MAAyB;CACzD,IAAI,iBAAiB,IAAI,GACvB;CAEF,IACE,YAAY,MAAM,eAAe,KAChC,KAAK,SAAS,4BACb,YAAY,MAAM,wBAAwB,GAC5C;EACA,KAAK,WAAW,2BAA2B,oBACzC;EACF;CACF;CACA,IAAI,YAAY,MAAM,eAAe,GACnC,KAAK,WAAW,2BAA2B,oBACzC;AAEN;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,kBAAkB,MAA0B;CAC1D,MAAM,UAAU;CAChB,IAAI,QAAQ,KAAK,WAAW,2BAA2B,GACrD,mBAAmB,OAAO;MACrB,IAAI,QAAQ,KAAK,WAAW,0BAA0B,GAC3D,kBAAkB,OAAO;MACpB,IAAI,iBAAiB,OAAO,GACjC,QAAQ,OAAO;MAEf,4BAA4B,OAAO;CAErC,IAAI,CAAC,WAAW,IAAI,GAClB;CAEF,yBAAyB,OAAO;CAChC,cAAc,OAAO;AACvB"}
package/dist/esm/main.mjs CHANGED
@@ -102,6 +102,8 @@ import { createRunHandlers } from "./session/handlers.mjs";
102
102
  import { AgentSession, createAgentSession } from "./session/AgentSession.mjs";
103
103
  import "./session/index.mjs";
104
104
  import { askUserQuestion } from "./hitl/askUserQuestion.mjs";
105
+ import { ASK_USER_QUESTION_ID_PATTERN, MAX_ASK_USER_QUESTIONS, isAskUserQuestionsInterrupt } from "./hitl/askUserQuestionsInterrupt.mjs";
106
+ import { askUserQuestions } from "./hitl/askUserQuestions.mjs";
105
107
  import "./hitl/index.mjs";
106
108
  import { AIMessage, AIMessageChunk, BaseMessage, BaseMessageChunk, HumanMessage, SystemMessage, ToolMessage, getBufferString, isAIMessage, isBaseMessage, isToolMessage } from "./langchain/messages.mjs";
107
109
  import { PromptTemplate } from "./langchain/prompts.mjs";
@@ -109,4 +111,4 @@ import { Runnable, RunnableLambda, RunnableSequence } from "./langchain/runnable
109
111
  import { DynamicStructuredTool, StructuredTool, Tool, tool } from "./langchain/tools.mjs";
110
112
  import "./langchain/index.mjs";
111
113
  import { BaseCheckpointSaver, Command, INTERRUPT, MemorySaver, interrupt, isInterrupted } from "@langchain/langgraph";
112
- export { AIMessage, AIMessageChunk, ANTHROPIC_TOOL_TOKEN_MULTIPLIER, AgentSession, BASH_SHELL_GUIDANCE, BaseCheckpointSaver, BaseMessage, BaseMessageChunk, BashExecutionToolDefinition, BashExecutionToolDescription, BashExecutionToolName, BashExecutionToolSchema, BashProgrammaticToolCallingDefinition, BashProgrammaticToolCallingDescription, BashProgrammaticToolCallingName, BashProgrammaticToolCallingSchema, BashToolOutputReferencesGuide, CALIBRATION_RATIO_MAX, CALIBRATION_RATIO_MIN, CLOUDFLARE_BASH_CODING_TOOL_NAMES, CLOUDFLARE_CODING_TOOL_NAMES, CODE_API_AUTHORIZATION_ERROR_MESSAGE, CODE_API_EXECUTION_FAILED_ERROR_MESSAGE, CODE_API_INVALID_REQUEST_ERROR_MESSAGE, CODE_API_RATE_LIMITED_ERROR_MESSAGE, CODE_API_UNAVAILABLE_ERROR_MESSAGE, CODE_ARTIFACT_PATH_GUIDANCE, CODE_EXECUTION_TOOLS, Calculator, CalculatorSchema, CalculatorToolDefinition, CalculatorToolDescription, CalculatorToolName, Callback, ChatModelStreamHandler, ChatOpenRouter, CloudflareBashExecutionToolDescription, CloudflareCodeExecutionToolDescription, CodeApiRequestError, CodeExecutionToolDefinition, CodeExecutionToolDescription, CodeExecutionToolName, CodeExecutionToolSchema, Command, CommonEvents, CompileCheckToolName, Constants, ContentTypes, CustomChatMistralAI, CustomOpenAIClient, DATE_RANGE, DEFAULT_CONTEXT_PRUNING_SETTINGS, DEFAULT_COUNTRY_DESCRIPTION, DEFAULT_HOOK_TIMEOUT_MS, DEFAULT_MAX_SEALS, DEFAULT_MAX_TOOL_CALL_ARG_BYTES, DEFAULT_PROMPT_CACHE_TTL, DEFAULT_QUERY_DESCRIPTION, DEFAULT_RECURSION_LIMIT, DEFAULT_RESERVE_RATIO, DEFAULT_RETAIN_RECENT_TURNS, DEFAULT_STREAM_DELAY, DEFAULT_SUBAGENT_DESCRIPTION, DEFAULT_TOOL_TOKEN_MULTIPLIER, DynamicStructuredTool, EnvVar, FAILED_EXECUTION_FILE_REMINDER, FakeChatModel, Graph, GraphEvents, GraphNodeActions, GraphNodeKeys, HARD_MAX_TOOL_RESULT_CHARS, HARD_MAX_TOTAL_TOOL_OUTPUT_SIZE, HOOK_EVENTS, HOOK_INJECTED_MESSAGES_CAPABLE, HOOK_PREEMPT_BOUNDARY_CAPABLE, HandlerRegistry, HookRegistry, HumanMessage, IMAGE_TOKEN_SAFETY_MARGIN, INTENT_ARG, INTENT_DESCRIPTION, INTENT_LABEL_MARKER, INTENT_PROPERTY, INTERRUPT, JsonlSessionStore, LLMStreamHandler, LOCAL_CODING_BUNDLE_NAMES, LOCAL_CODING_TOOL_NAMES, LOCAL_SPAWN_TIMEOUT_MS, LocalBashExecutionToolDescription, LocalCodeExecutionToolDescription, LocalEditFileToolName, LocalEditFileToolSchema, LocalFileCheckpointerImpl, LocalGlobSearchToolName, LocalGlobSearchToolSchema, LocalGrepSearchToolName, LocalGrepSearchToolSchema, LocalListDirectoryToolName, LocalListDirectoryToolSchema, LocalReadFileToolSchema, LocalWriteFileToolName, LocalWriteFileToolSchema, MAX_CACHE_SIZE, MAX_PATTERN_LENGTH, MemorySaver, ModelEndHandler, MultiAgentGraph, OPENAI_RESPONSES_REPLAY_POSITIONS_KEY, ORIGINAL_CONTENT_MAX_CHARS, PREDECESSOR_HANDOFF_CUE, PREEMPT_BOUNDARY_HOOK_TIMEOUT_MS, ProgrammaticToolCallingDefinition, ProgrammaticToolCallingDescription, ProgrammaticToolCallingName, ProgrammaticToolCallingSchema, PromptTemplate, Providers, REMOVE_ALL_MESSAGES, REPLY_PRIMER_TOKENS, ReadFileToolDefinition, ReadFileToolDescription, ReadFileToolName, ReadFileToolSchema, Run, Runnable, RunnableCallable, RunnableLambda, RunnableSequence, SDK_STREAM_DISPATCH, STATEFUL_BASH_NOTE, STATEFUL_ENV_NOTE, SessionManager, SkillToolDefinition, SkillToolDescription, SkillToolName, SkillToolSchema, StandardGraph, StatefulBashExecutionToolDescription, StatefulCodeExecutionToolDescription, StepTypes, StreamLimitExceededError, StructuredTool, SubagentExecutor, SubagentToolDefinition, SubagentToolDescription, SubagentToolName, SubagentToolSchema, SystemMessage, TMP_SCRATCH_OUTPUT_REMINDER, TOOL_APPROVAL_EXECUTION_SCOPE_CONFIG_KEY, TestChatStreamHandler, TestLLMStreamHandler, TitleMethod, TokenEncoderManager, Tool, ToolCallTypes, ToolEndHandler, ToolMessage, ToolNode, ToolSearchToolDefinition, ToolSearchToolDescription, ToolSearchToolName, ToolSearchToolSchema, UnsafeTokenMeasurementError, WebSearchToolDefinition, WebSearchToolDescription, WebSearchToolName, WebSearchToolSchema, _createBashProgramForTests, _resetLocalEngineWarningsForTests, _resetRipgrepCacheForTests, _resetSyntaxCheckProbeCacheForTests, _resetUnrecognizedTriggerWarnings, addBedrockCacheControl, addBedrockTailCacheControl, addCacheControl, addCacheControlToStablePrefixMessages, addTailCacheControl, appendCodeSessionFileSummary, appendFailedExecutionFileReminder, appendPredecessorHandoffCue, appendTmpScratchReminder, applyContextPruning, applyEdit, applyOutcome, applyPreToolUseHooksForBridge, apportionTokenCounts, askUserQuestion, attemptInvoke, bashAstFindingsToErrors, buildAnthropicCacheControl, buildBashExecutionToolDescription, buildBashExecutionToolSchema, buildBedrockCachePoint, buildChildInputs, buildCodeApiExecutionErrorMessage, buildCodeApiHttpErrorMessage, buildCodeExecutionToolDescription, buildCodeExecutionToolSchema, buildSandboxRuntimeConfig, buildSubagentToolParams, calculateMaxToolCallInputChars, calculateMaxToolResultChars, calculateMaxTotalToolOutputSize, calculateTotalTokens, canSealPreempt, checkValidNumber, clampCalibrationRatio, classifyAttachment, clientExecTimeoutMs, clientFsTimeoutMs, cloneMessage, coalesceAdjacentUserTurns, composeAbortSignals, composeEventHandlers, computeAdaptivePieceSize, convertInjectedMessages, convertMessagesToContent, countNestedGroups, countrySchema, createAgentSession, createBashExecutionTool, createBashProgrammaticToolCallingSchema, createBashProgrammaticToolCallingTool, createCloudflareBashExecutionTool, createCloudflareBashProgrammaticToolCallingTool, createCloudflareBridgeRuntime, createCloudflareCodeExecutionTool, createCloudflareCodingToolBundle, createCloudflareCodingTools, createCloudflareExecutionTool, createCloudflareLocalExecutionConfig, createCloudflareProgrammaticToolCallingTool, createCloudflareWorkspaceFS, createCodeExecutionTool, createCompileCheckTool, createCompileCheckToolDefinition, createContentAggregator, createFakeStreamingLLM, createGraph, createHandlers, createLocalBashExecutionTool, createLocalBashProgrammaticToolCallingTool, createLocalCodeExecutionTool, createLocalCodingToolBundle, createLocalCodingToolDefinitions, createLocalCodingToolRegistry, createLocalCodingTools, createLocalEditFileTool, createLocalFileCheckpointer, createLocalGlobSearchTool, createLocalGrepSearchTool, createLocalListDirectoryTool, createLocalProgrammaticToolCallingTool, createLocalReadFileTool, createLocalWriteFileTool, createMetadataAggregator, createProgrammaticToolCallingSchema, createProgrammaticToolCallingTool, createPruneMessages, createRemoveAllMessage, createRunHandlers, createSchemaOnlyTool, createSchemaOnlyTools, createSearchTool, createSubagentToolDefinition, createTokenCounter, createToolErrorOwnership, createToolPolicyHook, createToolSearch, createWorkspacePolicyHook, dateSchema, decodeFile, defaultOmitOptions, deserializeMessage, dispatchesChatModelStream, emptyOutputMessage, encodeFile, encodingForModel, enforceOriginalContentCap, ensureThinkingBlockInMessages, escapeRegexSpecialChars, estimateAnthropicImageTokens, estimateDocumentBlockTokens, estimateImageBlockTokens, estimateOpenAIImageTokens, estimateTimedMediaBlockTokens, execWithClientTimeout, executeCloudflareBash, executeCloudflareCode, executeHooks, executeLocalBash, executeLocalBashWithArgs, executeLocalCode, executeParallelSearches, executeTools, extractErrorMessage, extractImageDimensions, extractMcpServerName, extractTextFromContent, extractToolDiscoveries, extractUsedBashToolNames, extractUsedToolNames, fetchSessionFiles, filterBashToolsByUsage, filterGraphSubagentResult, filterSubagentResult, filterToolsByUsage, findLastIndex, foldToolBlocksForToollessAgent, formatAgentMessages, formatAnthropicArtifactContent, formatAnthropicMessage, formatArtifactPayload, formatCloudflareOutput, formatCompletedResponse, formatContentStrings, formatFromLangChain, formatLangChainMessages, formatMediaMessage, formatMessage, formatServerListing, formatSkillCatalog, getAssistantTextPhase, getAvailableMcpServers, getBaseToolName, getBufferString, getChatModelClass, getChunkContent, getCloudflareWorkspaceRoot, getCodeBaseURL, getContextOverflowInfo, getConverseOverrideMessage, getDeferredToolsListing, getLocalCwd, getLocalSessionId, getMaxOutputTokensKey, getMessageCreationContentMetadata, getMessageId, getMessagesWithinTokenLimit, getReadRoots, getSpawn, getTokenCountForMessage, getWorkspaceFS, getWorkspaceRoots, getWriteRoots, handleServerToolResult, handleToolCallChunks, handleToolCalls, hasNestedQuantifier, hasNestedQuantifiers, hasToolSearchInCurrentTurn, hasUnsafeStructuredSerialization, imageAttachmentContent, imagesSchema, initializeModel, interrupt, isAIMessage, isAnthropicLike, isBaseMessage, isContextOverflowError, isDangerousPattern, isFromAnyMcpServer, isFromMcpServer, isGoogleLike, isGraphSubagentConfig, isIntentLabelProperty, isInterrupted, isLegacyConvertible, isLikelyContextOverflowError, isOpenAILike, isPresent, isSyntheticProviderContextMessage, isThinkingEnabled, isToolMessage, isZodSchema, joinKeys, labelContentByAgent, locateEdit, makeIsDeferred, makeRequest, maskConsumedToolResults, matchesQuery, messagesStateReducer, modifyDeltaProperties, newsSchema, normalizeBashToolResultsForReplay, normalizeCodeApiRequestError, normalizeServerFilter, normalizeSubagentConfigEntries, normalizeSubagentConfigs, normalizeToBashIdentifier, normalizeToPythonIdentifier, outcomeFieldsFromResult, parseBooleanEnv, partitionAndMarkAnthropicToolCache, performLocalSearch, preFlightTruncateToolCallInputs, preFlightTruncateToolResults, projectAgentContextUsage, projectAnthropicArtifactContent, projectArtifactPayload, projectCacheControlledToolOutputsToText, projectComputerCallOutputsToText, projectOpenAIChatToolMessageContent, projectOpenAIResponsesToolMessageContent, projectOpenAIToolMessageContent, projectOpenRouterToolMessageContent, projectSingleTextToolOutputsToText, projectStructuredToolOutputsToText, projectToolCallInputs, projectToolStreamContentForProvider, querySchema, readIntent, readOutcomeFields, removePredecessorHandoffCue, repairOrphanedToolMessages, resetIfNotEmpty, resolveBedrockPromptCacheTtl, resolveCloudflareSandbox, resolveCodeApiAuthHeaders, resolveContextPruningSettings, resolveFetchProxyAgent, resolveLocalExecutionConfig, resolveLocalExecutionTools, resolveLocalToolRegistry, resolveLocalToolsForBinding, resolvePromptCacheTtl, resolveSearchOutcome, resolveStreamDelay, resolveStreamLimits, resolveSubagentConfigEntries, resolveSubagentConfigs, resolveToolOutcome, resolveWorkspacePath, resolveWorkspacePathSafe, runBashAstChecks, runPostEditSyntaxCheck, sanitizeOrphanToolBlocks, sanitizeRegex, serializeMessage, serializeToolCallInput, shellQuote, shiftIndexTokenCountMap, shouldBypassProxy, shouldTriggerSummarization, sleep, smoothStream, spawnLocalProcess, splitAssistantTextContentByPhase, splitAtRecencyBoundary, strictAlternationProviders, stripAnthropicCacheControl, stripBedrockCacheControl, stripCodeSessionFileSummary, stripIntent, summarizeEvent, supportsBedrockToolCache, syncBudgetDerivedFields, toJsonSchema, tool, toolResultTypes, toolsCondition, truncateLocalOutput, truncateToolInput, truncateToolResultContent, tryFallbackProviders, unescapeObject, unwrapToolResponse, validateBashCommand, validateCloudflareBashCommand, videosSchema, withClientTimeout, withIntent, withMessageRole, withoutIntent };
114
+ export { AIMessage, AIMessageChunk, ANTHROPIC_TOOL_TOKEN_MULTIPLIER, ASK_USER_QUESTION_ID_PATTERN, AgentSession, BASH_SHELL_GUIDANCE, BaseCheckpointSaver, BaseMessage, BaseMessageChunk, BashExecutionToolDefinition, BashExecutionToolDescription, BashExecutionToolName, BashExecutionToolSchema, BashProgrammaticToolCallingDefinition, BashProgrammaticToolCallingDescription, BashProgrammaticToolCallingName, BashProgrammaticToolCallingSchema, BashToolOutputReferencesGuide, CALIBRATION_RATIO_MAX, CALIBRATION_RATIO_MIN, CLOUDFLARE_BASH_CODING_TOOL_NAMES, CLOUDFLARE_CODING_TOOL_NAMES, CODE_API_AUTHORIZATION_ERROR_MESSAGE, CODE_API_EXECUTION_FAILED_ERROR_MESSAGE, CODE_API_INVALID_REQUEST_ERROR_MESSAGE, CODE_API_RATE_LIMITED_ERROR_MESSAGE, CODE_API_UNAVAILABLE_ERROR_MESSAGE, CODE_ARTIFACT_PATH_GUIDANCE, CODE_EXECUTION_TOOLS, Calculator, CalculatorSchema, CalculatorToolDefinition, CalculatorToolDescription, CalculatorToolName, Callback, ChatModelStreamHandler, ChatOpenRouter, CloudflareBashExecutionToolDescription, CloudflareCodeExecutionToolDescription, CodeApiRequestError, CodeExecutionToolDefinition, CodeExecutionToolDescription, CodeExecutionToolName, CodeExecutionToolSchema, Command, CommonEvents, CompileCheckToolName, Constants, ContentTypes, CustomChatMistralAI, CustomOpenAIClient, DATE_RANGE, DEFAULT_CONTEXT_PRUNING_SETTINGS, DEFAULT_COUNTRY_DESCRIPTION, DEFAULT_HOOK_TIMEOUT_MS, DEFAULT_MAX_SEALS, DEFAULT_MAX_TOOL_CALL_ARG_BYTES, DEFAULT_PROMPT_CACHE_TTL, DEFAULT_QUERY_DESCRIPTION, DEFAULT_RECURSION_LIMIT, DEFAULT_RESERVE_RATIO, DEFAULT_RETAIN_RECENT_TURNS, DEFAULT_STREAM_DELAY, DEFAULT_SUBAGENT_DESCRIPTION, DEFAULT_TOOL_TOKEN_MULTIPLIER, DynamicStructuredTool, EnvVar, FAILED_EXECUTION_FILE_REMINDER, FakeChatModel, Graph, GraphEvents, GraphNodeActions, GraphNodeKeys, HARD_MAX_TOOL_RESULT_CHARS, HARD_MAX_TOTAL_TOOL_OUTPUT_SIZE, HOOK_EVENTS, HOOK_INJECTED_MESSAGES_CAPABLE, HOOK_PREEMPT_BOUNDARY_CAPABLE, HandlerRegistry, HookRegistry, HumanMessage, IMAGE_TOKEN_SAFETY_MARGIN, INTENT_ARG, INTENT_DESCRIPTION, INTENT_LABEL_MARKER, INTENT_PROPERTY, INTERRUPT, JsonlSessionStore, LLMStreamHandler, LOCAL_CODING_BUNDLE_NAMES, LOCAL_CODING_TOOL_NAMES, LOCAL_SPAWN_TIMEOUT_MS, LocalBashExecutionToolDescription, LocalCodeExecutionToolDescription, LocalEditFileToolName, LocalEditFileToolSchema, LocalFileCheckpointerImpl, LocalGlobSearchToolName, LocalGlobSearchToolSchema, LocalGrepSearchToolName, LocalGrepSearchToolSchema, LocalListDirectoryToolName, LocalListDirectoryToolSchema, LocalReadFileToolSchema, LocalWriteFileToolName, LocalWriteFileToolSchema, MAX_ASK_USER_QUESTIONS, MAX_CACHE_SIZE, MAX_PATTERN_LENGTH, MemorySaver, ModelEndHandler, MultiAgentGraph, OPENAI_RESPONSES_REPLAY_POSITIONS_KEY, ORIGINAL_CONTENT_MAX_CHARS, PREDECESSOR_HANDOFF_CUE, PREEMPT_BOUNDARY_HOOK_TIMEOUT_MS, ProgrammaticToolCallingDefinition, ProgrammaticToolCallingDescription, ProgrammaticToolCallingName, ProgrammaticToolCallingSchema, PromptTemplate, Providers, REMOVE_ALL_MESSAGES, REPLY_PRIMER_TOKENS, ReadFileToolDefinition, ReadFileToolDescription, ReadFileToolName, ReadFileToolSchema, Run, Runnable, RunnableCallable, RunnableLambda, RunnableSequence, SDK_STREAM_DISPATCH, STATEFUL_BASH_NOTE, STATEFUL_ENV_NOTE, SessionManager, SkillToolDefinition, SkillToolDescription, SkillToolName, SkillToolSchema, StandardGraph, StatefulBashExecutionToolDescription, StatefulCodeExecutionToolDescription, StepTypes, StreamLimitExceededError, StructuredTool, SubagentExecutor, SubagentToolDefinition, SubagentToolDescription, SubagentToolName, SubagentToolSchema, SystemMessage, TMP_SCRATCH_OUTPUT_REMINDER, TOOL_APPROVAL_EXECUTION_SCOPE_CONFIG_KEY, TestChatStreamHandler, TestLLMStreamHandler, TitleMethod, TokenEncoderManager, Tool, ToolCallTypes, ToolEndHandler, ToolMessage, ToolNode, ToolSearchToolDefinition, ToolSearchToolDescription, ToolSearchToolName, ToolSearchToolSchema, UnsafeTokenMeasurementError, WebSearchToolDefinition, WebSearchToolDescription, WebSearchToolName, WebSearchToolSchema, _createBashProgramForTests, _resetLocalEngineWarningsForTests, _resetRipgrepCacheForTests, _resetSyntaxCheckProbeCacheForTests, _resetUnrecognizedTriggerWarnings, addBedrockCacheControl, addBedrockTailCacheControl, addCacheControl, addCacheControlToStablePrefixMessages, addTailCacheControl, appendCodeSessionFileSummary, appendFailedExecutionFileReminder, appendPredecessorHandoffCue, appendTmpScratchReminder, applyContextPruning, applyEdit, applyOutcome, applyPreToolUseHooksForBridge, apportionTokenCounts, askUserQuestion, askUserQuestions, attemptInvoke, bashAstFindingsToErrors, buildAnthropicCacheControl, buildBashExecutionToolDescription, buildBashExecutionToolSchema, buildBedrockCachePoint, buildChildInputs, buildCodeApiExecutionErrorMessage, buildCodeApiHttpErrorMessage, buildCodeExecutionToolDescription, buildCodeExecutionToolSchema, buildSandboxRuntimeConfig, buildSubagentToolParams, calculateMaxToolCallInputChars, calculateMaxToolResultChars, calculateMaxTotalToolOutputSize, calculateTotalTokens, canSealPreempt, checkValidNumber, clampCalibrationRatio, classifyAttachment, clientExecTimeoutMs, clientFsTimeoutMs, cloneMessage, coalesceAdjacentUserTurns, composeAbortSignals, composeEventHandlers, computeAdaptivePieceSize, convertInjectedMessages, convertMessagesToContent, countNestedGroups, countrySchema, createAgentSession, createBashExecutionTool, createBashProgrammaticToolCallingSchema, createBashProgrammaticToolCallingTool, createCloudflareBashExecutionTool, createCloudflareBashProgrammaticToolCallingTool, createCloudflareBridgeRuntime, createCloudflareCodeExecutionTool, createCloudflareCodingToolBundle, createCloudflareCodingTools, createCloudflareExecutionTool, createCloudflareLocalExecutionConfig, createCloudflareProgrammaticToolCallingTool, createCloudflareWorkspaceFS, createCodeExecutionTool, createCompileCheckTool, createCompileCheckToolDefinition, createContentAggregator, createFakeStreamingLLM, createGraph, createHandlers, createLocalBashExecutionTool, createLocalBashProgrammaticToolCallingTool, createLocalCodeExecutionTool, createLocalCodingToolBundle, createLocalCodingToolDefinitions, createLocalCodingToolRegistry, createLocalCodingTools, createLocalEditFileTool, createLocalFileCheckpointer, createLocalGlobSearchTool, createLocalGrepSearchTool, createLocalListDirectoryTool, createLocalProgrammaticToolCallingTool, createLocalReadFileTool, createLocalWriteFileTool, createMetadataAggregator, createProgrammaticToolCallingSchema, createProgrammaticToolCallingTool, createPruneMessages, createRemoveAllMessage, createRunHandlers, createSchemaOnlyTool, createSchemaOnlyTools, createSearchTool, createSubagentToolDefinition, createTokenCounter, createToolErrorOwnership, createToolPolicyHook, createToolSearch, createWorkspacePolicyHook, dateSchema, decodeFile, defaultOmitOptions, deserializeMessage, dispatchesChatModelStream, emptyOutputMessage, encodeFile, encodingForModel, enforceOriginalContentCap, ensureThinkingBlockInMessages, escapeRegexSpecialChars, estimateAnthropicImageTokens, estimateDocumentBlockTokens, estimateImageBlockTokens, estimateOpenAIImageTokens, estimateTimedMediaBlockTokens, execWithClientTimeout, executeCloudflareBash, executeCloudflareCode, executeHooks, executeLocalBash, executeLocalBashWithArgs, executeLocalCode, executeParallelSearches, executeTools, extractErrorMessage, extractImageDimensions, extractMcpServerName, extractTextFromContent, extractToolDiscoveries, extractUsedBashToolNames, extractUsedToolNames, fetchSessionFiles, filterBashToolsByUsage, filterGraphSubagentResult, filterSubagentResult, filterToolsByUsage, findLastIndex, foldToolBlocksForToollessAgent, formatAgentMessages, formatAnthropicArtifactContent, formatAnthropicMessage, formatArtifactPayload, formatCloudflareOutput, formatCompletedResponse, formatContentStrings, formatFromLangChain, formatLangChainMessages, formatMediaMessage, formatMessage, formatServerListing, formatSkillCatalog, getAssistantTextPhase, getAvailableMcpServers, getBaseToolName, getBufferString, getChatModelClass, getChunkContent, getCloudflareWorkspaceRoot, getCodeBaseURL, getContextOverflowInfo, getConverseOverrideMessage, getDeferredToolsListing, getLocalCwd, getLocalSessionId, getMaxOutputTokensKey, getMessageCreationContentMetadata, getMessageId, getMessagesWithinTokenLimit, getReadRoots, getSpawn, getTokenCountForMessage, getWorkspaceFS, getWorkspaceRoots, getWriteRoots, handleServerToolResult, handleToolCallChunks, handleToolCalls, hasNestedQuantifier, hasNestedQuantifiers, hasToolSearchInCurrentTurn, hasUnsafeStructuredSerialization, imageAttachmentContent, imagesSchema, initializeModel, interrupt, isAIMessage, isAnthropicLike, isAskUserQuestionsInterrupt, isBaseMessage, isContextOverflowError, isDangerousPattern, isFromAnyMcpServer, isFromMcpServer, isGoogleLike, isGraphSubagentConfig, isIntentLabelProperty, isInterrupted, isLegacyConvertible, isLikelyContextOverflowError, isOpenAILike, isPresent, isSyntheticProviderContextMessage, isThinkingEnabled, isToolMessage, isZodSchema, joinKeys, labelContentByAgent, locateEdit, makeIsDeferred, makeRequest, maskConsumedToolResults, matchesQuery, messagesStateReducer, modifyDeltaProperties, newsSchema, normalizeBashToolResultsForReplay, normalizeCodeApiRequestError, normalizeServerFilter, normalizeSubagentConfigEntries, normalizeSubagentConfigs, normalizeToBashIdentifier, normalizeToPythonIdentifier, outcomeFieldsFromResult, parseBooleanEnv, partitionAndMarkAnthropicToolCache, performLocalSearch, preFlightTruncateToolCallInputs, preFlightTruncateToolResults, projectAgentContextUsage, projectAnthropicArtifactContent, projectArtifactPayload, projectCacheControlledToolOutputsToText, projectComputerCallOutputsToText, projectOpenAIChatToolMessageContent, projectOpenAIResponsesToolMessageContent, projectOpenAIToolMessageContent, projectOpenRouterToolMessageContent, projectSingleTextToolOutputsToText, projectStructuredToolOutputsToText, projectToolCallInputs, projectToolStreamContentForProvider, querySchema, readIntent, readOutcomeFields, removePredecessorHandoffCue, repairOrphanedToolMessages, resetIfNotEmpty, resolveBedrockPromptCacheTtl, resolveCloudflareSandbox, resolveCodeApiAuthHeaders, resolveContextPruningSettings, resolveFetchProxyAgent, resolveLocalExecutionConfig, resolveLocalExecutionTools, resolveLocalToolRegistry, resolveLocalToolsForBinding, resolvePromptCacheTtl, resolveSearchOutcome, resolveStreamDelay, resolveStreamLimits, resolveSubagentConfigEntries, resolveSubagentConfigs, resolveToolOutcome, resolveWorkspacePath, resolveWorkspacePathSafe, runBashAstChecks, runPostEditSyntaxCheck, sanitizeOrphanToolBlocks, sanitizeRegex, serializeMessage, serializeToolCallInput, shellQuote, shiftIndexTokenCountMap, shouldBypassProxy, shouldTriggerSummarization, sleep, smoothStream, spawnLocalProcess, splitAssistantTextContentByPhase, splitAtRecencyBoundary, strictAlternationProviders, stripAnthropicCacheControl, stripBedrockCacheControl, stripCodeSessionFileSummary, stripIntent, summarizeEvent, supportsBedrockToolCache, syncBudgetDerivedFields, toJsonSchema, tool, toolResultTypes, toolsCondition, truncateLocalOutput, truncateToolInput, truncateToolResultContent, tryFallbackProviders, unescapeObject, unwrapToolResponse, validateBashCommand, validateCloudflareBashCommand, videosSchema, withClientTimeout, withIntent, withMessageRole, withoutIntent };