langflower 0.0.9 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/README.md +96 -70
  2. package/docs/public/README.md +2 -2
  3. package/docs/public/configuration.md +4 -0
  4. package/docs/public/extending.md +18 -2
  5. package/docs/public/getting-started.md +7 -0
  6. package/docs/public/how-it-works.md +18 -11
  7. package/docs/public/product.md +35 -25
  8. package/package.json +2 -2
  9. package/ui-dist/chunk-QI4IYILJ.js +4 -0
  10. package/ui-dist/{chunk-7UMVYN3A.js → chunk-UG3GFV4Y.js} +1 -1
  11. package/ui-dist/index.html +2 -2
  12. package/ui-dist/main-ODIDCCNX.js +315 -0
  13. package/ui-dist/styles-2JMBAQC3.css +1 -0
  14. package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-reducer.js +0 -12
  15. package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-types.d.ts +2 -7
  16. package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-types.js +1 -1
  17. package/vendor/common-nodes/dist/ai/features/llm-loop/run-agent-loop.d.ts +0 -3
  18. package/vendor/common-nodes/dist/ai/features/llm-loop/run-agent-loop.js +22 -36
  19. package/vendor/common-nodes/dist/ai/features/llm-loop/run-llm-loop.d.ts +1 -7
  20. package/vendor/common-nodes/dist/ai/features/llm-loop/run-llm-loop.js +12 -35
  21. package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.d.ts +5 -12
  22. package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.js +48 -21
  23. package/vendor/common-nodes/dist/ai/features/llm-session/run-session-machine.d.ts +11 -0
  24. package/vendor/common-nodes/dist/ai/features/llm-session/run-session-machine.js +2 -2
  25. package/vendor/common-nodes/dist/ai/features/path-choice/run-reactive-path-choice-loop.d.ts +0 -3
  26. package/vendor/common-nodes/dist/ai/features/path-choice/run-reactive-path-choice-loop.js +2 -15
  27. package/vendor/common-nodes/dist/ai/features/run-host-services.d.ts +10 -0
  28. package/vendor/common-nodes/dist/ai/features/sub-agent-protocol.d.ts +1 -0
  29. package/vendor/common-nodes/dist/ai/features/sub-agent-protocol.js +1 -0
  30. package/vendor/common-nodes/dist/ai/features/ui-schema/llm-recovery-ui-schema.d.ts +1 -1
  31. package/vendor/common-nodes/dist/ai/features/ui-schema/llm-recovery-ui-schema.js +1 -1
  32. package/vendor/common-nodes/dist/ai/features/wait-for-subagent-result.d.ts +1 -0
  33. package/vendor/common-nodes/dist/ai/features/wait-for-subagent-result.js +1 -0
  34. package/vendor/common-nodes/dist/ai/nodes/critique/node.d.ts +3 -3
  35. package/vendor/common-nodes/dist/ai/nodes/critique/node.js +10 -19
  36. package/vendor/common-nodes/dist/ai/nodes/fake-llm/node.d.ts +3 -3
  37. package/vendor/common-nodes/dist/ai/nodes/fake-llm/node.js +10 -11
  38. package/vendor/common-nodes/dist/ai/nodes/openai-llm/node.d.ts +3 -3
  39. package/vendor/common-nodes/dist/ai/nodes/openai-llm/node.js +7 -10
  40. package/vendor/common-nodes/dist/ai/nodes/review/node.d.ts +3 -3
  41. package/vendor/common-nodes/dist/ai/nodes/review/node.js +12 -19
  42. package/vendor/common-nodes/dist/ai/nodes/sub-agent/node.d.ts +5 -5
  43. package/vendor/common-nodes/dist/ai/nodes/sub-agent/node.js +251 -96
  44. package/vendor/common-nodes/dist/catalog.js +12 -0
  45. package/vendor/common-nodes/dist/crawl/crawl/node.js +11 -3
  46. package/vendor/common-nodes/dist/crawl/crawl-tools/node.js +5 -1
  47. package/vendor/common-nodes/dist/crawl/extract-links/node.js +7 -1
  48. package/vendor/common-nodes/dist/crawl/fetch-url/node.js +13 -4
  49. package/vendor/common-nodes/dist/crawl/save-page/node.js +11 -3
  50. package/vendor/common-nodes/dist/embeddings/create-embedding.d.ts +39 -0
  51. package/vendor/common-nodes/dist/embeddings/create-embedding.js +154 -0
  52. package/vendor/common-nodes/dist/embeddings/embed-provider/node.d.ts +53 -0
  53. package/vendor/common-nodes/dist/embeddings/embed-provider/node.js +126 -0
  54. package/vendor/common-nodes/dist/embeddings/embed-similarity/node.d.ts +20 -0
  55. package/vendor/common-nodes/dist/embeddings/embed-similarity/node.js +81 -0
  56. package/vendor/common-nodes/dist/embeddings/embed-text/node.d.ts +53 -0
  57. package/vendor/common-nodes/dist/embeddings/embed-text/node.js +91 -0
  58. package/vendor/common-nodes/dist/embeddings/from-embedding.d.ts +8 -0
  59. package/vendor/common-nodes/dist/embeddings/from-embedding.js +24 -0
  60. package/vendor/common-nodes/dist/embeddings/resolve-embedding-provider-model.d.ts +11 -0
  61. package/vendor/common-nodes/dist/embeddings/resolve-embedding-provider-model.js +8 -0
  62. package/vendor/common-nodes/dist/flow/checkpoint/node.js +7 -3
  63. package/vendor/common-nodes/dist/flow/delay/node.d.ts +2 -6
  64. package/vendor/common-nodes/dist/flow/delay/node.js +13 -9
  65. package/vendor/common-nodes/dist/flow/loop/node.js +7 -1
  66. package/vendor/common-nodes/dist/flow/merge/node.js +7 -1
  67. package/vendor/common-nodes/dist/flow/repeat/node.js +5 -1
  68. package/vendor/common-nodes/dist/flow/router/node.js +7 -1
  69. package/vendor/common-nodes/dist/hitl/chat-input/node.d.ts +2 -2
  70. package/vendor/common-nodes/dist/hitl/chat-input/node.js +8 -4
  71. package/vendor/common-nodes/dist/hitl/review-gate/node.js +11 -5
  72. package/vendor/common-nodes/dist/langflower-tools/node.js +5 -1
  73. package/vendor/common-nodes/dist/logic/assert/node.js +7 -1
  74. package/vendor/common-nodes/dist/logic/compare/node.js +7 -1
  75. package/vendor/common-nodes/dist/logic/gate/node.js +7 -1
  76. package/vendor/common-nodes/dist/logic/if/node.js +7 -1
  77. package/vendor/common-nodes/dist/logic/switch/node.js +7 -1
  78. package/vendor/common-nodes/dist/mcp/mcp-http/node.d.ts +4 -4
  79. package/vendor/common-nodes/dist/mcp/mcp-http/node.js +61 -60
  80. package/vendor/common-nodes/dist/mcp/mcp-stdio/node.d.ts +4 -4
  81. package/vendor/common-nodes/dist/mcp/mcp-stdio/node.js +58 -57
  82. package/vendor/common-nodes/dist/memory/memory-tools/node.js +5 -1
  83. package/vendor/common-nodes/dist/output/finish/node.js +13 -1
  84. package/vendor/common-nodes/dist/output/preview/node.js +9 -2
  85. package/vendor/common-nodes/dist/primitives/boolean/node.js +7 -1
  86. package/vendor/common-nodes/dist/primitives/number/node.js +7 -1
  87. package/vendor/common-nodes/dist/primitives/string/node.js +7 -1
  88. package/vendor/common-nodes/dist/primitives/string-multiline/node.d.ts +17 -0
  89. package/vendor/common-nodes/dist/primitives/string-multiline/node.js +31 -0
  90. package/vendor/common-nodes/dist/text/append-file/node.js +11 -3
  91. package/vendor/common-nodes/dist/text/concat/node.js +5 -1
  92. package/vendor/common-nodes/dist/text/read-file/node.js +9 -3
  93. package/vendor/common-nodes/dist/text/split-paced/node.d.ts +21 -0
  94. package/vendor/common-nodes/dist/text/split-paced/node.js +93 -0
  95. package/vendor/common-nodes/dist/text/write-file/node.js +11 -3
  96. package/vendor/common-nodes/dist/tools/collect-agent-tool-handles.d.ts +4 -4
  97. package/vendor/common-nodes/dist/tools/collect-agent-tool-handles.js +3 -11
  98. package/vendor/common-nodes/dist/tools/inventory-tool-round.d.ts +0 -10
  99. package/vendor/common-nodes/dist/tools/inventory-tool-round.js +0 -84
  100. package/vendor/common-nodes/dist/tools/tool-collection/node.d.ts +20 -0
  101. package/vendor/common-nodes/dist/tools/tool-collection/node.js +45 -0
  102. package/vendor/common-nodes/package.json +5 -5
  103. package/vendor/compiler/package.json +1 -1
  104. package/vendor/node-sdk/dist/node-factory/define-embed/embed-handle.d.ts +25 -0
  105. package/vendor/node-sdk/dist/node-factory/define-embed/embed-handle.js +25 -0
  106. package/vendor/node-sdk/dist/node-factory/define-llm-node/default-llm-ports.d.ts +3 -7
  107. package/vendor/node-sdk/dist/node-factory/define-llm-node/default-llm-ports.js +4 -44
  108. package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.d.ts +3 -5
  109. package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.js +3 -5
  110. package/vendor/node-sdk/dist/node-factory/define-llm-node/llm-inventory-wire.d.ts +1 -0
  111. package/vendor/node-sdk/dist/node-factory/define-llm-node/llm-inventory-wire.js +1 -0
  112. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.d.ts +4 -4
  113. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.js +2 -1
  114. package/vendor/node-sdk/dist/node-factory/define-node/define-node.d.ts +2 -0
  115. package/vendor/node-sdk/dist/node-factory/define-node/define-node.js +4 -1
  116. package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-reactive-node.d.ts +3 -1
  117. package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-reactive-node.js +2 -1
  118. package/vendor/node-sdk/dist/node-factory/define-reactive-node/io-helpers.d.ts +15 -0
  119. package/vendor/node-sdk/dist/node-factory/define-reactive-node/io-helpers.js +17 -1
  120. package/vendor/node-sdk/dist/node-factory/define-reactive-node/port-meta.d.ts +17 -4
  121. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/delay-node.js +4 -2
  122. package/vendor/node-sdk/dist/node-factory/define-reactive-node/types.d.ts +6 -7
  123. package/vendor/node-sdk/dist/node-factory/define-reactive-node/ui-schema-inference.d.ts +1 -1
  124. package/vendor/node-sdk/dist/testing/create-node-harness.d.ts +30 -0
  125. package/vendor/node-sdk/dist/testing/create-node-harness.js +68 -0
  126. package/vendor/node-sdk/package.json +5 -5
  127. package/vendor/runtime/dist/port-feed-override.d.ts +13 -0
  128. package/vendor/runtime/dist/port-feed-override.js +21 -0
  129. package/vendor/runtime/dist/port-signal-from-response.d.ts +15 -0
  130. package/vendor/runtime/dist/port-signal-from-response.js +48 -0
  131. package/vendor/runtime/dist/runtime-runner.d.ts +8 -3
  132. package/vendor/runtime/dist/runtime-runner.js +102 -81
  133. package/vendor/runtime/dist/runtime.d.ts +3 -2
  134. package/vendor/runtime/dist/runtime.js +1 -1
  135. package/vendor/runtime/dist/testing/workflows/workflow-events.d.ts +2 -0
  136. package/vendor/runtime/dist/testing/workflows/workflow-events.js +7 -5
  137. package/vendor/runtime/dist/types.d.ts +26 -9
  138. package/vendor/runtime/dist/types.js +3 -0
  139. package/vendor/runtime/package.json +1 -1
  140. package/vendor/server/dist/bootstrap/project-bootstrap.service.d.ts +1 -1
  141. package/vendor/server/dist/bootstrap/seed-skeleton.d.ts +2 -2
  142. package/vendor/server/dist/bootstrap/seed-skeleton.js +17 -2
  143. package/vendor/server/dist/bridge/bind-embed-context.d.ts +7 -0
  144. package/vendor/server/dist/bridge/bind-embed-context.js +16 -0
  145. package/vendor/server/dist/bridge/build-execution-context.d.ts +2 -2
  146. package/vendor/server/dist/bridge/build-execution-context.js +8 -4
  147. package/vendor/server/dist/bridge/emit-bootstrap.js +4 -1
  148. package/vendor/server/dist/bridge/get-live-wired-tools.d.ts +3 -2
  149. package/vendor/server/dist/bridge/get-live-wired-tools.js +8 -5
  150. package/vendor/server/dist/bridge/settings-draft-controller.js +7 -3
  151. package/vendor/server/dist/bridge/wire-config-handlers.js +2 -0
  152. package/vendor/server/dist/bridge/wire-editor-handlers.js +14 -0
  153. package/vendor/server/dist/bridge/wire-runner-handlers.js +2 -2
  154. package/vendor/server/dist/bridge/wire-workflow-handlers.js +23 -9
  155. package/vendor/server/dist/checkpoint/run-checkpoint-session.js +3 -3
  156. package/vendor/server/dist/config/langflower-config.service.d.ts +2 -0
  157. package/vendor/server/dist/config/langflower-config.service.js +30 -0
  158. package/vendor/server/dist/session/build-session-bootstrap.js +1 -0
  159. package/vendor/server/dist/session/langflower-session.d.ts +3 -1
  160. package/vendor/server/dist/session/langflower-session.js +3 -1
  161. package/vendor/server/dist/session/reset-session-execution-feed.d.ts +6 -0
  162. package/vendor/server/dist/session/reset-session-execution-feed.js +8 -0
  163. package/vendor/server/dist/workflow/apply-editor-mutation.js +6 -0
  164. package/vendor/server/dist/workflow/workflow-persisted-inputs.js +8 -6
  165. package/vendor/server/skeleton/instructions.md +15 -3
  166. package/vendor/server/skeleton/nodes/hello-embed/README.md +185 -0
  167. package/vendor/server/skeleton/nodes/hello-embed/hello-embed.nodes.test.ts +181 -0
  168. package/vendor/server/skeleton/nodes/hello-embed/ingest.ts +126 -0
  169. package/vendor/server/skeleton/nodes/hello-embed/lib/chunk-markdown.test.ts +40 -0
  170. package/vendor/server/skeleton/nodes/hello-embed/lib/chunk-markdown.ts +123 -0
  171. package/vendor/server/skeleton/nodes/hello-embed/lib/ingest-search.test.ts +180 -0
  172. package/vendor/server/skeleton/nodes/hello-embed/lib/ingest.ts +128 -0
  173. package/vendor/server/skeleton/nodes/hello-embed/lib/paths.test.ts +20 -0
  174. package/vendor/server/skeleton/nodes/hello-embed/lib/paths.ts +70 -0
  175. package/vendor/server/skeleton/nodes/hello-embed/lib/schema.ts +21 -0
  176. package/vendor/server/skeleton/nodes/hello-embed/lib/search.ts +254 -0
  177. package/vendor/server/skeleton/nodes/hello-embed/lib/text-embedder.ts +14 -0
  178. package/vendor/server/skeleton/nodes/hello-embed/lib/vectors.ts +126 -0
  179. package/vendor/server/skeleton/nodes/hello-embed/lib/walk-markdown.test.ts +62 -0
  180. package/vendor/server/skeleton/nodes/hello-embed/lib/walk-markdown.ts +67 -0
  181. package/vendor/server/skeleton/nodes/hello-embed/package.json +11 -0
  182. package/vendor/server/skeleton/nodes/hello-embed/search-handle.ts +119 -0
  183. package/vendor/server/skeleton/nodes/hello-embed/search.ts +98 -0
  184. package/vendor/server/skeleton/nodes/hello-embed/tsconfig.json +14 -0
  185. package/vendor/server/skeleton/nodes/my-nodes/README.md +13 -3
  186. package/vendor/server/skeleton/nodes/my-nodes/package.json +1 -1
  187. package/vendor/server/skeleton/schemas/langflower-config.schema.json +4 -0
  188. package/vendor/server/skeleton/skills/langflower-helper/SKILL.md +125 -38
  189. package/vendor/server/skeleton/skills/langflower-helper/architecture.md +17 -6
  190. package/vendor/server/skeleton/skills/langflower-helper/layout.md +24 -17
  191. package/vendor/server/skeleton/skills/langflower-node-writer/SKILL.md +8 -1
  192. package/vendor/server/skeleton/skills/langflower-workflow-writer/SKILL.md +12 -8
  193. package/vendor/server/skeleton/workflows/kb-create.json +15 -43
  194. package/vendor/server/skeleton/workflows/kb-ingest.json +88 -0
  195. package/vendor/server/skeleton/workflows/kb-manual-search.json +105 -0
  196. package/vendor/server/skeleton/workflows/kb-navigate.json +8 -22
  197. package/vendor/server/skeleton/workflows/kb-rag.json +192 -0
  198. package/vendor/server/skeleton/workflows/kb-tool.json +111 -0
  199. package/vendor/server/skeleton/workflows/simple-coder.json +18 -46
  200. package/vendor/server/skeleton/workflows/starter.json +8 -22
  201. package/vendor/shared/dist/execution/derive-run-settle-outcome.js +2 -2
  202. package/vendor/shared/dist/execution/derive-run-settle-outcome.test.js +11 -8
  203. package/vendor/shared/dist/langflower-bus-config.d.ts +22 -6
  204. package/vendor/shared/dist/langflower-bus-config.js +23 -7
  205. package/vendor/shared/dist/langflower-config/merge-langflower-config-layers.test.js +8 -0
  206. package/vendor/shared/dist/langflower-config/settings-draft.d.ts +5 -0
  207. package/vendor/shared/dist/langflower-config/settings-draft.js +15 -7
  208. package/vendor/shared/dist/langflower-ws-waits.d.ts +3 -1
  209. package/vendor/shared/dist/langflower-ws-waits.js +2 -2
  210. package/vendor/shared/dist/langflower.d.ts +1 -1
  211. package/vendor/shared/dist/langflower.js +1 -1
  212. package/vendor/shared/dist/types/langflower-bootstrap.d.ts +6 -0
  213. package/vendor/shared/dist/types/langflower-config.d.ts +17 -0
  214. package/vendor/shared/dist/types/langflower-palette.d.ts +2 -1
  215. package/vendor/tools/dist/harness-types.d.ts +1 -1
  216. package/vendor/tools/dist/mcp/build-mcp-handle.d.ts +3 -21
  217. package/vendor/tools/dist/mcp/build-mcp-handle.js +2 -11
  218. package/vendor/tools/dist/mcp/create-system-mcp-handles.d.ts +9 -6
  219. package/vendor/tools/dist/mcp/create-system-mcp-handles.js +21 -17
  220. package/vendor/tools/package.json +1 -0
  221. package/ui-dist/chunk-MDGXX73Z.js +0 -4
  222. package/ui-dist/main-2JJGCNTD.js +0 -313
  223. package/ui-dist/styles-EOXODOI7.css +0 -1
@@ -11,9 +11,13 @@ export const checkpointNode = defineReactiveNode({
11
11
  displayName: 'Checkpoint',
12
12
  category: 'Flow',
13
13
  paletteSecondary: true,
14
- description: 'Passthrough that **writes a durable checkpoint** when crossed. ' +
15
- 'Stop without crossing a Checkpoint does not create a resume point. ' +
16
- 'Optional **label** appears in the Continue picker.',
14
+ description: `
15
+ Save a resume point when the run passes this node. Stop without crossing it does **not** create Continue.
16
+
17
+ Typical uses:
18
+ - A safe place to resume a long job
19
+ - Optional **label** in the Continue picker
20
+ `.trim(),
17
21
  uiSchema: [],
18
22
  bind(_ctx, { makeInput, configureOutput }) {
19
23
  const value = makeInput('value', {
@@ -1,12 +1,8 @@
1
1
  /**
2
2
  * Pass-through with configurable RxJS delay on inline `delay` input (ms).
3
3
  *
4
- * Built with `combineInputs(...).pipeValue(concatMap(...))`. The runtime's
5
- * `tapOutputPort` taps this output and forwards its `pending`/`value` lifecycle
6
- * over the WS bridge — the bridge now holds an always-on `events$` subscription
7
- * (see BUG-2026-07-14 in `docs/FOUND_BUGS.md`), so the `pending` pulse is
8
- * delivered to the UI. `delayMs` is annotated because `combineInputs` passes the
9
- * combined value as an untyped tuple.
4
+ * Stamp pending with {@link withLoading} on the raw stream before async
5
+ * `pipeValue`. `pipeValue(concatMap(delay))` only delays success.
10
6
  */
11
7
  export declare const delayNode: {
12
8
  readonly emitOncePerActivation: boolean;
@@ -1,21 +1,23 @@
1
- import { defineReactiveNode } from '@langflower/node-sdk';
2
1
  import { concatMap, delay, of } from 'rxjs';
2
+ import { defineReactiveNode, withLoading } from '@langflower/node-sdk';
3
3
  /**
4
4
  * Pass-through with configurable RxJS delay on inline `delay` input (ms).
5
5
  *
6
- * Built with `combineInputs(...).pipeValue(concatMap(...))`. The runtime's
7
- * `tapOutputPort` taps this output and forwards its `pending`/`value` lifecycle
8
- * over the WS bridge — the bridge now holds an always-on `events$` subscription
9
- * (see BUG-2026-07-14 in `docs/FOUND_BUGS.md`), so the `pending` pulse is
10
- * delivered to the UI. `delayMs` is annotated because `combineInputs` passes the
11
- * combined value as an untyped tuple.
6
+ * Stamp pending with {@link withLoading} on the raw stream before async
7
+ * `pipeValue`. `pipeValue(concatMap(delay))` only delays success.
12
8
  */
13
9
  export const delayNode = defineReactiveNode({
14
10
  type: 'common-delay',
15
11
  displayName: 'Delay',
16
12
  category: 'Flow',
17
13
  paletteSecondary: true,
18
- description: 'Passes through the wired `value` after an inline **delay** in milliseconds.',
14
+ description: `
15
+ Hold a value for a number of milliseconds, then pass it on unchanged.
16
+
17
+ Typical uses:
18
+ - Pace a Repeat or Split (paced) loop
19
+ - Wait before the next API or file step
20
+ `.trim(),
19
21
  uiSchema: [],
20
22
  bind(_ctx, { makeInput, configureOutput, combineInputs }) {
21
23
  const value = makeInput('value', {
@@ -29,7 +31,9 @@ export const delayNode = defineReactiveNode({
29
31
  inline: 'text',
30
32
  defaultValue: 0,
31
33
  });
32
- const output$ = combineInputs([value, delayInput], ([inputValue, delayMs]) => ({ inputValue, delayMs })).pipeValue(concatMap(({ inputValue, delayMs }) => of(inputValue).pipe(delay(delayMs))));
34
+ const output$ = combineInputs([value, delayInput], ([inputValue, delayMs]) => ({ inputValue, delayMs }))
35
+ .pipe(withLoading())
36
+ .pipeValue(concatMap(({ inputValue, delayMs }) => of(inputValue).pipe(delay(Math.max(0, Number(delayMs) || 0)))));
33
37
  return {
34
38
  inputs: [value, delayInput],
35
39
  outputs: [
@@ -11,7 +11,13 @@ export const loopNode = defineReactiveNode({
11
11
  displayName: 'Loop',
12
12
  category: 'Flow',
13
13
  paletteSecondary: true,
14
- description: 'Map-collect over a runtime list: emit each **item** to an external body, collect **results** (JSON array). Dynamic N without graph rewrite.',
14
+ description: `
15
+ For each item in a list, run the body you wire, then collect the results.
16
+
17
+ Typical uses:
18
+ - Process many files or topics without duplicating nodes
19
+ - Map a list through an LLM or a file write
20
+ `.trim(),
15
21
  uiSchema: [],
16
22
  bind(_ctx, { makeInput, configureOutput }) {
17
23
  const items = makeInput('items', {
@@ -5,7 +5,13 @@ export const mergeNode = defineReactiveNode({
5
5
  displayName: 'Merge',
6
6
  category: 'Flow',
7
7
  paletteSecondary: true,
8
- description: 'Merges multiple `value` inputs into a **single stream** as values arrive.',
8
+ description: `
9
+ Join several wires into one. Each incoming value is forwarded as it arrives.
10
+
11
+ Typical uses:
12
+ - Fan-in parallel branches
13
+ - Collect results from Router channels
14
+ `.trim(),
9
15
  uiSchema: [],
10
16
  bind(_ctx, { makeInput, configureOutput }) {
11
17
  const value$ = makeInput('value', {
@@ -9,7 +9,11 @@ export const repeatNode = defineReactiveNode({
9
9
  displayName: 'Repeat',
10
10
  category: 'Flow',
11
11
  paletteSecondary: true,
12
- description: 'Repeats wired `value` **count** times. First emit ASAP; later emits wait for `trigger`. After the last value, the next trigger emits `done: true` instead of another value.',
12
+ description: `
13
+ Send the same value several times. The first copy starts immediately; pulse **trigger** for the next.
14
+
15
+ After the last copy, the next trigger fires **done** instead of another value. **index** counts from 0 so you can show progress.
16
+ `.trim(),
13
17
  uiSchema: [],
14
18
  bind(_ctx, { makeInput, configureOutput, combineInputs }) {
15
19
  const value = makeInput('value', {
@@ -5,7 +5,13 @@ export const routerNode = defineReactiveNode({
5
5
  type: COMMON_ROUTER_TYPE,
6
6
  displayName: 'Router',
7
7
  category: 'Flow',
8
- description: 'Use for **visual organisation of edges** in complex workflows. Any number of inputs can be connected — input ports expand dynamically.',
8
+ description: `
9
+ Tidy a busy canvas: any number of inputs can connect, and extra ports appear as you wire more.
10
+
11
+ Typical uses:
12
+ - Group many edges so they stay readable
13
+ - Fan-out one stream to several destinations
14
+ `.trim(),
9
15
  uiSchema: [],
10
16
  bind() {
11
17
  return { inputs: [], outputs: [] };
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Conversational run entry — no wireable inputs; the feed composer submits
3
- * `message`, which cold-starts the cluster via `pushIntoInput`.
2
+ * Conversational run entry. `message` is hidden + inline: field, no handle.
3
+ * Prefill on the node or in the composer; Start cold-starts via `pushIntoInput`.
4
4
  */
5
5
  export declare const chatInputNode: {
6
6
  readonly emitOncePerActivation: boolean;
@@ -1,15 +1,18 @@
1
1
  import { defineReactiveNode } from '@langflower/node-sdk';
2
2
  import { map } from 'rxjs';
3
3
  /**
4
- * Conversational run entry — no wireable inputs; the feed composer submits
5
- * `message`, which cold-starts the cluster via `pushIntoInput`.
4
+ * Conversational run entry. `message` is hidden + inline: field, no handle.
5
+ * Prefill on the node or in the composer; Start cold-starts via `pushIntoInput`.
6
6
  */
7
7
  export const chatInputNode = defineReactiveNode({
8
8
  type: 'common-chat-input',
9
9
  displayName: 'Chat Input',
10
10
  category: 'HITL',
11
- description: 'Starts a chat-style run from the feed composer. Clusters with this ' +
12
- 'node are **not** started by plain Run — submit a message instead.',
11
+ description: `
12
+ Start this graph from the composer **Start** control — not plain Run.
13
+
14
+ Prefill a message on the node or type in the composer. Stop then Start reuses it.
15
+ `.trim(),
13
16
  chatEntry: true,
14
17
  uiSchema: [],
15
18
  bind(_ctx, { makeInput, configureOutput }) {
@@ -17,6 +20,7 @@ export const chatInputNode = defineReactiveNode({
17
20
  name: 'Message',
18
21
  wireType: 'string',
19
22
  hidden: true,
23
+ inline: 'text-multiline',
20
24
  hitl: {
21
25
  title: 'Message',
22
26
  kind: 'textarea',
@@ -1,11 +1,17 @@
1
- import { defineReactiveNode } from '@langflower/node-sdk';
2
- import { filter, map, pipe, switchMap, take } from 'rxjs';
1
+ import { defineReactiveNode, withLoading } from '@langflower/node-sdk';
2
+ import { filter, map, switchMap, take } from 'rxjs';
3
3
  /** Review gate: separate HITL inputs for approve vs request-changes. */
4
4
  export const hitlReviewGateNode = defineReactiveNode({
5
5
  type: 'common-hitl-review-gate',
6
6
  displayName: 'Review Gate',
7
7
  category: 'HITL',
8
- description: 'HITL gate with separate **Approve** and **Request changes** actions.',
8
+ description: `
9
+ Pause for a human. **Approve** to continue, or **Request changes** with feedback.
10
+
11
+ Typical uses:
12
+ - Gate a draft before the next stage
13
+ - Collect edits without leaving the editor
14
+ `.trim(),
9
15
  uiSchema: [],
10
16
  bind(_ctx, { makeInput, configureOutput }) {
11
17
  const result = makeInput('result', {
@@ -42,8 +48,8 @@ export const hitlReviewGateNode = defineReactiveNode({
42
48
  inferTypeFrom: result,
43
49
  feed: { role: 'none' },
44
50
  });
45
- const response$ = approve.pipeValue(pipe(filter((approved) => approved === true), switchMap(() => result.value$.pipe(take(1))), map((reviewed) => reviewed ?? '')));
46
- const feedback$ = requestChanges.pipeValue(map((text) => text ?? ''));
51
+ const response$ = result.pipe(withLoading()).pipeValue(switchMap((reviewed) => approve.value$.pipe(filter((approved) => approved === true), take(1), map(() => reviewed ?? ''))));
52
+ const feedback$ = result.pipe(withLoading()).pipeValue(switchMap(() => requestChanges.value$.pipe(take(1), map((text) => text ?? ''))));
47
53
  return {
48
54
  inputs: [result, approve, requestChanges],
49
55
  outputs: [
@@ -64,7 +64,11 @@ export const langflowerToolsNode = defineReactiveNode({
64
64
  type: 'common-langflower-tools',
65
65
  displayName: 'Langflower Tools',
66
66
  category: 'Tools',
67
- description: 'Emits compile_custom_nodes (Custom → Update over the bus). Wire tools to opt in; later bus actions may be added to this pack.',
67
+ description: `
68
+ Wire this into an agent so it can recompile custom nodes from chat — same intent as Custom → **Update**.
69
+
70
+ On starter, Helper and Writer already have this wired.
71
+ `.trim(),
68
72
  uiSchema: [],
69
73
  bind(ctx, { configureOutput }) {
70
74
  return {
@@ -9,7 +9,13 @@ export const assertNode = defineReactiveNode({
9
9
  displayName: 'Assert',
10
10
  category: 'Logic',
11
11
  paletteSecondary: true,
12
- description: 'Fails the run branch when `condition` is not true; otherwise passthrough `value`.',
12
+ description: `
13
+ Stop this branch if **condition** is not true. Otherwise the **value** passes through.
14
+
15
+ Typical uses:
16
+ - Fail the run when tests did not pass
17
+ - Block the next stage until a check is green
18
+ `.trim(),
13
19
  uiSchema: [],
14
20
  bind(_ctx, { makeInput, configureOutput, combineInputs }) {
15
21
  const condition = makeInput('condition', {
@@ -6,7 +6,13 @@ export const compareNode = defineReactiveNode({
6
6
  displayName: 'Compare',
7
7
  category: 'Logic',
8
8
  paletteSecondary: true,
9
- description: 'Compares wired `a` and `b` with panel operator (`eq`, `ne`, `lt`, …) → boolean `result`.',
9
+ description: `
10
+ Compare **a** and **b** (equals, not-equals, less than, …) and emit a boolean.
11
+
12
+ Typical uses:
13
+ - Drive IF or Gate
14
+ - Check a score or a count
15
+ `.trim(),
10
16
  uiSchema: [
11
17
  {
12
18
  field: 'op',
@@ -6,7 +6,13 @@ export const gateNode = defineReactiveNode({
6
6
  displayName: 'Gate',
7
7
  category: 'Logic',
8
8
  paletteSecondary: true,
9
- description: 'Forwards wired `value` only when boolean `pass` is true; otherwise emits nothing.',
9
+ description: `
10
+ Forward **value** only when **pass** is true. Otherwise nothing is emitted.
11
+
12
+ Typical uses:
13
+ - Drop failed reviews
14
+ - Continue a loop only while a flag stays true
15
+ `.trim(),
10
16
  uiSchema: [],
11
17
  bind(_ctx, { makeInput, configureOutput, combineInputs }) {
12
18
  const pass = makeInput('pass', {
@@ -6,7 +6,13 @@ export const ifNode = defineReactiveNode({
6
6
  displayName: 'IF',
7
7
  category: 'Logic',
8
8
  paletteSecondary: true,
9
- description: 'Routes wired `value` to the `true` or `false` output from boolean `condition`.',
9
+ description: `
10
+ Send **value** out **true** or **false** depending on **condition**.
11
+
12
+ Typical uses:
13
+ - Branch after Compare or Assert
14
+ - Two different follow-up paths from one check
15
+ `.trim(),
10
16
  uiSchema: [],
11
17
  bind(_ctx, { makeInput, configureOutput, combineInputs }) {
12
18
  const condition = makeInput('condition', {
@@ -14,7 +14,13 @@ export const switchNode = defineReactiveNode({
14
14
  displayName: 'Switch',
15
15
  category: 'Logic',
16
16
  paletteSecondary: true,
17
- description: 'Routes string `value` to the first matching rule output (`pass` / `fail`) or `default`.',
17
+ description: `
18
+ Match a string against rules and send it to **pass**, **fail**, or **default**.
19
+
20
+ Typical uses:
21
+ - Route by status text
22
+ - Several named outcomes without stacking IF nodes
23
+ `.trim(),
18
24
  uiSchema: [
19
25
  {
20
26
  field: 'rules',
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Owns HTTP MCP connect/close (optional local launch); emits live {@link McpHandle}.
3
- * Handle id = graph nodeId; server name and tools come from MCP initialize /
4
- * tools/list. Connect/initialize/build failure → output port **error** (not
5
- * silent EMPTY).
2
+ * Owns HTTP MCP connect/close (optional local launch); emits live
3
+ * {@link ToolHandle}[] for LLM `tools`. Server name and tools come from MCP
4
+ * initialize / tools/list. Session stays in invoke closures.
5
+ * Connect/initialize/build failure → output port **error** (not silent EMPTY).
6
6
  */
7
7
  export declare const mcpHttpNode: {
8
8
  readonly emitOncePerActivation: boolean;
@@ -1,9 +1,8 @@
1
- import { defineReactiveNode } from '@langflower/node-sdk';
2
- import { MCP_HANDLE_WIRE_TYPE } from '@langflower/node-sdk/mcp';
1
+ import { defineReactiveNode, withLoading, TOOL_HANDLE_WIRE_TYPE, } from '@langflower/node-sdk';
3
2
  import { buildMcpHandle } from '@langflower/tools/build-mcp-handle';
4
3
  import { formatMcpConnectError } from '@langflower/tools/format-mcp-connect-error';
5
4
  import { connectMcpHttpWithOptionalLaunch } from '@langflower/tools/mcp-http-client';
6
- import { distinctUntilChanged, EMPTY, Observable, pipe, switchMap } from 'rxjs';
5
+ import { distinctUntilChanged, filter, Observable, switchMap } from 'rxjs';
7
6
  const paramsKey = (params) => JSON.stringify({
8
7
  nodeId: params.nodeId,
9
8
  projectDir: params.projectDir,
@@ -11,16 +10,20 @@ const paramsKey = (params) => JSON.stringify({
11
10
  command: params.command,
12
11
  });
13
12
  /**
14
- * Owns HTTP MCP connect/close (optional local launch); emits live {@link McpHandle}.
15
- * Handle id = graph nodeId; server name and tools come from MCP initialize /
16
- * tools/list. Connect/initialize/build failure → output port **error** (not
17
- * silent EMPTY).
13
+ * Owns HTTP MCP connect/close (optional local launch); emits live
14
+ * {@link ToolHandle}[] for LLM `tools`. Server name and tools come from MCP
15
+ * initialize / tools/list. Session stays in invoke closures.
16
+ * Connect/initialize/build failure → output port **error** (not silent EMPTY).
18
17
  */
19
18
  export const mcpHttpNode = defineReactiveNode({
20
19
  type: 'common-mcp-http',
21
20
  displayName: 'MCP http',
22
21
  category: 'Tools',
23
- description: 'Connects to an MCP server over Streamable HTTP. Optional shell command launches a local process first; URL alone targets an already-running server.',
22
+ description: `
23
+ Connect to an MCP server over HTTP and give its tools to an agent.
24
+
25
+ Paste a URL for a server that is already running, or set a launch command to start one first.
26
+ `.trim(),
24
27
  uiSchema: [],
25
28
  bind(ctx, { makeInput, configureOutput, combineInputs }) {
26
29
  const url = makeInput('url', {
@@ -36,66 +39,64 @@ export const mcpHttpNode = defineReactiveNode({
36
39
  inline: 'text',
37
40
  defaultValue: '',
38
41
  });
39
- const handle$ = combineInputs([ctx, url, command], ([ec, serverUrl, cli]) => ({
42
+ const params$ = combineInputs([ctx, url, command], ([ec, serverUrl, cli]) => ({
40
43
  nodeId: String(ec.nodeId ?? ''),
41
44
  projectDir: String(ec.projectDir ?? ''),
42
45
  url: String(serverUrl ?? '').trim(),
43
46
  command: String(cli ?? '').trim(),
44
- })).pipeValue(pipe(distinctUntilChanged((left, right) => paramsKey(left) === paramsKey(right)), switchMap((params) => {
45
- if (params.url.length === 0 ||
46
- params.nodeId.trim().length === 0) {
47
- return EMPTY;
48
- }
49
- return new Observable((subscriber) => {
50
- let closed = false;
51
- let closeSession;
52
- const fail = (cause) => {
53
- if (closed || subscriber.closed) {
54
- return;
55
- }
56
- subscriber.error(formatMcpConnectError(cause, {
57
- nodeId: params.nodeId,
58
- kind: 'http',
59
- target: params.url,
60
- }));
61
- };
62
- const run = async () => {
63
- const session = await connectMcpHttpWithOptionalLaunch({
64
- url: params.url,
65
- ...(params.command.length > 0
66
- ? { command: params.command }
67
- : {}),
68
- ...(params.projectDir.length > 0
69
- ? { cwd: params.projectDir }
70
- : {}),
71
- });
72
- closeSession = () => session.close();
73
- if (closed) {
74
- await session.close();
75
- return;
76
- }
77
- const handle = await buildMcpHandle({
78
- id: params.nodeId,
79
- client: session.client,
80
- });
81
- if (closed) {
82
- await session.close();
83
- return;
84
- }
85
- subscriber.next(handle);
86
- };
87
- void run().catch(fail);
88
- return () => {
89
- closed = true;
90
- void closeSession?.();
91
- };
92
- });
47
+ })).pipeValue(distinctUntilChanged((left, right) => paramsKey(left) === paramsKey(right)));
48
+ const handle$ = params$
49
+ .pipeValue(filter((params) => params.url.length > 0 &&
50
+ params.nodeId.trim().length > 0))
51
+ .pipe(withLoading())
52
+ .pipeValue(switchMap((params) => new Observable((subscriber) => {
53
+ let closed = false;
54
+ let closeSession;
55
+ const fail = (cause) => {
56
+ if (closed || subscriber.closed) {
57
+ return;
58
+ }
59
+ subscriber.error(formatMcpConnectError(cause, {
60
+ nodeId: params.nodeId,
61
+ kind: 'http',
62
+ target: params.url,
63
+ }));
64
+ };
65
+ const run = async () => {
66
+ const session = await connectMcpHttpWithOptionalLaunch({
67
+ url: params.url,
68
+ ...(params.command.length > 0
69
+ ? { command: params.command }
70
+ : {}),
71
+ ...(params.projectDir.length > 0
72
+ ? { cwd: params.projectDir }
73
+ : {}),
74
+ });
75
+ closeSession = () => session.close();
76
+ if (closed) {
77
+ await session.close();
78
+ return;
79
+ }
80
+ const tools = await buildMcpHandle({
81
+ client: session.client,
82
+ });
83
+ if (closed) {
84
+ await session.close();
85
+ return;
86
+ }
87
+ subscriber.next(tools);
88
+ };
89
+ void run().catch(fail);
90
+ return () => {
91
+ closed = true;
92
+ void closeSession?.();
93
+ };
93
94
  })));
94
95
  return {
95
96
  inputs: [url, command],
96
97
  outputs: [
97
- configureOutput('mcpTransport', handle$, {
98
- wireType: MCP_HANDLE_WIRE_TYPE,
98
+ configureOutput('tools', handle$, {
99
+ wireType: TOOL_HANDLE_WIRE_TYPE,
99
100
  }),
100
101
  ],
101
102
  };
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Owns stdio MCP connect/close; emits live {@link McpHandle} for LLM `mcp`.
3
- * Handle id = graph nodeId; server name and tools come from MCP initialize /
4
- * tools/list. Connect/initialize/build failure → output port **error** (not
5
- * silent EMPTY).
2
+ * Owns stdio MCP connect/close; emits live {@link ToolHandle}[] for LLM `tools`.
3
+ * Server name and tools come from MCP initialize / tools/list. Session stays
4
+ * in invoke closures. Connect/initialize/build failure → output port **error**
5
+ * (not silent EMPTY).
6
6
  */
7
7
  export declare const mcpStdioNode: {
8
8
  readonly emitOncePerActivation: boolean;
@@ -1,25 +1,30 @@
1
- import { defineReactiveNode } from '@langflower/node-sdk';
2
- import { MCP_HANDLE_WIRE_TYPE } from '@langflower/node-sdk/mcp';
1
+ import { defineReactiveNode, withLoading, TOOL_HANDLE_WIRE_TYPE, } from '@langflower/node-sdk';
3
2
  import { buildMcpHandle } from '@langflower/tools/build-mcp-handle';
4
3
  import { formatMcpConnectError } from '@langflower/tools/format-mcp-connect-error';
5
4
  import { connectMcpStdioFromCli } from '@langflower/tools/mcp-stdio-client';
6
- import { distinctUntilChanged, EMPTY, Observable, pipe, switchMap } from 'rxjs';
5
+ import { distinctUntilChanged, filter, Observable, switchMap } from 'rxjs';
7
6
  const paramsKey = (params) => JSON.stringify({
8
7
  nodeId: params.nodeId,
9
8
  projectDir: params.projectDir,
10
9
  command: params.command,
11
10
  });
12
11
  /**
13
- * Owns stdio MCP connect/close; emits live {@link McpHandle} for LLM `mcp`.
14
- * Handle id = graph nodeId; server name and tools come from MCP initialize /
15
- * tools/list. Connect/initialize/build failure → output port **error** (not
16
- * silent EMPTY).
12
+ * Owns stdio MCP connect/close; emits live {@link ToolHandle}[] for LLM `tools`.
13
+ * Server name and tools come from MCP initialize / tools/list. Session stays
14
+ * in invoke closures. Connect/initialize/build failure → output port **error**
15
+ * (not silent EMPTY).
17
16
  */
18
17
  export const mcpStdioNode = defineReactiveNode({
19
18
  type: 'common-mcp-stdio',
20
19
  displayName: 'MCP stdio',
21
20
  category: 'Tools',
22
- description: 'Launches an MCP server over stdio from a shell command line and emits a live handle for LLM `mcp` ports.',
21
+ description: `
22
+ Launch an MCP server from a command and give its tools to an agent.
23
+
24
+ Typical uses:
25
+ - Local stdio MCP (filesystem, browser, …)
26
+ - Extra tools without writing a custom node
27
+ `.trim(),
23
28
  uiSchema: [],
24
29
  bind(ctx, { makeInput, configureOutput, combineInputs }) {
25
30
  const command = makeInput('command', {
@@ -29,62 +34,58 @@ export const mcpStdioNode = defineReactiveNode({
29
34
  defaultValue: '',
30
35
  required: true,
31
36
  });
32
- const handle$ = combineInputs([ctx, command], ([ec, cli]) => ({
37
+ const params$ = combineInputs([ctx, command], ([ec, cli]) => ({
33
38
  nodeId: String(ec.nodeId ?? ''),
34
39
  projectDir: String(ec.projectDir ?? ''),
35
40
  command: String(cli ?? '').trim(),
36
- })).pipeValue(pipe(distinctUntilChanged((left, right) => paramsKey(left) === paramsKey(right)), switchMap((params) => {
37
- if (params.command.length === 0 ||
38
- params.nodeId.trim().length === 0) {
39
- return EMPTY;
40
- }
41
- return new Observable((subscriber) => {
42
- let closed = false;
43
- let closeClient;
44
- const fail = (cause) => {
45
- if (closed || subscriber.closed) {
46
- return;
47
- }
48
- subscriber.error(formatMcpConnectError(cause, {
49
- nodeId: params.nodeId,
50
- kind: 'stdio',
51
- target: params.command,
52
- }));
53
- };
54
- const run = async () => {
55
- const client = await connectMcpStdioFromCli({
56
- commandLine: params.command,
57
- ...(params.projectDir.length > 0
58
- ? { cwd: params.projectDir }
59
- : {}),
60
- });
61
- closeClient = () => client.close();
62
- if (closed) {
63
- await client.close();
64
- return;
65
- }
66
- const handle = await buildMcpHandle({
67
- id: params.nodeId,
68
- client,
69
- });
70
- if (closed) {
71
- await client.close();
72
- return;
73
- }
74
- subscriber.next(handle);
75
- };
76
- void run().catch(fail);
77
- return () => {
78
- closed = true;
79
- void closeClient?.();
80
- };
81
- });
41
+ })).pipeValue(distinctUntilChanged((left, right) => paramsKey(left) === paramsKey(right)));
42
+ const handle$ = params$
43
+ .pipeValue(filter((params) => params.command.length > 0 &&
44
+ params.nodeId.trim().length > 0))
45
+ .pipe(withLoading())
46
+ .pipeValue(switchMap((params) => new Observable((subscriber) => {
47
+ let closed = false;
48
+ let closeClient;
49
+ const fail = (cause) => {
50
+ if (closed || subscriber.closed) {
51
+ return;
52
+ }
53
+ subscriber.error(formatMcpConnectError(cause, {
54
+ nodeId: params.nodeId,
55
+ kind: 'stdio',
56
+ target: params.command,
57
+ }));
58
+ };
59
+ const run = async () => {
60
+ const client = await connectMcpStdioFromCli({
61
+ commandLine: params.command,
62
+ ...(params.projectDir.length > 0
63
+ ? { cwd: params.projectDir }
64
+ : {}),
65
+ });
66
+ closeClient = () => client.close();
67
+ if (closed) {
68
+ await client.close();
69
+ return;
70
+ }
71
+ const tools = await buildMcpHandle({ client });
72
+ if (closed) {
73
+ await client.close();
74
+ return;
75
+ }
76
+ subscriber.next(tools);
77
+ };
78
+ void run().catch(fail);
79
+ return () => {
80
+ closed = true;
81
+ void closeClient?.();
82
+ };
82
83
  })));
83
84
  return {
84
85
  inputs: [command],
85
86
  outputs: [
86
- configureOutput('mcpTransport', handle$, {
87
- wireType: MCP_HANDLE_WIRE_TYPE,
87
+ configureOutput('tools', handle$, {
88
+ wireType: TOOL_HANDLE_WIRE_TYPE,
88
89
  }),
89
90
  ],
90
91
  };