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.
- 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 +2 -2
- 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-loop/llm-loop-reducer.js +0 -12
- package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-types.d.ts +2 -7
- package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-types.js +1 -1
- package/vendor/common-nodes/dist/ai/features/llm-loop/run-agent-loop.d.ts +0 -3
- package/vendor/common-nodes/dist/ai/features/llm-loop/run-agent-loop.js +22 -36
- package/vendor/common-nodes/dist/ai/features/llm-loop/run-llm-loop.d.ts +1 -7
- package/vendor/common-nodes/dist/ai/features/llm-loop/run-llm-loop.js +12 -35
- package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.d.ts +5 -12
- package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.js +48 -21
- 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/path-choice/run-reactive-path-choice-loop.d.ts +0 -3
- package/vendor/common-nodes/dist/ai/features/path-choice/run-reactive-path-choice-loop.js +2 -15
- package/vendor/common-nodes/dist/ai/features/run-host-services.d.ts +10 -0
- package/vendor/common-nodes/dist/ai/features/sub-agent-protocol.d.ts +1 -0
- package/vendor/common-nodes/dist/ai/features/sub-agent-protocol.js +1 -0
- package/vendor/common-nodes/dist/ai/features/ui-schema/llm-recovery-ui-schema.d.ts +1 -1
- package/vendor/common-nodes/dist/ai/features/ui-schema/llm-recovery-ui-schema.js +1 -1
- package/vendor/common-nodes/dist/ai/features/wait-for-subagent-result.d.ts +1 -0
- package/vendor/common-nodes/dist/ai/features/wait-for-subagent-result.js +1 -0
- package/vendor/common-nodes/dist/ai/nodes/critique/node.d.ts +3 -3
- package/vendor/common-nodes/dist/ai/nodes/critique/node.js +10 -19
- package/vendor/common-nodes/dist/ai/nodes/fake-llm/node.d.ts +3 -3
- package/vendor/common-nodes/dist/ai/nodes/fake-llm/node.js +10 -11
- package/vendor/common-nodes/dist/ai/nodes/openai-llm/node.d.ts +3 -3
- package/vendor/common-nodes/dist/ai/nodes/openai-llm/node.js +7 -10
- package/vendor/common-nodes/dist/ai/nodes/review/node.d.ts +3 -3
- package/vendor/common-nodes/dist/ai/nodes/review/node.js +12 -19
- package/vendor/common-nodes/dist/ai/nodes/sub-agent/node.d.ts +5 -5
- package/vendor/common-nodes/dist/ai/nodes/sub-agent/node.js +251 -96
- package/vendor/common-nodes/dist/catalog.js +12 -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.d.ts +4 -4
- package/vendor/common-nodes/dist/mcp/mcp-http/node.js +61 -60
- package/vendor/common-nodes/dist/mcp/mcp-stdio/node.d.ts +4 -4
- package/vendor/common-nodes/dist/mcp/mcp-stdio/node.js +58 -57
- 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/collect-agent-tool-handles.d.ts +4 -4
- package/vendor/common-nodes/dist/tools/collect-agent-tool-handles.js +3 -11
- package/vendor/common-nodes/dist/tools/inventory-tool-round.d.ts +0 -10
- package/vendor/common-nodes/dist/tools/inventory-tool-round.js +0 -84
- package/vendor/common-nodes/dist/tools/tool-collection/node.d.ts +20 -0
- package/vendor/common-nodes/dist/tools/tool-collection/node.js +45 -0
- package/vendor/common-nodes/package.json +5 -5
- package/vendor/compiler/package.json +1 -1
- 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-llm-node/default-llm-ports.d.ts +3 -7
- package/vendor/node-sdk/dist/node-factory/define-llm-node/default-llm-ports.js +4 -44
- package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.d.ts +3 -5
- package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.js +3 -5
- package/vendor/node-sdk/dist/node-factory/define-llm-node/llm-inventory-wire.d.ts +1 -0
- package/vendor/node-sdk/dist/node-factory/define-llm-node/llm-inventory-wire.js +1 -0
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.d.ts +4 -4
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.js +2 -1
- 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 +6 -7
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/ui-schema-inference.d.ts +1 -1
- 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 +5 -5
- package/vendor/runtime/dist/port-feed-override.d.ts +13 -0
- package/vendor/runtime/dist/port-feed-override.js +21 -0
- package/vendor/runtime/dist/port-signal-from-response.d.ts +15 -0
- package/vendor/runtime/dist/port-signal-from-response.js +48 -0
- package/vendor/runtime/dist/runtime-runner.d.ts +8 -3
- package/vendor/runtime/dist/runtime-runner.js +102 -81
- package/vendor/runtime/dist/runtime.d.ts +3 -2
- package/vendor/runtime/dist/runtime.js +1 -1
- package/vendor/runtime/dist/testing/workflows/workflow-events.d.ts +2 -0
- package/vendor/runtime/dist/testing/workflows/workflow-events.js +7 -5
- package/vendor/runtime/dist/types.d.ts +26 -9
- package/vendor/runtime/dist/types.js +3 -0
- package/vendor/runtime/package.json +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 +8 -4
- package/vendor/server/dist/bridge/emit-bootstrap.js +4 -1
- package/vendor/server/dist/bridge/get-live-wired-tools.d.ts +3 -2
- package/vendor/server/dist/bridge/get-live-wired-tools.js +8 -5
- 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/bridge/wire-runner-handlers.js +2 -2
- package/vendor/server/dist/bridge/wire-workflow-handlers.js +23 -9
- package/vendor/server/dist/checkpoint/run-checkpoint-session.js +3 -3
- 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/session/reset-session-execution-feed.d.ts +6 -0
- package/vendor/server/dist/session/reset-session-execution-feed.js +8 -0
- 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/nodes/my-nodes/package.json +1 -1
- package/vendor/server/skeleton/schemas/langflower-config.schema.json +4 -0
- package/vendor/server/skeleton/skills/langflower-helper/SKILL.md +125 -38
- package/vendor/server/skeleton/skills/langflower-helper/architecture.md +17 -6
- package/vendor/server/skeleton/skills/langflower-helper/layout.md +24 -17
- package/vendor/server/skeleton/skills/langflower-node-writer/SKILL.md +8 -1
- package/vendor/server/skeleton/skills/langflower-workflow-writer/SKILL.md +12 -8
- package/vendor/server/skeleton/workflows/kb-create.json +15 -43
- 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-navigate.json +8 -22
- package/vendor/server/skeleton/workflows/kb-rag.json +192 -0
- package/vendor/server/skeleton/workflows/kb-tool.json +111 -0
- package/vendor/server/skeleton/workflows/simple-coder.json +18 -46
- package/vendor/server/skeleton/workflows/starter.json +8 -22
- package/vendor/shared/dist/execution/derive-run-settle-outcome.js +2 -2
- package/vendor/shared/dist/execution/derive-run-settle-outcome.test.js +11 -8
- 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-ws-waits.d.ts +3 -1
- package/vendor/shared/dist/langflower-ws-waits.js +2 -2
- 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-2JJGCNTD.js +0 -313
- package/ui-dist/styles-EOXODOI7.css +0 -1
|
@@ -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
|
};
|
|
@@ -4,7 +4,13 @@ export const booleanNode = defineReactiveNode({
|
|
|
4
4
|
type: 'common-boolean',
|
|
5
5
|
displayName: 'Boolean',
|
|
6
6
|
category: 'Primitives',
|
|
7
|
-
description:
|
|
7
|
+
description: `
|
|
8
|
+
Put a constant true/false on the canvas.
|
|
9
|
+
|
|
10
|
+
Typical uses:
|
|
11
|
+
- Drive IF, Gate, or Assert without another node
|
|
12
|
+
- A toggle you can flip while authoring
|
|
13
|
+
`.trim(),
|
|
8
14
|
uiSchema: [],
|
|
9
15
|
bind(_ctx, { makeInput, configureOutput }) {
|
|
10
16
|
const value$ = makeInput('value', {
|
|
@@ -4,7 +4,13 @@ export const numberNode = defineReactiveNode({
|
|
|
4
4
|
type: 'common-number',
|
|
5
5
|
displayName: 'Number',
|
|
6
6
|
category: 'Primitives',
|
|
7
|
-
description:
|
|
7
|
+
description: `
|
|
8
|
+
Put a constant number on the canvas and wire it onward.
|
|
9
|
+
|
|
10
|
+
Typical uses:
|
|
11
|
+
- A Repeat **count** or Delay milliseconds
|
|
12
|
+
- A threshold for Compare or Loop
|
|
13
|
+
`.trim(),
|
|
8
14
|
uiSchema: [],
|
|
9
15
|
bind(_ctx, { makeInput, configureOutput }) {
|
|
10
16
|
const value$ = makeInput('value', {
|
|
@@ -4,7 +4,13 @@ export const stringNode = defineReactiveNode({
|
|
|
4
4
|
type: 'common-string',
|
|
5
5
|
displayName: 'String',
|
|
6
6
|
category: 'Primitives',
|
|
7
|
-
description:
|
|
7
|
+
description: `
|
|
8
|
+
Put a short constant string on the canvas and wire it onward.
|
|
9
|
+
|
|
10
|
+
Typical uses:
|
|
11
|
+
- A file path for Read File
|
|
12
|
+
- A short label or prompt fragment
|
|
13
|
+
`.trim(),
|
|
8
14
|
uiSchema: [],
|
|
9
15
|
bind(_ctx, { makeInput, configureOutput }) {
|
|
10
16
|
const value$ = makeInput('value', {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Multiline string literal — inline `value` textarea, no wire required. */
|
|
2
|
+
export declare const stringMultilineNode: {
|
|
3
|
+
readonly emitOncePerActivation: boolean;
|
|
4
|
+
readonly stopsRun: boolean;
|
|
5
|
+
readonly chatEntry: boolean;
|
|
6
|
+
readonly uiSchema: readonly [];
|
|
7
|
+
readonly bypassPorts: Record<string, import("@langflower/node-sdk").WireType>;
|
|
8
|
+
readonly inputsConfigs: readonly [import("@langflower/node-sdk").InputPortMeta<import("@langflower/node-sdk").ExecutionContext<readonly [], Record<string, never>>>, ...import("@langflower/node-sdk").InputPortMeta<unknown>[]];
|
|
9
|
+
readonly outputsConfigs: (import("@langflower/node-sdk").OutputParams & import("@langflower/node-sdk").PortMeta)[];
|
|
10
|
+
readonly getInstance: () => import("@langflower/node-sdk").ReactiveNodeInstance<readonly [], Record<string, never>>;
|
|
11
|
+
readonly paletteSecondary?: true;
|
|
12
|
+
readonly description?: string;
|
|
13
|
+
readonly type: string;
|
|
14
|
+
readonly displayName: string;
|
|
15
|
+
readonly category: string | undefined;
|
|
16
|
+
readonly icon: string | undefined;
|
|
17
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { defineReactiveNode } from '@langflower/node-sdk';
|
|
2
|
+
/** Multiline string literal — inline `value` textarea, no wire required. */
|
|
3
|
+
export const stringMultilineNode = defineReactiveNode({
|
|
4
|
+
type: 'common-string-multiline',
|
|
5
|
+
displayName: 'String (multiline)',
|
|
6
|
+
category: 'Primitives',
|
|
7
|
+
description: `
|
|
8
|
+
Paste longer text on the node — several lines, not a single field.
|
|
9
|
+
|
|
10
|
+
Typical uses:
|
|
11
|
+
- A prompt or email draft
|
|
12
|
+
- CSV or log text to feed into Split (paced)
|
|
13
|
+
`.trim(),
|
|
14
|
+
uiSchema: [],
|
|
15
|
+
bind(_ctx, { makeInput, configureOutput }) {
|
|
16
|
+
const value$ = makeInput('value', {
|
|
17
|
+
name: 'value',
|
|
18
|
+
wireType: 'string',
|
|
19
|
+
inline: 'text-multiline',
|
|
20
|
+
defaultValue: '',
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
inputs: [value$],
|
|
24
|
+
outputs: [
|
|
25
|
+
configureOutput('value', value$, {
|
|
26
|
+
wireType: 'string',
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineReactiveNode } from '@langflower/node-sdk';
|
|
1
|
+
import { defineReactiveNode, withLoading } from '@langflower/node-sdk';
|
|
2
2
|
import { createProjectFilesContext } from '@langflower/tools/create-project-files-context';
|
|
3
3
|
import { from, map, mergeMap, throwError } from 'rxjs';
|
|
4
4
|
import { getRunHostServices } from '../../ai/features/run-host-services.js';
|
|
@@ -10,7 +10,13 @@ export const appendFileNode = defineReactiveNode({
|
|
|
10
10
|
type: 'common-append-file',
|
|
11
11
|
displayName: 'Append File',
|
|
12
12
|
category: 'Text',
|
|
13
|
-
description:
|
|
13
|
+
description: `
|
|
14
|
+
Add **content** to the end of a project file. If the file already has text, **delimiter** is inserted first.
|
|
15
|
+
|
|
16
|
+
Typical uses:
|
|
17
|
+
- Append a log line
|
|
18
|
+
- Grow a notes file across loop iterations
|
|
19
|
+
`.trim(),
|
|
14
20
|
uiSchema: [],
|
|
15
21
|
bind(ctx, { makeInput, configureOutput, combineInputs }) {
|
|
16
22
|
const pathInput = makeInput('path', {
|
|
@@ -37,7 +43,9 @@ export const appendFileNode = defineReactiveNode({
|
|
|
37
43
|
delimiter: String(rawDelimiter ?? ''),
|
|
38
44
|
content: String(rawContent ?? ''),
|
|
39
45
|
ec,
|
|
40
|
-
}))
|
|
46
|
+
}))
|
|
47
|
+
.pipe(withLoading())
|
|
48
|
+
.pipeValue(mergeMap(({ path: filePath, delimiter: fileDelimiter, content: fileContent, ec, }) => {
|
|
41
49
|
if (filePath.length === 0) {
|
|
42
50
|
return throwError(() => new Error('Append File requires a non-empty path.'));
|
|
43
51
|
}
|
|
@@ -4,7 +4,11 @@ export const concatNode = defineReactiveNode({
|
|
|
4
4
|
type: 'common-concat',
|
|
5
5
|
displayName: 'Concat',
|
|
6
6
|
category: 'Text',
|
|
7
|
-
description:
|
|
7
|
+
description: `
|
|
8
|
+
Join several strings with a **separator**. Emits only when every wired string has a fresh value.
|
|
9
|
+
|
|
10
|
+
Type \`\\n\` in the separator for a line break.
|
|
11
|
+
`.trim(),
|
|
8
12
|
uiSchema: [],
|
|
9
13
|
bind(_ctx, { makeInput, configureOutput, combineInputs }) {
|
|
10
14
|
const separator$ = makeInput('separator', {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineReactiveNode } from '@langflower/node-sdk';
|
|
1
|
+
import { defineReactiveNode, withLoading } from '@langflower/node-sdk';
|
|
2
2
|
import { createProjectFilesContext } from '@langflower/tools/create-project-files-context';
|
|
3
3
|
import { from, mergeMap, throwError } from 'rxjs';
|
|
4
4
|
import { getRunHostServices } from '../../ai/features/run-host-services.js';
|
|
@@ -10,7 +10,11 @@ export const readFileNode = defineReactiveNode({
|
|
|
10
10
|
type: 'common-read-file',
|
|
11
11
|
displayName: 'Read File',
|
|
12
12
|
category: 'Text',
|
|
13
|
-
description:
|
|
13
|
+
description: `
|
|
14
|
+
Read a file inside the project into **content**. Absolute paths are refused.
|
|
15
|
+
|
|
16
|
+
Pulse **update** to read the same path again after it changes on disk.
|
|
17
|
+
`.trim(),
|
|
14
18
|
uiSchema: [],
|
|
15
19
|
bind(ctx, { makeInput, configureOutput, combineInputs }) {
|
|
16
20
|
const pathInput = makeInput('path', {
|
|
@@ -28,7 +32,9 @@ export const readFileNode = defineReactiveNode({
|
|
|
28
32
|
const content$ = combineInputs([pathInput, update, ctx], ([rawPath, _update, ec]) => ({
|
|
29
33
|
path: String(rawPath ?? '').trim(),
|
|
30
34
|
ec,
|
|
31
|
-
}))
|
|
35
|
+
}))
|
|
36
|
+
.pipe(withLoading())
|
|
37
|
+
.pipeValue(mergeMap(({ path: filePath, ec }) => {
|
|
32
38
|
if (filePath.length === 0) {
|
|
33
39
|
return throwError(() => new Error('Read File requires a non-empty path.'));
|
|
34
40
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits `text` on `divider` and emits one non-empty chunk per pace slot:
|
|
3
|
+
* first ASAP, later on `trigger`. After the last chunk, the next slot emits
|
|
4
|
+
* `finish: true`. Use for CSV / logs line-by-line; not the one-shot Split array.
|
|
5
|
+
*/
|
|
6
|
+
export declare const splitPacedNode: {
|
|
7
|
+
readonly emitOncePerActivation: boolean;
|
|
8
|
+
readonly stopsRun: boolean;
|
|
9
|
+
readonly chatEntry: boolean;
|
|
10
|
+
readonly uiSchema: readonly [];
|
|
11
|
+
readonly bypassPorts: Record<string, import("@langflower/node-sdk").WireType>;
|
|
12
|
+
readonly inputsConfigs: readonly [import("@langflower/node-sdk").InputPortMeta<import("@langflower/node-sdk").ExecutionContext<readonly [], Record<string, never>>>, ...import("@langflower/node-sdk").InputPortMeta<unknown>[]];
|
|
13
|
+
readonly outputsConfigs: (import("@langflower/node-sdk").OutputParams & import("@langflower/node-sdk").PortMeta)[];
|
|
14
|
+
readonly getInstance: () => import("@langflower/node-sdk").ReactiveNodeInstance<readonly [], Record<string, never>>;
|
|
15
|
+
readonly paletteSecondary?: true;
|
|
16
|
+
readonly description?: string;
|
|
17
|
+
readonly type: string;
|
|
18
|
+
readonly displayName: string;
|
|
19
|
+
readonly category: string | undefined;
|
|
20
|
+
readonly icon: string | undefined;
|
|
21
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { defineReactiveNode } from '@langflower/node-sdk';
|
|
2
|
+
import { asapScheduler, filter, map, observeOn, of, startWith, switchMap, take, } from 'rxjs';
|
|
3
|
+
const remainingChunks = (text, divider, startFrom) => {
|
|
4
|
+
const splitDivider = divider.replaceAll('\\n', '\n');
|
|
5
|
+
const from = Math.max(0, Math.floor(Number(startFrom) || 0));
|
|
6
|
+
const pieces = String(text)
|
|
7
|
+
.split(splitDivider)
|
|
8
|
+
.map((piece) => piece.replace(/\r$/, ''))
|
|
9
|
+
.filter((piece) => piece.length > 0);
|
|
10
|
+
return pieces.slice(from).map((chunk, offset) => ({
|
|
11
|
+
text: chunk,
|
|
12
|
+
index: from + offset,
|
|
13
|
+
}));
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Splits `text` on `divider` and emits one non-empty chunk per pace slot:
|
|
17
|
+
* first ASAP, later on `trigger`. After the last chunk, the next slot emits
|
|
18
|
+
* `finish: true`. Use for CSV / logs line-by-line; not the one-shot Split array.
|
|
19
|
+
*/
|
|
20
|
+
export const splitPacedNode = defineReactiveNode({
|
|
21
|
+
type: 'common-split-paced',
|
|
22
|
+
displayName: 'Split (paced)',
|
|
23
|
+
category: 'Text',
|
|
24
|
+
description: `
|
|
25
|
+
Walk a large text one piece at a time — CSV rows, log lines, paragraphs.
|
|
26
|
+
|
|
27
|
+
The first piece starts immediately. Pulse **trigger** for the next. After the last piece, **finish** fires so you can stop the loop.
|
|
28
|
+
|
|
29
|
+
Skip ahead with **start from**. Empty pieces are ignored. In **divider**, type \`\\n\` for a line break.
|
|
30
|
+
`.trim(),
|
|
31
|
+
uiSchema: [],
|
|
32
|
+
bind(_ctx, { makeInput, configureOutput, combineInputs }) {
|
|
33
|
+
const text = makeInput('text', {
|
|
34
|
+
name: 'text',
|
|
35
|
+
wireType: 'string',
|
|
36
|
+
inline: 'text-multiline',
|
|
37
|
+
required: true,
|
|
38
|
+
defaultValue: '',
|
|
39
|
+
});
|
|
40
|
+
const divider = makeInput('divider', {
|
|
41
|
+
name: 'divider',
|
|
42
|
+
wireType: 'string',
|
|
43
|
+
inline: 'text',
|
|
44
|
+
defaultValue: '\\n',
|
|
45
|
+
description: '`\\n` is replaced with a line break.',
|
|
46
|
+
});
|
|
47
|
+
const startFrom = makeInput('startFrom', {
|
|
48
|
+
name: 'start from',
|
|
49
|
+
wireType: 'number',
|
|
50
|
+
inline: { type: 'number', min: 0, step: 1 },
|
|
51
|
+
defaultValue: 0,
|
|
52
|
+
});
|
|
53
|
+
const trigger = makeInput('trigger', {
|
|
54
|
+
name: 'trigger',
|
|
55
|
+
dynamic: true,
|
|
56
|
+
required: true,
|
|
57
|
+
});
|
|
58
|
+
const session$ = combineInputs([text, divider, startFrom], ([rawText, rawDivider, rawStart]) => remainingChunks(String(rawText ?? ''), String(rawDivider ?? ''), Number(rawStart))).pipeValue(switchMap((chunks) => {
|
|
59
|
+
const n = chunks.length;
|
|
60
|
+
if (n <= 0) {
|
|
61
|
+
return of({ kind: 'finish' });
|
|
62
|
+
}
|
|
63
|
+
return trigger.value$.pipe(startWith(undefined), take(n + 1), observeOn(asapScheduler), map((_, slot) => {
|
|
64
|
+
const chunk = chunks[slot];
|
|
65
|
+
return slot < n && chunk !== undefined
|
|
66
|
+
? {
|
|
67
|
+
kind: 'chunk',
|
|
68
|
+
text: chunk.text,
|
|
69
|
+
index: chunk.index,
|
|
70
|
+
}
|
|
71
|
+
: { kind: 'finish' };
|
|
72
|
+
}));
|
|
73
|
+
}));
|
|
74
|
+
const textOut$ = session$.pipeValue(filter((e) => e.kind === 'chunk'), map((e) => e.text));
|
|
75
|
+
const indexOut$ = session$.pipeValue(filter((e) => e.kind === 'chunk'), map((e) => e.index));
|
|
76
|
+
const finishOut$ = session$.pipeValue(filter((e) => e.kind === 'finish'), map(() => true));
|
|
77
|
+
return {
|
|
78
|
+
inputs: [text, divider, startFrom, trigger],
|
|
79
|
+
outputs: [
|
|
80
|
+
configureOutput('text', textOut$, {
|
|
81
|
+
wireType: 'string',
|
|
82
|
+
}),
|
|
83
|
+
configureOutput('index', indexOut$, {
|
|
84
|
+
wireType: 'number',
|
|
85
|
+
}),
|
|
86
|
+
configureOutput('finish', finishOut$, {
|
|
87
|
+
wireType: 'boolean',
|
|
88
|
+
feed: { role: 'none' },
|
|
89
|
+
}),
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineReactiveNode } from '@langflower/node-sdk';
|
|
1
|
+
import { defineReactiveNode, withLoading } from '@langflower/node-sdk';
|
|
2
2
|
import { createProjectFilesContext } from '@langflower/tools/create-project-files-context';
|
|
3
3
|
import { from, map, mergeMap, throwError } from 'rxjs';
|
|
4
4
|
import { getRunHostServices } from '../../ai/features/run-host-services.js';
|
|
@@ -9,7 +9,13 @@ export const writeFileNode = defineReactiveNode({
|
|
|
9
9
|
type: 'common-write-file',
|
|
10
10
|
displayName: 'Write File',
|
|
11
11
|
category: 'Text',
|
|
12
|
-
description:
|
|
12
|
+
description: `
|
|
13
|
+
Write **content** to a file inside the project (creates folders if needed). Absolute paths are refused.
|
|
14
|
+
|
|
15
|
+
Typical uses:
|
|
16
|
+
- Save an LLM draft
|
|
17
|
+
- Persist a generated config
|
|
18
|
+
`.trim(),
|
|
13
19
|
uiSchema: [],
|
|
14
20
|
bind(ctx, { makeInput, configureOutput, combineInputs }) {
|
|
15
21
|
const pathInput = makeInput('path', {
|
|
@@ -29,7 +35,9 @@ export const writeFileNode = defineReactiveNode({
|
|
|
29
35
|
path: String(rawPath ?? '').trim(),
|
|
30
36
|
content: String(rawContent ?? ''),
|
|
31
37
|
ec,
|
|
32
|
-
}))
|
|
38
|
+
}))
|
|
39
|
+
.pipe(withLoading())
|
|
40
|
+
.pipeValue(mergeMap(({ path: filePath, content: fileContent, ec }) => {
|
|
33
41
|
if (filePath.length === 0) {
|
|
34
42
|
return throwError(() => new Error('Write File requires a non-empty path.'));
|
|
35
43
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { ToolHandle } from '@langflower/node-sdk';
|
|
2
|
-
|
|
2
|
+
/** Flatten multi-wire values that may be single handles or arrays (packs). */
|
|
3
|
+
export declare const flattenToolHandles: (wired: readonly unknown[]) => readonly ToolHandle[];
|
|
3
4
|
/**
|
|
4
|
-
* Agent inventory: EC ∪ port for tools
|
|
5
|
+
* Agent inventory: EC ∪ port for tools.
|
|
5
6
|
* No catalog list, no enabledToolIds filter (server already filtered EC).
|
|
7
|
+
* Later `toolHandles` last-wins on `toolId` (jsonc MCP after builtins).
|
|
6
8
|
*/
|
|
7
9
|
export declare const collectAgentToolHandles: (options: {
|
|
8
10
|
readonly toolHandles: readonly ToolHandle[] | undefined;
|
|
9
11
|
readonly toolsPort: unknown;
|
|
10
|
-
readonly mcpHandles: readonly McpHandle[] | undefined;
|
|
11
|
-
readonly mcpPort: unknown;
|
|
12
12
|
}) => readonly ToolHandle[];
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { flattenMcpHandles } from '../mcp/flatten-mcp-handles.js';
|
|
2
1
|
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
2
|
const isToolHandle = (value) => {
|
|
4
3
|
if (!isRecord(value)) {
|
|
@@ -12,7 +11,7 @@ const isToolHandle = (value) => {
|
|
|
12
11
|
typeof value.invoke === 'function');
|
|
13
12
|
};
|
|
14
13
|
/** Flatten multi-wire values that may be single handles or arrays (packs). */
|
|
15
|
-
const flattenToolHandles = (wired) => wired.flatMap((item) => {
|
|
14
|
+
export const flattenToolHandles = (wired) => wired.flatMap((item) => {
|
|
16
15
|
if (Array.isArray(item)) {
|
|
17
16
|
return item.filter(isToolHandle);
|
|
18
17
|
}
|
|
@@ -22,8 +21,9 @@ const flattenToolHandles = (wired) => wired.flatMap((item) => {
|
|
|
22
21
|
return [];
|
|
23
22
|
});
|
|
24
23
|
/**
|
|
25
|
-
* Agent inventory: EC ∪ port for tools
|
|
24
|
+
* Agent inventory: EC ∪ port for tools.
|
|
26
25
|
* No catalog list, no enabledToolIds filter (server already filtered EC).
|
|
26
|
+
* Later `toolHandles` last-wins on `toolId` (jsonc MCP after builtins).
|
|
27
27
|
*/
|
|
28
28
|
export const collectAgentToolHandles = (options) => {
|
|
29
29
|
const portTools = Array.isArray(options.toolsPort)
|
|
@@ -38,13 +38,5 @@ export const collectAgentToolHandles = (options) => {
|
|
|
38
38
|
for (const handle of options.toolHandles ?? []) {
|
|
39
39
|
byId.set(handle.toolId, handle);
|
|
40
40
|
}
|
|
41
|
-
for (const mcp of [
|
|
42
|
-
...(options.mcpHandles ?? []),
|
|
43
|
-
...flattenMcpHandles(options.mcpPort),
|
|
44
|
-
]) {
|
|
45
|
-
for (const handle of mcp.tools) {
|
|
46
|
-
byId.set(handle.toolId, handle);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
41
|
return [...byId.values()];
|
|
50
42
|
};
|
|
@@ -2,8 +2,6 @@ import type { ToolHandle } from '@langflower/node-sdk';
|
|
|
2
2
|
import { type Harness } from '@langflower/tools/create-project-harness';
|
|
3
3
|
import type { ToolHandlerContext } from '@langflower/tools/domain-tool-configs';
|
|
4
4
|
import type { ChatCompletionToolCall, ChatCompletionToolDefinition } from '../ai/features/chat-completion-stream.js';
|
|
5
|
-
import type { SubAgentRegistration, SubAgentSpawnPayload } from '../ai/features/sub-agent-protocol.js';
|
|
6
|
-
export declare const SPAWN_SUBAGENT_TOOL = "spawn_subagent";
|
|
7
5
|
export declare const previewToolLogText: (text: string) => string;
|
|
8
6
|
export declare const toChatToolDefinitions: (tools: readonly ToolHandle[]) => readonly ChatCompletionToolDefinition[];
|
|
9
7
|
export declare const parseToolArgs: (raw: string) => Readonly<Record<string, unknown>>;
|
|
@@ -20,11 +18,3 @@ export declare const invokeInventoryTool: (harness: Harness | undefined, tools:
|
|
|
20
18
|
readonly ok: boolean;
|
|
21
19
|
readonly text: string;
|
|
22
20
|
}>;
|
|
23
|
-
export declare const buildSpawnSubagentChatTool: (registrations: readonly SubAgentRegistration[]) => ChatCompletionToolDefinition;
|
|
24
|
-
export declare const resolveSpawnPayload: (call: ChatCompletionToolCall, registrations: readonly SubAgentRegistration[], openCallId: string | undefined) => {
|
|
25
|
-
readonly ok: true;
|
|
26
|
-
readonly payload: SubAgentSpawnPayload;
|
|
27
|
-
} | {
|
|
28
|
-
readonly ok: false;
|
|
29
|
-
readonly text: string;
|
|
30
|
-
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { isBuiltinToolId, } from '@langflower/tools/create-project-harness';
|
|
2
2
|
import { formatPermissionDeniedText } from '@langflower/tools/permission';
|
|
3
|
-
export const SPAWN_SUBAGENT_TOOL = 'spawn_subagent';
|
|
4
3
|
const TOOL_LOG_PREVIEW = 400;
|
|
5
4
|
export const previewToolLogText = (text) => {
|
|
6
5
|
const trimmed = text.trim();
|
|
@@ -90,86 +89,3 @@ export const invokeInventoryTool = async (harness, tools, call, toolCtx, options
|
|
|
90
89
|
};
|
|
91
90
|
}
|
|
92
91
|
};
|
|
93
|
-
export const buildSpawnSubagentChatTool = (registrations) => {
|
|
94
|
-
const catalog = registrations
|
|
95
|
-
.map((reg) => {
|
|
96
|
-
const skills = reg.skills.length === 0
|
|
97
|
-
? 'none'
|
|
98
|
-
: reg.skills
|
|
99
|
-
.map((skill) => `${skill.skillId}${skill.description.length > 0 ? ` (${skill.description})` : ''}`)
|
|
100
|
-
.join(', ');
|
|
101
|
-
return `- nodeId=${reg.targetNodeId} name=${reg.name}: ${reg.description} skills=[${skills}]`;
|
|
102
|
-
})
|
|
103
|
-
.join('\n');
|
|
104
|
-
return {
|
|
105
|
-
type: 'function',
|
|
106
|
-
function: {
|
|
107
|
-
name: SPAWN_SUBAGENT_TOOL,
|
|
108
|
-
description: [
|
|
109
|
-
'Spawn one Sub-Agent on the canvas (sequential — wait for its result before another spawn).',
|
|
110
|
-
'Pick nodeId from the catalog. skillId may be empty if unused.',
|
|
111
|
-
'Catalog:',
|
|
112
|
-
catalog.length > 0 ? catalog : '(no Sub-Agents registered)',
|
|
113
|
-
].join('\n'),
|
|
114
|
-
parameters: {
|
|
115
|
-
type: 'object',
|
|
116
|
-
properties: {
|
|
117
|
-
nodeId: {
|
|
118
|
-
type: 'string',
|
|
119
|
-
description: 'targetNodeId of the Sub-Agent to spawn',
|
|
120
|
-
},
|
|
121
|
-
skillId: {
|
|
122
|
-
type: 'string',
|
|
123
|
-
description: 'Optional skill id announced by that Sub-Agent; empty if none',
|
|
124
|
-
},
|
|
125
|
-
task: {
|
|
126
|
-
type: 'string',
|
|
127
|
-
description: 'Task text for the Sub-Agent body',
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
required: ['nodeId', 'task'],
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
};
|
|
134
|
-
};
|
|
135
|
-
export const resolveSpawnPayload = (call, registrations, openCallId) => {
|
|
136
|
-
if (openCallId !== undefined) {
|
|
137
|
-
return {
|
|
138
|
-
ok: false,
|
|
139
|
-
text: `Serial spawn only: already waiting for callId=${openCallId}.`,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
const args = parseToolArgs(call.arguments);
|
|
143
|
-
const nodeId = typeof args.nodeId === 'string' ? args.nodeId.trim() : '';
|
|
144
|
-
const task = typeof args.task === 'string' ? args.task : '';
|
|
145
|
-
const skillId = typeof args.skillId === 'string' ? args.skillId.trim() : '';
|
|
146
|
-
if (nodeId.length === 0) {
|
|
147
|
-
return { ok: false, text: 'spawn_subagent requires nodeId.' };
|
|
148
|
-
}
|
|
149
|
-
if (task.trim().length === 0) {
|
|
150
|
-
return { ok: false, text: 'spawn_subagent requires a non-empty task.' };
|
|
151
|
-
}
|
|
152
|
-
const target = registrations.find((reg) => reg.targetNodeId === nodeId);
|
|
153
|
-
if (target === undefined) {
|
|
154
|
-
return {
|
|
155
|
-
ok: false,
|
|
156
|
-
text: `Unknown Sub-Agent nodeId «${nodeId}» (not in subagentRegistration).`,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
if (skillId.length > 0 &&
|
|
160
|
-
!target.skills.some((skill) => skill.skillId === skillId)) {
|
|
161
|
-
return {
|
|
162
|
-
ok: false,
|
|
163
|
-
text: `Skill «${skillId}» is not announced by Sub-Agent «${nodeId}».`,
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
return {
|
|
167
|
-
ok: true,
|
|
168
|
-
payload: {
|
|
169
|
-
callId: call.id,
|
|
170
|
-
nodeId,
|
|
171
|
-
skillId,
|
|
172
|
-
task,
|
|
173
|
-
},
|
|
174
|
-
};
|
|
175
|
-
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional hub: combine many `tools` wires into one `ToolHandle[]`.
|
|
3
|
+
* Duplicate `toolId` last-wins (later slot). Empty / unwired → `[]`.
|
|
4
|
+
*/
|
|
5
|
+
export declare const toolCollectionNode: {
|
|
6
|
+
readonly emitOncePerActivation: boolean;
|
|
7
|
+
readonly stopsRun: boolean;
|
|
8
|
+
readonly chatEntry: boolean;
|
|
9
|
+
readonly uiSchema: readonly [];
|
|
10
|
+
readonly bypassPorts: Record<string, import("@langflower/node-sdk").WireType>;
|
|
11
|
+
readonly inputsConfigs: readonly [import("@langflower/node-sdk").InputPortMeta<import("@langflower/node-sdk").ExecutionContext<readonly [], Record<string, never>>>, ...import("@langflower/node-sdk").InputPortMeta<unknown>[]];
|
|
12
|
+
readonly outputsConfigs: (import("@langflower/node-sdk").OutputParams & import("@langflower/node-sdk").PortMeta)[];
|
|
13
|
+
readonly getInstance: () => import("@langflower/node-sdk").ReactiveNodeInstance<readonly [], Record<string, never>>;
|
|
14
|
+
readonly paletteSecondary?: true;
|
|
15
|
+
readonly description?: string;
|
|
16
|
+
readonly type: string;
|
|
17
|
+
readonly displayName: string;
|
|
18
|
+
readonly category: string | undefined;
|
|
19
|
+
readonly icon: string | undefined;
|
|
20
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { defineReactiveNode, TOOL_HANDLE_WIRE_TYPE, } from '@langflower/node-sdk';
|
|
2
|
+
import { map } from 'rxjs';
|
|
3
|
+
import { flattenToolHandles } from '../collect-agent-tool-handles.js';
|
|
4
|
+
const mergeToolHandlesLastWins = (wired) => {
|
|
5
|
+
const flattened = Array.isArray(wired)
|
|
6
|
+
? flattenToolHandles(wired)
|
|
7
|
+
: flattenToolHandles(wired === undefined || wired === null ? [] : [wired]);
|
|
8
|
+
const byId = new Map();
|
|
9
|
+
for (const handle of flattened) {
|
|
10
|
+
byId.set(handle.toolId, handle);
|
|
11
|
+
}
|
|
12
|
+
return [...byId.values()];
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Optional hub: combine many `tools` wires into one `ToolHandle[]`.
|
|
16
|
+
* Duplicate `toolId` last-wins (later slot). Empty / unwired → `[]`.
|
|
17
|
+
*/
|
|
18
|
+
export const toolCollectionNode = defineReactiveNode({
|
|
19
|
+
type: 'common-tool-collection',
|
|
20
|
+
displayName: 'Tool collection',
|
|
21
|
+
category: 'Tools',
|
|
22
|
+
description: `
|
|
23
|
+
Combine several tool wires into one before an agent. Duplicate names: the last wire wins.
|
|
24
|
+
|
|
25
|
+
Optional — you can still plug many tool packs straight into the agent.
|
|
26
|
+
`.trim(),
|
|
27
|
+
uiSchema: [],
|
|
28
|
+
bind(_ctx, { makeInput, configureOutput }) {
|
|
29
|
+
const tools = makeInput('tools', {
|
|
30
|
+
name: 'tools',
|
|
31
|
+
wireType: TOOL_HANDLE_WIRE_TYPE,
|
|
32
|
+
multi: 'combine',
|
|
33
|
+
defaultValue: [],
|
|
34
|
+
});
|
|
35
|
+
const merged$ = tools.pipeValue(map((wired) => mergeToolHandlesLastWins(wired)));
|
|
36
|
+
return {
|
|
37
|
+
inputs: [tools],
|
|
38
|
+
outputs: [
|
|
39
|
+
configureOutput('tools', merged$, {
|
|
40
|
+
wireType: TOOL_HANDLE_WIRE_TYPE,
|
|
41
|
+
}),
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
});
|