@nodetool-ai/base-nodes 0.7.0-rc.11

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 (353) hide show
  1. package/dist/index.d.ts +72 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +270 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/lib/audio-wav.d.ts +66 -0
  6. package/dist/lib/audio-wav.d.ts.map +1 -0
  7. package/dist/lib/audio-wav.js +215 -0
  8. package/dist/lib/audio-wav.js.map +1 -0
  9. package/dist/nodes/agents.d.ts +253 -0
  10. package/dist/nodes/agents.d.ts.map +1 -0
  11. package/dist/nodes/agents.js +2784 -0
  12. package/dist/nodes/agents.js.map +1 -0
  13. package/dist/nodes/anthropic.d.ts +26 -0
  14. package/dist/nodes/anthropic.d.ts.map +1 -0
  15. package/dist/nodes/anthropic.js +133 -0
  16. package/dist/nodes/anthropic.js.map +1 -0
  17. package/dist/nodes/apify.d.ts +120 -0
  18. package/dist/nodes/apify.d.ts.map +1 -0
  19. package/dist/nodes/apify.js +618 -0
  20. package/dist/nodes/apify.js.map +1 -0
  21. package/dist/nodes/audio.d.ts +301 -0
  22. package/dist/nodes/audio.d.ts.map +1 -0
  23. package/dist/nodes/audio.js +1274 -0
  24. package/dist/nodes/audio.js.map +1 -0
  25. package/dist/nodes/code-node.d.ts +34 -0
  26. package/dist/nodes/code-node.d.ts.map +1 -0
  27. package/dist/nodes/code-node.js +343 -0
  28. package/dist/nodes/code-node.js.map +1 -0
  29. package/dist/nodes/code.d.ts +301 -0
  30. package/dist/nodes/code.d.ts.map +1 -0
  31. package/dist/nodes/code.js +850 -0
  32. package/dist/nodes/code.js.map +1 -0
  33. package/dist/nodes/compare.d.ts +18 -0
  34. package/dist/nodes/compare.d.ts.map +1 -0
  35. package/dist/nodes/compare.js +122 -0
  36. package/dist/nodes/compare.js.map +1 -0
  37. package/dist/nodes/constant.d.ts +315 -0
  38. package/dist/nodes/constant.d.ts.map +1 -0
  39. package/dist/nodes/constant.js +715 -0
  40. package/dist/nodes/constant.js.map +1 -0
  41. package/dist/nodes/control.d.ts +83 -0
  42. package/dist/nodes/control.d.ts.map +1 -0
  43. package/dist/nodes/control.js +212 -0
  44. package/dist/nodes/control.js.map +1 -0
  45. package/dist/nodes/data.d.ts +369 -0
  46. package/dist/nodes/data.d.ts.map +1 -0
  47. package/dist/nodes/data.js +1590 -0
  48. package/dist/nodes/data.js.map +1 -0
  49. package/dist/nodes/document.d.ts +134 -0
  50. package/dist/nodes/document.d.ts.map +1 -0
  51. package/dist/nodes/document.js +984 -0
  52. package/dist/nodes/document.js.map +1 -0
  53. package/dist/nodes/extended-placeholders.d.ts +6 -0
  54. package/dist/nodes/extended-placeholders.d.ts.map +1 -0
  55. package/dist/nodes/extended-placeholders.js +19 -0
  56. package/dist/nodes/extended-placeholders.js.map +1 -0
  57. package/dist/nodes/gemini.d.ts +109 -0
  58. package/dist/nodes/gemini.d.ts.map +1 -0
  59. package/dist/nodes/gemini.js +861 -0
  60. package/dist/nodes/gemini.js.map +1 -0
  61. package/dist/nodes/generators.d.ts +84 -0
  62. package/dist/nodes/generators.d.ts.map +1 -0
  63. package/dist/nodes/generators.js +937 -0
  64. package/dist/nodes/generators.js.map +1 -0
  65. package/dist/nodes/image.d.ts +232 -0
  66. package/dist/nodes/image.d.ts.map +1 -0
  67. package/dist/nodes/image.js +1395 -0
  68. package/dist/nodes/image.js.map +1 -0
  69. package/dist/nodes/input.d.ts +445 -0
  70. package/dist/nodes/input.d.ts.map +1 -0
  71. package/dist/nodes/input.js +1459 -0
  72. package/dist/nodes/input.js.map +1 -0
  73. package/dist/nodes/kie-dynamic.d.ts +31 -0
  74. package/dist/nodes/kie-dynamic.d.ts.map +1 -0
  75. package/dist/nodes/kie-dynamic.js +270 -0
  76. package/dist/nodes/kie-dynamic.js.map +1 -0
  77. package/dist/nodes/lib-audio-dsp.d.ts +85 -0
  78. package/dist/nodes/lib-audio-dsp.d.ts.map +1 -0
  79. package/dist/nodes/lib-audio-dsp.js +450 -0
  80. package/dist/nodes/lib-audio-dsp.js.map +1 -0
  81. package/dist/nodes/lib-audio-effects.d.ts +116 -0
  82. package/dist/nodes/lib-audio-effects.d.ts.map +1 -0
  83. package/dist/nodes/lib-audio-effects.js +905 -0
  84. package/dist/nodes/lib-audio-effects.js.map +1 -0
  85. package/dist/nodes/lib-browser.d.ts +99 -0
  86. package/dist/nodes/lib-browser.d.ts.map +1 -0
  87. package/dist/nodes/lib-browser.js +692 -0
  88. package/dist/nodes/lib-browser.js.map +1 -0
  89. package/dist/nodes/lib-charts.d.ts +20 -0
  90. package/dist/nodes/lib-charts.d.ts.map +1 -0
  91. package/dist/nodes/lib-charts.js +245 -0
  92. package/dist/nodes/lib-charts.js.map +1 -0
  93. package/dist/nodes/lib-datetime.d.ts +108 -0
  94. package/dist/nodes/lib-datetime.d.ts.map +1 -0
  95. package/dist/nodes/lib-datetime.js +421 -0
  96. package/dist/nodes/lib-datetime.js.map +1 -0
  97. package/dist/nodes/lib-doc-convert.d.ts +19 -0
  98. package/dist/nodes/lib-doc-convert.d.ts.map +1 -0
  99. package/dist/nodes/lib-doc-convert.js +257 -0
  100. package/dist/nodes/lib-doc-convert.js.map +1 -0
  101. package/dist/nodes/lib-doc-transform.d.ts +39 -0
  102. package/dist/nodes/lib-doc-transform.d.ts.map +1 -0
  103. package/dist/nodes/lib-doc-transform.js +335 -0
  104. package/dist/nodes/lib-doc-transform.js.map +1 -0
  105. package/dist/nodes/lib-docx.d.ts +106 -0
  106. package/dist/nodes/lib-docx.d.ts.map +1 -0
  107. package/dist/nodes/lib-docx.js +595 -0
  108. package/dist/nodes/lib-docx.js.map +1 -0
  109. package/dist/nodes/lib-epub.d.ts +55 -0
  110. package/dist/nodes/lib-epub.d.ts.map +1 -0
  111. package/dist/nodes/lib-epub.js +220 -0
  112. package/dist/nodes/lib-epub.js.map +1 -0
  113. package/dist/nodes/lib-excel.d.ts +74 -0
  114. package/dist/nodes/lib-excel.d.ts.map +1 -0
  115. package/dist/nodes/lib-excel.js +448 -0
  116. package/dist/nodes/lib-excel.js.map +1 -0
  117. package/dist/nodes/lib-graphql.d.ts +66 -0
  118. package/dist/nodes/lib-graphql.d.ts.map +1 -0
  119. package/dist/nodes/lib-graphql.js +333 -0
  120. package/dist/nodes/lib-graphql.js.map +1 -0
  121. package/dist/nodes/lib-grid.d.ts +27 -0
  122. package/dist/nodes/lib-grid.d.ts.map +1 -0
  123. package/dist/nodes/lib-grid.js +172 -0
  124. package/dist/nodes/lib-grid.js.map +1 -0
  125. package/dist/nodes/lib-html-parse.d.ts +108 -0
  126. package/dist/nodes/lib-html-parse.d.ts.map +1 -0
  127. package/dist/nodes/lib-html-parse.js +365 -0
  128. package/dist/nodes/lib-html-parse.js.map +1 -0
  129. package/dist/nodes/lib-http.d.ts +98 -0
  130. package/dist/nodes/lib-http.d.ts.map +1 -0
  131. package/dist/nodes/lib-http.js +267 -0
  132. package/dist/nodes/lib-http.js.map +1 -0
  133. package/dist/nodes/lib-image-color-grading.d.ts +3 -0
  134. package/dist/nodes/lib-image-color-grading.d.ts.map +1 -0
  135. package/dist/nodes/lib-image-color-grading.js +1386 -0
  136. package/dist/nodes/lib-image-color-grading.js.map +1 -0
  137. package/dist/nodes/lib-image-draw.d.ts +3 -0
  138. package/dist/nodes/lib-image-draw.d.ts.map +1 -0
  139. package/dist/nodes/lib-image-draw.js +470 -0
  140. package/dist/nodes/lib-image-draw.js.map +1 -0
  141. package/dist/nodes/lib-image-enhance.d.ts +3 -0
  142. package/dist/nodes/lib-image-enhance.d.ts.map +1 -0
  143. package/dist/nodes/lib-image-enhance.js +731 -0
  144. package/dist/nodes/lib-image-enhance.js.map +1 -0
  145. package/dist/nodes/lib-image-filter.d.ts +3 -0
  146. package/dist/nodes/lib-image-filter.d.ts.map +1 -0
  147. package/dist/nodes/lib-image-filter.js +684 -0
  148. package/dist/nodes/lib-image-filter.js.map +1 -0
  149. package/dist/nodes/lib-image-utils.d.ts +24 -0
  150. package/dist/nodes/lib-image-utils.d.ts.map +1 -0
  151. package/dist/nodes/lib-image-utils.js +150 -0
  152. package/dist/nodes/lib-image-utils.js.map +1 -0
  153. package/dist/nodes/lib-mail.d.ts +74 -0
  154. package/dist/nodes/lib-mail.d.ts.map +1 -0
  155. package/dist/nodes/lib-mail.js +452 -0
  156. package/dist/nodes/lib-mail.js.map +1 -0
  157. package/dist/nodes/lib-markdown.d.ts +70 -0
  158. package/dist/nodes/lib-markdown.d.ts.map +1 -0
  159. package/dist/nodes/lib-markdown.js +236 -0
  160. package/dist/nodes/lib-markdown.js.map +1 -0
  161. package/dist/nodes/lib-nlp.d.ts +98 -0
  162. package/dist/nodes/lib-nlp.d.ts.map +1 -0
  163. package/dist/nodes/lib-nlp.js +374 -0
  164. package/dist/nodes/lib-nlp.js.map +1 -0
  165. package/dist/nodes/lib-notion.d.ts +99 -0
  166. package/dist/nodes/lib-notion.d.ts.map +1 -0
  167. package/dist/nodes/lib-notion.js +601 -0
  168. package/dist/nodes/lib-notion.js.map +1 -0
  169. package/dist/nodes/lib-ocr.d.ts +31 -0
  170. package/dist/nodes/lib-ocr.d.ts.map +1 -0
  171. package/dist/nodes/lib-ocr.js +143 -0
  172. package/dist/nodes/lib-ocr.js.map +1 -0
  173. package/dist/nodes/lib-os.d.ts +312 -0
  174. package/dist/nodes/lib-os.d.ts.map +1 -0
  175. package/dist/nodes/lib-os.js +909 -0
  176. package/dist/nodes/lib-os.js.map +1 -0
  177. package/dist/nodes/lib-pdf.d.ts +142 -0
  178. package/dist/nodes/lib-pdf.d.ts.map +1 -0
  179. package/dist/nodes/lib-pdf.js +871 -0
  180. package/dist/nodes/lib-pdf.js.map +1 -0
  181. package/dist/nodes/lib-pptx.d.ts +29 -0
  182. package/dist/nodes/lib-pptx.d.ts.map +1 -0
  183. package/dist/nodes/lib-pptx.js +122 -0
  184. package/dist/nodes/lib-pptx.js.map +1 -0
  185. package/dist/nodes/lib-rss.d.ts +31 -0
  186. package/dist/nodes/lib-rss.d.ts.map +1 -0
  187. package/dist/nodes/lib-rss.js +163 -0
  188. package/dist/nodes/lib-rss.js.map +1 -0
  189. package/dist/nodes/lib-s3.d.ts +112 -0
  190. package/dist/nodes/lib-s3.d.ts.map +1 -0
  191. package/dist/nodes/lib-s3.js +521 -0
  192. package/dist/nodes/lib-s3.js.map +1 -0
  193. package/dist/nodes/lib-secret.d.ts +15 -0
  194. package/dist/nodes/lib-secret.d.ts.map +1 -0
  195. package/dist/nodes/lib-secret.js +42 -0
  196. package/dist/nodes/lib-secret.js.map +1 -0
  197. package/dist/nodes/lib-sqlite.d.ts +102 -0
  198. package/dist/nodes/lib-sqlite.d.ts.map +1 -0
  199. package/dist/nodes/lib-sqlite.js +532 -0
  200. package/dist/nodes/lib-sqlite.js.map +1 -0
  201. package/dist/nodes/lib-supabase.d.ts +86 -0
  202. package/dist/nodes/lib-supabase.d.ts.map +1 -0
  203. package/dist/nodes/lib-supabase.js +425 -0
  204. package/dist/nodes/lib-supabase.js.map +1 -0
  205. package/dist/nodes/lib-svg.d.ts +199 -0
  206. package/dist/nodes/lib-svg.d.ts.map +1 -0
  207. package/dist/nodes/lib-svg.js +1027 -0
  208. package/dist/nodes/lib-svg.js.map +1 -0
  209. package/dist/nodes/lib-tensorflow.d.ts +71 -0
  210. package/dist/nodes/lib-tensorflow.d.ts.map +1 -0
  211. package/dist/nodes/lib-tensorflow.js +351 -0
  212. package/dist/nodes/lib-tensorflow.js.map +1 -0
  213. package/dist/nodes/lib-twilio.d.ts +71 -0
  214. package/dist/nodes/lib-twilio.d.ts.map +1 -0
  215. package/dist/nodes/lib-twilio.js +469 -0
  216. package/dist/nodes/lib-twilio.js.map +1 -0
  217. package/dist/nodes/lib-validate.d.ts +84 -0
  218. package/dist/nodes/lib-validate.d.ts.map +1 -0
  219. package/dist/nodes/lib-validate.js +215 -0
  220. package/dist/nodes/lib-validate.js.map +1 -0
  221. package/dist/nodes/lib-video-download.d.ts +26 -0
  222. package/dist/nodes/lib-video-download.d.ts.map +1 -0
  223. package/dist/nodes/lib-video-download.js +299 -0
  224. package/dist/nodes/lib-video-download.js.map +1 -0
  225. package/dist/nodes/messaging.d.ts +88 -0
  226. package/dist/nodes/messaging.d.ts.map +1 -0
  227. package/dist/nodes/messaging.js +418 -0
  228. package/dist/nodes/messaging.js.map +1 -0
  229. package/dist/nodes/mistral.d.ts +83 -0
  230. package/dist/nodes/mistral.d.ts.map +1 -0
  231. package/dist/nodes/mistral.js +450 -0
  232. package/dist/nodes/mistral.js.map +1 -0
  233. package/dist/nodes/model3d/analysis.d.ts +13 -0
  234. package/dist/nodes/model3d/analysis.d.ts.map +1 -0
  235. package/dist/nodes/model3d/analysis.js +36 -0
  236. package/dist/nodes/model3d/analysis.js.map +1 -0
  237. package/dist/nodes/model3d/base.d.ts +11 -0
  238. package/dist/nodes/model3d/base.d.ts.map +1 -0
  239. package/dist/nodes/model3d/base.js +20 -0
  240. package/dist/nodes/model3d/base.js.map +1 -0
  241. package/dist/nodes/model3d/boolean-ops.d.ts +2 -0
  242. package/dist/nodes/model3d/boolean-ops.d.ts.map +1 -0
  243. package/dist/nodes/model3d/boolean-ops.js +172 -0
  244. package/dist/nodes/model3d/boolean-ops.js.map +1 -0
  245. package/dist/nodes/model3d/cleanup.d.ts +47 -0
  246. package/dist/nodes/model3d/cleanup.d.ts.map +1 -0
  247. package/dist/nodes/model3d/cleanup.js +136 -0
  248. package/dist/nodes/model3d/cleanup.js.map +1 -0
  249. package/dist/nodes/model3d/convert.d.ts +14 -0
  250. package/dist/nodes/model3d/convert.d.ts.map +1 -0
  251. package/dist/nodes/model3d/convert.js +64 -0
  252. package/dist/nodes/model3d/convert.js.map +1 -0
  253. package/dist/nodes/model3d/defaults.d.ts +34 -0
  254. package/dist/nodes/model3d/defaults.d.ts.map +1 -0
  255. package/dist/nodes/model3d/defaults.js +28 -0
  256. package/dist/nodes/model3d/defaults.js.map +1 -0
  257. package/dist/nodes/model3d/document-ops.d.ts +4 -0
  258. package/dist/nodes/model3d/document-ops.d.ts.map +1 -0
  259. package/dist/nodes/model3d/document-ops.js +40 -0
  260. package/dist/nodes/model3d/document-ops.js.map +1 -0
  261. package/dist/nodes/model3d/generation.d.ts +39 -0
  262. package/dist/nodes/model3d/generation.d.ts.map +1 -0
  263. package/dist/nodes/model3d/generation.js +179 -0
  264. package/dist/nodes/model3d/generation.js.map +1 -0
  265. package/dist/nodes/model3d/glb.d.ts +29 -0
  266. package/dist/nodes/model3d/glb.d.ts.map +1 -0
  267. package/dist/nodes/model3d/glb.js +255 -0
  268. package/dist/nodes/model3d/glb.js.map +1 -0
  269. package/dist/nodes/model3d/index.d.ts +20 -0
  270. package/dist/nodes/model3d/index.d.ts.map +1 -0
  271. package/dist/nodes/model3d/index.js +38 -0
  272. package/dist/nodes/model3d/index.js.map +1 -0
  273. package/dist/nodes/model3d/io.d.ts +38 -0
  274. package/dist/nodes/model3d/io.d.ts.map +1 -0
  275. package/dist/nodes/model3d/io.js +162 -0
  276. package/dist/nodes/model3d/io.js.map +1 -0
  277. package/dist/nodes/model3d/mesh-ops.d.ts +40 -0
  278. package/dist/nodes/model3d/mesh-ops.d.ts.map +1 -0
  279. package/dist/nodes/model3d/mesh-ops.js +775 -0
  280. package/dist/nodes/model3d/mesh-ops.js.map +1 -0
  281. package/dist/nodes/model3d/nodes.d.ts +2 -0
  282. package/dist/nodes/model3d/nodes.d.ts.map +1 -0
  283. package/dist/nodes/model3d/nodes.js +2 -0
  284. package/dist/nodes/model3d/nodes.js.map +1 -0
  285. package/dist/nodes/model3d/ops.d.ts +37 -0
  286. package/dist/nodes/model3d/ops.d.ts.map +1 -0
  287. package/dist/nodes/model3d/ops.js +137 -0
  288. package/dist/nodes/model3d/ops.js.map +1 -0
  289. package/dist/nodes/model3d/transforms.d.ts +49 -0
  290. package/dist/nodes/model3d/transforms.d.ts.map +1 -0
  291. package/dist/nodes/model3d/transforms.js +142 -0
  292. package/dist/nodes/model3d/transforms.js.map +1 -0
  293. package/dist/nodes/model3d/types.d.ts +81 -0
  294. package/dist/nodes/model3d/types.d.ts.map +1 -0
  295. package/dist/nodes/model3d/types.js +2 -0
  296. package/dist/nodes/model3d/types.js.map +1 -0
  297. package/dist/nodes/model3d/utils.d.ts +34 -0
  298. package/dist/nodes/model3d/utils.d.ts.map +1 -0
  299. package/dist/nodes/model3d/utils.js +185 -0
  300. package/dist/nodes/model3d/utils.js.map +1 -0
  301. package/dist/nodes/model3d.d.ts +2 -0
  302. package/dist/nodes/model3d.d.ts.map +1 -0
  303. package/dist/nodes/model3d.js +2 -0
  304. package/dist/nodes/model3d.js.map +1 -0
  305. package/dist/nodes/openai.d.ts +172 -0
  306. package/dist/nodes/openai.d.ts.map +1 -0
  307. package/dist/nodes/openai.js +1294 -0
  308. package/dist/nodes/openai.js.map +1 -0
  309. package/dist/nodes/output.d.ts +29 -0
  310. package/dist/nodes/output.d.ts.map +1 -0
  311. package/dist/nodes/output.js +87 -0
  312. package/dist/nodes/output.js.map +1 -0
  313. package/dist/nodes/sandbox.d.ts +67 -0
  314. package/dist/nodes/sandbox.d.ts.map +1 -0
  315. package/dist/nodes/sandbox.js +681 -0
  316. package/dist/nodes/sandbox.js.map +1 -0
  317. package/dist/nodes/search.d.ts +117 -0
  318. package/dist/nodes/search.d.ts.map +1 -0
  319. package/dist/nodes/search.js +607 -0
  320. package/dist/nodes/search.js.map +1 -0
  321. package/dist/nodes/team.d.ts +74 -0
  322. package/dist/nodes/team.d.ts.map +1 -0
  323. package/dist/nodes/team.js +304 -0
  324. package/dist/nodes/team.js.map +1 -0
  325. package/dist/nodes/text-extra.d.ts +633 -0
  326. package/dist/nodes/text-extra.d.ts.map +1 -0
  327. package/dist/nodes/text-extra.js +2226 -0
  328. package/dist/nodes/text-extra.js.map +1 -0
  329. package/dist/nodes/tool-agents.d.ts +334 -0
  330. package/dist/nodes/tool-agents.d.ts.map +1 -0
  331. package/dist/nodes/tool-agents.js +1861 -0
  332. package/dist/nodes/tool-agents.js.map +1 -0
  333. package/dist/nodes/triggers.d.ts +107 -0
  334. package/dist/nodes/triggers.d.ts.map +1 -0
  335. package/dist/nodes/triggers.js +706 -0
  336. package/dist/nodes/triggers.js.map +1 -0
  337. package/dist/nodes/vector.d.ts +168 -0
  338. package/dist/nodes/vector.d.ts.map +1 -0
  339. package/dist/nodes/vector.js +1121 -0
  340. package/dist/nodes/vector.js.map +1 -0
  341. package/dist/nodes/video.d.ts +387 -0
  342. package/dist/nodes/video.d.ts.map +1 -0
  343. package/dist/nodes/video.js +2361 -0
  344. package/dist/nodes/video.js.map +1 -0
  345. package/dist/nodes/workflow.d.ts +24 -0
  346. package/dist/nodes/workflow.d.ts.map +1 -0
  347. package/dist/nodes/workflow.js +146 -0
  348. package/dist/nodes/workflow.js.map +1 -0
  349. package/dist/nodes/workspace.d.ts +203 -0
  350. package/dist/nodes/workspace.d.ts.map +1 -0
  351. package/dist/nodes/workspace.js +795 -0
  352. package/dist/nodes/workspace.js.map +1 -0
  353. package/package.json +103 -0
@@ -0,0 +1,2226 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { BaseNode, prop } from "@nodetool-ai/node-sdk";
8
+ import { promises as fs } from "node:fs";
9
+ import { extname, join } from "node:path";
10
+ function flagsFromOpts(opts) {
11
+ let flags = "";
12
+ if (opts.ignorecase)
13
+ flags += "i";
14
+ if (opts.multiline)
15
+ flags += "m";
16
+ if (opts.dotall)
17
+ flags += "s";
18
+ return flags;
19
+ }
20
+ function toTitleCase(value) {
21
+ return value.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase());
22
+ }
23
+ function folderPath(value) {
24
+ if (typeof value === "string")
25
+ return value;
26
+ if (!value || typeof value !== "object")
27
+ return "";
28
+ const record = value;
29
+ if (typeof record.path === "string")
30
+ return record.path;
31
+ if (typeof record.uri === "string") {
32
+ return record.uri.startsWith("file://")
33
+ ? record.uri.slice("file://".length)
34
+ : record.uri;
35
+ }
36
+ return "";
37
+ }
38
+ function modelConfig(props) {
39
+ const model = (props.model ?? {});
40
+ return {
41
+ providerId: typeof model.provider === "string" ? model.provider : "",
42
+ modelId: typeof model.id === "string" ? model.id : ""
43
+ };
44
+ }
45
+ export class SplitTextNode extends BaseNode {
46
+ static nodeType = "nodetool.text.Split";
47
+ static title = "Split Text";
48
+ static description = "Separates text into a list of strings based on a specified delimiter.\n text, split, tokenize";
49
+ static metadataOutputTypes = {
50
+ output: "list[str]"
51
+ };
52
+ async process() {
53
+ const text = String(this.text ?? this.text ?? "");
54
+ const delimiter = String(this.delimiter ?? this.delimiter ?? ",");
55
+ return { output: text.split(delimiter) };
56
+ }
57
+ }
58
+ __decorate([
59
+ prop({ type: "str", default: "", title: "Text" })
60
+ ], SplitTextNode.prototype, "text", void 0);
61
+ __decorate([
62
+ prop({ type: "str", default: ",", title: "Delimiter" })
63
+ ], SplitTextNode.prototype, "delimiter", void 0);
64
+ export class ExtractTextNode extends BaseNode {
65
+ static nodeType = "nodetool.text.Extract";
66
+ static title = "Extract Text";
67
+ static description = "Extracts a substring from input text.\n text, extract, substring";
68
+ static metadataOutputTypes = {
69
+ output: "str"
70
+ };
71
+ async process() {
72
+ const text = String(this.text ?? this.text ?? "");
73
+ const start = Number(this.start ?? this.start ?? 0);
74
+ const end = Number(this.end ?? this.end ?? 0);
75
+ return { output: text.slice(start, end) };
76
+ }
77
+ }
78
+ __decorate([
79
+ prop({ type: "str", default: "", title: "Text" })
80
+ ], ExtractTextNode.prototype, "text", void 0);
81
+ __decorate([
82
+ prop({ type: "int", default: 0, title: "Start" })
83
+ ], ExtractTextNode.prototype, "start", void 0);
84
+ __decorate([
85
+ prop({ type: "int", default: 0, title: "End" })
86
+ ], ExtractTextNode.prototype, "end", void 0);
87
+ export class ChunkTextNode extends BaseNode {
88
+ static nodeType = "nodetool.text.Chunk";
89
+ static title = "Split Text into Chunks";
90
+ static description = "Splits text into chunks of specified word length.\n text, chunk, split";
91
+ static metadataOutputTypes = {
92
+ output: "list[str]"
93
+ };
94
+ async process() {
95
+ const text = String(this.text ?? this.text ?? "");
96
+ const length = Number(this.length ?? this.length ?? 100);
97
+ const overlap = Number(this.overlap ?? this.overlap ?? 0);
98
+ const separator = String(this.separator ?? this.separator ?? " ");
99
+ const step = length - overlap;
100
+ if (length < 1 || step <= 0) {
101
+ throw new Error("Invalid chunk parameters");
102
+ }
103
+ const words = text.split(separator);
104
+ const chunks = [];
105
+ for (let i = 0; i < words.length; i += step) {
106
+ chunks.push(words.slice(i, i + length).join(" "));
107
+ }
108
+ return { output: chunks };
109
+ }
110
+ }
111
+ __decorate([
112
+ prop({ type: "str", default: "", title: "Text" })
113
+ ], ChunkTextNode.prototype, "text", void 0);
114
+ __decorate([
115
+ prop({ type: "int", default: 100, title: "Length", min: 1, max: 1000 })
116
+ ], ChunkTextNode.prototype, "length", void 0);
117
+ __decorate([
118
+ prop({ type: "int", default: 0, title: "Overlap" })
119
+ ], ChunkTextNode.prototype, "overlap", void 0);
120
+ __decorate([
121
+ prop({ type: "str", default: " ", title: "Separator" })
122
+ ], ChunkTextNode.prototype, "separator", void 0);
123
+ export class ExtractRegexNode extends BaseNode {
124
+ static nodeType = "nodetool.text.ExtractRegex";
125
+ static title = "Extract Regex Groups";
126
+ static description = "Extracts substrings matching regex groups from text.\n text, regex, extract\n\n Use cases:\n - Extracting structured data (e.g., dates, emails) from unstructured text\n - Parsing specific patterns in log files or documents\n - Isolating relevant information from complex text formats";
127
+ static metadataOutputTypes = {
128
+ output: "list[str]"
129
+ };
130
+ async process() {
131
+ const text = String(this.text ?? this.text ?? "");
132
+ const pattern = String(this.regex ?? this.regex ?? "");
133
+ const flags = flagsFromOpts({
134
+ dotall: this.dotall ?? this.dotall,
135
+ ignorecase: this.ignorecase ?? this.ignorecase,
136
+ multiline: this.multiline ?? this.multiline
137
+ });
138
+ const match = new RegExp(pattern, flags).exec(text);
139
+ if (!match) {
140
+ return { output: [] };
141
+ }
142
+ return { output: match.slice(1) };
143
+ }
144
+ }
145
+ __decorate([
146
+ prop({ type: "str", default: "", title: "Text" })
147
+ ], ExtractRegexNode.prototype, "text", void 0);
148
+ __decorate([
149
+ prop({ type: "str", default: "", title: "Regex" })
150
+ ], ExtractRegexNode.prototype, "regex", void 0);
151
+ __decorate([
152
+ prop({ type: "bool", default: false, title: "Dotall" })
153
+ ], ExtractRegexNode.prototype, "dotall", void 0);
154
+ __decorate([
155
+ prop({ type: "bool", default: false, title: "Ignorecase" })
156
+ ], ExtractRegexNode.prototype, "ignorecase", void 0);
157
+ __decorate([
158
+ prop({ type: "bool", default: false, title: "Multiline" })
159
+ ], ExtractRegexNode.prototype, "multiline", void 0);
160
+ export class FindAllRegexNode extends BaseNode {
161
+ static nodeType = "nodetool.text.FindAllRegex";
162
+ static title = "Find All Regex Matches";
163
+ static description = "Finds all regex matches in text as separate substrings.\n text, regex, find";
164
+ static metadataOutputTypes = {
165
+ output: "list[str]"
166
+ };
167
+ async process() {
168
+ const text = String(this.text ?? this.text ?? "");
169
+ const pattern = String(this.regex ?? this.regex ?? "");
170
+ const flags = `${flagsFromOpts({
171
+ dotall: this.dotall ?? this.dotall,
172
+ ignorecase: this.ignorecase ?? this.ignorecase,
173
+ multiline: this.multiline ?? this.multiline
174
+ })}g`;
175
+ const matches = [...text.matchAll(new RegExp(pattern, flags))].map((m) => m[0]);
176
+ return { output: matches };
177
+ }
178
+ }
179
+ __decorate([
180
+ prop({ type: "str", default: "", title: "Text" })
181
+ ], FindAllRegexNode.prototype, "text", void 0);
182
+ __decorate([
183
+ prop({ type: "str", default: "", title: "Regex" })
184
+ ], FindAllRegexNode.prototype, "regex", void 0);
185
+ __decorate([
186
+ prop({ type: "bool", default: false, title: "Dotall" })
187
+ ], FindAllRegexNode.prototype, "dotall", void 0);
188
+ __decorate([
189
+ prop({ type: "bool", default: false, title: "Ignorecase" })
190
+ ], FindAllRegexNode.prototype, "ignorecase", void 0);
191
+ __decorate([
192
+ prop({ type: "bool", default: false, title: "Multiline" })
193
+ ], FindAllRegexNode.prototype, "multiline", void 0);
194
+ export class TextParseJSONNode extends BaseNode {
195
+ static nodeType = "nodetool.text.ParseJSON";
196
+ static title = "Parse JSON String";
197
+ static description = "Parses a JSON string into a Python object.\n json, parse, convert";
198
+ static metadataOutputTypes = {
199
+ output: "any"
200
+ };
201
+ async process() {
202
+ const text = String(this.text ?? this.text ?? "");
203
+ return { output: JSON.parse(text) };
204
+ }
205
+ }
206
+ __decorate([
207
+ prop({ type: "str", default: "", title: "JSON string" })
208
+ ], TextParseJSONNode.prototype, "text", void 0);
209
+ function jsonPathFind(path, root) {
210
+ if (!path.startsWith("$")) {
211
+ return [];
212
+ }
213
+ const tokens = path
214
+ .replace(/^\$\./, "")
215
+ .replace(/\[(\d+)\]/g, ".$1")
216
+ .split(".")
217
+ .filter(Boolean);
218
+ let current = [root];
219
+ for (const token of tokens) {
220
+ const next = [];
221
+ for (const value of current) {
222
+ if (token === "*") {
223
+ if (Array.isArray(value)) {
224
+ next.push(...value);
225
+ }
226
+ else if (value && typeof value === "object") {
227
+ next.push(...Object.values(value));
228
+ }
229
+ continue;
230
+ }
231
+ if (Array.isArray(value)) {
232
+ const idx = Number(token);
233
+ if (Number.isInteger(idx) && idx >= 0 && idx < value.length) {
234
+ next.push(value[idx]);
235
+ }
236
+ continue;
237
+ }
238
+ if (value && typeof value === "object" && token in value) {
239
+ next.push(value[token]);
240
+ }
241
+ }
242
+ current = next;
243
+ if (current.length === 0) {
244
+ break;
245
+ }
246
+ }
247
+ return current;
248
+ }
249
+ export class ExtractJSONNode extends BaseNode {
250
+ static nodeType = "nodetool.text.ExtractJSON";
251
+ static title = "Extract JSON";
252
+ static description = "Extracts data from JSON using JSONPath expressions.\n json, extract, jsonpath";
253
+ static metadataOutputTypes = {
254
+ output: "any"
255
+ };
256
+ async process() {
257
+ const text = String(this.text ?? this.text ?? "");
258
+ const jsonPath = String(this.json_path ?? this.json_path ?? "$.*");
259
+ const findAll = Boolean(this.find_all ?? this.find_all ?? false);
260
+ const parsed = JSON.parse(text);
261
+ const matches = jsonPathFind(jsonPath, parsed);
262
+ if (findAll) {
263
+ return { output: matches };
264
+ }
265
+ if (matches.length === 0) {
266
+ throw new Error("JSONPath did not match any value");
267
+ }
268
+ return { output: matches[0] };
269
+ }
270
+ }
271
+ __decorate([
272
+ prop({ type: "str", default: "", title: "JSON Text" })
273
+ ], ExtractJSONNode.prototype, "text", void 0);
274
+ __decorate([
275
+ prop({ type: "str", default: "$.*", title: "JSONPath Expression" })
276
+ ], ExtractJSONNode.prototype, "json_path", void 0);
277
+ __decorate([
278
+ prop({ type: "bool", default: false, title: "Find All" })
279
+ ], ExtractJSONNode.prototype, "find_all", void 0);
280
+ export class RegexMatchNode extends BaseNode {
281
+ static nodeType = "nodetool.text.RegexMatch";
282
+ static title = "Find Regex Matches";
283
+ static description = "Find all matches of a regex pattern in text.\n regex, search, pattern, match\n\n Use cases:\n - Extract specific patterns from text\n - Validate text against patterns\n - Find all occurrences of a pattern";
284
+ static metadataOutputTypes = {
285
+ output: "list[str]"
286
+ };
287
+ async process() {
288
+ const text = String(this.text ?? this.text ?? "");
289
+ const pattern = String(this.pattern ?? this.pattern ?? "");
290
+ const group = this.group ?? this.group;
291
+ if (group === null || group === undefined) {
292
+ return {
293
+ output: [...text.matchAll(new RegExp(pattern, "g"))].map((m) => m[0])
294
+ };
295
+ }
296
+ const groupIndex = Number(group);
297
+ const out = [...text.matchAll(new RegExp(pattern, "g"))].map((m) => m[groupIndex]);
298
+ return { output: out.filter((v) => v !== undefined) };
299
+ }
300
+ }
301
+ __decorate([
302
+ prop({
303
+ type: "str",
304
+ default: "",
305
+ title: "Text",
306
+ description: "Text to search in"
307
+ })
308
+ ], RegexMatchNode.prototype, "text", void 0);
309
+ __decorate([
310
+ prop({
311
+ type: "str",
312
+ default: "",
313
+ title: "Pattern",
314
+ description: "Regular expression pattern"
315
+ })
316
+ ], RegexMatchNode.prototype, "pattern", void 0);
317
+ __decorate([
318
+ prop({
319
+ type: "int",
320
+ default: 0,
321
+ title: "Group",
322
+ description: "Capture group to extract (0 for full match)"
323
+ })
324
+ ], RegexMatchNode.prototype, "group", void 0);
325
+ export class RegexReplaceNode extends BaseNode {
326
+ static nodeType = "nodetool.text.RegexReplace";
327
+ static title = "Replace with Regex";
328
+ static description = "Replace text matching a regex pattern.\n regex, replace, substitute\n\n Use cases:\n - Clean or standardize text\n - Remove unwanted patterns\n - Transform text formats";
329
+ static metadataOutputTypes = {
330
+ output: "str"
331
+ };
332
+ async process() {
333
+ let text = String(this.text ?? this.text ?? "");
334
+ const pattern = String(this.pattern ?? this.pattern ?? "");
335
+ const replacement = String(this.replacement ?? this.replacement ?? "");
336
+ const count = Number(this.count ?? this.count ?? 0);
337
+ if (count <= 0) {
338
+ return { output: text.replace(new RegExp(pattern, "g"), replacement) };
339
+ }
340
+ const regex = new RegExp(pattern, "g");
341
+ let replaced = 0;
342
+ text = text.replace(regex, (match) => {
343
+ if (replaced >= count) {
344
+ return match;
345
+ }
346
+ replaced += 1;
347
+ return replacement;
348
+ });
349
+ return { output: text };
350
+ }
351
+ }
352
+ __decorate([
353
+ prop({
354
+ type: "str",
355
+ default: "",
356
+ title: "Text",
357
+ description: "Text to perform replacements on"
358
+ })
359
+ ], RegexReplaceNode.prototype, "text", void 0);
360
+ __decorate([
361
+ prop({
362
+ type: "str",
363
+ default: "",
364
+ title: "Pattern",
365
+ description: "Regular expression pattern"
366
+ })
367
+ ], RegexReplaceNode.prototype, "pattern", void 0);
368
+ __decorate([
369
+ prop({
370
+ type: "str",
371
+ default: "",
372
+ title: "Replacement",
373
+ description: "Replacement text"
374
+ })
375
+ ], RegexReplaceNode.prototype, "replacement", void 0);
376
+ __decorate([
377
+ prop({
378
+ type: "int",
379
+ default: 0,
380
+ title: "Count",
381
+ description: "Maximum replacements (0 for unlimited)"
382
+ })
383
+ ], RegexReplaceNode.prototype, "count", void 0);
384
+ export class RegexSplitNode extends BaseNode {
385
+ static nodeType = "nodetool.text.RegexSplit";
386
+ static title = "Split with Regex";
387
+ static description = "Split text using a regex pattern as delimiter.\n regex, split, tokenize\n\n Use cases:\n - Parse structured text\n - Extract fields from formatted strings\n - Tokenize text";
388
+ static metadataOutputTypes = {
389
+ output: "list[str]"
390
+ };
391
+ async process() {
392
+ const text = String(this.text ?? this.text ?? "");
393
+ const pattern = String(this.pattern ?? this.pattern ?? "");
394
+ const maxsplit = Number(this.maxsplit ?? this.maxsplit ?? 0);
395
+ if (maxsplit <= 0) {
396
+ return { output: text.split(new RegExp(pattern)) };
397
+ }
398
+ const result = [];
399
+ let remaining = text;
400
+ let count = 0;
401
+ const re = new RegExp(pattern);
402
+ let match;
403
+ while (count < maxsplit && (match = re.exec(remaining)) !== null) {
404
+ result.push(remaining.slice(0, match.index));
405
+ remaining = remaining.slice(match.index + match[0].length);
406
+ re.lastIndex = 0;
407
+ count++;
408
+ }
409
+ result.push(remaining);
410
+ return { output: result };
411
+ }
412
+ }
413
+ __decorate([
414
+ prop({
415
+ type: "str",
416
+ default: "",
417
+ title: "Text",
418
+ description: "Text to split"
419
+ })
420
+ ], RegexSplitNode.prototype, "text", void 0);
421
+ __decorate([
422
+ prop({
423
+ type: "str",
424
+ default: "",
425
+ title: "Pattern",
426
+ description: "Regular expression pattern to split on"
427
+ })
428
+ ], RegexSplitNode.prototype, "pattern", void 0);
429
+ __decorate([
430
+ prop({
431
+ type: "int",
432
+ default: 0,
433
+ title: "Maxsplit",
434
+ description: "Maximum number of splits (0 for unlimited)"
435
+ })
436
+ ], RegexSplitNode.prototype, "maxsplit", void 0);
437
+ export class RegexValidateNode extends BaseNode {
438
+ static nodeType = "nodetool.text.RegexValidate";
439
+ static title = "Validate with Regex";
440
+ static description = "Check if text matches a regex pattern.\n regex, validate, check\n\n Use cases:\n - Validate input formats (email, phone, etc)\n - Check text structure\n - Filter text based on patterns";
441
+ static metadataOutputTypes = {
442
+ output: "bool"
443
+ };
444
+ async process() {
445
+ const text = String(this.text ?? this.text ?? "");
446
+ const pattern = String(this.pattern ?? this.pattern ?? "");
447
+ // Anchor at start to match Python's re.match() behavior
448
+ const anchored = pattern.startsWith("^") ? pattern : `^(?:${pattern})`;
449
+ return { output: new RegExp(anchored).test(text) };
450
+ }
451
+ }
452
+ __decorate([
453
+ prop({
454
+ type: "str",
455
+ default: "",
456
+ title: "Text",
457
+ description: "Text to validate"
458
+ })
459
+ ], RegexValidateNode.prototype, "text", void 0);
460
+ __decorate([
461
+ prop({
462
+ type: "str",
463
+ default: "",
464
+ title: "Pattern",
465
+ description: "Regular expression pattern"
466
+ })
467
+ ], RegexValidateNode.prototype, "pattern", void 0);
468
+ export class CompareTextNode extends BaseNode {
469
+ static nodeType = "nodetool.text.Compare";
470
+ static title = "Compare Text";
471
+ static description = "Compares two text values and reports ordering.\n text, compare, equality, sort, equals, =\n\n Use cases:\n - Checking if two strings are identical before branching\n - Determining lexical order for sorting or deduplication\n - Normalizing casing/spacing before compares";
472
+ static metadataOutputTypes = {
473
+ output: "str"
474
+ };
475
+ async process() {
476
+ const textA = String(this.text_a ?? this.text_a ?? "");
477
+ const textB = String(this.text_b ?? this.text_b ?? "");
478
+ const caseSensitive = Boolean(this.case_sensitive ?? this.case_sensitive ?? true);
479
+ const trimWhitespace = Boolean(this.trim_whitespace ?? this.trim_whitespace ?? false);
480
+ const normalize = (value) => {
481
+ const trimmed = trimWhitespace ? value.trim() : value;
482
+ return caseSensitive ? trimmed : trimmed.toLowerCase();
483
+ };
484
+ const left = normalize(textA);
485
+ const right = normalize(textB);
486
+ if (left < right) {
487
+ return { output: "less" };
488
+ }
489
+ if (left > right) {
490
+ return { output: "greater" };
491
+ }
492
+ return { output: "equal" };
493
+ }
494
+ }
495
+ __decorate([
496
+ prop({ type: "str", default: "", title: "First Text" })
497
+ ], CompareTextNode.prototype, "text_a", void 0);
498
+ __decorate([
499
+ prop({ type: "str", default: "", title: "Second Text" })
500
+ ], CompareTextNode.prototype, "text_b", void 0);
501
+ __decorate([
502
+ prop({
503
+ type: "bool",
504
+ default: true,
505
+ title: "Case Sensitive",
506
+ description: "Compare without lowercasing"
507
+ })
508
+ ], CompareTextNode.prototype, "case_sensitive", void 0);
509
+ __decorate([
510
+ prop({
511
+ type: "bool",
512
+ default: false,
513
+ title: "Trim Whitespace",
514
+ description: "Strip leading/trailing whitespace before comparing"
515
+ })
516
+ ], CompareTextNode.prototype, "trim_whitespace", void 0);
517
+ export class EqualsTextNode extends BaseNode {
518
+ static nodeType = "nodetool.text.Equals";
519
+ static title = "Equals";
520
+ static description = "Checks if two text inputs are equal.\n text, compare, equals, match, =";
521
+ static metadataOutputTypes = {
522
+ output: "bool"
523
+ };
524
+ async process() {
525
+ const cmp = new CompareTextNode();
526
+ cmp.assign(this.serialize());
527
+ const result = await cmp.process();
528
+ return { output: result.output === "equal" };
529
+ }
530
+ }
531
+ __decorate([
532
+ prop({ type: "str", default: "", title: "First Text" })
533
+ ], EqualsTextNode.prototype, "text_a", void 0);
534
+ __decorate([
535
+ prop({ type: "str", default: "", title: "Second Text" })
536
+ ], EqualsTextNode.prototype, "text_b", void 0);
537
+ __decorate([
538
+ prop({
539
+ type: "bool",
540
+ default: true,
541
+ title: "Case Sensitive",
542
+ description: "Disable lowercasing before compare"
543
+ })
544
+ ], EqualsTextNode.prototype, "case_sensitive", void 0);
545
+ __decorate([
546
+ prop({
547
+ type: "bool",
548
+ default: false,
549
+ title: "Trim Whitespace",
550
+ description: "Strip leading/trailing whitespace prior to comparison"
551
+ })
552
+ ], EqualsTextNode.prototype, "trim_whitespace", void 0);
553
+ export class ToUppercaseNode extends BaseNode {
554
+ static nodeType = "nodetool.text.ToUppercase";
555
+ static title = "To Uppercase";
556
+ static description = "Converts text to uppercase.\n text, transform, uppercase, format";
557
+ static metadataOutputTypes = {
558
+ output: "str"
559
+ };
560
+ async process() {
561
+ return { output: String(this.text ?? this.text ?? "").toUpperCase() };
562
+ }
563
+ }
564
+ __decorate([
565
+ prop({ type: "str", default: "", title: "Text" })
566
+ ], ToUppercaseNode.prototype, "text", void 0);
567
+ export class ToLowercaseNode extends BaseNode {
568
+ static nodeType = "nodetool.text.ToLowercase";
569
+ static title = "To Lowercase";
570
+ static description = "Converts text to lowercase.\n text, transform, lowercase, format";
571
+ static metadataOutputTypes = {
572
+ output: "str"
573
+ };
574
+ async process() {
575
+ return { output: String(this.text ?? this.text ?? "").toLowerCase() };
576
+ }
577
+ }
578
+ __decorate([
579
+ prop({ type: "str", default: "", title: "Text" })
580
+ ], ToLowercaseNode.prototype, "text", void 0);
581
+ export class ToTitlecaseNode extends BaseNode {
582
+ static nodeType = "nodetool.text.ToTitlecase";
583
+ static title = "To Title Case";
584
+ static description = "Converts text to title case.\n text, transform, titlecase, format\n\n Use cases:\n - Cleaning user provided titles before display\n - Normalizing headings in generated documents\n - Making list entries easier to scan";
585
+ static metadataOutputTypes = {
586
+ output: "str"
587
+ };
588
+ async process() {
589
+ return { output: toTitleCase(String(this.text ?? this.text ?? "")) };
590
+ }
591
+ }
592
+ __decorate([
593
+ prop({ type: "str", default: "", title: "Text" })
594
+ ], ToTitlecaseNode.prototype, "text", void 0);
595
+ export class CapitalizeTextNode extends BaseNode {
596
+ static nodeType = "nodetool.text.CapitalizeText";
597
+ static title = "Capitalize Text";
598
+ static description = "Capitalizes only the first character.\n text, transform, capitalize, format\n\n Use cases:\n - Formatting short labels or sentences\n - Cleaning up LLM output before UI rendering\n - Quickly fixing lowercase starts after concatenation";
599
+ static metadataOutputTypes = {
600
+ output: "str"
601
+ };
602
+ async process() {
603
+ const text = String(this.text ?? this.text ?? "");
604
+ if (!text) {
605
+ return { output: "" };
606
+ }
607
+ return {
608
+ output: text.charAt(0).toUpperCase() + text.slice(1).toLowerCase()
609
+ };
610
+ }
611
+ }
612
+ __decorate([
613
+ prop({ type: "str", default: "", title: "Text" })
614
+ ], CapitalizeTextNode.prototype, "text", void 0);
615
+ export class SliceTextNode extends BaseNode {
616
+ static nodeType = "nodetool.text.Slice";
617
+ static title = "Slice Text";
618
+ static description = "Slices text using Python's slice notation (start:stop:step).\n text, slice, substring\n\n Use cases:\n - Extracting specific portions of text with flexible indexing\n - Reversing text using negative step\n - Taking every nth character with step parameter\n\n Examples:\n - start=0, stop=5: first 5 characters\n - start=-5: last 5 characters\n - step=2: every second character\n - step=-1: reverse the text";
619
+ static metadataOutputTypes = {
620
+ output: "str"
621
+ };
622
+ async process() {
623
+ const text = String(this.text ?? this.text ?? "");
624
+ const start = Number(this.start ?? this.start ?? 0);
625
+ const stop = Number(this.stop ?? this.stop ?? 0);
626
+ const step = Number(this.step ?? this.step ?? 1);
627
+ if (step === 0) {
628
+ throw new Error("slice step cannot be zero");
629
+ }
630
+ if (step === 1) {
631
+ const effectiveStop = stop === 0 ? undefined : stop;
632
+ return { output: text.slice(start, effectiveStop) };
633
+ }
634
+ const chars = [...text];
635
+ const result = [];
636
+ const len = chars.length;
637
+ const normStart = start < 0 ? len + start : start;
638
+ const effectiveStop = stop === 0 ? len : stop;
639
+ const normStop = effectiveStop < 0 ? len + effectiveStop : effectiveStop;
640
+ if (step > 0) {
641
+ for (let i = Math.max(0, normStart); i < Math.min(len, normStop); i += step) {
642
+ result.push(chars[i]);
643
+ }
644
+ }
645
+ else {
646
+ for (let i = Math.min(len - 1, normStart); i > Math.max(-1, normStop); i += step) {
647
+ if (i >= 0 && i < len) {
648
+ result.push(chars[i]);
649
+ }
650
+ }
651
+ }
652
+ return { output: result.join("") };
653
+ }
654
+ }
655
+ __decorate([
656
+ prop({ type: "str", default: "", title: "Text" })
657
+ ], SliceTextNode.prototype, "text", void 0);
658
+ __decorate([
659
+ prop({ type: "int", default: 0, title: "Start Index" })
660
+ ], SliceTextNode.prototype, "start", void 0);
661
+ __decorate([
662
+ prop({ type: "int", default: 0, title: "Stop Index" })
663
+ ], SliceTextNode.prototype, "stop", void 0);
664
+ __decorate([
665
+ prop({ type: "int", default: 1, title: "Step" })
666
+ ], SliceTextNode.prototype, "step", void 0);
667
+ export class StartsWithTextNode extends BaseNode {
668
+ static nodeType = "nodetool.text.StartsWith";
669
+ static title = "Starts With";
670
+ static description = "Checks if text starts with a specified prefix.\n text, check, prefix, compare, validate, substring, string\n\n Use cases:\n - Validating string prefixes\n - Filtering text based on starting content\n - Checking file name patterns";
671
+ static metadataOutputTypes = {
672
+ output: "bool"
673
+ };
674
+ async process() {
675
+ const text = String(this.text ?? this.text ?? "");
676
+ const prefix = String(this.prefix ?? this.prefix ?? "");
677
+ return { output: text.startsWith(prefix) };
678
+ }
679
+ }
680
+ __decorate([
681
+ prop({ type: "str", default: "", title: "Text" })
682
+ ], StartsWithTextNode.prototype, "text", void 0);
683
+ __decorate([
684
+ prop({ type: "str", default: "", title: "Prefix" })
685
+ ], StartsWithTextNode.prototype, "prefix", void 0);
686
+ export class EndsWithTextNode extends BaseNode {
687
+ static nodeType = "nodetool.text.EndsWith";
688
+ static title = "Ends With";
689
+ static description = "Checks if text ends with a specified suffix.\n text, check, suffix, compare, validate, substring, string\n\n Use cases:\n - Validating file extensions\n - Checking string endings\n - Filtering text based on ending content";
690
+ static metadataOutputTypes = {
691
+ output: "bool"
692
+ };
693
+ async process() {
694
+ const text = String(this.text ?? this.text ?? "");
695
+ const suffix = String(this.suffix ?? this.suffix ?? "");
696
+ return { output: text.endsWith(suffix) };
697
+ }
698
+ }
699
+ __decorate([
700
+ prop({ type: "str", default: "", title: "Text" })
701
+ ], EndsWithTextNode.prototype, "text", void 0);
702
+ __decorate([
703
+ prop({ type: "str", default: "", title: "Suffix" })
704
+ ], EndsWithTextNode.prototype, "suffix", void 0);
705
+ export class ContainsTextNode extends BaseNode {
706
+ static nodeType = "nodetool.text.Contains";
707
+ static title = "Contains Text";
708
+ static description = "Checks if text contains a specified substring.\n text, compare, validate, substring, string";
709
+ static metadataOutputTypes = {
710
+ output: "bool"
711
+ };
712
+ async process() {
713
+ const text = String(this.text ?? this.text ?? "");
714
+ const substring = String(this.substring ?? this.substring ?? "");
715
+ const searchValues = Array.isArray(this.search_values ?? this.search_values)
716
+ ? (this.search_values ?? this.search_values).map((v) => String(v))
717
+ : [];
718
+ const caseSensitive = Boolean(this.case_sensitive ?? this.case_sensitive ?? true);
719
+ const matchMode = String(this.match_mode ?? this.match_mode ?? "any");
720
+ const targets = searchValues.length > 0 ? searchValues : substring ? [substring] : [];
721
+ if (targets.length === 0) {
722
+ return { output: false };
723
+ }
724
+ const haystack = caseSensitive ? text : text.toLowerCase();
725
+ const needles = caseSensitive
726
+ ? targets
727
+ : targets.map((n) => n.toLowerCase());
728
+ if (matchMode === "all") {
729
+ return { output: needles.every((needle) => haystack.includes(needle)) };
730
+ }
731
+ if (matchMode === "none") {
732
+ return { output: needles.every((needle) => !haystack.includes(needle)) };
733
+ }
734
+ return { output: needles.some((needle) => haystack.includes(needle)) };
735
+ }
736
+ }
737
+ __decorate([
738
+ prop({ type: "str", default: "", title: "Text" })
739
+ ], ContainsTextNode.prototype, "text", void 0);
740
+ __decorate([
741
+ prop({ type: "str", default: "", title: "Substring" })
742
+ ], ContainsTextNode.prototype, "substring", void 0);
743
+ __decorate([
744
+ prop({
745
+ type: "list[str]",
746
+ default: [],
747
+ title: "Search Values",
748
+ description: "Optional list of additional substrings to check"
749
+ })
750
+ ], ContainsTextNode.prototype, "search_values", void 0);
751
+ __decorate([
752
+ prop({ type: "bool", default: true, title: "Case Sensitive" })
753
+ ], ContainsTextNode.prototype, "case_sensitive", void 0);
754
+ __decorate([
755
+ prop({
756
+ type: "enum",
757
+ default: "any",
758
+ title: "Match Mode",
759
+ description: "ANY requires one match, ALL needs every value, NONE ensures none",
760
+ values: ["any", "all", "none"]
761
+ })
762
+ ], ContainsTextNode.prototype, "match_mode", void 0);
763
+ export class TrimWhitespaceNode extends BaseNode {
764
+ static nodeType = "nodetool.text.TrimWhitespace";
765
+ static title = "Trim Whitespace";
766
+ static description = "Trims whitespace from the start and/or end of text.\n text, whitespace, clean, remove";
767
+ static metadataOutputTypes = {
768
+ output: "str"
769
+ };
770
+ async process() {
771
+ const text = String(this.text ?? this.text ?? "");
772
+ const trimStart = Boolean(this.trim_start ?? this.trim_start ?? true);
773
+ const trimEnd = Boolean(this.trim_end ?? this.trim_end ?? true);
774
+ if (trimStart && trimEnd) {
775
+ return { output: text.trim() };
776
+ }
777
+ if (trimStart) {
778
+ return { output: text.replace(/^\s+/, "") };
779
+ }
780
+ if (trimEnd) {
781
+ return { output: text.replace(/\s+$/, "") };
782
+ }
783
+ return { output: text };
784
+ }
785
+ }
786
+ __decorate([
787
+ prop({ type: "str", default: "", title: "Text" })
788
+ ], TrimWhitespaceNode.prototype, "text", void 0);
789
+ __decorate([
790
+ prop({ type: "bool", default: true, title: "Trim Start" })
791
+ ], TrimWhitespaceNode.prototype, "trim_start", void 0);
792
+ __decorate([
793
+ prop({ type: "bool", default: true, title: "Trim End" })
794
+ ], TrimWhitespaceNode.prototype, "trim_end", void 0);
795
+ export class CollapseWhitespaceNode extends BaseNode {
796
+ static nodeType = "nodetool.text.CollapseWhitespace";
797
+ static title = "Collapse Whitespace";
798
+ static description = "Collapses consecutive whitespace into single separators.\n text, whitespace, normalize, clean, remove";
799
+ static metadataOutputTypes = {
800
+ output: "str"
801
+ };
802
+ async process() {
803
+ const text = String(this.text ?? this.text ?? "");
804
+ const preserveNewlines = Boolean(this.preserve_newlines ?? this.preserve_newlines ?? false);
805
+ const replacement = String(this.replacement ?? this.replacement ?? " ");
806
+ const trimEdges = Boolean(this.trim_edges ?? this.trim_edges ?? true);
807
+ const value = trimEdges ? text.trim() : text;
808
+ if (preserveNewlines) {
809
+ return { output: value.replace(/[^\S\r\n]+/g, replacement) };
810
+ }
811
+ return { output: value.replace(/\s+/g, replacement) };
812
+ }
813
+ }
814
+ __decorate([
815
+ prop({ type: "str", default: "", title: "Text" })
816
+ ], CollapseWhitespaceNode.prototype, "text", void 0);
817
+ __decorate([
818
+ prop({
819
+ type: "bool",
820
+ default: false,
821
+ title: "Preserve Newlines",
822
+ description: "Keep newline characters instead of replacing them"
823
+ })
824
+ ], CollapseWhitespaceNode.prototype, "preserve_newlines", void 0);
825
+ __decorate([
826
+ prop({
827
+ type: "str",
828
+ default: " ",
829
+ title: "Replacement",
830
+ description: "String used to replace whitespace runs"
831
+ })
832
+ ], CollapseWhitespaceNode.prototype, "replacement", void 0);
833
+ __decorate([
834
+ prop({
835
+ type: "bool",
836
+ default: true,
837
+ title: "Trim Edges",
838
+ description: "Strip whitespace before collapsing"
839
+ })
840
+ ], CollapseWhitespaceNode.prototype, "trim_edges", void 0);
841
+ export class IsEmptyTextNode extends BaseNode {
842
+ static nodeType = "nodetool.text.IsEmpty";
843
+ static title = "Is Empty";
844
+ static description = "Checks if text is empty or contains only whitespace.\n text, check, empty, compare, validate, whitespace, string";
845
+ static metadataOutputTypes = {
846
+ output: "bool"
847
+ };
848
+ async process() {
849
+ const text = String(this.text ?? this.text ?? "");
850
+ const trimWhitespace = Boolean(this.trim_whitespace ?? this.trim_whitespace ?? true);
851
+ return { output: (trimWhitespace ? text.trim() : text).length === 0 };
852
+ }
853
+ }
854
+ __decorate([
855
+ prop({ type: "str", default: "", title: "Text" })
856
+ ], IsEmptyTextNode.prototype, "text", void 0);
857
+ __decorate([
858
+ prop({ type: "bool", default: true, title: "Trim Whitespace" })
859
+ ], IsEmptyTextNode.prototype, "trim_whitespace", void 0);
860
+ export class RemovePunctuationNode extends BaseNode {
861
+ static nodeType = "nodetool.text.RemovePunctuation";
862
+ static title = "Remove Punctuation";
863
+ static description = "Removes punctuation characters from text.\n text, cleanup, punctuation, normalize";
864
+ static metadataOutputTypes = {
865
+ output: "str"
866
+ };
867
+ async process() {
868
+ const text = String(this.text ?? this.text ?? "");
869
+ const replacement = String(this.replacement ?? this.replacement ?? "");
870
+ const punctuation = String(this.punctuation ??
871
+ this.punctuation ??
872
+ `!"#$%&'()*+,\\-./:;<=>?@[\\]^_{|}~`);
873
+ const escaped = punctuation.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
874
+ return {
875
+ output: text.replace(new RegExp(`[${escaped}]`, "g"), replacement)
876
+ };
877
+ }
878
+ }
879
+ __decorate([
880
+ prop({ type: "str", default: "", title: "Text" })
881
+ ], RemovePunctuationNode.prototype, "text", void 0);
882
+ __decorate([
883
+ prop({
884
+ type: "str",
885
+ default: "",
886
+ title: "Replacement",
887
+ description: "String to insert where punctuation was removed"
888
+ })
889
+ ], RemovePunctuationNode.prototype, "replacement", void 0);
890
+ __decorate([
891
+ prop({
892
+ type: "str",
893
+ default: "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
894
+ title: "Punctuation Characters",
895
+ description: "Characters that should be removed or replaced"
896
+ })
897
+ ], RemovePunctuationNode.prototype, "punctuation", void 0);
898
+ export class StripAccentsNode extends BaseNode {
899
+ static nodeType = "nodetool.text.StripAccents";
900
+ static title = "Strip Accents";
901
+ static description = "Removes accent marks while keeping base characters.\n text, cleanup, accents, normalize";
902
+ static metadataOutputTypes = {
903
+ output: "str"
904
+ };
905
+ async process() {
906
+ const text = String(this.text ?? this.text ?? "");
907
+ const preserveNonAscii = Boolean(this.preserve_non_ascii ?? this.preserve_non_ascii ?? true);
908
+ const normalized = text.normalize("NFKD").replace(/[\u0300-\u036f]/g, "");
909
+ if (preserveNonAscii) {
910
+ return { output: normalized };
911
+ }
912
+ // eslint-disable-next-line no-control-regex
913
+ return { output: normalized.replace(/[^\x00-\x7F]/g, "") };
914
+ }
915
+ }
916
+ __decorate([
917
+ prop({ type: "str", default: "", title: "Text" })
918
+ ], StripAccentsNode.prototype, "text", void 0);
919
+ __decorate([
920
+ prop({
921
+ type: "bool",
922
+ default: true,
923
+ title: "Preserve Non-ASCII",
924
+ description: "Keep non-ASCII characters that are not accents"
925
+ })
926
+ ], StripAccentsNode.prototype, "preserve_non_ascii", void 0);
927
+ export class SlugifyNode extends BaseNode {
928
+ static nodeType = "nodetool.text.Slugify";
929
+ static title = "Slugify";
930
+ static description = "Converts text into a slug suitable for URLs or IDs.\n text, slug, normalize, id";
931
+ static metadataOutputTypes = {
932
+ output: "str"
933
+ };
934
+ async process() {
935
+ const text = String(this.text ?? this.text ?? "");
936
+ const separator = String(this.separator ?? this.separator ?? "-");
937
+ const lowercase = Boolean(this.lowercase ?? this.lowercase ?? true);
938
+ const allowUnicode = Boolean(this.allow_unicode ?? this.allow_unicode ?? false);
939
+ let value = text.normalize("NFKD");
940
+ if (!allowUnicode) {
941
+ // eslint-disable-next-line no-control-regex
942
+ value = value.replace(/[^\x00-\x7F]/g, "");
943
+ }
944
+ value = value.replace(/[^\w\s-]/g, "");
945
+ value = value.replace(/[\s_-]+/g, separator).replace(/^[-_]+|[-_]+$/g, "");
946
+ if (lowercase) {
947
+ value = value.toLowerCase();
948
+ }
949
+ return { output: value };
950
+ }
951
+ }
952
+ __decorate([
953
+ prop({ type: "str", default: "", title: "Text" })
954
+ ], SlugifyNode.prototype, "text", void 0);
955
+ __decorate([
956
+ prop({ type: "str", default: "-", title: "Separator" })
957
+ ], SlugifyNode.prototype, "separator", void 0);
958
+ __decorate([
959
+ prop({ type: "bool", default: true, title: "Lowercase" })
960
+ ], SlugifyNode.prototype, "lowercase", void 0);
961
+ __decorate([
962
+ prop({
963
+ type: "bool",
964
+ default: false,
965
+ title: "Allow Unicode",
966
+ description: "Keep unicode letters instead of converting to ASCII"
967
+ })
968
+ ], SlugifyNode.prototype, "allow_unicode", void 0);
969
+ export class HasLengthTextNode extends BaseNode {
970
+ static nodeType = "nodetool.text.HasLength";
971
+ static title = "Check Length";
972
+ static description = "Checks if text length meets specified conditions.\n text, check, length, compare, validate, whitespace, string";
973
+ static metadataOutputTypes = {
974
+ output: "bool"
975
+ };
976
+ async process() {
977
+ const text = String(this.text ?? this.text ?? "");
978
+ const minLength = Number(this.min_length ?? this.min_length ?? 0);
979
+ const maxLength = Number(this.max_length ?? this.max_length ?? 0);
980
+ const exactLength = Number(this.exact_length ?? this.exact_length ?? 0);
981
+ const length = text.length;
982
+ if (exactLength !== null) {
983
+ return { output: length === exactLength };
984
+ }
985
+ if (minLength !== null && length < minLength) {
986
+ return { output: false };
987
+ }
988
+ if (maxLength !== null && length > maxLength) {
989
+ return { output: false };
990
+ }
991
+ return { output: true };
992
+ }
993
+ }
994
+ __decorate([
995
+ prop({ type: "str", default: "", title: "Text" })
996
+ ], HasLengthTextNode.prototype, "text", void 0);
997
+ __decorate([
998
+ prop({ type: "int", default: 0, title: "Minimum Length" })
999
+ ], HasLengthTextNode.prototype, "min_length", void 0);
1000
+ __decorate([
1001
+ prop({ type: "int", default: 0, title: "Maximum Length" })
1002
+ ], HasLengthTextNode.prototype, "max_length", void 0);
1003
+ __decorate([
1004
+ prop({ type: "int", default: 0, title: "Exact Length" })
1005
+ ], HasLengthTextNode.prototype, "exact_length", void 0);
1006
+ export class TruncateTextNode extends BaseNode {
1007
+ static nodeType = "nodetool.text.TruncateText";
1008
+ static title = "Truncate Text";
1009
+ static description = "Truncates text to a maximum length.\n text, truncate, length, clip";
1010
+ static metadataOutputTypes = {
1011
+ output: "str"
1012
+ };
1013
+ async process() {
1014
+ const text = String(this.text ?? this.text ?? "");
1015
+ const maxLength = Number(this.max_length ?? this.max_length ?? 100);
1016
+ const ellipsis = String(this.ellipsis ?? this.ellipsis ?? "");
1017
+ if (maxLength <= 0) {
1018
+ return { output: ellipsis || "" };
1019
+ }
1020
+ if (text.length <= maxLength) {
1021
+ return { output: text };
1022
+ }
1023
+ if (ellipsis && ellipsis.length < maxLength) {
1024
+ const cut = maxLength - ellipsis.length;
1025
+ return { output: `${text.slice(0, cut)}${ellipsis}` };
1026
+ }
1027
+ return { output: text.slice(0, maxLength) };
1028
+ }
1029
+ }
1030
+ __decorate([
1031
+ prop({ type: "str", default: "", title: "Text" })
1032
+ ], TruncateTextNode.prototype, "text", void 0);
1033
+ __decorate([
1034
+ prop({ type: "int", default: 100, title: "Max Length", min: 0 })
1035
+ ], TruncateTextNode.prototype, "max_length", void 0);
1036
+ __decorate([
1037
+ prop({
1038
+ type: "str",
1039
+ default: "",
1040
+ title: "Ellipsis",
1041
+ description: "Optional suffix appended when truncation occurs"
1042
+ })
1043
+ ], TruncateTextNode.prototype, "ellipsis", void 0);
1044
+ export class PadTextNode extends BaseNode {
1045
+ static nodeType = "nodetool.text.PadText";
1046
+ static title = "Pad Text";
1047
+ static description = "Pads text to a target length.\n text, pad, length, format";
1048
+ static metadataOutputTypes = {
1049
+ output: "str"
1050
+ };
1051
+ async process() {
1052
+ const text = String(this.text ?? this.text ?? "");
1053
+ const length = Number(this.length ?? this.length ?? 0);
1054
+ const padCharacter = String(this.pad_character ?? this.pad_character ?? " ");
1055
+ const direction = String(this.direction ?? this.direction ?? "right");
1056
+ if (padCharacter.length !== 1) {
1057
+ throw new Error("pad_character must be a single character");
1058
+ }
1059
+ if (length <= text.length) {
1060
+ return { output: text };
1061
+ }
1062
+ const needed = length - text.length;
1063
+ if (direction === "left") {
1064
+ return { output: padCharacter.repeat(needed) + text };
1065
+ }
1066
+ if (direction === "both") {
1067
+ const left = Math.floor(needed / 2);
1068
+ const right = needed - left;
1069
+ return {
1070
+ output: `${padCharacter.repeat(left)}${text}${padCharacter.repeat(right)}`
1071
+ };
1072
+ }
1073
+ return { output: text + padCharacter.repeat(needed) };
1074
+ }
1075
+ }
1076
+ __decorate([
1077
+ prop({ type: "str", default: "", title: "Text" })
1078
+ ], PadTextNode.prototype, "text", void 0);
1079
+ __decorate([
1080
+ prop({ type: "int", default: 0, title: "Target Length", min: 0 })
1081
+ ], PadTextNode.prototype, "length", void 0);
1082
+ __decorate([
1083
+ prop({
1084
+ type: "str",
1085
+ default: " ",
1086
+ title: "Pad Character",
1087
+ description: "Single character to use for padding"
1088
+ })
1089
+ ], PadTextNode.prototype, "pad_character", void 0);
1090
+ __decorate([
1091
+ prop({
1092
+ type: "enum",
1093
+ default: "right",
1094
+ title: "Direction",
1095
+ description: "Where padding should be applied",
1096
+ values: ["left", "right", "both"]
1097
+ })
1098
+ ], PadTextNode.prototype, "direction", void 0);
1099
+ export class LengthTextNode extends BaseNode {
1100
+ static nodeType = "nodetool.text.Length";
1101
+ static title = "Measure Length";
1102
+ static description = "Measures text length as characters, words, or lines.\n text, analyze, length, count";
1103
+ static metadataOutputTypes = {
1104
+ output: "int"
1105
+ };
1106
+ async process() {
1107
+ const text = String(this.text ?? this.text ?? "");
1108
+ const measure = String(this.measure ?? this.measure ?? "characters");
1109
+ const trimWhitespace = Boolean(this.trim_whitespace ?? this.trim_whitespace ?? false);
1110
+ const value = trimWhitespace ? text.trim() : text;
1111
+ if (measure === "words") {
1112
+ return { output: value.split(/\s+/).filter(Boolean).length };
1113
+ }
1114
+ if (measure === "lines") {
1115
+ if (!value) {
1116
+ return { output: 0 };
1117
+ }
1118
+ return {
1119
+ output: value.split(/\r?\n/).filter((line) => line || !trimWhitespace)
1120
+ .length
1121
+ };
1122
+ }
1123
+ return { output: value.length };
1124
+ }
1125
+ }
1126
+ __decorate([
1127
+ prop({ type: "str", default: "", title: "Text" })
1128
+ ], LengthTextNode.prototype, "text", void 0);
1129
+ __decorate([
1130
+ prop({
1131
+ type: "enum",
1132
+ default: "characters",
1133
+ title: "Measure",
1134
+ description: "Choose whether to count characters, words, or lines",
1135
+ values: ["characters", "words", "lines"]
1136
+ })
1137
+ ], LengthTextNode.prototype, "measure", void 0);
1138
+ __decorate([
1139
+ prop({
1140
+ type: "bool",
1141
+ default: false,
1142
+ title: "Trim Whitespace",
1143
+ description: "Strip whitespace before counting"
1144
+ })
1145
+ ], LengthTextNode.prototype, "trim_whitespace", void 0);
1146
+ export class IndexOfTextNode extends BaseNode {
1147
+ static nodeType = "nodetool.text.IndexOf";
1148
+ static title = "Index Of";
1149
+ static description = "Finds the position of a substring in text.\n text, search, find, substring";
1150
+ static metadataOutputTypes = {
1151
+ output: "int"
1152
+ };
1153
+ async process() {
1154
+ let haystack = String(this.text ?? this.text ?? "");
1155
+ let needle = String(this.substring ?? this.substring ?? "");
1156
+ const caseSensitive = Boolean(this.case_sensitive ?? this.case_sensitive ?? true);
1157
+ const startIndex = Number(this.start_index ?? this.start_index ?? 0);
1158
+ const endIndex = Number(this.end_index ?? this.end_index ?? 0);
1159
+ const searchFromEnd = Boolean(this.search_from_end ?? this.search_from_end ?? false);
1160
+ if (!caseSensitive) {
1161
+ haystack = haystack.toLowerCase();
1162
+ needle = needle.toLowerCase();
1163
+ }
1164
+ const effectiveEnd = endIndex > 0 ? endIndex : haystack.length;
1165
+ if (searchFromEnd) {
1166
+ // lastIndexOf's second arg is the position to search backward from.
1167
+ // We want to find the last occurrence within [startIndex, effectiveEnd).
1168
+ // Search backward from effectiveEnd - 1, then verify >= startIndex.
1169
+ const idx = haystack.lastIndexOf(needle, effectiveEnd - 1);
1170
+ return { output: idx >= startIndex ? idx : -1 };
1171
+ }
1172
+ const searchRegion = haystack.slice(startIndex, effectiveEnd);
1173
+ const idx = searchRegion.indexOf(needle);
1174
+ return { output: idx < 0 ? -1 : startIndex + idx };
1175
+ }
1176
+ }
1177
+ __decorate([
1178
+ prop({ type: "str", default: "", title: "Text" })
1179
+ ], IndexOfTextNode.prototype, "text", void 0);
1180
+ __decorate([
1181
+ prop({ type: "str", default: "", title: "Substring" })
1182
+ ], IndexOfTextNode.prototype, "substring", void 0);
1183
+ __decorate([
1184
+ prop({ type: "bool", default: true, title: "Case Sensitive" })
1185
+ ], IndexOfTextNode.prototype, "case_sensitive", void 0);
1186
+ __decorate([
1187
+ prop({
1188
+ type: "int",
1189
+ default: 0,
1190
+ title: "Start Index",
1191
+ description: "Index to begin the search from",
1192
+ min: 0
1193
+ })
1194
+ ], IndexOfTextNode.prototype, "start_index", void 0);
1195
+ __decorate([
1196
+ prop({
1197
+ type: "int",
1198
+ default: 0,
1199
+ title: "End Index",
1200
+ description: "Optional exclusive end index for the search"
1201
+ })
1202
+ ], IndexOfTextNode.prototype, "end_index", void 0);
1203
+ __decorate([
1204
+ prop({
1205
+ type: "bool",
1206
+ default: false,
1207
+ title: "Search From End",
1208
+ description: "Use the last occurrence instead of the first"
1209
+ })
1210
+ ], IndexOfTextNode.prototype, "search_from_end", void 0);
1211
+ export class SurroundWithTextNode extends BaseNode {
1212
+ static nodeType = "nodetool.text.SurroundWith";
1213
+ static title = "Surround With";
1214
+ static description = "Wraps text with the provided prefix and suffix.\n text, format, surround, decorate";
1215
+ static metadataOutputTypes = {
1216
+ output: "str"
1217
+ };
1218
+ async process() {
1219
+ const text = String(this.text ?? this.text ?? "");
1220
+ const prefix = String(this.prefix ?? this.prefix ?? "");
1221
+ const suffix = String(this.suffix ?? this.suffix ?? "");
1222
+ const skipIfWrapped = Boolean(this.skip_if_wrapped ?? this.skip_if_wrapped ?? true);
1223
+ if (skipIfWrapped && text.startsWith(prefix) && text.endsWith(suffix)) {
1224
+ return { output: text };
1225
+ }
1226
+ return { output: `${prefix}${text}${suffix}` };
1227
+ }
1228
+ }
1229
+ __decorate([
1230
+ prop({ type: "str", default: "", title: "Text" })
1231
+ ], SurroundWithTextNode.prototype, "text", void 0);
1232
+ __decorate([
1233
+ prop({ type: "str", default: "", title: "Prefix" })
1234
+ ], SurroundWithTextNode.prototype, "prefix", void 0);
1235
+ __decorate([
1236
+ prop({ type: "str", default: "", title: "Suffix" })
1237
+ ], SurroundWithTextNode.prototype, "suffix", void 0);
1238
+ __decorate([
1239
+ prop({
1240
+ type: "bool",
1241
+ default: true,
1242
+ title: "Skip If Already Wrapped",
1243
+ description: "Do not add duplicates if the text is already wrapped"
1244
+ })
1245
+ ], SurroundWithTextNode.prototype, "skip_if_wrapped", void 0);
1246
+ export class CountTokensNode extends BaseNode {
1247
+ static nodeType = "nodetool.text.CountTokens";
1248
+ static title = "Count Tokens";
1249
+ static description = "Counts the number of tokens in text using tiktoken.\n text, tokens, count, encoding";
1250
+ static metadataOutputTypes = {
1251
+ output: "int"
1252
+ };
1253
+ async process() {
1254
+ const text = String(this.text ?? this.text ?? "");
1255
+ if (!text.trim()) {
1256
+ return { output: 0 };
1257
+ }
1258
+ const tokens = text.match(/[A-Za-z0-9_]+|[^\s]/g) ?? [];
1259
+ return { output: tokens.length };
1260
+ }
1261
+ }
1262
+ __decorate([
1263
+ prop({ type: "str", default: "", title: "Text" })
1264
+ ], CountTokensNode.prototype, "text", void 0);
1265
+ __decorate([
1266
+ prop({
1267
+ type: "enum",
1268
+ default: "cl100k_base",
1269
+ title: "Encoding",
1270
+ description: "The tiktoken encoding to use for token counting",
1271
+ values: ["cl100k_base", "p50k_base", "r50k_base"]
1272
+ })
1273
+ ], CountTokensNode.prototype, "encoding", void 0);
1274
+ export class HtmlToTextNode extends BaseNode {
1275
+ static nodeType = "nodetool.text.HtmlToText";
1276
+ static title = "HTML to Text";
1277
+ static description = "Converts HTML content to plain text using html2text.\n html, convert, text, parse, extract";
1278
+ static metadataOutputTypes = {
1279
+ output: "str"
1280
+ };
1281
+ async process() {
1282
+ const html = String(this.html ?? this.html ?? "");
1283
+ const baseUrl = String(this.base_url ?? this.base_url ?? "");
1284
+ const bodyWidth = Number(this.body_width ?? this.body_width ?? 1000);
1285
+ let text = html;
1286
+ // Remove scripts and styles
1287
+ text = text.replace(/<script[\s\S]*?<\/script>/gi, "");
1288
+ text = text.replace(/<style[\s\S]*?<\/style>/gi, "");
1289
+ // Convert headers to markdown-style
1290
+ text = text.replace(/<h([1-6])[^>]*>([\s\S]*?)<\/h\1>/gi, (_m, level, content) => {
1291
+ const hashes = "#".repeat(Number(level));
1292
+ const clean = content.replace(/<[^>]+>/g, "").trim();
1293
+ return `\n\n${hashes} ${clean}\n\n`;
1294
+ });
1295
+ // Convert links: <a href="url">text</a> -> text (url)
1296
+ text = text.replace(/<a\s+[^>]*href=["']([^"']*)["'][^>]*>([\s\S]*?)<\/a>/gi, (_m, href, linkText) => {
1297
+ const clean = linkText.replace(/<[^>]+>/g, "").trim();
1298
+ let resolvedUrl = href;
1299
+ if (baseUrl && href && !href.match(/^https?:\/\//)) {
1300
+ const base = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
1301
+ resolvedUrl = href.startsWith("/") ? baseUrl.replace(/\/$/, "") + href : base + href;
1302
+ }
1303
+ if (baseUrl && resolvedUrl && resolvedUrl !== clean) {
1304
+ return `${clean} (${resolvedUrl})`;
1305
+ }
1306
+ return clean;
1307
+ });
1308
+ // Convert unordered lists
1309
+ text = text.replace(/<ul[^>]*>([\s\S]*?)<\/ul>/gi, (_m, content) => {
1310
+ return "\n" + content.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, (_li, item) => {
1311
+ return ` * ${item.replace(/<[^>]+>/g, "").trim()}\n`;
1312
+ }) + "\n";
1313
+ });
1314
+ // Convert ordered lists
1315
+ text = text.replace(/<ol[^>]*>([\s\S]*?)<\/ol>/gi, (_m, content) => {
1316
+ let idx = 0;
1317
+ return "\n" + content.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, (_li, item) => {
1318
+ idx++;
1319
+ return ` ${idx}. ${item.replace(/<[^>]+>/g, "").trim()}\n`;
1320
+ }) + "\n";
1321
+ });
1322
+ // Convert block elements to double newlines
1323
+ text = text.replace(/<\/(p|div|section|article)>/gi, "\n\n");
1324
+ text = text.replace(/<(p|div|section|article)[^>]*>/gi, "");
1325
+ // Convert <br> to newlines
1326
+ text = text.replace(/<br\s*\/?>/gi, "\n");
1327
+ // Remove remaining tags
1328
+ text = text.replace(/<[^>]+>/g, "");
1329
+ // Decode HTML entities
1330
+ text = text
1331
+ .replace(/&nbsp;/g, " ")
1332
+ .replace(/&amp;/g, "&")
1333
+ .replace(/&lt;/g, "<")
1334
+ .replace(/&gt;/g, ">")
1335
+ .replace(/&#39;/g, "'")
1336
+ .replace(/&apos;/g, "'")
1337
+ .replace(/&quot;/g, '"')
1338
+ .replace(/&#(\d+);/g, (_m, code) => String.fromCharCode(Number(code)))
1339
+ .replace(/&#x([0-9a-fA-F]+);/g, (_m, code) => String.fromCharCode(parseInt(code, 16)));
1340
+ // Normalize whitespace: collapse multiple blank lines
1341
+ text = text.replace(/\n{3,}/g, "\n\n");
1342
+ // Apply body_width wrapping
1343
+ if (bodyWidth > 0) {
1344
+ const lines = text.split("\n");
1345
+ const wrapped = [];
1346
+ for (const line of lines) {
1347
+ if (line.length <= bodyWidth) {
1348
+ wrapped.push(line);
1349
+ }
1350
+ else {
1351
+ let remaining = line;
1352
+ while (remaining.length > bodyWidth) {
1353
+ let breakAt = remaining.lastIndexOf(" ", bodyWidth);
1354
+ if (breakAt <= 0)
1355
+ breakAt = bodyWidth;
1356
+ wrapped.push(remaining.slice(0, breakAt));
1357
+ remaining = remaining.slice(breakAt).trimStart();
1358
+ }
1359
+ if (remaining)
1360
+ wrapped.push(remaining);
1361
+ }
1362
+ }
1363
+ text = wrapped.join("\n");
1364
+ }
1365
+ return { output: text.trim() };
1366
+ }
1367
+ }
1368
+ __decorate([
1369
+ prop({
1370
+ type: "str",
1371
+ default: "",
1372
+ title: "HTML",
1373
+ description: "HTML content to convert"
1374
+ })
1375
+ ], HtmlToTextNode.prototype, "html", void 0);
1376
+ __decorate([
1377
+ prop({
1378
+ type: "str",
1379
+ default: "",
1380
+ title: "Base URL",
1381
+ description: "Base URL for resolving relative links"
1382
+ })
1383
+ ], HtmlToTextNode.prototype, "base_url", void 0);
1384
+ __decorate([
1385
+ prop({
1386
+ type: "int",
1387
+ default: 1000,
1388
+ title: "Body Width",
1389
+ description: "Width for text wrapping"
1390
+ })
1391
+ ], HtmlToTextNode.prototype, "body_width", void 0);
1392
+ __decorate([
1393
+ prop({
1394
+ type: "bool",
1395
+ default: true,
1396
+ title: "Ignore Images",
1397
+ description: "Whether to ignore image tags"
1398
+ })
1399
+ ], HtmlToTextNode.prototype, "ignore_images", void 0);
1400
+ __decorate([
1401
+ prop({
1402
+ type: "bool",
1403
+ default: true,
1404
+ title: "Ignore Mailto Links",
1405
+ description: "Whether to ignore mailto links"
1406
+ })
1407
+ ], HtmlToTextNode.prototype, "ignore_mailto_links", void 0);
1408
+ function seededEmbedding(input, dims = 64) {
1409
+ const out = new Array(dims).fill(0);
1410
+ for (let i = 0; i < input.length; i++) {
1411
+ const code = input.charCodeAt(i);
1412
+ const idx = i % dims;
1413
+ out[idx] += (code % 97) / 97;
1414
+ }
1415
+ const norm = Math.sqrt(out.reduce((a, b) => a + b * b, 0)) || 1;
1416
+ return out.map((v) => v / norm);
1417
+ }
1418
+ export class AutomaticSpeechRecognitionNode extends BaseNode {
1419
+ static nodeType = "nodetool.text.AutomaticSpeechRecognition";
1420
+ static title = "Automatic Speech Recognition";
1421
+ static description = "Transcribe audio to text using automatic speech recognition models.\n audio, speech, recognition, transcription, ASR, whisper";
1422
+ static metadataOutputTypes = {
1423
+ text: "str"
1424
+ };
1425
+ static exposeAsTool = true;
1426
+ async process(context) {
1427
+ const { providerId, modelId } = modelConfig(this.serialize());
1428
+ const audio = (this.audio ?? this.audio ?? {});
1429
+ let bytes = new Uint8Array();
1430
+ if (typeof audio.data === "string") {
1431
+ bytes = Uint8Array.from(Buffer.from(audio.data, "base64"));
1432
+ }
1433
+ else if (audio.data instanceof Uint8Array) {
1434
+ bytes = new Uint8Array(audio.data);
1435
+ }
1436
+ else if (typeof audio.uri === "string" && audio.uri) {
1437
+ if (context?.storage) {
1438
+ const stored = await context.storage.retrieve(audio.uri);
1439
+ if (stored !== null)
1440
+ bytes = new Uint8Array(stored);
1441
+ }
1442
+ if (bytes.length === 0 && audio.uri.startsWith("file://")) {
1443
+ bytes = new Uint8Array(await fs.readFile(audio.uri.slice("file://".length)));
1444
+ }
1445
+ }
1446
+ if (context &&
1447
+ typeof context.runProviderPrediction === "function" &&
1448
+ providerId &&
1449
+ modelId &&
1450
+ bytes.length > 0) {
1451
+ const text = (await context.runProviderPrediction({
1452
+ provider: providerId,
1453
+ capability: "automatic_speech_recognition",
1454
+ model: modelId,
1455
+ params: {
1456
+ audio: bytes,
1457
+ language: this.language,
1458
+ prompt: this.prompt,
1459
+ temperature: this.temperature
1460
+ }
1461
+ }));
1462
+ return { text, output: text };
1463
+ }
1464
+ throw new Error("AutomaticSpeechRecognition requires a provider-backed model and audio input.");
1465
+ }
1466
+ }
1467
+ __decorate([
1468
+ prop({
1469
+ type: "asr_model",
1470
+ default: {
1471
+ type: "asr_model",
1472
+ provider: "fal_ai",
1473
+ id: "openai/whisper-large-v3",
1474
+ name: "",
1475
+ path: null
1476
+ },
1477
+ title: "Model"
1478
+ })
1479
+ ], AutomaticSpeechRecognitionNode.prototype, "model", void 0);
1480
+ __decorate([
1481
+ prop({
1482
+ type: "audio",
1483
+ default: {
1484
+ type: "audio",
1485
+ uri: "",
1486
+ asset_id: null,
1487
+ data: null,
1488
+ metadata: null
1489
+ },
1490
+ title: "Audio",
1491
+ description: "The audio to transcribe",
1492
+ required: true
1493
+ })
1494
+ ], AutomaticSpeechRecognitionNode.prototype, "audio", void 0);
1495
+ export class EmbeddingTextNode extends BaseNode {
1496
+ static nodeType = "nodetool.text.Embedding";
1497
+ static title = "Embedding";
1498
+ static description = "Generate vector representations of text using any supported embedding provider.\n Automatically routes to the appropriate backend (OpenAI, Gemini, Mistral).\n embeddings, similarity, search, clustering, classification, vectors, semantic\n\n Uses embedding models to create dense vector representations of text.\n These vectors capture semantic meaning, enabling:\n - Semantic search\n - Text clustering\n - Document classification\n - Recommendation systems\n - Anomaly detection\n - Measuring text similarity and diversity";
1499
+ static metadataOutputTypes = {
1500
+ output: "list"
1501
+ };
1502
+ static basicFields = ["model", "input"];
1503
+ static exposeAsTool = true;
1504
+ async process() {
1505
+ const text = String(this.input ?? this.input ?? "");
1506
+ return { output: seededEmbedding(text) };
1507
+ }
1508
+ }
1509
+ __decorate([
1510
+ prop({
1511
+ type: "embedding_model",
1512
+ default: {
1513
+ type: "embedding_model",
1514
+ provider: "openai",
1515
+ id: "text-embedding-3-small",
1516
+ name: "Text Embedding 3 Small",
1517
+ dimensions: 0
1518
+ },
1519
+ title: "Model",
1520
+ description: "The embedding model to use"
1521
+ })
1522
+ ], EmbeddingTextNode.prototype, "model", void 0);
1523
+ __decorate([
1524
+ prop({
1525
+ type: "str",
1526
+ default: "",
1527
+ title: "Input",
1528
+ description: "The text to embed"
1529
+ })
1530
+ ], EmbeddingTextNode.prototype, "input", void 0);
1531
+ __decorate([
1532
+ prop({
1533
+ type: "int",
1534
+ default: 4096,
1535
+ title: "Chunk Size",
1536
+ description: "Size of text chunks for embedding (used when input exceeds model limits)",
1537
+ min: 1,
1538
+ max: 8192
1539
+ })
1540
+ ], EmbeddingTextNode.prototype, "chunk_size", void 0);
1541
+ export class SaveTextFileNode extends BaseNode {
1542
+ static nodeType = "nodetool.text.SaveTextFile";
1543
+ static title = "Save Text File";
1544
+ static description = "Saves input text to a file in the assets folder.\n text, save, file";
1545
+ static metadataOutputTypes = {
1546
+ output: "text"
1547
+ };
1548
+ async process() {
1549
+ const text = String(this.text ?? this.text ?? "");
1550
+ const folder = String(this.folder ?? this.folder ?? "");
1551
+ const name = String(this.name ?? this.name ?? "output.txt");
1552
+ if (!folder) {
1553
+ throw new Error("folder cannot be empty");
1554
+ }
1555
+ await fs.mkdir(folder, { recursive: true });
1556
+ const fsPath = join(folder, name);
1557
+ await fs.writeFile(fsPath, text, "utf-8");
1558
+ // The output `uri` is a portable, URI-style path (forward slashes) so
1559
+ // downstream nodes and the web UI never have to special-case Windows.
1560
+ const uri = fsPath.replace(/\\/g, "/");
1561
+ return { output: { uri, data: text } };
1562
+ }
1563
+ }
1564
+ __decorate([
1565
+ prop({ type: "str", default: "", title: "Text" })
1566
+ ], SaveTextFileNode.prototype, "text", void 0);
1567
+ __decorate([
1568
+ prop({
1569
+ type: "str",
1570
+ default: "",
1571
+ title: "Folder",
1572
+ description: "Path to the output folder."
1573
+ })
1574
+ ], SaveTextFileNode.prototype, "folder", void 0);
1575
+ __decorate([
1576
+ prop({
1577
+ type: "str",
1578
+ default: "%Y-%m-%d-%H-%M-%S.txt",
1579
+ title: "Name",
1580
+ description: "\n Name of the output file.\n You can use time and date variables to create unique names:\n %Y - Year\n %m - Month\n %d - Day\n %H - Hour\n %M - Minute\n %S - Second\n "
1581
+ })
1582
+ ], SaveTextFileNode.prototype, "name", void 0);
1583
+ export class SaveTextNode extends BaseNode {
1584
+ static nodeType = "nodetool.text.SaveText";
1585
+ static title = "Save Text";
1586
+ static description = "Saves input text to a file in the assets folder.\n text, save, file\n\n Use cases:\n - Persisting processed text results\n - Creating text files for downstream nodes or external use\n - Archiving text data within the workflow";
1587
+ static metadataOutputTypes = {
1588
+ output: "text"
1589
+ };
1590
+ async process() {
1591
+ const text = String(this.text ?? this.text ?? "");
1592
+ const name = String(this.name ?? this.name ?? "output.txt");
1593
+ await fs.writeFile(name, text, "utf-8");
1594
+ return { output: { uri: name, data: text } };
1595
+ }
1596
+ }
1597
+ __decorate([
1598
+ prop({ type: "str", default: "", title: "Text" })
1599
+ ], SaveTextNode.prototype, "text", void 0);
1600
+ __decorate([
1601
+ prop({
1602
+ type: "folder",
1603
+ default: {
1604
+ type: "folder",
1605
+ uri: "",
1606
+ asset_id: null,
1607
+ data: null,
1608
+ metadata: null
1609
+ },
1610
+ title: "Folder",
1611
+ description: "Name of the output folder."
1612
+ })
1613
+ ], SaveTextNode.prototype, "folder", void 0);
1614
+ __decorate([
1615
+ prop({
1616
+ type: "str",
1617
+ default: "%Y-%m-%d-%H-%M-%S.txt",
1618
+ title: "Name",
1619
+ description: "\n Name of the output file.\n You can use time and date variables to create unique names:\n %Y - Year\n %m - Month\n %d - Day\n %H - Hour\n %M - Minute\n %S - Second\n "
1620
+ })
1621
+ ], SaveTextNode.prototype, "name", void 0);
1622
+ export class LoadTextFolderNode extends BaseNode {
1623
+ static nodeType = "nodetool.text.LoadTextFolder";
1624
+ static title = "Load Text Folder";
1625
+ static description = "Load all text files from a folder, optionally including subfolders.\n text, load, folder, files";
1626
+ static metadataOutputTypes = {
1627
+ text: "str",
1628
+ path: "str",
1629
+ texts: "list",
1630
+ paths: "list"
1631
+ };
1632
+ static isStreamingOutput = true;
1633
+ async process() {
1634
+ const allTexts = [];
1635
+ const allPaths = [];
1636
+ for await (const item of this._walkFiles()) {
1637
+ allTexts.push(item.text);
1638
+ allPaths.push(item.path);
1639
+ }
1640
+ return {
1641
+ text: allTexts[0] ?? "",
1642
+ path: allPaths[0] ?? "",
1643
+ texts: allTexts,
1644
+ paths: allPaths
1645
+ };
1646
+ }
1647
+ async *_walkFiles() {
1648
+ const folder = String(this.folder ?? this.folder ?? "");
1649
+ const includeSubdirs = Boolean(this.include_subdirectories ?? this.include_subdirectories ?? false);
1650
+ const extensions = Array.isArray(this.extensions ?? this.extensions)
1651
+ ? (this.extensions ?? this.extensions).map((v) => String(v).toLowerCase())
1652
+ : [".txt"];
1653
+ if (!folder) {
1654
+ throw new Error("folder cannot be empty");
1655
+ }
1656
+ const walk = async function* (dir) {
1657
+ const entries = await fs.readdir(dir, { withFileTypes: true });
1658
+ for (const entry of entries) {
1659
+ const full = join(dir, entry.name);
1660
+ if (entry.isDirectory()) {
1661
+ if (includeSubdirs) {
1662
+ yield* walk(full);
1663
+ }
1664
+ continue;
1665
+ }
1666
+ yield full;
1667
+ }
1668
+ };
1669
+ for await (const filePath of walk(folder)) {
1670
+ if (!extensions.includes(extname(filePath).toLowerCase())) {
1671
+ continue;
1672
+ }
1673
+ const text = await fs.readFile(filePath, "utf-8");
1674
+ yield { path: filePath, text };
1675
+ }
1676
+ }
1677
+ async *genProcess() {
1678
+ const allTexts = [];
1679
+ const allPaths = [];
1680
+ for await (const item of this._walkFiles()) {
1681
+ allTexts.push(item.text);
1682
+ allPaths.push(item.path);
1683
+ yield { path: item.path, text: item.text };
1684
+ }
1685
+ // Emit collected lists as final output
1686
+ yield { texts: allTexts, paths: allPaths };
1687
+ }
1688
+ }
1689
+ __decorate([
1690
+ prop({
1691
+ type: "str",
1692
+ default: "",
1693
+ title: "Folder",
1694
+ description: "Folder to scan for text files"
1695
+ })
1696
+ ], LoadTextFolderNode.prototype, "folder", void 0);
1697
+ __decorate([
1698
+ prop({
1699
+ type: "bool",
1700
+ default: false,
1701
+ title: "Include Subdirectories",
1702
+ description: "Include text files in subfolders"
1703
+ })
1704
+ ], LoadTextFolderNode.prototype, "include_subdirectories", void 0);
1705
+ __decorate([
1706
+ prop({
1707
+ type: "list[str]",
1708
+ default: [".txt", ".csv", ".json", ".xml", ".md", ".html", ".pdf"],
1709
+ title: "Extensions",
1710
+ description: "Text file extensions to include"
1711
+ })
1712
+ ], LoadTextFolderNode.prototype, "extensions", void 0);
1713
+ __decorate([
1714
+ prop({
1715
+ type: "str",
1716
+ default: "",
1717
+ title: "Pattern",
1718
+ description: "Pattern to match text files"
1719
+ })
1720
+ ], LoadTextFolderNode.prototype, "pattern", void 0);
1721
+ export class LoadTextAssetsNode extends BaseNode {
1722
+ static nodeType = "nodetool.text.LoadTextAssets";
1723
+ static title = "Load Text Assets";
1724
+ static description = "Load text files from an asset folder.\n load, text, file, import";
1725
+ static metadataOutputTypes = {
1726
+ text: "text",
1727
+ name: "str",
1728
+ texts: "list",
1729
+ names: "list"
1730
+ };
1731
+ static isStreamingOutput = true;
1732
+ async process() {
1733
+ const allTexts = [];
1734
+ const allNames = [];
1735
+ const folder = folderPath(this.folder ?? "");
1736
+ if (!folder) {
1737
+ throw new Error("folder cannot be empty");
1738
+ }
1739
+ const walker = new LoadTextFolderNode();
1740
+ walker.assign({ folder });
1741
+ for await (const item of walker._walkFiles()) {
1742
+ allTexts.push(item.text);
1743
+ allNames.push(item.path);
1744
+ }
1745
+ return {
1746
+ text: allTexts[0] ?? "",
1747
+ name: allNames[0] ?? "",
1748
+ texts: allTexts,
1749
+ names: allNames
1750
+ };
1751
+ }
1752
+ async *genProcess() {
1753
+ const folder = folderPath(this.folder ?? "");
1754
+ if (!folder) {
1755
+ throw new Error("folder cannot be empty");
1756
+ }
1757
+ const allTexts = [];
1758
+ const allNames = [];
1759
+ const walker = new LoadTextFolderNode();
1760
+ walker.assign({ folder });
1761
+ for await (const item of walker._walkFiles()) {
1762
+ allTexts.push(item.text);
1763
+ allNames.push(item.path);
1764
+ yield { text: item.text, name: item.path };
1765
+ }
1766
+ // Emit collected lists as final output
1767
+ yield { texts: allTexts, names: allNames };
1768
+ }
1769
+ }
1770
+ __decorate([
1771
+ prop({
1772
+ type: "folder",
1773
+ default: {
1774
+ type: "folder",
1775
+ uri: "",
1776
+ asset_id: null,
1777
+ data: null,
1778
+ metadata: null
1779
+ },
1780
+ title: "Folder",
1781
+ description: "The asset folder to load the text files from."
1782
+ })
1783
+ ], LoadTextAssetsNode.prototype, "folder", void 0);
1784
+ export class FilterStringNode extends BaseNode {
1785
+ static nodeType = "nodetool.text.FilterString";
1786
+ static title = "Filter String";
1787
+ static description = "Filters a stream of strings based on various criteria.\n filter, strings, text, stream";
1788
+ static metadataOutputTypes = {
1789
+ output: "str"
1790
+ };
1791
+ static isStreamingOutput = true;
1792
+ static syncMode = "on_any";
1793
+ _filterType = "contains";
1794
+ _criteria = "";
1795
+ async initialize() {
1796
+ this._filterType = String(this.filter_type ?? "contains");
1797
+ this._criteria = String(this.criteria ?? "");
1798
+ }
1799
+ async process() {
1800
+ this._filterType = String(this.filter_type ?? "contains");
1801
+ this._criteria = String(this.criteria ?? "");
1802
+ const value = this.value;
1803
+ if (typeof value !== "string") {
1804
+ return {};
1805
+ }
1806
+ const criteria = this._criteria;
1807
+ const len = value.length;
1808
+ const n = Number(criteria);
1809
+ let matched;
1810
+ switch (this._filterType) {
1811
+ case "contains":
1812
+ matched = value.includes(criteria);
1813
+ break;
1814
+ case "starts_with":
1815
+ matched = value.startsWith(criteria);
1816
+ break;
1817
+ case "ends_with":
1818
+ matched = value.endsWith(criteria);
1819
+ break;
1820
+ case "length_greater":
1821
+ matched = Number.isFinite(n) && len > n;
1822
+ break;
1823
+ case "length_less":
1824
+ matched = Number.isFinite(n) && len < n;
1825
+ break;
1826
+ case "exact_length":
1827
+ matched = Number.isFinite(n) && len === n;
1828
+ break;
1829
+ default:
1830
+ matched = false;
1831
+ }
1832
+ if (!matched) {
1833
+ return {};
1834
+ }
1835
+ return { output: value };
1836
+ }
1837
+ }
1838
+ __decorate([
1839
+ prop({
1840
+ type: "str",
1841
+ default: "",
1842
+ title: "Value",
1843
+ description: "Input string stream"
1844
+ })
1845
+ ], FilterStringNode.prototype, "value", void 0);
1846
+ __decorate([
1847
+ prop({
1848
+ type: "enum",
1849
+ default: "contains",
1850
+ title: "Filter Type",
1851
+ description: "The type of filter to apply",
1852
+ values: [
1853
+ "contains",
1854
+ "starts_with",
1855
+ "ends_with",
1856
+ "length_greater",
1857
+ "length_less",
1858
+ "exact_length"
1859
+ ]
1860
+ })
1861
+ ], FilterStringNode.prototype, "filter_type", void 0);
1862
+ __decorate([
1863
+ prop({
1864
+ type: "str",
1865
+ default: "",
1866
+ title: "Criteria",
1867
+ description: "The filtering criteria (text to match or length as string)"
1868
+ })
1869
+ ], FilterStringNode.prototype, "criteria", void 0);
1870
+ export class FilterRegexStringNode extends BaseNode {
1871
+ static nodeType = "nodetool.text.FilterRegexString";
1872
+ static title = "Filter Regex String";
1873
+ static description = "Filters a stream of strings using regular expressions.\n filter, regex, pattern, text, stream";
1874
+ static metadataOutputTypes = {
1875
+ output: "str"
1876
+ };
1877
+ static isStreamingOutput = true;
1878
+ static syncMode = "on_any";
1879
+ _pattern = "";
1880
+ _fullMatch = false;
1881
+ async initialize() {
1882
+ this._pattern = String(this.pattern ?? "");
1883
+ this._fullMatch = Boolean(this.full_match ?? false);
1884
+ }
1885
+ async process() {
1886
+ this._pattern = String(this.pattern ?? "");
1887
+ this._fullMatch = Boolean(this.full_match ?? false);
1888
+ const value = this.value;
1889
+ if (typeof value !== "string") {
1890
+ return {};
1891
+ }
1892
+ let regex;
1893
+ try {
1894
+ regex = new RegExp(this._pattern);
1895
+ }
1896
+ catch {
1897
+ return {};
1898
+ }
1899
+ const matched = this._fullMatch
1900
+ ? (value.match(regex)?.[0] ?? "") === value
1901
+ : regex.test(value);
1902
+ if (!matched) {
1903
+ return {};
1904
+ }
1905
+ return { output: value };
1906
+ }
1907
+ }
1908
+ __decorate([
1909
+ prop({
1910
+ type: "str",
1911
+ default: "",
1912
+ title: "Value",
1913
+ description: "Input string stream"
1914
+ })
1915
+ ], FilterRegexStringNode.prototype, "value", void 0);
1916
+ __decorate([
1917
+ prop({
1918
+ type: "str",
1919
+ default: "",
1920
+ title: "Pattern",
1921
+ description: "The regular expression pattern to match against."
1922
+ })
1923
+ ], FilterRegexStringNode.prototype, "pattern", void 0);
1924
+ __decorate([
1925
+ prop({
1926
+ type: "bool",
1927
+ default: false,
1928
+ title: "Full Match",
1929
+ description: "Whether to match the entire string or find pattern anywhere in string"
1930
+ })
1931
+ ], FilterRegexStringNode.prototype, "full_match", void 0);
1932
+ export class ConcatTextNode extends BaseNode {
1933
+ static nodeType = "nodetool.text.Concat";
1934
+ static title = "Concatenate Text";
1935
+ static description = "Concatenates text inputs into a single output.\n text, combine, add, concatenate, merge, join, append";
1936
+ static metadataOutputTypes = {
1937
+ output: "str"
1938
+ };
1939
+ static isDynamic = true;
1940
+ async process() {
1941
+ const values = [this.a, this.b, ...Array.from(this.dynamicProps.values())].map((value) => String(value ?? ""));
1942
+ return { output: values.join("") };
1943
+ }
1944
+ }
1945
+ __decorate([
1946
+ prop({ type: "str", default: "", title: "A", description: "First text input." })
1947
+ ], ConcatTextNode.prototype, "a", void 0);
1948
+ __decorate([
1949
+ prop({ type: "str", default: "", title: "B", description: "Second text input." })
1950
+ ], ConcatTextNode.prototype, "b", void 0);
1951
+ export class JoinTextNode extends BaseNode {
1952
+ static nodeType = "nodetool.text.Join";
1953
+ static title = "Join";
1954
+ static description = "Joins a list of strings into a single string using a specified separator.\n text, join, combine, concatenate, merge, list";
1955
+ static metadataOutputTypes = {
1956
+ output: "str"
1957
+ };
1958
+ async process() {
1959
+ const list = Array.isArray(this.strings) ? this.strings : [];
1960
+ const sep = String(this.separator ?? "");
1961
+ return { output: list.map((s) => String(s ?? "")).join(sep) };
1962
+ }
1963
+ }
1964
+ __decorate([
1965
+ prop({
1966
+ type: "list[str]",
1967
+ default: [],
1968
+ title: "Strings",
1969
+ description: "The list of strings to join."
1970
+ })
1971
+ ], JoinTextNode.prototype, "strings", void 0);
1972
+ __decorate([
1973
+ prop({ type: "str", default: "", title: "Separator", description: "Separator between items." })
1974
+ ], JoinTextNode.prototype, "separator", void 0);
1975
+ export class CollectTextNode extends BaseNode {
1976
+ static nodeType = "nodetool.text.Collect";
1977
+ static title = "Collect Text";
1978
+ static description = "Collects streaming text inputs into a single concatenated string.\n text, collect, stream, aggregate";
1979
+ static metadataOutputTypes = {
1980
+ output: "str"
1981
+ };
1982
+ static syncMode = "on_any";
1983
+ _items = [];
1984
+ async initialize() {
1985
+ this._items = [];
1986
+ }
1987
+ async process() {
1988
+ this._items.push(String(this.input_item ?? ""));
1989
+ const sep = String(this.separator ?? "");
1990
+ return { output: this._items.join(sep) };
1991
+ }
1992
+ }
1993
+ __decorate([
1994
+ prop({ type: "str", default: "", title: "Input Item", description: "Text to collect." })
1995
+ ], CollectTextNode.prototype, "input_item", void 0);
1996
+ __decorate([
1997
+ prop({ type: "str", default: "", title: "Separator", description: "Separator between collected items." })
1998
+ ], CollectTextNode.prototype, "separator", void 0);
1999
+ export class FormatTextNode extends BaseNode {
2000
+ static nodeType = "nodetool.text.FormatText";
2001
+ static title = "Format Text";
2002
+ static description = "Replaces placeholders in a string with dynamic inputs using {{ variable }} or {variable} syntax.\n Supports Jinja2-style filters: {{ var|upper }}, {{ var|lower }}, {{ var|capitalize }},\n {{ var|title }}, {{ var|trim }}, {{ var|truncate(n) }}, {{ var|default(val) }}.\n text, template, formatting, format, variable, replace\n\n Use cases:\n - Generating personalized messages with dynamic content\n - Creating parameterized queries or commands";
2003
+ static metadataOutputTypes = {
2004
+ output: "str"
2005
+ };
2006
+ static isDynamic = true;
2007
+ applyFilter(value, filter) {
2008
+ const trimmed = filter.trim();
2009
+ if (trimmed === "upper")
2010
+ return value.toUpperCase();
2011
+ if (trimmed === "lower")
2012
+ return value.toLowerCase();
2013
+ if (trimmed === "capitalize") {
2014
+ return value.length === 0 ? "" : value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();
2015
+ }
2016
+ if (trimmed === "title") {
2017
+ return toTitleCase(value);
2018
+ }
2019
+ if (trimmed === "trim")
2020
+ return value.trim();
2021
+ const truncateMatch = trimmed.match(/^truncate\((\d+)\)$/);
2022
+ if (truncateMatch) {
2023
+ const n = Number(truncateMatch[1]);
2024
+ return value.length <= n ? value : value.slice(0, n) + "...";
2025
+ }
2026
+ const defaultMatch = trimmed.match(/^default\((.+)\)$/);
2027
+ if (defaultMatch) {
2028
+ return value === "" ? defaultMatch[1].replace(/^['"]|['"]$/g, "") : value;
2029
+ }
2030
+ return value;
2031
+ }
2032
+ applyFilters(value, filters) {
2033
+ let result = value;
2034
+ for (const f of filters) {
2035
+ result = this.applyFilter(result, f);
2036
+ }
2037
+ return result;
2038
+ }
2039
+ async process() {
2040
+ let result = String(this.template ?? "");
2041
+ const props = Object.fromEntries(this.dynamicProps);
2042
+ // Handle {{ var|filter1|filter2 }} syntax
2043
+ result = result.replace(/\{\{\s*([^}]+?)\s*\}\}/g, (_match, expr) => {
2044
+ const parts = expr.split("|").map((p) => p.trim());
2045
+ const varName = parts[0];
2046
+ if (varName in props) {
2047
+ const strValue = String(props[varName] ?? "");
2048
+ return parts.length > 1 ? this.applyFilters(strValue, parts.slice(1)) : strValue;
2049
+ }
2050
+ return _match;
2051
+ });
2052
+ // Handle {variable} syntax (no filters)
2053
+ for (const [key, value] of Object.entries(props)) {
2054
+ const strValue = String(value ?? "");
2055
+ const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2056
+ const single = new RegExp(`(?<!\\{)\\{${escapedKey}\\}(?!\\})`, "g");
2057
+ result = result.replace(single, () => strValue);
2058
+ }
2059
+ return { output: result };
2060
+ }
2061
+ }
2062
+ __decorate([
2063
+ prop({
2064
+ type: "str",
2065
+ default: "",
2066
+ title: "Template",
2067
+ description: "Template string with {{ variable }} or {variable} placeholders."
2068
+ })
2069
+ ], FormatTextNode.prototype, "template", void 0);
2070
+ export class TemplateTextNode extends BaseNode {
2071
+ static nodeType = "nodetool.text.Template";
2072
+ static title = "Template";
2073
+ static description = "Uses template syntax to format strings with variables. Supports {{ variable }} and {variable} patterns.\n text, template, formatting, format, combine, concatenate, variable, replace\n\n Use cases:\n - Generating personalized messages\n - Creating parameterized queries\n - Formatting text with variable inputs";
2074
+ static metadataOutputTypes = {
2075
+ output: "str"
2076
+ };
2077
+ static isDynamic = true;
2078
+ async process() {
2079
+ let result = String(this.string ?? "");
2080
+ const props = Object.fromEntries(this.dynamicProps);
2081
+ for (const [key, value] of Object.entries(props)) {
2082
+ const strValue = String(value ?? "");
2083
+ const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2084
+ const jinja = new RegExp(`\\{\\{\\s*${escapedKey}\\s*\\}\\}`, "g");
2085
+ result = result.replace(jinja, () => strValue);
2086
+ const single = new RegExp(`(?<!\\{)\\{${escapedKey}\\}(?!\\})`, "g");
2087
+ result = result.replace(single, () => strValue);
2088
+ }
2089
+ return { output: result };
2090
+ }
2091
+ }
2092
+ __decorate([
2093
+ prop({
2094
+ type: "str",
2095
+ default: "",
2096
+ title: "String",
2097
+ description: "Template string with {{ variable }} or {variable} placeholders."
2098
+ })
2099
+ ], TemplateTextNode.prototype, "string", void 0);
2100
+ export class ReplaceTextNode extends BaseNode {
2101
+ static nodeType = "nodetool.text.Replace";
2102
+ static title = "Replace Text";
2103
+ static description = "Replaces a substring in a text with another substring.\n text, replace, substitute\n\n Use cases:\n - Correcting or updating specific text patterns\n - Sanitizing or normalizing text data\n - Implementing simple text transformations";
2104
+ static metadataOutputTypes = {
2105
+ output: "str"
2106
+ };
2107
+ async process() {
2108
+ const text = String(this.text ?? "");
2109
+ const oldStr = String(this.old ?? "");
2110
+ // Support both "new_value" and "new" field names for Python compatibility
2111
+ const newStr = String(this.new_value ?? this["new"] ?? "");
2112
+ if (!oldStr)
2113
+ return { output: text };
2114
+ return { output: text.split(oldStr).join(newStr) };
2115
+ }
2116
+ }
2117
+ __decorate([
2118
+ prop({ type: "str", default: "", title: "Text", description: "The input text." })
2119
+ ], ReplaceTextNode.prototype, "text", void 0);
2120
+ __decorate([
2121
+ prop({ type: "str", default: "", title: "Old", description: "Substring to find." })
2122
+ ], ReplaceTextNode.prototype, "old", void 0);
2123
+ __decorate([
2124
+ prop({ type: "str", default: "", title: "New", description: "Replacement string." })
2125
+ ], ReplaceTextNode.prototype, "new_value", void 0);
2126
+ export class ToStringNode extends BaseNode {
2127
+ static nodeType = "nodetool.text.ToString";
2128
+ static title = "To String";
2129
+ static description = "Converts any input value to its string representation.\n text, string, convert, repr, str, cast";
2130
+ static metadataOutputTypes = {
2131
+ output: "str"
2132
+ };
2133
+ async process() {
2134
+ const v = this.value;
2135
+ const mode = String(this.mode ?? "str");
2136
+ const toJsonString = (value) => {
2137
+ if (value === undefined) {
2138
+ return "";
2139
+ }
2140
+ try {
2141
+ const json = JSON.stringify(value);
2142
+ if (json === undefined) {
2143
+ return "";
2144
+ }
2145
+ return json;
2146
+ }
2147
+ catch (_error) {
2148
+ // JSON.stringify can fail for non-serializable values (e.g. circular objects).
2149
+ return String(value);
2150
+ }
2151
+ };
2152
+ if (mode === "repr") {
2153
+ return { output: toJsonString(v) };
2154
+ }
2155
+ if (v === null || v === undefined)
2156
+ return { output: "" };
2157
+ if (typeof v === "object")
2158
+ return { output: toJsonString(v) };
2159
+ return { output: String(v) };
2160
+ }
2161
+ }
2162
+ __decorate([
2163
+ prop({ type: "any", default: "", title: "Value", description: "The value to convert to string." })
2164
+ ], ToStringNode.prototype, "value", void 0);
2165
+ __decorate([
2166
+ prop({
2167
+ type: "enum",
2168
+ default: "str",
2169
+ title: "Mode",
2170
+ description: "Conversion mode: 'str' for normal string, 'repr' for JSON-quoted representation.",
2171
+ values: ["str", "repr"]
2172
+ })
2173
+ ], ToStringNode.prototype, "mode", void 0);
2174
+ export const TEXT_EXTRA_NODES = [
2175
+ SplitTextNode,
2176
+ ExtractTextNode,
2177
+ ChunkTextNode,
2178
+ ExtractRegexNode,
2179
+ FindAllRegexNode,
2180
+ TextParseJSONNode,
2181
+ ExtractJSONNode,
2182
+ RegexMatchNode,
2183
+ RegexReplaceNode,
2184
+ RegexSplitNode,
2185
+ RegexValidateNode,
2186
+ CompareTextNode,
2187
+ EqualsTextNode,
2188
+ ToUppercaseNode,
2189
+ ToLowercaseNode,
2190
+ ToTitlecaseNode,
2191
+ CapitalizeTextNode,
2192
+ SliceTextNode,
2193
+ StartsWithTextNode,
2194
+ EndsWithTextNode,
2195
+ ContainsTextNode,
2196
+ TrimWhitespaceNode,
2197
+ CollapseWhitespaceNode,
2198
+ IsEmptyTextNode,
2199
+ RemovePunctuationNode,
2200
+ StripAccentsNode,
2201
+ SlugifyNode,
2202
+ HasLengthTextNode,
2203
+ TruncateTextNode,
2204
+ PadTextNode,
2205
+ LengthTextNode,
2206
+ IndexOfTextNode,
2207
+ SurroundWithTextNode,
2208
+ CountTokensNode,
2209
+ HtmlToTextNode,
2210
+ AutomaticSpeechRecognitionNode,
2211
+ EmbeddingTextNode,
2212
+ SaveTextFileNode,
2213
+ SaveTextNode,
2214
+ LoadTextFolderNode,
2215
+ LoadTextAssetsNode,
2216
+ FilterStringNode,
2217
+ FilterRegexStringNode,
2218
+ ConcatTextNode,
2219
+ JoinTextNode,
2220
+ CollectTextNode,
2221
+ FormatTextNode,
2222
+ TemplateTextNode,
2223
+ ReplaceTextNode,
2224
+ ToStringNode
2225
+ ];
2226
+ //# sourceMappingURL=text-extra.js.map