langflower 0.0.10 → 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.
- package/README.md +96 -70
- package/docs/public/README.md +2 -2
- package/docs/public/configuration.md +4 -0
- package/docs/public/extending.md +18 -2
- package/docs/public/getting-started.md +7 -0
- package/docs/public/how-it-works.md +18 -11
- package/docs/public/product.md +35 -25
- package/package.json +1 -1
- package/ui-dist/chunk-QI4IYILJ.js +4 -0
- package/ui-dist/{chunk-7UMVYN3A.js → chunk-UG3GFV4Y.js} +1 -1
- package/ui-dist/index.html +2 -2
- package/ui-dist/main-ODIDCCNX.js +315 -0
- package/ui-dist/styles-2JMBAQC3.css +1 -0
- package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.d.ts +2 -2
- package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.js +39 -7
- package/vendor/common-nodes/dist/ai/features/llm-session/run-session-machine.d.ts +11 -0
- package/vendor/common-nodes/dist/ai/features/llm-session/run-session-machine.js +2 -2
- package/vendor/common-nodes/dist/ai/features/run-host-services.d.ts +10 -0
- package/vendor/common-nodes/dist/ai/nodes/critique/node.js +5 -1
- package/vendor/common-nodes/dist/ai/nodes/fake-llm/node.js +7 -1
- package/vendor/common-nodes/dist/ai/nodes/openai-llm/node.js +5 -1
- package/vendor/common-nodes/dist/ai/nodes/review/node.js +7 -1
- package/vendor/common-nodes/dist/ai/nodes/sub-agent/node.js +62 -22
- package/vendor/common-nodes/dist/catalog.js +10 -0
- package/vendor/common-nodes/dist/crawl/crawl/node.js +11 -3
- package/vendor/common-nodes/dist/crawl/crawl-tools/node.js +5 -1
- package/vendor/common-nodes/dist/crawl/extract-links/node.js +7 -1
- package/vendor/common-nodes/dist/crawl/fetch-url/node.js +13 -4
- package/vendor/common-nodes/dist/crawl/save-page/node.js +11 -3
- package/vendor/common-nodes/dist/embeddings/create-embedding.d.ts +39 -0
- package/vendor/common-nodes/dist/embeddings/create-embedding.js +154 -0
- package/vendor/common-nodes/dist/embeddings/embed-provider/node.d.ts +53 -0
- package/vendor/common-nodes/dist/embeddings/embed-provider/node.js +126 -0
- package/vendor/common-nodes/dist/embeddings/embed-similarity/node.d.ts +20 -0
- package/vendor/common-nodes/dist/embeddings/embed-similarity/node.js +81 -0
- package/vendor/common-nodes/dist/embeddings/embed-text/node.d.ts +53 -0
- package/vendor/common-nodes/dist/embeddings/embed-text/node.js +91 -0
- package/vendor/common-nodes/dist/embeddings/from-embedding.d.ts +8 -0
- package/vendor/common-nodes/dist/embeddings/from-embedding.js +24 -0
- package/vendor/common-nodes/dist/embeddings/resolve-embedding-provider-model.d.ts +11 -0
- package/vendor/common-nodes/dist/embeddings/resolve-embedding-provider-model.js +8 -0
- package/vendor/common-nodes/dist/flow/checkpoint/node.js +7 -3
- package/vendor/common-nodes/dist/flow/delay/node.d.ts +2 -6
- package/vendor/common-nodes/dist/flow/delay/node.js +13 -9
- package/vendor/common-nodes/dist/flow/loop/node.js +7 -1
- package/vendor/common-nodes/dist/flow/merge/node.js +7 -1
- package/vendor/common-nodes/dist/flow/repeat/node.js +5 -1
- package/vendor/common-nodes/dist/flow/router/node.js +7 -1
- package/vendor/common-nodes/dist/hitl/chat-input/node.d.ts +2 -2
- package/vendor/common-nodes/dist/hitl/chat-input/node.js +8 -4
- package/vendor/common-nodes/dist/hitl/review-gate/node.js +11 -5
- package/vendor/common-nodes/dist/langflower-tools/node.js +5 -1
- package/vendor/common-nodes/dist/logic/assert/node.js +7 -1
- package/vendor/common-nodes/dist/logic/compare/node.js +7 -1
- package/vendor/common-nodes/dist/logic/gate/node.js +7 -1
- package/vendor/common-nodes/dist/logic/if/node.js +7 -1
- package/vendor/common-nodes/dist/logic/switch/node.js +7 -1
- package/vendor/common-nodes/dist/mcp/mcp-http/node.js +55 -53
- package/vendor/common-nodes/dist/mcp/mcp-stdio/node.js +52 -50
- package/vendor/common-nodes/dist/memory/memory-tools/node.js +5 -1
- package/vendor/common-nodes/dist/output/finish/node.js +13 -1
- package/vendor/common-nodes/dist/output/preview/node.js +9 -2
- package/vendor/common-nodes/dist/primitives/boolean/node.js +7 -1
- package/vendor/common-nodes/dist/primitives/number/node.js +7 -1
- package/vendor/common-nodes/dist/primitives/string/node.js +7 -1
- package/vendor/common-nodes/dist/primitives/string-multiline/node.d.ts +17 -0
- package/vendor/common-nodes/dist/primitives/string-multiline/node.js +31 -0
- package/vendor/common-nodes/dist/text/append-file/node.js +11 -3
- package/vendor/common-nodes/dist/text/concat/node.js +5 -1
- package/vendor/common-nodes/dist/text/read-file/node.js +9 -3
- package/vendor/common-nodes/dist/text/split-paced/node.d.ts +21 -0
- package/vendor/common-nodes/dist/text/split-paced/node.js +93 -0
- package/vendor/common-nodes/dist/text/write-file/node.js +11 -3
- package/vendor/common-nodes/dist/tools/tool-collection/node.js +5 -2
- package/vendor/common-nodes/package.json +4 -0
- package/vendor/node-sdk/dist/node-factory/define-embed/embed-handle.d.ts +25 -0
- package/vendor/node-sdk/dist/node-factory/define-embed/embed-handle.js +25 -0
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.d.ts +1 -0
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.js +1 -0
- package/vendor/node-sdk/dist/node-factory/define-node/define-node.d.ts +2 -0
- package/vendor/node-sdk/dist/node-factory/define-node/define-node.js +4 -1
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-reactive-node.d.ts +3 -1
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-reactive-node.js +2 -1
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/io-helpers.d.ts +15 -0
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/io-helpers.js +17 -1
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/port-meta.d.ts +17 -4
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/delay-node.js +4 -2
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/types.d.ts +4 -3
- package/vendor/node-sdk/dist/testing/create-node-harness.d.ts +30 -0
- package/vendor/node-sdk/dist/testing/create-node-harness.js +68 -0
- package/vendor/node-sdk/package.json +4 -4
- package/vendor/runtime/dist/types.d.ts +1 -1
- package/vendor/server/dist/bootstrap/project-bootstrap.service.d.ts +1 -1
- package/vendor/server/dist/bootstrap/seed-skeleton.d.ts +2 -2
- package/vendor/server/dist/bootstrap/seed-skeleton.js +17 -2
- package/vendor/server/dist/bridge/bind-embed-context.d.ts +7 -0
- package/vendor/server/dist/bridge/bind-embed-context.js +16 -0
- package/vendor/server/dist/bridge/build-execution-context.d.ts +2 -2
- package/vendor/server/dist/bridge/build-execution-context.js +6 -2
- package/vendor/server/dist/bridge/emit-bootstrap.js +4 -1
- package/vendor/server/dist/bridge/settings-draft-controller.js +7 -3
- package/vendor/server/dist/bridge/wire-config-handlers.js +2 -0
- package/vendor/server/dist/bridge/wire-editor-handlers.js +14 -0
- package/vendor/server/dist/config/langflower-config.service.d.ts +2 -0
- package/vendor/server/dist/config/langflower-config.service.js +30 -0
- package/vendor/server/dist/session/build-session-bootstrap.js +1 -0
- package/vendor/server/dist/session/langflower-session.d.ts +3 -1
- package/vendor/server/dist/session/langflower-session.js +3 -1
- package/vendor/server/dist/workflow/apply-editor-mutation.js +6 -0
- package/vendor/server/dist/workflow/workflow-persisted-inputs.js +8 -6
- package/vendor/server/skeleton/instructions.md +15 -3
- package/vendor/server/skeleton/nodes/hello-embed/README.md +185 -0
- package/vendor/server/skeleton/nodes/hello-embed/hello-embed.nodes.test.ts +181 -0
- package/vendor/server/skeleton/nodes/hello-embed/ingest.ts +126 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/chunk-markdown.test.ts +40 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/chunk-markdown.ts +123 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/ingest-search.test.ts +180 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/ingest.ts +128 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/paths.test.ts +20 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/paths.ts +70 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/schema.ts +21 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/search.ts +254 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/text-embedder.ts +14 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/vectors.ts +126 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/walk-markdown.test.ts +62 -0
- package/vendor/server/skeleton/nodes/hello-embed/lib/walk-markdown.ts +67 -0
- package/vendor/server/skeleton/nodes/hello-embed/package.json +11 -0
- package/vendor/server/skeleton/nodes/hello-embed/search-handle.ts +119 -0
- package/vendor/server/skeleton/nodes/hello-embed/search.ts +98 -0
- package/vendor/server/skeleton/nodes/hello-embed/tsconfig.json +14 -0
- package/vendor/server/skeleton/nodes/my-nodes/README.md +13 -3
- package/vendor/server/skeleton/schemas/langflower-config.schema.json +4 -0
- package/vendor/server/skeleton/skills/langflower-helper/SKILL.md +99 -26
- package/vendor/server/skeleton/skills/langflower-helper/architecture.md +11 -6
- package/vendor/server/skeleton/skills/langflower-helper/layout.md +24 -18
- package/vendor/server/skeleton/skills/langflower-node-writer/SKILL.md +8 -1
- package/vendor/server/skeleton/workflows/kb-ingest.json +88 -0
- package/vendor/server/skeleton/workflows/kb-manual-search.json +105 -0
- package/vendor/server/skeleton/workflows/kb-rag.json +192 -0
- package/vendor/server/skeleton/workflows/kb-tool.json +111 -0
- package/vendor/shared/dist/langflower-bus-config.d.ts +22 -6
- package/vendor/shared/dist/langflower-bus-config.js +23 -7
- package/vendor/shared/dist/langflower-config/merge-langflower-config-layers.test.js +8 -0
- package/vendor/shared/dist/langflower-config/settings-draft.d.ts +5 -0
- package/vendor/shared/dist/langflower-config/settings-draft.js +15 -7
- package/vendor/shared/dist/langflower.d.ts +1 -1
- package/vendor/shared/dist/langflower.js +1 -1
- package/vendor/shared/dist/types/langflower-bootstrap.d.ts +6 -0
- package/vendor/shared/dist/types/langflower-config.d.ts +17 -0
- package/vendor/shared/dist/types/langflower-palette.d.ts +2 -1
- package/vendor/tools/dist/harness-types.d.ts +1 -1
- package/vendor/tools/dist/mcp/build-mcp-handle.d.ts +3 -21
- package/vendor/tools/dist/mcp/build-mcp-handle.js +2 -11
- package/vendor/tools/dist/mcp/create-system-mcp-handles.d.ts +9 -6
- package/vendor/tools/dist/mcp/create-system-mcp-handles.js +21 -17
- package/vendor/tools/package.json +1 -0
- package/ui-dist/chunk-MDGXX73Z.js +0 -4
- package/ui-dist/main-Z7CPFXFA.js +0 -313
- package/ui-dist/styles-2TMDAUD7.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:
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
*
|
|
5
|
-
* `
|
|
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
|
-
*
|
|
7
|
-
* `
|
|
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:
|
|
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 }))
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
3
|
-
*
|
|
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
|
|
5
|
-
*
|
|
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:
|
|
12
|
-
|
|
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,
|
|
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:
|
|
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$ =
|
|
46
|
-
const feedback$ =
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
import { defineReactiveNode, TOOL_HANDLE_WIRE_TYPE, } from '@langflower/node-sdk';
|
|
1
|
+
import { defineReactiveNode, withLoading, TOOL_HANDLE_WIRE_TYPE, } from '@langflower/node-sdk';
|
|
2
2
|
import { buildMcpHandle } from '@langflower/tools/build-mcp-handle';
|
|
3
3
|
import { formatMcpConnectError } from '@langflower/tools/format-mcp-connect-error';
|
|
4
4
|
import { connectMcpHttpWithOptionalLaunch } from '@langflower/tools/mcp-http-client';
|
|
5
|
-
import { distinctUntilChanged,
|
|
5
|
+
import { distinctUntilChanged, filter, Observable, switchMap } from 'rxjs';
|
|
6
6
|
const paramsKey = (params) => JSON.stringify({
|
|
7
7
|
nodeId: params.nodeId,
|
|
8
8
|
projectDir: params.projectDir,
|
|
@@ -19,7 +19,11 @@ export const mcpHttpNode = defineReactiveNode({
|
|
|
19
19
|
type: 'common-mcp-http',
|
|
20
20
|
displayName: 'MCP http',
|
|
21
21
|
category: 'Tools',
|
|
22
|
-
description:
|
|
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(),
|
|
23
27
|
uiSchema: [],
|
|
24
28
|
bind(ctx, { makeInput, configureOutput, combineInputs }) {
|
|
25
29
|
const url = makeInput('url', {
|
|
@@ -35,60 +39,58 @@ export const mcpHttpNode = defineReactiveNode({
|
|
|
35
39
|
inline: 'text',
|
|
36
40
|
defaultValue: '',
|
|
37
41
|
});
|
|
38
|
-
const
|
|
42
|
+
const params$ = combineInputs([ctx, url, command], ([ec, serverUrl, cli]) => ({
|
|
39
43
|
nodeId: String(ec.nodeId ?? ''),
|
|
40
44
|
projectDir: String(ec.projectDir ?? ''),
|
|
41
45
|
url: String(serverUrl ?? '').trim(),
|
|
42
46
|
command: String(cli ?? '').trim(),
|
|
43
|
-
})).pipeValue(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
};
|
|
91
|
-
});
|
|
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
|
+
};
|
|
92
94
|
})));
|
|
93
95
|
return {
|
|
94
96
|
inputs: [url, command],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { defineReactiveNode, TOOL_HANDLE_WIRE_TYPE, } from '@langflower/node-sdk';
|
|
1
|
+
import { defineReactiveNode, withLoading, TOOL_HANDLE_WIRE_TYPE, } from '@langflower/node-sdk';
|
|
2
2
|
import { buildMcpHandle } from '@langflower/tools/build-mcp-handle';
|
|
3
3
|
import { formatMcpConnectError } from '@langflower/tools/format-mcp-connect-error';
|
|
4
4
|
import { connectMcpStdioFromCli } from '@langflower/tools/mcp-stdio-client';
|
|
5
|
-
import { distinctUntilChanged,
|
|
5
|
+
import { distinctUntilChanged, filter, Observable, switchMap } from 'rxjs';
|
|
6
6
|
const paramsKey = (params) => JSON.stringify({
|
|
7
7
|
nodeId: params.nodeId,
|
|
8
8
|
projectDir: params.projectDir,
|
|
@@ -18,7 +18,13 @@ export const mcpStdioNode = defineReactiveNode({
|
|
|
18
18
|
type: 'common-mcp-stdio',
|
|
19
19
|
displayName: 'MCP stdio',
|
|
20
20
|
category: 'Tools',
|
|
21
|
-
description:
|
|
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(),
|
|
22
28
|
uiSchema: [],
|
|
23
29
|
bind(ctx, { makeInput, configureOutput, combineInputs }) {
|
|
24
30
|
const command = makeInput('command', {
|
|
@@ -28,56 +34,52 @@ export const mcpStdioNode = defineReactiveNode({
|
|
|
28
34
|
defaultValue: '',
|
|
29
35
|
required: true,
|
|
30
36
|
});
|
|
31
|
-
const
|
|
37
|
+
const params$ = combineInputs([ctx, command], ([ec, cli]) => ({
|
|
32
38
|
nodeId: String(ec.nodeId ?? ''),
|
|
33
39
|
projectDir: String(ec.projectDir ?? ''),
|
|
34
40
|
command: String(cli ?? '').trim(),
|
|
35
|
-
})).pipeValue(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
void
|
|
76
|
-
|
|
77
|
-
closed = true;
|
|
78
|
-
void closeClient?.();
|
|
79
|
-
};
|
|
80
|
-
});
|
|
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
|
+
};
|
|
81
83
|
})));
|
|
82
84
|
return {
|
|
83
85
|
inputs: [command],
|
|
@@ -8,6 +8,10 @@ export const memoryToolsNode = defineToolRegistrations({
|
|
|
8
8
|
type: 'common-memory-tools',
|
|
9
9
|
displayName: 'Memory Tools',
|
|
10
10
|
category: 'Tools',
|
|
11
|
-
description:
|
|
11
|
+
description: `
|
|
12
|
+
Give an agent tools to read and write the project wiki (tree, search, append, update, create).
|
|
13
|
+
|
|
14
|
+
Wire **tools** into an LLM. Notes live under the project's memory folder.
|
|
15
|
+
`.trim(),
|
|
12
16
|
tools: MEMORY_TOOL_CONFIGS,
|
|
13
17
|
});
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
import { defineReactiveNode } from '@langflower/node-sdk';
|
|
2
|
+
import { map } from 'rxjs';
|
|
2
3
|
/** Passthrough sink — first output emission stops the run. */
|
|
3
4
|
export const finishNode = defineReactiveNode({
|
|
4
5
|
type: 'common-finish',
|
|
5
6
|
displayName: 'Finish',
|
|
6
7
|
category: 'Output',
|
|
7
|
-
description:
|
|
8
|
+
description: `
|
|
9
|
+
Last step of a run. When this node outputs, the run **stops**.
|
|
10
|
+
|
|
11
|
+
Wire the final result here so Start/Stop settle instead of hanging on open work.
|
|
12
|
+
`.trim(),
|
|
8
13
|
stopsRun: true,
|
|
9
14
|
emitOncePerActivation: true,
|
|
10
15
|
uiSchema: [],
|
|
11
16
|
bind(_ctx, { makeInput, configureOutput }) {
|
|
12
17
|
const value = makeInput('value', { name: 'value', required: true });
|
|
18
|
+
const done$ = value.pipeValue(map(() => 'done'));
|
|
13
19
|
return {
|
|
14
20
|
inputs: [value],
|
|
15
21
|
outputs: [
|
|
22
|
+
configureOutput('done', done$, {
|
|
23
|
+
wireType: 'string',
|
|
24
|
+
hidden: true,
|
|
25
|
+
feed: { role: 'result' },
|
|
26
|
+
}),
|
|
16
27
|
configureOutput('value', value, {
|
|
17
28
|
inferTypeFrom: value,
|
|
29
|
+
feed: { role: 'none' },
|
|
18
30
|
}),
|
|
19
31
|
],
|
|
20
32
|
};
|
|
@@ -19,14 +19,20 @@ export const previewNode = defineReactiveNode({
|
|
|
19
19
|
type: 'common-preview',
|
|
20
20
|
displayName: 'Preview',
|
|
21
21
|
category: 'Output',
|
|
22
|
-
description:
|
|
22
|
+
description: `
|
|
23
|
+
Show a wired value on the canvas and in the work log so you can inspect it.
|
|
24
|
+
|
|
25
|
+
Typical uses:
|
|
26
|
+
- Debug a mid-pipeline value
|
|
27
|
+
- A human-readable end of a small graph
|
|
28
|
+
`.trim(),
|
|
23
29
|
uiSchema: [],
|
|
24
30
|
bind(_ctx, { makeInput, configureOutput }) {
|
|
25
31
|
const text = makeInput('text', {
|
|
26
32
|
name: 'text',
|
|
27
33
|
wireType: 'string',
|
|
28
34
|
required: true,
|
|
29
|
-
inline: 'preview',
|
|
35
|
+
inline: 'preview-markdown',
|
|
30
36
|
});
|
|
31
37
|
const output$ = text.pipeValue(map(formatPreviewText));
|
|
32
38
|
return {
|
|
@@ -34,6 +40,7 @@ export const previewNode = defineReactiveNode({
|
|
|
34
40
|
outputs: [
|
|
35
41
|
configureOutput('text', output$, {
|
|
36
42
|
inferTypeFrom: text,
|
|
43
|
+
feed: { role: 'result' },
|
|
37
44
|
}),
|
|
38
45
|
],
|
|
39
46
|
};
|