langflower 0.0.9 → 0.0.10
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 +2 -2
- package/ui-dist/index.html +2 -2
- package/ui-dist/main-Z7CPFXFA.js +313 -0
- package/ui-dist/styles-2TMDAUD7.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 +3 -10
- package/vendor/common-nodes/dist/ai/features/llm-session/llm-session-shell.js +9 -14
- 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/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 +5 -18
- 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 +3 -10
- 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 +2 -9
- package/vendor/common-nodes/dist/ai/nodes/review/node.d.ts +3 -3
- package/vendor/common-nodes/dist/ai/nodes/review/node.js +5 -18
- 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 +211 -96
- package/vendor/common-nodes/dist/catalog.js +2 -0
- package/vendor/common-nodes/dist/mcp/mcp-http/node.d.ts +4 -4
- package/vendor/common-nodes/dist/mcp/mcp-http/node.js +9 -10
- package/vendor/common-nodes/dist/mcp/mcp-stdio/node.d.ts +4 -4
- package/vendor/common-nodes/dist/mcp/mcp-stdio/node.js +9 -10
- 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 +42 -0
- package/vendor/common-nodes/package.json +1 -5
- package/vendor/compiler/package.json +1 -1
- 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 +3 -4
- package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.js +1 -1
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/types.d.ts +2 -4
- package/vendor/node-sdk/dist/node-factory/define-reactive-node/ui-schema-inference.d.ts +1 -1
- package/vendor/node-sdk/package.json +1 -1
- 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 +25 -8
- package/vendor/runtime/dist/types.js +3 -0
- package/vendor/runtime/package.json +1 -1
- package/vendor/server/dist/bridge/build-execution-context.js +3 -3
- 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/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/session/reset-session-execution-feed.d.ts +6 -0
- package/vendor/server/dist/session/reset-session-execution-feed.js +8 -0
- package/vendor/server/skeleton/nodes/my-nodes/package.json +1 -1
- package/vendor/server/skeleton/skills/langflower-helper/SKILL.md +36 -22
- package/vendor/server/skeleton/skills/langflower-helper/architecture.md +7 -1
- package/vendor/server/skeleton/skills/langflower-helper/layout.md +3 -2
- 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-navigate.json +8 -22
- 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-ws-waits.d.ts +3 -1
- package/vendor/shared/dist/langflower-ws-waits.js +2 -2
- package/ui-dist/main-2JJGCNTD.js +0 -313
- package/ui-dist/styles-EOXODOI7.css +0 -1
|
@@ -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;
|
|
@@ -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
|
+
};
|
|
@@ -116,7 +116,11 @@ do not say coding pipelines “don’t exist” or are unavailable.
|
|
|
116
116
|
- **Can:** Chat Input graphs start from the composer **Start** control. Plain
|
|
117
117
|
**Run** stays disabled for those graphs.
|
|
118
118
|
- **Can:** While running — Hard **Stop**, soft **Pause**, HITL and
|
|
119
|
-
`permission.ask` in the composer.
|
|
119
|
+
`permission.ask` in the composer. Work log **clears** on successful
|
|
120
|
+
workflow load / create / copy (not rename).
|
|
121
|
+
- **Cannot:** Switch, rename, delete, copy, or create a workflow while a run
|
|
122
|
+
is active — Stop first. Same lock: inspector / canvas inline / palette
|
|
123
|
+
drag (`cursor-not-allowed`).
|
|
120
124
|
- **Cannot:** Tell users to press plain **Run** to start a Chat Input graph.
|
|
121
125
|
- **Cannot:** Claim the feed after reload must be **richer** than live.
|
|
122
126
|
- **Cannot:** Claim `basic-coder` proves chat-dense mood for the full
|
|
@@ -132,16 +136,16 @@ do not say coding pipelines “don’t exist” or are unavailable.
|
|
|
132
136
|
|
|
133
137
|
### 6. Coding workflows
|
|
134
138
|
|
|
135
|
-
| Name | Fact
|
|
136
|
-
| -------------- |
|
|
137
|
-
| `starter` | Onboarding chat + this skill + Writer Sub-Agent (`langflower-workflow-writer` + `langflower-node-writer`) — default open after seed
|
|
138
|
-
| Skeleton stubs | `simple-coder`, `advanced-coder`, `kb-create`, `kb-navigate`, … seeded on first-run; with provider → Start
|
|
139
|
-
| `simple-coder` | Plan⇄HITL→Coder⇄HITL→Finish smoke spine + `common-memory-tools` on Plan/Coder/Researcher/Worker; Researcher Sub-Agent under Plan, Worker under Coder — **not** full multi-loop `coding-agent`
|
|
140
|
-
| `kb-create` | Memory / project wiki create: Orchestrator **indexes** the repo with `glob`/`read`, persists `history/work-queue.md`, then **serially**
|
|
141
|
-
| `kb-navigate` | Memory navigate: Navigator + Searcher + memory tree/grep/section tools; HITL Review Gate for follow-ups
|
|
142
|
-
| `basic-coder` | Basic coding harness (Plan⇄HITL→Coder⇄HITL→Finish) — not a toy, **not** full multi-loop `coding-agent`
|
|
143
|
-
| `coding-agent` | Clarify HITL → red team → plan gate → coder → QA → `common-review` → result HITL; **graph** orders stages
|
|
144
|
-
| Status | Use-case **Partial**; real-LLM Implementable bar open; Fake CI ≠ end-user proof — **not** “no templates”
|
|
139
|
+
| Name | Fact |
|
|
140
|
+
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
141
|
+
| `starter` | Onboarding chat + this skill + Writer Sub-Agent (`langflower-workflow-writer` + `langflower-node-writer`) — default open after seed |
|
|
142
|
+
| Skeleton stubs | `simple-coder`, `advanced-coder`, `kb-create`, `kb-navigate`, … seeded on first-run; with provider → Start |
|
|
143
|
+
| `simple-coder` | Plan⇄HITL→Coder⇄HITL→Finish smoke spine + `common-memory-tools` on Plan/Coder/Researcher/Worker; Researcher Sub-Agent under Plan, Worker under Coder — **not** full multi-loop `coding-agent` |
|
|
144
|
+
| `kb-create` | Memory / project wiki create: Orchestrator **indexes** the repo with `glob`/`read`, persists `history/work-queue.md`, then **serially** calls Explorer → Composer **one unit at a time**; `common-memory-tools` writes `core/*` + `modules/*`; Review rejects non-empty Pending or thin overviews |
|
|
145
|
+
| `kb-navigate` | Memory navigate: Navigator + Searcher + memory tree/grep/section tools; HITL Review Gate for follow-ups |
|
|
146
|
+
| `basic-coder` | Basic coding harness (Plan⇄HITL→Coder⇄HITL→Finish) — not a toy, **not** full multi-loop `coding-agent` |
|
|
147
|
+
| `coding-agent` | Clarify HITL → red team → plan gate → coder → QA → `common-review` → result HITL; **graph** orders stages |
|
|
148
|
+
| Status | Use-case **Partial**; real-LLM Implementable bar open; Fake CI ≠ end-user proof — **not** “no templates” |
|
|
145
149
|
|
|
146
150
|
### 7. Run lifecycle
|
|
147
151
|
|
|
@@ -161,8 +165,12 @@ These four are **not** the same thing.
|
|
|
161
165
|
- **Can:** Harness builtins + `permission.ask` Allow/Deny for those builtins.
|
|
162
166
|
Wired pack / MCP tools (including memory writes and **Langflower Tools**)
|
|
163
167
|
do **not** ask — authoring the edge is consent. Write Allow does **not**
|
|
164
|
-
grant bash.
|
|
165
|
-
|
|
168
|
+
grant bash. MCP **nodes** wire `tools` → agent `tools` (`ToolHandle[]`).
|
|
169
|
+
Optional **Tool collection** (`common-tool-collection`) can merge several
|
|
170
|
+
`tools` wires into one before the agent. Direct multi-wire into the agent
|
|
171
|
+
still works. System MCP from `langflower.jsonc` starts only for ids enabled
|
|
172
|
+
on nodes in the active workflow; those tools land on `EC.toolHandles`,
|
|
173
|
+
never as raw config.
|
|
166
174
|
- **Can:** `compile_custom_nodes` exists only when **Langflower Tools**
|
|
167
175
|
(`common-langflower-tools`) is wired into that agent’s `tools` port
|
|
168
176
|
(starter Helper / Writer). Same intent as Custom → **Update**. Recompile
|
|
@@ -180,16 +188,21 @@ These four are **not** the same thing.
|
|
|
180
188
|
### 9. Sub-Agent and swarm
|
|
181
189
|
|
|
182
190
|
Sub-Agent is an **explicit canvas node** for **control and observability**
|
|
183
|
-
(own toolLog/response, visible
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
-
|
|
187
|
-
|
|
188
|
-
|
|
191
|
+
(own toolLog/response, visible specialist) — not magic inside one LLM turn.
|
|
192
|
+
|
|
193
|
+
- **Can:** First-class Sub-Agent node. Wire Sub-Agent
|
|
194
|
+
`subagent-registration` → parent `tools` (one edge). The parent calls the
|
|
195
|
+
specialist tool (`Writer(subagent)` / `toolId` `Writer_subagent`) with a
|
|
196
|
+
`task`
|
|
197
|
+
(optional `skillId` from the Inspector Skills enum). That call closes the
|
|
198
|
+
parent work-log visit; the specialist streams as its own card. Default swarm
|
|
199
|
+
invokes are **serial**. Wiki/memory create (`kb-create`) uses **serial**
|
|
200
|
+
scoped specialist calls driven by a persisted work queue — not parallel
|
|
189
201
|
whole-repo fan-out.
|
|
190
202
|
- **Cannot / not yet:** Hide Sub-Agent work only inside a single LLM turn with
|
|
191
203
|
no graph node (anti-pattern). Parallel fan-out as the **default**. Nested
|
|
192
|
-
**workflow files** (far future).
|
|
204
|
+
**workflow files** (far future). Do not look for `spawn_subagent` or
|
|
205
|
+
registration / spawn / result ports — those wires are gone.
|
|
193
206
|
|
|
194
207
|
### 10. Other demos
|
|
195
208
|
|
|
@@ -218,7 +231,8 @@ When the user asks to “create a project wiki”, “build a knowledge base”,
|
|
|
218
231
|
→ Orchestrator (`common-openai-llm` + builtins `glob`/`read`/`grep` + wired
|
|
219
232
|
`common-memory-tools`) → Sub-Agents Explorer (read) + Composer (write) →
|
|
220
233
|
`common-review` with readiness criteria → Finish. Persist a work queue in
|
|
221
|
-
memory **before** deep survey;
|
|
234
|
+
memory **before** deep survey; call the Explorer / Composer specialist
|
|
235
|
+
tools **one unit at a time**.
|
|
222
236
|
- **Cannot:** Recommend one LLM that “reads the whole repo once and dumps a
|
|
223
237
|
wiki”. Claim vector/embedding KB as base. Claim Obsidian vault helpers as
|
|
224
238
|
shipped.
|
|
@@ -248,7 +262,7 @@ When the user asks to “create a project wiki”, “build a knowledge base”,
|
|
|
248
262
|
|
|
249
263
|
When the user asks to add or change a custom node from this starter chat:
|
|
250
264
|
|
|
251
|
-
1.
|
|
265
|
+
1. Call Writer (or edit `.langflower/nodes/<pack>/*.ts` yourself).
|
|
252
266
|
2. Call **`compile_custom_nodes`** (no args). Report `status` / `nodeTypes` /
|
|
253
267
|
`errors` from the tool text. Pack failures also write
|
|
254
268
|
`COMPILATION_ERRORS.md`.
|
|
@@ -76,7 +76,13 @@ Project product data for Langflower lives under **`.langflower/`**.
|
|
|
76
76
|
|
|
77
77
|
- LLM / agent nodes use **skills** and harness tools as wired in the graph.
|
|
78
78
|
- **Sub-Agent** is an **explicit canvas node** for control and observability
|
|
79
|
-
(own toolLog/response
|
|
79
|
+
(own toolLog/response). Wire `subagent-registration` into the parent
|
|
80
|
+
`tools` — not hidden work inside one LLM turn. The announced tool is
|
|
81
|
+
`{name}(subagent)` (`toolId` slug `Name_subagent`). Calling that tool closes
|
|
82
|
+
the parent work-log visit; the specialist streams as its own card, and
|
|
83
|
+
the parent continues in a new visit below. Optional **Tool collection**
|
|
84
|
+
(`common-tool-collection`) can merge several `tools` wires; direct
|
|
85
|
+
multi-wire into the agent still works.
|
|
80
86
|
- **Graph order** stages the pipeline; the model does not invent the stage
|
|
81
87
|
sequence outside the graph.
|
|
82
88
|
- Project memory / wiki create is **queue-driven**: index with harness `glob`,
|
|
@@ -26,9 +26,10 @@ Facts for UI chrome and on-disk paths. Prefer this file over guessing.
|
|
|
26
26
|
| Allow or Deny `permission.ask` | Composer permission controls |
|
|
27
27
|
| Soft-pause last feed agent / continue | Composer **Pause** (per-node) / Send or Resume (soft pause ≠ Hard Stop) |
|
|
28
28
|
| Hard-stop a run | Composer **Stop** |
|
|
29
|
-
| Edit selected node params / ports | Select node → right aside **inspector** (not Settings)
|
|
29
|
+
| Edit selected node params / ports | Select node → right aside **inspector** (not Settings). Read-only while a run is active — Stop first. |
|
|
30
|
+
| Add a node from the palette | Drag from the left palette onto the canvas. Disabled while a run is active (`cursor-not-allowed`) — Stop first. |
|
|
30
31
|
| 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
|
+
| Switch workflow | Topbar workflow list. Load / New / Copy / rename / Delete are locked while a run is active — Stop first. |
|
|
32
33
|
| Open Settings without leaving canvas | Gear — Settings in right aside |
|
|
33
34
|
| Find sample coding graphs | Skeleton / demo-project workflow files — **manual copy** into project, then load → Start. No Sample workflows catalog UI. |
|
|
34
35
|
| Project instructions for agents | `.langflower/instructions.md` |
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
name: Langflower workflow writer
|
|
3
3
|
description: >-
|
|
4
4
|
Guides authors writing and editing `.langflower/workflows/*.json` graphs
|
|
5
|
-
(catalog node types, real ports, Soft↔Hard loops, Sub-Agent
|
|
5
|
+
(catalog node types, real ports, Soft↔Hard loops, Sub-Agent
|
|
6
|
+
`subagent-registration` wiring).
|
|
6
7
|
---
|
|
7
8
|
|
|
8
9
|
# Langflower workflow writer
|
|
@@ -55,11 +56,13 @@ Schema: `.langflower/schemas/workflow.schema.json`. Samples:
|
|
|
55
56
|
| Node type | Key ports |
|
|
56
57
|
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
57
58
|
| `common-chat-input` | out `message` (no wireable in) |
|
|
58
|
-
| `common-openai-llm` / `common-fake-llm` | in `userPrompt`, `systemPrompt`, `feedback`, `
|
|
59
|
+
| `common-openai-llm` / `common-fake-llm` | in `userPrompt`, `systemPrompt`, `feedback`, `tools`; out `response`, `toolLog`, … |
|
|
60
|
+
| `common-mcp-stdio` / `common-mcp-http` | out **`tools`** — wire into an agent `tools` port (not a separate `mcp` port) |
|
|
61
|
+
| `common-tool-collection` | in **`tools`** (multi combine) → out **`tools`** — optional hub; duplicate `toolId` last-wins. Direct pack → agent still OK |
|
|
59
62
|
| `common-hitl-review-gate` | in `result`; out `response`, `feedback` |
|
|
60
63
|
| `common-merge` | in/out **`value`** only (not `step` / `output`) |
|
|
61
|
-
| `common-review` | in `task`, `result`, `systemPrompt`; out `response`, `feedback`
|
|
62
|
-
| `common-sub-agent` | out
|
|
64
|
+
| `common-review` | in `task`, `result`, `systemPrompt`, `tools`; out `response`, `feedback` |
|
|
65
|
+
| `common-sub-agent` | out **`subagent-registration`** (one specialist handle) → parent `tools`; in `systemPrompt`, `tools` |
|
|
63
66
|
| `common-finish` | in `value` |
|
|
64
67
|
| `common-string` | in/out `value` |
|
|
65
68
|
| `common-langflower-tools` | out **`tools`** only — wire into an agent `tools` port to opt in to **`compile_custom_nodes`** (unsafe; starter Helper / Writer already wired). Not ambient. Canvas add/remove node or edge tools are **not** shipped. |
|
|
@@ -75,13 +78,14 @@ Typical HITL revise loop:
|
|
|
75
78
|
Do **not** feed Merge output into both gates and LLM feedback on every tick
|
|
76
79
|
without a clear phase split.
|
|
77
80
|
|
|
78
|
-
## Sub-Agent
|
|
81
|
+
## Sub-Agent (one registration wire)
|
|
79
82
|
|
|
80
83
|
Mirror `.langflower/workflows/kb-navigate.json`:
|
|
81
84
|
|
|
82
|
-
- Sub-Agent `registration` → parent `
|
|
83
|
-
- Parent
|
|
84
|
-
-
|
|
85
|
+
- Sub-Agent `subagent-registration` → parent `tools`
|
|
86
|
+
- Parent calls the specialist tool (`task`, optional `skillId` enum)
|
|
87
|
+
- Do **not** draw `registration` / `subagent` / `task` / `result` /
|
|
88
|
+
`subagentResult` — those ports are gone
|
|
85
89
|
|
|
86
90
|
## Load repair (product fact)
|
|
87
91
|
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"maxFeedbackTurns": 8
|
|
61
61
|
},
|
|
62
62
|
"inputs": {
|
|
63
|
-
"systemPrompt": "You are the Orchestrator for building a DETAILED project memory map (project wiki) under `.langflower/memory/`.\n\nGoal: grounding a coding agent can use to implement features without rediscovering the repo. A thin whole-repo skim is NOT enough.\n\n## Required memory layout (all under `.langflower/memory/`)\n\n1) `core/overview.md` — purpose, primary user, ships vs not, how to run\n2) `core/layout.md` — directory / package map with ownership\n3) `core/architecture.md` — runtime flow, boundaries, key ADRs / invariants\n4) `core/build-test.md` — install, build, typecheck, unit vs integration, verify\n5) `core/entrypoints.md` — CLI / server / UI / MCP paths and ports\n6) `core/conventions.md` — coding rules agents must follow\n7) `modules/<area>.md` — one file per major package/area (responsibility, layout, contracts, neighbors, pitfalls)\n8) `history/work-queue.md` — indexed work units (Pending / In progress / Done)\n9) `history/build-log.md` — chronological survey/write notes (append_memory_log)\n\nOptional when material exists: `core/config.md`, `core/workflows-skills.md`.\n\n## Process (STRICT order — serial
|
|
63
|
+
"systemPrompt": "You are the Orchestrator for building a DETAILED project memory map (project wiki) under `.langflower/memory/`.\n\nGoal: grounding a coding agent can use to implement features without rediscovering the repo. A thin whole-repo skim is NOT enough.\n\n## Required memory layout (all under `.langflower/memory/`)\n\n1) `core/overview.md` — purpose, primary user, ships vs not, how to run\n2) `core/layout.md` — directory / package map with ownership\n3) `core/architecture.md` — runtime flow, boundaries, key ADRs / invariants\n4) `core/build-test.md` — install, build, typecheck, unit vs integration, verify\n5) `core/entrypoints.md` — CLI / server / UI / MCP paths and ports\n6) `core/conventions.md` — coding rules agents must follow\n7) `modules/<area>.md` — one file per major package/area (responsibility, layout, contracts, neighbors, pitfalls)\n8) `history/work-queue.md` — indexed work units (Pending / In progress / Done)\n9) `history/build-log.md` — chronological survey/write notes (append_memory_log)\n\nOptional when material exists: `core/config.md`, `core/workflows-skills.md`.\n\n## Process (STRICT order — serial specialist tool calls)\n\n### Phase A — Index first (before any deep Explorer/Composer spawn)\n\n1) Use `glob` + `read` on package.json workspaces, top-level dirs, README*, AGENTS.md, docs/** (or equivalents). List every workspace package / major area and each mandatory `core/*` topic.\n2) Persist `.langflower/memory/history/work-queue.md` via create_memory_file / update_memory_section with ## Pending, ## In progress, ## Done. Each Pending item: id, path(s) to survey, target memory file (`modules/<area>.md` or `core/<name>.md`), status.\n3) Do NOT call Explorer/Composer for a vague “survey the whole repo” after the queue exists.\n\n### Phase B — One-unit loop\n\n1) Pick ONE Pending unit → move to In progress in work-queue.md.\n2) Call the Explorer specialist tool with a task that names ONLY that unit (paths, expected depth, target memory file).\n3) Call the Composer specialist tool for ONLY that unit’s target file/sections (pass Explorer findings).\n4) Mark the unit Done; append_memory_log on history/build-log.md.\n5) Repeat until Pending is empty (or explicit justified skips with evidence in the queue).\n\n### Phase C — Exit / Review feedback\n\n- Emit readiness only when Pending is empty AND mandatory files have real ## sections with concrete paths/commands/types.\n- Module pages MUST cover every indexed package/area from the queue.\n- On Review feedback: re-open specific queue items — do not restart a vague whole-repo pass.\n- Cite evidence (paths + section headings) in the readiness report."
|
|
64
64
|
},
|
|
65
65
|
"ui": {
|
|
66
66
|
"position": {
|
|
@@ -212,48 +212,6 @@
|
|
|
212
212
|
"toNodeId": "review",
|
|
213
213
|
"toPort": ["tools", 0]
|
|
214
214
|
},
|
|
215
|
-
{
|
|
216
|
-
"edgeId": "e-reg-explorer",
|
|
217
|
-
"fromNodeId": "explorer",
|
|
218
|
-
"fromPort": ["registration", 0],
|
|
219
|
-
"toNodeId": "orchestrator",
|
|
220
|
-
"toPort": ["subagentRegistration", 0]
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
"edgeId": "e-reg-composer",
|
|
224
|
-
"fromNodeId": "composer",
|
|
225
|
-
"fromPort": ["registration", 0],
|
|
226
|
-
"toNodeId": "orchestrator",
|
|
227
|
-
"toPort": ["subagentRegistration", 1]
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
"edgeId": "e-spawn-explorer",
|
|
231
|
-
"fromNodeId": "orchestrator",
|
|
232
|
-
"fromPort": ["subagent", 0],
|
|
233
|
-
"toNodeId": "explorer",
|
|
234
|
-
"toPort": ["task", 0]
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
"edgeId": "e-spawn-composer",
|
|
238
|
-
"fromNodeId": "orchestrator",
|
|
239
|
-
"fromPort": ["subagent", 0],
|
|
240
|
-
"toNodeId": "composer",
|
|
241
|
-
"toPort": ["task", 0]
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
"edgeId": "e-result-explorer",
|
|
245
|
-
"fromNodeId": "explorer",
|
|
246
|
-
"fromPort": ["result", 0],
|
|
247
|
-
"toNodeId": "orchestrator",
|
|
248
|
-
"toPort": ["subagentResult", 0]
|
|
249
|
-
},
|
|
250
|
-
{
|
|
251
|
-
"edgeId": "e-result-composer",
|
|
252
|
-
"fromNodeId": "composer",
|
|
253
|
-
"fromPort": ["result", 0],
|
|
254
|
-
"toNodeId": "orchestrator",
|
|
255
|
-
"toPort": ["subagentResult", 1]
|
|
256
|
-
},
|
|
257
215
|
{
|
|
258
216
|
"edgeId": "e-orch-review-result",
|
|
259
217
|
"fromNodeId": "orchestrator",
|
|
@@ -281,6 +239,20 @@
|
|
|
281
239
|
"fromPort": ["response", 0],
|
|
282
240
|
"toNodeId": "done",
|
|
283
241
|
"toPort": ["value", 0]
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"edgeId": "e-tools-explorer",
|
|
245
|
+
"fromNodeId": "explorer",
|
|
246
|
+
"fromPort": ["subagent-registration", 0],
|
|
247
|
+
"toNodeId": "orchestrator",
|
|
248
|
+
"toPort": ["tools", 1]
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"edgeId": "e-tools-composer",
|
|
252
|
+
"fromNodeId": "composer",
|
|
253
|
+
"fromPort": ["subagent-registration", 0],
|
|
254
|
+
"toNodeId": "orchestrator",
|
|
255
|
+
"toPort": ["tools", 2]
|
|
284
256
|
}
|
|
285
257
|
]
|
|
286
258
|
}
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"maxFeedbackTurns": 6
|
|
54
54
|
},
|
|
55
55
|
"inputs": {
|
|
56
|
-
"systemPrompt": "You answer questions about this project grounded in project memory.\n\nConvention: markdown under `.langflower/memory/` (built by the kb-create / Memory create workflow). Memory is also readable with harness file tools on `.langflower/memory/…`.\n\nBefore answering, use get_memory_tree / search_memory_grep / read_memory_section (yourself or via
|
|
56
|
+
"systemPrompt": "You answer questions about this project grounded in project memory.\n\nConvention: markdown under `.langflower/memory/` (built by the kb-create / Memory create workflow). Memory is also readable with harness file tools on `.langflower/memory/…`.\n\nBefore answering, use get_memory_tree / search_memory_grep / read_memory_section (yourself or via the Searcher specialist tool). Prefer memory hits over guessing. If memory is empty or hits are weak, say so and offer to run Memory create (kb-create) — do not invent.\n\nWhen HITL feedback arrives, revise the answer — do not ignore it. Keep answers short and cite memory file paths / headings when available."
|
|
57
57
|
},
|
|
58
58
|
"ui": {
|
|
59
59
|
"position": {
|
|
@@ -125,27 +125,6 @@
|
|
|
125
125
|
"toNodeId": "searcher",
|
|
126
126
|
"toPort": ["tools", 0]
|
|
127
127
|
},
|
|
128
|
-
{
|
|
129
|
-
"edgeId": "e-reg-searcher",
|
|
130
|
-
"fromNodeId": "searcher",
|
|
131
|
-
"fromPort": ["registration", 0],
|
|
132
|
-
"toNodeId": "navigator",
|
|
133
|
-
"toPort": ["subagentRegistration", 0]
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
"edgeId": "e-spawn-searcher",
|
|
137
|
-
"fromNodeId": "navigator",
|
|
138
|
-
"fromPort": ["subagent", 0],
|
|
139
|
-
"toNodeId": "searcher",
|
|
140
|
-
"toPort": ["task", 0]
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
"edgeId": "e-result-searcher",
|
|
144
|
-
"fromNodeId": "searcher",
|
|
145
|
-
"fromPort": ["result", 0],
|
|
146
|
-
"toNodeId": "navigator",
|
|
147
|
-
"toPort": ["subagentResult", 0]
|
|
148
|
-
},
|
|
149
128
|
{
|
|
150
129
|
"edgeId": "e-nav-review",
|
|
151
130
|
"fromNodeId": "navigator",
|
|
@@ -159,6 +138,13 @@
|
|
|
159
138
|
"fromPort": ["feedback", 0],
|
|
160
139
|
"toNodeId": "navigator",
|
|
161
140
|
"toPort": ["feedback", 0]
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"edgeId": "e-tools-searcher",
|
|
144
|
+
"fromNodeId": "searcher",
|
|
145
|
+
"fromPort": ["subagent-registration", 0],
|
|
146
|
+
"toNodeId": "navigator",
|
|
147
|
+
"toPort": ["tools", 1]
|
|
162
148
|
}
|
|
163
149
|
]
|
|
164
150
|
}
|