@langchain/core 1.1.5-dev-1765432861398 → 1.1.5

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 (276) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/agents.cjs +1 -0
  3. package/agents.d.cts +1 -0
  4. package/agents.d.ts +1 -0
  5. package/agents.js +1 -0
  6. package/caches.cjs +1 -0
  7. package/caches.d.cts +1 -0
  8. package/caches.d.ts +1 -0
  9. package/caches.js +1 -0
  10. package/callbacks/base.cjs +1 -0
  11. package/callbacks/base.d.cts +1 -0
  12. package/callbacks/base.d.ts +1 -0
  13. package/callbacks/base.js +1 -0
  14. package/callbacks/dispatch/web.cjs +1 -0
  15. package/callbacks/dispatch/web.d.cts +1 -0
  16. package/callbacks/dispatch/web.d.ts +1 -0
  17. package/callbacks/dispatch/web.js +1 -0
  18. package/callbacks/dispatch.cjs +1 -0
  19. package/callbacks/dispatch.d.cts +1 -0
  20. package/callbacks/dispatch.d.ts +1 -0
  21. package/callbacks/dispatch.js +1 -0
  22. package/callbacks/manager.cjs +1 -0
  23. package/callbacks/manager.d.cts +1 -0
  24. package/callbacks/manager.d.ts +1 -0
  25. package/callbacks/manager.js +1 -0
  26. package/callbacks/promises.cjs +1 -0
  27. package/callbacks/promises.d.cts +1 -0
  28. package/callbacks/promises.d.ts +1 -0
  29. package/callbacks/promises.js +1 -0
  30. package/chat_history.cjs +1 -0
  31. package/chat_history.d.cts +1 -0
  32. package/chat_history.d.ts +1 -0
  33. package/chat_history.js +1 -0
  34. package/context.cjs +1 -0
  35. package/context.d.cts +1 -0
  36. package/context.d.ts +1 -0
  37. package/context.js +1 -0
  38. package/dist/load/index.d.cts.map +1 -1
  39. package/dist/messages/format.cjs +1 -1
  40. package/dist/messages/format.cjs.map +1 -1
  41. package/dist/messages/format.js +1 -1
  42. package/dist/messages/format.js.map +1 -1
  43. package/dist/runnables/graph_mermaid.cjs +9 -3
  44. package/dist/runnables/graph_mermaid.cjs.map +1 -1
  45. package/dist/runnables/graph_mermaid.js +9 -3
  46. package/dist/runnables/graph_mermaid.js.map +1 -1
  47. package/dist/tracers/base.cjs +9 -10
  48. package/dist/tracers/base.cjs.map +1 -1
  49. package/dist/tracers/base.js +9 -10
  50. package/dist/tracers/base.js.map +1 -1
  51. package/dist/utils/fast-json-patch/src/core.cjs +10 -0
  52. package/dist/utils/fast-json-patch/src/core.cjs.map +1 -1
  53. package/dist/utils/fast-json-patch/src/core.js +10 -0
  54. package/dist/utils/fast-json-patch/src/core.js.map +1 -1
  55. package/dist/utils/json_schema.cjs +4 -3
  56. package/dist/utils/json_schema.cjs.map +1 -1
  57. package/dist/utils/json_schema.d.cts +5 -2
  58. package/dist/utils/json_schema.d.cts.map +1 -1
  59. package/dist/utils/json_schema.d.ts +5 -2
  60. package/dist/utils/json_schema.d.ts.map +1 -1
  61. package/dist/utils/json_schema.js +4 -3
  62. package/dist/utils/json_schema.js.map +1 -1
  63. package/dist/utils/testing/chat_models.cjs +45 -1
  64. package/dist/utils/testing/chat_models.cjs.map +1 -1
  65. package/dist/utils/testing/chat_models.d.cts +3 -0
  66. package/dist/utils/testing/chat_models.d.cts.map +1 -1
  67. package/dist/utils/testing/chat_models.d.ts +3 -0
  68. package/dist/utils/testing/chat_models.d.ts.map +1 -1
  69. package/dist/utils/testing/chat_models.js +45 -1
  70. package/dist/utils/testing/chat_models.js.map +1 -1
  71. package/dist/utils/types/zod.cjs +1 -1
  72. package/dist/utils/types/zod.cjs.map +1 -1
  73. package/dist/utils/types/zod.js +1 -1
  74. package/dist/utils/types/zod.js.map +1 -1
  75. package/dist/vectorstores.d.cts.map +1 -1
  76. package/document_loaders/base.cjs +1 -0
  77. package/document_loaders/base.d.cts +1 -0
  78. package/document_loaders/base.d.ts +1 -0
  79. package/document_loaders/base.js +1 -0
  80. package/document_loaders/langsmith.cjs +1 -0
  81. package/document_loaders/langsmith.d.cts +1 -0
  82. package/document_loaders/langsmith.d.ts +1 -0
  83. package/document_loaders/langsmith.js +1 -0
  84. package/documents.cjs +1 -0
  85. package/documents.d.cts +1 -0
  86. package/documents.d.ts +1 -0
  87. package/documents.js +1 -0
  88. package/embeddings.cjs +1 -0
  89. package/embeddings.d.cts +1 -0
  90. package/embeddings.d.ts +1 -0
  91. package/embeddings.js +1 -0
  92. package/example_selectors.cjs +1 -0
  93. package/example_selectors.d.cts +1 -0
  94. package/example_selectors.d.ts +1 -0
  95. package/example_selectors.js +1 -0
  96. package/indexing.cjs +1 -0
  97. package/indexing.d.cts +1 -0
  98. package/indexing.d.ts +1 -0
  99. package/indexing.js +1 -0
  100. package/language_models/base.cjs +1 -0
  101. package/language_models/base.d.cts +1 -0
  102. package/language_models/base.d.ts +1 -0
  103. package/language_models/base.js +1 -0
  104. package/language_models/chat_models.cjs +1 -0
  105. package/language_models/chat_models.d.cts +1 -0
  106. package/language_models/chat_models.d.ts +1 -0
  107. package/language_models/chat_models.js +1 -0
  108. package/language_models/llms.cjs +1 -0
  109. package/language_models/llms.d.cts +1 -0
  110. package/language_models/llms.d.ts +1 -0
  111. package/language_models/llms.js +1 -0
  112. package/language_models/profile.cjs +1 -0
  113. package/language_models/profile.d.cts +1 -0
  114. package/language_models/profile.d.ts +1 -0
  115. package/language_models/profile.js +1 -0
  116. package/load/serializable.cjs +1 -0
  117. package/load/serializable.d.cts +1 -0
  118. package/load/serializable.d.ts +1 -0
  119. package/load/serializable.js +1 -0
  120. package/load.cjs +1 -0
  121. package/load.d.cts +1 -0
  122. package/load.d.ts +1 -0
  123. package/load.js +1 -0
  124. package/memory.cjs +1 -0
  125. package/memory.d.cts +1 -0
  126. package/memory.d.ts +1 -0
  127. package/memory.js +1 -0
  128. package/messages/tool.cjs +1 -0
  129. package/messages/tool.d.cts +1 -0
  130. package/messages/tool.d.ts +1 -0
  131. package/messages/tool.js +1 -0
  132. package/messages.cjs +1 -0
  133. package/messages.d.cts +1 -0
  134. package/messages.d.ts +1 -0
  135. package/messages.js +1 -0
  136. package/output_parsers/openai_functions.cjs +1 -0
  137. package/output_parsers/openai_functions.d.cts +1 -0
  138. package/output_parsers/openai_functions.d.ts +1 -0
  139. package/output_parsers/openai_functions.js +1 -0
  140. package/output_parsers/openai_tools.cjs +1 -0
  141. package/output_parsers/openai_tools.d.cts +1 -0
  142. package/output_parsers/openai_tools.d.ts +1 -0
  143. package/output_parsers/openai_tools.js +1 -0
  144. package/output_parsers.cjs +1 -0
  145. package/output_parsers.d.cts +1 -0
  146. package/output_parsers.d.ts +1 -0
  147. package/output_parsers.js +1 -0
  148. package/outputs.cjs +1 -0
  149. package/outputs.d.cts +1 -0
  150. package/outputs.d.ts +1 -0
  151. package/outputs.js +1 -0
  152. package/package.json +1 -1
  153. package/prompt_values.cjs +1 -0
  154. package/prompt_values.d.cts +1 -0
  155. package/prompt_values.d.ts +1 -0
  156. package/prompt_values.js +1 -0
  157. package/prompts.cjs +1 -0
  158. package/prompts.d.cts +1 -0
  159. package/prompts.d.ts +1 -0
  160. package/prompts.js +1 -0
  161. package/retrievers/document_compressors.cjs +1 -0
  162. package/retrievers/document_compressors.d.cts +1 -0
  163. package/retrievers/document_compressors.d.ts +1 -0
  164. package/retrievers/document_compressors.js +1 -0
  165. package/retrievers.cjs +1 -0
  166. package/retrievers.d.cts +1 -0
  167. package/retrievers.d.ts +1 -0
  168. package/retrievers.js +1 -0
  169. package/runnables/graph.cjs +1 -0
  170. package/runnables/graph.d.cts +1 -0
  171. package/runnables/graph.d.ts +1 -0
  172. package/runnables/graph.js +1 -0
  173. package/runnables.cjs +1 -0
  174. package/runnables.d.cts +1 -0
  175. package/runnables.d.ts +1 -0
  176. package/runnables.js +1 -0
  177. package/singletons.cjs +1 -0
  178. package/singletons.d.cts +1 -0
  179. package/singletons.d.ts +1 -0
  180. package/singletons.js +1 -0
  181. package/stores.cjs +1 -0
  182. package/stores.d.cts +1 -0
  183. package/stores.d.ts +1 -0
  184. package/stores.js +1 -0
  185. package/structured_query.cjs +1 -0
  186. package/structured_query.d.cts +1 -0
  187. package/structured_query.d.ts +1 -0
  188. package/structured_query.js +1 -0
  189. package/tools.cjs +1 -0
  190. package/tools.d.cts +1 -0
  191. package/tools.d.ts +1 -0
  192. package/tools.js +1 -0
  193. package/tracers/base.cjs +1 -0
  194. package/tracers/base.d.cts +1 -0
  195. package/tracers/base.d.ts +1 -0
  196. package/tracers/base.js +1 -0
  197. package/tracers/console.cjs +1 -0
  198. package/tracers/console.d.cts +1 -0
  199. package/tracers/console.d.ts +1 -0
  200. package/tracers/console.js +1 -0
  201. package/tracers/log_stream.cjs +1 -0
  202. package/tracers/log_stream.d.cts +1 -0
  203. package/tracers/log_stream.d.ts +1 -0
  204. package/tracers/log_stream.js +1 -0
  205. package/tracers/run_collector.cjs +1 -0
  206. package/tracers/run_collector.d.cts +1 -0
  207. package/tracers/run_collector.d.ts +1 -0
  208. package/tracers/run_collector.js +1 -0
  209. package/tracers/tracer_langchain.cjs +1 -0
  210. package/tracers/tracer_langchain.d.cts +1 -0
  211. package/tracers/tracer_langchain.d.ts +1 -0
  212. package/tracers/tracer_langchain.js +1 -0
  213. package/types/stream.cjs +1 -0
  214. package/types/stream.d.cts +1 -0
  215. package/types/stream.d.ts +1 -0
  216. package/types/stream.js +1 -0
  217. package/utils/async_caller.cjs +1 -0
  218. package/utils/async_caller.d.cts +1 -0
  219. package/utils/async_caller.d.ts +1 -0
  220. package/utils/async_caller.js +1 -0
  221. package/utils/chunk_array.cjs +1 -0
  222. package/utils/chunk_array.d.cts +1 -0
  223. package/utils/chunk_array.d.ts +1 -0
  224. package/utils/chunk_array.js +1 -0
  225. package/utils/env.cjs +1 -0
  226. package/utils/env.d.cts +1 -0
  227. package/utils/env.d.ts +1 -0
  228. package/utils/env.js +1 -0
  229. package/utils/event_source_parse.cjs +1 -0
  230. package/utils/event_source_parse.d.cts +1 -0
  231. package/utils/event_source_parse.d.ts +1 -0
  232. package/utils/event_source_parse.js +1 -0
  233. package/utils/format.cjs +1 -0
  234. package/utils/format.d.cts +1 -0
  235. package/utils/format.d.ts +1 -0
  236. package/utils/format.js +1 -0
  237. package/utils/function_calling.cjs +1 -0
  238. package/utils/function_calling.d.cts +1 -0
  239. package/utils/function_calling.d.ts +1 -0
  240. package/utils/function_calling.js +1 -0
  241. package/utils/hash.cjs +1 -0
  242. package/utils/hash.d.cts +1 -0
  243. package/utils/hash.d.ts +1 -0
  244. package/utils/hash.js +1 -0
  245. package/utils/json_patch.cjs +1 -0
  246. package/utils/json_patch.d.cts +1 -0
  247. package/utils/json_patch.d.ts +1 -0
  248. package/utils/json_patch.js +1 -0
  249. package/utils/json_schema.cjs +1 -0
  250. package/utils/json_schema.d.cts +1 -0
  251. package/utils/json_schema.d.ts +1 -0
  252. package/utils/json_schema.js +1 -0
  253. package/utils/math.cjs +1 -0
  254. package/utils/math.d.cts +1 -0
  255. package/utils/math.d.ts +1 -0
  256. package/utils/math.js +1 -0
  257. package/utils/stream.cjs +1 -0
  258. package/utils/stream.d.cts +1 -0
  259. package/utils/stream.d.ts +1 -0
  260. package/utils/stream.js +1 -0
  261. package/utils/testing.cjs +1 -0
  262. package/utils/testing.d.cts +1 -0
  263. package/utils/testing.d.ts +1 -0
  264. package/utils/testing.js +1 -0
  265. package/utils/tiktoken.cjs +1 -0
  266. package/utils/tiktoken.d.cts +1 -0
  267. package/utils/tiktoken.d.ts +1 -0
  268. package/utils/tiktoken.js +1 -0
  269. package/utils/types.cjs +1 -0
  270. package/utils/types.d.cts +1 -0
  271. package/utils/types.d.ts +1 -0
  272. package/utils/types.js +1 -0
  273. package/vectorstores.cjs +1 -0
  274. package/vectorstores.d.cts +1 -0
  275. package/vectorstores.d.ts +1 -0
  276. package/vectorstores.js +1 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @langchain/core
2
2
 
3
+ ## 1.1.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [#9641](https://github.com/langchain-ai/langchainjs/pull/9641) [`005c729`](https://github.com/langchain-ai/langchainjs/commit/005c72903bcdf090e0f4c58960c8c243481f9874) Thanks [@christian-bromann](https://github.com/christian-bromann)! - fix(community/core): various security fixes
8
+
9
+ - [#7907](https://github.com/langchain-ai/langchainjs/pull/7907) [`ab78246`](https://github.com/langchain-ai/langchainjs/commit/ab782462753e6c3ae5d55c0c251f795af32929d5) Thanks [@jasonphillips](https://github.com/jasonphillips)! - fix(core): handle subgraph nesting better in graph_mermaid
10
+
11
+ - [#9589](https://github.com/langchain-ai/langchainjs/pull/9589) [`8cc81c7`](https://github.com/langchain-ai/langchainjs/commit/8cc81c7cee69530f7a6296c69123edbe227b2fce) Thanks [@nathannewyen](https://github.com/nathannewyen)! - test(core): add test for response_metadata in streamEvents
12
+
13
+ - [#9644](https://github.com/langchain-ai/langchainjs/pull/9644) [`f32e499`](https://github.com/langchain-ai/langchainjs/commit/f32e4991d0e707324e3f6af287a1ee87ab833b7e) Thanks [@hntrl](https://github.com/hntrl)! - add bindTools to FakeListChatModel
14
+
15
+ - [#9508](https://github.com/langchain-ai/langchainjs/pull/9508) [`a28d83d`](https://github.com/langchain-ai/langchainjs/commit/a28d83d49dd1fd31e67b52a44abc70f2cc2a2026) Thanks [@shubham-021](https://github.com/shubham-021)! - Fix toFormattedString() to properly display nested objects in tool call arguments instead of [object Object]
16
+
17
+ - [#9165](https://github.com/langchain-ai/langchainjs/pull/9165) [`2e5ad70`](https://github.com/langchain-ai/langchainjs/commit/2e5ad70d16c1f13eaaea95336bbe2ec4a4a4954a) Thanks [@pawel-twardziak](https://github.com/pawel-twardziak)! - fix(mcp-adapters): preserve timeout from RunnableConfig in MCP tool calls
18
+
19
+ - [#9647](https://github.com/langchain-ai/langchainjs/pull/9647) [`e456c66`](https://github.com/langchain-ai/langchainjs/commit/e456c661aa1ab8f1ed4a98c40616f5a13270e88e) Thanks [@hntrl](https://github.com/hntrl)! - handle missing parent runs in tracer to prevent LangSmith 400 errors
20
+
21
+ - [#9597](https://github.com/langchain-ai/langchainjs/pull/9597) [`1cfe603`](https://github.com/langchain-ai/langchainjs/commit/1cfe603e97d8711343ae5f1f5a75648e7bd2a16e) Thanks [@hntrl](https://github.com/hntrl)! - use uuid7 for run ids
22
+
3
23
  ## 1.1.4
4
24
 
5
25
  ### Patch Changes
package/agents.cjs ADDED
@@ -0,0 +1 @@
1
+ module.exports = require("./dist/agents.cjs");
package/agents.d.cts ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/agents.js";
package/agents.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/agents.js";
package/agents.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/agents.js";
package/caches.cjs ADDED
@@ -0,0 +1 @@
1
+ module.exports = require("./dist/caches/index.cjs");
package/caches.d.cts ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/caches/index.js";
package/caches.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/caches/index.js";
package/caches.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/caches/index.js";
@@ -0,0 +1 @@
1
+ module.exports = require("../dist/callbacks/base.cjs");
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/base.js";
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/base.js";
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/base.js";
@@ -0,0 +1 @@
1
+ module.exports = require("../../dist/callbacks/dispatch/web.cjs");
@@ -0,0 +1 @@
1
+ export * from "../../dist/callbacks/dispatch/web.js";
@@ -0,0 +1 @@
1
+ export * from "../../dist/callbacks/dispatch/web.js";
@@ -0,0 +1 @@
1
+ export * from "../../dist/callbacks/dispatch/web.js";
@@ -0,0 +1 @@
1
+ module.exports = require("../dist/callbacks/dispatch/index.cjs");
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/dispatch/index.js";
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/dispatch/index.js";
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/dispatch/index.js";
@@ -0,0 +1 @@
1
+ module.exports = require("../dist/callbacks/manager.cjs");
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/manager.js";
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/manager.js";
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/manager.js";
@@ -0,0 +1 @@
1
+ module.exports = require("../dist/callbacks/promises.cjs");
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/promises.js";
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/promises.js";
@@ -0,0 +1 @@
1
+ export * from "../dist/callbacks/promises.js";
@@ -0,0 +1 @@
1
+ module.exports = require("./dist/chat_history.cjs");
@@ -0,0 +1 @@
1
+ export * from "./dist/chat_history.js";
@@ -0,0 +1 @@
1
+ export * from "./dist/chat_history.js";
@@ -0,0 +1 @@
1
+ export * from "./dist/chat_history.js";
package/context.cjs ADDED
@@ -0,0 +1 @@
1
+ module.exports = require("./dist/context.cjs");
package/context.d.cts ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/context.js";
package/context.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/context.js";
package/context.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/context.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":["OptionalImportMap","SecretMap","load","T","Record","Promise"],"sources":["../../src/load/index.d.ts"],"sourcesContent":["import type { OptionalImportMap, SecretMap } from \"./import_type.js\";\nexport declare function load<T>(text: string, mappings?: {\n secretsMap?: SecretMap;\n optionalImportsMap?: OptionalImportMap;\n optionalImportEntrypoints?: string[];\n importMap?: Record<string, unknown>;\n}): Promise<T>;\n//# sourceMappingURL=index.d.ts.map"],"mappings":";;;iBACwBE,8BAIRE;eAHCH;EADOC,kBAAIC,CAAAA,EAEHH,iBAFG;EACXC,yBAAAA,CAAAA,EAAAA,MAAAA,EAAAA;EACQD,SAAAA,CAAAA,EAETI,MAFSJ,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA;CAETI,CAAAA,EACZC,OADYD,CACJD,CADIC,CAAAA"}
1
+ {"version":3,"file":"index.d.cts","names":["OptionalImportMap","SecretMap","load","T","Record","Promise"],"sources":["../../src/load/index.d.ts"],"sourcesContent":["import type { OptionalImportMap, SecretMap } from \"./import_type.js\";\nexport declare function load<T>(text: string, mappings?: {\n secretsMap?: SecretMap;\n optionalImportsMap?: OptionalImportMap;\n optionalImportEntrypoints?: string[];\n importMap?: Record<string, unknown>;\n}): Promise<T>;\n//# sourceMappingURL=index.d.ts.map"],"mappings":";;;iBACwBE,8BAIRE;eAHCH;EADOC,kBAAIC,CAAA,EAEHH,iBAFG;EACXC,yBAAAA,CAAAA,EAAAA,MAAAA,EAAAA;EACQD,SAAAA,CAAAA,EAETI,MAFSJ,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA;CAETI,CAAAA,EACZC,OADYD,CACJD,CADIC,CAAAA"}
@@ -19,7 +19,7 @@ function convertToPrettyString(message) {
19
19
  lines.push(` ${tc.name} (${tc.id})`);
20
20
  lines.push(` Call ID: ${tc.id}`);
21
21
  lines.push(" Args:");
22
- for (const [key, value] of Object.entries(tc.args)) lines.push(` ${key}: ${value}`);
22
+ for (const [key, value] of Object.entries(tc.args)) lines.push(` ${key}: ${typeof value === "object" ? JSON.stringify(value) : value}`);
23
23
  }
24
24
  }
25
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"format.cjs","names":["message: BaseMessage","format: MessageStringFormat","lines: string[]"],"sources":["../../src/messages/format.ts"],"sourcesContent":["import { type BaseMessage } from \"./base.js\";\nimport { type AIMessage } from \"./ai.js\";\nimport { type ToolMessage } from \"./tool.js\";\n\nexport type MessageStringFormat = \"pretty\";\n\nexport function convertToFormattedString(\n message: BaseMessage,\n format: MessageStringFormat = \"pretty\"\n): string {\n if (format === \"pretty\") return convertToPrettyString(message);\n return JSON.stringify(message);\n}\n\nfunction convertToPrettyString(message: BaseMessage): string {\n const lines: string[] = [];\n const title = ` ${\n message.type.charAt(0).toUpperCase() + message.type.slice(1)\n } Message `;\n const sepLen = Math.floor((80 - title.length) / 2);\n const sep = \"=\".repeat(sepLen);\n const secondSep = title.length % 2 === 0 ? sep : `${sep}=`;\n lines.push(`${sep}${title}${secondSep}`);\n\n // Add message type specific details\n if (message.type === \"ai\") {\n const aiMessage = message as AIMessage;\n if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {\n lines.push(\"Tool Calls:\");\n for (const tc of aiMessage.tool_calls) {\n lines.push(` ${tc.name} (${tc.id})`);\n lines.push(` Call ID: ${tc.id}`);\n lines.push(\" Args:\");\n for (const [key, value] of Object.entries(tc.args)) {\n lines.push(` ${key}: ${value}`);\n }\n }\n }\n }\n if (message.type === \"tool\") {\n const toolMessage = message as ToolMessage;\n if (toolMessage.name) {\n lines.push(`Name: ${toolMessage.name}`);\n }\n }\n\n // Add content if it's a string and not empty\n if (typeof message.content === \"string\" && message.content.trim()) {\n if (lines.length > 1) {\n lines.push(\"\"); // blank line before content\n }\n lines.push(message.content);\n }\n\n return lines.join(\"\\n\");\n}\n"],"mappings":";;AAMA,SAAgB,yBACdA,SACAC,SAA8B,UACtB;AACR,KAAI,WAAW,SAAU,QAAO,sBAAsB,QAAQ;AAC9D,QAAO,KAAK,UAAU,QAAQ;AAC/B;AAED,SAAS,sBAAsBD,SAA8B;CAC3D,MAAME,QAAkB,CAAE;CAC1B,MAAM,QAAQ,CAAC,CAAC,EACd,QAAQ,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,QAAQ,KAAK,MAAM,EAAE,CAC7D,SAAS,CAAC;CACX,MAAM,SAAS,KAAK,OAAO,KAAK,MAAM,UAAU,EAAE;CAClD,MAAM,MAAM,IAAI,OAAO,OAAO;CAC9B,MAAM,YAAY,MAAM,SAAS,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,CAAC;CAC1D,MAAM,KAAK,GAAG,MAAM,QAAQ,WAAW,CAAC;AAGxC,KAAI,QAAQ,SAAS,MAAM;EACzB,MAAM,YAAY;AAClB,MAAI,UAAU,cAAc,UAAU,WAAW,SAAS,GAAG;GAC3D,MAAM,KAAK,cAAc;AACzB,QAAK,MAAM,MAAM,UAAU,YAAY;IACrC,MAAM,KAAK,CAAC,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,KAAK,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,KAAK,UAAU;AACrB,SAAK,MAAM,CAAC,KAAK,MAAM,IAAI,OAAO,QAAQ,GAAG,KAAK,EAChD,MAAM,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC;GAErC;EACF;CACF;AACD,KAAI,QAAQ,SAAS,QAAQ;EAC3B,MAAM,cAAc;AACpB,MAAI,YAAY,MACd,MAAM,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM,CAAC;CAE1C;AAGD,KAAI,OAAO,QAAQ,YAAY,YAAY,QAAQ,QAAQ,MAAM,EAAE;AACjE,MAAI,MAAM,SAAS,GACjB,MAAM,KAAK,GAAG;EAEhB,MAAM,KAAK,QAAQ,QAAQ;CAC5B;AAED,QAAO,MAAM,KAAK,KAAK;AACxB"}
1
+ {"version":3,"file":"format.cjs","names":["message: BaseMessage","format: MessageStringFormat","lines: string[]"],"sources":["../../src/messages/format.ts"],"sourcesContent":["import { type BaseMessage } from \"./base.js\";\nimport { type AIMessage } from \"./ai.js\";\nimport { type ToolMessage } from \"./tool.js\";\n\nexport type MessageStringFormat = \"pretty\";\n\nexport function convertToFormattedString(\n message: BaseMessage,\n format: MessageStringFormat = \"pretty\"\n): string {\n if (format === \"pretty\") return convertToPrettyString(message);\n return JSON.stringify(message);\n}\n\nfunction convertToPrettyString(message: BaseMessage): string {\n const lines: string[] = [];\n const title = ` ${\n message.type.charAt(0).toUpperCase() + message.type.slice(1)\n } Message `;\n const sepLen = Math.floor((80 - title.length) / 2);\n const sep = \"=\".repeat(sepLen);\n const secondSep = title.length % 2 === 0 ? sep : `${sep}=`;\n lines.push(`${sep}${title}${secondSep}`);\n\n // Add message type specific details\n if (message.type === \"ai\") {\n const aiMessage = message as AIMessage;\n if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {\n lines.push(\"Tool Calls:\");\n for (const tc of aiMessage.tool_calls) {\n lines.push(` ${tc.name} (${tc.id})`);\n lines.push(` Call ID: ${tc.id}`);\n lines.push(\" Args:\");\n for (const [key, value] of Object.entries(tc.args)) {\n lines.push(\n ` ${key}: ${\n typeof value === \"object\" ? JSON.stringify(value) : value\n }`\n );\n }\n }\n }\n }\n if (message.type === \"tool\") {\n const toolMessage = message as ToolMessage;\n if (toolMessage.name) {\n lines.push(`Name: ${toolMessage.name}`);\n }\n }\n\n // Add content if it's a string and not empty\n if (typeof message.content === \"string\" && message.content.trim()) {\n if (lines.length > 1) {\n lines.push(\"\"); // blank line before content\n }\n lines.push(message.content);\n }\n\n return lines.join(\"\\n\");\n}\n"],"mappings":";;AAMA,SAAgB,yBACdA,SACAC,SAA8B,UACtB;AACR,KAAI,WAAW,SAAU,QAAO,sBAAsB,QAAQ;AAC9D,QAAO,KAAK,UAAU,QAAQ;AAC/B;AAED,SAAS,sBAAsBD,SAA8B;CAC3D,MAAME,QAAkB,CAAE;CAC1B,MAAM,QAAQ,CAAC,CAAC,EACd,QAAQ,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,QAAQ,KAAK,MAAM,EAAE,CAC7D,SAAS,CAAC;CACX,MAAM,SAAS,KAAK,OAAO,KAAK,MAAM,UAAU,EAAE;CAClD,MAAM,MAAM,IAAI,OAAO,OAAO;CAC9B,MAAM,YAAY,MAAM,SAAS,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,CAAC;CAC1D,MAAM,KAAK,GAAG,MAAM,QAAQ,WAAW,CAAC;AAGxC,KAAI,QAAQ,SAAS,MAAM;EACzB,MAAM,YAAY;AAClB,MAAI,UAAU,cAAc,UAAU,WAAW,SAAS,GAAG;GAC3D,MAAM,KAAK,cAAc;AACzB,QAAK,MAAM,MAAM,UAAU,YAAY;IACrC,MAAM,KAAK,CAAC,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,KAAK,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,KAAK,UAAU;AACrB,SAAK,MAAM,CAAC,KAAK,MAAM,IAAI,OAAO,QAAQ,GAAG,KAAK,EAChD,MAAM,KACJ,CAAC,IAAI,EAAE,IAAI,EAAE,EACX,OAAO,UAAU,WAAW,KAAK,UAAU,MAAM,GAAG,OACpD,CACH;GAEJ;EACF;CACF;AACD,KAAI,QAAQ,SAAS,QAAQ;EAC3B,MAAM,cAAc;AACpB,MAAI,YAAY,MACd,MAAM,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM,CAAC;CAE1C;AAGD,KAAI,OAAO,QAAQ,YAAY,YAAY,QAAQ,QAAQ,MAAM,EAAE;AACjE,MAAI,MAAM,SAAS,GACjB,MAAM,KAAK,GAAG;EAEhB,MAAM,KAAK,QAAQ,QAAQ;CAC5B;AAED,QAAO,MAAM,KAAK,KAAK;AACxB"}
@@ -18,7 +18,7 @@ function convertToPrettyString(message) {
18
18
  lines.push(` ${tc.name} (${tc.id})`);
19
19
  lines.push(` Call ID: ${tc.id}`);
20
20
  lines.push(" Args:");
21
- for (const [key, value] of Object.entries(tc.args)) lines.push(` ${key}: ${value}`);
21
+ for (const [key, value] of Object.entries(tc.args)) lines.push(` ${key}: ${typeof value === "object" ? JSON.stringify(value) : value}`);
22
22
  }
23
23
  }
24
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","names":["message: BaseMessage","format: MessageStringFormat","lines: string[]"],"sources":["../../src/messages/format.ts"],"sourcesContent":["import { type BaseMessage } from \"./base.js\";\nimport { type AIMessage } from \"./ai.js\";\nimport { type ToolMessage } from \"./tool.js\";\n\nexport type MessageStringFormat = \"pretty\";\n\nexport function convertToFormattedString(\n message: BaseMessage,\n format: MessageStringFormat = \"pretty\"\n): string {\n if (format === \"pretty\") return convertToPrettyString(message);\n return JSON.stringify(message);\n}\n\nfunction convertToPrettyString(message: BaseMessage): string {\n const lines: string[] = [];\n const title = ` ${\n message.type.charAt(0).toUpperCase() + message.type.slice(1)\n } Message `;\n const sepLen = Math.floor((80 - title.length) / 2);\n const sep = \"=\".repeat(sepLen);\n const secondSep = title.length % 2 === 0 ? sep : `${sep}=`;\n lines.push(`${sep}${title}${secondSep}`);\n\n // Add message type specific details\n if (message.type === \"ai\") {\n const aiMessage = message as AIMessage;\n if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {\n lines.push(\"Tool Calls:\");\n for (const tc of aiMessage.tool_calls) {\n lines.push(` ${tc.name} (${tc.id})`);\n lines.push(` Call ID: ${tc.id}`);\n lines.push(\" Args:\");\n for (const [key, value] of Object.entries(tc.args)) {\n lines.push(` ${key}: ${value}`);\n }\n }\n }\n }\n if (message.type === \"tool\") {\n const toolMessage = message as ToolMessage;\n if (toolMessage.name) {\n lines.push(`Name: ${toolMessage.name}`);\n }\n }\n\n // Add content if it's a string and not empty\n if (typeof message.content === \"string\" && message.content.trim()) {\n if (lines.length > 1) {\n lines.push(\"\"); // blank line before content\n }\n lines.push(message.content);\n }\n\n return lines.join(\"\\n\");\n}\n"],"mappings":";AAMA,SAAgB,yBACdA,SACAC,SAA8B,UACtB;AACR,KAAI,WAAW,SAAU,QAAO,sBAAsB,QAAQ;AAC9D,QAAO,KAAK,UAAU,QAAQ;AAC/B;AAED,SAAS,sBAAsBD,SAA8B;CAC3D,MAAME,QAAkB,CAAE;CAC1B,MAAM,QAAQ,CAAC,CAAC,EACd,QAAQ,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,QAAQ,KAAK,MAAM,EAAE,CAC7D,SAAS,CAAC;CACX,MAAM,SAAS,KAAK,OAAO,KAAK,MAAM,UAAU,EAAE;CAClD,MAAM,MAAM,IAAI,OAAO,OAAO;CAC9B,MAAM,YAAY,MAAM,SAAS,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,CAAC;CAC1D,MAAM,KAAK,GAAG,MAAM,QAAQ,WAAW,CAAC;AAGxC,KAAI,QAAQ,SAAS,MAAM;EACzB,MAAM,YAAY;AAClB,MAAI,UAAU,cAAc,UAAU,WAAW,SAAS,GAAG;GAC3D,MAAM,KAAK,cAAc;AACzB,QAAK,MAAM,MAAM,UAAU,YAAY;IACrC,MAAM,KAAK,CAAC,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,KAAK,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,KAAK,UAAU;AACrB,SAAK,MAAM,CAAC,KAAK,MAAM,IAAI,OAAO,QAAQ,GAAG,KAAK,EAChD,MAAM,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC;GAErC;EACF;CACF;AACD,KAAI,QAAQ,SAAS,QAAQ;EAC3B,MAAM,cAAc;AACpB,MAAI,YAAY,MACd,MAAM,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM,CAAC;CAE1C;AAGD,KAAI,OAAO,QAAQ,YAAY,YAAY,QAAQ,QAAQ,MAAM,EAAE;AACjE,MAAI,MAAM,SAAS,GACjB,MAAM,KAAK,GAAG;EAEhB,MAAM,KAAK,QAAQ,QAAQ;CAC5B;AAED,QAAO,MAAM,KAAK,KAAK;AACxB"}
1
+ {"version":3,"file":"format.js","names":["message: BaseMessage","format: MessageStringFormat","lines: string[]"],"sources":["../../src/messages/format.ts"],"sourcesContent":["import { type BaseMessage } from \"./base.js\";\nimport { type AIMessage } from \"./ai.js\";\nimport { type ToolMessage } from \"./tool.js\";\n\nexport type MessageStringFormat = \"pretty\";\n\nexport function convertToFormattedString(\n message: BaseMessage,\n format: MessageStringFormat = \"pretty\"\n): string {\n if (format === \"pretty\") return convertToPrettyString(message);\n return JSON.stringify(message);\n}\n\nfunction convertToPrettyString(message: BaseMessage): string {\n const lines: string[] = [];\n const title = ` ${\n message.type.charAt(0).toUpperCase() + message.type.slice(1)\n } Message `;\n const sepLen = Math.floor((80 - title.length) / 2);\n const sep = \"=\".repeat(sepLen);\n const secondSep = title.length % 2 === 0 ? sep : `${sep}=`;\n lines.push(`${sep}${title}${secondSep}`);\n\n // Add message type specific details\n if (message.type === \"ai\") {\n const aiMessage = message as AIMessage;\n if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {\n lines.push(\"Tool Calls:\");\n for (const tc of aiMessage.tool_calls) {\n lines.push(` ${tc.name} (${tc.id})`);\n lines.push(` Call ID: ${tc.id}`);\n lines.push(\" Args:\");\n for (const [key, value] of Object.entries(tc.args)) {\n lines.push(\n ` ${key}: ${\n typeof value === \"object\" ? JSON.stringify(value) : value\n }`\n );\n }\n }\n }\n }\n if (message.type === \"tool\") {\n const toolMessage = message as ToolMessage;\n if (toolMessage.name) {\n lines.push(`Name: ${toolMessage.name}`);\n }\n }\n\n // Add content if it's a string and not empty\n if (typeof message.content === \"string\" && message.content.trim()) {\n if (lines.length > 1) {\n lines.push(\"\"); // blank line before content\n }\n lines.push(message.content);\n }\n\n return lines.join(\"\\n\");\n}\n"],"mappings":";AAMA,SAAgB,yBACdA,SACAC,SAA8B,UACtB;AACR,KAAI,WAAW,SAAU,QAAO,sBAAsB,QAAQ;AAC9D,QAAO,KAAK,UAAU,QAAQ;AAC/B;AAED,SAAS,sBAAsBD,SAA8B;CAC3D,MAAME,QAAkB,CAAE;CAC1B,MAAM,QAAQ,CAAC,CAAC,EACd,QAAQ,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,QAAQ,KAAK,MAAM,EAAE,CAC7D,SAAS,CAAC;CACX,MAAM,SAAS,KAAK,OAAO,KAAK,MAAM,UAAU,EAAE;CAClD,MAAM,MAAM,IAAI,OAAO,OAAO;CAC9B,MAAM,YAAY,MAAM,SAAS,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,CAAC;CAC1D,MAAM,KAAK,GAAG,MAAM,QAAQ,WAAW,CAAC;AAGxC,KAAI,QAAQ,SAAS,MAAM;EACzB,MAAM,YAAY;AAClB,MAAI,UAAU,cAAc,UAAU,WAAW,SAAS,GAAG;GAC3D,MAAM,KAAK,cAAc;AACzB,QAAK,MAAM,MAAM,UAAU,YAAY;IACrC,MAAM,KAAK,CAAC,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,KAAK,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,KAAK,UAAU;AACrB,SAAK,MAAM,CAAC,KAAK,MAAM,IAAI,OAAO,QAAQ,GAAG,KAAK,EAChD,MAAM,KACJ,CAAC,IAAI,EAAE,IAAI,EAAE,EACX,OAAO,UAAU,WAAW,KAAK,UAAU,MAAM,GAAG,OACpD,CACH;GAEJ;EACF;CACF;AACD,KAAI,QAAQ,SAAS,QAAQ;EAC3B,MAAM,cAAc;AACpB,MAAI,YAAY,MACd,MAAM,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM,CAAC;CAE1C;AAGD,KAAI,OAAO,QAAQ,YAAY,YAAY,QAAQ,QAAQ,MAAM,EAAE;AACjE,MAAI,MAAM,SAAS,GACjB,MAAM,KAAK,GAAG;EAEhB,MAAM,KAAK,QAAQ,QAAQ;CAC5B;AAED,QAAO,MAAM,KAAK,KAAK;AACxB"}
@@ -43,14 +43,21 @@ function drawMermaid(nodes, edges, config) {
43
43
  edgeGroups[commonPrefix].push(edge);
44
44
  }
45
45
  const seenSubgraphs = /* @__PURE__ */ new Set();
46
+ function sortPrefixesByDepth(prefixes) {
47
+ return [...prefixes].sort((a, b) => {
48
+ return a.split(":").length - b.split(":").length;
49
+ });
50
+ }
46
51
  function addSubgraph(edges$1, prefix) {
47
52
  const selfLoop = edges$1.length === 1 && edges$1[0].source === edges$1[0].target;
48
53
  if (prefix && !selfLoop) {
49
54
  const subgraph = prefix.split(":").pop();
50
- if (seenSubgraphs.has(subgraph)) throw new Error(`Found duplicate subgraph '${subgraph}' -- this likely means that you're reusing a subgraph node with the same name. Please adjust your graph to have subgraph nodes with unique names.`);
51
- seenSubgraphs.add(subgraph);
55
+ if (seenSubgraphs.has(prefix)) throw new Error(`Found duplicate subgraph '${subgraph}' at '${prefix} -- this likely means that you're reusing a subgraph node with the same name. Please adjust your graph to have subgraph nodes with unique names.`);
56
+ seenSubgraphs.add(prefix);
52
57
  mermaidGraph += `\tsubgraph ${subgraph}\n`;
53
58
  }
59
+ const nestedPrefixes = sortPrefixesByDepth(Object.keys(edgeGroups).filter((nestedPrefix) => nestedPrefix.startsWith(`${prefix}:`) && nestedPrefix !== prefix && nestedPrefix.split(":").length === prefix.split(":").length + 1));
60
+ for (const nestedPrefix of nestedPrefixes) addSubgraph(edgeGroups[nestedPrefix], nestedPrefix);
54
61
  for (const edge of edges$1) {
55
62
  const { source, target, data, conditional } = edge;
56
63
  let edgeLabel = "";
@@ -62,7 +69,6 @@ function drawMermaid(nodes, edges, config) {
62
69
  } else edgeLabel = conditional ? " -.-> " : " --> ";
63
70
  mermaidGraph += `\t${_escapeNodeLabel(source)}${edgeLabel}${_escapeNodeLabel(target)};\n`;
64
71
  }
65
- for (const nestedPrefix in edgeGroups) if (nestedPrefix.startsWith(`${prefix}:`) && nestedPrefix !== prefix) addSubgraph(edgeGroups[nestedPrefix], nestedPrefix);
66
72
  if (prefix && !selfLoop) mermaidGraph += " end\n";
67
73
  }
68
74
  addSubgraph(edgeGroups[""] ?? [], "");
@@ -1 +1 @@
1
- {"version":3,"file":"graph_mermaid.cjs","names":["nodeLabel: string","nodeColors: Record<string, string>","nodes: Record<string, Node>","edges: Edge[]","config?: {\n firstNode?: string;\n lastNode?: string;\n curveStyle?: string;\n withStyles?: boolean;\n nodeColors?: Record<string, string>;\n wrapLabelNWords?: number;\n }","formatDict: Record<string, string>","edgeGroups: Record<string, Edge[]>","prefix: string","edges","mermaidSyntax: string","config?: {\n /**\n * The type of image to render.\n * @default \"png\"\n */\n imageType?: \"png\" | \"jpeg\" | \"webp\";\n backgroundColor?: string;\n }","toBase64Url"],"sources":["../../src/runnables/graph_mermaid.ts"],"sourcesContent":["import { Edge, Node } from \"./types.js\";\nimport { toBase64Url } from \"./utils.js\";\n\nfunction _escapeNodeLabel(nodeLabel: string): string {\n // Escapes the node label for Mermaid syntax.\n return nodeLabel.replace(/[^a-zA-Z-_0-9]/g, \"_\");\n}\n\nconst MARKDOWN_SPECIAL_CHARS = [\"*\", \"_\", \"`\"];\n\nfunction _generateMermaidGraphStyles(\n nodeColors: Record<string, string>\n): string {\n let styles = \"\";\n for (const [className, color] of Object.entries(nodeColors)) {\n styles += `\\tclassDef ${className} ${color};\\n`;\n }\n return styles;\n}\n\n/**\n * Draws a Mermaid graph using the provided graph data\n */\nexport function drawMermaid(\n nodes: Record<string, Node>,\n edges: Edge[],\n config?: {\n firstNode?: string;\n lastNode?: string;\n curveStyle?: string;\n withStyles?: boolean;\n nodeColors?: Record<string, string>;\n wrapLabelNWords?: number;\n }\n): string {\n const {\n firstNode,\n lastNode,\n nodeColors,\n withStyles = true,\n curveStyle = \"linear\",\n wrapLabelNWords = 9,\n } = config ?? {};\n // Initialize Mermaid graph configuration\n let mermaidGraph = withStyles\n ? `%%{init: {'flowchart': {'curve': '${curveStyle}'}}}%%\\ngraph TD;\\n`\n : \"graph TD;\\n\";\n if (withStyles) {\n // Node formatting templates\n const defaultClassLabel = \"default\";\n const formatDict: Record<string, string> = {\n [defaultClassLabel]: \"{0}({1})\",\n };\n if (firstNode !== undefined) {\n formatDict[firstNode] = \"{0}([{1}]):::first\";\n }\n if (lastNode !== undefined) {\n formatDict[lastNode] = \"{0}([{1}]):::last\";\n }\n\n // Add nodes to the graph\n for (const [key, node] of Object.entries(nodes)) {\n const nodeName = node.name.split(\":\").pop() ?? \"\";\n const label = MARKDOWN_SPECIAL_CHARS.some(\n (char) => nodeName.startsWith(char) && nodeName.endsWith(char)\n )\n ? `<p>${nodeName}</p>`\n : nodeName;\n\n let finalLabel = label;\n if (Object.keys(node.metadata ?? {}).length) {\n finalLabel += `<hr/><small><em>${Object.entries(node.metadata ?? {})\n .map(([k, v]) => `${k} = ${v}`)\n .join(\"\\n\")}</em></small>`;\n }\n\n const nodeLabel = (formatDict[key] ?? formatDict[defaultClassLabel])\n .replace(\"{0}\", _escapeNodeLabel(key))\n .replace(\"{1}\", finalLabel);\n\n mermaidGraph += `\\t${nodeLabel}\\n`;\n }\n }\n\n // Group edges by their common prefixes\n const edgeGroups: Record<string, Edge[]> = {};\n for (const edge of edges) {\n const srcParts = edge.source.split(\":\");\n const tgtParts = edge.target.split(\":\");\n const commonPrefix = srcParts\n .filter((src, i) => src === tgtParts[i])\n .join(\":\");\n if (!edgeGroups[commonPrefix]) {\n edgeGroups[commonPrefix] = [];\n }\n edgeGroups[commonPrefix].push(edge);\n }\n\n const seenSubgraphs = new Set<string>();\n\n function addSubgraph(edges: Edge[], prefix: string): void {\n const selfLoop = edges.length === 1 && edges[0].source === edges[0].target;\n if (prefix && !selfLoop) {\n const subgraph = prefix.split(\":\").pop()!;\n if (seenSubgraphs.has(subgraph)) {\n throw new Error(\n `Found duplicate subgraph '${subgraph}' -- this likely means that ` +\n \"you're reusing a subgraph node with the same name. \" +\n \"Please adjust your graph to have subgraph nodes with unique names.\"\n );\n }\n\n seenSubgraphs.add(subgraph);\n mermaidGraph += `\\tsubgraph ${subgraph}\\n`;\n }\n\n for (const edge of edges) {\n const { source, target, data, conditional } = edge;\n\n let edgeLabel = \"\";\n if (data !== undefined) {\n let edgeData = data;\n const words = edgeData.split(\" \");\n if (words.length > wrapLabelNWords) {\n edgeData = Array.from(\n { length: Math.ceil(words.length / wrapLabelNWords) },\n (_, i) =>\n words\n .slice(i * wrapLabelNWords, (i + 1) * wrapLabelNWords)\n .join(\" \")\n ).join(\"&nbsp;<br>&nbsp;\");\n }\n edgeLabel = conditional\n ? ` -. &nbsp;${edgeData}&nbsp; .-> `\n : ` -- &nbsp;${edgeData}&nbsp; --> `;\n } else {\n edgeLabel = conditional ? \" -.-> \" : \" --> \";\n }\n\n mermaidGraph += `\\t${_escapeNodeLabel(\n source\n )}${edgeLabel}${_escapeNodeLabel(target)};\\n`;\n }\n\n // Recursively add nested subgraphs\n for (const nestedPrefix in edgeGroups) {\n if (nestedPrefix.startsWith(`${prefix}:`) && nestedPrefix !== prefix) {\n addSubgraph(edgeGroups[nestedPrefix], nestedPrefix);\n }\n }\n\n if (prefix && !selfLoop) {\n mermaidGraph += \"\\tend\\n\";\n }\n }\n\n // Start with the top-level edges (no common prefix)\n addSubgraph(edgeGroups[\"\"] ?? [], \"\");\n\n // Add remaining subgraphs\n for (const prefix in edgeGroups) {\n if (!prefix.includes(\":\") && prefix !== \"\") {\n addSubgraph(edgeGroups[prefix], prefix);\n }\n }\n\n // Add custom styles for nodes\n if (withStyles) {\n mermaidGraph += _generateMermaidGraphStyles(nodeColors ?? {});\n }\n\n return mermaidGraph;\n}\n\n/**\n * Renders Mermaid graph using the Mermaid.INK API.\n *\n * @example\n * ```javascript\n * const image = await drawMermaidImage(mermaidSyntax, {\n * backgroundColor: \"white\",\n * imageType: \"png\",\n * });\n * fs.writeFileSync(\"image.png\", image);\n * ```\n *\n * @param mermaidSyntax - The Mermaid syntax to render.\n * @param config - The configuration for the image.\n * @returns The image as a Blob.\n */\nexport async function drawMermaidImage(\n mermaidSyntax: string,\n config?: {\n /**\n * The type of image to render.\n * @default \"png\"\n */\n imageType?: \"png\" | \"jpeg\" | \"webp\";\n backgroundColor?: string;\n }\n) {\n let backgroundColor = config?.backgroundColor ?? \"white\";\n const imageType = config?.imageType ?? \"png\";\n\n const mermaidSyntaxEncoded = toBase64Url(mermaidSyntax);\n\n // Check if the background color is a hexadecimal color code using regex\n if (backgroundColor !== undefined) {\n const hexColorPattern = /^#(?:[0-9a-fA-F]{3}){1,2}$/;\n if (!hexColorPattern.test(backgroundColor)) {\n backgroundColor = `!${backgroundColor}`;\n }\n }\n const imageUrl = `https://mermaid.ink/img/${mermaidSyntaxEncoded}?bgColor=${backgroundColor}&type=${imageType}`;\n const res = await fetch(imageUrl);\n if (!res.ok) {\n throw new Error(\n [\n `Failed to render the graph using the Mermaid.INK API.`,\n `Status code: ${res.status}`,\n `Status text: ${res.statusText}`,\n ].join(\"\\n\")\n );\n }\n const content = await res.blob();\n return content;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"graph_mermaid.cjs","names":["nodeLabel: string","nodeColors: Record<string, string>","nodes: Record<string, Node>","edges: Edge[]","config?: {\n firstNode?: string;\n lastNode?: string;\n curveStyle?: string;\n withStyles?: boolean;\n nodeColors?: Record<string, string>;\n wrapLabelNWords?: number;\n }","formatDict: Record<string, string>","edgeGroups: Record<string, Edge[]>","prefixes: string[]","prefix: string","edges","mermaidSyntax: string","config?: {\n /**\n * The type of image to render.\n * @default \"png\"\n */\n imageType?: \"png\" | \"jpeg\" | \"webp\";\n backgroundColor?: string;\n }","toBase64Url"],"sources":["../../src/runnables/graph_mermaid.ts"],"sourcesContent":["import { Edge, Node } from \"./types.js\";\nimport { toBase64Url } from \"./utils.js\";\n\nfunction _escapeNodeLabel(nodeLabel: string): string {\n // Escapes the node label for Mermaid syntax.\n return nodeLabel.replace(/[^a-zA-Z-_0-9]/g, \"_\");\n}\n\nconst MARKDOWN_SPECIAL_CHARS = [\"*\", \"_\", \"`\"];\n\nfunction _generateMermaidGraphStyles(\n nodeColors: Record<string, string>\n): string {\n let styles = \"\";\n for (const [className, color] of Object.entries(nodeColors)) {\n styles += `\\tclassDef ${className} ${color};\\n`;\n }\n return styles;\n}\n\n/**\n * Draws a Mermaid graph using the provided graph data\n */\nexport function drawMermaid(\n nodes: Record<string, Node>,\n edges: Edge[],\n config?: {\n firstNode?: string;\n lastNode?: string;\n curveStyle?: string;\n withStyles?: boolean;\n nodeColors?: Record<string, string>;\n wrapLabelNWords?: number;\n }\n): string {\n const {\n firstNode,\n lastNode,\n nodeColors,\n withStyles = true,\n curveStyle = \"linear\",\n wrapLabelNWords = 9,\n } = config ?? {};\n // Initialize Mermaid graph configuration\n let mermaidGraph = withStyles\n ? `%%{init: {'flowchart': {'curve': '${curveStyle}'}}}%%\\ngraph TD;\\n`\n : \"graph TD;\\n\";\n if (withStyles) {\n // Node formatting templates\n const defaultClassLabel = \"default\";\n const formatDict: Record<string, string> = {\n [defaultClassLabel]: \"{0}({1})\",\n };\n if (firstNode !== undefined) {\n formatDict[firstNode] = \"{0}([{1}]):::first\";\n }\n if (lastNode !== undefined) {\n formatDict[lastNode] = \"{0}([{1}]):::last\";\n }\n\n // Add nodes to the graph\n for (const [key, node] of Object.entries(nodes)) {\n const nodeName = node.name.split(\":\").pop() ?? \"\";\n const label = MARKDOWN_SPECIAL_CHARS.some(\n (char) => nodeName.startsWith(char) && nodeName.endsWith(char)\n )\n ? `<p>${nodeName}</p>`\n : nodeName;\n\n let finalLabel = label;\n if (Object.keys(node.metadata ?? {}).length) {\n finalLabel += `<hr/><small><em>${Object.entries(node.metadata ?? {})\n .map(([k, v]) => `${k} = ${v}`)\n .join(\"\\n\")}</em></small>`;\n }\n\n const nodeLabel = (formatDict[key] ?? formatDict[defaultClassLabel])\n .replace(\"{0}\", _escapeNodeLabel(key))\n .replace(\"{1}\", finalLabel);\n\n mermaidGraph += `\\t${nodeLabel}\\n`;\n }\n }\n\n // Group edges by their common prefixes\n const edgeGroups: Record<string, Edge[]> = {};\n for (const edge of edges) {\n const srcParts = edge.source.split(\":\");\n const tgtParts = edge.target.split(\":\");\n const commonPrefix = srcParts\n .filter((src, i) => src === tgtParts[i])\n .join(\":\");\n if (!edgeGroups[commonPrefix]) {\n edgeGroups[commonPrefix] = [];\n }\n edgeGroups[commonPrefix].push(edge);\n }\n\n const seenSubgraphs = new Set<string>();\n\n // sort prefixes by path length for correct nesting\n function sortPrefixesByDepth(prefixes: string[]): string[] {\n return [...prefixes].sort((a, b) => {\n return a.split(\":\").length - b.split(\":\").length;\n });\n }\n\n function addSubgraph(edges: Edge[], prefix: string): void {\n const selfLoop = edges.length === 1 && edges[0].source === edges[0].target;\n if (prefix && !selfLoop) {\n const subgraph = prefix.split(\":\").pop()!;\n\n if (seenSubgraphs.has(prefix)) {\n throw new Error(\n `Found duplicate subgraph '${subgraph}' at '${prefix} -- this likely means that ` +\n \"you're reusing a subgraph node with the same name. \" +\n \"Please adjust your graph to have subgraph nodes with unique names.\"\n );\n }\n\n seenSubgraphs.add(prefix);\n mermaidGraph += `\\tsubgraph ${subgraph}\\n`;\n }\n\n // all nested prefixes for this level, sorted by depth\n const nestedPrefixes = sortPrefixesByDepth(\n Object.keys(edgeGroups).filter(\n (nestedPrefix) =>\n nestedPrefix.startsWith(`${prefix}:`) &&\n nestedPrefix !== prefix &&\n nestedPrefix.split(\":\").length === prefix.split(\":\").length + 1\n )\n );\n\n for (const nestedPrefix of nestedPrefixes) {\n addSubgraph(edgeGroups[nestedPrefix], nestedPrefix);\n }\n\n for (const edge of edges) {\n const { source, target, data, conditional } = edge;\n\n let edgeLabel = \"\";\n if (data !== undefined) {\n let edgeData = data;\n const words = edgeData.split(\" \");\n if (words.length > wrapLabelNWords) {\n edgeData = Array.from(\n { length: Math.ceil(words.length / wrapLabelNWords) },\n (_, i) =>\n words\n .slice(i * wrapLabelNWords, (i + 1) * wrapLabelNWords)\n .join(\" \")\n ).join(\"&nbsp;<br>&nbsp;\");\n }\n edgeLabel = conditional\n ? ` -. &nbsp;${edgeData}&nbsp; .-> `\n : ` -- &nbsp;${edgeData}&nbsp; --> `;\n } else {\n edgeLabel = conditional ? \" -.-> \" : \" --> \";\n }\n\n mermaidGraph += `\\t${_escapeNodeLabel(\n source\n )}${edgeLabel}${_escapeNodeLabel(target)};\\n`;\n }\n\n if (prefix && !selfLoop) {\n mermaidGraph += \"\\tend\\n\";\n }\n }\n\n // Start with the top-level edges (no common prefix)\n addSubgraph(edgeGroups[\"\"] ?? [], \"\");\n\n // Add remaining top-level subgraphs\n for (const prefix in edgeGroups) {\n if (!prefix.includes(\":\") && prefix !== \"\") {\n addSubgraph(edgeGroups[prefix], prefix);\n }\n }\n\n // Add custom styles for nodes\n if (withStyles) {\n mermaidGraph += _generateMermaidGraphStyles(nodeColors ?? {});\n }\n\n return mermaidGraph;\n}\n\n/**\n * Renders Mermaid graph using the Mermaid.INK API.\n *\n * @example\n * ```javascript\n * const image = await drawMermaidImage(mermaidSyntax, {\n * backgroundColor: \"white\",\n * imageType: \"png\",\n * });\n * fs.writeFileSync(\"image.png\", image);\n * ```\n *\n * @param mermaidSyntax - The Mermaid syntax to render.\n * @param config - The configuration for the image.\n * @returns The image as a Blob.\n */\nexport async function drawMermaidImage(\n mermaidSyntax: string,\n config?: {\n /**\n * The type of image to render.\n * @default \"png\"\n */\n imageType?: \"png\" | \"jpeg\" | \"webp\";\n backgroundColor?: string;\n }\n) {\n let backgroundColor = config?.backgroundColor ?? \"white\";\n const imageType = config?.imageType ?? \"png\";\n\n const mermaidSyntaxEncoded = toBase64Url(mermaidSyntax);\n\n // Check if the background color is a hexadecimal color code using regex\n if (backgroundColor !== undefined) {\n const hexColorPattern = /^#(?:[0-9a-fA-F]{3}){1,2}$/;\n if (!hexColorPattern.test(backgroundColor)) {\n backgroundColor = `!${backgroundColor}`;\n }\n }\n const imageUrl = `https://mermaid.ink/img/${mermaidSyntaxEncoded}?bgColor=${backgroundColor}&type=${imageType}`;\n const res = await fetch(imageUrl);\n if (!res.ok) {\n throw new Error(\n [\n `Failed to render the graph using the Mermaid.INK API.`,\n `Status code: ${res.status}`,\n `Status text: ${res.statusText}`,\n ].join(\"\\n\")\n );\n }\n const content = await res.blob();\n return content;\n}\n"],"mappings":"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"}
@@ -43,14 +43,21 @@ function drawMermaid(nodes, edges, config) {
43
43
  edgeGroups[commonPrefix].push(edge);
44
44
  }
45
45
  const seenSubgraphs = /* @__PURE__ */ new Set();
46
+ function sortPrefixesByDepth(prefixes) {
47
+ return [...prefixes].sort((a, b) => {
48
+ return a.split(":").length - b.split(":").length;
49
+ });
50
+ }
46
51
  function addSubgraph(edges$1, prefix) {
47
52
  const selfLoop = edges$1.length === 1 && edges$1[0].source === edges$1[0].target;
48
53
  if (prefix && !selfLoop) {
49
54
  const subgraph = prefix.split(":").pop();
50
- if (seenSubgraphs.has(subgraph)) throw new Error(`Found duplicate subgraph '${subgraph}' -- this likely means that you're reusing a subgraph node with the same name. Please adjust your graph to have subgraph nodes with unique names.`);
51
- seenSubgraphs.add(subgraph);
55
+ if (seenSubgraphs.has(prefix)) throw new Error(`Found duplicate subgraph '${subgraph}' at '${prefix} -- this likely means that you're reusing a subgraph node with the same name. Please adjust your graph to have subgraph nodes with unique names.`);
56
+ seenSubgraphs.add(prefix);
52
57
  mermaidGraph += `\tsubgraph ${subgraph}\n`;
53
58
  }
59
+ const nestedPrefixes = sortPrefixesByDepth(Object.keys(edgeGroups).filter((nestedPrefix) => nestedPrefix.startsWith(`${prefix}:`) && nestedPrefix !== prefix && nestedPrefix.split(":").length === prefix.split(":").length + 1));
60
+ for (const nestedPrefix of nestedPrefixes) addSubgraph(edgeGroups[nestedPrefix], nestedPrefix);
54
61
  for (const edge of edges$1) {
55
62
  const { source, target, data, conditional } = edge;
56
63
  let edgeLabel = "";
@@ -62,7 +69,6 @@ function drawMermaid(nodes, edges, config) {
62
69
  } else edgeLabel = conditional ? " -.-> " : " --> ";
63
70
  mermaidGraph += `\t${_escapeNodeLabel(source)}${edgeLabel}${_escapeNodeLabel(target)};\n`;
64
71
  }
65
- for (const nestedPrefix in edgeGroups) if (nestedPrefix.startsWith(`${prefix}:`) && nestedPrefix !== prefix) addSubgraph(edgeGroups[nestedPrefix], nestedPrefix);
66
72
  if (prefix && !selfLoop) mermaidGraph += " end\n";
67
73
  }
68
74
  addSubgraph(edgeGroups[""] ?? [], "");
@@ -1 +1 @@
1
- {"version":3,"file":"graph_mermaid.js","names":["nodeLabel: string","nodeColors: Record<string, string>","nodes: Record<string, Node>","edges: Edge[]","config?: {\n firstNode?: string;\n lastNode?: string;\n curveStyle?: string;\n withStyles?: boolean;\n nodeColors?: Record<string, string>;\n wrapLabelNWords?: number;\n }","formatDict: Record<string, string>","edgeGroups: Record<string, Edge[]>","prefix: string","edges","mermaidSyntax: string","config?: {\n /**\n * The type of image to render.\n * @default \"png\"\n */\n imageType?: \"png\" | \"jpeg\" | \"webp\";\n backgroundColor?: string;\n }"],"sources":["../../src/runnables/graph_mermaid.ts"],"sourcesContent":["import { Edge, Node } from \"./types.js\";\nimport { toBase64Url } from \"./utils.js\";\n\nfunction _escapeNodeLabel(nodeLabel: string): string {\n // Escapes the node label for Mermaid syntax.\n return nodeLabel.replace(/[^a-zA-Z-_0-9]/g, \"_\");\n}\n\nconst MARKDOWN_SPECIAL_CHARS = [\"*\", \"_\", \"`\"];\n\nfunction _generateMermaidGraphStyles(\n nodeColors: Record<string, string>\n): string {\n let styles = \"\";\n for (const [className, color] of Object.entries(nodeColors)) {\n styles += `\\tclassDef ${className} ${color};\\n`;\n }\n return styles;\n}\n\n/**\n * Draws a Mermaid graph using the provided graph data\n */\nexport function drawMermaid(\n nodes: Record<string, Node>,\n edges: Edge[],\n config?: {\n firstNode?: string;\n lastNode?: string;\n curveStyle?: string;\n withStyles?: boolean;\n nodeColors?: Record<string, string>;\n wrapLabelNWords?: number;\n }\n): string {\n const {\n firstNode,\n lastNode,\n nodeColors,\n withStyles = true,\n curveStyle = \"linear\",\n wrapLabelNWords = 9,\n } = config ?? {};\n // Initialize Mermaid graph configuration\n let mermaidGraph = withStyles\n ? `%%{init: {'flowchart': {'curve': '${curveStyle}'}}}%%\\ngraph TD;\\n`\n : \"graph TD;\\n\";\n if (withStyles) {\n // Node formatting templates\n const defaultClassLabel = \"default\";\n const formatDict: Record<string, string> = {\n [defaultClassLabel]: \"{0}({1})\",\n };\n if (firstNode !== undefined) {\n formatDict[firstNode] = \"{0}([{1}]):::first\";\n }\n if (lastNode !== undefined) {\n formatDict[lastNode] = \"{0}([{1}]):::last\";\n }\n\n // Add nodes to the graph\n for (const [key, node] of Object.entries(nodes)) {\n const nodeName = node.name.split(\":\").pop() ?? \"\";\n const label = MARKDOWN_SPECIAL_CHARS.some(\n (char) => nodeName.startsWith(char) && nodeName.endsWith(char)\n )\n ? `<p>${nodeName}</p>`\n : nodeName;\n\n let finalLabel = label;\n if (Object.keys(node.metadata ?? {}).length) {\n finalLabel += `<hr/><small><em>${Object.entries(node.metadata ?? {})\n .map(([k, v]) => `${k} = ${v}`)\n .join(\"\\n\")}</em></small>`;\n }\n\n const nodeLabel = (formatDict[key] ?? formatDict[defaultClassLabel])\n .replace(\"{0}\", _escapeNodeLabel(key))\n .replace(\"{1}\", finalLabel);\n\n mermaidGraph += `\\t${nodeLabel}\\n`;\n }\n }\n\n // Group edges by their common prefixes\n const edgeGroups: Record<string, Edge[]> = {};\n for (const edge of edges) {\n const srcParts = edge.source.split(\":\");\n const tgtParts = edge.target.split(\":\");\n const commonPrefix = srcParts\n .filter((src, i) => src === tgtParts[i])\n .join(\":\");\n if (!edgeGroups[commonPrefix]) {\n edgeGroups[commonPrefix] = [];\n }\n edgeGroups[commonPrefix].push(edge);\n }\n\n const seenSubgraphs = new Set<string>();\n\n function addSubgraph(edges: Edge[], prefix: string): void {\n const selfLoop = edges.length === 1 && edges[0].source === edges[0].target;\n if (prefix && !selfLoop) {\n const subgraph = prefix.split(\":\").pop()!;\n if (seenSubgraphs.has(subgraph)) {\n throw new Error(\n `Found duplicate subgraph '${subgraph}' -- this likely means that ` +\n \"you're reusing a subgraph node with the same name. \" +\n \"Please adjust your graph to have subgraph nodes with unique names.\"\n );\n }\n\n seenSubgraphs.add(subgraph);\n mermaidGraph += `\\tsubgraph ${subgraph}\\n`;\n }\n\n for (const edge of edges) {\n const { source, target, data, conditional } = edge;\n\n let edgeLabel = \"\";\n if (data !== undefined) {\n let edgeData = data;\n const words = edgeData.split(\" \");\n if (words.length > wrapLabelNWords) {\n edgeData = Array.from(\n { length: Math.ceil(words.length / wrapLabelNWords) },\n (_, i) =>\n words\n .slice(i * wrapLabelNWords, (i + 1) * wrapLabelNWords)\n .join(\" \")\n ).join(\"&nbsp;<br>&nbsp;\");\n }\n edgeLabel = conditional\n ? ` -. &nbsp;${edgeData}&nbsp; .-> `\n : ` -- &nbsp;${edgeData}&nbsp; --> `;\n } else {\n edgeLabel = conditional ? \" -.-> \" : \" --> \";\n }\n\n mermaidGraph += `\\t${_escapeNodeLabel(\n source\n )}${edgeLabel}${_escapeNodeLabel(target)};\\n`;\n }\n\n // Recursively add nested subgraphs\n for (const nestedPrefix in edgeGroups) {\n if (nestedPrefix.startsWith(`${prefix}:`) && nestedPrefix !== prefix) {\n addSubgraph(edgeGroups[nestedPrefix], nestedPrefix);\n }\n }\n\n if (prefix && !selfLoop) {\n mermaidGraph += \"\\tend\\n\";\n }\n }\n\n // Start with the top-level edges (no common prefix)\n addSubgraph(edgeGroups[\"\"] ?? [], \"\");\n\n // Add remaining subgraphs\n for (const prefix in edgeGroups) {\n if (!prefix.includes(\":\") && prefix !== \"\") {\n addSubgraph(edgeGroups[prefix], prefix);\n }\n }\n\n // Add custom styles for nodes\n if (withStyles) {\n mermaidGraph += _generateMermaidGraphStyles(nodeColors ?? {});\n }\n\n return mermaidGraph;\n}\n\n/**\n * Renders Mermaid graph using the Mermaid.INK API.\n *\n * @example\n * ```javascript\n * const image = await drawMermaidImage(mermaidSyntax, {\n * backgroundColor: \"white\",\n * imageType: \"png\",\n * });\n * fs.writeFileSync(\"image.png\", image);\n * ```\n *\n * @param mermaidSyntax - The Mermaid syntax to render.\n * @param config - The configuration for the image.\n * @returns The image as a Blob.\n */\nexport async function drawMermaidImage(\n mermaidSyntax: string,\n config?: {\n /**\n * The type of image to render.\n * @default \"png\"\n */\n imageType?: \"png\" | \"jpeg\" | \"webp\";\n backgroundColor?: string;\n }\n) {\n let backgroundColor = config?.backgroundColor ?? \"white\";\n const imageType = config?.imageType ?? \"png\";\n\n const mermaidSyntaxEncoded = toBase64Url(mermaidSyntax);\n\n // Check if the background color is a hexadecimal color code using regex\n if (backgroundColor !== undefined) {\n const hexColorPattern = /^#(?:[0-9a-fA-F]{3}){1,2}$/;\n if (!hexColorPattern.test(backgroundColor)) {\n backgroundColor = `!${backgroundColor}`;\n }\n }\n const imageUrl = `https://mermaid.ink/img/${mermaidSyntaxEncoded}?bgColor=${backgroundColor}&type=${imageType}`;\n const res = await fetch(imageUrl);\n if (!res.ok) {\n throw new Error(\n [\n `Failed to render the graph using the Mermaid.INK API.`,\n `Status code: ${res.status}`,\n `Status text: ${res.statusText}`,\n ].join(\"\\n\")\n );\n }\n const content = await res.blob();\n return content;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"graph_mermaid.js","names":["nodeLabel: string","nodeColors: Record<string, string>","nodes: Record<string, Node>","edges: Edge[]","config?: {\n firstNode?: string;\n lastNode?: string;\n curveStyle?: string;\n withStyles?: boolean;\n nodeColors?: Record<string, string>;\n wrapLabelNWords?: number;\n }","formatDict: Record<string, string>","edgeGroups: Record<string, Edge[]>","prefixes: string[]","prefix: string","edges","mermaidSyntax: string","config?: {\n /**\n * The type of image to render.\n * @default \"png\"\n */\n imageType?: \"png\" | \"jpeg\" | \"webp\";\n backgroundColor?: string;\n }"],"sources":["../../src/runnables/graph_mermaid.ts"],"sourcesContent":["import { Edge, Node } from \"./types.js\";\nimport { toBase64Url } from \"./utils.js\";\n\nfunction _escapeNodeLabel(nodeLabel: string): string {\n // Escapes the node label for Mermaid syntax.\n return nodeLabel.replace(/[^a-zA-Z-_0-9]/g, \"_\");\n}\n\nconst MARKDOWN_SPECIAL_CHARS = [\"*\", \"_\", \"`\"];\n\nfunction _generateMermaidGraphStyles(\n nodeColors: Record<string, string>\n): string {\n let styles = \"\";\n for (const [className, color] of Object.entries(nodeColors)) {\n styles += `\\tclassDef ${className} ${color};\\n`;\n }\n return styles;\n}\n\n/**\n * Draws a Mermaid graph using the provided graph data\n */\nexport function drawMermaid(\n nodes: Record<string, Node>,\n edges: Edge[],\n config?: {\n firstNode?: string;\n lastNode?: string;\n curveStyle?: string;\n withStyles?: boolean;\n nodeColors?: Record<string, string>;\n wrapLabelNWords?: number;\n }\n): string {\n const {\n firstNode,\n lastNode,\n nodeColors,\n withStyles = true,\n curveStyle = \"linear\",\n wrapLabelNWords = 9,\n } = config ?? {};\n // Initialize Mermaid graph configuration\n let mermaidGraph = withStyles\n ? `%%{init: {'flowchart': {'curve': '${curveStyle}'}}}%%\\ngraph TD;\\n`\n : \"graph TD;\\n\";\n if (withStyles) {\n // Node formatting templates\n const defaultClassLabel = \"default\";\n const formatDict: Record<string, string> = {\n [defaultClassLabel]: \"{0}({1})\",\n };\n if (firstNode !== undefined) {\n formatDict[firstNode] = \"{0}([{1}]):::first\";\n }\n if (lastNode !== undefined) {\n formatDict[lastNode] = \"{0}([{1}]):::last\";\n }\n\n // Add nodes to the graph\n for (const [key, node] of Object.entries(nodes)) {\n const nodeName = node.name.split(\":\").pop() ?? \"\";\n const label = MARKDOWN_SPECIAL_CHARS.some(\n (char) => nodeName.startsWith(char) && nodeName.endsWith(char)\n )\n ? `<p>${nodeName}</p>`\n : nodeName;\n\n let finalLabel = label;\n if (Object.keys(node.metadata ?? {}).length) {\n finalLabel += `<hr/><small><em>${Object.entries(node.metadata ?? {})\n .map(([k, v]) => `${k} = ${v}`)\n .join(\"\\n\")}</em></small>`;\n }\n\n const nodeLabel = (formatDict[key] ?? formatDict[defaultClassLabel])\n .replace(\"{0}\", _escapeNodeLabel(key))\n .replace(\"{1}\", finalLabel);\n\n mermaidGraph += `\\t${nodeLabel}\\n`;\n }\n }\n\n // Group edges by their common prefixes\n const edgeGroups: Record<string, Edge[]> = {};\n for (const edge of edges) {\n const srcParts = edge.source.split(\":\");\n const tgtParts = edge.target.split(\":\");\n const commonPrefix = srcParts\n .filter((src, i) => src === tgtParts[i])\n .join(\":\");\n if (!edgeGroups[commonPrefix]) {\n edgeGroups[commonPrefix] = [];\n }\n edgeGroups[commonPrefix].push(edge);\n }\n\n const seenSubgraphs = new Set<string>();\n\n // sort prefixes by path length for correct nesting\n function sortPrefixesByDepth(prefixes: string[]): string[] {\n return [...prefixes].sort((a, b) => {\n return a.split(\":\").length - b.split(\":\").length;\n });\n }\n\n function addSubgraph(edges: Edge[], prefix: string): void {\n const selfLoop = edges.length === 1 && edges[0].source === edges[0].target;\n if (prefix && !selfLoop) {\n const subgraph = prefix.split(\":\").pop()!;\n\n if (seenSubgraphs.has(prefix)) {\n throw new Error(\n `Found duplicate subgraph '${subgraph}' at '${prefix} -- this likely means that ` +\n \"you're reusing a subgraph node with the same name. \" +\n \"Please adjust your graph to have subgraph nodes with unique names.\"\n );\n }\n\n seenSubgraphs.add(prefix);\n mermaidGraph += `\\tsubgraph ${subgraph}\\n`;\n }\n\n // all nested prefixes for this level, sorted by depth\n const nestedPrefixes = sortPrefixesByDepth(\n Object.keys(edgeGroups).filter(\n (nestedPrefix) =>\n nestedPrefix.startsWith(`${prefix}:`) &&\n nestedPrefix !== prefix &&\n nestedPrefix.split(\":\").length === prefix.split(\":\").length + 1\n )\n );\n\n for (const nestedPrefix of nestedPrefixes) {\n addSubgraph(edgeGroups[nestedPrefix], nestedPrefix);\n }\n\n for (const edge of edges) {\n const { source, target, data, conditional } = edge;\n\n let edgeLabel = \"\";\n if (data !== undefined) {\n let edgeData = data;\n const words = edgeData.split(\" \");\n if (words.length > wrapLabelNWords) {\n edgeData = Array.from(\n { length: Math.ceil(words.length / wrapLabelNWords) },\n (_, i) =>\n words\n .slice(i * wrapLabelNWords, (i + 1) * wrapLabelNWords)\n .join(\" \")\n ).join(\"&nbsp;<br>&nbsp;\");\n }\n edgeLabel = conditional\n ? ` -. &nbsp;${edgeData}&nbsp; .-> `\n : ` -- &nbsp;${edgeData}&nbsp; --> `;\n } else {\n edgeLabel = conditional ? \" -.-> \" : \" --> \";\n }\n\n mermaidGraph += `\\t${_escapeNodeLabel(\n source\n )}${edgeLabel}${_escapeNodeLabel(target)};\\n`;\n }\n\n if (prefix && !selfLoop) {\n mermaidGraph += \"\\tend\\n\";\n }\n }\n\n // Start with the top-level edges (no common prefix)\n addSubgraph(edgeGroups[\"\"] ?? [], \"\");\n\n // Add remaining top-level subgraphs\n for (const prefix in edgeGroups) {\n if (!prefix.includes(\":\") && prefix !== \"\") {\n addSubgraph(edgeGroups[prefix], prefix);\n }\n }\n\n // Add custom styles for nodes\n if (withStyles) {\n mermaidGraph += _generateMermaidGraphStyles(nodeColors ?? {});\n }\n\n return mermaidGraph;\n}\n\n/**\n * Renders Mermaid graph using the Mermaid.INK API.\n *\n * @example\n * ```javascript\n * const image = await drawMermaidImage(mermaidSyntax, {\n * backgroundColor: \"white\",\n * imageType: \"png\",\n * });\n * fs.writeFileSync(\"image.png\", image);\n * ```\n *\n * @param mermaidSyntax - The Mermaid syntax to render.\n * @param config - The configuration for the image.\n * @returns The image as a Blob.\n */\nexport async function drawMermaidImage(\n mermaidSyntax: string,\n config?: {\n /**\n * The type of image to render.\n * @default \"png\"\n */\n imageType?: \"png\" | \"jpeg\" | \"webp\";\n backgroundColor?: string;\n }\n) {\n let backgroundColor = config?.backgroundColor ?? \"white\";\n const imageType = config?.imageType ?? \"png\";\n\n const mermaidSyntaxEncoded = toBase64Url(mermaidSyntax);\n\n // Check if the background color is a hexadecimal color code using regex\n if (backgroundColor !== undefined) {\n const hexColorPattern = /^#(?:[0-9a-fA-F]{3}){1,2}$/;\n if (!hexColorPattern.test(backgroundColor)) {\n backgroundColor = `!${backgroundColor}`;\n }\n }\n const imageUrl = `https://mermaid.ink/img/${mermaidSyntaxEncoded}?bgColor=${backgroundColor}&type=${imageType}`;\n const res = await fetch(imageUrl);\n if (!res.ok) {\n throw new Error(\n [\n `Failed to render the graph using the Mermaid.INK API.`,\n `Status code: ${res.status}`,\n `Status text: ${res.statusText}`,\n ].join(\"\\n\")\n );\n }\n const content = await res.blob();\n return content;\n}\n"],"mappings":"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"}
@@ -62,17 +62,16 @@ var BaseTracer = class extends require_callbacks_base.BaseCallbackHandler {
62
62
  const { dottedOrder: currentDottedOrder, microsecondPrecisionDatestring } = (0, langsmith_run_trees.convertToDottedOrderFormat)(new Date(run.start_time).getTime(), run.id, run.execution_order);
63
63
  const storedRun = { ...run };
64
64
  const parentRun = this.getRunById(storedRun.parent_run_id);
65
- if (storedRun.parent_run_id !== void 0) {
66
- if (parentRun) {
67
- this._addChildRun(parentRun, storedRun);
68
- parentRun.child_execution_order = Math.max(parentRun.child_execution_order, storedRun.child_execution_order);
69
- storedRun.trace_id = parentRun.trace_id;
70
- if (parentRun.dotted_order !== void 0) {
71
- storedRun.dotted_order = [parentRun.dotted_order, currentDottedOrder].join(".");
72
- storedRun._serialized_start_time = microsecondPrecisionDatestring;
73
- }
65
+ if (storedRun.parent_run_id !== void 0) if (parentRun) {
66
+ this._addChildRun(parentRun, storedRun);
67
+ parentRun.child_execution_order = Math.max(parentRun.child_execution_order, storedRun.child_execution_order);
68
+ storedRun.trace_id = parentRun.trace_id;
69
+ if (parentRun.dotted_order !== void 0) {
70
+ storedRun.dotted_order = [parentRun.dotted_order, currentDottedOrder].join(".");
71
+ storedRun._serialized_start_time = microsecondPrecisionDatestring;
74
72
  }
75
- } else {
73
+ } else storedRun.parent_run_id = void 0;
74
+ else {
76
75
  storedRun.trace_id = storedRun.id;
77
76
  storedRun.dotted_order = currentDottedOrder;
78
77
  storedRun._serialized_start_time = microsecondPrecisionDatestring;