langflower 0.1.2 → 0.2.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.
Files changed (124) hide show
  1. package/README.md +573 -114
  2. package/dist/{chunk-WV2YWHOC.js → chunk-26UB55E5.js} +44 -4
  3. package/dist/{chunk-AO33IM2J.js → chunk-2LE3E2QP.js} +24 -23
  4. package/dist/{chunk-NIRPHJLO.js → chunk-3Z7Q6SQ5.js} +501 -242
  5. package/dist/{chunk-CVTPGIZE.js → chunk-RZUZX6PW.js} +2 -4
  6. package/dist/index.js +41152 -41395
  7. package/docs/public/README.md +1 -0
  8. package/docs/public/extending.md +21 -3
  9. package/docs/public/getting-started.md +9 -1
  10. package/docs/public/how-it-works.md +2 -2
  11. package/docs/public/launcher.md +111 -0
  12. package/package.json +1 -1
  13. package/ui-dist/apple-touch-icon.png +0 -0
  14. package/ui-dist/{chunk-EZTB7Q33.js → chunk-HEF6F5HN.js} +3 -3
  15. package/ui-dist/{chunk-BKIP5WRK.js → chunk-IASSR2ON.js} +1 -1
  16. package/ui-dist/favicon-32x32.png +0 -0
  17. package/ui-dist/favicon.ico +0 -0
  18. package/ui-dist/index.html +5 -2
  19. package/ui-dist/main-NBS6BFBP.js +323 -0
  20. package/ui-dist/styles-M2URERWI.css +1 -0
  21. package/vendor/node-sdk/dist/node-factory/define-llm-node/default-llm-ports.js +1 -1
  22. package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.d.ts +9 -21
  23. package/vendor/node-sdk/dist/node-factory/define-llm-node/define-llm-node.js +9 -3
  24. package/vendor/node-sdk/dist/node-factory/define-llm-node/recovery-notice.d.ts +0 -1
  25. package/vendor/node-sdk/dist/node-factory/define-llm-node/recovery-notice.js +0 -9
  26. package/vendor/node-sdk/dist/node-factory/define-node/define-node.d.ts +5 -1
  27. package/vendor/node-sdk/dist/node-factory/define-node/define-node.js +6 -3
  28. package/vendor/node-sdk/dist/node-factory/define-reactive-node/capabilities.d.ts +128 -0
  29. package/vendor/node-sdk/dist/node-factory/define-reactive-node/capabilities.js +25 -0
  30. package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-reactive-node.d.ts +29 -17
  31. package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-reactive-node.js +14 -6
  32. package/vendor/node-sdk/dist/node-factory/define-reactive-node/io-helpers.d.ts +19 -5
  33. package/vendor/node-sdk/dist/node-factory/define-reactive-node/io-helpers.js +4 -3
  34. package/vendor/node-sdk/dist/node-factory/define-reactive-node/port-meta.d.ts +6 -1
  35. package/vendor/node-sdk/dist/node-factory/define-reactive-node/types.d.ts +40 -22
  36. package/vendor/node-sdk/dist/node-factory/define-reactive-node/types.js +2 -0
  37. package/vendor/node-sdk/dist/node-factory/define-reactive-node/ui-schema-inference.d.ts +1 -1
  38. package/vendor/node-sdk/dist/node-factory/define-tool-registrations/define-tool-registrations.d.ts +13 -25
  39. package/vendor/node-sdk/dist/node-factory/define-tool-registrations/define-tool-registrations.js +9 -8
  40. package/vendor/node-sdk/dist/testing/create-node-harness.d.ts +9 -2
  41. package/vendor/node-sdk/dist/testing/create-node-harness.js +6 -2
  42. package/vendor/node-sdk/package.json +5 -0
  43. package/vendor/runtime/dist/bypass-ports.d.ts +0 -6
  44. package/vendor/runtime/dist/bypass-ports.js +0 -7
  45. package/vendor/runtime/dist/runtime-editor.d.ts +1 -1
  46. package/vendor/runtime/dist/runtime-editor.js +1 -1
  47. package/vendor/runtime/dist/runtime-helpers.d.ts +0 -1
  48. package/vendor/runtime/dist/runtime-helpers.js +0 -33
  49. package/vendor/runtime/dist/runtime-runner.d.ts +4 -0
  50. package/vendor/runtime/dist/runtime-runner.js +60 -36
  51. package/vendor/runtime/dist/runtime.d.ts +0 -1
  52. package/vendor/runtime/dist/runtime.js +0 -1
  53. package/vendor/runtime/dist/types.d.ts +27 -17
  54. package/vendor/server/skeleton/instructions.md +6 -0
  55. package/vendor/server/skeleton/nodes/my-nodes/README.md +19 -1
  56. package/vendor/server/skeleton/schemas/langflower-config.schema.json +1 -1
  57. package/vendor/server/skeleton/skills/langflower-helper/SKILL.md +44 -10
  58. package/vendor/server/skeleton/skills/langflower-helper/architecture.md +4 -1
  59. package/vendor/server/skeleton/skills/langflower-helper/layout.md +6 -4
  60. package/vendor/server/skeleton/skills/langflower-node-writer/SKILL.md +47 -3
  61. package/vendor/server/skeleton/skills/langflower-workflow-writer/SKILL.md +29 -17
  62. package/vendor/server/skeleton/workflows/advanced-coder.json +24 -2
  63. package/vendor/server/skeleton/workflows/kb-create.json +24 -16
  64. package/vendor/server/skeleton/workflows/kb-manual-search.json +1 -1
  65. package/vendor/server/skeleton/workflows/kb-navigate.json +24 -2
  66. package/vendor/server/skeleton/workflows/kb-rag.json +1 -0
  67. package/vendor/server/skeleton/workflows/simple-coder.json +3 -0
  68. package/vendor/server/skeleton/workflows/starter.json +2 -0
  69. package/ui-dist/main-JJURZFKA.js +0 -318
  70. package/ui-dist/styles-VA3HMZK7.css +0 -1
  71. package/vendor/node-sdk/dist/node-factory/define-llm-node/llm-inventory-wire.d.ts +0 -5
  72. package/vendor/node-sdk/dist/node-factory/define-llm-node/llm-inventory-wire.js +0 -5
  73. package/vendor/node-sdk/dist/node-factory/define-llm-node/llm.d.ts +0 -3
  74. package/vendor/node-sdk/dist/node-factory/define-llm-node/llm.js +0 -2
  75. package/vendor/node-sdk/dist/node-factory/define-mcp/define-mcp.d.ts +0 -50
  76. package/vendor/node-sdk/dist/node-factory/define-mcp/define-mcp.js +0 -60
  77. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.d.ts +0 -15
  78. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-handle.js +0 -2
  79. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-server-config.d.ts +0 -17
  80. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-server-config.js +0 -2
  81. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-transport.d.ts +0 -20
  82. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp-transport.js +0 -2
  83. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp.d.ts +0 -3
  84. package/vendor/node-sdk/dist/node-factory/define-mcp/mcp.js +0 -2
  85. package/vendor/node-sdk/dist/node-factory/define-node/test/samples/gate-node.d.ts +0 -20
  86. package/vendor/node-sdk/dist/node-factory/define-node/test/samples/gate-node.js +0 -22
  87. package/vendor/node-sdk/dist/node-factory/define-reactive-node/chat-completion-stream.d.ts +0 -50
  88. package/vendor/node-sdk/dist/node-factory/define-reactive-node/chat-completion-stream.js +0 -2
  89. package/vendor/node-sdk/dist/node-factory/define-reactive-node/crawl-context.d.ts +0 -22
  90. package/vendor/node-sdk/dist/node-factory/define-reactive-node/crawl-context.js +0 -2
  91. package/vendor/node-sdk/dist/node-factory/define-reactive-node/create-embedding.d.ts +0 -6
  92. package/vendor/node-sdk/dist/node-factory/define-reactive-node/create-embedding.js +0 -2
  93. package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-tool-registrations.d.ts +0 -52
  94. package/vendor/node-sdk/dist/node-factory/define-reactive-node/define-tool-registrations.js +0 -52
  95. package/vendor/node-sdk/dist/node-factory/define-reactive-node/kb-context.d.ts +0 -111
  96. package/vendor/node-sdk/dist/node-factory/define-reactive-node/kb-context.js +0 -2
  97. package/vendor/node-sdk/dist/node-factory/define-reactive-node/memory-context.d.ts +0 -12
  98. package/vendor/node-sdk/dist/node-factory/define-reactive-node/memory-context.js +0 -2
  99. package/vendor/node-sdk/dist/node-factory/define-reactive-node/project-files-context.d.ts +0 -10
  100. package/vendor/node-sdk/dist/node-factory/define-reactive-node/project-files-context.js +0 -2
  101. package/vendor/node-sdk/dist/node-factory/define-reactive-node/project-harness.d.ts +0 -56
  102. package/vendor/node-sdk/dist/node-factory/define-reactive-node/project-harness.js +0 -2
  103. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/agent-node.d.ts +0 -29
  104. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/agent-node.js +0 -60
  105. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/combine-node.d.ts +0 -29
  106. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/combine-node.js +0 -26
  107. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/constant-node.d.ts +0 -29
  108. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/constant-node.js +0 -21
  109. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/delay-node.d.ts +0 -29
  110. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/delay-node.js +0 -27
  111. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/finish-node.d.ts +0 -17
  112. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/finish-node.js +0 -21
  113. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/hitl-node.d.ts +0 -21
  114. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/hitl-node.js +0 -43
  115. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/join-node.d.ts +0 -29
  116. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/join-node.js +0 -31
  117. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/preview-node.d.ts +0 -17
  118. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/preview-node.js +0 -19
  119. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/router-node.d.ts +0 -18
  120. package/vendor/node-sdk/dist/node-factory/define-reactive-node/test/samples/router-node.js +0 -12
  121. package/vendor/node-sdk/dist/node-factory/define-reactive-node/tool-registration.d.ts +0 -36
  122. package/vendor/node-sdk/dist/node-factory/define-reactive-node/tool-registration.js +0 -2
  123. package/vendor/node-sdk/dist/node-factory/define-tool-registrations/tool-registration.d.ts +0 -46
  124. package/vendor/node-sdk/dist/node-factory/define-tool-registrations/tool-registration.js +0 -2
@@ -19,6 +19,11 @@ export type RuntimeFeedPortMeta = {
19
19
  readonly role?: RuntimeFeedRole;
20
20
  /** When true, feed visit stays open for chunks / interleaved streams. */
21
21
  readonly streaming?: boolean;
22
+ /**
23
+ * Stamped on every frame of a {@link RuntimeNode.feedVisitBoundary} node
24
+ * so the work log can close the caller visit without a palette lookup.
25
+ */
26
+ readonly closesPreviousVisit?: true;
22
27
  };
23
28
  /**
24
29
  * Typed metadata attached to every `statefulConnection` / `statefulObservable`
@@ -51,7 +56,7 @@ export type PortMeta = {
51
56
  */
52
57
  export type MetaFromStatefulObservable<T extends StatefulObservable<unknown, unknown, unknown>> = T extends StatefulObservable<unknown, unknown, infer Meta> ? Meta : never;
53
58
  /**
54
- * v2 runtime contracts — **execution only**.
59
+ * Runtime contracts — **execution only**.
55
60
  *
56
61
  * Responsibilities of `@langflower/runtime` (this module):
57
62
  * - Wire node ports and run reactive handlers (StatefulObservable graph).
@@ -60,9 +65,8 @@ export type MetaFromStatefulObservable<T extends StatefulObservable<unknown, unk
60
65
  * and `@langflower/server` on purpose — each layer must fail fast without
61
66
  * depending on the others.
62
67
  *
63
- * **Out of scope** (handled by `@langflower/server` or later phases):
64
- * - `WorkflowGraph` → {@link RuntimeNode} factory (isolated runtime first)
65
- * - `defineNode` / sync lift adapters
68
+ * **Out of scope** (owned by `@langflower/server` / UI / tools):
69
+ * - Persisted `WorkflowGraph` load/save (server hydrates {@link RuntimeFacade.editor})
66
70
  * - HITL / chat semantics — server marks which ports are HITL and maps
67
71
  * {@link RuntimeRunnerEvent} (+ user replies as seed) to chat / WS protocol
68
72
  * - runId persistence, harness, LLM, filesystem
@@ -70,8 +74,9 @@ export type MetaFromStatefulObservable<T extends StatefulObservable<unknown, unk
70
74
  * **Server telemetry:** subscribe to {@link RuntimeRunner.events$} and
71
75
  * translate frames to WebSocket; runtime does not speak WS.
72
76
  *
73
- * Phase 1 builds an **isolated runtime** — nodes wired manually in tests,
74
- * no Langflower workflow loader yet.
77
+ * Isolated unit tests still wire {@link RuntimeNode} instances by hand.
78
+ * Production server hydrates {@link RuntimeFacade.editor} from the workflow
79
+ * graph. There is no separate `WorkflowRuntime` / Phase-1-only loader.
75
80
  *
76
81
  * ## Status lifecycle
77
82
  * - {@link RuntimeRunner.start} / {@link RuntimeRunner.startNode} → `'running'`
@@ -113,7 +118,8 @@ export type MetaFromStatefulObservable<T extends StatefulObservable<unknown, unk
113
118
  * ## Input vs output ports
114
119
  * `inputs` expose {@link StatefulConnection} — runtime wires edges with
115
120
  * `connect(source)` on {@link RuntimeRunner.start} and `disconnect()` on
116
- * {@link RuntimeRunner.interrupt}. Seeds use `connect(of(value))` on open slots.
121
+ * {@link RuntimeRunner.interrupt}. Seeds use `connect(of(value))` on open slots,
122
+ * or `connect(value)` when `value` is already an Observable.
117
123
  * `outputs` expose {@link StatefulObservable} (read side) for telemetry and
118
124
  * optional {@link RuntimeNode.stopsRun} completion.
119
125
  */
@@ -153,7 +159,10 @@ export declare const isPortPendingTelemetry: (event: RuntimeRunnerEvent) => even
153
159
  };
154
160
  };
155
161
  export declare const isRuntimeDone: (event: RuntimeRunnerEvent) => event is RuntimeDoneTelemetry;
156
- /** Seed value pushed into an input port slot on {@link RuntimeRunner.start}. */
162
+ /**
163
+ * Seed value pushed into an input port slot on {@link RuntimeRunner.start}.
164
+ * Plain values are wrapped in `of`; Observables are connected as the stream.
165
+ */
157
166
  export type RuntimeSeedPortValue = {
158
167
  readonly portId: string | symbol;
159
168
  /** Multi-input slot index (`0` for single-slot ports). */
@@ -183,7 +192,7 @@ export type RuntimeNode = {
183
192
  *
184
193
  * On run start the runner calls `connect(upstreamOutput)` per edge; on
185
194
  * interrupt it calls `disconnect()`. Open slots may be seeded with
186
- * `connect(of(value))`.
195
+ * `connect(of(value))`, or `connect(value)` when `value` is an Observable.
187
196
  *
188
197
  * Port metadata lives on `connection.meta` as {@link PortMeta}.
189
198
  */
@@ -224,17 +233,18 @@ export type RuntimeNode = {
224
233
  * {@link RuntimeRunnerApi.pushIntoInput} (composer) instead.
225
234
  */
226
235
  readonly chatEntry?: boolean;
236
+ /**
237
+ * When `true`, every port frame from this node (including errors on
238
+ * role-less ports) carries {@link RuntimeFeedPortMeta.closesPreviousVisit}
239
+ * so the work log opens a new visit card.
240
+ */
241
+ readonly feedVisitBoundary?: boolean;
227
242
  /**
228
243
  * Declares handler contract: at most one output value per input
229
244
  * activation (e.g. constant, delay). Runtime does not enforce this —
230
245
  * metadata for factories and tests.
231
246
  */
232
247
  readonly emitOncePerActivation?: boolean;
233
- /**
234
- * Seeded snapshot node — emits cached outputs without re-execution.
235
- * Server skips running/completed telemetry for these nodes.
236
- */
237
- readonly skipExecutionTelemetry?: boolean;
238
248
  };
239
249
  export type RuntimeEdge = {
240
250
  readonly edgeId: EdgeId;
@@ -317,8 +327,8 @@ export type RuntimeEditorApi = {
317
327
  };
318
328
  /** Ready-to-use calculated graph clusters. Recalculated after graph edits. */
319
329
  allClusters: readonly GraphCluster[];
320
- /** Resolve the ready cluster containing `nodeId`. */
321
- getClusterByNodeId(nodeId: NodeId): GraphCluster;
330
+ /** Resolve the ready cluster containing `nodeId`, or `false` if missing. */
331
+ getClusterByNodeId(nodeId: NodeId): GraphCluster | false;
322
332
  };
323
333
  export type RuntimeRunnerApi = {
324
334
  /**
@@ -348,7 +358,7 @@ export type RuntimeRunnerApi = {
348
358
  * Run stays `'running'` until {@link RuntimeRunnerApi.interrupt} or a
349
359
  * {@link RuntimeNode.stopsRun} node in scope emits.
350
360
  *
351
- * Throws if status is already `'running'`.
361
+ * Returns `false` if status is already `'running'` or `nodeId` is missing.
352
362
  *
353
363
  * Flow: `RuntimeEditorApi.getClusterByNodeId(nodeId)` -> internal runner
354
364
  * `runScope` (cluster node/edge sets).
@@ -13,6 +13,12 @@ Each `*.ts` file may `export default` a definition or an array. No required
13
13
  Langflower does **not** auto-install on start, bootstrap, or palette reload.
14
14
  Startup **does** compile packs under `.langflower/nodes/`.
15
15
 
16
+ Port OpenCode / CLI `.mjs` tools into pack TypeScript (`defineToolRegistrations`)
17
+ and compile — do **not** spawn `node` on a leftover sidecar (that breaks when
18
+ the pack is copied). **Do** wrap named scripts from the project root or a
19
+ monorepo workspace `package.json` as tools (`npm run <script>`, allowlisted
20
+ literal, no `start` / `dev` / watch) so the agent does not need bash.
21
+
16
22
  If pack files `import` each other with a **`.ts` suffix**, set
17
23
  `"allowImportingTsExtensions": true` next to `"noEmit": true` in the pack
18
24
  `tsconfig.json` (hello-embed seed). Without it the pack does not compile.
@@ -28,8 +28,9 @@ its own `package.json`.
28
28
  Rules:
29
29
 
30
30
  - **One pack = one folder** with its own `package.json`.
31
- - **No required `index.ts`.** Each `*.ts` / `*.tsx` may `export default` a node
31
+ - **No required `index.ts`.** Each `*.ts` may `export default` a node
32
32
  definition or an array of definitions. Langflower discovers those defaults.
33
+ Custom nodes are not React — do not author `.tsx`.
33
34
  - Skip `*.test.ts`, `*.d.ts`, `dist/`, and `node_modules/` when scanning.
34
35
  - Import from **`@langflower/node-sdk`** directly — not from a root
35
36
  `nodes/types.ts`.
@@ -127,6 +128,23 @@ model calls `git_diff` on demand (optional `path` scopes the diff). Prefer this
127
128
  over `defineNode` when the value should be inventory for the tool loop, not a
128
129
  graph wire.
129
130
 
131
+ ### Common mistake: wrapping a `.mjs` CLI instead of compiling TypeScript
132
+
133
+ **Wrong:** keep `tool.mjs` and have `handler` spawn `node path/to/tool.mjs`
134
+ (`__dirname`, `import.meta.url`, or a hardcoded path). Only `*.ts` is a pack
135
+ entry. Copying the pack without that sidecar breaks the tool.
136
+
137
+ **Right:** port the script into TypeScript in this pack (helpers in `lib/` with
138
+ `from './lib/x.ts'` plus `allowImportingTsExtensions` if needed) so compile
139
+ bundles it. The original `.mjs` is not a runtime dependency of the node.
140
+
141
+ **Exception:** wrap named scripts from the **project root** or a **monorepo
142
+ workspace** `package.json` as tools (`npm run <script>`, allowlisted literal,
143
+ `cwd` under `ctx.projectDir`). Prefer that over granting bash. Do not register
144
+ hanging scripts (`start`, `dev`, `test:watch`). Seed `review-gate.ts` wraps
145
+ `npm run test` this way. Host `git` via `child_process` is also OK
146
+ (`git-diff-tool.ts`).
147
+
130
148
  ### Common mistake: `defineNode` for `ok` / `fail` gates
131
149
 
132
150
  **Wrong:** a review / QA gate with `defineNode` that returns `{ ok: true }` or
@@ -97,7 +97,7 @@
97
97
  },
98
98
  "permission": {
99
99
  "type": "object",
100
- "description": "Runtime allow/ask/deny for harness tools (≠ Inspector enabledToolIds).",
100
+ "description": "Runtime allow/ask/deny for harness tools (≠ node toolPermissions).",
101
101
  "additionalProperties": {
102
102
  "$ref": "#/$defs/permissionToolConfig"
103
103
  }
@@ -70,6 +70,18 @@ You only answer when an LLM provider is already configured. That means coding
70
70
  templates in the skeleton are **already usable** once copied into the project —
71
71
  do not say coding pipelines “don’t exist” or are unavailable.
72
72
 
73
+ - **Can:** Optional **desktop launcher** (Slint) picks a project folder
74
+ and runs the same CLI (`--no-open -p <port>`), then opens the editor in
75
+ the **system browser** after the instance is listening. Several
76
+ projects can run at once, each on its own port. Unsigned Windows/macOS
77
+ zips ship on GitHub Releases (`launcher-v*` tags, not npm `v*`). The
78
+ macOS zip contains `Langflower.app`. Closing the launcher stops
79
+ instances **it** started. Closing a browser tab does
80
+ not. The **?** control opens the user manual on GitHub
81
+ (`docs/public/launcher.md`).
82
+ - **Cannot:** Claim the launcher embeds the canvas, or that it is a
83
+ Tauri / Electron / WebView app. (Tauri was tried for the thin window
84
+ and rejected; the shipped launcher is Slint.)
73
85
  - **Can:** `langflower start [project-dir]` (default port **4010**) creates
74
86
  `.langflower/`, config, `instructions.md`, packs `nodes/my-nodes/` and
75
87
  `nodes/hello-embed/`, skills
@@ -152,11 +164,16 @@ do not say coding pipelines “don’t exist” or are unavailable.
152
164
 
153
165
  ### 5. Editor chrome
154
166
 
167
+ - **Can:** Infinite agent chat uses **Chat Loop** (`common-chat-loop`):
168
+ agent `response` → `result`, `feedback` → agent `feedback`. Send only —
169
+ no Approve; the run ends on Stop. Do not use Review Gate Approve for that
170
+ loop, and do not use bash for the conversation.
155
171
  - **Can:** Chat Input graphs start from the composer **Start** control. Plain
156
172
  **Run** stays disabled for those graphs. Prefill or last typed text lives on
157
173
  the Chat Input node (`inputs.message`) and reappears after Stop.
158
174
  - **Can:** While running — Hard **Stop**, soft **Pause**, HITL,
159
- `ask_user` (composer Send; question in the work log), and `permission.ask`
175
+ `ask_user` (composer Send; question in the work log; option chips when
176
+ the agent passed `questions`), and `permission.ask`
160
177
  in the composer. Work log **clears** on
161
178
  successful
162
179
  workflow load / create / copy (not rename).
@@ -234,9 +251,15 @@ These four are **not** the same thing.
234
251
 
235
252
  ### 8. Tools, permissions, MCP
236
253
 
237
- - **Can:** Harness builtins (including default `ask_user`) + `permission.ask`
238
- Allow/Deny for those builtins. `ask_user` shows the question in the work
239
- log and opens the composer textarea (Send), not Allow/Deny. Wired pack /
254
+ - **Can:** Harness builtins (including default `ask_user` and `sleep`) +
255
+ `permission.ask`
256
+ Allow/Deny for those builtins. Rename or move a file or directory with
257
+ builtin `move` (`from` + `to` under the project) — do not use bash `mv`.
258
+ Wait without bash with builtin `sleep` (`seconds` 1–300); Stop aborts.
259
+ Not a job-wait and not canvas Delay (`common-delay`).
260
+ `ask_user` shows the question in the work
261
+ log and opens the composer (textarea + optional option chips, Send), not
262
+ Allow/Deny. Wired pack /
240
263
  MCP tools (including memory writes and
241
264
  **Langflower Tools**)
242
265
  do **not** ask — authoring the edge is consent. Write Allow does **not**
@@ -250,7 +273,10 @@ These four are **not** the same thing.
250
273
  (`common-tool-invoke`: `tools` + `toolId` + JSON `args` → `result`). **Tool
251
274
  inspect** (`common-tool-inspect`) prints copy-paste `toolId`, example
252
275
  args, and `inputSchema` from the same `tools` wire (optional inspect
253
- `toolId` filters the dump). No LLM required on that path.
276
+ `toolId` filters the dump). No LLM required on that path. **Preview**
277
+ (`common-preview`) accepts any wire on **input** (including `tool-handle`):
278
+ the node and **text** show JSON; **output** passes the value through.
279
+ Tool inspect remains the structured dump.
254
280
  - **Can:** `compile_custom_nodes` exists only when **Langflower Tools**
255
281
  (`common-langflower-tools`) is wired into that agent’s `tools` port
256
282
  (starter Helper / Writer). Same intent as Custom → **Update**. Recompile
@@ -264,8 +290,6 @@ These four are **not** the same thing.
264
290
  unlock” as the product model (use graph stages / tool profiles). All
265
291
  `mcp.servers` always start. Agent sees raw MCP config instead of handles.
266
292
  Equating a checkbox allowlist with runtime allow — use the permission table.
267
- Preview (`common-preview`) showing a `tool-handle` wire — use **Tool
268
- inspect**.
269
293
 
270
294
  ### 9. Sub-Agent and swarm
271
295
 
@@ -301,7 +325,7 @@ Sub-Agent is an **explicit canvas node** for **control and observability**
301
325
  output, `feed.role: result`). There is no separate Plan mode. **Embeddings**
302
326
  catalog nodes + Settings default embedding model
303
327
  are shipped for API checks and pack **`EmbedHandle`** wiring — separate from
304
- vector KB ([ADR-033](../../../../../docs/ADR.md#adr-033--markdown-memory-tools-no-embedding-as-base)).
328
+ vector KB ([ADR-033](../../../../../docs/architecture/ADR.md#adr-033--markdown-memory-tools-no-embedding-as-base)).
305
329
  Obsidian vault helpers are **not** shipped (TBD-007).
306
330
  - **skill-refining:** CLI eval + `skillPath` / harness `read`; no canvas
307
331
  `skill-refining.json` demo.
@@ -347,6 +371,10 @@ When the user asks to “create a project wiki”, “build a knowledge base”,
347
371
  are extra packs (no jsonc registration).
348
372
  LLM tool `handler`s return short **strings** (expected failures as text,
349
373
  not throws). Do not dump raw subprocess logs at the model.
374
+ Wrap named scripts from the project root or a monorepo workspace
375
+ `package.json` as `ToolHandle`s (`npm run <script>`, allowlisted literal,
376
+ no hangers) so the agent uses tools instead of bash. Seed `review-gate`
377
+ wraps `npm run test` this way.
350
378
  Exclusive `ok` / `fail` gates are **`defineReactiveNode`**. Seed
351
379
  `review-gate` uses a boolean **pulse** on `ok`. If the next stage needs
352
380
  the original payload, `ok` **passthroughs `trigger`** (`inferTypeFrom`)
@@ -356,7 +384,9 @@ When the user asks to “create a project wiki”, “build a knowledge base”,
356
384
  (Stop / done / Start) until the user loads another workflow or shuts down
357
385
  Langflower — not the same as Checkpoint resume after process kill.
358
386
  - **Cannot:** Plain JS as the authoring path, Go, Python, or other languages.
359
- Server auto-install. Sandboxed arbitrary user-node execution as shipped.
387
+ Wrap OpenCode/CLI `.mjs` by spawning `node` on a sidecar file (not
388
+ TypeScript authoring; pack is not portable — port into pack `.ts` and
389
+ compile). Server auto-install. Sandboxed arbitrary user-node execution as shipped.
360
390
  Ambient compile without Langflower Tools wired. Canvas add/remove node or
361
391
  edge tools (not shipped). Claim that every node always resets on Stop, or
362
392
  that in-memory node state survives process restart without Checkpoints.
@@ -368,7 +398,11 @@ When the user asks to “create a project wiki”, “build a knowledge base”,
368
398
 
369
399
  When the user asks to add or change a custom node from this starter chat:
370
400
 
371
- 1. Call Writer (or edit `.langflower/nodes/<pack>/*.ts` yourself).
401
+ 1. Call Writer (or edit `.langflower/nodes/<pack>/*.ts` yourself). When
402
+ converting OpenCode / CLI `.mjs` tools, **port the logic into pack `.ts`**
403
+ and compile — do **not** keep a sidecar and spawn `node` on it. When they
404
+ ask for safe project commands, wrap `package.json` scripts as tools
405
+ (`npm run <script>`) instead of granting bash.
372
406
  2. Call **`compile_custom_nodes`** (no args). Report `status` / `nodeTypes` /
373
407
  `errors` from the tool text. Pack failures also write
374
408
  `COMPILATION_ERRORS.md`. If tsc rejects `.ts` import paths, add
@@ -13,10 +13,13 @@ this file over inventing infrastructure.
13
13
 
14
14
  ## Layers (user-facing)
15
15
 
16
- 1. CLI — `langflower start` (default port **4010**)
16
+ 1. CLI — `langflower start` (default port **4010**). Optional **Slint
17
+ launcher** can spawn several of these CLIs (one per project folder);
18
+ it does not embed the editor.
17
19
  2. Local **server** — owns runtime, project I/O under `.langflower/`
18
20
  3. **WebSocket bus** — control plane between server and editor
19
21
  4. Angular **editor** — canvas, feed, inspector, Settings, composer
22
+ (system browser; not a WebView inside the launcher)
20
23
 
21
24
  Project product data for Langflower lives under **`.langflower/`**.
22
25
 
@@ -16,8 +16,9 @@ Facts for UI chrome and on-disk paths. Prefer this file over guessing.
16
16
  **Settings**. Opening Settings (gear or empty-provider onboarding) swaps out
17
17
  feed/inspector; canvas stays. Settings open/close is server-driven.
18
18
  - **Composer (bottom)** — **Start** / Hard **Stop** / soft **Pause**; HITL
19
- input and actions; `ask_user` textarea + Send (question is in the work log);
20
- `permission.ask` Allow/Deny while a run needs them.
19
+ input and actions; `ask_user` textarea + optional option chips + Send
20
+ (question is in the work log); `permission.ask` Allow/Deny while a run
21
+ needs them.
21
22
 
22
23
  ## Where can I…?
23
24
 
@@ -28,11 +29,11 @@ Facts for UI chrome and on-disk paths. Prefer this file over guessing.
28
29
  | Start a Chat Input graph | Composer **Start** — not plain **Run**. Prefill lives on the node; Stop then Start reuses it. |
29
30
  | See run output / stream | Right aside **feed** |
30
31
  | Answer HITL / send into a waiting node | Composer + feed context |
31
- | Answer an agent's `ask_user` question | Work log shows the question; composer textarea + **Send** (not Allow/Deny) |
32
+ | Answer an agent's `ask_user` question | Work log shows the question; composer option chips (if any) + textarea + **Send** (not Allow/Deny) |
32
33
  | Allow or Deny `permission.ask` | Composer permission controls |
33
34
  | Soft-pause last feed agent / continue | Composer **Pause** (per-node) / Send or Resume (soft pause ≠ Hard Stop) |
34
35
  | Hard-stop a run | Composer **Stop** |
35
- | Edit selected node params / ports | Select node → right aside **inspector** (not Settings). Read-only while a run is active — Stop first. |
36
+ | Edit selected node params / ports | Select node → right aside **inspector** (not Settings). Close via canvas click or inspector **Close**. Read-only while a run is active — Stop first. |
36
37
  | See what a built-in node does | Hover a palette row (popover) **or** select the node → inspector **description** (markdown). |
37
38
  | 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. |
38
39
  | Hide / show the node palette | Palette title `<<` / canvas `>>`. Shared across tabs; stored as `paletteVisible` in project `langflower.jsonc`. Allowed during a run. |
@@ -54,6 +55,7 @@ Facts for UI chrome and on-disk paths. Prefer this file over guessing.
54
55
  | `instructions.md` | Project-level agent instructions |
55
56
  | `runs/` | Run artifacts / checkpoints when created |
56
57
  | `logs/` | Server bridge diagnostic JSONL logs when the server runs |
58
+ | `.gitignore` | Seeded ignore rules: compiled node cache (`.cache/`), `logs/`, pack `node_modules/` |
57
59
 
58
60
  ## Out of chrome
59
61
 
@@ -14,7 +14,10 @@ You help the user write **custom nodes** for Langflower.
14
14
 
15
15
  - Custom nodes are **TypeScript** via `@langflower/node-sdk` only — first-class
16
16
  language; `tsc` / IDE types are the compile-time validators. **Not** plain JS
17
- as the authoring path, Go, Python, Rust, or other runtimes.
17
+ as the authoring path, Go, Python, Rust, or other runtimes. Do **not** wrap
18
+ leftover `.mjs` by spawning `node` — port the logic into pack `.ts`. Wrapping
19
+ named `npm run <script>` entries from the project root or a monorepo
20
+ workspace `package.json` is the exception (tools instead of bash).
18
21
  - Do **not** claim sandboxed execution of arbitrary user-node code is shipped.
19
22
  - After file changes **call `compile_custom_nodes` yourself** (no args) — on
20
23
  starter, Writer has it because **Langflower Tools** is wired. Custom →
@@ -39,10 +42,16 @@ You help the user write **custom nodes** for Langflower.
39
42
  branches, streams, or advanced bind wiring are required.
40
43
  - Import from **`@langflower/node-sdk`** — never from a generated
41
44
  `nodes/types.ts` or a required `index.ts` barrel.
42
- - Each `*.ts` / `*.tsx` may `export default` a definition or an array.
43
- Skip `*.test.ts`, `*.d.ts`, `dist/`, `node_modules/`.
45
+ - Each `*.ts` may `export default` a definition or an array. Skip `*.test.ts`,
46
+ `*.d.ts`, `dist/`, `node_modules/`. Custom nodes are not React — do not
47
+ author `.tsx`.
44
48
  - Peer deps on the host SDK / RxJS are supplied by Langflower; author libs go
45
49
  in pack `dependencies`. The user runs `npm install` in the pack.
50
+ - The `@langflower/node-sdk` version in a pack `package.json` is an editor hint
51
+ only: compile and runtime always use the SDK inside the installed Langflower.
52
+ After a Langflower upgrade every pack is recompiled; if the new SDK dropped
53
+ API the pack used, fix the pack source (errors in `COMPILATION_ERRORS.md`) —
54
+ do not edit the version range to "downgrade".
46
55
  - After file changes: call **`compile_custom_nodes`** (wired on starter
47
56
  Helper / Writer via **Langflower Tools** — not ambient on every agent) or
48
57
  Custom section → **Update**. Stop is not required for already-placed
@@ -93,6 +102,41 @@ fails `tsc` (`TS2835`). Either keep one-file nodes with no local imports
93
102
  user paths under `ctx.projectDir` and reject `..` escapes.
94
103
  - Do not register hanging processes (`start`, `dev`, `test:watch`) as tools.
95
104
 
105
+ ### Convert CLI / OpenCode `.mjs` tools
106
+
107
+ **Wrong:** keep `tool.mjs` on disk and have `handler` spawn `node` on that
108
+ file (`npx`, `execFile('node', [script])`, `__dirname`, `import.meta.url`,
109
+ or a hardcoded path). `.mjs` is **not** a pack entry — only `*.ts` is
110
+ compiled. That shape breaks when the pack is copied, published, or moved.
111
+
112
+ **Right — port into the pack:**
113
+
114
+ 1. Map `process.argv` / stdin to `inputSchema`; stdout becomes the handler
115
+ return `string` (expected failures as text, not `throw`, except contract
116
+ like empty `ctx.projectDir`).
117
+ 2. Rewrite as TypeScript (`defineToolRegistrations`). Shared logic in
118
+ `lib/*.ts` with `from './lib/x.ts'` plus `allowImportingTsExtensions`
119
+ (copy hello-embed `tsconfig`).
120
+ 3. Resolve user paths under `ctx.projectDir`; reject `..` escapes. Do not
121
+ use the pack folder as cwd for project files.
122
+ 4. Do not leave the original `.mjs` as a runtime dependency of the node. If
123
+ the user still needs it for OpenCode, it may stay in the OpenCode tree
124
+ unused by Langflower.
125
+ 5. Call `compile_custom_nodes`. The bundled pack must run after a copy of
126
+ **only** the pack folder.
127
+
128
+ **Exception — wrap project npm scripts as tools (prefer this over bash):**
129
+ `handler` **may** spawn `npm run <script>` when the script exists on the
130
+ **project root** `package.json` or a **monorepo workspace** `package.json`.
131
+ Use an allowlisted **literal** script name (`shell: true` only for that
132
+ literal; never splice user paths). `cwd` is that package directory under
133
+ `ctx.projectDir`. Goal: expose finite, safe commands as `ToolHandle`s so the
134
+ agent does not need bash. Do not register hanging scripts (`start`, `dev`,
135
+ `test:watch`). Seed `review-gate.ts` wraps `npm run test` this way. `npm run`
136
+ looks up the **project** (or workspace) `package.json`, not a sidecar next to
137
+ the node — copying the custom-node pack does not break it. Host `git` via
138
+ `child_process` is also OK (seed `git-diff-tool.ts`).
139
+
96
140
  ### QA / review gates (`defineReactiveNode`)
97
141
 
98
142
  - Exclusive ports: pass → emit on `ok`, silent `fail`; fail → emit on
@@ -15,14 +15,15 @@ You help the user **author valid Langflower workflow JSON** under
15
15
 
16
16
  - Use only **catalog** node `type` strings that exist in the project palette /
17
17
  common-nodes **or compiled custom packs**. Do **not** invent types (e.g.
18
- there is no `common-hitl` — use `common-hitl-review-gate`).
18
+ there is no `common-hitl` — use `common-hitl-review-gate` or
19
+ `common-chat-loop`).
19
20
  - Use only **real port ids** from each node’s definition / `NODE.md`. Wrong
20
21
  ports are stripped on load (graceful repair) — inventing ports breaks the
21
22
  graph.
22
23
  - Identity is the **filename stem** (`my-flow.json` → `workflowId: my-flow`).
23
24
  Do not put `id` inside `metadata`.
24
25
  - Tool allowlists use plain builtin ids: `read`, `glob`, `grep`, `edit`,
25
- `write`, `create`, `delete`, `bash` — never `Bash(ls)`-style strings.
26
+ `write`, `create`, `delete`, `move`, `bash` — never `Bash(ls)`-style strings.
26
27
  - LLM `rolePreset` values are only: `custom` | `plan` | `coder` | `explorer`.
27
28
  Unknown values silently become `custom`.
28
29
  - Recompile is opt-in: wire `common-langflower-tools` `tools` → agent
@@ -53,21 +54,23 @@ Schema: `.langflower/schemas/workflow.schema.json`. Samples:
53
54
 
54
55
  ## Ports you must get right
55
56
 
56
- | Node type | Key ports |
57
- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
58
- | `common-chat-input` | out `message` (no wireable in) |
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). MCP http in **`headers`**: JSON object/string; `{lf_secrets:ID}` / `{env:VAR}` OK |
61
- | `common-tool-collection` | in **`tools`** (multi combine) → out **`tools`** — optional hub; duplicate `toolId` last-wins. Direct pack → agent still OK |
62
- | `common-tool-invoke` | in **`tools`** (single) + **`toolId`** (string) + **`args`** (json, blank default) → out **`result`**. Graph-side `invoke`; unknown id / bad JSON → port error. Empty inventory stays inactive. |
63
- | `common-tool-inspect` | in **`tools`** (single) + **`toolId`** (string, empty = all) → out **`text`** — copy-paste dump + `inputSchema`. Not Preview (`common-preview` is string-only). |
64
- | `common-hitl-review-gate` | in `result`; out `response`, `feedback` |
65
- | `common-merge` | in/out **`value`** only (not `step` / `output`) |
66
- | `common-review` | in `task`, `result`, `systemPrompt`, `tools`; out `response`, `feedback` |
67
- | `common-sub-agent` | out **`subagent-registration`** (one specialist handle) → parent `tools`; in `systemPrompt`, `tools` |
68
- | `common-finish` | in `value` |
69
- | `common-string` | in/out `value` |
70
- | `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. |
57
+ | Node type | Key ports |
58
+ | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
59
+ | `common-chat-input` | out `message` (no wireable in) |
60
+ | `common-openai-llm` / `common-fake-llm` | in `userPrompt`, `systemPrompt`, `feedback`, `tools`; out `response`, `toolLog`, … |
61
+ | `common-mcp-stdio` / `common-mcp-http` | out **`tools`** — wire into an agent `tools` port (not a separate `mcp` port). MCP http in **`headers`**: JSON object/string; `{lf_secrets:ID}` / `{env:VAR}` OK |
62
+ | `common-tool-collection` | in **`tools`** (multi combine) → out **`tools`** — optional hub; duplicate `toolId` last-wins. Direct pack → agent still OK |
63
+ | `common-tool-invoke` | in **`tools`** (single) + **`toolId`** (string) + **`args`** (json, blank default) → out **`result`**. Graph-side `invoke`; unknown id / bad JSON → port error. Empty inventory stays inactive. |
64
+ | `common-tool-inspect` | in **`tools`** (single) + **`toolId`** (string, empty = all) → out **`text`** — copy-paste dump + `inputSchema`. Preview (`common-preview`) is separate: in **`input`** (dynamic) → out **`output`** (same value) and **`text`** (formatted string). |
65
+ | `common-hitl-review-gate` | in `result`; out `response`, `feedback` (no `preview`) |
66
+ | `common-chat-loop` | in `result`; hidden HITL `message` (Send); out **`feedback`** only — wire to agent `feedback`. No Approve; run ends on Stop |
67
+ | `common-merge` | in/out **`value`** only (not `step` / `output`) |
68
+ | `common-review` | in `task`, `result`, `systemPrompt`, `tools`; out `response` (accept), `feedback` |
69
+ | `common-critique` | in `assignment`, `packet`, `systemPrompt`, `tools`; out `response` (accept), `feedback` |
70
+ | `common-sub-agent` | out **`subagent-registration`** (one specialist handle) → parent `tools`; in `systemPrompt`, `tools` |
71
+ | `common-finish` | in `value` |
72
+ | `common-string` | in/out `value` |
73
+ | `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. |
71
74
 
72
75
  ## Soft↔Hard loops
73
76
 
@@ -80,6 +83,15 @@ Typical HITL revise loop:
80
83
  Do **not** feed Merge output into both gates and LLM feedback on every tick
81
84
  without a clear phase split.
82
85
 
86
+ ## One response is not a branch
87
+
88
+ A path-choice output (`feedback`, or accept `response`) has one consumer.
89
+
90
+ - Do not wire one LLM `response` to several next stages (clarify, red-team, and an approve gate). That node cannot choose a branch.
91
+ - Do not wire one accept `response` to the next agent and also to later gates.
92
+ - Use `common-critique` (`assignment` / `packet`) or `common-review` (`task` / `result`) so fail is `feedback` and pass is `response`. A Review Gate has the same split.
93
+ - Copy `.langflower/workflows/red-team.json`. The same rule is in `docs/features/node-library.md` §5.2.
94
+
83
95
  ## Custom QA / review gates
84
96
 
85
97
  Custom exclusive-branch nodes (`defineReactiveNode`, seed `review-gate.ts`):
@@ -70,7 +70,18 @@
70
70
  "rolePreset": "custom",
71
71
  "providerId": "",
72
72
  "model": "",
73
- "enabledToolIds": ["read", "glob", "grep"],
73
+ "toolPermissions": {
74
+ "read": "allow",
75
+ "glob": "allow",
76
+ "grep": "allow",
77
+ "edit": "deny",
78
+ "write": "deny",
79
+ "create": "deny",
80
+ "delete": "deny",
81
+ "move": "deny",
82
+ "bash": "deny",
83
+ "ask_user": "deny"
84
+ },
74
85
  "maxIterations": 6,
75
86
  "maxFeedbackTurns": 0
76
87
  },
@@ -139,7 +150,18 @@
139
150
  "rolePreset": "custom",
140
151
  "providerId": "",
141
152
  "model": "",
142
- "enabledToolIds": ["read", "glob", "grep", "bash"],
153
+ "toolPermissions": {
154
+ "read": "allow",
155
+ "glob": "allow",
156
+ "grep": "allow",
157
+ "edit": "deny",
158
+ "write": "deny",
159
+ "create": "deny",
160
+ "delete": "deny",
161
+ "move": "deny",
162
+ "bash": "ask",
163
+ "ask_user": "deny"
164
+ },
143
165
  "maxIterations": 8,
144
166
  "maxFeedbackTurns": 0
145
167
  },
@@ -48,14 +48,18 @@
48
48
  "rolePreset": "custom",
49
49
  "providerId": "",
50
50
  "model": "",
51
- "enabledToolIds": [
52
- "read",
53
- "glob",
54
- "grep",
55
- "write",
56
- "edit",
57
- "create"
58
- ],
51
+ "toolPermissions": {
52
+ "read": "allow",
53
+ "glob": "allow",
54
+ "grep": "allow",
55
+ "edit": "allow",
56
+ "write": "allow",
57
+ "create": "allow",
58
+ "delete": "deny",
59
+ "move": "deny",
60
+ "bash": "deny",
61
+ "ask_user": "deny"
62
+ },
59
63
  "maxIterations": 24,
60
64
  "maxFeedbackTurns": 8
61
65
  },
@@ -105,14 +109,18 @@
105
109
  "rolePreset": "custom",
106
110
  "providerId": "",
107
111
  "model": "",
108
- "enabledToolIds": [
109
- "read",
110
- "glob",
111
- "grep",
112
- "write",
113
- "edit",
114
- "create"
115
- ],
112
+ "toolPermissions": {
113
+ "read": "allow",
114
+ "glob": "allow",
115
+ "grep": "allow",
116
+ "edit": "allow",
117
+ "write": "allow",
118
+ "create": "allow",
119
+ "delete": "deny",
120
+ "move": "deny",
121
+ "bash": "deny",
122
+ "ask_user": "deny"
123
+ },
116
124
  "maxIterations": 24,
117
125
  "contextSize": 32768,
118
126
  "compactOnError": false
@@ -91,7 +91,7 @@
91
91
  "fromNodeId": "search",
92
92
  "fromPort": ["text", 0],
93
93
  "toNodeId": "preview",
94
- "toPort": ["text", 0]
94
+ "toPort": ["input", 0]
95
95
  },
96
96
  {
97
97
  "edgeId": "e-search-done",