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
|
@@ -4,11 +4,11 @@ export type SeedSkeletonResult = {
|
|
|
4
4
|
};
|
|
5
5
|
export type SeedSkeletonOptions = {
|
|
6
6
|
readonly mode: SeedSkeletonMode;
|
|
7
|
-
/** When false, leave `nodes/` empty (no skeleton
|
|
7
|
+
/** When false, leave `nodes/` empty (no skeleton packs). Default true. */
|
|
8
8
|
readonly seedCustomNodes?: boolean;
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
|
-
* Copy skeleton workflows, skills,
|
|
11
|
+
* Copy skeleton workflows, skills, custom-node packs, and instructions into
|
|
12
12
|
* `.langflower/`. Create mode skips existing paths; force overwrites
|
|
13
13
|
* skeleton-owned files (extra project-only files stay).
|
|
14
14
|
*/
|
|
@@ -23,8 +23,21 @@ const listSkeletonSkillIds = async (skeletonRoot) => {
|
|
|
23
23
|
return [];
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
|
+
const listSkeletonPackIds = async (skeletonRoot) => {
|
|
27
|
+
const nodesDir = path.join(skeletonRoot, 'nodes');
|
|
28
|
+
try {
|
|
29
|
+
const entries = await fs.readdir(nodesDir, { withFileTypes: true });
|
|
30
|
+
return entries
|
|
31
|
+
.filter((entry) => entry.isDirectory())
|
|
32
|
+
.map((entry) => entry.name)
|
|
33
|
+
.sort();
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
};
|
|
26
39
|
/**
|
|
27
|
-
* Copy skeleton workflows, skills,
|
|
40
|
+
* Copy skeleton workflows, skills, custom-node packs, and instructions into
|
|
28
41
|
* `.langflower/`. Create mode skips existing paths; force overwrites
|
|
29
42
|
* skeleton-owned files (extra project-only files stay).
|
|
30
43
|
*/
|
|
@@ -34,7 +47,9 @@ export const seedSkeletonContent = async (skeletonRoot, langflowerDir, options)
|
|
|
34
47
|
const copyFile = mode === 'force' ? copyFileForce : copyFileIfMissing;
|
|
35
48
|
const copyDir = mode === 'force' ? copyDirForce : copyDirIfMissing;
|
|
36
49
|
if (seedCustomNodes) {
|
|
37
|
-
|
|
50
|
+
for (const packId of await listSkeletonPackIds(skeletonRoot)) {
|
|
51
|
+
await copyDir(path.join(skeletonRoot, 'nodes', packId), path.join(langflowerDir, 'nodes', packId));
|
|
52
|
+
}
|
|
38
53
|
}
|
|
39
54
|
else {
|
|
40
55
|
await fs.mkdir(path.join(langflowerDir, 'nodes'), { recursive: true });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type CreateEmbedding } from '@langflower/common-nodes/embeddings/create-embedding';
|
|
2
|
+
import type { LangflowerConfigService } from '../config/langflower-config.service.js';
|
|
3
|
+
/**
|
|
4
|
+
* Thin credential bind: secrets stay server-side; embeddings HTTP lives in
|
|
5
|
+
* common-nodes.
|
|
6
|
+
*/
|
|
7
|
+
export declare const bindCreateEmbedding: (langflowerConfigService: LangflowerConfigService) => CreateEmbedding;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createEmbedding, } from '@langflower/common-nodes/embeddings/create-embedding';
|
|
2
|
+
import { resolveProviderCredentials } from '../config/resolve-provider-credentials.js';
|
|
3
|
+
/**
|
|
4
|
+
* Thin credential bind: secrets stay server-side; embeddings HTTP lives in
|
|
5
|
+
* common-nodes.
|
|
6
|
+
*/
|
|
7
|
+
export const bindCreateEmbedding = (langflowerConfigService) => createEmbedding({
|
|
8
|
+
resolveProvider: async (providerId) => {
|
|
9
|
+
const config = await langflowerConfigService.read();
|
|
10
|
+
const resolved = resolveProviderCredentials(config, providerId);
|
|
11
|
+
if (!resolved.ok) {
|
|
12
|
+
throw new Error(resolved.message);
|
|
13
|
+
}
|
|
14
|
+
return resolved.credentials;
|
|
15
|
+
},
|
|
16
|
+
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { LangflowerBusRequest } from '@langflower/common-nodes/ai/run-host-services';
|
|
2
2
|
import { type ExecutionContext, type ToolHandle } from '@langflower/node-sdk';
|
|
3
3
|
import type { LlmExecutionCaps } from '@langflower/node-sdk/llm';
|
|
4
|
-
import type { McpHandle } from '@langflower/node-sdk/mcp';
|
|
5
4
|
import type { RuntimeSeedPortValue } from '@langflower/runtime';
|
|
6
5
|
import { type LangflowerConfig, type RunnerPermissionAskPayload } from '@langflower/shared/langflower.js';
|
|
6
|
+
import { type SystemMcpServerTools } from '@langflower/tools/create-system-mcp-handles';
|
|
7
7
|
import type { ServerContext } from '../server-context.js';
|
|
8
8
|
import type { LangflowerSession } from '../session/langflower-session.js';
|
|
9
9
|
type WorkflowGraphNode = {
|
|
@@ -20,7 +20,7 @@ type BuildHarnessHooks = {
|
|
|
20
20
|
readonly requestLangflowerBus?: LangflowerBusRequest;
|
|
21
21
|
readonly getLiveWiredTools?: (agentNodeId: string) => readonly ToolHandle[];
|
|
22
22
|
};
|
|
23
|
-
export declare const buildExecutionContext: (context: ExecutionContextDeps, runId: string, node: WorkflowGraphNode, hooks?: BuildHarnessHooks, preloadedConfig?: LangflowerConfig, runMcpHandles?: readonly
|
|
23
|
+
export declare const buildExecutionContext: (context: ExecutionContextDeps, runId: string, node: WorkflowGraphNode, hooks?: BuildHarnessHooks, preloadedConfig?: LangflowerConfig, runMcpHandles?: readonly SystemMcpServerTools[]) => Promise<ExecutionContext<never, LlmExecutionCaps>>;
|
|
24
24
|
/**
|
|
25
25
|
* Context seeds whose `value` is an Observable (e.g. `throwError` → CtxError)
|
|
26
26
|
* must be `connect`ed directly. Runner `applySeeds` wraps with `of(value)`,
|
|
@@ -2,12 +2,13 @@ import { parseLlmRolePreset, resolveEffectiveSkillId, resolveEffectiveToolPermis
|
|
|
2
2
|
import { attachRunHostServices } from '@langflower/common-nodes/ai/run-host-services';
|
|
3
3
|
import { contextSymbol, } from '@langflower/node-sdk';
|
|
4
4
|
import { parseDefaultChatModel, } from '@langflower/shared/langflower.js';
|
|
5
|
-
import { collectEnabledMcpIdsFromNodes, createSystemMcpHandles, filterMcpFailuresForNode,
|
|
5
|
+
import { collectEnabledMcpIdsFromNodes, createSystemMcpHandles, filterMcpFailuresForNode, filterSystemMcpToolsByServerIds, parseEnabledMcpIds, } from '@langflower/tools/create-system-mcp-handles';
|
|
6
6
|
import { createProjectHarness, } from '@langflower/tools/create-project-harness';
|
|
7
7
|
import { createWebFetch } from '@langflower/tools/create-web-fetch';
|
|
8
8
|
import { mergeProjectAndNodePermissions, } from '@langflower/tools/permission';
|
|
9
9
|
import { isObservable, throwError } from 'rxjs';
|
|
10
10
|
import { bindCreateChatCompletionStream } from './bind-llm-context.js';
|
|
11
|
+
import { bindCreateEmbedding } from './bind-embed-context.js';
|
|
11
12
|
import { wrapBuiltinToolHandles } from './wrap-builtin-tool-handles.js';
|
|
12
13
|
import { readAgentsMarkdown } from '../skills/read-agents-markdown.js';
|
|
13
14
|
import { readSkillMarkdown } from '../skills/read-skill-markdown.js';
|
|
@@ -73,8 +74,9 @@ export const buildExecutionContext = async (context, runId, node, hooks, preload
|
|
|
73
74
|
webFetch,
|
|
74
75
|
};
|
|
75
76
|
const enabledToolIds = toolPermissionsToEnabledIds(toolPermissions);
|
|
76
|
-
const
|
|
77
|
-
const
|
|
77
|
+
const builtinHandles = wrapBuiltinToolHandles(harness, enabledToolIds, permission);
|
|
78
|
+
const mcpTools = filterSystemMcpToolsByServerIds(runMcpHandles ?? [], parseEnabledMcpIds(node.params.enabledMcpIds)).flatMap((entry) => entry.tools);
|
|
79
|
+
const toolHandles = [...builtinHandles, ...mcpTools];
|
|
78
80
|
const base = {
|
|
79
81
|
projectDir: context.projectDir,
|
|
80
82
|
runId,
|
|
@@ -85,16 +87,18 @@ export const buildExecutionContext = async (context, runId, node, hooks, preload
|
|
|
85
87
|
params: node.params,
|
|
86
88
|
})?.uiSchema ?? []),
|
|
87
89
|
...(toolHandles.length > 0 ? { toolHandles } : {}),
|
|
88
|
-
...(mcpHandles.length > 0 ? { mcpHandles } : {}),
|
|
89
90
|
};
|
|
90
91
|
const defaultChat = parseDefaultChatModel(config.model);
|
|
92
|
+
const defaultEmbedding = parseDefaultChatModel(config.embedding);
|
|
91
93
|
return attachRunHostServices(base, {
|
|
92
94
|
...(node.type !== 'common-fake-llm'
|
|
93
95
|
? {
|
|
94
96
|
createChatCompletionStream: bindCreateChatCompletionStream(context.langflowerConfigService),
|
|
95
97
|
}
|
|
96
98
|
: {}),
|
|
99
|
+
createEmbedding: bindCreateEmbedding(context.langflowerConfigService),
|
|
97
100
|
...(defaultChat !== null ? { defaultChat } : {}),
|
|
101
|
+
...(defaultEmbedding !== null ? { defaultEmbedding } : {}),
|
|
98
102
|
...(skillMarkdown.length > 0 ? { skillMarkdown } : {}),
|
|
99
103
|
...(agentsMarkdown.length > 0 ? { agentsMarkdown } : {}),
|
|
100
104
|
...(toolHarness.authorize !== undefined
|
|
@@ -26,7 +26,10 @@ export const emitBootstrap = async (client, context, session, checkpoints, draft
|
|
|
26
26
|
if (langflowerConfig.dividerPositions !== undefined) {
|
|
27
27
|
session.dividerPositions = langflowerConfig.dividerPositions;
|
|
28
28
|
}
|
|
29
|
-
|
|
29
|
+
if (langflowerConfig.paletteVisible !== undefined) {
|
|
30
|
+
session.paletteVisible = langflowerConfig.paletteVisible;
|
|
31
|
+
}
|
|
32
|
+
// Thin bootstrap — version + config + dividers + palette chrome + selected node only
|
|
30
33
|
const bootstrap = await buildSessionBootstrap(session, context.langflowerConfigService, context.resolveDefinition, context.projectDir);
|
|
31
34
|
clientEmit(client, 'session.state.snapshot', bootstrap);
|
|
32
35
|
// Domain snapshots
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { ToolHandle } from '@langflower/node-sdk';
|
|
2
2
|
import type { LangflowerSession } from '../session/langflower-session.js';
|
|
3
3
|
/**
|
|
4
|
-
* Activate current editor `tools`
|
|
5
|
-
* so a later inbound peek in
|
|
4
|
+
* Activate current editor `tools` / `subagent-registration` outputs
|
|
5
|
+
* (including post-swap instances) so a later inbound peek in
|
|
6
|
+
* {@link getLiveWiredTools} sees live handles.
|
|
6
7
|
*/
|
|
7
8
|
export declare const refreshLiveWiredToolPacks: (session: LangflowerSession) => void;
|
|
8
9
|
/**
|
|
@@ -40,14 +40,17 @@ const peekPortValue = (port) => {
|
|
|
40
40
|
return peeked;
|
|
41
41
|
};
|
|
42
42
|
/**
|
|
43
|
-
* Activate current editor `tools`
|
|
44
|
-
* so a later inbound peek in
|
|
43
|
+
* Activate current editor `tools` / `subagent-registration` outputs
|
|
44
|
+
* (including post-swap instances) so a later inbound peek in
|
|
45
|
+
* {@link getLiveWiredTools} sees live handles.
|
|
45
46
|
*/
|
|
46
47
|
export const refreshLiveWiredToolPacks = (session) => {
|
|
47
48
|
for (const node of session.runtime.editor.getNodes()) {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
for (const portId of ['tools', 'subagent-registration']) {
|
|
50
|
+
const port = resolveToolsOutput(node.outputs, portId);
|
|
51
|
+
if (port !== undefined) {
|
|
52
|
+
peekPortValue(port);
|
|
53
|
+
}
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
};
|
|
@@ -154,12 +154,13 @@ export const createSettingsDraftController = (bridge, context, session) => {
|
|
|
154
154
|
const commitSave = async (scope, fallback) => {
|
|
155
155
|
await ensureSeeded(scope);
|
|
156
156
|
const state = getState(scope);
|
|
157
|
-
// Prefer an explicit Save payload (provider/model/serverLogs)
|
|
158
|
-
// trailing draft.patch cannot race past commit. Otherwise persist
|
|
159
|
-
// session draft (`{ scope }` only).
|
|
157
|
+
// Prefer an explicit Save payload (provider/model/embedding/serverLogs)
|
|
158
|
+
// so a trailing draft.patch cannot race past commit. Otherwise persist
|
|
159
|
+
// the session draft (`{ scope }` only).
|
|
160
160
|
const payload = fallback !== undefined &&
|
|
161
161
|
(fallback.provider !== undefined ||
|
|
162
162
|
fallback.model !== undefined ||
|
|
163
|
+
fallback.embedding !== undefined ||
|
|
163
164
|
'serverLogs' in fallback)
|
|
164
165
|
? fallback
|
|
165
166
|
: state !== undefined
|
|
@@ -172,6 +173,9 @@ export const createSettingsDraftController = (bridge, context, session) => {
|
|
|
172
173
|
const layers = await context.langflowerConfigService.writeSettings({
|
|
173
174
|
scope: payload.scope,
|
|
174
175
|
...(payload.model !== undefined ? { model: payload.model } : {}),
|
|
176
|
+
...(payload.embedding !== undefined
|
|
177
|
+
? { embedding: payload.embedding }
|
|
178
|
+
: {}),
|
|
175
179
|
...(payload.provider !== undefined
|
|
176
180
|
? { provider: payload.provider }
|
|
177
181
|
: {}),
|
|
@@ -9,6 +9,8 @@ const isSettingsDraft = (value) => {
|
|
|
9
9
|
const draft = value;
|
|
10
10
|
return (typeof draft['defaultProviderId'] === 'string' &&
|
|
11
11
|
typeof draft['defaultModelId'] === 'string' &&
|
|
12
|
+
typeof draft['defaultEmbeddingProviderId'] === 'string' &&
|
|
13
|
+
typeof draft['defaultEmbeddingModelId'] === 'string' &&
|
|
12
14
|
Array.isArray(draft['providers']) &&
|
|
13
15
|
(draft['serverLogs'] === 'off' ||
|
|
14
16
|
draft['serverLogs'] === 'default' ||
|
|
@@ -182,6 +182,20 @@ export const wireEditorHandlers = (bridge, context, session, draftController) =>
|
|
|
182
182
|
bridgeEmit(bridge, 'editor.dividers.snapshot', clamped);
|
|
183
183
|
void context.langflowerConfigService.setDividerPositions(clamped);
|
|
184
184
|
}));
|
|
185
|
+
subscription.add(bridge['editor.paletteVisible.requested'].subscribe((raw) => {
|
|
186
|
+
if (!isInboundEvent(raw)) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (findClientById(bridge, raw.clientId) === undefined) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (typeof raw.payload !== 'boolean') {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
session.paletteVisible = raw.payload;
|
|
196
|
+
bridgeEmit(bridge, 'editor.paletteVisible.snapshot', raw.payload);
|
|
197
|
+
void context.langflowerConfigService.setPaletteVisible(raw.payload);
|
|
198
|
+
}));
|
|
185
199
|
subscription.add(bridge['editor.settings.requested'].subscribe((raw) => {
|
|
186
200
|
if (!isInboundEvent(raw)) {
|
|
187
201
|
return;
|
|
@@ -3,6 +3,7 @@ import { buildWorkflowFingerprint, } from '@langflower/shared/langflower.js';
|
|
|
3
3
|
import { Subscription } from 'rxjs';
|
|
4
4
|
import { listResumableCheckpoints } from '../checkpoint/list-resumable-checkpoints.js';
|
|
5
5
|
import { resolveCheckpointBoundary } from '../checkpoint/resolve-checkpoint-boundary.js';
|
|
6
|
+
import { resetSessionExecutionFeed } from '../session/reset-session-execution-feed.js';
|
|
6
7
|
import { buildContextSeeds, applyObservableContextSeeds, } from './build-execution-context.js';
|
|
7
8
|
import { getLiveWiredTools } from './get-live-wired-tools.js';
|
|
8
9
|
import { createLangflowerToolsRpc } from './langflower-tools-rpc.js';
|
|
@@ -293,8 +294,7 @@ export const wireRunnerHandlers = (bridge, context, session, checkpoints) => {
|
|
|
293
294
|
if (session.runnerStatus === 'running') {
|
|
294
295
|
return;
|
|
295
296
|
}
|
|
296
|
-
session
|
|
297
|
-
session.runId = undefined;
|
|
297
|
+
resetSessionExecutionFeed(session);
|
|
298
298
|
// Re-broadcast the (now empty) feed to every tab.
|
|
299
299
|
bridgeEmit(bridge, 'executionFeed.snapshot', session.buildExecutionFeed());
|
|
300
300
|
}));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Subscription } from 'rxjs';
|
|
2
2
|
import { listResumableCheckpoints } from '../checkpoint/list-resumable-checkpoints.js';
|
|
3
3
|
import { WorkflowCheckpointStore } from '../checkpoint/workflow-checkpoint-store.js';
|
|
4
|
+
import { resetSessionExecutionFeed } from '../session/reset-session-execution-feed.js';
|
|
4
5
|
import { buildSaveCurrentPayload } from '../workflow/build-save-current-payload.js';
|
|
5
6
|
import { copyWorkflowToSession } from '../workflow/copy-workflow-to-session.js';
|
|
6
7
|
import { createEmptyWorkflowInSession } from '../workflow/create-empty-workflow-in-session.js';
|
|
@@ -10,11 +11,17 @@ import { bridgeEmit, clientEmit } from './bridge-outbound.js';
|
|
|
10
11
|
import { findClientById } from './client-index.js';
|
|
11
12
|
import { isInboundEvent } from './inbound-guards.js';
|
|
12
13
|
/**
|
|
13
|
-
* Composer: clear selection → current snapshot →
|
|
14
|
-
* Sibling steps — handlers do not
|
|
14
|
+
* Composer: optional feed reset → clear selection → current snapshot →
|
|
15
|
+
* optional catalog sync. Sibling steps — handlers do not nest these.
|
|
15
16
|
*/
|
|
16
17
|
const syncAfterWorkflowMutation = async (bridge, context, session, client, options) => {
|
|
17
|
-
// 1.
|
|
18
|
+
// 1. Document switch: empty feed before the new catalog so the UI never
|
|
19
|
+
// paints the previous run under the next workflow's nodes.
|
|
20
|
+
if (options.resetFeed === true) {
|
|
21
|
+
resetSessionExecutionFeed(session);
|
|
22
|
+
bridgeEmit(bridge, 'executionFeed.snapshot', session.buildExecutionFeed());
|
|
23
|
+
}
|
|
24
|
+
// 2. Clear selection (and notify tabs if it was set)
|
|
18
25
|
if (options.clearSelection) {
|
|
19
26
|
const hadSelection = session.selectedNodeId !== null;
|
|
20
27
|
session.selectedNodeId = null;
|
|
@@ -22,19 +29,19 @@ const syncAfterWorkflowMutation = async (bridge, context, session, client, optio
|
|
|
22
29
|
bridgeEmit(bridge, 'editor.nodeSelected', { node: null });
|
|
23
30
|
}
|
|
24
31
|
}
|
|
25
|
-
//
|
|
32
|
+
// 3. Authoritative current-workflow slice (session-shared — fan out)
|
|
26
33
|
bridgeEmit(bridge, 'workflow.current.snapshot', {
|
|
27
34
|
activeWorkflow: session.activeWorkflow,
|
|
28
35
|
currentStatus: { status: session.currentStatus },
|
|
29
36
|
});
|
|
30
|
-
//
|
|
37
|
+
// 4. Resumable checkpoints for the active workflow (explicit boundaries)
|
|
31
38
|
const workflowId = session.activeWorkflowId ?? null;
|
|
32
39
|
const checkpoints = await listResumableCheckpoints(new WorkflowCheckpointStore(context.projectDir), workflowId, session.activeWorkflow);
|
|
33
40
|
bridgeEmit(bridge, 'runner.checkpoints.snapshot', {
|
|
34
41
|
workflowId,
|
|
35
42
|
checkpoints,
|
|
36
43
|
});
|
|
37
|
-
//
|
|
44
|
+
// 5. Catalog sync
|
|
38
45
|
if (options.catalog.kind === 'broadcast') {
|
|
39
46
|
const workflows = await context.workflowService.list();
|
|
40
47
|
bridgeEmit(bridge, 'workflow.list.snapshot', { workflows });
|
|
@@ -67,11 +74,13 @@ export const wireWorkflowHandlers = (bridge, context, session) => {
|
|
|
67
74
|
return;
|
|
68
75
|
}
|
|
69
76
|
let clearSelection = false;
|
|
77
|
+
let resetFeed = false;
|
|
70
78
|
if (!session.isGraphLocked()) {
|
|
71
79
|
// 1. Load document into session
|
|
72
80
|
const loaded = await loadWorkflowIntoSession(session, context.workflowService, context.projectDir, raw.payload.workflowId, context.resolveDefinition);
|
|
73
81
|
// 2. Persist current-workflow id when load succeeded
|
|
74
82
|
if (loaded.ok) {
|
|
83
|
+
resetFeed = true;
|
|
75
84
|
await context.langflowerConfigService.setCurrentWorkflowId(raw.payload.workflowId);
|
|
76
85
|
if (loaded.repaired) {
|
|
77
86
|
const nodeCount = loaded.droppedNodeIds.length;
|
|
@@ -101,7 +110,7 @@ export const wireWorkflowHandlers = (bridge, context, session) => {
|
|
|
101
110
|
});
|
|
102
111
|
}
|
|
103
112
|
// 3. Sync outbound
|
|
104
|
-
await syncAfterWorkflowMutation(bridge, context, session, connected, { clearSelection, catalog: { kind: 'none' } });
|
|
113
|
+
await syncAfterWorkflowMutation(bridge, context, session, connected, { clearSelection, catalog: { kind: 'none' }, resetFeed });
|
|
105
114
|
}));
|
|
106
115
|
subscription.add(bridge['workflow.saveCurrent.requested'].subscribe(async (raw) => {
|
|
107
116
|
if (!isInboundEvent(raw)) {
|
|
@@ -163,11 +172,13 @@ export const wireWorkflowHandlers = (bridge, context, session) => {
|
|
|
163
172
|
return;
|
|
164
173
|
}
|
|
165
174
|
let clearSelection = false;
|
|
175
|
+
let resetFeed = false;
|
|
166
176
|
if (!session.isGraphLocked()) {
|
|
167
|
-
await createEmptyWorkflowInSession(session, context.workflowService, context.projectDir, context.resolveDefinition);
|
|
177
|
+
const created = await createEmptyWorkflowInSession(session, context.workflowService, context.projectDir, context.resolveDefinition);
|
|
168
178
|
clearSelection = true;
|
|
179
|
+
resetFeed = created;
|
|
169
180
|
}
|
|
170
|
-
await syncAfterWorkflowMutation(bridge, context, session, connected, { clearSelection, catalog: { kind: 'none' } });
|
|
181
|
+
await syncAfterWorkflowMutation(bridge, context, session, connected, { clearSelection, catalog: { kind: 'none' }, resetFeed });
|
|
171
182
|
}));
|
|
172
183
|
subscription.add(bridge['workflow.copy.requested'].subscribe(async (raw) => {
|
|
173
184
|
if (!isInboundEvent(raw)) {
|
|
@@ -179,16 +190,19 @@ export const wireWorkflowHandlers = (bridge, context, session) => {
|
|
|
179
190
|
}
|
|
180
191
|
let catalogChanged = false;
|
|
181
192
|
let clearSelection = false;
|
|
193
|
+
let resetFeed = false;
|
|
182
194
|
if (!session.isGraphLocked()) {
|
|
183
195
|
const copied = await copyWorkflowToSession(session, context.workflowService, context.projectDir, raw.payload.workflowId, context.resolveDefinition);
|
|
184
196
|
if (copied && session.activeWorkflowId !== undefined) {
|
|
185
197
|
catalogChanged = true;
|
|
198
|
+
resetFeed = true;
|
|
186
199
|
await context.langflowerConfigService.setCurrentWorkflowId(session.activeWorkflowId);
|
|
187
200
|
}
|
|
188
201
|
clearSelection = true;
|
|
189
202
|
}
|
|
190
203
|
await syncAfterWorkflowMutation(bridge, context, session, connected, {
|
|
191
204
|
clearSelection,
|
|
205
|
+
resetFeed,
|
|
192
206
|
catalog: catalogChanged
|
|
193
207
|
? { kind: 'broadcast' }
|
|
194
208
|
: { kind: 'none' },
|
|
@@ -62,11 +62,11 @@ export class RunCheckpointSession {
|
|
|
62
62
|
event[0] !== 'out') {
|
|
63
63
|
return false;
|
|
64
64
|
}
|
|
65
|
-
const [, nodeIdRaw, portId,
|
|
66
|
-
if (
|
|
65
|
+
const [, nodeIdRaw, portId, response] = event;
|
|
66
|
+
if (!('value' in response) || typeof portId !== 'string') {
|
|
67
67
|
return false;
|
|
68
68
|
}
|
|
69
|
-
const jsonValue = toCheckpointJsonValue(value);
|
|
69
|
+
const jsonValue = toCheckpointJsonValue(response.value);
|
|
70
70
|
if (jsonValue === undefined) {
|
|
71
71
|
this.unsupportedValue = `${String(nodeIdRaw)}.${portId}`;
|
|
72
72
|
return false;
|
|
@@ -6,6 +6,7 @@ export type LangflowerConfigLayers = {
|
|
|
6
6
|
export type LangflowerConfigSettingsWrite = {
|
|
7
7
|
readonly scope: LangflowerConfigScope;
|
|
8
8
|
readonly model?: string;
|
|
9
|
+
readonly embedding?: string;
|
|
9
10
|
readonly provider?: Readonly<Record<string, LangflowerProviderConfig>>;
|
|
10
11
|
readonly providerApiKeys?: Readonly<Record<string, string>>;
|
|
11
12
|
/** `null` clears the scope key (Settings Default). */
|
|
@@ -32,4 +33,5 @@ export declare class LangflowerConfigService {
|
|
|
32
33
|
writeSettings(input: LangflowerConfigSettingsWrite): Promise<LangflowerConfigLayers>;
|
|
33
34
|
setCurrentWorkflowId(workflowId: string | undefined): Promise<LangflowerConfig>;
|
|
34
35
|
setDividerPositions(positions: DividerPositions): Promise<LangflowerConfig>;
|
|
36
|
+
setPaletteVisible(visible: boolean): Promise<LangflowerConfig>;
|
|
35
37
|
}
|
|
@@ -147,6 +147,9 @@ function parseLangflowerConfig(raw) {
|
|
|
147
147
|
? { currentWorkflowId: raw.currentWorkflowId }
|
|
148
148
|
: {}),
|
|
149
149
|
...(typeof raw.model === 'string' ? { model: raw.model } : {}),
|
|
150
|
+
...(typeof raw.embedding === 'string'
|
|
151
|
+
? { embedding: raw.embedding }
|
|
152
|
+
: {}),
|
|
150
153
|
...(typeof raw.serverLogs === 'boolean'
|
|
151
154
|
? { serverLogs: raw.serverLogs }
|
|
152
155
|
: {}),
|
|
@@ -156,6 +159,9 @@ function parseLangflowerConfig(raw) {
|
|
|
156
159
|
...(harness !== undefined ? { harness } : {}),
|
|
157
160
|
...(mcp !== undefined ? { mcp } : {}),
|
|
158
161
|
...parseDividerPositions(raw.dividerPositions),
|
|
162
|
+
...(typeof raw.paletteVisible === 'boolean'
|
|
163
|
+
? { paletteVisible: raw.paletteVisible }
|
|
164
|
+
: {}),
|
|
159
165
|
};
|
|
160
166
|
}
|
|
161
167
|
function parseDividerPositions(raw) {
|
|
@@ -205,6 +211,14 @@ function mergeLangflowerConfig(existing, patch) {
|
|
|
205
211
|
merged.model = patch.model;
|
|
206
212
|
}
|
|
207
213
|
}
|
|
214
|
+
if (patch.embedding !== undefined) {
|
|
215
|
+
if (patch.embedding.trim().length === 0) {
|
|
216
|
+
delete merged.embedding;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
merged.embedding = patch.embedding;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
208
222
|
if ('serverLogs' in patch) {
|
|
209
223
|
if (patch.serverLogs === undefined) {
|
|
210
224
|
delete merged.serverLogs;
|
|
@@ -219,6 +233,9 @@ function mergeLangflowerConfig(existing, patch) {
|
|
|
219
233
|
if (patch.dividerPositions !== undefined) {
|
|
220
234
|
merged.dividerPositions = patch.dividerPositions;
|
|
221
235
|
}
|
|
236
|
+
if (patch.paletteVisible !== undefined) {
|
|
237
|
+
merged.paletteVisible = patch.paletteVisible;
|
|
238
|
+
}
|
|
222
239
|
return merged;
|
|
223
240
|
}
|
|
224
241
|
function serializeLangflowerConfig(merged) {
|
|
@@ -302,6 +319,9 @@ export class LangflowerConfigService {
|
|
|
302
319
|
? { currentWorkflowId: config.currentWorkflowId }
|
|
303
320
|
: {}),
|
|
304
321
|
...(config.model !== undefined ? { model: config.model } : {}),
|
|
322
|
+
...(config.embedding !== undefined
|
|
323
|
+
? { embedding: config.embedding }
|
|
324
|
+
: {}),
|
|
305
325
|
...(config.provider !== undefined
|
|
306
326
|
? { provider: config.provider }
|
|
307
327
|
: {}),
|
|
@@ -330,6 +350,9 @@ export class LangflowerConfigService {
|
|
|
330
350
|
]));
|
|
331
351
|
const patch = {
|
|
332
352
|
...(input.model !== undefined ? { model: input.model } : {}),
|
|
353
|
+
...(input.embedding !== undefined
|
|
354
|
+
? { embedding: input.embedding }
|
|
355
|
+
: {}),
|
|
333
356
|
...(provider !== undefined ? { provider } : {}),
|
|
334
357
|
...('serverLogs' in input
|
|
335
358
|
? {
|
|
@@ -357,4 +380,11 @@ export class LangflowerConfigService {
|
|
|
357
380
|
await this.writeRawAt(this.projectConfigPath(), merged);
|
|
358
381
|
return parseLangflowerConfig(merged);
|
|
359
382
|
}
|
|
383
|
+
async setPaletteVisible(visible) {
|
|
384
|
+
const merged = mergeLangflowerConfig(await this.readRawAt(this.projectConfigPath()), {
|
|
385
|
+
paletteVisible: visible,
|
|
386
|
+
});
|
|
387
|
+
await this.writeRawAt(this.projectConfigPath(), merged);
|
|
388
|
+
return parseLangflowerConfig(merged);
|
|
389
|
+
}
|
|
360
390
|
}
|
|
@@ -16,6 +16,7 @@ export async function buildSessionBootstrap(session, langflowerConfigService, re
|
|
|
16
16
|
version: LangflowerSession.snapshotVersion,
|
|
17
17
|
langflowerConfig,
|
|
18
18
|
dividerPositions: session.dividerPositions,
|
|
19
|
+
paletteVisible: session.paletteVisible,
|
|
19
20
|
selectedNode: buildSelectedNodePayload(session, resolveDefinition).node,
|
|
20
21
|
settings: session.settings,
|
|
21
22
|
};
|
|
@@ -14,6 +14,8 @@ export declare class LangflowerSession {
|
|
|
14
14
|
runnerStatus: RuntimeRunnerStatus;
|
|
15
15
|
runId: RunId | undefined;
|
|
16
16
|
dividerPositions: DividerPositions;
|
|
17
|
+
/** Left node palette shown. Hydrated from project jsonc; default visible. */
|
|
18
|
+
paletteVisible: boolean;
|
|
17
19
|
/** In-memory canvas selection, shared across tabs. `null` = nothing selected. */
|
|
18
20
|
selectedNodeId: string | null;
|
|
19
21
|
/** Settings aside chrome — session memory only (not persisted to disk). */
|
|
@@ -32,5 +34,5 @@ export declare class LangflowerSession {
|
|
|
32
34
|
markPristine(): void;
|
|
33
35
|
buildExecutionFeed(): ExecutionFeedSnapshotPayload | null;
|
|
34
36
|
static readonly sessionReadyVersion = 1;
|
|
35
|
-
static readonly snapshotVersion =
|
|
37
|
+
static readonly snapshotVersion = 7;
|
|
36
38
|
}
|
|
@@ -4,7 +4,7 @@ import { Subscription } from 'rxjs';
|
|
|
4
4
|
import { PendingPermissionAsks } from '../harness/pending-permission-asks.js';
|
|
5
5
|
import { emptySettingsDraftStore, } from './settings-draft-session.js';
|
|
6
6
|
const SESSION_READY_VERSION = 1;
|
|
7
|
-
const SNAPSHOT_VERSION =
|
|
7
|
+
const SNAPSHOT_VERSION = 7;
|
|
8
8
|
export class LangflowerSession {
|
|
9
9
|
runtime = new RuntimeFacade({ log: true });
|
|
10
10
|
/** Feed permission.ask pause/resume for the internal tool loop. */
|
|
@@ -20,6 +20,8 @@ export class LangflowerSession {
|
|
|
20
20
|
rightWidth: 360,
|
|
21
21
|
composerHeight: 168,
|
|
22
22
|
};
|
|
23
|
+
/** Left node palette shown. Hydrated from project jsonc; default visible. */
|
|
24
|
+
paletteVisible = true;
|
|
23
25
|
/** In-memory canvas selection, shared across tabs. `null` = nothing selected. */
|
|
24
26
|
selectedNodeId = null;
|
|
25
27
|
/** Settings aside chrome — session memory only (not persisted to disk). */
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LangflowerSession } from './langflower-session.js';
|
|
2
|
+
/**
|
|
3
|
+
* Drop the session run log so `buildExecutionFeed()` returns null.
|
|
4
|
+
* Call only when the runner is idle (document switch or user Clear).
|
|
5
|
+
*/
|
|
6
|
+
export declare const resetSessionExecutionFeed: (session: LangflowerSession) => void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drop the session run log so `buildExecutionFeed()` returns null.
|
|
3
|
+
* Call only when the runner is idle (document switch or user Clear).
|
|
4
|
+
*/
|
|
5
|
+
export const resetSessionExecutionFeed = (session) => {
|
|
6
|
+
session.runtime.runner.clearEventLog();
|
|
7
|
+
session.runId = undefined;
|
|
8
|
+
};
|
|
@@ -149,6 +149,12 @@ const materializeRuntimeNode = (projectDir, node, resolveDefinition) => {
|
|
|
149
149
|
if (input === undefined) {
|
|
150
150
|
continue;
|
|
151
151
|
}
|
|
152
|
+
// HITL ports stay inactive until `pushIntoInput` (composer Start /
|
|
153
|
+
// reply). Connecting a persisted Chat Input message here would
|
|
154
|
+
// double-emit when cold-start does startNode + pushIntoInput.
|
|
155
|
+
if (config.hitl !== undefined) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
152
158
|
if (Object.hasOwn(node.inputs, config.portId)) {
|
|
153
159
|
input.connect(of(node.inputs[config.portId]));
|
|
154
160
|
continue;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Persisted `node.inputs` hold visible UI overrides only (ADR-028).
|
|
3
|
-
* Wire-only /
|
|
4
|
-
*
|
|
3
|
+
* Wire-only / preview ports and values equal to the current definition
|
|
4
|
+
* `defaultValue` must not be written to disk. Hidden ports with an
|
|
5
|
+
* editable `inline` still persist (Chat Input `message`).
|
|
5
6
|
*/
|
|
6
7
|
const valuesEqual = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
7
8
|
const isPreviewInline = (inline) => {
|
|
@@ -18,10 +19,8 @@ const isPreviewInline = (inline) => {
|
|
|
18
19
|
}
|
|
19
20
|
return false;
|
|
20
21
|
};
|
|
21
|
-
/**
|
|
22
|
-
const hasVisibleUiInputField = (config) => config.
|
|
23
|
-
config.inline !== undefined &&
|
|
24
|
-
!isPreviewInline(config.inline);
|
|
22
|
+
/** Editable inline field (canvas / inspector), including hidden+inline. */
|
|
23
|
+
const hasVisibleUiInputField = (config) => config.inline !== undefined && !isPreviewInline(config.inline);
|
|
25
24
|
/**
|
|
26
25
|
* Keep only persistable overrides: visible UI field and value !== current
|
|
27
26
|
* definition defaultValue.
|
|
@@ -36,6 +35,9 @@ export const prunePersistedInputs = (inputs, definition) => {
|
|
|
36
35
|
if (!hasVisibleUiInputField(config)) {
|
|
37
36
|
continue;
|
|
38
37
|
}
|
|
38
|
+
if (typeof value === 'string' && value.trim() === '') {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
39
41
|
if (config.defaultValue !== undefined &&
|
|
40
42
|
valuesEqual(value, config.defaultValue)) {
|
|
41
43
|
continue;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Custom Nodes
|
|
2
2
|
|
|
3
|
-
Author packs under `.langflower/nodes/<pack>/`. Default seed
|
|
4
|
-
**`my-nodes
|
|
3
|
+
Author packs under `.langflower/nodes/<pack>/`. Default seed packs:
|
|
4
|
+
**`my-nodes/`** (git-diff / review-gate) and **`hello-embed/`** (markdown
|
|
5
|
+
→ local sqlite embeddings; copy as a starting point).
|
|
5
6
|
|
|
6
7
|
Import **`defineNode`** (default), `defineToolRegistrations` (LLM tool packs),
|
|
7
8
|
or `defineReactiveNode` from `@langflower/node-sdk` — not from a root
|
|
@@ -10,8 +11,19 @@ or `defineReactiveNode` from `@langflower/node-sdk` — not from a root
|
|
|
10
11
|
Each `*.ts` file may `export default` a definition or an array. No required
|
|
11
12
|
`index.ts`. Run `npm install` inside the pack when you add author dependencies;
|
|
12
13
|
Langflower does **not** auto-install on start, bootstrap, or palette reload.
|
|
14
|
+
Startup **does** compile packs under `.langflower/nodes/`.
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
If pack files `import` each other with a **`.ts` suffix**, set
|
|
17
|
+
`"allowImportingTsExtensions": true` next to `"noEmit": true` in the pack
|
|
18
|
+
`tsconfig.json` (hello-embed seed). Without it the pack does not compile.
|
|
19
|
+
`my-nodes` uses extensionless imports and does not need the flag.
|
|
20
|
+
|
|
21
|
+
- `hello-embed/` — sample embedding KB (`ingest` / `search` /
|
|
22
|
+
`search-handle`). See [`nodes/hello-embed/README.md`](nodes/hello-embed/README.md).
|
|
23
|
+
Workflows: `kb-ingest`, `kb-manual-search`, `kb-tool`, `kb-rag`.
|
|
24
|
+
Settings default embedding model required.
|
|
25
|
+
|
|
26
|
+
See [`nodes/my-nodes/README.md`](nodes/my-nodes/README.md) for the author
|
|
15
27
|
contract.
|
|
16
28
|
|
|
17
29
|
## Seed demo
|