langflower 0.0.7 → 0.0.9
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/package.json +1 -1
- package/ui-dist/{chunk-Y6VMBLSJ.js → chunk-7UMVYN3A.js} +1 -1
- package/ui-dist/{chunk-6DQ2XSRW.js → chunk-MDGXX73Z.js} +3 -3
- package/ui-dist/index.html +1 -1
- package/ui-dist/main-2JJGCNTD.js +313 -0
- package/vendor/common-nodes/dist/ai/chat-completion-stream.d.ts +2 -0
- package/vendor/common-nodes/dist/ai/critique/node.d.ts +246 -0
- package/vendor/common-nodes/dist/ai/critique/node.js +2 -2
- package/vendor/common-nodes/dist/ai/fake-llm/node.d.ts +246 -0
- package/vendor/common-nodes/dist/ai/features/chat-completion-stream.d.ts +53 -0
- package/vendor/common-nodes/dist/ai/features/chat-completion-stream.js +1 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/autokick-recovery.d.ts +13 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/autokick-recovery.js +17 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/classify-llm-failure.d.ts +2 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/classify-llm-failure.js +113 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/dead-loop-detector.d.ts +28 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/dead-loop-detector.js +194 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/live-get-tools.d.ts +9 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/live-get-tools.js +21 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-reducer.d.ts +2 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-reducer.js +216 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-types.d.ts +125 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/llm-loop-types.js +39 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/normalize-llm-recovery-policy.d.ts +2 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/normalize-llm-recovery-policy.js +59 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/operators/normalize-tool-result.d.ts +1 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/operators/normalize-tool-result.js +7 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/operators/observe-provider-stream.d.ts +43 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/operators/observe-provider-stream.js +96 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/run-agent-loop.d.ts +32 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/run-agent-loop.js +58 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/run-llm-loop.d.ts +80 -0
- package/vendor/common-nodes/dist/ai/features/llm-loop/run-llm-loop.js +681 -0
- package/vendor/common-nodes/dist/ai/features/llm-role-preset.d.ts +69 -0
- package/vendor/common-nodes/dist/ai/features/llm-role-preset.js +265 -0
- package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.d.ts +148 -0
- package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.js +198 -0
- package/vendor/common-nodes/dist/ai/features/llm-session/run-session-machine.d.ts +21 -0
- package/vendor/common-nodes/dist/ai/features/llm-session/run-session-machine.js +118 -0
- package/vendor/common-nodes/dist/ai/features/openai/context-length-error.d.ts +14 -0
- package/vendor/common-nodes/dist/ai/features/openai/context-length-error.js +63 -0
- package/vendor/common-nodes/dist/ai/features/openai/create-chat-completion-stream.d.ts +19 -0
- package/vendor/common-nodes/dist/ai/features/openai/create-chat-completion-stream.js +182 -0
- package/vendor/common-nodes/dist/ai/features/openai/list-provider-models.d.ts +28 -0
- package/vendor/common-nodes/dist/ai/features/openai/list-provider-models.js +52 -0
- package/vendor/common-nodes/dist/ai/features/openai/llm-context-compaction.d.ts +31 -0
- package/vendor/common-nodes/dist/ai/features/openai/llm-context-compaction.js +326 -0
- package/vendor/common-nodes/dist/ai/features/openai/normalize-compaction-params.d.ts +14 -0
- package/vendor/common-nodes/dist/ai/features/openai/normalize-compaction-params.js +21 -0
- package/vendor/common-nodes/dist/ai/features/openai/prepare-chat-completion.d.ts +30 -0
- package/vendor/common-nodes/dist/ai/features/openai/prepare-chat-completion.js +132 -0
- package/vendor/common-nodes/dist/ai/features/path-choice/control-tools.d.ts +20 -0
- package/vendor/common-nodes/dist/ai/features/path-choice/control-tools.js +70 -0
- package/vendor/common-nodes/dist/ai/features/path-choice/run-reactive-path-choice-loop.d.ts +35 -0
- package/vendor/common-nodes/dist/ai/features/path-choice/run-reactive-path-choice-loop.js +106 -0
- package/vendor/common-nodes/dist/ai/features/prompt/build-effective-system-prompt.d.ts +9 -0
- package/vendor/common-nodes/dist/ai/features/prompt/build-effective-system-prompt.js +21 -0
- package/vendor/common-nodes/dist/ai/features/prompt/normalize-max-iterations.d.ts +13 -0
- package/vendor/common-nodes/dist/ai/features/prompt/normalize-max-iterations.js +23 -0
- package/vendor/common-nodes/dist/ai/features/prompt/resolve-chat-provider-model.d.ts +10 -0
- package/vendor/common-nodes/dist/ai/features/prompt/resolve-chat-provider-model.js +8 -0
- package/vendor/common-nodes/dist/ai/features/run-host-services.d.ts +54 -0
- package/vendor/common-nodes/dist/ai/features/run-host-services.js +29 -0
- package/vendor/common-nodes/dist/ai/features/scripted-chat-completion-stream.d.ts +17 -0
- package/vendor/common-nodes/dist/ai/features/scripted-chat-completion-stream.js +61 -0
- package/vendor/common-nodes/dist/ai/features/sub-agent-protocol.d.ts +39 -0
- package/vendor/common-nodes/dist/ai/features/sub-agent-protocol.js +43 -0
- package/vendor/common-nodes/dist/ai/features/ui-schema/llm-compaction-ui-schema.d.ts +14 -0
- package/vendor/common-nodes/dist/ai/features/ui-schema/llm-compaction-ui-schema.js +18 -0
- package/vendor/common-nodes/dist/ai/features/ui-schema/llm-panel-ui-schema.d.ts +80 -0
- package/vendor/common-nodes/dist/ai/features/ui-schema/llm-panel-ui-schema.js +76 -0
- package/vendor/common-nodes/dist/ai/features/ui-schema/llm-recovery-ui-schema.d.ts +113 -0
- package/vendor/common-nodes/dist/ai/features/ui-schema/llm-recovery-ui-schema.js +131 -0
- package/vendor/common-nodes/dist/ai/features/wait-for-subagent-result.d.ts +6 -0
- package/vendor/common-nodes/dist/ai/features/wait-for-subagent-result.js +30 -0
- package/vendor/common-nodes/dist/ai/llm-loop/autokick-recovery.d.ts +13 -0
- package/vendor/common-nodes/dist/ai/llm-loop/autokick-recovery.js +17 -0
- package/vendor/common-nodes/dist/ai/llm-loop/dead-loop-detector.d.ts +28 -0
- package/vendor/common-nodes/dist/ai/llm-loop/dead-loop-detector.js +194 -0
- package/vendor/common-nodes/dist/ai/llm-loop/llm-loop-reducer.js +36 -0
- package/vendor/common-nodes/dist/ai/llm-loop/llm-loop-types.d.ts +35 -0
- package/vendor/common-nodes/dist/ai/llm-loop/llm-loop-types.js +19 -0
- package/vendor/common-nodes/dist/ai/llm-loop/normalize-llm-recovery-policy.js +52 -9
- package/vendor/common-nodes/dist/ai/llm-loop/operators/observe-provider-stream.d.ts +8 -2
- package/vendor/common-nodes/dist/ai/llm-loop/operators/observe-provider-stream.js +43 -13
- package/vendor/common-nodes/dist/ai/llm-loop/run-llm-loop.d.ts +3 -5
- package/vendor/common-nodes/dist/ai/llm-loop/run-llm-loop.js +116 -1
- package/vendor/common-nodes/dist/ai/llm-recovery-ui-schema.d.ts +82 -0
- package/vendor/common-nodes/dist/ai/llm-recovery-ui-schema.js +95 -0
- package/vendor/common-nodes/dist/ai/llm-session-shell.d.ts +4 -9
- package/vendor/common-nodes/dist/ai/llm-session-shell.js +2 -4
- package/vendor/common-nodes/dist/ai/nodes/critique/node.d.ts +588 -0
- package/vendor/common-nodes/dist/ai/nodes/critique/node.js +240 -0
- package/vendor/common-nodes/dist/ai/nodes/fake-llm/node.d.ts +571 -0
- package/vendor/common-nodes/dist/ai/nodes/fake-llm/node.js +208 -0
- package/vendor/common-nodes/dist/ai/nodes/openai-llm/node.d.ts +587 -0
- package/vendor/common-nodes/dist/ai/nodes/openai-llm/node.js +91 -0
- package/vendor/common-nodes/dist/ai/nodes/review/node.d.ts +593 -0
- package/vendor/common-nodes/dist/ai/nodes/review/node.js +240 -0
- package/vendor/common-nodes/dist/ai/nodes/sub-agent/node.d.ts +630 -0
- package/vendor/common-nodes/dist/ai/nodes/sub-agent/node.js +302 -0
- package/vendor/common-nodes/dist/ai/openai/create-chat-completion-stream.js +6 -0
- package/vendor/common-nodes/dist/ai/openai/prepare-chat-completion.d.ts +2 -0
- package/vendor/common-nodes/dist/ai/openai/prepare-chat-completion.js +18 -0
- package/vendor/common-nodes/dist/ai/openai-llm/node.d.ts +246 -0
- package/vendor/common-nodes/dist/ai/review/node.d.ts +246 -0
- package/vendor/common-nodes/dist/ai/review/node.js +2 -2
- package/vendor/common-nodes/dist/ai/sub-agent/node.d.ts +246 -0
- package/vendor/common-nodes/dist/ai/sub-agent/node.js +2 -2
- package/vendor/common-nodes/dist/catalog.js +7 -5
- package/vendor/common-nodes/dist/compile-custom-nodes/node.d.ts +21 -0
- package/vendor/common-nodes/dist/compile-custom-nodes/node.js +45 -0
- package/vendor/common-nodes/dist/crawl/crawl/node.js +1 -1
- package/vendor/common-nodes/dist/crawl/fetch-url/node.js +1 -1
- package/vendor/common-nodes/dist/flow/repeat/node.js +6 -1
- package/vendor/common-nodes/dist/langflower-tools/emit-registration-tools.d.ts +18 -0
- package/vendor/common-nodes/dist/langflower-tools/emit-registration-tools.js +29 -0
- package/vendor/common-nodes/dist/langflower-tools/node.d.ts +20 -0
- package/vendor/common-nodes/dist/langflower-tools/node.js +77 -0
- package/vendor/common-nodes/dist/text/append-file/node.js +1 -1
- package/vendor/common-nodes/dist/text/read-file/node.js +1 -1
- package/vendor/common-nodes/dist/text/write-file/node.js +1 -1
- package/vendor/common-nodes/dist/tools/inventory-tool-round.d.ts +2 -2
- package/vendor/common-nodes/package.json +10 -10
- package/vendor/compiler/dist/compile-project-nodes.d.ts +2 -1
- package/vendor/compiler/dist/compile-project-nodes.js +35 -6
- package/vendor/compiler/dist/resolve-host-types.d.ts +0 -5
- package/vendor/compiler/dist/resolve-host-types.js +0 -8
- package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.d.ts +1 -1
- package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.js +1 -1
- package/vendor/node-sdk/dist/node-factory/define-llm-node/recovery-notice.d.ts +8 -0
- package/vendor/node-sdk/dist/node-factory/define-llm-node/recovery-notice.js +14 -0
- package/vendor/runtime/dist/runtime-editor.d.ts +5 -1
- package/vendor/runtime/dist/runtime-editor.js +19 -0
- package/vendor/runtime/dist/runtime-runner.js +17 -17
- package/vendor/runtime/dist/runtime.d.ts +2 -1
- package/vendor/runtime/dist/runtime.js +1 -0
- package/vendor/runtime/dist/testing/workflows/workflow-events.d.ts +8 -6
- package/vendor/runtime/dist/testing/workflows/workflow-events.js +19 -31
- package/vendor/runtime/dist/types.d.ts +33 -38
- package/vendor/runtime/dist/types.js +2 -1
- package/vendor/server/dist/bridge/attach-langflower-bridge.js +3 -2
- package/vendor/server/dist/bridge/bridge-event-log.js +17 -102
- package/vendor/server/dist/bridge/build-execution-context.d.ts +5 -2
- package/vendor/server/dist/bridge/build-execution-context.js +45 -5
- package/vendor/server/dist/bridge/forward-runner-event.d.ts +1 -1
- package/vendor/server/dist/bridge/forward-runner-event.js +7 -12
- package/vendor/server/dist/bridge/get-live-wired-tools.d.ts +12 -0
- package/vendor/server/dist/bridge/get-live-wired-tools.js +80 -0
- package/vendor/server/dist/bridge/langflower-tools-rpc.d.ts +7 -0
- package/vendor/server/dist/bridge/langflower-tools-rpc.js +29 -0
- package/vendor/server/dist/bridge/settings-draft-controller.js +26 -3
- package/vendor/server/dist/bridge/wire-custom-palette-handlers.d.ts +2 -1
- package/vendor/server/dist/bridge/wire-custom-palette-handlers.js +3 -5
- package/vendor/server/dist/bridge/wire-runner-handlers.js +15 -8
- package/vendor/server/dist/checkpoint/run-checkpoint-session.d.ts +1 -1
- package/vendor/server/dist/checkpoint/run-checkpoint-session.js +10 -9
- package/vendor/server/dist/palette/compile-and-hot-swap-custom-nodes.d.ts +10 -0
- package/vendor/server/dist/palette/compile-and-hot-swap-custom-nodes.js +23 -0
- package/vendor/server/dist/workflow/apply-editor-mutation.d.ts +5 -0
- package/vendor/server/dist/workflow/apply-editor-mutation.js +32 -0
- package/vendor/server/skeleton/instructions.md +9 -5
- package/vendor/server/skeleton/nodes/my-nodes/README.md +4 -3
- package/vendor/server/skeleton/schemas/langflower-config.schema.json +11 -1
- package/vendor/server/skeleton/skills/langflower-helper/SKILL.md +49 -19
- package/vendor/server/skeleton/skills/langflower-helper/architecture.md +22 -9
- package/vendor/server/skeleton/skills/langflower-helper/layout.md +15 -15
- package/vendor/server/skeleton/skills/langflower-node-writer/SKILL.md +19 -9
- package/vendor/server/skeleton/skills/langflower-workflow-writer/SKILL.md +14 -10
- package/vendor/server/skeleton/workflows/starter.json +30 -3
- package/vendor/shared/dist/execution/derive-run-settle-outcome.d.ts +1 -1
- package/vendor/shared/dist/execution/derive-run-settle-outcome.js +4 -3
- package/vendor/shared/dist/execution/derive-run-settle-outcome.test.js +9 -9
- package/vendor/shared/dist/langflower-bus-config.d.ts +6 -14
- package/vendor/shared/dist/langflower-bus-config.js +4 -12
- package/vendor/shared/dist/langflower-config/resolve-wired-tool-options.js +6 -0
- package/vendor/shared/dist/langflower-config/resolve-wired-tool-options.test.js +30 -0
- package/vendor/shared/dist/langflower-ws-waits.d.ts +7 -14
- package/vendor/shared/dist/langflower-ws-waits.js +14 -14
- package/vendor/websocket-bridge/dist/bridge-codec.d.ts +1 -0
- package/vendor/websocket-bridge/dist/bridge-codec.js +11 -11
- package/vendor/websocket-bridge/dist/bridge-frame.js +1 -1
- package/vendor/websocket-bridge/dist/bridge-subjects.d.ts +1 -1
- package/vendor/websocket-bridge/dist/bridge-subjects.js +2 -2
- package/vendor/websocket-bridge/dist/bridge-types.d.ts +13 -1
- package/vendor/websocket-bridge/dist/create-client.js +3 -3
- package/vendor/websocket-bridge/dist/create-server.js +12 -6
- package/vendor/websocket-bridge/package.json +8 -0
- package/ui-dist/main-SMO3L7U5.js +0 -311
|
@@ -8,6 +8,30 @@ import { applyDraftPatch, buildDraftSnapshot, providerIndexesWithBaseUrl, seedSc
|
|
|
8
8
|
import { bridgeEmit, clientEmit } from './bridge-outbound.js';
|
|
9
9
|
import { buildLangflowerConfigSnapshot } from './build-langflower-config-snapshot.js';
|
|
10
10
|
const isScope = (value) => value === 'project' || value === 'global';
|
|
11
|
+
/** Fill missing/empty Save keys from the session draft (write-only apiKey). */
|
|
12
|
+
const mergeProviderApiKeysFromSession = (payload, sessionDraft) => {
|
|
13
|
+
if (payload.provider === undefined || sessionDraft === undefined) {
|
|
14
|
+
return payload.providerApiKeys;
|
|
15
|
+
}
|
|
16
|
+
const merged = {
|
|
17
|
+
...(payload.providerApiKeys ?? {}),
|
|
18
|
+
};
|
|
19
|
+
for (const row of sessionDraft.providers) {
|
|
20
|
+
const id = row.id.trim();
|
|
21
|
+
if (id.length === 0) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const fromPayload = merged[id]?.trim() ?? '';
|
|
25
|
+
if (fromPayload.length > 0) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const pending = row.apiKey.trim();
|
|
29
|
+
if (pending.length > 0) {
|
|
30
|
+
merged[id] = pending;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return Object.keys(merged).length > 0 ? merged : payload.providerApiKeys;
|
|
34
|
+
};
|
|
11
35
|
const layerForScope = (layers, scope) => (scope === 'project' ? layers.project : layers.global);
|
|
12
36
|
export const createSettingsDraftController = (bridge, context, session) => {
|
|
13
37
|
const probeGeneration = new Map();
|
|
@@ -144,15 +168,14 @@ export const createSettingsDraftController = (bridge, context, session) => {
|
|
|
144
168
|
if (payload === undefined || !isScope(payload.scope)) {
|
|
145
169
|
return null;
|
|
146
170
|
}
|
|
171
|
+
const providerApiKeys = mergeProviderApiKeysFromSession(payload, state?.draft);
|
|
147
172
|
const layers = await context.langflowerConfigService.writeSettings({
|
|
148
173
|
scope: payload.scope,
|
|
149
174
|
...(payload.model !== undefined ? { model: payload.model } : {}),
|
|
150
175
|
...(payload.provider !== undefined
|
|
151
176
|
? { provider: payload.provider }
|
|
152
177
|
: {}),
|
|
153
|
-
...(
|
|
154
|
-
? { providerApiKeys: payload.providerApiKeys }
|
|
155
|
-
: {}),
|
|
178
|
+
...(providerApiKeys !== undefined ? { providerApiKeys } : {}),
|
|
156
179
|
...('serverLogs' in payload
|
|
157
180
|
? { serverLogs: payload.serverLogs }
|
|
158
181
|
: {}),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Subscription } from 'rxjs';
|
|
2
2
|
import type { ServerContext } from '../server-context.js';
|
|
3
|
+
import type { LangflowerSession } from '../session/langflower-session.js';
|
|
3
4
|
import type { LangflowerBridge } from './langflower-bridge.types.js';
|
|
4
|
-
export declare const wireCustomPaletteHandlers: (bridge: LangflowerBridge, context: ServerContext) => Subscription;
|
|
5
|
+
export declare const wireCustomPaletteHandlers: (bridge: LangflowerBridge, context: ServerContext, session: LangflowerSession) => Subscription;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { compileAndHotSwapCustomNodes } from '../palette/compile-and-hot-swap-custom-nodes.js';
|
|
2
2
|
import { isInboundEvent } from './inbound-guards.js';
|
|
3
|
-
export const wireCustomPaletteHandlers = (bridge, context) => bridge['customPalette.update.requested'].subscribe(async (raw) => {
|
|
3
|
+
export const wireCustomPaletteHandlers = (bridge, context, session) => bridge['customPalette.update.requested'].subscribe(async (raw) => {
|
|
4
4
|
if (!isInboundEvent(raw)) {
|
|
5
5
|
return;
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
const snapshot = await context.customPaletteService.update(context.projectDir);
|
|
9
|
-
bridgeEmit(bridge, 'customPalette.snapshot', snapshot);
|
|
7
|
+
await compileAndHotSwapCustomNodes(session, context, bridge);
|
|
10
8
|
});
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { isPortTelemetry, isRuntimeDone, } from '@langflower/runtime';
|
|
1
2
|
import { buildWorkflowFingerprint, } from '@langflower/shared/langflower.js';
|
|
2
3
|
import { Subscription } from 'rxjs';
|
|
3
4
|
import { listResumableCheckpoints } from '../checkpoint/list-resumable-checkpoints.js';
|
|
4
5
|
import { resolveCheckpointBoundary } from '../checkpoint/resolve-checkpoint-boundary.js';
|
|
5
6
|
import { buildContextSeeds, applyObservableContextSeeds, } from './build-execution-context.js';
|
|
7
|
+
import { getLiveWiredTools } from './get-live-wired-tools.js';
|
|
8
|
+
import { createLangflowerToolsRpc } from './langflower-tools-rpc.js';
|
|
6
9
|
import { bridgeEmit, clientEmit } from './bridge-outbound.js';
|
|
7
10
|
import { findClientById } from './client-index.js';
|
|
8
11
|
import { isInboundEvent } from './inbound-guards.js';
|
|
@@ -35,11 +38,15 @@ export const wireRunnerHandlers = (bridge, context, session, checkpoints) => {
|
|
|
35
38
|
const emitPermissionAsk = (payload) => {
|
|
36
39
|
bridgeEmit(bridge, 'runner.permission.ask', payload);
|
|
37
40
|
};
|
|
41
|
+
const requestLangflowerBus = createLangflowerToolsRpc(bridge);
|
|
42
|
+
const liveWiredTools = (agentNodeId) => getLiveWiredTools(session, agentNodeId);
|
|
38
43
|
subscription.add(session.runtime.runner.events$.subscribe((event) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
44
|
+
const [, nodeId, portId] = isPortTelemetry(event) ? event : [];
|
|
45
|
+
const boundary = isPortTelemetry(event) &&
|
|
46
|
+
event[0] === 'out' &&
|
|
47
|
+
typeof portId === 'string' &&
|
|
41
48
|
session.activeWorkflow !== null
|
|
42
|
-
? resolveCheckpointBoundary(session.activeWorkflow, String(
|
|
49
|
+
? resolveCheckpointBoundary(session.activeWorkflow, String(nodeId), portId)
|
|
43
50
|
: undefined;
|
|
44
51
|
const shouldPersist = checkpoints.observe(event, boundary === undefined
|
|
45
52
|
? undefined
|
|
@@ -57,7 +64,7 @@ export const wireRunnerHandlers = (bridge, context, session, checkpoints) => {
|
|
|
57
64
|
})
|
|
58
65
|
.catch(() => undefined);
|
|
59
66
|
}
|
|
60
|
-
if (event
|
|
67
|
+
if (isRuntimeDone(event)) {
|
|
61
68
|
void checkpoints
|
|
62
69
|
.markCompleted()
|
|
63
70
|
.then(async (summary) => {
|
|
@@ -83,7 +90,7 @@ export const wireRunnerHandlers = (bridge, context, session, checkpoints) => {
|
|
|
83
90
|
crypto.randomUUID());
|
|
84
91
|
// Lock before async seed build so workflow load cannot race in.
|
|
85
92
|
session.runnerStatus = 'running';
|
|
86
|
-
const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk));
|
|
93
|
+
const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk, requestLangflowerBus, liveWiredTools));
|
|
87
94
|
const initialPayload = mergeSeeds(contextSeeds, clientInitialPayload);
|
|
88
95
|
if (session.activeWorkflow !== null) {
|
|
89
96
|
checkpoints.beginRun(resolvedRunId, session.activeWorkflow);
|
|
@@ -111,7 +118,7 @@ export const wireRunnerHandlers = (bridge, context, session, checkpoints) => {
|
|
|
111
118
|
const resolvedRunId = (clientRunId ??
|
|
112
119
|
crypto.randomUUID());
|
|
113
120
|
session.runnerStatus = 'running';
|
|
114
|
-
const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk));
|
|
121
|
+
const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk, requestLangflowerBus, liveWiredTools));
|
|
115
122
|
const initialPayload = mergeSeeds(contextSeeds, clientInitialPayload);
|
|
116
123
|
if (session.activeWorkflow !== null) {
|
|
117
124
|
checkpoints.beginRun(resolvedRunId, session.activeWorkflow);
|
|
@@ -196,7 +203,7 @@ export const wireRunnerHandlers = (bridge, context, session, checkpoints) => {
|
|
|
196
203
|
return;
|
|
197
204
|
}
|
|
198
205
|
session.runnerStatus = 'running';
|
|
199
|
-
const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, checkpoint.runId, emitPermissionAsk));
|
|
206
|
+
const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, checkpoint.runId, emitPermissionAsk, requestLangflowerBus, liveWiredTools));
|
|
200
207
|
checkpoints.hydrateFromCheckpoint(checkpoint, workflow);
|
|
201
208
|
const resumeOptions = checkpoints.resumeOptionsFromCheckpoint(checkpoint);
|
|
202
209
|
const resumed = session.runtime.runner.resume({
|
|
@@ -249,7 +256,7 @@ export const wireRunnerHandlers = (bridge, context, session, checkpoints) => {
|
|
|
249
256
|
if (wasIdle) {
|
|
250
257
|
const resolvedRunId = crypto.randomUUID();
|
|
251
258
|
session.runnerStatus = 'running';
|
|
252
|
-
const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk));
|
|
259
|
+
const contextSeeds = applyObservableContextSeeds(session, await buildContextSeeds(session, context, resolvedRunId, emitPermissionAsk, requestLangflowerBus, liveWiredTools));
|
|
253
260
|
if (session.activeWorkflow !== null) {
|
|
254
261
|
checkpoints.beginRun(resolvedRunId, session.activeWorkflow);
|
|
255
262
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type NodeId, type RunId, type RuntimeRunnerEvent } from '@langflower/runtime';
|
|
2
2
|
import { type WorkflowCheckpoint, type WorkflowCheckpointSummary, type WorkflowLoadedPayload } from '@langflower/shared/langflower.js';
|
|
3
3
|
import { WorkflowCheckpointStore } from './workflow-checkpoint-store.js';
|
|
4
4
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isPortTelemetry, } from '@langflower/runtime';
|
|
1
2
|
import { buildWorkflowFingerprint, toCheckpointJsonValue, } from '@langflower/shared/langflower.js';
|
|
2
3
|
import { summarizeCheckpoint, WorkflowCheckpointStore, } from './workflow-checkpoint-store.js';
|
|
3
4
|
/**
|
|
@@ -56,27 +57,27 @@ export class RunCheckpointSession {
|
|
|
56
57
|
* that should trigger an immediate persist.
|
|
57
58
|
*/
|
|
58
59
|
observe(event, boundary) {
|
|
59
|
-
if (this.active === undefined ||
|
|
60
|
+
if (this.active === undefined ||
|
|
61
|
+
!isPortTelemetry(event) ||
|
|
62
|
+
event[0] !== 'out') {
|
|
60
63
|
return false;
|
|
61
64
|
}
|
|
62
|
-
|
|
65
|
+
const [, nodeIdRaw, portId, state, value] = event;
|
|
66
|
+
if (state !== 'value' || typeof portId !== 'string') {
|
|
63
67
|
return false;
|
|
64
68
|
}
|
|
65
|
-
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
const jsonValue = toCheckpointJsonValue(event.value);
|
|
69
|
+
const jsonValue = toCheckpointJsonValue(value);
|
|
69
70
|
if (jsonValue === undefined) {
|
|
70
|
-
this.unsupportedValue = `${
|
|
71
|
+
this.unsupportedValue = `${String(nodeIdRaw)}.${portId}`;
|
|
71
72
|
return false;
|
|
72
73
|
}
|
|
73
|
-
const nodeId = String(
|
|
74
|
+
const nodeId = String(nodeIdRaw);
|
|
74
75
|
let ports = this.active.outputSnapshots.get(nodeId);
|
|
75
76
|
if (ports === undefined) {
|
|
76
77
|
ports = new Map();
|
|
77
78
|
this.active.outputSnapshots.set(nodeId, ports);
|
|
78
79
|
}
|
|
79
|
-
ports.set(
|
|
80
|
+
ports.set(portId, {
|
|
80
81
|
state: 'value',
|
|
81
82
|
value: jsonValue,
|
|
82
83
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CustomPaletteSnapshotPayload } from '@langflower/shared/langflower.js';
|
|
2
|
+
import type { LangflowerBridge } from '../bridge/langflower-bridge.types.js';
|
|
3
|
+
import type { ServerContext } from '../server-context.js';
|
|
4
|
+
import type { LangflowerSession } from '../session/langflower-session.js';
|
|
5
|
+
/**
|
|
6
|
+
* One composer for Custom → Update and `compile_custom_nodes` (via bus
|
|
7
|
+
* intent `customPalette.update.requested`): compile, registry, live swap,
|
|
8
|
+
* then palette snapshot (and deleteEdges if ports vanished).
|
|
9
|
+
*/
|
|
10
|
+
export declare const compileAndHotSwapCustomNodes: (session: LangflowerSession, context: ServerContext, bridge: LangflowerBridge) => Promise<CustomPaletteSnapshotPayload>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { swapCustomNodesInEditor } from '../workflow/apply-editor-mutation.js';
|
|
2
|
+
import { refreshLiveWiredToolPacks } from '../bridge/get-live-wired-tools.js';
|
|
3
|
+
import { bridgeEmit } from '../bridge/bridge-outbound.js';
|
|
4
|
+
/**
|
|
5
|
+
* One composer for Custom → Update and `compile_custom_nodes` (via bus
|
|
6
|
+
* intent `customPalette.update.requested`): compile, registry, live swap,
|
|
7
|
+
* then palette snapshot (and deleteEdges if ports vanished).
|
|
8
|
+
*/
|
|
9
|
+
export const compileAndHotSwapCustomNodes = async (session, context, bridge) => {
|
|
10
|
+
bridgeEmit(bridge, 'customPalette.snapshot', context.customPaletteService.compilingSnapshot());
|
|
11
|
+
const snapshot = await context.customPaletteService.update(context.projectDir);
|
|
12
|
+
const customTypes = new Set(snapshot.nodes.map((node) => node.type));
|
|
13
|
+
const droppedEdges = swapCustomNodesInEditor(session, context.projectDir, context.resolveDefinition, customTypes);
|
|
14
|
+
refreshLiveWiredToolPacks(session);
|
|
15
|
+
if (droppedEdges.length > 0) {
|
|
16
|
+
bridgeEmit(bridge, 'editor.deleteEdges', droppedEdges);
|
|
17
|
+
bridgeEmit(bridge, 'workflow.currentStatus.snapshot', {
|
|
18
|
+
status: session.currentStatus,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
bridgeEmit(bridge, 'customPalette.snapshot', snapshot);
|
|
22
|
+
return snapshot;
|
|
23
|
+
};
|
|
@@ -44,6 +44,11 @@ export declare const applyEditorRemoveEdge: (session: LangflowerSession, edgeId:
|
|
|
44
44
|
* Composer: snapshot → runtime remove → sync session topology from editor.
|
|
45
45
|
*/
|
|
46
46
|
export declare const applyEditorRemoveNode: (session: LangflowerSession, nodeId: NodeId) => WorkflowNodePersisted[];
|
|
47
|
+
/**
|
|
48
|
+
* Replace live editor instances whose persisted `type` is in `customTypes`.
|
|
49
|
+
* Types missing from the set keep the old instance. Allowed while locked.
|
|
50
|
+
*/
|
|
51
|
+
export declare const swapCustomNodesInEditor: (session: LangflowerSession, projectDir: string, resolveDefinition: ResolveNodeDefinition, customTypes: ReadonlySet<string>) => readonly RuntimeEdge[];
|
|
47
52
|
export type BindWorkflowResult = {
|
|
48
53
|
readonly ok: true;
|
|
49
54
|
readonly droppedNodeIds: readonly string[];
|
|
@@ -447,6 +447,38 @@ export const applyEditorRemoveNode = (session, nodeId) => {
|
|
|
447
447
|
syncActiveWorkflowTopologyFromEditor(session);
|
|
448
448
|
return nodeSnapshot !== undefined ? [nodeSnapshot] : [];
|
|
449
449
|
};
|
|
450
|
+
/**
|
|
451
|
+
* Replace live editor instances whose persisted `type` is in `customTypes`.
|
|
452
|
+
* Types missing from the set keep the old instance. Allowed while locked.
|
|
453
|
+
*/
|
|
454
|
+
export const swapCustomNodesInEditor = (session, projectDir, resolveDefinition, customTypes) => {
|
|
455
|
+
const active = session.activeWorkflow;
|
|
456
|
+
if (active === null) {
|
|
457
|
+
return [];
|
|
458
|
+
}
|
|
459
|
+
const persistedById = new Map(active.graph.nodes.map((node) => [node.id, node]));
|
|
460
|
+
const droppedEdges = [];
|
|
461
|
+
for (const runtimeNode of session.runtime.editor.getNodes()) {
|
|
462
|
+
const persisted = persistedById.get(runtimeNode.nodeId);
|
|
463
|
+
if (persisted === undefined || !customTypes.has(persisted.type)) {
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
const next = materializeRuntimeNode(projectDir, persisted, resolveDefinition);
|
|
467
|
+
if (next === undefined) {
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
const { nodeId: _nodeId, ...rest } = next;
|
|
471
|
+
const swapped = session.runtime.editor.swapNode(runtimeNode.nodeId, rest);
|
|
472
|
+
if (swapped === false) {
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
droppedEdges.push(...swapped.droppedEdges);
|
|
476
|
+
}
|
|
477
|
+
if (droppedEdges.length > 0) {
|
|
478
|
+
syncActiveWorkflowTopologyFromEditor(session);
|
|
479
|
+
}
|
|
480
|
+
return droppedEdges;
|
|
481
|
+
};
|
|
450
482
|
/**
|
|
451
483
|
* Load path: document → editor (activate/rename/rebind).
|
|
452
484
|
* Unsupported nodes and invalid edges are skipped (graceful degradation);
|
|
@@ -27,11 +27,15 @@ contract.
|
|
|
27
27
|
|
|
28
28
|
## Load custom nodes
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
Call **`compile_custom_nodes`** (no args) — on starter, Helper and Writer
|
|
31
|
+
already have it because **Langflower Tools** is wired — or, in the editor
|
|
32
|
+
Custom section, click **Update** (or reconnect). Same composer: typecheck
|
|
33
|
+
each pack (`tsc --noEmit` when `tsconfig.json` is present), esbuild-bundle
|
|
34
|
+
entries that passed, hot-swap live custom instances, refresh **Custom**.
|
|
35
|
+
Stop is not required for already-placed custom types. Already-wired custom
|
|
36
|
+
tools can be invoked later in the **same run**. New types are not auto-placed
|
|
37
|
+
or auto-wired mid-run. Failures write `COMPILATION_ERRORS.md` in the pack
|
|
38
|
+
without dropping other successful custom nodes.
|
|
35
39
|
|
|
36
40
|
## Gaps
|
|
37
41
|
|
|
@@ -199,9 +199,10 @@ even though Langflower bundles with esbuild for load.
|
|
|
199
199
|
2. `export default defineNode({ … })`, `defineToolRegistrations({ … })` for an
|
|
200
200
|
LLM `tools` pack, **or** `defineReactiveNode({ … })` when exclusive `ok` /
|
|
201
201
|
`fail` (or other silent-branch) ports are required.
|
|
202
|
-
3. Run `npm install` in the pack if
|
|
203
|
-
4.
|
|
204
|
-
appears under **Custom**.
|
|
202
|
+
3. Run `npm install` in the pack if author deps changed.
|
|
203
|
+
4. Call **`compile_custom_nodes`** (starter Helper / Writer) or Custom →
|
|
204
|
+
**Update**. The type appears under **Custom**. Already-placed instances
|
|
205
|
+
hot-swap (no Stop). Place **new** types on the canvas yourself.
|
|
205
206
|
|
|
206
207
|
## Second shareable pack
|
|
207
208
|
|
|
@@ -55,7 +55,17 @@
|
|
|
55
55
|
},
|
|
56
56
|
"options": {
|
|
57
57
|
"type": "object",
|
|
58
|
-
"additionalProperties": true
|
|
58
|
+
"additionalProperties": true,
|
|
59
|
+
"properties": {
|
|
60
|
+
"baseURL": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "OpenAI-compatible API base URL (e.g. https://api.openai.com/v1 or http://127.0.0.1:1234/v1)."
|
|
63
|
+
},
|
|
64
|
+
"apiKey": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"description": "API key or `{env:VAR_NAME}` placeholder. Resolved on the server only; omitted from WebSocket snapshots. Prefer `{env:…}` over literals on disk."
|
|
67
|
+
}
|
|
68
|
+
}
|
|
59
69
|
}
|
|
60
70
|
}
|
|
61
71
|
}
|
|
@@ -13,6 +13,10 @@ provider. They are past bootstrap; do not lead with CLI start or provider setup.
|
|
|
13
13
|
## Role and style
|
|
14
14
|
|
|
15
15
|
- Short, actionable steps. No long essays.
|
|
16
|
+
- On **starter**, **Langflower Tools** is wired to you and Writer — you
|
|
17
|
+
already have **`compile_custom_nodes`**. After pack file changes, **call
|
|
18
|
+
it** (no arguments). Do not send the user to Custom → **Update** as the
|
|
19
|
+
only path.
|
|
16
20
|
- Answer **only** from allowed fact sources: the **Companion docs** (via
|
|
17
21
|
`read` when relevant) and the **Knowledge base** below. If a fact is
|
|
18
22
|
missing, say **not in my facts** (or point at project use-case docs) —
|
|
@@ -35,8 +39,8 @@ Bootstrap and provider facts stay in the Knowledge base for when they ask.
|
|
|
35
39
|
Example opening:
|
|
36
40
|
|
|
37
41
|
> Glad you got Langflower running and a provider configured. I can explain what
|
|
38
|
-
> Langflower can do
|
|
39
|
-
> What do you want to build?
|
|
42
|
+
> Langflower can do, help you set up workflows and custom nodes, and compile
|
|
43
|
+
> packs from this chat (`compile_custom_nodes`). What do you want to build?
|
|
40
44
|
|
|
41
45
|
## Companion docs
|
|
42
46
|
|
|
@@ -141,23 +145,28 @@ do not say coding pipelines “don’t exist” or are unavailable.
|
|
|
141
145
|
|
|
142
146
|
### 7. Run lifecycle
|
|
143
147
|
|
|
144
|
-
| Mechanism | Meaning
|
|
145
|
-
| --------------------- |
|
|
146
|
-
| Hard Stop | Cancel; does **not** by itself create checkpoint Continue
|
|
147
|
-
| Soft Pause | Per-node Steer pause of the last feed agent; siblings keep working; Send / Resume continues that node
|
|
148
|
-
|
|
|
149
|
-
|
|
|
150
|
-
|
|
|
148
|
+
| Mechanism | Meaning |
|
|
149
|
+
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
150
|
+
| Hard Stop | Cancel; does **not** by itself create checkpoint Continue |
|
|
151
|
+
| Soft Pause | Per-node Steer pause of the last feed agent; siblings keep working; Send / Resume continues that node |
|
|
152
|
+
| Provider recovery | Idle: default **autokick** (abort, exponential backoff, full-store replay + kick). Dead-loop: abort + short `retryBaseDelayMs` wait (not idle backoff) + kick. 429/5xx/network: short transient budget, then autokick **wait** (no kick, no penalty). `'retry'` banner stays in the feed after reasoning/draft; does not open Steer. Off / cap exhausted → **Steer**. Auth/config stay fatal |
|
|
153
|
+
| Browser close | If `langflower start` stays up, run continues; reopen live or settled |
|
|
154
|
+
| Process kill / reboot | **Not** detachable resume |
|
|
155
|
+
| Checkpoint Continue | Needs explicit boundary (`common-checkpoint` / `createCheckpoint`); **no** every-node auto Continue |
|
|
151
156
|
|
|
152
157
|
These four are **not** the same thing.
|
|
153
158
|
|
|
154
159
|
### 8. Tools, permissions, MCP
|
|
155
160
|
|
|
156
161
|
- **Can:** Harness builtins + `permission.ask` Allow/Deny for those builtins.
|
|
157
|
-
Wired pack / MCP tools (including memory writes
|
|
158
|
-
the edge is consent. Write Allow does **not**
|
|
159
|
-
**McpHandle**s; system MCP starts only for ids
|
|
160
|
-
active workflow.
|
|
162
|
+
Wired pack / MCP tools (including memory writes and **Langflower Tools**)
|
|
163
|
+
do **not** ask — authoring the edge is consent. Write Allow does **not**
|
|
164
|
+
grant bash. Agents receive **McpHandle**s; system MCP starts only for ids
|
|
165
|
+
enabled on nodes in the active workflow.
|
|
166
|
+
- **Can:** `compile_custom_nodes` exists only when **Langflower Tools**
|
|
167
|
+
(`common-langflower-tools`) is wired into that agent’s `tools` port
|
|
168
|
+
(starter Helper / Writer). Same intent as Custom → **Update**. Recompile
|
|
169
|
+
is unsafe — not ambient on every agent.
|
|
161
170
|
- **Can:** First-run `langflower.jsonc` seeds `permission` allow-all (project
|
|
162
171
|
**floor**). Inspector **Tool permissions** table (`tool` / `deny` / `ask` /
|
|
163
172
|
`allow`) sets per-agent `toolPermissions` (cannot loosen past floor). Presets
|
|
@@ -217,17 +226,38 @@ When the user asks to “create a project wiki”, “build a knowledge base”,
|
|
|
217
226
|
### 11. Custom nodes
|
|
218
227
|
|
|
219
228
|
- **Can:** **TypeScript** via `@langflower/node-sdk` — first-class language;
|
|
220
|
-
`tsc` / IDE types act as compile-time validators
|
|
221
|
-
|
|
222
|
-
|
|
229
|
+
`tsc` / IDE types act as compile-time validators. After file changes call
|
|
230
|
+
**`compile_custom_nodes`** (no args) or Custom → **Update** — same
|
|
231
|
+
composer. On starter you already have the tool (Langflower Tools wired).
|
|
232
|
+
Stop is not required for already-placed custom types (hot-swap).
|
|
233
|
+
An already-wired custom tools pack can be invoked later in the **same run**
|
|
234
|
+
after compile. New types appear under **Custom**; Langflower does **not**
|
|
235
|
+
auto-place or auto-wire them mid-run.
|
|
236
|
+
Packs under `.langflower/nodes/<pack>/`; user runs `npm install` in the pack
|
|
237
|
+
when adding author deps. See `instructions.md` and `nodes/my-nodes/README.md`.
|
|
223
238
|
Nodes may **intentionally keep in-memory internal state across runs**
|
|
224
239
|
(Stop / done / Start) until the user loads another workflow or shuts down
|
|
225
240
|
Langflower — not the same as Checkpoint resume after process kill.
|
|
226
241
|
- **Cannot:** Plain JS as the authoring path, Go, Python, or other languages.
|
|
227
242
|
Server auto-install. Sandboxed arbitrary user-node execution as shipped.
|
|
228
|
-
|
|
229
|
-
Claim that every node always resets on Stop, or
|
|
230
|
-
survives process restart without Checkpoints.
|
|
243
|
+
Ambient compile without Langflower Tools wired. Canvas add/remove node or
|
|
244
|
+
edge tools (not shipped). Claim that every node always resets on Stop, or
|
|
245
|
+
that in-memory node state survives process restart without Checkpoints.
|
|
246
|
+
|
|
247
|
+
### 11a. Recipe — write / reload a custom node
|
|
248
|
+
|
|
249
|
+
When the user asks to add or change a custom node from this starter chat:
|
|
250
|
+
|
|
251
|
+
1. Spawn Writer (or edit `.langflower/nodes/<pack>/*.ts` yourself).
|
|
252
|
+
2. Call **`compile_custom_nodes`** (no args). Report `status` / `nodeTypes` /
|
|
253
|
+
`errors` from the tool text. Pack failures also write
|
|
254
|
+
`COMPILATION_ERRORS.md`.
|
|
255
|
+
3. **Already on the canvas** → live now, no Stop. **New type** → user places
|
|
256
|
+
it from Custom and wires it; this tool does not drop nodes on the canvas.
|
|
257
|
+
4. If a custom tools pack is already wired into this agent, you may call those
|
|
258
|
+
`toolId`s later in **this run** after compile.
|
|
259
|
+
|
|
260
|
+
Do **not** treat Custom → Update as the only reload path on starter.
|
|
231
261
|
|
|
232
262
|
### 12. Status vocabulary
|
|
233
263
|
|
|
@@ -57,11 +57,18 @@ Project product data for Langflower lives under **`.langflower/`**.
|
|
|
57
57
|
- **HITL loops** (Review Gate, feedback ports, composer Start/Send) are normal
|
|
58
58
|
**internal waiting state of nodes**, not a separate product “interrupt the
|
|
59
59
|
engine” mechanism.
|
|
60
|
-
- LLM provider idle
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
- LLM provider idle **aborts** the in-flight request, then default
|
|
61
|
+
**autokick** (exponential backoff, full stored messages + kick user
|
|
62
|
+
turn). Dead-loop aborts the same way but waits **`retryBaseDelayMs`**
|
|
63
|
+
(not idle backoff) before that replay. HTTP 429 / 5xx / network use the
|
|
64
|
+
short transient budget, then join the idle autokick wait **without** a
|
|
65
|
+
kick turn or penalty bump. `'retry'` notices on the `recovery` port stay
|
|
66
|
+
in the feed after reasoning/draft, tick locally on the visit tail, and
|
|
67
|
+
do **not** open Steer. Autokick off or a finite cap exhausted keep the
|
|
68
|
+
node alive for **Steer / Resume** (`'suspended'`).
|
|
69
|
+
Partial draft text is telemetry, not committed history.
|
|
70
|
+
Authentication/configuration failures are terminal. Generic reload of any
|
|
71
|
+
failed non-LLM node is not yet shipped.
|
|
65
72
|
- Also on the bus: runner start / resume / interrupt intents, `permission.ask`,
|
|
66
73
|
and related facts.
|
|
67
74
|
|
|
@@ -80,11 +87,17 @@ Project product data for Langflower lives under **`.langflower/`**.
|
|
|
80
87
|
## Extensibility
|
|
81
88
|
|
|
82
89
|
- Custom nodes use the same **`@langflower/node-sdk`** path as built-ins.
|
|
83
|
-
- **TypeScript** is first-class; `tsc` / IDE types act as compile-time gates
|
|
84
|
-
|
|
90
|
+
- **TypeScript** is first-class; `tsc` / IDE types act as compile-time gates.
|
|
91
|
+
After file changes call `compile_custom_nodes` (only if **Langflower
|
|
92
|
+
Tools** is wired — starter Helper / Writer already are) or Custom →
|
|
93
|
+
**Update**. Same composer: typecheck + bundle + hot-swap live custom
|
|
94
|
+
instances + refresh the Custom palette.
|
|
95
|
+
Stop is not required for already-placed custom types.
|
|
96
|
+
An already-wired custom tools pack can be invoked later in the same run
|
|
97
|
+
after compile. Do not auto-place or auto-wire a new type mid-run.
|
|
85
98
|
- Plain JS / Go / Python are not the authoring path. Sandboxed arbitrary
|
|
86
|
-
user-node execution
|
|
87
|
-
shipped
|
|
99
|
+
user-node execution is **not** shipped. Canvas add/remove node or edge
|
|
100
|
+
tools are **not** shipped (later rows on Langflower Tools).
|
|
88
101
|
|
|
89
102
|
## What stays local
|
|
90
103
|
|
|
@@ -17,21 +17,21 @@ Facts for UI chrome and on-disk paths. Prefer this file over guessing.
|
|
|
17
17
|
|
|
18
18
|
## Where can I…?
|
|
19
19
|
|
|
20
|
-
| Goal | Where
|
|
21
|
-
| -------------------------------------- |
|
|
22
|
-
| Change provider / API key | Gear → **Settings** (right aside; Global auto-opens when none configured), or edit `.langflower/langflower.jsonc` (prefer `{env:VAR}`)
|
|
23
|
-
| Start a Chat Input graph | Composer **Start** — not plain **Run** (Run stays disabled for those graphs)
|
|
24
|
-
| See run output / stream | Right aside **feed**
|
|
25
|
-
| Answer HITL / send into a waiting node | Composer + feed context
|
|
26
|
-
| Allow or Deny `permission.ask` | Composer permission controls
|
|
27
|
-
| Soft-pause last feed agent / continue | Composer **Pause** (per-node) / Send or Resume (soft pause ≠ Hard Stop)
|
|
28
|
-
| Hard-stop a run | Composer **Stop**
|
|
29
|
-
| Edit selected node params / ports | Select node → right aside **inspector** (not Settings)
|
|
30
|
-
| Add or reload custom nodes |
|
|
31
|
-
| Switch workflow | Topbar workflow list
|
|
32
|
-
| Open Settings without leaving canvas | Gear — Settings in right aside
|
|
33
|
-
| Find sample coding graphs | Skeleton / demo-project workflow files — **manual copy** into project, then load → Start. No Sample workflows catalog UI.
|
|
34
|
-
| Project instructions for agents | `.langflower/instructions.md`
|
|
20
|
+
| Goal | Where |
|
|
21
|
+
| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
22
|
+
| Change provider / API key | Gear → **Settings** (right aside; Global auto-opens when none configured), or edit `.langflower/langflower.jsonc` (prefer `{env:VAR}`) |
|
|
23
|
+
| Start a Chat Input graph | Composer **Start** — not plain **Run** (Run stays disabled for those graphs) |
|
|
24
|
+
| See run output / stream | Right aside **feed** |
|
|
25
|
+
| Answer HITL / send into a waiting node | Composer + feed context |
|
|
26
|
+
| Allow or Deny `permission.ask` | Composer permission controls |
|
|
27
|
+
| Soft-pause last feed agent / continue | Composer **Pause** (per-node) / Send or Resume (soft pause ≠ Hard Stop) |
|
|
28
|
+
| Hard-stop a run | Composer **Stop** |
|
|
29
|
+
| Edit selected node params / ports | Select node → right aside **inspector** (not Settings) |
|
|
30
|
+
| Add or reload custom nodes | Pack under `.langflower/nodes/<pack>/`. On starter, Helper / Writer call `compile_custom_nodes` (Langflower Tools is wired). Else Custom → **Update**. Hot-swap already-placed types; already-wired custom tools work later in the same run. New types: user places from Custom (no auto-place / auto-wire mid-run). |
|
|
31
|
+
| Switch workflow | Topbar workflow list |
|
|
32
|
+
| Open Settings without leaving canvas | Gear — Settings in right aside |
|
|
33
|
+
| Find sample coding graphs | Skeleton / demo-project workflow files — **manual copy** into project, then load → Start. No Sample workflows catalog UI. |
|
|
34
|
+
| Project instructions for agents | `.langflower/instructions.md` |
|
|
35
35
|
|
|
36
36
|
## On-disk `.langflower/` map
|
|
37
37
|
|
|
@@ -3,7 +3,7 @@ name: Langflower node writer
|
|
|
3
3
|
description: >-
|
|
4
4
|
Guides authors writing project custom nodes under .langflower/nodes packs
|
|
5
5
|
(defineNode / defineToolRegistrations / defineReactiveNode, ADR-030 layout,
|
|
6
|
-
reload via Custom Update).
|
|
6
|
+
reload via compile_custom_nodes or Custom Update).
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Langflower node writer
|
|
@@ -16,10 +16,14 @@ You help the user write **custom nodes** for Langflower.
|
|
|
16
16
|
language; `tsc` / IDE types are the compile-time validators. **Not** plain JS
|
|
17
17
|
as the authoring path, Go, Python, Rust, or other runtimes.
|
|
18
18
|
- Do **not** claim sandboxed execution of arbitrary user-node code is shipped.
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
`COMPILATION_ERRORS.md
|
|
19
|
+
- After file changes **call `compile_custom_nodes` yourself** (no args) — on
|
|
20
|
+
starter, Writer has it because **Langflower Tools** is wired. Custom →
|
|
21
|
+
**Update** is the same composer. Failures land in `COMPILATION_ERRORS.md`.
|
|
22
|
+
Do **not** only remind the user to click Update.
|
|
22
23
|
- Langflower does **not** auto-`npm install` pack dependencies.
|
|
24
|
+
- Do **not** claim you can place a newly compiled type on the canvas or wire
|
|
25
|
+
it mid-run. Already-placed types hot-swap; already-wired custom tools can
|
|
26
|
+
be invoked later in the **same run**.
|
|
23
27
|
|
|
24
28
|
## Contract (do not invent forks)
|
|
25
29
|
|
|
@@ -34,8 +38,12 @@ You help the user write **custom nodes** for Langflower.
|
|
|
34
38
|
Skip `*.test.ts`, `*.d.ts`, `dist/`, `node_modules/`.
|
|
35
39
|
- Peer deps on the host SDK / RxJS are supplied by Langflower; author libs go
|
|
36
40
|
in pack `dependencies`. The user runs `npm install` in the pack.
|
|
37
|
-
- After file changes:
|
|
38
|
-
|
|
41
|
+
- After file changes: call **`compile_custom_nodes`** (wired on starter
|
|
42
|
+
Helper / Writer via **Langflower Tools** — not ambient on every agent) or
|
|
43
|
+
Custom section → **Update**. Stop is not required for already-placed
|
|
44
|
+
custom types. An already-wired custom tools pack can be invoked later in
|
|
45
|
+
the **same run** after compile. Failures land in `COMPILATION_ERRORS.md`
|
|
46
|
+
in that pack.
|
|
39
47
|
|
|
40
48
|
## When drafting a node
|
|
41
49
|
|
|
@@ -44,9 +52,11 @@ You help the user write **custom nodes** for Langflower.
|
|
|
44
52
|
(`defineToolRegistrations` owns a `tools` output — no custom inputs).
|
|
45
53
|
3. Implement `execute` (`defineNode`), `tools` handlers
|
|
46
54
|
(`defineToolRegistrations`), or `bind` (`defineReactiveNode`).
|
|
47
|
-
4. Show the full file the user can paste into `my-nodes
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
4. Show the full file the user can paste into `my-nodes/` **or write it**
|
|
56
|
+
under `.langflower/nodes/<pack>/`.
|
|
57
|
+
5. Call **`compile_custom_nodes`**. If the snapshot lists errors, `read`
|
|
58
|
+
that pack’s `COMPILATION_ERRORS.md`, fix, and compile again. Tell the
|
|
59
|
+
user to place **new** types from Custom; already-placed types are live.
|
|
50
60
|
|
|
51
61
|
## References in the project
|
|
52
62
|
|