@struct-ai/sdk 0.1.0

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 (228) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +168 -0
  3. package/dist/commonjs/content-capture.d.ts +10 -0
  4. package/dist/commonjs/content-capture.js +23 -0
  5. package/dist/commonjs/context.d.ts +30 -0
  6. package/dist/commonjs/context.js +94 -0
  7. package/dist/commonjs/core.d.ts +120 -0
  8. package/dist/commonjs/core.js +408 -0
  9. package/dist/commonjs/events.d.ts +12 -0
  10. package/dist/commonjs/events.js +103 -0
  11. package/dist/commonjs/index.d.ts +6 -0
  12. package/dist/commonjs/index.js +10 -0
  13. package/dist/commonjs/integrations/anthropic-content.d.ts +24 -0
  14. package/dist/commonjs/integrations/anthropic-content.js +178 -0
  15. package/dist/commonjs/integrations/anthropic.d.ts +34 -0
  16. package/dist/commonjs/integrations/anthropic.js +377 -0
  17. package/dist/commonjs/integrations/index.d.ts +5 -0
  18. package/dist/commonjs/integrations/index.js +47 -0
  19. package/dist/commonjs/integrations/langchain-callback.d.ts +134 -0
  20. package/dist/commonjs/integrations/langchain-callback.js +723 -0
  21. package/dist/commonjs/integrations/langchain-content.d.ts +35 -0
  22. package/dist/commonjs/integrations/langchain-content.js +307 -0
  23. package/dist/commonjs/integrations/langchain.d.ts +11 -0
  24. package/dist/commonjs/integrations/langchain.js +100 -0
  25. package/dist/commonjs/package.json +3 -0
  26. package/dist/commonjs/semconv.d.ts +54 -0
  27. package/dist/commonjs/semconv.js +74 -0
  28. package/dist/commonjs/truncation.d.ts +10 -0
  29. package/dist/commonjs/truncation.js +103 -0
  30. package/dist/esm/content-capture.d.ts +10 -0
  31. package/dist/esm/content-capture.js +17 -0
  32. package/dist/esm/context.d.ts +30 -0
  33. package/dist/esm/context.js +80 -0
  34. package/dist/esm/core.d.ts +120 -0
  35. package/dist/esm/core.js +403 -0
  36. package/dist/esm/events.d.ts +12 -0
  37. package/dist/esm/events.js +99 -0
  38. package/dist/esm/index.d.ts +6 -0
  39. package/dist/esm/index.js +5 -0
  40. package/dist/esm/integrations/anthropic-content.d.ts +24 -0
  41. package/dist/esm/integrations/anthropic-content.js +168 -0
  42. package/dist/esm/integrations/anthropic.d.ts +34 -0
  43. package/dist/esm/integrations/anthropic.js +370 -0
  44. package/dist/esm/integrations/index.d.ts +5 -0
  45. package/dist/esm/integrations/index.js +42 -0
  46. package/dist/esm/integrations/langchain-callback.d.ts +134 -0
  47. package/dist/esm/integrations/langchain-callback.js +719 -0
  48. package/dist/esm/integrations/langchain-content.d.ts +35 -0
  49. package/dist/esm/integrations/langchain-content.js +294 -0
  50. package/dist/esm/integrations/langchain.d.ts +11 -0
  51. package/dist/esm/integrations/langchain.js +95 -0
  52. package/dist/esm/package.json +3 -0
  53. package/dist/esm/semconv.d.ts +54 -0
  54. package/dist/esm/semconv.js +71 -0
  55. package/dist/esm/truncation.d.ts +10 -0
  56. package/dist/esm/truncation.js +96 -0
  57. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/content-capture.d.ts +10 -0
  58. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/context.d.ts +30 -0
  59. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/core.d.ts +120 -0
  60. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/events.d.ts +12 -0
  61. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/index.d.ts +6 -0
  62. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/integrations/anthropic-content.d.ts +24 -0
  63. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/integrations/anthropic.d.ts +34 -0
  64. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/integrations/index.d.ts +5 -0
  65. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/integrations/langchain-callback.d.ts +134 -0
  66. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/integrations/langchain-content.d.ts +35 -0
  67. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/integrations/langchain.d.ts +11 -0
  68. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/package.json +3 -0
  69. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/semconv.d.ts +54 -0
  70. package/dist/node_modules/@struct-ai/sdk/dist/commonjs/truncation.d.ts +10 -0
  71. package/dist/node_modules/@struct-ai/sdk/dist/esm/content-capture.d.ts +10 -0
  72. package/dist/node_modules/@struct-ai/sdk/dist/esm/context.d.ts +30 -0
  73. package/dist/node_modules/@struct-ai/sdk/dist/esm/core.d.ts +120 -0
  74. package/dist/node_modules/@struct-ai/sdk/dist/esm/events.d.ts +12 -0
  75. package/dist/node_modules/@struct-ai/sdk/dist/esm/index.d.ts +6 -0
  76. package/dist/node_modules/@struct-ai/sdk/dist/esm/integrations/anthropic-content.d.ts +24 -0
  77. package/dist/node_modules/@struct-ai/sdk/dist/esm/integrations/anthropic.d.ts +34 -0
  78. package/dist/node_modules/@struct-ai/sdk/dist/esm/integrations/index.d.ts +5 -0
  79. package/dist/node_modules/@struct-ai/sdk/dist/esm/integrations/langchain-callback.d.ts +134 -0
  80. package/dist/node_modules/@struct-ai/sdk/dist/esm/integrations/langchain-content.d.ts +35 -0
  81. package/dist/node_modules/@struct-ai/sdk/dist/esm/integrations/langchain.d.ts +11 -0
  82. package/dist/node_modules/@struct-ai/sdk/dist/esm/package.json +3 -0
  83. package/dist/node_modules/@struct-ai/sdk/dist/esm/semconv.d.ts +54 -0
  84. package/dist/node_modules/@struct-ai/sdk/dist/esm/truncation.d.ts +10 -0
  85. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/dist/commonjs/package.json +3 -0
  86. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/dist/esm/package.json +3 -0
  87. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/package.json +100 -0
  88. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@anthropic-ai/sdk/package.json +103 -0
  89. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/anthropic/package.json +118 -0
  90. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/package.json +916 -0
  91. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/langgraph/package.json +188 -0
  92. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/api/package.json +96 -0
  93. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/api-logs/package.json +91 -0
  94. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/core/package.json +96 -0
  95. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/exporter-logs-otlp-proto/package.json +108 -0
  96. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/exporter-trace-otlp-proto/package.json +105 -0
  97. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/resources/package.json +100 -0
  98. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/sdk-logs/package.json +109 -0
  99. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/sdk-trace-base/package.json +100 -0
  100. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/sdk-trace-node/package.json +76 -0
  101. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/package.json +140 -0
  102. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/nock/package.json +89 -0
  103. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/tshy/package.json +81 -0
  104. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/typescript/package.json +120 -0
  105. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/node_modules/vitest/package.json +239 -0
  106. package/dist/node_modules/@struct-ai/sdk/dist/node_modules/@struct-ai/sdk/package.json +100 -0
  107. package/dist/node_modules/@struct-ai/sdk/node_modules/@anthropic-ai/sdk/core.d.ts +244 -0
  108. package/dist/node_modules/@struct-ai/sdk/node_modules/@anthropic-ai/sdk/error.d.ts +54 -0
  109. package/dist/node_modules/@struct-ai/sdk/node_modules/@anthropic-ai/sdk/index.d.ts +188 -0
  110. package/dist/node_modules/@struct-ai/sdk/node_modules/@anthropic-ai/sdk/package.json +103 -0
  111. package/dist/node_modules/@struct-ai/sdk/node_modules/@anthropic-ai/sdk/pagination.d.ts +26 -0
  112. package/dist/node_modules/@struct-ai/sdk/node_modules/@anthropic-ai/sdk/resource.d.ts +6 -0
  113. package/dist/node_modules/@struct-ai/sdk/node_modules/@anthropic-ai/sdk/streaming.d.ts +41 -0
  114. package/dist/node_modules/@struct-ai/sdk/node_modules/@anthropic-ai/sdk/uploads.d.ts +75 -0
  115. package/dist/node_modules/@struct-ai/sdk/node_modules/@anthropic-ai/sdk/version.d.ts +2 -0
  116. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/anthropic/experimental.d.ts +1 -0
  117. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/anthropic/index.d.ts +1 -0
  118. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/anthropic/package.json +118 -0
  119. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/agents.d.ts +1 -0
  120. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/caches.d.ts +1 -0
  121. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/chat_history.d.ts +1 -0
  122. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/context.d.ts +1 -0
  123. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/documents.d.ts +1 -0
  124. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/embeddings.d.ts +1 -0
  125. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/example_selectors.d.ts +1 -0
  126. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/index.d.ts +1 -0
  127. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/indexing.d.ts +1 -0
  128. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/load.d.ts +1 -0
  129. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/memory.d.ts +1 -0
  130. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/messages.d.ts +1 -0
  131. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/output_parsers.d.ts +1 -0
  132. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/outputs.d.ts +1 -0
  133. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/package.json +916 -0
  134. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/prompt_values.d.ts +1 -0
  135. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/prompts.d.ts +1 -0
  136. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/retrievers.d.ts +1 -0
  137. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/runnables.d.ts +1 -0
  138. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/singletons.d.ts +1 -0
  139. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/stores.d.ts +1 -0
  140. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/structured_query.d.ts +1 -0
  141. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/tools.d.ts +1 -0
  142. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/core/vectorstores.d.ts +1 -0
  143. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/langgraph/index.d.ts +1 -0
  144. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/langgraph/package.json +188 -0
  145. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/langgraph/prebuilt.d.ts +1 -0
  146. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/langgraph/pregel.d.ts +1 -0
  147. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/langgraph/remote.d.ts +1 -0
  148. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/langgraph/web.d.ts +1 -0
  149. package/dist/node_modules/@struct-ai/sdk/node_modules/@langchain/langgraph/zod.d.ts +1 -0
  150. package/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/api/package.json +96 -0
  151. package/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/api-logs/package.json +91 -0
  152. package/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/core/package.json +96 -0
  153. package/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/exporter-logs-otlp-proto/package.json +108 -0
  154. package/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/exporter-trace-otlp-proto/package.json +105 -0
  155. package/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/resources/package.json +100 -0
  156. package/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/sdk-logs/package.json +109 -0
  157. package/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/sdk-trace-base/package.json +100 -0
  158. package/dist/node_modules/@struct-ai/sdk/node_modules/@opentelemetry/sdk-trace-node/package.json +76 -0
  159. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/assert.d.ts +1062 -0
  160. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/async_hooks.d.ts +605 -0
  161. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/buffer.buffer.d.ts +471 -0
  162. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/buffer.d.ts +1936 -0
  163. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/child_process.d.ts +1475 -0
  164. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/cluster.d.ts +577 -0
  165. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/console.d.ts +452 -0
  166. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/constants.d.ts +21 -0
  167. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/crypto.d.ts +4590 -0
  168. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/dgram.d.ts +597 -0
  169. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/diagnostics_channel.d.ts +578 -0
  170. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/dns.d.ts +871 -0
  171. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/domain.d.ts +170 -0
  172. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/events.d.ts +977 -0
  173. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/fs.d.ts +4375 -0
  174. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/globals.d.ts +172 -0
  175. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/globals.typedarray.d.ts +38 -0
  176. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/http.d.ts +2049 -0
  177. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/http2.d.ts +2631 -0
  178. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/https.d.ts +578 -0
  179. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/index.d.ts +93 -0
  180. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/inspector.generated.d.ts +3966 -0
  181. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/module.d.ts +539 -0
  182. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/net.d.ts +1031 -0
  183. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/os.d.ts +506 -0
  184. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/package.json +140 -0
  185. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/path.d.ts +200 -0
  186. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/perf_hooks.d.ts +961 -0
  187. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/process.d.ts +1961 -0
  188. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/punycode.d.ts +117 -0
  189. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/querystring.d.ts +152 -0
  190. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/readline.d.ts +589 -0
  191. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/repl.d.ts +430 -0
  192. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/sea.d.ts +153 -0
  193. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/stream.d.ts +1698 -0
  194. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/string_decoder.d.ts +67 -0
  195. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/test.d.ts +1787 -0
  196. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/timers.d.ts +286 -0
  197. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/tls.d.ts +1259 -0
  198. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/trace_events.d.ts +197 -0
  199. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/tty.d.ts +208 -0
  200. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/url.d.ts +964 -0
  201. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/util.d.ts +2331 -0
  202. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/v8.d.ts +809 -0
  203. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/vm.d.ts +1001 -0
  204. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/wasi.d.ts +181 -0
  205. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/worker_threads.d.ts +715 -0
  206. package/dist/node_modules/@struct-ai/sdk/node_modules/@types/node/zlib.d.ts +598 -0
  207. package/dist/node_modules/@struct-ai/sdk/node_modules/nock/package.json +89 -0
  208. package/dist/node_modules/@struct-ai/sdk/node_modules/tshy/package.json +81 -0
  209. package/dist/node_modules/@struct-ai/sdk/node_modules/typescript/package.json +120 -0
  210. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/config.d.ts +3 -0
  211. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/coverage.d.ts +1 -0
  212. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/environments.d.ts +1 -0
  213. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/globals.d.ts +22 -0
  214. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/import-meta.d.ts +5 -0
  215. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/importMeta.d.ts +4 -0
  216. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/jsdom.d.ts +6 -0
  217. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/mocker.d.ts +1 -0
  218. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/node.d.ts +1 -0
  219. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/optional-runtime-types.d.ts +6 -0
  220. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/optional-types.d.ts +7 -0
  221. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/package.json +239 -0
  222. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/reporters.d.ts +1 -0
  223. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/runners.d.ts +1 -0
  224. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/snapshot.d.ts +1 -0
  225. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/suite.d.ts +1 -0
  226. package/dist/node_modules/@struct-ai/sdk/node_modules/vitest/worker.d.ts +1 -0
  227. package/dist/node_modules/@struct-ai/sdk/package.json +100 -0
  228. package/package.json +100 -0
@@ -0,0 +1,723 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StructCallbackHandler = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const api_1 = require("@opentelemetry/api");
6
+ const context_js_1 = require("../context.js");
7
+ const core_js_1 = require("../core.js");
8
+ const semconv_js_1 = require("../semconv.js");
9
+ const truncation_js_1 = require("../truncation.js");
10
+ const langchain_content_js_1 = require("./langchain-content.js");
11
+ /**
12
+ * LangChain CallbackHandler — creates OTel spans from LangChain callbacks.
13
+ *
14
+ * Parent-child linkage comes from `parentRunId` fields LangChain passes to us,
15
+ * NOT from OTel's async context. This survives LangGraph's internal task
16
+ * shuffling, which is why the callback API is the industry-standard integration
17
+ * point (LangSmith, OpenInference, Traceloop, Langfuse all use it).
18
+ *
19
+ * thread_id vs gen_ai.conversation.id
20
+ * -----------------------------------
21
+ * These are distinct concepts and Struct keeps them separate:
22
+ *
23
+ * - `config.configurable.thread_id` is LangGraph's checkpoint identifier,
24
+ * keying a conversation's state in the checkpointer. Multiple turns of
25
+ * the same conversation reuse one thread_id so history accumulates.
26
+ *
27
+ * - `gen_ai.conversation.id` is the OTel GenAI-spec conversation identifier
28
+ * and Struct's UI grouping unit — one value = one entry in the sessions
29
+ * list. For the top-level agent we auto-derive it from thread_id, so a
30
+ * stable thread_id across multi-turn chats collapses into one session.
31
+ *
32
+ * For SUBAGENTS (an agent invoked from inside another's tool body) we
33
+ * deliberately assign a DIFFERENT conversation.id — either from the subagent's
34
+ * own thread_id if supplied, or a fresh UUID. The resulting session is
35
+ * linked back to the outer agent's session via the
36
+ * `struct.agent.parent_session_id` span attribute (what powers "Spawned
37
+ * by" / subagent navigation in the UI). Without this split the subagent's
38
+ * spans would collapse into the outer session, burying delegation.
39
+ *
40
+ * LangChain quirk (handled automatically): when `agent.invoke(...)` runs
41
+ * nested inside a parent call, LangChain's config-merge inherits the
42
+ * parent's `metadata.thread_id` onto the child even if its config provided
43
+ * a different one. We detect that by comparing against the nearest agent
44
+ * ancestor's session; if they match, treat it as "inherited, not
45
+ * user-intended" and assign a fresh UUID to the subagent.
46
+ *
47
+ * End-user guidance:
48
+ * - Use thread_id per conversation; multi-turn chats reuse it.
49
+ * - For a subagent call, pass a DIFFERENT thread_id (or omit it and let
50
+ * LangGraph generate one). Each subagent then surfaces as its own
51
+ * session in the UI, linked back via parent_session_id.
52
+ */
53
+ class StructCallbackHandler {
54
+ sdk;
55
+ tracer;
56
+ logger;
57
+ name = "struct";
58
+ lc_namespace = ["struct", "callbacks"];
59
+ lc_serializable = false;
60
+ awaitHandlers = false;
61
+ ignoreLLM = false;
62
+ ignoreChain = false;
63
+ ignoreAgent = false;
64
+ ignoreRetriever = false;
65
+ ignoreCustomEvent = true;
66
+ /**
67
+ * LangChain reads `raiseError` to decide whether a callback throw should
68
+ * abort the user's run. We keep this `false` because every callback method
69
+ * is wrapped in `safe()` and never throws — but a `true` here would tell
70
+ * LangChain to surface our (impossible) throws into the user's call.
71
+ * Locked by `test_handler_raiseError_is_false`.
72
+ */
73
+ raiseError = false;
74
+ runs = new Map();
75
+ internalLogger;
76
+ constructor(sdk, tracer, logger) {
77
+ this.sdk = sdk;
78
+ this.tracer = tracer;
79
+ this.logger = logger;
80
+ this.internalLogger = sdk.getInternalLogger();
81
+ }
82
+ // ─── Chain / Agent (Pregel, AgentExecutor, custom Runnables) ─────────────
83
+ handleChainStart = (chain, inputs, runId, parentRunId, _tags, metadata, runType, runName) => {
84
+ // Non-agent chain (RunnableSequence, ChannelWrite, Branch, internal
85
+ // LangGraph nodes): don't create a span, but record the runId so
86
+ // downstream children with parentRunId pointing here can still find
87
+ // their effective parent span.
88
+ if (!isAgentChain(chain, runType, runName)) {
89
+ // Skipped chains inherit session from parent (so chat/tool spans
90
+ // created under them stay tied to the enclosing agent's session).
91
+ const sessionId = this.resolveSessionId(parentRunId, metadata);
92
+ const { parentSpan } = this.resolveParent(parentRunId);
93
+ this.runs.set(runId, {
94
+ span: undefined,
95
+ effectiveParentSpan: parentSpan,
96
+ sessionId,
97
+ nearestAgentSessionId: this.inheritedAgentSessionId(parentRunId),
98
+ kind: "skipped-chain",
99
+ });
100
+ return;
101
+ }
102
+ const agentName = runName ??
103
+ extractClassName(chain) ??
104
+ (typeof inputs === "object" && inputs
105
+ ? inputs.name
106
+ : undefined) ??
107
+ "agent";
108
+ // Agent-start: each agent invocation gets its OWN gen_ai.conversation.id.
109
+ // Prefer config.configurable.thread_id, then a fresh UUID. Never inherit
110
+ // from the parent agent — subagents should appear as separate sessions
111
+ // in the UI, linked via ``struct.agent.parent_session_id``.
112
+ //
113
+ // Convention (documented publicly):
114
+ // * thread_id is a LangGraph checkpoint identifier. Multiple turns
115
+ // of one conversation reuse a thread_id → we group them into one
116
+ // session.
117
+ // * Subagents should be given a distinct thread_id (or none at all,
118
+ // letting LangGraph generate one). That way a subagent surfaces
119
+ // as its own entry in the sessions list.
120
+ //
121
+ // LangChain quirk (handled below): when an invoke runs nested inside
122
+ // a parent's call (e.g. the tool body invokes a subagent), LangChain
123
+ // inherits the parent's ``metadata.thread_id`` into the child run's
124
+ // metadata — even when the child config supplied its own. Treat that
125
+ // inheritance as "no thread_id" and assign a fresh UUID.
126
+ //
127
+ // For the struct.agent.parent_session_id attribute, we need the
128
+ // NEAREST agent ancestor's session — not just the immediate parent
129
+ // run, which might be a tool span. That's what
130
+ // ``inheritedAgentSessionId`` walks.
131
+ const parentAgentSessionId = this.inheritedAgentSessionId(parentRunId);
132
+ const sessionId = this.resolveAgentSessionId(metadata, parentAgentSessionId);
133
+ if (process.env.STRUCT_SDK_DEBUG === "1") {
134
+ // eslint-disable-next-line no-console
135
+ console.error("[struct-sdk] agent-start", agentName, "metadata.thread_id=", metadata?.thread_id, "parent.agent.session=", parentAgentSessionId, "→ resolved session=", sessionId);
136
+ }
137
+ const { parentSpan, parentSpanIsAgent } = this.resolveParent(parentRunId);
138
+ void parentSpanIsAgent;
139
+ const parentCtx = parentSpan
140
+ ? api_1.trace.setSpan(api_1.context.active(), parentSpan)
141
+ : api_1.context.active();
142
+ // Span creation can fail (custom tracer / broken context). Skip
143
+ // run-state insertion when it does — end/error callbacks already
144
+ // tolerate missing run state via the early `_runs.get(...) === undefined`
145
+ // short-circuit at the top of each method.
146
+ let span;
147
+ (0, core_js_1.safe)(() => {
148
+ span = this.tracer.startSpan(`invoke_agent ${agentName}`, { kind: api_1.SpanKind.INTERNAL }, parentCtx);
149
+ }, "langchain.handleChainStart.create_span", this.internalLogger);
150
+ if (span === undefined)
151
+ return;
152
+ const startedSpan = span;
153
+ (0, core_js_1.safe)(() => {
154
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.OPERATION_NAME, "invoke_agent");
155
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.PROVIDER_NAME, "langchain");
156
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.AGENT_NAME, String(agentName));
157
+ // Do NOT set gen_ai.agent.id from sessionId — that conflates agent
158
+ // identity (spec: stable agent-definition id) with a per-invocation
159
+ // session. LangChain doesn't surface a stable agent-id to us, so we
160
+ // leave the attribute unset. Callers who use struct.agent() directly
161
+ // can pass their own agentId via the scope options.
162
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.CONVERSATION_ID, sessionId);
163
+ // Link subagents back to the parent agent's session. Use the nearest
164
+ // agent ancestor (NOT the immediate parent run) — a subagent spawned
165
+ // from inside a tool has the tool as its immediate parent, but we want
166
+ // to point at the outer agent's session.
167
+ if (parentAgentSessionId && parentAgentSessionId !== sessionId) {
168
+ startedSpan.setAttribute(semconv_js_1.STRUCT.AGENT_PARENT_SESSION_ID, parentAgentSessionId);
169
+ }
170
+ // User prompt propagation — set gen_ai.input.messages on the agent
171
+ // span so the waterfall UI shows the question without drilling into
172
+ // chat spans.
173
+ if (this.sdk.emitSpanContent) {
174
+ const messages = extractChainInputMessages(inputs);
175
+ if (messages && messages.length > 0) {
176
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.INPUT_MESSAGES, (0, langchain_content_js_1.langchainToInputMessages)(messages));
177
+ }
178
+ }
179
+ }, "langchain.handleChainStart.set_attrs", this.internalLogger);
180
+ this.runs.set(runId, {
181
+ span: startedSpan,
182
+ effectiveParentSpan: startedSpan,
183
+ sessionId,
184
+ // This agent IS itself the nearest agent ancestor for everything nested inside.
185
+ nearestAgentSessionId: sessionId,
186
+ kind: "chain",
187
+ });
188
+ };
189
+ handleChainEnd = (_outputs, runId) => {
190
+ const r = this.runs.get(runId);
191
+ this.runs.delete(runId);
192
+ if (!r || !r.span)
193
+ return;
194
+ const span = r.span;
195
+ (0, core_js_1.safe)(() => span.setStatus({ code: api_1.SpanStatusCode.OK }), "langchain.handleChainEnd.set_status", this.internalLogger);
196
+ (0, core_js_1.safe)(() => span.end(), "langchain.handleChainEnd.span_end", this.internalLogger);
197
+ };
198
+ handleChainError = (err, runId) => {
199
+ const r = this.runs.get(runId);
200
+ this.runs.delete(runId);
201
+ if (!r || !r.span)
202
+ return;
203
+ const span = r.span;
204
+ (0, core_js_1.safe)(() => recordError(span, err), "langchain.handleChainError.record_error", this.internalLogger);
205
+ (0, core_js_1.safe)(() => span.end(), "langchain.handleChainError.span_end", this.internalLogger);
206
+ };
207
+ // ─── LLM / Chat model ────────────────────────────────────────────────────
208
+ handleChatModelStart = (llm, messages, runId, parentRunId, extraParams, _tags, metadata, runName) => {
209
+ const provider = detectProviderFromSerialized(llm);
210
+ // Note: we emit a chat span from the callback handler even when a
211
+ // provider-direct SDK monkey-patch is also active. The two integration
212
+ // layers often run against different @anthropic-ai/sdk instances due to
213
+ // pnpm hoisting; skipping here would silently drop the only chat span.
214
+ // Duplicate-span de-dup is done server-side if ever needed.
215
+ const model = extractParam(extraParams, "model") ??
216
+ extractParam(extraParams?.invocation_params, "model") ??
217
+ extractParam(extraParams?.invocation_params, "modelName") ??
218
+ runName ??
219
+ "unknown";
220
+ const { parentSpan } = this.resolveParent(parentRunId);
221
+ const parentCtx = parentSpan
222
+ ? api_1.trace.setSpan(api_1.context.active(), parentSpan)
223
+ : api_1.context.active();
224
+ let span;
225
+ (0, core_js_1.safe)(() => {
226
+ span = this.tracer.startSpan(`chat ${model}`, { kind: api_1.SpanKind.CLIENT }, parentCtx);
227
+ }, "langchain.handleChatModelStart.create_span", this.internalLogger);
228
+ if (span === undefined)
229
+ return;
230
+ const startedSpan = span;
231
+ const sessionId = this.resolveSessionId(parentRunId, metadata);
232
+ (0, core_js_1.safe)(() => {
233
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.OPERATION_NAME, "chat");
234
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.PROVIDER_NAME, provider);
235
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.REQUEST_MODEL, String(model));
236
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.CONVERSATION_ID, sessionId);
237
+ setRequestAttrsFromInvocation(startedSpan, extraParams?.invocation_params);
238
+ const flat = messages.flat();
239
+ if (flat.length > 0) {
240
+ startedSpan.setAttribute(semconv_js_1.STRUCT.INPUT_MESSAGE_COUNT, flat.length);
241
+ if (this.sdk.emitEvents && this.logger) {
242
+ emitMessageEvents(this.logger, flat, provider, sessionId, startedSpan);
243
+ }
244
+ if (this.sdk.emitSpanContent) {
245
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.INPUT_MESSAGES, (0, langchain_content_js_1.langchainToInputMessages)(flat));
246
+ }
247
+ // Propagate the most recent user message onto the nearest agent span.
248
+ const ancestorAgentSpan = this.resolveParent(parentRunId).parentSpan ?? (0, context_js_1.getAgentSpan)();
249
+ if (ancestorAgentSpan)
250
+ this.propagateUserPrompt(ancestorAgentSpan, flat);
251
+ }
252
+ }, "langchain.handleChatModelStart.set_attrs", this.internalLogger);
253
+ this.runs.set(runId, {
254
+ span: startedSpan,
255
+ effectiveParentSpan: startedSpan,
256
+ sessionId,
257
+ nearestAgentSessionId: this.inheritedAgentSessionId(parentRunId),
258
+ kind: "llm",
259
+ });
260
+ };
261
+ handleLLMStart = (llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) => {
262
+ // Treat completion-style LLMs as chat with a single user message.
263
+ const messages = prompts.map((p) => [
264
+ { _getType: () => "human", content: p },
265
+ ]);
266
+ this.handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName);
267
+ };
268
+ handleLLMEnd = (output, runId) => {
269
+ const r = this.runs.get(runId);
270
+ this.runs.delete(runId);
271
+ if (!r || !r.span)
272
+ return;
273
+ const span = r.span;
274
+ const sessionId = r.sessionId;
275
+ (0, core_js_1.safe)(() => {
276
+ const gen = output.generations?.[0]?.[0];
277
+ const message = gen?.message;
278
+ if (!message)
279
+ return;
280
+ setLlmResponseAttrs(span, this.sdk, this.logger, message, span.attributes?.[semconv_js_1.GEN_AI.PROVIDER_NAME], sessionId);
281
+ }, "langchain.handleLLMEnd.set_response_attrs", this.internalLogger);
282
+ (0, core_js_1.safe)(() => {
283
+ const gen = output.generations?.[0]?.[0];
284
+ const message = gen?.message;
285
+ if (!message)
286
+ return;
287
+ // Bridge tool_calls into the pending queue so @struct.tool() can autofill.
288
+ const toolCalls = message.tool_calls;
289
+ if (!Array.isArray(toolCalls) || toolCalls.length === 0)
290
+ return;
291
+ const pairs = [];
292
+ for (const tc of toolCalls) {
293
+ if (tc && typeof tc === "object") {
294
+ const n = tc.name;
295
+ const id = tc.id;
296
+ if (typeof n === "string" && typeof id === "string" && n && id) {
297
+ pairs.push([n, id]);
298
+ }
299
+ }
300
+ }
301
+ if (pairs.length > 0)
302
+ (0, context_js_1.pushPendingToolCalls)(pairs);
303
+ }, "langchain.handleLLMEnd.record_pending_tool_calls", this.internalLogger);
304
+ (0, core_js_1.safe)(() => span.setStatus({ code: api_1.SpanStatusCode.OK }), "langchain.handleLLMEnd.set_status", this.internalLogger);
305
+ (0, core_js_1.safe)(() => span.end(), "langchain.handleLLMEnd.span_end", this.internalLogger);
306
+ };
307
+ handleLLMError = (err, runId) => {
308
+ const r = this.runs.get(runId);
309
+ this.runs.delete(runId);
310
+ if (!r || !r.span)
311
+ return;
312
+ const span = r.span;
313
+ (0, core_js_1.safe)(() => recordError(span, err), "langchain.handleLLMError.record_error", this.internalLogger);
314
+ (0, core_js_1.safe)(() => span.end(), "langchain.handleLLMError.span_end", this.internalLogger);
315
+ };
316
+ // ─── Tool ────────────────────────────────────────────────────────────────
317
+ handleToolStart = (tool, input, runId, parentRunId, _tags, metadata, runName) => {
318
+ const toolName = runName ??
319
+ (typeof tool === "object" && tool?.name) ??
320
+ extractClassName(tool) ??
321
+ "tool";
322
+ const { parentSpan } = this.resolveParent(parentRunId);
323
+ const parentCtx = parentSpan
324
+ ? api_1.trace.setSpan(api_1.context.active(), parentSpan)
325
+ : api_1.context.active();
326
+ let span;
327
+ (0, core_js_1.safe)(() => {
328
+ span = this.tracer.startSpan(`execute_tool ${toolName}`, { kind: api_1.SpanKind.INTERNAL }, parentCtx);
329
+ }, "langchain.handleToolStart.create_span", this.internalLogger);
330
+ if (span === undefined)
331
+ return;
332
+ const startedSpan = span;
333
+ const sessionId = this.resolveSessionId(parentRunId, metadata);
334
+ (0, core_js_1.safe)(() => {
335
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.OPERATION_NAME, "execute_tool");
336
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.PROVIDER_NAME, "langchain");
337
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.TOOL_NAME, String(toolName));
338
+ // Tool call id from metadata (LangChain passes it there for ToolCall inputs)
339
+ // or fallback to the pending queue populated by the LLM's tool_calls.
340
+ const callId = metadata?.tool_call_id ??
341
+ extractToolCallIdFromInput(input) ??
342
+ (0, context_js_1.popPendingToolCallId)(String(toolName));
343
+ if (callId)
344
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.TOOL_CALL_ID, callId);
345
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.CONVERSATION_ID, sessionId);
346
+ if (this.sdk.captureContent && input !== undefined) {
347
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.TOOL_CALL_ARGUMENTS, (0, truncation_js_1.safeJsonStringify)(input).slice(0, 8192));
348
+ }
349
+ }, "langchain.handleToolStart.set_attrs", this.internalLogger);
350
+ this.runs.set(runId, {
351
+ span: startedSpan,
352
+ effectiveParentSpan: startedSpan,
353
+ sessionId,
354
+ nearestAgentSessionId: this.inheritedAgentSessionId(parentRunId),
355
+ kind: "tool",
356
+ });
357
+ };
358
+ handleToolEnd = (output, runId) => {
359
+ const r = this.runs.get(runId);
360
+ this.runs.delete(runId);
361
+ if (!r || !r.span)
362
+ return;
363
+ const span = r.span;
364
+ (0, core_js_1.safe)(() => {
365
+ if (this.sdk.captureContent && output != null) {
366
+ span.setAttribute(semconv_js_1.GEN_AI.TOOL_CALL_RESULT, (0, truncation_js_1.safeJsonStringify)(output).slice(0, 8192));
367
+ }
368
+ }, "langchain.handleToolEnd.set_result", this.internalLogger);
369
+ (0, core_js_1.safe)(() => span.setStatus({ code: api_1.SpanStatusCode.OK }), "langchain.handleToolEnd.set_status", this.internalLogger);
370
+ (0, core_js_1.safe)(() => span.end(), "langchain.handleToolEnd.span_end", this.internalLogger);
371
+ };
372
+ handleToolError = (err, runId) => {
373
+ const r = this.runs.get(runId);
374
+ this.runs.delete(runId);
375
+ if (!r || !r.span)
376
+ return;
377
+ const span = r.span;
378
+ (0, core_js_1.safe)(() => recordError(span, err), "langchain.handleToolError.record_error", this.internalLogger);
379
+ (0, core_js_1.safe)(() => span.end(), "langchain.handleToolError.span_end", this.internalLogger);
380
+ };
381
+ // ─── Retriever ───────────────────────────────────────────────────────────
382
+ handleRetrieverStart = (retriever, query, runId, parentRunId, _tags, metadata, runName) => {
383
+ const name = runName ??
384
+ retriever?.name ??
385
+ extractClassName(retriever) ??
386
+ "retriever";
387
+ const { parentSpan } = this.resolveParent(parentRunId);
388
+ const parentCtx = parentSpan
389
+ ? api_1.trace.setSpan(api_1.context.active(), parentSpan)
390
+ : api_1.context.active();
391
+ let span;
392
+ (0, core_js_1.safe)(() => {
393
+ span = this.tracer.startSpan(`retrieval ${name}`, { kind: api_1.SpanKind.INTERNAL }, parentCtx);
394
+ }, "langchain.handleRetrieverStart.create_span", this.internalLogger);
395
+ if (span === undefined)
396
+ return;
397
+ const startedSpan = span;
398
+ const sessionId = this.resolveSessionId(parentRunId, metadata);
399
+ (0, core_js_1.safe)(() => {
400
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.OPERATION_NAME, "retrieval");
401
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.PROVIDER_NAME, "langchain");
402
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.DATA_SOURCE_ID, String(name));
403
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.CONVERSATION_ID, sessionId);
404
+ if (this.sdk.captureContent && typeof query === "string") {
405
+ startedSpan.setAttribute(semconv_js_1.GEN_AI.RETRIEVAL_QUERY_TEXT, query.slice(0, 4096));
406
+ }
407
+ }, "langchain.handleRetrieverStart.set_attrs", this.internalLogger);
408
+ this.runs.set(runId, {
409
+ span: startedSpan,
410
+ effectiveParentSpan: startedSpan,
411
+ sessionId,
412
+ nearestAgentSessionId: this.inheritedAgentSessionId(parentRunId),
413
+ kind: "retriever",
414
+ });
415
+ };
416
+ handleRetrieverEnd = (documents, runId) => {
417
+ const r = this.runs.get(runId);
418
+ this.runs.delete(runId);
419
+ if (!r || !r.span)
420
+ return;
421
+ const span = r.span;
422
+ (0, core_js_1.safe)(() => {
423
+ if (Array.isArray(documents)) {
424
+ span.setAttribute(semconv_js_1.GEN_AI.RETRIEVAL_DOCUMENTS, documents.length);
425
+ }
426
+ }, "langchain.handleRetrieverEnd.set_doc_count", this.internalLogger);
427
+ (0, core_js_1.safe)(() => span.setStatus({ code: api_1.SpanStatusCode.OK }), "langchain.handleRetrieverEnd.set_status", this.internalLogger);
428
+ (0, core_js_1.safe)(() => span.end(), "langchain.handleRetrieverEnd.span_end", this.internalLogger);
429
+ };
430
+ handleRetrieverError = (err, runId) => {
431
+ const r = this.runs.get(runId);
432
+ this.runs.delete(runId);
433
+ if (!r || !r.span)
434
+ return;
435
+ const span = r.span;
436
+ (0, core_js_1.safe)(() => recordError(span, err), "langchain.handleRetrieverError.record_error", this.internalLogger);
437
+ (0, core_js_1.safe)(() => span.end(), "langchain.handleRetrieverError.span_end", this.internalLogger);
438
+ };
439
+ // ─── Internals ───────────────────────────────────────────────────────────
440
+ resolveParent(parentRunId) {
441
+ if (parentRunId) {
442
+ const p = this.runs.get(parentRunId);
443
+ if (p) {
444
+ // Use the effective parent span, which correctly skips over
445
+ // filtered chains (RunnableSequence, ChannelWrite, ...).
446
+ return {
447
+ parentSpan: p.effectiveParentSpan,
448
+ parentSpanIsAgent: p.kind === "chain",
449
+ };
450
+ }
451
+ }
452
+ return { parentSpan: (0, context_js_1.getAgentSpan)(), parentSpanIsAgent: true };
453
+ }
454
+ /**
455
+ * Conversation-id resolution for chat/tool/retriever spans — INHERIT from
456
+ * the parent agent so everything rolls up under one gen_ai.conversation.id.
457
+ */
458
+ resolveSessionId(parentRunId, metadata) {
459
+ if (parentRunId) {
460
+ const p = this.runs.get(parentRunId);
461
+ if (p?.sessionId)
462
+ return p.sessionId;
463
+ }
464
+ const threadId = metadata?.thread_id;
465
+ if (typeof threadId === "string" && threadId.length > 0)
466
+ return threadId;
467
+ const ambient = (0, context_js_1.getSessionId)();
468
+ if (ambient)
469
+ return ambient;
470
+ return (0, node_crypto_1.randomUUID)();
471
+ }
472
+ /**
473
+ * Walk the run tree to find the nearest ``invoke_agent`` ancestor's
474
+ * gen_ai.conversation.id.
475
+ *
476
+ * The immediate ``parentRunId`` might be a tool, LLM, retriever, or a
477
+ * filtered RunnableSequence — none of which are agents themselves. We
478
+ * populate ``nearestAgentSessionId`` at each run's creation so any
479
+ * descendant can read it in O(1).
480
+ *
481
+ * Used to set ``struct.agent.parent_session_id`` on nested ``invoke_agent``
482
+ * spans (our UI's "Spawned by" / "Subagents" linkage).
483
+ */
484
+ inheritedAgentSessionId(parentRunId) {
485
+ if (!parentRunId)
486
+ return undefined;
487
+ return this.runs.get(parentRunId)?.nearestAgentSessionId;
488
+ }
489
+ /**
490
+ * Conversation-id resolution for AGENT spans — each agent invocation gets
491
+ * its own gen_ai.conversation.id. We deliberately do NOT inherit from the
492
+ * parent run, so subagents surface as separate entries in the sessions
493
+ * list. Parent linkage is preserved via `struct.agent.parent_session_id`.
494
+ *
495
+ * LangChain inherits `metadata.thread_id` from the parent invoke's config
496
+ * when a nested invoke runs inside it (even if the child config supplied
497
+ * its own). We detect that inheritance by comparing against the parent's
498
+ * resolved session and ignore the inherited value.
499
+ */
500
+ resolveAgentSessionId(metadata, parentSessionId) {
501
+ const threadId = metadata?.thread_id;
502
+ if (typeof threadId === "string" && threadId.length > 0) {
503
+ if (parentSessionId && threadId === parentSessionId) {
504
+ // Inherited from parent — treat as unset, assign fresh.
505
+ return (0, node_crypto_1.randomUUID)();
506
+ }
507
+ return threadId;
508
+ }
509
+ const ambient = (0, context_js_1.getSessionId)();
510
+ if (ambient)
511
+ return ambient;
512
+ return (0, node_crypto_1.randomUUID)();
513
+ }
514
+ propagateUserPrompt(parentSpan, messages) {
515
+ try {
516
+ const attrs = parentSpan
517
+ .attributes;
518
+ if (attrs && attrs[semconv_js_1.GEN_AI.INPUT_MESSAGES])
519
+ return;
520
+ const parts = (0, langchain_content_js_1.lastUserMessageParts)(messages);
521
+ if (!parts)
522
+ return;
523
+ parentSpan.setAttribute(semconv_js_1.GEN_AI.INPUT_MESSAGES, (0, truncation_js_1.truncateAndSerialize)([{ role: "user", parts }]));
524
+ }
525
+ catch {
526
+ /* never fail telemetry */
527
+ }
528
+ }
529
+ }
530
+ exports.StructCallbackHandler = StructCallbackHandler;
531
+ // ─── helpers ─────────────────────────────────────────────────────────────────
532
+ /**
533
+ * Only promote explicit agent classes to `invoke_agent`. LangGraph fires
534
+ * chain-start for every internal node (`ChannelWrite`, `Branch`, `prompt`,
535
+ * `tools`, `__start__`, etc.); those are plumbing, not user-meaningful
536
+ * agent invocations, so we drop them to avoid flooding the waterfall.
537
+ *
538
+ * Users of non-standard agent frameworks can opt in by setting
539
+ * `runType: "agent"` in the Runnable config.
540
+ */
541
+ const AGENT_CLASSES = new Set([
542
+ "AgentExecutor",
543
+ "CompiledStateGraph",
544
+ "CompiledGraph",
545
+ "Pregel",
546
+ "LangGraph",
547
+ ]);
548
+ function isAgentChain(chain, runType, _runName) {
549
+ if (runType === "agent")
550
+ return true;
551
+ const cls = extractClassName(chain);
552
+ return !!cls && AGENT_CLASSES.has(cls);
553
+ }
554
+ function extractClassName(obj) {
555
+ if (!obj)
556
+ return undefined;
557
+ if (Array.isArray(obj.id) && obj.id.length > 0) {
558
+ const last = obj.id[obj.id.length - 1];
559
+ if (typeof last === "string")
560
+ return last;
561
+ }
562
+ if (typeof obj.name === "string")
563
+ return obj.name;
564
+ return undefined;
565
+ }
566
+ function detectProviderFromSerialized(llm) {
567
+ const cls = extractClassName(llm) ?? "";
568
+ const fake = { constructor: { name: cls }, _llmType: undefined };
569
+ return (0, langchain_content_js_1.detectProvider)(fake);
570
+ }
571
+ function extractParam(obj, key) {
572
+ if (!obj || typeof obj !== "object")
573
+ return undefined;
574
+ const v = obj[key];
575
+ return typeof v === "string" && v.length > 0 ? v : undefined;
576
+ }
577
+ function setRequestAttrsFromInvocation(span, invocation) {
578
+ if (!invocation || typeof invocation !== "object")
579
+ return;
580
+ const m = invocation;
581
+ const mapping = [
582
+ ["temperature", semconv_js_1.GEN_AI.REQUEST_TEMPERATURE],
583
+ ["maxTokens", semconv_js_1.GEN_AI.REQUEST_MAX_TOKENS],
584
+ ["max_tokens", semconv_js_1.GEN_AI.REQUEST_MAX_TOKENS],
585
+ ["topP", semconv_js_1.GEN_AI.REQUEST_TOP_P],
586
+ ["top_p", semconv_js_1.GEN_AI.REQUEST_TOP_P],
587
+ ["topK", semconv_js_1.GEN_AI.REQUEST_TOP_K],
588
+ ["top_k", semconv_js_1.GEN_AI.REQUEST_TOP_K],
589
+ ["frequencyPenalty", semconv_js_1.GEN_AI.REQUEST_FREQUENCY_PENALTY],
590
+ ["presencePenalty", semconv_js_1.GEN_AI.REQUEST_PRESENCE_PENALTY],
591
+ ];
592
+ for (const [src, dst] of mapping) {
593
+ const v = m[src];
594
+ if (typeof v === "number")
595
+ span.setAttribute(dst, v);
596
+ }
597
+ const stop = m.stop ?? m.stopSequences ?? m.stop_sequences;
598
+ if (Array.isArray(stop) && stop.length > 0) {
599
+ span.setAttribute(semconv_js_1.GEN_AI.REQUEST_STOP_SEQUENCES, stop);
600
+ }
601
+ }
602
+ function setLlmResponseAttrs(span, sdk, logger, message, provider, sessionId) {
603
+ if (!message || typeof message !== "object")
604
+ return;
605
+ const m = message;
606
+ const usage = m.usage_metadata;
607
+ if (usage) {
608
+ if (typeof usage.input_tokens === "number")
609
+ span.setAttribute(semconv_js_1.GEN_AI.USAGE_INPUT_TOKENS, usage.input_tokens);
610
+ if (typeof usage.output_tokens === "number")
611
+ span.setAttribute(semconv_js_1.GEN_AI.USAGE_OUTPUT_TOKENS, usage.output_tokens);
612
+ const cr = usage.input_token_details?.cache_read;
613
+ const cc = usage.input_token_details?.cache_creation;
614
+ if (typeof cr === "number" && cr > 0)
615
+ span.setAttribute(semconv_js_1.GEN_AI.USAGE_CACHE_READ_INPUT_TOKENS, cr);
616
+ if (typeof cc === "number" && cc > 0)
617
+ span.setAttribute(semconv_js_1.GEN_AI.USAGE_CACHE_CREATION_INPUT_TOKENS, cc);
618
+ }
619
+ const respMeta = m.response_metadata ?? {};
620
+ const respModel = (typeof respMeta.model_name === "string" && respMeta.model_name) ||
621
+ (typeof respMeta.model === "string" && respMeta.model) ||
622
+ null;
623
+ if (respModel)
624
+ span.setAttribute(semconv_js_1.GEN_AI.RESPONSE_MODEL, respModel);
625
+ const finish = (typeof respMeta.finish_reason === "string" && respMeta.finish_reason) ||
626
+ (typeof respMeta.stop_reason === "string" && respMeta.stop_reason) ||
627
+ null;
628
+ if (finish) {
629
+ const mapped = semconv_js_1.LANGCHAIN_FINISH_REASON_MAP[finish] ?? finish;
630
+ span.setAttribute(semconv_js_1.GEN_AI.RESPONSE_FINISH_REASONS, [mapped]);
631
+ }
632
+ const respId = (typeof m.id === "string" && m.id) ||
633
+ (typeof respMeta.id === "string" && respMeta.id) ||
634
+ null;
635
+ if (respId)
636
+ span.setAttribute(semconv_js_1.GEN_AI.RESPONSE_ID, respId);
637
+ if (sdk.emitEvents && logger) {
638
+ emitChoiceEvent(logger, message, provider ?? "langchain", sessionId, span);
639
+ }
640
+ if (sdk.emitSpanContent) {
641
+ span.setAttribute(semconv_js_1.GEN_AI.OUTPUT_MESSAGES, (0, langchain_content_js_1.langchainToOutputMessages)(message));
642
+ }
643
+ }
644
+ // OTel logs convention for our emitted log events:
645
+ // - Body column = event tag string (human-readable signal)
646
+ // - LogAttributes["body"] = JSON-serialised structured payload
647
+ // Both emitMessageEvents and emitChoiceEvent bypass the central emitLogRecord
648
+ // helper in events.ts because they need to bind a specific span context (the
649
+ // callback handler creates spans directly and doesn't enter them with
650
+ // context.with). The flip is inlined at both sites.
651
+ function emitMessageEvents(logger, messages, provider, sessionId, span) {
652
+ // Bind the log record's context to the chat span so the exported LogRecord
653
+ // carries non-zero TraceId/SpanId. Using `otelContext.active()` here would
654
+ // only work if the caller had entered `context.with(spanCtx, ...)` first —
655
+ // the LangChain callback handler doesn't (it creates the span directly).
656
+ const logCtx = api_1.trace.setSpan(api_1.context.active(), span);
657
+ for (let i = 0; i < messages.length; i++) {
658
+ const { role, parts } = (0, langchain_content_js_1.langchainMessageToRoleAndParts)(messages[i]);
659
+ const eventName = semconv_js_1.ROLE_TO_EVENT_NAME[role] ?? `gen_ai.${role}.message`;
660
+ const payload = (0, truncation_js_1.safeJsonStringify)({ role, parts: (0, truncation_js_1.truncateParts)(parts) });
661
+ logger.emit({
662
+ body: eventName,
663
+ context: logCtx,
664
+ attributes: {
665
+ [semconv_js_1.EVENT_NAME]: eventName,
666
+ body: payload,
667
+ [semconv_js_1.GEN_AI.SYSTEM]: provider,
668
+ [semconv_js_1.GEN_AI.MESSAGE_INDEX]: i,
669
+ [semconv_js_1.GEN_AI.CONVERSATION_ID]: sessionId,
670
+ },
671
+ });
672
+ }
673
+ }
674
+ function emitChoiceEvent(logger, message, provider, sessionId, span) {
675
+ const { parts } = (0, langchain_content_js_1.langchainMessageToRoleAndParts)(message);
676
+ const respMeta = (message && typeof message === "object"
677
+ ? message.response_metadata
678
+ : undefined) ?? {};
679
+ const finish = (typeof respMeta.finish_reason === "string" && respMeta.finish_reason) ||
680
+ (typeof respMeta.stop_reason === "string" && respMeta.stop_reason) ||
681
+ "stop";
682
+ const mapped = semconv_js_1.LANGCHAIN_FINISH_REASON_MAP[finish] ?? finish;
683
+ const payload = (0, truncation_js_1.safeJsonStringify)({
684
+ index: 0,
685
+ finish_reason: mapped,
686
+ message: { role: "assistant", parts: (0, truncation_js_1.truncateParts)(parts) },
687
+ });
688
+ logger.emit({
689
+ body: semconv_js_1.EVENT_NAMES.CHOICE,
690
+ context: api_1.trace.setSpan(api_1.context.active(), span),
691
+ attributes: {
692
+ [semconv_js_1.EVENT_NAME]: semconv_js_1.EVENT_NAMES.CHOICE,
693
+ body: payload,
694
+ [semconv_js_1.GEN_AI.SYSTEM]: provider,
695
+ [semconv_js_1.GEN_AI.CONVERSATION_ID]: sessionId,
696
+ },
697
+ });
698
+ }
699
+ function extractChainInputMessages(inputs) {
700
+ if (!inputs || typeof inputs !== "object")
701
+ return undefined;
702
+ const msgs = inputs.messages;
703
+ if (Array.isArray(msgs))
704
+ return msgs;
705
+ return undefined;
706
+ }
707
+ function extractToolCallIdFromInput(input) {
708
+ if (input && typeof input === "object" && !Array.isArray(input)) {
709
+ const id = input.id;
710
+ if (typeof id === "string" && id.length > 0)
711
+ return id;
712
+ }
713
+ return undefined;
714
+ }
715
+ function recordError(span, err) {
716
+ const errorType = err instanceof Error ? err.constructor.name : typeof err;
717
+ const message = err instanceof Error ? err.message : String(err);
718
+ span.setAttribute(semconv_js_1.ERROR_TYPE, errorType);
719
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message });
720
+ if (err instanceof Error)
721
+ span.recordException(err);
722
+ }
723
+ //# sourceMappingURL=langchain-callback.js.map